Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / ext / vorbis / gstvorbisenc.c
index 45c871a..c699d5f 100644 (file)
@@ -63,10 +63,9 @@ static GstStaticPadTemplate vorbis_enc_sink_factory =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-float, "
-        "rate = (int) [ 1, 200000 ], "
-        "channels = (int) [ 1, 255 ], " "endianness = (int) BYTE_ORDER, "
-        "width = (int) 32")
+    GST_STATIC_CAPS ("audio/x-raw, "
+        "format = (string) " GST_AUDIO_NE (F32) ", "
+        "rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
     );
 
 static GstStaticPadTemplate vorbis_enc_src_factory =
@@ -103,7 +102,8 @@ static gboolean gst_vorbis_enc_set_format (GstAudioEncoder * enc,
     GstAudioInfo * info);
 static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc,
     GstBuffer * in_buf);
-static GstCaps *gst_vorbis_enc_getcaps (GstAudioEncoder * enc);
+static GstCaps *gst_vorbis_enc_getcaps (GstAudioEncoder * enc,
+    GstCaps * filter);
 static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc,
     GstEvent * event);
 static GstFlowReturn gst_vorbis_enc_pre_push (GstAudioEncoder * enc,
@@ -116,57 +116,26 @@ static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
-static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
 
-GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstAudioEncoder,
-    GST_TYPE_AUDIO_ENCODER, gst_vorbis_enc_add_interfaces);
-
-static void
-gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
-{
-  static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
-
-  g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
-      &tag_setter_info);
-}
-
-static void
-gst_vorbis_enc_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&vorbis_enc_src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&vorbis_enc_sink_factory));
-
-  gst_element_class_set_details_simple (element_class,
-      "Vorbis audio encoder", "Codec/Encoder/Audio",
-      "Encodes audio in Vorbis format",
-      "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
-}
+#define gst_vorbis_enc_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstVorbisEnc, gst_vorbis_enc,
+    GST_TYPE_AUDIO_ENCODER, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
 
 static void
 gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
 {
   GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
   GstAudioEncoderClass *base_class;
 
   gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
   base_class = (GstAudioEncoderClass *) (klass);
 
   gobject_class->set_property = gst_vorbis_enc_set_property;
   gobject_class->get_property = gst_vorbis_enc_get_property;
   gobject_class->dispose = gst_vorbis_enc_dispose;
 
-  base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
-  base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
-  base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
-  base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
-  base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
-  base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
-  base_class->pre_push = GST_DEBUG_FUNCPTR (gst_vorbis_enc_pre_push);
-
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
       g_param_spec_int ("max-bitrate", "Maximum Bitrate",
           "Specify a maximum bitrate (in bps). Useful for streaming "
@@ -197,10 +166,28 @@ gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
       g_param_spec_string ("last-message", "last-message",
           "The last status message", NULL,
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&vorbis_enc_src_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&vorbis_enc_sink_factory));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "Vorbis audio encoder", "Codec/Encoder/Audio",
+      "Encodes audio in Vorbis format",
+      "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
+
+  base_class->start = GST_DEBUG_FUNCPTR (gst_vorbis_enc_start);
+  base_class->stop = GST_DEBUG_FUNCPTR (gst_vorbis_enc_stop);
+  base_class->set_format = GST_DEBUG_FUNCPTR (gst_vorbis_enc_set_format);
+  base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame);
+  base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps);
+  base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event);
+  base_class->pre_push = GST_DEBUG_FUNCPTR (gst_vorbis_enc_pre_push);
 }
 
 static void
-gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
+gst_vorbis_enc_init (GstVorbisEnc * vorbisenc)
 {
   GstAudioEncoder *enc = GST_AUDIO_ENCODER (vorbisenc);
 
@@ -239,7 +226,7 @@ gst_vorbis_enc_start (GstAudioEncoder * enc)
   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
 
   GST_DEBUG_OBJECT (enc, "start");
-  vorbisenc->tags = gst_tag_list_new ();
+  vorbisenc->tags = gst_tag_list_new_empty ();
   vorbisenc->header_sent = FALSE;
 
   return TRUE;
@@ -272,17 +259,15 @@ gst_vorbis_enc_generate_sink_caps (void)
   GstCaps *caps = gst_caps_new_empty ();
   int i, c;
 
-  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
+  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
+          "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
           "rate", GST_TYPE_INT_RANGE, 1, 200000,
-          "channels", G_TYPE_INT, 1,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
-          NULL));
+          "channels", G_TYPE_INT, 1, NULL));
 
-  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
+  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
+          "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
           "rate", GST_TYPE_INT_RANGE, 1, 200000,
-          "channels", G_TYPE_INT, 2,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
-          NULL));
+          "channels", G_TYPE_INT, 2, NULL));
 
   for (i = 3; i <= 8; i++) {
     GValue chanpos = { 0 };
@@ -298,34 +283,42 @@ gst_vorbis_enc_generate_sink_caps (void)
     }
     g_value_unset (&pos);
 
-    structure = gst_structure_new ("audio/x-raw-float",
-        "rate", GST_TYPE_INT_RANGE, 1, 200000,
-        "channels", G_TYPE_INT, i,
-        "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
+    structure = gst_structure_new ("audio/x-raw",
+        "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
+        "rate", GST_TYPE_INT_RANGE, 1, 200000, "channels", G_TYPE_INT, i, NULL);
     gst_structure_set_value (structure, "channel-positions", &chanpos);
     g_value_unset (&chanpos);
 
     gst_caps_append_structure (caps, structure);
   }
 
-  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
+  gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
+          "format", G_TYPE_STRING, GST_AUDIO_NE (F32),
           "rate", GST_TYPE_INT_RANGE, 1, 200000,
-          "channels", GST_TYPE_INT_RANGE, 9, 255,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
-          NULL));
+          "channels", GST_TYPE_INT_RANGE, 9, 255, NULL));
 
   return caps;
 }
 
 static GstCaps *
-gst_vorbis_enc_getcaps (GstAudioEncoder * enc)
+gst_vorbis_enc_getcaps (GstAudioEncoder * enc, GstCaps * filter)
 {
   GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);
+  GstCaps *caps;
 
   if (vorbisenc->sinkcaps == NULL)
     vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
 
-  return gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
+  if (filter) {
+    GstCaps *int_caps = gst_caps_intersect_full (filter, vorbisenc->sinkcaps,
+        GST_CAPS_INTERSECT_FIRST);
+    caps = gst_audio_encoder_proxy_getcaps (enc, int_caps);
+    gst_caps_unref (int_caps);
+  } else {
+    caps = gst_audio_encoder_proxy_getcaps (enc, vorbisenc->sinkcaps);
+  }
+
+  return caps;
 }
 
 static gint64
@@ -580,14 +573,14 @@ gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
   GstBuffer *outbuf;
 
   outbuf = gst_buffer_new_and_alloc (packet->bytes);
-  memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
+  gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
   GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
   GST_BUFFER_OFFSET_END (outbuf) = 0;
   GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
 
-  GST_DEBUG ("created header packet buffer, %d bytes",
-      GST_BUFFER_SIZE (outbuf));
+  GST_DEBUG ("created header packet buffer, %" G_GSIZE_FORMAT " bytes",
+      gst_buffer_get_size (outbuf));
   return outbuf;
 }
 
@@ -627,8 +620,6 @@ gst_vorbis_enc_push_header (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
       "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
       GST_BUFFER_OFFSET_END (buffer),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-  gst_buffer_set_caps (buffer,
-      GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc)));
   return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), buffer);
 }
 
@@ -667,7 +658,7 @@ _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
   va_start (va, buf);
   /* put buffers in a fixed list */
   while (buf) {
-    g_assert (gst_buffer_is_metadata_writable (buf));
+    g_assert (gst_buffer_is_writable (buf));
 
     /* mark buffer */
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
@@ -694,8 +685,9 @@ gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
 {
   GstVorbisEnc *vorbisenc;
   GstFlowReturn ret = GST_FLOW_OK;
-  gfloat *data;
+  gfloat *data, *ptr;
   gulong size;
+  gsize bsize;
   gulong i, j;
   float **vorbis_buffer;
   GstBuffer *buf1, *buf2, *buf3;
@@ -739,16 +731,12 @@ gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
     buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
 
     /* mark and put on caps */
-    caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
+    caps = gst_caps_new_empty_simple ("audio/x-vorbis");
     caps = _gst_caps_set_buffer_array (caps, "streamheader",
         buf1, buf2, buf3, NULL);
 
     /* negotiate with these caps */
     GST_DEBUG_OBJECT (vorbisenc, "here are the caps: %" GST_PTR_FORMAT, caps);
-
-    gst_buffer_set_caps (buf1, caps);
-    gst_buffer_set_caps (buf2, caps);
-    gst_buffer_set_caps (buf3, caps);
     gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), caps);
     gst_caps_unref (caps);
 
@@ -766,9 +754,12 @@ gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
   if (!buffer)
     return gst_vorbis_enc_clear (vorbisenc);
 
+  data = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_WRITE);
+
   /* data to encode */
-  data = (gfloat *) GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
+  size = bsize / (vorbisenc->channels * sizeof (float));
+
+  ptr = data;
 
   /* expose the buffer to submit data */
   vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
@@ -776,12 +767,13 @@ gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
   /* deinterleave samples, write the buffer data */
   for (i = 0; i < size; i++) {
     for (j = 0; j < vorbisenc->channels; j++) {
-      vorbis_buffer[j][i] = *data++;
+      vorbis_buffer[j][i] = *ptr++;
     }
   }
 
   /* tell the library how much we actually submitted */
   vorbis_analysis_wrote (&vorbisenc->vd, size);
+  gst_buffer_unmap (buffer, data, bsize);
 
   GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size);
 
@@ -814,7 +806,7 @@ gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
 
       GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
       buf = gst_buffer_new_and_alloc (op.bytes);
-      memcpy (GST_BUFFER_DATA (buf), op.packet, op.bytes);
+      gst_buffer_fill (buf, 0, op.packet, op.bytes);
       /* tracking granulepos should tell us samples accounted for */
       ret =
           gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER