Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavfilter
buffersink.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Stefano Sabatini
3
*
4
* This file is part of Libav.
5
*
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.
10
*
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.
15
*
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
19
*/
20
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
"
31
32
#include "
audio.h
"
33
#include "
avfilter.h
"
34
#include "
buffersink.h
"
35
#include "
internal.h
"
36
37
typedef
struct
{
38
AVFilterBufferRef
*
cur_buf
;
39
AVAudioFifo
*
audio_fifo
;
40
int64_t
next_pts
;
41
}
BufferSinkContext
;
42
43
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
44
{
45
BufferSinkContext
*sink = ctx->
priv
;
46
47
if
(sink->
audio_fifo
)
48
av_audio_fifo_free
(sink->
audio_fifo
);
49
}
50
51
static
int
filter_frame
(
AVFilterLink
*link,
AVFilterBufferRef
*buf)
52
{
53
BufferSinkContext
*s = link->
dst
->
priv
;
54
55
av_assert0
(!s->
cur_buf
);
56
s->
cur_buf
= buf;
57
58
return
0;
59
}
60
61
int
av_buffersink_read
(
AVFilterContext
*ctx,
AVFilterBufferRef
**buf)
62
{
63
BufferSinkContext
*s = ctx->
priv
;
64
AVFilterLink
*link = ctx->
inputs
[0];
65
int
ret;
66
67
if
(!buf)
68
return
ff_poll_frame
(ctx->
inputs
[0]);
69
70
if
((ret =
ff_request_frame
(link)) < 0)
71
return
ret;
72
73
if
(!s->
cur_buf
)
74
return
AVERROR
(EINVAL);
75
76
*buf = s->
cur_buf
;
77
s->
cur_buf
=
NULL
;
78
79
return
0;
80
}
81
82
static
int
read_from_fifo
(
AVFilterContext
*ctx,
AVFilterBufferRef
**pbuf,
83
int
nb_samples
)
84
{
85
BufferSinkContext
*s = ctx->
priv
;
86
AVFilterLink
*link = ctx->
inputs
[0];
87
AVFilterBufferRef
*buf;
88
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);
92
93
buf->
pts
= s->
next_pts
;
94
s->
next_pts
+=
av_rescale_q
(nb_samples, (
AVRational
){1, link->
sample_rate
},
95
link->
time_base
);
96
97
*pbuf = buf;
98
return
0;
99
100
}
101
102
int
av_buffersink_read_samples
(
AVFilterContext
*ctx,
AVFilterBufferRef
**pbuf,
103
int
nb_samples
)
104
{
105
BufferSinkContext
*s = ctx->
priv
;
106
AVFilterLink
*link = ctx->
inputs
[0];
107
int
ret = 0;
108
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);
113
}
114
115
while
(ret >= 0) {
116
AVFilterBufferRef
*buf;
117
118
if
(
av_audio_fifo_size
(s->
audio_fifo
) >= nb_samples)
119
return
read_from_fifo
(ctx, pbuf, nb_samples);
120
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
));
124
else
if
(ret < 0)
125
return
ret;
126
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
},
131
link->
time_base
);
132
}
133
134
ret =
av_audio_fifo_write
(s->
audio_fifo
, (
void
**)buf->extended_data,
135
buf->audio->
nb_samples
);
136
avfilter_unref_buffer
(buf);
137
}
138
139
return
ret;
140
}
141
142
static
const
AVFilterPad
avfilter_vsink_buffer_inputs
[] = {
143
{
144
.
name
=
"default"
,
145
.type =
AVMEDIA_TYPE_VIDEO
,
146
.filter_frame =
filter_frame
,
147
.min_perms =
AV_PERM_READ
,
148
.needs_fifo = 1
149
},
150
{
NULL
}
151
};
152
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
),
157
.
uninit
=
uninit
,
158
159
.
inputs
= avfilter_vsink_buffer_inputs,
160
.
outputs
=
NULL
,
161
};
162
163
static
const
AVFilterPad
avfilter_asink_abuffer_inputs
[] = {
164
{
165
.
name
=
"default"
,
166
.type =
AVMEDIA_TYPE_AUDIO
,
167
.filter_frame =
filter_frame
,
168
.min_perms =
AV_PERM_READ
,
169
.needs_fifo = 1
170
},
171
{
NULL
}
172
};
173
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
),
178
.
uninit
=
uninit
,
179
180
.
inputs
= avfilter_asink_abuffer_inputs,
181
.
outputs
=
NULL
,
182
};