audio: rework audio caps.
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 18 Aug 2011 17:15:03 +0000 (19:15 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 18 Aug 2011 17:15:03 +0000 (19:15 +0200)
Rework the audio caps similar to the video caps. Remove
width/depth/endianness/signed fields and replace with a simple string
format and media type audio/x-raw.
Create a GstAudioInfo and some helper methods to parse caps.
Remove duplicate code from the ringbuffer and replace with audio info.
Use AudioInfo in the base audio filter class.
Port elements to new API.

39 files changed:
ext/alsa/gstalsasink.c
ext/alsa/gstalsasink.h
ext/alsa/gstalsasrc.c
ext/alsa/gstalsasrc.h
ext/vorbis/gstvorbisdec.c
ext/vorbis/gstvorbisdec.h
ext/vorbis/gstvorbisdeclib.c
ext/vorbis/gstvorbisdeclib.h
gst-libs/gst/audio/Makefile.am
gst-libs/gst/audio/audio.c
gst-libs/gst/audio/audio.h
gst-libs/gst/audio/gstaudiofilter.c
gst-libs/gst/audio/gstaudiofilter.h
gst-libs/gst/audio/gstaudioiec61937.c
gst-libs/gst/audio/gstbaseaudiosink.c
gst-libs/gst/audio/gstbaseaudiosrc.c
gst-libs/gst/audio/gstringbuffer.c
gst-libs/gst/audio/gstringbuffer.h
gst-libs/gst/audio/multichannel.c
gst-libs/gst/audio/multichannel.h
gst-libs/gst/video/video.h
gst/adder/gstadder.c
gst/audioconvert/audioconvert.c
gst/audioconvert/audioconvert.h
gst/audioconvert/gstaudioconvert.c
gst/audioconvert/gstaudioconvert.h
gst/audioconvert/gstaudioquantize.c
gst/audioconvert/gstchannelmix.c
gst/audiorate/Makefile.am
gst/audiorate/gstaudiorate.c
gst/audiorate/gstaudiorate.h
gst/audioresample/Makefile.am
gst/audioresample/gstaudioresample.c
gst/audioresample/gstaudioresample.h
gst/audiotestsrc/Makefile.am
gst/audiotestsrc/gstaudiotestsrc.c
gst/audiotestsrc/gstaudiotestsrc.h
gst/playback/gstrawcaps.h
gst/volume/gstvolume.c

index 9dc5b53..298e5a8 100644 (file)
@@ -95,46 +95,13 @@ static gint output_ref;         /* 0    */
 static snd_output_t *output;    /* NULL */
 static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
 
-
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-# define ALSA_SINK_FACTORY_ENDIANNESS  "LITTLE_ENDIAN, BIG_ENDIAN"
-#else
-# define ALSA_SINK_FACTORY_ENDIANNESS  "BIG_ENDIAN, LITTLE_ENDIAN"
-#endif
-
 static GstStaticPadTemplate alsasink_sink_factory =
     GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SINK_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_SINK_FACTORY_ENDIANNESS " }, "
-        "signed = (boolean) { TRUE, FALSE }, "
-        "width = (int) 24, "
-        "depth = (int) 24, "
+    GST_STATIC_CAPS ("audio/x-raw, "
+        "formats = (string) " GST_AUDIO_FORMATS_ALL ", "
         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) { " ALSA_SINK_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_SINK_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, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
         "audio/x-iec958")
     );
 
@@ -627,26 +594,96 @@ alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec)
   alsa->iec958 = FALSE;
 
   switch (spec->type) {
-    case GST_BUFTYPE_LINEAR:
-      GST_DEBUG_OBJECT (alsa,
-          "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
-          spec->width, spec->sign, spec->bigend);
-
-      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_S16_LE:
+          alsa->format = SND_PCM_FORMAT_S16_LE;
+          break;
+        case GST_AUDIO_FORMAT_S16_BE:
+          alsa->format = SND_PCM_FORMAT_S16_BE;
+          break;
+        case GST_AUDIO_FORMAT_U16_LE:
+          alsa->format = SND_PCM_FORMAT_U16_LE;
+          break;
+        case GST_AUDIO_FORMAT_U16_BE:
+          alsa->format = SND_PCM_FORMAT_U16_BE;
+          break;
+        case GST_AUDIO_FORMAT_S24_LE:
+          alsa->format = SND_PCM_FORMAT_S24_LE;
+          break;
+        case GST_AUDIO_FORMAT_S24_BE:
+          alsa->format = SND_PCM_FORMAT_S24_BE;
+          break;
+        case GST_AUDIO_FORMAT_U24_LE:
+          alsa->format = SND_PCM_FORMAT_U24_LE;
+          break;
+        case GST_AUDIO_FORMAT_U24_BE:
+          alsa->format = SND_PCM_FORMAT_U24_BE;
+          break;
+        case GST_AUDIO_FORMAT_S32_LE:
+          alsa->format = SND_PCM_FORMAT_S32_LE;
+          break;
+        case GST_AUDIO_FORMAT_S32_BE:
+          alsa->format = SND_PCM_FORMAT_S32_BE;
+          break;
+        case GST_AUDIO_FORMAT_U32_LE:
+          alsa->format = SND_PCM_FORMAT_U32_LE;
+          break;
+        case GST_AUDIO_FORMAT_U32_BE:
+          alsa->format = SND_PCM_FORMAT_U32_BE;
+          break;
+        case GST_AUDIO_FORMAT_S24_3LE:
+          alsa->format = SND_PCM_FORMAT_S24_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S24_3BE:
+          alsa->format = SND_PCM_FORMAT_S24_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U24_3LE:
+          alsa->format = SND_PCM_FORMAT_U24_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U24_3BE:
+          alsa->format = SND_PCM_FORMAT_U24_3BE;
+          break;
+        case GST_AUDIO_FORMAT_S20_3LE:
+          alsa->format = SND_PCM_FORMAT_S20_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S20_3BE:
+          alsa->format = SND_PCM_FORMAT_S20_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U20_3LE:
+          alsa->format = SND_PCM_FORMAT_U20_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U20_3BE:
+          alsa->format = SND_PCM_FORMAT_U20_3BE;
+          break;
+        case GST_AUDIO_FORMAT_S18_3LE:
+          alsa->format = SND_PCM_FORMAT_S18_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S18_3BE:
+          alsa->format = SND_PCM_FORMAT_S18_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U18_3LE:
+          alsa->format = SND_PCM_FORMAT_U18_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U18_3BE:
+          alsa->format = SND_PCM_FORMAT_U18_3BE;
+          break;
+        case GST_AUDIO_FORMAT_F32_LE:
           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
           break;
-        case GST_FLOAT32_BE:
+        case GST_AUDIO_FORMAT_F32_BE:
           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
           break;
-        case GST_FLOAT64_LE:
+        case GST_AUDIO_FORMAT_F64_LE:
           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
           break;
-        case GST_FLOAT64_BE:
+        case GST_AUDIO_FORMAT_F64_BE:
           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
           break;
         default:
@@ -667,8 +704,8 @@ alsasink_parse_spec (GstAlsaSink * 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;
@@ -724,7 +761,7 @@ gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
 
   alsa = GST_ALSA_SINK (asink);
 
-  if (spec->format == GST_IEC958) {
+  if (spec->type == GST_BUFTYPE_IEC958) {
     snd_pcm_close (alsa->handle);
     alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
     if (G_UNLIKELY (!alsa->handle)) {
@@ -738,8 +775,8 @@ gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
   CHECK (set_hwparams (alsa), hw_params_failed);
   CHECK (set_swparams (alsa), sw_params_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;
 
   {
@@ -867,7 +904,7 @@ gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
 
   GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
 
-  cptr = length / alsa->bytes_per_sample;
+  cptr = length / alsa->bpf;
 
   GST_ALSA_SINK_LOCK (asink);
   while (cptr > 0) {
@@ -896,7 +933,7 @@ gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
   }
   GST_ALSA_SINK_UNLOCK (asink);
 
-  return length - (cptr * alsa->bytes_per_sample);
+  return length - (cptr * alsa->bpf);
 
 write_error:
   {
index 902dbf7..a4bcdbe 100644 (file)
@@ -61,7 +61,7 @@ struct _GstAlsaSink {
   snd_pcm_format_t format;
   guint rate;
   guint channels;
-  gint bytes_per_sample;
+  gint bpf;
   gboolean iec958;
   gboolean need_swap;
 
index 350c9a7..425dc7f 100644 (file)
@@ -107,37 +107,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 ]")
     );
 
@@ -655,22 +629,96 @@ static gboolean
 alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * 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_S16_LE:
+          alsa->format = SND_PCM_FORMAT_S16_LE;
+          break;
+        case GST_AUDIO_FORMAT_S16_BE:
+          alsa->format = SND_PCM_FORMAT_S16_BE;
+          break;
+        case GST_AUDIO_FORMAT_U16_LE:
+          alsa->format = SND_PCM_FORMAT_U16_LE;
+          break;
+        case GST_AUDIO_FORMAT_U16_BE:
+          alsa->format = SND_PCM_FORMAT_U16_BE;
+          break;
+        case GST_AUDIO_FORMAT_S24_LE:
+          alsa->format = SND_PCM_FORMAT_S24_LE;
+          break;
+        case GST_AUDIO_FORMAT_S24_BE:
+          alsa->format = SND_PCM_FORMAT_S24_BE;
+          break;
+        case GST_AUDIO_FORMAT_U24_LE:
+          alsa->format = SND_PCM_FORMAT_U24_LE;
+          break;
+        case GST_AUDIO_FORMAT_U24_BE:
+          alsa->format = SND_PCM_FORMAT_U24_BE;
+          break;
+        case GST_AUDIO_FORMAT_S32_LE:
+          alsa->format = SND_PCM_FORMAT_S32_LE;
+          break;
+        case GST_AUDIO_FORMAT_S32_BE:
+          alsa->format = SND_PCM_FORMAT_S32_BE;
+          break;
+        case GST_AUDIO_FORMAT_U32_LE:
+          alsa->format = SND_PCM_FORMAT_U32_LE;
+          break;
+        case GST_AUDIO_FORMAT_U32_BE:
+          alsa->format = SND_PCM_FORMAT_U32_BE;
+          break;
+        case GST_AUDIO_FORMAT_S24_3LE:
+          alsa->format = SND_PCM_FORMAT_S24_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S24_3BE:
+          alsa->format = SND_PCM_FORMAT_S24_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U24_3LE:
+          alsa->format = SND_PCM_FORMAT_U24_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U24_3BE:
+          alsa->format = SND_PCM_FORMAT_U24_3BE;
+          break;
+        case GST_AUDIO_FORMAT_S20_3LE:
+          alsa->format = SND_PCM_FORMAT_S20_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S20_3BE:
+          alsa->format = SND_PCM_FORMAT_S20_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U20_3LE:
+          alsa->format = SND_PCM_FORMAT_U20_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U20_3BE:
+          alsa->format = SND_PCM_FORMAT_U20_3BE;
+          break;
+        case GST_AUDIO_FORMAT_S18_3LE:
+          alsa->format = SND_PCM_FORMAT_S18_3LE;
+          break;
+        case GST_AUDIO_FORMAT_S18_3BE:
+          alsa->format = SND_PCM_FORMAT_S18_3BE;
+          break;
+        case GST_AUDIO_FORMAT_U18_3LE:
+          alsa->format = SND_PCM_FORMAT_U18_3LE;
+          break;
+        case GST_AUDIO_FORMAT_U18_3BE:
+          alsa->format = SND_PCM_FORMAT_U18_3BE;
+          break;
+        case GST_AUDIO_FORMAT_F32_LE:
           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
           break;
-        case GST_FLOAT32_BE:
+        case GST_AUDIO_FORMAT_F32_BE:
           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
           break;
-        case GST_FLOAT64_LE:
+        case GST_AUDIO_FORMAT_F64_LE:
           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
           break;
-        case GST_FLOAT64_BE:
+        case GST_AUDIO_FORMAT_F64_BE:
           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
           break;
         default:
@@ -687,8 +735,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;
@@ -753,13 +801,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;
 
@@ -869,7 +913,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);
@@ -889,7 +933,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:
   {
index 7072ab7..de33833 100644 (file)
@@ -63,7 +63,7 @@ struct _GstAlsaSrc {
   snd_pcm_format_t      format;
   guint                 rate;
   guint                 channels;
-  gint                  bytes_per_sample;
+  gint                  bpf;
   gboolean              driver_timestamps;
 
   guint                 buffer_time;
index df58a44..db8b8c7 100644 (file)
@@ -224,7 +224,7 @@ vorbis_dec_convert (GstPad * pad,
     case GST_FORMAT_TIME:
       switch (*dest_format) {
         case GST_FORMAT_BYTES:
-          scale = dec->width * dec->vi.channels;
+          scale = dec->info.bpf;
         case GST_FORMAT_DEFAULT:
           *dest_value =
               scale * gst_util_uint64_scale_int (src_value, dec->vi.rate,
@@ -237,7 +237,7 @@ vorbis_dec_convert (GstPad * pad,
     case GST_FORMAT_DEFAULT:
       switch (*dest_format) {
         case GST_FORMAT_BYTES:
-          *dest_value = src_value * dec->width * dec->vi.channels;
+          *dest_value = src_value * dec->info.bpf;
           break;
         case GST_FORMAT_TIME:
           *dest_value =
@@ -250,11 +250,11 @@ vorbis_dec_convert (GstPad * pad,
     case GST_FORMAT_BYTES:
       switch (*dest_format) {
         case GST_FORMAT_DEFAULT:
-          *dest_value = src_value / (dec->width * dec->vi.channels);
+          *dest_value = src_value / dec->info.bpf;
           break;
         case GST_FORMAT_TIME:
           *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
-              dec->vi.rate * dec->width * dec->vi.channels);
+              dec->vi.rate * dec->info.bpf);
           break;
         default:
           res = FALSE;
@@ -545,10 +545,13 @@ static GstFlowReturn
 vorbis_handle_identification_packet (GstVorbisDec * vd)
 {
   GstCaps *caps;
+  GstAudioInfo info;
   const GstAudioChannelPosition *pos = NULL;
-  gint width = GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH;
 
-  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 */
@@ -559,59 +562,27 @@ vorbis_handle_identification_packet (GstVorbisDec * vd)
     case 6:
     case 7:
     case 8:
-      pos = gst_vorbis_channel_positions[vd->vi.channels - 1];
+      pos = gst_vorbis_channel_positions[info.channels - 1];
       break;
-    default:{
-      gint i;
-      GstAudioChannelPosition *posn =
-          g_new (GstAudioChannelPosition, vd->vi.channels);
+    default:
+    {
+      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;
     }
   }
 
-  /* negotiate width with downstream */
-  caps = gst_pad_get_allowed_caps (vd->srcpad);
-  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_pad_set_caps (vd->srcpad, 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_make_writable (gst_pad_get_pad_template_caps (vd->srcpad));
-  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 (vd->srcpad, caps);
-  gst_caps_unref (caps);
+  vd->copy_samples = get_copy_sample_func (info.channels);
 
   return GST_FLOW_OK;
 }
@@ -792,7 +763,7 @@ vorbis_dec_push_forward (GstVorbisDec * dec, GstBuffer * buf)
 
   /* clip */
   if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate,
-              dec->vi.channels * dec->width))) {
+              dec->info.bpf))) {
     GST_LOG_OBJECT (dec, "clipped buffer");
     return GST_FLOW_OK;
   }
@@ -856,9 +827,7 @@ static GstFlowReturn
 vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
     GstClockTime timestamp, GstClockTime duration)
 {
-#ifdef USE_TREMOLO
-  vorbis_sample_t *pcm;
-#else
+#ifndef USE_TREMOLO
   vorbis_sample_t **pcm;
 #endif
   guint sample_count;
@@ -899,17 +868,17 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
 #endif
     goto done;
 
-  size = sample_count * vd->vi.channels * vd->width;
+  size = sample_count * vd->info.bpf;
   GST_LOG_OBJECT (vd, "%d samples ready for reading, size %" G_GSIZE_FORMAT,
       sample_count, size);
 
   /* alloc buffer for it */
   out = gst_buffer_new_and_alloc (size);
 
+  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,
+  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))
@@ -918,9 +887,8 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
 
 #ifndef USE_TREMOLO
   /* copy samples in buffer */
-  data = gst_buffer_map (out, NULL, NULL, GST_MAP_WRITE);
   vd->copy_samples ((vorbis_sample_t *) data, pcm,
-      sample_count, vd->vi.channels, vd->width);
+      sample_count, vd->info.channels);
 #endif
 
   GST_LOG_OBJECT (vd, "setting output size to %" G_GSIZE_FORMAT, size);
index 04e4677..d122a0e 100644 (file)
@@ -65,7 +65,7 @@ struct _GstVorbisDec {
 #endif
 
   gboolean          initialized;
-  guint             width;
+  GstAudioInfo      info;
 
   /* list of buffers that need timestamps */
   GList            *queued;
index 1ddce38..66a2ee3 100644 (file)
  * is allowed, downstream elements are supposed to clip */
 static void
 copy_samples_m (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
-    gint channels, gint width)
+    gint channels)
 {
   memcpy (out, in[0], samples * sizeof (float));
 }
 
 static void
 copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
-    gint channels, gint width)
+    gint channels)
 {
 #ifdef GST_VORBIS_DEC_SEQUENTIAL
   memcpy (out, in[0], samples * sizeof (float));
@@ -59,7 +59,7 @@ copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
 
 static void
 copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
-    gint channels, gint width)
+    gint channels)
 {
 #ifdef GST_VORBIS_DEC_SEQUENTIAL
   gint i;
@@ -80,12 +80,10 @@ copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
 }
 
 CopySampleFunc
-get_copy_sample_func (gint channels, gint width)
+get_copy_sample_func (gint channels)
 {
   CopySampleFunc f = NULL;
 
-  g_assert (width == 4);
-
   switch (channels) {
     case 1:
       f = copy_samples_m;
@@ -131,50 +129,8 @@ CLIP_TO_15 (ogg_int32_t x)
 #endif
 
 static void
-copy_samples_32_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
-    guint samples, gint channels, gint width)
-{
-  gint32 *out = (gint32 *) _out;
-  ogg_int32_t **in = (ogg_int32_t **) _in;
-  gint j;
-
-  for (j = 0; j < samples; j++) {
-    *out++ = CLIP_TO_15 (in[0][j] >> 9);
-  }
-}
-
-static void
-copy_samples_32_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
-    guint samples, gint channels, gint width)
-{
-  gint32 *out = (gint32 *) _out;
-  ogg_int32_t **in = (ogg_int32_t **) _in;
-  gint j;
-
-  for (j = 0; j < samples; j++) {
-    *out++ = CLIP_TO_15 (in[0][j] >> 9);
-    *out++ = CLIP_TO_15 (in[1][j] >> 9);
-  }
-}
-
-static void
-copy_samples_32 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
-    gint channels, gint width)
-{
-  gint32 *out = (gint32 *) _out;
-  ogg_int32_t **in = (ogg_int32_t **) _in;
-  gint i, j;
-
-  for (j = 0; j < samples; j++) {
-    for (i = 0; i < channels; i++) {
-      *out++ = CLIP_TO_15 (in[i][j] >> 9);
-    }
-  }
-}
-
-static void
 copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
-    guint samples, gint channels, gint width)
+    guint samples, gint channels)
 {
   gint16 *out = (gint16 *) _out;
   ogg_int32_t **in = (ogg_int32_t **) _in;
@@ -187,7 +143,7 @@ copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
 
 static void
 copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
-    guint samples, gint channels, gint width)
+    guint samples, gint channels)
 {
   gint16 *out = (gint16 *) _out;
   ogg_int32_t **in = (ogg_int32_t **) _in;
@@ -201,7 +157,7 @@ copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
 
 static void
 copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
-    gint channels, gint width)
+    gint channels)
 {
   gint16 *out = (gint16 *) _out;
   ogg_int32_t **in = (ogg_int32_t **) _in;
@@ -215,36 +171,20 @@ copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
 }
 
 CopySampleFunc
