diff options
author | Paul B Mahol <onemda@gmail.com> | 2013-09-06 18:34:28 +0400 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2013-09-06 22:34:37 +0400 |
commit | 6770fa4df8e1e11c2d76e6b2ebb30d66f5d0bf3f (patch) | |
tree | cd8f996e82a0e1c907a1d8998b5963061ad4bfcc | |
parent | 33dacda40b7af74f9d7f5aea29e39c1aa12acdc7 (diff) |
lavfi/fieldorder: work with non writtable frames too
Signed-off-by: Paul B Mahol <onemda@gmail.com>
-rw-r--r-- | libavfilter/vf_fieldorder.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index d2c01d3951..610664f855 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -80,21 +80,35 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) AVFilterContext *ctx = inlink->dst; FieldOrderContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - int h, plane, line_step, line_size, line; - uint8_t *data; + int h, plane, src_line_step, dst_line_step, line_size, line; + uint8_t *dst, *src; + AVFrame *out; if (!frame->interlaced_frame || frame->top_field_first == s->dst_tff) return ff_filter_frame(outlink, frame); + if (av_frame_is_writable(frame)) { + out = frame; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&frame); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, frame); + } + av_dlog(ctx, "picture will move %s one line\n", s->dst_tff ? "up" : "down"); h = frame->height; for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { - line_step = frame->linesize[plane]; + dst_line_step = out->linesize[plane]; + src_line_step = frame->linesize[plane]; line_size = s->line_size[plane]; - data = frame->data[plane]; + dst = out->data[plane]; + src = frame->data[plane]; if (s->dst_tff) { /** Move every line up one line, working from * the top to the bottom of the frame. @@ -103,11 +117,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) * penultimate line from that field. */ for (line = 0; line < h; line++) { if (1 + line < frame->height) { - memcpy(data, data + line_step, line_size); + memcpy(dst, src + src_line_step, line_size); } else { - memcpy(data, data - line_step - line_step, line_size); + memcpy(dst, src - 2 * src_line_step, line_size); } - data += line_step; + dst += dst_line_step; + src += src_line_step; } } else { /** Move every line down one line, working from @@ -115,20 +130,24 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) * The original bottom line is lost. * The new first line is created as a copy of the * second line from that field. */ - data += (h - 1) * line_step; + dst += (h - 1) * dst_line_step; + src += (h - 1) * src_line_step; for (line = h - 1; line >= 0 ; line--) { if (line > 0) { - memcpy(data, data - line_step, line_size); + memcpy(dst, src - src_line_step, line_size); } else { - memcpy(data, data + line_step + line_step, line_size); + memcpy(dst, src + 2 * src_line_step, line_size); } - data -= line_step; + dst -= dst_line_step; + src -= src_line_step; } } } - frame->top_field_first = s->dst_tff; + out->top_field_first = s->dst_tff; - return ff_filter_frame(outlink, frame); + if (frame != out) + av_frame_free(&frame); + return ff_filter_frame(outlink, out); } #define OFFSET(x) offsetof(FieldOrderContext, x) @@ -149,7 +168,6 @@ static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, .filter_frame = filter_frame, - .needs_writable = 1, }, { NULL } }; |