../../../ffmpeg/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
365 / 460
79.3%
Branches:
226 / 326
69.3%
Functions:
20 / 25
80.0%

libavformat/seek.c
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 "avformat_internal.h"
33 #include "avio_internal.h"
34 #include "demux.h"
35 #include "internal.h"
36
37 1347 void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
38 {
39
2/2
✓ Branch 5 → 3 taken 1660 times.
✓ Branch 5 → 6 taken 1347 times.
3007 for (unsigned i = 0; i < s->nb_streams; i++) {
40 1660 AVStream *const st = s->streams[i];
41 1660 FFStream *const sti = ffstream(st);
42
43 1660 sti->cur_dts =
44 1660 av_rescale(timestamp,
45 1660 st->time_base.den * (int64_t) ref_st->time_base.num,
46 1660 st->time_base.num * (int64_t) ref_st->time_base.den);
47 }
48 1347 }
49
50 322271 void ff_reduce_index(AVFormatContext *s, int stream_index)
51 {
52 322271 AVStream *const st = s->streams[stream_index];
53 322271 FFStream *const sti = ffstream(st);
54 322271 unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry);
55
56
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 8 taken 322271 times.
322271 if ((unsigned) sti->nb_index_entries >= max_entries) {
57 int i;
58
0/2
✗ Branch 6 → 5 not taken.
✗ Branch 6 → 7 not taken.
✗ for (i = 0; 2 * i < sti->nb_index_entries; i++)
59 ✗ sti->index_entries[i] = sti->index_entries[2 * i];
60 ✗ sti->nb_index_entries = i;
61 }
62 322271 }
63
64 384091 int ff_add_index_entry(AVIndexEntry **index_entries,
65 int *nb_index_entries,
66 unsigned int *index_entries_allocated_size,
67 int64_t pos, int64_t timestamp,
68 int size, int distance, int flags)
69 {
70 AVIndexEntry *entries, *ie;
71 int index;
72
73
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 384091 times.
384091 if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
74 ✗ return -1;
75
76
2/2
✓ Branch 4 → 5 taken 2538 times.
✓ Branch 4 → 6 taken 381553 times.
384091 if (timestamp == AV_NOPTS_VALUE)
77 2538 return AVERROR(EINVAL);
78
79
2/4
✓ Branch 6 → 7 taken 381553 times.
✗ Branch 6 → 8 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 381553 times.
381553 if (size < 0 || size > 0x3FFFFFFF)
80 ✗ return AVERROR(EINVAL);
81
82
2/2
✓ Branch 10 → 11 taken 155737 times.
✓ Branch 10 → 12 taken 225816 times.
381553 if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known
83 155737 timestamp -= RELATIVE_TS_BASE;
84
85 381553 entries = av_fast_realloc(*index_entries,
86 index_entries_allocated_size,
87 381553 (*nb_index_entries + 1) *
88 sizeof(AVIndexEntry));
89
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 381553 times.
381553 if (!entries)
90 ✗ return -1;
91
92 381553 *index_entries = entries;
93
94 381553 index = ff_index_search_timestamp(*index_entries, *nb_index_entries,
95 timestamp, AVSEEK_FLAG_ANY);
96
2/2
✓ Branch 16 → 17 taken 279400 times.
✓ Branch 16 → 21 taken 102153 times.
381553 if (index < 0) {
97 279400 index = (*nb_index_entries)++;
98 279400 ie = &entries[index];
99
3/4
✓ Branch 17 → 18 taken 272831 times.
✓ Branch 17 → 28 taken 6569 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 28 taken 272831 times.
279400 av_assert0(index == 0 || ie[-1].timestamp < timestamp);
100 } else {
101 102153 ie = &entries[index];
102
2/2
✓ Branch 21 → 22 taken 3524 times.
✓ Branch 21 → 25 taken 98629 times.
102153 if (ie->timestamp != timestamp) {
103
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 3524 times.
3524 if (ie->timestamp <= timestamp)
104 ✗ return -1;
105 3524 memmove(entries + index + 1, entries + index,
106 3524 sizeof(AVIndexEntry) * (*nb_index_entries - index));
107 3524 (*nb_index_entries)++;
108
4/4
✓ Branch 25 → 26 taken 97148 times.
✓ Branch 25 → 28 taken 1481 times.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 28 taken 97146 times.
98629 } else if (ie->pos == pos && distance < ie->min_distance)
109 // do not reduce the distance
110 2 distance = ie->min_distance;
111 }
112
113 381553 ie->pos = pos;
114 381553 ie->timestamp = timestamp;
115 381553 ie->min_distance = distance;
116 381553 ie->size = size;
117 381553 ie->flags = flags;
118
119 381553 return index;
120 }
121
122 383770 int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
123 int size, int distance, int flags)
124 {
125 383770 FFStream *const sti = ffstream(st);
126 383770 timestamp = ff_wrap_timestamp(st, timestamp);
127 383770 return ff_add_index_entry(&sti->index_entries, &sti->nb_index_entries,
128 &sti->index_entries_allocated_size, pos,
129 timestamp, size, distance, flags);
130 }
131
132 417879 int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries,
133 int64_t wanted_timestamp, int flags)
134 {
135 int a, b, m;
136 int64_t timestamp;
137
138 417879 a = -1;
139 417879 b = nb_entries;
140
141 // Optimize appending index entries at the end.
142
4/4
✓ Branch 2 → 3 taken 408146 times.
✓ Branch 2 → 5 taken 9733 times.
✓ Branch 3 → 4 taken 277943 times.
✓ Branch 3 → 5 taken 130203 times.
417879 if (b && entries[b - 1].timestamp < wanted_timestamp)
143 277943 a = b - 1;
144
145
2/2
✓ Branch 19 → 6 taken 811859 times.
✓ Branch 19 → 20 taken 417879 times.
1229738 while (b - a > 1) {
146 811859 m = (a + b) >> 1;
147
148 // Search for the next non-discarded packet.
149
4/6
✓ Branch 11 → 12 taken 18 times.
✓ Branch 11 → 14 taken 811847 times.
✓ Branch 12 → 13 taken 18 times.
✗ Branch 12 → 14 not taken.
✓ Branch 13 → 7 taken 18 times.
✗ Branch 13 → 14 not taken.
811865 while ((entries[m].flags & AVINDEX_DISCARD_FRAME) && m < b && m < nb_entries - 1) {
150 18 m++;
151
3/4
✓ Branch 7 → 8 taken 12 times.
✓ Branch 7 → 10 taken 6 times.
✓ Branch 8 → 9 taken 12 times.
✗ Branch 8 → 10 not taken.
18 if (m == b && entries[m].timestamp >= wanted_timestamp) {
152 12 m = b - 1;
153 12 break;
154 }
155 }
156
157 811859 timestamp = entries[m].timestamp;
158
2/2
✓ Branch 14 → 15 taken 244450 times.
✓ Branch 14 → 16 taken 567409 times.
811859 if (timestamp >= wanted_timestamp)
159 244450 b = m;
160
2/2
✓ Branch 16 → 17 taken 690872 times.
✓ Branch 16 → 18 taken 120987 times.
811859 if (timestamp <= wanted_timestamp)
161 690872 a = m;
162 }
163
2/2
✓ Branch 20 → 21 taken 10022 times.
✓ Branch 20 → 22 taken 407857 times.
417879 m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
164
165
2/2
✓ Branch 23 → 24 taken 11887 times.
✓ Branch 23 → 32 taken 405992 times.
417879 if (!(flags & AVSEEK_FLAG_ANY))
166
4/4
✓ Branch 29 → 30 taken 11299 times.
✓ Branch 29 → 32 taken 3515 times.
✓ Branch 30 → 31 taken 10158 times.
✓ Branch 30 → 32 taken 1141 times.
14814 while (m >= 0 && m < nb_entries &&
167
2/2
✓ Branch 31 → 25 taken 2927 times.
✓ Branch 31 → 32 taken 7231 times.
10158 !(entries[m].flags & AVINDEX_KEYFRAME))
168
2/2
✓ Branch 25 → 26 taken 1861 times.
✓ Branch 25 → 27 taken 1066 times.
2927 m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
169
170
2/2
✓ Branch 32 → 33 taken 280654 times.
✓ Branch 32 → 34 taken 137225 times.
417879 if (m == nb_entries)
171 280654 return -1;
172 137225 return m;
173 }
174
175 680 void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
176 {
177 680 int64_t pos_delta = 0;
178 680 int64_t skip = 0;
179 //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable
180 680 const char *proto = avio_find_protocol_name(s->url);
181 FFIOContext *ctx;
182
183
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 680 times.
680 av_assert0(time_tolerance >= 0);
184
185
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 680 times.
680 if (!proto) {
186 ✗ av_log(s, AV_LOG_INFO,
187 "Protocol name not provided, cannot determine if input is local or "
188 "a network protocol, buffers and access patterns cannot be configured "
189 "optimally without knowing the protocol\n");
190 }
191
192
2/8
✓ Branch 8 → 9 taken 680 times.
✗ Branch 8 → 13 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 680 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 13 not taken.
680 if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))
193 680 return;
194
195
0/2
✗ Branch 37 → 14 not taken.
✗ Branch 37 → 38 not taken.
✗ for (unsigned ist1 = 0; ist1 < s->nb_streams; ist1++) {
196 ✗ AVStream *const st1 = s->streams[ist1];
197 ✗ FFStream *const sti1 = ffstream(st1);
198
0/2
✗ Branch 35 → 16 not taken.
✗ Branch 35 → 36 not taken.
✗ for (unsigned ist2 = 0; ist2 < s->nb_streams; ist2++) {
199 ✗ AVStream *const st2 = s->streams[ist2];
200 ✗ FFStream *const sti2 = ffstream(st2);
201
202
0/2
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
✗ if (ist1 == ist2)
203 ✗ continue;
204
205
0/2
✗ Branch 33 → 20 not taken.
✗ Branch 33 → 34 not taken.
✗ for (int i1 = 0, i2 = 0; i1 < sti1->nb_index_entries; i1++) {
206 ✗ const AVIndexEntry *const e1 = &sti1->index_entries[i1];
207 ✗ int64_t e1_pts = av_rescale_q(e1->timestamp, st1->time_base, AV_TIME_BASE_Q);
208
209
0/2
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 22 not taken.
✗ if (e1->size < (1 << 23))
210 ✗ skip = FFMAX(skip, e1->size);
211
212
0/2
✗ Branch 31 → 23 not taken.
✗ Branch 31 → 32 not taken.
✗ for (; i2 < sti2->nb_index_entries; i2++) {
213 ✗ const AVIndexEntry *const e2 = &sti2->index_entries[i2];
214 ✗ int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q);
215 int64_t cur_delta;
216
0/4
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
✗ if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance)
217 ✗ continue;
218 ✗ cur_delta = FFABS(e1->pos - e2->pos);
219
0/2
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
✗ if (cur_delta < (1 << 23))
220 ✗ pos_delta = FFMAX(pos_delta, cur_delta);
221 ✗ break;
222 }
223 }
224 }
225 }
226
227 ✗ pos_delta *= 2;
228 ✗ ctx = ffiocontext(s->pb);
229 /* XXX This could be adjusted depending on protocol*/
230
0/2
✗ Branch 39 → 40 not taken.
✗ Branch 39 → 46 not taken.
✗ if (s->pb->buffer_size < pos_delta) {
231 ✗ av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);
232
233 /* realloc the buffer and the original data will be retained */
234
0/2
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 45 not taken.
✗ if (ffio_realloc_buf(s->pb, pos_delta)) {
235 ✗ av_log(s, AV_LOG_ERROR, "Realloc buffer fail.\n");
236 ✗ return;
237 }
238
239 ✗ ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, pos_delta/2);
240 }
241
242 ✗ ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip);
243 }
244
245 36245 int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
246 {
247 36245 const FFStream *const sti = ffstream(st);
248 36245 return ff_index_search_timestamp(sti->index_entries, sti->nb_index_entries,
249 wanted_timestamp, flags);
250 }
251
252 ✗ int avformat_index_get_entries_count(const AVStream *st)
253 {
254 ✗ return cffstream(st)->nb_index_entries;
255 }
256
257 ✗ const AVIndexEntry *avformat_index_get_entry(AVStream *st, int idx)
258 {
259 ✗ const FFStream *const sti = ffstream(st);
260
0/4
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✗ if (idx < 0 || idx >= sti->nb_index_entries)
261 ✗ return NULL;
262
263 ✗ return &sti->index_entries[idx];
264 }
265
266 ✗ const AVIndexEntry *avformat_index_get_entry_from_timestamp(AVStream *st,
267 int64_t wanted_timestamp,
268 int flags)
269 {
270 ✗ const FFStream *const sti = ffstream(st);
271 ✗ int idx = ff_index_search_timestamp(sti->index_entries,
272 ✗ sti->nb_index_entries,
273 wanted_timestamp, flags);
274
275
0/2
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✗ if (idx < 0)
276 ✗ return NULL;
277
278 ✗ return &sti->index_entries[idx];
279 }
280
281 833 static int64_t read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit,
282 int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t ))
283 {
284 833 int64_t ts = read_timestamp(s, stream_index, ppos, pos_limit);
285
1/2
✓ Branch 3 → 4 taken 833 times.
✗ Branch 3 → 5 not taken.
833 if (stream_index >= 0)
286 833 ts = ff_wrap_timestamp(s->streams[stream_index], ts);
287 833 return ts;
288 }
289
290 214 int ff_seek_frame_binary(AVFormatContext *s, int stream_index,
291 int64_t target_ts, int flags)
292 {
293 214 const FFInputFormat *const avif = ffifmt(s->iformat);
294 214 int64_t pos_min = 0, pos_max = 0, pos, pos_limit;
295 int64_t ts_min, ts_max, ts;
296 int index;
297 int64_t ret;
298 AVStream *st;
299 FFStream *sti;
300
301
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 214 times.
214 if (stream_index < 0)
302 ✗ return -1;
303
304 214 av_log(s, AV_LOG_TRACE, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
305
306 214 ts_max =
307 214 ts_min = AV_NOPTS_VALUE;
308 214 pos_limit = -1; // GCC falsely says it may be uninitialized.
309
310 214 st = s->streams[stream_index];
311 214 sti = ffstream(st);
312
2/2
✓ Branch 8 → 9 taken 202 times.
✓ Branch 8 → 23 taken 12 times.
214 if (sti->index_entries) {
313 const AVIndexEntry *e;
314
315 /* FIXME: Whole function must be checked for non-keyframe entries in
316 * index case, especially read_timestamp(). */
317 202 index = av_index_search_timestamp(st, target_ts,
318 flags | AVSEEK_FLAG_BACKWARD);
319 202 index = FFMAX(index, 0);
320 202 e = &sti->index_entries[index];
321
322
3/4
✓ Branch 10 → 11 taken 71 times.
✓ Branch 10 → 12 taken 131 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 15 taken 71 times.
202 if (e->timestamp <= target_ts || e->pos == e->min_distance) {
323 131 pos_min = e->pos;
324 131 ts_min = e->timestamp;
325 131 av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
326 131 pos_min, av_ts2str(ts_min));
327 } else {
328 av_assert1(index == 0);
329 }
330
331 202 index = av_index_search_timestamp(st, target_ts,
332 flags & ~AVSEEK_FLAG_BACKWARD);
333
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 19 taken 202 times.
202 av_assert0(index < sti->nb_index_entries);
334
2/2
✓ Branch 19 → 20 taken 124 times.
✓ Branch 19 → 23 taken 78 times.
202 if (index >= 0) {
335 124 e = &sti->index_entries[index];
336 av_assert1(e->timestamp >= target_ts);
337 124 pos_max = e->pos;
338 124 ts_max = e->timestamp;
339 124 pos_limit = pos_max - e->min_distance;
340 124 av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64
341 124 " dts_max=%s\n", pos_max, pos_limit, av_ts2str(ts_max));
342 }
343 }
344
345 214 pos = ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit,
346 214 ts_min, ts_max, flags, &ts, avif->read_timestamp);
347
2/2
✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 26 taken 212 times.
214 if (pos < 0)
348 2 return -1;
349
350 /* do the seek */
351
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 212 times.
212 if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0)
352 ✗ return ret;
353
354 212 ff_read_frame_flush(s);
355 212 avpriv_update_cur_dts(s, st, ts);
356
357 212 return 0;
358 }
359
360 89 int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos,
361 int64_t (*read_timestamp_func)(struct AVFormatContext *, int , int64_t *, int64_t ))
362 {
363 89 int64_t step = 1024;
364 int64_t limit, ts_max;
365 89 int64_t filesize = avio_size(s->pb);
366 89 int64_t pos_max = filesize - 1;
367 do {
368 386 limit = pos_max;
369 386 pos_max = FFMAX(0, (pos_max) - step);
370 386 ts_max = read_timestamp(s, stream_index,
371 &pos_max, limit, read_timestamp_func);
372 386 step += step;
373
3/4
✓ Branch 5 → 6 taken 297 times.
✓ Branch 5 → 8 taken 89 times.
✓ Branch 6 → 7 taken 297 times.
✗ Branch 6 → 8 not taken.
386 } while (ts_max == AV_NOPTS_VALUE && 2*limit > step);
374
1/2
✓ Branch 8 → 9 taken 89 times.
✗ Branch 8 → 10 not taken.
89 if (ts_max == AV_NOPTS_VALUE)
375 ✗ return -1;
376
377 22 for (;;) {
378 111 int64_t tmp_pos = pos_max + 1;
379 111 int64_t tmp_ts = read_timestamp(s, stream_index,
380 &tmp_pos, INT64_MAX, read_timestamp_func);
381
2/2
✓ Branch 12 → 13 taken 89 times.
✓ Branch 12 → 14 taken 22 times.
111 if (tmp_ts == AV_NOPTS_VALUE)
382 89 break;
383
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 17 taken 22 times.
22 av_assert0(tmp_pos > pos_max);
384 22 ts_max = tmp_ts;
385 22 pos_max = tmp_pos;
386
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 22 times.
22 if (tmp_pos >= filesize)
387 ✗ break;
388 }
389
390
1/2
✓ Branch 20 → 21 taken 89 times.
✗ Branch 20 → 22 not taken.
89 if (ts)
391 89 *ts = ts_max;
392
1/2
✓ Branch 22 → 23 taken 89 times.
✗ Branch 22 → 24 not taken.
89 if (pos)
393 89 *pos = pos_max;
394
395 89 return 0;
396 }
397
398 214 int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
399 int64_t pos_min, int64_t pos_max, int64_t pos_limit,
400 int64_t ts_min, int64_t ts_max,
401 int flags, int64_t *ts_ret,
402 int64_t (*read_timestamp_func)(struct AVFormatContext *,
403 int, int64_t *, int64_t))
404 {
405 214 FFFormatContext *const si = ffformatcontext(s);
406 int64_t pos, ts;
407 int64_t start_pos;
408 int no_change;
409 int ret;
410
411 214 av_log(s, AV_LOG_TRACE, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
412
413
2/2
✓ Branch 5 → 6 taken 83 times.
✓ Branch 5 → 9 taken 131 times.
214 if (ts_min == AV_NOPTS_VALUE) {
414 83 pos_min = si->data_offset;
415 83 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
416
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 83 times.
83 if (ts_min == AV_NOPTS_VALUE)
417 ✗ return -1;
418 }
419
420
2/2
✓ Branch 9 → 10 taken 71 times.
✓ Branch 9 → 11 taken 143 times.
214 if (ts_min >= target_ts) {
421 71 *ts_ret = ts_min;
422 71 return pos_min;
423 }
424
425
2/2
✓ Branch 11 → 12 taken 89 times.
✓ Branch 11 → 16 taken 54 times.
143 if (ts_max == AV_NOPTS_VALUE) {
426
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 89 times.
89 if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp_func)) < 0)
427 ✗ return ret;
428 89 pos_limit = pos_max;
429 }
430
431
2/2
✓ Branch 16 → 17 taken 73 times.
✓ Branch 16 → 18 taken 70 times.
143 if (ts_max <= target_ts) {
432 73 *ts_ret = ts_max;
433 73 return pos_max;
434 }
435
436
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 21 taken 70 times.
70 av_assert0(ts_min < ts_max);
437
438 70 no_change = 0;
439
2/2
✓ Branch 54 → 22 taken 253 times.
✓ Branch 54 → 55 taken 68 times.
321 while (pos_min < pos_limit) {
440 253 av_log(s, AV_LOG_TRACE,
441 "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
442 253 pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
443
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 28 taken 253 times.
253 av_assert0(pos_limit <= pos_max);
444
445
2/2
✓ Branch 28 → 29 taken 138 times.
✓ Branch 28 → 30 taken 115 times.
253 if (no_change == 0) {
446 138 int64_t approximate_keyframe_distance = pos_max - pos_limit;
447 // interpolate position (better than dichotomy)
448 138 pos = av_rescale(target_ts - ts_min, pos_max - pos_min,
449 138 ts_max - ts_min) +
450 138 pos_min - approximate_keyframe_distance;
451
2/2
✓ Branch 30 → 31 taken 68 times.
✓ Branch 30 → 32 taken 47 times.
115 } else if (no_change == 1) {
452 // bisection if interpolation did not change min / max pos last time
453 68 pos = (pos_min + pos_limit) >> 1;
454 } else {
455 /* linear search if bisection failed, can only happen if there
456 * are very few or no keyframes between min/max */
457 47 pos = pos_min;
458 }
459
2/2
✓ Branch 33 → 34 taken 66 times.
✓ Branch 33 → 35 taken 187 times.
253 if (pos <= pos_min)
460 66 pos = pos_min + 1;
461
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 187 times.
187 else if (pos > pos_limit)
462 ✗ pos = pos_limit;
463 253 start_pos = pos;
464
465 // May pass pos_limit instead of -1.
466 253 ts = read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp_func);
467
2/2
✓ Branch 38 → 39 taken 177 times.
✓ Branch 38 → 40 taken 76 times.
253 if (pos == pos_max)
468 177 no_change++;
469 else
470 76 no_change = 0;
471 253 av_log(s, AV_LOG_TRACE, "%"PRId64" %"PRId64" %"PRId64" / %s %s %s"
472 " target:%s limit:%"PRId64" start:%"PRId64" noc:%d\n",
473 pos_min, pos, pos_max,
474 253 av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
475 pos_limit, start_pos, no_change);
476
2/2
✓ Branch 46 → 47 taken 2 times.
✓ Branch 46 → 49 taken 251 times.
253 if (ts == AV_NOPTS_VALUE) {
477 2 av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
478 2 return -1;
479 }
480
2/2
✓ Branch 49 → 50 taken 216 times.
✓ Branch 49 → 51 taken 35 times.
251 if (target_ts <= ts) {
481 216 pos_limit = start_pos - 1;
482 216 pos_max = pos;
483 216 ts_max = ts;
484 }
485
2/2
✓ Branch 51 → 52 taken 37 times.
✓ Branch 51 → 53 taken 214 times.
251 if (target_ts >= ts) {
486 37 pos_min = pos;
487 37 ts_min = ts;
488 }
489 }
490
491
2/2
✓ Branch 55 → 56 taken 38 times.
✓ Branch 55 → 57 taken 30 times.
68 pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
492
2/2
✓ Branch 58 → 59 taken 38 times.
✓ Branch 58 → 60 taken 30 times.
68 ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
493 #if 0
494 pos_min = pos;
495 ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
496 pos_min++;
497 ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
498 av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" %s<=%s<=%s\n",
499 pos, av_ts2str(ts_min), av_ts2str(target_ts), av_ts2str(ts_max));
500 #endif
501 68 *ts_ret = ts;
502 68 return pos;
503 }
504
505 ✗ static int seek_frame_byte(AVFormatContext *s, int stream_index,
506 int64_t pos, int flags)
507 {
508 ✗ FFFormatContext *const si = ffformatcontext(s);
509 int64_t pos_min, pos_max;
510
511 ✗ pos_min = si->data_offset;
512 ✗ pos_max = avio_size(s->pb) - 1;
513
514
0/2
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✗ if (pos < pos_min)
515 ✗ pos = pos_min;
516
0/2
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
✗ else if (pos > pos_max)
517 ✗ pos = pos_max;
518
519 ✗ avio_seek(s->pb, pos, SEEK_SET);
520
521 ✗ s->io_repositioned = 1;
522
523 ✗ return 0;
524 }
525
526 1213 static int seek_frame_generic(AVFormatContext *s, int stream_index,
527 int64_t timestamp, int flags)
528 {
529 1213 FFFormatContext *const si = ffformatcontext(s);
530 1213 AVStream *const st = s->streams[stream_index];
531 1213 FFStream *const sti = ffstream(st);
532 const AVIndexEntry *ie;
533 int index;
534 int64_t ret;
535
536 1213 index = av_index_search_timestamp(st, timestamp, flags);
537
538
4/4
✓ Branch 5 → 6 taken 727 times.
✓ Branch 5 → 9 taken 486 times.
✓ Branch 6 → 7 taken 463 times.
✓ Branch 6 → 9 taken 264 times.
1213 if (index < 0 && sti->nb_index_entries &&
539
2/2
✓ Branch 7 → 8 taken 222 times.
✓ Branch 7 → 9 taken 241 times.
463 timestamp < sti->index_entries[0].timestamp)
540 222 return -1;
541
542
4/4
✓ Branch 9 → 10 taken 486 times.
✓ Branch 9 → 11 taken 505 times.
✓ Branch 10 → 11 taken 169 times.
✓ Branch 10 → 43 taken 317 times.
991 if (index < 0 || index == sti->nb_index_entries - 1) {
543 674 AVPacket *const pkt = si->pkt;
544 674 int nonkey = 0;
545
546
2/2
✓ Branch 11 → 12 taken 410 times.
✓ Branch 11 → 19 taken 264 times.
674 if (sti->nb_index_entries) {
547
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 15 taken 410 times.
410 av_assert0(sti->index_entries);
548 410 ie = &sti->index_entries[sti->nb_index_entries - 1];
549
2/2
✓ Branch 16 → 17 taken 33 times.
✓ Branch 16 → 18 taken 377 times.
410 if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
550 33 return ret;
551 377 s->io_repositioned = 1;
552 377 avpriv_update_cur_dts(s, st, ie->timestamp);
553 } else {
554
2/2
✓ Branch 20 → 21 taken 184 times.
✓ Branch 20 → 22 taken 80 times.
264 if ((ret = avio_seek(s->pb, si->data_offset, SEEK_SET)) < 0)
555 184 return ret;
556 80 s->io_repositioned = 1;
557 }
558 457 av_packet_unref(pkt);
559 5137 for (;;) {
560 int read_status;
561 do {
562 5594 read_status = av_read_frame(s, pkt);
563
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 5594 times.
5594 } while (read_status == AVERROR(EAGAIN));
564
2/2
✓ Branch 28 → 29 taken 384 times.
✓ Branch 28 → 30 taken 5210 times.
5594 if (read_status < 0)
565 384 break;
566
4/4
✓ Branch 30 → 31 taken 4547 times.
✓ Branch 30 → 39 taken 663 times.
✓ Branch 31 → 32 taken 1178 times.
✓ Branch 31 → 39 taken 3369 times.
5210 if (stream_index == pkt->stream_index && pkt->dts > timestamp) {
567
2/2
✓ Branch 32 → 33 taken 73 times.
✓ Branch 32 → 34 taken 1105 times.
1178 if (pkt->flags & AV_PKT_FLAG_KEY) {
568 73 av_packet_unref(pkt);
569 73 break;
570 }
571
1/4
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 39 taken 1105 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 39 not taken.
1105 if (nonkey++ > 1000 && st->codecpar->codec_id != AV_CODEC_ID_CDGRAPHICS) {
572 ✗ 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);
573 ✗ av_packet_unref(pkt);
574 ✗ break;
575 }
576 }
577 5137 av_packet_unref(pkt);
578 }
579 457 index = av_index_search_timestamp(st, timestamp, flags);
580 }
581
2/2
✓ Branch 43 → 44 taken 284 times.
✓ Branch 43 → 45 taken 490 times.
774 if (index < 0)
582 284 return -1;
583
584 490 ff_read_frame_flush(s);
585
2/2
✓ Branch 47 → 48 taken 203 times.
✓ Branch 47 → 52 taken 287 times.
490 if (ffifmt(s->iformat)->read_seek)
586
1/2
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 203 times.
203 if (ffifmt(s->iformat)->read_seek(s, stream_index, timestamp, flags) >= 0)
587 ✗ return 0;
588 490 ie = &sti->index_entries[index];
589
2/2
✓ Branch 53 → 54 taken 21 times.
✓ Branch 53 → 55 taken 469 times.
490 if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
590 21 return ret;
591 469 s->io_repositioned = 1;
592 469 avpriv_update_cur_dts(s, st, ie->timestamp);
593
594 469 return 0;
595 }
596
597 3600 static int seek_frame_internal(AVFormatContext *s, int stream_index,
598 int64_t timestamp, int flags)
599 {
600 AVStream *st;
601 int ret;
602
603
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 8 taken 3600 times.
3600 if (flags & AVSEEK_FLAG_BYTE) {
604
0/2
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ if (s->iformat->flags & AVFMT_NO_BYTE_SEEK)
605 ✗ return -1;
606 ✗ ff_read_frame_flush(s);
607 ✗ return seek_frame_byte(s, stream_index, timestamp, flags);
608 }
609
610
2/2
✓ Branch 8 → 9 taken 1906 times.
✓ Branch 8 → 13 taken 1694 times.
3600 if (stream_index < 0) {
611 1906 stream_index = av_find_default_stream_index(s);
612
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1906 times.
1906 if (stream_index < 0)
613 ✗ return -1;
614
615 1906 st = s->streams[stream_index];
616 /* timestamp for default must be expressed in AV_TIME_BASE units */
617 1906 timestamp = av_rescale(timestamp, st->time_base.den,
618 1906 AV_TIME_BASE * (int64_t) st->time_base.num);
619 }
620
621 /* first, we try the format specific seek */
622
2/2
✓ Branch 14 → 15 taken 3031 times.
✓ Branch 14 → 18 taken 569 times.
3600 if (ffifmt(s->iformat)->read_seek) {
623 3031 ff_read_frame_flush(s);
624 3031 ret = ffifmt(s->iformat)->read_seek(s, stream_index, timestamp, flags);
625 } else
626 569 ret = -1;
627
2/2
✓ Branch 19 → 20 taken 2287 times.
✓ Branch 19 → 21 taken 1313 times.
3600 if (ret >= 0)
628 2287 return 0;
629
630
2/2
✓ Branch 22 → 23 taken 95 times.
✓ Branch 22 → 27 taken 1218 times.
1313 if (ffifmt(s->iformat)->read_timestamp &&
631
1/2
✓ Branch 23 → 24 taken 95 times.
✗ Branch 23 → 27 not taken.
95 !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
632 95 ff_read_frame_flush(s);
633 95 return ff_seek_frame_binary(s, stream_index, timestamp, flags);
634
2/2
✓ Branch 27 → 28 taken 1213 times.
✓ Branch 27 → 31 taken 5 times.
1218 } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
635 1213 ff_read_frame_flush(s);
636 1213 return seek_frame_generic(s, stream_index, timestamp, flags);
637 } else
638 5 return -1;
639 }
640
641 3600 int av_seek_frame(AVFormatContext *s, int stream_index,
642 int64_t timestamp, int flags)
643 {
644 int ret;
645
646
2/4
✓ Branch 2 → 3 taken 3600 times.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3600 times.
3600 if (stream_index < -1 || stream_index >= (int)s->nb_streams)
647 ✗ return AVERROR(EINVAL);
648
649
1/4
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 14 taken 3600 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 14 not taken.
3600 if (ffifmt(s->iformat)->read_seek2 && !ffifmt(s->iformat)->read_seek) {
650 ✗ int64_t min_ts = INT64_MIN, max_ts = INT64_MAX;
651
0/2
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
✗ if ((flags & AVSEEK_FLAG_BACKWARD))
652 ✗ max_ts = timestamp;
653 else
654 ✗ min_ts = timestamp;
655 ✗ return avformat_seek_file(s, stream_index, min_ts, timestamp, max_ts,
656 flags & ~AVSEEK_FLAG_BACKWARD);
657 }
658
659 3600 ret = seek_frame_internal(s, stream_index, timestamp, flags);
660
661
2/2
✓ Branch 15 → 16 taken 2850 times.
✓ Branch 15 → 17 taken 750 times.
3600 if (ret >= 0)
662 2850 ret = avformat_queue_attached_pictures(s);
663
664 3600 return ret;
665 }
666
667 /**
668 * The largest pre-roll of the audio streams that are not discarded, in the
669 * units of the seek: the time base of the stream, or AV_TIME_BASE when no
670 * stream is given. Audio decoders need the frames before the target to
671 * produce reliable output at it, and declare how many samples in
672 * AVCodecParameters.seek_preroll.
673 */
674 3595 static int64_t seek_preroll(const AVFormatContext *s, int stream_index)
675 {
676 3595 AVRational unit = stream_index >= 0 ? s->streams[stream_index]->time_base
677
2/2
✓ Branch 2 → 3 taken 1676 times.
✓ Branch 2 → 4 taken 1919 times.
3595 : AV_TIME_BASE_Q;
678 3595 int64_t preroll = 0;
679
680
2/2
✓ Branch 15 → 6 taken 4163 times.
✓ Branch 15 → 16 taken 3595 times.
7758 for (unsigned i = 0; i < s->nb_streams; i++) {
681 4163 const AVStream *st = s->streams[i];
682 4163 const AVCodecParameters *par = st->codecpar;
683 int64_t v;
684
685
2/2
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 8 taken 4159 times.
4163 if (st->discard >= AVDISCARD_ALL)
686 3910 continue;
687
4/4
✓ Branch 8 → 9 taken 1792 times.
✓ Branch 8 → 11 taken 2367 times.
✓ Branch 9 → 10 taken 253 times.
✓ Branch 9 → 11 taken 1539 times.
4159 if (par->codec_type != AVMEDIA_TYPE_AUDIO || par->seek_preroll <= 0 ||
688
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 253 times.
253 par->sample_rate <= 0)
689 3906 continue;
690
691 253 v = av_rescale_q_rnd(par->seek_preroll, (AVRational){ 1, par->sample_rate },
692 unit, AV_ROUND_UP);
693 253 preroll = FFMAX(preroll, v);
694 }
695
696 3595 return preroll;
697 }
698
699 /**
700 * Ask the demuxer to discard the priming or the pre-roll from the first
701 * packet of each stream. A stream whose start the target does not pass
702 * is decoded from its start, which has no pre-roll to discard.
703 */
704 2850 static void request_seek_discard(AVFormatContext *s, int stream_index,
705 int64_t ts, int flags)
706 {
707 2850 AVRational time_base = stream_index >= 0 ? s->streams[stream_index]->time_base
708
2/2
✓ Branch 2 → 3 taken 1344 times.
✓ Branch 2 → 4 taken 1506 times.
2850 : AV_TIME_BASE_Q;
709
710
2/2
✓ Branch 14 → 6 taken 3389 times.
✓ Branch 14 → 15 taken 2850 times.
6239 for (unsigned i = 0; i < s->nb_streams; i++) {
711 3389 AVStream *const st = s->streams[i];
712 3389 FFStream *const sti = ffstream(st);
713
714 3389 sti->seek_discard = 1;
715 3389 sti->seek_to_start = !(flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME)) &&
716
5/6
✓ Branch 7 → 8 taken 3389 times.
✗ Branch 7 → 12 not taken.
✓ Branch 8 → 9 taken 2662 times.
✓ Branch 8 → 12 taken 727 times.
✓ Branch 10 → 11 taken 752 times.
✓ Branch 10 → 12 taken 1910 times.
6051 st->start_time != AV_NOPTS_VALUE &&
717 2662 av_compare_ts(ts, time_base, st->start_time,
718 st->time_base) <= 0;
719 }
720 2850 }
721
722 3601 static int seek_file(AVFormatContext *s, int stream_index, int64_t min_ts,
723 int64_t ts, int64_t max_ts, int flags)
724 {
725 int dir;
726 int ret;
727
728
2/2
✓ Branch 3 → 4 taken 29 times.
✓ Branch 3 → 14 taken 3572 times.
3601 if (ffifmt(s->iformat)->read_seek2) {
729 29 ff_read_frame_flush(s);
730
731
3/4
✓ Branch 5 → 6 taken 17 times.
✓ Branch 5 → 9 taken 12 times.
✓ Branch 6 → 7 taken 17 times.
✗ Branch 6 → 9 not taken.
29 if (stream_index == -1 && s->nb_streams == 1) {
732 17 ff_rescale_interval(AV_TIME_BASE_Q, s->streams[0]->time_base,
733 &min_ts, &ts, &max_ts);
734 17 stream_index = 0;
735 }
736
737 29 ret = ffifmt(s->iformat)->read_seek2(s, stream_index, min_ts,
738 ts, max_ts, flags);
739
740
2/2
✓ Branch 11 → 12 taken 28 times.
✓ Branch 11 → 13 taken 1 time.
29 if (ret >= 0)
741 28 ret = avformat_queue_attached_pictures(s);
742 29 return ret;
743 }
744
745 // Fall back on old API if new is not implemented but old is.
746 // Note the old API has somewhat different semantics.
747 3572 dir = (ts - (uint64_t)min_ts > (uint64_t)max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0);
748 3572 ret = av_seek_frame(s, stream_index, ts, flags | dir);
749
5/6
✓ Branch 15 → 16 taken 750 times.
✓ Branch 15 → 24 taken 2822 times.
✓ Branch 16 → 17 taken 373 times.
✓ Branch 16 → 24 taken 377 times.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 24 taken 373 times.
3572 if (ret < 0 && ts != min_ts && max_ts != ts) {
750
0/2
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 20 not taken.
✗ ret = av_seek_frame(s, stream_index, dir ? max_ts : min_ts, flags | dir);
751
0/2
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
✗ if (ret >= 0)
752 ✗ ret = av_seek_frame(s, stream_index, ts, flags | (dir^AVSEEK_FLAG_BACKWARD));
753 }
754 3572 return ret;
755 }
756
757 3595 int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts,
758 int64_t ts, int64_t max_ts, int flags)
759 {
760 3595 int64_t target = ts, target_max = max_ts;
761 int ret;
762
763
2/4
✓ Branch 2 → 3 taken 3595 times.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3595 times.
3595 if (min_ts > ts || max_ts < ts)
764 ✗ return -1;
765
2/4
✓ Branch 5 → 6 taken 3595 times.
✗ Branch 5 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 3595 times.
3595 if (stream_index < -1 || stream_index >= (int)s->nb_streams)
766 ✗ return AVERROR(EINVAL);
767
768
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 3595 times.
3595 if (s->seek2any > 0)
769 ✗ flags |= AVSEEK_FLAG_ANY;
770 3595 flags &= ~AVSEEK_FLAG_BACKWARD;
771
772
1/2
✓ Branch 10 → 11 taken 3595 times.
✗ Branch 10 → 24 not taken.
3595 if (!(flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME))) {
773 3595 int64_t preroll = seek_preroll(s, stream_index);
774 3595 int64_t start = stream_index >= 0 ? s->streams[stream_index]->start_time
775
2/2
✓ Branch 12 → 13 taken 1676 times.
✓ Branch 12 → 14 taken 1919 times.
3595 : s->start_time;
776
777 // Land early enough to decode the pre-roll, without leaving the
778 // range the caller asked for or going before the start.
779
2/2
✓ Branch 16 → 17 taken 1879 times.
✓ Branch 16 → 18 taken 1716 times.
3595 target = FFMAX(av_sat_sub64(ts, preroll), min_ts);
780
2/2
✓ Branch 19 → 20 taken 2682 times.
✓ Branch 19 → 21 taken 913 times.
3595 if (start != AV_NOPTS_VALUE)
781 2682 target = FFMAX(target, FFMIN(start, ts));
782 // Move the finite upper bound back by the same amount as the target.
783 // An open upper bound stays open.
784
2/2
✓ Branch 21 → 22 taken 1857 times.
✓ Branch 21 → 24 taken 1738 times.
3595 if (max_ts != INT64_MAX)
785 1857 target_max = av_sat_sub64(max_ts, av_sat_sub64(ts, target));
786 }
787
788 3595 ret = seek_file(s, stream_index, min_ts, target, target_max, flags);
789 // Without a known start, the earlier target may come before the first
790 // packet.
791
4/4
✓ Branch 25 → 26 taken 746 times.
✓ Branch 25 → 28 taken 2849 times.
✓ Branch 26 → 27 taken 6 times.
✓ Branch 26 → 28 taken 740 times.
3595 if (ret < 0 && target != ts) {
792 6 target = ts;
793 6 ret = seek_file(s, stream_index, min_ts, ts, max_ts, flags);
794 }
795
2/2
✓ Branch 28 → 29 taken 2850 times.
✓ Branch 28 → 30 taken 745 times.
3595 if (ret >= 0)
796 2850 request_seek_discard(s, stream_index, target, flags);
797 3595 return ret;
798 }
799
800 /** Flush the frame reader. */
801 5255 void ff_read_frame_flush(AVFormatContext *s)
802 {
803 5255 ff_flush_packet_queue(s);
804
805 /* Reset read state for each stream. */
806
2/2
✓ Branch 15 → 4 taken 6098 times.
✓ Branch 15 → 16 taken 5255 times.
11353 for (unsigned i = 0; i < s->nb_streams; i++) {
807 6098 AVStream *const st = s->streams[i];
808 6098 FFStream *const sti = ffstream(st);
809
810
2/2
✓ Branch 5 → 6 taken 1379 times.
✓ Branch 5 → 8 taken 4719 times.
6098 if (sti->parser) {
811 1379 av_parser_close(sti->parser);
812 1379 sti->parser = NULL;
813 }
814 6098 sti->last_IP_pts = AV_NOPTS_VALUE;
815 6098 sti->last_dts_for_order_check = AV_NOPTS_VALUE;
816
2/2
✓ Branch 8 → 9 taken 1755 times.
✓ Branch 8 → 10 taken 4343 times.
6098 if (sti->first_dts == AV_NOPTS_VALUE)
817 1755 sti->cur_dts = RELATIVE_TS_BASE;
818 else
819 /* We set the current DTS to an unspecified origin. */
820 4343 sti->cur_dts = AV_NOPTS_VALUE;
821
822 6098 sti->probe_packets = s->max_probe_packets;
823
824
2/2
✓ Branch 13 → 12 taken 103666 times.
✓ Branch 13 → 14 taken 6098 times.
109764 for (int j = 0; j < MAX_REORDER_DELAY + 1; j++)
825 103666 sti->pts_buffer[j] = AV_NOPTS_VALUE;
826
827 6098 sti->skip_samples = 0;
828 6098 sti->seek_discard = 0;
829 }
830 5255 }
831
832 ✗ int avformat_flush(AVFormatContext *s)
833 {
834 ✗ ff_read_frame_flush(s);
835 ✗ return 0;
836 }
837
838 74 void ff_rescale_interval(AVRational tb_in, AVRational tb_out,
839 int64_t *min_ts, int64_t *ts, int64_t *max_ts)
840 {
841 74 *ts = av_rescale_q (* ts, tb_in, tb_out);
842 74 *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out,
843 AV_ROUND_UP | AV_ROUND_PASS_MINMAX);
844 74 *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out,
845 AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
846 // Rounding to the nearest can take the target out of the interval.
847 74 *ts = FFMAX(FFMIN(*ts, *max_ts), *min_ts);
848 74 }
849