1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <stdint.h>
20 #include <string.h>
21
27
30
34
35 /* stream head: largest timestamp seen */
38 /* no more frames will be sent for this stream */
40
44
47
48 /* no more frames will be sent for any stream */
50 /* sync head: the stream with the _smallest_ head timestamp
51 * this stream determines which frames can be output */
53 /* the finished stream with the smallest finish timestamp or -1 */
55
56 // maximum buffering duration in microseconds
58
61
62 // pool of preallocated frames to avoid constant allocations
64 };
65
68 {
71 else
73 }
74
76 {
80 }
81
83 {
85 }
86
88 {
90
92
94 /* check if this stream is the new finished head */
100 }
101
102 /* mark as finished all streams that should no longer receive new frames,
103 * due to them being ahead of some finished stream */
110 }
111 }
112
113 /* mark the whole queue as finished if all streams are finished */
116 return;
117 }
119 }
120
122 {
124 /* wait for one timestamp in each stream before determining
125 * the queue head */
129 return;
130 }
131
132 // placeholder value, correct one will be found below
134 }
135
143 }
144 }
145
146 /* update this stream's head timestamp */
148 {
150
153 return;
154
156
157 /* if this stream is now ahead of some finished stream, then
158 * this stream is also finished */
164
165 /* update the overall head timestamp if it could have changed */
169 }
170
171 /* If the queue for the given stream (or all streams when stream_idx=-1)
172 * is overflowing, trigger a fake heartbeat on lagging streams.
173 *
174 * @return 1 if heartbeat triggered, 0 otherwise
175 */
177 {
181
182 /* if no stream specified, pick the one that is most ahead */
183 if (stream_idx < 0) {
185
194 }
195 }
196 /* no stream has a timestamp yet -> nothing to do */
197 if (stream_idx < 0)
198 return 0;
199 }
200
202
203 /* get the chosen stream's tail timestamp */
207
208 /* overflow triggers when the tail is over specified duration behind the head */
211 return 0;
212
213 /* signal a fake timestamp for all streams that prevent tail_ts from being output */
214 tail_ts++;
217 int64_t ts;
218
222 continue;
223
227
229 }
230
231 return 1;
232 }
233
235 {
238 int64_t ts;
240
243
245
248 return 0;
249 }
252
256
258
260
266 }
267
269
273
274 return 0;
275 }
276
279 {
283
286
289 int64_t ts;
291
294
295 /* check if this stream's tail timestamp does not overtake
296 * the overall queue head */
299
300 /* We can release frames that do not end after the queue head.
301 * Frames with no timestamps are just passed through with no conditions.
302 */
307 return 0;
308 }
309 }
310
313 }
314
316 {
317 int nb_eof = 0;
319
320 /* read a frame for a specific stream */
321 if (stream_idx >= 0) {
323 return (
ret < 0) ?
ret : stream_idx;
324 }
325
326 /* read a frame for any stream with available output */
331 continue;
332 }
334 }
335
337 }
338
340 {
342
343 /* try again if the queue overflowed and triggered a fake heartbeat
344 * for lagging streams */
347
349 }
350
352 {
354
359
361 memset(st, 0, sizeof(*st));
362
366
367 /* we set a valid default, so that a pathological stream that never
368 * receives even a real timebase (and no frames) won't stall all other
369 * streams forever; cf. overflow_heartbeat() */
374
376 }
377
379 {
381
384
386
389
391 }
392
394 {
396
399
403 }
404
406 {
408
409 if (!sq)
411
414
417
423 }
424
425 return sq;
426 }
427
429 {
431
432 if (!sq)
433 return;
434
439
441 }
442
444
446
448 }