FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
framesync.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2013 Nicolas George
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 License
8
* 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 License
17
* along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include "
libavutil/avassert.h
"
22
#include "
avfilter.h
"
23
#include "
bufferqueue.h
"
24
#include "
framesync.h
"
25
#include "
internal.h
"
26
27
#define OFFSET(member) offsetof(FFFrameSync, member)
28
29
static
const
char
*
framesync_name
(
void
*ptr)
30
{
31
return
"framesync"
;
32
}
33
34
static
const
AVClass
framesync_class
= {
35
.
version
=
LIBAVUTIL_VERSION_INT
,
36
.class_name =
"framesync"
,
37
.item_name =
framesync_name
,
38
.category =
AV_CLASS_CATEGORY_FILTER
,
39
.option = NULL,
40
.parent_log_context_offset =
OFFSET
(parent),
41
};
42
43
enum
{
44
STATE_BOF
,
45
STATE_RUN
,
46
STATE_EOF
,
47
};
48
49
void
ff_framesync_init
(
FFFrameSync
*fs,
void
*parent,
unsigned
nb_in)
50
{
51
fs->
class
= &
framesync_class
;
52
fs->
parent
= parent;
53
fs->
nb_in
= nb_in;
54
}
55
56
static
void
framesync_sync_level_update
(
FFFrameSync
*fs)
57
{
58
unsigned
i,
level
= 0;
59
60
for
(i = 0; i < fs->
nb_in
; i++)
61
if
(fs->
in
[i].
state
!=
STATE_EOF
)
62
level =
FFMAX
(level, fs->
in
[i].
sync
);
63
av_assert0
(level <= fs->sync_level);
64
if
(level < fs->sync_level)
65
av_log
(fs,
AV_LOG_VERBOSE
,
"Sync level %u\n"
, level);
66
if
(level)
67
fs->
sync_level
=
level
;
68
else
69
fs->
eof
= 1;
70
}
71
72
int
ff_framesync_configure
(
FFFrameSync
*fs)
73
{
74
unsigned
i;
75
int64_t gcd, lcm;
76
77
if
(!fs->
time_base
.
num
) {
78
for
(i = 0; i < fs->
nb_in
; i++) {
79
if
(fs->
in
[i].
sync
) {
80
if
(fs->
time_base
.
num
) {
81
gcd =
av_gcd
(fs->
time_base
.
den
, fs->
in
[i].
time_base
.
den
);
82
lcm = (fs->
time_base
.
den
/ gcd) * fs->
in
[i].
time_base
.
den
;
83
if
(lcm <
AV_TIME_BASE
/ 2) {
84
fs->
time_base
.
den
= lcm;
85
fs->
time_base
.
num
=
av_gcd
(fs->
time_base
.
num
,
86
fs->
in
[i].
time_base
.
num
);
87
}
else
{
88
fs->
time_base
.
num
= 1;
89
fs->
time_base
.
den
=
AV_TIME_BASE
;
90
break
;
91
}
92
}
else
{
93
fs->
time_base
= fs->
in
[i].
time_base
;
94
}
95
}
96
}
97
if
(!fs->
time_base
.
num
) {
98
av_log
(fs,
AV_LOG_ERROR
,
"Impossible to set time base\n"
);
99
return
AVERROR
(EINVAL);
100
}
101
av_log
(fs,
AV_LOG_VERBOSE
,
"Selected %d/%d time base\n"
,
102
fs->
time_base
.
num
, fs->
time_base
.
den
);
103
}
104
105
for
(i = 0; i < fs->
nb_in
; i++)
106
fs->
in
[i].
pts
= fs->
in
[i].
pts_next
=
AV_NOPTS_VALUE
;
107
fs->
sync_level
= UINT_MAX;
108
framesync_sync_level_update
(fs);
109
110
return
0;
111
}
112
113
static
void
framesync_advance
(
FFFrameSync
*fs)
114
{
115
int
latest;
116
unsigned
i;
117
int64_t pts;
118
119
if
(fs->
eof
)
120
return
;
121
while
(!fs->
frame_ready
) {
122
latest = -1;
123
for
(i = 0; i < fs->
nb_in
; i++) {
124
if
(!fs->
in
[i].
have_next
) {
125
if
(latest < 0 || fs->
in
[i].pts < fs->
in
[latest].pts)
126
latest = i;
127
}
128
}
129
if
(latest >= 0) {
130
fs->
in_request
= latest;
131
break
;
132
}
133
134
pts = fs->
in
[0].
pts_next
;
135
for
(i = 1; i < fs->
nb_in
; i++)
136
if
(fs->
in
[i].
pts_next
< pts)
137
pts = fs->
in
[i].
pts_next
;
138
if
(pts == INT64_MAX) {
139
fs->
eof
= 1;
140
break
;
141
}
142
for
(i = 0; i < fs->
nb_in
; i++) {
143
if
(fs->
in
[i].
pts_next
== pts ||
144
(fs->
in
[i].
before
==
EXT_INFINITY
&&
145
fs->
in
[i].
state
==
STATE_BOF
)) {
146
av_frame_free
(&fs->
in
[i].
frame
);
147
fs->
in
[i].
frame
= fs->
in
[i].
frame_next
;
148
fs->
in
[i].
pts
= fs->
in
[i].
pts_next
;
149
fs->
in
[i].
frame_next
= NULL;
150
fs->
in
[i].
pts_next
=
AV_NOPTS_VALUE
;
151
fs->
in
[i].
have_next
= 0;
152
fs->
in
[i].
state
= fs->
in
[i].
frame
?
STATE_RUN
:
STATE_EOF
;
153
if
(fs->
in
[i].
sync
== fs->
sync_level
&& fs->
in
[i].
frame
)
154
fs->
frame_ready
= 1;
155
if
(fs->
in
[i].
state
==
STATE_EOF
&&
156
fs->
in
[i].
after
==
EXT_STOP
)
157
fs->
eof
= 1;
158
}
159
}
160
if
(fs->
eof
)
161
fs->
frame_ready
= 0;
162
if
(fs->
frame_ready
)
163
for
(i = 0; i < fs->
nb_in
; i++)
164
if
((fs->
in
[i].
state
==
STATE_BOF
&&
165
fs->
in
[i].
before
==
EXT_STOP
))
166
fs->
frame_ready
= 0;
167
fs->
pts
= pts;
168
}
169
}
170
171
static
int64_t
framesync_pts_extrapolate
(
FFFrameSync
*fs,
unsigned
in
,
172
int64_t pts)
173
{
174
/* Possible enhancement: use the link's frame rate */
175
return
pts + 1;
176
}
177
178
static
void
framesync_inject_frame
(
FFFrameSync
*fs,
unsigned
in
,
AVFrame
*
frame
)
179
{
180
int64_t pts;
181
182
av_assert0
(!fs->
in
[in].
have_next
);
183
if
(frame) {
184
pts =
av_rescale_q
(frame->
pts
, fs->
in
[in].
time_base
, fs->
time_base
);
185
frame->
pts
= pts;
186
}
else
{
187
pts = fs->
in
[
in
].
state
!=
STATE_RUN
|| fs->
in
[
in
].
after
==
EXT_INFINITY
188
? INT64_MAX :
framesync_pts_extrapolate
(fs, in, fs->
in
[in].
pts
);
189
fs->
in
[
in
].
sync
= 0;
190
framesync_sync_level_update
(fs);
191
}
192
fs->
in
[
in
].
frame_next
=
frame
;
193
fs->
in
[
in
].
pts_next
= pts;
194
fs->
in
[
in
].
have_next
= 1;
195
}
196
197
int
ff_framesync_add_frame
(
FFFrameSync
*fs,
unsigned
in
,
AVFrame
*
frame
)
198
{
199
av_assert1
(in < fs->nb_in);
200
if
(!fs->
in
[in].
have_next
)
201
framesync_inject_frame
(fs, in, frame);
202
else
203
ff_bufqueue_add
(fs, &fs->
in
[in].
queue
, frame);
204
return
0;
205
}
206
207
void
ff_framesync_next
(
FFFrameSync
*fs)
208
{
209
unsigned
i;
210
211
av_assert0
(!fs->
frame_ready
);
212
for
(i = 0; i < fs->
nb_in
; i++)
213
if
(!fs->
in
[i].
have_next
&& fs->
in
[i].
queue
.
available
)
214
framesync_inject_frame
(fs, i,
ff_bufqueue_get
(&fs->
in
[i].
queue
));
215
fs->
frame_ready
= 0;
216
framesync_advance
(fs);
217
}
218
219
void
ff_framesync_drop
(
FFFrameSync
*fs)
220
{
221
fs->
frame_ready
= 0;
222
}
223
224
int
ff_framesync_get_frame
(
FFFrameSync
*fs,
unsigned
in
,
AVFrame
**rframe,
225
unsigned
get
)
226
{
227
AVFrame
*
frame
;
228
unsigned
need_copy = 0, i;
229
int64_t pts_next;
230
int
ret
;
231
232
if
(!fs->
in
[in].
frame
) {
233
*rframe = NULL;
234
return
0;
235
}
236
frame = fs->
in
[
in
].
frame
;
237
if
(
get
) {
238
/* Find out if we need to copy the frame: is there another sync
239
stream, and do we know if its current frame will outlast this one? */
240
pts_next = fs->
in
[
in
].
have_next
? fs->
in
[
in
].
pts_next
: INT64_MAX;
241
for
(i = 0; i < fs->
nb_in
&& !need_copy; i++)
242
if
(i != in && fs->
in
[i].
sync
&&
243
(!fs->
in
[i].
have_next
|| fs->
in
[i].
pts_next
< pts_next))
244
need_copy = 1;
245
if
(need_copy) {
246
if
(!(frame =
av_frame_clone
(frame)))
247
return
AVERROR
(ENOMEM);
248
if
((ret =
av_frame_make_writable
(frame)) < 0) {
249
av_frame_free
(&frame);
250
return
ret
;
251
}
252
}
else
{
253
fs->
in
[
in
].
frame
= NULL;
254
}
255
fs->
frame_ready
= 0;
256
}
257
*rframe =
frame
;
258
return
0;
259
}
260
261
void
ff_framesync_uninit
(
FFFrameSync
*fs)
262
{
263
unsigned
i;
264
265
for
(i = 0; i < fs->
nb_in
; i++) {
266
av_frame_free
(&fs->
in
[i].
frame
);
267
av_frame_free
(&fs->
in
[i].
frame_next
);
268
ff_bufqueue_discard_all
(&fs->
in
[i].
queue
);
269
}
270
}
271
272
int
ff_framesync_process_frame
(
FFFrameSync
*fs,
unsigned
all)
273
{
274
int
ret
,
count
= 0;
275
276
av_assert0
(fs->
on_event
);
277
while
(1) {
278
ff_framesync_next
(fs);
279
if
(fs->
eof
|| !fs->
frame_ready
)
280
break
;
281
if
((ret = fs->
on_event
(fs)) < 0)
282
return
ret
;
283
ff_framesync_drop
(fs);
284
count++;
285
if
(!all)
286
break
;
287
}
288
if
(!count && fs->
eof
)
289
return
AVERROR_EOF
;
290
return
count
;
291
}
292
293
int
ff_framesync_filter_frame
(
FFFrameSync
*fs,
AVFilterLink
*inlink,
294
AVFrame
*
in
)
295
{
296
int
ret
;
297
298
if
((ret =
ff_framesync_process_frame
(fs, 1)) < 0)
299
return
ret
;
300
if
((ret =
ff_framesync_add_frame
(fs,
FF_INLINK_IDX
(inlink), in)) < 0)
301
return
ret
;
302
if
((ret =
ff_framesync_process_frame
(fs, 0)) < 0)
303
return
ret
;
304
return
0;
305
}
306
307
int
ff_framesync_request_frame
(
FFFrameSync
*fs,
AVFilterLink
*outlink)
308
{
309
AVFilterContext
*ctx = outlink->
src
;
310
int
input,
ret
;
311
312
if
((ret =
ff_framesync_process_frame
(fs, 0)) < 0)
313
return
ret
;
314
if
(ret > 0)
315
return
0;
316
if
(fs->
eof
)
317
return
AVERROR_EOF
;
318
outlink->
flags
|=
FF_LINK_FLAG_REQUEST_LOOP
;
319
input = fs->
in_request
;
320
ret =
ff_request_frame
(ctx->
inputs
[input]);
321
if
(ret ==
AVERROR_EOF
) {
322
if
((ret =
ff_framesync_add_frame
(fs, input, NULL)) < 0)
323
return
ret
;
324
if
((ret =
ff_framesync_process_frame
(fs, 0)) < 0)
325
return
ret
;
326
ret = 0;
327
}
328
return
ret
;
329
}
Generated on Sat Jan 25 2014 19:52:00 for FFmpeg by
1.8.2