Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / ext / vorbis / gstvorbisdec.c
index 9a89fe7..45f0dc8 100644 (file)
@@ -64,8 +64,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
     GST_STATIC_CAPS ("audio/x-vorbis")
     );
 
-GST_BOILERPLATE (GstVorbisDec, gst_vorbis_dec, GstAudioDecoder,
-    GST_TYPE_AUDIO_DECODER);
+#define gst_vorbis_dec_parent_class parent_class
+G_DEFINE_TYPE (GstVorbisDec, gst_vorbis_dec, GST_TYPE_AUDIO_DECODER);
 
 static void vorbis_dec_finalize (GObject * object);
 
@@ -76,10 +76,14 @@ static GstFlowReturn vorbis_dec_handle_frame (GstAudioDecoder * dec,
 static void vorbis_dec_flush (GstAudioDecoder * dec, gboolean hard);
 
 static void
-gst_vorbis_dec_base_init (gpointer g_class)
+gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
 {
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
   GstPadTemplate *src_template, *sink_template;
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
+
+  gobject_class->finalize = vorbis_dec_finalize;
 
   src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
   gst_element_class_add_pad_template (element_class, src_template);
@@ -91,15 +95,6 @@ gst_vorbis_dec_base_init (gpointer g_class)
       "Vorbis audio decoder", "Codec/Decoder/Audio",
       GST_VORBIS_DEC_DESCRIPTION,
       "Benjamin Otte <otte@gnome.org>, Chris Lord <chris@openedhand.com>");
-}
-
-static void
-gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
-
-  gobject_class->finalize = vorbis_dec_finalize;
 
   base_class->start = GST_DEBUG_FUNCPTR (vorbis_dec_start);
   base_class->stop = GST_DEBUG_FUNCPTR (vorbis_dec_stop);
@@ -108,7 +103,7 @@ gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
 }
 
 static void
-gst_vorbis_dec_init (GstVorbisDec * dec, GstVorbisDecClass * g_class)
+gst_vorbis_dec_init (GstVorbisDec * dec)
 {
 }
 
@@ -233,10 +228,12 @@ static GstFlowReturn
 vorbis_handle_identification_packet (GstVorbisDec * vd)
 {
   GstCaps *caps;
-  const GstAudioChannelPosition *pos = NULL;
-  gint width = GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH;
+  GstAudioInfo info;
 
-  switch (vd->vi.channels) {
+  gst_audio_info_set_format (&info, GST_VORBIS_AUDIO_FORMAT, vd->vi.rate,
+      vd->vi.channels);
+
+  switch (info.channels) {
     case 1:
     case 2:
       /* nothing */
@@ -247,60 +244,34 @@ vorbis_handle_identification_packet (GstVorbisDec * vd)
     case 6:
     case 7:
     case 8:
-      pos = gst_vorbis_channel_positions[vd->vi.channels - 1];
+    {
+      const GstAudioChannelPosition *pos;
+      gint i;
+
+      pos = gst_vorbis_channel_positions[info.channels - 1];
+      for (i = 0; i < info.channels; i++)
+        info.position[i] = pos[i];
       break;
+    }
     default:{
-      gint i;
-      GstAudioChannelPosition *posn =
-          g_new (GstAudioChannelPosition, vd->vi.channels);
+      gint i, max_pos = MAX (info.channels, 64);
 
-      GST_ELEMENT_WARNING (GST_ELEMENT (vd), STREAM, DECODE,
+      GST_ELEMENT_WARNING (vd, STREAM, DECODE,
           (NULL), ("Using NONE channel layout for more than 8 channels"));
-
-      for (i = 0; i < vd->vi.channels; i++)
-        posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
-
-      pos = posn;
+      for (i = 0; i < max_pos; i++)
+        info.position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+      break;
     }
   }
 
-  /* negotiate width with downstream */
-  caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (vd));
-  if (caps) {
-    if (!gst_caps_is_empty (caps)) {
-      GstStructure *s;
-
-      s = gst_caps_get_structure (caps, 0);
-      /* template ensures 16 or 32 */
-      gst_structure_get_int (s, "width", &width);
-
-      GST_INFO_OBJECT (vd, "using %s with %d channels and %d bit audio depth",
-          gst_structure_get_name (s), vd->vi.channels, width);
-    }
-    gst_caps_unref (caps);
-  }
-  vd->width = width >> 3;
+  caps = gst_audio_info_to_caps (&info);
+  gst_audio_decoder_set_outcaps (GST_AUDIO_DECODER (vd), caps);
+  gst_caps_unref (caps);
 
+  vd->info = info;
   /* select a copy_samples function, this way we can have specialized versions
    * for mono/stereo and avoid the depth switch in tremor case */
-  vd->copy_samples = get_copy_sample_func (vd->vi.channels, vd->width);
-
-  caps =
-      gst_caps_copy (gst_pad_get_pad_template_caps
-      (GST_AUDIO_DECODER_SRC_PAD (vd)));
-  gst_caps_set_simple (caps, "rate", G_TYPE_INT, vd->vi.rate, "channels",
-      G_TYPE_INT, vd->vi.channels, "width", G_TYPE_INT, width, NULL);
-
-  if (pos) {
-    gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
-  }
-
-  if (vd->vi.channels > 8) {
-    g_free ((GstAudioChannelPosition *) pos);
-  }
-
-  gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (vd), caps);
-  gst_caps_unref (caps);
+  vd->copy_samples = get_copy_sample_func (info.channels);
 
   return GST_FLOW_OK;
 }
