h265parse: recognize more HEVC extension streams
authorHaihao Xiang <haihao.xiang@intel.com>
Tue, 9 Jun 2020 02:10:12 +0000 (10:10 +0800)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 16 Sep 2020 16:51:45 +0000 (16:51 +0000)
There are streams which have the right general_profile_idc and
general_profile_compatibility_flag, but don't have the right extension
flags. We may try to use chroma_format_idc and bit_depth to
recognize these streams.

e.g.
https://www.itu.int/wftp3/av-arch/jctvc-site/bitstream_exchange/draft_conformance/SCC/IBF_Disabled_A_MediaTek_2.zip

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1328>

gst-libs/gst/codecparsers/gsth265parser.c
gst-libs/gst/codecparsers/gsth265parser.h
gst/videoparsers/gsth265parse.c
tests/check/libs/h265parser.c

index 69166ca..121f844 100644 (file)
@@ -4289,3 +4289,91 @@ gst_h265_parser_insert_sei_hevc (GstH265Parser * parser, guint8 nal_length_size,
   return gst_h265_parser_insert_sei_internal (parser, nal_length_size, TRUE,
       au, sei);
 }
+
+/**
+ * gst_h265_get_profile_from_sps:
+ * @sps: a #GstH265SPS
+ *
+ * Return the H265 profile from @sps.
+ *
+ * Returns: a #GstH265Profile
+ * Since: 1.20
+ */
+GstH265Profile
+gst_h265_get_profile_from_sps (GstH265SPS * sps)
+{
+  GstH265Profile p;
+
+  p = gst_h265_profile_tier_level_get_profile (&sps->profile_tier_level);
+
+  if (p == GST_H265_PROFILE_INVALID) {
+    GstH265ProfileTierLevel tmp_ptl = sps->profile_tier_level;
+    guint chroma_format_idc = sps->chroma_format_idc;
+    guint bit_depth_luma = sps->bit_depth_luma_minus8 + 8;
+    guint bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
+
+    /* Set the conformance indicators based on chroma_format_idc / bit_depth */
+    switch (chroma_format_idc) {
+      case 0:
+        tmp_ptl.max_monochrome_constraint_flag = 1;
+        tmp_ptl.max_420chroma_constraint_flag = 1;
+        tmp_ptl.max_422chroma_constraint_flag = 1;
+        break;
+
+      case 1:
+        tmp_ptl.max_monochrome_constraint_flag = 0;
+        tmp_ptl.max_420chroma_constraint_flag = 1;
+        tmp_ptl.max_422chroma_constraint_flag = 1;
+        break;
+
+      case 2:
+        tmp_ptl.max_monochrome_constraint_flag = 0;
+        tmp_ptl.max_420chroma_constraint_flag = 0;
+        tmp_ptl.max_422chroma_constraint_flag = 1;
+        break;
+
+      case 3:
+        tmp_ptl.max_monochrome_constraint_flag = 0;
+        tmp_ptl.max_420chroma_constraint_flag = 0;
+        tmp_ptl.max_422chroma_constraint_flag = 0;
+        break;
+
+      default:
+        g_assert_not_reached ();
+        break;
+    }
+
+    tmp_ptl.max_8bit_constraint_flag = 1;
+    tmp_ptl.max_10bit_constraint_flag = 1;
+    tmp_ptl.max_12bit_constraint_flag = 1;
+    tmp_ptl.max_14bit_constraint_flag = 1;
+
+    if (bit_depth_luma > 8 || bit_depth_chroma > 8)
+      tmp_ptl.max_8bit_constraint_flag = 0;
+
+    if (bit_depth_luma > 10 || bit_depth_chroma > 10)
+      tmp_ptl.max_10bit_constraint_flag = 0;
+
+    if (bit_depth_luma > 12 || bit_depth_chroma > 12)
+      tmp_ptl.max_12bit_constraint_flag = 0;
+
+    if (tmp_ptl.profile_idc == GST_H265_PROFILE_IDC_HIGH_THROUGHPUT
+        || tmp_ptl.profile_idc == GST_H265_PROFILE_IDC_SCREEN_CONTENT_CODING
+        || tmp_ptl.profile_idc ==
+        GST_H265_PROFILE_IDC_SCALABLE_FORMAT_RANGE_EXTENSION
+        || tmp_ptl.profile_idc ==
+        GST_H265_PROFILE_IDC_HIGH_THROUGHPUT_SCREEN_CONTENT_CODING_EXTENSION
+        || tmp_ptl.profile_compatibility_flag[5]
+        || tmp_ptl.profile_compatibility_flag[9]
+        || tmp_ptl.profile_compatibility_flag[10]
+        || tmp_ptl.profile_compatibility_flag[11]) {
+      if (bit_depth_luma > 14 || bit_depth_chroma > 14)
+        tmp_ptl.max_14bit_constraint_flag = 0;
+    } else
+      tmp_ptl.max_14bit_constraint_flag = 0;
+
+    p = gst_h265_profile_tier_level_get_profile (&tmp_ptl);
+  }
+
+  return p;
+}
index 073123d..8234761 100644 (file)
@@ -1808,5 +1808,8 @@ GstBuffer * gst_h265_parser_insert_sei_hevc (GstH265Parser * parser,
                                              GstBuffer * au,
                                              GstMemory * sei);
 
