diff --git a/libavformat/hls.c b/libavformat/hls.c index ea58a6d2f6..80a0b3f01c 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -159,6 +159,9 @@ struct playlist { HLSAudioSetupInfo audio_setup_info; + /* Constant offset of this playlist's DTS baseline relative to + * c->first_timestamp. */ + int64_t ts_offset; int64_t seek_timestamp; int seek_flags; int seek_stream_index; /* into subdemuxer stream array */ @@ -349,6 +352,7 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, return NULL; } av_strlcpy(pls->url, abs_url, sizeof(pls->url)); + pls->ts_offset = AV_NOPTS_VALUE; pls->seek_timestamp = AV_NOPTS_VALUE; pls->is_id3_timestamped = -1; @@ -2582,7 +2586,8 @@ static int recheck_discard_flags(AVFormatContext *s, int first) pls->pb.pub.eof_reached = 0; if (c->cur_timestamp != AV_NOPTS_VALUE) { /* catch up */ - pls->seek_timestamp = c->cur_timestamp; + pls->seek_timestamp = c->cur_timestamp + + (pls->ts_offset != AV_NOPTS_VALUE ? pls->ts_offset : 0); pls->seek_flags = AVSEEK_FLAG_ANY; pls->seek_stream_index = -1; } @@ -2700,24 +2705,29 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) fill_timing_for_id3_timestamped_stream(pls); } - if (c->first_timestamp == AV_NOPTS_VALUE && - pls->pkt->dts != AV_NOPTS_VALUE) { + if (pls->ts_offset == AV_NOPTS_VALUE && + pls->pkt->dts != AV_NOPTS_VALUE) { int64_t seg_idx = pls->cur_seq_no - pls->start_seq_no; - c->first_timestamp = av_rescale_q(pls->pkt->dts, + int64_t ts = av_rescale_q(pls->pkt->dts, get_timebase(pls), AV_TIME_BASE_Q); /* EVENT playlists preserve all segments from the start */ - if (pls->type == PLS_TYPE_EVENT) { + if (pls->type == PLS_TYPE_EVENT) for (int64_t k = 0; k < seg_idx && k < pls->n_segments; k++) - c->first_timestamp -= pls->segments[k]->duration; + ts -= pls->segments[k]->duration; - for (unsigned k = 0; k < s->nb_streams; k++) { - AVStream *st = s->streams[k]; - if (st->start_time == AV_NOPTS_VALUE) - st->start_time = av_rescale_q(c->first_timestamp, - AV_TIME_BASE_Q, st->time_base); - } + if (c->first_timestamp == AV_NOPTS_VALUE) { + c->first_timestamp = ts; + + if (pls->type == PLS_TYPE_EVENT) + for (unsigned k = 0; k < s->nb_streams; k++) { + AVStream *st = s->streams[k]; + if (st->start_time == AV_NOPTS_VALUE) + st->start_time = av_rescale_q(ts, + AV_TIME_BASE_Q, st->time_base); + } } + pls->ts_offset = ts - c->first_timestamp; } } @@ -2934,7 +2944,15 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, /* Reset the init segment so it's re-fetched and served appropriately */ pls->cur_init_section = NULL; - pls->seek_timestamp = seek_timestamp; + /* The discard in hls_read_packet compares this playlist's packet DTS + * against seek_timestamp, but seek_timestamp is on c->first_timestamp's + * baseline (whichever stream produced the first packet). Streams can + * have different DTS baselines, so translate the threshold onto this + * playlist's own baseline using its captured offset. */ + if (pls->ts_offset != AV_NOPTS_VALUE) + pls->seek_timestamp = seek_timestamp + pls->ts_offset; + else + pls->seek_timestamp = seek_timestamp; pls->seek_flags = flags; if (pls != seek_pls) { diff --git a/tests/ref/seek/hls b/tests/ref/seek/hls index a9b3badaf8..0f2085916b 100644 --- a/tests/ref/seek/hls +++ b/tests/ref/seek/hls @@ -2,19 +2,19 @@ ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st:-1 flags:1 ts:-0.105833 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 0 flags:1 ts: 1.682500 -ret: 0 st: 0 flags:1 dts: 1.698078 pts: 1.698078 pos: 11092 size: 1253 +ret: 0 st: 1 flags:0 dts: 1.600000 pts: 1.600000 pos: 8836 size: 2330 ret: 0 st: 1 flags:0 ts: 2.576667 ret: 0 st: 0 flags:1 dts: 2.586233 pts: 2.586233 pos: 55836 size: 1254 ret: 0 st: 1 flags:1 ts: 3.470833 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st:-1 flags:0 ts: 4.365002 ret: 0 st: 0 flags:1 dts: 4.388689 pts: 4.388689 pos: 45308 size: 1254 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 0 flags:0 ts: 0.153333 ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 0 flags:1 ts: 1.047500 @@ -22,7 +22,7 @@ ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 1 flags:0 ts: 1.941667 ret: 0 st: 0 flags:1 dts: 1.959300 pts: 1.959300 pos: 24252 size: 1254 ret: 0 st: 1 flags:1 ts: 2.835833 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st:-1 flags:0 ts: 3.730004 ret: 0 st: 0 flags:1 dts: 3.735622 pts: 3.735622 pos: -1 size: 1254 ret: 0 st:-1 flags:1 ts: 4.624171 @@ -34,20 +34,20 @@ ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 1 flags:0 ts: 1.306667 ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 1 flags:1 ts: 2.200844 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st:-1 flags:0 ts: 3.095006 ret: 0 st: 0 flags:1 dts: 3.108689 pts: 3.108689 pos: 82156 size: 1254 ret: 0 st:-1 flags:1 ts: 3.989173 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 0 flags:0 ts: 4.883344 -ret: 0 st: 0 flags:1 dts: 4.885011 pts: 4.885011 pos: -1 size: 1253 +ret: 0 st: 1 flags:0 dts: 4.800000 pts: 5.100000 pos: 20492 size: 3860 ret: 0 st: 0 flags:1 ts:-0.222489 ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 1 flags:0 ts: 0.671678 ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st: 1 flags:1 ts: 1.565844 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913 ret: 0 st:-1 flags:0 ts: 2.460008 ret: 0 st: 0 flags:1 dts: 2.481744 pts: 2.481744 pos: 50572 size: 1254 ret: 0 st:-1 flags:1 ts: 3.354175 -ret: 0 st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos: -1 size: 1254 +ret: 0 st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 564 size: 3913