summaryrefslogtreecommitdiff
path: root/libavfilter/buffersink.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-05-16 02:27:31 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-05-16 02:27:31 +0200
commit1cbf7fb4345a3e5b7791d483241bf4759bde4ece (patch)
treed7acd8317309e051fb240e3505f77aabe2ea0437 /libavfilter/buffersink.c
parenta48abf5e263ad7f2e68821766e7cf4d29befb58e (diff)
parent0ff0af731ce4544f84b2f748dcc699717a2df8d6 (diff)
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.c102
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 }},
+};