summaryrefslogtreecommitdiff
path: root/gst
diff options
context:
space:
mode:
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>2015-08-07 05:58:22 +0300
committerSebastian Dröge <sebastian@centricular.com>2015-08-07 13:11:53 +0200
commit69becd734d3f94264f6f0ef2e6147205646c1abd (patch)
treee50f7be7b6115686c5d2ee5868dd7cd486d917fe /gst
parentef7a074fa04895208530a2ffd370a8fabb699b2b (diff)
downloadgstreamer-plugins-bad-69becd734d3f94264f6f0ef2e6147205646c1abd.tar.gz
h265parse: expose compatible profiles to downstream
Some video bitstreams report a too restrictive set of profiles. If a video decoder was to strictly follow the indicated profile, it wouldn't support that stream, whereas it could in theory and in practice. So we should relax the profile restriction for allowing the decoder to get connected with parser. https://bugzilla.gnome.org/show_bug.cgi?id=747613
Diffstat (limited to 'gst')
-rw-r--r--gst/videoparsers/gsth265parse.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/gst/videoparsers/gsth265parse.c b/gst/videoparsers/gsth265parse.c
index 983ffec1d..a11b7fc5d 100644
--- a/gst/videoparsers/gsth265parse.c
+++ b/gst/videoparsers/gsth265parse.c
@@ -1273,6 +1273,109 @@ get_level_string (guint8 level_idc)
}
}
+static GstCaps *
+get_compatible_profile_caps (GstH265SPS * sps)
+{
+ GstCaps *caps = NULL;
+ const gchar **profiles = NULL;
+ gint i;
+ GValue compat_profiles = G_VALUE_INIT;
+ g_value_init (&compat_profiles, GST_TYPE_LIST);
+
+ switch (sps->profile_tier_level.profile_idc) {
+ case GST_H265_PROFILE_MAIN_10:
+ if (sps->profile_tier_level.profile_compatibility_flag[1]) {
+ if (sps->profile_tier_level.profile_compatibility_flag[3]) {
+ static const gchar *profile_array[] =
+ { "main", "main-still-picture", NULL };
+ profiles = profile_array;
+ } else {
+ static const gchar *profile_array[] = { "main", NULL };
+ profiles = profile_array;
+ }
+ }
+ break;
+ case GST_H265_PROFILE_MAIN:
+ if (sps->profile_tier_level.profile_compatibility_flag[3]) {
+ static const gchar *profile_array[] =
+ { "main-still-picture", "main-10", NULL
+ };
+ profiles = profile_array;
+ } else {
+ static const gchar *profile_array[] = { "main-10", NULL };
+ profiles = profile_array;
+ }
+ break;
+ case GST_H265_PROFILE_MAIN_STILL_PICTURE:
+ {
+ static const gchar *profile_array[] = { "main", "main-10", NULL
+ };
+ profiles = profile_array;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (profiles) {
+ GValue value = G_VALUE_INIT;
+ caps = gst_caps_new_empty_simple ("video/x-h265");
+ for (i = 0; profiles[i]; i++) {
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, profiles[i]);
+ gst_value_list_append_value (&compat_profiles, &value);
+ g_value_unset (&value);
+ }
+ gst_caps_set_value (caps, "profile", &compat_profiles);
+ g_value_unset (&compat_profiles);
+ }
+
+ return caps;
+}
+
+/* if downstream didn't support the exact profile indicated in sps header,
+ * check for the compatible profiles also */
+static void
+ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps)
+{
+ GstCaps *filter_caps, *peer_caps, *compat_caps;
+
+ filter_caps = gst_caps_new_empty_simple ("video/x-h265");
+ peer_caps =
+ gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse), filter_caps);
+
+ if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
+ GstStructure *structure;
+
+ compat_caps = get_compatible_profile_caps (sps);
+ if (compat_caps != NULL) {
+ GstCaps *res_caps = NULL;
+
+ res_caps = gst_caps_intersect (peer_caps, compat_caps);
+
+ if (res_caps && !gst_caps_is_empty (res_caps)) {
+ const gchar *profile_str = NULL;
+
+ res_caps = gst_caps_fixate (res_caps);
+ structure = gst_caps_get_structure (res_caps, 0);
+ profile_str = gst_structure_get_string (structure, "profile");
+ if (profile_str) {
+ gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
+ NULL);
+ GST_DEBUG_OBJECT (h265parse,
+ "Setting compatible profile %s to the caps", profile_str);
+ }
+ }
+ if (res_caps)
+ gst_caps_unref (res_caps);
+ gst_caps_unref (compat_caps);
+ }
+ }
+ if (peer_caps)
+ gst_caps_unref (peer_caps);
+ gst_caps_unref (filter_caps);
+}
+
static void
gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
{
@@ -1445,6 +1548,9 @@ gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
level = get_level_string (sps->profile_tier_level.level_idc);
if (level != NULL)
gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
+
+ /* relax the profile constraint to find a suitable decoder */
+ ensure_caps_profile (h265parse, caps, sps);
}
src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));