From 97a9d2ebf2abde9c61cadb355cfe2ca2f960c5c7 Mon Sep 17 00:00:00 2001
From: Philippe Symons <philippe.symons@gmail.com>
Date: Mon, 19 Nov 2018 20:34:36 +0100
Subject: [PATCH] avformat/hls,dash: add LANGUAGE attribute to #EXT-X-MEDIA tag
for audio-only variant streams
Signed-off-by: Philippe Symons <philippe.symons@gmail.com>
---
libavformat/dashenc.c | 2 +-
libavformat/hlsenc.c | 20 +++++++++++++++++++-
libavformat/hlsplaylist.c | 6 +++++-
libavformat/hlsplaylist.h | 2 +-
4 files changed, 26 insertions(+), 4 deletions(-)
@@ -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);
@@ -1228,12 +1228,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 +1265,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);
}
@@ -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);
}
@@ -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