@@ -311,16 +282,16 @@ vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
   guint bitrate = 0;
   gchar *encoder = NULL;
   GstTagList *list, *old_list;
-  GstBuffer *buf;
+  guint8 *data;
+  gsize size;
 
   GST_DEBUG_OBJECT (vd, "parsing comment packet");
 
-  buf = gst_buffer_new ();
-  GST_BUFFER_DATA (buf) = gst_ogg_packet_data (packet);
-  GST_BUFFER_SIZE (buf) = gst_ogg_packet_size (packet);
+  data = gst_ogg_packet_data (packet);
+  size = gst_ogg_packet_size (packet);
 
   list =
-      gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
+      gst_tag_list_from_vorbiscomment (data, size, (guint8 *) "\003vorbis", 7,
       &encoder);
 
   old_list = vd->taglist;
@@ -329,7 +300,6 @@ vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
   if (old_list)
     gst_tag_list_free (old_list);
   gst_tag_list_free (list);
-  gst_buffer_unref (buf);
 
   if (!vd->taglist) {
     GST_ERROR_OBJECT (vd, "couldn't decode comments");
@@ -474,11 +444,16 @@ vorbis_dec_handle_header_buffer (GstVorbisDec * vd, GstBuffer * buffer)
 {
   ogg_packet *packet;
   ogg_packet_wrapper packet_wrapper;
+  GstFlowReturn ret;
 
-  gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer);
+  gst_ogg_packet_wrapper_map (&packet_wrapper, buffer);
   packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
 
-  return vorbis_handle_header_packet (vd, packet);
+  ret = vorbis_handle_header_packet (vd, packet);
+
+  gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer);
+
+  return ret;
 }
 
 #define MIN_NUM_HEADERS 3
@@ -490,12 +465,15 @@ vorbis_dec_handle_header_caps (GstVorbisDec * vd)
   GstStructure *s = NULL;
   const GValue *array = NULL;
 
-  caps = GST_PAD_CAPS (GST_AUDIO_DECODER_SINK_PAD (vd));
+  caps = gst_pad_get_current_caps (GST_AUDIO_DECODER_SINK_PAD (vd));
   if (caps)
     s = gst_caps_get_structure (caps, 0);
   if (s)
     array = gst_structure_get_value (s, "streamheader");
 
+  if (caps)
+    gst_caps_unref (caps);
+
   if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) {
     const GValue *value = NULL;
     GstBuffer *buf = NULL;
@@ -543,7 +521,8 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
   guint sample_count;
   GstBuffer *out = NULL;
   GstFlowReturn result;
-  gint size;
+  guint8 *data;
+  gsize size;
 
   if (G_UNLIKELY (!vd->initialized)) {
     result = vorbis_dec_handle_header_caps (vd);
@@ -580,22 +559,17 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
     goto done;
 #endif
 
-  size = sample_count * vd->vi.channels * vd->width;
+  size = sample_count * vd->info.bpf;
   GST_LOG_OBJECT (vd, "%d samples ready for reading, size %d", sample_count,
       size);
 
   /* alloc buffer for it */
-  result =
-      gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (vd),
-      GST_BUFFER_OFFSET_NONE, size,
-      GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (vd)), &out);
-  if (G_UNLIKELY (result != GST_FLOW_OK))
-    goto done;
+  out = gst_buffer_new_allocate (NULL, size, 0);
 
+  data = gst_buffer_map (out, NULL, NULL, GST_MAP_WRITE);
   /* get samples ready for reading now, should be sample_count */
 #ifdef USE_TREMOLO
-  pcm = GST_BUFFER_DATA (out);
-  if (G_UNLIKELY (vorbis_dsp_pcmout (&vd->vd, pcm, sample_count) !=
+  if (G_UNLIKELY (vorbis_dsp_pcmout (&vd->vd, data, sample_count) !=
           sample_count))
 #else
   if (G_UNLIKELY (vorbis_synthesis_pcmout (&vd->vd, &pcm) != sample_count))
@@ -604,12 +578,12 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
 
 #ifndef USE_TREMOLO
   /* copy samples in buffer */
-  vd->copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm,
-      sample_count, vd->vi.channels, vd->width);
+  vd->copy_samples ((vorbis_sample_t *) data, pcm,
+      sample_count, vd->info.channels);
 #endif
 
   GST_LOG_OBJECT (vd, "setting output size to %d", size);
-  GST_BUFFER_SIZE (out) = size;
+  gst_buffer_unmap (out, data, size);
 
 done:
   /* whether or not data produced, consume one frame and advance time */
@@ -663,8 +637,9 @@ vorbis_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
   if (G_UNLIKELY (!buffer))
     return GST_FLOW_OK;
 
+  GST_LOG_OBJECT (vd, "got buffer %p", buffer);
   /* make ogg_packet out of the buffer */
-  gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer);
+  gst_ogg_packet_wrapper_map (&packet_wrapper, buffer);
   packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
   /* set some more stuff */
   packet->granulepos = -1;
@@ -702,6 +677,9 @@ vorbis_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
   }
 
 done:
+  GST_LOG_OBJECT (vd, "unmap buffer %p", buffer);
+  gst_ogg_packet_wrapper_unmap (&packet_wrapper, buffer);
+
   return result;
 
 empty_buffer: