[FFmpeg-devel,v4,3/3] avformat/hlsenc:addition of CODECS attribute in the master playlist

Submitted by kjeyapal@akamai.com on Nov. 24, 2017, 3:30 p.m.

Details

Message ID 1511537439-13604-1-git-send-email-kjeyapal@akamai.com
State New
Headers show

Commit Message

kjeyapal@akamai.com Nov. 24, 2017, 3:30 p.m.
From: Vishwanath Dixit <vdixit@akamai.com>

---
 libavformat/hlsenc.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 66 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 58d7c58..d48963c 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -39,6 +39,7 @@ 
 #include "libavutil/avstring.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/random_seed.h"
+#include "libavutil/reverse.h"
 #include "libavutil/opt.h"
 #include "libavutil/log.h"
 #include "libavutil/time_internal.h"
@@ -1066,6 +1067,63 @@  static int get_relative_url(const char *master_url, const char *media_url,
     return 0;
 }
 
+static char *get_codec_str(AVStream *vid_st, AVStream *aud_st) {
+    size_t codec_str_size = 64;
+    char *codec_str = av_malloc(codec_str_size);
+    int video_str_len = 0;
+
+    if (!codec_str)
+        return NULL;
+
+    if (!vid_st && !aud_st) {
+        goto fail;
+    }
+
+    if (vid_st) {
+        if (vid_st->codecpar->profile != FF_PROFILE_UNKNOWN &&
+            vid_st->codecpar->level != FF_LEVEL_UNKNOWN &&
+            vid_st->codecpar->codec_id == AV_CODEC_ID_H264) {
+            snprintf(codec_str, codec_str_size, "avc1.%02x%02x%02x",
+                     vid_st->codecpar->profile & 0xFF,
+                     ff_reverse[(vid_st->codecpar->profile >> 8) & 0xFF],
+                     vid_st->codecpar->level);
+        } else {
+            goto fail;
+        }
+        video_str_len = strlen(codec_str);
+    }
+
+    if (aud_st) {
+        char *audio_str = codec_str;
+        if (video_str_len) {
+            codec_str[video_str_len] = ',';
+            video_str_len += 1;
+            audio_str += video_str_len;
+            codec_str_size -= video_str_len;
+        }
+        if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP2) {
+            snprintf(audio_str, codec_str_size, "mp4a.40.33");
+        } else if (aud_st->codecpar->codec_id == AV_CODEC_ID_MP3) {
+            snprintf(audio_str, codec_str_size, "mp4a.40.34");
+        } else if (aud_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(audio_str, codec_str_size, "mp4a.40.2");
+        } else if (aud_st->codecpar->codec_id == AV_CODEC_ID_AC3) {
+            snprintf(audio_str, codec_str_size, "mp4a.A5");
+        } else if (aud_st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
+            snprintf(audio_str, codec_str_size, "mp4a.A6");
+        } else {
+            goto fail;
+        }
+    }
+
+    return codec_str;
+
+fail:
+    av_free(codec_str);
+    return NULL;
+}
+
 static int create_master_playlist(AVFormatContext *s,
                                   VariantStream * const input_vs)
 {
@@ -1076,7 +1134,7 @@  static int create_master_playlist(AVFormatContext *s,
     AVDictionary *options = NULL;
     unsigned int i, j;
     int m3u8_name_size, ret, bandwidth;
-    char *m3u8_rel_name;
+    char *m3u8_rel_name, *codec_str;
 
     input_vs->m3u8_created = 1;
     if (!hls->master_m3u8_created) {
@@ -1203,6 +1261,13 @@  static int create_master_playlist(AVFormatContext *s,
             avio_printf(master_pb, ",RESOLUTION=%dx%d", vid_st->codecpar->width,
                     vid_st->codecpar->height);
 
+        codec_str = get_codec_str(vid_st, aud_st);
+
+        if (codec_str) {
+            avio_printf(master_pb, ",CODECS=\"%s\"", codec_str);
+            av_free(codec_str);
+        }
+
         if (vs->agroup && aud_st)
             avio_printf(master_pb, ",AUDIO=\"group_%s\"", vs->agroup);