From 2319c85f469b92221dd86e9d89dda268a8a127b4 Mon Sep 17 00:00:00 2001 From: Sreerenj Balachandran Date: Tue, 14 Sep 2010 23:08:51 +0300 Subject: [PATCH] oggdemux: perform more (vorbis comment header) tag extractions In particular, move comment header parsing to gstoggstrem.c. Thanks to Felipe Contreras. Fixes #629349 (partially). --- ext/ogg/gstoggdemux.c | 61 ++++--------------------- ext/ogg/gstoggstream.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++-- ext/ogg/gstoggstream.h | 6 +++ 3 files changed, 132 insertions(+), 56 deletions(-) diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index 6f83176..20eba9a 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -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); diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 62d3f22..eecde0c 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -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; diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index 54d2fa4..00c4527 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -25,6 +25,7 @@ #include #include +#include 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 */ -- 2.7.4