]> git.sesse.net Git - ffmpeg/blob - libavfilter/vf_premultiply.c
Merge commit 'b9ea301e02472d0982b0fa0f80294bd95885bde8'
[ffmpeg] / libavfilter / vf_premultiply.c
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 static int query_formats(AVFilterContext *ctx)
63 {
64     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     return ff_set_common_formats(ctx, ff_make_format_list(s->inplace ? alpha_pix_fmts : no_alpha_pix_fmts));
86 }
87
88 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     for (y = 0; y < h; y++) {
98         for (x = 0; x < w; x++) {
99             dst[x] = ((msrc[x] * (((asrc[x] >> 1) & 1) + asrc[x])) + 128) >> 8;
100         }
101
102         dst  += dlinesize;
103         msrc += mlinesize;
104         asrc += alinesize;
105     }
106 }
107
108 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     for (y = 0; y < h; y++) {
118         for (x = 0; x < w; x++) {
119             dst[x] = ((((msrc[x] - 128) * (((asrc[x] >> 1) & 1) + asrc[x]))) >> 8) + 128;
120         }
121
122         dst  += dlinesize;
123         msrc += mlinesize;
124         asrc += alinesize;
125     }
126 }
127
128 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     for (y = 0; y < h; y++) {
138         for (x = 0; x < w; x++) {
139             dst[x] = ((((msrc[x] - offset) * (((asrc[x] >> 1) & 1) + asrc[x])) + 128) >> 8) + offset;
140         }
141
142         dst  += dlinesize;
143         msrc += mlinesize;
144         asrc += alinesize;
145     }
146 }
147
148 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     const uint16_t *msrc = (const uint16_t *)mmsrc;
156     const uint16_t *asrc = (const uint16_t *)aasrc;
157     uint16_t *dst = (uint16_t *)ddst;
158     int x, y;
159
160     for (y = 0; y < h; y++) {
161         for (x = 0; x < w; x++) {
162             dst[x] = ((msrc[x] * (((asrc[x] >> 1) & 1) + asrc[x])) + half) >> shift;
163         }
164
165         dst  += dlinesize / 2;
166         msrc += mlinesize / 2;
167         asrc += alinesize / 2;
168     }
169 }
170
171 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     const uint16_t *msrc = (const uint16_t *)mmsrc;
179     const uint16_t *asrc = (const uint16_t *)aasrc;
180     uint16_t *dst = (uint16_t *)ddst;
181     int x, y;
182
183     for (y = 0; y < h; y++) {
184         for (x = 0; x < w; x++) {
185             dst[x] = ((((msrc[x] - half) * (((asrc[x] >> 1) & 1) + asrc[x]))) >> shift) + half;
186         }
187
188         dst  += dlinesize / 2;
189         msrc += mlinesize / 2;
190         asrc += alinesize / 2;
191     }
192 }
193
194 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     const uint16_t *msrc = (const uint16_t *)mmsrc;
202     const uint16_t *asrc = (const uint16_t *)aasrc;
203     uint16_t *dst = (uint16_t *)ddst;
204     int x, y;
205
206     for (y = 0; y < h; y++) {
207         for (x = 0; x < w; x++) {
208             dst[x] = ((((msrc[x] - offset) * (((asrc[x] >> 1) & 1) + asrc[x])) + half) >> shift) + offset;
209         }
210
211         dst  += dlinesize / 2;
212         msrc += mlinesize / 2;
213         asrc += alinesize / 2;
214     }
215 }
216
217 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     for (y = 0; y < h; y++) {
227         for (x = 0; x < w; x++) {
228             if (asrc[x] > 0 && asrc[x] < 255)
229                 dst[x] = FFMIN(msrc[x] * 255 / asrc[x], 255);
230             else
231                 dst[x] = msrc[x];
232         }
233
234         dst  += dlinesize;
235         msrc += mlinesize;
236         asrc += alinesize;
237     }
238 }
239
240 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     for (y = 0; y < h; y++) {
250         for (x = 0; x < w; x++) {
251             if (asrc[x] > 0 && asrc[x] < 255)
252                 dst[x] = FFMIN((msrc[x] - 128) * 255 / asrc[x] + 128, 255);
253             else
254                 dst[x] = msrc[x];
255         }
256
257         dst  += dlinesize;
258         msrc += mlinesize;
259         asrc += alinesize;
260     }
261 }
262
263 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     for (y = 0; y < h; y++) {
273         for (x = 0; x < w; x++) {
274             if (asrc[x] > 0 && asrc[x] < 255)
275                 dst[x] = FFMIN(FFMAX(msrc[x] - offset, 0) * 255 / asrc[x] + offset, 255);
276             else
277                 dst[x] = msrc[x];
278         }
279
280         dst  += dlinesize;
281         msrc += mlinesize;
282         asrc += alinesize;
283     }
284 }
285
286 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     const uint16_t *msrc = (const uint16_t *)mmsrc;
294     const uint16_t *asrc = (const uint16_t *)aasrc;
295     uint16_t *dst = (uint16_t *)ddst;
296     int x, y;
297
298     for (y = 0; y < h; y++) {
299         for (x = 0; x < w; x++) {
300             if (asrc[x] > 0 && asrc[x] < max)
301                 dst[x] = FFMIN(msrc[x] * (unsigned)max / asrc[x], max);
302             else
303                 dst[x] = msrc[x];
304         }
305
306         dst  += dlinesize / 2;
307         msrc += mlinesize / 2;
308         asrc += alinesize / 2;
309     }
310 }
311
312 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     const uint16_t *msrc = (const uint16_t *)mmsrc;
320     const uint16_t *asrc = (const uint16_t *)aasrc;
321     uint16_t *dst = (uint16_t *)ddst;
322     int x, y;
323
324     for (y = 0; y < h; y++) {
325         for (x = 0; x < w; x++) {
326             if (asrc[x] > 0 && asrc[x] < max)
327                 dst[x] = FFMAX(FFMIN((msrc[x] - half) * max / asrc[x], half - 1), -half) + half;
328             else
329                 dst[x] = msrc[x];
330         }
331
332         dst  += dlinesize / 2;
333         msrc += mlinesize / 2;
334         asrc += alinesize / 2;
335     }
336 }
337
338 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     const uint16_t *msrc = (const uint16_t *)mmsrc;
346     const uint16_t *asrc = (const uint16_t *)aasrc;
347     uint16_t *dst = (uint16_t *)ddst;
348     int x, y;
349
350     for (y = 0; y < h; y++) {
351         for (x = 0; x < w; x++) {
352             if (asrc[x] > 0 && asrc[x] < max)
353                 dst[x] = FFMAX(FFMIN(FFMAX(msrc[x] - offset, 0) * (unsigned)max / asrc[x] + offset, max), 0);
354             else
355                 dst[x] = msrc[x];
356         }
357
358         dst  += dlinesize / 2;
359         msrc += mlinesize / 2;
360         asrc += alinesize / 2;
361     }
362 }
363
364 static int filter_frame(AVFilterContext *ctx,
365                         AVFrame **out, AVFrame *base, AVFrame *alpha)
366 {
367     PreMultiplyContext *s = ctx->priv;
368     AVFilterLink *outlink = ctx->outputs[0];
369
370     if (ctx->is_disabled) {
371         *out = av_frame_clone(base);
372         if (!*out)
373             return AVERROR(ENOMEM);
374     } else {
375         int p, full, limited;
376
377         *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
378         if (!*out)
379             return AVERROR(ENOMEM);
380         av_frame_copy_props(*out, base);
381
382         full = base->color_range == AVCOL_RANGE_JPEG;
383         limited = base->color_range == AVCOL_RANGE_MPEG;
384
385         if (s->inverse) {
386             switch (outlink->format) {
387             case AV_PIX_FMT_YUV444P:
388             case AV_PIX_FMT_YUVA444P:
389                 s->premultiply[0] = full ? unpremultiply8 : unpremultiply8offset;
390                 s->premultiply[1] = s->premultiply[2] = unpremultiply8yuv;
391                 break;
392             case AV_PIX_FMT_YUVJ444P:
393                 s->premultiply[0] = unpremultiply8;
394                 s->premultiply[1] = s->premultiply[2] = unpremultiply8yuv;
395                 break;
396             case AV_PIX_FMT_GBRP:
397             case AV_PIX_FMT_GBRAP:
398                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? unpremultiply8offset : unpremultiply8;
399                 break;
400             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                 s->premultiply[0] = full ? unpremultiply16 : unpremultiply16offset;
409                 s->premultiply[1] = s->premultiply[2] = unpremultiply16yuv;
410                 break;
411             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                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? unpremultiply16offset : unpremultiply16;
420                 break;
421             case AV_PIX_FMT_GRAY8:
422                 s->premultiply[0] = limited ? unpremultiply8offset : unpremultiply8;
423                 break;
424             case AV_PIX_FMT_GRAY9:
425             case AV_PIX_FMT_GRAY10:
426             case AV_PIX_FMT_GRAY12:
427             case AV_PIX_FMT_GRAY16:
428                 s->premultiply[0] = limited ? unpremultiply16offset : unpremultiply16;
429                 break;
430             }
431         } else {
432             switch (outlink->format) {
433             case AV_PIX_FMT_YUV444P:
434             case AV_PIX_FMT_YUVA444P:
435                 s->premultiply[0] = full ? premultiply8 : premultiply8offset;
436                 s->premultiply[1] = s->premultiply[2] = premultiply8yuv;
437                 break;
438             case AV_PIX_FMT_YUVJ444P:
439                 s->premultiply[0] = premultiply8;
440                 s->premultiply[1] = s->premultiply[2] = premultiply8yuv;
441                 break;
442             case AV_PIX_FMT_GBRP:
443             case AV_PIX_FMT_GBRAP:
444                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? premultiply8offset : premultiply8;
445                 break;
446             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                 s->premultiply[0] = full ? premultiply16 : premultiply16offset;
455                 s->premultiply[1] = s->premultiply[2] = premultiply16yuv;
456                 break;
457             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                 s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? premultiply16offset : premultiply16;
466                 break;
467             case AV_PIX_FMT_GRAY8:
468                 s->premultiply[0] = limited ? premultiply8offset : premultiply8;
469                 break;
470             case AV_PIX_FMT_GRAY9:
471             case AV_PIX_FMT_GRAY10:
472             case AV_PIX_FMT_GRAY12:
473             case AV_PIX_FMT_GRAY16:
474                 s->premultiply[0] = limited ? premultiply16offset : premultiply16;
475                 break;
476             }
477         }
478
479         for (p = 0; p < s->nb_planes; p++) {
480             if (!((1 << p) & s->planes) || p == 3) {
481                 av_image_copy_plane((*out)->data[p], (*out)->linesize[p], base->data[p], base->linesize[p],
482                                     s->linesize[p], s->height[p]);
483                 continue;
484             }
485
486             s->premultiply[p](base->data[p], s->inplace ? alpha->data[3] : alpha->data[0],
487                               (*out)->data[p],
488                               base->linesize[p], s->inplace ? alpha->linesize[3] : alpha->linesize[0],
489                               (*out)->linesize[p],
490                               s->width[p], s->height[p],
491                               s->half, s->inverse ? s->max : s->depth, s->offset);
492         }
493     }
494
495     return 0;
496 }
497
498 static int process_frame(FFFrameSync *fs)
499 {
500     AVFilterContext *ctx = fs->parent;
501     PreMultiplyContext *s = fs->opaque;
502     AVFilterLink *outlink = ctx->outputs[0];
503     AVFrame *out = NULL, *base, *alpha;
504     int ret;
505
506     if ((ret = ff_framesync_get_frame(&s->fs, 0, &base,  0)) < 0 ||
507         (ret = ff_framesync_get_frame(&s->fs, 1, &alpha, 0)) < 0)
508         return ret;
509
510     if ((ret = filter_frame(ctx, &out, base, alpha)) < 0)
511         return ret;
512
513     out->pts = av_rescale_q(base->pts, s->fs.time_base, outlink->time_base);
514
515     return ff_filter_frame(outlink, out);
516 }
517
518 static int config_input(AVFilterLink *inlink)
519 {
520     AVFilterContext *ctx = inlink->dst;
521     PreMultiplyContext *s = ctx->priv;
522     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
523     int vsub, hsub, ret;
524
525     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
526
527     if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
528         return ret;
529
530     hsub = desc->log2_chroma_w;
531     vsub = desc->log2_chroma_h;
532     s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, vsub);
533     s->height[0] = s->height[3] = inlink->h;
534     s->width[1]  = s->width[2]  = AV_CEIL_RSHIFT(inlink->w, hsub);
535     s->width[0]  = s->width[3]  = inlink->w;
536
537     s->depth = desc->comp[0].depth;
538     s->max = (1 << s->depth) - 1;
539     s->half = (1 << s->depth) / 2;
540     s->offset = 16 << (s->depth - 8);
541
542     return 0;
543 }
544
545 static int config_output(AVFilterLink *outlink)
546 {
547     AVFilterContext *ctx = outlink->src;
548     PreMultiplyContext *s = ctx->priv;
549     AVFilterLink *base = ctx->inputs[0];
550     AVFilterLink *alpha;
551     FFFrameSyncIn *in;
552     int ret;
553
554     if (!s->inplace) {
555         alpha = ctx->inputs[1];
556
557         if (base->format != alpha->format) {
558             av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
559             return AVERROR(EINVAL);
560         }
561         if (base->w                       != alpha->w ||
562             base->h                       != alpha->h) {
563             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                    ctx->input_pads[0].name, base->w, base->h,
567                    ctx->input_pads[1].name, alpha->w, alpha->h);
568             return AVERROR(EINVAL);
569         }
570     }
571
572     outlink->w = base->w;
573     outlink->h = base->h;
574     outlink->time_base = base->time_base;
575     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
576     outlink->frame_rate = base->frame_rate;
577
578     if (s->inplace)
579         return 0;
580
581     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
582         return ret;
583
584     in = s->fs.in;
585     in[0].time_base = base->time_base;
586     in[1].time_base = alpha->time_base;
587     in[0].sync   = 1;
588     in[0].before = EXT_STOP;
589     in[0].after  = EXT_INFINITY;
590     in[1].sync   = 1;
591     in[1].before = EXT_STOP;
592     in[1].after  = EXT_INFINITY;
593     s->fs.opaque   = s;
594     s->fs.on_event = process_frame;
595
596     return ff_framesync_configure(&s->fs);
597 }
598
599 static int activate(AVFilterContext *ctx)
600 {
601     PreMultiplyContext *s = ctx->priv;
602
603     if (s->inplace) {
604         AVFrame *frame = NULL;
605         AVFrame *out = NULL;
606         int ret, status;
607         int64_t pts;
608
609         if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) {
610             ret = filter_frame(ctx, &out, frame, frame);
611             av_frame_free(&frame);
612             if (ret < 0)
613                 return ret;
614             ret = ff_filter_frame(ctx->outputs[0], out);
615         }
616         if (ret < 0) {
617             return ret;
618         } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
619             ff_outlink_set_status(ctx->outputs[0], status, pts);
620             return 0;
621         } else {
622             if (ff_outlink_frame_wanted(ctx->outputs[0]))
623                 ff_inlink_request_frame(ctx->inputs[0]);
624             return 0;
625         }
626     } else {
627         return ff_framesync_activate(&s->fs);
628     }
629 }
630
631 static av_cold int init(AVFilterContext *ctx)
632 {
633     PreMultiplyContext *s = ctx->priv;
634     AVFilterPad pad = { 0 };
635     int ret;
636
637     if (!strcmp(ctx->filter->name, "unpremultiply"))
638         s->inverse = 1;
639
640     pad.type         = AVMEDIA_TYPE_VIDEO;
641     pad.name         = av_strdup("main");
642     pad.config_props = config_input;
643     if (!pad.name)
644         return AVERROR(ENOMEM);
645
646     if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) {
647         av_freep(&pad.name);
648         return ret;
649     }
650
651     if (!s->inplace) {
652         pad.type         = AVMEDIA_TYPE_VIDEO;
653         pad.name         = av_strdup("alpha");
654         pad.config_props = NULL;
655         if (!pad.name)
656             return AVERROR(ENOMEM);
657
658         if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) {
659             av_freep(&pad.name);
660             return ret;
661         }
662     }
663
664     return 0;
665 }
666
667 static av_cold void uninit(AVFilterContext *ctx)
668 {
669     PreMultiplyContext *s = ctx->priv;
670
671     if (!s->inplace)
672         ff_framesync_uninit(&s->fs);
673 }
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 */