Line | Branch | Exec | Source |
---|---|---|---|
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 "libavutil/mem.h" | ||
23 | #include "libavutil/opt.h" | ||
24 | #include "avfilter.h" | ||
25 | #include "filters.h" | ||
26 | #include "framesync.h" | ||
27 | |||
28 | #define OFFSET(member) offsetof(FFFrameSync, member) | ||
29 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | ||
30 | |||
31 | ✗ | static const char *framesync_name(void *ptr) | |
32 | { | ||
33 | ✗ | return "framesync"; | |
34 | } | ||
35 | |||
36 | static const AVOption framesync_options[] = { | ||
37 | { "eof_action", "Action to take when encountering EOF from secondary input ", | ||
38 | OFFSET(opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT }, | ||
39 | EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, .unit = "eof_action" }, | ||
40 | { "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, .unit = "eof_action" }, | ||
41 | { "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, .unit = "eof_action" }, | ||
42 | { "pass", "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS }, .flags = FLAGS, .unit = "eof_action" }, | ||
43 | { "shortest", "force termination when the shortest input terminates", OFFSET(opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, | ||
44 | { "repeatlast", "extend last frame of secondary streams beyond EOF", OFFSET(opt_repeatlast), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, | ||
45 | { "ts_sync_mode", "How strictly to sync streams based on secondary input timestamps", | ||
46 | OFFSET(opt_ts_sync_mode), AV_OPT_TYPE_INT, { .i64 = TS_DEFAULT }, | ||
47 | TS_DEFAULT, TS_NEAREST, .flags = FLAGS, .unit = "ts_sync_mode" }, | ||
48 | { "default", "Frame from secondary input with the nearest lower or equal timestamp to the primary input frame", | ||
49 | 0, AV_OPT_TYPE_CONST, { .i64 = TS_DEFAULT }, .flags = FLAGS, .unit = "ts_sync_mode" }, | ||
50 | { "nearest", "Frame from secondary input with the absolute nearest timestamp to the primary input frame", | ||
51 | 0, AV_OPT_TYPE_CONST, { .i64 = TS_NEAREST }, .flags = FLAGS, .unit = "ts_sync_mode" }, | ||
52 | { NULL } | ||
53 | }; | ||
54 | const AVClass ff_framesync_class = { | ||
55 | .version = LIBAVUTIL_VERSION_INT, | ||
56 | .class_name = "framesync", | ||
57 | .item_name = framesync_name, | ||
58 | .category = AV_CLASS_CATEGORY_FILTER, | ||
59 | .option = framesync_options, | ||
60 | .parent_log_context_offset = OFFSET(parent), | ||
61 | }; | ||
62 | |||
63 | ✗ | const AVClass *ff_framesync_child_class_iterate(void **iter) | |
64 | { | ||
65 | ✗ | const AVClass *c = *iter ? NULL : &ff_framesync_class; | |
66 | ✗ | *iter = (void *)(uintptr_t)c; | |
67 | ✗ | return c; | |
68 | } | ||
69 | |||
70 | enum { | ||
71 | STATE_BOF, | ||
72 | STATE_RUN, | ||
73 | STATE_EOF, | ||
74 | }; | ||
75 | |||
76 | static int consume_from_fifos(FFFrameSync *fs); | ||
77 | |||
78 | 15854 | void ff_framesync_preinit(FFFrameSync *fs) | |
79 | { | ||
80 |
2/2✓ Branch 0 taken 5868 times.
✓ Branch 1 taken 9986 times.
|
15854 | if (fs->class) |
81 | 5868 | return; | |
82 | 9986 | fs->class = &ff_framesync_class; | |
83 | 9986 | av_opt_set_defaults(fs); | |
84 | } | ||
85 | |||
86 | 5876 | int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in) | |
87 | { | ||
88 | /* For filters with several outputs, we will not be able to assume which | ||
89 | output is relevant for ff_outlink_frame_wanted() and | ||
90 | ff_outlink_set_status(). To be designed when needed. */ | ||
91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5876 times.
|
5876 | av_assert0(parent->nb_outputs == 1); |
92 | |||
93 | 5876 | ff_framesync_preinit(fs); | |
94 | 5876 | fs->parent = parent; | |
95 | 5876 | fs->nb_in = nb_in; | |
96 | |||
97 | 5876 | fs->in = av_calloc(nb_in, sizeof(*fs->in)); | |
98 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5876 times.
|
5876 | if (!fs->in) { |
99 | ✗ | fs->nb_in = 0; | |
100 | ✗ | return AVERROR(ENOMEM); | |
101 | } | ||
102 | |||
103 | 5876 | return 0; | |
104 | } | ||
105 | |||
106 | 2290 | static void framesync_eof(FFFrameSync *fs, int64_t pts) | |
107 | { | ||
108 | 2290 | fs->eof = 1; | |
109 | 2290 | fs->frame_ready = 0; | |
110 | 2290 | ff_outlink_set_status(fs->parent->outputs[0], AVERROR_EOF, pts); | |
111 | 2290 | } | |
112 | |||
113 | 7052 | static void framesync_sync_level_update(FFFrameSync *fs, int64_t eof_pts) | |
114 | { | ||
115 | 7052 | unsigned i, level = 0; | |
116 | |||
117 |
2/2✓ Branch 0 taken 7158 times.
✓ Branch 1 taken 7052 times.
|
14210 | for (i = 0; i < fs->nb_in; i++) |
118 |
1/2✓ Branch 0 taken 7158 times.
✗ Branch 1 not taken.
|
7158 | if (fs->in[i].state != STATE_EOF) |
119 | 7158 | level = FFMAX(level, fs->in[i].sync); | |
120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7052 times.
|
7052 | av_assert0(level <= fs->sync_level); |
121 |
2/2✓ Branch 0 taken 7038 times.
✓ Branch 1 taken 14 times.
|
7052 | if (level < fs->sync_level) |
122 | 7038 | av_log(fs, AV_LOG_VERBOSE, "Sync level %u\n", level); | |
123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7052 times.
|
7052 | if (fs->opt_ts_sync_mode > TS_DEFAULT) { |
124 | ✗ | for (i = 0; i < fs->nb_in; i++) { | |
125 | ✗ | if (fs->in[i].sync < level) | |
126 | ✗ | fs->in[i].ts_mode = fs->opt_ts_sync_mode; | |
127 | else | ||
128 | ✗ | fs->in[i].ts_mode = TS_DEFAULT; | |
129 | } | ||
130 | } | ||
131 |
2/2✓ Branch 0 taken 5907 times.
✓ Branch 1 taken 1145 times.
|
7052 | if (level) |
132 | 5907 | fs->sync_level = level; | |
133 | else | ||
134 | 1145 | framesync_eof(fs, eof_pts); | |
135 | 7052 | } | |
136 | |||
137 | 5876 | int ff_framesync_configure(FFFrameSync *fs) | |
138 | { | ||
139 | unsigned i; | ||
140 | |||
141 |
2/4✓ Branch 0 taken 5876 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5876 times.
|
5876 | if (!fs->opt_repeatlast || fs->opt_eof_action == EOF_ACTION_PASS) { |
142 | ✗ | fs->opt_repeatlast = 0; | |
143 | ✗ | fs->opt_eof_action = EOF_ACTION_PASS; | |
144 | } | ||
145 |
2/4✓ Branch 0 taken 5876 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5876 times.
|
5876 | if (fs->opt_shortest || fs->opt_eof_action == EOF_ACTION_ENDALL) { |
146 | ✗ | fs->opt_shortest = 1; | |
147 | ✗ | fs->opt_eof_action = EOF_ACTION_ENDALL; | |
148 | } | ||
149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5876 times.
|
5876 | if (!fs->opt_repeatlast) { |
150 | ✗ | for (i = 1; i < fs->nb_in; i++) { | |
151 | ✗ | fs->in[i].after = EXT_NULL; | |
152 | ✗ | fs->in[i].sync = 0; | |
153 | } | ||
154 | } | ||
155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5876 times.
|
5876 | if (fs->opt_shortest) { |
156 | ✗ | for (i = 0; i < fs->nb_in; i++) | |
157 | ✗ | fs->in[i].after = EXT_STOP; | |
158 | } | ||
159 | |||
160 |
2/2✓ Branch 0 taken 5825 times.
✓ Branch 1 taken 51 times.
|
5876 | if (!fs->time_base.num) { |
161 |
2/2✓ Branch 0 taken 5870 times.
✓ Branch 1 taken 5825 times.
|
11695 | for (i = 0; i < fs->nb_in; i++) { |
162 |
2/2✓ Branch 0 taken 5869 times.
✓ Branch 1 taken 1 times.
|
5870 | if (fs->in[i].sync) { |
163 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 5825 times.
|
5869 | if (fs->time_base.num) { |
164 | 44 | fs->time_base = av_gcd_q(fs->time_base, fs->in[i].time_base, | |
165 | 44 | AV_TIME_BASE / 2, AV_TIME_BASE_Q); | |
166 | } else { | ||
167 | 5825 | fs->time_base = fs->in[i].time_base; | |
168 | } | ||
169 | } | ||
170 | } | ||
171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5825 times.
|
5825 | if (!fs->time_base.num) { |
172 | ✗ | av_log(fs, AV_LOG_ERROR, "Impossible to set time base\n"); | |
173 | ✗ | return AVERROR(EINVAL); | |
174 | } | ||
175 | 5825 | av_log(fs, AV_LOG_VERBOSE, "Selected %d/%d time base\n", | |
176 | fs->time_base.num, fs->time_base.den); | ||
177 | } | ||
178 | |||
179 |
2/2✓ Branch 0 taken 5921 times.
✓ Branch 1 taken 5876 times.
|
11797 | for (i = 0; i < fs->nb_in; i++) |
180 | 5921 | fs->in[i].pts = fs->in[i].pts_next = AV_NOPTS_VALUE; | |
181 | 5876 | fs->sync_level = UINT_MAX; | |
182 | 5876 | framesync_sync_level_update(fs, AV_NOPTS_VALUE); | |
183 | |||
184 | 5876 | return 0; | |
185 | } | ||
186 | |||
187 | 179464 | static int framesync_advance(FFFrameSync *fs) | |
188 | { | ||
189 | unsigned i; | ||
190 | int64_t pts; | ||
191 | int ret; | ||
192 | |||
193 |
4/4✓ Branch 0 taken 180661 times.
✓ Branch 1 taken 90406 times.
✓ Branch 2 taken 179552 times.
✓ Branch 3 taken 1109 times.
|
271067 | while (!(fs->frame_ready || fs->eof)) { |
194 | 179552 | ret = consume_from_fifos(fs); | |
195 |
2/2✓ Branch 0 taken 87913 times.
✓ Branch 1 taken 91639 times.
|
179552 | if (ret <= 0) |
196 | 87913 | return ret; | |
197 | |||
198 | 91639 | pts = INT64_MAX; | |
199 |
2/2✓ Branch 0 taken 93154 times.
✓ Branch 1 taken 91639 times.
|
184793 | for (i = 0; i < fs->nb_in; i++) |
200 |
3/4✓ Branch 0 taken 93154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91691 times.
✓ Branch 3 taken 1463 times.
|
93154 | if (fs->in[i].have_next && fs->in[i].pts_next < pts) |
201 | 91691 | pts = fs->in[i].pts_next; | |
202 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 91603 times.
|
91639 | if (pts == INT64_MAX) { |
203 | 36 | framesync_eof(fs, AV_NOPTS_VALUE); | |
204 | 36 | break; | |
205 | } | ||
206 |
2/2✓ Branch 0 taken 93088 times.
✓ Branch 1 taken 91603 times.
|
184691 | for (i = 0; i < fs->nb_in; i++) { |
207 |
2/2✓ Branch 0 taken 721 times.
✓ Branch 1 taken 92367 times.
|
93088 | if (fs->in[i].pts_next == pts || |
208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 721 times.
|
721 | (fs->in[i].ts_mode == TS_NEAREST && |
209 | ✗ | fs->in[i].have_next && | |
210 | ✗ | fs->in[i].pts_next != INT64_MAX && fs->in[i].pts != AV_NOPTS_VALUE && | |
211 | ✗ | fs->in[i].pts_next - pts < pts - fs->in[i].pts) || | |
212 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 441 times.
|
721 | (fs->in[i].before == EXT_INFINITY && |
213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | fs->in[i].state == STATE_BOF)) { |
214 | 92367 | av_frame_free(&fs->in[i].frame); | |
215 | 92367 | fs->in[i].frame = fs->in[i].frame_next; | |
216 | 92367 | fs->in[i].pts = fs->in[i].pts_next; | |
217 | 92367 | fs->in[i].frame_next = NULL; | |
218 | 92367 | fs->in[i].pts_next = AV_NOPTS_VALUE; | |
219 | 92367 | fs->in[i].have_next = 0; | |
220 |
2/2✓ Branch 0 taken 91258 times.
✓ Branch 1 taken 1109 times.
|
92367 | fs->in[i].state = fs->in[i].frame ? STATE_RUN : STATE_EOF; |
221 |
3/4✓ Branch 0 taken 90556 times.
✓ Branch 1 taken 1811 times.
✓ Branch 2 taken 90556 times.
✗ Branch 3 not taken.
|
92367 | if (fs->in[i].sync == fs->sync_level && fs->in[i].frame) |
222 | 90556 | fs->frame_ready = 1; | |
223 |
2/2✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 91258 times.
|
92367 | if (fs->in[i].state == STATE_EOF && |
224 |
1/2✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
|
1109 | fs->in[i].after == EXT_STOP) |
225 | 1109 | framesync_eof(fs, AV_NOPTS_VALUE); | |
226 | } | ||
227 | } | ||
228 |
2/2✓ Branch 0 taken 90406 times.
✓ Branch 1 taken 1197 times.
|
91603 | if (fs->frame_ready) |
229 |
2/2✓ Branch 0 taken 91803 times.
✓ Branch 1 taken 90406 times.
|
182209 | for (i = 0; i < fs->nb_in; i++) |
230 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 91800 times.
|
91803 | if ((fs->in[i].state == STATE_BOF && |
231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | fs->in[i].before == EXT_STOP)) |
232 | ✗ | fs->frame_ready = 0; | |
233 | 91603 | fs->pts = pts; | |
234 | } | ||
235 | 91551 | return 0; | |
236 | } | ||
237 | |||
238 | 1109 | static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in, | |
239 | int64_t pts) | ||
240 | { | ||
241 | /* Possible enhancement: use the link's frame rate */ | ||
242 | 1109 | return pts + 1; | |
243 | } | ||
244 | |||
245 | 91258 | static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame) | |
246 | { | ||
247 | int64_t pts; | ||
248 | |||
249 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91258 times.
|
91258 | av_assert0(!fs->in[in].have_next); |
250 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91258 times.
|
91258 | av_assert0(frame); |
251 | 91258 | pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base); | |
252 | 91258 | frame->pts = pts; | |
253 | 91258 | fs->in[in].frame_next = frame; | |
254 | 91258 | fs->in[in].pts_next = pts; | |
255 | 91258 | fs->in[in].have_next = 1; | |
256 | 91258 | } | |
257 | |||
258 | 1176 | static void framesync_inject_status(FFFrameSync *fs, unsigned in, int status, int64_t eof_pts) | |
259 | { | ||
260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1176 times.
|
1176 | av_assert0(!fs->in[in].have_next); |
261 | 1176 | fs->in[in].sync = 0; | |
262 |
1/2✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
|
1176 | framesync_sync_level_update(fs, status == AVERROR_EOF ? eof_pts : AV_NOPTS_VALUE); |
263 | 1176 | fs->in[in].frame_next = NULL; | |
264 |
2/2✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 61 times.
|
1170 | fs->in[in].pts_next = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY |
265 |
2/2✓ Branch 0 taken 1170 times.
✓ Branch 1 taken 6 times.
|
2346 | ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts); |
266 | 1176 | fs->in[in].have_next = 1; | |
267 | 1176 | } | |
268 | |||
269 | 91803 | int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, | |
270 | unsigned get) | ||
271 | { | ||
272 | AVFrame *frame; | ||
273 | 91803 | unsigned need_copy = 0, i; | |
274 | int64_t pts_next; | ||
275 | |||
276 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 91800 times.
|
91803 | if (!fs->in[in].frame) { |
277 | 3 | *rframe = NULL; | |
278 | 3 | return 0; | |
279 | } | ||
280 | 91800 | frame = fs->in[in].frame; | |
281 |
2/2✓ Branch 0 taken 90206 times.
✓ Branch 1 taken 1594 times.
|
91800 | if (get) { |
282 | /* Find out if we need to copy the frame: is there another sync | ||
283 | stream, and do we know if its current frame will outlast this one? */ | ||
284 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 90118 times.
|
90206 | pts_next = fs->in[in].have_next ? fs->in[in].pts_next : INT64_MAX; |
285 |
3/4✓ Branch 0 taken 91453 times.
✓ Branch 1 taken 90206 times.
✓ Branch 2 taken 91453 times.
✗ Branch 3 not taken.
|
181659 | for (i = 0; i < fs->nb_in && !need_copy; i++) |
286 |
4/4✓ Branch 0 taken 1247 times.
✓ Branch 1 taken 90206 times.
✓ Branch 2 taken 953 times.
✓ Branch 3 taken 294 times.
|
91453 | if (i != in && fs->in[i].sync && |
287 |
3/4✓ Branch 0 taken 256 times.
✓ Branch 1 taken 697 times.
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
|
953 | (!fs->in[i].have_next || fs->in[i].pts_next < pts_next)) |
288 | 953 | need_copy = 1; | |
289 |
2/2✓ Branch 0 taken 953 times.
✓ Branch 1 taken 89253 times.
|
90206 | if (need_copy) { |
290 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 953 times.
|
953 | if (!(frame = av_frame_clone(frame))) |
291 | ✗ | return AVERROR(ENOMEM); | |
292 | } else { | ||
293 | 89253 | fs->in[in].frame = NULL; | |
294 | } | ||
295 | 90206 | fs->frame_ready = 0; | |
296 | } | ||
297 | 91800 | *rframe = frame; | |
298 | 91800 | return 0; | |
299 | } | ||
300 | |||
301 | 15827 | void ff_framesync_uninit(FFFrameSync *fs) | |
302 | { | ||
303 | unsigned i; | ||
304 | |||
305 |
2/2✓ Branch 0 taken 5921 times.
✓ Branch 1 taken 15827 times.
|
21748 | for (i = 0; i < fs->nb_in; i++) { |
306 | 5921 | av_frame_free(&fs->in[i].frame); | |
307 | 5921 | av_frame_free(&fs->in[i].frame_next); | |
308 | } | ||
309 | |||
310 | 15827 | av_freep(&fs->in); | |
311 | 15827 | } | |
312 | |||
313 | 179552 | static int consume_from_fifos(FFFrameSync *fs) | |
314 | { | ||
315 | 179552 | AVFilterContext *ctx = fs->parent; | |
316 | 179552 | AVFrame *frame = NULL; | |
317 | int64_t pts; | ||
318 | unsigned i, nb_active, nb_miss; | ||
319 | int ret, status; | ||
320 | |||
321 | 179552 | nb_active = nb_miss = 0; | |
322 |
2/2✓ Branch 0 taken 183234 times.
✓ Branch 1 taken 179552 times.
|
362786 | for (i = 0; i < fs->nb_in; i++) { |
323 |
3/4✓ Branch 0 taken 181039 times.
✓ Branch 1 taken 2195 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 181039 times.
|
183234 | if (fs->in[i].have_next || fs->in[i].state == STATE_EOF) |
324 | 2195 | continue; | |
325 | 181039 | nb_active++; | |
326 | 181039 | ret = ff_inlink_consume_frame(ctx->inputs[i], &frame); | |
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 181039 times.
|
181039 | if (ret < 0) |
328 | ✗ | return ret; | |
329 |
2/2✓ Branch 0 taken 91258 times.
✓ Branch 1 taken 89781 times.
|
181039 | if (ret) { |
330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 91258 times.
|
91258 | av_assert0(frame); |
331 | 91258 | framesync_inject_frame(fs, i, frame); | |
332 | } else { | ||
333 | 89781 | ret = ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts); | |
334 |
2/2✓ Branch 0 taken 1176 times.
✓ Branch 1 taken 88605 times.
|
89781 | if (ret > 0) { |
335 | 1176 | framesync_inject_status(fs, i, status, pts); | |
336 |
1/2✓ Branch 0 taken 88605 times.
✗ Branch 1 not taken.
|
88605 | } else if (!ret) { |
337 | 88605 | nb_miss++; | |
338 | } | ||
339 | } | ||
340 | } | ||
341 |
2/2✓ Branch 0 taken 87913 times.
✓ Branch 1 taken 91639 times.
|
179552 | if (nb_miss) { |
342 |
4/4✓ Branch 0 taken 87292 times.
✓ Branch 1 taken 621 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 87288 times.
|
87913 | if (nb_miss == nb_active && !ff_outlink_frame_wanted(ctx->outputs[0])) |
343 | 4 | return FFERROR_NOT_READY; | |
344 |
2/2✓ Branch 0 taken 90072 times.
✓ Branch 1 taken 87909 times.
|
177981 | for (i = 0; i < fs->nb_in; i++) |
345 |
3/4✓ Branch 0 taken 88601 times.
✓ Branch 1 taken 1471 times.
✓ Branch 2 taken 88601 times.
✗ Branch 3 not taken.
|
90072 | if (!fs->in[i].have_next && fs->in[i].state != STATE_EOF) |
346 | 88601 | ff_inlink_request_frame(ctx->inputs[i]); | |
347 | 87909 | return 0; | |
348 | } | ||
349 | 91639 | return 1; | |
350 | } | ||
351 | |||
352 | 180598 | int ff_framesync_activate(FFFrameSync *fs) | |
353 | { | ||
354 | 180598 | AVFilterContext *ctx = fs->parent; | |
355 | int ret; | ||
356 | |||
357 |
4/4✓ Branch 1 taken 1134 times.
✓ Branch 2 taken 179464 times.
✓ Branch 4 taken 1139 times.
✓ Branch 5 taken 1134 times.
|
181737 | FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); |
358 | |||
359 | 179464 | ret = framesync_advance(fs); | |
360 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 179460 times.
|
179464 | if (ret < 0) |
361 | 4 | return ret; | |
362 |
4/4✓ Branch 0 taken 178315 times.
✓ Branch 1 taken 1145 times.
✓ Branch 2 taken 87909 times.
✓ Branch 3 taken 90406 times.
|
179460 | if (fs->eof || !fs->frame_ready) |
363 | 89054 | return 0; | |
364 | 90406 | ret = fs->on_event(fs); | |
365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90406 times.
|
90406 | if (ret < 0) |
366 | ✗ | return ret; | |
367 | 90406 | fs->frame_ready = 0; | |
368 | |||
369 | 90406 | return 0; | |
370 | } | ||
371 | |||
372 | 41 | int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent) | |
373 | { | ||
374 | int ret; | ||
375 | |||
376 | 41 | ret = ff_framesync_init(fs, parent, 2); | |
377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (ret < 0) |
378 | ✗ | return ret; | |
379 | 41 | fs->in[0].time_base = parent->inputs[0]->time_base; | |
380 | 41 | fs->in[1].time_base = parent->inputs[1]->time_base; | |
381 | 41 | fs->in[0].sync = 2; | |
382 | 41 | fs->in[0].before = EXT_STOP; | |
383 | 41 | fs->in[0].after = EXT_INFINITY; | |
384 | 41 | fs->in[1].sync = 1; | |
385 | 41 | fs->in[1].before = EXT_NULL; | |
386 | 41 | fs->in[1].after = EXT_INFINITY; | |
387 | 41 | return 0; | |
388 | } | ||
389 | |||
390 | 1242 | int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1) | |
391 | { | ||
392 | 1242 | AVFilterContext *ctx = fs->parent; | |
393 | 1242 | AVFrame *mainpic = NULL, *secondpic = NULL; | |
394 | int ret; | ||
395 | |||
396 |
2/4✓ Branch 1 taken 1242 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1242 times.
|
2484 | if ((ret = ff_framesync_get_frame(fs, 0, &mainpic, 1)) < 0 || |
397 | 1242 | (ret = ff_framesync_get_frame(fs, 1, &secondpic, 0)) < 0) { | |
398 | ✗ | av_frame_free(&mainpic); | |
399 | ✗ | return ret; | |
400 | } | ||
401 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1242 times.
|
1242 | av_assert0(mainpic); |
402 | 1242 | mainpic->pts = av_rescale_q(fs->pts, fs->time_base, ctx->outputs[0]->time_base); | |
403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1242 times.
|
1242 | if (ctx->is_disabled) |
404 | ✗ | secondpic = NULL; | |
405 | 1242 | *f0 = mainpic; | |
406 | 1242 | *f1 = secondpic; | |
407 | 1242 | return 0; | |
408 | } | ||
409 | |||
410 | 1208 | int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1) | |
411 | { | ||
412 | int ret; | ||
413 | |||
414 | 1208 | ret = ff_framesync_dualinput_get(fs, f0, f1); | |
415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1208 times.
|
1208 | if (ret < 0) |
416 | ✗ | return ret; | |
417 | 1208 | ret = ff_inlink_make_frame_writable(fs->parent->inputs[0], f0); | |
418 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1208 times.
|
1208 | if (ret < 0) { |
419 | ✗ | av_frame_free(f0); | |
420 | ✗ | *f1 = NULL; | |
421 | ✗ | return ret; | |
422 | } | ||
423 | 1208 | return 0; | |
424 | } | ||
425 |