From 7e350379f87e7f74420b4813170fe808e2313911 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 28 Nov 2012 08:41:07 +0100 Subject: lavfi: switch to AVFrame. Deprecate AVFilterBuffer/AVFilterBufferRef and everything related to it and use AVFrame instead. --- libavfilter/buffersrc.c | 200 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 137 insertions(+), 63 deletions(-) (limited to 'libavfilter/buffersrc.c') diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 3cee68da43..d35b302a9e 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -26,6 +26,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/fifo.h" +#include "libavutil/frame.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/samplefmt.h" @@ -69,95 +70,168 @@ typedef struct { return AVERROR(EINVAL);\ } -int av_buffersrc_write_frame(AVFilterContext *buffer_filter, const AVFrame *frame) +int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame) { - BufferSourceContext *c = buffer_filter->priv; - AVFilterBufferRef *buf; + AVFrame *copy; + int ret = 0; + + if (!(copy = av_frame_alloc())) + return AVERROR(ENOMEM); + ret = av_frame_ref(copy, frame); + if (ret >= 0) + ret = av_buffersrc_add_frame(ctx, copy); + + av_frame_free(©); + return ret; +} + +int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame) +{ + BufferSourceContext *s = ctx->priv; + AVFrame *copy; int ret; if (!frame) { - c->eof = 1; + s->eof = 1; return 0; - } else if (c->eof) + } else if (s->eof) return AVERROR(EINVAL); - if (!av_fifo_space(c->fifo) && - (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + - sizeof(buf))) < 0) - return ret; - - switch (buffer_filter->outputs[0]->type) { + switch (ctx->outputs[0]->type) { case AVMEDIA_TYPE_VIDEO: - CHECK_VIDEO_PARAM_CHANGE(buffer_filter, c, frame->width, frame->height, + CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height, frame->format); - buf = ff_get_video_buffer(buffer_filter->outputs[0], AV_PERM_WRITE, - c->w, c->h); - if (!buf) - return AVERROR(ENOMEM); - - av_image_copy(buf->data, buf->linesize, frame->data, frame->linesize, - c->pix_fmt, c->w, c->h); break; case AVMEDIA_TYPE_AUDIO: - CHECK_AUDIO_PARAM_CHANGE(buffer_filter, c, frame->sample_rate, frame->channel_layout, + CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout, frame->format); - buf = ff_get_audio_buffer(buffer_filter->outputs[0], AV_PERM_WRITE, - frame->nb_samples); - if (!buf) - return AVERROR(ENOMEM); - - av_samples_copy(buf->extended_data, frame->extended_data, - 0, 0, frame->nb_samples, - av_get_channel_layout_nb_channels(frame->channel_layout), - frame->format); break; default: return AVERROR(EINVAL); } - avfilter_copy_frame_props(buf, frame); + if (!av_fifo_space(s->fifo) && + (ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) + + sizeof(copy))) < 0) + return ret; + + if (!(copy = av_frame_alloc())) + return AVERROR(ENOMEM); + av_frame_move_ref(copy, frame); - if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) { - avfilter_unref_buffer(buf); + if ((ret = av_fifo_generic_write(s->fifo, ©, sizeof(copy), NULL)) < 0) { + av_frame_move_ref(frame, copy); + av_frame_free(©); return ret; } return 0; } -int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf) +#if FF_API_AVFILTERBUFFER +static void compat_free_buffer(void *opaque, uint8_t *data) { - BufferSourceContext *c = s->priv; - int ret; + AVFilterBufferRef *buf = opaque; + avfilter_unref_buffer(buf); +} + +static void compat_unref_buffer(void *opaque, uint8_t *data) +{ + AVBufferRef *buf = opaque; + av_buffer_unref(&buf); +} + +int av_buffersrc_buffer(AVFilterContext *ctx, AVFilterBufferRef *buf) +{ + BufferSourceContext *s = ctx->priv; + AVFrame *frame = NULL; + AVBufferRef *dummy_buf = NULL; + int ret = 0, planes, i; if (!buf) { - c->eof = 1; + s->eof = 1; return 0; - } else if (c->eof) + } else if (s->eof) return AVERROR(EINVAL); - if (!av_fifo_space(c->fifo) && - (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + - sizeof(buf))) < 0) - return ret; + frame = av_frame_alloc(); + if (!frame) + return AVERROR(ENOMEM); - switch (s->outputs[0]->type) { - case AVMEDIA_TYPE_VIDEO: - CHECK_VIDEO_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format); - break; - case AVMEDIA_TYPE_AUDIO: - CHECK_AUDIO_PARAM_CHANGE(s, c, buf->audio->sample_rate, buf->audio->channel_layout, - buf->format); - break; - default: - return AVERROR(EINVAL); + dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, buf, 0); + if (!dummy_buf) { + ret = AVERROR(ENOMEM); + goto fail; } - if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) - return ret; + if ((ret = avfilter_copy_buf_props(frame, buf)) < 0) + goto fail; - return 0; +#define WRAP_PLANE(ref_out, data, data_size) \ +do { \ + AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf); \ + if (!dummy_ref) { \ + ret = AVERROR(ENOMEM); \ + goto fail; \ + } \ + ref_out = av_buffer_create(data, data_size, compat_unref_buffer, \ + dummy_ref, 0); \ + if (!ref_out) { \ + av_frame_unref(frame); \ + ret = AVERROR(ENOMEM); \ + goto fail; \ + } \ +} while (0) + + if (ctx->outputs[0]->type == AVMEDIA_TYPE_VIDEO) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + + if (!desc) { + ret = AVERROR(EINVAL); + goto fail; + } + planes = (desc->flags & PIX_FMT_PLANAR) ? desc->nb_components : 1; + + for (i = 0; i < planes; i++) { + int h_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; + int plane_size = (frame->width >> h_shift) * frame->linesize[i]; + + WRAP_PLANE(frame->buf[i], frame->data[i], plane_size); + } + } else { + int planar = av_sample_fmt_is_planar(frame->format); + int channels = av_get_channel_layout_nb_channels(frame->channel_layout); + + planes = planar ? channels : 1; + + if (planes > FF_ARRAY_ELEMS(frame->buf)) { + frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf); + frame->extended_buf = av_mallocz(sizeof(*frame->extended_buf) * + frame->nb_extended_buf); + if (!frame->extended_buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++) + WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]); + + for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++) + WRAP_PLANE(frame->extended_buf[i], + frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)], + frame->linesize[0]); + } + + ret = av_buffersrc_add_frame(ctx, frame); + +fail: + av_buffer_unref(&dummy_buf); + av_frame_free(&frame); + + return ret; } +#endif static av_cold int init_video(AVFilterContext *ctx, const char *args) { @@ -181,7 +255,7 @@ static av_cold int init_video(AVFilterContext *ctx, const char *args) } } - if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) + if (!(c->fifo = av_fifo_alloc(sizeof(AVFrame*)))) return AVERROR(ENOMEM); av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_get_pix_fmt_name(c->pix_fmt)); @@ -234,7 +308,7 @@ static av_cold int init_audio(AVFilterContext *ctx, const char *args) goto fail; } - if (!(s->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) { + if (!(s->fifo = av_fifo_alloc(sizeof(AVFrame*)))) { ret = AVERROR(ENOMEM); goto fail; } @@ -255,9 +329,9 @@ static av_cold void uninit(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; while (s->fifo && av_fifo_size(s->fifo)) { - AVFilterBufferRef *buf; - av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL); - avfilter_unref_buffer(buf); + AVFrame *frame; + av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL); + av_frame_free(&frame); } av_fifo_free(s->fifo); s->fifo = NULL; @@ -317,7 +391,7 @@ static int config_props(AVFilterLink *link) static int request_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; - AVFilterBufferRef *buf; + AVFrame *frame; int ret = 0; if (!av_fifo_size(c->fifo)) { @@ -325,9 +399,9 @@ static int request_frame(AVFilterLink *link) return AVERROR_EOF; return AVERROR(EAGAIN); } - av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL); + av_fifo_generic_read(c->fifo, &frame, sizeof(frame), NULL); - ff_filter_frame(link, buf); + ff_filter_frame(link, frame); return ret; } @@ -338,7 +412,7 @@ static int poll_frame(AVFilterLink *link) int size = av_fifo_size(c->fifo); if (!size && c->eof) return AVERROR_EOF; - return size/sizeof(AVFilterBufferRef*); + return size/sizeof(AVFrame*); } static const AVFilterPad avfilter_vsrc_buffer_outputs[] = { -- cgit v1.2.3