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