fix for ext-discontinuity

This commit is contained in:
Ninja Jiraiya 2023-08-21 01:46:33 +08:00
parent 5511102b0c
commit 7ad49b423e
1 changed files with 39 additions and 3 deletions

View File

@ -66,7 +66,9 @@ enum KeyType {
};
struct segment {
int64_t previous_duration;
int64_t duration;
int64_t start_time;
int64_t url_offset;
int64_t size;
char *url;
@ -716,7 +718,7 @@ static int parse_playlist(HLSContext *c, const char *url,
struct playlist *pls, AVIOContext *in)
{
int ret = 0, is_segment = 0, is_variant = 0;
int64_t duration = 0;
int64_t duration = 0, previous_duration1 = 0, previous_duration = 0, total_duration = 0;
enum KeyType key_type = KEY_NONE;
uint8_t iv[16] = "";
int has_iv = 0;
@ -874,6 +876,8 @@ static int parse_playlist(HLSContext *c, const char *url,
} else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
if (pls)
pls->finished = 1;
} else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
previous_duration = previous_duration1;
} else if (av_strstart(line, "#EXTINF:", &ptr)) {
is_segment = 1;
duration = atof(ptr) * AV_TIME_BASE;
@ -903,6 +907,14 @@ static int parse_playlist(HLSContext *c, const char *url,
ret = AVERROR(ENOMEM);
goto fail;
}
previous_duration1 += duration;
seg->previous_duration = previous_duration;
seg->start_time = total_duration;
total_duration += duration;
seg->duration = duration;
seg->key_type = key_type;
if (has_iv) {
memcpy(seg->iv, iv, sizeof(iv));
} else {
@ -949,8 +961,9 @@ static int parse_playlist(HLSContext *c, const char *url,
" set to default value to 1ms.\n", seg->url);
duration = 0.001 * AV_TIME_BASE;
}
seg->duration = duration;
seg->key_type = key_type;
// seg->duration = duration;
// seg->key_type = key_type;
dynarray_add(&pls->segments, &pls->n_segments, seg);
is_segment = 0;
@ -2257,6 +2270,29 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
ist->time_base,
AV_TIME_BASE_Q);
if (c->playlists[minplaylist]->finished) {
struct playlist *pls = c->playlists[minplaylist];
int seq_no = pls->cur_seq_no - pls->start_seq_no;
if (seq_no < pls->n_segments && s->streams[pkt->stream_index]) {
struct segment *seg = pls->segments[seq_no];
int64_t pred = av_rescale_q(seg->previous_duration,
AV_TIME_BASE_Q,
s->streams[pkt->stream_index]->time_base);
int64_t max_ts = av_rescale_q(seg->start_time + seg->duration,
AV_TIME_BASE_Q,
s->streams[pkt->stream_index]->time_base);
/* EXTINF duration is not precise enough */
max_ts += 2 * AV_TIME_BASE;
if (s->start_time > 0) {
max_ts += av_rescale_q(s->start_time,
AV_TIME_BASE_Q,
s->streams[pkt->stream_index]->time_base);
}
if (pkt->dts != AV_NOPTS_VALUE && pkt->dts + pred < max_ts) pkt->dts += pred;
if (pkt->pts != AV_NOPTS_VALUE && pkt->pts + pred < max_ts) pkt->pts += pred;
}
}
/* There may be more situations where this would be useful, but this at least
* handles newly probed codecs properly (i.e. request_probe by mpegts). */
if (ist->codecpar->codec_id != st->codecpar->codec_id) {