Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / ext / alsa / gstalsasrc.c
index 14eb95d..82615e1 100644 (file)
@@ -48,6 +48,7 @@
 
 #include "gstalsasrc.h"
 #include "gstalsadeviceprobe.h"
+#include "gst/glib-compat-private.h"
 
 #include <gst/gst-i18n-plugin.h>
 
@@ -81,18 +82,12 @@ static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
 
 static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
 static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
-    GstRingBufferSpec * spec);
+    GstAudioRingBufferSpec * spec);
 static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
 static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
 static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
 static guint gst_alsasrc_delay (GstAudioSrc * asrc);
 static void gst_alsasrc_reset (GstAudioSrc * asrc);
-static GstStateChangeReturn gst_alsasrc_change_state (GstElement * element,
-    GstStateChange transition);
-static GstFlowReturn gst_alsasrc_create (GstBaseSrc * bsrc, guint64 offset,
-    guint length, GstBuffer ** outbuf);
-static GstClockTime gst_alsasrc_get_timestamp (GstAlsaSrc * src);
-
 
 /* AlsaSrc signals and args */
 enum
@@ -107,37 +102,11 @@ enum
 #endif
 
 static GstStaticPadTemplate alsasrc_src_factory =
-    GST_STATIC_PAD_TEMPLATE ("src",
+GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 32, "
-        "depth = (int) 32, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 32, "
-        "depth = (int) 24, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 24, "
-        "depth = (int) 24, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 16, "
-        "depth = (int) 16, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 8, "
-        "depth = (int) 8, "
+    GST_STATIC_CAPS ("audio/x-raw, "
+        "format = (string) " GST_AUDIO_FORMATS_ALL ", "
         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
     );
 
@@ -152,37 +121,15 @@ gst_alsasrc_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static gboolean
-gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type)
-{
-  /* only support this one interface (wrapped by GstImplementsInterface) */
-  g_assert (interface_type == GST_TYPE_MIXER);
-
-  return gst_alsasrc_mixer_supported (this, interface_type);
-}
-
-static void
-gst_implements_interface_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = (gpointer) gst_alsasrc_interface_supported;
-}
-
 static void
 gst_alsasrc_init_interfaces (GType type)
 {
-  static const GInterfaceInfo implements_iface_info = {
-    (GInterfaceInitFunc) gst_implements_interface_init,
-    NULL,
-    NULL,
-  };
   static const GInterfaceInfo mixer_iface_info = {
     (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init,
     NULL,
     NULL,
   };
 
-  g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
-      &implements_iface_info);
   g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
 
   gst_alsa_type_add_device_property_probe_interface (type);
@@ -212,10 +159,7 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&alsasrc_src_factory));
 
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_alsasrc_change_state);
-
   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
-  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_alsasrc_create);
 
   gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
@@ -241,49 +185,6 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
           DEFAULT_PROP_CARD_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 }
 
-static GstClockTime
-gst_alsasrc_get_timestamp (GstAlsaSrc * src)
-{
-  snd_pcm_status_t *status;
-  snd_htimestamp_t tstamp;
-  GstClockTime timestamp;
-  snd_pcm_uframes_t availmax;
-
-  GST_DEBUG_OBJECT (src, "Getting alsa timestamp!");
-
-  if (!src) {
-    GST_ERROR_OBJECT (src, "No alsa handle created yet !");
-    return 0;
-  }
-
-  if (snd_pcm_status_malloc (&status) != 0) {
-    GST_ERROR_OBJECT (src, "snd_pcm_status_malloc failed");
-  }
-
-  if (snd_pcm_status (src->handle, status) != 0) {
-    GST_ERROR_OBJECT (src, "snd_pcm_status failed");
-  }
-
-  /* get high resolution time stamp from driver */
-  snd_pcm_status_get_htstamp (status, &tstamp);
-  timestamp = GST_TIMESPEC_TO_TIME (tstamp);
-
-  /* Max available frames sets the depth of the buffer */
-  availmax = snd_pcm_status_get_avail_max (status);
-
-  /* Compensate the fact that the timestamp references the last sample */
-  timestamp -= gst_util_uint64_scale_int (availmax * 2, GST_SECOND, src->rate);
-  /* Compensate for the delay until the package is available */
-  timestamp += gst_util_uint64_scale_int (snd_pcm_status_get_delay (status),
-      GST_SECOND, src->rate);
-
-  snd_pcm_status_free (status);
-
-  GST_DEBUG_OBJECT (src, "ALSA timestamp : %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (timestamp));
-  return timestamp;
-}
-
 static void
 gst_alsasrc_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -334,57 +235,6 @@ gst_alsasrc_get_property (GObject * object, guint prop_id,
   }
 }
 
