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")
);
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:
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;
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)) {
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;
{
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) {
}
GST_ALSA_SINK_UNLOCK (asink);
- return length - (cptr * alsa->bytes_per_sample);
+ return length - (cptr * alsa->bpf);
write_error:
{
snd_pcm_format_t format;
guint rate;
guint channels;
- gint bytes_per_sample;
+ gint bpf;
gboolean iec958;
gboolean need_swap;
#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 ]")
);
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:
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;
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;
alsa = GST_ALSA_SRC (asrc);
- cptr = length / alsa->bytes_per_sample;
+ cptr = length / alsa->bpf;
ptr = data;
GST_ALSA_SRC_LOCK (asrc);
}
GST_ALSA_SRC_UNLOCK (asrc);
- return length - (cptr * alsa->bytes_per_sample);
+ return length - (cptr * alsa->bpf);
read_error:
{
snd_pcm_format_t format;
guint rate;
guint channels;
- gint bytes_per_sample;
+ gint bpf;
gboolean driver_timestamps;
guint buffer_time;
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,
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 =
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;
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 */
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;
}
/* 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;
}
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;
#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))
#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);
#endif
gboolean initialized;
- guint width;
+ GstAudioInfo info;
/* list of buffers that need timestamps */
GList *queued;
* 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));
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;
}
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;
}
#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;
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;
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;
}
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;
}
#define __GST_VORBIS_DEC_LIB_H__
#include <gst/gst.h>
+#include <gst/audio/audio.h>
#ifndef TREMOR
#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)
#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
#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__ */
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 \
# 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
/* 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
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
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;
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;
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
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
-#include <gst/audio/gstringbuffer.h>
+#include <gst/audio/audio.h>
G_BEGIN_DECLS
GstBaseTransform basetransform;
/*< protected >*/
- GstRingBufferSpec format; /* currently configured format */
+ GstAudioInfo info; /* currently configured format */
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
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];
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;
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);
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,
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 */
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 */
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 %"
/* 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;
{
if (!sink->ringbuffer)
return TRUE;
- if (!sink->ringbuffer->spec.rate)
+ if (!sink->ringbuffer->spec.info.rate)
return TRUE;
/* if PLAYING is interrupted,
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
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
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. */
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;
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,
guint8 *data;
gsize size;
guint samples, written;
- gint bps;
+ gint bpf, rate;
gint accum;
gint out_samples;
GstClockTime base_time, render_delay, latency;
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);
/* 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
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;
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
break;
samples -= written;
- offset += written * bps;
+ offset += written * bpf;
} while (TRUE);
gst_buffer_unmap (buf, data, size);
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);
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 %"
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);
}
{
GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
GstRingBufferSpec *spec;
+ gint bpf, rate;
spec = &src->ringbuffer->spec;
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);
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);
{
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,
guchar *data, *ptr;
guint samples, total_samples;
guint64 sample;
- gint bps;
+ gint bpf, rate;
GstRingBuffer *ringbuffer;
GstRingBufferSpec *spec;
guint read;
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)
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);
/* read next samples */
sample += read;
samples -= read;
- ptr += read * bps;
+ ptr += read * bpf;
} while (TRUE);
gst_buffer_unmap (buf, data, 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)))
/* 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;
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;
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
(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",
"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
/**
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);
for (i = 0; i < bytes; i++) {
GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]);
}
+#endif
}
/**
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",
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);
}
/**
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);
/* 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
gst_ring_buffer_debug_spec_caps (spec);
gst_ring_buffer_debug_spec_buff (spec);
+ spec->info = info;
+
return TRUE;
/* ERRORS */
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,
/* 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;
}
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;
*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;
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;
{
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);
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 */
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");
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;
#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
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
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
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
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
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;
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;
/* 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) {
/* 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);
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:
guint len)
{
gint segdone;
- gint segsize, segtotal, bps, sps;
+ gint segsize, segtotal, bpf, sps;
guint8 *dest;
guint to_read;
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;
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;
}
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;
#define __GST_RING_BUFFER_H__
#include <gst/gst.h>
+#include <gst/audio/audio.h>
G_BEGIN_DECLS
/**
* 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
*/
typedef enum
{
- GST_BUFTYPE_LINEAR,
- GST_BUFTYPE_FLOAT,
+ GST_BUFTYPE_RAW,
GST_BUFTYPE_MU_LAW,
GST_BUFTYPE_A_LAW,
GST_BUFTYPE_IMA_ADPCM,
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.
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
* 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. */
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 */
#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
/* 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
*
* 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],
*/
#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,
/* 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",
(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;
}
}
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);
/* 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 {
/* 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
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);
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);
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;
}
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);
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) {
}
/* 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
#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)
} GstAudioConvertNoiseShaping;
typedef struct _AudioConvertCtx AudioConvertCtx;
+#if 0
typedef struct _AudioConvertFmt AudioConvertFmt;
struct _AudioConvertFmt
gint unit_size;
};
+#endif
typedef void (*AudioConvertUnpack) (gpointer src, gpointer dst, gint scale,
gint count);
struct _AudioConvertCtx
{
- AudioConvertFmt in;
- AudioConvertFmt out;
+ GstAudioInfo in;
+ GstAudioInfo out;
AudioConvertUnpack unpack;
AudioConvertPack pack;
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);
/* 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
*
* <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.
* |[
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
/*** 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",
/*** 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;
}
}
-/* 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] = {
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));
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);
}
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;
}
}
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)
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 */
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;
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
#include "audioconvert.h"
{
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);
{
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;
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;
}
}
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;
}
*/
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;
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 */
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;
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);
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);
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)
};
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);
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;
}
}
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;;
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;;
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:
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 */
*/
/* 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);
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;
}
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,
", 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));
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);
* 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);
} 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;
/* truncate buffer */
truncsamples = audiorate->next_offset - in_offset;
- truncsize = truncsamples * audiorate->bytes_per_sample;
+ truncsize = truncsamples * bpf;
leftsize = in_size - truncsize;
trunc =
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) {
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:
GstPad *sinkpad, *srcpad;
/* audio format */
- gint bytes_per_sample;
- gint rate;
+ GstAudioInfo info;
/* stats */
guint64 in, out, add, drop;
$(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) \
* <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>
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
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);
resample->tmp_out = NULL;
resample->tmp_out_size = 0;
- gst_caps_replace (&resample->sinkcaps, NULL);
- gst_caps_replace (&resample->srccaps, NULL);
-
return TRUE;
}
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 *
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)
{
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);
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;
}
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,
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)
GstBaseTransform element;
/* <private> */
-
- GstCaps *srccaps, *sinkcaps;
-
gboolean need_discont;
GstClockTime t0;
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;
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
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 ]")
);
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;
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);
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
{
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) {
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;
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;
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); \
} \
} \
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); \
} \
} \
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); \
} \
} \
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); \
} \
} \
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);
{ \
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)); \
} \
}
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); \
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)]; \
} \
}
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++) { \
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; \
} \
} \
}
{ \
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)); \
} \
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; \
{ \
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; \
{ \
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; \
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;
{
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,
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;
gint bytes, samples;
GstElementClass *eclass;
guint8 *data;
+ gint samplerate, bpf;
src = GST_AUDIO_TEST_SRC (basesrc);
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)
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;
}
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));
#include <gst/gst.h>
#include <gst/base/gstbasesrc.h>
+#include <gst/audio/audio.h>
+
G_BEGIN_DECLS
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;
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 ? */
#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; " \
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);
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);
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;
/* 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);
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;
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);