From patchwork Wed Sep 7 19:34:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 468 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.134 with SMTP id o128csp469000vsd; Wed, 7 Sep 2016 12:38:32 -0700 (PDT) X-Received: by 10.194.200.36 with SMTP id jp4mr48125369wjc.26.1473277111456; Wed, 07 Sep 2016 12:38:31 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b75si5142505wma.30.2016.09.07.12.38.28; Wed, 07 Sep 2016 12:38:31 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C67A068A1B2; Wed, 7 Sep 2016 22:38:15 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from vie01a-dmta-pe01-2.mx.upcmail.net (vie01a-dmta-pe01-2.mx.upcmail.net [62.179.121.155]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 22EFD68A19D for ; Wed, 7 Sep 2016 22:38:10 +0300 (EEST) Received: from [172.31.216.43] (helo=vie01a-pemc-psmtp-pe01) by vie01a-dmta-pe01.mx.upcmail.net with esmtp (Exim 4.87) (envelope-from ) id 1bhifr-0001lZ-8S for ffmpeg-devel@ffmpeg.org; Wed, 07 Sep 2016 21:38:19 +0200 Received: from localhost ([213.47.41.20]) by vie01a-pemc-psmtp-pe01 with SMTP @ mailcloud.upcmail.net id gjeH1t00Z0S5wYM01jeJUu; Wed, 07 Sep 2016 21:38:19 +0200 X-SourceIP: 213.47.41.20 From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Wed, 7 Sep 2016 21:34:44 +0200 Message-Id: <20160907193444.27361-1-michael@niedermayer.cc> X-Mailer: git-send-email 2.9.3 Subject: [FFmpeg-devel] [PATCH] avformat/hlsenc: implement program_date_time 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" TODO: docs, version bump Signed-off-by: Michael Niedermayer --- libavformat/hlsenc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index c0b5ef2..a376312 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -64,6 +64,7 @@ typedef enum HLSFlags { HLS_OMIT_ENDLIST = (1 << 4), HLS_SPLIT_BY_TIME = (1 << 5), HLS_APPEND_LIST = (1 << 6), + HLS_PROGRAM_DATE_TIME = (1 << 7), } HLSFlags; typedef enum { @@ -128,6 +129,7 @@ typedef struct HLSContext { char *method; + double initial_prog_date_time; } HLSContext; static int hls_delete_old_segments(HLSContext *hls) { @@ -481,6 +483,7 @@ static int hls_window(AVFormatContext *s, int last) char *key_uri = NULL; char *iv_string = NULL; AVDictionary *options = NULL; + double prog_date_time = hls->initial_prog_date_time; if (!use_rename && !warned_non_file++) av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporarly partial files\n"); @@ -533,6 +536,19 @@ static int hls_window(AVFormatContext *s, int last) if (hls->flags & HLS_SINGLE_FILE) avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n", en->size, en->pos); + if (hls->flags & HLS_PROGRAM_DATE_TIME) { + time_t tt; + int milli; + struct tm *tm, tmpbuf; + char buf0[128], buf1[128]; + tt = (int64_t)prog_date_time; + milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999); + tm = localtime_r(&tt, &tmpbuf); + strftime(buf0, sizeof(buf0), "%FT%T", tm); + strftime(buf1, sizeof(buf1), "%z", tm); + avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1); + prog_date_time += en->duration; + } if (hls->baseurl) avio_printf(out, "%s", hls->baseurl); avio_printf(out, "%s\n", en->filename); @@ -710,6 +726,12 @@ static int hls_write_header(AVFormatContext *s) hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; hls->start_pts = AV_NOPTS_VALUE; + if (hls->flags & HLS_PROGRAM_DATE_TIME) { + time_t now0; + time(&now0); + hls->initial_prog_date_time = now0; + } + if (hls->format_options_str) { ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0); if (ret < 0) { @@ -1005,6 +1027,7 @@ static const AVOption options[] = { {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"}, {"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX, E, "flags"}, {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, "flags"}, + {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, "flags"}, {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" },