-static GstStateChangeReturn
-gst_alsasrc_change_state (GstElement * element, GstStateChange transition)
-{
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element);
-  GstAlsaSrc *asrc = GST_ALSA_SRC (element);
-  GstClock *clk;
-
-  switch (transition) {
-      /* Show the compiler that we care */
-    case GST_STATE_CHANGE_NULL_TO_READY:
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      clk = src->clock;
-      asrc->driver_timestamps = FALSE;
-      if (GST_IS_SYSTEM_CLOCK (clk)) {
-        gint clocktype;
-        g_object_get (clk, "clock-type", &clocktype, NULL);
-        if (clocktype == GST_CLOCK_TYPE_MONOTONIC) {
-          asrc->driver_timestamps = TRUE;
-        }
-      }
-      break;
-  }
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  return ret;
-}
-
-static GstFlowReturn
-gst_alsasrc_create (GstBaseSrc * bsrc, guint64 offset, guint length,
-    GstBuffer ** outbuf)
-{
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstAlsaSrc *asrc = GST_ALSA_SRC (bsrc);
-
-  ret =
-      GST_BASE_SRC_CLASS (parent_class)->create (bsrc, offset, length, outbuf);
-  if (asrc->driver_timestamps == TRUE && *outbuf) {
-    GST_BUFFER_TIMESTAMP (*outbuf) =
-        gst_alsasrc_get_timestamp ((GstAlsaSrc *) bsrc);
-  }
-
-  return ret;
-}
-
 static void
 gst_alsasrc_init (GstAlsaSrc * alsasrc)
 {
@@ -392,7 +242,6 @@ gst_alsasrc_init (GstAlsaSrc * alsasrc)
 
   alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
   alsasrc->cached_caps = NULL;
-  alsasrc->driver_timestamps = FALSE;
 
   alsasrc->alsa_lock = g_mutex_new ();
 }
@@ -416,7 +265,7 @@ gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
 
   if (src->handle == NULL) {
     GST_DEBUG_OBJECT (src, "device not open, using template caps");
-    return NULL;                /* base class will get template caps for us */
+    return GST_BASE_SRC_CLASS (parent_class)->get_caps (bsrc, filter);
   }
 
   if (src->cached_caps) {
@@ -433,6 +282,8 @@ gst_alsasrc_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
   g_return_val_if_fail (pad_template != NULL, NULL);
 
   templ_caps = gst_pad_template_get_caps (pad_template);
+  GST_INFO_OBJECT (src, "template caps %" GST_PTR_FORMAT, templ_caps);
+
   caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
       templ_caps);
   gst_caps_unref (templ_caps);
@@ -674,25 +525,99 @@ set_sw_params:
 }
 
 static gboolean
-alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
+alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
 {
   switch (spec->type) {
-    case GST_BUFTYPE_LINEAR:
-      alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
-          spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
-      break;
-    case GST_BUFTYPE_FLOAT:
-      switch (spec->format) {
-        case GST_FLOAT32_LE:
+    case GST_BUFTYPE_RAW:
+      switch (GST_AUDIO_INFO_FORMAT (&spec->info)) {
+        case GST_AUDIO_FORMAT_U8:
+          alsa->format = SND_PCM_FORMAT_U8;
+          break;
+        case GST_AUDIO_FORMAT_S8:
+          alsa->format = SND_PCM_FORMAT_S8;
+          break;
+        case GST_AUDIO_FORMAT_S16LE:
+          alsa->format = SND_PCM_FORMAT_S16_LE;
+          break;
+        case GST_AUDIO_FORMAT_S16BE:
+          alsa->format = SND_PCM_FORMAT_S16_BE;
+          break;
+        case GST_AUDIO_FORMAT_U16LE:
+          alsa->format = SND_PCM_FORMAT_U16_LE;
+          break;
+        case GST_AUDIO_FORMAT_U16BE:
+          alsa->format = SND_PCM_FORMAT_U16_BE;
+          break;
+        case GST_AUDIO_FORMAT_S24_32LE:
+          alsa->format = SND_PCM_FORMAT_S24_LE;
+          break;
+        case GST_AUDIO_FORMAT_S24_32BE:
+          alsa->format = SND_PCM_FORMAT_S24_BE;
+          break;
+        case GST_AUDIO_FORMAT_U24_32LE:
+          alsa->format = SND_PCM_FORMAT_U24_LE;
+          break;
+        case GST_AUDIO_FORMAT_U24_32BE:
+          alsa->format = SND_PCM_FORMAT_U24_BE;
+          break;
+        case GST_AUDIO_FORMAT_S32LE:
+          alsa->format = SND_PCM_FORMAT_S32_LE;
+          break;
+        case GST_AUDIO_FORMAT_S32BE:
+          alsa->format = SND_PCM_FORMAT_S32_BE;
+          break;
+        case GST_AUDIO_FORMAT_U32LE:
+          alsa->format = SND_PCM_FORMAT_U32_LE;
+          break;
+        case GST_AUDIO_FORMAT_U32BE:
+          alsa->format = SND_PCM_FORMAT_U32_BE;
+          break;
+        case GST_AUDIO_FORMAT_S24LE:
+          alsa->format = SND_PCM_FORMAT_S24_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S24BE:
+          alsa->format = SND_PCM_FORMAT_S24_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U24LE:
+          alsa->format = SND_PCM_FORMAT_U24_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U24BE:
+          alsa->format = SND_PCM_FORMAT_U24_3BE;
+          break;
+        case GST_AUDIO_FORMAT_S20LE:
+          alsa->format = SND_PCM_FORMAT_S20_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S20BE:
+          alsa->format = SND_PCM_FORMAT_S20_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U20LE:
+          alsa->format = SND_PCM_FORMAT_U20_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U20BE:
+          alsa->format = SND_PCM_FORMAT_U20_3BE;
+          break;
+        case GST_AUDIO_FORMAT_S18LE:
+          alsa->format = SND_PCM_FORMAT_S18_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S18BE:
+          alsa->format = SND_PCM_FORMAT_S18_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U18LE:
+          alsa->format = SND_PCM_FORMAT_U18_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U18BE:
+          alsa->format = SND_PCM_FORMAT_U18_3BE;
+          break;
+        case GST_AUDIO_FORMAT_F32LE:
           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
           break;
-        case GST_FLOAT32_BE:
+        case GST_AUDIO_FORMAT_F32BE:
           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
           break;
-        case GST_FLOAT64_LE:
+        case GST_AUDIO_FORMAT_F64LE:
           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
           break;
-        case GST_FLOAT64_BE:
+        case GST_AUDIO_FORMAT_F64BE:
           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
           break;
         default:
@@ -709,8 +634,8 @@ alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
       goto error;
 
   }
-  alsa->rate = spec->rate;
-  alsa->channels = spec->channels;
+  alsa->rate = GST_AUDIO_INFO_RATE (&spec->info);
+  alsa->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
   alsa->buffer_time = spec->buffer_time;
   alsa->period_time = spec->latency_time;
   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
@@ -759,7 +684,7 @@ open_error:
 }
 
 static gboolean
-gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
 {
   GstAlsaSrc *alsa;
   gint err;
@@ -775,13 +700,9 @@ gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
   CHECK (set_swparams (alsa), sw_params_failed);
   CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
 
-  alsa->bytes_per_sample = spec->bytes_per_sample;
-  spec->segsize = alsa->period_size * spec->bytes_per_sample;
+  alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info);
+  spec->segsize = alsa->period_size * alsa->bpf;
   spec->segtotal = alsa->buffer_size / alsa->period_size;
-  spec->silence_sample[0] = 0;
-  spec->silence_sample[1] = 0;
-  spec->silence_sample[2] = 0;
-  spec->silence_sample[3] = 0;
 
   return TRUE;
 
@@ -891,7 +812,7 @@ gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
 
   alsa = GST_ALSA_SRC (asrc);
 
-  cptr = length / alsa->bytes_per_sample;
+  cptr = length / alsa->bpf;
   ptr = data;
 
   GST_ALSA_SRC_LOCK (asrc);
@@ -911,7 +832,7 @@ gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
   }
   GST_ALSA_SRC_UNLOCK (asrc);
 
-  return length - (cptr * alsa->bytes_per_sample);
+  return length - (cptr * alsa->bpf);
 
 read_error:
   {