[FFmpeg-devel] [PATCH] avfilter/yadif: Check more fields for the spatial/temporal decission

Paul B Mahol onemda at gmail.com
Thu Sep 5 21:20:08 CEST 2013


On 9/5/13, Michael Niedermayer <michaelni at gmx.at> wrote:
> This increases the in->out delay by 1 frame
>
> Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> ---
>  libavfilter/vf_yadif.c |   75
> +++++++++++++++++++++++++++++++++++-------------
>  libavfilter/yadif.h    |    8 ++++--
>  2 files changed, 61 insertions(+), 22 deletions(-)
>
> diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c
> index abf8cd5..687e889 100644
> --- a/libavfilter/vf_yadif.c
> +++ b/libavfilter/vf_yadif.c
> @@ -74,6 +74,9 @@ typedef struct ThreadData {
>   \
>              diff = FFMAX3(diff, min, -max); \
>          } \
> +        if (!(mode&4)) { \
> +            diff = FFMAX3(diff, FFABS(prev4[0] - prev2[0]), FFABS(next2[0]
> - next4[0])); \
> +        } \
>   \
>          if (spatial_pred > d + diff) \
>             spatial_pred = d + diff; \
> @@ -91,7 +94,8 @@ typedef struct ThreadData {
>      }
>
>  static void filter_line_c(void *dst1,
> -                          void *prev1, void *cur1, void *next1,
> +                          void *prev3, void *prev1,
> +                          void *cur1, void *next1, void *next3,
>                            int w, int prefs, int mrefs, int parity, int
> mode)
>  {
>      uint8_t *dst  = dst1;
> @@ -101,6 +105,8 @@ static void filter_line_c(void *dst1,
>      int x;
>      uint8_t *prev2 = parity ? prev : cur ;
>      uint8_t *next2 = parity ? cur  : next;
> +    uint8_t *prev4 = parity ? prev3: prev ;
> +    uint8_t *next4 = parity ? next : next3;
>
>      /* The function is called with the pointers already pointing to data[3]
> and
>       * with 6 subtracted from the width.  This allows the FILTER macro to
> be
> @@ -110,7 +116,8 @@ static void filter_line_c(void *dst1,
>  }
>
>  #define MAX_ALIGN 8
> -static void filter_edges(void *dst1, void *prev1, void *cur1, void *next1,
> +static void filter_edges(void *dst1, void *prev3, void *prev1,
> +                         void *cur1, void *next1, void *next3,
>                           int w, int prefs, int mrefs, int parity, int
> mode)
>  {
>      uint8_t *dst  = dst1;
> @@ -120,6 +127,8 @@ static void filter_edges(void *dst1, void *prev1, void
> *cur1, void *next1,
>      int x;
>      uint8_t *prev2 = parity ? prev : cur ;
>      uint8_t *next2 = parity ? cur  : next;
> +    uint8_t *prev4 = parity ? prev3: prev ;
> +    uint8_t *next4 = parity ? next : next3;
>
>      /* Only edge pixels need to be processed here.  A constant value of
> false
>       * for is_not_edge should let the compiler ignore the whole branch. */
> @@ -131,6 +140,8 @@ static void filter_edges(void *dst1, void *prev1, void
> *cur1, void *next1,
>      next = (uint8_t*)next1 + w - (MAX_ALIGN-1);
>      prev2 = (uint8_t*)(parity ? prev : cur);
>      next2 = (uint8_t*)(parity ? cur  : next);
> +    prev4 = (uint8_t*)(parity ? prev3: next);
> +    next4 = (uint8_t*)(parity ? prev : next3);
>
>      FILTER(w - (MAX_ALIGN-1), w - 3, 1)
>      FILTER(w - 3, w, 0)
> @@ -138,7 +149,8 @@ static void filter_edges(void *dst1, void *prev1, void
> *cur1, void *next1,
>
>
>  static void filter_line_c_16bit(void *dst1,
> -                                void *prev1, void *cur1, void *next1,
> +                                void *prev3, void *prev1,
> +                                void *cur1, void *next1, void *next3,
>                                  int w, int prefs, int mrefs, int parity,
>                                  int mode)
>  {
> @@ -149,13 +161,16 @@ static void filter_line_c_16bit(void *dst1,
>      int x;
>      uint16_t *prev2 = parity ? prev : cur ;
>      uint16_t *next2 = parity ? cur  : next;
> +    uint16_t *prev4 = parity ? prev3: prev ;
> +    uint16_t *next4 = parity ? next : next3;
>      mrefs /= 2;
>      prefs /= 2;
>
>      FILTER(0, w, 1)
>  }
>
> -static void filter_edges_16bit(void *dst1, void *prev1, void *cur1, void
> *next1,
> +static void filter_edges_16bit(void *dst1, void *prev3, void *prev1,
> +                               void *cur1, void *next1, void *next3,
>                                 int w, int prefs, int mrefs, int parity, int
> mode)
>  {
>      uint16_t *dst  = dst1;
> @@ -165,6 +180,8 @@ static void filter_edges_16bit(void *dst1, void *prev1,
> void *cur1, void *next1,
>      int x;
>      uint16_t *prev2 = parity ? prev : cur ;
>      uint16_t *next2 = parity ? cur  : next;
> +    uint16_t *prev4 = parity ? prev3: prev ;
> +    uint16_t *next4 = parity ? next : next3;
>      mrefs /= 2;
>      prefs /= 2;
>
> @@ -176,6 +193,8 @@ static void filter_edges_16bit(void *dst1, void *prev1,
> void *cur1, void *next1,
>      next  = (uint16_t*)next1 + w - (MAX_ALIGN/2-1);
>      prev2 = (uint16_t*)(parity ? prev : cur);
>      next2 = (uint16_t*)(parity ? cur  : next);
> +    prev4 = (uint16_t*)(parity ? prev3: next);
> +    next4 = (uint16_t*)(parity ? prev : next3);
>
>      FILTER(w - (MAX_ALIGN/2-1), w - 3, 1)
>      FILTER(w - 3, w, 0)
> @@ -197,17 +216,19 @@ static int filter_slice(AVFilterContext *ctx, void
> *arg, int jobnr, int nb_jobs)
>       */
>      for (y = slice_start; y < slice_end; y++) {
>          if ((y ^ td->parity) & 1) {
> +            uint8_t *prev2= &s->prev2->data[td->plane][y * refs];
>              uint8_t *prev = &s->prev->data[td->plane][y * refs];
>              uint8_t *cur  = &s->cur ->data[td->plane][y * refs];
>              uint8_t *next = &s->next->data[td->plane][y * refs];
> +            uint8_t *next2= &s->next2->data[td->plane][y * refs];
>              uint8_t *dst  = &td->frame->data[td->plane][y *
> td->frame->linesize[td->plane]];
>              int     mode  = y == 1 || y + 2 == td->h ? 2 : s->mode;
> -            s->filter_line(dst + pix_3, prev + pix_3, cur + pix_3,
> -                           next + pix_3, td->w - (3 + MAX_ALIGN/df-1),
> +            s->filter_line(dst + pix_3, prev2 + pix_3, prev + pix_3, cur +
> pix_3,
> +                           next + pix_3, next2 + pix_3, td->w - (3 +
> MAX_ALIGN/df-1),
>                             y + 1 < td->h ? refs : -refs,
>                             y ? -refs : refs,
>                             td->parity ^ td->tff, mode);
> -            s->filter_edges(dst, prev, cur, next, td->w,
> +            s->filter_edges(dst, prev2, prev, cur, next, next2, td->w,
>                              y + 1 < td->h ? refs : -refs,
>                              y ? -refs : refs,
>                              td->parity ^ td->tff, mode);
> @@ -319,24 +340,33 @@ static int filter_frame(AVFilterLink *link, AVFrame
> *frame)
>      if (yadif->frame_pending)
>          return_frame(ctx, 1);
>
> -    if (yadif->prev)
> -        av_frame_free(&yadif->prev);
> +    if (yadif->prev2)
> +        av_frame_free(&yadif->prev2);
> +    yadif->prev2= yadif->prev;
>      yadif->prev = yadif->cur;
>      yadif->cur  = yadif->next;
> -    yadif->next = frame;
> +    yadif->next = yadif->next2;
> +    yadif->next2= frame;
>
>      if (!yadif->cur)
>          return 0;
>
> -    if (checkstride(yadif, yadif->next, yadif->cur)) {
> +    if (checkstride(yadif, yadif->next2, yadif->next)) {
>          av_log(ctx, AV_LOG_VERBOSE, "Reallocating frame due to differing
> stride\n");
> -        fixstride(link, yadif->next);
> +        fixstride(link, yadif->next2);
>      }
> +    if (checkstride(yadif, yadif->next2, yadif->next))
> +        fixstride(link, yadif->next);
>      if (checkstride(yadif, yadif->next, yadif->cur))
>          fixstride(link, yadif->cur);
>      if (yadif->prev && checkstride(yadif, yadif->next, yadif->prev))
>          fixstride(link, yadif->prev);
> -    if (checkstride(yadif, yadif->next, yadif->cur) || (yadif->prev &&
> checkstride(yadif, yadif->next, yadif->prev))) {
> +    if (yadif->prev && checkstride(yadif, yadif->prev, yadif->prev2))
> +        fixstride(link, yadif->prev2);
> +    if (   checkstride(yadif, yadif->next2, yadif->next)
> +        || checkstride(yadif, yadif->next, yadif->cur)
> +        || (yadif->prev  && checkstride(yadif, yadif->next, yadif->prev))
> +        || (yadif->prev2 && checkstride(yadif, yadif->prev, yadif->prev2)))
> {
>          av_log(ctx, AV_LOG_ERROR, "Failed to reallocate frame\n");
>          return -1;
>      }
> @@ -355,6 +385,9 @@ static int filter_frame(AVFilterLink *link, AVFrame
> *frame)
>      if (!yadif->prev &&
>          !(yadif->prev = av_frame_clone(yadif->cur)))
>          return AVERROR(ENOMEM);
> +    if (!yadif->prev2 &&
> +        !(yadif->prev2 = av_frame_clone(yadif->prev)))
> +        return AVERROR(ENOMEM);
>
>      yadif->out = ff_get_video_buffer(ctx->outputs[0], link->w, link->h);
>      if (!yadif->out)
> @@ -382,21 +415,21 @@ static int request_frame(AVFilterLink *link)
>      do {
>          int ret;
>
> -        if (yadif->eof)
> +        if (yadif->eof>1)
>              return AVERROR_EOF;
>
>          ret  = ff_request_frame(link->src->inputs[0]);
>
>          if (ret == AVERROR_EOF && yadif->cur) {
> -            AVFrame *next = av_frame_clone(yadif->next);
> +            AVFrame *next = av_frame_clone(yadif->next2);
>
>              if (!next)
>                  return AVERROR(ENOMEM);
>
> -            next->pts = yadif->next->pts * 2 - yadif->cur->pts;
> +            next->pts = yadif->next2->pts * 2 - yadif->next->pts;
>
>              filter_frame(link->src->inputs[0], next);
> -            yadif->eof = 1;
> +            yadif->eof++;
>          } else if (ret < 0) {
>              return ret;
>          }
> @@ -409,9 +442,11 @@ static av_cold void uninit(AVFilterContext *ctx)
>  {
>      YADIFContext *yadif = ctx->priv;
>
> +    av_frame_free(&yadif->prev2);
>      av_frame_free(&yadif->prev);
>      av_frame_free(&yadif->cur );
>      av_frame_free(&yadif->next);
> +    av_frame_free(&yadif->next2);
>  }
>
>  static int query_formats(AVFilterContext *ctx)
> @@ -484,8 +519,8 @@ static int config_props(AVFilterLink *link)
>          s->filter_edges = filter_edges;
>      }
>
> -    if (ARCH_X86)
> -        ff_yadif_init_x86(s);
> +//     if (ARCH_X86)
> +//         ff_yadif_init_x86(s);
>
>      return 0;
>  }
> @@ -497,7 +532,7 @@ static int config_props(AVFilterLink *link)
>  #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST,
> {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit }
>
>  static const AVOption yadif_options[] = {
> -    { "mode",   "specify the interlacing mode", OFFSET(mode),
> AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 3, FLAGS, "mode"},
> +    { "mode",   "specify the interlacing mode", OFFSET(mode),

The way how this is documented and presented to the user is far from optimal.

If it is flag then it should be set like that and not by adding extra modes.

> AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 7, FLAGS, "mode"},
>      CONST("send_frame",           "send one frame for each frame",
>                            YADIF_MODE_SEND_FRAME,           "mode"),
>      CONST("send_field",           "send one frame for each field",
>                            YADIF_MODE_SEND_FIELD,           "mode"),
>      CONST("send_frame_nospatial", "send one frame for each frame, but skip
> spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"),
> diff --git a/libavfilter/yadif.h b/libavfilter/yadif.h
> index 3ddf005..ee5c9af 100644
> --- a/libavfilter/yadif.h
> +++ b/libavfilter/yadif.h
> @@ -50,17 +50,21 @@ typedef struct YADIFContext {
>      int frame_pending;
>
>      AVFrame *cur;
> +    AVFrame *next2;
>      AVFrame *next;
>      AVFrame *prev;
> +    AVFrame *prev2;
>      AVFrame *out;
>
>      /**
>       * Required alignment for filter_line
>       */
>      void (*filter_line)(void *dst,
> -                        void *prev, void *cur, void *next,
> +                        void *prev2, void *prev, void
> +                        *cur, void *next, void *next2,
>                          int w, int prefs, int mrefs, int parity, int
> mode);
> -    void (*filter_edges)(void *dst, void *prev, void *cur, void *next,
> +    void (*filter_edges)(void *dst, void *prev2, void *prev,
> +                         void *cur, void *next, void *next2,
>                           int w, int prefs, int mrefs, int parity, int
> mode);
>
>      const AVPixFmtDescriptor *csp;
> --
> 1.7.9.5
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list