From patchwork Tue Aug 1 15:57:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liu Steven X-Patchwork-Id: 4576 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.46.211 with SMTP id u202csp129170vsu; Tue, 1 Aug 2017 08:58:06 -0700 (PDT) X-Received: by 10.223.169.131 with SMTP id b3mr17161544wrd.126.1501603086558; Tue, 01 Aug 2017 08:58:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501603086; cv=none; d=google.com; s=arc-20160816; b=dGGK7VJL0VU+RTyna+tId1v1nnbvgxCLGTjoQpk8fT6+08194DQzgKUMKXEx2AkBII 2QIEiZJF+gc0H8+Iq6Mbd6qgn6atOAmIh8j9c6ByFXMlYC6bF+wJwZV3k1yL0xN9lVWp 3tjPA3ziFo0KffSSAOY/Myw6sPJARppVAMgUBiOhejMngCijSUmExA9Ue5XR0loLMNz5 byeiYQj2jpV6+SOfqngFw9lHMaVrodSMIJTp8xaKRCb877cd5+QGVfN3Hybzr8q/s2/p G2hOq19dj5c1OsuLgSTvqU+/7m+EtR589Af39dD6HrhScr94+W8GLgWjyOUoGqTOebKy fakg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:feedback-id:references:in-reply-to :message-id:date:to:from:delivered-to:arc-authentication-results; bh=7DB88VLmOQ3pG5vwnjW3bHqXjjBVOJHCTQhiUA3VyK4=; b=PnsYjfZYQxHRbRXSAzarBTPldXQyVfaop61D6sZYjR4J/42YlDl9CysWPPsV4630Qj 4W9ddKg4mx00kiyJJpaH/J7B1QLfT9hZBST1o/rNeL3mgZeZTKrjki/N8MExAcpp8nxV LDwJTY0jcPw4wKxcJH9VtSFOdcZNojfY4qoeU3xqOA/sr4gTY5HTmP/UILPFGi2kUbBd fe7B5eKaORHWJKiC5vO36A8ylEAyrpB4MB2/g1b4BOhXVju23WK2GZ/NzBWHt1Xntf5q vMRN2nj92jBVA/nSfrxAk0mf5d/f+xGNMvP/Wdm4TMLwsw+gdN/yH0K0scTB+DVRCvXQ Pwzw== ARC-Authentication-Results: i=1; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o130si1454839wmg.195.2017.08.01.08.58.05; Tue, 01 Aug 2017 08:58:06 -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 4A0E568A499; Tue, 1 Aug 2017 18:57:59 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtpbg352.qq.com (SMTPBG352.QQ.COM [183.57.50.167]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8722068A398 for ; Tue, 1 Aug 2017 18:57:52 +0300 (EEST) X-QQ-mid: bizesmtp15t1501603031t9avr9wh Received: from localhost (unknown [114.254.179.173]) by esmtp4.qq.com (ESMTP) with id ; Tue, 01 Aug 2017 23:57:10 +0800 (CST) X-QQ-SSF: 01100000004000F0FH50B00A0000000 X-QQ-FEAT: IBShUBz8YqQW1IxTOXLBCwj4B6RYDmqTjVmb/8jhCY9qIhjKTAa0zPIo6GmBT SdG1pfUcYEwC5yhFWaFgHz0+q8Ea9BhzLvWcwOdn4+LqkDoNTgZVYOlghqrPwMQwZjA7bMg G5AFraESYO2SJsw2xjiR+SCj7wOpqN+Py6NUMS6Ln5Q8KbKMINfc3dkbUe+YNH8lXce5k+J hYVrIYq7UMD7XQjRF63DXwjbrNrcAuHUBg18W1aWegbbdPll0iWu/5Nmat2OtuU4A+YejsR f3MuK+j26hxDEH X-QQ-GoodBg: 0 From: Steven Liu To: ffmpeg-devel@ffmpeg.org Date: Tue, 1 Aug 2017 23:57:03 +0800 Message-Id: <20170801155703.29117-1-lq@chinaffmpeg.org> X-Mailer: git-send-email 2.11.0 (Apple Git-81) In-Reply-To: <7fa41165-fb44-bd36-1c90-1980da5e6a8d@gmail.com> References: <7fa41165-fb44-bd36-1c90-1980da5e6a8d@gmail.com> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:chinaffmpeg.org:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [FFmpeg-devel] [PATCH v2] avformat/hlsenc: support fmp4 single file mode 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: Steven Liu , Steven Liu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" add byterange mode of the hls fmp4 Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 83 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index f98f04100c..9f8472bb87 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -531,6 +531,7 @@ static int hls_mux_init(AVFormatContext *s) HLSContext *hls = s->priv_data; AVFormatContext *oc; AVFormatContext *vtt_oc = NULL; + int byterange_mode = ((hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0)); int i, ret; ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL); @@ -584,7 +585,11 @@ static int hls_mux_init(AVFormatContext *s) hls->fmp4_init_mode = 0; if (hls->segment_type == SEGMENT_TYPE_FMP4) { - hls->fmp4_init_mode = 1; + if (hls->max_seg_size > 0) { + av_log(s, AV_LOG_WARNING, "Have not support multiple fmp4 byterange mode file in hls yet now\n"); + return AVERROR_PATCHWELCOME; + } + hls->fmp4_init_mode = !byterange_mode; if ((ret = s->io_open(s, &oc->pb, hls->base_output_dirname, AVIO_FLAG_WRITE, NULL)) < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename); return ret; @@ -780,7 +785,7 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double { HLSSegment *en = av_malloc(sizeof(*en)); const char *filename; - int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); + int byterange_mode = ((hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0)); int ret; if (!en) @@ -980,9 +985,6 @@ static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version } avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration); avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - avio_printf(out, "#EXT-X-MAP:URI=\"%s\"\n", hls->fmp4_init_filename); - } av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence); } @@ -1015,7 +1017,7 @@ static int hls_window(AVFormatContext *s, int last) char *iv_string = NULL; AVDictionary *options = NULL; double prog_date_time = hls->initial_prog_date_time; - int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); + int byterange_mode = ((hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0)); if (byterange_mode) { version = 4; @@ -1066,13 +1068,21 @@ static int hls_window(AVFormatContext *s, int last) avio_printf(out, "#EXT-X-DISCONTINUITY\n"); } - if (hls->flags & HLS_ROUND_DURATIONS) - avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration)); - else - avio_printf(out, "#EXTINF:%f,\n", en->duration); - if (byterange_mode) - avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n", - en->size, en->pos); + if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments)) { + avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", hls->fmp4_init_filename); + if (hls->flags & HLS_SINGLE_FILE) { + avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", en->size, en->pos); + } + avio_printf(out, "\n"); + } else { + if (hls->flags & HLS_ROUND_DURATIONS) + avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration)); + else + avio_printf(out, "#EXTINF:%f,\n", en->duration); + if (byterange_mode) + avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", + en->size, en->pos); + } if (hls->flags & HLS_PROGRAM_DATE_TIME) { time_t tt, wrongsecs; int milli; @@ -1097,9 +1107,11 @@ static int hls_window(AVFormatContext *s, int last) 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); + if (!((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments))) { + if (hls->baseurl) + avio_printf(out, "%s", hls->baseurl); + avio_printf(out, "%s\n", en->filename); + } } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) @@ -1262,7 +1274,7 @@ static int hls_start(AVFormatContext *s) } av_dict_free(&options); - if (c->segment_type == SEGMENT_TYPE_FMP4) { + if (c->segment_type == SEGMENT_TYPE_FMP4 && !(c->flags & HLS_SINGLE_FILE)) { write_styp(oc->pb); } else { /* We only require one PAT/PMT per segment. */ @@ -1315,15 +1327,10 @@ static int hls_write_header(AVFormatContext *s) const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); const char *vtt_pattern = "%d.vtt"; AVDictionary *options = NULL; - int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); int basename_size; int vtt_basename_size; if (hls->segment_type == SEGMENT_TYPE_FMP4) { - if (byterange_mode) { - av_log(s, AV_LOG_WARNING, "Have not support fmp4 byterange mode yet now\n"); - return AVERROR_PATCHWELCOME; - } pattern = "%d.m4s"; } if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) || @@ -1400,8 +1407,13 @@ static int hls_write_header(AVFormatContext *s) goto fail; } } else { - if (hls->flags & HLS_SINGLE_FILE) - pattern = ".ts"; + if (hls->flags & HLS_SINGLE_FILE) { + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + pattern = ".m4s"; + } else { + pattern = ".ts"; + } + } if (hls->use_localtime) { basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1; @@ -1490,6 +1502,14 @@ static int hls_write_header(AVFormatContext *s) av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size); } + if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) { + hls->fmp4_init_filename = av_strdup(hls->basename); + if (!hls->fmp4_init_filename) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + if ((ret = hls_mux_init(s)) < 0) goto fail; @@ -1504,7 +1524,7 @@ static int hls_write_header(AVFormatContext *s) } } - if (hls->segment_type != SEGMENT_TYPE_FMP4) { + if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) { if ((ret = hls_start(s)) < 0) goto fail; } @@ -1545,6 +1565,7 @@ fail: av_dict_free(&options); if (ret < 0) { + av_freep(&hls->fmp4_init_filename); av_freep(&hls->basename); av_freep(&hls->vtt_basename); av_freep(&hls->key_basename); @@ -1615,7 +1636,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; char *old_filename = av_strdup(hls->avf->filename); - int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); + int byterange_mode = ((hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0)); if (!old_filename) { return AVERROR(ENOMEM); @@ -1643,7 +1664,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) hls->number--; } - if (!hls->fmp4_init_mode) + if (!hls->fmp4_init_mode || byterange_mode) ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size); hls->start_pos = new_start_pos; @@ -1679,9 +1700,10 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } - if ((ret = hls_window(s, 0)) < 0) { - return ret; - } + if (!hls->fmp4_init_mode || byterange_mode) + if ((ret = hls_window(s, 0)) < 0) { + return ret; + } } ret = ff_write_chained(oc, stream_index, pkt, s, 0); @@ -1722,6 +1744,7 @@ static int hls_write_trailer(struct AVFormatContext *s) hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos; ff_format_io_close(s, &vtt_oc->pb); } + av_freep(&hls->fmp4_init_filename); av_freep(&hls->basename); av_freep(&hls->base_output_dirname); av_freep(&hls->key_basename);