LCOV - code coverage report
Current view: top level - libavfilter - vf_despill.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 51 0.0 %
Date: 2017-12-13 10:57:33 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 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/opt.h"
      22             : #include "libavutil/imgutils.h"
      23             : #include "avfilter.h"
      24             : #include "formats.h"
      25             : #include "internal.h"
      26             : #include "video.h"
      27             : 
      28             : typedef struct DespillContext {
      29             :     const AVClass *class;
      30             : 
      31             :     int co[4]; /* color offsets rgba */
      32             : 
      33             :     int alpha;
      34             :     int type;
      35             :     float spillmix;
      36             :     float spillexpand;
      37             :     float redscale;
      38             :     float greenscale;
      39             :     float bluescale;
      40             :     float brightness;
      41             : } DespillContext;
      42             : 
      43           0 : static int do_despill_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
      44             : {
      45           0 :     DespillContext *s = ctx->priv;
      46           0 :     AVFrame *frame = arg;
      47           0 :     const int ro = s->co[0], go = s->co[1], bo = s->co[2], ao = s->co[3];
      48           0 :     const int slice_start = (frame->height * jobnr) / nb_jobs;
      49           0 :     const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
      50           0 :     const float brightness = s->brightness;
      51           0 :     const float redscale = s->redscale;
      52           0 :     const float greenscale = s->greenscale;
      53           0 :     const float bluescale = s->bluescale;
      54           0 :     const float spillmix = s->spillmix;
      55           0 :     const float factor = (1.f - spillmix) * (1.f - s->spillexpand);
      56             :     float red, green, blue;
      57             :     int x, y;
      58             : 
      59           0 :     for (y = slice_start; y < slice_end; y++) {
      60           0 :         uint8_t *dst = frame->data[0] + y * frame->linesize[0];
      61             : 
      62           0 :         for (x = 0; x < frame->width; x++) {
      63             :             float spillmap;
      64             : 
      65           0 :             red   = dst[x * 4 + ro] / 255.f;
      66           0 :             green = dst[x * 4 + go] / 255.f;
      67           0 :             blue  = dst[x * 4 + bo] / 255.f;
      68             : 
      69           0 :             if (s->type) {
      70           0 :                 spillmap = FFMAX(blue  - (red * spillmix + green * factor), 0.f);
      71             :             } else {
      72           0 :                 spillmap = FFMAX(green - (red * spillmix + blue  * factor), 0.f);
      73             :             }
      74             : 
      75           0 :             red   = FFMAX(red   + spillmap * redscale   + brightness * spillmap, 0.f);
      76           0 :             green = FFMAX(green + spillmap * greenscale + brightness * spillmap, 0.f);
      77           0 :             blue  = FFMAX(blue  + spillmap * bluescale  + brightness * spillmap, 0.f);
      78             : 
      79           0 :             dst[x * 4 + ro] = av_clip_uint8(red   * 255);
      80           0 :             dst[x * 4 + go] = av_clip_uint8(green * 255);
      81           0 :             dst[x * 4 + bo] = av_clip_uint8(blue  * 255);
      82           0 :             if (s->alpha) {
      83           0 :                 spillmap = 1.f - spillmap;
      84           0 :                 dst[x * 4 + ao] = av_clip_uint8(spillmap * 255);
      85             :             }
      86             :         }
      87             :     }
      88             : 
      89           0 :     return 0;
      90             : }
      91             : 
      92           0 : static int filter_frame(AVFilterLink *link, AVFrame *frame)
      93             : {
      94           0 :     AVFilterContext *ctx = link->dst;
      95             :     int ret;
      96             : 
      97           0 :     if (ret = av_frame_make_writable(frame))
      98           0 :         return ret;
      99             : 
     100           0 :     if (ret = ctx->internal->execute(ctx, do_despill_slice, frame, NULL, FFMIN(frame->height, ff_filter_get_nb_threads(ctx))))
     101           0 :         return ret;
     102             : 
     103           0 :     return ff_filter_frame(ctx->outputs[0], frame);
     104             : }
     105             : 
     106           0 : static av_cold int config_output(AVFilterLink *outlink)
     107             : {
     108           0 :     AVFilterContext *ctx = outlink->src;
     109           0 :     DespillContext *s = ctx->priv;
     110           0 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     111             :     int i;
     112             : 
     113           0 :     for (i = 0; i < 4; ++i)
     114           0 :         s->co[i] = desc->comp[i].offset;
     115             : 
     116           0 :     return 0;
     117             : }
     118             : 
     119           0 : static av_cold int query_formats(AVFilterContext *ctx)
     120             : {
     121             :     static const enum AVPixelFormat pixel_fmts[] = {
     122             :         AV_PIX_FMT_ARGB,
     123             :         AV_PIX_FMT_RGBA,
     124             :         AV_PIX_FMT_ABGR,
     125             :         AV_PIX_FMT_BGRA,
     126             :         AV_PIX_FMT_NONE
     127             :     };
     128           0 :     AVFilterFormats *formats = NULL;
     129             : 
     130           0 :     formats = ff_make_format_list(pixel_fmts);
     131           0 :     if (!formats)
     132           0 :         return AVERROR(ENOMEM);
     133             : 
     134           0 :     return ff_set_common_formats(ctx, formats);
     135             : }
     136             : 
     137             : static const AVFilterPad despill_inputs[] = {
     138             :     {
     139             :         .name         = "default",
     140             :         .type         = AVMEDIA_TYPE_VIDEO,
     141             :         .filter_frame = filter_frame,
     142             :     },
     143             :     { NULL }
     144             : };
     145             : 
     146             : static const AVFilterPad despill_outputs[] = {
     147             :     {
     148             :         .name         = "default",
     149             :         .type         = AVMEDIA_TYPE_VIDEO,
     150             :         .config_props = config_output,
     151             :     },
     152             :     { NULL }
     153             : };
     154             : 
     155             : #define OFFSET(x) offsetof(DespillContext, x)
     156             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
     157             : 
     158             : static const AVOption despill_options[] = {
     159             :     { "type",       "set the screen type",     OFFSET(type),        AV_OPT_TYPE_INT,     {.i64=0},     0,   1, FLAGS, "type" },
     160             :     {   "green",    "greenscreen",             0,                   AV_OPT_TYPE_CONST,   {.i64=0},     0,   0, FLAGS, "type" },
     161             :     {   "blue",     "bluescreen",              0,                   AV_OPT_TYPE_CONST,   {.i64=1},     0,   0, FLAGS, "type" },
     162             :     { "mix",        "set the spillmap mix",    OFFSET(spillmix),    AV_OPT_TYPE_FLOAT,   {.dbl=0.5},   0,   1, FLAGS },
     163             :     { "expand",     "set the spillmap expand", OFFSET(spillexpand), AV_OPT_TYPE_FLOAT,   {.dbl=0},     0,   1, FLAGS },
     164             :     { "red",        "set red scale",           OFFSET(redscale),    AV_OPT_TYPE_FLOAT,   {.dbl=0},  -100, 100, FLAGS },
     165             :     { "green",      "set green scale",         OFFSET(greenscale),  AV_OPT_TYPE_FLOAT,   {.dbl=-1}, -100, 100, FLAGS },
     166             :     { "blue",       "set blue scale",          OFFSET(bluescale),   AV_OPT_TYPE_FLOAT,   {.dbl=0},  -100, 100, FLAGS },
     167             :     { "brightness", "set brightness",          OFFSET(brightness),  AV_OPT_TYPE_FLOAT,   {.dbl=0},   -10,  10, FLAGS },
     168             :     { "alpha",      "change alpha component",  OFFSET(alpha),       AV_OPT_TYPE_BOOL,    {.i64=0},     0,   1, FLAGS },
     169             :     { NULL }
     170             : };
     171             : 
     172             : AVFILTER_DEFINE_CLASS(despill);
     173             : 
     174             : AVFilter ff_vf_despill = {
     175             :     .name          = "despill",
     176             :     .description   = NULL_IF_CONFIG_SMALL("Despill video."),
     177             :     .priv_size     = sizeof(DespillContext),
     178             :     .priv_class    = &despill_class,
     179             :     .query_formats = query_formats,
     180             :     .inputs        = despill_inputs,
     181             :     .outputs       = despill_outputs,
     182             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     183             : };

Generated by: LCOV version 1.13