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/avassert.h"
00029 #include "libavutil/common.h"
00030 #include "libavutil/mathematics.h"
00031
00032 #include "audio.h"
00033 #include "avfilter.h"
00034 #include "buffersink.h"
00035 #include "internal.h"
00036
00037 typedef struct {
00038 AVFilterBufferRef *cur_buf;
00039 AVAudioFifo *audio_fifo;
00040 int64_t next_pts;
00041 } BufferSinkContext;
00042
00043 static av_cold void uninit(AVFilterContext *ctx)
00044 {
00045 BufferSinkContext *sink = ctx->priv;
00046
00047 if (sink->audio_fifo)
00048 av_audio_fifo_free(sink->audio_fifo);
00049 }
00050
00051 static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
00052 {
00053 BufferSinkContext *s = link->dst->priv;
00054
00055
00056 s->cur_buf = buf;
00057 link->cur_buf = NULL;
00058
00059 return 0;
00060 }
00061
00062 int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf)
00063 {
00064 BufferSinkContext *s = ctx->priv;
00065 AVFilterLink *link = ctx->inputs[0];
00066 int ret;
00067
00068 if (!buf)
00069 return ff_poll_frame(ctx->inputs[0]);
00070
00071 if ((ret = ff_request_frame(link)) < 0)
00072 return ret;
00073
00074 if (!s->cur_buf)
00075 return AVERROR(EINVAL);
00076
00077 *buf = s->cur_buf;
00078 s->cur_buf = NULL;
00079
00080 return 0;
00081 }
00082
00083 static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
00084 int nb_samples)
00085 {
00086 BufferSinkContext *s = ctx->priv;
00087 AVFilterLink *link = ctx->inputs[0];
00088 AVFilterBufferRef *buf;
00089
00090 if (!(buf = ff_get_audio_buffer(link, AV_PERM_WRITE, nb_samples)))
00091 return AVERROR(ENOMEM);
00092 av_audio_fifo_read(s->audio_fifo, (void**)buf->extended_data, nb_samples);
00093
00094 buf->pts = s->next_pts;
00095 s->next_pts += av_rescale_q(nb_samples, (AVRational){1, link->sample_rate},
00096 link->time_base);
00097
00098 *pbuf = buf;
00099 return 0;
00100
00101 }
00102
00103 int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
00104 int nb_samples)
00105 {
00106 BufferSinkContext *s = ctx->priv;
00107 AVFilterLink *link = ctx->inputs[0];
00108 int ret = 0;
00109
00110 if (!s->audio_fifo) {
00111 int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
00112 if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples)))
00113 return AVERROR(ENOMEM);
00114 }
00115
00116 while (ret >= 0) {
00117 AVFilterBufferRef *buf;
00118
00119 if (av_audio_fifo_size(s->audio_fifo) >= nb_samples)
00120 return read_from_fifo(ctx, pbuf, nb_samples);
00121
00122 ret = av_buffersink_read(ctx, &buf);
00123 if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo))
00124 return read_from_fifo(ctx, pbuf, av_audio_fifo_size(s->audio_fifo));
00125 else if (ret < 0)
00126 return ret;
00127
00128 if (buf->pts != AV_NOPTS_VALUE) {
00129 s->next_pts = buf->pts -
00130 av_rescale_q(av_audio_fifo_size(s->audio_fifo),
00131 (AVRational){ 1, link->sample_rate },
00132 link->time_base);
00133 }
00134
00135 ret = av_audio_fifo_write(s->audio_fifo, (void**)buf->extended_data,
00136 buf->audio->nb_samples);
00137 avfilter_unref_buffer(buf);
00138 }
00139
00140 return ret;
00141 }
00142
00143 AVFilter avfilter_vsink_buffer = {
00144 #if AV_HAVE_INCOMPATIBLE_FORK_ABI
00145 .name = "buffersink",
00146 #else
00147 .name = "buffersink_old",
00148 #endif
00149 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
00150 .priv_size = sizeof(BufferSinkContext),
00151 .uninit = uninit,
00152
00153 .inputs = (const AVFilterPad[]) {{ .name = "default",
00154 .type = AVMEDIA_TYPE_VIDEO,
00155 .start_frame = start_frame,
00156 .min_perms = AV_PERM_READ,
00157 .needs_fifo = 1 },
00158 { .name = NULL }},
00159 .outputs = NULL,
00160 };
00161
00162 AVFilter avfilter_asink_abuffer = {
00163 #if AV_HAVE_INCOMPATIBLE_FORK_ABI
00164 .name = "abuffersink",
00165 #else
00166 .name = "abuffersink_old",
00167 #endif
00168 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
00169 .priv_size = sizeof(BufferSinkContext),
00170 .uninit = uninit,
00171
00172 .inputs = (const AVFilterPad[]) {{ .name = "default",
00173 .type = AVMEDIA_TYPE_AUDIO,
00174 .filter_samples = start_frame,
00175 .min_perms = AV_PERM_READ,
00176 .needs_fifo = 1 },
00177 { .name = NULL }},
00178 .outputs = NULL,
00179 };