summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPanagiotis H.M. Issaris <[email protected]>2012-01-10 14:48:57 +0100
committerMichael Niedermayer <[email protected]>2012-01-16 03:43:32 +0100
commit811de351eab675ca108db9b0c018fe82afa577fc (patch)
tree592186d587337de49204a909af0507a94394bab6
parentebc9ff8e7d6e9b33a5839d027dd823cf83824d60 (diff)
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: Michael Niedermayer <[email protected]>
-rw-r--r--libavformat/applehttp.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c
index 5733f5fb27..883427ce97 100644
--- a/libavformat/applehttp.c
+++ b/libavformat/applehttp.c
@@ -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;
}