FFmpeg: libavfilter/vf_pullup.c Source File
Go to the documentation of this file. 1 /*
2 * Copyright (c) 2003 Rich Felker
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 General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
30
31 #define F_HAVE_BREAKS 1
32 #define F_HAVE_AFFINITY 2
33
36
37 #define OFFSET(x) offsetof(PullupContext, x)
38 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
39
51 };
52
54
63 };
64
65 #define ABS(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
66
67 static int diff_c(
const uint8_t *
a,
const uint8_t *
b, ptrdiff_t
s)
68 {
70
71 for (
i = 0;
i < 4;
i++) {
72 for (j = 0; j < 8; j++)
76 }
77
79 }
80
81 static int comb_c(
const uint8_t *
a,
const uint8_t *
b, ptrdiff_t
s)
82 {
84
85 for (
i = 0;
i < 4;
i++) {
86 for (j = 0; j < 8; j++)
87 comb +=
ABS((
a[j] << 1) -
b[j -
s] -
b[j ]) +
88 ABS((
b[j] << 1) -
a[j ] -
a[j +
s]);
91 }
92
93 return comb;
94 }
95
96 static int var_c(
const uint8_t *
a,
const uint8_t *
b, ptrdiff_t
s)
97 {
99
100 for (
i = 0;
i < 3;
i++) {
101 for (j = 0; j < 8; j++)
102 var +=
ABS(
a[j] -
a[j +
s]);
104 }
105
106 return 4 * var; /* match comb scaling */
107 }
108
110 {
114
115 if (!
f->diffs || !
f->combs || !
f->vars) {
120 }
121 return 0;
122 }
123
125 {
127 do {
130 break;
135 memset(
f, 0,
sizeof(*
f));
// clear all pointers to avoid stale ones
139 }
140
142 {
144
148
152 }
153
159 }
160
166 }
167 }
168
171
172 return head;
173 }
174
176 {
180 int mp =
s->metric_plane;
181
183
184 if (
mp + 1 >
s->nb_planes) {
187 }
188
190 s->planeheight[0] =
s->planeheight[3] =
inlink->h;
192 s->planewidth[0] =
s->planewidth[3] =
inlink->w;
193
194 s->metric_w = (
s->planewidth[
mp] - ((
s->junk_left +
s->junk_right) << 3)) >> 3;
195 s->metric_h = (
s->planeheight[
mp] - ((
s->junk_top +
s->junk_bottom) << 1)) >> 3;
196 s->metric_offset = (
s->junk_left << 3) + (
s->junk_top << 1) *
s->planewidth[
mp];
197 s->metric_length =
s->metric_w *
s->metric_h;
198
201
205
209
210 #if ARCH_X86
212 #endif
213 return 0;
214 }
215
217 {
220
225
227 }
228
230 {
232 return;
233
238 }
239
241 {
243
245 return 0;
246 for (
i = 0;
i <
s->nb_planes;
i++) {
248 }
249 if (
s->nb_planes == 1)
251
252 return 0;
253 }
254
256 {
258
259 /* Try first to get the sister buffer for the previous field */
260 if (parity < 2 && s->last &&
parity !=
s->last->parity
261 && !
s->last->buffer->lock[
parity]) {
264 }
265
266 /* Prefer a buffer with both fields open */
268 if (
s->buffers[
i].lock[0])
269 continue;
270 if (
s->buffers[
i].lock[1])
271 continue;
274 }
275
277 return 0;
278
279 /* Search for any half-free buffer */
281 if (((
parity + 1) & 1) &&
s->buffers[
i].lock[0])
282 continue;
283 if (((
parity + 1) & 2) &&
s->buffers[
i].lock[1])
284 continue;
287 }
288
290 }
291
293 {
295 int count = 1;
296
297 if (!begin || !end)
298 return 0;
299
300 for (
f = begin;
f != end;
f =
f->next)
301 count++;
302
303 return count;
304 }
305
307 {
309
310 for (
i = 0;
i <
max;
i++) {
314 }
315
316 return 0;
317 }
318
320 {
324 int i, l, max_l = 0, max_r = 0;
325
327 return;
328
330
331 /* Special case when fields are 100% identical */
334 return;
335 }
336
339 return;
340 }
341
342 for (
i = 0;
i <
s->metric_length;
i++) {
344
345 if ( l > max_l)
346 max_l = l;
347 if (-l > max_r)
348 max_r = -l;
349 }
350
351 /* Don't get tripped up when differences are mostly quant error */
352 if (max_l + max_r < 128)
353 return;
354 if (max_l > 4 * max_r)
356 if (max_r > 4 * max_l)
358 }
359
361 {
362 int i, max_l = 0, max_r = 0, l;
363
365 return;
366
368
369 if (
f->buffer ==
f->next->next->buffer) {
371 f->next->affinity = 0;
372 f->next->next->affinity = -1;
375 return;
376 }
377
378 for (
i = 0;
i <
s->metric_length;
i++) {
380 int lv =
f->prev->vars[
i];
381 int rv =
f->next->vars[
i];
382 int lc =
f-> combs[
i] - 2*(v < lv ? v : lv);
383 int rc =
f->next->combs[
i] - 2*(v < rv ? v : rv);
384
387 l = lc - rc;
388
389 if ( l > max_l)
390 max_l = l;
391 if (-l > max_r)
392 max_r = -l;
393 }
394
395 if (max_l + max_r < 64)
396 return;
397
398 if (max_r > 6 * max_l)
400 else if (max_l > 6 * max_r)
402 }
403
405 {
411
413 return 0;
414
417 for (
i = 0;
i < n - 1;
i++) {
420
422
424 }
425
427 return 1;
428
430
431 if (l == 1 &&
s->strict_breaks < 0)
432 l = 0;
433
434 switch (l) {
435 case 1:
437 case 2:
438 /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
442 return 1;
444 case 3:
446 default:
447 /* 9 possibilities covered before switch */
449 return 1; /* covers 6 */
451 return 2; /* covers 6 */
452 else if (f2->
affinity == -1) {
/* covers 2 */
454 } else {
455 return 2; /* the remaining 6 */
456 }
457 }
458 }
459
461 {
464 int aff =
s->first->next->affinity;
465
469
474
475 for (
i = 0;
i < n;
i++) {
476 /* We cheat and steal the buffer without release+relock */
478 s->first->buffer = 0;
479 s->first =
s->first->next;
480 }
481
482 if (n == 1) {
485 } else if (n == 2) {
488 } else if (n == 3) {
489 if (!aff)
493 }
494
497
501 return fr;
502 }
503
504 return fr;
505 }
506
508 {
510
511 for (
i = 0;
i <
f->length;
i++)
513
516
520 }
521
524 int (*
func)(
const uint8_t *,
const uint8_t *, ptrdiff_t))
525 {
526 int mp =
s->metric_plane;
527 int xstep = 8;
528 int ystep =
s->planewidth[
mp] << 3;
529 int stride =
s->planewidth[
mp] << 1;
/* field stride */
530 int w =
s->metric_w * xstep;
532 int x, y;
533
535 return;
536
537 /* Shortcut for duplicate fields (e.g. from RFF flag) */
538 if (fa->
buffer ==
fb->buffer && pa == pb) {
539 memset(dest, 0,
s->metric_length *
sizeof(*dest));
540 return;
541 }
542
544 b =
fb->buffer->planes[
mp] + pb *
s->planewidth[
mp] +
s->metric_offset;
545
546 for (y = 0; y <
s->metric_h; y++) {
547 for (x = 0; x <
w; x += xstep)
549 a += ystep;
b += ystep;
550 }
551 }
552
554 {
556
557 if (
s->head->next ==
s->first) {
559
562
566 }
567
572 }
573
574 return 0;
575 }
576
578 {
580
581 /* Grow the circular list if needed */
583 return;
584
585 /* Cannot have two fields of same parity in a row; drop the new one */
586 if (
s->last &&
s->last->parity ==
parity)
587 return;
588
595
599
600 /* Advance the circular list */
603
605 s->head =
s->head->next;
606 }
607
610 {
613
614 for (
i = 0;
i <
s->nb_planes;
i++) {
617
619 ss,
s->planewidth[
i] << 1,
620 s->planewidth[
i],
s->planeheight[
i] >> 1);
621 }
622 }
623
625 {
627
629 return;
630
632 return; /* FIXME: deal with this */
633
634 for (
i = 0;
i < 2;
i++) {
636 continue;
637
641 return;
642 }
643
645
648 }
649
651 {
659
665 goto end;
666 }
667
671
676
679
681
684 goto end;
685
690 goto end;
694 goto end;
697 goto end;
700 goto end;
701 }
702 }
703 }
704
705 /* If the frame isn't already exportable... */
708
712 goto end;
713 }
715
717 f->buffer->planes,
s->planewidth,
719
722 end:
725 }
726
728 {
731
734
739 }
740 }
741
743 {
748 },
749 };
750
754 .p.priv_class = &pullup_class,
760 };
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
int(* func)(AVBPrint *dst, const char *in, const char *arg)
#define AV_LOG_WARNING
Something somehow does not look correct.
AVPixelFormat
Pixel format.
static const AVOption pullup_options[]
Filter the word "frame" indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
#define FILTER_PIXFMTS_ARRAY(array)
static PullupFrame * pullup_get_frame(PullupContext *s)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
static PullupBuffer * pullup_get_buffer(PullupContext *s, int parity)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
const FFFilter ff_vf_pullup
static int config_input(AVFilterLink *inlink)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
static double mp(int i, double w0, double r)
static int alloc_buffer(PullupContext *s, PullupBuffer *b)
#define FILTER_INPUTS(array)
This structure describes decoded (raw) audio or video data.
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
const char * name
Filter name.
static void pullup_pack_frame(PullupContext *s, PullupFrame *fr)
static int queue_length(PullupField *begin, PullupField *end)
A link between two filters.
static int var_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
static int comb_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static void compute_metric(PullupContext *s, int *dest, PullupField *fa, int pa, PullupField *fb, int pb, int(*func)(const uint8_t *, const uint8_t *, ptrdiff_t))
#define ss(width, name, subs,...)
A filter pad used for either input or output.
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
static const AVFilterPad pullup_inputs[]
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
AVFILTER_DEFINE_CLASS(pullup)
static void pullup_release_buffer(PullupBuffer *b, int parity)
#define AV_CEIL_RSHIFT(a, b)
static PullupBuffer * pullup_lock_buffer(PullupBuffer *b, int parity)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
#define FILTER_OUTPUTS(array)
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
static int check_field_queue(PullupContext *s)
static int decide_frame_length(PullupContext *s)
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
PullupBuffer * ifields[4]
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
static enum AVPixelFormat pix_fmts[]
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
static void pullup_submit_field(PullupContext *s, PullupBuffer *b, int parity)
static int alloc_metrics(PullupContext *s, PullupField *f)
static void compute_breaks(PullupContext *s, PullupField *f0)
static void compute_affinity(PullupContext *s, PullupField *f)
#define i(width, name, range_min, range_max)
int w
agreed upon image width
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
static int find_first_break(PullupField *f, int max)
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
static void copy_field(PullupContext *s, PullupBuffer *dst, PullupBuffer *src, int parity)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
static av_cold void uninit(AVFilterContext *ctx)
const char * name
Pad name.
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
void * av_calloc(size_t nmemb, size_t size)
PullupBuffer * ofields[2]
static void free_field_queue(PullupField *head)
struct PullupField * next
static PullupField * make_field_queue(PullupContext *s, int len)
int h
agreed upon image height
struct PullupField * prev
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
@ AV_OPT_TYPE_INT
Underlying C type is int.
static int diff_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
AVFilter p
The public AVFilter.
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
void ff_pullup_init_x86(PullupContext *s)
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
static void pullup_release_frame(PullupFrame *f)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
int repeat_pict
Number of fields in this frame which should be repeated, i.e.
Generated on Sat Oct 18 2025 19:23:10 for FFmpeg by
doxygen
1.8.17