LCOV - code coverage report
Current view: top level - libavfilter - vf_tinterlace.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 208 258 80.6 %
Date: 2017-12-18 06:23:41 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Thomas Mundt <tmundt75@gmail.com>
       3             :  * Copyright (c) 2011 Stefano Sabatini
       4             :  * Copyright (c) 2010 Baptiste Coudurier
       5             :  * Copyright (c) 2003 Michael Zucchi <notzed@ximian.com>
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or modify
      10             :  * it under the terms of the GNU General Public License as published by
      11             :  * the Free Software Foundation; either version 2 of the License, or
      12             :  * (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :  * GNU General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU General Public License along
      20             :  * with FFmpeg if not, write to the Free Software Foundation, Inc.,
      21             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      22             :  */
      23             : 
      24             : /**
      25             :  * @file
      26             :  * temporal field interlace filter, ported from MPlayer/libmpcodecs
      27             :  */
      28             : 
      29             : #include "libavutil/opt.h"
      30             : #include "libavutil/imgutils.h"
      31             : #include "libavutil/avassert.h"
      32             : #include "avfilter.h"
      33             : #include "internal.h"
      34             : #include "tinterlace.h"
      35             : 
      36             : #define OFFSET(x) offsetof(TInterlaceContext, x)
      37             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
      38             : 
      39             : static const AVOption tinterlace_options[] = {
      40             :     {"mode",              "select interlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_MERGE}, 0, MODE_NB-1, FLAGS, "mode"},
      41             :     {"merge",             "merge fields",                                 0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGE},             INT_MIN, INT_MAX, FLAGS, "mode"},
      42             :     {"drop_even",         "drop even fields",                             0, AV_OPT_TYPE_CONST, {.i64=MODE_DROP_EVEN},         INT_MIN, INT_MAX, FLAGS, "mode"},
      43             :     {"drop_odd",          "drop odd fields",                              0, AV_OPT_TYPE_CONST, {.i64=MODE_DROP_ODD},          INT_MIN, INT_MAX, FLAGS, "mode"},
      44             :     {"pad",               "pad alternate lines with black",               0, AV_OPT_TYPE_CONST, {.i64=MODE_PAD},               INT_MIN, INT_MAX, FLAGS, "mode"},
      45             :     {"interleave_top",    "interleave top and bottom fields",             0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_TOP},    INT_MIN, INT_MAX, FLAGS, "mode"},
      46             :     {"interleave_bottom", "interleave bottom and top fields",             0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE_BOTTOM}, INT_MIN, INT_MAX, FLAGS, "mode"},
      47             :     {"interlacex2",       "interlace fields from two consecutive frames", 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLACEX2},       INT_MIN, INT_MAX, FLAGS, "mode"},
      48             :     {"mergex2",           "merge fields keeping same frame rate",         0, AV_OPT_TYPE_CONST, {.i64=MODE_MERGEX2},           INT_MIN, INT_MAX, FLAGS, "mode"},
      49             : 
      50             :     {"flags",             "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" },
      51             :     {"low_pass_filter",   "enable vertical low-pass filter",              0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" },
      52             :     {"vlpf",              "enable vertical low-pass filter",              0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" },
      53             :     {"complex_filter",    "enable complex vertical low-pass filter",      0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" },
      54             :     {"cvlpf",             "enable complex vertical low-pass filter",      0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" },
      55             :     {"exact_tb",          "force a timebase which can represent timestamps exactly", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_EXACT_TB}, INT_MIN, INT_MAX, FLAGS, "flags" },
      56             : 
      57             :     {NULL}
      58             : };
      59             : 
      60             : AVFILTER_DEFINE_CLASS(tinterlace);
      61             : 
      62             : #define FULL_SCALE_YUVJ_FORMATS \
      63             :     AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P
      64             : 
      65             : static const enum AVPixelFormat full_scale_yuvj_pix_fmts[] = {
      66             :     FULL_SCALE_YUVJ_FORMATS, AV_PIX_FMT_NONE
      67             : };
      68             : 
      69             : static const AVRational standard_tbs[] = {
      70             :     {1, 25},
      71             :     {1, 30},
      72             :     {1001, 30000},
      73             : };
      74             : 
      75         114 : static int query_formats(AVFilterContext *ctx)
      76             : {
      77             :     static const enum AVPixelFormat pix_fmts[] = {
      78             :         AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
      79             :         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
      80             :         AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
      81             :         AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUV422P10LE,
      82             :         AV_PIX_FMT_YUV440P10LE, AV_PIX_FMT_YUV444P10LE,
      83             :         AV_PIX_FMT_YUV420P12LE, AV_PIX_FMT_YUV422P12LE,
      84             :         AV_PIX_FMT_YUV440P12LE, AV_PIX_FMT_YUV444P12LE,
      85             :         AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
      86             :         AV_PIX_FMT_YUVA420P10LE, AV_PIX_FMT_YUVA422P10LE, AV_PIX_FMT_YUVA444P10LE,
      87             :         AV_PIX_FMT_GRAY8, FULL_SCALE_YUVJ_FORMATS,
      88             :         AV_PIX_FMT_NONE
      89             :     };
      90             : 
      91         114 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
      92         114 :     if (!fmts_list)
      93           0 :         return AVERROR(ENOMEM);
      94         114 :     return ff_set_common_formats(ctx, fmts_list);
      95             : }
      96             : 
      97       10512 : static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
      98             :                            ptrdiff_t mref, ptrdiff_t pref, int clip_max)
      99             : {
     100       10512 :     const uint8_t *srcp_above = srcp + mref;
     101       10512 :     const uint8_t *srcp_below = srcp + pref;
     102             :     int i;
     103     3064464 :     for (i = 0; i < width; i++) {
     104             :         // this calculation is an integer representation of
     105             :         // '0.5 * current + 0.25 * above + 0.25 * below'
     106             :         // '1 +' is for rounding.
     107     3053952 :         dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
     108             :     }
     109       10512 : }
     110             : 
     111        8928 : static void lowpass_line_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8,
     112             :                               ptrdiff_t mref, ptrdiff_t pref, int clip_max)
     113             : {
     114        8928 :     uint16_t *dstp = (uint16_t *)dst8;
     115        8928 :     const uint16_t *srcp = (const uint16_t *)src8;
     116        8928 :     const uint16_t *srcp_above = srcp + mref / 2;
     117        8928 :     const uint16_t *srcp_below = srcp + pref / 2;
     118             :     int i, src_x;
     119     2695392 :     for (i = 0; i < width; i++) {
     120             :         // this calculation is an integer representation of
     121             :         // '0.5 * current + 0.25 * above + 0.25 * below'
     122             :         // '1 +' is for rounding.
     123     2686464 :         src_x   = av_le2ne16(srcp[i]) << 1;
     124     2686464 :         dstp[i] = av_le2ne16((1 + src_x + av_le2ne16(srcp_above[i])
     125             :                              + av_le2ne16(srcp_below[i])) >> 2);
     126             :     }
     127        8928 : }
     128             : 
     129       10512 : static void lowpass_line_complex_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
     130             :                                    ptrdiff_t mref, ptrdiff_t pref, int clip_max)
     131             : {
     132       10512 :     const uint8_t *srcp_above = srcp + mref;
     133       10512 :     const uint8_t *srcp_below = srcp + pref;
     134       10512 :     const uint8_t *srcp_above2 = srcp + mref * 2;
     135       10512 :     const uint8_t *srcp_below2 = srcp + pref * 2;
     136             :     int i, src_x, src_ab;
     137     3064464 :     for (i = 0; i < width; i++) {
     138             :         // this calculation is an integer representation of
     139             :         // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
     140             :         // '4 +' is for rounding.
     141     3053952 :         src_x   = srcp[i] << 1;
     142     3053952 :         src_ab  = srcp_above[i] + srcp_below[i];
     143     6107904 :         dstp[i] = av_clip_uint8((4 + ((srcp[i] + src_x + src_ab) << 1)
     144     3053952 :                                 - srcp_above2[i] - srcp_below2[i]) >> 3);
     145             :         // Prevent over-sharpening:
     146             :         // dst must not exceed src when the average of above and below
     147             :         // is less than src. And the other way around.
     148     3053952 :         if (src_ab > src_x) {
     149     1145198 :             if (dstp[i] < srcp[i])
     150      208619 :                 dstp[i] = srcp[i];
     151     1908754 :         } else if (dstp[i] > srcp[i])
     152      259829 :             dstp[i] = srcp[i];
     153             :     }
     154       10512 : }
     155             : 
     156        8928 : static void lowpass_line_complex_c_16(uint8_t *dst8, ptrdiff_t width, const uint8_t *src8,
     157             :                                       ptrdiff_t mref, ptrdiff_t pref, int clip_max)
     158             : {
     159        8928 :     uint16_t *dstp = (uint16_t *)dst8;
     160        8928 :     const uint16_t *srcp = (const uint16_t *)src8;
     161        8928 :     const uint16_t *srcp_above = srcp + mref / 2;
     162        8928 :     const uint16_t *srcp_below = srcp + pref / 2;
     163        8928 :     const uint16_t *srcp_above2 = srcp + mref;
     164        8928 :     const uint16_t *srcp_below2 = srcp + pref;
     165             :     int i, dst_le, src_le, src_x, src_ab;
     166     2695392 :     for (i = 0; i < width; i++) {
     167             :         // this calculation is an integer representation of
     168             :         // '0.75 * current + 0.25 * above + 0.25 * below - 0.125 * above2 - 0.125 * below2'
     169             :         // '4 +' is for rounding.
     170     2686464 :         src_le = av_le2ne16(srcp[i]);
     171     2686464 :         src_x  = src_le << 1;
     172     2686464 :         src_ab = av_le2ne16(srcp_above[i]) + av_le2ne16(srcp_below[i]);
     173     5372928 :         dst_le = av_clip((4 + ((src_le + src_x + src_ab) << 1)
     174     2686464 :                          - av_le2ne16(srcp_above2[i])
     175     2686464 :                          - av_le2ne16(srcp_below2[i])) >> 3, 0, clip_max);
     176             :         // Prevent over-sharpening:
     177             :         // dst must not exceed src when the average of above and below
     178             :         // is less than src. And the other way around.
     179     2686464 :         if (src_ab > src_x) {
     180     1072111 :             if (dst_le < src_le)
     181      270609 :                 dstp[i] = av_le2ne16(src_le);
     182             :             else
     183      801502 :                 dstp[i] = av_le2ne16(dst_le);
     184     1614353 :         } else if (dst_le > src_le) {
     185      306777 :             dstp[i] = av_le2ne16(src_le);
     186             :         } else
     187     1307576 :             dstp[i] = av_le2ne16(dst_le);
     188             :     }
     189        8928 : }
     190             : 
     191         114 : static av_cold void uninit(AVFilterContext *ctx)
     192             : {
     193         114 :     TInterlaceContext *tinterlace = ctx->priv;
     194             : 
     195         114 :     av_frame_free(&tinterlace->cur );
     196         114 :     av_frame_free(&tinterlace->next);
     197         114 :     av_freep(&tinterlace->black_data[0]);
     198         114 : }
     199             : 
     200         110 : static int config_out_props(AVFilterLink *outlink)
     201             : {
     202         110 :     AVFilterContext *ctx = outlink->src;
     203         110 :     AVFilterLink *inlink = outlink->src->inputs[0];
     204         110 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     205         110 :     TInterlaceContext *tinterlace = ctx->priv;
     206             :     int i;
     207             : 
     208         110 :     tinterlace->vsub = desc->log2_chroma_h;
     209         110 :     outlink->w = inlink->w;
     210         305 :     outlink->h = tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2?
     211         160 :         inlink->h*2 : inlink->h;
     212         110 :     if (tinterlace->mode == MODE_MERGE || tinterlace->mode == MODE_PAD || tinterlace->mode == MODE_MERGEX2)
     213          50 :         outlink->sample_aspect_ratio = av_mul_q(inlink->sample_aspect_ratio,
     214             :                                                 av_make_q(2, 1));
     215             : 
     216         110 :     if (tinterlace->mode == MODE_PAD) {
     217          25 :         uint8_t black[4] = { 0, 0, 0, 16 };
     218             :         int ret;
     219          25 :         ff_draw_init(&tinterlace->draw, outlink->format, 0);
     220          25 :         ff_draw_color(&tinterlace->draw, &tinterlace->color, black);
     221          25 :         if (ff_fmt_is_in(outlink->format, full_scale_yuvj_pix_fmts))
     222           4 :             tinterlace->color.comp[0].u8[0] = 0;
     223          25 :         ret = av_image_alloc(tinterlace->black_data, tinterlace->black_linesize,
     224          25 :                              outlink->w, outlink->h, outlink->format, 16);
     225          25 :         if (ret < 0)
     226           0 :             return ret;
     227             : 
     228          50 :         ff_fill_rectangle(&tinterlace->draw, &tinterlace->color, tinterlace->black_data,
     229          25 :                           tinterlace->black_linesize, 0, 0, outlink->w, outlink->h);
     230             :     }
     231         110 :     if (tinterlace->flags & (TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF)
     232          50 :             && !(tinterlace->mode == MODE_INTERLEAVE_TOP
     233           0 :               || tinterlace->mode == MODE_INTERLEAVE_BOTTOM)) {
     234           0 :         av_log(ctx, AV_LOG_WARNING, "low_pass_filter flags ignored with mode %d\n",
     235             :                 tinterlace->mode);
     236           0 :         tinterlace->flags &= ~(TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF);
     237             :     }
     238         110 :     tinterlace->preout_time_base = inlink->time_base;
     239         110 :     if (tinterlace->mode == MODE_INTERLACEX2) {
     240           0 :         tinterlace->preout_time_base.den *= 2;
     241           0 :         outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1});
     242           0 :         outlink->time_base  = av_mul_q(inlink->time_base , (AVRational){1,2});
     243         110 :     } else if (tinterlace->mode == MODE_MERGEX2) {
     244           0 :         outlink->frame_rate = inlink->frame_rate;
     245           0 :         outlink->time_base  = inlink->time_base;
     246         110 :     } else if (tinterlace->mode != MODE_PAD) {
     247          85 :         outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2});
     248          85 :         outlink->time_base  = av_mul_q(inlink->time_base , (AVRational){2,1});
     249             :     }
     250             : 
     251         440 :     for (i = 0; i<FF_ARRAY_ELEMS(standard_tbs); i++){
     252         330 :         if (!av_cmp_q(standard_tbs[i], outlink->time_base))
     253           0 :             break;
     254             :     }
     255         110 :     if (i == FF_ARRAY_ELEMS(standard_tbs) ||
     256           0 :         (tinterlace->flags & TINTERLACE_FLAG_EXACT_TB))
     257         110 :         outlink->time_base = tinterlace->preout_time_base;
     258             : 
     259         110 :     tinterlace->csp = av_pix_fmt_desc_get(outlink->format);
     260         110 :     if (tinterlace->flags & TINTERLACE_FLAG_CVLPF) {
     261          25 :         if (tinterlace->csp->comp[0].depth > 8)
     262          11 :             tinterlace->lowpass_line = lowpass_line_complex_c_16;
     263             :         else
     264          14 :             tinterlace->lowpass_line = lowpass_line_complex_c;
     265             :         if (ARCH_X86)
     266          25 :             ff_tinterlace_init_x86(tinterlace);
     267          85 :     } else if (tinterlace->flags & TINTERLACE_FLAG_VLPF) {
     268          25 :         if (tinterlace->csp->comp[0].depth > 8)
     269          11 :             tinterlace->lowpass_line = lowpass_line_c_16;
     270             :         else
     271          14 :             tinterlace->lowpass_line = lowpass_line_c;
     272             :         if (ARCH_X86)
     273          25 :             ff_tinterlace_init_x86(tinterlace);
     274             :     }
     275             : 
     276         305 :     av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode,
     277         110 :            (tinterlace->flags & TINTERLACE_FLAG_CVLPF) ? "complex" :
     278          85 :            (tinterlace->flags & TINTERLACE_FLAG_VLPF) ? "linear" : "off",
     279             :            inlink->h, outlink->h);
     280             : 
     281         110 :     return 0;
     282             : }
     283             : 
     284             : #define FIELD_UPPER           0
     285             : #define FIELD_LOWER           1
     286             : #define FIELD_UPPER_AND_LOWER 2
     287             : 
     288             : /**
     289             :  * Copy picture field from src to dst.
     290             :  *
     291             :  * @param src_field copy from upper, lower field or both
     292             :  * @param interleave leave a padding line between each copied line
     293             :  * @param dst_field copy to upper or lower field,
     294             :  *        only meaningful when interleave is selected
     295             :  * @param flags context flags
     296             :  */
     297             : static inline
     298         220 : void copy_picture_field(TInterlaceContext *tinterlace,
     299             :                         uint8_t *dst[4], int dst_linesize[4],
     300             :                         const uint8_t *src[4], int src_linesize[4],
     301             :                         enum AVPixelFormat format, int w, int src_h,
     302             :                         int src_field, int interleave, int dst_field,
     303             :                         int flags)
     304             : {
     305         220 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
     306         220 :     int hsub = desc->log2_chroma_w;
     307         220 :     int plane, vsub = desc->log2_chroma_h;
     308         220 :     int k = src_field == FIELD_UPPER_AND_LOWER ? 1 : 2;
     309             :     int h;
     310             : 
     311         912 :     for (plane = 0; plane < desc->nb_components; plane++) {
     312         692 :         int lines = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT(src_h, vsub) : src_h;
     313         692 :         int cols  = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT(    w, hsub) : w;
     314         692 :         uint8_t *dstp = dst[plane];
     315         692 :         const uint8_t *srcp = src[plane];
     316         692 :         int srcp_linesize = src_linesize[plane] * k;
     317         692 :         int dstp_linesize = dst_linesize[plane] * (interleave ? 2 : 1);
     318         692 :         int clip_max = (1 << tinterlace->csp->comp[plane].depth) - 1;
     319             : 
     320         692 :         lines = (lines + (src_field == FIELD_UPPER)) / k;
     321         692 :         if (src_field == FIELD_LOWER)
     322         188 :             srcp += src_linesize[plane];
     323         692 :         if (interleave && dst_field == FIELD_LOWER)
     324         346 :             dstp += dst_linesize[plane];
     325             :         // Low-pass filtering is required when creating an interlaced destination from
     326             :         // a progressive source which contains high-frequency vertical detail.
     327             :         // Filtering will reduce interlace 'twitter' and Moire patterning.
     328         692 :         if (flags & (TINTERLACE_FLAG_VLPF | TINTERLACE_FLAG_CVLPF)) {
     329         316 :             int x = !!(flags & TINTERLACE_FLAG_CVLPF);
     330       39196 :             for (h = lines; h > 0; h--) {
     331       38880 :                 ptrdiff_t pref = src_linesize[plane];
     332       38880 :                 ptrdiff_t mref = -pref;
     333       38880 :                 if (h >= (lines - x))  mref = 0; // there is no line above
     334       38406 :                 else if (h <= (1 + x)) pref = 0; // there is no line below
     335             : 
     336       38880 :                 tinterlace->lowpass_line(dstp, cols, srcp, mref, pref, clip_max);
     337       38880 :                 dstp += dstp_linesize;
     338       38880 :                 srcp += srcp_linesize;
     339             :             }
     340             :         } else {
     341         376 :             if (tinterlace->csp->comp[plane].depth > 8)
     342         144 :                 cols *= 2;
     343         376 :             av_image_copy_plane(dstp, dstp_linesize, srcp, srcp_linesize, cols, lines);
     344             :         }
     345             :     }
     346         220 : }
     347             : 
     348         220 : static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
     349             : {
     350         220 :     AVFilterContext *ctx = inlink->dst;
     351         220 :     AVFilterLink *outlink = ctx->outputs[0];
     352         220 :     TInterlaceContext *tinterlace = ctx->priv;
     353             :     AVFrame *cur, *next, *out;
     354             :     int field, tff, ret;
     355             : 
     356         220 :     av_frame_free(&tinterlace->cur);
     357         220 :     tinterlace->cur  = tinterlace->next;
     358         220 :     tinterlace->next = picref;
     359             : 
     360         220 :     cur = tinterlace->cur;
     361         220 :     next = tinterlace->next;
     362             :     /* we need at least two frames */
     363         220 :     if (!tinterlace->cur)
     364         110 :         return 0;
     365             : 
     366         110 :     switch (tinterlace->mode) {
     367          25 :     case MODE_MERGEX2: /* move the odd frame into the upper field of the new image, even into
     368             :                         * the lower field, generating a double-height video at same framerate */
     369             :     case MODE_MERGE: /* move the odd frame into the upper field of the new image, even into
     370             :              * the lower field, generating a double-height video at half framerate */
     371          25 :         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     372          25 :         if (!out)
     373           0 :             return AVERROR(ENOMEM);
     374          25 :         av_frame_copy_props(out, cur);
     375          25 :         out->height = outlink->h;
     376          25 :         out->interlaced_frame = 1;
     377          25 :         out->top_field_first = 1;
     378          25 :         out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1));
     379             : 
     380             :         /* write odd frame lines into the upper field of the new frame */
     381          75 :         copy_picture_field(tinterlace, out->data, out->linesize,
     382          25 :                            (const uint8_t **)cur->data, cur->linesize,
     383          25 :                            inlink->format, inlink->w, inlink->h,
     384          25 :                            FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? inlink->frame_count_out & 1 ? FIELD_LOWER : FIELD_UPPER : FIELD_UPPER, tinterlace->flags);
     385             :         /* write even frame lines into the lower field of the new frame */
     386          75 :         copy_picture_field(tinterlace, out->data, out->linesize,
     387          25 :                            (const uint8_t **)next->data, next->linesize,
     388          25 :                            inlink->format, inlink->w, inlink->h,
     389          25 :                            FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? inlink->frame_count_out & 1 ? FIELD_UPPER : FIELD_LOWER : FIELD_LOWER, tinterlace->flags);
     390          25 :         if (tinterlace->mode != MODE_MERGEX2)
     391          25 :             av_frame_free(&tinterlace->next);
     392          25 :         break;
     393             : 
     394           0 :     case MODE_DROP_ODD:  /* only output even frames, odd  frames are dropped; height unchanged, half framerate */
     395             :     case MODE_DROP_EVEN: /* only output odd  frames, even frames are dropped; height unchanged, half framerate */
     396           0 :         out = av_frame_clone(tinterlace->mode == MODE_DROP_EVEN ? cur : next);
     397           0 :         if (!out)
     398           0 :             return AVERROR(ENOMEM);
     399           0 :         av_frame_free(&tinterlace->next);
     400           0 :         break;
     401             : 
     402          25 :     case MODE_PAD: /* expand each frame to double height, but pad alternate
     403             :                     * lines with black; framerate unchanged */
     404          25 :         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     405          25 :         if (!out)
     406           0 :             return AVERROR(ENOMEM);
     407          25 :         av_frame_copy_props(out, cur);
     408          25 :         out->height = outlink->h;
     409          25 :         out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1));
     410             : 
     411          25 :         field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER;
     412             :         /* copy upper and lower fields */
     413          50 :         copy_picture_field(tinterlace, out->data, out->linesize,
     414          25 :                            (const uint8_t **)cur->data, cur->linesize,
     415          25 :                            inlink->format, inlink->w, inlink->h,
     416             :                            FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags);
     417             :         /* pad with black the other field */
     418          50 :         copy_picture_field(tinterlace, out->data, out->linesize,
     419          25 :                            (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize,
     420          25 :                            inlink->format, inlink->w, inlink->h,
     421             :                            FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags);
     422          25 :         break;
     423             : 
     424             :         /* interleave upper/lower lines from odd frames with lower/upper lines from even frames,
     425             :          * halving the frame rate and preserving image height */
     426          60 :     case MODE_INTERLEAVE_TOP:    /* top    field first */
     427             :     case MODE_INTERLEAVE_BOTTOM: /* bottom field first */
     428          60 :         tff = tinterlace->mode == MODE_INTERLEAVE_TOP;
     429          60 :         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     430          60 :         if (!out)
     431           0 :             return AVERROR(ENOMEM);
     432          60 :         av_frame_copy_props(out, cur);
     433          60 :         out->interlaced_frame = 1;
     434          60 :         out->top_field_first = tff;
     435             : 
     436             :         /* copy upper/lower field from cur */
     437         120 :         copy_picture_field(tinterlace, out->data, out->linesize,
     438          60 :                            (const uint8_t **)cur->data, cur->linesize,
     439          60 :                            inlink->format, inlink->w, inlink->h,
     440             :                            tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
     441             :                            tinterlace->flags);
     442             :         /* copy lower/upper field from next */
     443         120 :         copy_picture_field(tinterlace, out->data, out->linesize,
     444          60 :                            (const uint8_t **)next->data, next->linesize,
     445          60 :                            inlink->format, inlink->w, inlink->h,
     446             :                            tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
     447             :                            tinterlace->flags);
     448          60 :         av_frame_free(&tinterlace->next);
     449          60 :         break;
     450           0 :     case MODE_INTERLACEX2: /* re-interlace preserving image height, double frame rate */
     451             :         /* output current frame first */
     452           0 :         out = av_frame_clone(cur);
     453           0 :         if (!out)
     454           0 :             return AVERROR(ENOMEM);
     455           0 :         out->interlaced_frame = 1;
     456           0 :         if (cur->pts != AV_NOPTS_VALUE)
     457           0 :             out->pts = cur->pts*2;
     458             : 
     459           0 :         out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
     460           0 :         if ((ret = ff_filter_frame(outlink, out)) < 0)
     461           0 :             return ret;
     462             : 
     463             :         /* output mix of current and next frame */
     464           0 :         tff = next->top_field_first;
     465           0 :         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     466           0 :         if (!out)
     467           0 :             return AVERROR(ENOMEM);
     468           0 :         av_frame_copy_props(out, next);
     469           0 :         out->interlaced_frame = 1;
     470           0 :         out->top_field_first = !tff;
     471             : 
     472           0 :         if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE)
     473           0 :             out->pts = cur->pts + next->pts;
     474             :         else
     475           0 :             out->pts = AV_NOPTS_VALUE;
     476             :         /* write current frame second field lines into the second field of the new frame */
     477           0 :         copy_picture_field(tinterlace, out->data, out->linesize,
     478           0 :                            (const uint8_t **)cur->data, cur->linesize,
     479           0 :                            inlink->format, inlink->w, inlink->h,
     480             :                            tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
     481             :                            tinterlace->flags);
     482             :         /* write next frame first field lines into the first field of the new frame */
     483           0 :         copy_picture_field(tinterlace, out->data, out->linesize,
     484           0 :                            (const uint8_t **)next->data, next->linesize,
     485           0 :                            inlink->format, inlink->w, inlink->h,
     486             :                            tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
     487             :                            tinterlace->flags);
     488           0 :         break;
     489           0 :     default:
     490           0 :         av_assert0(0);
     491             :     }
     492             : 
     493         110 :     out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
     494         110 :     ret = ff_filter_frame(outlink, out);
     495         110 :     tinterlace->frame++;
     496             : 
     497         110 :     return ret;
     498             : }
     499             : 
     500             : static const AVFilterPad tinterlace_inputs[] = {
     501             :     {
     502             :         .name         = "default",
     503             :         .type         = AVMEDIA_TYPE_VIDEO,
     504             :         .filter_frame = filter_frame,
     505             :     },
     506             :     { NULL }
     507             : };
     508             : 
     509             : static const AVFilterPad tinterlace_outputs[] = {
     510             :     {
     511             :         .name         = "default",
     512             :         .type         = AVMEDIA_TYPE_VIDEO,
     513             :         .config_props = config_out_props,
     514             :     },
     515             :     { NULL }
     516             : };
     517             : 
     518             : AVFilter ff_vf_tinterlace = {
     519             :     .name          = "tinterlace",
     520             :     .description   = NULL_IF_CONFIG_SMALL("Perform temporal field interlacing."),
     521             :     .priv_size     = sizeof(TInterlaceContext),
     522             :     .uninit        = uninit,
     523             :     .query_formats = query_formats,
     524             :     .inputs        = tinterlace_inputs,
     525             :     .outputs       = tinterlace_outputs,
     526             :     .priv_class    = &tinterlace_class,
     527             : };

Generated by: LCOV version 1.13