-get_copy_sample_func (gint channels, gint width)
+get_copy_sample_func (gint channels)
 {
   CopySampleFunc f = NULL;
 
-  if (width == 4) {
-    switch (channels) {
-      case 1:
-        f = copy_samples_32_m;
-        break;
-      case 2:
-        f = copy_samples_32_s;
-        break;
-      default:
-        f = copy_samples_32;
-        break;
-    }
-  } else if (width == 2) {
-    switch (channels) {
-      case 1:
-        f = copy_samples_16_m;
-        break;
-      case 2:
-        f = copy_samples_16_s;
-        break;
-      default:
-        f = copy_samples_16;
-        break;
-    }
-  } else {
-    g_assert_not_reached ();
+  switch (channels) {
+    case 1:
+      f = copy_samples_16_m;
+      break;
+    case 2:
+      f = copy_samples_16_s;
+      break;
+    default:
+      f = copy_samples_16;
+      break;
   }
   return f;
 }
index 2e39422..fd41643 100644 (file)
@@ -26,6 +26,7 @@
 #define __GST_VORBIS_DEC_LIB_H__
 
 #include <gst/gst.h>
+#include <gst/audio/audio.h>
 
 #ifndef TREMOR
 
@@ -36,12 +37,19 @@ typedef ogg_packet                     ogg_packet_wrapper;
 
 #define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to float audio"
 
-#define GST_VORBIS_DEC_SRC_CAPS \
-    GST_STATIC_CAPS ("audio/x-raw-float, " \
-        "rate = (int) [ 1, MAX ], " \
-        "channels = (int) [ 1, 256 ], " \
-        "endianness = (int) BYTE_ORDER, " \
-        "width = (int) 32")
+#define GST_VORBIS_AUDIO_FORMAT     GST_AUDIO_FORMAT_F32
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define GST_VORBIS_AUDIO_FORMAT_STR "F32_BE"
+#else
+#define GST_VORBIS_AUDIO_FORMAT_STR "F32_LE"
+#endif
+
+#define GST_VORBIS_DEC_SRC_CAPS       \
+    GST_STATIC_CAPS ("audio/x-raw, "  \
+        "format = (string)" GST_VORBIS_AUDIO_FORMAT_STR ", "     \
+        "rate = (int) [ 1, MAX ], "   \
+        "channels = (int) [ 1, 256 ]")
 
 #define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH           (32)
 
@@ -101,16 +109,19 @@ struct _ogg_packet_wrapper {
 
 #define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to integer audio"
 
-#define GST_VORBIS_DEC_SRC_CAPS \
-    GST_STATIC_CAPS ("audio/x-raw-int, "   \
-        "rate = (int) [ 1, MAX ], "        \
-        "channels = (int) [ 1, 6 ], "      \
-        "endianness = (int) BYTE_ORDER, "  \
-        "width = (int) { 16, 32 }, "       \
-        "depth = (int) 16, "               \
-        "signed = (boolean) true")
+#define GST_VORBIS_AUDIO_FORMAT GST_AUDIO_FORMAT_S16
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define GST_VORBIS_AUDIO_FORMAT_STR "S16_BE"
+#else
+#define GST_VORBIS_AUDIO_FORMAT_STR "S16_LE"
+#endif
 
-#define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH           (16)
+#define GST_VORBIS_DEC_SRC_CAPS        \
+    GST_STATIC_CAPS ("audio/x-raw, "   \
+        "format = (string) " GST_VORBIS_AUDIO_FORMAT_STR ", "      \
+        "rate = (int) [ 1, MAX ], "    \
+        "channels = (int) [ 1, 6 ]")
 
 /* we need a different type name here */
 #define GST_VORBIS_DEC_GLIB_TYPE_NAME      GstIVorbisDec
@@ -176,8 +187,8 @@ gst_ogg_packet_from_wrapper (ogg_packet_wrapper * packet)
 #endif
 
 typedef void (*CopySampleFunc)(vorbis_sample_t *out, vorbis_sample_t **in,
-                           guint samples, gint channels, gint width);
+                           guint samples, gint channels);
 
-CopySampleFunc get_copy_sample_func (gint channels, gint width);
+CopySampleFunc get_copy_sample_func (gint channels);
 
 #endif /* __GST_VORBIS_DEC_LIB_H__ */
index f0c59fc..bf38ead 100644 (file)
@@ -69,6 +69,7 @@ GstAudio-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstaudio-@GST_MAJORMI
                GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \
                $(INTROSPECTION_SCANNER) -v --namespace GstAudio \
                --nsversion=@GST_MAJORMINOR@ \
+               --warn-all \
                --strip-prefix=Gst \
                -DGST_USE_UNSTABLE_API \
                -I$(top_srcdir)/gst-libs \
index 52ca633..ea415c3 100644 (file)
 #  include "config.h"
 #endif
 
+#include <string.h>
+
 #include "audio.h"
 #include "audio-enumtypes.h"
 
 #include <gst/gststructure.h>
 
+#define SINT (GST_AUDIO_FORMAT_FLAG_INT | GST_AUDIO_FORMAT_FLAG_SIGNED)
+#define UINT (GST_AUDIO_FORMAT_FLAG_INT)
+
+#define MAKE_FORMAT(str,flags,end,width,depth,silent) \
+  { GST_AUDIO_FORMAT_ ##str, G_STRINGIFY(str), flags, end, width, depth, silent }
+
+#define SILENT_0       { 0, 0, 0, 0, 0, 0, 0, 0 }
+#define SILENT_U8      { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
+#define SILENT_U16_LE  { 0x00, 0x80,  0x00, 0x80,  0x00, 0x80,  0x00, 0x80 }
+#define SILENT_U16_BE  { 0x80, 0x00,  0x80, 0x00,  0x80, 0x00,  0x80, 0x00 }
+#define SILENT_U24_LE  { 0x00, 0x00, 0x80, 0x00,  0x00, 0x00, 0x80, 0x00 }
+#define SILENT_U24_BE  { 0x00, 0x80, 0x00, 0x00,  0x00, 0x80, 0x00, 0x00 }
+#define SILENT_U32_LE  { 0x00, 0x00, 0x00, 0x80,  0x00, 0x00, 0x00, 0x80 }
+#define SILENT_U32_BE  { 0x80, 0x00, 0x00, 0x00,  0x80, 0x00, 0x00, 0x00 }
+#define SILENT_U24_3LE { 0x00, 0x00, 0x80,  0x00, 0x00, 0x80 }
+#define SILENT_U24_3BE { 0x80, 0x00, 0x00,  0x80, 0x00, 0x00 }
+#define SILENT_U20_3LE { 0x00, 0x00, 0x08,  0x00, 0x00, 0x08 }
+#define SILENT_U20_3BE { 0x08, 0x00, 0x00,  0x08, 0x00, 0x00 }
+#define SILENT_U18_3LE { 0x00, 0x00, 0x02,  0x00, 0x00, 0x02 }
+#define SILENT_U18_3BE { 0x02, 0x00, 0x00,  0x02, 0x00, 0x00 }
+
+static GstAudioFormatInfo formats[] = {
+  {GST_AUDIO_FORMAT_UNKNOWN, "UNKNOWN", 0, 0, 0, 0},
+  /* 8 bit */
+  MAKE_FORMAT (S8, SINT, 0, 8, 8, SILENT_0),
+  MAKE_FORMAT (U8, UINT, 0, 8, 8, SILENT_U8),
+  /* 16 bit */
+  MAKE_FORMAT (S16_LE, SINT, G_LITTLE_ENDIAN, 16, 16, SILENT_0),
+  MAKE_FORMAT (S16_BE, SINT, G_BIG_ENDIAN, 16, 16, SILENT_0),
+  MAKE_FORMAT (U16_LE, UINT, G_LITTLE_ENDIAN, 16, 16, SILENT_U16_LE),
+  MAKE_FORMAT (U16_BE, UINT, G_BIG_ENDIAN, 16, 16, SILENT_U16_BE),
+  /* 24 bit in low 3 bytes of 32 bits */
+  MAKE_FORMAT (S24_LE, SINT, G_LITTLE_ENDIAN, 32, 24, SILENT_0),
+  MAKE_FORMAT (S24_BE, SINT, G_BIG_ENDIAN, 32, 24, SILENT_0),
+  MAKE_FORMAT (U24_LE, UINT, G_LITTLE_ENDIAN, 32, 24, SILENT_U24_LE),
+  MAKE_FORMAT (U24_BE, UINT, G_BIG_ENDIAN, 32, 24, SILENT_U24_BE),
+  /* 32 bit */
+  MAKE_FORMAT (S32_LE, SINT, G_LITTLE_ENDIAN, 32, 32, SILENT_0),
+  MAKE_FORMAT (S32_BE, SINT, G_BIG_ENDIAN, 32, 32, SILENT_0),
+  MAKE_FORMAT (U32_LE, UINT, G_LITTLE_ENDIAN, 32, 32, SILENT_U32_LE),
+  MAKE_FORMAT (U32_BE, UINT, G_BIG_ENDIAN, 32, 32, SILENT_U32_BE),
+  /* 24 bit in 3 bytes */
+  MAKE_FORMAT (S24_3LE, SINT, G_LITTLE_ENDIAN, 24, 24, SILENT_0),
+  MAKE_FORMAT (S24_3BE, SINT, G_BIG_ENDIAN, 24, 24, SILENT_0),
+  MAKE_FORMAT (U24_3LE, UINT, G_LITTLE_ENDIAN, 24, 24, SILENT_U24_3LE),
+  MAKE_FORMAT (U24_3BE, UINT, G_BIG_ENDIAN, 24, 24, SILENT_U24_3BE),
+  /* 20 bit in 3 bytes */
+  MAKE_FORMAT (S20_3LE, SINT, G_LITTLE_ENDIAN, 24, 20, SILENT_0),
+  MAKE_FORMAT (S20_3BE, SINT, G_BIG_ENDIAN, 24, 20, SILENT_0),
+  MAKE_FORMAT (U20_3LE, UINT, G_LITTLE_ENDIAN, 24, 20, SILENT_U20_3LE),
+  MAKE_FORMAT (U20_3BE, UINT, G_BIG_ENDIAN, 24, 20, SILENT_U20_3BE),
+  /* 18 bit in 3 bytes */
+  MAKE_FORMAT (S18_3LE, SINT, G_LITTLE_ENDIAN, 24, 18, SILENT_0),
+  MAKE_FORMAT (S18_3BE, SINT, G_BIG_ENDIAN, 24, 18, SILENT_0),
+  MAKE_FORMAT (U18_3LE, UINT, G_LITTLE_ENDIAN, 24, 18, SILENT_U18_3LE),
+  MAKE_FORMAT (U18_3BE, UINT, G_BIG_ENDIAN, 24, 18, SILENT_U18_3BE),
+  /* float */
+  MAKE_FORMAT (F32_LE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 32, 32,
+      SILENT_0),
+  MAKE_FORMAT (F32_BE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 32, 32,
+      SILENT_0),
+  MAKE_FORMAT (F64_LE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 64, 64,
+      SILENT_0),
+  MAKE_FORMAT (F64_BE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 64, 64,
+      SILENT_0)
+};
+
+/**
+ * gst_audio_format_from_string:
+ * @format: a format string
+ *
+ * Convert the @format string to its #GstAudioFormat.
+ *
+ * Returns: the #GstAudioFormat for @format or GST_AUDIO_FORMAT_UNKNOWN when the
+ * string is not a known format.
+ */
+GstAudioFormat
+gst_audio_format_from_string (const gchar * format)
+{
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (formats); i++) {
+    if (strcmp (GST_AUDIO_FORMAT_INFO_NAME (&formats[i]), format) == 0)
+      return GST_AUDIO_FORMAT_INFO_FORMAT (&formats[i]);
+  }
+  return GST_AUDIO_FORMAT_UNKNOWN;
+}
+
+const gchar *
+gst_audio_format_to_string (GstAudioFormat format)
+{
+  g_return_val_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN, NULL);
+
+  if (format >= G_N_ELEMENTS (formats))
+    return NULL;
+
+  return GST_AUDIO_FORMAT_INFO_NAME (&formats[format]);
+}
+
+/**
+ * gst_audio_format_get_info:
+ * @format: a #GstAudioFormat
+ *
+ * Get the #GstAudioFormatInfo for @format
+ *
+ * Returns: The #GstAudioFormatInfo for @format.
+ */
+const GstAudioFormatInfo *
+gst_audio_format_get_info (GstAudioFormat format)
+{
+  g_return_val_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN, NULL);
+  g_return_val_if_fail (format < G_N_ELEMENTS (formats), NULL);
+
+  return &formats[format];
+}
+
+/**
+ * gst_audio_format_fill_silence:
+ * @info: a #GstAudioFormatInfo
+ * @dest: a destination to fill
+ * @lenfth: the length to fill
+ *
+ * Fill @length bytes in @dest with silence samples for @info.
+ */
+void
+gst_audio_format_fill_silence (const GstAudioFormatInfo * info,
+    gpointer dest, gsize length)
+{
+  guint8 *dptr = dest;
+
+  g_return_if_fail (info != NULL);
+  g_return_if_fail (dest != NULL);
+
+  if (info->flags & GST_AUDIO_FORMAT_FLAG_FLOAT ||
+      info->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) {
+    /* float or signed always 0 */
+    memset (dest, 0, length);
+  } else {
+    gint i, j, bps = info->width >> 3;
+
+    switch (bps) {
+      case 1:
+        memset (dest, info->silence[0], length);
+        break;
+      default:
+        for (i = 0; i < length; i += bps) {
+          for (j = 0; j < bps; j++)
+            *dptr++ = info->silence[j];
+        }
+        break;
+    }
+  }
+}
+
+
+/**
+ * gst_audio_info_init:
+ * @info: a #GstAudioInfo
+ *
+ * Initialize @info with default values.
+ */
+void
+gst_audio_info_init (GstAudioInfo * info)
+{
+  g_return_if_fail (info != NULL);
+
+  memset (info, 0, sizeof (GstAudioInfo));
+}
+
+/**
+ * gst_audio_info_set_format:
+ * @info: a #GstAudioInfo
+ * @format: the format
+ * @rate: the samplerate
+ * @channels: the number of channels
+ *
+ * Set the default info for the audio info of @format and @rate and @channels.
+ */
+void
+gst_audio_info_set_format (GstAudioInfo * info, GstAudioFormat format,
+    gint rate, gint channels)
+{
+  const GstAudioFormatInfo *finfo;
+
+  g_return_if_fail (info != NULL);
+  g_return_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN);
+
+  finfo = &formats[format];
+
+  info->flags = 0;
+  info->finfo = finfo;
+  info->rate = rate;
+  info->channels = channels;
+  info->bpf = (finfo->width * channels) / 8;
+}
+
+/**
+ * gst_audio_info_from_caps:
+ * @info: a #GstAudioInfo
+ * @caps: a #GstCaps
+ *
+ * Parse @caps and update @info.
+ *
+ * Returns: TRUE if @caps could be parsed
+ */
+gboolean
+gst_audio_info_from_caps (GstAudioInfo * info, const GstCaps * caps)
+{
+  GstStructure *str;
+  const gchar *s;
+  GstAudioFormat format;
+  gint rate, channels;
+  const GValue *pos_val_arr, *pos_val_entry;
+  gint i;
+
+  g_return_val_if_fail (info != NULL, FALSE);
+  g_return_val_if_fail (caps != NULL, FALSE);
+  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
+
+  GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
+
+  str = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_has_name (str, "audio/x-raw"))
+    goto wrong_name;
+
+  if (!(s = gst_structure_get_string (str, "format")))
+    goto no_format;
+
+  format = gst_audio_format_from_string (s);
+  if (format == GST_AUDIO_FORMAT_UNKNOWN)
+    goto unknown_format;
+
+  if (!gst_structure_get_int (str, "rate", &rate))
+    goto no_rate;
+  if (!gst_structure_get_int (str, "channels", &channels))
+    goto no_channels;
+
+  gst_audio_info_set_format (info, format, rate, channels);
+
+  pos_val_arr = gst_structure_get_value (str, "channel-positions");
+  if (pos_val_arr) {
+    guint max_pos = MAX (channels, 64);
+    for (i = 0; i < max_pos; i++) {
+      pos_val_entry = gst_value_array_get_value (pos_val_arr, i);
+      info->position[i] = g_value_get_enum (pos_val_entry);
+    }
+  } else {
+    info->flags |= GST_AUDIO_FLAG_UNPOSITIONED;
+  }
+
+  return TRUE;
+
+  /* ERROR */
+wrong_name:
+  {
+    GST_ERROR ("wrong name, expected audio/x-raw");
+    return FALSE;
+  }
+no_format:
+  {
+    GST_ERROR ("no format given");
+    return FALSE;
+  }
+unknown_format:
+  {
+    GST_ERROR ("unknown format given");
+    return FALSE;
+  }
+no_rate:
+  {
+    GST_ERROR ("no rate property given");
+    return FALSE;
+  }
+no_channels:
+  {
+    GST_ERROR ("no channels property given");
+    return FALSE;
+  }
+}
+
+/**
+ * gst_audio_info_to_caps:
+ * @info: a #GstAudioInfo
+ *
+ * Convert the values of @info into a #GstCaps.
+ *
+ * Returns: a new #GstCaps containing the info of @info.
+ */
+GstCaps *
+gst_audio_info_to_caps (GstAudioInfo * info)
+{
+  GstCaps *caps;
+  const gchar *format;
+
+  g_return_val_if_fail (info != NULL, NULL);
+  g_return_val_if_fail (info->finfo != NULL, NULL);
+  g_return_val_if_fail (info->finfo->format != GST_AUDIO_FORMAT_UNKNOWN, NULL);
+
+  format = gst_audio_format_to_string (info->finfo->format);
+  g_return_val_if_fail (format != NULL, NULL);
+
+  caps = gst_caps_new_simple ("audio/x-raw",
+      "format", G_TYPE_STRING, format,
+      "rate", G_TYPE_INT, info->rate,
+      "channels", G_TYPE_INT, info->channels, NULL);
+
+  if (info->channels > 2) {
+    GValue pos_val_arr = { 0 }
+    , pos_val_entry = {
+    0};
+    gint i, max_pos;
+    GstStructure *str;
+
+    /* build gvaluearray from positions */
+    g_value_init (&pos_val_arr, GST_TYPE_ARRAY);
+    g_value_init (&pos_val_entry, GST_TYPE_AUDIO_CHANNEL_POSITION);
+    max_pos = MAX (info->channels, 64);
+    for (i = 0; i < max_pos; i++) {
+      g_value_set_enum (&pos_val_entry, info->position[i]);
+      gst_value_array_append_value (&pos_val_arr, &pos_val_entry);
+    }
+    g_value_unset (&pos_val_entry);
+
+    /* add to structure */
+    str = gst_caps_get_structure (caps, 0);
+    gst_structure_set_value (str, "channel-positions", &pos_val_arr);
+    g_value_unset (&pos_val_arr);
+  }
+
+  return caps;
+}
+
+
 /**
  * gst_audio_frame_byte_size:
  * @pad: the #GstPad to get the caps from
index 65b3cce..24a3ca1 100644 (file)
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
  * Library       <2001> Thomas Vander Stichele <thomas@apestaart.org>
+ *               <2011> Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #ifndef __GST_AUDIO_AUDIO_H__
 #define __GST_AUDIO_AUDIO_H__
 
+#include <gst/audio/multichannel.h>
+
 G_BEGIN_DECLS
 
-/* For people that are looking at this source: the purpose of these defines is
- * to make GstCaps a bit easier, in that you don't have to know all of the
- * properties that need to be defined. you can just use these macros. currently
- * (8/01) the only plugins that use these are the passthrough, speed, volume,
- * adder, and [de]interleave plugins. These are for convenience only, and do not
- * specify the 'limits' of GStreamer. you might also use these definitions as a
- * base for making your own caps, if need be.
+/**
+ * GstAudioFormat:
+ * @GST_AUDIO_FORMAT_UNKNOWN: unknown audio format
+ * @GST_AUDIO_FORMAT_S8: sample
+ * @GST_AUDIO_FORMAT_U8: sample
+ * @GST_AUDIO_FORMAT_S16_LE: sample
+ * @GST_AUDIO_FORMAT_S16_BE: sample
+ * @GST_AUDIO_FORMAT_U16_LE: sample
+ * @GST_AUDIO_FORMAT_U16_BE: sample
+ * @GST_AUDIO_FORMAT_S24_LE: sample
+ * @GST_AUDIO_FORMAT_S24_BE: sample
+ * @GST_AUDIO_FORMAT_U24_LE: sample
+ * @GST_AUDIO_FORMAT_U24_BE: sample
+ * @GST_AUDIO_FORMAT_S32_LE: sample
+ * @GST_AUDIO_FORMAT_S32_BE: sample
+ * @GST_AUDIO_FORMAT_U32_LE: sample
+ * @GST_AUDIO_FORMAT_U32_BE: sample
+ * @GST_AUDIO_FORMAT_S24_3LE: sample
+ * @GST_AUDIO_FORMAT_S24_3BE: sample
+ * @GST_AUDIO_FORMAT_U24_3LE: sample
+ * @GST_AUDIO_FORMAT_U24_3BE: sample
+ * @GST_AUDIO_FORMAT_S20_3LE: sample
+ * @GST_AUDIO_FORMAT_S20_3BE: sample
+ * @GST_AUDIO_FORMAT_U20_3LE: sample
+ * @GST_AUDIO_FORMAT_U20_3BE: sample
+ * @GST_AUDIO_FORMAT_S18_3LE: sample
+ * @GST_AUDIO_FORMAT_S18_3BE: sample
+ * @GST_AUDIO_FORMAT_U18_3LE: sample
+ * @GST_AUDIO_FORMAT_U18_3BE: sample
+ * @GST_AUDIO_FORMAT_F32_LE: sample
+ * @GST_AUDIO_FORMAT_F32_BE: sample
+ * @GST_AUDIO_FORMAT_F64_LE: sample
+ * @GST_AUDIO_FORMAT_F64_BE: sample
  *
- * For example, to make a source pad that can output streams of either mono
- * float or any channel int:
+ * Enum value describing the most common audio formats.
+ */
+typedef enum {
+  GST_AUDIO_FORMAT_UNKNOWN,
+  /* 8 bit */
+  GST_AUDIO_FORMAT_S8,
+  GST_AUDIO_FORMAT_U8,
+  /* 16 bit */
+  GST_AUDIO_FORMAT_S16_LE,
+  GST_AUDIO_FORMAT_S16_BE,
+  GST_AUDIO_FORMAT_U16_LE,
+  GST_AUDIO_FORMAT_U16_BE,
+  /* 24 bit in low 3 bytes of 32 bits*/
+  GST_AUDIO_FORMAT_S24_LE,
+  GST_AUDIO_FORMAT_S24_BE,
+  GST_AUDIO_FORMAT_U24_LE,
+  GST_AUDIO_FORMAT_U24_BE,
+  /* 32 bit */
+  GST_AUDIO_FORMAT_S32_LE,
+  GST_AUDIO_FORMAT_S32_BE,
+  GST_AUDIO_FORMAT_U32_LE,
+  GST_AUDIO_FORMAT_U32_BE,
+  /* 24 bit in 3 bytes*/
+  GST_AUDIO_FORMAT_S24_3LE,
+  GST_AUDIO_FORMAT_S24_3BE,
+  GST_AUDIO_FORMAT_U24_3LE,
+  GST_AUDIO_FORMAT_U24_3BE,
+  /* 20 bit in 3 bytes*/
+  GST_AUDIO_FORMAT_S20_3LE,
+  GST_AUDIO_FORMAT_S20_3BE,
+  GST_AUDIO_FORMAT_U20_3LE,
+  GST_AUDIO_FORMAT_U20_3BE,
+  /* 18 bit in 3 bytes*/
+  GST_AUDIO_FORMAT_S18_3LE,
+  GST_AUDIO_FORMAT_S18_3BE,
+  GST_AUDIO_FORMAT_U18_3LE,
+  GST_AUDIO_FORMAT_U18_3BE,
+  /* float */
+  GST_AUDIO_FORMAT_F32_LE,
+  GST_AUDIO_FORMAT_F32_BE,
+  GST_AUDIO_FORMAT_F64_LE,
+  GST_AUDIO_FORMAT_F64_BE,
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+  GST_AUDIO_FORMAT_S16 = GST_AUDIO_FORMAT_S16_BE,
+  GST_AUDIO_FORMAT_U16 = GST_AUDIO_FORMAT_U16_BE,
+  GST_AUDIO_FORMAT_S24 = GST_AUDIO_FORMAT_S24_BE,
+  GST_AUDIO_FORMAT_U24 = GST_AUDIO_FORMAT_U24_BE,
+  GST_AUDIO_FORMAT_S32 = GST_AUDIO_FORMAT_S32_BE,
+  GST_AUDIO_FORMAT_U32 = GST_AUDIO_FORMAT_U32_BE,
+  GST_AUDIO_FORMAT_S24_3 = GST_AUDIO_FORMAT_S24_3BE,
+  GST_AUDIO_FORMAT_U24_3 = GST_AUDIO_FORMAT_U24_3BE,
+  GST_AUDIO_FORMAT_S20_3 = GST_AUDIO_FORMAT_S20_3BE,
+  GST_AUDIO_FORMAT_U20_3 = GST_AUDIO_FORMAT_U20_3BE,
+  GST_AUDIO_FORMAT_S18_3 = GST_AUDIO_FORMAT_S18_3BE,
+  GST_AUDIO_FORMAT_U18_3 = GST_AUDIO_FORMAT_U18_3BE,
+  GST_AUDIO_FORMAT_F32 = GST_AUDIO_FORMAT_F32_BE,
+  GST_AUDIO_FORMAT_F64 = GST_AUDIO_FORMAT_F64_BE
+#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
+  GST_AUDIO_FORMAT_S16 = GST_AUDIO_FORMAT_S16_LE,
+  GST_AUDIO_FORMAT_U16 = GST_AUDIO_FORMAT_U16_LE,
+  GST_AUDIO_FORMAT_S24 = GST_AUDIO_FORMAT_S24_LE,
+  GST_AUDIO_FORMAT_U24 = GST_AUDIO_FORMAT_U24_LE,
+  GST_AUDIO_FORMAT_S32 = GST_AUDIO_FORMAT_S32_LE,
+  GST_AUDIO_FORMAT_U32 = GST_AUDIO_FORMAT_U32_LE,
+  GST_AUDIO_FORMAT_S24_3 = GST_AUDIO_FORMAT_S24_3LE,
+  GST_AUDIO_FORMAT_U24_3 = GST_AUDIO_FORMAT_U24_3LE,
+  GST_AUDIO_FORMAT_S20_3 = GST_AUDIO_FORMAT_S20_3LE,
+  GST_AUDIO_FORMAT_U20_3 = GST_AUDIO_FORMAT_U20_3LE,
+  GST_AUDIO_FORMAT_S18_3 = GST_AUDIO_FORMAT_S18_3LE,
+  GST_AUDIO_FORMAT_U18_3 = GST_AUDIO_FORMAT_U18_3LE,
+  GST_AUDIO_FORMAT_F32 = GST_AUDIO_FORMAT_F32_LE,
+  GST_AUDIO_FORMAT_F64 = GST_AUDIO_FORMAT_F64_LE
+#endif
+} GstAudioFormat;
+
+typedef struct _GstAudioFormatInfo GstAudioFormatInfo;
+typedef struct _GstAudioInfo GstAudioInfo;
+
+/**
+ * GstAudioFormatFlags:
+ * @GST_AUDIO_FORMAT_FLAG_INT: int samples
+ * @GST_AUDIO_FORMAT_FLAG_FLOAT: float samples
+ * @GST_AUDIO_FORMAT_FLAG_SIGNED: signed samples
+ * @GST_AUDIO_FORMAT_FLAG_COMPLEX: complex layout
  *
- *  template = gst_pad_template_new
- *    ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
- *    gst_caps_append(gst_caps_new ("sink_int",  "audio/x-raw-int",
- *                                  GST_AUDIO_INT_PAD_TEMPLATE_PROPS),
- *                    gst_caps_new ("sink_float", "audio/x-raw-float",
- *                                  GST_AUDIO_FLOAT_PAD_TEMPLATE_PROPS)),
- *    NULL);
+ * The different audio flags that a format info can have.
+ */
+typedef enum
+{
+  GST_AUDIO_FORMAT_FLAG_INT      = (1 << 0),
+  GST_AUDIO_FORMAT_FLAG_FLOAT    = (1 << 1),
+  GST_AUDIO_FORMAT_FLAG_SIGNED   = (1 << 2),
+  GST_AUDIO_FORMAT_FLAG_COMPLEX  = (1 << 4)
+} GstAudioFormatFlags;
+
+/**
+ * GstAudioFormatUnpack:
+ * @info: a #GstAudioFormatInfo
+ * @dest: a destination array
+ * @data: pointer to the audio data
+ * @length: the amount of samples to unpack.
  *
- *  sinkpad = gst_pad_new_from_template(template, "sink");
+ * Unpacks @length samples from the given data of format @info.
+ * The samples will be unpacked into @dest which each channel
+ * interleaved. @dest should at least be big enough to hold @length *
+ * channels * unpack_size bytes.
+ */
+typedef void (*GstAudioFormatUnpack)         (GstAudioFormatInfo *info, gpointer dest,
+                                              const gpointer data, gint length);
+/**
+ * GstAudioFormatPack:
+ * @info: a #GstAudioFormatInfo
+ * @src: a source array
+ * @data: pointer to the destination data
+ * @length: the amount of samples to pack.
  *
- * Andy Wingo, 18 August 2001
- * Thomas, 6 September 2002 */
+ * Packs @length samples from @src to the data array in format @info.
+ * The samples from source have each channel interleaved
+ * and will be packed into @data.
+ */
+typedef void (*GstAudioFormatPack)           (GstAudioFormatInfo *info, const gpointer src,
+                                              gpointer data, gint length);
 
-/* conversion macros */
 /**
- * GST_FRAMES_TO_CLOCK_TIME:
- * @frames: sample frames
- * @rate: sampling rate
- * 
- * Calculate clocktime from sample @frames and @rate.
+ * GstAudioFormatInfo:
+ * @format: #GstAudioFormat
+ * @name: string representation of the format
+ * @flags: #GstAudioFormatFlags
+ * @endianness: the endianness
+ * @width: amount of bits used for one sample
+ * @depth: amount of valid bits in @width
+ * @silence: @width/8 bytes with 1 silent sample
+ * @unpack_size: number of bytes for the unpack functions
+ * @unpack_func: function to unpack samples
+ * @pack_func: function to pack samples
+ *
+ * Information for an audio format.
  */
-#define GST_FRAMES_TO_CLOCK_TIME(frames, rate) \
-  ((GstClockTime) gst_util_uint64_scale_round (frames, GST_SECOND, rate))
+struct _GstAudioFormatInfo {
+  GstAudioFormat format;
+  const gchar *name;
+  GstAudioFormatFlags flags;
+  gint endianness;
+  gint width;
+  gint depth;
+  guint8 silence[8];
+  guint unpack_size;
+  GstAudioFormatUnpack unpack_func;
+  GstAudioFormatPack pack_func;
+};
+
+#define GST_AUDIO_FORMAT_INFO_FORMAT(info)       ((info)->format)
+#define GST_AUDIO_FORMAT_INFO_NAME(info)         ((info)->name)
+#define GST_AUDIO_FORMAT_INFO_FLAGS(info)        ((info)->flags)
+
+#define GST_AUDIO_FORMAT_INFO_IS_INT(info)       ((info)->flags & GST_AUDIO_FORMAT_FLAG_INT)
+#define GST_AUDIO_FORMAT_INFO_IS_FLOAT(info)     ((info)->flags & GST_AUDIO_FORMAT_FLAG_FLOAT)
+#define GST_AUDIO_FORMAT_INFO_IS_SIGNED(info)    ((info)->flags & GST_AUDIO_FORMAT_FLAG_SIGNED)
 
+#define GST_AUDIO_FORMAT_INFO_ENDIANNESS(info)   ((info)->endianness)
+#define GST_AUDIO_FORMAT_INFO_IS_LE(info)        ((info)->endianness == G_LITTLE_ENDIAN)
+#define GST_AUDIO_FORMAT_INFO_IS_BE(info)        ((info)->endianness == G_BIG_ENDIAN)
+#define GST_AUDIO_FORMAT_INFO_WIDTH(info)        ((info)->width)
+#define GST_AUDIO_FORMAT_INFO_DEPTH(info)        ((info)->depth)
+
+GstAudioFormat gst_audio_format_from_string          (const gchar *format) G_GNUC_CONST;
+const gchar *  gst_audio_format_to_string            (GstAudioFormat format) G_GNUC_CONST;
+const GstAudioFormatInfo *
+               gst_audio_format_get_info             (GstAudioFormat format) G_GNUC_CONST;
+
+void           gst_audio_format_fill_silence         (const GstAudioFormatInfo *info,
+                                                      gpointer dest, gsize length);
 /**
- * GST_CLOCK_TIME_TO_FRAMES:
- * @clocktime: clock time
- * @rate: sampling rate
- * 
- * Calculate frames from @clocktime and sample @rate.
+ * GstAudioFlags:
+ * @GST_AUDIO_FLAG_NONE: no valid flag
+ * @GST_AUDIO_FLAG_UNPOSITIONED: unpositioned audio layout, position array
+ *     contains the default layout.
+ *
+ * Extra audio flags
  */
