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 33void 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 46void 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 60int 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 118int 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 128int 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 171void 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 238int 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 245int avformat_index_get_entries_count(const AVStream *st) 246{ 247 return cffstream(st)->nb_index_entries; 248} 249 250const 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 259const 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 274static 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 283int 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 353int 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 391int64_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 498static 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 519static 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 590static 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 634int 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 657int 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. */ 715void 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 750int avformat_flush(AVFormatContext *s) 751{ 752 ff_read_frame_flush(s); 753 return 0; 754} 755 756void 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