From patchwork Wed Jan 23 11:24:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liu Steven X-Patchwork-Id: 11840 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 904CE44DDBE for ; Wed, 23 Jan 2019 13:24:28 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B4D3D68AC4D; Wed, 23 Jan 2019 13:24:16 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BB9DB68AC30 for ; Wed, 23 Jan 2019 13:24:08 +0200 (EET) X-QQ-mid: bizesmtp6t1548242659tpunwe7sd Received: from localhost (unknown [43.247.177.226]) by esmtp6.qq.com (ESMTP) with id ; Wed, 23 Jan 2019 19:24:18 +0800 (CST) X-QQ-SSF: 01100000002000K0ZNF1000A0000000 X-QQ-FEAT: DW7AxydIg/t/QQB20hysRP1xzMBDo+x7izkSi1yneyZxZpMHPEtMceMjRJvwM mY2h5eHskayCVjgqaSMorbQsqrVpIubaWeXqzGHnZ500E8UFtuHIZbeSNgM+axACqwrq6uk DIGXrwMgWZ0wV0eyHuWFuz2Hn8P0K/isWxh+damAKPO2vyHhyl8uJQ6RXpNe04ORvyopvFZ NAsvhbhdR0VXu3m94xK80cwMrqLH7Fo5a9YrXMcViU+VkspkNDlD0Ot1OCqBhM2ca4OLtnC AA8dLfvgZZ5kehrWG/5Nx/GIz7KiGDzkLni+KFwfxgZu3u X-QQ-GoodBg: 0 From: Steven Liu To: ffmpeg-devel@ffmpeg.org Date: Wed, 23 Jan 2019 19:24:09 +0800 Message-Id: <20190123112410.75235-2-lq@chinaffmpeg.org> X-Mailer: git-send-email 2.15.2 (Apple Git-101.1) In-Reply-To: <20190123112410.75235-1-lq@chinaffmpeg.org> References: <20190123112410.75235-1-lq@chinaffmpeg.org> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:chinaffmpeg.org:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Subject: [FFmpeg-devel] [PATCH 2/3] avformat/hlsenc: add var_stream_map DEFAULT field status parameter 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" use a:0,agroup:aud_low,default:Yes a:1,agroup:aud_low, a:2,agroup:aud_high,default:Yes a:3, agroup:aud_high, v:0,agroup:aud_low v:1,agroup:aud_high create master m3u8 list. result: EXTM3U EXT-X-VERSION:3 EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud_low",NAME="audio_0",DEFAULT=YES,URI="out_0.m3u8" EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud_low",NAME="audio_1",DEFAULT=NO,URI="out_1.m3u8" EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud_high",NAME="audio_2",DEFAULT=YES,URI="out_2.m3u8" EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud_high",NAME="audio_3",DEFAULT=NO,URI="out_3.m3u8" EXT-X-STREAM-INF:BANDWIDTH=1170400,RESOLUTION=640x480,CODECS="avc1.64001e,mp4a.40.2",AUDIO="group_aud_low" out_4.m3u8 EXT-X-STREAM-INF:BANDWIDTH=3440800,RESOLUTION=640x480,CODECS="avc1.64001e,mp4a.40.2",AUDIO="group_aud_high" out_5.m3u8 Signed-off-by: Steven Liu --- doc/muxers.texi | 15 +++++++++++++++ libavformat/hlsenc.c | 29 ++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 4ed46a2220..f5d4f67b7e 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -965,6 +965,21 @@ and they are mapped to the two video only variant streams with audio group names By default, a single hls variant containing all the encoded streams is created. +@example +ffmpeg -re -i in.ts -b:a:0 32k -b:a:1 64k -b:v:0 1000k \ + -map 0:a -map 0:a -map 0:v -f hls \ + -var_stream_map "a:0,agroup:aud_low,default:yes a:1,agroup:aud_low v:0,agroup:aud_low" \ + -master_pl_name master.m3u8 \ + http://example.com/live/out_%v.m3u8 +@end example +This example creates two audio only and one video only variant streams. In +addition to the #EXT-X-STREAM-INF tag for each variant stream in the master +playlist, #EXT-X-MEDIA tag is also added for the two audio only variant streams +and they are mapped to the one video only variant streams with audio group name +'aud_low', and the audio group have default stat is NO or YES. + +By default, a single hls variant containing all the encoded streams is created. + @item cc_stream_map Map string which specifies different closed captions groups and their attributes. The closed captions stream groups are separated by space. diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index eb094f7490..e6628145f8 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -153,6 +153,7 @@ typedef struct VariantStream { CodecAttributeStatus attr_status; unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ + int is_default; /* default status of audio group */ char *agroup; /* audio group name */ char *ccgroup; /* closed caption group name */ char *baseurl; @@ -228,6 +229,8 @@ typedef struct HLSContext { AVIOContext *sub_m3u8_out; int64_t timeout; int ignore_io_errors; + int has_default_key; /* has DEFAULT field of var_stream_map */ + int has_video_m3u8; /* has video stream m3u8 list */ } HLSContext; static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, @@ -1258,7 +1261,7 @@ static int create_master_playlist(AVFormatContext *s, goto fail; } - ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, i, 1); + ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, i, hls->has_default_key ? vs->is_default : 1); av_freep(&m3u8_rel_name); } @@ -1336,8 +1339,15 @@ static int create_master_playlist(AVFormatContext *s, vs->ccgroup); } - ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, - aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup); + if (!hls->has_default_key || !hls->has_video_m3u8) { + ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, + aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup); + } else { + if (vid_st) { + ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, + aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup); + } + } av_freep(&m3u8_rel_name); } @@ -1819,7 +1829,7 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) /** * Expected format for var_stream_map string is as below: * "a:0,v:0 a:1,v:1" - * "a:0,agroup:a0 a:1,agroup:a1 v:0,agroup:a0 v:1,agroup:a1" + * "a:0,agroup:a0,default:1 a:1,agroup:a1,defalut:0 v:0,agroup:a0 v:1,agroup:a1" * This string specifies how to group the audio, video and subtitle streams * into different variant streams. The variant stream groups are separated * by space. @@ -1850,6 +1860,7 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) if (nb_varstreams < hls->nb_varstreams) { vs = &(hls->var_streams[nb_varstreams]); vs->var_stream_idx = nb_varstreams; + vs->is_default = 0; nb_varstreams++; } else return AVERROR(EINVAL); @@ -1869,7 +1880,12 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) while (keyval = av_strtok(varstr, ",", &saveptr2)) { varstr = NULL; - if (av_strstart(keyval, "agroup:", &val)) { + if (av_strstart(keyval, "default:", &val)) { + vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) || + (!av_strncasecmp(val, "1", strlen("1")))); + hls->has_default_key = 1; + continue; + } else if (av_strstart(keyval, "agroup:", &val)) { vs->agroup = av_strdup(val); if (!vs->agroup) return AVERROR(ENOMEM); @@ -1881,6 +1897,7 @@ static int parse_variant_stream_mapstring(AVFormatContext *s) continue; } else if (av_strstart(keyval, "v:", &val)) { codec_type = AVMEDIA_TYPE_VIDEO; + hls->has_video_m3u8 = 1; } else if (av_strstart(keyval, "a:", &val)) { codec_type = AVMEDIA_TYPE_AUDIO; } else if (av_strstart(keyval, "s:", &val)) { @@ -2519,6 +2536,8 @@ static int hls_init(AVFormatContext *s) int vtt_basename_size = 0; int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; + hls->has_default_key = 0; + hls->has_video_m3u8 = 0; ret = update_variant_stream_info(s); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",