oggdemux: perform more (vorbis comment header) tag extractions
authorSreerenj Balachandran <sreerenj.balachandran@nokia.com>
Tue, 14 Sep 2010 20:08:51 +0000 (23:08 +0300)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 3 Dec 2010 12:53:54 +0000 (13:53 +0100)
In particular, move comment header parsing to gstoggstrem.c.
Thanks to Felipe Contreras.

Fixes #629349 (partially).

ext/ogg/gstoggdemux.c
ext/ogg/gstoggstream.c
ext/ogg/gstoggstream.h

index 6f83176..20eba9a 100644 (file)
@@ -452,36 +452,10 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
     if (bytes < 1)
       goto empty_packet;
 
-    if (data[0] & 1) {
+    if ((data[0] & 1) || (data[0] & 3 && pad->map.is_ogm_text)) {
       /* We don't push header packets for OGM */
       cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
       goto done;
-    } else if (data[0] & 3 && pad->map.is_ogm_text) {
-      GstTagList *tags;
-
-      /* We don't push comment packets either for text streams,
-       * other streams will handle the comment packets in the
-       * decoder */
-      buf = gst_buffer_new ();
-
-      GST_BUFFER_DATA (buf) = (guint8 *) data;
-      GST_BUFFER_SIZE (buf) = bytes;
-
-      tags = gst_tag_list_from_vorbiscomment_buffer (buf,
-          (const guint8 *) "\003vorbis", 7, NULL);
-      gst_buffer_unref (buf);
-      buf = NULL;
-
-      if (tags) {
-        GST_DEBUG_OBJECT (ogg, "tags = %" GST_PTR_FORMAT, tags);
-        gst_element_found_tags_for_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad),
-            tags);
-      } else {
-        GST_DEBUG_OBJECT (ogg, "failed to extract tags from vorbis comment");
-      }
-
-      cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
-      goto done;
     }
 
     offset = 1 + (((data[0] & 0xc0) >> 6) | ((data[0] & 0x02) << 1));
@@ -497,32 +471,9 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
       }
     }
   } else if (pad->map.is_vp8) {
-    if (packet->bytes >= 7 && memcmp (packet->packet, "OVP80\2 ", 7) == 0) {
-      GstTagList *tags;
-
-      buf = gst_buffer_new ();
-
-      GST_BUFFER_DATA (buf) = (guint8 *) packet->packet;
-      GST_BUFFER_SIZE (buf) = packet->bytes;
-
-      tags = gst_tag_list_from_vorbiscomment_buffer (buf,
-          (const guint8 *) "OVP80\2 ", 7, NULL);
-      gst_buffer_unref (buf);
-      buf = NULL;
-
-      if (tags) {
-        GST_DEBUG_OBJECT (ogg, "tags = %" GST_PTR_FORMAT, tags);
-        gst_element_found_tags_for_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad),
-            tags);
-      } else {
-        GST_DEBUG_OBJECT (ogg,
-            "failed to extract VP8 tags from vorbis comment");
-      }
-      /* We don't push header packets for VP8 */
-      cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
-      goto done;
-    } else if (packet->b_o_s || (packet->bytes >= 5
-            && memcmp (packet->packet, "OVP80", 5) == 0)) {
+    if ((packet->bytes >= 7 && memcmp (packet->packet, "OVP80\2 ", 7) == 0) ||
+        packet->b_o_s ||
+        (packet->bytes >= 5 && memcmp (packet->packet, "OVP80", 5) == 0)) {
       /* We don't push header packets for VP8 */
       cret = gst_ogg_demux_combine_flows (ogg, pad, GST_FLOW_OK);
       goto done;
@@ -1791,6 +1742,10 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
 
     gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad));
     pad->added = TRUE;
+    if (event && pad->map.taglist) {
+      gst_element_found_tags_for_pad (GST_ELEMENT_CAST (ogg),
+          GST_PAD_CAST (pad), pad->map.taglist);
+    }
   }
   /* prefer the index bitrate over the ones encoded in the streams */
   ogg->bitrate = (idx_bitrate ? idx_bitrate : bitrate);
index 62d3f22..eecde0c 100644 (file)
@@ -596,6 +596,32 @@ granulepos_to_key_granule_vp8 (GstOggStream * pad, gint64 granulepos)
 static gboolean
 is_header_vp8 (GstOggStream * pad, ogg_packet * packet)
 {
+  if (packet->bytes >= 7 && memcmp (packet->packet, "OVP80\2 ", 7) == 0) {
+    GstBuffer *buf = NULL;
+    gchar *encoder = NULL;
+
+    buf = gst_buffer_new ();
+
+    GST_BUFFER_DATA (buf) = (guint8 *) packet->packet;
+    GST_BUFFER_SIZE (buf) = packet->bytes;
+
+    pad->taglist = gst_tag_list_from_vorbiscomment_buffer (buf,
+        (const guint8 *) "OVP80\2 ", 7, &encoder);
+    if (!pad->taglist) {
+      GST_ERROR_OBJECT (pad, "couldn't decode comments");
+      pad->taglist = gst_tag_list_new ();
+    }
+
+    gst_buffer_unref (buf);
+    buf = NULL;
+    if (encoder) {
+      if (encoder[0])
+        gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+            GST_TAG_ENCODER, encoder, NULL);
+      g_free (encoder);
+    }
+  }
+
   if (packet->bytes >= 5 && packet->packet[0] == 0x4F &&
       packet->packet[1] == 0x56 && packet->packet[2] == 0x50 &&
       packet->packet[3] == 0x38 && packet->packet[4] == 0x30)
@@ -611,7 +637,9 @@ setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet)
   guint8 *data = packet->packet;
   guint chans;
 
