amldemux: CB1 refine-mp4-dv-parameter [1/1]

PD#SWPL-149025

Problem:
refine mp4 dv parameter

Solution:
00041-SWPL-149025-refine-mp4-dv-parameter.patch

Verify:
AH212

Signed-off-by: zengliang.li <zengliang.li@amlogic.com>
Change-Id: I1e0da3c7058cd4f770807323428654fb11119f6e
diff --git a/aml-qtdemux/fourcc.h b/aml-qtdemux/fourcc.h
index 2e75b11..3dcabfb 100644
--- a/aml-qtdemux/fourcc.h
+++ b/aml-qtdemux/fourcc.h
@@ -93,7 +93,9 @@
 #define FOURCC_alis     GST_MAKE_FOURCC('a','l','i','s')
 #define FOURCC_appl     GST_MAKE_FOURCC('a','p','p','l')
 #define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
+#define FOURCC_avc2     GST_MAKE_FOURCC('a','v','c','2')
 #define FOURCC_avc3     GST_MAKE_FOURCC('a','v','c','3')
+#define FOURCC_avc4     GST_MAKE_FOURCC('a','v','c','4')
 #define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
 #define FOURCC_c608     GST_MAKE_FOURCC('c','6','0','8')
 #define FOURCC_c708     GST_MAKE_FOURCC('c','7','0','8')
@@ -117,6 +119,7 @@
 #define FOURCC_dac3     GST_MAKE_FOURCC('d','a','c','3')
 #define FOURCC_damr     GST_MAKE_FOURCC('d','a','m','r')
 #define FOURCC_data     GST_MAKE_FOURCC('d','a','t','a')
+#define FOURCC_dav1     GST_MAKE_FOURCC('d','a','v','1')
 #define FOURCC_dcom     GST_MAKE_FOURCC('d','c','o','m')
 #define FOURCC_desc     GST_MAKE_FOURCC('d','e','s','c')
 #define FOURCC_dhlr     GST_MAKE_FOURCC('d','h','l','r')
@@ -138,6 +141,8 @@
 #define FOURCC_dvcC     GST_MAKE_FOURCC('d','v','c','C')
 #define FOURCC_dvvC     GST_MAKE_FOURCC('d','v','v','C')
 #define FOURCC_dvwC     GST_MAKE_FOURCC('d','v','w','C')
+#define FOURCC_dvzC     GST_MAKE_FOURCC('d','v','z','C')
+#define FOURCC_dvxC     GST_MAKE_FOURCC('d','v','x','C')
 #define FOURCC_edts     GST_MAKE_FOURCC('e','d','t','s')
 #define FOURCC_elst     GST_MAKE_FOURCC('e','l','s','t')
 #define FOURCC_enda     GST_MAKE_FOURCC('e','n','d','a')
@@ -277,6 +282,10 @@
 #define FOURCC_vp08     GST_MAKE_FOURCC('v','p','0','8')
 #define FOURCC_vp09     GST_MAKE_FOURCC('v','p','0','9')
 #define FOURCC_vpcC     GST_MAKE_FOURCC('v','p','c','C')
+#define FOURCC_vvc1     GST_MAKE_FOURCC('v','v','c','1')
+#define FOURCC_vvcN     GST_MAKE_FOURCC('v','v','c','N')
+#define FOURCC_vvi1     GST_MAKE_FOURCC('v','v','i','1')
+#define FOURCC_vvs1     GST_MAKE_FOURCC('v','v','s','1')
 #define FOURCC_vtta     GST_MAKE_FOURCC('v','t','t','a')
 #define FOURCC_vttc     GST_MAKE_FOURCC('v','t','t','c')
 #define FOURCC_vttC     GST_MAKE_FOURCC('v','t','t','C')
@@ -305,6 +314,8 @@
 #define FOURCC_vivo     GST_MAKE_FOURCC('v','i','v','o')
 #define FOURCC_saiz     GST_MAKE_FOURCC('s','a','i','z')
 #define FOURCC_saio     GST_MAKE_FOURCC('s','a','i','o')
+#define FOURCC_sbgp     GST_MAKE_FOURCC('s','b','g','p')
+#define FOURCC_sgpd     GST_MAKE_FOURCC('s','g','p','d')
 
 #define FOURCC_3gg6     GST_MAKE_FOURCC('3','g','g','6')
 #define FOURCC_3gg7     GST_MAKE_FOURCC('3','g','g','7')
