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 one_picture_only_constraint_flag;
|
||||
gboolean lower_bit_rate_constraint_flag_set;
|
||||
|
||||
/* Tie breaker if more than one profiles are matching */
|
||||
guint priority;
|
||||
} 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
|
||||
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},
|
||||
{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, 1},
|
||||
{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, 3},
|
||||
{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, 5},
|
||||
{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, 7},
|
||||
{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, 9},
|
||||
{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, 11},
|
||||
{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, 13},
|
||||
{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, 15},
|
||||
{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, 17},
|
||||
{GST_H265_PROFILE_MAIN_444_STILL_PICTURE, 1, 1, 1, 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;
|
||||
GList *matches = NULL;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
extra_constraints++;
|
||||
}
|
||||
|
||||
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;
|
||||
extra_constraints++;
|
||||
}
|
||||
|
||||
if (p.lower_bit_rate_constraint_flag_set
|
||||
&& !ptl->lower_bit_rate_constraint_flag)
|
||||
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_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 *
|
||||
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_compat);
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue