diff --git a/video/filter/vf_fingerprint.c b/video/filter/vf_fingerprint.c index 7061b74c3c..b65400000d 100644 --- a/video/filter/vf_fingerprint.c +++ b/video/filter/vf_fingerprint.c @@ -15,8 +15,6 @@ * License along with mpv. If not, see . */ -#include - #include "common/common.h" #include "common/tags.h" #include "filters/filter.h" @@ -25,11 +23,10 @@ #include "options/m_option.h" #include "video/img_format.h" #include "video/sws_utils.h" +#include "video/zimg.h" #include "osdep/timer.h" -#define ZIMG_ALIGN 32 - #define PRINT_ENTRY_NUM 10 struct f_opts { @@ -66,24 +63,14 @@ struct priv { struct f_opts *opts; struct mp_image *scaled; struct mp_sws_context *sws; + struct mp_zimg_context *zimg; struct print_entry entries[PRINT_ENTRY_NUM]; int num_entries; int last_imgfmt, last_w, last_h; int gray_plane_imgfmt; - zimg_filter_graph *zimg_graph; - void *zimg_tmp; + bool fallback_warning; }; -static void destroy_zimg(struct mp_filter *f) -{ - struct priv *p = f->priv; - - free(p->zimg_tmp); - p->zimg_tmp = NULL; - zimg_filter_graph_free(p->zimg_graph); - p->zimg_graph = NULL; -} - // (Other code internal to this filter also calls this to reset the frame list.) static void f_reset(struct mp_filter *f) { @@ -106,50 +93,14 @@ static void reinit_fmt(struct mp_filter *f, struct mp_image *mpi) p->last_imgfmt = mpi->imgfmt; p->last_w = mpi->w; p->last_h = mpi->h; + p->gray_plane_imgfmt = 0; + p->fallback_warning = false; - destroy_zimg(f); - - if (!(mpi->fmt.flags & (MP_IMGFLAG_YUV_NV | MP_IMGFLAG_YUV_P))) - return; - - zimg_image_format src_fmt, dst_fmt; - - // Note: we try to pass only the first plane. Formats which do not have - // such a luma plane are excluded above. - zimg_image_format_default(&src_fmt, ZIMG_API_VERSION); - src_fmt.width = mpi->w; - src_fmt.height = mpi->h; - src_fmt.color_family = ZIMG_COLOR_GREY; - src_fmt.pixel_type = ZIMG_PIXEL_BYTE; - src_fmt.depth = mpi->fmt.component_bits; - src_fmt.pixel_range = mpi->params.color.levels == MP_CSP_LEVELS_PC ? - ZIMG_RANGE_FULL : ZIMG_RANGE_LIMITED; - - zimg_image_format_default(&dst_fmt, ZIMG_API_VERSION); - dst_fmt.width = p->scaled->w; - dst_fmt.height = p->scaled->h; - dst_fmt.color_family = ZIMG_COLOR_GREY; - dst_fmt.pixel_type = ZIMG_PIXEL_BYTE; - dst_fmt.depth = 8; - dst_fmt.pixel_range = ZIMG_RANGE_FULL; - - zimg_graph_builder_params params; - zimg_graph_builder_params_default(¶ms, ZIMG_API_VERSION); - params.resample_filter = ZIMG_RESIZE_BILINEAR; - - p->zimg_graph = zimg_filter_graph_build(&src_fmt, &dst_fmt, ¶ms); - if (!p->zimg_graph) - return; - - size_t tmp_size; - if (!zimg_filter_graph_get_tmp_size(p->zimg_graph, &tmp_size)) { - tmp_size = MP_ALIGN_UP(tmp_size, ZIMG_ALIGN); - p->zimg_tmp = aligned_alloc(ZIMG_ALIGN, tmp_size); - } - - if (!p->zimg_tmp) { - zimg_filter_graph_free(p->zimg_graph); - p->zimg_graph = NULL; + if (mpi->fmt.flags & (MP_IMGFLAG_YUV_NV | MP_IMGFLAG_YUV_P)) { + // Try to pass only the first plane, in the hope that it might be + // faster. + p->gray_plane_imgfmt = + mp_imgfmt_find(0, 0, 1, mpi->fmt.component_bits, MP_IMGFLAG_YUV_P); } } @@ -174,23 +125,22 @@ static void f_process(struct mp_filter *f) reinit_fmt(f, mpi); - if (p->zimg_graph && - !((uintptr_t)mpi->planes[0] % ZIMG_ALIGN) && - !(mpi->stride[0] % ZIMG_ALIGN)) - { - zimg_image_buffer_const src_buf = {ZIMG_API_VERSION}; - src_buf.plane[0].data = mpi->planes[0]; - src_buf.plane[0].stride = mpi->stride[0]; - src_buf.plane[0].mask = ZIMG_BUFFER_MAX; - zimg_image_buffer dst_buf = {ZIMG_API_VERSION}; - dst_buf.plane[0].data = p->scaled->planes[0]; - dst_buf.plane[0].stride = p->scaled->stride[0]; - dst_buf.plane[0].mask = ZIMG_BUFFER_MAX; - // (The API promises to succeed if no user callbacks fail, so no need - // to check the return value.) - zimg_filter_graph_process(p->zimg_graph, &src_buf, &dst_buf, - p->zimg_tmp, NULL, NULL, NULL, NULL); - } else { + // Try to achieve minimum conversion, even if it makes the fingerprints less + // "portable" across source video. + p->scaled->params.color = mpi->params.color; + // Make output always full range; no reason to lose precision. + p->scaled->params.color.levels = MP_CSP_LEVELS_PC; + + struct mp_image src = *mpi; + + if (p->gray_plane_imgfmt) + mp_image_setfmt(&src, p->gray_plane_imgfmt); + + if (!mp_zimg_convert(p->zimg, p->scaled, &src)) { + if (!p->fallback_warning) { + MP_WARN(f, "Falling back to libswscale.\n"); + p->fallback_warning = true; + } if (mp_sws_scale(p->sws, p->scaled, mpi) < 0) goto error; } @@ -262,7 +212,6 @@ static const struct mp_filter_info filter = { .process = f_process, .command = f_command, .reset = f_reset, - .destroy = destroy_zimg, .priv_size = sizeof(struct priv), }; @@ -283,9 +232,10 @@ static struct mp_filter *f_create(struct mp_filter *parent, void *options) p->scaled = mp_image_alloc(IMGFMT_Y8, size, size); MP_HANDLE_OOM(p->scaled); talloc_steal(p, p->scaled); - p->scaled->params.color.levels = MP_CSP_LEVELS_PC; p->sws = mp_sws_alloc(p); MP_HANDLE_OOM(p->sws); + p->zimg = mp_zimg_alloc(); + talloc_steal(p, p->zimg); return f; }