[FFmpeg-cvslog] avformat/hls: Fixes overwriting existing #EXT-X-PROGRAM-DATE-TIME value in HLS playlist
Vignesh Ravichandran
git at videolan.org
Tue Dec 8 14:57:34 EET 2020
ffmpeg | branch: master | Vignesh Ravichandran <vignesh.ravichandran02 at gmail.com> | Tue Dec 1 15:58:40 2020 +0530| [45a673ebee2e603a87c0ecb259c0027c14321018] | committer: liuqi05
avformat/hls: Fixes overwriting existing #EXT-X-PROGRAM-DATE-TIME value in HLS playlist
fix ticket: 8989
This is is due to the following behavior in the current code:
1. The initial_prog_date_time gets set to the current local time
2. The existing playlist (.m3u8) file gets parsed and the segments
present are added to the variant stream
3. The new segment is created and added
4. The existing segments and the new segment are written to the
playlist file. The initial_prog_date_time from point 1 is used
for calculating "#EXT-X-PROGRAM-DATE-TIME" for the segments,
which results in incorrect "#EXT-X-PROGRAM-DATE-TIME" values
for existing segments
The following approach fixes this bug:
1. Add a new variable "discont_program_date_time" of type double
to HLSSegment struct
2. Store the "EXT-X-PROGRAM-DATE-TIME" value from the existing
segments in this variable
3. When writing to playlist file if "discont_program_date_time"
is set, then use that value for "EXT-X-PROGRAM-DATE-TIME" else
use the value present in vs->initial_prog_date_time
Signed-off-by: Vignesh Ravichandran <vignesh.ravichandran02 at gmail.com>
Signed-off-by: liuqi05 <liuqi05 at kuaishou.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=45a673ebee2e603a87c0ecb259c0027c14321018
---
libavformat/hlsenc.c | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index cbfd8f7c0d..9bce374605 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -88,6 +88,7 @@ typedef struct HLSSegment {
char iv_string[KEYSIZE*2 + 1];
struct HLSSegment *next;
+ double discont_program_date_time;
} HLSSegment;
typedef enum HLSFlags {
@@ -1124,6 +1125,7 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls,
en->keyframe_size = vs->video_keyframe_size;
en->next = NULL;
en->discont = 0;
+ en->discont_program_date_time = 0;
if (vs->discontinuity) {
en->discont = 1;
@@ -1148,7 +1150,8 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls,
if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
en = vs->segments;
- vs->initial_prog_date_time += en->duration;
+ if (!en->next->discont_program_date_time && !en->discont_program_date_time)
+ vs->initial_prog_date_time += en->duration;
vs->segments = en->next;
if (en && hls->flags & HLS_DELETE_SEGMENTS &&
#if FF_API_HLS_WRAP
@@ -1182,6 +1185,7 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs
char line[MAX_URL_SIZE];
const char *ptr;
const char *end;
+ double discont_program_date_time = 0;
if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
&s->interrupt_callback, NULL,
@@ -1236,7 +1240,25 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs
av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string));
}
}
+ } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
+ struct tm program_date_time;
+ int y,M,d,h,m,s;
+ double ms;
+ if (sscanf(ptr, "%d-%d-%dT%d:%d:%d.%lf", &y, &M, &d, &h, &m, &s, &ms) != 7) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ program_date_time.tm_year = y - 1900;
+ program_date_time.tm_mon = M - 1;
+ program_date_time.tm_mday = d;
+ program_date_time.tm_hour = h;
+ program_date_time.tm_min = m;
+ program_date_time.tm_sec = s;
+ program_date_time.tm_isdst = -1;
+ discont_program_date_time = mktime(&program_date_time);
+ discont_program_date_time += (double)(ms / 1000);
} else if (av_strstart(line, "#", NULL)) {
continue;
} else if (line[0]) {
@@ -1250,8 +1272,9 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs
is_segment = 0;
new_start_pos = avio_tell(vs->avf->pb);
vs->size = new_start_pos - vs->start_pos;
- vs->initial_prog_date_time -= vs->duration; // this is a previously existing segment
ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
+ vs->last_segment->discont_program_date_time = discont_program_date_time;
+ discont_program_date_time += vs->duration;
if (ret < 0)
goto fail;
vs->start_pos = new_start_pos;
@@ -1572,7 +1595,11 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
en->duration, hls->flags & HLS_ROUND_DURATIONS,
en->size, en->pos, hls->baseurl,
- en->filename, prog_date_time_p, en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY);
+ en->filename,
+ en->discont_program_date_time ? &en->discont_program_date_time : prog_date_time_p,
+ en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY);
+ if (en->discont_program_date_time)
+ en->discont_program_date_time -= en->duration;
if (ret < 0) {
av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
}
More information about the ffmpeg-cvslog
mailing list