From patchwork Wed Nov 14 23:29:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Philippe Symons X-Patchwork-Id: 11030 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 A526444CD6A for ; Thu, 15 Nov 2018 01:29:19 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 87D1F687EC0; Thu, 15 Nov 2018 01:28:41 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 49F0F680CAD for ; Thu, 15 Nov 2018 01:28:35 +0200 (EET) Received: by mail-wm1-f47.google.com with SMTP id p2-v6so16207509wmc.2 for ; Wed, 14 Nov 2018 15:29:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=TE7TTA7uOTZuGIX40ttirHKwRGr6s1EzLeQKB8j19Co=; b=qRSO7F9T1QFI7Iu9D4LhmlqJbE7kUOCTkOGu5/+VrJrR19C7o2etYswG/CEVpdXpIL f/2nDcIIX5sze7Yy6eSref+zPQEvn3qzqJj64lBVACi3Gfk1e9OmWU8i8pTJBUHTx3Qo qnWUydsojCHhexJ5s7l6TDT0rQ5iJVE921OvzcLbdj+w4Eh3GCX4KpP7EXrN61uxUKJk N+xUdWSn9grk0mWSuKRIaQc/JdmTWMIq5BOtA1O1B4lJd9wJQbinQmPLmMoAAt+rjO/0 QOVUUCdR6ZNXeKPF4TrfJyY1xahqaIFnQZaJR59OMPBjwcX/wKloFrF2fMTHRXI4e6kl W83g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=TE7TTA7uOTZuGIX40ttirHKwRGr6s1EzLeQKB8j19Co=; b=N2wktdUY7+GC3/ngnJ6HdPuW2ogoHZcUoJxVu/fvh5OhhgpPrcNOkLzfe2WLAzUQ+b fi4QnYt/+Wodso7MuZYqa+I1dxZyyTGqB7My14MXhHhXXq6bZD78kzIsMr6ascnKHP8k Tn1BIV7zDGEypz1arbLytoyf3EosscCRw+RXZgS2k1xSUtv9pAIx23rlIHLb1ufuCs18 RPoOVYDoMfPXrftrl1wWQYkVqfsIc76Vp1uR0MI1ld+d+FUrPJ9PxiH5mgrzSur+cmW0 7KgAliYpmMppah7gg8hY5C0cchQSdtBtyuCsAdkwzl2t2JljeMHCjRKaGvZNOMbTm1nM Ki4g== X-Gm-Message-State: AGRZ1gLjGU3UbNtkiCHmoJ3yPj0J/19Niythxz0i10ves4XNGhCAUbas /XW4pRtRdw9V+EZEDO4bmVucATaRma7IsVekqAhhBDPWJWk= X-Google-Smtp-Source: AJdET5eTrxInc4w4+88YUq2AFGamwWCFdZSEg0kVAZq/pMy/w9CYsNqvNVFZhi5iofdXCN/aAeD6rmr5tITF1bJP1+8= X-Received: by 2002:a1c:bb42:: with SMTP id l63-v6mr3345487wmf.32.1542238152623; Wed, 14 Nov 2018 15:29:12 -0800 (PST) MIME-Version: 1.0 References: <1560DEDB-A8E6-45F9-82FE-5AEE9E56B8E1@chinaffmpeg.org> In-Reply-To: From: Philippe Symons Date: Thu, 15 Nov 2018 00:29:00 +0100 Message-ID: To: ffmpeg-devel@ffmpeg.org X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: Re: [FFmpeg-devel] [PATCH] [HLS] Add LANGUAGE attribute to #EXT-X-MEDIA tag for audio-only variant streams. 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: lq@chinaffmpeg.org Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Hello everyone, Here is the new version of the patch in which the comments on the curly braces have been resolved as well. I hope it's okay now. Best regards, Philippe Symons Op do 15 nov. 2018 om 00:13 schreef Philippe Symons < philippe.symons@gmail.com>: > Hold on, I just noticed the feedback on the curly braces. I'll create a > new version of the patch to resolve this as well. > > Op wo 14 nov. 2018 om 23:49 schreef Philippe Symons < > philippe.symons@gmail.com>: > >> Hello, >> >> I've created a new version of the patch in which the second empty line >> was removed. I couldn't find any other feedback inline in your response, so >> that's all I changed. >> >> Best regards, >> >> Philippe Symons >> >> >> Op di 13 nov. 2018 om 03:29 schreef Liu Steven : >> >>> >>> >>> > 在 2018年11月13日,上午6:36,Philippe Symons 写道: >>> > >>> > Hello everyone, >>> > >>> > This is my first patch to FFMpeg or any open-source project for that >>> > matter. In this patch, I've added the LANGUAGE attribute to the >>> > #EXT-X-MEDIA tag for for audio only variant streams for HLS streams. >>> > >>> > This attribute will be added to the output in >>> > avformats' ff_hls_write_audio_rendition() function, if the language >>> code >>> > can be found in the metadata of the variant stream. >>> > >>> > The reason why I implemented this, was because I was working with a >>> player >>> > which needs this attribute to determine the language of the audio >>> stream. >>> > After asking the question on StackOverflow ( >>> > >>> https://stackoverflow.com/questions/53205283/ffmpeg-hls-multiple-audio-languages-with-var-stream-map-ext-x-mediatype-doesn/53206492#53206492 >>> ), >>> > I noticed that it wasn't implemented. >>> > >>> > I've tested these changes with the following command: >>> > >>> > ffmpeg -re -i /home/philippe/Videos/example.ts -map 0:v -c:v copy -map >>> 0:a >>> > -c:a copy -f hls -hls_time 6 -hls_list_size 10 -hls_flags >>> > delete_segments+program_date_time -hls_segment_filename >>> > "/var/www/html/live/stream_%v_%d.ts" -var_stream_map "v:0,agroup:lang >>> > a:0,agroup:lang a:1,agroup:lang a:2,agroup:lang a: >>> > 3,agroup:lang" -master_pl_name master.m3u8 >>> /var/www/html/live/stream-%v.m3u8 >>> > >>> > Looking forward to your feedback. I hope it's okay. >>> > >>> >>> Signed-off-by: Philippe Symons >>> --- >>> libavformat/dashenc.c | 2 +- >>> libavformat/hlsenc.c | 24 ++++++++++++++++++++++-- >>> libavformat/hlsplaylist.c | 6 +++++- >>> libavformat/hlsplaylist.h | 2 +- >>> 4 files changed, 29 insertions(+), 5 deletions(-) >>> >>> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c >>> index f8b3d106d5..ca5ef01e3f 100644 >>> --- a/libavformat/dashenc.c >>> +++ b/libavformat/dashenc.c >>> @@ -897,7 +897,7 @@ static int write_manifest(AVFormatContext *s, int >>> final) >>> if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) >>> continue; >>> get_hls_playlist_name(playlist_file, sizeof(playlist_file), >>> NULL, i); >>> - ff_hls_write_audio_rendition(c->m3u8_out, (char >>> *)audio_group, >>> + ff_hls_write_audio_rendition(c->m3u8_out, (char >>> *)audio_group, NULL, >>> playlist_file, i, is_default); >>> max_audio_bitrate = FFMAX(st->codecpar->bit_rate + >>> os->muxer_overhead, >>> max_audio_bitrate); >>> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c >>> index e0048aa9d8..b31daa108e 100644 >>> --- a/libavformat/hlsenc.c >>> +++ b/libavformat/hlsenc.c >>> @@ -1205,7 +1205,6 @@ static int create_master_playlist(AVFormatContext >>> *s, >>> } >>> >>> set_http_options(s, &options, hls); >>> - >>> ret = hlsenc_io_open(s, &hls->m3u8_out, hls->master_m3u8_url, >>> &options); >>> av_dict_free(&options); >>> if (ret < 0) { >>> @@ -1228,12 +1227,33 @@ static int >>> create_master_playlist(AVFormatContext *s, >>> >>> /* For audio only variant streams add #EXT-X-MEDIA tag with >>> attributes*/ >>> for (i = 0; i < hls->nb_varstreams; i++) { >>> + AVFormatContext* var_context; >>> + char* language = NULL; >>> + >>> vs = &(hls->var_streams[i]); >>> + var_context = vs->avf; >>> >>> if (vs->has_video || vs->has_subtitle || !vs->agroup) >>> continue; >>> >>> m3u8_name_size = strlen(vs->m3u8_name) + 1; >>> + >>> + /* >>> + * Try to obtain the language code of the audio stream. >>> + * -if available- it will be used to write the LANGUAGE >>> + * attribute in the #EXT-X-MEDIA tag >>> + */ >>> + if(var_context && var_context->nb_streams > 0) >>> + { >>> if (var_context && var_context->nb_streams > 0) { >>> + AVDictionary* meta_dict = vs->streams[0]->metadata; >>> + AVDictionaryEntry *langEntry = av_dict_get(meta_dict, >>> "language", NULL, 0); >>> + if(langEntry) >>> + { >>> if (langEntry) { >>> + language = langEntry->value; >>> + } >>> + } >>> + >>> + >>> >>> two empty line? >>> m3u8_rel_name = av_malloc(m3u8_name_size); >>> if (!m3u8_rel_name) { >>> ret = AVERROR(ENOMEM); >>> @@ -1247,7 +1267,7 @@ static int create_master_playlist(AVFormatContext >>> *s, >>> goto fail; >>> } >>> >>> - ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, >>> m3u8_rel_name, 0, 1); >>> + ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, >>> language, m3u8_rel_name, 0, 1); >>> >>> av_freep(&m3u8_rel_name); >>> } >>> diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c >>> index efcbff0009..42c7cf5727 100644 >>> --- a/libavformat/hlsplaylist.c >>> +++ b/libavformat/hlsplaylist.c >>> @@ -35,12 +35,16 @@ void ff_hls_write_playlist_version(AVIOContext *out, >>> int version) { >>> avio_printf(out, "#EXT-X-VERSION:%d\n", version); >>> } >>> >>> -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, >>> +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char* >>> language, >>> char *filename, int name_id, int >>> is_default) { >>> if (!out || !agroup || !filename) >>> return; >>> >>> avio_printf(out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", >>> agroup); >>> + >>> + if(language) >>> + avio_printf(out, ",LANGUAGE=\"%s\"", language); >>> + >>> avio_printf(out, ",NAME=\"audio_%d\",DEFAULT=%s,URI=\"%s\"\n", >>> name_id, >>> is_default ? "YES" : "NO", filename); >>> } >>> diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h >>> index 5054b01c8f..faf1ccdd02 100644 >>> --- a/libavformat/hlsplaylist.h >>> +++ b/libavformat/hlsplaylist.h >>> @@ -37,7 +37,7 @@ typedef enum { >>> } PlaylistType; >>> >>> void ff_hls_write_playlist_version(AVIOContext *out, int version); >>> -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, >>> +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char* >>> language, >>> char *filename, int name_id, int >>> is_default); >>> void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, >>> int bandwidth, char *filename, char >>> *agroup, >>> -- >>> 2.17.1 >>> >>> >>> >>> >>> >>> >>> > Best regards, >>> > >>> > Philippe Symons >>> > >>> <0001-HLS-Add-LANGUAGE-attribute-to-EXT-X-MEDIA-tag-for-au.patch>_______________________________________________ >>> > ffmpeg-devel mailing list >>> > ffmpeg-devel@ffmpeg.org >>> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel >>> >>> >>> >>> _______________________________________________ >>> ffmpeg-devel mailing list >>> ffmpeg-devel@ffmpeg.org >>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel >>> >> From 2f2d4a829d30a8dfc6084b347bb597ac994d6dda Mon Sep 17 00:00:00 2001 From: Philippe Symons Date: Thu, 15 Nov 2018 00:20:17 +0100 Subject: [PATCH] [HLS] Add LANGUAGE attribute to #EXT-X-MEDIA tag for audio-only variant streams. Signed-off-by: Philippe Symons --- libavformat/dashenc.c | 2 +- libavformat/hlsenc.c | 21 +++++++++++++++++++-- libavformat/hlsplaylist.c | 6 +++++- libavformat/hlsplaylist.h | 2 +- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d151921175..17465c1917 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -898,7 +898,7 @@ static int write_manifest(AVFormatContext *s, int final) if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) continue; get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); - ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group, + ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group, NULL, playlist_file, i, is_default); max_audio_bitrate = FFMAX(st->codecpar->bit_rate + os->muxer_overhead, max_audio_bitrate); diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index e0048aa9d8..fb77aa9ba8 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1205,7 +1205,6 @@ static int create_master_playlist(AVFormatContext *s, } set_http_options(s, &options, hls); - ret = hlsenc_io_open(s, &hls->m3u8_out, hls->master_m3u8_url, &options); av_dict_free(&options); if (ret < 0) { @@ -1228,12 +1227,30 @@ static int create_master_playlist(AVFormatContext *s, /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { + AVFormatContext* var_context; + char* language = NULL; + vs = &(hls->var_streams[i]); + var_context = vs->avf; if (vs->has_video || vs->has_subtitle || !vs->agroup) continue; m3u8_name_size = strlen(vs->m3u8_name) + 1; + + /* + * Try to obtain the language code of the audio stream. + * -if available- it will be used to write the LANGUAGE + * attribute in the #EXT-X-MEDIA tag + */ + if(var_context && var_context->nb_streams > 0) { + AVDictionary* meta_dict = vs->streams[0]->metadata; + AVDictionaryEntry *langEntry = av_dict_get(meta_dict, "language", NULL, 0); + if(langEntry) { + language = langEntry->value; + } + } + m3u8_rel_name = av_malloc(m3u8_name_size); if (!m3u8_rel_name) { ret = AVERROR(ENOMEM); @@ -1247,7 +1264,7 @@ static int create_master_playlist(AVFormatContext *s, goto fail; } - ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, 0, 1); + ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, language, m3u8_rel_name, 0, 1); av_freep(&m3u8_rel_name); } diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c index efcbff0009..42c7cf5727 100644 --- a/libavformat/hlsplaylist.c +++ b/libavformat/hlsplaylist.c @@ -35,12 +35,16 @@ void ff_hls_write_playlist_version(AVIOContext *out, int version) { avio_printf(out, "#EXT-X-VERSION:%d\n", version); } -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char* language, char *filename, int name_id, int is_default) { if (!out || !agroup || !filename) return; avio_printf(out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", agroup); + + if(language) + avio_printf(out, ",LANGUAGE=\"%s\"", language); + avio_printf(out, ",NAME=\"audio_%d\",DEFAULT=%s,URI=\"%s\"\n", name_id, is_default ? "YES" : "NO", filename); } diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 5054b01c8f..faf1ccdd02 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -37,7 +37,7 @@ typedef enum { } PlaylistType; void ff_hls_write_playlist_version(AVIOContext *out, int version); -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, +void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char* language, char *filename, int name_id, int is_default); void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup, -- 2.17.1