[FFmpeg-devel] [PATCH] Add "split" mode to tinterlace filter.

Paul B Mahol onemda at gmail.com
Sun Mar 29 04:48:59 CEST 2015


Dana 28. 3. 2015. 23:35 osoba "Brian Matherly" <code at brianmatherly.com>
napisala je:
>
> From: Brian Matherly <pez4brian at yahoo.com>
>
> This mode is the opposite of the "merge" mode.
> ---
> This patch adds a new mode to tinterlace which performs the opposite
operation
> as the "merge" mode.
>
> My primary motivation is that I have been working with Derek Buitenhuis
to see
> about adding interlace support to the libx265 encoder. It turns out that
this is
> a complex situation since libx265 requires each field to be encoded
separately
> but ffmpeg stores fields together as an interlaced frame. tinterlace can
be used
> with this new mode to provide each field as a separate frame to libx265 -
and
> therefore perform valid interlaced h.265 encoding.
>
> At first I considered this patch a hack and planned on keeping it to
myself. But
> now I think that it must be generally useful since it can produce the
exact
> format of data that would be the input to the tinterlace "merge" mode.
> As a test, I have checked:
>     ffmpeg -i input.file -vf "tinterlace=split,tinterlace=merge"
output.file
> And the image makes a successful round trip.

What about separatefields filter?

>  doc/filters.texi            | 24 ++++++++++++++++++++++++
>  libavfilter/tinterlace.h    |  1 +
>  libavfilter/vf_tinterlace.c | 43
+++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 15f8ed5..9b3fd02 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -9197,6 +9197,30 @@ Output:
>   11111   11111   22222   22222   33333   33333   44444
>  @end example
>
> + at item split, 7
> +Perform the inverse operation as merge. Move upper field to odd frames,
lower
> +field to even frames, generating a half height frame at double frame
rate.
> + at example
> + ------> time
> +Input:
> +Frame 1                         Frame 2
> +11111                           33333
> +22222                           44444
> +11111                           33333
> +22222                           44444
> +11111                           33333
> +22222                           44444
> +11111                           33333
> +22222                           44444
> +
> +Output:
> +Frame 1         Frame 2         Frame 3         Frame 4
> +11111           22222           33333           44444
> +11111           22222           33333           44444
> +11111           22222           33333           44444
> +11111           22222           33333           44444
> + at end example
> +
>
>  @end table
>
> diff --git a/libavfilter/tinterlace.h b/libavfilter/tinterlace.h
> index fa0a83a..ece8ce4 100644
> --- a/libavfilter/tinterlace.h
> +++ b/libavfilter/tinterlace.h
> @@ -38,6 +38,7 @@ enum TInterlaceMode {
>      MODE_INTERLEAVE_TOP,
>      MODE_INTERLEAVE_BOTTOM,
>      MODE_INTERLACEX2,
> +    MODE_SPLIT,
>      MODE_NB,
>  };
>
> diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
> index f3411f9..2c9047b 100644
> --- a/libavfilter/vf_tinterlace.c
> +++ b/libavfilter/vf_tinterlace.c
> @@ -46,6 +46,7 @@ static const AVOption tinterlace_options[] = {
>      {"interleave_top",    "interleave top and bottom fields",
 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_TOP},    INT_MIN, INT_MAX,
FLAGS, "mode"},
>      {"interleave_bottom", "interleave bottom and top fields",
 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_BOTTOM}, INT_MIN, INT_MAX,
FLAGS, "mode"},
>      {"interlacex2",       "interlace fields from two consecutive
frames", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLACEX2},       INT_MIN,
INT_MAX, FLAGS, "mode"},
> +    {"split",             "split fields",
 0, AV_OPT_TYPE_CONST, {.i64=MODE_SPLIT},             INT_MIN, INT_MAX,
FLAGS, "mode"},
>
>      {"flags",             "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS,
{.i64 = 0}, 0, INT_MAX, 0, "flags" },
>      {"low_pass_filter",   "enable vertical low-pass filter",
  0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX,
FLAGS, "flags" },
> @@ -118,7 +119,8 @@ static int config_out_props(AVFilterLink *outlink)
>      outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
>      outlink->w = inlink->w;
>      outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode ==
MODE_PAD ?
> -        inlink->h*2 : inlink->h;
> +            inlink->h*2 : tinterlace->mode == MODE_SPLIT ?
> +            inlink->h/2 : inlink->h;
>
>      if (tinterlace->mode == MODE_PAD) {
>          uint8_t black[4] = { 16, 128, 128, 16 };
> @@ -145,7 +147,7 @@ static int config_out_props(AVFilterLink *outlink)
>          tinterlace->flags &= ~TINTERLACE_FLAG_VLPF;
>      }
>      tinterlace->preout_time_base = inlink->time_base;
> -    if (tinterlace->mode == MODE_INTERLACEX2) {
> +    if (tinterlace->mode == MODE_INTERLACEX2 || tinterlace->mode ==
MODE_SPLIT) {
>          tinterlace->preout_time_base.den *= 2;
>          outlink->frame_rate = av_mul_q(inlink->frame_rate,
(AVRational){2,1});
>          outlink->time_base  = av_mul_q(inlink->time_base ,
(AVRational){1,2});
> @@ -372,6 +374,43 @@ static int filter_frame(AVFilterLink *inlink,
AVFrame *picref)
>                             tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ?
FIELD_UPPER : FIELD_LOWER,
>                             tinterlace->flags);
>          break;
> +    case MODE_SPLIT: /* move the upper field into the new odd frame,
lower into the new
> +                      * even frame, generating a half-height video at
double framerate */
> +        /* output upper field first */
> +        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
> +        if (!out)
> +            return AVERROR(ENOMEM);
> +        av_frame_copy_props(out, cur);
> +        out->height = outlink->h;
> +        out->interlaced_frame = 0;
> +        if (cur->pts != AV_NOPTS_VALUE)
> +            out->pts = cur->pts*2;
> +        out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base,
outlink->time_base);
> +        /* write upper field lines into the new odd frame */
> +        copy_picture_field(tinterlace, out->data, out->linesize,
> +                           (const uint8_t **)cur->data, cur->linesize,
> +                           inlink->format, inlink->w, inlink->h,
> +                           FIELD_UPPER, 0, FIELD_UPPER_AND_LOWER,
tinterlace->flags);
> +        if ((ret = ff_filter_frame(outlink, out)) < 0)
> +            return ret;
> +
> +        /* output lower field */
> +        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
> +        if (!out)
> +            return AVERROR(ENOMEM);
> +        av_frame_copy_props(out, cur);
> +        out->height = outlink->h;
> +        out->interlaced_frame = 0;
> +        if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE)
> +            out->pts = cur->pts + next->pts;
> +        else
> +            out->pts = AV_NOPTS_VALUE;
> +        /* write lower field lines into the new even frame */
> +        copy_picture_field(tinterlace, out->data, out->linesize,
> +                           (const uint8_t **)cur->data, cur->linesize,
> +                           inlink->format, inlink->w, inlink->h,
> +                           FIELD_LOWER, 0, FIELD_UPPER_AND_LOWER,
tinterlace->flags);
> +        break;
>      default:
>          av_assert0(0);
>      }
> --
> 1.9.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


More information about the ffmpeg-devel mailing list