FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
af_astreamsync.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
3
*
4
* This file is part of FFmpeg.
5
*
6
* FFmpeg 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
* FFmpeg 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
14
* GNU 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 FFmpeg; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
/**
22
* @file
23
* Stream (de)synchronization filter
24
*/
25
26
#include "
libavutil/eval.h
"
27
#include "
avfilter.h
"
28
#include "
audio.h
"
29
#include "
internal.h
"
30
31
#define QUEUE_SIZE 16
32
33
static
const
char
*
const
var_names
[] = {
34
"b1"
,
"b2"
,
35
"s1"
,
"s2"
,
36
"t1"
,
"t2"
,
37
NULL
38
};
39
40
enum
var_name
{
41
VAR_B1
,
VAR_B2
,
42
VAR_S1
,
VAR_S2
,
43
VAR_T1
,
VAR_T2
,
44
VAR_NB
45
};
46
47
typedef
struct
{
48
AVExpr
*
expr
;
49
double
var_values[
VAR_NB
];
50
struct
buf_queue
{
51
AVFilterBufferRef
*buf[
QUEUE_SIZE
];
52
unsigned
tail
, nb;
53
/* buf[tail] is the oldest,
54
buf[(tail + nb) % QUEUE_SIZE] is where the next is added */
55
} queue[2];
56
int
req[2];
57
int
next_out
;
58
int
eof
;
/* bitmask, one bit for each stream */
59
}
AStreamSyncContext
;
60
61
static
const
char
*
default_expr
=
"t1-t2"
;
62
63
static
av_cold
int
init
(
AVFilterContext
*ctx,
const
char
*args0)
64
{
65
AStreamSyncContext
*as = ctx->
priv
;
66
const
char
*expr = args0 ? args0 :
default_expr
;
67
int
r
, i;
68
69
r =
av_expr_parse
(&as->
expr
, expr,
var_names
,
70
NULL
,
NULL
,
NULL
,
NULL
, 0, ctx);
71
if
(r < 0) {
72
av_log
(ctx,
AV_LOG_ERROR
,
"Error in expression \"%s\"\n"
, expr);
73
return
r
;
74
}
75
for
(i = 0; i < 42; i++)
76
av_expr_eval
(as->
expr
, as->
var_values
,
NULL
);
/* exercize prng */
77
return
0;
78
}
79
80
static
int
query_formats
(
AVFilterContext
*ctx)
81
{
82
int
i;
83
AVFilterFormats
*
formats
, *
rates
;
84
AVFilterChannelLayouts
*
layouts
;
85
86
for
(i = 0; i < 2; i++) {
87
formats = ctx->
inputs
[i]->
in_formats
;
88
ff_formats_ref
(formats, &ctx->
inputs
[i]->
out_formats
);
89
ff_formats_ref
(formats, &ctx->
outputs
[i]->
in_formats
);
90
rates =
ff_all_samplerates
();
91
ff_formats_ref
(rates, &ctx->
inputs
[i]->
out_samplerates
);
92
ff_formats_ref
(rates, &ctx->
outputs
[i]->
in_samplerates
);
93
layouts = ctx->
inputs
[i]->
in_channel_layouts
;
94
ff_channel_layouts_ref
(layouts, &ctx->
inputs
[i]->
out_channel_layouts
);
95
ff_channel_layouts_ref
(layouts, &ctx->
outputs
[i]->
in_channel_layouts
);
96
}
97
return
0;
98
}
99
100
static
int
config_output
(
AVFilterLink
*outlink)
101
{
102
AVFilterContext
*ctx = outlink->
src
;
103
int
id
= outlink == ctx->
outputs
[1];
104
105
outlink->
sample_rate
= ctx->
inputs
[
id
]->
sample_rate
;
106
outlink->
time_base
= ctx->
inputs
[
id
]->
time_base
;
107
return
0;
108
}
109
110
static
int
send_out
(
AVFilterContext
*ctx,
int
out_id)
111
{
112
AStreamSyncContext
*as = ctx->
priv
;
113
struct
buf_queue *queue = &as->
queue
[out_id];
114
AVFilterBufferRef
*buf = queue->
buf
[queue->tail];
115
int
ret;
116
117
queue->buf[queue->tail] =
NULL
;
118
as->
var_values
[
VAR_B1
+ out_id]++;
119
as->
var_values
[
VAR_S1
+ out_id] += buf->
audio
->
nb_samples
;
120
if
(buf->
pts
!=
AV_NOPTS_VALUE
)
121
as->
var_values
[
VAR_T1
+ out_id] =
122
av_q2d
(ctx->
outputs
[out_id]->
time_base
) * buf->
pts
;
123
as->
var_values
[
VAR_T1
+ out_id] += buf->
audio
->
nb_samples
/
124
(double)ctx->
inputs
[out_id]->
sample_rate
;
125
ret =
ff_filter_frame
(ctx->
outputs
[out_id], buf);
126
queue->nb--;
127
queue->tail = (queue->tail + 1) %
QUEUE_SIZE
;
128
if
(as->
req
[out_id])
129
as->
req
[out_id]--;
130
return
ret;
131
}
132
133
static
void
send_next
(
AVFilterContext
*ctx)
134
{
135
AStreamSyncContext
*as = ctx->
priv
;
136
int
i;
137
138
while
(1) {
139
if
(!as->
queue
[as->
next_out
].
nb
)
140
break
;
141
send_out
(ctx, as->
next_out
);
142
if
(!as->
eof
)
143
as->
next_out
=
av_expr_eval
(as->
expr
, as->
var_values
,
NULL
) >= 0;
144
}
145
for
(i = 0; i < 2; i++)
146
if
(as->
queue
[i].
nb
==
QUEUE_SIZE
)
147
send_out
(ctx, i);
148
}
149
150
static
int
request_frame
(
AVFilterLink
*outlink)
151
{
152
AVFilterContext
*ctx = outlink->
src
;
153
AStreamSyncContext
*as = ctx->
priv
;
154
int
id
= outlink == ctx->
outputs
[1];
155
156
as->
req
[
id
]++;
157
while
(as->
req
[
id
] && !(as->
eof
& (1 <<
id
))) {
158
if
(as->
queue
[as->
next_out
].
nb
) {
159
send_next
(ctx);
160
}
else
{
161
as->
eof
|= 1 << as->
next_out
;
162
ff_request_frame
(ctx->
inputs
[as->
next_out
]);
163
if
(as->
eof
& (1 << as->
next_out
))
164
as->
next_out
= !as->
next_out
;
165
}
166
}
167
return
0;
168
}
169
170
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*insamples)
171
{
172
AVFilterContext
*ctx = inlink->
dst
;
173
AStreamSyncContext
*as = ctx->
priv
;
174
int
id
= inlink == ctx->
inputs
[1];
175
176
as->
queue
[
id
].
buf
[(as->
queue
[
id
].
tail
+ as->
queue
[
id
].
nb
++) %
QUEUE_SIZE
] =
177
insamples;
178
as->
eof
&= ~(1 <<
id
);
179
send_next
(ctx);
180
return
0;
181
}
182
183
static
const
AVFilterPad
astreamsync_inputs
[] = {
184
{
185
.
name
=
"in1"
,
186
.type =
AVMEDIA_TYPE_AUDIO
,
187
.filter_frame =
filter_frame
,
188
.min_perms =
AV_PERM_READ
|
AV_PERM_PRESERVE
,
189
},{
190
.name =
"in2"
,
191
.type =
AVMEDIA_TYPE_AUDIO
,
192
.filter_frame =
filter_frame
,
193
.min_perms =
AV_PERM_READ
|
AV_PERM_PRESERVE
,
194
},
195
{
NULL
}
196
};
197
198
static
const
AVFilterPad
astreamsync_outputs
[] = {
199
{
200
.
name
=
"out1"
,
201
.type =
AVMEDIA_TYPE_AUDIO
,
202
.config_props =
config_output
,
203
.request_frame =
request_frame
,
204
},{
205
.name =
"out2"
,
206
.type =
AVMEDIA_TYPE_AUDIO
,
207
.config_props =
config_output
,
208
.request_frame =
request_frame
,
209
},
210
{
NULL
}
211
};
212
213
AVFilter
avfilter_af_astreamsync
= {
214
.
name
=
"astreamsync"
,
215
.description =
NULL_IF_CONFIG_SMALL
(
"Copy two streams of audio data "
216
"in a configurable order."
),
217
.priv_size =
sizeof
(
AStreamSyncContext
),
218
.
init
=
init
,
219
.
query_formats
=
query_formats
,
220
.
inputs
= astreamsync_inputs,
221
.
outputs
= astreamsync_outputs,
222
};
Generated on Sat May 25 2013 04:01:14 for FFmpeg by
1.8.2