LCOV - code coverage report
Current view: top level - libavfilter - vf_separatefields.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 55 60 91.7 %
Date: 2017-12-16 21:16:39 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Paul B Mahol
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with FFmpeg; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include "libavutil/pixdesc.h"
      22             : #include "avfilter.h"
      23             : #include "internal.h"
      24             : 
      25             : typedef struct SeparateFieldsContext {
      26             :     int nb_planes;
      27             :     AVFrame *second;
      28             : } SeparateFieldsContext;
      29             : 
      30           1 : static int config_props_output(AVFilterLink *outlink)
      31             : {
      32           1 :     AVFilterContext *ctx = outlink->src;
      33           1 :     SeparateFieldsContext *s = ctx->priv;
      34           1 :     AVFilterLink *inlink = ctx->inputs[0];
      35             : 
      36           1 :     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
      37             : 
      38           1 :     if (inlink->h & 1) {
      39           0 :         av_log(ctx, AV_LOG_ERROR, "height must be even\n");
      40           0 :         return AVERROR_INVALIDDATA;
      41             :     }
      42             : 
      43           1 :     outlink->time_base.num = inlink->time_base.num;
      44           1 :     outlink->time_base.den = inlink->time_base.den * 2;
      45           1 :     outlink->frame_rate.num = inlink->frame_rate.num * 2;
      46           1 :     outlink->frame_rate.den = inlink->frame_rate.den;
      47           1 :     outlink->w = inlink->w;
      48           1 :     outlink->h = inlink->h / 2;
      49             : 
      50           1 :     return 0;
      51             : }
      52             : 
      53         100 : static void extract_field(AVFrame *frame, int nb_planes, int type)
      54             : {
      55             :     int i;
      56             : 
      57         400 :     for (i = 0; i < nb_planes; i++) {
      58         300 :         if (type)
      59         150 :             frame->data[i] = frame->data[i] + frame->linesize[i];
      60         300 :         frame->linesize[i] *= 2;
      61             :     }
      62         100 : }
      63             : 
      64          50 : static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
      65             : {
      66          50 :     AVFilterContext *ctx = inlink->dst;
      67          50 :     SeparateFieldsContext *s = ctx->priv;
      68          50 :     AVFilterLink *outlink = ctx->outputs[0];
      69             :     int ret;
      70             : 
      71          50 :     inpicref->height = outlink->h;
      72          50 :     inpicref->interlaced_frame = 0;
      73             : 
      74          50 :     if (!s->second) {
      75           1 :         goto clone;
      76             :     } else {
      77          49 :         AVFrame *second = s->second;
      78             : 
      79          49 :         extract_field(second, s->nb_planes, second->top_field_first);
      80             : 
      81          98 :         if (second->pts != AV_NOPTS_VALUE &&
      82          49 :             inpicref->pts != AV_NOPTS_VALUE)
      83          49 :             second->pts += inpicref->pts;
      84             :         else
      85           0 :             second->pts = AV_NOPTS_VALUE;
      86             : 
      87          49 :         ret = ff_filter_frame(outlink, second);
      88          49 :         if (ret < 0)
      89           0 :             return ret;
      90          49 : clone:
      91          50 :         s->second = av_frame_clone(inpicref);
      92          50 :         if (!s->second)
      93           0 :             return AVERROR(ENOMEM);
      94             :     }
      95             : 
      96          50 :     extract_field(inpicref, s->nb_planes, !inpicref->top_field_first);
      97             : 
      98          50 :     if (inpicref->pts != AV_NOPTS_VALUE)
      99          50 :         inpicref->pts *= 2;
     100             : 
     101          50 :     return ff_filter_frame(outlink, inpicref);
     102             : }
     103             : 
     104          52 : static int request_frame(AVFilterLink *outlink)
     105             : {
     106          52 :     AVFilterContext *ctx = outlink->src;
     107          52 :     SeparateFieldsContext *s = ctx->priv;
     108             :     int ret;
     109             : 
     110          52 :     ret = ff_request_frame(ctx->inputs[0]);
     111          52 :     if (ret == AVERROR_EOF && s->second) {
     112           1 :         s->second->pts *= 2;
     113           1 :         extract_field(s->second, s->nb_planes, s->second->top_field_first);
     114           1 :         ret = ff_filter_frame(outlink, s->second);
     115           1 :         s->second = 0;
     116             :     }
     117             : 
     118          52 :     return ret;
     119             : }
     120             : 
     121           1 : static av_cold void uninit(AVFilterContext *ctx)
     122             : {
     123           1 :     SeparateFieldsContext *s = ctx->priv;
     124             : 
     125           1 :     av_frame_free(&s->second);
     126           1 : }
     127             : 
     128             : static const AVFilterPad separatefields_inputs[] = {
     129             :     {
     130             :         .name         = "default",
     131             :         .type         = AVMEDIA_TYPE_VIDEO,
     132             :         .filter_frame = filter_frame,
     133             :     },
     134             :     { NULL }
     135             : };
     136             : 
     137             : static const AVFilterPad separatefields_outputs[] = {
     138             :     {
     139             :         .name          = "default",
     140             :         .type          = AVMEDIA_TYPE_VIDEO,
     141             :         .config_props  = config_props_output,
     142             :         .request_frame = request_frame,
     143             :     },
     144             :     { NULL }
     145             : };
     146             : 
     147             : AVFilter ff_vf_separatefields = {
     148             :     .name        = "separatefields",
     149             :     .description = NULL_IF_CONFIG_SMALL("Split input video frames into fields."),
     150             :     .priv_size   = sizeof(SeparateFieldsContext),
     151             :     .uninit      = uninit,
     152             :     .inputs      = separatefields_inputs,
     153             :     .outputs     = separatefields_outputs,
     154             : };

Generated by: LCOV version 1.13