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 9dc5b53e9c8a3523ca6c7c9602e7e695bbefd8ab..298e5a85fe5a72233d9c5712e8cb99bd93d217fe 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 902dbf77e56cfdedb22372a82e469122aa77a8c1..a4bcdbe30470466febba4dbce9c6964a6bc92fe3 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 350c9a72485c1943a304fee81daad13b26e025de..425dc7f5947925ea33c18a0a63d6610e4e0181cd 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 7072ab784da04710ccad69634003e14e8bebdfe8..de3383346abbe69c1a0aee6c2cc4f8f6f5f360a9 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 df58a44f6f9f09810de1392cfdde3bf9a8152dff..db8b8c7f13030123e71aac0063a9a83626198e53 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 04e4677410b6bb05785315263b473ee45bda2f7f..d122a0e02d64f89fa6eb8673b1f5477753ffbe40 100644 (file)
@@ -65,7 +65,7 @@ struct _GstVorbisDec {
 #endif
 
   gboolean          initialized;
-  guint             width;
+  GstAudioInfo      info;
 
   /* list of buffers that need timestamps */
   GList            *queued;
index 1ddce3877241c77dbf14e125bc8cd394a0131203..66a2ee39fc5bf8ac4ad1944c95872720774d91d3 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;
@@ -130,51 +128,9 @@ 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 2e3942267fd83bfebf6dc2868f4a172814ca36ef..fd416432c19f49b4f936e59bf8887ffe0b1cc789 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 f0c59fcc79b3a28702c146838150c6a5d40b2dfe..bf38ead07b8c0b4bfb8ea0ca9d5267d0384347c2 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 52ca63344dfb45050d57822c7bedbda2ef274e33..ea415c3df00550d4384bc1782dc4d64ec1010a6c 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 65b3cce868eb803051a959f49f4fb0357626f673..24a3ca14b6ef10ffc02604fe970f6f92651b2e0b 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 fe6ad8a8f0294ba77b4625bed34203dd9b9a656a..52d7eeecbf3d85da475b7cac2af4e3f1195b4f80 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 ed50317b35582cb5632e03fbcc4240376aae6e5d..5f4b6568c1fe3c4af25a29704f671845b179ed17 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 9ad787b3d9c56e7cea641c129ba3ef0ec8c88da7..5742d282b7b35dac81845709d657ec7eb6ba6d5c 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 262a97bfd120eedb69afe0406b4cac94be8d2541..45b66a602b1d00051c619c5fd695bb1770100b3b 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 7a1df7b2f9d0e32647ec0c9f0ec627198b087d89..23c89878e50c562cd03611a3d55e8821de24d12a 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 7528a78212d79b64ecb85de9572f071909590062..cb18f764efc529e552438f124fe83fa63df3042b 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 99a6966a8b4dbd4762b03c2c34e5e00f63ee0230..76e61c36a82f903e85ccd4055e3e09a250b4c5c7 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,
@@ -116,107 +115,6 @@ typedef enum
   GST_BUFTYPE_MPEG4_AAC,
 } 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.
@@ -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 bd26f1c2b5ffaee32027bab53f84b7f0c055ab36..388adcd8d52d086053ee73ffb4fcc16067fa4caf 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 3a3efe3d7946c2a210792cef07852e3dc5ad8f40..6f28d37c318ad190eb2a419fc1a20dc58cfc4bc0 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 a1ce234fb187a69dcdcc401ea52cf1e01a6fafbe..59a32ab755f4fcd47d3645c0a37f1ab61c658ace 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 bf6465c2e2523c8041bb85ecbd796f4cda388082..4cf7f746b997902a65b7472491b5ac64dd2df0ff 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 524098c2aa911ea6f26122c269805fec31563985..65d13093e0fb22a92352a807c2e0424a6ca551e4 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 ccc40146d508dc925ed96bff825c3c1c6ec9b49b..638a42a8156a3f01d4717de40208b5dc17b02d88 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 15620886120cd63fc166d8f8afcb77d954e243a2..6cf8775733f8374e2dbca1966addc100c6fee6f0 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 9370d380694e4e1619da9c098d70cb6a7b7bcc5b..62f324f60a61a2999b90ebb500ef42cdeba0b587 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 2155397cb4e95f74a4d2e715213d4a50d57bfe3b..aea2c92f60513508d364f013e3583c8170def3a5 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 055f28d7af02397032beeb62040f4463786be5d3..033068639af5c39f959974c762c3d0752356f3e2 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 72c33558f79144b942f776be28a90cb759e40f18..bcb6625d8a07253e2c7e7787374f5c381cc43e1d 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 7ba9ddda4b9721ad539b8969a66908159924cab5..8661c24ad3e3598682bb2de79b3006ce6ebef07d 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 f2eafcfc9b01433f6489396c042d648827fee0ed..b0b191efd0d4a8f962ffd087c8444cd622bf47cd 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 f2be5c702a12467a5b0afa2aa51768c1d33be350..9c2999c8dd02a14f436aae1e6716852861eb6419 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 5b9e162b0a630891593b89a0adf4c85d0aac6a66..29464b0b3efbd6194d5434613faec6a576c92360 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 f5f746482ddd1e0b1789822514b6e8857e44f8df..da75b64581b362d734430811d53dc7f68920fbd8 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 67a2c0bbb2765efa14759ead9d57760c066bad60..c00f9ff1cc8fd43f4be0689fc00762f179de8524 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 84432695ad69a9003f376e57035e9997473d949c..b545787f2c2cdd0e49a2eaae0969f77c392a52b0 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 529ad63c3eeda63fe1dbafe35cf15e6b2fc2f460..29c4285331b09023b0c0680ca604b9bbed81f0a0 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 5fb156e5185f65be6ed6eb91a95b1ce9aa1511a8..7f9ef35b52e6d2063cfb9ff261a7125c98bb84b5 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 1dc37e52a31120f890a476a8a916113647313058..bf76863a1e94fb84d67047cfcd2e6166c9e7a2f4 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);