mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 20:42:30 +00:00
h265parser: allow partial matching on range extension profile
Best to return a valid profiles rather than no profile if bitstream uses a not standard profile. https://bugzilla.gnome.org/show_bug.cgi?id=793876
This commit is contained in:
parent
9f25fcdfc9
commit
6dd997541c
2 changed files with 130 additions and 38 deletions
|
@ -2655,64 +2655,140 @@ typedef struct
|
||||||
guint8 intra_constraint_flag;
|
guint8 intra_constraint_flag;
|
||||||
guint8 one_picture_only_constraint_flag;
|
guint8 one_picture_only_constraint_flag;
|
||||||
gboolean lower_bit_rate_constraint_flag_set;
|
gboolean lower_bit_rate_constraint_flag_set;
|
||||||
|
|
||||||
|
/* Tie breaker if more than one profiles are matching */
|
||||||
|
guint priority;
|
||||||
} FormatRangeExtensionProfile;
|
} FormatRangeExtensionProfile;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FormatRangeExtensionProfile *profile;
|
||||||
|
guint extra_constraints;
|
||||||
|
} FormatRangeExtensionProfileMatch;
|
||||||
|
|
||||||
|
static gint
|
||||||
|
sort_fre_profile_matches (FormatRangeExtensionProfileMatch * a,
|
||||||
|
FormatRangeExtensionProfileMatch * b)
|
||||||
|
{
|
||||||
|
gint d;
|
||||||
|
|
||||||
|
d = a->extra_constraints - b->extra_constraints;
|
||||||
|
if (d)
|
||||||
|
return d;
|
||||||
|
|
||||||
|
return b->profile->priority - a->profile->priority;
|
||||||
|
}
|
||||||
|
|
||||||
static GstH265Profile
|
static GstH265Profile
|
||||||
get_format_range_extension_profile (GstH265ProfileTierLevel * ptl)
|
get_format_range_extension_profile (GstH265ProfileTierLevel * ptl)
|
||||||
{
|
{
|
||||||
/* See Table A.2 for the definition of those formats */
|
/* See Table A.2 for the definition of those formats */
|
||||||
FormatRangeExtensionProfile profiles[] = {
|
FormatRangeExtensionProfile profiles[] = {
|
||||||
{GST_H265_PROFILE_MONOCHROME, 1, 1, 1, 1, 1, 1, 0, 0, TRUE},
|
{GST_H265_PROFILE_MONOCHROME, 1, 1, 1, 1, 1, 1, 0, 0, TRUE, 0},
|
||||||
{GST_H265_PROFILE_MONOCHROME_12, 1, 0, 0, 1, 1, 1, 0, 0, TRUE},
|
{GST_H265_PROFILE_MONOCHROME_12, 1, 0, 0, 1, 1, 1, 0, 0, TRUE, 1},
|
||||||
{GST_H265_PROFILE_MONOCHROME_16, 0, 0, 0, 1, 1, 1, 0, 0, TRUE},
|
{GST_H265_PROFILE_MONOCHROME_16, 0, 0, 0, 1, 1, 1, 0, 0, TRUE, 2},
|
||||||
{GST_H265_PROFILE_MAIN_12, 1, 0, 0, 1, 1, 0, 0, 0, TRUE},
|
{GST_H265_PROFILE_MAIN_12, 1, 0, 0, 1, 1, 0, 0, 0, TRUE, 3},
|
||||||
{GST_H265_PROFILE_MAIN_422_10, 1, 1, 0, 1, 0, 0, 0, 0, TRUE},
|
{GST_H265_PROFILE_MAIN_422_10, 1, 1, 0, 1, 0, 0, 0, 0, TRUE, 4},
|
||||||
{GST_H265_PROFILE_MAIN_422_12, 1, 0, 0, 1, 0, 0, 0, 0, TRUE},
|
{GST_H265_PROFILE_MAIN_422_12, 1, 0, 0, 1, 0, 0, 0, 0, TRUE, 5},
|
||||||
{GST_H265_PROFILE_MAIN_444, 1, 1, 1, 0, 0, 0, 0, 0, TRUE},
|
{GST_H265_PROFILE_MAIN_444, 1, 1, 1, 0, 0, 0, 0, 0, TRUE, 6},
|
||||||
{GST_H265_PROFILE_MAIN_444_10, 1, 1, 0, 0, 0, 0, 0, 0, TRUE},
|
{GST_H265_PROFILE_MAIN_444_10, 1, 1, 0, 0, 0, 0, 0, 0, TRUE, 7},
|
||||||
{GST_H265_PROFILE_MAIN_444_12, 1, 0, 0, 0, 0, 0, 0, 0, TRUE},
|
{GST_H265_PROFILE_MAIN_444_12, 1, 0, 0, 0, 0, 0, 0, 0, TRUE, 8},
|
||||||
{GST_H265_PROFILE_MAIN_INTRA, 1, 1, 1, 1, 1, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_INTRA, 1, 1, 1, 1, 1, 0, 1, 0, FALSE, 9},
|
||||||
{GST_H265_PROFILE_MAIN_10_INTRA, 1, 1, 0, 1, 1, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_10_INTRA, 1, 1, 0, 1, 1, 0, 1, 0, FALSE, 10},
|
||||||
{GST_H265_PROFILE_MAIN_12_INTRA, 1, 0, 0, 1, 1, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_12_INTRA, 1, 0, 0, 1, 1, 0, 1, 0, FALSE, 11},
|
||||||
{GST_H265_PROFILE_MAIN_422_10_INTRA, 1, 1, 0, 1, 0, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_422_10_INTRA, 1, 1, 0, 1, 0, 0, 1, 0, FALSE, 12},
|
||||||
{GST_H265_PROFILE_MAIN_422_12_INTRA, 1, 0, 0, 1, 0, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_422_12_INTRA, 1, 0, 0, 1, 0, 0, 1, 0, FALSE, 13},
|
||||||
{GST_H265_PROFILE_MAIN_444_INTRA, 1, 1, 1, 0, 0, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_444_INTRA, 1, 1, 1, 0, 0, 0, 1, 0, FALSE, 14},
|
||||||
{GST_H265_PROFILE_MAIN_444_10_INTRA, 1, 1, 0, 0, 0, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_444_10_INTRA, 1, 1, 0, 0, 0, 0, 1, 0, FALSE, 15},
|
||||||
{GST_H265_PROFILE_MAIN_444_12_INTRA, 1, 0, 0, 0, 0, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_444_12_INTRA, 1, 0, 0, 0, 0, 0, 1, 0, FALSE, 16},
|
||||||
{GST_H265_PROFILE_MAIN_444_16_INTRA, 0, 0, 0, 0, 0, 0, 1, 0, FALSE},
|
{GST_H265_PROFILE_MAIN_444_16_INTRA, 0, 0, 0, 0, 0, 0, 1, 0, FALSE, 17},
|
||||||
{GST_H265_PROFILE_MAIN_444_STILL_PICTURE, 1, 1, 1, 0, 0, 0, 1, 1, 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},
|
18},
|
||||||
|
{GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE, 0, 0, 0, 0, 0, 0, 1, 1, FALSE,
|
||||||
|
19},
|
||||||
};
|
};
|
||||||
|
GstH265Profile result = GST_H265_PROFILE_INVALID;
|
||||||
guint i;
|
guint i;
|
||||||
|
GList *matches = NULL;
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (profiles); i++) {
|
for (i = 0; i < G_N_ELEMENTS (profiles); i++) {
|
||||||
FormatRangeExtensionProfile p = profiles[i];
|
FormatRangeExtensionProfile p = profiles[i];
|
||||||
|
guint extra_constraints = 0;
|
||||||
|
FormatRangeExtensionProfileMatch *m;
|
||||||
|
|
||||||
if (p.max_12bit_constraint_flag != ptl->max_12bit_constraint_flag)
|
/* Filter out all the profiles having constraints not satisified by @ptl.
|
||||||
|
* Then pick the one having the least extra contraints. This allow us
|
||||||
|
* to match the closet profile if bitstream contains not standard
|
||||||
|
* constraints. */
|
||||||
|
if (p.max_12bit_constraint_flag != ptl->max_12bit_constraint_flag) {
|
||||||
|
if (p.max_12bit_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
if (p.max_10bit_constraint_flag != ptl->max_10bit_constraint_flag)
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.max_10bit_constraint_flag != ptl->max_10bit_constraint_flag) {
|
||||||
|
if (p.max_10bit_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
if (p.max_8bit_constraint_flag != ptl->max_8bit_constraint_flag)
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.max_8bit_constraint_flag != ptl->max_8bit_constraint_flag) {
|
||||||
|
if (p.max_8bit_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
if (p.max_422chroma_constraint_flag != ptl->max_422chroma_constraint_flag)
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.max_422chroma_constraint_flag != ptl->max_422chroma_constraint_flag) {
|
||||||
|
if (p.max_422chroma_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
if (p.max_420chroma_constraint_flag != ptl->max_420chroma_constraint_flag)
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.max_420chroma_constraint_flag != ptl->max_420chroma_constraint_flag) {
|
||||||
|
if (p.max_420chroma_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
if (p.max_monochrome_constraint_flag != ptl->max_monochrome_constraint_flag)
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.max_monochrome_constraint_flag != ptl->max_monochrome_constraint_flag) {
|
||||||
|
if (p.max_monochrome_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
if (p.intra_constraint_flag != ptl->intra_constraint_flag)
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.intra_constraint_flag != ptl->intra_constraint_flag) {
|
||||||
|
if (p.intra_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
if (p.one_picture_only_constraint_flag !=
|
if (p.one_picture_only_constraint_flag !=
|
||||||
ptl->one_picture_only_constraint_flag)
|
ptl->one_picture_only_constraint_flag) {
|
||||||
|
if (p.one_picture_only_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
|
extra_constraints++;
|
||||||
|
}
|
||||||
|
|
||||||
if (p.lower_bit_rate_constraint_flag_set
|
if (p.lower_bit_rate_constraint_flag_set
|
||||||
&& !ptl->lower_bit_rate_constraint_flag)
|
&& !ptl->lower_bit_rate_constraint_flag)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return p.profile;
|
m = g_new0 (FormatRangeExtensionProfileMatch, 1);
|
||||||
|
m->profile = &profiles[i];
|
||||||
|
m->extra_constraints = extra_constraints;
|
||||||
|
matches = g_list_prepend (matches, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_H265_PROFILE_INVALID;
|
if (matches) {
|
||||||
|
FormatRangeExtensionProfileMatch *m;
|
||||||
|
|
||||||
|
matches = g_list_sort (matches, (GCompareFunc) sort_fre_profile_matches);
|
||||||
|
m = matches->data;
|
||||||
|
result = m->profile->profile;
|
||||||
|
g_list_free_full (matches, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -217,6 +217,21 @@ GST_START_TEST (test_h265_format_range_profiles_exact_match)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_h265_format_range_profiles_partial_match)
|
||||||
|
{
|
||||||
|
/* Test matching compatible profiles from non-standard bitstream */
|
||||||
|
GstH265ProfileTierLevel ptl;
|
||||||
|
|
||||||
|
memset (&ptl, 0, sizeof (ptl));
|
||||||
|
ptl.profile_idc = 4;
|
||||||
|
|
||||||
|
set_format_range_fields (&ptl, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
h265parser_suite (void)
|
h265parser_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -228,6 +243,7 @@ h265parser_suite (void)
|
||||||
tcase_add_test (tc_chain, test_h265_base_profiles);
|
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_base_profiles_compat);
|
||||||
tcase_add_test (tc_chain, test_h265_format_range_profiles_exact_match);
|
tcase_add_test (tc_chain, test_h265_format_range_profiles_exact_match);
|
||||||
|
tcase_add_test (tc_chain, test_h265_format_range_profiles_partial_match);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue