diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c index 384714f23d..8624bdb91a 100644 --- a/libavfilter/vf_fieldmatch.c +++ b/libavfilter/vf_fieldmatch.c @@ -34,6 +34,7 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/timestamp.h" @@ -195,6 +196,40 @@ static void fill_buf(uint8_t *data, int w, int h, int linesize, uint8_t v) } } +static av_always_inline void mark_combed_chroma(const FieldMatchContext *fm, const AVFrame *src, + int hsub, int vsub) +{ + const uint8_t *cmkpU = fm->cmask_data[1]; + const uint8_t *cmkpV = fm->cmask_data[2]; + const int width = AV_CEIL_RSHIFT(src->width, hsub); + const int height = AV_CEIL_RSHIFT(src->height, vsub); + const ptrdiff_t cmk_linesize = fm->cmask_linesize[0]; + const ptrdiff_t cmk_linesizeUV = fm->cmask_linesize[2]; + + for (int y = 1; y < height - 1; y++) { + uint8_t *cmkp_row = fm->cmask_data[0] + ((y << vsub) - (vsub ? y & 1 : 0)) * cmk_linesize; + cmkpV += cmk_linesizeUV; + cmkpU += cmk_linesizeUV; + for (int x = 1; x < width - 1; x++) { +#define HAS_FF_AROUND(p, lz) (p[(x)-1 - (lz)] == 0xff || p[(x) - (lz)] == 0xff || p[(x)+1 - (lz)] == 0xff || \ + p[(x)-1 ] == 0xff || p[(x)+1 ] == 0xff || \ + p[(x)-1 + (lz)] == 0xff || p[(x) + (lz)] == 0xff || p[(x)+1 + (lz)] == 0xff) + if ((cmkpV[x] == 0xff && HAS_FF_AROUND(cmkpV, cmk_linesizeUV)) || + (cmkpU[x] == 0xff && HAS_FF_AROUND(cmkpU, cmk_linesizeUV))) { + uint8_t *cmkp = cmkp_row + (x << hsub); + for (int i = 0; i < (1 << vsub) + !!vsub; i++, cmkp += cmk_linesize) { + if (hsub == 2) + AV_WN32A(cmkp, 0xffffffff); + else if (hsub) + AV_WN16A(cmkp, 0xffff); + else + *cmkp = 0xff; + } + } + } + } +} + static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src) { int x, y, plane, max_v = 0; @@ -271,36 +306,13 @@ static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src) } if (fm->chroma) { - 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[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); - uint8_t *cmkpn = cmkp + (cmk_linesize>>1); - uint8_t *cmkpnn = cmkp + cmk_linesize; - for (y = 1; y < height - 1; y++) { - cmkpp += cmk_linesize; - cmkp += cmk_linesize; - cmkpn += cmk_linesize; - cmkpnn += cmk_linesize; - cmkpV += cmk_linesizeUV; - cmkpU += cmk_linesizeUV; - for (x = 1; x < width - 1; x++) { -#define HAS_FF_AROUND(p, lz) (p[(x)-1 - (lz)] == 0xff || p[(x) - (lz)] == 0xff || p[(x)+1 - (lz)] == 0xff || \ - p[(x)-1 ] == 0xff || p[(x)+1 ] == 0xff || \ - p[(x)-1 + (lz)] == 0xff || p[(x) + (lz)] == 0xff || p[(x)+1 + (lz)] == 0xff) - if ((cmkpV[x] == 0xff && HAS_FF_AROUND(cmkpV, cmk_linesizeUV)) || - (cmkpU[x] == 0xff && HAS_FF_AROUND(cmkpU, cmk_linesizeUV))) { - ((uint16_t*)cmkp)[x] = 0xffff; - ((uint16_t*)cmkpn)[x] = 0xffff; - if (y&1) ((uint16_t*)cmkpp)[x] = 0xffff; - else ((uint16_t*)cmkpnn)[x] = 0xffff; - } - } - } + const int hsub = fm->hsub[INPUT_MAIN]; + const int vsub = fm->vsub[INPUT_MAIN]; + if (hsub == 0 && vsub == 0) mark_combed_chroma(fm, src, 0, 0); + else if (hsub == 1 && vsub == 0) mark_combed_chroma(fm, src, 1, 0); + else if (hsub == 1 && vsub == 1) mark_combed_chroma(fm, src, 1, 1); + else if (hsub == 2 && vsub == 0) mark_combed_chroma(fm, src, 2, 0); + else mark_combed_chroma(fm, src, hsub, vsub); } {