summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2018-03-05 14:21:14 +0100
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2018-03-05 13:22:12 -0500
commit6dd997541c15d877d4ca46ba23f0234958c9c6c8 (patch)
tree2b23cf57022dd868688ca31ece4f58db7bbc1700
parent9f25fcdfc9959bc8fd1154d233b567b36b06e278 (diff)
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
-rw-r--r--gst-libs/gst/codecparsers/gsth265parser.c152
-rw-r--r--tests/check/libs/h265parser.c16
2 files changed, 130 insertions, 38 deletions
diff --git a/gst-libs/gst/codecparsers/gsth265parser.c b/gst-libs/gst/codecparsers/gsth265parser.c
index 495f42066..cf7f71f5d 100644
--- a/gst-libs/gst/codecparsers/gsth265parser.c
+++ b/gst-libs/gst/codecparsers/gsth265parser.c
@@ -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;
+
+ /* 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;
+ extra_constraints++;
+ }
+
+ if (p.max_10bit_constraint_flag != ptl->max_10bit_constraint_flag) {
+ if (p.max_10bit_constraint_flag)
+ continue;
+ extra_constraints++;
+ }
+
+ if (p.max_8bit_constraint_flag != ptl->max_8bit_constraint_flag) {
+ if (p.max_8bit_constraint_flag)
+ continue;
+ extra_constraints++;
+ }
+
+ if (p.max_422chroma_constraint_flag != ptl->max_422chroma_constraint_flag) {
+ if (p.max_422chroma_constraint_flag)
+ continue;
+ extra_constraints++;
+ }
+
+ if (p.max_420chroma_constraint_flag != ptl->max_420chroma_constraint_flag) {
+ if (p.max_420chroma_constraint_flag)
+ continue;
+ extra_constraints++;
+ }
+
+ if (p.max_monochrome_constraint_flag != ptl->max_monochrome_constraint_flag) {
+ if (p.max_monochrome_constraint_flag)
+ continue;
+ extra_constraints++;
+ }
+
+ if (p.intra_constraint_flag != ptl->intra_constraint_flag) {
+ if (p.intra_constraint_flag)
+ continue;
+ extra_constraints++;
+ }
- 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;
+ 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;
}
/**
diff --git a/tests/check/libs/h265parser.c b/tests/check/libs/h265parser.c
index 0a7a5e10c..37de71f4c 100644
--- a/tests/check/libs/h265parser.c
+++ b/tests/check/libs/h265parser.c
@@ -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;
}