diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-05-16 02:27:31 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-05-16 02:27:31 +0200 |
commit | 1cbf7fb4345a3e5b7791d483241bf4759bde4ece (patch) | |
tree | d7acd8317309e051fb240e3505f77aabe2ea0437 /libavfilter/buffersink.c | |
parent | a48abf5e263ad7f2e68821766e7cf4d29befb58e (diff) | |
parent | 0ff0af731ce4544f84b2f748dcc699717a2df8d6 (diff) | |
download | ffmpeg-1cbf7fb4345a3e5b7791d483241bf4759bde4ece.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master: (26 commits)
fate: use diff -b in oneline comparison
Add missing version bumps and APIchanges/Changelog entries.
lavfi: move buffer management function to a separate file.
lavfi: move formats-related functions from default.c to formats.c
lavfi: move video-related functions to a separate file.
fate: make smjpeg a demux test
fate: separate sierra-vmd audio and video tests
fate: separate smacker audio and video tests
libmp3lame: set supported channel layouts.
avconv: automatically insert asyncts when -async is used.
avconv: add support for audio filters.
lavfi: add asyncts filter.
lavfi: add aformat filter
lavfi: add an audio buffer sink.
lavfi: add an audio buffer source.
buffersrc: add av_buffersrc_write_frame().
buffersrc: fix invalid read in uninit if the fifo hasn't been allocated
lavfi: rename vsrc_buffer.c to buffersrc.c
avfiltergraph: reindent
lavfi: add channel layout/sample rate negotiation.
...
Conflicts:
Changelog
doc/APIchanges
doc/filters.texi
ffmpeg.c
ffprobe.c
libavcodec/libmp3lame.c
libavfilter/Makefile
libavfilter/af_aformat.c
libavfilter/allfilters.c
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/avfiltergraph.c
libavfilter/buffersrc.c
libavfilter/defaults.c
libavfilter/formats.c
libavfilter/src_buffer.c
libavfilter/version.h
libavfilter/vf_yadif.c
libavfilter/vsrc_buffer.c
libavfilter/vsrc_buffer.h
libavutil/avutil.h
tests/fate/audio.mak
tests/fate/demux.mak
tests/fate/video.mak
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter/buffersink.c')
-rw-r--r-- | libavfilter/buffersink.c | 102 |
1 files changed, 98 insertions, 4 deletions
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index f0fcab553e..90ebd93908 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -23,13 +23,20 @@ * buffer sink */ +#include "libavutil/audio_fifo.h" +#include "libavutil/audioconvert.h" #include "libavutil/fifo.h" +#include "libavutil/mathematics.h" +#include "audio.h" #include "avfilter.h" #include "buffersink.h" typedef struct { - AVFifoBuffer *fifo; ///< FIFO buffer of video frame references + AVFifoBuffer *fifo; ///< FIFO buffer of frame references + + AVAudioFifo *audio_fifo; ///< FIFO for audio samples + int64_t next_pts; ///< interpolating audio pts } BufferSinkContext; #define FIFO_INIT_SIZE 8 @@ -44,6 +51,9 @@ static av_cold void uninit(AVFilterContext *ctx) avfilter_unref_buffer(buf); } av_fifo_free(sink->fifo); + + if (sink->audio_fifo) + av_audio_fifo_free(sink->audio_fifo); } static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) @@ -58,9 +68,8 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) return 0; } -static void end_frame(AVFilterLink *link) +static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf) { - AVFilterContext *ctx = link->dst; BufferSinkContext *sink = ctx->priv; if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) && @@ -69,10 +78,20 @@ static void end_frame(AVFilterLink *link) return; } - av_fifo_generic_write(sink->fifo, &link->cur_buf, sizeof(link->cur_buf), NULL); + av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL); +} + +static void end_frame(AVFilterLink *link) +{ + write_buf(link->dst, link->cur_buf); link->cur_buf = NULL; } +static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) +{ + write_buf(link->dst, buf); +} + int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) { BufferSinkContext *sink = ctx->priv; @@ -98,6 +117,66 @@ int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf) return 0; } +static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf, + int nb_samples) +{ + BufferSinkContext *s = ctx->priv; + AVFilterLink *link = ctx->inputs[0]; + AVFilterBufferRef *buf; + + if (!(buf = ff_get_audio_buffer(link, AV_PERM_WRITE, nb_samples))) + return AVERROR(ENOMEM); + av_audio_fifo_read(s->audio_fifo, (void**)buf->extended_data, nb_samples); + + buf->pts = s->next_pts; + s->next_pts += av_rescale_q(nb_samples, (AVRational){1, link->sample_rate}, + link->time_base); + + *pbuf = buf; + return 0; + +} + +int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf, + int nb_samples) +{ + BufferSinkContext *s = ctx->priv; + AVFilterLink *link = ctx->inputs[0]; + int ret = 0; + + if (!s->audio_fifo) { + int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); + if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples))) + return AVERROR(ENOMEM); + } + + while (ret >= 0) { + AVFilterBufferRef *buf; + + if (av_audio_fifo_size(s->audio_fifo) >= nb_samples) + return read_from_fifo(ctx, pbuf, nb_samples); + + ret = av_buffersink_read(ctx, &buf); + if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo)) + return read_from_fifo(ctx, pbuf, av_audio_fifo_size(s->audio_fifo)); + else if (ret < 0) + return ret; + + if (buf->pts != AV_NOPTS_VALUE) { + s->next_pts = buf->pts - + av_rescale_q(av_audio_fifo_size(s->audio_fifo), + (AVRational){ 1, link->sample_rate }, + link->time_base); + } + + ret = av_audio_fifo_write(s->audio_fifo, (void**)buf->extended_data, + buf->audio->nb_samples); + avfilter_unref_buffer(buf); + } + + return ret; +} + AVFilter avfilter_vsink_buffer = { .name = "buffersink_old", .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), @@ -112,3 +191,18 @@ AVFilter avfilter_vsink_buffer = { { .name = NULL }}, .outputs = (AVFilterPad[]) {{ .name = NULL }}, }; + +AVFilter avfilter_asink_abuffer = { + .name = "abuffersink_old", + .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), + .priv_size = sizeof(BufferSinkContext), + .init = init, + .uninit = uninit, + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_samples = filter_samples, + .min_perms = AV_PERM_READ, }, + { .name = NULL }}, + .outputs = (AVFilterPad[]) {{ .name = NULL }}, +}; |