-#define GST_CLOCK_TIME_TO_FRAMES(clocktime, rate) \
-  gst_util_uint64_scale_round (clocktime, rate, GST_SECOND)
+typedef enum {
+  GST_AUDIO_FLAG_NONE         = 0,
+  GST_AUDIO_FLAG_UNPOSITIONED = (1 << 0)
+} GstAudioFlags;
+
+/**
+ * GstAudioInfo:
+ * @finfo: the format info of the audio
+ * @flags: additional audio flags
+ * @rate: the audio sample rate
+ * @channels: the number of channels
+ * @bpf: the number of bytes for one frame, this is the size of one
+ *         sample * @channels
+ * @positions: the positions for each channel
+ *
+ * Information describing audio properties. This information can be filled
+ * in from GstCaps with gst_audio_info_from_caps().
+ *
+ * Use the provided macros to access the info in this structure.
+ */
+struct _GstAudioInfo {
+  const GstAudioFormatInfo *finfo;
+  GstAudioFlags             flags;
+  gint                      rate;
+  gint                      channels;
+  gint                      bpf;
+  GstAudioChannelPosition   position[64];
+};
+
+#define GST_AUDIO_INFO_FORMAT(i)             (GST_AUDIO_FORMAT_INFO_FORMAT((i)->finfo))
+#define GST_AUDIO_INFO_NAME(i)               (GST_AUDIO_FORMAT_INFO_NAME((i)->finfo))
+
+#define GST_AUDIO_INFO_FLAGS(info)           ((info)->flags)
+#define GST_AUDIO_INFO_IS_UNPOSITIONED(info) ((info)->flags & GST_AUDIO_FLAG_UNPOSITIONED)
+
+#define GST_AUDIO_INFO_RATE(info)            ((info)->rate)
+#define GST_AUDIO_INFO_CHANNELS(info)        ((info)->channels)
+#define GST_AUDIO_INFO_BPF(info)             ((info)->bpf)
+#define GST_AUDIO_INFO_POSITION(info,c)      ((info)->position[c])
+
+void         gst_audio_info_init        (GstAudioInfo *info);
+void         gst_audio_info_set_format  (GstAudioInfo *info, GstAudioFormat format,
+                                         gint rate, gint channels);
+
+gboolean     gst_audio_info_from_caps   (GstAudioInfo *info, const GstCaps *caps);
+GstCaps *    gst_audio_info_to_caps     (GstAudioInfo *info);
+
+
+#define GST_AUDIO_RATE_RANGE "(int) [ 1, max ]"
+#define GST_AUDIO_CHANNELS_RANGE "(int) [ 1, max ]"
+
+#define GST_AUDIO_FORMATS_ALL " { S8, U8, " \
+    "S16_LE, S16_BE, U16_LE, U16_BE, " \
+    "S24_LE, S24_BE, U24_LE, U24_BE, " \
+    "S32_LE, S32_BE, U32_LE, U32_BE, " \
+    "S24_3LE, S24_3BE, U24_3LE, U24_3BE, " \
+    "S20_3LE, S20_3BE, U20_3LE, U20_3BE, " \
+    "S18_3LE, S18_3BE, U18_3LE, U18_3BE, " \
+    "F32_LE, F32_BE, F64_LE, F64_BE }"
+
+/**
+ * GST_AUDIO_CAPS_MAKE:
+ * @format: string format that describes the pixel layout, as string
+ *     (e.g. "S16_LE", "S8", etc.)
+ *
+ * Generic caps string for audio, for use in pad templates.
+ */
+#define GST_AUDIO_CAPS_MAKE(format)                                    \
+    "audio/x-raw, "                                                    \
+    "format = (string) " format ", "                                   \
+    "rate = " GST_AUDIO_RATE_RANGE ", "                                \
+    "channels = " GST_AUDIO_CHANNELS_RANGE
 
 /**
  * GST_AUDIO_DEF_RATE:
- * 
+ *
  * Standard sampling rate used in consumer audio.
  */
 #define GST_AUDIO_DEF_RATE 44100
-
 /**
- * GST_AUDIO_INT_PAD_TEMPLATE_CAPS:
- * 
- * Template caps for integer audio. Can be used when defining a 
- * #GstStaticPadTemplate
+ * GST_AUDIO_DEF_CHANNELS:
+ *
+ * Standard number of channels used in consumer audio.
  */
-#define GST_AUDIO_INT_PAD_TEMPLATE_CAPS \
-  "audio/x-raw-int, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) [ 1, MAX ], " \
-  "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
-  "width = (int) { 8, 16, 24, 32 }, " \
-  "depth = (int) [ 1, 32 ], " \
-  "signed = (boolean) { true, false }"
-
+#define GST_AUDIO_DEF_CHANNELS 2
 /**
- * GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS:
- * 
- * Template caps for 16bit integer stereo audio in native byte-order.
- * Can be used when defining a #GstStaticPadTemplate
+ * GST_AUDIO_DEF_FORMAT:
+ *
+ * Standard format used in consumer audio.
  */
-#define GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS \
-  "audio/x-raw-int, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) 2, " \
-  "endianness = (int) BYTE_ORDER, " \
-  "width = (int) 16, " \
-  "depth = (int) 16, " \
-  "signed = (boolean) true"
+#define GST_AUDIO_DEF_FORMAT "S16_LE"
 
+/* conversion macros */
 /**
- * GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS:
- * 
- * Template caps for float audio. Can be used when defining a 
- * #GstStaticPadTemplate
+ * GST_FRAMES_TO_CLOCK_TIME:
+ * @frames: sample frames
+ * @rate: sampling rate
+ *
+ * Calculate clocktime from sample @frames and @rate.
  */
-#define GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS \
-  "audio/x-raw-float, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) [ 1, MAX ], " \
-  "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " \
-  "width = (int) { 32, 64 }"
+#define GST_FRAMES_TO_CLOCK_TIME(frames, rate) \
+  ((GstClockTime) gst_util_uint64_scale_round (frames, GST_SECOND, rate))
 
 /**
- * GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS:
- * 
- * Template caps for 32bit float mono audio in native byte-order.
- * Can be used when defining a #GstStaticPadTemplate
+ * GST_CLOCK_TIME_TO_FRAMES:
+ * @clocktime: clock time
+ * @rate: sampling rate
+ *
+ * Calculate frames from @clocktime and sample @rate.
  */
-#define GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS \
-  "audio/x-raw-float, " \
-  "width = (int) 32, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) 1, " \
-  "endianness = (int) BYTE_ORDER"
+#define GST_CLOCK_TIME_TO_FRAMES(clocktime, rate) \
+  gst_util_uint64_scale_round (clocktime, rate, GST_SECOND)
 
 /*
  * this library defines and implements some helper functions for audio
index fe6ad8a..52d7eee 100644 (file)
@@ -78,12 +78,6 @@ gst_audio_filter_class_init (GstAudioFilterClass * klass)
   basetrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_filter_set_caps);
   basetrans_class->get_unit_size =
       GST_DEBUG_FUNCPTR (gst_audio_filter_get_unit_size);
-
-  /* FIXME: Ref the GstRingerBuffer class to get it's debug category
-   * initialized. gst_ring_buffer_parse_caps () which we use later
-   * uses this debug category.
-   */
-  g_type_class_ref (GST_TYPE_RING_BUFFER);
 }
 
 static void
@@ -103,9 +97,7 @@ gst_audio_filter_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
-      memset (&filter->format, 0, sizeof (GstRingBufferSpec));
-      /* to make gst_buffer_spec_parse_caps() happy */
-      filter->format.latency_time = GST_SECOND;
+      gst_audio_info_init (&filter->info);
       break;
     default:
       break;
@@ -120,7 +112,7 @@ gst_audio_filter_change_state (GstElement * element, GstStateChange transition)
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:
     case GST_STATE_CHANGE_READY_TO_NULL:
-      gst_caps_replace (&filter->format.caps, NULL);
+      gst_audio_info_init (&filter->info);
       break;
     default:
       break;
@@ -139,17 +131,22 @@ gst_audio_filter_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
 
   GST_LOG_OBJECT (filter, "caps: %" GST_PTR_FORMAT, incaps);
 
-  if (!gst_ring_buffer_parse_caps (&filter->format, incaps)) {
-    GST_WARNING_OBJECT (filter, "couldn't parse %" GST_PTR_FORMAT, incaps);
-    return FALSE;
-  }
+  if (!gst_audio_info_from_caps (&filter->info, incaps))
+    goto invalid_format;
 
   klass = GST_AUDIO_FILTER_CLASS_CAST (G_OBJECT_GET_CLASS (filter));
 
   if (klass->setup)
-    ret = klass->setup (filter, &filter->format);
+    ret = klass->setup (filter, &filter->info);
 
   return ret;
+
+  /* ERROR */
+invalid_format:
+  {
+    GST_WARNING_OBJECT (filter, "couldn't parse %" GST_PTR_FORMAT, incaps);
+    return FALSE;
+  }
 }
 
 static gboolean
index ed50317..5f4b656 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <gst/gst.h>
 #include <gst/base/gstbasetransform.h>
-#include <gst/audio/gstringbuffer.h>
+#include <gst/audio/audio.h>
 
 G_BEGIN_DECLS
 
@@ -56,7 +56,7 @@ struct _GstAudioFilter {
   GstBaseTransform basetransform;
 
   /*< protected >*/
-  GstRingBufferSpec format;   /* currently configured format */
+  GstAudioInfo info;   /* currently configured format */
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -78,7 +78,7 @@ struct _GstAudioFilterClass {
   GstBaseTransformClass basetransformclass;
 
   /* virtual function, called whenever the format changes */
-  gboolean  (*setup) (GstAudioFilter * filter, GstRingBufferSpec * format);
+  gboolean  (*setup) (GstAudioFilter * filter, GstAudioInfo * info);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
index 9ad787b..5742d28 100644 (file)
@@ -114,9 +114,9 @@ gst_audio_iec61937_frame_size (const GstRingBufferSpec * spec)
 
       if (version == 1 && layer == 1)
         frames = 384;
-      else if (version == 2 && layer == 1 && spec->rate < 32000)
+      else if (version == 2 && layer == 1 && spec->info.rate < 32000)
         frames = 768;
-      else if (version == 2 && layer == 1 && spec->rate < 32000)
+      else if (version == 2 && layer == 1 && spec->info.rate < 32000)
         frames = 2304;
       else
         frames = 1152;
@@ -271,13 +271,13 @@ gst_audio_iec61937_payload (const guint8 * src, guint src_n, guint8 * dst,
       if (version == 1 && layer == 1)
         dst[five] = 0x04;
       else if ((version == 1 && (layer == 2 || layer == 3)) ||
-          (version == 2 && spec->rate >= 32000))
+          (version == 2 && spec->info.rate >= 32000))
         dst[five] = 0x05;
-      else if (version == 2 && layer == 1 && spec->rate < 32000)
+      else if (version == 2 && layer == 1 && spec->info.rate < 32000)
         dst[five] = 0x08;
-      else if (version == 2 && layer == 2 && spec->rate < 32000)
+      else if (version == 2 && layer == 2 && spec->info.rate < 32000)
         dst[five] = 0x09;
-      else if (version == 2 && layer == 3 && spec->rate < 32000)
+      else if (version == 2 && layer == 3 && spec->info.rate < 32000)
         dst[five] = 0x0A;
       else
         g_return_val_if_reached (FALSE);
index 262a97b..45b66a6 100644 (file)
@@ -395,7 +395,7 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
           GstRingBufferSpec *spec;
 
           GST_OBJECT_LOCK (basesink);
-          if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) {
+          if (!basesink->ringbuffer || !basesink->ringbuffer->spec.info.rate) {
             GST_OBJECT_UNLOCK (basesink);
 
             GST_DEBUG_OBJECT (basesink,
@@ -409,7 +409,7 @@ gst_base_audio_sink_query (GstElement * element, GstQuery * query)
 
           base_latency =
               gst_util_uint64_scale_int (spec->seglatency * spec->segsize,
-              GST_SECOND, spec->rate * spec->bytes_per_sample);
+              GST_SECOND, spec->info.rate * spec->info.bpf);
           GST_OBJECT_UNLOCK (basesink);
 
           /* we cannot go lower than the buffer size and the min peer latency */
@@ -470,7 +470,7 @@ gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
   guint delay;
   GstClockTime result;
 
-  if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0)
+  if (sink->ringbuffer == NULL || sink->ringbuffer->spec.info.rate == 0)
     return GST_CLOCK_TIME_NONE;
 
   /* our processed samples are always increasing */
@@ -486,7 +486,7 @@ gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
     samples = 0;
 
   result = gst_util_uint64_scale_int (samples, GST_SECOND,
-      sink->ringbuffer->spec.rate);
+      sink->ringbuffer->spec.info.rate);
 
   GST_DEBUG_OBJECT (sink,
       "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"
@@ -756,7 +756,7 @@ gst_base_audio_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
   /* calculate actual latency and buffer times.
    * FIXME: In 0.11, store the latency_time internally in ns */
   spec->latency_time = gst_util_uint64_scale (spec->segsize,
-      (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample);
+      (GST_SECOND / GST_USECOND), spec->info.rate * spec->info.bpf);
 
   spec->buffer_time = spec->segtotal * spec->latency_time;
 
@@ -821,7 +821,7 @@ gst_base_audio_sink_drain (GstBaseAudioSink * sink)
 {
   if (!sink->ringbuffer)
     return TRUE;
-  if (!sink->ringbuffer->spec.rate)
+  if (!sink->ringbuffer->spec.info.rate)
     return TRUE;
 
   /* if PLAYING is interrupted,
@@ -1066,7 +1066,7 @@ gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink,
     cexternal = cexternal > mdrift ? cexternal - mdrift : 0;
     sink->priv->avg_skew -= mdrift;
 
-    driftsamples = (sink->ringbuffer->spec.rate * mdrift) / GST_SECOND;
+    driftsamples = (sink->ringbuffer->spec.info.rate * mdrift) / GST_SECOND;
     last_align = sink->priv->last_align;
 
     /* if we were aligning in the wrong direction or we aligned more than what we
@@ -1088,7 +1088,7 @@ gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink,
     cexternal += mdrift;
     sink->priv->avg_skew += mdrift;
 
-    driftsamples = (sink->ringbuffer->spec.rate * mdrift) / GST_SECOND;
+    driftsamples = (sink->ringbuffer->spec.info.rate * mdrift) / GST_SECOND;
     last_align = sink->priv->last_align;
 
     /* if we were aligning in the wrong direction or we aligned more than what we
@@ -1308,6 +1308,7 @@ gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
   gint64 samples_done = segdone * ringbuf->samples_per_seg;
   gint64 headroom = sample_offset - samples_done;
   gboolean allow_align = TRUE;
+  gint rate;
 
   /* now try to align the sample to the previous one, first see how big the
    * difference is. */
@@ -1316,9 +1317,11 @@ gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
   else
     diff = sink->next_sample - sample_offset;
 
+  rate = GST_AUDIO_INFO_RATE (&ringbuf->spec.info);
+
   /* calculate the max allowed drift in units of samples. By default this is
    * 20ms and should be anough to compensate for timestamp rounding errors. */
-  maxdrift = (ringbuf->spec.rate * sink->priv->drift_tolerance) / GST_MSECOND;
+  maxdrift = (rate * sink->priv->drift_tolerance) / GST_MSECOND;
 
   /* calc align with previous sample */
   align = sink->next_sample - sample_offset;
@@ -1333,8 +1336,7 @@ gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
         G_GINT64_FORMAT, align, maxdrift);
   } else {
     /* calculate sample diff in seconds for error message */
-    gint64 diff_s =
-        gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate);
+    gint64 diff_s = gst_util_uint64_scale_int (diff, GST_SECOND, rate);
     /* timestamps drifted apart from previous samples too much, we need to
      * resync. We log this as an element warning. */
     GST_WARNING_OBJECT (sink,
@@ -1362,7 +1364,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
   guint8 *data;
   gsize size;
   guint samples, written;
-  gint bps;
+  gint bpf, rate;
   gint accum;
   gint out_samples;
   GstClockTime base_time, render_delay, latency;
@@ -1409,13 +1411,14 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
     buf = out;
   }
 
-  bps = ringbuf->spec.bytes_per_sample;
+  bpf = GST_AUDIO_INFO_BPF (&ringbuf->spec.info);
+  rate = GST_AUDIO_INFO_RATE (&ringbuf->spec.info);
 
   size = gst_buffer_get_size (buf);
-  if (G_UNLIKELY (size % bps) != 0)
+  if (G_UNLIKELY (size % bpf) != 0)
     goto wrong_size;
 
-  samples = size / bps;
+  samples = size / bpf;
   out_samples = samples;
 
   in_offset = GST_BUFFER_OFFSET (buf);
@@ -1442,8 +1445,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
 
   /* let's calc stop based on the number of samples in the buffer instead
    * of trusting the DURATION */
-  stop = time + gst_util_uint64_scale_int (samples, GST_SECOND,
-      ringbuf->spec.rate);
+  stop = time + gst_util_uint64_scale_int (samples, GST_SECOND, rate);
 
   /* prepare the clipping segment. Since we will be subtracting ts-offset and
    * device-delay later we scale the start and stop with those values so that we
@@ -1484,17 +1486,17 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
   diff = ctime - time;
   if (diff > 0) {
     /* bring clipped time to samples */
-    diff = gst_util_uint64_scale_int (diff, ringbuf->spec.rate, GST_SECOND);
+    diff = gst_util_uint64_scale_int (diff, rate, GST_SECOND);
     GST_DEBUG_OBJECT (sink, "clipping start to %" GST_TIME_FORMAT " %"
         G_GUINT64_FORMAT " samples", GST_TIME_ARGS (ctime), diff);
     samples -= diff;
-    offset += diff * bps;
+    offset += diff * bpf;
     time = ctime;
   }
   diff = stop - cstop;
   if (diff > 0) {
     /* bring clipped time to samples */
-    diff = gst_util_uint64_scale_int (diff, ringbuf->spec.rate, GST_SECOND);
+    diff = gst_util_uint64_scale_int (diff, rate, GST_SECOND);
     GST_DEBUG_OBJECT (sink, "clipping stop to %" GST_TIME_FORMAT " %"
         G_GUINT64_FORMAT " samples", GST_TIME_ARGS (cstop), diff);
     samples -= diff;
@@ -1588,10 +1590,8 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
     goto too_late;
 
   /* and bring the time to the rate corrected offset in the buffer */
-  render_start = gst_util_uint64_scale_int (render_start,
-      ringbuf->spec.rate, GST_SECOND);
-  render_stop = gst_util_uint64_scale_int (render_stop,
-      ringbuf->spec.rate, GST_SECOND);
+  render_start = gst_util_uint64_scale_int (render_start, rate, GST_SECOND);
+  render_stop = gst_util_uint64_scale_int (render_stop, rate, GST_SECOND);
 
   /* positive playback rate, first sample is render_start, negative rate, first
    * sample is render_stop. When no rate conversion is active, render exactly
@@ -1677,7 +1677,7 @@ no_sync:
       break;
 
     samples -= written;
-    offset += written * bps;
+    offset += written * bpf;
   } while (TRUE);
   gst_buffer_unmap (buf, data, size);
 
index 7a1df7b..23c8987 100644 (file)
@@ -323,7 +323,8 @@ gst_base_audio_src_get_time (GstClock * clock, GstBaseAudioSrc * src)
   guint delay;
   GstClockTime result;
 
-  if (G_UNLIKELY (src->ringbuffer == NULL || src->ringbuffer->spec.rate == 0))
+  if (G_UNLIKELY (src->ringbuffer == NULL
+          || src->ringbuffer->spec.info.rate == 0))
     return GST_CLOCK_TIME_NONE;
 
   raw = samples = gst_ring_buffer_samples_done (src->ringbuffer);
@@ -335,7 +336,7 @@ gst_base_audio_src_get_time (GstClock * clock, GstBaseAudioSrc * src)
   samples += delay;
 
   result = gst_util_uint64_scale_int (samples, GST_SECOND,
-      src->ringbuffer->spec.rate);
+      src->ringbuffer->spec.info.rate);
 
   GST_DEBUG_OBJECT (src,
       "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %"
@@ -509,26 +510,14 @@ static void
 gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
 {
   GstStructure *s;
-  gint width, depth;
 
   s = gst_caps_get_structure (caps, 0);
 
   /* fields for all formats */
-  gst_structure_fixate_field_nearest_int (s, "rate", 44100);
-  gst_structure_fixate_field_nearest_int (s, "channels", 2);
-  gst_structure_fixate_field_nearest_int (s, "width", 16);
-
-  /* fields for int */
-  if (gst_structure_has_field (s, "depth")) {
-    gst_structure_get_int (s, "width", &width);
-    /* round width to nearest multiple of 8 for the depth */
-    depth = GST_ROUND_UP_8 (width);
-    gst_structure_fixate_field_nearest_int (s, "depth", depth);
-  }
-  if (gst_structure_has_field (s, "signed"))
-    gst_structure_fixate_field_boolean (s, "signed", TRUE);
-  if (gst_structure_has_field (s, "endianness"))
-    gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER);
+  gst_structure_fixate_field_nearest_int (s, "rate", GST_AUDIO_DEF_RATE);
+  gst_structure_fixate_field_nearest_int (s, "channels",
+      GST_AUDIO_DEF_CHANNELS);
+  gst_structure_fixate_field_string (s, "format", GST_AUDIO_DEF_FORMAT);
 
   GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
 }
@@ -538,6 +527,7 @@ gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
 {
   GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
   GstRingBufferSpec *spec;
+  gint bpf, rate;
 
   spec = &src->ringbuffer->spec;
 
@@ -550,9 +540,11 @@ gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
     goto parse_error;
   }
 
+  bpf = GST_AUDIO_INFO_BPF (&spec->info);
+  rate = GST_AUDIO_INFO_RATE (&spec->info);
+
   /* calculate suggested segsize and segtotal */
-  spec->segsize =
-      spec->rate * spec->bytes_per_sample * spec->latency_time / GST_MSECOND;
+  spec->segsize = rate * bpf * spec->latency_time / GST_MSECOND;
   spec->segtotal = spec->buffer_time / spec->latency_time;
 
   GST_OBJECT_UNLOCK (src);
@@ -569,11 +561,9 @@ gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
     goto acquire_error;
 
   /* calculate actual latency and buffer times */
-  spec->latency_time =
-      spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample);
+  spec->latency_time = spec->segsize * GST_MSECOND / (rate * bpf);
   spec->buffer_time =
-      spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
-      spec->bytes_per_sample);
+      spec->segtotal * spec->segsize * GST_MSECOND / (rate * bpf);
 
   gst_ring_buffer_debug_spec_buff (spec);
 
@@ -616,24 +606,26 @@ gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query)
     {
       GstClockTime min_latency, max_latency;
       GstRingBufferSpec *spec;
+      gint bpf, rate;
 
       GST_OBJECT_LOCK (src);
       if (G_UNLIKELY (src->ringbuffer == NULL
-              || src->ringbuffer->spec.rate == 0)) {
+              || src->ringbuffer->spec.info.rate == 0)) {
         GST_OBJECT_UNLOCK (src);
         goto done;
       }
 
       spec = &src->ringbuffer->spec;
+      rate = GST_AUDIO_INFO_RATE (&spec->info);
+      bpf = GST_AUDIO_INFO_BPF (&spec->info);
 
       /* we have at least 1 segment of latency */
       min_latency =
-          gst_util_uint64_scale_int (spec->segsize, GST_SECOND,
-          spec->rate * spec->bytes_per_sample);
+          gst_util_uint64_scale_int (spec->segsize, GST_SECOND, rate * bpf);
       /* we cannot delay more than the buffersize else we lose data */
       max_latency =
           gst_util_uint64_scale_int (spec->segtotal * spec->segsize, GST_SECOND,
-          spec->rate * spec->bytes_per_sample);
+          rate * bpf);
       GST_OBJECT_UNLOCK (src);
 
       GST_DEBUG_OBJECT (src,
@@ -757,7 +749,7 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
   guchar *data, *ptr;
   guint samples, total_samples;
   guint64 sample;
-  gint bps;
+  gint bpf, rate;
   GstRingBuffer *ringbuffer;
   GstRingBufferSpec *spec;
   guint read;
@@ -770,18 +762,19 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
   if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuffer)))
     goto wrong_state;
 
-  bps = spec->bytes_per_sample;
+  bpf = GST_AUDIO_INFO_BPF (&spec->info);
+  rate = GST_AUDIO_INFO_RATE (&spec->info);
 
   if ((length == 0 && bsrc->blocksize == 0) || length == -1)
     /* no length given, use the default segment size */
     length = spec->segsize;
   else
     /* make sure we round down to an integral number of samples */
-    length -= length % bps;
+    length -= length % bpf;
 
   /* figure out the offset in the ringbuffer */
   if (G_UNLIKELY (offset != -1)) {
-    sample = offset / bps;
+    sample = offset / bpf;
     /* if a specific offset was given it must be the next sequential
      * offset we expect or we fail for now. */
     if (src->next_sample != -1 && sample != src->next_sample)
@@ -796,7 +789,7 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
       sample, length);
 
   /* get the number of samples to read */
-  total_samples = samples = length / bps;
+  total_samples = samples = length / bpf;
 
   /* use the basesrc allocation code to use bufferpools or custom allocators */
   ret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, &buf);
@@ -821,7 +814,7 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
     /* read next samples */
     sample += read;
     samples -= read;
-    ptr += read * bps;
+    ptr += read * bpf;
   } while (TRUE);
   gst_buffer_unmap (buf, data, length);
 
@@ -841,9 +834,9 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
   src->next_sample = sample + samples;
 
   /* get the normal timestamp to get the duration. */
-  timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, spec->rate);
+  timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, rate);
   duration = gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
