summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/decode/vd_lavc.c6
-rw-r--r--video/filter/vf_d3d11vpp.c2
-rw-r--r--video/hwdec.c8
-rw-r--r--video/hwdec.h9
-rw-r--r--video/out/gpu/video.c75
-rw-r--r--video/out/gpu/video.h3
-rw-r--r--video/out/vo_gpu.c11
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);