pa_channel_map * gst_pulse_gst_to_channel_map (pa_channel_map * map, const GstRingBufferSpec * spec) { int i; GstAudioChannelPosition *pos; pa_channel_map_init (map); if (!(pos = gst_audio_get_channel_positions (gst_caps_get_structure (spec->caps, 0)))) { return NULL; } for (i = 0; i < spec->channels; i++) { if (pos[i] == GST_AUDIO_CHANNEL_POSITION_NONE) { /* no valid mappings for these channels */ g_free (pos); return NULL; } else if (pos[i] < GST_AUDIO_CHANNEL_POSITION_NUM) map->map[i] = gst_pos_to_pa[pos[i]]; else map->map[i] = PA_CHANNEL_POSITION_INVALID; } g_free (pos); map->channels = spec->channels; if (!pa_channel_map_valid (map)) { return NULL; } return map; }
static gboolean gst_wavpack_enc_sink_set_caps (GstPad * pad, GstCaps * caps) { GstWavpackEnc *enc = GST_WAVPACK_ENC (gst_pad_get_parent (pad)); GstStructure *structure = gst_caps_get_structure (caps, 0); GstAudioChannelPosition *pos; if (!gst_structure_get_int (structure, "channels", &enc->channels) || !gst_structure_get_int (structure, "rate", &enc->samplerate) || !gst_structure_get_int (structure, "depth", &enc->depth)) { GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL), ("got invalid caps: %" GST_PTR_FORMAT, caps)); gst_object_unref (enc); return FALSE; } pos = gst_audio_get_channel_positions (structure); /* If one channel is NONE they'll be all undefined */ if (pos != NULL && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { g_free (pos); pos = NULL; } if (pos == NULL) { GST_ELEMENT_ERROR (enc, STREAM, FORMAT, (NULL), ("input has no valid channel layout")); gst_object_unref (enc); return FALSE; } enc->channel_mask = gst_wavpack_get_channel_mask_from_positions (pos, enc->channels); enc->need_channel_remap = gst_wavpack_set_channel_mapping (pos, enc->channels, enc->channel_mapping); g_free (pos); /* set fixed src pad caps now that we know what we will get */ caps = gst_caps_new_simple ("audio/x-wavpack", "channels", G_TYPE_INT, enc->channels, "rate", G_TYPE_INT, enc->samplerate, "width", G_TYPE_INT, enc->depth, "framed", G_TYPE_BOOLEAN, TRUE, NULL); if (!gst_wavpack_set_channel_layout (caps, enc->channel_mask)) GST_WARNING_OBJECT (enc, "setting channel layout failed"); if (!gst_pad_set_caps (enc->srcpad, caps)) { GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL), ("setting caps failed: %" GST_PTR_FORMAT, caps)); gst_caps_unref (caps); gst_object_unref (enc); return FALSE; } gst_pad_use_fixed_caps (enc->srcpad); gst_caps_unref (caps); gst_object_unref (enc); return TRUE; }
GstFlowReturn AudioFileReader::handleBuffer(GstAppSink* sink) { GstBuffer* buffer = gst_app_sink_pull_buffer(sink); if (!buffer) return GST_FLOW_ERROR; GstCaps* caps = gst_buffer_get_caps(buffer); GstStructure* structure = gst_caps_get_structure(caps, 0); gint channels = 0; if (!gst_structure_get_int(structure, "channels", &channels) || !channels) { gst_caps_unref(caps); gst_buffer_unref(buffer); return GST_FLOW_ERROR; } gint sampleRate = 0; if (!gst_structure_get_int(structure, "rate", &sampleRate) || !sampleRate) { gst_caps_unref(caps); gst_buffer_unref(buffer); return GST_FLOW_ERROR; } gint width = 0; if (!gst_structure_get_int(structure, "width", &width) || !width) { gst_caps_unref(caps); gst_buffer_unref(buffer); return GST_FLOW_ERROR; } GstClockTime duration = (static_cast<guint64>(GST_BUFFER_SIZE(buffer)) * 8 * GST_SECOND) / (sampleRate * channels * width); int frames = GST_CLOCK_TIME_TO_FRAMES(duration, sampleRate); // Check the first audio channel. The buffer is supposed to store // data of a single channel anyway. GstAudioChannelPosition* positions = gst_audio_get_channel_positions(structure); switch (positions[0]) { case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: gst_buffer_list_iterator_add(m_frontLeftBuffersIterator, buffer); m_channelSize += frames; break; case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: gst_buffer_list_iterator_add(m_frontRightBuffersIterator, buffer); break; default: gst_buffer_unref(buffer); break; } g_free(positions); gst_caps_unref(caps); return GST_FLOW_OK; }
static gboolean gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps) { GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad)); GstStructure *structure = gst_caps_get_structure (caps, 0); /* Check if we can set the caps here already */ if (gst_structure_get_int (structure, "channels", &dec->channels) && gst_structure_get_int (structure, "rate", &dec->sample_rate) && gst_structure_get_int (structure, "width", &dec->depth)) { GstCaps *caps; GstAudioChannelPosition *pos; caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, dec->sample_rate, "channels", G_TYPE_INT, dec->channels, "depth", G_TYPE_INT, dec->depth, "width", G_TYPE_INT, 32, "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, NULL); /* If we already have the channel layout set from upstream * take this */ if (gst_structure_has_field (structure, "channel-positions")) { pos = gst_audio_get_channel_positions (structure); if (pos != NULL && dec->channels > 2) { GstStructure *new_str = gst_caps_get_structure (caps, 0); gst_audio_set_channel_positions (new_str, pos); dec->channel_mask = gst_wavpack_get_channel_mask_from_positions (pos, dec->channels); } if (pos != NULL) g_free (pos); } GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps); /* should always succeed */ gst_pad_set_caps (dec->srcpad, caps); gst_caps_unref (caps); /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something * is decoded or after the format has changed */ gst_wavpack_dec_post_tags (dec); } gst_object_unref (dec); return TRUE; }
static gboolean query_data(struct input_handle* ih) { GstBuffer *preroll; GstCaps *src_caps; GstStructure *s; int i; ih->n_channels = 0; ih->sample_rate = 0; ih->channel_positions = NULL; preroll = gst_app_sink_pull_preroll(GST_APP_SINK(ih->appsink)); src_caps = gst_buffer_get_caps(preroll); s = gst_caps_get_structure(src_caps, 0); gst_structure_get_int(s, "rate", &(ih->sample_rate)); gst_structure_get_int(s, "channels", &(ih->n_channels)); if (!ih->sample_rate || !ih->n_channels) { gst_caps_unref(src_caps); gst_buffer_unref(preroll); return FALSE; } ih->channel_positions = gst_audio_get_channel_positions(s); if (verbose) { if (ih->channel_positions) { for (i = 0; i < ih->n_channels; ++i) { printf("Channel %d: %d\n", i, ih->channel_positions[i]); } } g_print ("%d channels @ %d Hz\n", ih->n_channels, ih->sample_rate); } gst_caps_unref(src_caps); gst_buffer_unref(preroll); return TRUE; }
static gboolean gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps) { GstDeinterleave *self; GstCaps *srccaps; GstStructure *s; self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps); if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) { gint new_channels, i; GstAudioChannelPosition *pos; gboolean same_layout = TRUE; s = gst_caps_get_structure (caps, 0); /* We allow caps changes as long as the number of channels doesn't change * and the channel positions stay the same. _getcaps() should've cared * for this already but better be safe. */ if (!gst_structure_get_int (s, "channels", &new_channels) || new_channels != self->channels || !gst_deinterleave_set_process_function (self, caps)) goto cannot_change_caps; /* Now check the channel positions. If we had no channel positions * and get them or the other way around things have changed. * If we had channel positions and get different ones things have * changed too of course */ pos = gst_audio_get_channel_positions (s); if ((pos && !self->pos) || (!pos && self->pos)) goto cannot_change_caps; if (pos) { for (i = 0; i < self->channels; i++) { if (self->pos[i] != pos[i]) { same_layout = FALSE; break; } } g_free (pos); if (!same_layout) goto cannot_change_caps; } } else { s = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (s, "channels", &self->channels)) goto no_channels; if (!gst_deinterleave_set_process_function (self, caps)) goto unsupported_caps; self->pos = gst_audio_get_channel_positions (s); } gst_caps_replace (&self->sinkcaps, caps); /* Get srcpad caps */ srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL); gst_structure_remove_field (s, "channel-positions"); /* If we already have pads, update the caps otherwise * add new pads */ if (self->srcpads) { gst_deinterleave_set_pads_caps (self, srccaps); } else { gst_deinterleave_add_new_pads (self, srccaps); } gst_caps_unref (srccaps); gst_object_unref (self); return TRUE; cannot_change_caps: { GST_ERROR_OBJECT (self, "can't set new caps: %" GST_PTR_FORMAT, caps); gst_object_unref (self); return FALSE; } unsupported_caps: { GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps); gst_object_unref (self); return FALSE; } no_channels: { GST_ERROR_OBJECT (self, "invalid caps"); gst_object_unref (self); return FALSE; } }
static gboolean gst_rtp_g722_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps) { GstRtpG722Pay *rtpg722pay; GstStructure *structure; gint rate, channels, clock_rate; gboolean res; gchar *params; #if 0 GstAudioChannelPosition *pos; const GstRTPChannelOrder *order; #endif GstRTPBaseAudioPayload *rtpbaseaudiopayload; rtpbaseaudiopayload = GST_RTP_BASE_AUDIO_PAYLOAD (basepayload); rtpg722pay = GST_RTP_G722_PAY (basepayload); structure = gst_caps_get_structure (caps, 0); /* first parse input caps */ if (!gst_structure_get_int (structure, "rate", &rate)) goto no_rate; if (!gst_structure_get_int (structure, "channels", &channels)) goto no_channels; /* FIXME: Do something with the channel positions */ #if 0 /* get the channel order */ pos = gst_audio_get_channel_positions (structure); if (pos) order = gst_rtp_channels_get_by_pos (channels, pos); else order = NULL; #endif /* Clock rate is always 8000 Hz for G722 according to * RFC 3551 although the sampling rate is 16000 Hz */ clock_rate = 8000; gst_rtp_base_payload_set_options (basepayload, "audio", basepayload->pt != GST_RTP_PAYLOAD_G722, "G722", clock_rate); params = g_strdup_printf ("%d", channels); #if 0 if (!order && channels > 2) { GST_ELEMENT_WARNING (rtpg722pay, STREAM, DECODE, (NULL), ("Unknown channel order for %d channels", channels)); } if (order && order->name) { res = gst_rtp_base_payload_set_outcaps (basepayload, "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT, channels, "channel-order", G_TYPE_STRING, order->name, NULL); } else { #endif res = gst_rtp_base_payload_set_outcaps (basepayload, "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT, channels, NULL); #if 0 } #endif g_free (params); #if 0 g_free (pos); #endif rtpg722pay->rate = rate; rtpg722pay->channels = channels; /* bits-per-sample is 4 * channels for G722, but as the RTP clock runs at * half speed (8 instead of 16 khz), pretend it's 8 bits per sample * channels. */ gst_rtp_base_audio_payload_set_samplebits_options (rtpbaseaudiopayload, 8 * rtpg722pay->channels); return res; /* ERRORS */ no_rate: { GST_DEBUG_OBJECT (rtpg722pay, "no rate given"); return FALSE; } no_channels: { GST_DEBUG_OBJECT (rtpg722pay, "no channels given"); return FALSE; } }
static gboolean gst_rtp_g722_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps) { GstRtpG722Pay *rtpg722pay; GstStructure *structure; gint rate, channels, clock_rate; gboolean res; gchar *params; GstAudioChannelPosition *pos; const GstRTPChannelOrder *order; GstBaseRTPAudioPayload *basertpaudiopayload; basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (basepayload); rtpg722pay = GST_RTP_G722_PAY (basepayload); structure = gst_caps_get_structure (caps, 0); /* first parse input caps */ if (!gst_structure_get_int (structure, "rate", &rate)) goto no_rate; if (!gst_structure_get_int (structure, "channels", &channels)) goto no_channels; /* get the channel order */ pos = gst_audio_get_channel_positions (structure); if (pos) order = gst_rtp_channels_get_by_pos (channels, pos); else order = NULL; /* Clock rate is always 8000 Hz for G722 according to * RFC 3551 although the sampling rate is 16000 Hz */ clock_rate = 8000; gst_basertppayload_set_options (basepayload, "audio", TRUE, "G722", clock_rate); params = g_strdup_printf ("%d", channels); if (!order && channels > 2) { GST_ELEMENT_WARNING (rtpg722pay, STREAM, DECODE, (NULL), ("Unknown channel order for %d channels", channels)); } if (order && order->name) { res = gst_basertppayload_set_outcaps (basepayload, "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT, channels, "channel-order", G_TYPE_STRING, order->name, NULL); } else { res = gst_basertppayload_set_outcaps (basepayload, "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT, channels, NULL); } g_free (params); g_free (pos); rtpg722pay->rate = rate; rtpg722pay->channels = channels; /* octet-per-sample is 1 * channels for G722 */ gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload, 4 * rtpg722pay->channels); return res; /* ERRORS */ no_rate: { GST_DEBUG_OBJECT (rtpg722pay, "no rate given"); return FALSE; } no_channels: { GST_DEBUG_OBJECT (rtpg722pay, "no channels given"); return FALSE; } }
gboolean gst_core_audio_set_channels_layout (GstCoreAudio * core_audio, gint channels, GstCaps * caps) { /* Configure the output stream and allocate ringbuffer memory */ AudioChannelLayout *layout = NULL; OSStatus status; int layoutSize, element, i; AudioUnitScope scope; GstStructure *structure; GstAudioChannelPosition *positions; /* Describe channels */ layoutSize = sizeof (AudioChannelLayout) + channels * sizeof (AudioChannelDescription); layout = g_malloc (layoutSize); structure = gst_caps_get_structure (caps, 0); positions = gst_audio_get_channel_positions (structure); layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; layout->mChannelBitmap = 0; /* Not used */ layout->mNumberChannelDescriptions = channels; for (i = 0; i < channels; i++) { if (positions) { layout->mChannelDescriptions[i].mChannelLabel = gst_audio_channel_position_to_coreaudio_channel_label (positions[i], i); } else { /* Discrete channel numbers are ORed into this */ layout->mChannelDescriptions[i].mChannelLabel = kAudioChannelLabel_Discrete_0 | i; } /* Others unused */ layout->mChannelDescriptions[i].mChannelFlags = 0; layout->mChannelDescriptions[i].mCoordinates[0] = 0.f; layout->mChannelDescriptions[i].mCoordinates[1] = 0.f; layout->mChannelDescriptions[i].mCoordinates[2] = 0.f; } if (positions) { g_free (positions); positions = NULL; } scope = core_audio->is_src ? kAudioUnitScope_Output : kAudioUnitScope_Input; element = core_audio->is_src ? 1 : 0; if (layoutSize) { status = AudioUnitSetProperty (core_audio->audiounit, kAudioUnitProperty_AudioChannelLayout, scope, element, layout, layoutSize); if (status) { GST_WARNING_OBJECT (core_audio->osxbuf, "Failed to set output channel layout: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (status)); return FALSE; } } g_free (layout); return TRUE; }