diff --git a/gst-libs/gst/codecparsers/gsth265parser.c b/gst-libs/gst/codecparsers/gsth265parser.c index 01f9d587a6..495f420665 100644 --- a/gst-libs/gst/codecparsers/gsth265parser.c +++ b/gst-libs/gst/codecparsers/gsth265parser.c @@ -2642,6 +2642,88 @@ gst_h265_quant_matrix_8x8_get_raster_from_uprightdiagonal (guint8 out_quant[64], out_quant[uprightdiagonal_8x8[i]] = quant[i]; } +typedef struct +{ + GstH265Profile profile; + + guint8 max_12bit_constraint_flag; + guint8 max_10bit_constraint_flag; + guint8 max_8bit_constraint_flag; + guint8 max_422chroma_constraint_flag; + guint8 max_420chroma_constraint_flag; + guint8 max_monochrome_constraint_flag; + guint8 intra_constraint_flag; + guint8 one_picture_only_constraint_flag; + gboolean lower_bit_rate_constraint_flag_set; +} FormatRangeExtensionProfile; + +static GstH265Profile +get_format_range_extension_profile (GstH265ProfileTierLevel * ptl) +{ + /* See Table A.2 for the definition of those formats */ + FormatRangeExtensionProfile profiles[] = { + {GST_H265_PROFILE_MONOCHROME, 1, 1, 1, 1, 1, 1, 0, 0, TRUE}, + {GST_H265_PROFILE_MONOCHROME_12, 1, 0, 0, 1, 1, 1, 0, 0, TRUE}, + {GST_H265_PROFILE_MONOCHROME_16, 0, 0, 0, 1, 1, 1, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_12, 1, 0, 0, 1, 1, 0, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_422_10, 1, 1, 0, 1, 0, 0, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_422_12, 1, 0, 0, 1, 0, 0, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_444, 1, 1, 1, 0, 0, 0, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_444_10, 1, 1, 0, 0, 0, 0, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_444_12, 1, 0, 0, 0, 0, 0, 0, 0, TRUE}, + {GST_H265_PROFILE_MAIN_INTRA, 1, 1, 1, 1, 1, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_10_INTRA, 1, 1, 0, 1, 1, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_12_INTRA, 1, 0, 0, 1, 1, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_422_10_INTRA, 1, 1, 0, 1, 0, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_422_12_INTRA, 1, 0, 0, 1, 0, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_444_INTRA, 1, 1, 1, 0, 0, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_444_10_INTRA, 1, 1, 0, 0, 0, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_444_12_INTRA, 1, 0, 0, 0, 0, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_444_16_INTRA, 0, 0, 0, 0, 0, 0, 1, 0, FALSE}, + {GST_H265_PROFILE_MAIN_444_STILL_PICTURE, 1, 1, 1, 0, 0, 0, 1, 1, FALSE}, + {GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE, 0, 0, 0, 0, 0, 0, 1, 1, FALSE}, + }; + guint i; + + for (i = 0; i < G_N_ELEMENTS (profiles); i++) { + FormatRangeExtensionProfile p = profiles[i]; + + if (p.max_12bit_constraint_flag != ptl->max_12bit_constraint_flag) + continue; + if (p.max_10bit_constraint_flag != ptl->max_10bit_constraint_flag) + continue; + if (p.max_8bit_constraint_flag != ptl->max_8bit_constraint_flag) + continue; + if (p.max_422chroma_constraint_flag != ptl->max_422chroma_constraint_flag) + continue; + if (p.max_420chroma_constraint_flag != ptl->max_420chroma_constraint_flag) + continue; + if (p.max_monochrome_constraint_flag != ptl->max_monochrome_constraint_flag) + continue; + if (p.intra_constraint_flag != ptl->intra_constraint_flag) + continue; + if (p.one_picture_only_constraint_flag != + ptl->one_picture_only_constraint_flag) + continue; + if (p.lower_bit_rate_constraint_flag_set + && !ptl->lower_bit_rate_constraint_flag) + continue; + + return p.profile; + } + + return GST_H265_PROFILE_INVALID; +} + +/** + * gst_h265_profile_tier_level_get_profile: + * @ptl: a #GstH265ProfileTierLevel + * + * Return the H265 profile defined in @ptl. + * + * Returns: a #GstH265Profile + * Since: 1.14 + */ GstH265Profile gst_h265_profile_tier_level_get_profile (GstH265ProfileTierLevel * ptl) { @@ -2657,8 +2739,11 @@ gst_h265_profile_tier_level_get_profile (GstH265ProfileTierLevel * ptl) || ptl->profile_compatibility_flag[3]) return GST_H265_PROFILE_MAIN_STILL_PICTURE; + if (ptl->profile_idc == GST_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSION + || ptl->profile_compatibility_flag[4]) + return get_format_range_extension_profile (ptl); + /* TODO: - * - GST_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSION * - GST_H265_PROFILE_IDC_HIGH_THROUGHPUT * - GST_H265_PROFILE_IDC_SCREEN_CONTENT_CODING */ diff --git a/gst-libs/gst/codecparsers/gsth265parser.h b/gst-libs/gst/codecparsers/gsth265parser.h index 45c5e54846..985e1b5655 100644 --- a/gst-libs/gst/codecparsers/gsth265parser.h +++ b/gst-libs/gst/codecparsers/gsth265parser.h @@ -46,6 +46,26 @@ G_BEGIN_DECLS * @GST_H265_PROFILE_MAIN: Main profile (A.3.2) * @GST_H265_PROFILE_MAIN_10: Main 10 profile (A.3.3) * @GST_H265_PROFILE_MAIN_STILL_PICTURE: Main Still Picture profile (A.3.4) + * @GST_H265_PROFILE_MONOCHROME: Monochrome profile (A.3.4) + * @GST_H265_PROFILE_MONOCHROME_12: Monochrome 12-bits profile (A.3.4) + * @GST_H265_PROFILE_MONOCHROME_16: Monochrome 16-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_12: Main profile 12-bits (A.3.4) + * @GST_H265_PROFILE_MAIN_422_10: Main 4:2:2 profile 10-bits (A.3.4) + * @GST_H265_PROFILE_MAIN_422_12: Main 4:2:2 profile 12-bits (A.3.4) + * @GST_H265_PROFILE_MAIN_444: Main 4:4:4 profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_10: Main 4:4:4 10-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_12: Main 4:4:4 12-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_INTRA: Main Intra profile (A.3.4) + * @GST_H265_PROFILE_MAIN_10_INTRA: Main Intra 10-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_12_INTRA: Main Intra 12-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_422_10_INTRA: Main Intra 4:2:2 10-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_422_12_INTRA: Main Intra 4:2:2 12-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_INTRA: Main Intra 4:4:4 profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_10_INTRA: Main Intra 4:4:4 10-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_12_INTRA: Main Intra 4:4:4 12-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_16_INTRA: Main Intra 4:4:4 16-bits profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_STILL_PICTURE: Main 4:4:4 Still Picture profile (A.3.4) + * @GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE: Main 4:4:4 16-bits Still Picture profile (A.3.4) * * H.265 Profiles. * @@ -54,7 +74,27 @@ typedef enum { GST_H265_PROFILE_INVALID = -1, GST_H265_PROFILE_MAIN = 1, GST_H265_PROFILE_MAIN_10 = 2, - GST_H265_PROFILE_MAIN_STILL_PICTURE = 3 + GST_H265_PROFILE_MAIN_STILL_PICTURE = 3, + GST_H265_PROFILE_MONOCHROME, + GST_H265_PROFILE_MONOCHROME_12, + GST_H265_PROFILE_MONOCHROME_16, + GST_H265_PROFILE_MAIN_12, + GST_H265_PROFILE_MAIN_422_10, + GST_H265_PROFILE_MAIN_422_12, + GST_H265_PROFILE_MAIN_444, + GST_H265_PROFILE_MAIN_444_10, + GST_H265_PROFILE_MAIN_444_12, + GST_H265_PROFILE_MAIN_INTRA, + GST_H265_PROFILE_MAIN_10_INTRA, + GST_H265_PROFILE_MAIN_12_INTRA, + GST_H265_PROFILE_MAIN_422_10_INTRA, + GST_H265_PROFILE_MAIN_422_12_INTRA, + GST_H265_PROFILE_MAIN_444_INTRA, + GST_H265_PROFILE_MAIN_444_10_INTRA, + GST_H265_PROFILE_MAIN_444_12_INTRA, + GST_H265_PROFILE_MAIN_444_16_INTRA, + GST_H265_PROFILE_MAIN_444_STILL_PICTURE, + GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE, } GstH265Profile; /** diff --git a/gst/videoparsers/gsth265parse.c b/gst/videoparsers/gsth265parse.c index 9722d7ef06..46de66f514 100644 --- a/gst/videoparsers/gsth265parse.c +++ b/gst/videoparsers/gsth265parse.c @@ -1234,6 +1234,46 @@ get_profile_string (GstH265Profile profile) return "main-10"; case GST_H265_PROFILE_MAIN_STILL_PICTURE: return "main-still-picture"; + case GST_H265_PROFILE_MONOCHROME: + return "monochrome"; + case GST_H265_PROFILE_MONOCHROME_12: + return "monochrome-12"; + case GST_H265_PROFILE_MONOCHROME_16: + return "monochrome-16"; + case GST_H265_PROFILE_MAIN_12: + return "main-12"; + case GST_H265_PROFILE_MAIN_422_10: + return "main-422-10"; + case GST_H265_PROFILE_MAIN_422_12: + return "main-422-12"; + case GST_H265_PROFILE_MAIN_444: + return "main-444"; + case GST_H265_PROFILE_MAIN_444_10: + return "main-444-10"; + case GST_H265_PROFILE_MAIN_444_12: + return "main-444-12"; + case GST_H265_PROFILE_MAIN_INTRA: + return "main-intra"; + case GST_H265_PROFILE_MAIN_10_INTRA: + return "main-10-intra"; + case GST_H265_PROFILE_MAIN_12_INTRA: + return "main-12-intra"; + case GST_H265_PROFILE_MAIN_422_10_INTRA: + return "main-422-10-intra"; + case GST_H265_PROFILE_MAIN_422_12_INTRA: + return "main-422-12-intra"; + case GST_H265_PROFILE_MAIN_444_INTRA: + return "main-444-intra"; + case GST_H265_PROFILE_MAIN_444_10_INTRA: + return "main-444-10-intra"; + case GST_H265_PROFILE_MAIN_444_12_INTRA: + return "main-444-12-intra"; + case GST_H265_PROFILE_MAIN_444_16_INTRA: + return "main-444-16-intra"; + case GST_H265_PROFILE_MAIN_444_STILL_PICTURE: + return "main-444-still-picture"; + case GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE: + return "main-444-16-still-picture"; default: break; } diff --git a/tests/check/libs/h265parser.c b/tests/check/libs/h265parser.c index 0a58e76e5f..0a7a5e10c4 100644 --- a/tests/check/libs/h265parser.c +++ b/tests/check/libs/h265parser.c @@ -70,6 +70,153 @@ GST_START_TEST (test_h265_base_profiles_compat) GST_END_TEST; +static void +set_format_range_fields (GstH265ProfileTierLevel * ptl, + guint8 max_12bit_constraint_flag, + guint8 max_10bit_constraint_flag, + guint8 max_8bit_constraint_flag, + guint8 max_422chroma_constraint_flag, + guint8 max_420chroma_constraint_flag, + guint8 max_monochrome_constraint_flag, + guint8 intra_constraint_flag, + guint8 one_picture_only_constraint_flag, + guint8 lower_bit_rate_constraint_flag) +{ + ptl->max_12bit_constraint_flag = max_12bit_constraint_flag; + ptl->max_10bit_constraint_flag = max_10bit_constraint_flag; + ptl->max_8bit_constraint_flag = max_8bit_constraint_flag; + ptl->max_422chroma_constraint_flag = max_422chroma_constraint_flag; + ptl->max_420chroma_constraint_flag = max_420chroma_constraint_flag; + ptl->max_monochrome_constraint_flag = max_monochrome_constraint_flag; + ptl->intra_constraint_flag = intra_constraint_flag; + ptl->one_picture_only_constraint_flag = one_picture_only_constraint_flag; + ptl->lower_bit_rate_constraint_flag = lower_bit_rate_constraint_flag; +} + +GST_START_TEST (test_h265_format_range_profiles_exact_match) +{ + /* Test all the combinations from Table A.2 */ + GstH265ProfileTierLevel ptl; + + memset (&ptl, 0, sizeof (ptl)); + ptl.profile_idc = 4; + + set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 1, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MONOCHROME); + + set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 1, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MONOCHROME_12); + + set_format_range_fields (&ptl, 0, 0, 0, 1, 1, 1, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MONOCHROME_16); + + set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 0, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_12); + + set_format_range_fields (&ptl, 1, 1, 0, 1, 0, 0, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_422_10); + + set_format_range_fields (&ptl, 1, 0, 0, 1, 0, 0, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_422_12); + + set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444); + + set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_10); + + set_format_range_fields (&ptl, 1, 0, 0, 0, 0, 0, 0, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_12); + + set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_INTRA); + set_format_range_fields (&ptl, 1, 1, 1, 1, 1, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_INTRA); + + set_format_range_fields (&ptl, 1, 1, 0, 1, 1, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_10_INTRA); + set_format_range_fields (&ptl, 1, 1, 0, 1, 1, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_10_INTRA); + + set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_12_INTRA); + set_format_range_fields (&ptl, 1, 0, 0, 1, 1, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_12_INTRA); + + set_format_range_fields (&ptl, 1, 1, 0, 1, 0, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_422_10_INTRA); + set_format_range_fields (&ptl, 1, 1, 0, 1, 0, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_422_10_INTRA); + + set_format_range_fields (&ptl, 1, 0, 0, 1, 0, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_422_12_INTRA); + set_format_range_fields (&ptl, 1, 0, 0, 1, 0, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_422_12_INTRA); + + set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_INTRA); + set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_INTRA); + + set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_10_INTRA); + set_format_range_fields (&ptl, 1, 1, 0, 0, 0, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_10_INTRA); + + set_format_range_fields (&ptl, 1, 0, 0, 0, 0, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_12_INTRA); + set_format_range_fields (&ptl, 1, 0, 0, 0, 0, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_12_INTRA); + + set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 0, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_16_INTRA); + set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 0, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_16_INTRA); + + set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 1, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_STILL_PICTURE); + set_format_range_fields (&ptl, 1, 1, 1, 0, 0, 0, 1, 1, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_STILL_PICTURE); + + set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 1, 0); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE); + set_format_range_fields (&ptl, 0, 0, 0, 0, 0, 0, 1, 1, 1); + g_assert_cmpuint (gst_h265_profile_tier_level_get_profile (&ptl), ==, + GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE); +} + +GST_END_TEST; + static Suite * h265parser_suite (void) { @@ -80,6 +227,7 @@ h265parser_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_h265_base_profiles); tcase_add_test (tc_chain, test_h265_base_profiles_compat); + tcase_add_test (tc_chain, test_h265_format_range_profiles_exact_match); return s; }