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

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
1271 return frag_stream_info->tfdt_dts;1271 return frag_stream_info->tfdt_dts;
1272}1272}
1273 1273
1274static int64_t get_frag_time(MOVFragmentIndex *frag_index,1274static int64_t get_frag_time(AVFormatContext *s, AVStream *dst_st,
1275 int index, int track_id)1275 MOVFragmentIndex *frag_index, int index)
1276{1276{
1277 MOVFragmentStreamInfo * frag_stream_info;1277 MOVFragmentStreamInfo * frag_stream_info;
1278 MOVStreamContext *sc = dst_st->priv_data;
1278 int64_t timestamp;1279 int64_t timestamp;
1279 int i;1280 int i, j;
1280 1281
1281 if (track_id >= 0) {1282 // If the stream is referenced by any sidx, limit the search
1282 frag_stream_info = get_frag_stream_info(frag_index, index, track_id);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);
1283 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)1286 if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE)
1284 return frag_stream_info->sidx_pts;1287 return frag_stream_info->sidx_pts;
1285 if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE)1288 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
1288 }1291 }
1289 1292
1290 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {1293 for (i = 0; i < frag_index->item[index].nb_stream_info; i++) {
1294 AVStream *frag_stream = NULL;
1291 frag_stream_info = &frag_index->item[index].stream_info[i];1295 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 }
1292 timestamp = get_stream_info_time(frag_stream_info);1303 timestamp = get_stream_info_time(frag_stream_info);
1293 if (timestamp != AV_NOPTS_VALUE)1304 if (timestamp != AV_NOPTS_VALUE)
1294 return timestamp;1305 return av_rescale_q(timestamp, frag_stream->time_base, dst_st->time_base);
1295 }1306 }
1296 return AV_NOPTS_VALUE;1307 return AV_NOPTS_VALUE;
1297}1308}
1298 1309
1299static int search_frag_timestamp(MOVFragmentIndex *frag_index,1310static int search_frag_timestamp(AVFormatContext *s, MOVFragmentIndex *frag_index,
1300 AVStream *st, int64_t timestamp)1311 AVStream *st, int64_t timestamp)
1301{1312{
1302 int a, b, m, m0;1313 int a, b, m, m0;
1303 int64_t frag_time;1314 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 }
1313 1315
1314 a = -1;1316 a = -1;
1315 b = frag_index->nb_items;1317 b = frag_index->nb_items;
@@ -1318,7 +1320,7 @@ static int search_frag_timestamp(MOVFragmentIndex *frag_index, · 2 unmodified lines
1318 m0 = m = (a + b) >> 1;1320 m0 = m = (a + b) >> 1;
1319 1321
1320 while (m < b &&1322 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)
1322 m++;1324 m++;
1323 1325
1324 if (m < b && frag_time <= timestamp)1326 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
8862 if (!mov->frag_index.complete)8864 if (!mov->frag_index.complete)
8863 return 0;8865 return 0;
8864 8866
8865 index = search_frag_timestamp(&mov->frag_index, st, timestamp);8867 index = search_frag_timestamp(s, &mov->frag_index, st, timestamp);
8866 if (index < 0)8868 if (index < 0)
8867 index = 0;8869 index = 0;
8868 if (!mov->frag_index.item[index].headers_read)8870 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