LCOV - code coverage report
Current view: top level - libavfilter - vf_il.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 47 61 77.0 %
Date: 2017-12-14 08:27:08 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
       3             :  * Copyright (c) 2013 Paul B Mahol
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * (de)interleave fields filter
      25             :  */
      26             : 
      27             : #include "libavutil/opt.h"
      28             : #include "libavutil/imgutils.h"
      29             : #include "libavutil/pixdesc.h"
      30             : #include "avfilter.h"
      31             : #include "internal.h"
      32             : 
      33             : enum FilterMode {
      34             :     MODE_NONE,
      35             :     MODE_INTERLEAVE,
      36             :     MODE_DEINTERLEAVE
      37             : };
      38             : 
      39             : typedef struct IlContext {
      40             :     const AVClass *class;
      41             :     int luma_mode, chroma_mode, alpha_mode; ///<FilterMode
      42             :     int luma_swap, chroma_swap, alpha_swap;
      43             :     int nb_planes;
      44             :     int linesize[4], chroma_height;
      45             :     int has_alpha;
      46             : } IlContext;
      47             : 
      48             : #define OFFSET(x) offsetof(IlContext, x)
      49             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
      50             : 
      51             : static const AVOption il_options[] = {
      52             :     {"luma_mode",   "select luma mode", OFFSET(luma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "luma_mode"},
      53             :     {"l",           "select luma mode", OFFSET(luma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "luma_mode"},
      54             :     {"none",         NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NONE},         0, 0, FLAGS, "luma_mode"},
      55             :     {"interleave",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "luma_mode"},
      56             :     {"i",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "luma_mode"},
      57             :     {"deinterleave", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "luma_mode"},
      58             :     {"d",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "luma_mode"},
      59             :     {"chroma_mode", "select chroma mode", OFFSET(chroma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "chroma_mode"},
      60             :     {"c",           "select chroma mode", OFFSET(chroma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "chroma_mode"},
      61             :     {"none",         NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NONE},         0, 0, FLAGS, "chroma_mode"},
      62             :     {"interleave",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "chroma_mode"},
      63             :     {"i",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "chroma_mode"},
      64             :     {"deinterleave", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "chroma_mode"},
      65             :     {"d",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "chroma_mode"},
      66             :     {"alpha_mode", "select alpha mode", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "alpha_mode"},
      67             :     {"a",          "select alpha mode", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "alpha_mode"},
      68             :     {"none",         NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_NONE},         0, 0, FLAGS, "alpha_mode"},
      69             :     {"interleave",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "alpha_mode"},
      70             :     {"i",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_INTERLEAVE},   0, 0, FLAGS, "alpha_mode"},
      71             :     {"deinterleave", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "alpha_mode"},
      72             :     {"d",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_DEINTERLEAVE}, 0, 0, FLAGS, "alpha_mode"},
      73             :     {"luma_swap",   "swap luma fields",   OFFSET(luma_swap),   AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
      74             :     {"ls",          "swap luma fields",   OFFSET(luma_swap),   AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
      75             :     {"chroma_swap", "swap chroma fields", OFFSET(chroma_swap), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
      76             :     {"cs",          "swap chroma fields", OFFSET(chroma_swap), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
      77             :     {"alpha_swap",  "swap alpha fields",  OFFSET(alpha_swap),  AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
      78             :     {"as",          "swap alpha fields",  OFFSET(alpha_swap),  AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
      79             :     {NULL}
      80             : };
      81             : 
      82             : AVFILTER_DEFINE_CLASS(il);
      83             : 
      84         141 : static int query_formats(AVFilterContext *ctx)
      85             : {
      86         141 :     AVFilterFormats *formats = NULL;
      87             :     int fmt, ret;
      88             : 
      89       25944 :     for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
      90       25803 :         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
      91       51465 :         if (!(desc->flags & AV_PIX_FMT_FLAG_PAL) &&
      92       49209 :             !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) &&
      93       23547 :             (ret = ff_add_format(&formats, fmt)) < 0)
      94           0 :             return ret;
      95             :     }
      96             : 
      97         141 :     return ff_set_common_formats(ctx, formats);
      98             : }
      99             : 
     100         140 : static int config_input(AVFilterLink *inlink)
     101             : {
     102         140 :     IlContext *s = inlink->dst->priv;
     103         140 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     104             :     int ret;
     105             : 
     106         140 :     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
     107             : 
     108         140 :     s->has_alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
     109         140 :     if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
     110           0 :         return ret;
     111             : 
     112         140 :     s->chroma_height = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
     113             : 
     114         140 :     return 0;
     115             : }
     116             : 
     117         350 : static void interleave(uint8_t *dst, uint8_t *src, int w, int h,
     118             :                        int dst_linesize, int src_linesize,
     119             :                        enum FilterMode mode, int swap)
     120             : {
     121         350 :     const int a = swap;
     122         350 :     const int b = 1 - a;
     123         350 :     const int m = h >> 1;
     124             :     int y;
     125             : 
     126         350 :     switch (mode) {
     127         350 :     case MODE_DEINTERLEAVE:
     128       46646 :         for (y = 0; y < m; y++) {
     129       46296 :             memcpy(dst + dst_linesize *  y     , src + src_linesize * (y * 2 + a), w);
     130       46296 :             memcpy(dst + dst_linesize * (y + m), src + src_linesize * (y * 2 + b), w);
     131             :         }
     132         350 :         break;
     133           0 :     case MODE_NONE:
     134           0 :         for (y = 0; y < m; y++) {
     135           0 :             memcpy(dst + dst_linesize *  y * 2     , src + src_linesize * (y * 2 + a), w);
     136           0 :             memcpy(dst + dst_linesize * (y * 2 + 1), src + src_linesize * (y * 2 + b), w);
     137             :         }
     138           0 :         break;
     139           0 :     case MODE_INTERLEAVE:
     140           0 :         for (y = 0; y < m; y++) {
     141           0 :             memcpy(dst + dst_linesize * (y * 2 + a), src + src_linesize *  y     , w);
     142           0 :             memcpy(dst + dst_linesize * (y * 2 + b), src + src_linesize * (y + m), w);
     143             :         }
     144           0 :         break;
     145             :     }
     146         350 : }
     147             : 
     148         140 : static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     149             : {
     150         140 :     IlContext *s = inlink->dst->priv;
     151         140 :     AVFilterLink *outlink = inlink->dst->outputs[0];
     152             :     AVFrame *out;
     153             :     int comp;
     154             : 
     155         140 :     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     156         140 :     if (!out) {
     157           0 :         av_frame_free(&inpicref);
     158           0 :         return AVERROR(ENOMEM);
     159             :     }
     160         140 :     av_frame_copy_props(out, inpicref);
     161             : 
     162         420 :     interleave(out->data[0], inpicref->data[0],
     163             :                s->linesize[0], inlink->h,
     164         140 :                out->linesize[0], inpicref->linesize[0],
     165         140 :                s->luma_mode, s->luma_swap);
     166             : 
     167         312 :     for (comp = 1; comp < (s->nb_planes - s->has_alpha); comp++) {
     168         516 :         interleave(out->data[comp], inpicref->data[comp],
     169             :                    s->linesize[comp], s->chroma_height,
     170         172 :                    out->linesize[comp], inpicref->linesize[comp],
     171         172 :                    s->chroma_mode, s->chroma_swap);
     172             :     }
     173             : 
     174         140 :     if (s->has_alpha) {
     175          38 :         comp = s->nb_planes - 1;
     176         114 :         interleave(out->data[comp], inpicref->data[comp],
     177             :                    s->linesize[comp], inlink->h,
     178          38 :                    out->linesize[comp], inpicref->linesize[comp],
     179          38 :                    s->alpha_mode, s->alpha_swap);
     180             :     }
     181             : 
     182         140 :     av_frame_free(&inpicref);
     183         140 :     return ff_filter_frame(outlink, out);
     184             : }
     185             : 
     186             : static const AVFilterPad inputs[] = {
     187             :     {
     188             :         .name         = "default",
     189             :         .type         = AVMEDIA_TYPE_VIDEO,
     190             :         .filter_frame = filter_frame,
     191             :         .config_props = config_input,
     192             :     },
     193             :     { NULL }
     194             : };
     195             : 
     196             : static const AVFilterPad outputs[] = {
     197             :     {
     198             :         .name = "default",
     199             :         .type = AVMEDIA_TYPE_VIDEO,
     200             :     },
     201             :     { NULL }
     202             : };
     203             : 
     204             : AVFilter ff_vf_il = {
     205             :     .name          = "il",
     206             :     .description   = NULL_IF_CONFIG_SMALL("Deinterleave or interleave fields."),
     207             :     .priv_size     = sizeof(IlContext),
     208             :     .query_formats = query_formats,
     209             :     .inputs        = inputs,
     210             :     .outputs       = outputs,
     211             :     .priv_class    = &il_class,
     212             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     213             : };

Generated by: LCOV version 1.13