From patchwork Thu Dec 28 11:47:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jeyapal, Karthick" X-Patchwork-Id: 7000 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.79.195 with SMTP id r64csp9161537jad; Thu, 28 Dec 2017 03:48:20 -0800 (PST) X-Google-Smtp-Source: ACJfBotDZyqYwu8YNemTs8wZNZ5aIa/OnrH3h8rWn9dE12uzOlyMZBNBXe9P+DW1y1T63mlwOAl1 X-Received: by 10.223.199.203 with SMTP id y11mr33073490wrg.37.1514461700385; Thu, 28 Dec 2017 03:48:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1514461700; cv=none; d=google.com; s=arc-20160816; b=v9BW925lpfHHjiEPiTQANAvddNuyQkD/bUqElsDW+wKUBD04pZiVMdekpYKXFQWKOJ DTyYTdgmUHAJOuKIiKQ5/8a/Sn472F/DsrINJioY2yQ2PyL8UJ1b3FaiJ++VSXHlF2gg eKaKAhoNqoi0gAkdvBw/oLwZb5CWMT4xjvVWrEl/M1ebh/3h2unSCFLucstfxE1E7Kav xuOWAcqjh9uBimx+EuDpBYwlKbEAxdPxMx11VrNBXYID+dPtEHLHh9GfEYQVTni7Gx7E R2YXGwdsT6apokA4iqtsm3WXEPYRDIPZxFhdmtd1NwBrDjAKTm5uNDo7/nMeiGDQnzHo sJ9w== 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:dkim-signature:delivered-to :arc-authentication-results; bh=4+5Rf0YwdJfEDbC96jChSq04f+XSUkYIJZCJq53GxK4=; b=EjU0KJWCN46e8Mr68gIXbGim6SV3ZyVhZQ3vZJPk4c2pY8vjVRla3XetRjtKp47UtL EEGBSvhI0hVmWbqjw51Eh+EgBAlKGb0kNCvpHGQwxGejZFqsb0g0/3aabSL5pv1e/Jyn XAeHYcsvMk1TOMbu/kPJz77BRD8UEL6bMHT+em7H3plh3XCGyu+DkfHFOMSabLpcXx/G COwwY7PNGmMFhAcGGaT/VNleSBEr3k8cL9SnSByFuNiNL8IGzBM9wsgLUNvxfmMMxTx2 4WV2/c9LgAT4SqxgNiYaNMnstIDpm/2MK6/6CRF9BCthVIwS2XQ0d6I5sITy66Bo+dEp cgvw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@smtpservice.net header.s=m78bu0.a1-4.dyn header.b=JyfPreCG; 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=QUARANTINE sp=NONE dis=NONE) header.from=akamai.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id p71si19937171wrc.37.2017.12.28.03.48.19; Thu, 28 Dec 2017 03:48:20 -0800 (PST) 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=@smtpservice.net header.s=m78bu0.a1-4.dyn header.b=JyfPreCG; 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=QUARANTINE sp=NONE dis=NONE) header.from=akamai.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AEF5168997A; Thu, 28 Dec 2017 13:48:04 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from a2i831.smtp2go.com (a2i831.smtp2go.com [103.47.207.63]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BFA18689828 for ; Thu, 28 Dec 2017 13:47:57 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=smtpservice.net; s=m78bu0.a1-4.dyn; x=1514462597; h=Feedback-ID: X-Smtpcorp-Track:Message-Id:Date:Subject:To:From:Reply-To:Sender: List-Unsubscribe; bh=HbVd26UTQ+Qw84yU/TD2p6nbAFBVg+R6Qn40eGrpNE8=; b=JyfPreCG kPPLfVXnfAzLj7tvN7wzuuf0GUFeVsQ5vDsJzfCLaJzL0jboiXuigmA9PNWolp444SKxTQHC976mJ ewK22kxej2nTeEbAi/RJjmkIjPbtJMo3CHcP/WPqehT4vXjebRF8F/5qxYlL0YxffngVXjPPNQ1YX Jtg1/jJnsbSVr6E93eA0YqFf8Jo8dStvyiLLhPMvjjfyVsP/kyhqQGXJ71tRkvj+xcDzCfza8RUQ+ MsQ4qa4Qg6Sq/wVZMVF3Nwo/h/NZvF8QHA/xpcgyGfe9QIja9cULr+6gumkaO75NQQr2gqUU0HJmy WBnG4kPxeQWplqb77f26A37UpA==; From: Karthick J To: ffmpeg-devel@ffmpeg.org Date: Thu, 28 Dec 2017 17:17:51 +0530 Message-Id: <1514461671-23193-1-git-send-email-kjeyapal@akamai.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: References: X-Smtpcorp-Track: 1-lWfQDIIgh9G7.RJn5uud0N Feedback-ID: 337386m:337386asVRLGB:337386sqvWNSxmph:SMTPCORP X-Report-Abuse: Please forward a copy of this message, including all headers, to Subject: [FFmpeg-devel] [PATCH v2] avformat/hlsenc: Add CODECS attribute to master 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: Karthick Jeyapal MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Karthick Jeyapal --- libavformat/dashenc.c | 2 +- libavformat/hlsenc.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++- libavformat/hlsplaylist.c | 5 +++- libavformat/hlsplaylist.h | 3 ++- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 478a384..8797959 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -760,7 +760,7 @@ static int write_manifest(AVFormatContext *s, int final) AVStream *st = s->streams[i]; get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); ff_hls_write_stream_info(st, out, st->codecpar->bit_rate, - playlist_file, NULL); + playlist_file, NULL, NULL); } avio_close(out); if (use_rename) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 74f66ce..bb442f5 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -58,6 +58,11 @@ typedef enum { HLS_START_SEQUENCE_AS_FORMATTED_DATETIME = 2, // YYYYMMDDhhmmss } StartSequenceSourceType; +typedef enum { + CODEC_ATTRIBUTE_WRITTEN = 0, + CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN, +} CodecAttributeStatus; + #define KEYSIZE 16 #define LINE_BUFFER_SIZE 1024 #define HLS_MICROSECOND_UNIT 1000000 @@ -142,6 +147,8 @@ typedef struct VariantStream { int fmp4_init_mode; AVStream **streams; + char codec_attr[128]; + CodecAttributeStatus attr_status; unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ char *agroup; /* audio group name */ @@ -296,6 +303,51 @@ static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSCont } +static void write_codec_attr(AVStream *st, VariantStream *vs) { + int codec_strlen = strlen(vs->codec_attr); + char attr[32]; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + return; + if (vs->attr_status == CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN) + return; + + if (st->codecpar->codec_id == AV_CODEC_ID_H264) { + uint8_t *data = st->codecpar->extradata; + if ((data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) { + snprintf(attr, sizeof(attr), + "avc1.%02x%02x%02x", data[5], data[6], data[7]); + } else { + goto fail; + } + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) { + snprintf(attr, sizeof(attr), "mp4a.40.33"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) { + snprintf(attr, sizeof(attr), "mp4a.40.34"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + /* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 5 and 29 respectively */ + snprintf(attr, sizeof(attr), "mp4a.40.2"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { + snprintf(attr, sizeof(attr), "ac-3"); + } else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3) { + snprintf(attr, sizeof(attr), "ec-3"); + } else { + goto fail; + } + // Don't write the same attribute multiple times + if (!av_stristr(vs->codec_attr, attr)) { + snprintf(vs->codec_attr + codec_strlen, + sizeof(vs->codec_attr) - codec_strlen, + "%s%s", codec_strlen ? "," : "", attr); + } + return; + +fail: + vs->codec_attr[0] = '\0'; + vs->attr_status = CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN; + return; +} + static int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number) { const char *p; @@ -1235,7 +1287,7 @@ static int create_master_playlist(AVFormatContext *s, bandwidth += bandwidth / 10; ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, - aud_st ? vs->agroup : NULL); + aud_st ? vs->agroup : NULL, vs->codec_attr); av_freep(&m3u8_rel_name); } @@ -1764,6 +1816,19 @@ static int hls_write_header(AVFormatContext *s) continue; } avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den); + write_codec_attr(outer_st, vs); + + } + /* Update the Codec Attr string for the mapped audio groups */ + if (vs->has_video && vs->agroup) { + for (j = 0; j < hls->nb_varstreams; j++) { + VariantStream *vs_agroup = &(hls->var_streams[j]); + if (!vs_agroup->has_video && !vs_agroup->has_subtitle && + vs_agroup->agroup && + !av_strcasecmp(vs_agroup->agroup, vs->agroup)) { + write_codec_attr(vs_agroup->streams[0], vs); + } + } } } fail: diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index 42f059a..99231c9 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -36,7 +36,8 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version) { } void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename, char *agroup) { + int bandwidth, char *filename, char *agroup, + char *codecs) { if (!out || !filename) return; @@ -50,6 +51,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, if (st && st->codecpar->width > 0 && st->codecpar->height > 0) avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, st->codecpar->height); + if (codecs && strlen(codecs) > 0) + avio_printf(out, ",CODECS=\"%s\"", codecs); if (agroup && strlen(agroup) > 0) avio_printf(out, ",AUDIO=\"group_%s\"", agroup); avio_printf(out, "\n%s\n\n", filename); diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index ac03550..5bbdf86 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -38,7 +38,8 @@ typedef enum { void ff_hls_write_playlist_version(AVIOContext *out, int version); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename, char *agroup); + int bandwidth, char *filename, char *agroup, + char *codecs); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type);