History

mov: Compare frag times in correct time base when seeking a stream without a corresponding sidx

Some muxers, such as GPAC, create files with only one sidx, but two streams muxed into the same fragments pointed to by this sidx. Prevously, in such a case, when we seeked in such files, we fell back to, for example, using the sidx associated with the video stream, to seek the audio stream, leaving the seekhead in the wrong place. We can still do this, but we need to take care to compare timestamps in the same time base.

Derek Buitenhuis committed 4 years ago

Commit e1e981c1 parent 8bec2251 file · +20 −18Browse files

Showing the changes to libavformat (1 of 1 file). Show all

Unified · Split

libavformat/mov.c+20−18
@@ -1271,15 +1271,18 @@ static int64_t get_stream_info_time(MOVFragmentStreamInfo * frag_stream_info) · 1270 unmodified lines
12711271 return frag_stream_info->tfdt_dts;
12721272 }
12731273
1274−static int64_t get_frag_time(MOVFragmentIndex *frag_index,
1275− int index, int track_id)
1274+static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1275+ MOVFragmentIndex *frag_index, int index)
12761276 {
12771277 MOVFragmentStreamInfo * frag_stream_info;
1278+ MOVStreamContext *sc = dst_st->priv_data;
12781279 int64_t timestamp;
1279− int i;
1280+ int i, j;
12801281
1281− if (track_id >= 0) {
1282− frag_stream_info = get_frag_stream_info(frag_index, index, track_id);
1282+ // If the stream is referenced by any sidx, limit the search
1283+ // to fragments that referenced this stream in the sidx
1284+ if (sc->has_sidx) {
1285+ frag_stream_info = get_frag_stream_info(frag_index, index, dst_st->id);
12831286 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
12841287 return frag_stream_info->sidx_pts;
12851288 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)
@@ -1288,28 +1291,27 @@ static int64_t get_frag_time(MOVFragmentIndex *frag_index, · 2 unmodified lines
12881291 }
12891292
12901293 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1294+ AVStream *frag_stream = NULL;
12911295 frag_stream_info = &frag_index->item[index].stream_info[i];
1296+ for (j = 0; j < s->nb_streams; j++)
1297+ if (s->streams[j]->id == frag_stream_info->id)
1298+ frag_stream = s->streams[j];
1299+ if (!frag_stream) {
1300+ av_log(s, AV_LOG_WARNING, "No stream matching sidx ID found.\n");
1301+ continue;
1302+ }
12921303 timestamp = get_stream_info_time(frag_stream_info);
12931304 if (timestamp != AV_NOPTS_VALUE)
1294− return timestamp;
1305+ return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
12951306 }
12961307 return AV_NOPTS_VALUE;
12971308 }
12981309
1299−static int search_frag_timestamp(MOVFragmentIndex *frag_index,
1310+static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
13001311 AVStream *st, int64_t timestamp)
13011312 {
13021313 int a, b, m, m0;
13031314 int64_t frag_time;
1304− int id = -1;
1305−
1306− if (st) {
1307− // If the stream is referenced by any sidx, limit the search
1308− // to fragments that referenced this stream in the sidx
1309− MOVStreamContext *sc = st->priv_data;
1310− if (sc->has_sidx)
1311− id = st->id;
1312− }
13131315
13141316 a = -1;
13151317 b = frag_index->nb_items;
@@ -1318,7 +1320,7 @@ static int search_frag_timestamp(MOVFragmentIndex *frag_index, · 2 unmodified lines
13181320 m0 = m = (a + b) >> 1;
13191321
13201322 while (m < b &&
1321− (frag_time = get_frag_time(frag_index, m, id)) == AV_NOPTS_VALUE)
1323+ (frag_time = get_frag_time(s, st, frag_index, m)) == AV_NOPTS_VALUE)
13221324 m++;
13231325
13241326 if (m < b && frag_time <= timestamp)
@@ -8862,7 +8864,7 @@ static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp · 7537 unmodified lines
88628864 if (!mov->frag_index.complete)
88638865 return 0;
88648866
8865− index = search_frag_timestamp(&mov->frag_index, st, timestamp);
8867+ index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
88668868 if (index < 0)
88678869 index = 0;
88688870 if (!mov->frag_index.item[index].headers_read)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t