+GST_CODEC_PARSERS_API
+GstH265Profile gst_h265_get_profile_from_sps (GstH265SPS * sps);
+
 G_END_DECLS
 #endif
index 58d3d24..9b9a899 100644 (file)
@@ -2194,7 +2194,8 @@ gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
       const gchar *profile, *tier, *level;
       GstH265Profile p;
 
-      p = gst_h265_profile_tier_level_get_profile (&sps->profile_tier_level);
+      p = gst_h265_get_profile_from_sps (sps);
+
       profile = gst_h265_profile_to_string (p);
       if (profile != NULL)
         gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
index 5676aea..449fe2f 100644 (file)
@@ -331,6 +331,15 @@ set_format_range_fields (GstH265ProfileTierLevel * ptl,
   ptl->lower_bit_rate_constraint_flag = lower_bit_rate_constraint_flag;
 }
 
+static void
+set_chroma_idc_and_depth (GstH265SPS * sps, guint8 chroma_idc,
+    guint8 depth_luma, guint8 depth_chroma)
+{
+  sps->chroma_format_idc = chroma_idc;
+  sps->bit_depth_luma_minus8 = depth_luma - 8;
+  sps->bit_depth_chroma_minus8 = depth_chroma - 8;
+}
+
 GST_START_TEST (test_h265_format_range_profiles_exact_match)
 {
   /* Test all the combinations from Table A.2 */
@@ -508,72 +517,81 @@ GST_END_TEST;
 GST_START_TEST (test_h265_format_range_profiles_partial_match)
 {
   /* Test matching compatible profiles from non-standard bitstream */
-  GstH265ProfileTierLevel ptl;
+  GstH265SPS sps;
+  GstH265ProfileTierLevel *ptl = &sps.profile_tier_level;
 
-  memset (&ptl, 0, sizeof (ptl));
-  ptl.profile_idc = 4;
-  set_format_range_fields (&ptl, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  memset (&sps, 0, sizeof (sps));
+  ptl->profile_idc = 4;
+  set_format_range_fields (ptl, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_MAIN_444);
 
-  ptl.profile_idc = 5;
+  ptl->profile_idc = 5;
   /* wrong max_monochrome_constraint_flag, should still be compatible
      with GST_H265_PROFILE_HIGH_THROUGHPUT_444_10 */
-  set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_HIGH_THROUGHPUT_444_10);
   /* wrong max_12bit_constraint_flag, should still be compatible
      with GST_H265_PROFILE_HIGH_THROUGHPUT_444_14 */
-  set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_HIGH_THROUGHPUT_444_14);
   /* wrong intra_constraint_flag, GST_H265_PROFILE_HIGH_THROUGHPUT_444_14
      and GST_H265_PROFILE_HIGH_THROUGHPUT_444_16_INTRA are both compatible,
      but GST_H265_PROFILE_HIGH_THROUGHPUT_444_16_INTRA should be chosen
      because of the higher priority. */
-  set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_HIGH_THROUGHPUT_444_16_INTRA);
 
-  ptl.profile_idc = 6;
+  ptl->profile_idc = 6;
   /* wrong max_12bit_constraint_flag, should not be compatible with any */
-  set_format_range_fields (&ptl, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_INVALID);
 
-  ptl.profile_idc = 7;
+  ptl->profile_idc = 7;
   /* wrong max_monochrome_constraint_flag, and intra_constraint_flag,
      still compatible with GST_H265_PROFILE_SCALABLE_MAIN_10 */
-  set_format_range_fields (&ptl, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_SCALABLE_MAIN_10);
 
-  ptl.profile_idc = 8;
+  ptl->profile_idc = 8;
   /* wrong one_picture_only_constraint_flag, still compatible
      with GST_H265_PROFILE_3D_MAIN */
-  set_format_range_fields (&ptl, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_3D_MAIN);
 
-  ptl.profile_idc = 9;
+  ptl->profile_idc = 9;
   /* wrong one_picture_only_constraint_flag, still compatible
      with GST_H265_PROFILE_SCREEN_EXTENDED_MAIN */
-  set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
+  /* wrong indications but have right chroma_format_idc and bit_depth in SPS,
+     should be recognized as GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444 */
+  set_format_range_fields (ptl, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
+      GST_H265_PROFILE_INVALID);
+  set_chroma_idc_and_depth (&sps, 3, 8, 8);
+  g_assert_cmpuint (gst_h265_get_profile_from_sps (&sps), ==,
+      GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
 
-  ptl.profile_idc = 10;
+  ptl->profile_idc = 10;
   /* wrong max_10bit_constraint_flag, still compatible
      with GST_H265_PROFILE_SCALABLE_MONOCHROME_16 */
-  set_format_range_fields (&ptl, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_SCALABLE_MONOCHROME_16);
 
-  ptl.profile_idc = 11;
+  ptl->profile_idc = 11;
   /* wrong max_12bit_constraint_flag and max_422chroma_constraint_flag,
      should be recognized as GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14 */
-  set_format_range_fields (&ptl, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1);
-  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==,
+  set_format_range_fields (ptl, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1);
+  g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (ptl), ==,
       GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
 }