matroska: Export h.264 profile and level in caps
authorArun Raghavan <ford_prefect@gentoo.org>
Thu, 1 Apr 2010 13:18:43 +0000 (18:48 +0530)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 2 Apr 2010 16:51:34 +0000 (18:51 +0200)
This replicates the code in qtdemux to export the h.264 profile and
level in the stream caps.

https://bugzilla.gnome.org/show_bug.cgi?id=614651

gst/matroska/matroska-demux.c
gst/qtdemux/qtdemux.c

index 926afad..414d6a3 100644 (file)
@@ -50,6 +50,7 @@
 
 #include <math.h>
 #include <string.h>
+#include <glib/gprintf.h>
 
 /* For AVI compatibility mode
    and for fourcc stuff */
@@ -5803,6 +5804,103 @@ gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
   return TRUE;
 }
 
+/*
+ * XXX: This code is duplicated in gst/qtdemux/qtdemux.c. Please replicate any
+ * changes you make over there as well.
+ */
+static gchar *
+avc_profile_idc_to_string (guint profile_idc, guint constraint_set_flags)
+{
+  const gchar *profile = NULL;
+  gint csf1, csf3;
+
+  csf1 = (constraint_set_flags & 0x40) >> 6;
+  csf3 = (constraint_set_flags & 0x10) >> 4;
+
+  switch (profile_idc) {
+    case 66:
+      if (csf1)
+        profile = "constrained-baseline";
+      else
+        profile = "baseline";
+      break;
+    case 77:
+      profile = "main";
+      break;
+    case 88:
+      profile = "extended";
+      break;
+    case 100:
+      profile = "high";
+      break;
+    case 110:
+      if (csf3)
+        profile = "high-10-intra";
+      else
+        profile = "high-10";
+      break;
+    case 122:
+      if (csf3)
+        profile = "high-4:2:2-intra";
+      else
+        profile = "high-4:2:2";
+      break;
+    case 244:
+      if (csf3)
+        profile = "high-4:4:4-intra";
+      else
+        profile = "high-4:4:4";
+      break;
+    case 44:
+      profile = "cavlc-4:4:4-intra";
+      break;
+    default:
+      return NULL;
+  }
+
+  return g_strdup (profile);
+}
+
+static gchar *
+avc_level_idc_to_string (guint level_idc, guint constraint_set_flags)
+{
+  const gchar *level = NULL;
+  gchar buf[4];
+  gint csf3;
+
+  csf3 = (constraint_set_flags & 0x10) >> 4;
+
+  if (level_idc == 11 && csf3)
+    level = "1b";
+  else {
+    /* Level is (level_idc / 10) */
+    if (level_idc % 10 == 0)
+      g_sprintf (buf, "%u", level_idc / 10);
+    else
+      g_sprintf (buf, "%u.%u", level_idc / 10, level_idc % 10);
+
+    level = buf;
+  }
+
+  return g_strdup (level);
+}
+
+static void
+avc_get_profile_and_level_string (const guint8 * avc_data, gint size,
+    gchar ** profile, gchar ** level)
+{
+  if (size >= 2)
+    /* First byte is the version, second is the profile indication,
+     * and third is the 5 contraint_set_flags and 3 reserved bits */
+    *profile = avc_profile_idc_to_string (GST_READ_UINT8 (avc_data + 1),
+        GST_READ_UINT8 (avc_data + 2));
+
+  if (size >= 4)
+    /* Fourth byte is the level indication */
+    *level = avc_level_idc_to_string (GST_READ_UINT8 (avc_data + 3),
+        GST_READ_UINT8 (avc_data + 2));
+}
+
 static GstCaps *
 gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
     videocontext, const gchar * codec_id, guint8 * data, guint size,
@@ -5967,6 +6065,17 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
     caps = gst_caps_new_simple ("video/x-h264", NULL);
     if (data) {
       GstBuffer *priv = gst_buffer_new_and_alloc (size);
+      gchar *profile = NULL, *level = NULL;
+
+      avc_get_profile_and_level_string (data, size, &profile, &level);
+      if (profile) {
+        gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
+        g_free (profile);
+      }
+      if (level) {
+        gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
+        g_free (level);
+      }
 
       memcpy (GST_BUFFER_DATA (priv), data, size);
       gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
index 347b6e1..f99ebec 100644 (file)
@@ -5013,6 +5013,10 @@ qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
   return uri;
 }
 
+/*
+ * XXX: This code is duplicated in gst/mastroska/matroska-demux.c. Please
+ * replicate any changes you make over there as well.
+ */
 static gchar *
 avc_profile_idc_to_string (guint profile_idc, guint constraint_set_flags)
 {