LCOV - code coverage report
Current view: top level - libavfilter - vf_weave.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 47 63 74.6 %
Date: 2017-12-12 11:08:38 Functions: 3 4 75.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/imgutils.h"
      22             : #include "libavutil/opt.h"
      23             : #include "libavutil/pixdesc.h"
      24             : #include "avfilter.h"
      25             : #include "internal.h"
      26             : 
      27             : typedef struct WeaveContext {
      28             :     const AVClass *class;
      29             :     int first_field;
      30             :     int double_weave;
      31             :     int nb_planes;
      32             :     int planeheight[4];
      33             :     int linesize[4];
      34             : 
      35             :     AVFrame *prev;
      36             : } WeaveContext;
      37             : 
      38             : #define OFFSET(x) offsetof(WeaveContext, x)
      39             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
      40             : 
      41             : static const AVOption weave_options[] = {
      42             :     { "first_field", "set first field", OFFSET(first_field), AV_OPT_TYPE_INT,   {.i64=0}, 0, 1, FLAGS, "field"},
      43             :         { "top",     "set top field first",               0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field"},
      44             :         { "t",       "set top field first",               0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field"},
      45             :         { "bottom",  "set bottom field first",            0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field"},
      46             :         { "b",       "set bottom field first",            0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field"},
      47             :     { NULL }
      48             : };
      49             : 
      50             : AVFILTER_DEFINE_CLASS(weave);
      51             : 
      52           1 : static int config_props_output(AVFilterLink *outlink)
      53             : {
      54           1 :     AVFilterContext *ctx = outlink->src;
      55           1 :     WeaveContext *s = ctx->priv;
      56           1 :     AVFilterLink *inlink = ctx->inputs[0];
      57           1 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
      58             :     int ret;
      59             : 
      60           1 :     if (!s->double_weave) {
      61           1 :         outlink->time_base.num = inlink->time_base.num * 2;
      62           1 :         outlink->time_base.den = inlink->time_base.den;
      63           1 :         outlink->frame_rate.num = inlink->frame_rate.num;
      64           1 :         outlink->frame_rate.den = inlink->frame_rate.den * 2;
      65             :     }
      66           1 :     outlink->w = inlink->w;
      67           1 :     outlink->h = inlink->h * 2;
      68             : 
      69           1 :     if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
      70           0 :         return ret;
      71             : 
      72           1 :     s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
      73           1 :     s->planeheight[0] = s->planeheight[3] = inlink->h;
      74             : 
      75           1 :     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
      76             : 
      77           1 :     return 0;
      78             : }
      79             : 
      80          50 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
      81             : {
      82          50 :     AVFilterContext *ctx = inlink->dst;
      83          50 :     WeaveContext *s = ctx->priv;
      84          50 :     AVFilterLink *outlink = ctx->outputs[0];
      85             :     AVFrame *out;
      86             :     int i;
      87             : 
      88          50 :     if (!s->prev) {
      89          25 :         s->prev = in;
      90          25 :         return 0;
      91             :     }
      92             : 
      93          25 :     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
      94          25 :     if (!out) {
      95           0 :         av_frame_free(&in);
      96           0 :         av_frame_free(&s->prev);
      97           0 :         return AVERROR(ENOMEM);
      98             :     }
      99          25 :     av_frame_copy_props(out, in);
     100             : 
     101         100 :     for (i = 0; i < s->nb_planes; i++) {
     102          75 :         if (s->double_weave && !(inlink->frame_count_out & 1)) {
     103           0 :             av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field,
     104           0 :                                 out->linesize[i] * 2,
     105           0 :                                 in->data[i], in->linesize[i],
     106             :                                 s->linesize[i], s->planeheight[i]);
     107           0 :             av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field,
     108           0 :                                 out->linesize[i] * 2,
     109           0 :                                 s->prev->data[i], s->prev->linesize[i],
     110             :                                 s->linesize[i], s->planeheight[i]);
     111             :         } else {
     112         225 :             av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field,
     113          75 :                                 out->linesize[i] * 2,
     114         150 :                                 in->data[i], in->linesize[i],
     115             :                                 s->linesize[i], s->planeheight[i]);
     116         225 :             av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field,
     117          75 :                                 out->linesize[i] * 2,
     118         150 :                                 s->prev->data[i], s->prev->linesize[i],
     119             :                                 s->linesize[i], s->planeheight[i]);
     120             :         }
     121             :     }
     122             : 
     123          25 :     out->pts = s->double_weave ? s->prev->pts : in->pts / 2;
     124          25 :     out->interlaced_frame = 1;
     125          25 :     out->top_field_first = !s->first_field;
     126             : 
     127          25 :     if (!s->double_weave)
     128          25 :         av_frame_free(&in);
     129          25 :     av_frame_free(&s->prev);
     130          25 :     if (s->double_weave)
     131           0 :         s->prev = in;
     132          25 :     return ff_filter_frame(outlink, out);
     133             : }
     134             : 
     135           1 : static av_cold void uninit(AVFilterContext *ctx)
     136             : {
     137           1 :     WeaveContext *s = ctx->priv;
     138             : 
     139           1 :     av_frame_free(&s->prev);
     140           1 : }
     141             : 
     142             : static const AVFilterPad weave_inputs[] = {
     143             :     {
     144             :         .name             = "default",
     145             :         .type             = AVMEDIA_TYPE_VIDEO,
     146             :         .filter_frame     = filter_frame,
     147             :     },
     148             :     { NULL }
     149             : };
     150             : 
     151             : static const AVFilterPad weave_outputs[] = {
     152             :     {
     153             :         .name          = "default",
     154             :         .type          = AVMEDIA_TYPE_VIDEO,
     155             :         .config_props  = config_props_output,
     156             :     },
     157             :     { NULL }
     158             : };
     159             : 
     160             : AVFilter ff_vf_weave = {
     161             :     .name          = "weave",
     162             :     .description   = NULL_IF_CONFIG_SMALL("Weave input video fields into frames."),
     163             :     .priv_size     = sizeof(WeaveContext),
     164             :     .priv_class    = &weave_class,
     165             :     .uninit        = uninit,
     166             :     .inputs        = weave_inputs,
     167             :     .outputs       = weave_outputs,
     168             : };
     169             : 
     170           0 : static av_cold int init(AVFilterContext *ctx)
     171             : {
     172           0 :     WeaveContext *s = ctx->priv;
     173             : 
     174           0 :     if (!strcmp(ctx->filter->name, "doubleweave"))
     175           0 :         s->double_weave = 1;
     176             : 
     177           0 :     return 0;
     178             : }
     179             : 
     180             : #define doubleweave_options weave_options
     181             : AVFILTER_DEFINE_CLASS(doubleweave);
     182             : 
     183             : AVFilter ff_vf_doubleweave = {
     184             :     .name          = "doubleweave",
     185             :     .description   = NULL_IF_CONFIG_SMALL("Weave input video fields into double number of frames."),
     186             :     .priv_size     = sizeof(WeaveContext),
     187             :     .priv_class    = &doubleweave_class,
     188             :     .init          = init,
     189             :     .uninit        = uninit,
     190             :     .inputs        = weave_inputs,
     191             :     .outputs       = weave_outputs,
     192             : };

Generated by: LCOV version 1.13