You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
hls: Store all durations in AV_TIME_BASE
Also parse segment durations as floating point, which is allowed since HLS version 3. This is based on a patch by Zhang Rui. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
@@ -56,7 +56,7 @@ enum KeyType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct segment {
|
struct segment {
|
||||||
int duration;
|
int64_t duration;
|
||||||
char url[MAX_URL_SIZE];
|
char url[MAX_URL_SIZE];
|
||||||
char key[MAX_URL_SIZE];
|
char key[MAX_URL_SIZE];
|
||||||
enum KeyType key_type;
|
enum KeyType key_type;
|
||||||
@@ -81,7 +81,7 @@ struct variant {
|
|||||||
int stream_offset;
|
int stream_offset;
|
||||||
|
|
||||||
int finished;
|
int finished;
|
||||||
int target_duration;
|
int64_t target_duration;
|
||||||
int start_seq_no;
|
int start_seq_no;
|
||||||
int n_segments;
|
int n_segments;
|
||||||
struct segment **segments;
|
struct segment **segments;
|
||||||
@@ -202,7 +202,8 @@ static void handle_key_args(struct key_info *info, const char *key,
|
|||||||
static int parse_playlist(HLSContext *c, const char *url,
|
static int parse_playlist(HLSContext *c, const char *url,
|
||||||
struct variant *var, AVIOContext *in)
|
struct variant *var, AVIOContext *in)
|
||||||
{
|
{
|
||||||
int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
|
int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
|
||||||
|
int64_t duration = 0;
|
||||||
enum KeyType key_type = KEY_NONE;
|
enum KeyType key_type = KEY_NONE;
|
||||||
uint8_t iv[16] = "";
|
uint8_t iv[16] = "";
|
||||||
int has_iv = 0;
|
int has_iv = 0;
|
||||||
@@ -257,7 +258,7 @@ static int parse_playlist(HLSContext *c, const char *url,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var->target_duration = atoi(ptr);
|
var->target_duration = atoi(ptr) * AV_TIME_BASE;
|
||||||
} else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
|
} else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
|
||||||
if (!var) {
|
if (!var) {
|
||||||
var = new_variant(c, 0, url, NULL);
|
var = new_variant(c, 0, url, NULL);
|
||||||
@@ -272,7 +273,7 @@ static int parse_playlist(HLSContext *c, const char *url,
|
|||||||
var->finished = 1;
|
var->finished = 1;
|
||||||
} else if (av_strstart(line, "#EXTINF:", &ptr)) {
|
} else if (av_strstart(line, "#EXTINF:", &ptr)) {
|
||||||
is_segment = 1;
|
is_segment = 1;
|
||||||
duration = atoi(ptr);
|
duration = atof(ptr) * AV_TIME_BASE;
|
||||||
} else if (av_strstart(line, "#", NULL)) {
|
} else if (av_strstart(line, "#", NULL)) {
|
||||||
continue;
|
continue;
|
||||||
} else if (line[0]) {
|
} else if (line[0]) {
|
||||||
@@ -383,7 +384,6 @@ restart:
|
|||||||
int64_t reload_interval = v->n_segments > 0 ?
|
int64_t reload_interval = v->n_segments > 0 ?
|
||||||
v->segments[v->n_segments - 1]->duration :
|
v->segments[v->n_segments - 1]->duration :
|
||||||
v->target_duration;
|
v->target_duration;
|
||||||
reload_interval *= 1000000;
|
|
||||||
|
|
||||||
reload:
|
reload:
|
||||||
if (!v->finished &&
|
if (!v->finished &&
|
||||||
@@ -393,7 +393,7 @@ reload:
|
|||||||
/* If we need to reload the playlist again below (if
|
/* If we need to reload the playlist again below (if
|
||||||
* there's still no more segments), switch to a reload
|
* there's still no more segments), switch to a reload
|
||||||
* interval of half the target duration. */
|
* interval of half the target duration. */
|
||||||
reload_interval = v->target_duration * 500000;
|
reload_interval = v->target_duration / 2;
|
||||||
}
|
}
|
||||||
if (v->cur_seq_no < v->start_seq_no) {
|
if (v->cur_seq_no < v->start_seq_no) {
|
||||||
av_log(NULL, AV_LOG_WARNING,
|
av_log(NULL, AV_LOG_WARNING,
|
||||||
@@ -481,7 +481,7 @@ static int hls_read_header(AVFormatContext *s)
|
|||||||
int64_t duration = 0;
|
int64_t duration = 0;
|
||||||
for (i = 0; i < c->variants[0]->n_segments; i++)
|
for (i = 0; i < c->variants[0]->n_segments; i++)
|
||||||
duration += c->variants[0]->segments[i]->duration;
|
duration += c->variants[0]->segments[i]->duration;
|
||||||
s->duration = duration * AV_TIME_BASE;
|
s->duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the demuxer for each variant */
|
/* Open the demuxer for each variant */
|
||||||
@@ -717,7 +717,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
|
|||||||
s->streams[stream_index]->time_base.den,
|
s->streams[stream_index]->time_base.den,
|
||||||
flags & AVSEEK_FLAG_BACKWARD ?
|
flags & AVSEEK_FLAG_BACKWARD ?
|
||||||
AV_ROUND_DOWN : AV_ROUND_UP);
|
AV_ROUND_DOWN : AV_ROUND_UP);
|
||||||
timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ?
|
timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, stream_index >= 0 ?
|
||||||
s->streams[stream_index]->time_base.den :
|
s->streams[stream_index]->time_base.den :
|
||||||
AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
|
AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
|
||||||
AV_ROUND_DOWN : AV_ROUND_UP);
|
AV_ROUND_DOWN : AV_ROUND_UP);
|
||||||
@@ -730,9 +730,8 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
|
|||||||
for (i = 0; i < c->n_variants; i++) {
|
for (i = 0; i < c->n_variants; i++) {
|
||||||
/* Reset reading */
|
/* Reset reading */
|
||||||
struct variant *var = c->variants[i];
|
struct variant *var = c->variants[i];
|
||||||
int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 :
|
int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ?
|
||||||
av_rescale_rnd(c->first_timestamp, 1, AV_TIME_BASE,
|
0 : c->first_timestamp;
|
||||||
flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
|
|
||||||
if (var->input) {
|
if (var->input) {
|
||||||
ffurl_close(var->input);
|
ffurl_close(var->input);
|
||||||
var->input = NULL;
|
var->input = NULL;
|
||||||
|
Reference in New Issue
Block a user