-      spec->rate) - timestamp;
+      rate) - timestamp;
 
   GST_OBJECT_LOCK (src);
   if (!(clock = GST_ELEMENT_CLOCK (src)))
@@ -890,7 +883,7 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
 
         /* the running_time converted to a sample (relative to the ringbuffer) */
         running_time_sample =
-            gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND);
+            gst_util_uint64_scale_int (running_time, rate, GST_SECOND);
 
         /* the segmentnr corrensponding to running_time, round down */
         running_time_segment = running_time_sample / sps;
@@ -944,8 +937,7 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
           new_sample = ((guint64) new_read_segment) * sps;
 
           /* and get the relative time to this -> our new timestamp */
-          timestamp =
-              gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate);
+          timestamp = gst_util_uint64_scale_int (new_sample, GST_SECOND, rate);
 
           /* we update the next sample accordingly */
           src->next_sample = new_sample + samples;
@@ -974,8 +966,7 @@ gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
           timestamp = 0;
 
         /* subtract latency */
-        latency =
-            gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate);
+        latency = gst_util_uint64_scale_int (total_samples, GST_SECOND, rate);
         if (timestamp > latency)
           timestamp -= latency;
         else
index 7528a78..cb18f76 100644 (file)
@@ -111,95 +111,9 @@ gst_ring_buffer_finalize (GObject * object)
       (ringbuffer));
 }
 
-typedef struct
-{
-  const GstBufferFormat format;
-  const guint8 silence[4];
-} FormatDef;
-
-static const FormatDef linear_defs[4 * 2 * 2] = {
-  {GST_S8, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S8, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U8, {0x80, 0x80, 0x80, 0x80}},
-  {GST_U8, {0x80, 0x80, 0x80, 0x80}},
-  {GST_S16_LE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S16_BE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U16_LE, {0x00, 0x80, 0x00, 0x80}},
-  {GST_U16_BE, {0x80, 0x00, 0x80, 0x00}},
-  {GST_S24_LE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S24_BE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U24_LE, {0x00, 0x00, 0x80, 0x00}},
-  {GST_U24_BE, {0x80, 0x00, 0x00, 0x00}},
-  {GST_S32_LE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S32_BE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U32_LE, {0x00, 0x00, 0x00, 0x80}},
-  {GST_U32_BE, {0x80, 0x00, 0x00, 0x00}}
-};
-
-static const FormatDef linear24_defs[3 * 2 * 2] = {
-  {GST_S24_3LE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S24_3BE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U24_3LE, {0x00, 0x00, 0x80, 0x00}},
-  {GST_U24_3BE, {0x80, 0x00, 0x00, 0x00}},
-  {GST_S20_3LE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S20_3BE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U20_3LE, {0x00, 0x00, 0x08, 0x00}},
-  {GST_U20_3BE, {0x08, 0x00, 0x00, 0x00}},
-  {GST_S18_3LE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_S18_3BE, {0x00, 0x00, 0x00, 0x00}},
-  {GST_U18_3LE, {0x00, 0x00, 0x02, 0x00}},
-  {GST_U18_3BE, {0x02, 0x00, 0x00, 0x00}}
-};
-
-static const FormatDef *
-build_linear_format (int depth, int width, int unsignd, int big_endian)
-{
-  const FormatDef *formats;
-
-  if (width == 24) {
-    switch (depth) {
-      case 24:
-        formats = &linear24_defs[0];
-        break;
-      case 20:
-        formats = &linear24_defs[4];
-        break;
-      case 18:
-        formats = &linear24_defs[8];
-        break;
-      default:
-        return NULL;
-    }
-  } else {
-    switch (depth) {
-      case 8:
-        formats = &linear_defs[0];
-        break;
-      case 16:
-        formats = &linear_defs[4];
-        break;
-      case 24:
-        formats = &linear_defs[8];
-        break;
-      case 32:
-        formats = &linear_defs[12];
-        break;
-      default:
-        return NULL;
-    }
-  }
-  if (unsignd)
-    formats += 2;
-  if (big_endian)
-    formats += 1;
-
-  return formats;
-}
-
 #ifndef GST_DISABLE_GST_DEBUG
 static const gchar *format_type_names[] = {
-  "linear",
-  "float",
+  "raw",
   "mu law",
   "a law",
   "ima adpcm",
@@ -210,49 +124,6 @@ static const gchar *format_type_names[] = {
   "eac3",
   "dts"
 };
-
-static const gchar *format_names[] = {
-  "unknown",
-  "s8",
-  "u8",
-  "s16_le",
-  "s16_be",
-  "u16_le",
-  "u16_be",
-  "s24_le",
-  "s24_be",
-  "u24_le",
-  "u24_be",
-  "s32_le",
-  "s32_be",
-  "u32_le",
-  "u32_be",
-  "s24_3le",
-  "s24_3be",
-  "u24_3le",
-  "u24_3be",
-  "s20_3le",
-  "s20_3be",
-  "u20_3le",
-  "u20_3be",
-  "s18_3le",
-  "s18_3be",
-  "u18_3le",
-  "u18_3be",
-  "float32_le",
-  "float32_be",
-  "float64_le",
-  "float64_be",
-  "mu_law",
-  "a_law",
-  "ima_adpcm",
-  "mpeg",
-  "gsm",
-  "iec958",
-  "ac3",
-  "eac3",
-  "dts"
-};
 #endif
 
 /**
@@ -264,15 +135,15 @@ static const gchar *format_names[] = {
 void
 gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
 {
+#if 0
   gint i, bytes;
+#endif
 
   GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps);
   GST_DEBUG ("parsed caps: type:         %d, '%s'", spec->type,
       format_type_names[spec->type]);
-  GST_DEBUG ("parsed caps: format:       %d, '%s'", spec->format,
-      format_names[spec->format]);
+#if 0
   GST_DEBUG ("parsed caps: width:        %d", spec->width);
-  GST_DEBUG ("parsed caps: depth:        %d", spec->depth);
   GST_DEBUG ("parsed caps: sign:         %d", spec->sign);
   GST_DEBUG ("parsed caps: bigend:       %d", spec->bigend);
   GST_DEBUG ("parsed caps: rate:         %d", spec->rate);
@@ -282,6 +153,7 @@ gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
   for (i = 0; i < bytes; i++) {
     GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]);
   }
+#endif
 }
 
 /**
@@ -293,6 +165,8 @@ gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
 void
 gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
 {
+  gint bpf = GST_AUDIO_INFO_BPF (&spec->info);
+
   GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec",
       spec->buffer_time);
   GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec",
@@ -300,10 +174,9 @@ gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
   GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal);
   GST_DEBUG ("acquire ringbuffer: latency segments: %d", spec->seglatency);
   GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples",
-      spec->segsize, spec->segsize / spec->bytes_per_sample);
+      spec->segsize, spec->segsize / bpf);
   GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples",
-      spec->segsize * spec->segtotal,
-      spec->segsize * spec->segtotal / spec->bytes_per_sample);
+      spec->segsize * spec->segtotal, spec->segsize * spec->segtotal / bpf);
 }
 
 /**
@@ -321,160 +194,77 @@ gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
   const gchar *mimetype;
   GstStructure *structure;
   gint i;
+  GstAudioInfo info;
 
   structure = gst_caps_get_structure (caps, 0);
+  gst_audio_info_init (&info);
 
   /* we have to differentiate between int and float formats */
   mimetype = gst_structure_get_name (structure);
 
-  if (g_str_equal (mimetype, "audio/x-raw-int")) {
-    gint endianness;
-    const FormatDef *def;
-    gint j, bytes;
-
-    spec->type = GST_BUFTYPE_LINEAR;
-
-    /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
-            gst_structure_get_int (structure, "channels", &spec->channels) &&
-            gst_structure_get_int (structure, "width", &spec->width) &&
-            gst_structure_get_int (structure, "depth", &spec->depth) &&
-            gst_structure_get_boolean (structure, "signed", &spec->sign)))
-      goto parse_error;
-
-    /* extract endianness if needed */
-    if (spec->width > 8) {
-      if (!gst_structure_get_int (structure, "endianness", &endianness))
-        goto parse_error;
-    } else {
-      endianness = G_BYTE_ORDER;
-    }
-
-    spec->bigend = endianness == G_LITTLE_ENDIAN ? FALSE : TRUE;
-
-    def = build_linear_format (spec->depth, spec->width, spec->sign ? 0 : 1,
-        spec->bigend ? 1 : 0);
-
-    if (def == NULL)
-      goto parse_error;
-
-    spec->format = def->format;
-
-    bytes = spec->width >> 3;
-
-    for (i = 0; i < spec->channels; i++) {
-      for (j = 0; j < bytes; j++) {
-        spec->silence_sample[i * bytes + j] = def->silence[j];
-      }
-    }
-  } else if (g_str_equal (mimetype, "audio/x-raw-float")) {
-
-    spec->type = GST_BUFTYPE_FLOAT;
-
-    /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
-            gst_structure_get_int (structure, "channels", &spec->channels) &&
-            gst_structure_get_int (structure, "width", &spec->width)))
+  if (g_str_equal (mimetype, "audio/x-raw")) {
+    if (!gst_audio_info_from_caps (&info, caps))
       goto parse_error;
 
-    /* match layout to format wrt to endianness */
-    switch (spec->width) {
-      case 32:
-        spec->format =
-            G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT32_LE : GST_FLOAT32_BE;
-        break;
-      case 64:
-        spec->format =
-            G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT64_LE : GST_FLOAT64_BE;
-        break;
-      default:
-        goto parse_error;
-    }
-    /* float silence is all zeros.. */
-    memset (spec->silence_sample, 0, 32);
+    spec->type = GST_BUFTYPE_RAW;
   } else if (g_str_equal (mimetype, "audio/x-alaw")) {
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
-            gst_structure_get_int (structure, "channels", &spec->channels)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
+            gst_structure_get_int (structure, "channels", &info.channels)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_A_LAW;
-    spec->format = GST_A_LAW;
-    spec->width = 8;
-    spec->depth = 8;
-    for (i = 0; i < spec->channels; i++)
-      spec->silence_sample[i] = 0xd5;
+    spec->info.bpf = info.channels;
   } else if (g_str_equal (mimetype, "audio/x-mulaw")) {
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate) &&
-            gst_structure_get_int (structure, "channels", &spec->channels)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate) &&
+            gst_structure_get_int (structure, "channels", &info.channels)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_MU_LAW;
-    spec->format = GST_MU_LAW;
-    spec->width = 8;
-    spec->depth = 8;
-    for (i = 0; i < spec->channels; i++)
-      spec->silence_sample[i] = 0xff;
+    spec->info.bpf = info.channels;
   } else if (g_str_equal (mimetype, "audio/x-iec958")) {
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_IEC958;
-    spec->format = GST_IEC958;
-    spec->width = 16;
-    spec->depth = 16;
-    spec->channels = 2;
+    spec->info.bpf = 4;
   } else if (g_str_equal (mimetype, "audio/x-ac3")) {
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_AC3;
-    spec->format = GST_AC3;
-    spec->width = 16;
-    spec->depth = 16;
-    spec->channels = 2;
+    spec->info.bpf = 4;
   } else if (g_str_equal (mimetype, "audio/x-eac3")) {
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_EAC3;
-    spec->format = GST_EAC3;
-    spec->width = 64;
-    spec->depth = 64;
-    spec->channels = 2;
+    spec->info.bpf = 16;
   } else if (g_str_equal (mimetype, "audio/x-dts")) {
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_DTS;
-    spec->format = GST_DTS;
-    spec->width = 16;
-    spec->depth = 16;
-    spec->channels = 2;
+    spec->info.bpf = 4;
   } else if (g_str_equal (mimetype, "audio/mpeg") &&
       gst_structure_get_int (structure, "mpegaudioversion", &i) &&
       (i == 1 || i == 2)) {
     /* Now we know this is MPEG-1 or MPEG-2 (non AAC) */
     /* extract the needed information from the cap */
-    if (!(gst_structure_get_int (structure, "rate", &spec->rate)))
+    if (!(gst_structure_get_int (structure, "rate", &info.rate)))
       goto parse_error;
 
     spec->type = GST_BUFTYPE_MPEG;
-    spec->format = GST_MPEG;
-    spec->width = 16;
-    spec->depth = 16;
-    spec->channels = 2;
+    spec->info.bpf = 4;
   } else {
     goto parse_error;
   }
 
-  spec->bytes_per_sample = (spec->width >> 3) * spec->channels;
-
   gst_caps_replace (&spec->caps, caps);
 
   g_return_val_if_fail (spec->latency_time != 0, FALSE);
@@ -482,10 +272,10 @@ gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
   /* calculate suggested segsize and segtotal. segsize should be one unit
    * of 'latency_time' samples, scaling for the fact that latency_time is
    * currently stored in microseconds (FIXME: in 0.11) */
-  spec->segsize = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample,
+  spec->segsize = gst_util_uint64_scale (info.rate * info.bpf,
       spec->latency_time, GST_SECOND / GST_USECOND);
   /* Round to an integer number of samples */
-  spec->segsize -= spec->segsize % spec->bytes_per_sample;
+  spec->segsize -= spec->segsize % info.bpf;
 
   spec->segtotal = spec->buffer_time / spec->latency_time;
   /* leave the latency undefined now, implementations can change it but if it's
@@ -495,6 +285,8 @@ gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
   gst_ring_buffer_debug_spec_caps (spec);
   gst_ring_buffer_debug_spec_buff (spec);
 
+  spec->info = info;
+
   return TRUE;
 
   /* ERRORS */
@@ -525,7 +317,7 @@ gst_ring_buffer_convert (GstRingBuffer * buf,
     GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val)
 {
   gboolean res = TRUE;
-  gint bps, rate;
+  gint bpf, rate;
 
   GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)",
       src_val, gst_format_get_name (src_fmt), src_fmt,
@@ -538,12 +330,12 @@ gst_ring_buffer_convert (GstRingBuffer * buf,
 
   /* get important info */
   GST_OBJECT_LOCK (buf);
-  bps = buf->spec.bytes_per_sample;
-  rate = buf->spec.rate;
+  bpf = GST_AUDIO_INFO_BPF (&buf->spec.info);
+  rate = GST_AUDIO_INFO_RATE (&buf->spec.info);
   GST_OBJECT_UNLOCK (buf);
 
-  if (bps == 0 || rate == 0) {
-    GST_DEBUG ("no rate or bps configured");
+  if (bpf == 0 || rate == 0) {
+    GST_DEBUG ("no rate or bpf configured");
     res = FALSE;
     goto done;
   }
@@ -552,11 +344,11 @@ gst_ring_buffer_convert (GstRingBuffer * buf,
     case GST_FORMAT_BYTES:
       switch (dest_fmt) {
         case GST_FORMAT_TIME:
-          *dest_val = gst_util_uint64_scale_int (src_val / bps, GST_SECOND,
+          *dest_val = gst_util_uint64_scale_int (src_val / bpf, GST_SECOND,
               rate);
           break;
         case GST_FORMAT_DEFAULT:
-          *dest_val = src_val / bps;
+          *dest_val = src_val / bpf;
           break;
         default:
           res = FALSE;
@@ -569,7 +361,7 @@ gst_ring_buffer_convert (GstRingBuffer * buf,
           *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate);
           break;
         case GST_FORMAT_BYTES:
-          *dest_val = src_val * bps;
+          *dest_val = src_val * bpf;
           break;
         default:
           res = FALSE;
@@ -583,7 +375,7 @@ gst_ring_buffer_convert (GstRingBuffer * buf,
           break;
         case GST_FORMAT_BYTES:
           *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
-          *dest_val *= bps;
+          *dest_val *= bpf;
           break;
         default:
           res = FALSE;
@@ -794,8 +586,7 @@ gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 {
   gboolean res = FALSE;
   GstRingBufferClass *rclass;
-  gint i, j;
-  gint segsize, bps;
+  gint segsize, bpf;
 
   g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE);
 
@@ -817,8 +608,8 @@ gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
   if (G_UNLIKELY (!res))
     goto acquire_failed;
 
-  if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0))
-    goto invalid_bps;
+  if (G_UNLIKELY ((bpf = buf->spec.info.bpf) == 0))
+    goto invalid_bpf;
 
   /* if the seglatency was overwritten with something else than -1, use it, else
    * assume segtotal as the latency */
@@ -827,18 +618,18 @@ gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 
   segsize = buf->spec.segsize;
 
-  buf->samples_per_seg = segsize / bps;
+  buf->samples_per_seg = segsize / bpf;
 
   /* create an empty segment */
   g_free (buf->empty_seg);
   buf->empty_seg = g_malloc (segsize);
 
-  /* FIXME, we only have 32 silence samples, which might not be enough to
-   * represent silence in all channels */
-  bps = MIN (bps, 32);
-  for (i = 0, j = 0; i < segsize; i++) {
-    buf->empty_seg[i] = buf->spec.silence_sample[j];
-    j = (j + 1) % bps;
+  if (buf->spec.type == GST_BUFTYPE_RAW) {
+    gst_audio_format_fill_silence (buf->spec.info.finfo, buf->empty_seg,
+        segsize);
+  } else {
+    /* FIXME, non-raw formats get 0 as the empty sample */
+    memset (buf->empty_seg, 0, segsize);
   }
   GST_DEBUG_OBJECT (buf, "acquired device");
 
@@ -867,10 +658,10 @@ acquire_failed:
     GST_DEBUG_OBJECT (buf, "failed to acquire device");
     goto done;
   }
-invalid_bps:
+invalid_bpf:
   {
     g_warning
-        ("invalid bytes_per_sample from acquire ringbuffer %p, fix the element",
+        ("invalid bytes_per_frame from acquire ringbuffer %p, fix the element",
         buf);
     buf->acquired = FALSE;
     res = FALSE;
@@ -1547,12 +1338,12 @@ no_start:
 #define FWD_SAMPLES(s,se,d,de)                 \
 G_STMT_START {                                 \
   /* no rate conversion */                     \
-  guint towrite = MIN (se + bps - s, de - d);  \
+  guint towrite = MIN (se + bpf - s, de - d);  \
   /* simple copy */                            \
   if (!skip)                                   \
     memcpy (d, s, towrite);                    \
-  in_samples -= towrite / bps;                 \
-  out_samples -= towrite / bps;                        \
+  in_samples -= towrite / bpf;                 \
+  out_samples -= towrite / bpf;                        \
   s += towrite;                                        \
   GST_DEBUG ("copy %u bytes", towrite);                \
 } G_STMT_END
@@ -1563,16 +1354,16 @@ G_STMT_START {                                  \
   guint8 *sb = s, *db = d;                     \
   while (s <= se && d < de) {                  \
     if (!skip)                                 \
-      memcpy (d, s, bps);                      \
-    s += bps;                                  \
+      memcpy (d, s, bpf);                      \
+    s += bpf;                                  \
     *accum += outr;                            \
     if ((*accum << 1) >= inr) {                        \
       *accum -= inr;                           \
-      d += bps;                                        \
+      d += bpf;                                        \
     }                                          \
   }                                            \
-  in_samples -= (s - sb)/bps;                  \
-  out_samples -= (d - db)/bps;                 \
+  in_samples -= (s - sb)/bpf;                  \
+  out_samples -= (d - db)/bpf;                 \
   GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess);    \
 } G_STMT_END
 
@@ -1582,16 +1373,16 @@ G_STMT_START {                                  \
   guint8 *sb = s, *db = d;                     \
   while (s <= se && d < de) {                  \
     if (!skip)                                 \
-      memcpy (d, s, bps);                      \
-    d += bps;                                  \
+      memcpy (d, s, bpf);                      \
+    d += bpf;                                  \
     *accum += inr;                             \
     if ((*accum << 1) >= outr) {               \
       *accum -= outr;                          \
-      s += bps;                                        \
+      s += bpf;                                        \
     }                                          \
   }                                            \
-  in_samples -= (s - sb)/bps;                  \
-  out_samples -= (d - db)/bps;                 \
+  in_samples -= (s - sb)/bpf;                  \
+  out_samples -= (d - db)/bpf;                 \
   GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess);  \
 } G_STMT_END
 
@@ -1600,16 +1391,16 @@ G_STMT_START {                                  \
   guint8 *sb = se, *db = d;                    \
   while (s <= se && d < de) {                  \
     if (!skip)                                 \
-      memcpy (d, se, bps);                     \
-    se -= bps;                                 \
+      memcpy (d, se, bpf);                     \
+    se -= bpf;                                 \
     *accum += outr;                            \
     while (d < de && (*accum << 1) >= inr) {   \
       *accum -= inr;                           \
-      d += bps;                                        \
+      d += bpf;                                        \
     }                                          \
   }                                            \
-  in_samples -= (sb - se)/bps;                 \
-  out_samples -= (d - db)/bps;                 \
+  in_samples -= (sb - se)/bpf;                 \
+  out_samples -= (d - db)/bpf;                 \
   GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess);    \
 } G_STMT_END
 
@@ -1618,16 +1409,16 @@ G_STMT_START {                                  \
   guint8 *sb = se, *db = d;                    \
   while (s <= se && d < de) {                  \
     if (!skip)                                 \
-      memcpy (d, se, bps);                     \
-    d += bps;                                  \
+      memcpy (d, se, bpf);                     \
+    d += bpf;                                  \
     *accum += inr;                             \
     while (s <= se && (*accum << 1) >= outr) { \
       *accum -= outr;                          \
-      se -= bps;                               \
+      se -= bpf;                               \
     }                                          \
   }                                            \
-  in_samples -= (sb - se)/bps;                 \
-  out_samples -= (d - db)/bps;                 \
+  in_samples -= (sb - se)/bpf;                 \
+  out_samples -= (d - db)/bpf;                 \
   GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess);  \
 } G_STMT_END
 
@@ -1636,7 +1427,7 @@ default_commit (GstRingBuffer * buf, guint64 * sample,
     guchar * data, gint in_samples, gint out_samples, gint * accum)
 {
   gint segdone;
-  gint segsize, segtotal, bps, sps;
+  gint segsize, segtotal, bpf, sps;
   guint8 *dest, *data_end;
   gint writeseg, sampleoff;
   gint *toprocess;
@@ -1649,7 +1440,7 @@ default_commit (GstRingBuffer * buf, guint64 * sample,
   dest = buf->memory;
   segsize = buf->spec.segsize;
   segtotal = buf->spec.segtotal;
-  bps = buf->spec.bytes_per_sample;
+  bpf = buf->spec.info.bpf;
   sps = buf->samples_per_seg;
 
   reverse = out_samples < 0;
@@ -1665,12 +1456,12 @@ default_commit (GstRingBuffer * buf, guint64 * sample,
 
   /* data_end points to the last sample we have to write, not past it. This is
    * needed to properly handle reverse playback: it points to the last sample. */
-  data_end = data + (bps * inr);
+  data_end = data + (bpf * inr);
 
   /* figure out the segment and the offset inside the segment where
    * the first sample should be written. */
   writeseg = *sample / sps;
-  sampleoff = (*sample % sps) * bps;
+  sampleoff = (*sample % sps) * bpf;
 
   /* write out all samples */
   while (*toprocess > 0) {
@@ -1714,11 +1505,11 @@ default_commit (GstRingBuffer * buf, guint64 * sample,
 
     /* we can write now */
     ws = writeseg % segtotal;
-    avail = MIN (segsize - sampleoff, bps * out_samples);
+    avail = MIN (segsize - sampleoff, bpf * out_samples);
 
     d = dest + (ws * segsize) + sampleoff;
     d_end = d + avail;
-    *sample += avail / bps;
+    *sample += avail / bpf;
 
     GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d",
         dest + ws * segsize, ws, sps, sampleoff, avail);
@@ -1747,10 +1538,10 @@ default_commit (GstRingBuffer * buf, guint64 * sample,
     sampleoff = 0;
   }
   /* we consumed all samples here */
-  data = data_end + bps;
+  data = data_end + bpf;
 
 done:
-  return inr - ((data_end - data) / bps);
+  return inr - ((data_end - data) / bpf);
 
   /* ERRORS */
 not_started:
@@ -1867,7 +1658,7 @@ gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
     guint len)
 {
   gint segdone;
-  gint segsize, segtotal, bps, sps;
+  gint segsize, segtotal, bpf, sps;
   guint8 *dest;
   guint to_read;
 
@@ -1878,7 +1669,7 @@ gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
   dest = buf->memory;
   segsize = buf->spec.segsize;
   segtotal = buf->spec.segtotal;
-  bps = buf->spec.bytes_per_sample;
+  bpf = buf->spec.info.bpf;
   sps = buf->samples_per_seg;
 
   to_read = len;
@@ -1913,7 +1704,7 @@ gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
       if (G_UNLIKELY (diff >= segtotal)) {
         /* pretend we read an empty segment. */
         sampleslen = MIN (sps, to_read);
-        memcpy (data, buf->empty_seg, sampleslen * bps);
+        memcpy (data, buf->empty_seg, sampleslen * bpf);
         goto next;
       }
 
@@ -1934,13 +1725,13 @@ gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
     GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d",
         dest + readseg * segsize, readseg, sampleoff, sampleslen);
 
-    memcpy (data, dest + (readseg * segsize) + (sampleoff * bps),
-        (sampleslen * bps));
+    memcpy (data, dest + (readseg * segsize) + (sampleoff * bpf),
+        (sampleslen * bpf));
 
   next:
     to_read -= sampleslen;
     sample += sampleslen;
-    data += sampleslen * bps;
+    data += sampleslen * bpf;
   }
 
   return len - to_read;
index 99a6966..76e61c3 100644 (file)
@@ -24,6 +24,7 @@
 #define __GST_RING_BUFFER_H__
 
 #include <gst/gst.h>
+#include <gst/audio/audio.h>
 
 G_BEGIN_DECLS
 
@@ -83,8 +84,7 @@ typedef enum {
 
 /**
  * GstBufferFormatType:
- * @GST_BUFTYPE_LINEAR: samples in linear PCM
- * @GST_BUFTYPE_FLOAT: samples in float
+ * @GST_BUFTYPE_RAW: samples in linear or float
  * @GST_BUFTYPE_MU_LAW: samples in mulaw
  * @GST_BUFTYPE_A_LAW: samples in alaw
  * @GST_BUFTYPE_IMA_ADPCM: samples in ima adpcm
@@ -101,8 +101,7 @@ typedef enum {
  */
 typedef enum
 {
-  GST_BUFTYPE_LINEAR,
-  GST_BUFTYPE_FLOAT,
+  GST_BUFTYPE_RAW,
   GST_BUFTYPE_MU_LAW,
   GST_BUFTYPE_A_LAW,
   GST_BUFTYPE_IMA_ADPCM,
@@ -117,107 +116,6 @@ typedef enum
 } GstBufferFormatType;
 
 /**
- * GstBufferFormat:
- * @GST_UNKNOWN: unspecified
- * @GST_S8: integer signed 8 bit
- * @GST_U8: integer unsigned 8 bit
- * @GST_S16_LE: integer signed 16 bit little endian
- * @GST_S16_BE: integer signed 16 bit big endian
- * @GST_U16_LE: integer unsigned 16 bit little endian
- * @GST_U16_BE: integer unsigned 16 bit big endian
- * @GST_S24_LE: integer signed 24 bit little endian
- * @GST_S24_BE: integer signed 24 bit big endian
- * @GST_U24_LE: integer unsigned 24 bit little endian
- * @GST_U24_BE: integer unsigned 24 bit big endian
- * @GST_S32_LE: integer signed 32 bit little endian
- * @GST_S32_BE: integer signed 32 bit big endian
- * @GST_U32_LE: integer unsigned 32 bit little endian
- * @GST_U32_BE: integer unsigned 32 bit big endian
- * @GST_S24_3LE: integer signed 24 bit little endian packed in 3 bytes
- * @GST_S24_3BE: integer signed 24 bit big endian packed in 3 bytes
- * @GST_U24_3LE: integer unsigned 24 bit little endian packed in 3 bytes
- * @GST_U24_3BE: integer unsigned 24 bit big endian packed in 3 bytes
- * @GST_S20_3LE: integer signed 20 bit little endian packed in 3 bytes
- * @GST_S20_3BE: integer signed 20 bit big endian packed in 3 bytes
- * @GST_U20_3LE: integer unsigned 20 bit little endian packed in 3 bytes
- * @GST_U20_3BE: integer unsigned 20 bit big endian packed in 3 bytes
- * @GST_S18_3LE: integer signed 18 bit little endian packed in 3 bytes
- * @GST_S18_3BE: integer signed 18 bit big endian packed in 3 bytes
- * @GST_U18_3LE: integer unsigned 18 bit little endian packed in 3 bytes
- * @GST_U18_3BE: integer unsigned 18 bit big endian packed in 3 bytes
- * @GST_FLOAT32_LE: floating 32 bit little endian
- * @GST_FLOAT32_BE: floating 32 bit big endian
- * @GST_FLOAT64_LE: floating 64 bit little endian
- * @GST_FLOAT64_BE: floating 64 bit big endian
- * @GST_MU_LAW: mu-law
- * @GST_A_LAW: a-law
- * @GST_IMA_ADPCM: ima adpcm
- * @GST_MPEG: mpeg audio (but not aac)
- * @GST_GSM: gsm
- * @GST_IEC958: IEC958 frames
- * @GST_AC3: ac3
- * @GST_EAC3: eac3
- * @GST_DTS: dts
- * @GST_MPEG2_AAC: mpeg-2 aac
- * @GST_MPEG4_AAC: mpeg-4 aac
- *
- * The detailed format of the samples in the ringbuffer.
- */
-typedef enum
-{
-  GST_UNKNOWN,
-
-  GST_S8,
-  GST_U8,
-
-  GST_S16_LE,
-  GST_S16_BE,
-  GST_U16_LE,
-  GST_U16_BE,
-
-  GST_S24_LE,
-  GST_S24_BE,
-  GST_U24_LE,
-  GST_U24_BE,
-
-  GST_S32_LE,
-  GST_S32_BE,
-  GST_U32_LE,
-  GST_U32_BE,
-
-  GST_S24_3LE,
-  GST_S24_3BE,
-  GST_U24_3LE,
-  GST_U24_3BE,
-  GST_S20_3LE,
-  GST_S20_3BE,
-  GST_U20_3LE,
-  GST_U20_3BE,
-  GST_S18_3LE,
-  GST_S18_3BE,
-  GST_U18_3LE,
-  GST_U18_3BE,
-
-  GST_FLOAT32_LE,
-  GST_FLOAT32_BE,
-
-  GST_FLOAT64_LE,
-  GST_FLOAT64_BE,
-
-  GST_MU_LAW,
-  GST_A_LAW,
-  GST_IMA_ADPCM,
-  GST_MPEG,
-  GST_GSM,
-  GST_IEC958,
-  GST_AC3,
-  GST_EAC3,
-  GST_DTS,
-  GST_MPEG2_AAC,
-  GST_MPEG4_AAC,
-} GstBufferFormat;
-
-/**
  * GstRingBufferSpec:
  * @caps: The caps that generated the Spec.
  * @type: the sample type
@@ -246,14 +144,8 @@ struct _GstRingBufferSpec
   GstCaps  *caps;               /* the caps of the buffer */
 
   /* in/out */
-  GstBufferFormatType   type;
-  GstBufferFormat format;
-  gboolean  sign;
-  gboolean  bigend;
-  gint      width;
-  gint      depth;
-  gint      rate;
-  gint      channels;
+  GstBufferFormatType type;
+  GstAudioInfo        info;
 
   guint64  latency_time;        /* the required/actual latency time, this is the
                                 * actual the size of one segment and the
@@ -268,10 +160,6 @@ struct _GstRingBufferSpec
                                 * number of segments of @segsize and should be
                                 * chosen so that it matches buffer_time as
                                 * close as possible. */
-  /* out */
-  gint     bytes_per_sample;    /* number of bytes of one sample */
-  guint8   silence_sample[32];  /* bytes representing silence */
-
   /* ABI added 0.10.20 */
   gint     seglatency;          /* number of segments queued in the lower
                                 * level device, defaults to segtotal. */
index bd26f1c..388adcd 100644 (file)
@@ -231,13 +231,9 @@ GstAudioChannelPosition *
 gst_audio_get_channel_positions (GstStructure * str)
 {
   GstAudioChannelPosition *pos;
-
   gint channels, n;
-
   const GValue *pos_val_arr, *pos_val_entry;
-
   gboolean res;
-
   GType t;
 
   /* get number of channels, general type checkups */
index 3a3efe3..6f28d37 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef __GST_AUDIO_MULTICHANNEL_H__
 #define __GST_AUDIO_MULTICHANNEL_H__
 
-#include <gst/audio/audio.h>
+#include <gst/gst.h>
 #include <gst/audio/audio-enumtypes.h>
 
 G_BEGIN_DECLS
index a1ce234..59a32ab 100644 (file)
@@ -1,6 +1,5 @@
 /* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -196,7 +195,7 @@ typedef void (*GstVideoFormatUnpack)         (GstVideoFormatInfo *info, gpointer
  *
  * Packs @width pixels from @src to the given planes and strides in the
  * format @info. The pixels from source have each component interleaved
- * and will be packed into @src.
+ * and will be packed into the planes in @data.
  */
 typedef void (*GstVideoFormatPack)           (GstVideoFormatInfo *info, const gpointer src,
                                               gpointer data[GST_VIDEO_MAX_PLANES],
@@ -529,7 +528,7 @@ gboolean    gst_video_frame_copy          (GstVideoFrame *dest, const GstVideoFr
  */
 #define GST_VIDEO_BUFFER_PROGRESSIVE GST_BUFFER_FLAG_MEDIA4
 
-/* functions */
+/* some helper functions */
 gboolean       gst_video_calculate_display_ratio (guint * dar_n,
                                                   guint * dar_d,
                                                   guint   video_width,
index bf6465c..4cf7f74 100644 (file)
@@ -75,32 +75,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 /* elementfactory information */
 
 #define CAPS \
-  "audio/x-raw-int, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) [ 1, MAX ], " \
-  "endianness = (int) BYTE_ORDER, " \
-  "width = (int) 32, " \
-  "depth = (int) 32, " \
-  "signed = (boolean) { true, false } ;" \
-  "audio/x-raw-int, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) [ 1, MAX ], " \
-  "endianness = (int) BYTE_ORDER, " \
-  "width = (int) 16, " \
-  "depth = (int) 16, " \
-  "signed = (boolean) { true, false } ;" \
-  "audio/x-raw-int, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) [ 1, MAX ], " \
-  "endianness = (int) BYTE_ORDER, " \
-  "width = (int) 8, " \
-  "depth = (int) 8, " \
-  "signed = (boolean) { true, false } ;" \
-  "audio/x-raw-float, " \
-  "rate = (int) [ 1, MAX ], " \
-  "channels = (int) [ 1, MAX ], " \
-  "endianness = (int) BYTE_ORDER, " \
-  "width = (int) { 32, 64 }"
+  GST_AUDIO_CAPS_MAKE ("{ S32, U32, S16, U16, S8, U8, F32, F64 }")
 
 static GstStaticPadTemplate gst_adder_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
index 524098c..65d1309 100644 (file)
@@ -556,24 +556,27 @@ static AudioConvertPack pack_funcs[] = {
   (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be_float),
 };
 
-#define DOUBLE_INTERMEDIATE_FORMAT(ctx)                                 \
-    ((!ctx->in.is_int && !ctx->out.is_int) || (ctx->ns != NOISE_SHAPING_NONE))
+#define DOUBLE_INTERMEDIATE_FORMAT(ctx)                   \
+    ((!GST_AUDIO_FORMAT_INFO_IS_INT (ctx->in.finfo) &&    \
+      !GST_AUDIO_FORMAT_INFO_IS_INT (ctx->out.finfo)) ||  \
+     (ctx->ns != NOISE_SHAPING_NONE))
 
 static gint
-audio_convert_get_func_index (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
+audio_convert_get_func_index (AudioConvertCtx * ctx,
+    const GstAudioFormatInfo * fmt)
 {
   gint index = 0;
 
-  if (fmt->is_int) {
-    index += (fmt->width / 8 - 1) * 4;
-    index += fmt->endianness == G_LITTLE_ENDIAN ? 0 : 2;
-    index += fmt->sign ? 1 : 0;
+  if (GST_AUDIO_FORMAT_INFO_IS_INT (fmt)) {
+    index += (GST_AUDIO_FORMAT_INFO_WIDTH (fmt) / 8 - 1) * 4;
+    index += GST_AUDIO_FORMAT_INFO_IS_LE (fmt) ? 0 : 2;
+    index += GST_AUDIO_FORMAT_INFO_IS_SIGNED (fmt) ? 1 : 0;
     index += (ctx->ns == NOISE_SHAPING_NONE) ? 0 : 24;
   } else {
     /* this is float/double */
     index = 16;
-    index += (fmt->width == 32) ? 0 : 2;
-    index += (fmt->endianness == G_LITTLE_ENDIAN) ? 0 : 1;
+    index += (GST_AUDIO_FORMAT_INFO_WIDTH (fmt) == 32) ? 0 : 2;
+    index += GST_AUDIO_FORMAT_INFO_IS_LE (fmt) ? 0 : 1;
     index += (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? 4 : 0;
   }
 
@@ -581,34 +584,22 @@ audio_convert_get_func_index (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
 }
 
 static inline gboolean
-check_default (AudioConvertCtx * ctx, AudioConvertFmt * fmt)
+check_default (AudioConvertCtx * ctx, const GstAudioFormatInfo * fmt)
 {
   if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) {
-    return (fmt->width == 32 && fmt->depth == 32 &&
-        fmt->endianness == G_BYTE_ORDER && fmt->sign == TRUE);
+    return GST_AUDIO_FORMAT_INFO_FORMAT (fmt) == GST_AUDIO_FORMAT_S32;
   } else {
-    return (fmt->width == 64 && fmt->endianness == G_BYTE_ORDER);
+    return GST_AUDIO_FORMAT_INFO_FORMAT (fmt) == GST_AUDIO_FORMAT_F64;
   }
 }
 
 gboolean
-audio_convert_clean_fmt (AudioConvertFmt * fmt)
-{
-  g_return_val_if_fail (fmt != NULL, FALSE);
-
-  g_free (fmt->pos);
-  fmt->pos = NULL;
-
-  return TRUE;
-}
-
-
-gboolean
-audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
-    AudioConvertFmt * out, GstAudioConvertDithering dither,
+audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in,
+    GstAudioInfo * out, GstAudioConvertDithering dither,
     GstAudioConvertNoiseShaping ns)
 {
   gint idx_in, idx_out;
+  gint in_depth, out_depth;
 
   g_return_val_if_fail (ctx != NULL, FALSE);
   g_return_val_if_fail (in != NULL, FALSE);
@@ -617,18 +608,21 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
   /* first clean the existing context */
   audio_convert_clean_context (ctx);
 
-  g_return_val_if_fail (in->unpositioned_layout == out->unpositioned_layout,
-      FALSE);
+  g_return_val_if_fail (GST_AUDIO_INFO_IS_UNPOSITIONED (in) ==
+      GST_AUDIO_INFO_IS_UNPOSITIONED (out), FALSE);
 
   ctx->in = *in;
   ctx->out = *out;
 
+  in_depth = GST_AUDIO_FORMAT_INFO_DEPTH (in->finfo);
+  out_depth = GST_AUDIO_FORMAT_INFO_DEPTH (out->finfo);
+
   /* Don't dither or apply noise shaping if target depth is bigger than 20 bits
    * as DA converters only can do a SNR up to 20 bits in reality.
    * Also don't dither or apply noise shaping if target depth is larger than
    * source depth. */
-  if (ctx->out.depth <= 20 && (!ctx->in.is_int
-          || ctx->in.depth >= ctx->out.depth)) {
+  if (out_depth <= 20 && (!GST_AUDIO_FORMAT_INFO_IS_INT (in->finfo)
+          || in_depth >= out_depth)) {
     ctx->dither = dither;
     ctx->ns = ns;
   } else {
@@ -638,15 +632,15 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
 
   /* Use simple error feedback when output sample rate is smaller than
    * 32000 as the other methods might move the noise to audible ranges */
-  if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && ctx->out.rate < 32000)
+  if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
     ctx->ns = NOISE_SHAPING_ERROR_FEEDBACK;
 
   gst_channel_mix_setup_matrix (ctx);
 
-  idx_in = audio_convert_get_func_index (ctx, in);
+  idx_in = audio_convert_get_func_index (ctx, in->finfo);
   ctx->unpack = unpack_funcs[idx_in];
 
-  idx_out = audio_convert_get_func_index (ctx, out);
+  idx_out = audio_convert_get_func_index (ctx, out->finfo);
   ctx->pack = pack_funcs[idx_out];
 
   /* if both formats are float/double or we use noise shaping use double as
@@ -658,20 +652,22 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in,
     GST_INFO ("use float mixing");
     ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float;
   }
-  GST_INFO ("unitsizes: %d -> %d", in->unit_size, out->unit_size);
+  GST_INFO ("unitsizes: %d -> %d", in->bpf, out->bpf);
 
   /* check if input is in default format */
-  ctx->in_default = check_default (ctx, in);
+  ctx->in_default = check_default (ctx, in->finfo);
   /* check if channel mixer is passthrough */
   ctx->mix_passthrough = gst_channel_mix_passthrough (ctx);
   /* check if output is in default format */
-  ctx->out_default = check_default (ctx, out);
+  ctx->out_default = check_default (ctx, out->finfo);
 
   GST_INFO ("in default %d, mix passthrough %d, out default %d",
       ctx->in_default, ctx->mix_passthrough, ctx->out_default);
 
-  ctx->in_scale = (in->is_int) ? (32 - in->depth) : 0;
-  ctx->out_scale = (out->is_int) ? (32 - out->depth) : 0;
+  ctx->in_scale =
+      GST_AUDIO_FORMAT_INFO_IS_INT (in->finfo) ? (32 - in_depth) : 0;
+  ctx->out_scale =
+      GST_AUDIO_FORMAT_INFO_IS_INT (out->finfo) ? (32 - out_depth) : 0;
 
   gst_audio_quantize_setup (ctx);
 
@@ -684,8 +680,8 @@ audio_convert_clean_context (AudioConvertCtx * ctx)
   g_return_val_if_fail (ctx != NULL, FALSE);
 
   gst_audio_quantize_free (ctx);
-  audio_convert_clean_fmt (&ctx->in);
-  audio_convert_clean_fmt (&ctx->out);
+  gst_audio_info_init (&ctx->in);
+  gst_audio_info_init (&ctx->out);
   gst_channel_mix_unset_matrix (ctx);
 
   g_free (ctx->tmpbuf);
@@ -702,9 +698,9 @@ audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples, gint * srcsize,
   g_return_val_if_fail (ctx != NULL, FALSE);
 
   if (srcsize)
-    *srcsize = samples * ctx->in.unit_size;
+    *srcsize = samples * ctx->in.bpf;
   if (dstsize)
-    *dstsize = samples * ctx->out.unit_size;
+    *dstsize = samples * ctx->out.bpf;
 
   return TRUE;
 }
@@ -716,6 +712,7 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
   guint insize, outsize, size;
   gpointer outbuf, tmpbuf;
   guint intemp = 0, outtemp = 0, biggest;
+  gint in_width, out_width;
 
   g_return_val_if_fail (ctx != NULL, FALSE);
   g_return_val_if_fail (src != NULL, FALSE);
@@ -725,23 +722,26 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
   if (samples == 0)
     return TRUE;
 
-  insize = ctx->in.unit_size * samples;
-  outsize = ctx->out.unit_size * samples;
+  insize = ctx->in.bpf * samples;
+  outsize = ctx->out.bpf * samples;
+
+  in_width = GST_AUDIO_FORMAT_INFO_WIDTH (ctx->in.finfo);
+  out_width = GST_AUDIO_FORMAT_INFO_WIDTH (ctx->out.finfo);
 
   /* find biggest temp buffer size */
   size = (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? sizeof (gdouble)
       : sizeof (gint32);
 
   if (!ctx->in_default)
-    intemp = gst_util_uint64_scale (insize, size * 8, ctx->in.width);
+    intemp = gst_util_uint64_scale (insize, size * 8, in_width);
   if (!ctx->mix_passthrough || !ctx->out_default)
-    outtemp = gst_util_uint64_scale (outsize, size * 8, ctx->out.width);
+    outtemp = gst_util_uint64_scale (outsize, size * 8, out_width);
   biggest = MAX (intemp, outtemp);
 
   /* see if one of the buffers can be used as temp */
-  if ((outsize >= biggest) && (ctx->out.unit_size <= size))
+  if ((outsize >= biggest) && (ctx->out.bpf <= size))
     tmpbuf = dst;
-  else if ((insize >= biggest) && src_writable && (ctx->in.unit_size >= size))
+  else if ((insize >= biggest) && src_writable && (ctx->in.bpf >= size))
     tmpbuf = src;
   else {
     if (biggest > ctx->tmpbufsize) {
@@ -779,7 +779,7 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src,
   }
 
   /* we only need to quantize if output format is int */
-  if (ctx->out.is_int) {
+  if (GST_AUDIO_FORMAT_INFO_IS_INT (ctx->out.finfo)) {
     if (ctx->out_default)
       outbuf = dst;
     else
index ccc4014..638a42a 100644 (file)
@@ -23,7 +23,7 @@
 #define __AUDIO_CONVERT_H__
 
 #include <gst/gst.h>
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
 
 GST_DEBUG_CATEGORY_EXTERN (audio_convert_debug);
 #define GST_CAT_DEFAULT (audio_convert_debug)
@@ -65,6 +65,7 @@ typedef enum
 } GstAudioConvertNoiseShaping;
 
 typedef struct _AudioConvertCtx AudioConvertCtx;
+#if 0
 typedef struct _AudioConvertFmt AudioConvertFmt;
 
 struct _AudioConvertFmt
@@ -84,6 +85,7 @@ struct _AudioConvertFmt
 
   gint unit_size;
 };
+#endif
 
 typedef void (*AudioConvertUnpack) (gpointer src, gpointer dst, gint scale,
     gint count);
@@ -96,8 +98,8 @@ typedef void (*AudioConvertQuantize) (AudioConvertCtx * ctx, gpointer src,
 
 struct _AudioConvertCtx
 {
-  AudioConvertFmt in;
-  AudioConvertFmt out;
+  GstAudioInfo in;
+  GstAudioInfo out;
 
   AudioConvertUnpack unpack;
   AudioConvertPack pack;
@@ -130,10 +132,8 @@ struct _AudioConvertCtx
   gdouble *error_buf;
 };
 
-gboolean audio_convert_clean_fmt (AudioConvertFmt * fmt);
-
 gboolean audio_convert_prepare_context (AudioConvertCtx * ctx,
-    AudioConvertFmt * in, AudioConvertFmt * out,
+    GstAudioInfo * in, GstAudioInfo * out,
     GstAudioConvertDithering dither, GstAudioConvertNoiseShaping ns);
 gboolean audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples,
     gint * srcsize, gint * dstsize);
index 1562088..6cf8775 100644 (file)
@@ -1,7 +1,7 @@
 /* GStreamer
  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
  * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2005 Wim Taymans <wim at fluendo dot com>
+ * Copyright (C) 2011 Wim Taymans <wim.taymans at gmail dot com>
  *
  * gstaudioconvert.c: Convert audio to different audio formats automatically
  *
@@ -31,7 +31,7 @@
  * <refsect2>
  * <title>Example launch line</title>
  * |[
- * gst-launch -v -m audiotestsrc ! audioconvert ! audio/x-raw-int,channels=2,width=8,depth=8 ! level ! fakesink silent=TRUE
+ * gst-launch -v -m audiotestsrc ! audioconvert ! audio/x-raw,format=S8,channels=2 ! level ! fakesink silent=TRUE
  * ]| This pipeline converts audio to 8-bit.  The level element shows that
  * the output levels still match the one for a sine wave.
  * |[
@@ -91,8 +91,6 @@ static void gst_audio_convert_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_audio_convert_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static gboolean structure_has_fixed_channel_positions (GstStructure * s,
-    gboolean * unpositioned_layout);
 
 /* AudioConvert signals and args */
 enum
@@ -118,45 +116,7 @@ G_DEFINE_TYPE_WITH_CODE (GstAudioConvert, gst_audio_convert,
 /*** GSTREAMER PROTOTYPES *****************************************************/
 
 #define STATIC_CAPS \
-GST_STATIC_CAPS ( \
-  "audio/x-raw-float, " \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], " \
-    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
-    "width = (int) 64;" \
-  "audio/x-raw-float, " \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], " \
-    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
-    "width = (int) 32;" \
-  "audio/x-raw-int, " \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], " \
-    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
-    "width = (int) 32, " \
-    "depth = (int) [ 1, 32 ], " \
-    "signed = (boolean) { true, false }; " \
-  "audio/x-raw-int, "   \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], "       \
-    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "        \
-    "width = (int) 24, "        \
-    "depth = (int) [ 1, 24 ], " "signed = (boolean) { true, false }; "  \
-  "audio/x-raw-int, " \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], " \
-    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
-    "width = (int) 16, " \
-    "depth = (int) [ 1, 16 ], " \
-    "signed = (boolean) { true, false }; " \
-  "audio/x-raw-int, " \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], " \
-    "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
-    "width = (int) 8, " \
-    "depth = (int) [ 1, 8 ], " \
-    "signed = (boolean) { true, false } " \
-)
+GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL))
 
 static GstStaticPadTemplate gst_audio_convert_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
@@ -284,90 +244,20 @@ gst_audio_convert_dispose (GObject * obj)
 
 /*** GSTREAMER FUNCTIONS ******************************************************/
 
-/* convert the given GstCaps to our format */
-static gboolean
-gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt)
-{
-  GstStructure *structure = gst_caps_get_structure (caps, 0);
-
-  GST_DEBUG ("parse caps %p and %" GST_PTR_FORMAT, caps, caps);
-
-  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
-  g_return_val_if_fail (fmt != NULL, FALSE);
-
-  /* cleanup old */
-  audio_convert_clean_fmt (fmt);
-
-  fmt->endianness = G_BYTE_ORDER;
-  fmt->is_int =
-      (strcmp (gst_structure_get_name (structure), "audio/x-raw-int") == 0);
-
-  /* parse common fields */
-  if (!gst_structure_get_int (structure, "channels", &fmt->channels))
-    goto no_values;
-  if (!(fmt->pos = gst_audio_get_channel_positions (structure)))
-    goto no_values;
-
-  fmt->unpositioned_layout = FALSE;
-  structure_has_fixed_channel_positions (structure, &fmt->unpositioned_layout);
-
-  if (!gst_structure_get_int (structure, "width", &fmt->width))
-    goto no_values;
-  if (!gst_structure_get_int (structure, "rate", &fmt->rate))
-    goto no_values;
-  /* width != 8 needs an endianness field */
-  if (fmt->width != 8) {
-    if (!gst_structure_get_int (structure, "endianness", &fmt->endianness))
-      goto no_values;
-  }
-
-  if (fmt->is_int) {
-    /* int specific fields */
-    if (!gst_structure_get_boolean (structure, "signed", &fmt->sign))
-      goto no_values;
-    if (!gst_structure_get_int (structure, "depth", &fmt->depth))
-      goto no_values;
-
-    /* depth cannot be bigger than the width */
-    if (fmt->depth > fmt->width)
-      goto not_allowed;
-  }
-
-  fmt->unit_size = (fmt->width * fmt->channels) / 8;
-
-  return TRUE;
-
-  /* ERRORS */
-no_values:
-  {
-    GST_DEBUG ("could not get some values from structure");
-    audio_convert_clean_fmt (fmt);
-    return FALSE;
-  }
-not_allowed:
-  {
-    GST_DEBUG ("width > depth, not allowed - make us advertise correct fmt");
-    audio_convert_clean_fmt (fmt);
-    return FALSE;
-  }
-}
-
 /* BaseTransform vmethods */
 static gboolean
 gst_audio_convert_get_unit_size (GstBaseTransform * base, GstCaps * caps,
     gsize * size)
 {
-  AudioConvertFmt fmt = { 0 };
+  GstAudioInfo info;
 
   g_assert (size);
 
-  if (!gst_audio_convert_parse_caps (caps, &fmt))
+  if (!gst_audio_info_from_caps (&info, caps))
     goto parse_error;
 
-  GST_INFO_OBJECT (base, "unit_size = %u", fmt.unit_size);
-  *size = fmt.unit_size;
-
-  audio_convert_clean_fmt (&fmt);
+  *size = info.bpf;
+  GST_INFO_OBJECT (base, "unit_size = %" G_GSIZE_FORMAT, *size);
 
   return TRUE;
 
@@ -378,351 +268,61 @@ parse_error:
   }
 }
 
-/* Set widths (a list); multiples of 8 between min and max */
-static void
-set_structure_widths (GstStructure * s, int min, int max)
-{
-  GValue list = { 0 };
-  GValue val = { 0 };
-  int width;
-
-  if (min == max) {
-    gst_structure_set (s, "width", G_TYPE_INT, min, NULL);
-    return;
-  }
-
-  g_value_init (&list, GST_TYPE_LIST);
-  g_value_init (&val, G_TYPE_INT);
-  for (width = min; width <= max; width += 8) {
-    g_value_set_int (&val, width);
-    gst_value_list_append_value (&list, &val);
-  }
-  gst_structure_set_value (s, "width", &list);
-  g_value_unset (&val);
-  g_value_unset (&list);
-}
-
-/* Set widths of 32 bits and 64 bits (as list) */
-static void
-set_structure_widths_32_and_64 (GstStructure * s)
-{
-  GValue list = { 0 };
-  GValue val = { 0 };
-
-  g_value_init (&list, GST_TYPE_LIST);
-  g_value_init (&val, G_TYPE_INT);
-  g_value_set_int (&val, 32);
-  gst_value_list_append_value (&list, &val);
-  g_value_set_int (&val, 64);
-  gst_value_list_append_value (&list, &val);
-  gst_structure_set_value (s, "width", &list);
-  g_value_unset (&val);
-  g_value_unset (&list);
-}
-
-/* Modify the structure so that things that must always have a single
- * value (for float), or can always be losslessly converted (for int), have
- * appropriate values.
- */
-static GstStructure *
-make_lossless_changes (GstStructure * s, gboolean isfloat)
-{
-  GValue list = { 0 };
-  GValue val = { 0 };
-  int i;
-  const gint endian[] = { G_LITTLE_ENDIAN, G_BIG_ENDIAN };
-  const gboolean booleans[] = { TRUE, FALSE };
-
-  g_value_init (&list, GST_TYPE_LIST);
-  g_value_init (&val, G_TYPE_INT);
-  for (i = 0; i < 2; i++) {
-    g_value_set_int (&val, endian[i]);
-    gst_value_list_append_value (&list, &val);
-  }
-  gst_structure_set_value (s, "endianness", &list);
-  g_value_unset (&val);
-  g_value_unset (&list);
-
-  if (isfloat) {
-    /* float doesn't have a depth or signedness field and only supports
-     * widths of 32 and 64 bits */
-    gst_structure_remove_field (s, "depth");
-    gst_structure_remove_field (s, "signed");
-    set_structure_widths_32_and_64 (s);
-  } else {
-    /* int supports signed and unsigned. GValues are a pain */
-    g_value_init (&list, GST_TYPE_LIST);
-    g_value_init (&val, G_TYPE_BOOLEAN);
-    for (i = 0; i < 2; i++) {
-      g_value_set_boolean (&val, booleans[i]);
-      gst_value_list_append_value (&list, &val);
-    }
-    gst_structure_set_value (s, "signed", &list);
-    g_value_unset (&val);
-    g_value_unset (&list);
-  }
-
-  return s;
-}
-
-static void
-strip_width_64 (GstStructure * s)
+/* copies the given caps */
+static GstCaps *
+gst_audio_convert_caps_remove_format_info (GstCaps * caps)
 {
-  const GValue *v = gst_structure_get_value (s, "width");
-  GValue widths = { 0 };
-
-  if (GST_VALUE_HOLDS_LIST (v)) {
-    int i;
-    int len = gst_value_list_get_size (v);
+  GstStructure *st;
+  gint i, n;
+  GstCaps *res;
 
-    g_value_init (&widths, GST_TYPE_LIST);
+  res = gst_caps_new_empty ();
 
-    for (i = 0; i < len; i++) {
-      const GValue *width = gst_value_list_get_value (v, i);
-
-      if (g_value_get_int (width) != 64)
-        gst_value_list_append_value (&widths, width);
-    }
-    gst_structure_set_value (s, "width", &widths);
-    g_value_unset (&widths);
-  }
-}
-
-/* Little utility function to create a related structure for float/int */
-static void
-append_with_other_format (GstCaps * caps, const GstStructure * s,
-    gboolean isfloat)
-{
-  GstStructure *s2;
-
-  if (isfloat) {
-    s2 = gst_structure_copy (s);
-    gst_structure_set_name (s2, "audio/x-raw-int");
-    make_lossless_changes (s2, FALSE);
-    /* If 64 bit float was allowed; remove width 64: we don't support it for 
-     * integer*/
-    strip_width_64 (s2);
-    gst_caps_merge_structure (caps, s2);
-  } else {
-    s2 = gst_structure_copy (s);
-    gst_structure_set_name (s2, "audio/x-raw-float");
-    make_lossless_changes (s2, TRUE);
-    gst_caps_merge_structure (caps, s2);
-  }
-}
-
-static gboolean
-structure_has_fixed_channel_positions (GstStructure * s,
-    gboolean * unpositioned_layout)
-{
-  GstAudioChannelPosition *pos;
-  const GValue *val;
-  gint channels = 0;
+  n = gst_caps_get_size (caps);
+  for (i = 0; i < n; i++) {
+    st = gst_caps_get_structure (caps, i);
 
-  if (!gst_structure_get_int (s, "channels", &channels))
-    return FALSE;               /* probably a range */
+    /* If this is already expressed by the existing caps
+     * skip this structure */
+    if (i > 0 && gst_caps_is_subset_structure (res, st))
+      continue;
 
-  val = gst_structure_get_value (s, "channel-positions");
-  if ((val == NULL || !gst_value_is_fixed (val)) && channels <= 8) {
-    GST_LOG ("no or unfixed channel-positions in %" GST_PTR_FORMAT, s);
-    return FALSE;
-  } else if (val == NULL || !gst_value_is_fixed (val)) {
-    GST_LOG ("implicit undefined channel-positions");
-    *unpositioned_layout = TRUE;
-    return TRUE;
-  }
+    st = gst_structure_copy (st);
+    gst_structure_remove_fields (st, "format", "channel-positions", NULL);
 
-  pos = gst_audio_get_channel_positions (s);
-  if (pos && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
-    GST_LOG ("fixed undefined channel-positions in %" GST_PTR_FORMAT, s);
-    *unpositioned_layout = TRUE;
-  } else {
-    GST_LOG ("fixed defined channel-positions in %" GST_PTR_FORMAT, s);
-    *unpositioned_layout = FALSE;
+    gst_caps_append_structure (res, st);
   }
-  g_free (pos);
 
-  return TRUE;
+  return res;
 }
 
-/* Audioconvert can perform all conversions on audio except for resampling. 
- * However, there are some conversions we _prefer_ not to do. For example, it's
- * better to convert format (float<->int, endianness, etc) than the number of
- * channels, as the latter conversion is not lossless.
- *
- * So, we return, in order (assuming input caps have only one structure; 
- * which is enforced by basetransform):
- *  - input caps with a different format (lossless conversions).
- *  - input caps with a different format (slightly lossy conversions).
- *  - input caps with a different number of channels (very lossy!)
- */
+/* The caps can be transformed into any other caps with format info removed.
+ * However, we should prefer passthrough, so if passthrough is possible,
+ * put it first in the list. */
 static GstCaps *
-gst_audio_convert_transform_caps (GstBaseTransform * base,
+gst_audio_convert_transform_caps (GstBaseTransform * btrans,
     GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
-  GstCaps *ret;
-  GstStructure *s, *structure;
-  gboolean isfloat, allow_mixing;
-  gint width, depth, channels = 0;
-  const gchar *fields_used[] = {
-    "width", "depth", "rate", "channels", "endianness", "signed"
-  };
-  const gchar *structure_name;
-  gint n, j;
-  int i;
-
-  n = gst_caps_get_size (caps);
-
-  ret = gst_caps_new_empty ();
-
-  for (j = 0; j < n; j++) {
-    structure = gst_caps_get_structure (caps, j);
-
-    if (j > 0) {
-      /* If the new structure is a subset of the already existing transformed
-       * caps we can safely skip it because we would transform it to the
-       * same caps again.
-       */
-      if (gst_caps_is_subset_structure (ret, structure))
-        continue;
-    }
-
-    structure_name = gst_structure_get_name (structure);
-
-    isfloat = strcmp (structure_name, "audio/x-raw-float") == 0;
+  GstCaps *tmp, *tmp2;
+  GstCaps *result;
 
-    /* We operate on a version of the original structure with any additional
-     * fields absent */
-    s = gst_structure_empty_new (structure_name);
-    for (i = 0; i < sizeof (fields_used) / sizeof (*fields_used); i++) {
-      if (gst_structure_has_field (structure, fields_used[i]))
-        gst_structure_set_value (s, fields_used[i],
-            gst_structure_get_value (structure, fields_used[i]));
-    }
-
-    if (!isfloat) {
-      /* Commonly, depth is left out: set it equal to width if we have a fixed
-       * width, if so */
-      if (!gst_structure_has_field (s, "depth") &&
-          gst_structure_get_int (s, "width", &width))
-        gst_structure_set (s, "depth", G_TYPE_INT, width, NULL);
-    }
-
-    /* All lossless conversions */
-    s = make_lossless_changes (s, isfloat);
-    gst_caps_merge_structure (ret, gst_structure_copy (s));
-
-    /* Same, plus a float<->int conversion */
-    append_with_other_format (ret, s, isfloat);
-    GST_DEBUG_OBJECT (base, "  step1: (%d) %" GST_PTR_FORMAT,
-        gst_caps_get_size (ret), ret);
-
-    /* We don't mind increasing width/depth/channels, but reducing them is 
-     * Very Bad. Only available if width, depth, channels are already fixed. */
-    if (!isfloat) {
-      if (gst_structure_get_int (structure, "width", &width))
-        set_structure_widths (s, width, 32);
-      if (gst_structure_get_int (structure, "depth", &depth)) {
-        if (depth == 32)
-          gst_structure_set (s, "depth", G_TYPE_INT, 32, NULL);
-        else
-          gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, depth, 32, NULL);
-      }
-    }
-
-    allow_mixing = TRUE;
-    if (gst_structure_get_int (structure, "channels", &channels)) {
-      gboolean unpositioned;
-
-      /* we don't support mixing for channels without channel positions */
-      if (structure_has_fixed_channel_positions (structure, &unpositioned))
-        allow_mixing = (unpositioned == FALSE);
-    }
+  result = gst_caps_copy (caps);
 
-    if (!allow_mixing) {
-      gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
-      if (gst_structure_has_field (structure, "channel-positions"))
-        gst_structure_set_value (s, "channel-positions",
-            gst_structure_get_value (structure, "channel-positions"));
-    } else {
-      if (channels == 0)
-        gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 11, NULL);
-      else if (channels == 11)
-        gst_structure_set (s, "channels", G_TYPE_INT, 11, NULL);
-      else
-        gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 11,
-            NULL);
-      gst_structure_remove_field (s, "channel-positions");
-    }
-    gst_caps_merge_structure (ret, gst_structure_copy (s));
-
-    /* Same, plus a float<->int conversion */
-    append_with_other_format (ret, s, isfloat);
-
-    /* We'll reduce depth if we must. We reduce as low as 16 bits (for integer); 
-     * reducing to less than this is even worse than dropping channels. We only 
-     * do this if we haven't already done the equivalent above. */
-    if (!gst_structure_get_int (structure, "width", &width) || width > 16) {
-      if (isfloat) {
-        GstStructure *s2 = gst_structure_copy (s);
-
-        set_structure_widths_32_and_64 (s2);
-        append_with_other_format (ret, s2, TRUE);
-        gst_structure_free (s2);
-      } else {
-        GstStructure *s2 = gst_structure_copy (s);
-
-        set_structure_widths (s2, 16, 32);
-        gst_structure_set (s2, "depth", GST_TYPE_INT_RANGE, 16, 32, NULL);
-        gst_caps_merge_structure (ret, s2);
-      }
-    }
+  /* Get all possible caps that we can transform to */
+  tmp = gst_audio_convert_caps_remove_format_info (caps);
 
-    /* Channel conversions to fewer channels is only done if needed - generally
-     * it's very bad to drop channels entirely.
-     */
-    if (allow_mixing) {
-      gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 11, NULL);
-      gst_structure_remove_field (s, "channel-positions");
-    } else {
-      /* allow_mixing can only be FALSE if we got a fixed number of channels */
-      gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
-      if (gst_structure_has_field (structure, "channel-positions"))
-        gst_structure_set_value (s, "channel-positions",
-            gst_structure_get_value (structure, "channel-positions"));
-    }
-    gst_caps_merge_structure (ret, gst_structure_copy (s));
-
-    /* Same, plus a float<->int conversion */
-    append_with_other_format (ret, s, isfloat);
-
-    /* And, finally, for integer only, we allow conversion to any width/depth we
-     * support: this should be equivalent to our (non-float) template caps. (the
-     * floating point case should be being handled just above) */
-    set_structure_widths (s, 8, 32);
-    gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, 1, 32, NULL);
-
-    if (isfloat) {
-      append_with_other_format (ret, s, TRUE);
-      gst_structure_free (s);
-    } else
-      gst_caps_merge_structure (ret, s);
+  if (filter) {
+    tmp2 = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (tmp);
+    tmp = tmp2;
   }
 
-  GST_DEBUG_OBJECT (base, "Caps transformed to %" GST_PTR_FORMAT, ret);
+  result = tmp;
 
-  if (filter) {
-    GstCaps *intersection;
-
-    GST_DEBUG_OBJECT (base, "Using filter caps %" GST_PTR_FORMAT, filter);
-    intersection =
-        gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
-    gst_caps_unref (ret);
-    ret = intersection;
-    GST_DEBUG_OBJECT (base, "Intersection %" GST_PTR_FORMAT, ret);
-  }
+  GST_DEBUG_OBJECT (btrans, "transformed %" GST_PTR_FORMAT " into %"
+      GST_PTR_FORMAT, caps, result);
 
-  return ret;
+  return result;
 }
 
 static const GstAudioChannelPosition default_positions[8][8] = {
@@ -924,8 +524,8 @@ gst_audio_convert_fixate_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
 {
   GstStructure *ins, *outs;
-  gint rate, endianness, depth, width;
-  gboolean signedness;
+  gint rate;
+  const gchar *fmt;
 
   g_return_if_fail (gst_caps_is_fixed (caps));
 
@@ -937,41 +537,16 @@ gst_audio_convert_fixate_caps (GstBaseTransform * base,
 
   gst_audio_convert_fixate_channels (base, ins, outs);
 
+  if ((fmt = gst_structure_get_string (ins, "format"))) {
+    /* FIXME, find the best format */
+    gst_structure_fixate_field_string (outs, "format", fmt);
+  }
+
   if (gst_structure_get_int (ins, "rate", &rate)) {
     if (gst_structure_has_field (outs, "rate")) {
       gst_structure_fixate_field_nearest_int (outs, "rate", rate);
     }
   }
-  if (gst_structure_get_int (ins, "endianness", &endianness)) {
-    if (gst_structure_has_field (outs, "endianness")) {
-      gst_structure_fixate_field_nearest_int (outs, "endianness", endianness);
-    }
-  }
-  if (gst_structure_get_int (ins, "width", &width)) {
-    if (gst_structure_has_field (outs, "width")) {
-      gst_structure_fixate_field_nearest_int (outs, "width", width);
-    }
-  } else {
-    /* this is not allowed */
-  }
-
-  if (gst_structure_get_int (ins, "depth", &depth)) {
-    if (gst_structure_has_field (outs, "depth")) {
-      gst_structure_fixate_field_nearest_int (outs, "depth", depth);
-    }
-  } else {
-    /* set depth as width */
-    if (gst_structure_has_field (outs, "depth")) {
-      gst_structure_fixate_field_nearest_int (outs, "depth", width);
-    }
-  }
-
-  if (gst_structure_get_boolean (ins, "signed", &signedness)) {
-    if (gst_structure_has_field (outs, "signed")) {
-      gst_structure_fixate_field_boolean (outs, "signed", signedness);
-    }
-  }
-
   GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
 }
 
@@ -979,26 +554,38 @@ static gboolean
 gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps,
     GstCaps * outcaps)
 {
-  AudioConvertFmt in_ac_caps = { 0 };
-  AudioConvertFmt out_ac_caps = { 0 };
   GstAudioConvert *this = GST_AUDIO_CONVERT (base);
+  GstAudioInfo in_info;
+  GstAudioInfo out_info;
 
   GST_DEBUG_OBJECT (base, "incaps %" GST_PTR_FORMAT ", outcaps %"
       GST_PTR_FORMAT, incaps, outcaps);
 
-  if (!gst_audio_convert_parse_caps (incaps, &in_ac_caps))
-    return FALSE;
-  if (!gst_audio_convert_parse_caps (outcaps, &out_ac_caps))
-    return FALSE;
+  if (!gst_audio_info_from_caps (&in_info, incaps))
+    goto invalid_in;
+  if (!gst_audio_info_from_caps (&out_info, outcaps))
+    goto invalid_out;
 
-  if (!audio_convert_prepare_context (&this->ctx, &in_ac_caps, &out_ac_caps,
+  if (!audio_convert_prepare_context (&this->ctx, &in_info, &out_info,
           this->dither, this->ns))
     goto no_converter;
 
   return TRUE;
 
+  /* ERRORS */
+invalid_in:
+  {
+    GST_ERROR_OBJECT (base, "invalid input caps");
+    return FALSE;
+  }
+invalid_out:
+  {
+    GST_ERROR_OBJECT (base, "invalid output caps");
+    return FALSE;
+  }
 no_converter:
   {
+    GST_ERROR_OBJECT (base, "could not find converter");
     return FALSE;
   }
 }
@@ -1010,79 +597,6 @@ gst_audio_convert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
   return GST_FLOW_OK;
 }
 
-static void
-gst_audio_convert_create_silence_buffer (GstAudioConvert * this, gpointer dst,
-    gint size)
-{
-  if (this->ctx.out.is_int && !this->ctx.out.sign) {
-    gint i;
-
-    switch (this->ctx.out.width) {
-      case 8:{
-        guint8 zero = 0x80 >> (8 - this->ctx.out.depth);
-
-        memset (dst, zero, size);
-        break;
-      }
-      case 16:{
-        guint16 *data = (guint16 *) dst;
-        guint16 zero = 0x8000 >> (16 - this->ctx.out.depth);
-
-        if (this->ctx.out.endianness == G_LITTLE_ENDIAN)
-          zero = GUINT16_TO_LE (zero);
-        else
-          zero = GUINT16_TO_BE (zero);
-
-        size /= 2;
-
-        for (i = 0; i < size; i++)
-          data[i] = zero;
-        break;
-      }
-      case 24:{
-        guint32 zero = 0x800000 >> (24 - this->ctx.out.depth);
-        guint8 *data = (guint8 *) dst;
-
-        if (this->ctx.out.endianness == G_LITTLE_ENDIAN) {
-          for (i = 0; i < size; i += 3) {
-            data[i] = zero & 0xff;
-            data[i + 1] = (zero >> 8) & 0xff;
-            data[i + 2] = (zero >> 16) & 0xff;
-          }
-        } else {
-          for (i = 0; i < size; i += 3) {
-            data[i + 2] = zero & 0xff;
-            data[i + 1] = (zero >> 8) & 0xff;
-            data[i] = (zero >> 16) & 0xff;
-          }
-        }
-        break;
-      }
-      case 32:{
-        guint32 *data = (guint32 *) dst;
-        guint32 zero = (0x80000000 >> (32 - this->ctx.out.depth));
-
-        if (this->ctx.out.endianness == G_LITTLE_ENDIAN)
-          zero = GUINT32_TO_LE (zero);
-        else
-          zero = GUINT32_TO_BE (zero);
-
-        size /= 4;
-
-        for (i = 0; i < size; i++)
-          data[i] = zero;
-        break;
-      }
-      default:
-        memset (dst, 0, size);
-        g_return_if_reached ();
-        break;
-    }
-  } else {
-    memset (dst, 0, size);
-  }
-}
-
 static GstFlowReturn
 gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf,
     GstBuffer * outbuf)
@@ -1095,7 +609,7 @@ gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf,
   gpointer src, dst;
 
   /* get amount of samples to convert. */
-  samples = gst_buffer_get_size (inbuf) / this->ctx.in.unit_size;
+  samples = gst_buffer_get_size (inbuf) / this->ctx.in.bpf;
 
   /* get in/output sizes, to see if the buffers we got are of correct
    * sizes */
@@ -1122,7 +636,7 @@ gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf,
       goto convert_error;
   } else {
     /* Create silence buffer */
-    gst_audio_convert_create_silence_buffer (this, dst, outsize);
+    gst_audio_format_fill_silence (this->ctx.out.finfo, dst, outsize);
   }
   ret = GST_FLOW_OK;
 
index 9370d38..62f324f 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <gst/gst.h>
 #include <gst/base/gstbasetransform.h>
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
 
 #include "audioconvert.h"
 
index 2155397..aea2c92 100644 (file)
@@ -439,7 +439,7 @@ gst_audio_quantize_setup_dither (AudioConvertCtx * ctx)
 {
   switch (ctx->dither) {
     case DITHER_TPDF_HF:
-      if (ctx->out.is_int)
+      if (GST_AUDIO_FORMAT_INFO_IS_INT (ctx->out.finfo))
         ctx->last_random = g_new0 (gint32, ctx->out.channels);
       else
         ctx->last_random = g_new0 (gdouble, ctx->out.channels);
@@ -469,14 +469,14 @@ gst_audio_quantize_setup_quantize_func (AudioConvertCtx * ctx)
 {
   gint index = 0;
 
-  if (!ctx->out.is_int) {
+  if (!GST_AUDIO_FORMAT_INFO_IS_INT (ctx->out.finfo)) {
     ctx->quantize = NULL;
     return;
   }
 
   if (ctx->ns == NOISE_SHAPING_NONE) {
     index += ctx->dither;
-    index += (ctx->out.sign) ? 0 : 4;
+    index += GST_AUDIO_FORMAT_INFO_IS_SIGNED (ctx->out.finfo) ? 0 : 4;
   } else {
     index += 8 + (4 * ctx->dither);
     index += ctx->ns - 1;
index 055f28d..0330686 100644 (file)
@@ -70,7 +70,7 @@ gst_channel_mix_fill_identical (AudioConvertCtx * this)
   for (co = 0; co < this->out.channels; co++) {
     /* find a channel in input with same position */
     for (ci = 0; ci < this->in.channels; ci++) {
-      if (this->in.pos[ci] == this->out.pos[co]) {
+      if (this->in.position[ci] == this->out.position[co]) {
         this->matrix[ci][co] = 1.0;
       }
     }
@@ -118,19 +118,19 @@ gst_channel_mix_fill_compatible (AudioConvertCtx * this)
     gint n;
 
     for (n = 0; n < this->in.channels; n++) {
-      if (this->in.pos[n] == conv[c].pos1[0])
+      if (this->in.position[n] == conv[c].pos1[0])
         pos1_0 = n;
-      else if (this->in.pos[n] == conv[c].pos1[1])
+      else if (this->in.position[n] == conv[c].pos1[1])
         pos1_1 = n;
-      else if (this->in.pos[n] == conv[c].pos2[0])
+      else if (this->in.position[n] == conv[c].pos2[0])
         pos1_2 = n;
     }
     for (n = 0; n < this->out.channels; n++) {
-      if (this->out.pos[n] == conv[c].pos1[0])
+      if (this->out.position[n] == conv[c].pos1[0])
         pos2_0 = n;
-      else if (this->out.pos[n] == conv[c].pos1[1])
+      else if (this->out.position[n] == conv[c].pos1[1])
         pos2_1 = n;
-      else if (this->out.pos[n] == conv[c].pos2[0])
+      else if (this->out.position[n] == conv[c].pos2[0])
         pos2_2 = n;
     }
 
@@ -182,15 +182,15 @@ gst_channel_mix_fill_compatible (AudioConvertCtx * this)
  */
 
 static void
-gst_channel_mix_detect_pos (AudioConvertFmt * caps,
+gst_channel_mix_detect_pos (GstAudioInfo * info,
     gint * f, gboolean * has_f,
     gint * c, gboolean * has_c, gint * r, gboolean * has_r,
     gint * s, gboolean * has_s, gint * b, gboolean * has_b)
 {
   gint n;
 
-  for (n = 0; n < caps->channels; n++) {
-    switch (caps->pos[n]) {
+  for (n = 0; n < info->channels; n++) {
+    switch (info->position[n]) {
       case GST_AUDIO_CHANNEL_POSITION_FRONT_MONO:
         f[1] = n;
         *has_f = TRUE;
@@ -247,8 +247,8 @@ gst_channel_mix_detect_pos (AudioConvertFmt * caps,
 
 static void
 gst_channel_mix_fill_one_other (gfloat ** matrix,
-    AudioConvertFmt * from_caps, gint * from_idx,
-    AudioConvertFmt * to_caps, gint * to_idx, gfloat ratio)
+    GstAudioInfo * from_info, gint * from_idx,
+    GstAudioInfo * to_info, gint * to_idx, gfloat ratio)
 {
 
   /* src & dst have center => passthrough */
@@ -542,26 +542,26 @@ gst_channel_mix_fill_normalize (AudioConvertCtx * this)
 static gboolean
 gst_channel_mix_fill_special (AudioConvertCtx * this)
 {
-  AudioConvertFmt *in = &this->in, *out = &this->out;
+  GstAudioInfo *in = &this->in, *out = &this->out;
 
   /* Special, standard conversions here */
 
   /* Mono<->Stereo, just a fast-path */
   if (in->channels == 2 && out->channels == 1 &&
-      ((in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT &&
-              in->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) ||
-          (in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT &&
-              in->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) &&
-      out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
+      ((in->position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT &&
+              in->position[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) ||
+          (in->position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT &&
+              in->position[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) &&
+      out->position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
     this->matrix[0][0] = 0.5;
     this->matrix[1][0] = 0.5;
     return TRUE;
   } else if (in->channels == 1 && out->channels == 2 &&
-      ((out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT &&
-              out->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) ||
-          (out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT &&
-              out->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) &&
-      in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
+      ((out->position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT &&
+              out->position[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) ||
+          (out->position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT &&
+              out->position[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) &&
+      in->position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) {
     this->matrix[0][0] = 1.0;
     this->matrix[0][1] = 1.0;
     return TRUE;
@@ -584,7 +584,7 @@ gst_channel_mix_fill_matrix (AudioConvertCtx * this)
 
   gst_channel_mix_fill_identical (this);
 
-  if (!this->in.unpositioned_layout) {
+  if (!GST_AUDIO_INFO_IS_UNPOSITIONED (&this->in)) {
     gst_channel_mix_fill_compatible (this);
     gst_channel_mix_fill_others (this);
     gst_channel_mix_fill_normalize (this);
@@ -601,7 +601,8 @@ gst_channel_mix_setup_matrix (AudioConvertCtx * this)
   gst_channel_mix_unset_matrix (this);
 
   /* temp storage */
-  if (this->in.is_int || this->out.is_int) {
+  if (GST_AUDIO_FORMAT_INFO_IS_INT (this->in.finfo) ||
+      GST_AUDIO_FORMAT_INFO_IS_INT (this->out.finfo)) {
     this->tmp = (gpointer) g_new (gint32, this->out.channels);
   } else {
     this->tmp = (gpointer) g_new (gdouble, this->out.channels);
index 72c3355..bcb6625 100644 (file)
@@ -5,7 +5,9 @@ plugin_LTLIBRARIES = libgstaudiorate.la
 libgstaudiorate_la_SOURCES = gstaudiorate.c
 libgstaudiorate_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
 libgstaudiorate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstaudiorate_la_LIBADD = $(GST_LIBS)
+libgstaudiorate_la_LIBADD = $(GST_LIBS) \
+        $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la
+
 libgstaudiorate_la_LIBTOOLFLAGS = --tag=disable-static
 
 Android.mk: Makefile.am $(BUILT_SOURCES)
index 7ba9ddd..8661c24 100644 (file)
@@ -93,19 +93,17 @@ enum
 };
 
 static GstStaticPadTemplate gst_audio_rate_src_template =
-    GST_STATIC_PAD_TEMPLATE ("src",
+GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS ";"
-        GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS)
+    GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL))
     );
 
 static GstStaticPadTemplate gst_audio_rate_sink_template =
-    GST_STATIC_PAD_TEMPLATE ("sink",
+GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS ";"
-        GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS)
+    GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL))
     );
 
 static gboolean gst_audio_rate_sink_event (GstPad * pad, GstEvent * event);
@@ -208,35 +206,19 @@ gst_audio_rate_reset (GstAudioRate * audiorate)
 static gboolean
 gst_audio_rate_setcaps (GstAudioRate * audiorate, GstCaps * caps)
 {
-  GstStructure *structure;
-  gint channels, width, rate;
+  GstAudioInfo info;
 
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (!gst_structure_get_int (structure, "channels", &channels))
-    goto wrong_caps;
-  if (!gst_structure_get_int (structure, "width", &width))
-    goto wrong_caps;
-  if (!gst_structure_get_int (structure, "rate", &rate))
+  if (!gst_audio_info_from_caps (&info, caps))
     goto wrong_caps;
 
-  audiorate->bytes_per_sample = channels * (width / 8);
-  if (audiorate->bytes_per_sample == 0)
-    goto wrong_format;
-
-  audiorate->rate = rate;
+  audiorate->info = info;
 
   return TRUE;
 
   /* ERRORS */
 wrong_caps:
   {
-    GST_DEBUG_OBJECT (audiorate, "could not get channels/width from caps");
-    return FALSE;
-  }
-wrong_format:
-  {
-    GST_DEBUG_OBJECT (audiorate, "bytes_per_samples gave 0");
+    GST_DEBUG_OBJECT (audiorate, "could not parse caps");
     return FALSE;
   }
 }
@@ -386,20 +368,24 @@ static gboolean
 gst_audio_rate_convert (GstAudioRate * audiorate,
     GstFormat src_fmt, guint64 src_val, GstFormat dest_fmt, guint64 * dest_val)
 {
+  gint rate, bpf;
+
   if (src_fmt == dest_fmt) {
     *dest_val = src_val;
     return TRUE;
   }
 
+  rate = GST_AUDIO_INFO_RATE (&audiorate->info);
+  bpf = GST_AUDIO_INFO_BPF (&audiorate->info);
+
   switch (src_fmt) {
     case GST_FORMAT_DEFAULT:
       switch (dest_fmt) {
         case GST_FORMAT_BYTES:
-          *dest_val = src_val * audiorate->bytes_per_sample;
+          *dest_val = src_val * bpf;
           break;
         case GST_FORMAT_TIME:
-          *dest_val =
-              gst_util_uint64_scale_int (src_val, GST_SECOND, audiorate->rate);
+          *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate);
           break;
         default:
           return FALSE;;
@@ -408,11 +394,11 @@ gst_audio_rate_convert (GstAudioRate * audiorate,
     case GST_FORMAT_BYTES:
       switch (dest_fmt) {
         case GST_FORMAT_DEFAULT:
-          *dest_val = src_val / audiorate->bytes_per_sample;
+          *dest_val = src_val / bpf;
           break;
         case GST_FORMAT_TIME:
           *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND,
-              audiorate->rate * audiorate->bytes_per_sample);
+              rate * bpf);
           break;
         default:
           return FALSE;;
@@ -422,14 +408,13 @@ gst_audio_rate_convert (GstAudioRate * audiorate,
       switch (dest_fmt) {
         case GST_FORMAT_BYTES:
           *dest_val = gst_util_uint64_scale_int (src_val,
-              audiorate->rate * audiorate->bytes_per_sample, GST_SECOND);
+              rate * bpf, GST_SECOND);
           break;
         case GST_FORMAT_DEFAULT:
-          *dest_val =
-              gst_util_uint64_scale_int (src_val, audiorate->rate, GST_SECOND);
+          *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
           break;
         default:
-          return FALSE;;
+          return FALSE;
       }
       break;
     default:
@@ -493,11 +478,15 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
   guint in_size;
   GstFlowReturn ret = GST_FLOW_OK;
   GstClockTimeDiff diff;
+  gint rate, bpf;
 
   audiorate = GST_AUDIO_RATE (gst_pad_get_parent (pad));
 
+  rate = GST_AUDIO_INFO_RATE (&audiorate->info);
+  bpf = GST_AUDIO_INFO_BPF (&audiorate->info);
+
   /* need to be negotiated now */
-  if (audiorate->bytes_per_sample == 0)
+  if (bpf == 0)
     goto not_negotiated;
 
   /* we have a new pending segment */
@@ -514,7 +503,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
      */
     /* convert first timestamp of segment to sample position */
     pos = gst_util_uint64_scale_int (audiorate->src_segment.start,
-        audiorate->rate, GST_SECOND);
+        GST_AUDIO_INFO_RATE (&audiorate->info), GST_SECOND);
 
     GST_DEBUG_OBJECT (audiorate, "resync to offset %" G_GINT64_FORMAT, pos);
 
@@ -523,12 +512,12 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
 
     audiorate->next_offset = pos;
     audiorate->next_ts = gst_util_uint64_scale_int (audiorate->next_offset,
-        GST_SECOND, audiorate->rate);
+        GST_SECOND, GST_AUDIO_INFO_RATE (&audiorate->info));
 
     if (audiorate->skip_to_first && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
       GST_DEBUG_OBJECT (audiorate, "but skipping to first buffer instead");
       pos = gst_util_uint64_scale_int (GST_BUFFER_TIMESTAMP (buf),
-          audiorate->rate, GST_SECOND);
+          GST_AUDIO_INFO_RATE (&audiorate->info), GST_SECOND);
       GST_DEBUG_OBJECT (audiorate, "so resync to offset %" G_GINT64_FORMAT,
           pos);
       audiorate->next_offset = pos;
@@ -545,11 +534,10 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
   }
 
   in_size = gst_buffer_get_size (buf);
-  in_samples = in_size / audiorate->bytes_per_sample;
+  in_samples = in_size / bpf;
 
   /* calculate the buffer offset */
-  in_offset = gst_util_uint64_scale_int_round (in_time, audiorate->rate,
-      GST_SECOND);
+  in_offset = gst_util_uint64_scale_int_round (in_time, rate, GST_SECOND);
   in_offset_end = in_offset + in_samples;
 
   GST_LOG_OBJECT (audiorate,
@@ -557,7 +545,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
       ", in_size:%u, in_offset:%" G_GUINT64_FORMAT ", in_offset_end:%"
       G_GUINT64_FORMAT ", ->next_offset:%" G_GUINT64_FORMAT ", ->next_ts:%"
       GST_TIME_FORMAT, GST_TIME_ARGS (in_time),
-      GST_TIME_ARGS (GST_FRAMES_TO_CLOCK_TIME (in_samples, audiorate->rate)),
+      GST_TIME_ARGS (GST_FRAMES_TO_CLOCK_TIME (in_samples, rate)),
       in_size, in_offset, in_offset_end, audiorate->next_offset,
       GST_TIME_ARGS (audiorate->next_ts));
 
@@ -587,11 +575,11 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
     fillsamples = in_offset - audiorate->next_offset;
 
     while (fillsamples > 0) {
-      guint64 cursamples = MIN (fillsamples, audiorate->rate);
+      guint64 cursamples = MIN (fillsamples, rate);
       guint8 *data;
 
       fillsamples -= cursamples;
-      fillsize = cursamples * audiorate->bytes_per_sample;
+      fillsize = cursamples * bpf;
 
       fill = gst_buffer_new_and_alloc (fillsize);
 
@@ -612,7 +600,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
        * streams */
       GST_BUFFER_TIMESTAMP (fill) = audiorate->next_ts;
       audiorate->next_ts = gst_util_uint64_scale_int (audiorate->next_offset,
-          GST_SECOND, audiorate->rate);
+          GST_SECOND, rate);
       GST_BUFFER_DURATION (fill) = audiorate->next_ts -
           GST_BUFFER_TIMESTAMP (fill);
 
@@ -638,7 +626,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
   } else if (in_offset < audiorate->next_offset) {
     /* need to remove samples */
     if (in_offset_end <= audiorate->next_offset) {
-      guint64 drop = in_size / audiorate->bytes_per_sample;
+      guint64 drop = in_size / bpf;
 
       audiorate->drop += drop;
 
@@ -660,7 +648,7 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf)
 
       /* truncate buffer */
       truncsamples = audiorate->next_offset - in_offset;
-      truncsize = truncsamples * audiorate->bytes_per_sample;
+      truncsize = truncsamples * bpf;
       leftsize = in_size - truncsize;
 
       trunc =
@@ -690,7 +678,7 @@ send:
 
   GST_BUFFER_TIMESTAMP (buf) = audiorate->next_ts;
   audiorate->next_ts = gst_util_uint64_scale_int (in_offset_end,
-      GST_SECOND, audiorate->rate);
+      GST_SECOND, rate);
   GST_BUFFER_DURATION (buf) = audiorate->next_ts - GST_BUFFER_TIMESTAMP (buf);
 
   if (audiorate->discont) {
@@ -804,8 +792,8 @@ gst_audio_rate_change_state (GstElement * element, GstStateChange transition)
       audiorate->in = 0;
       audiorate->out = 0;
       audiorate->drop = 0;
-      audiorate->bytes_per_sample = 0;
       audiorate->add = 0;
+      gst_audio_info_init (&audiorate->info);
       gst_audio_rate_reset (audiorate);
       break;
     default:
index f2eafcf..b0b191e 100644 (file)
@@ -51,8 +51,7 @@ struct _GstAudioRate
   GstPad *sinkpad, *srcpad;
 
   /* audio format */
-  gint bytes_per_sample;
-  gint rate;
+  GstAudioInfo info;
 
   /* stats */
   guint64 in, out, add, drop;
index f2be5c7..9c2999c 100644 (file)
@@ -20,6 +20,7 @@ libgstaudioresample_la_CFLAGS = \
        $(ORC_CFLAGS)
 
 libgstaudioresample_la_LIBADD = \
+       $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \
        $(GST_BASE_LIBS) \
        $(GST_LIBS) \
        $(ORC_LIBS) $(ORC_TEST_LIBS) \
index 5b9e162..29464b0 100644 (file)
@@ -28,7 +28,7 @@
  * <refsect2>
  * <title>Example launch line</title>
  * |[
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! audio/x-raw-int, rate=8000 ! alsasink
+ * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! audio/x-raw, rate=8000 ! alsasink
  * ]| Decode an Ogg/Vorbis downsample to 8Khz and play sound through alsa.
  * To create the Ogg/Vorbis file refer to the documentation of vorbisenc.
  * </refsect2>
@@ -65,42 +65,13 @@ enum
   PROP_QUALITY
 };
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 #define SUPPORTED_CAPS \
-GST_STATIC_CAPS ( \
-    "audio/x-raw-float, " \
-      "rate = (int) [ 1, MAX ], "      \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) { 32, 64 }; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 32, " \
-      "depth = (int) 32, " \
-      "signed = (boolean) true; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 24, " \
-      "depth = (int) 24, " \
-      "signed = (boolean) true; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 16, " \
-      "depth = (int) 16, " \
-      "signed = (boolean) true; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 8, " \
-      "depth = (int) 8, " \
-      "signed = (boolean) true" \
-)
+  GST_AUDIO_CAPS_MAKE ("{ F32_LE, F64_LE, S32_LE, S24_3LE, S16_LE, S8 }")
+#else
+#define SUPPORTED_CAPS \
+  GST_AUDIO_CAPS_MAKE ("{ F32_BE, F64_BE, S32_BE, S24_3BE, S16_BE, S8 }")
+#endif
 
 /* If TRUE integer arithmetic resampling is faster and will be used if appropiate */
 #if defined AUDIORESAMPLE_FORMAT_INT
@@ -113,11 +84,15 @@ static gboolean gst_audio_resample_use_int = FALSE;
 
 static GstStaticPadTemplate gst_audio_resample_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS);
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (SUPPORTED_CAPS));
 
 static GstStaticPadTemplate gst_audio_resample_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC, GST_PAD_ALWAYS, SUPPORTED_CAPS);
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (SUPPORTED_CAPS));
 
 static void gst_audio_resample_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -252,9 +227,6 @@ gst_audio_resample_stop (GstBaseTransform * base)
   resample->tmp_out = NULL;
   resample->tmp_out_size = 0;
 
-  gst_caps_replace (&resample->sinkcaps, NULL);
-  gst_caps_replace (&resample->srccaps, NULL);
-
   return TRUE;
 }
 
@@ -262,23 +234,21 @@ static gboolean
 gst_audio_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps,
     gsize * size)
 {
-  gint width, channels;
-  GstStructure *structure;
-  gboolean ret;
+  GstAudioInfo info;
 
-  g_return_val_if_fail (size != NULL, FALSE);
+  if (!gst_audio_info_from_caps (&info, caps))
+    goto invalid_caps;
 
-  /* this works for both float and int */
-  structure = gst_caps_get_structure (caps, 0);
-  ret = gst_structure_get_int (structure, "width", &width);
-  ret &= gst_structure_get_int (structure, "channels", &channels);
-
-  if (G_UNLIKELY (!ret))
-    return FALSE;
-
-  *size = (width / 8) * channels;
+  *size = GST_AUDIO_INFO_BPF (&info);
 
   return TRUE;
+
+  /* ERRORS */
+invalid_caps:
+  {
+    GST_ERROR_OBJECT (base, "invalid caps");
+    return FALSE;
+  }
 }
 
 static GstCaps *
@@ -455,63 +425,6 @@ gst_audio_resample_reset_state (GstAudioResample * resample)
     resample->funcs->reset_mem (resample->state);
 }
 
-static gboolean
-gst_audio_resample_parse_caps (GstCaps * incaps,
-    GstCaps * outcaps, gint * width, gint * channels, gint * inrate,
-    gint * outrate, gboolean * fp)
-{
-  GstStructure *structure;
-  gboolean ret;
-  gint mywidth, myinrate, myoutrate, mychannels;
-  gboolean myfp;
-
-  GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %"
-      GST_PTR_FORMAT, incaps, outcaps);
-
-  structure = gst_caps_get_structure (incaps, 0);
-
-  if (gst_structure_has_name (structure, "audio/x-raw-float"))
-    myfp = TRUE;
-  else
-    myfp = FALSE;
-
-  ret = gst_structure_get_int (structure, "rate", &myinrate);
-  ret &= gst_structure_get_int (structure, "channels", &mychannels);
-  ret &= gst_structure_get_int (structure, "width", &mywidth);
-  if (G_UNLIKELY (!ret))
-    goto no_in_rate_channels;
-
-  structure = gst_caps_get_structure (outcaps, 0);
-  ret = gst_structure_get_int (structure, "rate", &myoutrate);
-  if (G_UNLIKELY (!ret))
-    goto no_out_rate;
-
-  if (channels)
-    *channels = mychannels;
-  if (inrate)
-    *inrate = myinrate;
-  if (outrate)
-    *outrate = myoutrate;
-  if (width)
-    *width = mywidth;
-  if (fp)
-    *fp = myfp;
-
-  return TRUE;
-
-  /* ERRORS */
-no_in_rate_channels:
-  {
-    GST_DEBUG ("could not get input rate and channels");
-    return FALSE;
-  }
-no_out_rate:
-  {
-    GST_DEBUG ("could not get output rate");
-    return FALSE;
-  }
-}
-
 static gint
 _gcd (gint a, gint b)
 {
@@ -531,26 +444,29 @@ gst_audio_resample_transform_size (GstBaseTransform * base,
     gsize * othersize)
 {
   gboolean ret = TRUE;
+  GstAudioInfo in, out;
   guint32 ratio_den, ratio_num;
   gint inrate, outrate, gcd;
-  gint bytes_per_samp, channels;
+  gint bpf;
 
   GST_LOG_OBJECT (base, "asked to transform size %" G_GSIZE_FORMAT
       " in direction %s", size, direction == GST_PAD_SINK ? "SINK" : "SRC");
 
   /* Get sample width -> bytes_per_samp, channels, inrate, outrate */
-  ret =
-      gst_audio_resample_parse_caps (caps, othercaps, &bytes_per_samp,
-      &channels, &inrate, &outrate, NULL);
+  ret = gst_audio_info_from_caps (&in, caps);
+  ret &= gst_audio_info_from_caps (&out, othercaps);
   if (G_UNLIKELY (!ret)) {
     GST_ERROR_OBJECT (base, "Wrong caps");
     return FALSE;
   }
   /* Number of samples in either buffer is size / (width*channels) ->
    * calculate the factor */
-  bytes_per_samp = bytes_per_samp * channels / 8;
+  bpf = GST_AUDIO_INFO_BPF (&in);
+  inrate = GST_AUDIO_INFO_RATE (&in);
+  outrate = GST_AUDIO_INFO_RATE (&out);
+
   /* Convert source buffer size to samples */
-  size /= bytes_per_samp;
+  size /= bpf;
 
   /* Simplify the conversion ratio factors */
   gcd = _gcd (inrate, outrate);
@@ -560,16 +476,16 @@ gst_audio_resample_transform_size (GstBaseTransform * base,
   if (direction == GST_PAD_SINK) {
     /* asked to convert size of an incoming buffer. Round up the output size */
     *othersize = gst_util_uint64_scale_int_ceil (size, ratio_den, ratio_num);
-    *othersize *= bytes_per_samp;
+    *othersize *= bpf;
   } else {
     /* asked to convert size of an outgoing buffer. Round down the input size */
     *othersize = gst_util_uint64_scale_int (size, ratio_num, ratio_den);
-    *othersize *= bytes_per_samp;
+    *othersize *= bpf;
   }
 
   GST_LOG_OBJECT (base,
       "transformed size %" G_GSIZE_FORMAT " to %" G_GSIZE_FORMAT,
-      size * bytes_per_samp, *othersize);
+      size * bpf, *othersize);
 
   return ret;
 }
@@ -579,18 +495,27 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
     GstCaps * outcaps)
 {
   gboolean ret;
-  gint width = 0, inrate = 0, outrate = 0, channels = 0;
+  gint width, inrate, outrate, channels;
   gboolean fp;
   GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
+  GstAudioInfo in, out;
 
   GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %"
       GST_PTR_FORMAT, incaps, outcaps);
 
-  ret = gst_audio_resample_parse_caps (incaps, outcaps,
-      &width, &channels, &inrate, &outrate, &fp);
+  if (!gst_audio_info_from_caps (&in, incaps))
+    goto invalid_incaps;
+  if (!gst_audio_info_from_caps (&out, outcaps))
+    goto invalid_outcaps;
 
-  if (G_UNLIKELY (!ret))
-    return FALSE;
+  /* FIXME do some checks */
+
+  /* take new values */
+  width = GST_AUDIO_FORMAT_INFO_WIDTH (in.finfo);
+  channels = GST_AUDIO_INFO_CHANNELS (&in);
+  inrate = GST_AUDIO_INFO_RATE (&in);
+  outrate = GST_AUDIO_INFO_RATE (&out);
+  fp = GST_AUDIO_FORMAT_INFO_IS_FLOAT (in.finfo);
 
   ret =
       gst_audio_resample_update_state (resample, width, channels, inrate,
@@ -599,12 +524,19 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
   if (G_UNLIKELY (!ret))
     return FALSE;
 
-  /* save caps so we can short-circuit in the size_transform if the caps
-   * are the same */
-  gst_caps_replace (&resample->sinkcaps, incaps);
-  gst_caps_replace (&resample->srccaps, outcaps);
-
   return TRUE;
+
+  /* ERROR */
+invalid_incaps:
+  {
+    GST_ERROR_OBJECT (base, "invalid incaps");
+    return FALSE;
+  }
+invalid_outcaps:
+  {
+    GST_ERROR_OBJECT (base, "invalid outcaps");
+    return FALSE;
+  }
 }
 
 #define GST_MAXINT24 (8388607)
index f5f7464..da75b64 100644 (file)
@@ -53,9 +53,6 @@ struct _GstAudioResample {
   GstBaseTransform element;
 
   /* <private> */
-
-  GstCaps *srccaps, *sinkcaps;
-
   gboolean need_discont;
 
   GstClockTime t0;
@@ -67,12 +64,18 @@ struct _GstAudioResample {
   guint64 num_gap_samples;
   guint64 num_nongap_samples;
 
+  GstAudioInfo in;
+  GstAudioInfo out;
+
+  /* properties */
+  gint quality;
+
+  /* state */
+  gboolean fp;
+  gint width;
   gint channels;
   gint inrate;
   gint outrate;
-  gint quality;
-  gint width;
-  gboolean fp;
 
   guint8 *tmp_in;
   guint tmp_in_size;
index 67a2c0b..c00f9ff 100644 (file)
@@ -1,9 +1,11 @@
 plugin_LTLIBRARIES = libgstaudiotestsrc.la
 
 libgstaudiotestsrc_la_SOURCES = gstaudiotestsrc.c
-libgstaudiotestsrc_la_CFLAGS = $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS)
+libgstaudiotestsrc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS)
 libgstaudiotestsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstaudiotestsrc_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GST_CONTROLLER_LIBS) $(LIBM)
+libgstaudiotestsrc_la_LIBADD = \
+       $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \
+       $(GST_BASE_LIBS) $(GST_LIBS) $(GST_CONTROLLER_LIBS) $(LIBM)
 libgstaudiotestsrc_la_LIBTOOLFLAGS = --tag=disable-static
 
 noinst_HEADERS = gstaudiotestsrc.h
index 8443269..b545787 100644 (file)
@@ -76,28 +76,20 @@ enum
   PROP_LAST
 };
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define FORMAT_STR "{ S16_LE, S32_LE, F32_LE, F64_LE }"
+#define DEFAULT_FORMAT_STR "S16_LE"
+#else
+#define FORMAT_STR "{ S16_BE, S32_BE, F32_BE, F64_BE }"
+#define DEFAULT_FORMAT_STR "S16_BE"
+#endif
 
 static GstStaticPadTemplate gst_audio_test_src_src_template =
-    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) BYTE_ORDER, "
-        "signed = (boolean) true, "
-        "width = (int) 16, "
-        "depth = (int) 16, "
-        "rate = (int) [ 1, MAX ], "
-        "channels = (int) [ 1, 2 ]; "
-        "audio/x-raw-int, "
-        "endianness = (int) BYTE_ORDER, "
-        "signed = (boolean) true, "
-        "width = (int) 32, "
-        "depth = (int) 32,"
-        "rate = (int) [ 1, MAX ], "
-        "channels = (int) [ 1, 2 ]; "
-        "audio/x-raw-float, "
-        "endianness = (int) BYTE_ORDER, "
-        "width = (int) { 32, 64 }, "
+    GST_STATIC_CAPS ("audio/x-raw, "
+        "format = (string) " FORMAT_STR ", "
         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
     );
 
@@ -234,9 +226,6 @@ gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
 static void
 gst_audio_test_src_init (GstAudioTestSrc * src)
 {
-  src->samplerate = 44100;
-  src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE;
-
   src->volume = DEFAULT_VOLUME;
   src->freq = DEFAULT_FREQ;
 
@@ -271,20 +260,16 @@ static void
 gst_audio_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
 {
   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (bsrc);
-  const gchar *name;
   GstStructure *structure;
 
   structure = gst_caps_get_structure (caps, 0);
 
-  GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate);
+  GST_DEBUG_OBJECT (src, "fixating samplerate to %d", GST_AUDIO_DEF_RATE);
 
-  gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
+  gst_structure_fixate_field_nearest_int (structure, "rate",
+      GST_AUDIO_DEF_RATE);
 
-  name = gst_structure_get_name (structure);
-  if (strcmp (name, "audio/x-raw-int") == 0)
-    gst_structure_fixate_field_nearest_int (structure, "width", 32);
-  else if (strcmp (name, "audio/x-raw-float") == 0)
-    gst_structure_fixate_field_nearest_int (structure, "width", 64);
+  gst_structure_fixate_field_string (structure, "format", DEFAULT_FORMAT_STR);
 
   /* fixate to mono unless downstream requires stereo, for backwards compat */
   gst_structure_fixate_field_nearest_int (structure, "channels", 1);
@@ -296,53 +281,25 @@ static gboolean
 gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
 {
   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
-  const GstStructure *structure;
-  const gchar *name;
-  gint width;
-  gboolean ret;
+  GstAudioInfo info;
 
-  structure = gst_caps_get_structure (caps, 0);
-  ret = gst_structure_get_int (structure, "rate", &src->samplerate);
+  if (!gst_audio_info_from_caps (&info, caps))
+    goto invalid_caps;
 
-  GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate);
+  GST_DEBUG_OBJECT (src, "negotiated to caps %" GST_PTR_FORMAT, caps);
 
-  name = gst_structure_get_name (structure);
-  if (strcmp (name, "audio/x-raw-int") == 0) {
-    ret &= gst_structure_get_int (structure, "width", &width);
-    src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_S32 :
-        GST_AUDIO_TEST_SRC_FORMAT_S16;
-  } else {
-    ret &= gst_structure_get_int (structure, "width", &width);
-    src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_F32 :
-        GST_AUDIO_TEST_SRC_FORMAT_F64;
-  }
-
-  /* allocate a new buffer suitable for this pad */
-  switch (src->format) {
-    case GST_AUDIO_TEST_SRC_FORMAT_S16:
-      src->sample_size = sizeof (gint16);
-      break;
-    case GST_AUDIO_TEST_SRC_FORMAT_S32:
-      src->sample_size = sizeof (gint32);
-      break;
-    case GST_AUDIO_TEST_SRC_FORMAT_F32:
-      src->sample_size = sizeof (gfloat);
-      break;
-    case GST_AUDIO_TEST_SRC_FORMAT_F64:
-      src->sample_size = sizeof (gdouble);
-      break;
-    default:
-      /* can't really happen */
-      ret = FALSE;
-      break;
-  }
-
-  ret &= gst_structure_get_int (structure, "channels", &src->channels);
-  GST_DEBUG_OBJECT (src, "negotiated to %d channels", src->channels);
+  src->info = info;
 
   gst_audio_test_src_change_wave (src);
 
-  return ret;
+  return TRUE;
+
+  /* ERROR */
+invalid_caps:
+  {
+    GST_ERROR_OBJECT (basesrc, "received invalid caps");
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -356,6 +313,7 @@ gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
     {
       GstFormat src_fmt, dest_fmt;
       gint64 src_val, dest_val;
+      gint rate;
 
       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
       if (src_fmt == dest_fmt) {
@@ -363,14 +321,14 @@ gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
         goto done;
       }
 
+      rate = GST_AUDIO_INFO_RATE (&src->info);
+
       switch (src_fmt) {
         case GST_FORMAT_DEFAULT:
           switch (dest_fmt) {
             case GST_FORMAT_TIME:
               /* samples to time */
-              dest_val =
-                  gst_util_uint64_scale_int (src_val, GST_SECOND,
-                  src->samplerate);
+              dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate);
               break;
             default:
               goto error;
@@ -380,9 +338,7 @@ gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query)
           switch (dest_fmt) {
             case GST_FORMAT_DEFAULT:
               /* time to samples */
-              dest_val =
-                  gst_util_uint64_scale_int (src_val, src->samplerate,
-                  GST_SECOND);
+              dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND);
               break;
             default:
               goto error;
@@ -422,19 +378,20 @@ error:
 static void \
 gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels; \
   gdouble step, amp; \
   \
-  step = M_PI_M2 * src->freq / src->samplerate; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
+  step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
   amp = src->volume * scale; \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    for (c = 0; c < src->channels; ++c) { \
+    for (c = 0; c < channels; ++c) { \
       samples[i++] = (g##type) (sin (src->accumulator) * amp); \
     } \
   } \
@@ -456,19 +413,20 @@ static const ProcessFunc sine_funcs[] = {
 static void \
 gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels; \
   gdouble step, amp; \
   \
-  step = M_PI_M2 * src->freq / src->samplerate; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
+  step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
   amp = src->volume * scale; \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    for (c = 0; c < src->channels; ++c) { \
+    for (c = 0; c < channels; ++c) { \
       samples[i++] = (g##type) ((src->accumulator < G_PI) ? amp : -amp); \
     } \
   } \
@@ -490,23 +448,24 @@ static const ProcessFunc square_funcs[] = {
 static void \
 gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels; \
   gdouble step, amp; \
   \
-  step = M_PI_M2 * src->freq / src->samplerate; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
+  step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
   amp = (src->volume * scale) / G_PI; \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
     if (src->accumulator < G_PI) { \
-      for (c = 0; c < src->channels; ++c) \
+      for (c = 0; c < channels; ++c) \
         samples[i++] = (g##type) (src->accumulator * amp); \
     } else { \
-      for (c = 0; c < src->channels; ++c) \
+      for (c = 0; c < channels; ++c) \
         samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
     } \
   } \
@@ -528,26 +487,27 @@ static const ProcessFunc saw_funcs[] = {
 static void \
 gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels; \
   gdouble step, amp; \
   \
-  step = M_PI_M2 * src->freq / src->samplerate; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
+  step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
   amp = (src->volume * scale) / G_PI_2; \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
     if (src->accumulator < (G_PI_2)) { \
-      for (c = 0; c < src->channels; ++c) \
+      for (c = 0; c < channels; ++c) \
         samples[i++] = (g##type) (src->accumulator * amp); \
     } else if (src->accumulator < (G_PI * 1.5)) { \
-      for (c = 0; c < src->channels; ++c) \
+      for (c = 0; c < channels; ++c) \
         samples[i++] = (g##type) ((src->accumulator - G_PI) * -amp); \
     } else { \
-      for (c = 0; c < src->channels; ++c) \
+      for (c = 0; c < channels; ++c) \
         samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \
     } \
   } \
@@ -569,7 +529,7 @@ static const ProcessFunc triangle_funcs[] = {
 static void \
 gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \
+  memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->info.channels); \
 }
 
 DEFINE_SILENCE (int16);
@@ -590,10 +550,11 @@ gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * s
 { \
   gint i, c; \
   gdouble amp = (src->volume * scale); \
+  gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
-    for (c = 0; c < src->channels; ++c) \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
+    for (c = 0; c < channels; ++c) \
       samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \
   } \
 }
@@ -681,14 +642,15 @@ gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src)
 static void \
 gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels; \
   gdouble amp; \
   \
   amp = src->volume * scale; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
-    for (c = 0; c < src->channels; ++c) { \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
+    for (c = 0; c < channels; ++c) { \
       samples[i++] = \
         (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \
         amp); \
@@ -726,19 +688,20 @@ gst_audio_test_src_init_sine_table (GstAudioTestSrc * src)
 static void \
 gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels; \
   gdouble step, scl; \
   \
-  step = M_PI_M2 * src->freq / src->samplerate; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
+  step = M_PI_M2 * src->freq / GST_AUDIO_INFO_RATE (&src->info); \
   scl = 1024.0 / M_PI_M2; \
   \
   i = 0; \
-  while (i < (src->generate_samples_per_buffer * src->channels)) { \
+  while (i < (src->generate_samples_per_buffer * channels)) { \
     src->accumulator += step; \
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    for (c = 0; c < src->channels; ++c) \
+    for (c = 0; c < channels; ++c) \
       samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
   } \
 }
@@ -759,10 +722,12 @@ static const ProcessFunc sine_table_funcs[] = {
 static void \
 gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \
 { \
-  gint i, c; \
+  gint i, c, channels, samplerate; \
   gdouble step, scl; \
   \
-  step = M_PI_M2 * src->freq / src->samplerate; \
+  channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
+  samplerate = GST_AUDIO_INFO_RATE (&src->info); \
+  step = M_PI_M2 * src->freq / samplerate; \
   scl = 1024.0 / M_PI_M2; \
   \
   for (i = 0; i < src->generate_samples_per_buffer; i++) { \
@@ -770,12 +735,12 @@ gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples)
     if (src->accumulator >= M_PI_M2) \
       src->accumulator -= M_PI_M2; \
     \
-    if ((src->next_sample + i)%src->samplerate < 1600) { \
-      for (c = 0; c < src->channels; ++c) \
-        samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
+    if ((src->next_sample + i)%samplerate < 1600) { \
+      for (c = 0; c < channels; ++c) \
+        samples[(i * channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
     } else { \
-      for (c = 0; c < src->channels; ++c) \
-        samples[(i * src->channels) + c] = 0; \
+      for (c = 0; c < channels; ++c) \
+        samples[(i * channels) + c] = 0; \
     } \
   } \
 }
@@ -804,14 +769,15 @@ gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g#
 { \
   gint i, c; \
   gdouble amp = (src->volume * scale); \
+  gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
   \
-  for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
-    for (c = 0; c < src->channels; ++c) { \
+  for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
+    for (c = 0; c < channels; ++c) { \
       gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \
       gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \
       \
       samples[i++] = (g##type) (amp * mag * cos (phs)); \
-      if (++c >= src->channels) \
+      if (++c >= channels) \
         break; \
       samples[i++] = (g##type) (amp * mag * sin (phs)); \
     } \
@@ -844,9 +810,10 @@ gst_audio_test_src_create_red_noise_##type (GstAudioTestSrc * src, g##type * sam
   gint i, c; \
   gdouble amp = (src->volume * scale); \
   gdouble state = src->red.state; \
+  gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
   \
-  for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
-    for (c = 0; c < src->channels; ++c) { \
+  for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
+    for (c = 0; c < channels; ++c) { \
       while (TRUE) { \
         gdouble  r = g_rand_double_range (src->gen, -1.0, 1.0); \
         state += r; \
@@ -879,10 +846,11 @@ gst_audio_test_src_create_blue_noise_##type (GstAudioTestSrc * src, g##type * sa
 { \
   gint i, c; \
   static gdouble flip=1.0; \
+  gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
   \
   gst_audio_test_src_create_pink_noise_##type (src, samples); \
-  for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
-    for (c = 0; c < src->channels; ++c) { \
+  for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
+    for (c = 0; c < channels; ++c) { \
       samples[i++] *= flip; \
     } \
     flip *= -1.0; \
@@ -910,10 +878,11 @@ gst_audio_test_src_create_violet_noise_##type (GstAudioTestSrc * src, g##type *
 { \
   gint i, c; \
   static gdouble flip=1.0; \
+  gint channels = GST_AUDIO_INFO_CHANNELS (&src->info); \
   \
   gst_audio_test_src_create_red_noise_##type (src, samples); \
-  for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \
-    for (c = 0; c < src->channels; ++c) { \
+  for (i = 0; i < src->generate_samples_per_buffer * channels; ) { \
+    for (c = 0; c < channels; ++c) { \
       samples[i++] *= flip; \
     } \
     flip *= -1.0; \
@@ -940,68 +909,83 @@ static const ProcessFunc violet_noise_funcs[] = {
 static void
 gst_audio_test_src_change_wave (GstAudioTestSrc * src)
 {
-  if (src->format == -1) {
-    src->process = NULL;
-    return;
+  gint idx;
+
+  switch (GST_AUDIO_FORMAT_INFO_FORMAT (src->info.finfo)) {
+    case GST_AUDIO_FORMAT_S16:
+      idx = 0;
+      break;
+    case GST_AUDIO_FORMAT_S32:
+      idx = 1;
+      break;
+    case GST_AUDIO_FORMAT_F32:
+      idx = 2;
+      break;
+    case GST_AUDIO_FORMAT_F64:
+      idx = 3;
+      break;
+    default:
+      src->process = NULL;
+      return;
   }
 
   switch (src->wave) {
     case GST_AUDIO_TEST_SRC_WAVE_SINE:
-      src->process = sine_funcs[src->format];
+      src->process = sine_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_SQUARE:
-      src->process = square_funcs[src->format];
+      src->process = square_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_SAW:
-      src->process = saw_funcs[src->format];
+      src->process = saw_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE:
-      src->process = triangle_funcs[src->format];
+      src->process = triangle_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_SILENCE:
-      src->process = silence_funcs[src->format];
+      src->process = silence_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE:
       if (!(src->gen))
         src->gen = g_rand_new ();
-      src->process = white_noise_funcs[src->format];
+      src->process = white_noise_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE:
       if (!(src->gen))
         src->gen = g_rand_new ();
       gst_audio_test_src_init_pink_noise (src);
-      src->process = pink_noise_funcs[src->format];
+      src->process = pink_noise_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB:
       gst_audio_test_src_init_sine_table (src);
-      src->process = sine_table_funcs[src->format];
+      src->process = sine_table_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_TICKS:
       gst_audio_test_src_init_sine_table (src);
-      src->process = tick_funcs[src->format];
+      src->process = tick_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE:
       if (!(src->gen))
         src->gen = g_rand_new ();
-      src->process = gaussian_white_noise_funcs[src->format];
+      src->process = gaussian_white_noise_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_RED_NOISE:
       if (!(src->gen))
         src->gen = g_rand_new ();
       src->red.state = 0.0;
-      src->process = red_noise_funcs[src->format];
+      src->process = red_noise_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_BLUE_NOISE:
       if (!(src->gen))
         src->gen = g_rand_new ();
       gst_audio_test_src_init_pink_noise (src);
-      src->process = blue_noise_funcs[src->format];
+      src->process = blue_noise_funcs[idx];
       break;
     case GST_AUDIO_TEST_SRC_WAVE_VIOLET_NOISE:
       if (!(src->gen))
         src->gen = g_rand_new ();
       src->red.state = 0.0;
-      src->process = violet_noise_funcs[src->format];
+      src->process = violet_noise_funcs[idx];
     default:
       GST_ERROR ("invalid wave-form");
       break;
@@ -1076,18 +1060,24 @@ gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
 {
   GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
   GstClockTime time;
+  gint samplerate, bpf;
 
   GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment);
 
   time = segment->position;
   src->reverse = (segment->rate < 0.0);
 
+  samplerate = GST_AUDIO_INFO_RATE (&src->info);
+  bpf = GST_AUDIO_INFO_BPF (&src->info);
+
   /* now move to the time indicated */
-  src->next_sample =
-      gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND);
-  src->next_byte = src->next_sample * src->sample_size * src->channels;
-  src->next_time =
-      gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate);
+  src->next_sample = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
+  src->next_byte = src->next_sample * bpf;
+  if (samplerate == 0)
+    src->next_time = 0;
+  else
+    src->next_time =
+        gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
 
   GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT
       " next_time=%" GST_TIME_FORMAT, src->next_sample,
@@ -1107,8 +1097,7 @@ gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
 
   if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
     time = segment->stop;
-    src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate,
-        GST_SECOND);
+    src->sample_stop = gst_util_uint64_scale_int (time, samplerate, GST_SECOND);
     src->check_seek_stop = TRUE;
   } else {
     src->check_seek_stop = FALSE;
@@ -1136,6 +1125,7 @@ gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
   gint bytes, samples;
   GstElementClass *eclass;
   guint8 *data;
+  gint samplerate, bpf;
 
   src = GST_AUDIO_TEST_SRC (basesrc);
 
@@ -1160,12 +1150,15 @@ gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
     return GST_FLOW_UNEXPECTED;
   }
 
+  samplerate = GST_AUDIO_INFO_RATE (&src->info);
+  bpf = GST_AUDIO_INFO_BPF (&src->info);
+
   /* if no length was given, use our default length in samples otherwise convert
    * the length in bytes to samples. */
   if (length == -1)
     samples = src->samples_per_buffer;
   else
-    samples = length / (src->sample_size * src->channels);
+    samples = length / bpf;
 
   /* if no offset was given, use our next logical byte */
   if (offset == -1)
@@ -1175,10 +1168,9 @@ gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
   if (offset != src->next_byte) {
     GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
     /* we have a discont in the expected sample offset, do a 'seek' */
-    src->next_sample = offset / (src->sample_size * src->channels);
+    src->next_sample = offset / bpf;
     src->next_time =
-        gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
-        src->samplerate);
+        gst_util_uint64_scale_int (src->next_sample, GST_SECOND, samplerate);
     src->next_byte = offset;
   }
 
@@ -1197,15 +1189,14 @@ gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
     next_sample = src->next_sample + (src->reverse ? (-samples) : samples);
   }
 
-  bytes = src->generate_samples_per_buffer * src->sample_size * src->channels;
+  bytes = src->generate_samples_per_buffer * bpf;
 
   buf = gst_buffer_new_and_alloc (bytes);
 
   next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes);
-  next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND,
-      src->samplerate);
+  next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);
 
-  GST_LOG_OBJECT (src, "samplerate %d", src->samplerate);
+  GST_LOG_OBJECT (src, "samplerate %d", samplerate);
   GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
       next_sample, GST_TIME_ARGS (next_time));
 
index 529ad63..29c4285 100644 (file)
@@ -24,6 +24,8 @@
 #include <gst/gst.h>
 #include <gst/base/gstbasesrc.h>
 
+#include <gst/audio/audio.h>
+
 G_BEGIN_DECLS
 
 
@@ -86,14 +88,6 @@ typedef struct {
   gdouble    state;         /* noise state */
 } GstRedNoise;
 
-typedef enum {
-  GST_AUDIO_TEST_SRC_FORMAT_NONE = -1,
-  GST_AUDIO_TEST_SRC_FORMAT_S16 = 0,
-  GST_AUDIO_TEST_SRC_FORMAT_S32,
-  GST_AUDIO_TEST_SRC_FORMAT_F32,
-  GST_AUDIO_TEST_SRC_FORMAT_F64
-} GstAudioTestSrcFormat;
-
 typedef struct _GstAudioTestSrc GstAudioTestSrc;
 typedef struct _GstAudioTestSrcClass GstAudioTestSrcClass;
 
@@ -115,11 +109,8 @@ struct _GstAudioTestSrc {
   gdouble freq;
 
   /* audio parameters */
-  gint channels;
-  gint samplerate;
+  GstAudioInfo info;
   gint samples_per_buffer;
-  gint sample_size;
-  GstAudioTestSrcFormat format;
 
   /*< private >*/
   gboolean tags_pushed;                        /* send tags just once ? */
index 5fb156e..7f9ef35 100644 (file)
@@ -27,8 +27,7 @@ G_BEGIN_DECLS
 
 #define DEFAULT_RAW_CAPS \
     "video/x-raw; " \
-    "audio/x-raw-int; " \
-    "audio/x-raw-float; " \
+    "audio/x-raw; " \
     "text/plain; " \
     "text/x-pango-markup; " \
     "video/x-dvd-subpicture; " \
index 1dc37e5..bf76863 100644 (file)
@@ -104,40 +104,13 @@ enum
   PROP_VOLUME
 };
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 #define ALLOWED_CAPS \
-        "audio/x-raw-float, " \
-        "rate = (int) [ 1, MAX ], " \
-        "channels = (int) [ 1, MAX ], " \
-        "endianness = (int) BYTE_ORDER, " \
-        "width = (int) {32, 64}; " \
-        "audio/x-raw-int, " \
-        "channels = (int) [ 1, MAX ], " \
-        "rate = (int) [ 1,  MAX ], " \
-        "endianness = (int) BYTE_ORDER, " \
-        "width = (int) 8, " \
-        "depth = (int) 8, " \
-        "signed = (bool) TRUE; " \
-        "audio/x-raw-int, " \
-        "channels = (int) [ 1, MAX ], " \
-        "rate = (int) [ 1,  MAX ], " \
-        "endianness = (int) BYTE_ORDER, " \
-        "width = (int) 16, " \
-        "depth = (int) 16, " \
-        "signed = (bool) TRUE; " \
-        "audio/x-raw-int, " \
-        "channels = (int) [ 1, MAX ], " \
-        "rate = (int) [ 1,  MAX ], " \
-        "endianness = (int) BYTE_ORDER, " \
-        "width = (int) 24, " \
-        "depth = (int) 24, " \
-        "signed = (bool) TRUE; " \
-        "audio/x-raw-int, " \
-        "channels = (int) [ 1, MAX ], " \
-        "rate = (int) [ 1,  MAX ], " \
-        "endianness = (int) BYTE_ORDER, " \
-        "width = (int) 32, " \
-       "depth = (int) 32, " \
-       "signed = (bool) TRUE"
+    GST_AUDIO_CAPS_MAKE ("{ F32_LE, F64_LE, S8, S16_LE, S24_3LE, S32_LE }")
+#else
+#define ALLOWED_CAPS \
+    GST_AUDIO_CAPS_MAKE ("{ F32_BE, F64_BE, S8, S16_BE, S24_3BE, S32_BE }")
+#endif
 
 static void gst_volume_mixer_init (GstMixerClass * iface);
 
@@ -157,8 +130,7 @@ static void volume_before_transform (GstBaseTransform * base,
 static GstFlowReturn volume_transform_ip (GstBaseTransform * base,
     GstBuffer * outbuf);
 static gboolean volume_stop (GstBaseTransform * base);
-static gboolean volume_setup (GstAudioFilter * filter,
-    GstRingBufferSpec * format);
+static gboolean volume_setup (GstAudioFilter * filter, GstAudioInfo * info);
 
 static void volume_process_double (GstVolume * self, gpointer bytes,
     guint n_bytes);
@@ -199,68 +171,61 @@ static void volume_process_controlled_int8_clamp (GstVolume * self,
 static gboolean
 volume_choose_func (GstVolume * self)
 {
+  GstAudioFilter *filter = GST_AUDIO_FILTER (self);
+  GstAudioFormat format;
+
   self->process = NULL;
   self->process_controlled = NULL;
 
-  if (GST_AUDIO_FILTER (self)->format.caps == NULL)
+  format = GST_AUDIO_FORMAT_INFO_FORMAT (filter->info.finfo);
+
+  if (format == GST_AUDIO_FORMAT_UNKNOWN)
     return FALSE;
 
-  switch (GST_AUDIO_FILTER (self)->format.type) {
-    case GST_BUFTYPE_LINEAR:
-      switch (GST_AUDIO_FILTER (self)->format.width) {
-        case 32:
-          /* only clamp if the gain is greater than 1.0
-           */
-          if (self->current_vol_i32 > VOLUME_UNITY_INT32) {
-            self->process = volume_process_int32_clamp;
-          } else {
-            self->process = volume_process_int32;
-          }
-          self->process_controlled = volume_process_controlled_int32_clamp;
-          break;
-        case 24:
-          /* only clamp if the gain is greater than 1.0
-           */
-          if (self->current_vol_i24 > VOLUME_UNITY_INT24) {
-            self->process = volume_process_int24_clamp;
-          } else {
-            self->process = volume_process_int24;
-          }
-          self->process_controlled = volume_process_controlled_int24_clamp;
-          break;
-        case 16:
-          /* only clamp if the gain is greater than 1.0
-           */
-          if (self->current_vol_i16 > VOLUME_UNITY_INT16) {
-            self->process = volume_process_int16_clamp;
-          } else {
-            self->process = volume_process_int16;
-          }
-          self->process_controlled = volume_process_controlled_int16_clamp;
-          break;
-        case 8:
-          /* only clamp if the gain is greater than 1.0
-           */
-          if (self->current_vol_i8 > VOLUME_UNITY_INT8) {
-            self->process = volume_process_int8_clamp;
-          } else {
-            self->process = volume_process_int8;
-          }
-          self->process_controlled = volume_process_controlled_int8_clamp;
-          break;
+  switch (format) {
+    case GST_AUDIO_FORMAT_S32:
+      /* only clamp if the gain is greater than 1.0 */
+      if (self->current_vol_i32 > VOLUME_UNITY_INT32) {
+        self->process = volume_process_int32_clamp;
+      } else {
+        self->process = volume_process_int32;
+      }
+      self->process_controlled = volume_process_controlled_int32_clamp;
+      break;
+    case GST_AUDIO_FORMAT_S24_3:
+      /* only clamp if the gain is greater than 1.0 */
+      if (self->current_vol_i24 > VOLUME_UNITY_INT24) {
+        self->process = volume_process_int24_clamp;
+      } else {
+        self->process = volume_process_int24;
+      }
+      self->process_controlled = volume_process_controlled_int24_clamp;
+      break;
+    case GST_AUDIO_FORMAT_S16:
+      /* only clamp if the gain is greater than 1.0 */
+      if (self->current_vol_i16 > VOLUME_UNITY_INT16) {
+        self->process = volume_process_int16_clamp;
+      } else {
+        self->process = volume_process_int16;
       }
+      self->process_controlled = volume_process_controlled_int16_clamp;
       break;
-    case GST_BUFTYPE_FLOAT:
-      switch (GST_AUDIO_FILTER (self)->format.width) {
-        case 32:
-          self->process = volume_process_float;
-          self->process_controlled = volume_process_controlled_float;
-          break;
-        case 64:
-          self->process = volume_process_double;
-          self->process_controlled = volume_process_controlled_double;
-          break;
+    case GST_AUDIO_FORMAT_S8:
+      /* only clamp if the gain is greater than 1.0 */
+      if (self->current_vol_i8 > VOLUME_UNITY_INT8) {
+        self->process = volume_process_int8_clamp;
+      } else {
+        self->process = volume_process_int8;
       }
+      self->process_controlled = volume_process_controlled_int8_clamp;
+      break;
+    case GST_AUDIO_FORMAT_F32:
+      self->process = volume_process_float;
+      self->process_controlled = volume_process_controlled_float;
+      break;
+    case GST_AUDIO_FORMAT_F64:
+      self->process = volume_process_double;
+      self->process_controlled = volume_process_controlled_double;
       break;
     default:
       break;
@@ -756,7 +721,7 @@ volume_process_controlled_int8_clamp (GstVolume * self, gpointer bytes,
 
 /* get notified of caps and plug in the correct process function */
 static gboolean
-volume_setup (GstAudioFilter * filter, GstRingBufferSpec * format)
+volume_setup (GstAudioFilter * filter, GstAudioInfo * info)
 {
   gboolean res;
   GstVolume *self = GST_VOLUME (filter);
@@ -833,6 +798,7 @@ volume_before_transform (GstBaseTransform * base, GstBuffer * buffer)
 static GstFlowReturn
 volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
 {
+  GstAudioFilter *filter = GST_AUDIO_FILTER_CAST (base);
   GstVolume *self = GST_VOLUME (base);
   guint8 *data;
   gsize size;
@@ -850,10 +816,11 @@ volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
 
   mute_csource = gst_object_get_control_source (G_OBJECT (self), "mute");
   volume_csource = gst_object_get_control_source (G_OBJECT (self), "volume");
+
   if (mute_csource || (volume_csource && !self->current_mute)) {
-    gint rate = GST_AUDIO_FILTER_CAST (self)->format.rate;
-    gint width = GST_AUDIO_FILTER_CAST (self)->format.width / 8;
-    gint channels = GST_AUDIO_FILTER_CAST (self)->format.channels;
+    gint rate = GST_AUDIO_INFO_RATE (&filter->info);
+    gint width = GST_AUDIO_FORMAT_INFO_WIDTH (filter->info.finfo) / 8;
+    gint channels = GST_AUDIO_INFO_CHANNELS (&filter->info);
     guint nsamples = size / (width * channels);
     GstClockTime interval = gst_util_uint64_scale_int (1, GST_SECOND, rate);
     GstClockTime ts = GST_BUFFER_TIMESTAMP (outbuf);