qtdemux: Add more fields to SVQ3 caps
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>
Thu, 29 Oct 2009 11:29:38 +0000 (08:29 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Wed, 18 Nov 2009 19:41:50 +0000 (16:41 -0300)
qtdemux only added the whole stsd atom as 'codec_data'
in its output caps for SVQ3. This patch makes it add
the SEQH (inside a SMI atom) and a gamma field (taken
from the gama atom) if available.

Fixes #587922

gst/qtdemux/qtdemux.c
gst/qtdemux/qtdemux_fourcc.h

index 720f68c..cf13a22 100644 (file)
@@ -4281,6 +4281,96 @@ done:
   return TRUE;
 }
 
+/*
+ * Parses the stsd atom of a svq3 trak looking for
+ * the SMI and gama atoms.
+ */
+static void
+qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
+    guint8 ** gamma, GstBuffer ** seqh)
+{
+  guint8 *_gamma = NULL;
+  GstBuffer *_seqh = NULL;
+  guint8 *stsd_data = stsd->data;
+  guint32 length = QT_UINT32 (stsd_data);
+  guint16 version;
+
+  if (length < 32) {
+    GST_WARNING_OBJECT (qtdemux, "stsd too short");
+    goto end;
+  }
+
+  stsd_data += 32;
+  length -= 32;
+  version = QT_UINT16 (stsd_data);
+  if (version == 3) {
+    if (length >= 70) {
+      length -= 70;
+      stsd_data += 70;
+      while (length > 8) {
+        guint32 fourcc, size;
+        guint8 *data;
+        size = QT_UINT32 (stsd_data);
+        fourcc = QT_FOURCC (stsd_data + 4);
+        data = stsd_data + 8;
+
+        switch (fourcc) {
+          case FOURCC_gama:{
+            if (size == 12) {
+              _gamma = data;
+            } else {
+              GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
+                  " for gama atom, expected 12", size);
+            }
+            break;
+          }
+          case FOURCC_SMI_:{
+            if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
+              guint32 seqh_size;
+              if (_seqh != NULL) {
+                GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
+                    " found, ignoring");
+              } else {
+                seqh_size = QT_UINT32 (data + 4);
+                if (seqh_size > 0) {
+                  _seqh = gst_buffer_new_and_alloc (seqh_size);
+                  memcpy (GST_BUFFER_DATA (_seqh), data + 8, seqh_size);
+                }
+              }
+            }
+            break;
+          }
+          default:{
+            GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
+                " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
+          }
+        }
+
+        if (size <= length) {
+          length -= size;
+          stsd_data += size;
+        }
+      }
+    } else {
+      GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
+    }
+  } else {
+    GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
+        G_GUINT16_FORMAT, version);
+    goto end;
+  }
+
+end:
+  if (gamma) {
+    *gamma = _gamma;
+  }
+  if (seqh) {
+    *seqh = _seqh;
+  } else if (_seqh) {
+    gst_buffer_unref (_seqh);
+  }
+}
+
 /* parse the traks.
  * With each track we associate a new QtDemuxStream that contains all the info
  * about the trak.
@@ -4722,10 +4812,23 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
         case FOURCC_VP31:
         {
           GstBuffer *buf;
+          GstBuffer *seqh = NULL;
+          guint8 *gamma_data = NULL;
           gint len = QT_UINT32 (stsd_data);
 
-          GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
+          qtdemux_parse_svq3_stsd_data (qtdemux, stsd, &gamma_data, &seqh);
+          if (gamma_data) {
+            gst_caps_set_simple (stream->caps, "applied-gamma", G_TYPE_DOUBLE,
+                QT_FP32 (gamma_data), NULL);
+          }
+          if (seqh) {
+            /* sorry for the bad name, but we don't know what this is, other
+             * than its own fourcc */
+            gst_caps_set_simple (stream->caps, "seqh", GST_TYPE_BUFFER, seqh,
+                NULL);
+          }
 
+          GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
           buf = gst_buffer_new_and_alloc (len);
           memcpy (GST_BUFFER_DATA (buf), stsd_data, len);
           gst_caps_set_simple (stream->caps,
index 952d079..0533417 100644 (file)
@@ -149,6 +149,11 @@ G_BEGIN_DECLS
 #define FOURCC_text     GST_MAKE_FOURCC('t','e','x','t')
 #define FOURCC_tx3g     GST_MAKE_FOURCC('t','x','3','g')
 #define FOURCC_mp4s     GST_MAKE_FOURCC('m','p','4','s')
+#define FOURCC_gama     GST_MAKE_FOURCC('g','a','m','a')
+
+/* SVQ3 fourcc */
+#define FOURCC_SEQH     GST_MAKE_FOURCC('S','E','Q','H')
+#define FOURCC_SMI_     GST_MAKE_FOURCC('S','M','I',' ')
 
 /* 3gpp asset meta data fourcc */
 #define FOURCC_titl     GST_MAKE_FOURCC('t','i','t','l')