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

Generated by: LCOV version 1.13