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

Submitted by Dixit, Vishwanath on Nov. 30, 2017, 11:32 a.m.

Details

Message ID 1512041572-23671-1-git-send-email-vdixit@akamai.com
State New
Headers show

Commit Message

Dixit, Vishwanath Nov. 30, 2017, 11:32 a.m.
From: Vishwanath Dixit <vdixit@akamai.com>

---
 libavformat/Makefile      |  2 +-
 libavformat/dashenc.c     |  2 +-
 libavformat/hlsenc.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++--
 libavformat/hlsplaylist.c |  5 +++-
 libavformat/hlsplaylist.h |  3 ++-
 libavformat/reverse.c     |  1 +
 tests/ref/fate/source     |  1 +
 7 files changed, 73 insertions(+), 6 deletions(-)
 create mode 100644 libavformat/reverse.c

Comments

Steven Liu Nov. 30, 2017, noon
2017-11-30 19:32 GMT+08:00  <vdixit@akamai.com>:
> From: Vishwanath Dixit <vdixit@akamai.com>
>
> ---
>  libavformat/Makefile      |  2 +-
>  libavformat/dashenc.c     |  2 +-
>  libavformat/hlsenc.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++--
>  libavformat/hlsplaylist.c |  5 +++-
>  libavformat/hlsplaylist.h |  3 ++-
>  libavformat/reverse.c     |  1 +
Remove this modify if this have nothing to do.

>  tests/ref/fate/source     |  1 +
>  7 files changed, 73 insertions(+), 6 deletions(-)
>  create mode 100644 libavformat/reverse.c
>
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 4bffdf2..2bdb777 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -61,7 +61,7 @@ OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
>                                              rtpdec_vp9.o                \
>                                              rtpdec_xiph.o
>  OBJS-$(CONFIG_RTPENC_CHAIN)              += rtpenc_chain.o rtp.o
> -OBJS-$(CONFIG_SHARED)                    += log2_tab.o golomb_tab.o
> +OBJS-$(CONFIG_SHARED)                    += log2_tab.o golomb_tab.o reverse.o
>  OBJS-$(CONFIG_SRTP)                      += srtp.o
>
>  # muxers/demuxers
> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> index 90cd2d0..e0b1679 100644
> --- a/libavformat/dashenc.c
> +++ b/libavformat/dashenc.c
> @@ -754,7 +754,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 8d4b333..0702124 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"
> @@ -1074,6 +1075,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)
>  {
> @@ -1084,7 +1142,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) {
> @@ -1198,9 +1256,12 @@ static int create_master_playlist(AVFormatContext *s,
>              bandwidth += aud_st->codecpar->bit_rate;
>          bandwidth += bandwidth / 10;
>
> +        codec_str = get_codec_str(vid_st, aud_st);
> +
>          ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name,
> -                aud_st ? vs->agroup : NULL);
> +                codec_str, aud_st ? vs->agroup : NULL);
>
> +        av_freep(&codec_str);
>          av_freep(&m3u8_rel_name);
>      }
>  fail:
> diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c
> index 5e12682..eaf598f 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 *codec_str,
> +                              char *agroup) {
>      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 (codec_str && strlen(codec_str) > 0)
> +        avio_printf(out, ",CODECS=\"%s\"", codec_str);
>      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 3231733..476cfc4 100644
> --- a/libavformat/hlsplaylist.h
> +++ b/libavformat/hlsplaylist.h
> @@ -43,7 +43,8 @@ static inline int hls_get_int_from_double(double val)
>
>  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 *codec_str,
> +                              char *agroup);
>  void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache,
>                                    int target_duration, int64_t sequence,
>                                    uint32_t playlist_type);
> diff --git a/libavformat/reverse.c b/libavformat/reverse.c
> new file mode 100644
> index 0000000..440bada
> --- /dev/null
> +++ b/libavformat/reverse.c
> @@ -0,0 +1 @@
> +#include "libavutil/reverse.c"
> diff --git a/tests/ref/fate/source b/tests/ref/fate/source
> index 2def034..b68873b 100644
> --- a/tests/ref/fate/source
> +++ b/tests/ref/fate/source
> @@ -11,6 +11,7 @@ libavfilter/log2_tab.c
>  libavformat/file_open.c
>  libavformat/golomb_tab.c
>  libavformat/log2_tab.c
> +libavformat/reverse.c
>  libswresample/log2_tab.c
>  libswscale/log2_tab.c
>  tools/uncoded_frame.c
> --
> 1.9.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Dixit, Vishwanath Nov. 30, 2017, 4:41 p.m.
>On 11/30/17, 5:31 PM, "Steven Liu" <lingjiujianke@gmail.com> wrote:

