|
|
|
@ -20,6 +20,7 @@ |
|
|
|
|
|
|
|
|
|
#include "libavutil/imgutils.h" |
|
|
|
|
#include "avfilter.h" |
|
|
|
|
#include "filters.h" |
|
|
|
|
#include "internal.h" |
|
|
|
|
|
|
|
|
|
typedef struct RepeatFieldsContext { |
|
|
|
@ -75,23 +76,23 @@ static void update_pts(AVFilterLink *link, AVFrame *f, int64_t pts, int fields) |
|
|
|
|
f->pts = AV_NOPTS_VALUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { |
|
|
|
|
static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
|
|
|
{ |
|
|
|
|
AVFilterContext *ctx = inlink->dst; |
|
|
|
|
AVFilterLink *outlink = inlink->dst->outputs[0]; |
|
|
|
|
RepeatFieldsContext *s = ctx->priv; |
|
|
|
|
AVFrame *out; |
|
|
|
|
int ret, i; |
|
|
|
|
int state = s->state; |
|
|
|
|
|
|
|
|
|
if (!s->frame) { |
|
|
|
|
s->frame = av_frame_clone(in); |
|
|
|
|
if (!s->frame) |
|
|
|
|
if (!s->frame) { |
|
|
|
|
av_frame_free(&in); |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
s->frame->pts = AV_NOPTS_VALUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
out = s->frame; |
|
|
|
|
|
|
|
|
|
if ((state == 0 && !in->top_field_first) || |
|
|
|
|
(state == 1 && in->top_field_first)) { |
|
|
|
|
av_log(ctx, AV_LOG_WARNING, "Unexpected field flags: " |
|
|
|
@ -104,16 +105,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { |
|
|
|
|
AVFrame *new; |
|
|
|
|
|
|
|
|
|
new = av_frame_clone(in); |
|
|
|
|
if (!new) |
|
|
|
|
if (!new) { |
|
|
|
|
av_frame_free(&in); |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret = ff_filter_frame(outlink, new); |
|
|
|
|
|
|
|
|
|
if (in->repeat_pict) { |
|
|
|
|
av_frame_make_writable(out); |
|
|
|
|
update_pts(outlink, out, in->pts, 2); |
|
|
|
|
ret = ff_inlink_make_frame_writable(inlink, &s->frame); |
|
|
|
|
if (ret < 0) { |
|
|
|
|
av_frame_free(&in); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
update_pts(outlink, s->frame, in->pts, 2); |
|
|
|
|
for (i = 0; i < s->nb_planes; i++) { |
|
|
|
|
av_image_copy_plane(out->data[i], out->linesize[i] * 2, |
|
|
|
|
av_image_copy_plane(s->frame->data[i], s->frame->linesize[i] * 2, |
|
|
|
|
in->data[i], in->linesize[i] * 2, |
|
|
|
|
s->linesize[i], s->planeheight[i] / 2); |
|
|
|
|
} |
|
|
|
@ -121,28 +128,38 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
for (i = 0; i < s->nb_planes; i++) { |
|
|
|
|
av_frame_make_writable(out); |
|
|
|
|
av_image_copy_plane(out->data[i] + out->linesize[i], out->linesize[i] * 2, |
|
|
|
|
ret = ff_inlink_make_frame_writable(inlink, &s->frame); |
|
|
|
|
if (ret < 0) { |
|
|
|
|
av_frame_free(&in); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
av_image_copy_plane(s->frame->data[i] + s->frame->linesize[i], s->frame->linesize[i] * 2, |
|
|
|
|
in->data[i] + in->linesize[i], in->linesize[i] * 2, |
|
|
|
|
s->linesize[i], s->planeheight[i] / 2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret = ff_filter_frame(outlink, av_frame_clone(out)); |
|
|
|
|
ret = ff_filter_frame(outlink, av_frame_clone(s->frame)); |
|
|
|
|
|
|
|
|
|
if (in->repeat_pict) { |
|
|
|
|
AVFrame *new; |
|
|
|
|
|
|
|
|
|
new = av_frame_clone(in); |
|
|
|
|
if (!new) |
|
|
|
|
if (!new) { |
|
|
|
|
av_frame_free(&in); |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret = ff_filter_frame(outlink, new); |
|
|
|
|
state = 0; |
|
|
|
|
} else { |
|
|
|
|
av_frame_make_writable(out); |
|
|
|
|
update_pts(outlink, out, in->pts, 1); |
|
|
|
|
ret = ff_inlink_make_frame_writable(inlink, &s->frame); |
|
|
|
|
if (ret < 0) { |
|
|
|
|
av_frame_free(&in); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
update_pts(outlink, s->frame, in->pts, 1); |
|
|
|
|
for (i = 0; i < s->nb_planes; i++) { |
|
|
|
|
av_image_copy_plane(out->data[i], out->linesize[i] * 2, |
|
|
|
|
av_image_copy_plane(s->frame->data[i], s->frame->linesize[i] * 2, |
|
|
|
|
in->data[i], in->linesize[i] * 2, |
|
|
|
|
s->linesize[i], s->planeheight[i] / 2); |
|
|
|
|
} |
|
|
|
|