From patchwork Thu Aug 11 15:04:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Liu X-Patchwork-Id: 156 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.67 with SMTP id o64csp114838vsd; Thu, 11 Aug 2016 08:10:50 -0700 (PDT) X-Received: by 10.194.123.228 with SMTP id md4mr9717808wjb.91.1470928250392; Thu, 11 Aug 2016 08:10:50 -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 d1si2899163wjf.18.2016.08.11.08.10.47; Thu, 11 Aug 2016 08:10:50 -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; dkim=neutral (body hash did not verify) header.i=@gmail.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; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DE1AC68A5F7; Thu, 11 Aug 2016 18:10:38 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk0-f169.google.com (mail-qk0-f169.google.com [209.85.220.169]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C000768A60E for ; Thu, 11 Aug 2016 18:10:28 +0300 (EEST) Received: by mail-qk0-f169.google.com with SMTP id v123so7263256qkh.2 for ; Thu, 11 Aug 2016 08:10:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=ZdeY/n2ToDfwKVdFhTrzW9aV0+izqIX56Hgbuf+8hb4=; b=NcTmkA5J552s5CQuRlDRTouiEGl53W0oGvTCYowVLVThGohUZFpg2Ppu6zfAps1HrW MNHD39H6JrdTIT80lCbc7GbHJXHrfopVLNBQIYe3NbljbnxG2CQIzDjhAEC16p/avTGl ZlqTDcMxRE9Nq0C35VC0+E6ajcXZLEDgvbj/q2lOPl1JyTOvKUFm8uD2D1PkWppXg4rk w5tWu51OWnXD4AGWzJsyR4ZpFMwayodsosJeFOZ3DbsatbrqxlR05htrnUHCkR/kW//q ZY+NvGU2rwOjLzYhbrgOMhb5UfoSeMldWFfFa0FlEYFQ9NRzcxJH4opfy6V6FTZtvh99 hlsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=ZdeY/n2ToDfwKVdFhTrzW9aV0+izqIX56Hgbuf+8hb4=; b=mJOkuDnA+rR29xFaqZWImmnYN+YoTuPGyR6eiOMtVcOhMOZwNqKy4OpiQf+B/ZXK3R uoGv6j2OuZHauPOcv7DKogmIen1mkauAN+JrsAed0Cc5HaqwGTRys1RoZLmClqMIGsBA C208PCYG+BoGPuRevRTvOjp8hJRWFHXr5HS3DTeT15zEhok9QgWQADIs2Y+QoFXzCpna GlJZK5VROQM59UDPrz1F6RabzeWR5ylcc6+K7bAvGAsTKTWfLnX1El9Cio5LeH4Z8Rsa kV7wX3kp3YK7dmYU7Vam8GzpMfSE2p6MuSQlBvVRT57yWTlptQ+XtPM/Gg1Z51zKqjFx h00g== X-Gm-Message-State: AEkooutM25LnGZbK4bvOlX6eYSZn7d71dAQciExv+Qd7g7AcCObBQm7Vbvb055e1MuEpagJGzgNbm/VLn5arLA== X-Received: by 10.55.104.150 with SMTP id d144mr11068120qkc.147.1470927884295; Thu, 11 Aug 2016 08:04:44 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.99.85 with HTTP; Thu, 11 Aug 2016 08:04:43 -0700 (PDT) From: Steven Liu Date: Thu, 11 Aug 2016 23:04:43 +0800 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] [PATCH] add append_list flag into hlsenc 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" When ffmpeg exit by exception, start a new ffmpeg will cover the old segment list, add this flag can continue append the new segments into old hls segment list Signed-off-by: LiuQi --- doc/muxers.texi | 4 ++++ libavformat/hlsenc.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) static void hls_free_segments(HLSSegment *p) { HLSSegment *en; @@ -752,6 +810,10 @@ static int hls_write_header(AVFormatContext *s) if ((ret = hls_mux_init(s)) < 0) goto fail; + if (hls->flags & HLS_APPEND_LIST) { + parse_playlist(s, s->filename); + } + if ((ret = hls_start(s)) < 0) goto fail; @@ -927,6 +989,7 @@ static const AVOption options[] = { {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"}, {"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"}, {"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" }, -- 2.7.4 (Apple Git-66) diff --git a/doc/muxers.texi b/doc/muxers.texi index 5873269..2e95c6f 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -495,6 +495,10 @@ Will produce the playlist, @file{out.m3u8}, and a single segment file, Segment files removed from the playlist are deleted after a period of time equal to the duration of the segment plus the duration of the playlist. +@item hls_flags append_list +Append new segments into the end of old segment list, +and remove the @code{#EXT-X-ENDLIST} from the old segment list. + @item hls_flags round_durations Round the duration info in the playlist file segment info to integer values, instead of using floating point. diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 9f076ba..a570db4 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -63,6 +63,7 @@ typedef enum HLSFlags { HLS_DISCONT_START = (1 << 3), HLS_OMIT_ENDLIST = (1 << 4), HLS_SPLIT_BY_TIME = (1 << 5), + HLS_APPEND_LIST = (1 << 6), } HLSFlags; typedef enum { @@ -265,6 +266,14 @@ static int hls_encryption_start(AVFormatContext *s) return 0; } +static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) +{ + int len = ff_get_line(s, buf, maxlen); + while (len > 0 && av_isspace(buf[len - 1])) + buf[--len] = '\0'; + return len; +} + static int hls_mux_init(AVFormatContext *s) { HLSContext *hls = s->priv_data; @@ -389,6 +398,55 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double return 0; } +static int parse_playlist(AVFormatContext *s, const char *url) +{ + HLSContext *hls = s->priv_data; + AVIOContext *in; + int ret = 0, is_segment = 0; + int64_t new_start_pos; + int64_t duration = 0; + char line[1024]; + const char *ptr; + + if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ, + &s->interrupt_callback, NULL, + s->protocol_whitelist, s->protocol_blacklist)) < 0) + return ret; + + read_chomp_line(in, line, sizeof(line)); + if (strcmp(line, "#EXTM3U")) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + while (!avio_feof(in)) { + read_chomp_line(in, line, sizeof(line)); + if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { + duration = atoi(ptr); + } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { + hls->sequence = atoi(ptr); + } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { + } else if (av_strstart(line, "#EXTINF:", &ptr)) { + is_segment = 1; + hls->duration = atof(ptr); + } else if (av_strstart(line, "#", NULL)) { + continue; + } else if (line[0]) { + if (is_segment) { + new_start_pos = avio_tell(hls->avf->pb); + hls->size = new_start_pos - hls->start_pos; + av_strlcpy(hls->avf->filename, line, sizeof(line)); + hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size); + is_segment = 0; + } + } + } + +fail: + avio_close(in); + return ret; +} +