FFmpeg
Loading...
Searching...
No Matches
seek.c
Go to the documentation of this file.
1/*
2 * Seeking and index-related functions
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdint.h>
23
24#include "libavutil/avassert.h"
26#include "libavutil/mem.h"
27#include "libavutil/timestamp.h"
28
29#include "libavcodec/avcodec.h"
30
31#include "avformat.h"
32#include "avformat_internal.h"
33#include "avio_internal.h"
34#include "demux.h"
35#include "internal.h"
36
38{
39 for (unsigned i = 0; i < s->nb_streams; i++) {
40 AVStream *const st = s->streams[i];
41 FFStream *const sti = ffstream(st);
42
43 sti->cur_dts =
44 av_rescale(timestamp,
45 st->time_base.den * (int64_t) ref_st->time_base.num,
46 st->time_base.num * (int64_t) ref_st->time_base.den);
47 }
48}
49
50void ff_reduce_index(AVFormatContext *s, int stream_index)
51{
52 AVStream *const st = s->streams[stream_index];
53 FFStream *const sti = ffstream(st);
54 unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry);
55
56 if ((unsigned) sti->nb_index_entries >= max_entries) {
57 int i;
58 for (i = 0; 2 * i < sti->nb_index_entries; i++)
59 sti->index_entries[i] = sti->index_entries[2 * i];
60 sti->nb_index_entries = i;
61 }
62}
63
64int ff_add_index_entry(AVIndexEntry **index_entries,
65 int *nb_index_entries,
66 unsigned int *index_entries_allocated_size,
67 int64_t pos, int64_t timestamp,
68 int size, int distance, int flags)
69{
70 AVIndexEntry *entries, *ie;
71 int index;
72
73 if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
74 return -1;
75
76 if (timestamp == AV_NOPTS_VALUE)
77 return AVERROR(EINVAL);
78
79 if (size < 0 || size > 0x3FFFFFFF)
80 return AVERROR(EINVAL);
81
82 if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known
83 timestamp -= RELATIVE_TS_BASE;
84
85 entries = av_fast_realloc(*index_entries,
86 index_entries_allocated_size,
87 (*nb_index_entries + 1) *
88 sizeof(AVIndexEntry));
89 if (!entries)
90 return -1;
91
92 *index_entries = entries;
93
94 index = ff_index_search_timestamp(*index_entries, *nb_index_entries,
95 timestamp, AVSEEK_FLAG_ANY);
96 if (index < 0) {
97 index = (*nb_index_entries)++;
98 ie = &entries[index];
99 av_assert0(index == 0 || ie[-1].timestamp < timestamp);
100 } else {
101 ie = &entries[index];
102 if (ie->timestamp != timestamp) {
103 if (ie->timestamp <= timestamp)
104 return -1;
105 memmove(entries + index + 1, entries + index,
106 sizeof(AVIndexEntry) * (*nb_index_entries - index));
107 (*nb_index_entries)++;
108 } else if (ie->pos == pos && distance < ie->min_distance)
109 // do not reduce the distance
111 }
112
113 ie->pos = pos;
114 ie->timestamp = timestamp;
116 ie->size = size;
117 ie->flags = flags;
118
119 return index;
120}
121
123 int size, int distance, int flags)
124{
125 FFStream *const sti = ffstream(st);
126 timestamp = ff_wrap_timestamp(st, timestamp);
129 timestamp, size, distance, flags);
130}
131
132int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries,
133 int64_t wanted_timestamp, int flags)
134{
135 int a, b, m;
136 int64_t timestamp;
137
138 a = -1;
139 b = nb_entries;
140
141 // Optimize appending index entries at the end.
142 if (b && entries[b - 1].timestamp < wanted_timestamp)
143 a = b - 1;
144
145 while (b - a > 1) {
146 m = (a + b) >> 1;
147
148 // Search for the next non-discarded packet.
149 while ((entries[m].flags & AVINDEX_DISCARD_FRAME) && m < b && m < nb_entries - 1) {
150 m++;
151 if (m == b && entries[m].timestamp >= wanted_timestamp) {
152 m = b - 1;
153 break;
154 }
155 }
156
157 timestamp = entries[m].timestamp;
158 if (timestamp >= wanted_timestamp)
159 b = m;
160 if (timestamp <= wanted_timestamp)
161 a = m;
162 }
163 m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
164
165 if (!(flags & AVSEEK_FLAG_ANY))
166 while (m >= 0 && m < nb_entries &&
167 !(entries[m].flags & AVINDEX_KEYFRAME))
168 m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
169
170 if (m == nb_entries)
171 return -1;
172 return m;
173}
174
176{
177 int64_t pos_delta = 0;
178 int64_t skip = 0;
179 //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable
180 const char *proto = avio_find_protocol_name(s->url);
182
183 av_assert0(time_tolerance >= 0);
184
185 if (!proto) {
187 "Protocol name not provided, cannot determine if input is local or "
188 "a network protocol, buffers and access patterns cannot be configured "
189 "optimally without knowing the protocol\n");
190 }
191
192 if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))
193 return;
194
195 for (unsigned ist1 = 0; ist1 < s->nb_streams; ist1++) {
196 AVStream *const st1 = s->streams[ist1];
197 FFStream *const sti1 = ffstream(st1);
198 for (unsigned ist2 = 0; ist2 < s->nb_streams; ist2++) {
199 AVStream *const st2 = s->streams[ist2];
200 FFStream *const sti2 = ffstream(st2);
201
202 if (ist1 == ist2)
203 continue;
204
205 for (int i1 = 0, i2 = 0; i1 < sti1->nb_index_entries; i1++) {
206 const AVIndexEntry *const e1 = &sti1->index_entries[i1];
208
209 if (e1->size < (1 << 23))
210 skip = FFMAX(skip, e1->size);
211
212 for (; i2 < sti2->nb_index_entries; i2++) {
213 const AVIndexEntry *const e2 = &sti2->index_entries[i2];
215 int64_t cur_delta;
216 if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance)
217 continue;
218 cur_delta = FFABS(e1->pos - e2->pos);
219 if (cur_delta < (1 << 23))
220 pos_delta = FFMAX(pos_delta, cur_delta);
221 break;
222 }
223 }
224 }
225 }
226
227 pos_delta *= 2;
228 ctx = ffiocontext(s->pb);
229 /* XXX This could be adjusted depending on protocol*/
230 if (s->pb->buffer_size < pos_delta) {
231 av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);
232
233 /* realloc the buffer and the original data will be retained */
234 if (ffio_realloc_buf(s->pb, pos_delta)) {
235 av_log(s, AV_LOG_ERROR, "Realloc buffer fail.\n");
236 return;
237 }
238
239 ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, pos_delta/2);
240 }
241
242 ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip);
243}
244
245int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
246{
247 const FFStream *const sti = ffstream(st);
249 wanted_timestamp, flags);
250}
251
253{
254 return cffstream(st)->nb_index_entries;
255}
256
258{
259 const FFStream *const sti = ffstream(st);
260 if (idx < 0 || idx >= sti->nb_index_entries)
261 return NULL;
262
263 return &sti->index_entries[idx];
264}
265
267 int64_t wanted_timestamp,
268 int flags)
269{
270 const FFStream *const sti = ffstream(st);
272 sti->nb_index_entries,
273 wanted_timestamp, flags);
274
275 if (idx < 0)
276 return NULL;
277
278 return &sti->index_entries[idx];
279}
280
281static int64_t read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit,
282 int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
283{
284 int64_t ts = read_timestamp(s, stream_index, ppos, pos_limit);
285 if (stream_index >= 0)
286 ts = ff_wrap_timestamp(s->streams[stream_index], ts);
287 return ts;
288}
289
291 int64_t target_ts, int flags)
292{
293 const FFInputFormat *const avif = ffifmt(s->iformat);
294 int64_t pos_min = 0, pos_max = 0, pos, pos_limit;
295 int64_t ts_min, ts_max, ts;
296 int index;
297 int64_t ret;
298 AVStream *st;
299 FFStream *sti;
300
301 if (stream_index < 0)
302 return -1;
303
304 av_log(s, AV_LOG_TRACE, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
305
306 ts_max =
307 ts_min = AV_NOPTS_VALUE;
308 pos_limit = -1; // GCC falsely says it may be uninitialized.
309
310 st = s->streams[stream_index];
311 sti = ffstream(st);
312 if (sti->index_entries) {
313 const AVIndexEntry *e;
314
315 /* FIXME: Whole function must be checked for non-keyframe entries in
316 * index case, especially read_timestamp(). */
317 index = av_index_search_timestamp(st, target_ts,
319 index = FFMAX(index, 0);
320 e = &sti->index_entries[index];
321
322 if (e->timestamp <= target_ts || e->pos == e->min_distance) {
323 pos_min = e->pos;
324 ts_min = e->timestamp;
325 av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
326 pos_min, av_ts2str(ts_min));
327 } else {
328 av_assert1(index == 0);
329 }
330
331 index = av_index_search_timestamp(st, target_ts,
333 av_assert0(index < sti->nb_index_entries);
334 if (index >= 0) {
335 e = &sti->index_entries[index];
336 av_assert1(e->timestamp >= target_ts);
337 pos_max = e->pos;
338 ts_max = e->timestamp;
339 pos_limit = pos_max - e->min_distance;
340 av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64
341 " dts_max=%s\n", pos_max, pos_limit, av_ts2str(ts_max));
342 }
343 }
344
345 pos = ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit,
346 ts_min, ts_max, flags, &ts, avif->read_timestamp);
347 if (pos < 0)
348 return -1;
349
350 /* do the seek */
351 if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0)
352 return ret;
353
355 avpriv_update_cur_dts(s, st, ts);
356
357 return 0;
358}
359
360int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos,
361 int64_t (*read_timestamp_func)(struct AVFormatContext *, int , int64_t *, int64_t ))
362{
363 int64_t step = 1024;
364 int64_t limit, ts_max;
366 int64_t pos_max = filesize - 1;
367 do {
368 limit = pos_max;
369 pos_max = FFMAX(0, (pos_max) - step);
370 ts_max = read_timestamp(s, stream_index,
371 &pos_max, limit, read_timestamp_func);
372 step += step;
373 } while (ts_max == AV_NOPTS_VALUE && 2*limit > step);
374 if (ts_max == AV_NOPTS_VALUE)
375 return -1;
376
377 for (;;) {
378 int64_t tmp_pos = pos_max + 1;
379 int64_t tmp_ts = read_timestamp(s, stream_index,
380 &tmp_pos, INT64_MAX, read_timestamp_func);
381 if (tmp_ts == AV_NOPTS_VALUE)
382 break;
383 av_assert0(tmp_pos > pos_max);
384 ts_max = tmp_ts;
385 pos_max = tmp_pos;
386 if (tmp_pos >= filesize)
387 break;
388 }
389
390 if (ts)
391 *ts = ts_max;
392 if (pos)
393 *pos = pos_max;
394
395 return 0;
396}
397
398int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
399 int64_t pos_min, int64_t pos_max, int64_t pos_limit,
400 int64_t ts_min, int64_t ts_max,
401 int flags, int64_t *ts_ret,
402 int64_t (*read_timestamp_func)(struct AVFormatContext *,
403 int, int64_t *, int64_t))
404{
405 FFFormatContext *const si = ffformatcontext(s);
406 int64_t pos, ts;
407 int64_t start_pos;
408 int no_change;
409 int ret;
410
411 av_log(s, AV_LOG_TRACE, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
412
413 if (ts_min == AV_NOPTS_VALUE) {
414 pos_min = si->data_offset;
415 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
416 if (ts_min == AV_NOPTS_VALUE)
417 return -1;
418 }
419
420 if (ts_min >= target_ts) {
421 *ts_ret = ts_min;
422 return pos_min;
423 }
424
425 if (ts_max == AV_NOPTS_VALUE) {
426 if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp_func)) < 0)
427 return ret;
428 pos_limit = pos_max;
429 }
430
431 if (ts_max <= target_ts) {
432 *ts_ret = ts_max;
433 return pos_max;
434 }
435
436 av_assert0(ts_min < ts_max);
437
438 no_change = 0;
439 while (pos_min < pos_limit) {
441 "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
442 pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
443 av_assert0(pos_limit <= pos_max);
444
445 if (no_change == 0) {
446 int64_t approximate_keyframe_distance = pos_max - pos_limit;
447 // interpolate position (better than dichotomy)
448 pos = av_rescale(target_ts - ts_min, pos_max - pos_min,
449 ts_max - ts_min) +
450 pos_min - approximate_keyframe_distance;
451 } else if (no_change == 1) {
452 // bisection if interpolation did not change min / max pos last time
453 pos = (pos_min + pos_limit) >> 1;
454 } else {
455 /* linear search if bisection failed, can only happen if there
456 * are very few or no keyframes between min/max */
457 pos = pos_min;
458 }
459 if (pos <= pos_min)
460 pos = pos_min + 1;
461 else if (pos > pos_limit)
462 pos = pos_limit;
463 start_pos = pos;
464
465 // May pass pos_limit instead of -1.
466 ts = read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp_func);
467 if (pos == pos_max)
468 no_change++;
469 else
470 no_change = 0;
471 av_log(s, AV_LOG_TRACE, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s"
472 " target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
473 pos_min, pos, pos_max,
474 av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
475 pos_limit, start_pos, no_change);
476 if (ts == AV_NOPTS_VALUE) {
477 av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
478 return -1;
479 }
480 if (target_ts <= ts) {
481 pos_limit = start_pos - 1;
482 pos_max = pos;
483 ts_max = ts;
484 }
485 if (target_ts >= ts) {
486 pos_min = pos;
487 ts_min = ts;
488 }
489 }
490
491 pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
492 ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
493#if 0
494 pos_min = pos;
495 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
496 pos_min++;
497 ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
498 av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %s<=%s<=%s\n",
499 pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
500#endif
501 *ts_ret = ts;
502 return pos;
503}
504
505static int seek_frame_byte(AVFormatContext *s, int stream_index,
506 int64_t pos, int flags)
507{
508 FFFormatContext *const si = ffformatcontext(s);
509 int64_t pos_min, pos_max;
510
511 pos_min = si->data_offset;
512 pos_max = avio_size(s->pb) - 1;
513
514 if (pos < pos_min)
515 pos = pos_min;
516 else if (pos > pos_max)
517 pos = pos_max;
518
519 avio_seek(s->pb, pos, SEEK_SET);
520
521 s->io_repositioned = 1;
522
523 return 0;
524}
525
526static int seek_frame_generic(AVFormatContext *s, int stream_index,
527 int64_t timestamp, int flags)
528{
529 FFFormatContext *const si = ffformatcontext(s);
530 AVStream *const st = s->streams[stream_index];
531 FFStream *const sti = ffstream(st);
532 const AVIndexEntry *ie;
533 int index;
534 int64_t ret;
535
536 index = av_index_search_timestamp(st, timestamp, flags);
537
538 if (index < 0 && sti->nb_index_entries &&
539 timestamp < sti->index_entries[0].timestamp)
540 return -1;
541
542 if (index < 0 || index == sti->nb_index_entries - 1) {
543 AVPacket *const pkt = si->pkt;
544 int nonkey = 0;
545
546 if (sti->nb_index_entries) {
548 ie = &sti->index_entries[sti->nb_index_entries - 1];
549 if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
550 return ret;
551 s->io_repositioned = 1;
553 } else {
554 if ((ret = avio_seek(s->pb, si->data_offset, SEEK_SET)) < 0)
555 return ret;
556 s->io_repositioned = 1;
557 }
559 for (;;) {
560 int read_status;
561 do {
562 read_status = av_read_frame(s, pkt);
563 } while (read_status == AVERROR(EAGAIN));
564 if (read_status < 0)
565 break;
566 if (stream_index == pkt->stream_index && pkt->dts > timestamp) {
567 if (pkt->flags & AV_PKT_FLAG_KEY) {
569 break;
570 }
571 if (nonkey++ > 1000 && st->codecpar->codec_id != AV_CODEC_ID_CDGRAPHICS) {
572 av_log(s, AV_LOG_ERROR,"seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found\n", nonkey);
574 break;
575 }
576 }
578 }
579 index = av_index_search_timestamp(st, timestamp, flags);
580 }
581 if (index < 0)
582 return -1;
583
585 if (ffifmt(s->iformat)->read_seek)
586 if (ffifmt(s->iformat)->read_seek(s, stream_index, timestamp, flags) >= 0)
587 return 0;
588 ie = &sti->index_entries[index];
589 if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
590 return ret;
591 s->io_repositioned = 1;
593
594 return 0;
595}
596
597static int seek_frame_internal(AVFormatContext *s, int stream_index,
598 int64_t timestamp, int flags)
599{
600 AVStream *st;
601 int ret;
602
603 if (flags & AVSEEK_FLAG_BYTE) {
604 if (s->iformat->flags & AVFMT_NO_BYTE_SEEK)
605 return -1;
607 return seek_frame_byte(s, stream_index, timestamp, flags);
608 }
609
610 if (stream_index < 0) {
611 stream_index = av_find_default_stream_index(s);
612 if (stream_index < 0)
613 return -1;
614
615 st = s->streams[stream_index];
616 /* timestamp for default must be expressed in AV_TIME_BASE units */
617 timestamp = av_rescale(timestamp, st->time_base.den,
619 }
620
621 /* first, we try the format specific seek */
622 if (ffifmt(s->iformat)->read_seek) {
624 ret = ffifmt(s->iformat)->read_seek(s, stream_index, timestamp, flags);
625 } else
626 ret = -1;
627 if (ret >= 0)
628 return 0;
629
630 if (ffifmt(s->iformat)->read_timestamp &&
631 !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
633 return ff_seek_frame_binary(s, stream_index, timestamp, flags);
634 } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
636 return seek_frame_generic(s, stream_index, timestamp, flags);
637 } else
638 return -1;
639}
640
641int av_seek_frame(AVFormatContext *s, int stream_index,
642 int64_t timestamp, int flags)
643{
644 int ret;
645
646 if (ffifmt(s->iformat)->read_seek2 && !ffifmt(s->iformat)->read_seek) {
647 int64_t min_ts = INT64_MIN, max_ts = INT64_MAX;
649 max_ts = timestamp;
650 else
651 min_ts = timestamp;
652 return avformat_seek_file(s, stream_index, min_ts, timestamp, max_ts,
654 }
655
656 ret = seek_frame_internal(s, stream_index, timestamp, flags);
657
658 if (ret >= 0)
660
661 return ret;
662}
663
664int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts,
665 int64_t ts, int64_t max_ts, int flags)
666{
667 int dir;
668 int ret;
669
670 if (min_ts > ts || max_ts < ts)
671 return -1;
672 if (stream_index < -1 || stream_index >= (int)s->nb_streams)
673 return AVERROR(EINVAL);
674
675 if (s->seek2any > 0)
678
679 if (ffifmt(s->iformat)->read_seek2) {
680 int ret;
682
683 if (stream_index == -1 && s->nb_streams == 1) {
684 AVRational time_base = s->streams[0]->time_base;
685 ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base);
686 min_ts = av_rescale_rnd(min_ts, time_base.den,
687 time_base.num * (int64_t)AV_TIME_BASE,
689 max_ts = av_rescale_rnd(max_ts, time_base.den,
690 time_base.num * (int64_t)AV_TIME_BASE,
692 stream_index = 0;
693 }
694
695 ret = ffifmt(s->iformat)->read_seek2(s, stream_index, min_ts,
696 ts, max_ts, flags);
697
698 if (ret >= 0)
700 return ret;
701 }
702
703 // Fall back on old API if new is not implemented but old is.
704 // Note the old API has somewhat different semantics.
705 dir = (ts - (uint64_t)min_ts > (uint64_t)max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0);
706 ret = av_seek_frame(s, stream_index, ts, flags | dir);
707 if (ret < 0 && ts != min_ts && max_ts != ts) {
708 ret = av_seek_frame(s, stream_index, dir ? max_ts : min_ts, flags | dir);
709 if (ret >= 0)
710 ret = av_seek_frame(s, stream_index, ts, flags | (dir^AVSEEK_FLAG_BACKWARD));
711 }
712 return ret;
713}
714
715/** Flush the frame reader. */
717{
719
720 /* Reset read state for each stream. */
721 for (unsigned i = 0; i < s->nb_streams; i++) {
722 AVStream *const st = s->streams[i];
723 FFStream *const sti = ffstream(st);
724
725 if (sti->parser) {
727 sti->parser = NULL;
728 }
731 if (sti->first_dts == AV_NOPTS_VALUE)
733 else
734 /* We set the current DTS to an unspecified origin. */
735 sti->cur_dts = AV_NOPTS_VALUE;
736
737 sti->probe_packets = s->max_probe_packets;
738
739 for (int j = 0; j < MAX_REORDER_DELAY + 1; j++)
740 sti->pts_buffer[j] = AV_NOPTS_VALUE;
741
742 sti->skip_samples = 0;
743 }
744}
745
747{
749 return 0;
750}
751
753 int64_t *min_ts, int64_t *ts, int64_t *max_ts)
754{
755 *ts = av_rescale_q (* ts, tb_in, tb_out);
756 *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out,
758 *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out,
760}
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
void ff_flush_packet_queue(AVFormatContext *s)
Definition avformat.c:139
Main libavformat public API header.
#define AVINDEX_KEYFRAME
Definition avformat.h:628
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition avformat.h:506
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition avformat.h:2617
#define AVFMT_NOGENSEARCH
Format does not allow to fall back on generic search.
Definition avformat.h:505
#define AVFMT_NOBINSEARCH
Format does not allow to fall back on binary search via read_timestamp.
Definition avformat.h:504
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition avformat.h:2618
#define AVINDEX_DISCARD_FRAME
Definition avformat.h:629
#define AVSEEK_FLAG_BACKWARD
seek backward
Definition avformat.h:2616
#define RELATIVE_TS_BASE
static av_always_inline int is_relative(int64_t ts)
int64_t ff_wrap_timestamp(const AVStream *st, int64_t timestamp)
Wrap a given time stamp, if there is an indication for an overflow.
Definition demux.c:68
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition avio.c:725
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition aviobuf.c:326
static av_always_inline FFIOContext * ffiocontext(AVIOContext *ctx)
int ffio_realloc_buf(AVIOContext *s, int buf_size)
Reallocate a given buffer for AVIOContext.
Definition aviobuf.c:1106
static void BS_FUNC skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition common.h:74
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static const FFInputFormat * ffifmt(const AVInputFormat *fmt)
Definition demux.h:186
static AVPacket * pkt
static int64_t filesize(AVIOContext *pb)
Definition ffmpeg_mux.c:51
@ AV_CODEC_ID_CDGRAPHICS
Definition codec_id.h:182
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
void av_parser_close(AVCodecParserContext *s)
Definition parser.c:203
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition seek.c:664
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition demux.c:1588
int avformat_flush(AVFormatContext *s)
Discard all internally buffered data.
Definition seek.c:746
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
Definition seek.c:641
int avformat_index_get_entries_count(const AVStream *st)
Get the index entry count for the given AVStream.
Definition seek.c:252
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Add an index entry into a sorted list.
Definition seek.c:122
int avformat_queue_attached_pictures(AVFormatContext *s)
Definition demux_utils.c:84
const AVIndexEntry * avformat_index_get_entry(AVStream *st, int idx)
Get the AVIndexEntry corresponding to the given index.
Definition seek.c:257
int av_find_default_stream_index(AVFormatContext *s)
Definition avformat.c:469
const AVIndexEntry * avformat_index_get_entry_from_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
Get the AVIndexEntry corresponding to the given timestamp.
Definition seek.c:266
int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
Get the index for a specific timestamp.
Definition seek.c:245
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition mathematics.c:58
int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd)
Rescale a 64-bit integer by 2 rational numbers with specified rounding.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AV_ROUND_DOWN
Round toward -infinity.
@ AV_ROUND_PASS_MINMAX
Flag telling rescaling functions to pass INT64_MIN/MAX through unchanged, avoiding special cases for ...
@ AV_ROUND_UP
Round toward +infinity.
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:495
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE
Internal time base represented as integer.
Definition avutil.h:253
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
int index
Definition gxfenc.c:90
int a
#define MAX_REORDER_DELAY
#define b
Definition input.c:43
static av_always_inline FFStream * ffstream(AVStream *st)
Definition internal.h:365
static av_always_inline const FFStream * cffstream(const AVStream *st)
Definition internal.h:370
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition internal.h:130
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
static float distance(float x, float y, int band)
int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
Perform a binary search using av_index_search_timestamp() and FFInputFormat.read_timestamp().
Definition seek.c:290
void ff_rescale_interval(AVRational tb_in, AVRational tb_out, int64_t *min_ts, int64_t *ts, int64_t *max_ts)
Rescales a timestamp and the endpoints of an interval to which the temstamp belongs,...
Definition seek.c:752
int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos, int64_t(*read_timestamp_func)(struct AVFormatContext *, int, int64_t *, int64_t))
Definition seek.c:360
int ff_add_index_entry(AVIndexEntry **index_entries, int *nb_index_entries, unsigned int *index_entries_allocated_size, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Internal version of av_add_index_entry.
Definition seek.c:64
static int seek_frame_generic(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition seek.c:526
int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries, int64_t wanted_timestamp, int flags)
Internal version of av_index_search_timestamp.
Definition seek.c:132
void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
Definition seek.c:175
static int seek_frame_internal(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition seek.c:597
void ff_read_frame_flush(AVFormatContext *s)
Flush the frame reader.
Definition seek.c:716
static int64_t read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit, int64_t(*read_timestamp)(struct AVFormatContext *, int, int64_t *, int64_t))
Definition seek.c:281
void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
Update cur_dts of all streams based on the given timestamp and AVStream.
Definition seek.c:37
int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t(*read_timestamp_func)(struct AVFormatContext *, int, int64_t *, int64_t))
Perform a binary search using read_timestamp().
Definition seek.c:398
void ff_reduce_index(AVFormatContext *s, int stream_index)
Ensure the index uses less memory than the maximum specified in AVFormatContext.max_index_size by dis...
Definition seek.c:50
static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags)
Definition seek.c:505
unsigned int pos
Definition spdifenc.c:431
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
Format I/O context.
Definition avformat.h:1333
int64_t pos
Definition avformat.h:621
int min_distance
Minimum distance between this and the previous keyframe, used to avoid unneeded searching.
Definition avformat.h:632
int64_t timestamp
Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are...
Definition avformat.h:622
This structure stores compressed data.
Definition packet.h:580
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:805
int64_t data_offset
offset of the first packet
Definition internal.h:89
AVPacket * pkt
Used to hold temporary packets for the generic demuxing code.
Definition internal.h:111
int(* read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags)
Seek to a given timestamp relative to the frames in stream component stream_index.
Definition demux.h:125
int64_t(* read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit)
Get the next timestamp in stream[stream_index].time_base units.
Definition demux.h:132
int(* read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition demux.h:177
int probe_packets
Number of packets to buffer for codec probing.
Definition internal.h:318
int64_t cur_dts
Definition internal.h:360
int64_t pts_buffer[MAX_REORDER_DELAY+1]
Definition internal.h:289
int64_t last_dts_for_order_check
Internal data to analyze DTS and detect faulty mpeg streams.
Definition internal.h:294
int skip_samples
Number of samples to skip at the start of the frame decoded from the next packet.
Definition internal.h:215
int nb_index_entries
Definition internal.h:193
struct AVCodecParserContext * parser
Definition internal.h:322
int64_t first_dts
Timestamp corresponding to the last dts sync point.
Definition internal.h:359
int64_t last_IP_pts
Definition internal.h:312
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
Definition internal.h:191
unsigned int index_entries_allocated_size
Definition internal.h:194
#define av_log(a,...)
static AVFormatContext * ctx
Definition movenc.c:49
timestamp utils, mostly useful for debugging/logging purposes
#define av_ts2str(ts)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition timestamp.h:54
int size
static double limit(double x)