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"
25 #include "libavutil/mathematics.h"
26 #include "libavutil/timestamp.h"
27
28 #include "avformat.h"
29 #include "avio_internal.h"
30 #include "demux.h"
31 #include "internal.h"
32
avpriv_update_cur_dts(AVFormatContext * s,AVStream * ref_st,int64_t timestamp)33 void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
34 {
35 for (unsigned i = 0; i < s->nb_streams; i++) {
36 AVStream *const st = s->streams[i];
37 FFStream *const sti = ffstream(st);
38
39 sti->cur_dts =
40 av_rescale(timestamp,
41 st->time_base.den * (int64_t) ref_st->time_base.num,
42 st->time_base.num * (int64_t) ref_st->time_base.den);
43 }
44 }
45
ff_reduce_index(AVFormatContext * s,int stream_index)46 void ff_reduce_index(AVFormatContext *s, int stream_index)
47 {
48 AVStream *const st = s->streams[stream_index];
49 FFStream *const sti = ffstream(st);
50 unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry);
51
52 if ((unsigned) sti->nb_index_entries >= max_entries) {
53 int i;
54 for (i = 0; 2 * i < sti->nb_index_entries; i++)
55 sti->index_entries[i] = sti->index_entries[2 * i];
56 sti->nb_index_entries = i;
57 }
58 }
59
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)60 int ff_add_index_entry(AVIndexEntry **index_entries,
61 int *nb_index_entries,
62 unsigned int *index_entries_allocated_size,
63 int64_t pos, int64_t timestamp,
64 int size, int distance, int flags)
65 {
66 AVIndexEntry *entries, *ie;
67 int index;
68
69 if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
70 return -1;
71
72 if (timestamp == AV_NOPTS_VALUE)
73 return AVERROR(EINVAL);
74
75 if (size < 0 || size > 0x3FFFFFFF)
76 return AVERROR(EINVAL);
77
78 if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known
79 timestamp -= RELATIVE_TS_BASE;
80
81 entries = av_fast_realloc(*index_entries,
82 index_entries_allocated_size,
83 (*nb_index_entries + 1) *
84 sizeof(AVIndexEntry));
85 if (!entries)
86 return -1;
87
88 *index_entries = entries;
89
90 index = ff_index_search_timestamp(*index_entries, *nb_index_entries,
91 timestamp, AVSEEK_FLAG_ANY);
92 if (index < 0) {
93 index = (*nb_index_entries)++;
94 ie = &entries[index];
95 av_assert0(index == 0 || ie[-1].timestamp < timestamp);
96 } else {
97 ie = &entries[index];
98 if (ie->timestamp != timestamp) {
99 if (ie->timestamp <= timestamp)
100 return -1;
101 memmove(entries + index + 1, entries + index,
102 sizeof(AVIndexEntry) * (*nb_index_entries - index));
103 (*nb_index_entries)++;
104 } else if (ie->pos == pos && distance < ie->min_distance)
105 // do not reduce the distance
106 distance = ie->min_distance;
107 }
108
109 ie->pos = pos;
110 ie->timestamp = timestamp;
111 ie->min_distance = distance;
112 ie->size = size;
113 ie->flags = flags;
114
115 return index;
116 }
117
av_add_index_entry(AVStream * st,int64_t pos,int64_t timestamp,int size,int distance,int flags)118 int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
119 int size, int distance, int flags)
120 {
121 FFStream *const sti = ffstream(st);
122 timestamp = ff_wrap_timestamp(st, timestamp);
123 return ff_add_index_entry(&sti->index_entries, &sti->nb_index_entries,
124 &sti->index_entries_allocated_size, pos,
125 timestamp, size, distance, flags);
126 }
127
ff_index_search_timestamp(const AVIndexEntry * entries,int nb_entries,int64_t wanted_timestamp,int flags)128 int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries,
129 int64_t wanted_timestamp, int flags)
130 {
131 int a, b, m;
132 int64_t timestamp;
133
134 a = -1;
135 b = nb_entries;
136
137 // Optimize appending index entries at the end.
138 if (b && entries[b - 1].timestamp < wanted_timestamp)
139 a = b - 1;
140
141 while (b - a > 1) {
142 m = (a + b) >> 1;
143
144 // Search for the next non-discarded packet.
145 while ((entries[m].flags & AVINDEX_DISCARD_FRAME) && m < b && m < nb_entries - 1) {
146 m++;
147 if (m == b && entries[m].timestamp >= wanted_timestamp) {
148 m = b - 1;
149 break;
150 }
151 }
152
153 timestamp = entries[m].timestamp;
154 if (timestamp >= wanted_timestamp)
155 b = m;
156 if (timestamp <= wanted_timestamp)
157 a = m;
158 }
159 m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
160
161 if (!(flags & AVSEEK_FLAG_ANY))
162 while (m >= 0 && m < nb_entries &&
163 !(entries[m].flags & AVINDEX_KEYFRAME))
164 m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
165
166 if (m == nb_entries)
167 return -1;
168 return m;
169 }
170
ff_configure_buffers_for_index(AVFormatContext * s,int64_t time_tolerance)171 void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
172 {
173 int64_t pos_delta = 0;
174 int64_t skip = 0;
175 //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable
176 const char *proto = avio_find_protocol_name(s->url);
177 FFIOContext *ctx;
178
179 av_assert0(time_tolerance >= 0);
180
181 if (!proto) {
182 av_log(s, AV_LOG_INFO,
183 "Protocol name not provided, cannot determine if input is local or "
184 "a network protocol, buffers and access patterns cannot be configured "
185 "optimally without knowing the protocol\n");
186 }
187
188 if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))
189 return;
190
191 for (unsigned ist1 = 0; ist1 < s->nb_streams; ist1++) {
192 AVStream *const st1 = s->streams[ist1];
193 FFStream *const sti1 = ffstream(st1);
194 for (unsigned ist2 = 0; ist2 < s->nb_streams; ist2++) {
195 AVStream *const st2 = s->streams[ist2];
196 FFStream *const sti2 = ffstream(st2);
197
198 if (ist1 == ist2)
199 continue;
200
201 for (int i1 = 0, i2 = 0; i1 < sti1->nb_index_entries; i1++) {
202 const AVIndexEntry *const e1 = &sti1->index_entries[i1];
203 int64_t e1_pts = av_rescale_q(e1->timestamp, st1->time_base, AV_TIME_BASE_Q);
204
205 skip = FFMAX(skip, e1->size);
206 for (; i2 < sti2->nb_index_entries; i2++) {
207 const AVIndexEntry *const e2 = &sti2->index_entries[i2];
208 int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q);
209 if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance)
210 continue;
211 pos_delta = FFMAX(pos_delta, e1->pos - e2->pos);
212 break;
213 }
214 }
215 }
216 }
217
218 pos_delta *= 2;
219 ctx = ffiocontext(s->pb);
220 /* XXX This could be adjusted depending on protocol*/
221 if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) {
222 av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);
223
224 /* realloc the buffer and the original data will be retained */
225 if (ffio_realloc_buf(s->pb, pos_delta)) {
226 av_log(s, AV_LOG_ERROR, "Realloc buffer fail.\n");
227 return;
228 }
229
230 ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, pos_delta/2);
231 }
232
233 if (skip < (1<<23)) {
234 ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip);
235 }
236 }
237
av_index_search_timestamp(AVStream * st,int64_t wanted_timestamp,int flags)238 int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
239 {
240 const FFStream *const sti = ffstream(st);
241 return ff_index_search_timestamp(sti->index_entries, sti->nb_index_entries,
242 wanted_timestamp, flags);
243 }
244
avformat_index_get_entries_count(const AVStream * st)245 int avformat_index_get_entries_count(const AVStream *st)
246 {
247 return cffstream(st)->nb_index_entries;
248 }
249
avformat_index_get_entry(AVStream * st,int idx)250 const AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx)
251 {
252 const FFStream *const sti = ffstream(st);
253 if (idx < 0 || idx >= sti->nb_index_entries)
254 return NULL;
255
256 return &sti->index_entries[idx];
257 }
258
avformat_index_get_entry_from_timestamp(AVStream * st,int64_t wanted_timestamp,int flags)259 const AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st,
260 int64_t wanted_timestamp,
261 int flags)
262 {
263 const FFStream *const sti = ffstream(st);
264 int idx = ff_index_search_timestamp(sti->index_entries,
265 sti->nb_index_entries,
266 wanted_timestamp, flags);
267
268 if (idx < 0)
269 return NULL;
270
271 return &sti->index_entries[idx];
272 }
273
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))274 static int64_t read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit,
275 int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
276 {
277 int64_t ts = read_timestamp(s, stream_index, ppos, pos_limit);
278 if (stream_index >= 0)
279 ts = ff_wrap_timestamp(s->streams[stream_index], ts);
280 return ts;
281 }
282
ff_seek_frame_binary(AVFormatContext * s,int stream_index,int64_t target_ts,int flags)283 int ff_seek_frame_binary(AVFormatContext *s, int stream_index,
284 int64_t target_ts, int flags)
285 {
286 const AVInputFormat *const avif = s->iformat;
287 int64_t pos_min = 0, pos_max = 0, pos, pos_limit;
288 int64_t ts_min, ts_max, ts;
289 int index;
290 int64_t ret;
291 AVStream *st;
292 FFStream *sti;
293
294 if (stream_index < 0)
295 return -1;
296
297 av_log(s, AV_LOG_TRACE, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
298
299 ts_max =
300 ts_min = AV_NOPTS_VALUE;
301 pos_limit = -1; // GCC falsely says it may be uninitialized.
302
303 st = s->streams[stream_index];
304 sti = ffstream(st);
305 if (sti->index_entries) {
306 const AVIndexEntry *e;
307
308 /* FIXME: Whole function must be checked for non-keyframe entries in
309 * index case, especially read_timestamp(). */
310 index = av_index_search_timestamp(st, target_ts,
311 flags | AVSEEK_FLAG_BACKWARD);
312 index = FFMAX(index, 0);
313 e = &sti->index_entries[index];
314
315 if (e->timestamp <= target_ts || e->pos == e->min_distance) {
316 pos_min = e->pos;
317 ts_min = e->timestamp;
318 av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
319 pos_min, av_ts2str(ts_min));
320 } else {
321 av_assert1(index == 0);
322 }
323
324 index = av_index_search_timestamp(st, target_ts,
325 flags & ~AVSEEK_FLAG_BACKWARD);
326 av_assert0(index < sti->nb_index_entries);
327 if (index >= 0) {
328 e = &sti->index_entries[index];
329 av_assert1(e->timestamp >= target_ts);
330 pos_max = e->pos;
331 ts_max = e->timestamp;
332 pos_limit = pos_max - e->min_distance;
333 av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64
334 " dts_max=%s\n", pos_max, pos_limit, av_ts2str(ts_max));
335 }
336 }
337
338 pos = ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit,
339 ts_min, ts_max, flags, &ts, avif->read_timestamp);
340 if (pos < 0)
341 return -1;
342
343 /* do the seek */
344 if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0)
345 return ret;
346
347 ff_read_frame_flush(s);
348 avpriv_update_cur_dts(s, st, ts);
349
350 return 0;
351 }
352
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))353 int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos,
354 int64_t (*read_timestamp_func)(struct AVFormatContext *, int , int64_t *, int64_t ))
355 {
356 int64_t step = 1024;
357 int64_t limit, ts_max;
358 int64_t filesize = avio_size(s->pb);
359 int64_t pos_max = filesize - 1;
360 do {
361 limit = pos_max;
362 pos_max = FFMAX(0, (pos_max) - step);
363 ts_max = read_timestamp(s, stream_index,
364 &pos_max, limit, read_timestamp_func);
365 step += step;
366 } while (ts_max == AV_NOPTS_VALUE && 2*limit > step);
367 if (ts_max == AV_NOPTS_VALUE)
368 return -1;
369
370 for (;;) {
371 int64_t tmp_pos = pos_max + 1;
372 int64_t tmp_ts = read_timestamp(s, stream_index,
373 &tmp_pos, INT64_MAX, read_timestamp_func);
374 if (tmp_ts == AV_NOPTS_VALUE)
375 break;
376 av_assert0(tmp_pos > pos_max);
377 ts_max = tmp_ts;
378 pos_max = tmp_pos;
379 if (tmp_pos >= filesize)
380 break;
381 }
382
383 if (ts)
384 *ts = ts_max;
385 if (pos)
386 *pos = pos_max;
387
388 return 0;
389 }
390
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))391 int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
392 int64_t pos_min, int64_t pos_max, int64_t pos_limit,
393 int64_t ts_min, int64_t ts_max,
394 int flags, int64_t *ts_ret,
395 int64_t (*read_timestamp_func)(struct AVFormatContext *,
396 int, int64_t *, int64_t))
397 {
398 FFFormatContext *const si = ffformatcontext(s);
399 int64_t pos, ts;
400 int64_t start_pos;
401 int no_change;
402 int ret;
403
404 av_log(s, AV_LOG_TRACE, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
405
406 if (ts_min == AV_NOPTS_VALUE) {
407 pos_min = si->data_offset;
408 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
409 if (ts_min == AV_NOPTS_VALUE)
410 return -1;
411 }
412
413 if (ts_min >= target_ts) {
414 *ts_ret = ts_min;
415 return pos_min;
416 }
417
418 if (ts_max == AV_NOPTS_VALUE) {
419 if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp_func)) < 0)
420 return ret;
421 pos_limit = pos_max;
422 }
423
424 if (ts_max <= target_ts) {
425 *ts_ret = ts_max;
426 return pos_max;
427 }
428
429 av_assert0(ts_min < ts_max);
430
431 no_change = 0;
432 while (pos_min < pos_limit) {
433 av_log(s, AV_LOG_TRACE,
434 "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
435 pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
436 av_assert0(pos_limit <= pos_max);
437
438 if (no_change == 0) {
439 int64_t approximate_keyframe_distance = pos_max - pos_limit;
440 // interpolate position (better than dichotomy)
441 pos = av_rescale(target_ts - ts_min, pos_max - pos_min,
442 ts_max - ts_min) +
443 pos_min - approximate_keyframe_distance;
444 } else if (no_change == 1) {
445 // bisection if interpolation did not change min / max pos last time
446 pos = (pos_min + pos_limit) >> 1;
447 } else {
448 /* linear search if bisection failed, can only happen if there
449 * are very few or no keyframes between min/max */
450 pos = pos_min;
451 }
452 if (pos <= pos_min)
453 pos = pos_min + 1;
454 else if (pos > pos_limit)
455 pos = pos_limit;
456 start_pos = pos;
457
458 // May pass pos_limit instead of -1.
459 ts = read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp_func);
460 if (pos == pos_max)
461 no_change++;
462 else
463 no_change = 0;
464 av_log(s, AV_LOG_TRACE, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s"
465 " target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
466 pos_min, pos, pos_max,
467 av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
468 pos_limit, start_pos, no_change);
469 if (ts == AV_NOPTS_VALUE) {
470 av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
471 return -1;
472 }
473 if (target_ts <= ts) {
474 pos_limit = start_pos - 1;
475 pos_max = pos;
476 ts_max = ts;
477 }
478 if (target_ts >= ts) {
479 pos_min = pos;
480 ts_min = ts;
481 }
482 }
483
484 pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
485 ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
486 #if 0
487 pos_min = pos;
488 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
489 pos_min++;
490 ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
491 av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %s<=%s<=%s\n",
492 pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
493 #endif
494 *ts_ret = ts;
495 return pos;
496 }
497
seek_frame_byte(AVFormatContext * s,int stream_index,int64_t pos,int flags)498 static int seek_frame_byte(AVFormatContext *s, int stream_index,
499 int64_t pos, int flags)
500 {
501 FFFormatContext *const si = ffformatcontext(s);
502 int64_t pos_min, pos_max;
503
504 pos_min = si->data_offset;
505 pos_max = avio_size(s->pb) - 1;
506
507 if (pos < pos_min)
508 pos = pos_min;
509 else if (pos > pos_max)
510 pos = pos_max;
511
512 avio_seek(s->pb, pos, SEEK_SET);
513
514 s->io_repositioned = 1;
515
516 return 0;
517 }
518
seek_frame_generic(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)519 static int seek_frame_generic(AVFormatContext *s, int stream_index,
520 int64_t timestamp, int flags)
521 {
522 FFFormatContext *const si = ffformatcontext(s);
523 AVStream *const st = s->streams[stream_index];
524 FFStream *const sti = ffstream(st);
525 const AVIndexEntry *ie;
526 int index;
527 int64_t ret;
528
529 index = av_index_search_timestamp(st, timestamp, flags);
530
531 if (index < 0 && sti->nb_index_entries &&
532 timestamp < sti->index_entries[0].timestamp)
533 return -1;
534
535 if (index < 0 || index == sti->nb_index_entries - 1) {
536 AVPacket *const pkt = si->pkt;
537 int nonkey = 0;
538
539 if (sti->nb_index_entries) {
540 av_assert0(sti->index_entries);
541 ie = &sti->index_entries[sti->nb_index_entries - 1];
542 if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
543 return ret;
544 s->io_repositioned = 1;
545 avpriv_update_cur_dts(s, st, ie->timestamp);
546 } else {
547 if ((ret = avio_seek(s->pb, si->data_offset, SEEK_SET)) < 0)
548 return ret;
549 s->io_repositioned = 1;
550 }
551 av_packet_unref(pkt);
552 for (;;) {
553 int read_status;
554 do {
555 read_status = av_read_frame(s, pkt);
556 } while (read_status == AVERROR(EAGAIN));
557 if (read_status < 0)
558 break;
559 if (stream_index == pkt->stream_index && pkt->dts > timestamp) {
560 if (pkt->flags & AV_PKT_FLAG_KEY) {
561 av_packet_unref(pkt);
562 break;
563 }
564 if (nonkey++ > 1000 && st->codecpar->codec_id != AV_CODEC_ID_CDGRAPHICS) {
565 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);
566 av_packet_unref(pkt);
567 break;
568 }
569 }
570 av_packet_unref(pkt);
571 }
572 index = av_index_search_timestamp(st, timestamp, flags);
573 }
574 if (index < 0)
575 return -1;
576
577 ff_read_frame_flush(s);
578 if (s->iformat->read_seek)
579 if (s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0)
580 return 0;
581 ie = &sti->index_entries[index];
582 if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
583 return ret;
584 s->io_repositioned = 1;
585 avpriv_update_cur_dts(s, st, ie->timestamp);
586
587 return 0;
588 }
589
seek_frame_internal(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)590 static int seek_frame_internal(AVFormatContext *s, int stream_index,
591 int64_t timestamp, int flags)
592 {
593 AVStream *st;
594 int ret;
595
596 if (flags & AVSEEK_FLAG_BYTE) {
597 if (s->iformat->flags & AVFMT_NO_BYTE_SEEK)
598 return -1;
599 ff_read_frame_flush(s);
600 return seek_frame_byte(s, stream_index, timestamp, flags);
601 }
602
603 if (stream_index < 0) {
604 stream_index = av_find_default_stream_index(s);
605 if (stream_index < 0)
606 return -1;
607
608 st = s->streams[stream_index];
609 /* timestamp for default must be expressed in AV_TIME_BASE units */
610 timestamp = av_rescale(timestamp, st->time_base.den,
611 AV_TIME_BASE * (int64_t) st->time_base.num);
612 }
613
614 /* first, we try the format specific seek */
615 if (s->iformat->read_seek) {
616 ff_read_frame_flush(s);
617 ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
618 } else
619 ret = -1;
620 if (ret >= 0)
621 return 0;
622
623 if (s->iformat->read_timestamp &&
624 !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
625 ff_read_frame_flush(s);
626 return ff_seek_frame_binary(s, stream_index, timestamp, flags);
627 } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
628 ff_read_frame_flush(s);
629 return seek_frame_generic(s, stream_index, timestamp, flags);
630 } else
631 return -1;
632 }
633
av_seek_frame(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)634 int av_seek_frame(AVFormatContext *s, int stream_index,
635 int64_t timestamp, int flags)
636 {
637 int ret;
638
639 if (s->iformat->read_seek2 && !s->iformat->read_seek) {
640 int64_t min_ts = INT64_MIN, max_ts = INT64_MAX;
641 if ((flags & AVSEEK_FLAG_BACKWARD))
642 max_ts = timestamp;
643 else
644 min_ts = timestamp;
645 return avformat_seek_file(s, stream_index, min_ts, timestamp, max_ts,
646 flags & ~AVSEEK_FLAG_BACKWARD);
647 }
648
649 ret = seek_frame_internal(s, stream_index, timestamp, flags);
650
651 if (ret >= 0)
652 ret = avformat_queue_attached_pictures(s);
653
654 return ret;
655 }
656
avformat_seek_file(AVFormatContext * s,int stream_index,int64_t min_ts,int64_t ts,int64_t max_ts,int flags)657 int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts,
658 int64_t ts, int64_t max_ts, int flags)
659 {
660 if (min_ts > ts || max_ts < ts)
661 return -1;
662 if (stream_index < -1 || stream_index >= (int)s->nb_streams)
663 return AVERROR(EINVAL);
664
665 if (s->seek2any > 0)
666 flags |= AVSEEK_FLAG_ANY;
667 flags &= ~AVSEEK_FLAG_BACKWARD;
668
669 if (s->iformat->read_seek2) {
670 int ret;
671 ff_read_frame_flush(s);
672
673 if (stream_index == -1 && s->nb_streams == 1) {
674 AVRational time_base = s->streams[0]->time_base;
675 ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base);
676 min_ts = av_rescale_rnd(min_ts, time_base.den,
677 time_base.num * (int64_t)AV_TIME_BASE,
678 AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
679 max_ts = av_rescale_rnd(max_ts, time_base.den,
680 time_base.num * (int64_t)AV_TIME_BASE,
681 AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
682 stream_index = 0;
683 }
684
685 ret = s->iformat->read_seek2(s, stream_index, min_ts,
686 ts, max_ts, flags);
687
688 if (ret >= 0)
689 ret = avformat_queue_attached_pictures(s);
690 return ret;
691 }
692
693 if (s->iformat->read_timestamp) {
694 // try to seek via read_timestamp()
695 }
696
697 // Fall back on old API if new is not implemented but old is.
698 // Note the old API has somewhat different semantics.
699 if (s->iformat->read_seek || 1) {
700 int dir = (ts - (uint64_t)min_ts > (uint64_t)max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0);
701 int ret = av_seek_frame(s, stream_index, ts, flags | dir);
702 if (ret < 0 && ts != min_ts && max_ts != ts) {
703 ret = av_seek_frame(s, stream_index, dir ? max_ts : min_ts, flags | dir);
704 if (ret >= 0)
705 ret = av_seek_frame(s, stream_index, ts, flags | (dir^AVSEEK_FLAG_BACKWARD));
706 }
707 return ret;
708 }
709
710 // try some generic seek like seek_frame_generic() but with new ts semantics
711 return -1; //unreachable
712 }
713
714 /** Flush the frame reader. */
ff_read_frame_flush(AVFormatContext * s)715 void ff_read_frame_flush(AVFormatContext *s)
716 {
717 FFFormatContext *const si = ffformatcontext(s);
718
719 ff_flush_packet_queue(s);
720
721 /* Reset read state for each stream. */
722 for (unsigned i = 0; i < s->nb_streams; i++) {
723 AVStream *const st = s->streams[i];
724 FFStream *const sti = ffstream(st);
725
726 if (sti->parser) {
727 av_parser_close(sti->parser);
728 sti->parser = NULL;
729 }
730 sti->last_IP_pts = AV_NOPTS_VALUE;
731 sti->last_dts_for_order_check = AV_NOPTS_VALUE;
732 if (sti->first_dts == AV_NOPTS_VALUE)
733 sti->cur_dts = RELATIVE_TS_BASE;
734 else
735 /* We set the current DTS to an unspecified origin. */
736 sti->cur_dts = AV_NOPTS_VALUE;
737
738 sti->probe_packets = s->max_probe_packets;
739
740 for (int j = 0; j < MAX_REORDER_DELAY + 1; j++)
741 sti->pts_buffer[j] = AV_NOPTS_VALUE;
742
743 if (si->inject_global_side_data)
744 sti->inject_global_side_data = 1;
745
746 sti->skip_samples = 0;
747 }
748 }
749
avformat_flush(AVFormatContext * s)750 int avformat_flush(AVFormatContext *s)
751 {
752 ff_read_frame_flush(s);
753 return 0;
754 }
755
ff_rescale_interval(AVRational tb_in,AVRational tb_out,int64_t * min_ts,int64_t * ts,int64_t * max_ts)756 void ff_rescale_interval(AVRational tb_in, AVRational tb_out,
757 int64_t *min_ts, int64_t *ts, int64_t *max_ts)
758 {
759 *ts = av_rescale_q (* ts, tb_in, tb_out);
760 *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out,
761 AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
762 *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out,
763 AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
764 }
765