00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libavutil/audio_fifo.h"
00027 #include "libavutil/audioconvert.h"
00028 #include "libavutil/fifo.h"
00029 #include "libavutil/mathematics.h"
00030
00031 #include "audio.h"
00032 #include "avfilter.h"
00033 #include "buffersink.h"
00034
00035 typedef struct {
00036 AVFifoBuffer *fifo;
00037
00038 AVAudioFifo *audio_fifo;
00039 int64_t next_pts;
00040 } BufferSinkContext;
00041
00042 #define FIFO_INIT_SIZE 8
00043
00044 static av_cold void uninit(AVFilterContext *ctx)
00045 {
00046 BufferSinkContext *sink = ctx->priv;
00047
00048 while (sink->fifo && av_fifo_size(sink->fifo)) {
00049 AVFilterBufferRef *buf;
00050 av_fifo_generic_read(sink->fifo, &buf, sizeof(buf), NULL);
00051 avfilter_unref_buffer(buf);
00052 }
00053 av_fifo_free(sink->fifo);
00054
00055 if (sink->audio_fifo)
00056 av_audio_fifo_free(sink->audio_fifo);
00057 }
00058
00059 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
00060 {
00061 BufferSinkContext *sink = ctx->priv;
00062
00063 if (!(sink->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef*)))) {
00064 av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
00065 return AVERROR(ENOMEM);
00066 }
00067
00068 return 0;
00069 }
00070
00071 static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
00072 {
00073 BufferSinkContext *sink = ctx->priv;
00074
00075 if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) &&
00076 (av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) {
00077 av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n");
00078 return;
00079 }
00080
00081 av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL);
00082 }
00083
00084 static void end_frame(AVFilterLink *link)
00085 {
00086 write_buf(link->dst, link->cur_buf);
00087 link->cur_buf = NULL;
00088 }
00089
00090 static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
00091 {
00092 write_buf(link->dst, buf);
00093 }
00094
00095 int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
00096 {
00097 BufferSinkContext *sink = ctx->priv;
00098 AVFilterLink *link = ctx->inputs[0];
00099 int ret;
00100
00101 if (!buf) {
00102 if (av_fifo_size(sink->fifo))
00103 return av_fifo_size(sink->fifo)/sizeof(*buf);
00104 else
00105 return avfilter_poll_frame(ctx->inputs[0]);
00106 }
00107
00108 if (!av_fifo_size(sink->fifo) &&
00109 (ret = avfilter_request_frame(link)) < 0)
00110 return ret;
00111
00112 if (!av_fifo_size(sink->fifo))
00113 return AVERROR(EINVAL);
00114
00115 av_fifo_generic_read(sink->fifo, buf, sizeof(*buf), NULL);
00116
00117 return 0;
00118 }
00119
00120 static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
00121 int nb_samples)
00122 {
00123 BufferSinkContext *s = ctx->priv;
00124 AVFilterLink *link = ctx->inputs[0];
00125 AVFilterBufferRef *buf;
00126
00127 if (!(buf = ff_get_audio_buffer(link, AV_PERM_WRITE, nb_samples)))
00128 return AVERROR(ENOMEM);
00129 av_audio_fifo_read(s->audio_fifo, (void**)buf->extended_data, nb_samples);
00130
00131 buf->pts = s->next_pts;
00132 s->next_pts += av_rescale_q(nb_samples, (AVRational){1, link->sample_rate},
00133 link->time_base);
00134
00135 *pbuf = buf;
00136 return 0;
00137
00138 }
00139
00140 int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
00141 int nb_samples)
00142 {
00143 BufferSinkContext *s = ctx->priv;
00144 AVFilterLink *link = ctx->inputs[0];
00145 int ret = 0;
00146
00147 if (!s->audio_fifo) {
00148 int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
00149 if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples)))
00150 return AVERROR(ENOMEM);
00151 }
00152
00153 while (ret >= 0) {
00154 AVFilterBufferRef *buf;
00155
00156 if (av_audio_fifo_size(s->audio_fifo) >= nb_samples)
00157 return read_from_fifo(ctx, pbuf, nb_samples);
00158
00159 ret = av_buffersink_read(ctx, &buf);
00160 if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo))
00161 return read_from_fifo(ctx, pbuf, av_audio_fifo_size(s->audio_fifo));
00162 else if (ret < 0)
00163 return ret;
00164
00165 if (buf->pts != AV_NOPTS_VALUE) {
00166 s->next_pts = buf->pts -
00167 av_rescale_q(av_audio_fifo_size(s->audio_fifo),
00168 (AVRational){ 1, link->sample_rate },
00169 link->time_base);
00170 }
00171
00172 ret = av_audio_fifo_write(s->audio_fifo, (void**)buf->extended_data,
00173 buf->audio->nb_samples);
00174 avfilter_unref_buffer(buf);
00175 }
00176
00177 return ret;
00178 }
00179
00180 AVFilter avfilter_vsink_buffer = {
00181 .name = "buffersink_old",
00182 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
00183 .priv_size = sizeof(BufferSinkContext),
00184 .init = init,
00185 .uninit = uninit,
00186
00187 .inputs = (AVFilterPad[]) {{ .name = "default",
00188 .type = AVMEDIA_TYPE_VIDEO,
00189 .end_frame = end_frame,
00190 .min_perms = AV_PERM_READ, },
00191 { .name = NULL }},
00192 .outputs = (AVFilterPad[]) {{ .name = NULL }},
00193 };
00194
00195 AVFilter avfilter_asink_abuffer = {
00196 .name = "abuffersink_old",
00197 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
00198 .priv_size = sizeof(BufferSinkContext),
00199 .init = init,
00200 .uninit = uninit,
00201
00202 .inputs = (AVFilterPad[]) {{ .name = "default",
00203 .type = AVMEDIA_TYPE_AUDIO,
00204 .filter_samples = filter_samples,
00205 .min_perms = AV_PERM_READ, },
00206 { .name = NULL }},
00207 .outputs = (AVFilterPad[]) {{ .name = NULL }},
00208 };