summaryrefslogtreecommitdiff
path: root/libavfilter/buffersrc.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2013-03-10 01:30:30 +0100
committerMichael Niedermayer <michaelni@gmx.at>2013-03-10 01:40:35 +0100
commita05a44e205d6ae13d5eb1cd8d4ad2dba6ec940b3 (patch)
tree450d7173e72748db59d6cfb7107c688bc825fc9a /libavfilter/buffersrc.c
parent586ae70ba78e023d16c0c812b05a26c7d423833b (diff)
parent7e350379f87e7f74420b4813170fe808e2313911 (diff)
Merge commit '7e350379f87e7f74420b4813170fe808e2313911'
* commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter/buffersrc.c')
-rw-r--r--libavfilter/buffersrc.c282
1 files changed, 192 insertions, 90 deletions
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index d150357ffa..6c6689b4ca 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"
@@ -74,99 +75,193 @@ typedef struct {
return AVERROR(EINVAL);\
}
-int av_buffersrc_add_frame(AVFilterContext *buffer_src,
- const AVFrame *frame, int flags)
+int av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
{
- AVFilterBufferRef *picref;
- int ret;
+ return av_buffersrc_add_frame(ctx, frame);
+}
+
+int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
+{
+ AVFrame *copy;
+ int ret = 0;
+ int64_t layout = frame->channel_layout;
- if (!frame) /* NULL for EOF */
- return av_buffersrc_add_ref(buffer_src, NULL, flags);
+ if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) {
+ av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n");
+ return AVERROR(EINVAL);
+ }
- picref = avfilter_get_buffer_ref_from_frame(buffer_src->outputs[0]->type,
- frame, AV_PERM_WRITE);
- if (!picref)
+ if (!(copy = av_frame_alloc()))
return AVERROR(ENOMEM);
- ret = av_buffersrc_add_ref(buffer_src, picref, flags);
- picref->buf->data[0] = NULL;
- avfilter_unref_buffer(picref);
- return ret;
-}
+ ret = av_frame_ref(copy, frame);
+ if (ret >= 0)
+ ret = av_buffersrc_add_frame(ctx, copy);
-int av_buffersrc_write_frame(AVFilterContext *buffer_filter, const AVFrame *frame)
-{
- return av_buffersrc_add_frame(buffer_filter, frame, 0);
+ av_frame_free(&copy);
+ return ret;
}
-int av_buffersrc_add_ref(AVFilterContext *s, AVFilterBufferRef *buf, int flags)
+int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame)
{
- BufferSourceContext *c = s->priv;
- AVFilterBufferRef *to_free = NULL;
+ BufferSourceContext *s = ctx->priv;
+ AVFrame *copy;
int ret;
+ int64_t layout;
- if (!buf) {
- c->eof = 1;
+ if (!frame) {
+ 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 (ctx->outputs[0]->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
+ frame->format);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout,
+ frame->format);
- if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) {
- 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:
- if (!buf->audio->channel_layout)
- buf->audio->channel_layout = c->channel_layout;
- CHECK_AUDIO_PARAM_CHANGE(s, c, buf->audio->sample_rate, buf->audio->channel_layout,
- buf->format);
- break;
- default:
+ layout = frame->channel_layout;
+ if (layout && av_get_channel_layout_nb_channels(layout) != av_frame_get_channels(frame)) {
+ av_log(0, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n");
return AVERROR(EINVAL);
}
+ break;
+ default:
+ return AVERROR(EINVAL);
}
- if (!(flags & AV_BUFFERSRC_FLAG_NO_COPY))
- to_free = buf = ff_copy_buffer_ref(s->outputs[0], buf);
- if(!buf)
- return -1;
- if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
- avfilter_unref_buffer(to_free);
+ if (!av_fifo_space(s->fifo) &&
+ (ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) +
+ sizeof(copy))) < 0)
return ret;
- }
- c->nb_failed_requests = 0;
- if (c->warning_limit &&
- av_fifo_size(c->fifo) / sizeof(buf) >= c->warning_limit) {
- av_log(s, AV_LOG_WARNING,
- "%d buffers queued in %s, something may be wrong.\n",
- c->warning_limit,
- (char *)av_x_if_null(s->name, s->filter->name));
- c->warning_limit *= 10;
- }
- if ((flags & AV_BUFFERSRC_FLAG_PUSH))
- if ((ret = s->output_pads[0].request_frame(s->outputs[0])) < 0)
- return ret;
+ if (!(copy = av_frame_alloc()))
+ return AVERROR(ENOMEM);
+ av_frame_move_ref(copy, frame);
+
+ if ((ret = av_fifo_generic_write(s->fifo, &copy, sizeof(copy), NULL)) < 0) {
+ av_frame_move_ref(frame, copy);
+ av_frame_free(&copy);
+ return ret;
+ }
return 0;
}
-#ifdef FF_API_BUFFERSRC_BUFFER
-int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
+#if FF_API_AVFILTERBUFFER
+static void compat_free_buffer(void *opaque, uint8_t *data)
{
- return av_buffersrc_add_ref(s, buf, AV_BUFFERSRC_FLAG_NO_COPY);
+ AVFilterBufferRef *buf = opaque;
+ avfilter_unref_buffer(buf);
}
-#endif
-unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src)
+static void compat_unref_buffer(void *opaque, uint8_t *data)
{
- return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests;
+ AVBufferRef *buf = opaque;
+ av_buffer_unref(&buf);
+}
+
+int av_buffersrc_add_ref(AVFilterContext *ctx, AVFilterBufferRef *buf,
+ int flags)
+{
+ BufferSourceContext *s = ctx->priv;
+ AVFrame *frame = NULL;
+ AVBufferRef *dummy_buf = NULL;
+ int ret = 0, planes, i;
+
+ if (!buf) {
+ s->eof = 1;
+ return 0;
+ } else if (s->eof)
+ return AVERROR(EINVAL);
+
+ frame = av_frame_alloc();
+ if (!frame)
+ return AVERROR(ENOMEM);
+
+ dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, buf,
+ (buf->perms & AV_PERM_WRITE) ? 0 : AV_BUFFER_FLAG_READONLY);
+ if (!dummy_buf) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if ((ret = avfilter_copy_buf_props(frame, buf)) < 0)
+ goto fail;
+
+#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, (buf->perms & AV_PERM_WRITE) ? 0 : AV_BUFFER_FLAG_READONLY); \
+ 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_flags(ctx, frame, flags);
+
+fail:
+ av_buffer_unref(&dummy_buf);
+ av_frame_free(&frame);
+
+ return ret;
+}
+
+int av_buffersrc_buffer(AVFilterContext *ctx, AVFilterBufferRef *buf)
+{
+ return av_buffersrc_add_ref(ctx, buf, 0);
}
+#endif
#define OFFSET(x) offsetof(BufferSourceContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
@@ -186,7 +281,7 @@ AVFILTER_DEFINE_CLASS(buffer);
static av_cold int init_video(AVFilterContext *ctx, const char *args)
{
BufferSourceContext *c = ctx->priv;
- char pix_fmt_str[128], sws_param[256] = "", *colon, *equal;
+ char pix_fmt_str[128], *colon, *equal;
int ret, n = 0;
c->class = &buffer_class;
@@ -195,6 +290,7 @@ static av_cold int init_video(AVFilterContext *ctx, const char *args)
av_log(ctx, AV_LOG_ERROR, "Arguments required\n");
return AVERROR(EINVAL);
}
+
colon = strchr(args, ':');
equal = strchr(args, '=');
if (equal && (!colon || equal < colon)) {
@@ -203,28 +299,25 @@ static av_cold int init_video(AVFilterContext *ctx, const char *args)
if (ret < 0)
goto fail;
} else {
- if ((n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d:%255c", &c->w, &c->h, pix_fmt_str,
+ if (!args ||
+ (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d", &c->w, &c->h, pix_fmt_str,
&c->time_base.num, &c->time_base.den,
- &c->pixel_aspect.num, &c->pixel_aspect.den, sws_param)) < 7) {
- av_log(ctx, AV_LOG_ERROR, "Expected at least 7 arguments, but only %d found in '%s'\n", n, args);
- ret = AVERROR(EINVAL);
- goto fail;
+ &c->pixel_aspect.num, &c->pixel_aspect.den)) != 7) {
+ av_log(ctx, AV_LOG_ERROR, "Expected 7 arguments, but %d found in '%s'\n", n, args);
+ return AVERROR(EINVAL);
}
- av_log(ctx, AV_LOG_WARNING, "Flat options syntax is deprecated, use key=value pairs\n");
-
- if ((ret = ff_parse_pixel_format(&c->pix_fmt, pix_fmt_str, ctx)) < 0)
- goto fail;
- c->sws_param = av_strdup(sws_param);
- if (!c->sws_param) {
- ret = AVERROR(ENOMEM);
- goto fail;
+ if ((c->pix_fmt = av_get_pix_fmt(pix_fmt_str)) == AV_PIX_FMT_NONE) {
+ char *tail;
+ c->pix_fmt = strtol(pix_fmt_str, &tail, 10);
+ if (*tail || c->pix_fmt < 0 || c->pix_fmt >= AV_PIX_FMT_NB) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", pix_fmt_str);
+ return AVERROR(EINVAL);
+ }
}
}
- if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
+ if (!(c->fifo = av_fifo_alloc(sizeof(AVFrame*))))
+ return AVERROR(ENOMEM);
av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d sws_param:%s\n",
c->w, c->h, av_get_pix_fmt_name(c->pix_fmt),
@@ -238,6 +331,11 @@ fail:
return ret;
}
+unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src)
+{
+ return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests;
+}
+
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
static const AVOption abuffer_options[] = {
{ "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS },
@@ -298,7 +396,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;
}
@@ -321,9 +419,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;
@@ -387,7 +485,8 @@ 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)) {
if (c->eof)
@@ -395,9 +494,12 @@ static int request_frame(AVFilterLink *link)
c->nb_failed_requests++;
return AVERROR(EAGAIN);
}
- av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
+ av_fifo_generic_read(c->fifo, &frame, sizeof(frame), NULL);
- return ff_filter_frame(link, buf);
+ /* CIG TODO do not ignore error */
+ ff_filter_frame(link, frame);
+
+ return ret;
}
static int poll_frame(AVFilterLink *link)
@@ -406,7 +508,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[] = {