[FFmpeg-cvslog] avfilter/vf_fieldmatch: fix crash when inputs have different subsampling

Paul B Mahol git at videolan.org
Thu Feb 17 20:27:05 EET 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Thu Feb 17 10:45:49 2022 +0100| [891c3bef6fcaf54a953e05da9ab2d2c2d1f597d6] | committer: Paul B Mahol

avfilter/vf_fieldmatch: fix crash when inputs have different subsampling

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=891c3bef6fcaf54a953e05da9ab2d2c2d1f597d6
---

 libavfilter/vf_fieldmatch.c | 66 ++++++++++++++++++++++++---------------------
 1 file changed, 36 insertions(+), 30 deletions(-)

diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
index ab027b80eb..40e559df9e 100644
--- a/libavfilter/vf_fieldmatch.c
+++ b/libavfilter/vf_fieldmatch.c
@@ -79,7 +79,7 @@ typedef struct FieldMatchContext {
     AVFrame *prv,  *src,  *nxt;     ///< main sliding window of 3 frames
     AVFrame *prv2, *src2, *nxt2;    ///< sliding window of the optional second stream
     int got_frame[2];               ///< frame request flag for each input stream
-    int hsub, vsub;                 ///< chroma subsampling values
+    int hsub[2], vsub[2];           ///< chroma subsampling values
     int bpc;                        ///< bytes per component
     uint32_t eof;                   ///< bitmask for end of stream
     int64_t lastscdiff;
@@ -153,14 +153,14 @@ static const AVOption fieldmatch_options[] = {
 
 AVFILTER_DEFINE_CLASS(fieldmatch);
 
-static int get_width(const FieldMatchContext *fm, const AVFrame *f, int plane)
+static int get_width(const FieldMatchContext *fm, const AVFrame *f, int plane, int input)
 {
-    return plane ? AV_CEIL_RSHIFT(f->width, fm->hsub) : f->width;
+    return plane ? AV_CEIL_RSHIFT(f->width, fm->hsub[input]) : f->width;
 }
 
-static int get_height(const FieldMatchContext *fm, const AVFrame *f, int plane)
+static int get_height(const FieldMatchContext *fm, const AVFrame *f, int plane, int input)
 {
-    return plane ? AV_CEIL_RSHIFT(f->height, fm->vsub) : f->height;
+    return plane ? AV_CEIL_RSHIFT(f->height, fm->vsub[input]) : f->height;
 }
 
 static int64_t luma_abs_diff(const AVFrame *f1, const AVFrame *f2)
@@ -202,8 +202,8 @@ static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src)
     for (plane = 0; plane < (fm->chroma ? 3 : 1); plane++) {
         const uint8_t *srcp = src->data[plane];
         const int src_linesize = src->linesize[plane];
-        const int width  = get_width (fm, src, plane);
-        const int height = get_height(fm, src, plane);
+        const int width  = get_width (fm, src, plane, INPUT_MAIN);
+        const int height = get_height(fm, src, plane, INPUT_MAIN);
         uint8_t *cmkp = fm->cmask_data[plane];
         const int cmk_linesize = fm->cmask_linesize[plane];
 
@@ -272,8 +272,8 @@ static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src)
         uint8_t *cmkp  = fm->cmask_data[0];
         uint8_t *cmkpU = fm->cmask_data[1];
         uint8_t *cmkpV = fm->cmask_data[2];
-        const int width  = AV_CEIL_RSHIFT(src->width,  fm->hsub);
-        const int height = AV_CEIL_RSHIFT(src->height, fm->vsub);
+        const int width  = AV_CEIL_RSHIFT(src->width,  fm->hsub[INPUT_MAIN]);
+        const int height = AV_CEIL_RSHIFT(src->height, fm->vsub[INPUT_MAIN]);
         const int cmk_linesize   = fm->cmask_linesize[0] << 1;
         const int cmk_linesizeUV = fm->cmask_linesize[2];
         uint8_t *cmkpp  = cmkp - (cmk_linesize>>1);
@@ -503,11 +503,11 @@ static int compare_fields(FieldMatchContext *fm, int match1, int match2, int fie
         const int srcf_linesize = src_linesize << 1;
         int prv_linesize,  nxt_linesize;
         int prvf_linesize, nxtf_linesize;
-        const int width  = get_width (fm, src, plane);
-        const int height = get_height(fm, src, plane);
-        const int y0a = fm->y0 >> (plane ? fm->vsub : 0);
-        const int y1a = fm->y1 >> (plane ? fm->vsub : 0);
-        const int startx = (plane == 0 ? 8 : 8 >> fm->hsub);
+        const int width  = get_width (fm, src, plane, INPUT_MAIN);
+        const int height = get_height(fm, src, plane, INPUT_MAIN);
+        const int y0a = fm->y0 >> (plane ? fm->vsub[INPUT_MAIN] : 0);
+        const int y1a = fm->y1 >> (plane ? fm->vsub[INPUT_MAIN] : 0);
+        const int startx = (plane == 0 ? 8 : 8 >> fm->hsub[INPUT_MAIN]);
         const int stopx  = width - startx;
         const uint8_t *srcpf, *srcf, *srcnf;
         const uint8_t *prvpf, *prvnf, *nxtpf, *nxtnf;
@@ -607,20 +607,20 @@ static int compare_fields(FieldMatchContext *fm, int match1, int match2, int fie
 }
 
 static void copy_fields(const FieldMatchContext *fm, AVFrame *dst,
-                        const AVFrame *src, int field)
+                        const AVFrame *src, int field, int input)
 {
     int plane;
     for (plane = 0; plane < 4 && src->data[plane] && src->linesize[plane]; plane++) {
-        const int plane_h = get_height(fm, src, plane);
+        const int plane_h = get_height(fm, src, plane, input);
         const int nb_copy_fields = (plane_h >> 1) + (field ? 0 : (plane_h & 1));
         av_image_copy_plane(dst->data[plane] + field*dst->linesize[plane], dst->linesize[plane] << 1,
                             src->data[plane] + field*src->linesize[plane], src->linesize[plane] << 1,
-                            get_width(fm, src, plane) * fm->bpc, nb_copy_fields);
+                            get_width(fm, src, plane, input) * fm->bpc, nb_copy_fields);
     }
 }
 
 static AVFrame *create_weave_frame(AVFilterContext *ctx, int match, int field,
-                                   const AVFrame *prv, AVFrame *src, const AVFrame *nxt)
+                                   const AVFrame *prv, AVFrame *src, const AVFrame *nxt, int input)
 {
     AVFrame *dst;
     FieldMatchContext *fm = ctx->priv;
@@ -628,18 +628,18 @@ static AVFrame *create_weave_frame(AVFilterContext *ctx, int match, int field,
     if (match == mC) {
         dst = av_frame_clone(src);
     } else {
-        AVFilterLink *outlink = ctx->outputs[0];
+        AVFilterLink *link = input == INPUT_CLEANSRC ? ctx->outputs[0] : ctx->inputs[INPUT_MAIN];
 
-        dst = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+        dst = ff_get_video_buffer(link, link->w, link->h);
         if (!dst)
             return NULL;
         av_frame_copy_props(dst, src);
 
         switch (match) {
-        case mP: copy_fields(fm, dst, src, 1-field); copy_fields(fm, dst, prv,   field); break;
-        case mN: copy_fields(fm, dst, src, 1-field); copy_fields(fm, dst, nxt,   field); break;
-        case mB: copy_fields(fm, dst, src,   field); copy_fields(fm, dst, prv, 1-field); break;
-        case mU: copy_fields(fm, dst, src,   field); copy_fields(fm, dst, nxt, 1-field); break;
+        case mP: copy_fields(fm, dst, src, 1-field, input); copy_fields(fm, dst, prv,   field, input); break;
+        case mN: copy_fields(fm, dst, src, 1-field, input); copy_fields(fm, dst, nxt,   field, input); break;
+        case mB: copy_fields(fm, dst, src,   field, input); copy_fields(fm, dst, prv, 1-field, input); break;
+        case mU: copy_fields(fm, dst, src,   field, input); copy_fields(fm, dst, nxt, 1-field, input); break;
         default: av_assert0(0);
         }
     }
@@ -655,7 +655,8 @@ static int checkmm(AVFilterContext *ctx, int *combs, int m1, int m2,
     if (combs[mid] < 0) {                                                       \
         if (!gen_frames[mid])                                                   \
             gen_frames[mid] = create_weave_frame(ctx, mid, field,               \
-                                                 fm->prv, fm->src, fm->nxt);    \
+                                                 fm->prv, fm->src, fm->nxt,     \
+                                                 INPUT_MAIN);                   \
         combs[mid] = calc_combed_score(fm, gen_frames[mid]);                    \
     }                                                                           \
 } while (0)
@@ -724,7 +725,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         for (i = 0; i < FF_ARRAY_ELEMS(combs); i++) {
             if (i > mN && fm->combdbg == COMBDBG_PCN)
                 break;
-            gen_frames[i] = create_weave_frame(ctx, i, field, fm->prv, fm->src, fm->nxt);
+            gen_frames[i] = create_weave_frame(ctx, i, field, fm->prv, fm->src, fm->nxt, INPUT_MAIN);
             if (!gen_frames[i]) {
                 ret = AVERROR(ENOMEM);
                 goto fail;
@@ -796,10 +797,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     if (fm->ppsrc) {
         /* field matching was based on a filtered/post-processed input, we now
          * pick the untouched fields from the clean source */
-        dst = create_weave_frame(ctx, match, field, fm->prv2, fm->src2, fm->nxt2);
+        dst = create_weave_frame(ctx, match, field, fm->prv2, fm->src2, fm->nxt2, INPUT_CLEANSRC);
     } else {
         if (!gen_frames[match]) { // XXX: is that possible?
-            dst = create_weave_frame(ctx, match, field, fm->prv, fm->src, fm->nxt);
+            dst = create_weave_frame(ctx, match, field, fm->prv, fm->src, fm->nxt, INPUT_MAIN);
         } else {
             dst = gen_frames[match];
             gen_frames[match] = NULL;
@@ -944,8 +945,13 @@ static int config_input(AVFilterLink *inlink)
         (ret = av_image_alloc(fm->cmask_data, fm->cmask_linesize, w, h, inlink->format, 32)) < 0)
         return ret;
 
-    fm->hsub = pix_desc->log2_chroma_w;
-    fm->vsub = pix_desc->log2_chroma_h;
+    fm->hsub[INPUT_MAIN] = pix_desc->log2_chroma_w;
+    fm->vsub[INPUT_MAIN] = pix_desc->log2_chroma_h;
+    if (fm->ppsrc) {
+        pix_desc = av_pix_fmt_desc_get(ctx->inputs[INPUT_CLEANSRC]->format);
+        fm->hsub[INPUT_CLEANSRC] = pix_desc->log2_chroma_w;
+        fm->vsub[INPUT_CLEANSRC] = pix_desc->log2_chroma_h;
+    }
 
     fm->tpitchy  = FFALIGN(w,      16);
     fm->tpitchuv = FFALIGN(w >> 1, 16);



More information about the ffmpeg-cvslog mailing list