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"
22 #include "libavutil/imgutils.h"
23 #include "libavutil/pixdesc.h"
24 #include "libavutil/opt.h"
42 typedef struct PhaseContext
{
45 AVFrame
*frame
; /* previous frame */
51 #define OFFSET(x) offsetof(PhaseContext, x)
52 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
53 #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit }
55 static const AVOption phase_options
[] = {
56 { "mode", "set phase mode", OFFSET(mode
), AV_OPT_TYPE_INT
, {.i64
=AUTO_ANALYZE
}, PROGRESSIVE
, AUTO_ANALYZE
, FLAGS
, "mode" },
57 CONST("p", "progressive", PROGRESSIVE
, "mode"),
58 CONST("t", "top first", TOP_FIRST
, "mode"),
59 CONST("b", "bottom first", BOTTOM_FIRST
, "mode"),
60 CONST("T", "top first analyze", TOP_FIRST_ANALYZE
, "mode"),
61 CONST("B", "bottom first analyze", BOTTOM_FIRST_ANALYZE
, "mode"),
62 CONST("u", "analyze", ANALYZE
, "mode"),
63 CONST("U", "full analyze", FULL_ANALYZE
, "mode"),
64 CONST("a", "auto", AUTO
, "mode"),
65 CONST("A", "auto analyze", AUTO_ANALYZE
, "mode"),
69 AVFILTER_DEFINE_CLASS(phase
);
71 static int query_formats(AVFilterContext
*ctx
)
73 static const enum AVPixelFormat pix_fmts
[] = {
74 AV_PIX_FMT_YUVA444P
, AV_PIX_FMT_YUVA422P
, AV_PIX_FMT_YUVA420P
,
75 AV_PIX_FMT_YUVJ444P
, AV_PIX_FMT_YUVJ440P
, AV_PIX_FMT_YUVJ422P
,AV_PIX_FMT_YUVJ420P
, AV_PIX_FMT_YUVJ411P
,
76 AV_PIX_FMT_YUV444P
, AV_PIX_FMT_YUV440P
, AV_PIX_FMT_YUV422P
, AV_PIX_FMT_YUV420P
, AV_PIX_FMT_YUV411P
, AV_PIX_FMT_YUV410P
,
77 AV_PIX_FMT_GBRP
, AV_PIX_FMT_GBRAP
, AV_PIX_FMT_GRAY8
, AV_PIX_FMT_NONE
80 ff_set_common_formats(ctx
, ff_make_format_list(pix_fmts
));
84 static int config_input(AVFilterLink
*inlink
)
86 PhaseContext
*s
= inlink
->dst
->priv
;
87 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(inlink
->format
);
90 if ((ret
= av_image_fill_linesizes(s
->linesize
, inlink
->format
, inlink
->w
)) < 0)
93 s
->planeheight
[1] = s
->planeheight
[2] = FF_CEIL_RSHIFT(inlink
->h
, desc
->log2_chroma_h
);
94 s
->planeheight
[0] = s
->planeheight
[3] = inlink
->h
;
96 s
->nb_planes
= av_pix_fmt_count_planes(inlink
->format
);
102 * This macro interpolates the value of both fields at a point halfway
103 * between lines and takes the squared difference. In field resolution
104 * the point is a quarter pixel below a line in one field and a quarter
105 * pixel above a line in other.
107 * (The result is actually multiplied by 25)
109 #define DIFF(a, as, b, bs) (t = ((*a - b[bs]) << 2) + a[as << 1] - b[-bs], t * t)
112 * Find which field combination has the smallest average squared difference
113 * between the fields.
115 static enum PhaseMode
analyze_plane(void *ctx
, enum PhaseMode mode
, AVFrame
*old
, AVFrame
*new)
117 double bdiff
, tdiff
, pdiff
, scale
;
118 const int ns
= new->linesize
[0];
119 const int os
= old
->linesize
[0];
120 const uint8_t *nptr
= new->data
[0];
121 const uint8_t *optr
= old
->data
[0];
122 const int h
= new->height
;
123 const int w
= new->width
;
124 int bdif
, tdif
, pdif
;
127 mode
= new->interlaced_frame
? new->top_field_first
?
128 TOP_FIRST
: BOTTOM_FIRST
: PROGRESSIVE
;
129 } else if (mode
== AUTO_ANALYZE
) {
130 mode
= new->interlaced_frame
? new->top_field_first
?
131 TOP_FIRST_ANALYZE
: BOTTOM_FIRST_ANALYZE
: FULL_ANALYZE
;
134 if (mode
<= BOTTOM_FIRST
) {
135 bdiff
= pdiff
= tdiff
= 65536.0;
138 const uint8_t *rend
, *end
= nptr
+ (h
- 2) * ns
;
140 bdiff
= pdiff
= tdiff
= 0.0;
145 pdif
= tdif
= bdif
= 0;
148 case TOP_FIRST_ANALYZE
:
150 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
151 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
152 tdif
+= DIFF(nptr
, ns
, optr
, os
);
155 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
156 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
157 tdif
+= DIFF(optr
, os
, nptr
, ns
);
161 case BOTTOM_FIRST_ANALYZE
:
163 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
164 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
165 bdif
+= DIFF(optr
, os
, nptr
, ns
);
168 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
169 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
170 bdif
+= DIFF(nptr
, ns
, optr
, os
);
176 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
177 tdif
+= DIFF(nptr
, ns
, optr
, os
);
178 bdif
+= DIFF(optr
, os
, nptr
, ns
);
181 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
182 bdif
+= DIFF(nptr
, ns
, optr
, os
);
183 tdif
+= DIFF(optr
, os
, nptr
, ns
);
189 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
190 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
191 tdif
+= DIFF(nptr
, ns
, optr
, os
);
192 bdif
+= DIFF(optr
, os
, nptr
, ns
);
195 for (rend
= nptr
+ w
; nptr
< rend
; nptr
++, optr
++) {
196 pdif
+= DIFF(nptr
, ns
, nptr
, ns
);
197 bdif
+= DIFF(nptr
, ns
, optr
, os
);
198 tdif
+= DIFF(optr
, os
, nptr
, ns
);
206 pdiff
+= (double)pdif
;
207 tdiff
+= (double)tdif
;
208 bdiff
+= (double)bdif
;
214 scale
= 1.0 / (w
* (h
- 3)) / 25.0;
219 if (mode
== TOP_FIRST_ANALYZE
) {
221 } else if (mode
== BOTTOM_FIRST_ANALYZE
) {
223 } else if (mode
== ANALYZE
) {
227 if (bdiff
< pdiff
&& bdiff
< tdiff
) {
229 } else if (tdiff
< pdiff
&& tdiff
< bdiff
) {
236 av_log(ctx
, AV_LOG_DEBUG
, "mode=%c tdiff=%f bdiff=%f pdiff=%f\n",
237 mode
== BOTTOM_FIRST
? 'b' : mode
== TOP_FIRST
? 't' : 'p',
238 tdiff
, bdiff
, pdiff
);
242 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*in
)
244 AVFilterContext
*ctx
= inlink
->dst
;
245 AVFilterLink
*outlink
= ctx
->outputs
[0];
246 PhaseContext
*s
= ctx
->priv
;
251 if (ctx
->is_disabled
) {
252 av_frame_free(&s
->frame
);
253 /* we keep a reference to the previous frame so the filter can start
254 * being useful as soon as it's not disabled, avoiding the 1-frame
256 s
->frame
= av_frame_clone(in
);
257 return ff_filter_frame(outlink
, in
);
260 out
= ff_get_video_buffer(outlink
, outlink
->w
, outlink
->h
);
263 return AVERROR(ENOMEM
);
265 av_frame_copy_props(out
, in
);
271 mode
= analyze_plane(ctx
, s
->mode
, s
->frame
, in
);
274 for (plane
= 0; plane
< s
->nb_planes
; plane
++) {
275 const uint8_t *buf
= s
->frame
->data
[plane
];
276 const uint8_t *from
= in
->data
[plane
];
277 uint8_t *to
= out
->data
[plane
];
279 for (y
= 0, top
= 1; y
< s
->planeheight
[plane
]; y
++, top
^= 1) {
280 memcpy(to
, mode
== (top
? BOTTOM_FIRST
: TOP_FIRST
) ? buf
: from
, s
->linesize
[plane
]);
282 buf
+= s
->frame
->linesize
[plane
];
283 from
+= in
->linesize
[plane
];
284 to
+= out
->linesize
[plane
];
289 av_frame_free(&s
->frame
);
291 return ff_filter_frame(outlink
, out
);
294 static av_cold
void uninit(AVFilterContext
*ctx
)
296 PhaseContext
*s
= ctx
->priv
;
298 av_frame_free(&s
->frame
);
301 static const AVFilterPad phase_inputs
[] = {
304 .type
= AVMEDIA_TYPE_VIDEO
,
305 .filter_frame
= filter_frame
,
306 .config_props
= config_input
,
311 static const AVFilterPad phase_outputs
[] = {
314 .type
= AVMEDIA_TYPE_VIDEO
,
319 AVFilter ff_vf_phase
= {
321 .description
= NULL_IF_CONFIG_SMALL("Phase shift fields."),
322 .priv_size
= sizeof(PhaseContext
),
323 .priv_class
= &phase_class
,
325 .query_formats
= query_formats
,
326 .inputs
= phase_inputs
,
327 .outputs
= phase_outputs
,
328 .flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
,