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