2 * Copyright (c) 2011 Stefano Sabatini
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "libavutil/audio_fifo.h"
27 #include "libavutil/avassert.h"
28 #include "libavutil/channel_layout.h"
29 #include "libavutil/common.h"
30 #include "libavutil/mathematics.h"
34 #include "buffersink.h"
38 AVFilterBufferRef
*cur_buf
; ///< last buffer delivered on the sink
39 AVAudioFifo
*audio_fifo
; ///< FIFO for audio samples
40 int64_t next_pts
; ///< interpolating audio pts
43 static av_cold
void uninit(AVFilterContext
*ctx
)
45 BufferSinkContext
*sink
= ctx
->priv
;
48 av_audio_fifo_free(sink
->audio_fifo
);
51 static int filter_frame(AVFilterLink
*link
, AVFilterBufferRef
*buf
)
53 BufferSinkContext
*s
= link
->dst
->priv
;
55 av_assert0(!s
->cur_buf
);
61 int av_buffersink_read(AVFilterContext
*ctx
, AVFilterBufferRef
**buf
)
63 BufferSinkContext
*s
= ctx
->priv
;
64 AVFilterLink
*link
= ctx
->inputs
[0];
68 return ff_poll_frame(ctx
->inputs
[0]);
70 if ((ret
= ff_request_frame(link
)) < 0)
74 return AVERROR(EINVAL
);
82 static int read_from_fifo(AVFilterContext
*ctx
, AVFilterBufferRef
**pbuf
,
85 BufferSinkContext
*s
= ctx
->priv
;
86 AVFilterLink
*link
= ctx
->inputs
[0];
87 AVFilterBufferRef
*buf
;
89 if (!(buf
= ff_get_audio_buffer(link
, AV_PERM_WRITE
, nb_samples
)))
90 return AVERROR(ENOMEM
);
91 av_audio_fifo_read(s
->audio_fifo
, (void**)buf
->extended_data
, nb_samples
);
93 buf
->pts
= s
->next_pts
;
94 s
->next_pts
+= av_rescale_q(nb_samples
, (AVRational
){1, link
->sample_rate
},
102 int av_buffersink_read_samples(AVFilterContext
*ctx
, AVFilterBufferRef
**pbuf
,
105 BufferSinkContext
*s
= ctx
->priv
;
106 AVFilterLink
*link
= ctx
->inputs
[0];
109 if (!s
->audio_fifo
) {
110 int nb_channels
= av_get_channel_layout_nb_channels(link
->channel_layout
);
111 if (!(s
->audio_fifo
= av_audio_fifo_alloc(link
->format
, nb_channels
, nb_samples
)))
112 return AVERROR(ENOMEM
);
116 AVFilterBufferRef
*buf
;
118 if (av_audio_fifo_size(s
->audio_fifo
) >= nb_samples
)
119 return read_from_fifo(ctx
, pbuf
, nb_samples
);
121 ret
= av_buffersink_read(ctx
, &buf
);
122 if (ret
== AVERROR_EOF
&& av_audio_fifo_size(s
->audio_fifo
))
123 return read_from_fifo(ctx
, pbuf
, av_audio_fifo_size(s
->audio_fifo
));
127 if (buf
->pts
!= AV_NOPTS_VALUE
) {
128 s
->next_pts
= buf
->pts
-
129 av_rescale_q(av_audio_fifo_size(s
->audio_fifo
),
130 (AVRational
){ 1, link
->sample_rate
},
134 ret
= av_audio_fifo_write(s
->audio_fifo
, (void**)buf
->extended_data
,
135 buf
->audio
->nb_samples
);
136 avfilter_unref_buffer(buf
);
142 static const AVFilterPad avfilter_vsink_buffer_inputs
[] = {
145 .type
= AVMEDIA_TYPE_VIDEO
,
146 .filter_frame
= filter_frame
,
147 .min_perms
= AV_PERM_READ
,
153 AVFilter avfilter_vsink_buffer
= {
154 .name
= "buffersink",
155 .description
= NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
156 .priv_size
= sizeof(BufferSinkContext
),
159 .inputs
= avfilter_vsink_buffer_inputs
,
163 static const AVFilterPad avfilter_asink_abuffer_inputs
[] = {
166 .type
= AVMEDIA_TYPE_AUDIO
,
167 .filter_frame
= filter_frame
,
168 .min_perms
= AV_PERM_READ
,
174 AVFilter avfilter_asink_abuffer
= {
175 .name
= "abuffersink",
176 .description
= NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
177 .priv_size
= sizeof(BufferSinkContext
),
180 .inputs
= avfilter_asink_abuffer_inputs
,