FFmpeg
phase_template.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004 Ville Saari
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 
21 #include "libavutil/avassert.h"
22 #include "avfilter.h"
23 #include "internal.h"
24 #include "video.h"
25 
26 #undef pixel
27 #undef accumulator
28 #if DEPTH == 8
29 #define pixel uint8_t
30 #define accumulator int
31 #else
32 #define pixel uint16_t
33 #define accumulator int64_t
34 #endif
35 
36 #define fn3(a,b) a##_##b
37 #define fn2(a,b) fn3(a,b)
38 #define fn(a) fn2(a, DEPTH)
39 
40 /*
41  * This macro interpolates the value of both fields at a point halfway
42  * between lines and takes the squared difference. In field resolution
43  * the point is a quarter pixel below a line in one field and a quarter
44  * pixel above a line in other.
45  *
46  * (The result is actually multiplied by 25)
47  */
48 #define DIFF(a, as, b, bs) ((t) = ((*(a) - (b)[bs]) * 4) + (a)[(as) * 2] - (b)[-(bs)], (t) * (t))
49 
50 /*
51  * Find which field combination has the smallest average squared difference
52  * between the fields.
53  */
54 static enum PhaseMode fn(analyze_plane)(void *ctx, enum PhaseMode mode, AVFrame *old, AVFrame *new)
55 {
56  double bdiff, tdiff, pdiff;
57 
58  if (mode == AUTO) {
59  mode = (new->flags & AV_FRAME_FLAG_INTERLACED) ? (new->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ?
61  } else if (mode == AUTO_ANALYZE) {
62  mode = (new->flags & AV_FRAME_FLAG_INTERLACED) ? (new->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ?
64  }
65 
66  if (mode <= BOTTOM_FIRST) {
67  bdiff = pdiff = tdiff = 65536.0;
68  } else {
69  const double factor = 1. / (25. * (1 << (DEPTH - 8)) * (1 << (DEPTH - 8)));
70  const int ns = new->linesize[0] / sizeof(pixel);
71  const int os = old->linesize[0] / sizeof(pixel);
72  const pixel *nptr = (pixel *)new->data[0];
73  const pixel *optr = (pixel *)old->data[0];
74  const int h = new->height;
75  const int w = new->width;
76  accumulator bdif, tdif, pdif;
77  double scale;
78 
79  int top = 0, t;
80  const pixel *rend, *end = nptr + (h - 2) * ns;
81 
82  bdiff = pdiff = tdiff = 0.0;
83 
84  nptr += ns;
85  optr += os;
86  while (nptr < end) {
87  pdif = tdif = bdif = 0;
88 
89  switch (mode) {
90  case TOP_FIRST_ANALYZE:
91  if (top) {
92  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
93  pdif += DIFF(nptr, ns, nptr, ns);
94  tdif += DIFF(nptr, ns, optr, os);
95  }
96  } else {
97  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
98  pdif += DIFF(nptr, ns, nptr, ns);
99  tdif += DIFF(optr, os, nptr, ns);
100  }
101  }
102  break;
104  if (top) {
105  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
106  pdif += DIFF(nptr, ns, nptr, ns);
107  bdif += DIFF(optr, os, nptr, ns);
108  }
109  } else {
110  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
111  pdif += DIFF(nptr, ns, nptr, ns);
112  bdif += DIFF(nptr, ns, optr, os);
113  }
114  }
115  break;
116  case ANALYZE:
117  if (top) {
118  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
119  tdif += DIFF(nptr, ns, optr, os);
120  bdif += DIFF(optr, os, nptr, ns);
121  }
122  } else {
123  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
124  bdif += DIFF(nptr, ns, optr, os);
125  tdif += DIFF(optr, os, nptr, ns);
126  }
127  }
128  break;
129  case FULL_ANALYZE:
130  if (top) {
131  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
132  pdif += DIFF(nptr, ns, nptr, ns);
133  tdif += DIFF(nptr, ns, optr, os);
134  bdif += DIFF(optr, os, nptr, ns);
135  }
136  } else {
137  for (rend = nptr + w; nptr < rend; nptr++, optr++) {
138  pdif += DIFF(nptr, ns, nptr, ns);
139  bdif += DIFF(nptr, ns, optr, os);
140  tdif += DIFF(optr, os, nptr, ns);
141  }
142  }
143  break;
144  default:
145  av_assert0(0);
146  }
147 
148  pdiff += (double)pdif;
149  tdiff += (double)tdif;
150  bdiff += (double)bdif;
151  nptr += ns - w;
152  optr += os - w;
153  top ^= 1;
154  }
155 
156  scale = 1.0 / (w * (h - 3)) * factor;
157  pdiff *= scale;
158  tdiff *= scale;
159  bdiff *= scale;
160 
161  if (mode == TOP_FIRST_ANALYZE) {
162  bdiff = 65536.0;
163  } else if (mode == BOTTOM_FIRST_ANALYZE) {
164  tdiff = 65536.0;
165  } else if (mode == ANALYZE) {
166  pdiff = 65536.0;
167  }
168 
169  if (bdiff < pdiff && bdiff < tdiff) {
170  mode = BOTTOM_FIRST;
171  } else if (tdiff < pdiff && tdiff < bdiff) {
172  mode = TOP_FIRST;
173  } else {
174  mode = PROGRESSIVE;
175  }
176  }
177 
178  av_log(ctx, AV_LOG_DEBUG, "mode=%c tdiff=%f bdiff=%f pdiff=%f\n",
179  mode == BOTTOM_FIRST ? 'b' : mode == TOP_FIRST ? 't' : 'p',
180  tdiff, bdiff, pdiff);
181  return mode;
182 }
BOTTOM_FIRST
@ BOTTOM_FIRST
Definition: vf_phase.c:32
PROGRESSIVE
@ PROGRESSIVE
in the bitstream is reported as 00b
Definition: vc1.h:149
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:375
w
uint8_t w
Definition: llviddspenc.c:38
video.h
AV_FRAME_FLAG_TOP_FIELD_FIRST
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition: frame.h:639
DIFF
#define DIFF(a, as, b, bs)
Definition: phase_template.c:48
ANALYZE
@ ANALYZE
Definition: vf_phase.c:35
avassert.h
AUTO
@ AUTO
Definition: vf_phase.c:37
TOP_FIRST
@ TOP_FIRST
Definition: vf_phase.c:31
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
TOP_FIRST_ANALYZE
@ TOP_FIRST_ANALYZE
Definition: vf_phase.c:33
pixel
uint8_t pixel
Definition: tiny_ssim.c:41
analyze_plane
static enum PhaseMode fn() analyze_plane(void *ctx, enum PhaseMode mode, AVFrame *old, AVFrame *new)
Definition: phase_template.c:54
double
double
Definition: af_crystalizer.c:131
accumulator
#define accumulator
Definition: phase_template.c:33
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: vvc_intra.c:291
FULL_ANALYZE
@ FULL_ANALYZE
Definition: vf_phase.c:36
ns
#define ns(max_value, name, subs,...)
Definition: cbs_av1.c:608
internal.h
pixel
#define pixel
Definition: phase_template.c:32
PhaseMode
PhaseMode
Definition: vf_phase.c:29
fn
#define fn(a)
Definition: phase_template.c:38
DEPTH
#define DEPTH
Definition: v210enc.c:43
AV_FRAME_FLAG_INTERLACED
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition: frame.h:634
AUTO_ANALYZE
@ AUTO_ANALYZE
Definition: vf_phase.c:38
mode
mode
Definition: ebur128.h:83
avfilter.h
factor
static const int factor[16]
Definition: vf_pp7.c:78
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2038
BOTTOM_FIRST_ANALYZE
@ BOTTOM_FIRST_ANALYZE
Definition: vf_phase.c:34