LCOV - code coverage report
Current view: top level - libavfilter - vf_premultiply.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 317 0.0 %
Date: 2017-12-11 04:34:20 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 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/pixdesc.h"
      23             : #include "libavutil/opt.h"
      24             : #include "avfilter.h"
      25             : #include "filters.h"
      26             : #include "formats.h"
      27             : #include "framesync.h"
      28             : #include "internal.h"
      29             : #include "video.h"
      30             : 
      31             : typedef struct PreMultiplyContext {
      32             :     const AVClass *class;
      33             :     int width[4], height[4];
      34             :     int linesize[4];
      35             :     int nb_planes;
      36             :     int planes;
      37             :     int inverse;
      38             :     int inplace;
      39             :     int half, depth, offset, max;
      40             :     FFFrameSync fs;
      41             : 
      42             :     void (*premultiply[4])(const uint8_t *msrc, const uint8_t *asrc,
      43             :                            uint8_t *dst,
      44             :                            ptrdiff_t mlinesize, ptrdiff_t alinesize,
      45             :                            ptrdiff_t dlinesize,
      46             :                            int w, int h,
      47             :                            int half, int shift, int offset);
      48             : } PreMultiplyContext;
      49             : 
      50             : #define OFFSET(x) offsetof(PreMultiplyContext, x)
      51             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
      52             : 
      53             : static const AVOption options[] = {
      54             :     { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS },
      55             :     { "inplace","enable inplace mode", OFFSET(inplace), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
      56             :     { NULL }
      57             : };
      58             : 
      59             : #define premultiply_options options
      60             : AVFILTER_DEFINE_CLASS(premultiply);
      61             : 
      62           0 : static int query_formats(AVFilterContext *ctx)
      63             : {
      64           0 :     PreMultiplyContext *s = ctx->priv;
      65             : 
      66             :     static const enum AVPixelFormat no_alpha_pix_fmts[] = {
      67             :         AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
      68             :         AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
      69             :         AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14,
      70             :         AV_PIX_FMT_YUV444P16,
      71             :         AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
      72             :         AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
      73             :         AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16,
      74             :         AV_PIX_FMT_NONE
      75             :     };
      76             : 
      77             :     static const enum AVPixelFormat alpha_pix_fmts[] = {
      78             :         AV_PIX_FMT_YUVA444P,
      79             :         AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16,
      80             :         AV_PIX_FMT_GBRAP,
      81             :         AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16,
      82             :         AV_PIX_FMT_NONE
      83             :     };
      84             : 
      85           0 :     return ff_set_common_formats(ctx, ff_make_format_list(s->inplace ? alpha_pix_fmts : no_alpha_pix_fmts));
      86             : }
      87             : 
      88           0 : static void premultiply8(const uint8_t *msrc, const uint8_t *asrc,
      89             :                          uint8_t *dst,
      90             :                          ptrdiff_t mlinesize, ptrdiff_t alinesize,
      91             :                          ptrdiff_t dlinesize,
      92             :                          int w, int h,
      93             :                          int half, int shift, int offset)
      94             : {
      95             :     int x, y;
      96             : 
      97           0 :     for (y = 0; y < h; y++) {
      98           0 :         for (x = 0; x < w; x++) {
      99           0 :             dst[x] = ((msrc[x] * (((asrc[x] >> 1) & 1) + asrc[x])) + 128) >> 8;
     100             :         }
     101             : 
     102           0 :         dst  += dlinesize;
     103           0 :         msrc += mlinesize;
     104           0 :         asrc += alinesize;
     105             :     }
     106           0 : }
     107             : 
     108           0 : static void premultiply8yuv(const uint8_t *msrc, const uint8_t *asrc,
     109             :                             uint8_t *dst,
     110             :                             ptrdiff_t mlinesize, ptrdiff_t alinesize,
     111             :                             ptrdiff_t dlinesize,
     112             :                             int w, int h,
     113             :                             int half, int shift, int offset)
     114             : {
     115             :     int x, y;
     116             : 
     117           0 :     for (y = 0; y < h; y++) {
     118           0 :         for (x = 0; x < w; x++) {
     119           0 :             dst[x] = ((((msrc[x] - 128) * (((asrc[x] >> 1) & 1) + asrc[x]))) >> 8) + 128;
     120             :         }
     121             : 
     122           0 :         dst  += dlinesize;
     123           0 :         msrc += mlinesize;
     124           0 :         asrc += alinesize;
     125             :     }
     126           0 : }
     127             : 
     128           0 : static void premultiply8offset(const uint8_t *msrc, const uint8_t *asrc,
     129             :                                uint8_t *dst,
     130             :                                ptrdiff_t mlinesize, ptrdiff_t alinesize,
     131             :                                ptrdiff_t dlinesize,
     132             :                                int w, int h,
     133             :                                int half, int shift, int offset)
     134             : {
     135             :     int x, y;
     136             : 
     137           0 :     for (y = 0; y < h; y++) {
     138           0 :         for (x = 0; x < w; x++) {
     139           0 :             dst[x] = ((((msrc[x] - offset) * (((asrc[x] >> 1) & 1) + asrc[x])) + 128) >> 8) + offset;
     140             :         }
     141             : 
     142           0 :         dst  += dlinesize;
     143           0 :         msrc += mlinesize;
     144           0 :         asrc += alinesize;
     145             :     }
     146           0 : }
     147             : 
     148           0 : static void premultiply16(const uint8_t *mmsrc, const uint8_t *aasrc,
     149             :                           uint8_t *ddst,
     150             :                           ptrdiff_t mlinesize, ptrdiff_t alinesize,
     151             :                           ptrdiff_t dlinesize,
     152             :                           int w, int h,
     153             :                           int half, int shift, int offset)
     154             : {
     155           0 :     const uint16_t *msrc = (const uint16_t *)mmsrc;
     156           0 :     const uint16_t *asrc = (const uint16_t *)aasrc;
     157           0 :     uint16_t *dst = (uint16_t *)ddst;
     158             :     int x, y;
     159             : 
     160           0 :     for (y = 0; y < h; y++) {
     161           0 :         for (x = 0; x < w; x++) {
     162           0 :             dst[x] = ((msrc[x] * (((asrc[x] >> 1) & 1) + asrc[x])) + half) >> shift;
     163             :         }
     164             : 
     165           0 :         dst  += dlinesize / 2;
     166           0 :         msrc += mlinesize / 2;
     167           0 :         asrc += alinesize / 2;
     168             :     }
     169           0 : }
     170             : 
     171           0 : static void premultiply16yuv(const uint8_t *mmsrc, const uint8_t *aasrc,
     172             :                              uint8_t *ddst,
     173             :                              ptrdiff_t mlinesize, ptrdiff_t alinesize,
     174             :                              ptrdiff_t dlinesize,
     175             :                              int w, int h,
     176             :                              int half, int shift, int offset)
     177             : {
     178           0 :     const uint16_t *msrc = (const uint16_t *)mmsrc;
     179           0 :     const uint16_t *asrc = (const uint16_t *)aasrc;
     180           0 :     uint16_t *dst = (uint16_t *)ddst;
     181             :     int x, y;
     182             : 
     183           0 :     for (y = 0; y < h; y++) {
     184           0 :         for (x = 0; x < w; x++) {
     185           0 :             dst[x] = ((((msrc[x] - half) * (((asrc[x] >> 1) & 1) + asrc[x]))) >> shift) + half;
     186             :         }
     187             : 
     188           0 :         dst  += dlinesize / 2;
     189           0 :         msrc += mlinesize / 2;
     190           0 :         asrc += alinesize / 2;
     191             :     }
     192           0 : }
     193             : 
     194           0 : static void premultiply16offset(const uint8_t *mmsrc, const uint8_t *aasrc,
     195             :                                 uint8_t *ddst,
     196             :                                 ptrdiff_t mlinesize, ptrdiff_t alinesize,
     197             :                                 ptrdiff_t dlinesize,
     198             :                                 int w, int h,
     199             :                                 int half, int shift, int offset)
     200             : {
     201           0 :     const uint16_t *msrc = (const uint16_t *)mmsrc;
     202           0 :     const uint16_t *asrc = (const uint16_t *)aasrc;
     203           0 :     uint16_t *dst = (uint16_t *)ddst;
     204             :     int x, y;
     205             : 
     206           0 :     for (y = 0; y < h; y++) {
     207           0 :         for (x = 0; x < w; x++) {
     208           0 :             dst[x] = ((((msrc[x] - offset) * (((asrc[x] >> 1) & 1) + asrc[x])) + half) >> shift) + offset;
     209             :         }
     210             : 
     211           0 :         dst  += dlinesize / 2;
     212           0 :         msrc += mlinesize / 2;
     213           0 :         asrc += alinesize / 2;
     214             :     }
     215           0 : }
     216             : 
     217           0 : static void unpremultiply8(const uint8_t *msrc, const uint8_t *asrc,
     218             :                            uint8_t *dst,
     219             :                            ptrdiff_t mlinesize, ptrdiff_t alinesize,
     220             :                            ptrdiff_t dlinesize,
     221             :                            int w, int h,
     222             :                            int half, int max, int offset)
     223             : {
     224             :     int x, y;
     225             : 
     226           0 :     for (y = 0; y < h; y++) {
     227           0 :         for (x = 0; x < w; x++) {
     228           0 :             if (asrc[x] > 0 && asrc[x] < 255)
     229           0 :                 dst[x] = FFMIN(msrc[x] * 255 / asrc[x], 255);
     230             :             else
     231           0 :                 dst[x] = msrc[x];
     232             :         }
     233             : 
     234           0 :         dst  += dlinesize;
     235           0 :         msrc += mlinesize;
     236           0 :         asrc += alinesize;
     237             :     }
     238           0 : }
     239             : 
     240           0 : static void unpremultiply8yuv(const uint8_t *msrc, const uint8_t *asrc,
     241             :                               uint8_t *dst,
     242             :                               ptrdiff_t mlinesize, ptrdiff_t alinesize,
     243             :                               ptrdiff_t dlinesize,
     244             :                               int w, int h,
     245             :                               int half, int max, int offset)
     246             : {
     247             :     int x, y;
     248             : 
     249           0 :     for (y = 0; y < h; y++) {
     250           0 :         for (x = 0; x < w; x++) {
     251           0 :             if (asrc[x] > 0 && asrc[x] < 255)
     252           0 :                 dst[x] = FFMIN((msrc[x] - 128) * 255 / asrc[x] + 128, 255);
     253             :             else
     254           0 :                 dst[x] = msrc[x];
     255             :         }
     256             : 
     257           0 :         dst  += dlinesize;
     258           0 :         msrc += mlinesize;
     259           0 :         asrc += alinesize;
     260             :     }
     261           0 : }
     262             : 
     263           0 : static void unpremultiply8offset(const uint8_t *msrc, const uint8_t *asrc,
     264             :                                  uint8_t *dst,
     265             :                                  ptrdiff_t mlinesize, ptrdiff_t alinesize,
     266             :                                  ptrdiff_t dlinesize,
     267             :                                  int w, int h,
     268             :                                  int half, int max, int offset)
     269             : {
     270             :     int x, y;
     271             : 
     272           0 :     for (y = 0; y < h; y++) {
     273           0 :         for (x = 0; x < w; x++) {
     274           0 :             if (asrc[x] > 0 && asrc[x] < 255)
     275           0 :                 dst[x] = FFMIN((msrc[x] - offset) * 255 / asrc[x] + offset, 255);
     276             :             else
     277           0 :                 dst[x] = msrc[x];
     278             :         }
     279             : 
     280           0 :         dst  += dlinesize;
     281           0 :         msrc += mlinesize;
     282           0 :         asrc += alinesize;
     283             :     }
     284           0 : }
     285             : 
     286           0 : static void unpremultiply16(const uint8_t *mmsrc, const uint8_t *aasrc,
     287             :                             uint8_t *ddst,
     288             :                             ptrdiff_t mlinesize, ptrdiff_t alinesize,
     289             :                             ptrdiff_t dlinesize,
     290             :                             int w, int h,
     291             :                             int half, int max, int offset)
     292             : {
     293           0 :     const uint16_t *msrc = (const uint16_t *)mmsrc;
     294           0 :     const uint16_t *asrc = (const uint16_t *)aasrc;
     295           0 :     uint16_t *dst = (uint16_t *)ddst;
     296             :     int x, y;
     297             : 
     298           0 :     for (y = 0; y < h; y++) {
     299           0 :         for (x = 0; x < w; x++) {
     300           0 :             if (asrc[x] > 0 && asrc[x] < max)
     301           0 :                 dst[x] = FFMIN(msrc[x] * (unsigned)max / asrc[x], max);
     302             :             else
     303           0 :                 dst[x] = msrc[x];
     304             :         }
     305             : 
     306           0 :         dst  += dlinesize / 2;
     307           0 :         msrc += mlinesize / 2;
     308           0 :         asrc += alinesize / 2;
     309             :     }
     310           0 : }
     311             : 
     312           0 : static void unpremultiply16yuv(const uint8_t *mmsrc, const uint8_t *aasrc,
     313             :                                uint8_t *ddst,
     314             :                                ptrdiff_t mlinesize, ptrdiff_t alinesize,
     315             :                                ptrdiff_t dlinesize,
     316             :                                int w, int h,
     317             :                                int half, int max, int offset)
     318             : {
     319           0 :     const uint16_t *msrc = (const uint16_t *)mmsrc;
     320           0 :     const uint16_t *asrc = (const uint16_t *)aasrc;
     321           0 :     uint16_t *dst = (uint16_t *)ddst;
     322             :     int x, y;
     323             : 
     324           0 :     for (y = 0; y < h; y++) {
     325           0 :         for (x = 0; x < w; x++) {
     326           0 :             if (asrc[x] > 0 && asrc[x] < max)
     327           0 :                 dst[x] = FFMAX(FFMIN((msrc[x] - half) * max / asrc[x], half - 1), -half) + half;
     328             :             else
     329           0 :                 dst[x] = msrc[x];
     330             :         }
     331             : 
     332           0 :         dst  += dlinesize / 2;
     333           0 :         msrc += mlinesize / 2;
     334           0 :         asrc += alinesize / 2;
     335             :     }
     336           0 : }
     337             : 
     338           0 : static void unpremultiply16offset(const uint8_t *mmsrc, const uint8_t *aasrc,
     339             :                                   uint8_t *ddst,
     340             :                                   ptrdiff_t mlinesize, ptrdiff_t alinesize,
     341             :                                   ptrdiff_t dlinesize,
     342             :                                   int w, int h,
     343             :                                   int half, int max, int offset)
     344             : {
     345           0 :     const uint16_t *msrc = (const uint16_t *)mmsrc;
     346           0 :     const uint16_t *asrc = (const uint16_t *)aasrc;
     347           0 :     uint16_t *dst = (uint16_t *)ddst;
     348             :     int x, y;
     349             : 
     350           0 :     for (y = 0; y < h; y++) {
     351           0 :         for (x = 0; x < w; x++) {
     352           0 :             if (asrc[x] > 0 && asrc[x] < max)
     353           0 :                 dst[x] = FFMAX(FFMIN((msrc[x] - offset) * (unsigned)max / asrc[x] + offset, max), 0);
     354             :             else
     355           0 :                 dst[x] = msrc[x];
     356             :         }
     357             : 
     358           0 :         dst  += dlinesize / 2;
     359           0 :         msrc += mlinesize / 2;
     360           0 :         asrc += alinesize / 2;
     361             :     }
     362           0 : }
     363             : 
     364           0 : static int filter_frame(AVFilterContext *ctx,
     365             :                         AVFrame **out, AVFrame *base, AVFrame *alpha)
     366             : {
     367           0 :     PreMultiplyContext *s = ctx->priv;
     368           0 :     AVFilterLink *outlink = ctx->outputs[0];
     369             : 
     370           0 :     if (ctx->is_disabled) {
     371           0 :         *out = av_frame_clone(base);
     372           0 :         if (!*out)
     373           0 :             return AVERROR(ENOMEM);
     374             :     } else {
     375             :         int p, full, limited;
     376             : 
     377           0 :         *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     378           0 :         if (!*out)
     379           0 :             return AVERROR(ENOMEM);
     380           0 :         av_frame_copy_props(*out, base);
     381             : 
     382           0 :         full = base->color_range == AVCOL_RANGE_JPEG;
     383           0 :         limited = base->color_range == AVCOL_RANGE_MPEG;
     384             : 
     385           0 :         if (s->inverse) {
     386           0 :             switch (outlink->format) {
     387           0 :             case AV_PIX_FMT_YUV444P:
     388             :             case AV_PIX_FMT_YUVA444P:
     389           0 :                 s->premultiply[0] = full ? unpremultiply8 : unpremultiply8offset;
     390           0 :                 s->premultiply[1] = s->premultiply[2] = unpremultiply8yuv;
     391           0 :                 break;
     392           0 :             case AV_PIX_FMT_YUVJ444P:
     393           0 :                 s->premultiply[0] = unpremultiply8;
     394           0 :                 s->premultiply[1] = s->premultiply[2] = unpremultiply8yuv;
     395           0 :                 break;
     396           0 :             case AV_PIX_FMT_GBRP:
     397             :             case AV_PIX_FMT_GBRAP:
     398           0 :                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? unpremultiply8offset : unpremultiply8;
     399           0 :                 break;
     400           0 :             case AV_PIX_FMT_YUV444P9:
     401             :             case AV_PIX_FMT_YUVA444P9:
     402             :             case AV_PIX_FMT_YUV444P10:
     403             :             case AV_PIX_FMT_YUVA444P10:
     404             :             case AV_PIX_FMT_YUV444P12:
     405             :             case AV_PIX_FMT_YUV444P14:
     406             :             case AV_PIX_FMT_YUV444P16:
     407             :             case AV_PIX_FMT_YUVA444P16:
     408           0 :                 s->premultiply[0] = full ? unpremultiply16 : unpremultiply16offset;
     409           0 :                 s->premultiply[1] = s->premultiply[2] = unpremultiply16yuv;
     410           0 :                 break;
     411           0 :             case AV_PIX_FMT_GBRP9:
     412             :             case AV_PIX_FMT_GBRP10:
     413             :             case AV_PIX_FMT_GBRAP10:
     414             :             case AV_PIX_FMT_GBRP12:
     415             :             case AV_PIX_FMT_GBRAP12:
     416             :             case AV_PIX_FMT_GBRP14:
     417             :             case AV_PIX_FMT_GBRP16:
     418             :             case AV_PIX_FMT_GBRAP16:
     419           0 :                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? unpremultiply16offset : unpremultiply16;
     420           0 :                 break;
     421           0 :             case AV_PIX_FMT_GRAY8:
     422           0 :                 s->premultiply[0] = limited ? unpremultiply8offset : unpremultiply8;
     423           0 :                 break;
     424           0 :             case AV_PIX_FMT_GRAY9:
     425             :             case AV_PIX_FMT_GRAY10:
     426             :             case AV_PIX_FMT_GRAY12:
     427             :             case AV_PIX_FMT_GRAY16:
     428           0 :                 s->premultiply[0] = limited ? unpremultiply16offset : unpremultiply16;
     429           0 :                 break;
     430             :             }
     431             :         } else {
     432           0 :             switch (outlink->format) {
     433           0 :             case AV_PIX_FMT_YUV444P:
     434             :             case AV_PIX_FMT_YUVA444P:
     435           0 :                 s->premultiply[0] = full ? premultiply8 : premultiply8offset;
     436           0 :                 s->premultiply[1] = s->premultiply[2] = premultiply8yuv;
     437           0 :                 break;
     438           0 :             case AV_PIX_FMT_YUVJ444P:
     439           0 :                 s->premultiply[0] = premultiply8;
     440           0 :                 s->premultiply[1] = s->premultiply[2] = premultiply8yuv;
     441           0 :                 break;
     442           0 :             case AV_PIX_FMT_GBRP:
     443             :             case AV_PIX_FMT_GBRAP:
     444           0 :                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? premultiply8offset : premultiply8;
     445           0 :                 break;
     446           0 :             case AV_PIX_FMT_YUV444P9:
     447             :             case AV_PIX_FMT_YUVA444P9:
     448             :             case AV_PIX_FMT_YUV444P10:
     449             :             case AV_PIX_FMT_YUVA444P10:
     450             :             case AV_PIX_FMT_YUV444P12:
     451             :             case AV_PIX_FMT_YUV444P14:
     452             :             case AV_PIX_FMT_YUV444P16:
     453             :             case AV_PIX_FMT_YUVA444P16:
     454           0 :                 s->premultiply[0] = full ? premultiply16 : premultiply16offset;
     455           0 :                 s->premultiply[1] = s->premultiply[2] = premultiply16yuv;
     456           0 :                 break;
     457           0 :             case AV_PIX_FMT_GBRP9:
     458             :             case AV_PIX_FMT_GBRP10:
     459             :             case AV_PIX_FMT_GBRAP10:
     460             :             case AV_PIX_FMT_GBRP12:
     461             :             case AV_PIX_FMT_GBRAP12:
     462             :             case AV_PIX_FMT_GBRP14:
     463             :             case AV_PIX_FMT_GBRP16:
     464             :             case AV_PIX_FMT_GBRAP16:
     465           0 :                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? premultiply16offset : premultiply16;
     466           0 :                 break;
     467           0 :             case AV_PIX_FMT_GRAY8:
     468           0 :                 s->premultiply[0] = limited ? premultiply8offset : premultiply8;
     469           0 :                 break;
     470           0 :             case AV_PIX_FMT_GRAY9:
     471             :             case AV_PIX_FMT_GRAY10:
     472             :             case AV_PIX_FMT_GRAY12:
     473             :             case AV_PIX_FMT_GRAY16:
     474           0 :                 s->premultiply[0] = limited ? premultiply16offset : premultiply16;
     475           0 :                 break;
     476             :             }
     477             :         }
     478             : 
     479           0 :         for (p = 0; p < s->nb_planes; p++) {
     480           0 :             if (!((1 << p) & s->planes) || p == 3) {
     481           0 :                 av_image_copy_plane((*out)->data[p], (*out)->linesize[p], base->data[p], base->linesize[p],
     482             :                                     s->linesize[p], s->height[p]);
     483           0 :                 continue;
     484             :             }
     485             : 
     486           0 :             s->premultiply[p](base->data[p], s->inplace ? alpha->data[3] : alpha->data[0],
     487           0 :                               (*out)->data[p],
     488           0 :                               base->linesize[p], s->inplace ? alpha->linesize[3] : alpha->linesize[0],
     489           0 :                               (*out)->linesize[p],
     490             :                               s->width[p], s->height[p],
     491           0 :                               s->half, s->inverse ? s->max : s->depth, s->offset);
     492             :         }
     493             :     }
     494             : 
     495           0 :     return 0;
     496             : }
     497             : 
     498           0 : static int process_frame(FFFrameSync *fs)
     499             : {
     500           0 :     AVFilterContext *ctx = fs->parent;
     501           0 :     PreMultiplyContext *s = fs->opaque;
     502           0 :     AVFilterLink *outlink = ctx->outputs[0];
     503           0 :     AVFrame *out = NULL, *base, *alpha;
     504             :     int ret;
     505             : 
     506           0 :     if ((ret = ff_framesync_get_frame(&s->fs, 0, &base,  0)) < 0 ||
     507           0 :         (ret = ff_framesync_get_frame(&s->fs, 1, &alpha, 0)) < 0)
     508           0 :         return ret;
     509             : 
     510           0 :     if ((ret = filter_frame(ctx, &out, base, alpha)) < 0)
     511           0 :         return ret;
     512             : 
     513           0 :     out->pts = av_rescale_q(base->pts, s->fs.time_base, outlink->time_base);
     514             : 
     515           0 :     return ff_filter_frame(outlink, out);
     516             : }
     517             : 
     518           0 : static int config_input(AVFilterLink *inlink)
     519             : {
     520           0 :     AVFilterContext *ctx = inlink->dst;
     521           0 :     PreMultiplyContext *s = ctx->priv;
     522           0 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     523             :     int vsub, hsub, ret;
     524             : 
     525           0 :     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
     526             : 
     527           0 :     if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
     528           0 :         return ret;
     529             : 
     530           0 :     hsub = desc->log2_chroma_w;
     531           0 :     vsub = desc->log2_chroma_h;
     532           0 :     s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, vsub);
     533           0 :     s->height[0] = s->height[3] = inlink->h;
     534           0 :     s->width[1]  = s->width[2]  = AV_CEIL_RSHIFT(inlink->w, hsub);
     535           0 :     s->width[0]  = s->width[3]  = inlink->w;
     536             : 
     537           0 :     s->depth = desc->comp[0].depth;
     538           0 :     s->max = (1 << s->depth) - 1;
     539           0 :     s->half = (1 << s->depth) / 2;
     540           0 :     s->offset = 16 << (s->depth - 8);
     541             : 
     542           0 :     return 0;
     543             : }
     544             : 
     545           0 : static int config_output(AVFilterLink *outlink)
     546             : {
     547           0 :     AVFilterContext *ctx = outlink->src;
     548           0 :     PreMultiplyContext *s = ctx->priv;
     549           0 :     AVFilterLink *base = ctx->inputs[0];
     550             :     AVFilterLink *alpha;
     551             :     FFFrameSyncIn *in;
     552             :     int ret;
     553             : 
     554           0 :     if (!s->inplace) {
     555           0 :         alpha = ctx->inputs[1];
     556             : 
     557           0 :         if (base->format != alpha->format) {
     558           0 :             av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
     559           0 :             return AVERROR(EINVAL);
     560             :         }
     561           0 :         if (base->w                       != alpha->w ||
     562           0 :             base->h                       != alpha->h) {
     563           0 :             av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
     564             :                    "(size %dx%d) do not match the corresponding "
     565             :                    "second input link %s parameters (%dx%d) ",
     566           0 :                    ctx->input_pads[0].name, base->w, base->h,
     567           0 :                    ctx->input_pads[1].name, alpha->w, alpha->h);
     568           0 :             return AVERROR(EINVAL);
     569             :         }
     570             :     }
     571             : 
     572           0 :     outlink->w = base->w;
     573           0 :     outlink->h = base->h;
     574           0 :     outlink->time_base = base->time_base;
     575           0 :     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
     576           0 :     outlink->frame_rate = base->frame_rate;
     577             : 
     578           0 :     if (s->inplace)
     579           0 :         return 0;
     580             : 
     581           0 :     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
     582           0 :         return ret;
     583             : 
     584           0 :     in = s->fs.in;
     585           0 :     in[0].time_base = base->time_base;
     586           0 :     in[1].time_base = alpha->time_base;
     587           0 :     in[0].sync   = 1;
     588           0 :     in[0].before = EXT_STOP;
     589           0 :     in[0].after  = EXT_INFINITY;
     590           0 :     in[1].sync   = 1;
     591           0 :     in[1].before = EXT_STOP;
     592           0 :     in[1].after  = EXT_INFINITY;
     593           0 :     s->fs.opaque   = s;
     594           0 :     s->fs.on_event = process_frame;
     595             : 
     596           0 :     return ff_framesync_configure(&s->fs);
     597             : }
     598             : 
     599           0 : static int activate(AVFilterContext *ctx)
     600             : {
     601           0 :     PreMultiplyContext *s = ctx->priv;
     602             : 
     603           0 :     if (s->inplace) {
     604           0 :         AVFrame *frame = NULL;
     605           0 :         AVFrame *out = NULL;
     606             :         int ret, status;
     607             :         int64_t pts;
     608             : 
     609           0 :         if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) {
     610           0 :             ret = filter_frame(ctx, &out, frame, frame);
     611           0 :             av_frame_free(&frame);
     612           0 :             if (ret < 0)
     613           0 :                 return ret;
     614           0 :             ret = ff_filter_frame(ctx->outputs[0], out);
     615             :         }
     616           0 :         if (ret < 0) {
     617           0 :             return ret;
     618           0 :         } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
     619           0 :             ff_outlink_set_status(ctx->outputs[0], status, pts);
     620           0 :             return 0;
     621             :         } else {
     622           0 :             if (ff_outlink_frame_wanted(ctx->outputs[0]))
     623           0 :                 ff_inlink_request_frame(ctx->inputs[0]);
     624           0 :             return 0;
     625             :         }
     626             :     } else {
     627           0 :         return ff_framesync_activate(&s->fs);
     628             :     }
     629             : }
     630             : 
     631           0 : static av_cold int init(AVFilterContext *ctx)
     632             : {
     633           0 :     PreMultiplyContext *s = ctx->priv;
     634           0 :     AVFilterPad pad = { 0 };
     635             :     int ret;
     636             : 
     637           0 :     if (!strcmp(ctx->filter->name, "unpremultiply"))
     638           0 :         s->inverse = 1;
     639             : 
     640           0 :     pad.type         = AVMEDIA_TYPE_VIDEO;
     641           0 :     pad.name         = av_strdup("main");
     642           0 :     pad.config_props = config_input;
     643           0 :     if (!pad.name)
     644           0 :         return AVERROR(ENOMEM);
     645             : 
     646           0 :     if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) {
     647           0 :         av_freep(&pad.name);
     648           0 :         return ret;
     649             :     }
     650             : 
     651           0 :     if (!s->inplace) {
     652           0 :         pad.type         = AVMEDIA_TYPE_VIDEO;
     653           0 :         pad.name         = av_strdup("alpha");
     654           0 :         pad.config_props = NULL;
     655           0 :         if (!pad.name)
     656           0 :             return AVERROR(ENOMEM);
     657             : 
     658           0 :         if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) {
     659           0 :             av_freep(&pad.name);
     660           0 :             return ret;
     661             :         }
     662             :     }
     663             : 
     664           0 :     return 0;
     665             : }
     666             : 
     667           0 : static av_cold void uninit(AVFilterContext *ctx)
     668             : {
     669           0 :     PreMultiplyContext *s = ctx->priv;
     670             : 
     671           0 :     if (!s->inplace)
     672           0 :         ff_framesync_uninit(&s->fs);
     673           0 : }
     674             : 
     675             : static const AVFilterPad premultiply_outputs[] = {
     676             :     {
     677             :         .name          = "default",
     678             :         .type          = AVMEDIA_TYPE_VIDEO,
     679             :         .config_props  = config_output,
     680             :     },
     681             :     { NULL }
     682             : };
     683             : 
     684             : #if CONFIG_PREMULTIPLY_FILTER
     685             : 
     686             : AVFilter ff_vf_premultiply = {
     687             :     .name          = "premultiply",
     688             :     .description   = NULL_IF_CONFIG_SMALL("PreMultiply first stream with first plane of second stream."),
     689             :     .priv_size     = sizeof(PreMultiplyContext),
     690             :     .init          = init,
     691             :     .uninit        = uninit,
     692             :     .query_formats = query_formats,
     693             :     .activate      = activate,
     694             :     .inputs        = NULL,
     695             :     .outputs       = premultiply_outputs,
     696             :     .priv_class    = &premultiply_class,
     697             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
     698             :                      AVFILTER_FLAG_DYNAMIC_INPUTS,
     699             : };
     700             : 
     701             : #endif /* CONFIG_PREMULTIPLY_FILTER */
     702             : 
     703             : #if CONFIG_UNPREMULTIPLY_FILTER
     704             : 
     705             : #define unpremultiply_options options
     706             : AVFILTER_DEFINE_CLASS(unpremultiply);
     707             : 
     708             : AVFilter ff_vf_unpremultiply = {
     709             :     .name          = "unpremultiply",
     710             :     .description   = NULL_IF_CONFIG_SMALL("UnPreMultiply first stream with first plane of second stream."),
     711             :     .priv_size     = sizeof(PreMultiplyContext),
     712             :     .init          = init,
     713             :     .uninit        = uninit,
     714             :     .query_formats = query_formats,
     715             :     .activate      = activate,
     716             :     .inputs        = NULL,
     717             :     .outputs       = premultiply_outputs,
     718             :     .priv_class    = &unpremultiply_class,
     719             :     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
     720             :                      AVFILTER_FLAG_DYNAMIC_INPUTS,
     721             : };
     722             : 
     723             : #endif /* CONFIG_UNPREMULTIPLY_FILTER */

Generated by: LCOV version 1.13