FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/seek.c
Date: 2024-02-16 17:37:06
Exec Total Coverage
Lines: 321 421 76.2%
Functions: 17 22 77.3%
Branches: 182 286 63.6%

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