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 Sun Mar 23 2014 23:50:08 for FFmpeg by
1.8.2