[FFmpeg-devel] mp4: Support writing declarative SEis to hvcC

Submitted by Vittorio Giovara on Aug. 17, 2017, 11:54 a.m.

Details

Message ID 20170817115444.24936-1-vittorio.giovara@gmail.com
State New
Headers show

Commit Message

Vittorio Giovara Aug. 17, 2017, 11:54 a.m.
Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
---
Right now only one SEI type is added, there could be more declarative
ones, but I'm not sure how to properly identify them.
Also, the way to check for the seiPayloadType could be improved,
suggestions are welcome.
Vittorio

 libavcodec/extract_extradata_bsf.c |  1 +
 libavformat/hevc.c                 | 28 ++++++++++++++++++++--------
 2 files changed, 21 insertions(+), 8 deletions(-)

Comments

James Almer Aug. 17, 2017, 3:25 p.m.
On 8/17/2017 8:54 AM, Vittorio Giovara wrote:
> Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
> ---
> Right now only one SEI type is added, there could be more declarative
> ones, but I'm not sure how to properly identify them.

Content Light Level probably, judging by the fact Mastering Display is one.

> Also, the way to check for the seiPayloadType could be improved,
> suggestions are welcome.
> Vittorio
> 
>  libavcodec/extract_extradata_bsf.c |  1 +
>  libavformat/hevc.c                 | 28 ++++++++++++++++++++--------
>  2 files changed, 21 insertions(+), 8 deletions(-)
> 
> diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c
> index 4cd0ca1137..e0d8aa99b5 100644
> --- a/libavcodec/extract_extradata_bsf.c
> +++ b/libavcodec/extract_extradata_bsf.c
> @@ -54,6 +54,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
>  {
>      static const int extradata_nal_types_hevc[] = {
>          HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
> +        HEVC_NAL_SEI_PREFIX, HEVC_NAL_SEI_SUFFIX,
>      };
>      static const int extradata_nal_types_h264[] = {
>          H264_NAL_SPS, H264_NAL_PPS,
> diff --git a/libavformat/hevc.c b/libavformat/hevc.c
> index 1a2d6cdd2b..9ff2b858dd 100644
> --- a/libavformat/hevc.c
> +++ b/libavformat/hevc.c
> @@ -22,6 +22,7 @@
>  #include "libavcodec/get_bits.h"
>  #include "libavcodec/golomb.h"
>  #include "libavcodec/hevc.h"
> +#include "libavcodec/hevc_sei.h"
>  #include "libavutil/intreadwrite.h"
>  #include "avc.h"
>  #include "avio.h"
> @@ -763,17 +764,10 @@ static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
>  
>      nal_unit_parse_header(&gbc, &nal_type);
>  
> -    /*
> -     * Note: only 'declarative' SEI messages are allowed in
> -     * hvcC. Perhaps the SEI playload type should be checked
> -     * and non-declarative SEI messages discarded?
> -     */
>      switch (nal_type) {
>      case HEVC_NAL_VPS:
>      case HEVC_NAL_SPS:
>      case HEVC_NAL_PPS:
> -    case HEVC_NAL_SEI_PREFIX:
> -    case HEVC_NAL_SEI_SUFFIX:
>          ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
>                                        ps_array_completeness, hvcc);
>          if (ret < 0)
> @@ -787,6 +781,15 @@ static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
>          if (ret < 0)
>              goto end;
>          break;
> +    case HEVC_NAL_SEI_PREFIX:
> +    case HEVC_NAL_SEI_SUFFIX:
> +        if (nal_size > 2 && *(nal_buf + 2) == HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO) {
> +            ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
> +                                          ps_array_completeness, hvcc);
> +            if (ret < 0)
> +                goto end;
> +        }
> +        break;
>      default:
>          ret = AVERROR_INVALIDDATA;
>          goto end;
> @@ -835,6 +838,7 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
>  {
>      uint8_t i;
>      uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0;
> +    int sei_prefix_count = 0, sei_suffix_count = 0;
>  
>      /*
>       * We only support writing HEVCDecoderConfigurationRecord version 1.
> @@ -925,12 +929,20 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
>          case HEVC_NAL_PPS:
>              pps_count += hvcc->array[i].numNalus;
>              break;
> +        case HEVC_NAL_SEI_PREFIX:
> +            sei_suffix_count += hvcc->array[i].numNalus;
> +            break;
> +        case HEVC_NAL_SEI_SUFFIX:
> +            sei_prefix_count += hvcc->array[i].numNalus;
> +            break;
>          default:
>              break;
>          }
>      if (!vps_count || vps_count > HEVC_MAX_VPS_COUNT ||
>          !sps_count || sps_count > HEVC_MAX_SPS_COUNT ||
> -        !pps_count || pps_count > HEVC_MAX_PPS_COUNT)
> +        !pps_count || pps_count > HEVC_MAX_PPS_COUNT ||
> +        sei_prefix_count > UINT16_MAX ||
> +        sei_suffix_count > UINT16_MAX)
>          return AVERROR_INVALIDDATA;
>  
>      /* unsigned int(8) configurationVersion = 1; */
>

Patch hide | download patch | download mbox

diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c
index 4cd0ca1137..e0d8aa99b5 100644
--- a/libavcodec/extract_extradata_bsf.c
+++ b/libavcodec/extract_extradata_bsf.c
@@ -54,6 +54,7 @@  static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
 {
     static const int extradata_nal_types_hevc[] = {
         HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
+        HEVC_NAL_SEI_PREFIX, HEVC_NAL_SEI_SUFFIX,
     };
     static const int extradata_nal_types_h264[] = {
         H264_NAL_SPS, H264_NAL_PPS,
diff --git a/libavformat/hevc.c b/libavformat/hevc.c
index 1a2d6cdd2b..9ff2b858dd 100644
--- a/libavformat/hevc.c
+++ b/libavformat/hevc.c
@@ -22,6 +22,7 @@ 
 #include "libavcodec/get_bits.h"
 #include "libavcodec/golomb.h"
 #include "libavcodec/hevc.h"
+#include "libavcodec/hevc_sei.h"
 #include "libavutil/intreadwrite.h"
 #include "avc.h"
 #include "avio.h"
@@ -763,17 +764,10 @@  static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
 
     nal_unit_parse_header(&gbc, &nal_type);
 
-    /*
-     * Note: only 'declarative' SEI messages are allowed in
-     * hvcC. Perhaps the SEI playload type should be checked
-     * and non-declarative SEI messages discarded?
-     */
     switch (nal_type) {
     case HEVC_NAL_VPS:
     case HEVC_NAL_SPS:
     case HEVC_NAL_PPS:
-    case HEVC_NAL_SEI_PREFIX:
-    case HEVC_NAL_SEI_SUFFIX:
         ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
                                       ps_array_completeness, hvcc);
         if (ret < 0)
@@ -787,6 +781,15 @@  static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
         if (ret < 0)
             goto end;
         break;
+    case HEVC_NAL_SEI_PREFIX:
+    case HEVC_NAL_SEI_SUFFIX:
+        if (nal_size > 2 && *(nal_buf + 2) == HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO) {
+            ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
+                                          ps_array_completeness, hvcc);
+            if (ret < 0)
+                goto end;
+        }
+        break;
     default:
         ret = AVERROR_INVALIDDATA;
         goto end;
@@ -835,6 +838,7 @@  static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
 {
     uint8_t i;
     uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0;
+    int sei_prefix_count = 0, sei_suffix_count = 0;
 
     /*
      * We only support writing HEVCDecoderConfigurationRecord version 1.
@@ -925,12 +929,20 @@  static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
         case HEVC_NAL_PPS:
             pps_count += hvcc->array[i].numNalus;
             break;
+        case HEVC_NAL_SEI_PREFIX:
+            sei_suffix_count += hvcc->array[i].numNalus;
+            break;
+        case HEVC_NAL_SEI_SUFFIX:
+            sei_prefix_count += hvcc->array[i].numNalus;
+            break;
         default:
             break;
         }
     if (!vps_count || vps_count > HEVC_MAX_VPS_COUNT ||
         !sps_count || sps_count > HEVC_MAX_SPS_COUNT ||
-        !pps_count || pps_count > HEVC_MAX_PPS_COUNT)
+        !pps_count || pps_count > HEVC_MAX_PPS_COUNT ||
+        sei_prefix_count > UINT16_MAX ||
+        sei_suffix_count > UINT16_MAX)
         return AVERROR_INVALIDDATA;
 
     /* unsigned int(8) configurationVersion = 1; */