FFmpeg
seek.c
Go to the documentation of this file.
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 void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
36 {
37  for (unsigned i = 0; i < s->nb_streams; i++) {
38  AVStream *const st = s->streams[i];
39  FFStream *const sti = ffstream(st);
40 
41  sti->cur_dts =
42  av_rescale(timestamp,
43  st->time_base.den * (int64_t) ref_st->time_base.num,
44  st->time_base.num * (int64_t) ref_st->time_base.den);
45  }
46 }
47 
48 void ff_reduce_index(AVFormatContext *s, int stream_index)
49 {
50  AVStream *const st = s->streams[stream_index];
51  FFStream *const sti = ffstream(st);
52  unsigned int max_entries = s->max_index_size / sizeof(AVIndexEntry);
53 
54  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 }
61 
62 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  if ((unsigned) *nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
72  return -1;
73 
74  if (timestamp == AV_NOPTS_VALUE)
75  return AVERROR(EINVAL);
76 
77  if (size < 0 || size > 0x3FFFFFFF)
78  return AVERROR(EINVAL);
79 
80  if (is_relative(timestamp)) //FIXME this maintains previous behavior but we should shift by the correct offset once known
81  timestamp -= RELATIVE_TS_BASE;
82 
83  entries = av_fast_realloc(*index_entries,
84  index_entries_allocated_size,
85  (*nb_index_entries + 1) *
86  sizeof(AVIndexEntry));
87  if (!entries)
88  return -1;
89 
90  *index_entries = entries;
91 
92  index = ff_index_search_timestamp(*index_entries, *nb_index_entries,
93  timestamp, AVSEEK_FLAG_ANY);
94  if (index < 0) {
95  index = (*nb_index_entries)++;
96  ie = &entries[index];
97  av_assert0(index == 0 || ie[-1].timestamp < timestamp);
98  } else {
99  ie = &entries[index];
100  if (ie->timestamp != timestamp) {
101  if (ie->timestamp <= timestamp)
102  return -1;
103  memmove(entries + index + 1, entries + index,
104  sizeof(AVIndexEntry) * (*nb_index_entries - index));
105  (*nb_index_entries)++;
106  } else if (ie->pos == pos && distance < ie->min_distance)
107  // do not reduce the distance
108  distance = ie->min_distance;
109  }
110 
111  ie->pos = pos;
112  ie->timestamp = timestamp;
113  ie->min_distance = distance;
114  ie->size = size;
115  ie->flags = flags;
116 
117  return index;
118 }
119 
120 int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
121  int size, int distance, int flags)
122 {
123  FFStream *const sti = ffstream(st);
124  timestamp = ff_wrap_timestamp(st, timestamp);
127  timestamp, size, distance, flags);
128 }
129 
130 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  a = -1;
137  b = nb_entries;
138 
139  // Optimize appending index entries at the end.
140  if (b && entries[b - 1].timestamp < wanted_timestamp)
141  a = b - 1;
142 
143  while (b - a > 1) {
144  m = (a + b) >> 1;
145 
146  // Search for the next non-discarded packet.
147  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  timestamp = entries[m].timestamp;
156  if (timestamp >= wanted_timestamp)
157  b = m;
158  if (timestamp <= wanted_timestamp)
159  a = m;
160  }
161  m = (flags & AVSEEK_FLAG_BACKWARD) ? a : b;
162 
163  if (!(flags & AVSEEK_FLAG_ANY))
164  while (m >= 0 && m < nb_entries &&
165  !(entries[m].flags & AVINDEX_KEYFRAME))
166  m += (flags & AVSEEK_FLAG_BACKWARD) ? -1 : 1;
167 
168  if (m == nb_entries)
169  return -1;
170  return m;
171 }
172 
173 void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
174 {
175  int64_t pos_delta = 0;
176  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  const char *proto = avio_find_protocol_name(s->url);
179  FFIOContext *ctx;
180 
181  av_assert0(time_tolerance >= 0);
182 
183  if (!proto) {
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  if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))
191  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 int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
244 {
245  const FFStream *const sti = ffstream(st);
247  wanted_timestamp, flags);
248 }
249 
251 {
252  return cffstream(st)->nb_index_entries;
253 }
254 
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 
265  int64_t wanted_timestamp,
266  int flags)
267 {
268  const FFStream *const sti = ffstream(st);
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 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  int64_t ts = read_timestamp(s, stream_index, ppos, pos_limit);
283  if (stream_index >= 0)
284  ts = ff_wrap_timestamp(s->streams[stream_index], ts);
285  return ts;
286 }
287 
288 int ff_seek_frame_binary(AVFormatContext *s, int stream_index,
289  int64_t target_ts, int flags)
290 {
291  const AVInputFormat *const avif = s->iformat;
292  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  if (stream_index < 0)
300  return -1;
301 
302  av_log(s, AV_LOG_TRACE, "read_seek: %d %s\n", stream_index, av_ts2str(target_ts));
303 
304  ts_max =
305  ts_min = AV_NOPTS_VALUE;
306  pos_limit = -1; // GCC falsely says it may be uninitialized.
307 
308  st = s->streams[stream_index];
309  sti = ffstream(st);
310  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  index = av_index_search_timestamp(st, target_ts,
317  index = FFMAX(index, 0);
318  e = &sti->index_entries[index];
319 
320  if (e->timestamp <= target_ts || e->pos == e->min_distance) {
321  pos_min = e->pos;
322  ts_min = e->timestamp;
323  av_log(s, AV_LOG_TRACE, "using cached pos_min=0x%"PRIx64" dts_min=%s\n",
324  pos_min, av_ts2str(ts_min));
325  } else {
326  av_assert1(index == 0);
327  }
328 
329  index = av_index_search_timestamp(st, target_ts,
331  av_assert0(index < sti->nb_index_entries);
332  if (index >= 0) {
333  e = &sti->index_entries[index];
334  av_assert1(e->timestamp >= target_ts);
335  pos_max = e->pos;
336  ts_max = e->timestamp;
337  pos_limit = pos_max - e->min_distance;
338  av_log(s, AV_LOG_TRACE, "using cached pos_max=0x%"PRIx64" pos_limit=0x%"PRIx64
339  " dts_max=%s\n", pos_max, pos_limit, av_ts2str(ts_max));
340  }
341  }
342 
343  pos = ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit,
344  ts_min, ts_max, flags, &ts, avif->read_timestamp);
345  if (pos < 0)
346  return -1;
347 
348  /* do the seek */
349  if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0)
350  return ret;
351 
353  avpriv_update_cur_dts(s, st, ts);
354 
355  return 0;
356 }
357 
358 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  int64_t step = 1024;
362  int64_t limit, ts_max;
363  int64_t filesize = avio_size(s->pb);
364  int64_t pos_max = filesize - 1;
365  do {
366  limit = pos_max;
367  pos_max = FFMAX(0, (pos_max) - step);
368  ts_max = read_timestamp(s, stream_index,
369  &pos_max, limit, read_timestamp_func);
370  step += step;
371  } while (ts_max == AV_NOPTS_VALUE && 2*limit > step);
372  if (ts_max == AV_NOPTS_VALUE)
373  return -1;
374 
375  for (;;) {
376  int64_t tmp_pos = pos_max + 1;
377  int64_t tmp_ts = read_timestamp(s, stream_index,
378  &tmp_pos, INT64_MAX, read_timestamp_func);
379  if (tmp_ts == AV_NOPTS_VALUE)
380  break;
381  av_assert0(tmp_pos > pos_max);
382  ts_max = tmp_ts;
383  pos_max = tmp_pos;
384  if (tmp_pos >= filesize)
385  break;
386  }
387 
388  if (ts)
389  *ts = ts_max;
390  if (pos)
391  *pos = pos_max;
392 
393  return 0;
394 }
395 
396 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  FFFormatContext *const si = ffformatcontext(s);
404  int64_t pos, ts;
405  int64_t start_pos;
406  int no_change;
407  int ret;
408 
409  av_log(s, AV_LOG_TRACE, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts));
410 
411  if (ts_min == AV_NOPTS_VALUE) {
412  pos_min = si->data_offset;
413  ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func);
414  if (ts_min == AV_NOPTS_VALUE)
415  return -1;
416  }
417 
418  if (ts_min >= target_ts) {
419  *ts_ret = ts_min;
420  return pos_min;
421  }
422 
423  if (ts_max == AV_NOPTS_VALUE) {
424  if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp_func)) < 0)
425  return ret;
426  pos_limit = pos_max;
427  }
428 
429  if (ts_max <= target_ts) {
430  *ts_ret = ts_max;
431  return pos_max;
432  }
433 
434  av_assert0(ts_min < ts_max);
435 
436  no_change = 0;
437  while (pos_min < pos_limit) {
439  "pos_min=0x%"PRIx64" pos_max=0x%"PRIx64" dts_min=%s dts_max=%s\n",
440  pos_min, pos_max, av_ts2str(ts_min), av_ts2str(ts_max));
441  av_assert0(pos_limit <= pos_max);
442 
443  if (no_change == 0) {
444  int64_t approximate_keyframe_distance = pos_max - pos_limit;
445  // interpolate position (better than dichotomy)
446  pos = av_rescale(target_ts - ts_min, pos_max - pos_min,
447  ts_max - ts_min) +
448  pos_min - approximate_keyframe_distance;
449  } else if (no_change == 1) {
450  // bisection if interpolation did not change min / max pos last time
451  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  pos = pos_min;
456  }
457  if (pos <= pos_min)
458  pos = pos_min + 1;
459  else if (pos > pos_limit)
460  pos = pos_limit;
461  start_pos = pos;
462 
463  // May pass pos_limit instead of -1.
464  ts = read_timestamp(s, stream_index, &pos, INT64_MAX, read_timestamp_func);
465  if (pos == pos_max)
466  no_change++;
467  else
468  no_change = 0;
469  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  av_ts2str(ts_min), av_ts2str(ts), av_ts2str(ts_max), av_ts2str(target_ts),
473  pos_limit, start_pos, no_change);
474  if (ts == AV_NOPTS_VALUE) {
475  av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n");
476  return -1;
477  }
478  if (target_ts <= ts) {
479  pos_limit = start_pos - 1;
480  pos_max = pos;
481  ts_max = ts;
482  }
483  if (target_ts >= ts) {
484  pos_min = pos;
485  ts_min = ts;
486  }
487  }
488 
489  pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
490  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  *ts_ret = ts;
500  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 static int seek_frame_generic(AVFormatContext *s, int stream_index,
525  int64_t timestamp, int flags)
526 {
527  FFFormatContext *const si = ffformatcontext(s);
528  AVStream *const st = s->streams[stream_index];
529  FFStream *const sti = ffstream(st);
530  const AVIndexEntry *ie;
531  int index;
532  int64_t ret;
533 
534  index = av_index_search_timestamp(st, timestamp, flags);
535 
536  if (index < 0 && sti->nb_index_entries &&
537  timestamp < sti->index_entries[0].timestamp)
538  return -1;
539 
540  if (index < 0 || index == sti->nb_index_entries - 1) {
541  AVPacket *const pkt = si->pkt;
542  int nonkey = 0;
543 
544  if (sti->nb_index_entries) {
546  ie = &sti->index_entries[sti->nb_index_entries - 1];
547  if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
548  return ret;
549  s->io_repositioned = 1;
551  } else {
552  if ((ret = avio_seek(s->pb, si->data_offset, SEEK_SET)) < 0)
553  return ret;
554  s->io_repositioned = 1;
555  }
557  for (;;) {
558  int read_status;
559  do {
560  read_status = av_read_frame(s, pkt);
561  } while (read_status == AVERROR(EAGAIN));
562  if (read_status < 0)
563  break;
564  if (stream_index == pkt->stream_index && pkt->dts > timestamp) {
565  if (pkt->flags & AV_PKT_FLAG_KEY) {
567  break;
568  }
569  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);
572  break;
573  }
574  }
576  }
577  index = av_index_search_timestamp(st, timestamp, flags);
578  }
579  if (index < 0)
580  return -1;
581 
583  if (s->iformat->read_seek)
584  if (s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0)
585  return 0;
586  ie = &sti->index_entries[index];
587  if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0)
588  return ret;
589  s->io_repositioned = 1;
591 
592  return 0;
593 }
594 
595 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  if (flags & AVSEEK_FLAG_BYTE) {
602  if (s->iformat->flags & AVFMT_NO_BYTE_SEEK)
603  return -1;
605  return seek_frame_byte(s, stream_index, timestamp, flags);
606  }
607 
608  if (stream_index < 0) {
609  stream_index = av_find_default_stream_index(s);
610  if (stream_index < 0)
611  return -1;
612 
613  st = s->streams[stream_index];
614  /* timestamp for default must be expressed in AV_TIME_BASE units */
615  timestamp = av_rescale(timestamp, st->time_base.den,
616  AV_TIME_BASE * (int64_t) st->time_base.num);
617  }
618 
619  /* first, we try the format specific seek */
620  if (s->iformat->read_seek) {
622  ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
623  } else
624  ret = -1;
625  if (ret >= 0)
626  return 0;
627 
628  if (s->iformat->read_timestamp &&
629  !(s->iformat->flags & AVFMT_NOBINSEARCH)) {
631  return ff_seek_frame_binary(s, stream_index, timestamp, flags);
632  } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) {
634  return seek_frame_generic(s, stream_index, timestamp, flags);
635  } else
636  return -1;
637 }
638 
639 int av_seek_frame(AVFormatContext *s, int stream_index,
640  int64_t timestamp, int flags)
641 {
642  int ret;
643 
644  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,
652  }
653 
654  ret = seek_frame_internal(s, stream_index, timestamp, flags);
655 
656  if (ret >= 0)
658 
659  return ret;
660 }
661 
662 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  if (min_ts > ts || max_ts < ts)
666  return -1;
667  if (stream_index < -1 || stream_index >= (int)s->nb_streams)
668  return AVERROR(EINVAL);
669 
670  if (s->seek2any > 0)
673 
674  if (s->iformat->read_seek2) {
675  int ret;
677 
678  if (stream_index == -1 && s->nb_streams == 1) {
679  AVRational time_base = s->streams[0]->time_base;
680  ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base);
681  min_ts = av_rescale_rnd(min_ts, time_base.den,
682  time_base.num * (int64_t)AV_TIME_BASE,
684  max_ts = av_rescale_rnd(max_ts, time_base.den,
685  time_base.num * (int64_t)AV_TIME_BASE,
687  stream_index = 0;
688  }
689 
690  ret = s->iformat->read_seek2(s, stream_index, min_ts,
691  ts, max_ts, flags);
692 
693  if (ret >= 0)
695  return ret;
696  }
697 
698  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  int dir = (ts - (uint64_t)min_ts > (uint64_t)max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0);
706  int ret = av_seek_frame(s, stream_index, ts, flags | dir);
707  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  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. */
721 {
722  FFFormatContext *const si = ffformatcontext(s);
723 
725 
726  /* Reset read state for each stream. */
727  for (unsigned i = 0; i < s->nb_streams; i++) {
728  AVStream *const st = s->streams[i];
729  FFStream *const sti = ffstream(st);
730 
731  if (sti->parser) {
732  av_parser_close(sti->parser);
733  sti->parser = NULL;
734  }
737  if (sti->first_dts == AV_NOPTS_VALUE)
738  sti->cur_dts = RELATIVE_TS_BASE;
739  else
740  /* We set the current DTS to an unspecified origin. */
741  sti->cur_dts = AV_NOPTS_VALUE;
742 
743  sti->probe_packets = s->max_probe_packets;
744 
745  for (int j = 0; j < MAX_REORDER_DELAY + 1; j++)
746  sti->pts_buffer[j] = AV_NOPTS_VALUE;
747 
749  if (si->inject_global_side_data)
750  sti->inject_global_side_data = 1;
751 #endif
752 
753  sti->skip_samples = 0;
754  }
755 }
756 
758 {
760  return 0;
761 }
762 
764  int64_t *min_ts, int64_t *ts, int64_t *max_ts)
765 {
766  *ts = av_rescale_q (* ts, tb_in, tb_out);
767  *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out,
769  *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out,
771 }
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:423
FFStream::skip_samples
int skip_samples
Number of samples to skip at the start of the frame decoded from the next packet.
Definition: internal.h:278
AVFMT_NO_BYTE_SEEK
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition: avformat.h:488
ffio_realloc_buf
int ffio_realloc_buf(AVIOContext *s, int buf_size)
Reallocate a given buffer for AVIOContext.
Definition: aviobuf.c:1151
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
FFStream::first_dts
int64_t first_dts
Timestamp corresponding to the last dts sync point.
Definition: internal.h:414
ffiocontext
static av_always_inline FFIOContext * ffiocontext(AVIOContext *ctx)
Definition: avio_internal.h:81
FFStream::last_IP_pts
int64_t last_IP_pts
Definition: internal.h:382
ffformatcontext
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition: internal.h:194
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
b
#define b
Definition: input.c:41
FF_API_AVSTREAM_SIDE_DATA
#define FF_API_AVSTREAM_SIDE_DATA
Definition: version_major.h:51
AVSEEK_FLAG_BYTE
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition: avformat.h:2225
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AVINDEX_DISCARD_FRAME
#define AVINDEX_DISCARD_FRAME
Definition: avformat.h:709
mathematics.h
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: demux.c:1462
cffstream
static const av_always_inline FFStream * cffstream(const AVStream *st)
Definition: internal.h:425
AVFMT_NOBINSEARCH
#define AVFMT_NOBINSEARCH
Format does not allow to fall back on binary search via read_timestamp.
Definition: avformat.h:486
FFStream::last_dts_for_order_check
int64_t last_dts_for_order_check
Internal data to analyze DTS and detect faulty mpeg streams.
Definition: internal.h:357
avformat_index_get_entry_from_timestamp
const AVIndexEntry * avformat_index_get_entry_from_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
Get the AVIndexEntry corresponding to the given timestamp.
Definition: seek.c:264
avio_size
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition: aviobuf.c:370
FFIOContext
Definition: avio_internal.h:28
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:546
AVIndexEntry
Definition: avformat.h:700
AVINDEX_KEYFRAME
#define AVINDEX_KEYFRAME
Definition: avformat.h:708
avformat_queue_attached_pictures
int avformat_queue_attached_pictures(AVFormatContext *s)
Definition: demux_utils.c:93
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:420
AVSEEK_FLAG_ANY
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition: avformat.h:2226
av_add_index_entry
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Add an index entry into a sorted list.
Definition: seek.c:120
FFStream::index_entries_allocated_size
unsigned int index_entries_allocated_size
Definition: internal.h:257
AV_ROUND_UP
@ AV_ROUND_UP
Round toward +infinity.
Definition: mathematics.h:134
AVRational::num
int num
Numerator.
Definition: rational.h:59
avassert.h
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
avformat_index_get_entries_count
int avformat_index_get_entries_count(const AVStream *st)
Get the index entry count for the given AVStream.
Definition: seek.c:250
AVInputFormat
Definition: avformat.h:549
ff_reduce_index
void ff_reduce_index(AVFormatContext *s, int stream_index)
Ensure the index uses less memory than the maximum specified in AVFormatContext.max_index_size by dis...
Definition: seek.c:48
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:495
s
#define s(width, name)
Definition: cbs_vp9.c:198
av_seek_frame
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
Definition: seek.c:639
seek_frame_internal
static int seek_frame_internal(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: seek.c:595
AVIndexEntry::size
int size
Definition: avformat.h:711
RELATIVE_TS_BASE
#define RELATIVE_TS_BASE
Definition: demux.h:64
ff_read_frame_flush
void ff_read_frame_flush(AVFormatContext *s)
Flush the frame reader.
Definition: seek.c:720
AVIndexEntry::timestamp
int64_t timestamp
Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are...
Definition: avformat.h:702
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
FFFormatContext::data_offset
int64_t data_offset
offset of the first packet
Definition: internal.h:107
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ff_find_last_ts
int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos, int64_t(*read_timestamp_func)(struct AVFormatContext *, int, int64_t *, int64_t))
Definition: seek.c:358
avformat_flush
int avformat_flush(AVFormatContext *s)
Discard all internally buffered data.
Definition: seek.c:757
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVIndexEntry::min_distance
int min_distance
Minimum distance between this and the previous keyframe, used to avoid unneeded searching.
Definition: avformat.h:712
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:65
if
if(ret)
Definition: filter_design.txt:179
FFFormatContext
Definition: internal.h:70
AVFormatContext
Format I/O context.
Definition: avformat.h:1115
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:864
AVSEEK_FLAG_BACKWARD
#define AVSEEK_FLAG_BACKWARD
Definition: avformat.h:2224
ff_index_search_timestamp
int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries, int64_t wanted_timestamp, int flags)
Internal version of av_index_search_timestamp.
Definition: seek.c:130
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:880
NULL
#define NULL
Definition: coverity.c:32
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVIndexEntry::flags
int flags
Definition: avformat.h:710
FFStream::nb_index_entries
int nb_index_entries
Definition: internal.h:256
index
int index
Definition: gxfenc.c:89
AV_CODEC_ID_CDGRAPHICS
@ AV_CODEC_ID_CDGRAPHICS
Definition: codec_id.h:184
ff_rescale_interval
void ff_rescale_interval(AVRational tb_in, AVRational tb_out, int64_t *min_ts, int64_t *ts, int64_t *max_ts)
Rescales a timestamp and the endpoints of an interval to which the temstamp belongs,...
Definition: seek.c:763
av_rescale_rnd
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition: mathematics.c:58
FFStream
Definition: internal.h:199
ff_seek_frame_binary
int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
Perform a binary search using av_index_search_timestamp() and AVInputFormat.read_timestamp().
Definition: seek.c:288
size
int size
Definition: twinvq_data.h:10344
avformat_seek_file
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition: seek.c:662
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:490
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:497
seek_frame_byte
static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags)
Definition: seek.c:503
FFStream::probe_packets
int probe_packets
Number of packets to buffer for codec probing.
Definition: internal.h:388
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
filesize
static int64_t filesize(AVIOContext *pb)
Definition: ffmpeg_mux.c:48
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
avio_internal.h
MAX_REORDER_DELAY
@ MAX_REORDER_DELAY
Definition: vaapi_encode.h:45
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
avformat_index_get_entry
const AVIndexEntry * avformat_index_get_entry(AVStream *st, int idx)
Get the AVIndexEntry corresponding to the given index.
Definition: seek.c:255
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
AV_ROUND_DOWN
@ AV_ROUND_DOWN
Round toward -infinity.
Definition: mathematics.h:133
ff_wrap_timestamp
int64_t ff_wrap_timestamp(const AVStream *st, int64_t timestamp)
Wrap a given time stamp, if there is an indication for an overflow.
Definition: demux.c:66
FFStream::pts_buffer
int64_t pts_buffer[MAX_REORDER_DELAY+1]
Definition: internal.h:352
av_find_default_stream_index
int av_find_default_stream_index(AVFormatContext *s)
Definition: avformat.c:354
demux.h
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
avcodec.h
limit
static double limit(double x)
Definition: vf_pseudocolor.c:142
ff_configure_buffers_for_index
void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
Definition: seek.c:173
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:841
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:278
pos
unsigned int pos
Definition: spdifenc.c:413
avformat.h
ff_add_index_entry
int ff_add_index_entry(AVIndexEntry **index_entries, int *nb_index_entries, unsigned int *index_entries_allocated_size, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Internal version of av_add_index_entry.
Definition: seek.c:62
seek_frame_generic
static int seek_frame_generic(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: seek.c:524
AVRational::den
int den
Denominator.
Definition: rational.h:60
ff_flush_packet_queue
void ff_flush_packet_queue(AVFormatContext *s)
Definition: avformat.c:92
AVFMT_NOGENSEARCH
#define AVFMT_NOGENSEARCH
Format does not allow to fall back on generic search.
Definition: avformat.h:487
AVIndexEntry::pos
int64_t pos
Definition: avformat.h:701
AVPacket::stream_index
int stream_index
Definition: packet.h:493
FFStream::index_entries
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
Definition: internal.h:254
FFFormatContext::pkt
AVPacket * pkt
Used to hold temporary packets for the generic demuxing code.
Definition: internal.h:140
AV_ROUND_PASS_MINMAX
@ AV_ROUND_PASS_MINMAX
Flag telling rescaling functions to pass INT64_MIN/MAX through unchanged, avoiding special cases for ...
Definition: mathematics.h:159
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:468
FFStream::cur_dts
int64_t cur_dts
Definition: internal.h:415
avpriv_update_cur_dts
void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
Update cur_dts of all streams based on the given timestamp and AVStream.
Definition: seek.c:35
avio_find_protocol_name
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:468
distance
static float distance(float x, float y, int band)
Definition: nellymoserenc.c:230
timestamp.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
AVInputFormat::read_timestamp
int64_t(* read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit)
Get the next timestamp in stream[stream_index].time_base units.
Definition: avformat.h:655
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFStream::parser
struct AVCodecParserContext * parser
Definition: internal.h:392
av_ts2str
#define av_ts2str(ts)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: timestamp.h:54
read_timestamp
static int64_t read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit, int64_t(*read_timestamp)(struct AVFormatContext *, int, int64_t *, int64_t))
Definition: seek.c:279
is_relative
static av_always_inline int is_relative(int64_t ts)
Definition: demux.h:66
ff_gen_search
int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t(*read_timestamp_func)(struct AVFormatContext *, int, int64_t *, int64_t))
Perform a binary search using read_timestamp().
Definition: seek.c:396
av_rescale_q_rnd
int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd)
Rescale a 64-bit integer by 2 rational numbers with specified rounding.
Definition: mathematics.c:134
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375
av_parser_close
void av_parser_close(AVCodecParserContext *s)
Definition: parser.c:193
av_index_search_timestamp
int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags)
Get the index for a specific timestamp.
Definition: seek.c:243