FFmpeg coverage


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