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