h265parse: recognize more HEVC extension streams

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>
This commit is contained in:
Haihao Xiang 2020-06-09 10:10:12 +08:00 committed by GStreamer Merge Bot
parent 626af12498
commit 4a93f6e651
4 changed files with 141 additions and 31 deletions

View 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;
}

View 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

View 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);

View 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);
}