summaryrefslogtreecommitdiff
authorPaul B Mahol <onemda@gmail.com>2013-10-12 14:55:42 (GMT)
committer Paul B Mahol <onemda@gmail.com>2013-10-12 15:10:19 (GMT)
commit1d8ce109e91d8e8f87676a2f24af18f14fa297a5 (patch)
tree27538b6ef534fcb4ce40b43b6ee0b0e1e3746544
parent8de021fabe3a1c7a1465d5fa6e238803a3d82f04 (diff)
downloadffmpeg-1d8ce109e91d8e8f87676a2f24af18f14fa297a5.zip
ffmpeg-1d8ce109e91d8e8f87676a2f24af18f14fa297a5.tar.gz
ffmpeg-1d8ce109e91d8e8f87676a2f24af18f14fa297a5.tar.bz2
avfilter/vf_separatefields: do not reset pts to 0
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat
-rw-r--r--libavfilter/vf_separatefields.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/libavfilter/vf_separatefields.c b/libavfilter/vf_separatefields.c
index d37ca9a..00ecac1 100644
--- a/libavfilter/vf_separatefields.c
+++ b/libavfilter/vf_separatefields.c
@@ -24,7 +24,7 @@
typedef struct {
int nb_planes;
- double ts_unit;
+ AVFrame *second;
} SeparateFieldsContext;
static int config_props_output(AVFilterLink *outlink)
@@ -46,44 +46,76 @@ static int config_props_output(AVFilterLink *outlink)
outlink->frame_rate.den = inlink->frame_rate.den;
outlink->w = inlink->w;
outlink->h = inlink->h / 2;
- sf->ts_unit = av_q2d(av_inv_q(av_mul_q(outlink->frame_rate, outlink->time_base)));
return 0;
}
+static void extract_field(AVFrame *frame, int nb_planes, int type)
+{
+ int i;
+
+ for (i = 0; i < nb_planes; i++) {
+ if (type)
+ frame->data[i] = frame->data[i] + frame->linesize[i];
+ frame->linesize[i] *= 2;
+ }
+}
+
static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
{
AVFilterContext *ctx = inlink->dst;
SeparateFieldsContext *sf = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- AVFrame *second;
- int i, ret;
+ int ret;
inpicref->height = outlink->h;
inpicref->interlaced_frame = 0;
- second = av_frame_clone(inpicref);
- if (!second)
- return AVERROR(ENOMEM);
+ if (!sf->second) {
+ goto clone;
+ } else {
+ AVFrame *second = sf->second;
- for (i = 0; i < sf->nb_planes; i++) {
- if (!inpicref->top_field_first)
- inpicref->data[i] = inpicref->data[i] + inpicref->linesize[i];
+ extract_field(second, sf->nb_planes, second->top_field_first);
+
+ if (second->pts != AV_NOPTS_VALUE &&
+ inpicref->pts != AV_NOPTS_VALUE)
+ second->pts += inpicref->pts;
else
- second->data[i] = second->data[i] + second->linesize[i];
- inpicref->linesize[i] *= 2;
- second->linesize[i] *= 2;
+ second->pts = AV_NOPTS_VALUE;
+
+ ret = ff_filter_frame(outlink, second);
+ if (ret < 0)
+ return ret;
+clone:
+ sf->second = av_frame_clone(inpicref);
+ if (!sf->second)
+ return AVERROR(ENOMEM);
}
- inpicref->pts = outlink->frame_count * sf->ts_unit;
- ret = ff_filter_frame(outlink, inpicref);
- if (ret < 0) {
- av_frame_free(&second);
- return ret;
+ extract_field(inpicref, sf->nb_planes, !inpicref->top_field_first);
+
+ if (inpicref->pts != AV_NOPTS_VALUE)
+ inpicref->pts *= 2;
+
+ return ff_filter_frame(outlink, inpicref);
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+ AVFilterContext *ctx = outlink->src;
+ SeparateFieldsContext *sf = ctx->priv;
+ int ret;
+
+ ret = ff_request_frame(ctx->inputs[0]);
+ if (ret == AVERROR_EOF && sf->second) {
+ sf->second->pts *= 2;
+ extract_field(sf->second, sf->nb_planes, sf->second->top_field_first);
+ ret = ff_filter_frame(outlink, sf->second);
+ sf->second = 0;
}
- second->pts = outlink->frame_count * sf->ts_unit;
- return ff_filter_frame(outlink, second);
+ return ret;
}
static const AVFilterPad separatefields_inputs[] = {
@@ -97,9 +129,10 @@ static const AVFilterPad separatefields_inputs[] = {
static const AVFilterPad separatefields_outputs[] = {
{
- .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .config_props = config_props_output,
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .config_props = config_props_output,
+ .request_frame = request_frame,
},
{ NULL }
};