diff --git a/aml-qtdemux/qtdemux.c b/aml-qtdemux/qtdemux.c
index 3d38ed8..13a537f 100644
--- a/aml-qtdemux/qtdemux.c
+++ b/aml-qtdemux/qtdemux.c
@@ -10925,6 +10925,240 @@
   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
 }
 
+
+static gint
+qtdemux_parse_dvcc (guint32 sampleEntry, guint32 dvConfig, const guint8 * data, GstCaps *caps)
+{
+    gint len;
+    const guint8 *config_data;
+    guint16 buf;
+    guint8 dv_profile;
+    guint8 dv_level;
+    guint8 rpu_present_flag;
+    gboolean dv_bl_present_flag = FALSE;
+    gboolean dv_el_present_flag = FALSE;
+    gboolean bRejectPlay = FALSE;
+
+    if (NULL == data || NULL == caps)
+    {
+        return 0;
+    }
+
+    len = QT_UINT32 (data);
+    config_data = data + 0x8;
+
+    if (((1<<30) < len) || (1 != config_data[0]) || (0 != config_data[1]))
+    {
+        return 0;
+    }
+
+    buf = (config_data[2] << 8) | config_data[3];
+
+    dv_profile        = (buf >> 9) & 0x7f;      // 7 bits
+    dv_level          = (buf >> 3) & 0x3f;      // 6 bits
+    rpu_present_flag  = (buf >> 2) & 0x01;      // 1 bit
+    dv_el_present_flag = (buf >> 1) & 0x01;     // 1 bit
+    dv_bl_present_flag = buf & 0x01;            // 1 bit
+
+    GST_DEBUG ("entry type:          %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (sampleEntry));
+    GST_DEBUG ("dvConfig type:       %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (dvConfig));
+    GST_DEBUG ("dv_profile: %d, dv_level: %d, dv_el_present_flag: %d, dv_bl_present_flag: %d",
+      dv_profile, dv_level, dv_el_present_flag, dv_bl_present_flag);
+
+    if (sampleEntry == FOURCC_hev1 || sampleEntry == FOURCC_hvc1)
+    {
+      if (dvConfig == FOURCC_dvcC || dvConfig == FOURCC_dvvC || dvConfig == FOURCC_dvwC)
+      {
+        if (dv_profile == 4 || dv_profile == 7 || dv_profile == 8)
+        {
+          GST_DEBUG ("Playback Dolby Vision");
+        }
+        else
+        {
+          GST_DEBUG ("invalid profile, playback as non-dv.");
+          dv_el_present_flag = 0;
+          dv_bl_present_flag = 0;
+        }
+      }
+      else
+      {
+        GST_DEBUG ("invalid dvConfig type, playback as non-dv.");
+        dv_el_present_flag = 0;
+        dv_bl_present_flag = 0;
+      }
+    }
+    else if (sampleEntry == FOURCC_dvhe || sampleEntry == FOURCC_dvh1)
+    {
+      if (dvConfig == FOURCC_dvcC)
+      {
+        if (dv_profile == 5)
+          GST_DEBUG ("Playback Dolby Vision");
+        else
+        {
+          GST_WARNING("reject play for invalid profile:%d", dv_profile);
+          bRejectPlay = TRUE;
+        }
+      }
+      else
+      {
+        GST_WARNING ("reject play for invalid dv config %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (dvConfig));
+        bRejectPlay = TRUE;
+      }
+    }
+    else if (sampleEntry == FOURCC_avc1 || sampleEntry == FOURCC_avc3 || sampleEntry == FOURCC_avc2 || sampleEntry == FOURCC_avc4)
+    {
+      if (dvConfig == FOURCC_dvcC || dvConfig == FOURCC_dvvC || dvConfig == FOURCC_dvwC)
+      {
+        if (dv_profile == 9)
+          GST_DEBUG ("Playback Dolby Vision");
+        else
+        {
+          GST_DEBUG ("invalid profile, Playback HEVC bitstream using base-layer");
+          dv_el_present_flag = 0;
+          dv_bl_present_flag = 0;
+        }
+      }
+      else
+      {
+        GST_DEBUG ("invalid dv config %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (dvConfig));
+        dv_el_present_flag = 0;
+        dv_bl_present_flag = 0;
+      }
+    }
+    else if (sampleEntry == FOURCC_dvav || sampleEntry == FOURCC_dva1)
+    {
+      if (dvConfig == FOURCC_dvcC)
+      {
+        if (dv_profile == 1)
+        {
+          GST_WARNING("reject play for invalid profile:%d", dv_profile);
+          bRejectPlay = TRUE;
+        }
+      }
+      else
+      {
+        GST_WARNING ("reject play for invalid dv config %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (dvConfig));
+        bRejectPlay = TRUE;
+      }
+    }
+    else if (sampleEntry == FOURCC_av01)
+    {
+      GST_DEBUG ("ToDo sampleEntry %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (sampleEntry));
+    }
+    else if (sampleEntry == FOURCC_dav1)
+    {
+      if (dvConfig == FOURCC_dvvC || dvConfig == FOURCC_dvwC)
+      {
+        if (dv_profile != 10)
+        {
+          GST_WARNING("reject play for invalid profile:%d", dv_profile);
+          bRejectPlay = TRUE;
+        }
+      }
+      else
+      {
+        GST_WARNING ("reject play for invalid dv config %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (dvConfig));
+        bRejectPlay = TRUE;
+      }
+    }
+    else if (sampleEntry == FOURCC_vvcN || sampleEntry == FOURCC_vvc1 || sampleEntry == FOURCC_vvi1 || sampleEntry == FOURCC_vvs1)
+    {
+      GST_DEBUG ("invalid sampleEntry %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (sampleEntry));
+      dv_el_present_flag = 0;
+      dv_bl_present_flag = 0;
+    }
+
+    gst_caps_set_simple (caps, "dv_bl_present_flag", G_TYPE_BOOLEAN, dv_bl_present_flag, NULL);
+    gst_caps_set_simple (caps, "dv_el_present_flag", G_TYPE_BOOLEAN, dv_el_present_flag, NULL);
+
+    return bRejectPlay ? -1 : 0;
+}
+
+static gint
+qtdemux_parse_sgpd_av1M (GstQTDemux * qtdemux, GNode * node)
+{
+  GNode *sgpd;
+  const guint8 *sgpd_data;
+  gint sgpd_size;
+  guint32 sgpd_fourcc;
+  gint sgpd_version;
+  gint sgpd_flag;
+  guint32 sgpd_group_type;
+  gint sgpd_default_len = -1;
+  guint sgpd_entry_cnt;
+  guint32 group_fourcc;
+  guint metadata_type;
+  guint metadata_specific_parameters;
+  gboolean bRejectPlay = FALSE;
+
+  GST_DEBUG_OBJECT (qtdemux, "try to find sgpd");
+
+  sgpd = qtdemux_tree_get_child_by_type (node, FOURCC_sgpd);
+  if (sgpd)
+  {
+      int rIdx = 0;
+      int entryIdx = 0;
+      sgpd_data = (const guint8 *) sgpd->data;
+      sgpd_size = QT_UINT32 (sgpd_data + rIdx);
+      rIdx += 4;
+
+      sgpd_fourcc = QT_FOURCC (sgpd_data + rIdx);
+      rIdx += 4;
+
+      sgpd_version = QT_UINT8 (sgpd_data + rIdx);
+      rIdx += 4; // 1 byte version + 3 byte flags
+
+      sgpd_group_type = QT_UINT32 (sgpd_data + rIdx);
+      rIdx += 4;
+
+      if (sgpd_version == 1) {
+        sgpd_default_len = QT_UINT32 (sgpd_data + rIdx);
+        rIdx += 4;
+      }
+      else if (sgpd_version >= 2)
+        rIdx += 4; // 4 byte default_sample_descriotion_index
+
+      sgpd_entry_cnt = QT_UINT32 (sgpd_data + rIdx);
+      rIdx += 4;
+
+      GST_WARNING_OBJECT (qtdemux, "sgpd_size=0x%x, sgpd_fourcc=0x%x, sgpd_version=0x%x, sgpd_group_type=0x%x, sgpd_entry_cnt=0x%x",
+        sgpd_size, sgpd_fourcc, sgpd_version, sgpd_group_type, sgpd_entry_cnt);
+
+      for (entryIdx = 0; entryIdx < sgpd_entry_cnt; entryIdx++)
+      {
+        if (sgpd_version == 1 && sgpd_default_len == 0) {
+          sgpd_default_len = QT_UINT32 (sgpd_data + rIdx);
+          rIdx += 4;
+        }
+
+        group_fourcc = QT_FOURCC (sgpd_data + rIdx);
+        rIdx += 4;
+
+        if (group_fourcc == FOURCC_av1M) {
+          metadata_type = QT_UINT8 (sgpd_data + rIdx);
+          rIdx += 1;
+
+          metadata_specific_parameters = QT_UINT32 (sgpd_data + rIdx);
+          rIdx += 4;
+
+          if ( metadata_type != 4 || metadata_specific_parameters != 0xB5003B) {
+            // METADATA_TYPE_ITUT_T35  and 0xB5003B
+            bRejectPlay = TRUE;
+          }
+        }
+      GST_WARNING_OBJECT (qtdemux, "group_fourcc=0x%x, metadata_type=0x%x, metadata_specific_parameters=0x%x",
+        group_fourcc, metadata_type, metadata_specific_parameters);
+
+      }
+    }
+    else
+    {
+      GST_DEBUG_OBJECT (qtdemux, "no sgpd");
+    }
+
+    return bRejectPlay ? -1 : 0;
+}
+
 static gboolean
 qtdemux_parse_stereo_svmi_atom (GstQTDemux * qtdemux, QtDemuxStream * stream,
     GNode * stbl)
@@ -11519,6 +11753,7 @@
           case FOURCC_H264:
           case FOURCC_avc1:
           case FOURCC_avc3:
+          case FOURCC_dav1:
           {
             guint len = QT_UINT32 (stsd_entry_data);
             len = len <= 0x56 ? 0 : len - 0x56;
@@ -11527,6 +11762,7 @@
             /* find avcC */
             while (len >= 0x8) {
               guint size;
+              guint32 dvconfig;
 
               if (QT_UINT32 (avc_data) <= 0x8)
                 size = 0;
@@ -11539,7 +11775,15 @@
                 /* No real data, so break out */
                 break;
 
-              switch (QT_FOURCC (avc_data + 0x4)) {
+              dvconfig = QT_FOURCC (avc_data + 0x4);
+              switch (dvconfig) {
+                case FOURCC_dvcC:
+                case FOURCC_dvvC:
+                case FOURCC_dvwC:
+                {
+                  qtdemux_parse_dvcc (fourcc, dvconfig, avc_data, entry->caps);
+                  break;
+                }
                 case FOURCC_avcC:
                 {
                   /* parse, if found */
@@ -11560,6 +11804,17 @@
 
                   break;
                 }
+                case FOURCC_av1C:
+                {
+                     GST_DEBUG_OBJECT (qtdemux, "found av1C in stsd,so try to find sgpd");
+
+                     if (qtdemux_parse_sgpd_av1M(qtdemux, stbl) == -1)
+                     {
+                        GST_WARNING_OBJECT (qtdemux, "reject play for invalid metadata_type and specific_parameters");
+                        goto corrupt_file;
+                     }
+                   break;
+                }
                 case FOURCC_strf:
                 {
                   GstBuffer *buf;
@@ -11620,60 +11875,7 @@
 
                   break;
                 }
-                case FOURCC_dvcC:
-                case FOURCC_dvvC:
-                case FOURCC_dvwC:
-                {
-                  guint32 dv_version_major = QT_UINT8(avc_data+8);
-                  guint32 dv_version_minor = QT_UINT8(avc_data+9);
-                  guint32 tmp = QT_UINT16(avc_data+10);
-                  guint32 dv_profile = (tmp >> 9) & 0x7f;	  // 7 bits
-                  guint32 dv_level = (tmp >> 3) & 0x3f;	// 6 bits
-                  guint32 rpu_present_flag = (tmp >> 2) & 0x01;
-                  gboolean el_present_flag = (tmp >> 1) & 0x01;	  // 1 bit
-                  gboolean bl_present_flag = tmp & 0x01;    // 1 bit
 
-                  guint32 dv_bl_signal_compatibility_id = 0;// 0 stands for None
-                  if (len >= 24) {
-                    guint32 id = QT_UINT8(avc_data+12);
-                    dv_bl_signal_compatibility_id = (id >> 4) & 0x0f; // 4 bits
-                  }
-
-                  gst_caps_set_simple (entry->caps, "dv_bl_present_flag", G_TYPE_BOOLEAN, bl_present_flag, NULL);
-                  gst_caps_set_simple (entry->caps, "dv_el_present_flag", G_TYPE_BOOLEAN, el_present_flag, NULL);
-
-                  GST_DEBUG_OBJECT (qtdemux,"DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, "
-                    "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
-                    dv_version_major, dv_version_minor,
-                    dv_profile, dv_level,
-                    rpu_present_flag,
-                    el_present_flag,
-                    bl_present_flag,
-                    dv_bl_signal_compatibility_id
-                  );
-                  /*
-                  Expected results are:
-                  • If the test vector (MP4) carries an undefined/unknown Base Layer Signal Compatibility ID (dv_bl_signal_
-                  compatibility_id), the device under test rejects the playback.
-                  • If the test vector (MP4) is of an undefined/unknown Dolby Vision profile, but its Base Layer Signal
-                  Compatibility ID (dv_bl_signal_compatibility_id) is valid, the device under test plays the content
-                  properly and TV displays in Dolby Vision picture mode.
-                  Note: Level 11 metadata changes when the embedded label on the left side of the test pattern
-                  changes.
-                  • If the Dolby Vision configuration box contains unknown elements (reserved fields with non-zero value),
-                  the device under test ignores the unknown elements properly and play the MP4 test vector properly and
-                  TV displays in Dolby Vision picture mode.
-                  */
-                 if (dv_bl_signal_compatibility_id != 0 &&
-                       dv_bl_signal_compatibility_id != 1 &&
-                       dv_bl_signal_compatibility_id != 2 &&
-                       dv_bl_signal_compatibility_id != 4 &&
-                       dv_bl_signal_compatibility_id != 6) {
-                         GST_ERROR_OBJECT(qtdemux,"Not support dolby vision config box");
-                    goto corrupt_file;
-                  }
-
-                } break;
                 default:
                   break;
               }
@@ -11697,6 +11899,7 @@
             /* find hevc */
             while (len >= 0x8) {
               guint size;
+              guint32 dvconfig;
 
               if (QT_UINT32 (hevc_data) <= 0x8)
                 size = 0;
@@ -11709,7 +11912,24 @@
                 /* No real data, so break out */
                 break;
 
-              switch (QT_FOURCC (hevc_data + 0x4)) {
+              dvconfig = QT_FOURCC (hevc_data + 0x4);
+
+              switch (dvconfig) {
+                case FOURCC_dvcC:
+                case FOURCC_dvvC:
+                case FOURCC_dvwC:
+                case FOURCC_dvzC:
+                case FOURCC_dvxC:
+                {
+                  gint ret = qtdemux_parse_dvcc (fourcc, dvconfig, hevc_data, entry->caps);
+                  if (ret == -1)
+                  {
+                    GST_WARNING_OBJECT (qtdemux, "reject play!");
+                    goto corrupt_file;
+                  }
+                  break;
+                }
+
                 case FOURCC_hvcC:
                 {
                   /* parse, if found */
@@ -11730,30 +11950,6 @@
                   gst_buffer_unref (buf);
                   break;
                 }
-                case FOURCC_dvcC:
-                case FOURCC_dvvC:
-                {
-                    gint len = QT_UINT32 (hevc_data);
-                    const guint8 *config_data = hevc_data + 0x8;
-                    gboolean dv_bl_present_flag = FALSE;
-                    gboolean dv_el_present_flag = FALSE;
-
-                    if (((1<<30) < len) || (1 != config_data[0]) || (0 != config_data[1]))
-                    {
-                         GST_DEBUG_OBJECT (qtdemux, "incorrect hvcC codec_data.");
-                    }
-                    else
-                    {
-                       dv_bl_present_flag = (config_data[3] & 0x01);
-                       dv_el_present_flag = ((config_data[3] >> 1) & 0x01);
-
-                       GST_DEBUG_OBJECT (qtdemux, "dv_bl_present_flag=%d, dv_el_present_flag=%d", dv_bl_present_flag, dv_el_present_flag);
-
-                       gst_caps_set_simple (entry->caps, "dv_bl_present_flag", G_TYPE_BOOLEAN, dv_bl_present_flag, NULL);
-                       gst_caps_set_simple (entry->caps, "dv_el_present_flag", G_TYPE_BOOLEAN, dv_el_present_flag, NULL);
-                    }
-                    break;
-                }
                 default:
                   break;
               }