2 * Copyright (c) 2004 Ville Saari
4 * This file is part of FFmpeg.
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.
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.
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
21 #include "libavutil/avassert.h"
29 #define accumulator int
31 #define pixel uint16_t
32 #define accumulator int64_t
35 #define fn3(a,b) a##_##b
36 #define fn2(a,b) fn3(a,b)
37 #define fn(a) fn2(a, DEPTH)
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.
45 * (The result is actually multiplied by 25)
47 #define DIFF(a, as, b, bs) ((t) = ((*(a) - (b)[bs]) * 4) + (a)[(as) * 2] - (b)[-(bs)], (t) * (t))
50 * Find which field combination has the smallest average squared difference
53 static enum PhaseMode
fn(analyze_plane
)(void *ctx
, enum PhaseMode mode
, AVFrame
*old
, AVFrame
*new)
55 double bdiff
, tdiff
, pdiff
;
58 mode
= (new->flags
& AV_FRAME_FLAG_INTERLACED
) ? (new->flags
& AV_FRAME_FLAG_TOP_FIELD_FIRST
) ?
59 TOP_FIRST
: BOTTOM_FIRST
: PROGRESSIVE
;
60 } else if (mode
== AUTO_ANALYZE
) {
61 mode
= (new->flags
& AV_FRAME_FLAG_INTERLACED
) ? (new->flags
& AV_FRAME_FLAG_TOP_FIELD_FIRST
) ?
62 TOP_FIRST_ANALYZE
: BOTTOM_FIRST_ANALYZE
: FULL_ANALYZE
;
65 if (mode
<= BOTTOM_FIRST
) {
66 bdiff
= pdiff
= tdiff
= 65536.0;
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
;
79 const pixel
*rend
, *end
= nptr
+ (h
- 2) * ns
;
81 bdiff
= pdiff
= tdiff
= 0.0;
86 pdif
= tdif
= bdif
= 0;
89 case TOP_FIRST_ANALYZE
:
91 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
92 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
93 tdif
+= DIFF(nptr
, ns
, optr
, os
);
96 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
97 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
98 tdif
+= DIFF(optr
, os
, nptr
, ns
);
102 case BOTTOM_FIRST_ANALYZE
:
104 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
105 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
106 bdif
+= DIFF(optr
, os
, nptr
, ns
);
109 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
110 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
111 bdif
+= DIFF(nptr
, ns
, optr
, os
);
117 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
118 tdif
+= DIFF(nptr
, ns
, optr
, os
);
119 bdif
+= DIFF(optr
, os
, nptr
, ns
);
122 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
123 bdif
+= DIFF(nptr
, ns
, optr
, os
);
124 tdif
+= DIFF(optr
, os
, nptr
, ns
);
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
);
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
);
147 pdiff
+= (double)pdif
;
148 tdiff
+= (double)tdif
;
149 bdiff
+= (double)bdif
;
155 scale
= 1.0 / (w
* (h
- 3)) * factor
;
160 if (mode
== TOP_FIRST_ANALYZE
) {
162 } else if (mode
== BOTTOM_FIRST_ANALYZE
) {
164 } else if (mode
== ANALYZE
) {
168 if (bdiff
< pdiff
&& bdiff
< tdiff
) {
170 } else if (tdiff
< pdiff
&& tdiff
< bdiff
) {
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
);