wavparse: support rf64 format
authorPeter G. Baum <peter@dr-baum.net>
Wed, 27 Aug 2014 16:55:18 +0000 (18:55 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 29 Aug 2014 08:49:42 +0000 (11:49 +0300)
https://bugzilla.gnome.org/show_bug.cgi?id=735627

gst/wavparse/gstwavparse.c
gst/wavparse/gstwavparse.h

index 28d2063..1f371e6 100644 (file)
@@ -66,6 +66,10 @@ GST_DEBUG_CATEGORY_STATIC (wavparse_debug);
 #define GST_BWF_TAG_link GST_MAKE_FOURCC ('l','i','n','k')
 #define GST_BWF_TAG_axml GST_MAKE_FOURCC ('a','x','m','l')
 
+/* Data size chunk of RF64,
+ * see http://tech.ebu.ch/docs/tech/tech3306-2009.pdf */
+#define GST_RS64_TAG_DS64 GST_MAKE_FOURCC ('d','s','6','4')
+
 static void gst_wavparse_dispose (GObject * object);
 
 static gboolean gst_wavparse_sink_activate (GstPad * sinkpad,
@@ -1024,6 +1028,31 @@ gst_wavparse_create_toc (GstWavParse * wav)
 
 #define MAX_BUFFER_SIZE 4096
 
+static gboolean
+parse_ds64 (GstWavParse * wav, GstBuffer * buf)
+{
+  GstMapInfo map;
+  guint32 dataSizeLow, dataSizeHigh;
+  guint32 sampleCountLow, sampleCountHigh;
+
+  gst_buffer_map (buf, &map, GST_MAP_READ);
+  dataSizeLow = GST_READ_UINT32_LE (map.data + 2 * 4);
+  dataSizeHigh = GST_READ_UINT32_LE (map.data + 3 * 4);
+  sampleCountLow = GST_READ_UINT32_LE (map.data + 4 * 4);
+  sampleCountHigh = GST_READ_UINT32_LE (map.data + 5 * 4);
+  gst_buffer_unmap (buf, &map);
+  if (dataSizeHigh != 0xFFFFFFFF && dataSizeLow != 0xFFFFFFFF) {
+    wav->datasize = ((guint64) dataSizeHigh << 32) | dataSizeLow;
+  }
+  if (sampleCountHigh != 0xFFFFFFFF && sampleCountLow != 0xFFFFFFFF) {
+    wav->fact = ((guint64) sampleCountHigh << 32) | sampleCountLow;
+  }
+
+  GST_DEBUG_OBJECT (wav, "Got 'ds64' TAG, datasize : %" G_GINT64_FORMAT
+      " fact: %" G_GINT64_FORMAT, wav->datasize, wav->fact);
+  return TRUE;
+}
+
 static GstFlowReturn
 gst_wavparse_stream_headers (GstWavParse * wav)
 {
@@ -1078,6 +1107,13 @@ gst_wavparse_stream_headers (GstWavParse * wav)
       continue;
     }
 
+    if (tag == GST_RS64_TAG_DS64) {
+      if (!parse_ds64 (wav, buf))
+        goto fail;
+      else
+        continue;
+    }
+
     if (tag != GST_RIFF_TAG_fmt)
       goto invalid_wav;
 
@@ -1238,6 +1274,11 @@ gst_wavparse_stream_headers (GstWavParse * wav)
         }
         wav->offset += 8;
         wav->datastart = wav->offset;
+        /* use size from ds64 chunk if available */
+        if (size == -1 && wav->datasize > 0) {
+          GST_DEBUG_OBJECT (wav, "Using ds64 datasize");
+          size = wav->datasize;
+        }
         /* If size is zero, then the data chunk probably actually extends to
            the end of the file */
         if (size == 0 && upstream_size) {
@@ -1258,7 +1299,8 @@ gst_wavparse_stream_headers (GstWavParse * wav)
         break;
       }
       case GST_RIFF_TAG_fact:{
-        if (wav->format != GST_RIFF_WAVE_FORMAT_MPEGL12 &&
+        if (wav->fact == 0 &&
+            wav->format != GST_RIFF_WAVE_FORMAT_MPEGL12 &&
             wav->format != GST_RIFF_WAVE_FORMAT_MPEGL3) {
           const guint data_size = 4;
 
@@ -1295,7 +1337,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
             wav->fact = GUINT32_FROM_LE (wav->fact);
             gst_buffer_unref (buf);
           }
-          GST_DEBUG_OBJECT (wav, "have fact %u", wav->fact);
+          GST_DEBUG_OBJECT (wav, "have fact %" G_GUINT64_FORMAT, wav->fact);
           wav->offset += 8 + GST_ROUND_UP_2 (size);
           break;
         } else {
index 7dc43bc..bed478e 100644 (file)
@@ -86,7 +86,7 @@ struct _GstWavParse {
   guint16 blockalign;
   guint16 width;
   guint32 av_bps;
-  guint32 fact;
+  guint64 fact;
 
   /* real bps used or 0 when no bitrate is known */
   guint32 bps;