LCOV - code coverage report
Current view: top level - libavfilter - vf_shuffleplanes.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 36 50 72.0 %
Date: 2017-12-14 01:15:32 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This file is part of FFmpeg.
       3             :  *
       4             :  * FFmpeg is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Lesser General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2.1 of the License, or (at your option) any later version.
       8             :  *
       9             :  * FFmpeg is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Lesser General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public
      15             :  * License along with FFmpeg; if not, write to the Free Software
      16             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      17             :  */
      18             : 
      19             : #include "libavutil/avstring.h"
      20             : #include "libavutil/common.h"
      21             : #include "libavutil/internal.h"
      22             : #include "libavutil/opt.h"
      23             : #include "libavutil/pixdesc.h"
      24             : #include "libavutil/pixfmt.h"
      25             : 
      26             : #include "avfilter.h"
      27             : #include "internal.h"
      28             : #include "video.h"
      29             : 
      30             : typedef struct ShufflePlanesContext {
      31             :     const AVClass *class;
      32             : 
      33             :     /* number of planes in the selected pixel format */
      34             :     int planes;
      35             : 
      36             :     /* mapping indices */
      37             :     int map[4];
      38             : 
      39             :     /* set to 1 if some plane is used more than once, so we need to make a copy */
      40             :     int copy;
      41             : } ShufflePlanesContext;
      42             : 
      43           2 : static av_cold int shuffleplanes_config_input(AVFilterLink *inlink)
      44             : {
      45           2 :     AVFilterContext    *ctx = inlink->dst;
      46           2 :     ShufflePlanesContext *s = ctx->priv;
      47             :     const AVPixFmtDescriptor *desc;
      48           2 :     int used[4] = { 0 };
      49             :     int i;
      50             : 
      51           2 :     s->copy   = 0;
      52           2 :     s->planes = av_pix_fmt_count_planes(inlink->format);
      53           2 :     desc      = av_pix_fmt_desc_get(inlink->format);
      54             : 
      55           9 :     for (i = 0; i < s->planes; i++) {
      56           7 :         if (s->map[i] >= s->planes) {
      57           0 :             av_log(ctx, AV_LOG_ERROR,
      58             :                    "Non-existing input plane #%d mapped to output plane #%d.\n",
      59             :                    s->map[i], i);
      60           0 :             return AVERROR(EINVAL);
      61             :         }
      62             : 
      63          10 :         if ((desc->log2_chroma_h || desc->log2_chroma_w) &&
      64           3 :             (i == 1 || i == 2) != (s->map[i] == 1 || s->map[i] == 2)) {
      65           0 :             av_log(ctx, AV_LOG_ERROR,
      66             :                    "Cannot map between a subsampled chroma plane and a luma "
      67             :                    "or alpha plane.\n");
      68           0 :             return AVERROR(EINVAL);
      69             :         }
      70             : 
      71          14 :         if ((desc->flags & AV_PIX_FMT_FLAG_PAL ||
      72           7 :              desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) &&
      73           0 :             (i == 1) != (s->map[i] == 1)) {
      74           0 :             av_log(ctx, AV_LOG_ERROR,
      75             :                    "Cannot map between a palette plane and a data plane.\n");
      76           0 :             return AVERROR(EINVAL);
      77             :         }
      78           7 :         if (used[s->map[i]])
      79           3 :             s->copy = 1;
      80           7 :         used[s->map[i]]++;
      81             :     }
      82             : 
      83           2 :     return 0;
      84             : }
      85             : 
      86         100 : static int shuffleplanes_filter_frame(AVFilterLink *inlink, AVFrame *frame)
      87             : {
      88         100 :     AVFilterContext          *ctx = inlink->dst;
      89         100 :     ShufflePlanesContext       *s = ctx->priv;
      90         100 :     uint8_t *shuffled_data[4]     = { NULL };
      91         100 :     int      shuffled_linesize[4] = { 0 };
      92             :     int i, ret;
      93             : 
      94         450 :     for (i = 0; i < s->planes; i++) {
      95         350 :         shuffled_data[i]     = frame->data[s->map[i]];
      96         350 :         shuffled_linesize[i] = frame->linesize[s->map[i]];
      97             :     }
      98         100 :     memcpy(frame->data,     shuffled_data,     sizeof(shuffled_data));
      99         100 :     memcpy(frame->linesize, shuffled_linesize, sizeof(shuffled_linesize));
     100             : 
     101         100 :     if (s->copy) {
     102          50 :         AVFrame *copy = ff_get_video_buffer(ctx->outputs[0], frame->width, frame->height);
     103             : 
     104          50 :         if (!copy) {
     105           0 :             ret = AVERROR(ENOMEM);
     106           0 :             goto fail;
     107             :         }
     108             : 
     109          50 :         av_frame_copy(copy, frame);
     110             : 
     111          50 :         ret = av_frame_copy_props(copy, frame);
     112          50 :         if (ret < 0) {
     113           0 :             av_frame_free(&copy);
     114           0 :             goto fail;
     115             :         }
     116             : 
     117          50 :         av_frame_free(&frame);
     118          50 :         frame = copy;
     119             :     }
     120             : 
     121         100 :     return ff_filter_frame(ctx->outputs[0], frame);
     122           0 : fail:
     123           0 :     av_frame_free(&frame);
     124           0 :     return ret;
     125             : }
     126             : 
     127             : #define OFFSET(x) offsetof(ShufflePlanesContext, x)
     128             : #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
     129             : static const AVOption shuffleplanes_options[] = {
     130             :     { "map0", "Index of the input plane to be used as the first output plane ",  OFFSET(map[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, FLAGS },
     131             :     { "map1", "Index of the input plane to be used as the second output plane ", OFFSET(map[1]), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 4, FLAGS },
     132             :     { "map2", "Index of the input plane to be used as the third output plane ",  OFFSET(map[2]), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, FLAGS },
     133             :     { "map3", "Index of the input plane to be used as the fourth output plane ", OFFSET(map[3]), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, 4, FLAGS },
     134             :     { NULL },
     135             : };
     136             : 
     137             : AVFILTER_DEFINE_CLASS(shuffleplanes);
     138             : 
     139             : static const AVFilterPad shuffleplanes_inputs[] = {
     140             :     {
     141             :         .name             = "default",
     142             :         .type             = AVMEDIA_TYPE_VIDEO,
     143             :         .config_props     = shuffleplanes_config_input,
     144             :         .filter_frame     = shuffleplanes_filter_frame,
     145             :         .get_video_buffer = ff_null_get_video_buffer,
     146             :     },
     147             :     { NULL },
     148             : };
     149             : 
     150             : static const AVFilterPad shuffleplanes_outputs[] = {
     151             :     {
     152             :         .name = "default",
     153             :         .type = AVMEDIA_TYPE_VIDEO,
     154             :     },
     155             :     { NULL },
     156             : };
     157             : 
     158             : AVFilter ff_vf_shuffleplanes = {
     159             :     .name         = "shuffleplanes",
     160             :     .description  = NULL_IF_CONFIG_SMALL("Shuffle video planes."),
     161             : 
     162             :     .priv_size    = sizeof(ShufflePlanesContext),
     163             :     .priv_class   = &shuffleplanes_class,
     164             : 
     165             :     .inputs       = shuffleplanes_inputs,
     166             :     .outputs      = shuffleplanes_outputs,
     167             : };

Generated by: LCOV version 1.13