diff options
author | Niklas Haas <git@haasn.dev> | 2022-04-09 23:58:59 +0200 |
---|---|---|
committer | Niklas Haas <github-daiK1o@haasn.dev> | 2022-04-11 15:43:51 +0200 |
commit | 26a3a0686179627de6c9bffd45ae4c15a0b37771 (patch) | |
tree | d2523ba898c4ca1161767ee81a138035f2301cc1 /video/out | |
parent | 2cafe5137f1544df130face8f748cc571ddf0445 (diff) | |
download | mpv-26a3a0686179627de6c9bffd45ae4c15a0b37771.tar.bz2 mpv-26a3a0686179627de6c9bffd45ae4c15a0b37771.tar.xz |
vo_gpu_next: switch to unpooled hwdec mapping
This makes use of the new frame acquire/release callbacks to hold on to
hwdec images only as long as necessary. This should greatly improve the
smoothness/efficiency of hwdec interop, by not holding on to them for
longer than needed.
This also avoids the need to pool hwdec mappers altogether.
Should fix #10067 as well, since frames are now only mapped when we
actually use them.
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/gpu/hwdec.c | 2 | ||||
-rw-r--r-- | video/out/gpu/hwdec.h | 2 | ||||
-rw-r--r-- | video/out/vo_gpu_next.c | 145 |
3 files changed, 85 insertions, 64 deletions
diff --git a/video/out/gpu/hwdec.c b/video/out/gpu/hwdec.c index 4fe835aa95..14c36347c0 100644 --- a/video/out/gpu/hwdec.c +++ b/video/out/gpu/hwdec.c @@ -122,7 +122,7 @@ bool ra_hwdec_test_format(struct ra_hwdec *hwdec, int imgfmt) } struct ra_hwdec_mapper *ra_hwdec_mapper_create(struct ra_hwdec *hwdec, - struct mp_image_params *params) + const struct mp_image_params *params) { assert(ra_hwdec_test_format(hwdec, params->imgfmt)); diff --git a/video/out/gpu/hwdec.h b/video/out/gpu/hwdec.h index 9026f40ef3..24a2efc344 100644 --- a/video/out/gpu/hwdec.h +++ b/video/out/gpu/hwdec.h @@ -138,7 +138,7 @@ void ra_hwdec_uninit(struct ra_hwdec *hwdec); bool ra_hwdec_test_format(struct ra_hwdec *hwdec, int imgfmt); struct ra_hwdec_mapper *ra_hwdec_mapper_create(struct ra_hwdec *hwdec, - struct mp_image_params *params); + const struct mp_image_params *params); void ra_hwdec_mapper_free(struct ra_hwdec_mapper **mapper); void ra_hwdec_mapper_unmap(struct ra_hwdec_mapper *mapper); int ra_hwdec_mapper_map(struct ra_hwdec_mapper *mapper, struct mp_image *img); diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index d54305cf6e..d859195200 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -90,10 +90,7 @@ struct priv { struct ra_ctx *ra_ctx; struct gpu_ctx *context; struct ra_hwdec_ctx hwdec_ctx; - - // Pooled/cached mappers, for performance - struct ra_hwdec_mapper **hwdec_mappers; - int num_hwdec_mappers; + struct ra_hwdec_mapper *hwdec_mapper; // Allocated DR buffers pthread_mutex_t dr_lock; @@ -323,7 +320,7 @@ struct frame_priv { struct vo *vo; struct osd_state subs; uint64_t osd_sync; - struct ra_hwdec_mapper *hwdec_mapper; + struct ra_hwdec *hwdec; }; static int plane_data_from_imgfmt(struct pl_plane_data out_data[4], @@ -459,12 +456,31 @@ static struct pl_color_space get_mpi_csp(struct vo *vo, struct mp_image *mpi) return csp; } +static bool hwdec_reconfig(struct priv *p, struct ra_hwdec *hwdec, + const struct mp_image_params *par) +{ + if (p->hwdec_mapper) { + if (mp_image_params_equal(par, &p->hwdec_mapper->src_params)) { + return p->hwdec_mapper; + } else { + ra_hwdec_mapper_free(&p->hwdec_mapper); + } + } + + p->hwdec_mapper = ra_hwdec_mapper_create(hwdec, par); + if (!p->hwdec_mapper) { + MP_ERR(p, "Initializing texture for hardware decoding failed.\n"); + return NULL; + } + + return p->hwdec_mapper; +} + // For RAs not based on ra_pl, this creates a new pl_tex wrapper -static pl_tex hwdec_get_tex(struct frame_priv *fp, int n) +static pl_tex hwdec_get_tex(struct priv *p, int n) { - struct priv *p = fp->vo->priv; - struct ra_tex *ratex = fp->hwdec_mapper->tex[n]; - struct ra *ra = fp->hwdec_mapper->ra; + struct ra_tex *ratex = p->hwdec_mapper->tex[n]; + struct ra *ra = p->hwdec_mapper->ra; if (ra_pl_get(ra)) return (pl_tex) ratex->priv; @@ -502,35 +518,38 @@ static pl_tex hwdec_get_tex(struct frame_priv *fp, int n) return false; } -static void discard_frame(const struct pl_source_frame *src) +static bool hwdec_acquire(pl_gpu gpu, struct pl_frame *frame) { - struct mp_image *mpi = src->frame_data; - talloc_free(mpi); + struct mp_image *mpi = frame->user_data; + struct frame_priv *fp = mpi->priv; + struct priv *p = fp->vo->priv; + if (!hwdec_reconfig(p, fp->hwdec, &mpi->params)) + return false; + + if (ra_hwdec_mapper_map(p->hwdec_mapper, mpi) < 0) { + MP_ERR(p, "Mapping hardware decoded surface failed.\n"); + return false; + } + + for (int n = 0; n < frame->num_planes; n++) { + if (!(frame->planes[n].texture = hwdec_get_tex(p, n))) + return false; + } + + return true; } -static void unmap_frame(pl_gpu gpu, struct pl_frame *frame, - const struct pl_source_frame *src) +static void hwdec_release(pl_gpu gpu, struct pl_frame *frame) { - struct mp_image *mpi = src->frame_data; + struct mp_image *mpi = frame->user_data; struct frame_priv *fp = mpi->priv; struct priv *p = fp->vo->priv; - if (fp->hwdec_mapper) { - // Clean up after wrapped plane textures - if (!ra_pl_get(fp->hwdec_mapper->ra)) { - for (int n = 0; n < frame->num_planes; n++) - pl_tex_destroy(p->gpu, &frame->planes[n].texture); - } - - ra_hwdec_mapper_unmap(fp->hwdec_mapper); - MP_TARRAY_APPEND(p, p->hwdec_mappers, p->num_hwdec_mappers, fp->hwdec_mapper); - fp->hwdec_mapper = NULL; + if (!ra_pl_get(p->hwdec_mapper->ra)) { + for (int n = 0; n < frame->num_planes; n++) + pl_tex_destroy(p->gpu, &frame->planes[n].texture); } - for (int i = 0; i < MP_ARRAY_SIZE(fp->subs.entries); i++) { - pl_tex tex = fp->subs.entries[i].tex; - if (tex) - MP_TARRAY_APPEND(p, p->sub_tex, p->num_sub_tex, tex); - } - talloc_free(mpi); + + ra_hwdec_mapper_unmap(p->hwdec_mapper); } static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src, @@ -542,31 +561,18 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src struct vo *vo = fp->vo; struct priv *p = vo->priv; - struct ra_hwdec *hwdec = ra_hwdec_get(&p->hwdec_ctx, mpi->imgfmt); - if (hwdec) { - if (MP_TARRAY_POP(p->hwdec_mappers, p->num_hwdec_mappers, &fp->hwdec_mapper)) { - if (!mp_image_params_equal(&mpi->params, &fp->hwdec_mapper->src_params)) - ra_hwdec_mapper_free(&fp->hwdec_mapper); - } - - if (!fp->hwdec_mapper) { - fp->hwdec_mapper = ra_hwdec_mapper_create(hwdec, &mpi->params); - if (!fp->hwdec_mapper) { - MP_ERR(p, "Initializing texture for hardware decoding failed.\n"); - talloc_free(mpi); - return false; - } - } - - if (ra_hwdec_mapper_map(fp->hwdec_mapper, mpi) < 0) { - MP_ERR(p, "Mapping hardware decoded surface failed.\n"); - MP_TARRAY_APPEND(p, p->hwdec_mappers, p->num_hwdec_mappers, fp->hwdec_mapper); - fp->hwdec_mapper = NULL; + fp->hwdec = ra_hwdec_get(&p->hwdec_ctx, mpi->imgfmt); + if (fp->hwdec) { + // Note: We don't actually need the mapper to map the frame yet, we + // only reconfig the mapper here (potentially creating it) to access + // `dst_params`. In practice, though, this should not matter unless the + // image format changes mid-stream. + if (!hwdec_reconfig(p, fp->hwdec, &mpi->params)) { talloc_free(mpi); return false; } - par = &fp->hwdec_mapper->dst_params; + par = &p->hwdec_mapper->dst_params; } *frame = (struct pl_frame) { @@ -601,18 +607,14 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src default: break; } - if (hwdec) { + if (fp->hwdec) { struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(par->imgfmt); + frame->acquire = hwdec_acquire; + frame->release = hwdec_release; frame->num_planes = desc.num_planes; for (int n = 0; n < frame->num_planes; n++) { struct pl_plane *plane = &frame->planes[n]; - plane->texture = hwdec_get_tex(fp, n); - if (!plane->texture) { - unmap_frame(gpu, frame, src); - return false; - } - int *map = plane->component_mapping; for (int c = 0; c < mp_imgfmt_desc_get_num_comps(&desc); c++) { if (desc.comps[c].plane != n) @@ -659,7 +661,7 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src if (!pl_upload_plane(gpu, plane, &tex[n], &data[n])) { MP_ERR(vo, "Failed uploading frame!\n"); talloc_free(data[n].priv); - unmap_frame(gpu, frame, src); + talloc_free(mpi); return false; } } @@ -704,6 +706,26 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src return true; } +static void unmap_frame(pl_gpu gpu, struct pl_frame *frame, + const struct pl_source_frame *src) +{ + struct mp_image *mpi = src->frame_data; + struct frame_priv *fp = mpi->priv; + struct priv *p = fp->vo->priv; + for (int i = 0; i < MP_ARRAY_SIZE(fp->subs.entries); i++) { + pl_tex tex = fp->subs.entries[i].tex; + if (tex) + MP_TARRAY_APPEND(p, p->sub_tex, p->num_sub_tex, tex); + } + talloc_free(mpi); +} + +static void discard_frame(const struct pl_source_frame *src) +{ + struct mp_image *mpi = src->frame_data; + talloc_free(mpi); +} + static void info_callback(void *priv, const struct pl_render_info *info) { struct vo *vo = priv; @@ -1284,8 +1306,7 @@ static void uninit(struct vo *vo) pl_mpv_user_shader_destroy(&p->user_hooks[i].hook); if (vo->hwdec_devs) { - for (int n = 0; n < p->num_hwdec_mappers; n++) - ra_hwdec_mapper_free(&p->hwdec_mappers[n]); + ra_hwdec_mapper_free(&p->hwdec_mapper); ra_hwdec_ctx_uninit(&p->hwdec_ctx); hwdec_devices_set_loader(vo->hwdec_devs, NULL, NULL); hwdec_devices_destroy(vo->hwdec_devs); |