@@ -34,6 +34,7 @@
#include "libavutil/opt.h"
#include "libavutil/dict.h"
#include "libavutil/time.h"
+#include "libavutil/parseutils.h"
#include "avformat.h"
#include "internal.h"
#include "avio_internal.h"
@@ -67,6 +68,7 @@ enum KeyType {
struct segment {
int64_t duration;
+ int64_t timestamp;
int64_t url_offset;
int64_t size;
char *url;
@@ -714,6 +716,7 @@ static int parse_playlist(HLSContext *c, const char *url,
{
int ret = 0, is_segment = 0, is_variant = 0;
int64_t duration = 0;
+ int64_t timestamp = 0;
enum KeyType key_type = KEY_NONE;
uint8_t iv[16] = "";
int has_iv = 0;
@@ -868,6 +871,11 @@ static int parse_playlist(HLSContext *c, const char *url,
} else if (av_strstart(line, "#EXTINF:", &ptr)) {
is_segment = 1;
duration = atof(ptr) * AV_TIME_BASE;
+ } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
+ if (av_parse_time(×tamp, ptr, 0) < 0) {
+ av_log(c->ctx, AV_LOG_INFO, "Cannot parse ('%s')\n", line);
+ timestamp = 0;
+ }
} else if (av_strstart(line, "#EXT-X-BYTERANGE:", &ptr)) {
seg_size = strtoll(ptr, NULL, 10);
ptr = strchr(ptr, '@');
@@ -941,6 +949,8 @@ static int parse_playlist(HLSContext *c, const char *url,
duration = 0.001 * AV_TIME_BASE;
}
seg->duration = duration;
+ seg->timestamp = timestamp;
+ timestamp = 0;
seg->key_type = key_type;
dynarray_add(&pls->segments, &pls->n_segments, seg);
is_segment = 0;
@@ -1644,6 +1654,21 @@ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls,
return 0;
}
+ /* If all segments have timestamps then more accurate than using segment duration */
+ if (pls->n_segments && pls->segments[0]->timestamp) {
+ int64_t initial_timestamp = pls->segments[0]->timestamp;
+ for (i = 1; i < pls->n_segments; i++) {
+ if (!pls->segments[i]->timestamp) break;
+ if (timestamp < pls->segments[i]->timestamp - initial_timestamp) {
+ *seq_no = pls->start_seq_no + i - 1;
+ return 1;
+ } else if (i == pls->n_segments - 1) {
+ *seq_no = pls->start_seq_no + i;
+ return 1;
+ }
+ }
+ }
+
for (i = 0; i < pls->n_segments; i++) {
int64_t diff = pos + pls->segments[i]->duration - timestamp;
if (diff > 0) {