-  data += 1 + 6 + 4;
+  data += 1 + 6;
+  pad->version = GST_READ_UINT32_LE (data);
+  data += 4;
   chans = GST_READ_UINT8 (data);
   data += 1;
   pad->granulerate_n = GST_READ_UINT32_LE (data);
@@ -620,8 +648,26 @@ setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet)
   pad->last_size = 0;
   GST_LOG ("sample rate: %d", pad->granulerate_n);
 
-  data += 8;
-  pad->bitrate = GST_READ_UINT32_LE (data);
+  data += 4;
+  pad->bitrate_upper = GST_READ_UINT32_LE (data);
+  data += 4;
+  pad->bitrate_nominal = GST_READ_UINT32_LE (data);
+  data += 4;
+  pad->bitrate_lower = GST_READ_UINT32_LE (data);
+
+  if (pad->bitrate_nominal > 0 && pad->bitrate_nominal <= 0x7FFFFFFF)
+    pad->bitrate = pad->bitrate_nominal;
+
+  if (pad->bitrate_upper > 0 && pad->bitrate_upper <= 0x7FFFFFFF)
+    if (!pad->bitrate)
+      pad->bitrate = pad->bitrate_upper;
+
+  if (pad->bitrate_lower > 0 && pad->bitrate_lower <= 0x7FFFFFFF)
+    if (!pad->bitrate)
+      pad->bitrate = pad->bitrate_lower;
+
+  pad->taglist = NULL;
+
   GST_LOG ("bit rate: %d", pad->bitrate);
 
   pad->n_header_packets = 3;
@@ -644,6 +690,49 @@ is_header_vorbis (GstOggStream * pad, ogg_packet * packet)
   if (packet->bytes > 0 && (packet->packet[0] & 0x01) == 0)
     return FALSE;
 
+  if (((guint8 *) (packet->packet))[0] == 0x03) {
+    GstBuffer *buf = NULL;
+    gchar *encoder = NULL;
+    buf = gst_buffer_new ();
+    GST_BUFFER_DATA (buf) = (guint8 *) packet->packet;
+    GST_BUFFER_SIZE (buf) = packet->bytes;
+
+    pad->taglist = gst_tag_list_from_vorbiscomment_buffer (buf,
+        (const guint8 *) "\003vorbis", 7, &encoder);
+
+    if (!pad->taglist) {
+      GST_ERROR_OBJECT (pad, "couldn't decode comments");
+      pad->taglist = gst_tag_list_new ();
+    }
+
+    gst_buffer_unref (buf);
+    buf = NULL;
+    if (encoder) {
+      if (encoder[0])
+        gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+            GST_TAG_ENCODER, encoder, NULL);
+      g_free (encoder);
+    }
+    gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+        GST_TAG_ENCODER_VERSION, pad->version, NULL);
+
+    if (pad->bitrate_nominal > 0 && pad->bitrate_nominal <= 0x7FFFFFFF)
+      gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+          GST_TAG_NOMINAL_BITRATE, (guint) pad->bitrate_nominal, NULL);
+
+    if (pad->bitrate_upper > 0 && pad->bitrate_upper <= 0x7FFFFFFF)
+      gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+          GST_TAG_MAXIMUM_BITRATE, (guint) pad->bitrate_upper, NULL);
+
+    if (pad->bitrate_lower > 0 && pad->bitrate_lower <= 0x7FFFFFFF)
+      gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+          GST_TAG_MINIMUM_BITRATE, (guint) pad->bitrate_lower, NULL);
+
+    if (pad->bitrate)
+      gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+          GST_TAG_BITRATE, (guint) pad->bitrate, NULL);
+  }
+
   if (packet->packet[0] == 5) {
     parse_vorbis_setup_packet (pad, packet);
   }
@@ -1204,6 +1293,32 @@ gst_ogg_map_search_index (GstOggStream * pad, gboolean before,
 static gboolean
 is_header_ogm (GstOggStream * pad, ogg_packet * packet)
 {
+  if (!(packet->packet[0] & 1) && (packet->packet[0] & 3 && pad->is_ogm_text)) {
+    GstBuffer *buf = NULL;
+    gchar *encoder = NULL;
+
+    buf = gst_buffer_new ();
+    GST_BUFFER_DATA (buf) = (guint8 *) packet->packet;
+    GST_BUFFER_SIZE (buf) = packet->bytes;;
+
+    pad->taglist = gst_tag_list_from_vorbiscomment_buffer (buf,
+        (const guint8 *) "\003vorbis", 7, &encoder);
+
+    if (!pad->taglist) {
+      GST_ERROR ("couldn't decode comments");
+      pad->taglist = gst_tag_list_new ();
+    }
+
+    gst_buffer_unref (buf);
+    buf = NULL;
+    if (encoder) {
+      if (encoder[0])
+        gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE,
+            GST_TAG_ENCODER, encoder, NULL);
+      g_free (encoder);
+    }
+  }
+
   if (packet->bytes >= 1 && (packet->packet[0] & 0x01))
     return TRUE;
 
index 54d2fa4..00c4527 100644 (file)
@@ -25,6 +25,7 @@
 #include <ogg/ogg.h>
 
 #include <gst/gst.h>
+#include <gst/tag/tag.h>
 
 G_BEGIN_DECLS
 
@@ -79,6 +80,11 @@ struct _GstOggStream
   int vorbis_log2_num_modes;
   int vorbis_mode_sizes[256];
   int last_size;
+  int version;
+  long bitrate_upper;
+  long bitrate_nominal;
+  long bitrate_lower;
+  GstTagList *taglist;
   /* theora stuff */
   gboolean theora_has_zero_keyoffset;
   /* VP8 stuff */