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