avfilter/vf_tinterlace: add mergex2 mode
authorPaul B Mahol <onemda@gmail.com>
Wed, 30 Sep 2015 13:35:55 +0000 (15:35 +0200)
committerPaul B Mahol <onemda@gmail.com>
Sat, 3 Oct 2015 13:22:16 +0000 (15:22 +0200)
Signed-off-by: Paul B Mahol <onemda@gmail.com>
doc/filters.texi
libavfilter/tinterlace.h
libavfilter/vf_tinterlace.c

index a4d828e..04b2d22 100644 (file)
@@ -10774,6 +10774,29 @@ Output:
  11111   11111   22222   22222   33333   33333   44444
 @end example
 
+@item mergex2, 7
+Move odd frames into the upper field, even into the lower field,
+generating a double height frame at same frame rate.
+@example
+ ------> time
+Input:
+Frame 1         Frame 2         Frame 3         Frame 4
+
+11111           22222           33333           44444
+11111           22222           33333           44444
+11111           22222           33333           44444
+11111           22222           33333           44444
+
+Output:
+11111           33333           33333           55555
+22222           22222           44444           44444
+11111           33333           33333           55555
+22222           22222           44444           44444
+11111           33333           33333           55555
+22222           22222           44444           44444
+11111           33333           33333           55555
+22222           22222           44444           44444
+@end example
 
 @end table
 
index d80a6e2..3b703e7 100644 (file)
@@ -38,6 +38,7 @@ enum TInterlaceMode {
     MODE_INTERLEAVE_TOP,
     MODE_INTERLEAVE_BOTTOM,
     MODE_INTERLACEX2,
+    MODE_MERGEX2,
     MODE_NB,
 };
 
index 4bdcd45..3d6140f 100644 (file)
@@ -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"},
+    {"mergex2",           "merge fields keeping same frame rate",         0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGEX2},           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,9 +119,9 @@ static int config_out_props(AVFilterLink *outlink)
 
     tinterlace->vsub = desc->log2_chroma_h;
     outlink->w = inlink->w;
-    outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD ?
+    outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2?
         inlink->h*2 : inlink->h;
-    if (tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD)
+    if (tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2)
         outlink->sample_aspect_ratio = av_mul_q(inlink->sample_aspect_ratio,
                                                 av_make_q(2, 1));
 
@@ -153,6 +154,9 @@ static int config_out_props(AVFilterLink *outlink)
         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});
+    } else if (tinterlace->mode == MODE_MERGEX2) {
+        outlink->frame_rate = inlink->frame_rate;
+        outlink->time_base  = inlink->time_base;
     } else if (tinterlace->mode != MODE_PAD) {
         outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2});
         outlink->time_base  = av_mul_q(inlink->time_base , (AVRational){2,1});
@@ -259,6 +263,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
         return 0;
 
     switch (tinterlace->mode) {
+    case MODE_MERGEX2: /* move the odd frame into the upper field of the new image, even into
+                        * the lower field, generating a double-height video at same framerate */
     case MODE_MERGE: /* move the odd frame into the upper field of the new image, even into
              * the lower field, generating a double-height video at half framerate */
         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
@@ -274,13 +280,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
         copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)cur->data, cur->linesize,
                            inlink->format, inlink->w, inlink->h,
-                           FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags);
+                           FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? inlink->frame_count & 1 ? FIELD_LOWER : FIELD_UPPER : FIELD_UPPER, tinterlace->flags);
         /* write even frame lines into the lower field of the new frame */
         copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)next->data, next->linesize,
                            inlink->format, inlink->w, inlink->h,
-                           FIELD_UPPER_AND_LOWER, 1, FIELD_LOWER, tinterlace->flags);
-        av_frame_free(&tinterlace->next);
+                           FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? inlink->frame_count & 1 ? FIELD_UPPER : FIELD_LOWER : FIELD_LOWER, tinterlace->flags);
+        if (tinterlace->mode != MODE_MERGEX2)
+            av_frame_free(&tinterlace->next);
         break;
 
     case MODE_DROP_ODD:  /* only output even frames, odd  frames are dropped; height unchanged, half framerate */