Commit 811de351 authored by Panagiotis H.M. Issaris's avatar Panagiotis H.M. Issaris Committed by Michael Niedermayer

Enhance HLS seeking.

Enhances seeking by demuxing until the requested timestamp is reached within
the segment selected by the seek code using the playlist info.
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent ebc9ff8e
......@@ -100,6 +100,8 @@ typedef struct AppleHTTPContext {
int end_of_segment;
int first_packet;
int64_t first_timestamp;
int64_t seek_timestamp;
int seek_flags;
AVIOInterruptCB *interrupt_callback;
} AppleHTTPContext;
......@@ -545,6 +547,7 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap)
c->first_packet = 1;
c->first_timestamp = AV_NOPTS_VALUE;
c->seek_timestamp = AV_NOPTS_VALUE;
return 0;
fail:
......@@ -604,14 +607,44 @@ start:
/* Make sure we've got one buffered packet from each open variant
* stream */
if (var->needed && !var->pkt.data) {
ret = av_read_frame(var->ctx, &var->pkt);
if (ret < 0) {
if (!url_feof(&var->pb))
return ret;
reset_packet(&var->pkt);
} else {
if (c->first_timestamp == AV_NOPTS_VALUE)
c->first_timestamp = var->pkt.dts;
while (1) {
int64_t ts_diff;
ret = av_read_frame(var->ctx, &var->pkt);
if (ret < 0) {
if (!url_feof(&var->pb)) {
return ret;
} else {
if ((var->cur_seq_no - var->start_seq_no) == (var->n_segments)) {
return AVERROR_EOF;
}
}
reset_packet(&var->pkt);
} else {
if (c->first_timestamp == AV_NOPTS_VALUE)
c->first_timestamp = var->pkt.dts;
}
if (c->seek_timestamp == AV_NOPTS_VALUE)
break;
if (var->pkt.dts == AV_NOPTS_VALUE) {
c->seek_timestamp = AV_NOPTS_VALUE;
break;
}
ts_diff = var->pkt.dts - c->seek_timestamp;
if (ts_diff >= 0) {
if (c->seek_flags & AVSEEK_FLAG_ANY) {
c->seek_timestamp = AV_NOPTS_VALUE;
break;
}
/* Seek to keyframe */
if (var->pkt.flags & AV_PKT_FLAG_KEY) {
c->seek_timestamp = AV_NOPTS_VALUE;
break;
}
}
}
}
/* Check if this stream has the packet with the lowest dts */
......@@ -652,10 +685,17 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index,
if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
return AVERROR(ENOSYS);
c->seek_timestamp = timestamp;
c->seek_flags = flags;
timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ?
s->streams[stream_index]->time_base.den :
AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
AV_ROUND_DOWN : AV_ROUND_UP);
if (s->duration < c->seek_timestamp) {
c->seek_timestamp = AV_NOPTS_VALUE;
return AVERROR(EIO);
}
ret = AVERROR(EIO);
for (i = 0; i < c->n_variants; i++) {
/* Reset reading */
......@@ -683,6 +723,8 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index,
}
pos += var->segments[j]->duration;
}
if (ret != 0)
c->seek_timestamp = AV_NOPTS_VALUE;
}
return ret;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment