Dav1dPlay: Allow runtime renderer selection
This commit is contained in:
+37
-73
@@ -29,71 +29,19 @@
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "common/attributes.h"
|
||||
|
||||
#include "dav1d/dav1d.h"
|
||||
|
||||
#include "common/attributes.h"
|
||||
#include "tools/input/input.h"
|
||||
#include "dp_fifo.h"
|
||||
|
||||
// Determine which renderer we are going to compile:
|
||||
// Selection order by preference:
|
||||
// - libplacebo Vulkan renderer
|
||||
// - libplacebo OpenGL renderer
|
||||
// - SDL2 renderer
|
||||
#ifdef HAVE_PLACEBO
|
||||
# include <libplacebo/config.h>
|
||||
#endif
|
||||
|
||||
// Check libplacebo Vulkan rendering
|
||||
#if defined(HAVE_VULKAN) && defined(SDL_VIDEO_VULKAN)
|
||||
# if defined(PL_HAVE_VULKAN) && PL_HAVE_VULKAN
|
||||
# define HAVE_RENDERER_PLACEBO
|
||||
# define HAVE_PLACEBO_VULKAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Check libplacebo OpenGL rendering
|
||||
#ifndef HAVE_RENDERER_PLACEBO
|
||||
# if defined(PL_HAVE_OPENGL) && PL_HAVE_OPENGL
|
||||
# define HAVE_RENDERER_PLACEBO
|
||||
# define HAVE_PLACEBO_OPENGL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Fallback to SDL if we can't use placebo
|
||||
#ifndef HAVE_RENDERER_PLACEBO
|
||||
# define HAVE_RENDERER_SDL
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Settings structure
|
||||
* Hold all settings available for the player,
|
||||
* this is usually filled by parsing arguments
|
||||
* from the console.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *inputfile;
|
||||
int highquality;
|
||||
int untimed;
|
||||
int zerocopy;
|
||||
} Dav1dPlaySettings;
|
||||
|
||||
#define WINDOW_WIDTH 910
|
||||
#define WINDOW_HEIGHT 512
|
||||
|
||||
#define DAV1D_EVENT_NEW_FRAME 1
|
||||
#define DAV1D_EVENT_DEC_QUIT 2
|
||||
|
||||
#include "dp_renderer.h"
|
||||
|
||||
// Selected renderer callbacks and cookie
|
||||
static const Dav1dPlayRenderInfo *renderer_info = { NULL };
|
||||
|
||||
/**
|
||||
* Render context structure
|
||||
* This structure contains informations necessary
|
||||
@@ -151,7 +99,8 @@ static void dp_settings_print_usage(const char *const app,
|
||||
" --tilethreads $num: number of tile threads (default: 1)\n"
|
||||
" --highquality: enable high quality rendering\n"
|
||||
" --zerocopy/-z: enable zero copy upload path\n"
|
||||
" --version/-v: print version and exit\n");
|
||||
" --version/-v: print version and exit\n"
|
||||
" --renderer/-r: select renderer backend (default: auto)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -174,7 +123,7 @@ static void dp_rd_ctx_parse_args(Dav1dPlayRenderContext *rd_ctx,
|
||||
Dav1dSettings *lib_settings = &rd_ctx->lib_settings;
|
||||
|
||||
// Short options
|
||||
static const char short_opts[] = "i:vuz";
|
||||
static const char short_opts[] = "i:vuzr:";
|
||||
|
||||
enum {
|
||||
ARG_FRAME_THREADS = 256,
|
||||
@@ -191,6 +140,7 @@ static void dp_rd_ctx_parse_args(Dav1dPlayRenderContext *rd_ctx,
|
||||
{ "tilethreads", 1, NULL, ARG_TILE_THREADS },
|
||||
{ "highquality", 0, NULL, ARG_HIGH_QUALITY },
|
||||
{ "zerocopy", 0, NULL, 'z' },
|
||||
{ "renderer", 0, NULL, 'r'},
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
@@ -217,6 +167,9 @@ static void dp_rd_ctx_parse_args(Dav1dPlayRenderContext *rd_ctx,
|
||||
fprintf(stderr, "warning: --zerocopy requires libplacebo\n");
|
||||
#endif
|
||||
break;
|
||||
case 'r':
|
||||
settings->renderer_name = optarg;
|
||||
break;
|
||||
case ARG_FRAME_THREADS:
|
||||
lib_settings->n_frame_threads =
|
||||
parse_unsigned(optarg, ARG_FRAME_THREADS, argv[0]);
|
||||
@@ -235,6 +188,8 @@ static void dp_rd_ctx_parse_args(Dav1dPlayRenderContext *rd_ctx,
|
||||
"Extra/unused arguments found, e.g. '%s'\n", argv[optind]);
|
||||
if (!settings->inputfile)
|
||||
dp_settings_print_usage(argv[0], "Input file (-i/--input) is required");
|
||||
if (settings->renderer_name && strcmp(settings->renderer_name, "auto") == 0)
|
||||
settings->renderer_name = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,7 +199,7 @@ static void dp_rd_ctx_destroy(Dav1dPlayRenderContext *rd_ctx)
|
||||
{
|
||||
assert(rd_ctx != NULL);
|
||||
|
||||
renderer_info.destroy_renderer(rd_ctx->rd_priv);
|
||||
renderer_info->destroy_renderer(rd_ctx->rd_priv);
|
||||
dp_fifo_destroy(rd_ctx->fifo);
|
||||
SDL_DestroyMutex(rd_ctx->lock);
|
||||
free(rd_ctx);
|
||||
@@ -256,7 +211,7 @@ static void dp_rd_ctx_destroy(Dav1dPlayRenderContext *rd_ctx)
|
||||
* \note The Dav1dPlayRenderContext must be destroyed
|
||||
* again by using dp_rd_ctx_destroy.
|
||||
*/
|
||||
static Dav1dPlayRenderContext *dp_rd_ctx_create(void *rd_data)
|
||||
static Dav1dPlayRenderContext *dp_rd_ctx_create(void *rd_data, int argc, char **argv)
|
||||
{
|
||||
Dav1dPlayRenderContext *rd_ctx;
|
||||
|
||||
@@ -290,7 +245,22 @@ static Dav1dPlayRenderContext *dp_rd_ctx_create(void *rd_data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rd_ctx->rd_priv = renderer_info.create_renderer(rd_data);
|
||||
// Parse and validate arguments
|
||||
dav1d_default_settings(&rd_ctx->lib_settings);
|
||||
memset(&rd_ctx->settings, 0, sizeof(rd_ctx->settings));
|
||||
dp_rd_ctx_parse_args(rd_ctx, argc, argv);
|
||||
|
||||
// Select renderer
|
||||
renderer_info = dp_get_renderer(rd_ctx->settings.renderer_name);
|
||||
|
||||
if (renderer_info == NULL) {
|
||||
printf("No suitable rendered matching %s found.\n",
|
||||
(rd_ctx->settings.renderer_name) ? rd_ctx->settings.renderer_name : "auto");
|
||||
} else {
|
||||
printf("Using %s renderer\n", renderer_info->name);
|
||||
}
|
||||
|
||||
rd_ctx->rd_priv = (renderer_info) ? renderer_info->create_renderer(rd_data) : NULL;
|
||||
if (rd_ctx->rd_priv == NULL) {
|
||||
SDL_DestroyMutex(rd_ctx->lock);
|
||||
dp_fifo_destroy(rd_ctx->fifo);
|
||||
@@ -298,9 +268,6 @@ static Dav1dPlayRenderContext *dp_rd_ctx_create(void *rd_data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dav1d_default_settings(&rd_ctx->lib_settings);
|
||||
memset(&rd_ctx->settings, 0, sizeof(rd_ctx->settings));
|
||||
|
||||
rd_ctx->last_pts = 0;
|
||||
rd_ctx->last_ticks = 0;
|
||||
rd_ctx->current_pts = 0;
|
||||
@@ -332,7 +299,7 @@ static void dp_rd_ctx_post_event(Dav1dPlayRenderContext *rd_ctx, uint32_t code)
|
||||
static void dp_rd_ctx_update_with_dav1d_picture(Dav1dPlayRenderContext *rd_ctx,
|
||||
Dav1dPicture *dav1d_pic)
|
||||
{
|
||||
renderer_info.update_frame(rd_ctx->rd_priv, dav1d_pic, &rd_ctx->settings);
|
||||
renderer_info->update_frame(rd_ctx->rd_priv, dav1d_pic, &rd_ctx->settings);
|
||||
rd_ctx->current_pts = dav1d_pic->m.timestamp;
|
||||
}
|
||||
|
||||
@@ -387,7 +354,7 @@ static void dp_rd_ctx_render(Dav1dPlayRenderContext *rd_ctx)
|
||||
fprintf(stderr, "Frame displayed %f seconds too late\n", wait_time/(float)1000);
|
||||
}
|
||||
|
||||
renderer_info.render(rd_ctx->rd_priv, &rd_ctx->settings);
|
||||
renderer_info->render(rd_ctx->rd_priv, &rd_ctx->settings);
|
||||
|
||||
rd_ctx->last_ticks = SDL_GetTicks();
|
||||
}
|
||||
@@ -564,21 +531,18 @@ int main(int argc, char **argv)
|
||||
SDL_SetWindowResizable(win, SDL_TRUE);
|
||||
|
||||
// Create render context
|
||||
Dav1dPlayRenderContext *rd_ctx = dp_rd_ctx_create(win);
|
||||
Dav1dPlayRenderContext *rd_ctx = dp_rd_ctx_create(win, argc, argv);
|
||||
if (rd_ctx == NULL) {
|
||||
fprintf(stderr, "Failed creating render context\n");
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Parse and validate arguments
|
||||
dp_rd_ctx_parse_args(rd_ctx, argc, argv);
|
||||
|
||||
if (rd_ctx->settings.zerocopy) {
|
||||
if (renderer_info.alloc_pic) {
|
||||
if (renderer_info->alloc_pic) {
|
||||
rd_ctx->lib_settings.allocator = (Dav1dPicAllocator) {
|
||||
.cookie = rd_ctx->rd_priv,
|
||||
.alloc_picture_callback = renderer_info.alloc_pic,
|
||||
.release_picture_callback = renderer_info.release_pic,
|
||||
.alloc_picture_callback = renderer_info->alloc_pic,
|
||||
.release_picture_callback = renderer_info->release_pic,
|
||||
};
|
||||
} else {
|
||||
fprintf(stderr, "--zerocopy unsupported by compiled renderer\n");
|
||||
|
||||
+68
-5
@@ -24,11 +24,57 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dav1d/dav1d.h"
|
||||
|
||||
#include <SDL_config.h>
|
||||
#ifdef HAVE_PLACEBO
|
||||
# include <libplacebo/config.h>
|
||||
#endif
|
||||
|
||||
// Check libplacebo Vulkan rendering
|
||||
#if defined(HAVE_VULKAN) && defined(SDL_VIDEO_VULKAN)
|
||||
# if defined(PL_HAVE_VULKAN) && PL_HAVE_VULKAN
|
||||
# define HAVE_RENDERER_PLACEBO
|
||||
# define HAVE_PLACEBO_VULKAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Check libplacebo OpenGL rendering
|
||||
#if defined(PL_HAVE_OPENGL) && PL_HAVE_OPENGL
|
||||
# define HAVE_RENDERER_PLACEBO
|
||||
# define HAVE_PLACEBO_OPENGL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Settings structure
|
||||
* Hold all settings available for the player,
|
||||
* this is usually filled by parsing arguments
|
||||
* from the console.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *inputfile;
|
||||
const char *renderer_name;
|
||||
int highquality;
|
||||
int untimed;
|
||||
int zerocopy;
|
||||
} Dav1dPlaySettings;
|
||||
|
||||
#define WINDOW_WIDTH 910
|
||||
#define WINDOW_HEIGHT 512
|
||||
|
||||
#define DAV1D_EVENT_NEW_FRAME 1
|
||||
#define DAV1D_EVENT_DEC_QUIT 2
|
||||
|
||||
/**
|
||||
* Renderer info
|
||||
*/
|
||||
typedef struct rdr_info
|
||||
{
|
||||
// Renderer name
|
||||
const char *name;
|
||||
// Cookie passed to the renderer implementation callbacks
|
||||
void *cookie;
|
||||
// Callback to create the renderer
|
||||
@@ -45,8 +91,25 @@ typedef struct rdr_info
|
||||
void (*release_pic)(Dav1dPicture *pic, void *cookie);
|
||||
} Dav1dPlayRenderInfo;
|
||||
|
||||
#ifdef HAVE_RENDERER_PLACEBO
|
||||
# include "dp_renderer_placebo.h"
|
||||
#else
|
||||
# include "dp_renderer_sdl.h"
|
||||
#endif
|
||||
extern const Dav1dPlayRenderInfo rdr_placebo;
|
||||
extern const Dav1dPlayRenderInfo rdr_sdl;
|
||||
|
||||
// Available renderes ordered by priority
|
||||
static const Dav1dPlayRenderInfo* const dp_renderers[] = {
|
||||
&rdr_placebo,
|
||||
&rdr_sdl,
|
||||
};
|
||||
|
||||
static inline const Dav1dPlayRenderInfo *dp_get_renderer(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < (sizeof(dp_renderers)/sizeof(*dp_renderers)); ++i)
|
||||
{
|
||||
if (dp_renderers[i]->name == NULL)
|
||||
continue;
|
||||
|
||||
if (name == NULL || strcmp(name, dp_renderers[i]->name) == 0) {
|
||||
return dp_renderers[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "dp_renderer.h"
|
||||
|
||||
#ifdef HAVE_RENDERER_PLACEBO
|
||||
#include <assert.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <libplacebo/renderer.h>
|
||||
#include <libplacebo/utils/upload.h>
|
||||
|
||||
@@ -486,7 +493,8 @@ static void placebo_release_pic(Dav1dPicture *pic, void *cookie)
|
||||
SDL_UnlockMutex(rd_priv_ctx->lock);
|
||||
}
|
||||
|
||||
static const Dav1dPlayRenderInfo renderer_info = {
|
||||
const Dav1dPlayRenderInfo rdr_placebo = {
|
||||
.name = "placebo",
|
||||
.create_renderer = placebo_renderer_create,
|
||||
.destroy_renderer = placebo_renderer_destroy,
|
||||
.render = placebo_render,
|
||||
@@ -494,3 +502,7 @@ static const Dav1dPlayRenderInfo renderer_info = {
|
||||
.alloc_pic = placebo_alloc_pic,
|
||||
.release_pic = placebo_release_pic,
|
||||
};
|
||||
|
||||
#else
|
||||
const Dav1dPlayRenderInfo rdr_placebo = { NULL };
|
||||
#endif
|
||||
@@ -24,6 +24,12 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "dp_renderer.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
/**
|
||||
* Renderer context for SDL
|
||||
*/
|
||||
@@ -146,7 +152,8 @@ static int sdl_update_texture(void *cookie, Dav1dPicture *dav1d_pic,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const Dav1dPlayRenderInfo renderer_info = {
|
||||
const Dav1dPlayRenderInfo rdr_sdl = {
|
||||
.name = "sdl",
|
||||
.create_renderer = sdl_renderer_create,
|
||||
.destroy_renderer = sdl_renderer_destroy,
|
||||
.render = sdl_render,
|
||||
@@ -36,6 +36,8 @@ endif
|
||||
dav1dplay_sources = files(
|
||||
'dav1dplay.c',
|
||||
'dp_fifo.c',
|
||||
'dp_renderer_placebo.c',
|
||||
'dp_renderer_sdl.c',
|
||||
)
|
||||
|
||||
sdl2_dependency = dependency('sdl2', version: '>= 2.0.1', required: true)
|
||||
|
||||
Reference in New Issue
Block a user