2 * Copyright (C) 2006-2011 Michael Niedermayer <michaelni@gmx.at>
3 * 2010 James Darnley <james.darnley@gmail.com>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/avassert.h"
23 #include "libavutil/imgutils.h"
28 static int return_frame(AVFilterContext
*ctx
, int is_second
)
30 YADIFContext
*yadif
= ctx
->priv
;
31 AVFilterLink
*link
= ctx
->outputs
[0];
34 if (yadif
->parity
== -1) {
35 tff
= (yadif
->cur
->flags
& AV_FRAME_FLAG_INTERLACED
) ?
36 !!(yadif
->cur
->flags
& AV_FRAME_FLAG_TOP_FIELD_FIRST
) : 1;
38 tff
= yadif
->parity
^ 1;
42 yadif
->out
= ff_get_video_buffer(link
, link
->w
, link
->h
);
44 return AVERROR(ENOMEM
);
46 av_frame_copy_props(yadif
->out
, yadif
->cur
);
47 #if FF_API_INTERLACED_FRAME
48 FF_DISABLE_DEPRECATION_WARNINGS
49 yadif
->out
->interlaced_frame
= 0;
50 FF_ENABLE_DEPRECATION_WARNINGS
52 yadif
->out
->flags
&= ~AV_FRAME_FLAG_INTERLACED
;
53 if (yadif
->current_field
== YADIF_FIELD_BACK_END
)
54 yadif
->current_field
= YADIF_FIELD_END
;
57 yadif
->filter(ctx
, yadif
->out
, tff
^ !is_second
, tff
);
60 int64_t cur_pts
= yadif
->cur
->pts
;
61 int64_t next_pts
= yadif
->next
->pts
;
63 if (next_pts
!= AV_NOPTS_VALUE
&& cur_pts
!= AV_NOPTS_VALUE
) {
64 yadif
->out
->pts
= cur_pts
+ next_pts
;
65 if (yadif
->pts_multiplier
== 1) {
66 yadif
->out
->pts
>>= 1;
67 yadif
->out
->duration
>>= 1;
70 yadif
->out
->pts
= AV_NOPTS_VALUE
;
74 ff_ccfifo_inject(&yadif
->cc_fifo
, yadif
->out
);
75 ret
= ff_filter_frame(ctx
->outputs
[0], yadif
->out
);
77 yadif
->frame_pending
= (yadif
->mode
&1) && !is_second
;
81 static int checkstride(YADIFContext
*yadif
, const AVFrame
*a
, const AVFrame
*b
)
84 for (i
= 0; i
< yadif
->csp
->nb_components
; i
++)
85 if (a
->linesize
[i
] != b
->linesize
[i
])
90 static void fixstride(AVFilterLink
*link
, AVFrame
*f
)
92 AVFrame
*dst
= ff_default_get_video_buffer(link
, f
->width
, f
->height
);
95 av_frame_copy_props(dst
, f
);
96 av_image_copy2(dst
->data
, dst
->linesize
,
98 dst
->format
, dst
->width
, dst
->height
);
100 av_frame_move_ref(f
, dst
);
104 int ff_yadif_filter_frame(AVFilterLink
*link
, AVFrame
*frame
)
106 AVFilterContext
*ctx
= link
->dst
;
107 YADIFContext
*yadif
= ctx
->priv
;
111 ff_ccfifo_extract(&yadif
->cc_fifo
, frame
);
113 if (yadif
->frame_pending
)
114 return_frame(ctx
, 1);
117 av_frame_free(&yadif
->prev
);
118 yadif
->prev
= yadif
->cur
;
119 yadif
->cur
= yadif
->next
;
123 yadif
->cur
= av_frame_clone(yadif
->next
);
125 return AVERROR(ENOMEM
);
126 yadif
->current_field
= YADIF_FIELD_END
;
129 if (checkstride(yadif
, yadif
->next
, yadif
->cur
)) {
130 av_log(ctx
, AV_LOG_VERBOSE
, "Reallocating frame due to differing stride\n");
131 fixstride(link
, yadif
->next
);
133 if (checkstride(yadif
, yadif
->next
, yadif
->cur
))
134 fixstride(link
, yadif
->cur
);
135 if (yadif
->prev
&& checkstride(yadif
, yadif
->next
, yadif
->prev
))
136 fixstride(link
, yadif
->prev
);
137 if (checkstride(yadif
, yadif
->next
, yadif
->cur
) || (yadif
->prev
&& checkstride(yadif
, yadif
->next
, yadif
->prev
))) {
138 av_log(ctx
, AV_LOG_ERROR
, "Failed to reallocate frame\n");
145 if ((yadif
->deint
&& !(yadif
->cur
->flags
& AV_FRAME_FLAG_INTERLACED
)) ||
147 (yadif
->deint
&& !(yadif
->prev
->flags
& AV_FRAME_FLAG_INTERLACED
) && yadif
->prev
->repeat_pict
) ||
148 (yadif
->deint
&& !(yadif
->next
->flags
& AV_FRAME_FLAG_INTERLACED
) && yadif
->next
->repeat_pict
)
150 yadif
->out
= av_frame_clone(yadif
->cur
);
152 return AVERROR(ENOMEM
);
154 ff_ccfifo_inject(&yadif
->cc_fifo
, yadif
->out
);
155 av_frame_free(&yadif
->prev
);
156 if (yadif
->out
->pts
!= AV_NOPTS_VALUE
)
157 yadif
->out
->pts
*= yadif
->pts_multiplier
;
158 yadif
->out
->duration
*= yadif
->pts_multiplier
;
159 return ff_filter_frame(ctx
->outputs
[0], yadif
->out
);
162 yadif
->out
= ff_get_video_buffer(ctx
->outputs
[0], link
->w
, link
->h
);
164 return AVERROR(ENOMEM
);
166 av_frame_copy_props(yadif
->out
, yadif
->cur
);
167 #if FF_API_INTERLACED_FRAME
168 FF_DISABLE_DEPRECATION_WARNINGS
169 yadif
->out
->interlaced_frame
= 0;
170 FF_ENABLE_DEPRECATION_WARNINGS
172 yadif
->out
->flags
&= ~AV_FRAME_FLAG_INTERLACED
;
174 if (yadif
->out
->pts
!= AV_NOPTS_VALUE
)
175 yadif
->out
->pts
*= yadif
->pts_multiplier
;
176 if (!(yadif
->mode
& 1))
177 yadif
->out
->duration
*= yadif
->pts_multiplier
;
178 else if (yadif
->pts_multiplier
== 1)
179 yadif
->out
->duration
>>= 1;
181 return return_frame(ctx
, 0);
184 int ff_yadif_request_frame(AVFilterLink
*link
)
186 AVFilterContext
*ctx
= link
->src
;
187 YADIFContext
*yadif
= ctx
->priv
;
190 if (yadif
->frame_pending
) {
191 return_frame(ctx
, 1);
198 ret
= ff_request_frame(ctx
->inputs
[0]);
200 if (ret
== AVERROR_EOF
&& yadif
->cur
) {
201 AVFrame
*next
= av_frame_clone(yadif
->next
);
204 return AVERROR(ENOMEM
);
206 yadif
->current_field
= YADIF_FIELD_BACK_END
;
207 next
->pts
= yadif
->next
->pts
* 2 - yadif
->cur
->pts
;
209 ff_yadif_filter_frame(ctx
->inputs
[0], next
);
211 } else if (ret
< 0) {
218 int ff_yadif_config_output_common(AVFilterLink
*outlink
)
220 AVFilterContext
*ctx
= outlink
->src
;
221 FilterLink
*il
= ff_filter_link(ctx
->inputs
[0]);
222 FilterLink
*ol
= ff_filter_link(outlink
);
223 YADIFContext
*yadif
= ctx
->priv
;
224 AVRational tb
= ctx
->inputs
[0]->time_base
;
227 if (av_reduce(&outlink
->time_base
.num
, &outlink
->time_base
.den
, tb
.num
, tb
.den
* 2LL, INT_MAX
)) {
228 yadif
->pts_multiplier
= 2;
230 av_log(ctx
, AV_LOG_WARNING
, "Cannot use exact output timebase\n");
231 outlink
->time_base
= tb
;
232 yadif
->pts_multiplier
= 1;
235 outlink
->w
= ctx
->inputs
[0]->w
;
236 outlink
->h
= ctx
->inputs
[0]->h
;
238 if (outlink
->w
< 3 || outlink
->h
< 3) {
239 av_log(ctx
, AV_LOG_ERROR
, "Video of less than 3 columns or lines is not supported\n");
240 return AVERROR(EINVAL
);
244 ol
->frame_rate
= av_mul_q(il
->frame_rate
,
247 ol
->frame_rate
= il
->frame_rate
;
249 ret
= ff_ccfifo_init(&yadif
->cc_fifo
, ol
->frame_rate
, ctx
);
251 av_log(ctx
, AV_LOG_ERROR
, "Failure to setup CC FIFO queue\n");
258 void ff_yadif_uninit(AVFilterContext
*ctx
)
260 YADIFContext
*yadif
= ctx
->priv
;
262 av_frame_free(&yadif
->prev
);
263 av_frame_free(&yadif
->cur
);
264 av_frame_free(&yadif
->next
);
265 ff_ccfifo_uninit(&yadif
->cc_fifo
);
268 #define OFFSET(x) offsetof(YADIFContext, x)
269 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
271 #define CONST(name, help, val, u) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, .unit = u }
273 const AVOption ff_yadif_options
[] = {
274 { "mode", "specify the interlacing mode", OFFSET(mode
), AV_OPT_TYPE_INT
, {.i64
=YADIF_MODE_SEND_FRAME
}, 0, 3, FLAGS
, .unit
= "mode"},
275 CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME
, "mode"),
276 CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD
, "mode"),
277 CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL
, "mode"),
278 CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL
, "mode"),
280 { "parity", "specify the assumed picture field parity", OFFSET(parity
), AV_OPT_TYPE_INT
, {.i64
=YADIF_PARITY_AUTO
}, -1, 1, FLAGS
, .unit
= "parity" },
281 CONST("tff", "assume top field first", YADIF_PARITY_TFF
, "parity"),
282 CONST("bff", "assume bottom field first", YADIF_PARITY_BFF
, "parity"),
283 CONST("auto", "auto detect parity", YADIF_PARITY_AUTO
, "parity"),
285 { "deint", "specify which frames to deinterlace", OFFSET(deint
), AV_OPT_TYPE_INT
, {.i64
=YADIF_DEINT_ALL
}, 0, 1, FLAGS
, .unit
= "deint" },
286 CONST("all", "deinterlace all frames", YADIF_DEINT_ALL
, "deint"),
287 CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED
, "deint"),