diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/decode/vd_lavc.c | 6 | ||||
-rw-r--r-- | video/filter/vf_d3d11vpp.c | 2 | ||||
-rw-r--r-- | video/hwdec.c | 8 | ||||
-rw-r--r-- | video/hwdec.h | 9 | ||||
-rw-r--r-- | video/out/gpu/video.c | 75 | ||||
-rw-r--r-- | video/out/gpu/video.h | 3 | ||||
-rw-r--r-- | video/out/vo_gpu.c | 11 |
7 files changed, 91 insertions, 23 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 0e3afa1957..69769e3178 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -431,7 +431,8 @@ static AVBufferRef *hwdec_create_dev(struct mp_filter *vd, return ref; } } else if (ctx->hwdec_devs) { - hwdec_devices_request_all(ctx->hwdec_devs); + hwdec_devices_request_for_img_fmt(ctx->hwdec_devs, + pixfmt2imgfmt(hwdec->pix_fmt)); return hwdec_devices_get_lavc(ctx->hwdec_devs, hwdec->lavc_device); } @@ -510,7 +511,8 @@ static void select_and_set_hwdec(struct mp_filter *vd) // Most likely METHOD_INTERNAL, which often use delay-loaded // VO support as well. if (ctx->hwdec_devs) - hwdec_devices_request_all(ctx->hwdec_devs); + hwdec_devices_request_for_img_fmt( + ctx->hwdec_devs, pixfmt2imgfmt(hwdec->pix_fmt)); } ctx->use_hwdec = true; diff --git a/video/filter/vf_d3d11vpp.c b/video/filter/vf_d3d11vpp.c index e3aa90c05e..6c4e840b5c 100644 --- a/video/filter/vf_d3d11vpp.c +++ b/video/filter/vf_d3d11vpp.c @@ -428,7 +428,7 @@ static struct mp_filter *vf_d3d11vpp_create(struct mp_filter *parent, if (!info || !info->hwdec_devs) goto fail; - hwdec_devices_request_all(info->hwdec_devs); + hwdec_devices_request_for_img_fmt(info->hwdec_devs, IMGFMT_D3D11); struct mp_hwdec_ctx *hwctx = hwdec_devices_get_by_lavc(info->hwdec_devs, AV_HWDEVICE_TYPE_D3D11VA); diff --git a/video/hwdec.c b/video/hwdec.c index 97b984db18..596a418865 100644 --- a/video/hwdec.c +++ b/video/hwdec.c @@ -13,7 +13,7 @@ struct mp_hwdec_devices { struct mp_hwdec_ctx **hwctxs; int num_hwctxs; - void (*load_api)(void *ctx); + void (*load_api)(void *ctx, int imgfmt); void *load_api_ctx; }; @@ -95,16 +95,16 @@ void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ct } void hwdec_devices_set_loader(struct mp_hwdec_devices *devs, - void (*load_api)(void *ctx), void *load_api_ctx) + void (*load_api)(void *ctx, int imgfmt), void *load_api_ctx) { devs->load_api = load_api; devs->load_api_ctx = load_api_ctx; } -void hwdec_devices_request_all(struct mp_hwdec_devices *devs) +void hwdec_devices_request_for_img_fmt(struct mp_hwdec_devices *devs, int imgfmt) { if (devs->load_api && !hwdec_devices_get_first(devs)) - devs->load_api(devs->load_api_ctx); + devs->load_api(devs->load_api_ctx, imgfmt); } char *hwdec_devices_get_names(struct mp_hwdec_devices *devs) diff --git a/video/hwdec.h b/video/hwdec.h index b2ca8ca894..a57010d33f 100644 --- a/video/hwdec.h +++ b/video/hwdec.h @@ -55,11 +55,12 @@ void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ct // If used at all, this must be set/unset during initialization/uninitialization, // as concurrent use with hwdec_devices_request() is a race condition. void hwdec_devices_set_loader(struct mp_hwdec_devices *devs, - void (*load_api)(void *ctx), void *load_api_ctx); + void (*load_api)(void *ctx, int imgfmt), void *load_api_ctx); -// Cause VO to lazily load all devices, and will block until this is done (even -// if not available). -void hwdec_devices_request_all(struct mp_hwdec_devices *devs); +// Cause VO to lazily load all devices for a specified img format, and will +// block until this is done (even if not available). Pass IMGFMT_NONE to load +// all available devices. +void hwdec_devices_request_for_img_fmt(struct mp_hwdec_devices *devs, int imgfmt); // Return "," concatenated list (for introspection/debugging). Use talloc_free(). char *hwdec_devices_get_names(struct mp_hwdec_devices *devs); diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index 449728ccb5..e28a88de5b 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -4329,15 +4329,49 @@ struct mp_image *gl_video_get_image(struct gl_video *p, int imgfmt, int w, int h static void load_add_hwdec(struct gl_video *p, struct mp_hwdec_devices *devs, const struct ra_hwdec_driver *drv, bool is_auto) { + bool needs_loading = true; + for (int j = 0; j < p->num_hwdecs; j++) { + const struct ra_hwdec *hwdec = p->hwdecs[j]; + if (hwdec->driver == drv) { + needs_loading = false; + break; + } + } + if (!needs_loading) { + return; + } + struct ra_hwdec *hwdec = ra_hwdec_load_driver(p->ra, p->log, p->global, devs, drv, is_auto); if (hwdec) MP_TARRAY_APPEND(p, p->hwdecs, p->num_hwdecs, hwdec); } +static void load_hwdecs_all(struct gl_video *p, struct mp_hwdec_devices *devs) +{ + if (!p->hwdec_interop_loading_done) { + for (int n = 0; ra_hwdec_drivers[n]; n++) + load_add_hwdec(p, devs, ra_hwdec_drivers[n], true); + p->hwdec_interop_loading_done = true; + } +} + void gl_video_load_hwdecs(struct gl_video *p, struct mp_hwdec_devices *devs, bool load_all_by_default) { + /* + * By default, or if the option value is "auto", we will not pre-emptively + * load any interops, and instead allow them to be loaded on-demand. + * + * If the option value is "no", then no interops will be loaded now, and + * no interops will be loaded, even if requested later. + * + * If the option value is "all", then all interops will be loaded now, and + * obviously no interops will need to be loaded later. + * + * Finally, if a specific interop is requested, it will be loaded now, and + * no other interop will be loaded, even if requested later. + */ char *type = p->opts.hwdec_interop; if (!type || !type[0] || strcmp(type, "auto") == 0) { if (!load_all_by_default) @@ -4347,7 +4381,7 @@ void gl_video_load_hwdecs(struct gl_video *p, struct mp_hwdec_devices *devs, if (strcmp(type, "no") == 0) { // do nothing, just block further loading } else if (strcmp(type, "all") == 0) { - gl_video_load_hwdecs_all(p, devs); + load_hwdecs_all(p, devs); } else { for (int n = 0; ra_hwdec_drivers[n]; n++) { const struct ra_hwdec_driver *drv = ra_hwdec_drivers[n]; @@ -4360,11 +4394,40 @@ void gl_video_load_hwdecs(struct gl_video *p, struct mp_hwdec_devices *devs, p->hwdec_interop_loading_done = true; } -void gl_video_load_hwdecs_all(struct gl_video *p, struct mp_hwdec_devices *devs) +void gl_video_load_hwdecs_for_img_fmt(struct gl_video *p, + struct mp_hwdec_devices *devs, + int imgfmt) { - if (!p->hwdec_interop_loading_done) { - for (int n = 0; ra_hwdec_drivers[n]; n++) - load_add_hwdec(p, devs, ra_hwdec_drivers[n], true); - p->hwdec_interop_loading_done = true; + if (p->hwdec_interop_loading_done) { + /* + * If we previously marked interop loading as done (for reasons + * discussed above), then do not load any other interops regardless + * of imgfmt. + */ + return; + } + + if (imgfmt == IMGFMT_NONE) { + MP_VERBOSE(p, "Loading hwdec drivers for all formats\n"); + load_hwdecs_all(p, devs); + return; + } + + MP_VERBOSE(p, "Loading hwdec drivers for format: '%s'\n", + mp_imgfmt_to_name(imgfmt)); + for (int i = 0; ra_hwdec_drivers[i]; i++) { + bool matched_fmt = false; + const struct ra_hwdec_driver *drv = ra_hwdec_drivers[i]; + for (int j = 0; drv->imgfmts[j]; j++) { + if (imgfmt == drv->imgfmts[j]) { + matched_fmt = true; + break; + } + } + if (!matched_fmt) { + continue; + } + + load_add_hwdec(p, devs, drv, false); } } diff --git a/video/out/gpu/video.h b/video/out/gpu/video.h index 0bb180e514..4c6422b1ab 100644 --- a/video/out/gpu/video.h +++ b/video/out/gpu/video.h @@ -220,7 +220,8 @@ bool gl_video_showing_interpolated_frame(struct gl_video *p); struct mp_hwdec_devices; void gl_video_load_hwdecs(struct gl_video *p, struct mp_hwdec_devices *devs, bool load_all_by_default); -void gl_video_load_hwdecs_all(struct gl_video *p, struct mp_hwdec_devices *devs); +void gl_video_load_hwdecs_for_img_fmt(struct gl_video *p, struct mp_hwdec_devices *devs, + int imgfmt); struct vo; void gl_video_configure_queue(struct gl_video *p, struct vo *vo); diff --git a/video/out/vo_gpu.c b/video/out/vo_gpu.c index 9e83b380b8..817d750c76 100644 --- a/video/out/vo_gpu.c +++ b/video/out/vo_gpu.c @@ -126,18 +126,19 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) return 0; } -static void request_hwdec_api(struct vo *vo) +static void request_hwdec_api(struct vo *vo, void *data) { struct gpu_priv *p = vo->priv; + int imgfmt = (intptr_t)data; - gl_video_load_hwdecs_all(p->renderer, vo->hwdec_devs); + gl_video_load_hwdecs_for_img_fmt(p->renderer, vo->hwdec_devs, imgfmt); } -static void call_request_hwdec_api(void *ctx) +static void call_request_hwdec_api(void *ctx, int imgfmt) { // Roundabout way to run hwdec loading on the VO thread. // Redirects to request_hwdec_api(). - vo_control(ctx, VOCTRL_LOAD_HWDEC_API, NULL); + vo_control(ctx, VOCTRL_LOAD_HWDEC_API, (void *)(intptr_t)imgfmt); } static void get_and_update_icc_profile(struct gpu_priv *p) @@ -200,7 +201,7 @@ static int control(struct vo *vo, uint32_t request, void *data) return true; } case VOCTRL_LOAD_HWDEC_API: - request_hwdec_api(vo); + request_hwdec_api(vo, data); return true; case VOCTRL_UPDATE_RENDER_OPTS: { update_ra_ctx_options(vo); |