Reported-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Inspired by discussion with Kieran Kunhya <kierank@obe.tv>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -44,6 +44,7 @@ enum TInterlaceMode { |
44 | 44 |
typedef struct { |
45 | 45 |
const AVClass *class; |
46 | 46 |
enum TInterlaceMode mode; ///< interlace mode selected |
47 |
+ AVRational preout_time_base; |
|
47 | 48 |
int flags; ///< flags affecting interlacing algorithm |
48 | 49 |
int frame; ///< number of the output frame |
49 | 50 |
int vsub; ///< chroma vertical subsampling |
... | ... |
@@ -35,6 +35,7 @@ |
35 | 35 |
#define OFFSET(x) offsetof(TInterlaceContext, x) |
36 | 36 |
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
37 | 37 |
#define TINTERLACE_FLAG_VLPF 01 |
38 |
+#define TINTERLACE_FLAG_EXACT_TB 2 |
|
38 | 39 |
|
39 | 40 |
static const AVOption tinterlace_options[] = { |
40 | 41 |
{"mode", "select interlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_MERGE}, 0, MODE_NB-1, FLAGS, "mode"}, |
... | ... |
@@ -49,6 +50,7 @@ static const AVOption tinterlace_options[] = { |
49 | 49 |
{"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" }, |
50 | 50 |
{"low_pass_filter", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" }, |
51 | 51 |
{"vlpf", "enable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" }, |
52 |
+ {"exact_tb", "force a timebase which can represent timestamps exactly", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_EXACT_TB}, INT_MIN, INT_MAX, FLAGS, "flags" }, |
|
52 | 53 |
|
53 | 54 |
{NULL} |
54 | 55 |
}; |
... | ... |
@@ -62,6 +64,12 @@ static const enum AVPixelFormat full_scale_yuvj_pix_fmts[] = { |
62 | 62 |
FULL_SCALE_YUVJ_FORMATS, AV_PIX_FMT_NONE |
63 | 63 |
}; |
64 | 64 |
|
65 |
+static const AVRational standard_tbs[] = { |
|
66 |
+ {1, 25}, |
|
67 |
+ {1, 30}, |
|
68 |
+ {1001, 30000}, |
|
69 |
+}; |
|
70 |
+ |
|
65 | 71 |
static int query_formats(AVFilterContext *ctx) |
66 | 72 |
{ |
67 | 73 |
static const enum AVPixelFormat pix_fmts[] = { |
... | ... |
@@ -104,6 +112,7 @@ static int config_out_props(AVFilterLink *outlink) |
104 | 104 |
AVFilterLink *inlink = outlink->src->inputs[0]; |
105 | 105 |
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); |
106 | 106 |
TInterlaceContext *tinterlace = ctx->priv; |
107 |
+ int i; |
|
107 | 108 |
|
108 | 109 |
tinterlace->vsub = desc->log2_chroma_h; |
109 | 110 |
outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP; |
... | ... |
@@ -135,13 +144,23 @@ static int config_out_props(AVFilterLink *outlink) |
135 | 135 |
tinterlace->mode); |
136 | 136 |
tinterlace->flags &= ~TINTERLACE_FLAG_VLPF; |
137 | 137 |
} |
138 |
+ tinterlace->preout_time_base = inlink->time_base; |
|
138 | 139 |
if (tinterlace->mode == MODE_INTERLACEX2) { |
139 |
- outlink->time_base.num = inlink->time_base.num; |
|
140 |
- outlink->time_base.den = inlink->time_base.den * 2; |
|
140 |
+ tinterlace->preout_time_base.den *= 2; |
|
141 | 141 |
outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1}); |
142 |
+ outlink->time_base = av_mul_q(inlink->time_base , (AVRational){1,2}); |
|
142 | 143 |
} else if (tinterlace->mode != MODE_PAD) { |
143 | 144 |
outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2}); |
145 |
+ outlink->time_base = av_mul_q(inlink->time_base , (AVRational){2,1}); |
|
146 |
+ } |
|
147 |
+ |
|
148 |
+ for (i = 0; i<FF_ARRAY_ELEMS(standard_tbs); i++){ |
|
149 |
+ if (!av_cmp_q(standard_tbs[i], outlink->time_base)) |
|
150 |
+ break; |
|
144 | 151 |
} |
152 |
+ if (i == FF_ARRAY_ELEMS(standard_tbs) || |
|
153 |
+ (tinterlace->flags & TINTERLACE_FLAG_EXACT_TB)) |
|
154 |
+ outlink->time_base = tinterlace->preout_time_base; |
|
145 | 155 |
|
146 | 156 |
if (tinterlace->flags & TINTERLACE_FLAG_VLPF) { |
147 | 157 |
tinterlace->lowpass_line = lowpass_line_c; |
... | ... |
@@ -326,6 +345,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) |
326 | 326 |
if (cur->pts != AV_NOPTS_VALUE) |
327 | 327 |
out->pts = cur->pts*2; |
328 | 328 |
|
329 |
+ out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); |
|
329 | 330 |
if ((ret = ff_filter_frame(outlink, out)) < 0) |
330 | 331 |
return ret; |
331 | 332 |
|
... | ... |
@@ -359,6 +379,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) |
359 | 359 |
av_assert0(0); |
360 | 360 |
} |
361 | 361 |
|
362 |
+ out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); |
|
362 | 363 |
ret = ff_filter_frame(outlink, out); |
363 | 364 |
tinterlace->frame++; |
364 | 365 |
|