diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-03-10 01:30:30 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-03-10 01:40:35 +0100 |
commit | a05a44e205d6ae13d5eb1cd8d4ad2dba6ec940b3 (patch) | |
tree | 450d7173e72748db59d6cfb7107c688bc825fc9a /libavfilter/buffersrc.c | |
parent | 586ae70ba78e023d16c0c812b05a26c7d423833b (diff) | |
parent | 7e350379f87e7f74420b4813170fe808e2313911 (diff) | |
download | ffmpeg-a05a44e205d6ae13d5eb1cd8d4ad2dba6ec940b3.tar.gz |
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.c | 282 |
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(©); + 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, ©, sizeof(copy), NULL)) < 0) { + av_frame_move_ref(frame, copy); + av_frame_free(©); + 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[] = { |