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 AVFrame
*cur_frame
; ///< last frame 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
, AVFrame
*frame
)
53 BufferSinkContext
*s
= link
->dst
->priv
;
55 av_assert0(!s
->cur_frame
);
61 int av_buffersink_get_frame(AVFilterContext
*ctx
, AVFrame
*frame
)
63 BufferSinkContext
*s
= ctx
->priv
;
64 AVFilterLink
*link
= ctx
->inputs
[0];
67 if ((ret
= ff_request_frame(link
)) < 0)
71 return AVERROR(EINVAL
);
73 av_frame_move_ref(frame
, s
->cur_frame
);
74 av_frame_free(&s
->cur_frame
);
79 static int read_from_fifo(AVFilterContext
*ctx
, AVFrame
*frame
,
82 BufferSinkContext
*s
= ctx
->priv
;
83 AVFilterLink
*link
= ctx
->inputs
[0];
86 if (!(tmp
= ff_get_audio_buffer(link
, nb_samples
)))
87 return AVERROR(ENOMEM
);
88 av_audio_fifo_read(s
->audio_fifo
, (void**)tmp
->extended_data
, nb_samples
);
90 tmp
->pts
= s
->next_pts
;
91 s
->next_pts
+= av_rescale_q(nb_samples
, (AVRational
){1, link
->sample_rate
},
94 av_frame_move_ref(frame
, tmp
);
101 int av_buffersink_get_samples(AVFilterContext
*ctx
, AVFrame
*frame
, int nb_samples
)
103 BufferSinkContext
*s
= ctx
->priv
;
104 AVFilterLink
*link
= ctx
->inputs
[0];
107 if (!s
->audio_fifo
) {
108 int nb_channels
= av_get_channel_layout_nb_channels(link
->channel_layout
);
109 if (!(s
->audio_fifo
= av_audio_fifo_alloc(link
->format
, nb_channels
, nb_samples
)))
110 return AVERROR(ENOMEM
);
114 if (av_audio_fifo_size(s
->audio_fifo
) >= nb_samples
)
115 return read_from_fifo(ctx
, frame
, nb_samples
);
117 ret
= ff_request_frame(link
);
118 if (ret
== AVERROR_EOF
&& av_audio_fifo_size(s
->audio_fifo
))
119 return read_from_fifo(ctx
, frame
, av_audio_fifo_size(s
->audio_fifo
));
123 if (s
->cur_frame
->pts
!= AV_NOPTS_VALUE
) {
124 s
->next_pts
= s
->cur_frame
->pts
-
125 av_rescale_q(av_audio_fifo_size(s
->audio_fifo
),
126 (AVRational
){ 1, link
->sample_rate
},
130 ret
= av_audio_fifo_write(s
->audio_fifo
, (void**)s
->cur_frame
->extended_data
,
131 s
->cur_frame
->nb_samples
);
132 av_frame_free(&s
->cur_frame
);
139 #if FF_API_AVFILTERBUFFER
140 static void compat_free_buffer(AVFilterBuffer
*buf
)
142 AVFrame
*frame
= buf
->priv
;
143 av_frame_free(&frame
);
147 static int compat_read(AVFilterContext
*ctx
, AVFilterBufferRef
**pbuf
, int nb_samples
)
149 AVFilterBufferRef
*buf
;
154 return ff_poll_frame(ctx
->inputs
[0]);
156 frame
= av_frame_alloc();
158 return AVERROR(ENOMEM
);
161 ret
= av_buffersink_get_frame(ctx
, frame
);
163 ret
= av_buffersink_get_samples(ctx
, frame
, nb_samples
);
168 if (ctx
->inputs
[0]->type
== AVMEDIA_TYPE_VIDEO
) {
169 buf
= avfilter_get_video_buffer_ref_from_arrays(frame
->data
, frame
->linesize
,
171 frame
->width
, frame
->height
,
174 buf
= avfilter_get_audio_buffer_ref_from_arrays(frame
->extended_data
,
175 frame
->linesize
[0], AV_PERM_READ
,
178 frame
->channel_layout
);
181 ret
= AVERROR(ENOMEM
);
185 avfilter_copy_frame_props(buf
, frame
);
187 buf
->buf
->priv
= frame
;
188 buf
->buf
->free
= compat_free_buffer
;
194 av_frame_free(&frame
);
198 int av_buffersink_read(AVFilterContext
*ctx
, AVFilterBufferRef
**buf
)
200 return compat_read(ctx
, buf
, 0);
203 int av_buffersink_read_samples(AVFilterContext
*ctx
, AVFilterBufferRef
**buf
,
206 return compat_read(ctx
, buf
, nb_samples
);
210 static const AVFilterPad avfilter_vsink_buffer_inputs
[] = {
213 .type
= AVMEDIA_TYPE_VIDEO
,
214 .filter_frame
= filter_frame
,
220 AVFilter avfilter_vsink_buffer
= {
221 .name
= "buffersink",
222 .description
= NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
223 .priv_size
= sizeof(BufferSinkContext
),
226 .inputs
= avfilter_vsink_buffer_inputs
,
230 static const AVFilterPad avfilter_asink_abuffer_inputs
[] = {
233 .type
= AVMEDIA_TYPE_AUDIO
,
234 .filter_frame
= filter_frame
,
240 AVFilter avfilter_asink_abuffer
= {
241 .name
= "abuffersink",
242 .description
= NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
243 .priv_size
= sizeof(BufferSinkContext
),
246 .inputs
= avfilter_asink_abuffer_inputs
,