From patchwork Wed Nov 25 05:16:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vignesh Ravichandran X-Patchwork-Id: 24028 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7FBBC44A695 for ; Wed, 25 Nov 2020 07:25:00 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4E14068BCE3; Wed, 25 Nov 2020 07:25:00 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f195.google.com (mail-oi1-f195.google.com [209.85.167.195]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B672068BC02 for ; Wed, 25 Nov 2020 07:24:53 +0200 (EET) Received: by mail-oi1-f195.google.com with SMTP id c80so1539043oib.2 for ; Tue, 24 Nov 2020 21:24:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=x9yuAGx1vmz1S1VK3L0tfzB3h1GAmhNPqQttUL1Svys=; b=iZkOdGuh1eK2Jl1EVJM0sVstqjOl7he15373sUOV399fGiSPEee27ojGhgntI+qy8w JRjFtloMCNPDOrT/GdpG70me3qwe0OUSIDxdo4HtqfCO/ryeV8oFm7XTZHjvrZsSOQPh 37MMx/v+6yJst+xl3VqnDkv+Lg7S8DPKSx/IxB9b5bRyjWq8jOWXl9WvUWwNwhYcTvzx lDDTZH/UcaCc3cG0GI83coqamZVoW4KYydGDdrkmwxQ23e4S49noGRxkMoh5Qq9hdOmn ynTS9tZB54UG+GP00bW/6lKNCsCN4yMPSINaHDsVB92mRqXbDdgqZurpmsb13VyPJcjO VALA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=x9yuAGx1vmz1S1VK3L0tfzB3h1GAmhNPqQttUL1Svys=; b=cqKKaumbdjYJWiuahRoZrhgT7I+c4ImtNOLldktXrcEJ1/2L+gXLsnIoGbzjuDEhqZ ZmBS8aick1PQES3j/Y7+qDby2ou7sY/t5jRibZ18V8HHFnEMSQlRg/Ftu3q0UThTk06q EBor37cyOZXI3c6gd2bh5LD4nEtg1yexLXo9ocNIZwcyBDYw47fbqB7dX8AQeKkoaiG/ iOJ+6B41SNPieVLa50MNrR+iUNiY+1Btm06FWvCVriVuhxgHYy+T0gPuOpLDhieAjb8d 5c5q+aW9Q2XEZE0V8yJapcJFKUbyseMMXcFZzCfkC+CYlzQx73EXAjYKWOMOSSBQQDqu OSjQ== X-Gm-Message-State: AOAM533kimipKWjsX/CaPkjjVZTBLWqNqGkwWIIqixhISdG4fP+Nefi5 6xyO1ntXN5WaeSrc+khkYCdAYtXwpjoBhA== X-Google-Smtp-Source: ABdhPJyg4Zfr4z4zVLmGxQgagTuXDlZXPttnrPv77Xk6S36i7T/Q3ZPfgCVeUiFWqY6BdQtLVJfSKw== X-Received: by 2002:a17:90a:dc16:: with SMTP id i22mr2172777pjv.32.1606281470822; Tue, 24 Nov 2020 21:17:50 -0800 (PST) Received: from localhost.localdomain ([122.164.136.135]) by smtp.gmail.com with ESMTPSA id m13sm673247pfa.115.2020.11.24.21.17.48 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 24 Nov 2020 21:17:49 -0800 (PST) From: Vignesh Ravichandran To: ffmpeg-devel@ffmpeg.org Date: Wed, 25 Nov 2020 10:46:45 +0530 Message-Id: <20201125051645.35202-1-vignesh.ravichandran02@gmail.com> X-Mailer: git-send-email 2.24.2 (Apple Git-127) MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avformat/hls: Fixes overwriting existing #EXT-X-PROGRAM-DATE-TIME value in HLS playlist X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Vignesh Ravichandran Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Bug ID: 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 --- libavformat/hlsenc.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index cbfd8f7c0d..030a2d3b97 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,8 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs char line[MAX_URL_SIZE]; const char *ptr; const char *end; + int is_discont_detected = 0; + double discont_program_date_time = 0; if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ, &s->interrupt_callback, NULL, @@ -1211,6 +1216,7 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) { is_segment = 1; vs->discontinuity = 1; + is_discont_detected = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; vs->duration = atof(ptr); @@ -1236,7 +1242,23 @@ 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) && is_discont_detected) { + struct tm program_date_time; + int y,M,d,h,m,s; + double ms; + sscanf(ptr, "%d-%d-%dT%d:%d:%d.%lf", &y, &M, &d, &h, &m, &s, &ms); + + 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); + is_discont_detected = 0; } 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"); }