>

>    2017-11-30 19:32 GMT+08:00  <vdixit@akamai.com>:

>>   From: Vishwanath Dixit <vdixit@akamai.com>

>>    

>>    ---

>>      libavformat/Makefile      |  2 +-

>>      libavformat/dashenc.c     |  2 +-

>>      libavformat/hlsenc.c      | 65 +++++++++++++++++++++++++++++++++++++++++++++--

>>      libavformat/hlsplaylist.c |  5 +++-

>>      libavformat/hlsplaylist.h |  3 ++-

>>      libavformat/reverse.c     |  1 +

>    Remove this modify if this have nothing to do.

This new wrapper file is needed, as the patch is using the function ff_reverse, which is defined in libavutil/reverse.c. Without this libavformat library compilation will fail with the same error as reported for libavdevice here https://trac.ffmpeg.org/ticket/6544.

Patch hide | download patch | download mbox

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 4bffdf2..2bdb777 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -61,7 +61,7 @@  OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
                                             rtpdec_vp9.o                \
                                             rtpdec_xiph.o
 OBJS-$(CONFIG_RTPENC_CHAIN)              += rtpenc_chain.o rtp.o
-OBJS-$(CONFIG_SHARED)                    += log2_tab.o golomb_tab.o
+OBJS-$(CONFIG_SHARED)                    += log2_tab.o golomb_tab.o reverse.o
 OBJS-$(CONFIG_SRTP)                      += srtp.o
 
 # muxers/demuxers
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 90cd2d0..e0b1679 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -754,7 +754,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 8d4b333..0702124 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"
@@ -1074,6 +1075,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)
 {
@@ -1084,7 +1142,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) {
@@ -1198,9 +1256,12 @@  static int create_master_playlist(AVFormatContext *s,
             bandwidth += aud_st->codecpar->bit_rate;
         bandwidth += bandwidth / 10;
 
+        codec_str = get_codec_str(vid_st, aud_st);
+
         ff_hls_write_stream_info(vid_st, master_pb, bandwidth, m3u8_rel_name,
-                aud_st ? vs->agroup : NULL);
+                codec_str, aud_st ? vs->agroup : NULL);
 
+        av_freep(&codec_str);
         av_freep(&m3u8_rel_name);
     }
 fail:
diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c
index 5e12682..eaf598f 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 *codec_str,
+                              char *agroup) {
     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 (codec_str && strlen(codec_str) > 0)
+        avio_printf(out, ",CODECS=\"%s\"", codec_str);
     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 3231733..476cfc4 100644
--- a/libavformat/hlsplaylist.h
+++ b/libavformat/hlsplaylist.h
@@ -43,7 +43,8 @@  static inline int hls_get_int_from_double(double val)
 
 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 *codec_str,
+                              char *agroup);
 void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache,
                                   int target_duration, int64_t sequence,
                                   uint32_t playlist_type);
diff --git a/libavformat/reverse.c b/libavformat/reverse.c
new file mode 100644
index 0000000..440bada
--- /dev/null
+++ b/libavformat/reverse.c
@@ -0,0 +1 @@ 
+#include "libavutil/reverse.c"
diff --git a/tests/ref/fate/source b/tests/ref/fate/source
index 2def034..b68873b 100644
--- a/tests/ref/fate/source
+++ b/tests/ref/fate/source
@@ -11,6 +11,7 @@  libavfilter/log2_tab.c
 libavformat/file_open.c
 libavformat/golomb_tab.c
 libavformat/log2_tab.c
+libavformat/reverse.c
 libswresample/log2_tab.c
 libswscale/log2_tab.c
 tools/uncoded_frame.c