gboolean gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f, guint * channels) { pa_format_info *format; pa_sample_format_t sf = PA_SAMPLE_INVALID; GstAudioInfo *ainfo = &spec->info; format = pa_format_info_new (); if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MU_LAW && GST_AUDIO_INFO_WIDTH (ainfo) == 8) { format->encoding = PA_ENCODING_PCM; sf = PA_SAMPLE_ULAW; } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_A_LAW && GST_AUDIO_INFO_WIDTH (ainfo) == 8) { format->encoding = PA_ENCODING_PCM; sf = PA_SAMPLE_ALAW; } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) { format->encoding = PA_ENCODING_PCM; if (!gstaudioformat_to_pasampleformat (GST_AUDIO_INFO_FORMAT (ainfo), &sf)) goto fail; } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3) { format->encoding = PA_ENCODING_AC3_IEC61937; } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3) { format->encoding = PA_ENCODING_EAC3_IEC61937; } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS) { format->encoding = PA_ENCODING_DTS_IEC61937; } else if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG) { format->encoding = PA_ENCODING_MPEG_IEC61937; } else { goto fail; } if (format->encoding == PA_ENCODING_PCM) { pa_format_info_set_sample_format (format, sf); pa_format_info_set_channels (format, GST_AUDIO_INFO_CHANNELS (ainfo)); } pa_format_info_set_rate (format, GST_AUDIO_INFO_RATE (ainfo)); if (!pa_format_info_valid (format)) goto fail; *f = format; *channels = GST_AUDIO_INFO_CHANNELS (ainfo); return TRUE; fail: if (format) pa_format_info_free (format); return FALSE; }
void gst_audio_parse_update_frame_size (GstAudioParse * ap) { gint framesize, width; switch (ap->format) { case GST_AUDIO_PARSE_FORMAT_ALAW: case GST_AUDIO_PARSE_FORMAT_MULAW: width = 8; break; case GST_AUDIO_PARSE_FORMAT_RAW: default: { GstAudioInfo info; gst_audio_info_init (&info); /* rate, etc do not really matter here */ gst_audio_info_set_format (&info, ap->raw_format, 44100, ap->channels, NULL); width = GST_AUDIO_INFO_WIDTH (&info); break; } } framesize = (width / 8) * ap->channels; gst_raw_parse_set_framesize (GST_RAW_PARSE (ap), framesize); }
static GstFlowReturn gst_deinterleave_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstDeinterleave *self = GST_DEINTERLEAVE (parent); GstFlowReturn ret; g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED); g_return_val_if_fail (GST_AUDIO_INFO_WIDTH (&self->audio_info) > 0, GST_FLOW_NOT_NEGOTIATED); g_return_val_if_fail (GST_AUDIO_INFO_CHANNELS (&self->audio_info) > 0, GST_FLOW_NOT_NEGOTIATED); ret = gst_deinterleave_process (self, buffer); if (ret != GST_FLOW_OK) GST_DEBUG_OBJECT (self, "flow return: %s", gst_flow_get_name (ret)); return ret; }
static gboolean gst_audio_segment_clip_set_caps (GstSegmentClip * base, GstCaps * caps) { GstAudioSegmentClip *self = GST_AUDIO_SEGMENT_CLIP (base); gboolean ret; GstAudioInfo info; gint rate, channels, width; gst_audio_info_init (&info); ret = gst_audio_info_from_caps (&info, caps); if (ret) { rate = GST_AUDIO_INFO_RATE (&info); channels = GST_AUDIO_INFO_CHANNELS (&info); width = GST_AUDIO_INFO_WIDTH (&info); GST_DEBUG_OBJECT (self, "Configured: rate %d channels %d width %d", rate, channels, width); self->rate = rate; self->framesize = (width / 8) * channels; } return ret; }
static gboolean gst_deinterleave_set_process_function (GstDeinterleave * self) { switch (GST_AUDIO_INFO_WIDTH (&self->audio_info)) { case 8: self->func = (GstDeinterleaveFunc) deinterleave_8; break; case 16: self->func = (GstDeinterleaveFunc) deinterleave_16; break; case 24: self->func = (GstDeinterleaveFunc) deinterleave_24; break; case 32: self->func = (GstDeinterleaveFunc) deinterleave_32; break; case 64: self->func = (GstDeinterleaveFunc) deinterleave_64; break; default: return FALSE; } return TRUE; }
static gboolean gst_wavenc_sink_setcaps (GstPad * pad, GstCaps * caps) { GstWavEnc *wavenc; GstStructure *structure; const gchar *name; gint chans, rate; GstCaps *ccaps; wavenc = GST_WAVENC (gst_pad_get_parent (pad)); ccaps = gst_pad_get_current_caps (pad); if (wavenc->sent_header && ccaps && !gst_caps_can_intersect (caps, ccaps)) { gst_caps_unref (ccaps); GST_WARNING_OBJECT (wavenc, "cannot change format in middle of stream"); goto fail; } if (ccaps) gst_caps_unref (ccaps); GST_DEBUG_OBJECT (wavenc, "got caps: %" GST_PTR_FORMAT, caps); structure = gst_caps_get_structure (caps, 0); name = gst_structure_get_name (structure); if (!gst_structure_get_int (structure, "channels", &chans) || !gst_structure_get_int (structure, "rate", &rate)) { GST_WARNING_OBJECT (wavenc, "caps incomplete"); goto fail; } if (strcmp (name, "audio/x-raw") == 0) { GstAudioInfo info; if (!gst_audio_info_from_caps (&info, caps)) goto fail; if (GST_AUDIO_INFO_IS_INTEGER (&info)) wavenc->format = GST_RIFF_WAVE_FORMAT_PCM; else if (GST_AUDIO_INFO_IS_FLOAT (&info)) wavenc->format = GST_RIFF_WAVE_FORMAT_IEEE_FLOAT; else goto fail; wavenc->width = GST_AUDIO_INFO_WIDTH (&info); } else if (strcmp (name, "audio/x-alaw") == 0) { wavenc->format = GST_RIFF_WAVE_FORMAT_ALAW; wavenc->width = 8; } else if (strcmp (name, "audio/x-mulaw") == 0) { wavenc->format = GST_RIFF_WAVE_FORMAT_MULAW; wavenc->width = 8; } else { GST_WARNING_OBJECT (wavenc, "Unsupported format %s", name); goto fail; } wavenc->channels = chans; wavenc->rate = rate; GST_LOG_OBJECT (wavenc, "accepted caps: format=0x%04x chans=%u width=%u rate=%u", wavenc->format, wavenc->channels, wavenc->width, wavenc->rate); gst_object_unref (wavenc); return TRUE; fail: gst_object_unref (wavenc); return FALSE; }
static gboolean gst_interleave_sink_setcaps (GstInterleave * self, GstPad * pad, const GstCaps * caps, const GstAudioInfo * info) { g_return_val_if_fail (GST_IS_INTERLEAVE_PAD (pad), FALSE); /* TODO: handle caps changes */ if (self->sinkcaps && !gst_caps_is_subset (caps, self->sinkcaps)) { goto cannot_change_caps; } else { GstCaps *srccaps; GstStructure *s; gboolean res; self->width = GST_AUDIO_INFO_WIDTH (info); self->rate = GST_AUDIO_INFO_RATE (info); gst_interleave_set_process_function (self); srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); gst_structure_remove_field (s, "channel-mask"); gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL); gst_interleave_set_channel_positions (self, s); gst_pad_set_active (self->src, TRUE); res = gst_pad_set_caps (self->src, srccaps); gst_caps_unref (srccaps); if (!res) goto src_did_not_accept; } if (!self->sinkcaps) { GstCaps *sinkcaps = gst_caps_copy (caps); GstStructure *s = gst_caps_get_structure (sinkcaps, 0); gst_structure_remove_field (s, "channel-mask"); GST_DEBUG_OBJECT (self, "setting sinkcaps %" GST_PTR_FORMAT, sinkcaps); gst_caps_replace (&self->sinkcaps, sinkcaps); gst_caps_unref (sinkcaps); } return TRUE; cannot_change_caps: { GST_WARNING_OBJECT (self, "caps of %" GST_PTR_FORMAT " already set, can't " "change", self->sinkcaps); return FALSE; } src_did_not_accept: { GST_WARNING_OBJECT (self, "src did not accept setcaps()"); return FALSE; } }
gboolean gst_sndio_prepare (struct gstsndio *sio, GstAudioRingBufferSpec *spec) { struct sio_par par, retpar; unsigned nchannels; GST_DEBUG_OBJECT (sio, "prepare"); if (spec->type != GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) { GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE, ("Only raw buffer format supported by sndio"), (NULL)); return FALSE; } if (!GST_AUDIO_INFO_IS_INTEGER(&spec->info)) { GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE, ("Only integer format supported"), (NULL)); return FALSE; } if (GST_AUDIO_INFO_DEPTH(&spec->info) % 8) { GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE, ("Only depths multiple of 8 are supported"), (NULL)); return FALSE; } sio_initpar (&par); switch (GST_AUDIO_INFO_FORMAT (&spec->info)) { case GST_AUDIO_FORMAT_S8: case GST_AUDIO_FORMAT_U8: case GST_AUDIO_FORMAT_S16LE: case GST_AUDIO_FORMAT_S16BE: case GST_AUDIO_FORMAT_U16LE: case GST_AUDIO_FORMAT_U16BE: case GST_AUDIO_FORMAT_S32LE: case GST_AUDIO_FORMAT_S32BE: case GST_AUDIO_FORMAT_U32LE: case GST_AUDIO_FORMAT_U32BE: case GST_AUDIO_FORMAT_S24_32LE: case GST_AUDIO_FORMAT_S24_32BE: case GST_AUDIO_FORMAT_U24_32LE: case GST_AUDIO_FORMAT_U24_32BE: case GST_AUDIO_FORMAT_S24LE: case GST_AUDIO_FORMAT_S24BE: case GST_AUDIO_FORMAT_U24LE: case GST_AUDIO_FORMAT_U24BE: break; default: GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_READ_WRITE, ("Unsupported audio format"), ("format = %d", GST_AUDIO_INFO_FORMAT (&spec->info))); return FALSE; } par.sig = GST_AUDIO_INFO_IS_SIGNED(&spec->info); par.bits = GST_AUDIO_INFO_WIDTH(&spec->info); par.bps = GST_AUDIO_INFO_DEPTH(&spec->info) / 8; if (par.bps > 1) par.le = GST_AUDIO_INFO_IS_LITTLE_ENDIAN(&spec->info); if (par.bits < par.bps * 8) par.msb = 0; par.rate = GST_AUDIO_INFO_RATE(&spec->info); if (sio->mode == SIO_PLAY) par.pchan = GST_AUDIO_INFO_CHANNELS(&spec->info); else par.rchan = GST_AUDIO_INFO_CHANNELS(&spec->info); par.round = par.rate / 1000000. * spec->latency_time; par.appbufsz = par.rate / 1000000. * spec->buffer_time; if (!sio_setpar (sio->hdl, &par)) { GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE, ("Unsupported audio encoding"), (NULL)); return FALSE; } if (!sio_getpar (sio->hdl, &retpar)) { GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE, ("Couldn't get audio device parameters"), (NULL)); return FALSE; } #if 0 fprintf(stderr, "format = %s, " "requested: sig = %d, bits = %d, bps = %d, le = %d, msb = %d, " "rate = %d, pchan = %d, round = %d, appbufsz = %d; " "returned: sig = %d, bits = %d, bps = %d, le = %d, msb = %d, " "rate = %d, pchan = %d, round = %d, appbufsz = %d, bufsz = %d\n", GST_AUDIO_INFO_NAME(&spec->info), par.sig, par.bits, par.bps, par.le, par.msb, par.rate, par.pchan, par.round, par.appbufsz, retpar.sig, retpar.bits, retpar.bps, retpar.le, retpar.msb, retpar.rate, retpar.pchan, retpar.round, retpar.appbufsz, retpar.bufsz); #endif if (par.bits != retpar.bits || par.bps != retpar.bps || par.rate != retpar.rate || (sio->mode == SIO_PLAY && par.pchan != retpar.pchan) || (sio->mode == SIO_REC && par.rchan != retpar.rchan) || (par.bps > 1 && par.le != retpar.le) || (par.bits < par.bps * 8 && par.msb != retpar.msb)) { GST_ELEMENT_ERROR (sio, RESOURCE, OPEN_WRITE, ("Audio device refused requested parameters"), (NULL)); return FALSE; } nchannels = (sio->mode == SIO_PLAY) ? retpar.pchan : retpar.rchan; spec->segsize = retpar.round * retpar.bps * nchannels; spec->segtotal = retpar.bufsz / retpar.round; sio->bpf = retpar.bps * nchannels; sio->delay = 0; sio_onmove (sio->hdl, gst_sndio_cb, sio); if (!sio_start (sio->hdl)) { GST_ELEMENT_ERROR (sio->obj, RESOURCE, OPEN_READ_WRITE, ("Could not start sndio"), (NULL)); return FALSE; } return TRUE; }
static FLAC__StreamDecoderWriteStatus gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame, const FLAC__int32 * const buffer[]) { GstFlowReturn ret = GST_FLOW_OK; GstBuffer *outbuf; guint depth = frame->header.bits_per_sample; guint width, gdepth; guint sample_rate = frame->header.sample_rate; guint channels = frame->header.channels; guint samples = frame->header.blocksize; guint j, i; GstMapInfo map; gboolean caps_changed; GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples); if (depth == 0) { if (flacdec->depth < 4 || flacdec->depth > 32) { GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO", flacdec->depth); ret = GST_FLOW_ERROR; goto done; } depth = flacdec->depth; } switch (depth) { case 8: gdepth = width = 8; break; case 12: case 16: gdepth = width = 16; break; case 20: case 24: gdepth = 24; width = 32; break; case 32: gdepth = width = 32; break; default: GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth); ret = GST_FLOW_ERROR; goto done; } if (sample_rate == 0) { if (flacdec->info.rate != 0) { sample_rate = flacdec->info.rate; } else { GST_ERROR_OBJECT (flacdec, "unknown sample rate"); ret = GST_FLOW_ERROR; goto done; } } caps_changed = (sample_rate != GST_AUDIO_INFO_RATE (&flacdec->info)) || (width != GST_AUDIO_INFO_WIDTH (&flacdec->info)) || (gdepth != GST_AUDIO_INFO_DEPTH (&flacdec->info)) || (channels != GST_AUDIO_INFO_CHANNELS (&flacdec->info)); if (caps_changed || !gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (flacdec))) { GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels", sample_rate, channels); gst_audio_info_set_format (&flacdec->info, gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, gdepth), sample_rate, channels, NULL); memcpy (flacdec->info.position, channel_positions[flacdec->info.channels - 1], sizeof (GstAudioChannelPosition) * flacdec->info.channels); gst_audio_channel_positions_to_valid_order (flacdec->info.position, flacdec->info.channels); /* Note: we create the inverse reordering map here */ gst_audio_get_channel_reorder_map (flacdec->info.channels, flacdec->info.position, channel_positions[flacdec->info.channels - 1], flacdec->channel_reorder_map); flacdec->depth = depth; gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (flacdec), &flacdec->info); } outbuf = gst_buffer_new_allocate (NULL, samples * channels * (width / 8), NULL); gst_buffer_map (outbuf, &map, GST_MAP_WRITE); if (width == 8) { gint8 *outbuffer = (gint8 *) map.data; gint *reorder_map = flacdec->channel_reorder_map; if (gdepth != depth) { for (i = 0; i < samples; i++) { for (j = 0; j < channels; j++) { *outbuffer++ = (gint8) (buffer[reorder_map[j]][i] << (gdepth - depth)); } } } else { for (i = 0; i < samples; i++) { for (j = 0; j < channels; j++) { *outbuffer++ = (gint8) buffer[reorder_map[j]][i]; } } } } else if (width == 16) { gint16 *outbuffer = (gint16 *) map.data; gint *reorder_map = flacdec->channel_reorder_map; if (gdepth != depth) { for (i = 0; i < samples; i++) { for (j = 0; j < channels; j++) { *outbuffer++ = (gint16) (buffer[reorder_map[j]][i] << (gdepth - depth)); } } } else { for (i = 0; i < samples; i++) { for (j = 0; j < channels; j++) { *outbuffer++ = (gint16) buffer[reorder_map[j]][i]; } } } } else if (width == 32) { gint32 *outbuffer = (gint32 *) map.data; gint *reorder_map = flacdec->channel_reorder_map; if (gdepth != depth) { for (i = 0; i < samples; i++) { for (j = 0; j < channels; j++) { *outbuffer++ = (gint32) (buffer[reorder_map[j]][i] << (gdepth - depth)); } } } else { for (i = 0; i < samples; i++) { for (j = 0; j < channels; j++) { *outbuffer++ = (gint32) buffer[reorder_map[j]][i]; } } } } else { g_assert_not_reached (); } gst_buffer_unmap (outbuf, &map); GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples); if (flacdec->error_count) flacdec->error_count--; ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1); if (G_UNLIKELY (ret != GST_FLOW_OK)) { GST_DEBUG_OBJECT (flacdec, "finish_frame flow %s", gst_flow_get_name (ret)); } done: /* we act on the flow return value later in the handle_frame function, as we * don't want to mess up the internal decoder state by returning ABORT when * the error is in fact non-fatal (like a pad in flushing mode) and we want * to continue later. So just pretend everything's dandy and act later. */ flacdec->last_flow = ret; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; }
static GstFlowReturn gst_deinterleave_process (GstDeinterleave * self, GstBuffer * buf) { GstFlowReturn ret = GST_FLOW_OK; guint channels = GST_AUDIO_INFO_CHANNELS (&self->audio_info); guint pads_pushed = 0, buffers_allocated = 0; guint nframes = gst_buffer_get_size (buf) / channels / (GST_AUDIO_INFO_WIDTH (&self->audio_info) / 8); guint bufsize = nframes * (GST_AUDIO_INFO_WIDTH (&self->audio_info) / 8); guint i; GList *srcs; GstBuffer **buffers_out = g_new0 (GstBuffer *, channels); guint8 *in, *out; GstMapInfo read_info; GList *pending_events, *l; /* Send any pending events to all src pads */ GST_OBJECT_LOCK (self); pending_events = self->pending_events; self->pending_events = NULL; GST_OBJECT_UNLOCK (self); if (pending_events) { GstEvent *event; GST_DEBUG_OBJECT (self, "Sending pending events to all src pads"); for (l = pending_events; l; l = l->next) { event = l->data; for (srcs = self->srcpads; srcs != NULL; srcs = srcs->next) gst_pad_push_event (GST_PAD (srcs->data), gst_event_ref (event)); gst_event_unref (event); } g_list_free (pending_events); } gst_buffer_map (buf, &read_info, GST_MAP_READ); /* Allocate buffers */ for (srcs = self->srcpads, i = 0; srcs; srcs = srcs->next, i++) { buffers_out[i] = gst_buffer_new_allocate (NULL, bufsize, NULL); /* Make sure we got a correct buffer. The only other case we allow * here is an unliked pad */ if (!buffers_out[i]) goto alloc_buffer_failed; else if (buffers_out[i] && gst_buffer_get_size (buffers_out[i]) != bufsize) goto alloc_buffer_bad_size; if (buffers_out[i]) { gst_buffer_copy_into (buffers_out[i], buf, GST_BUFFER_COPY_METADATA, 0, -1); buffers_allocated++; } } /* Return NOT_LINKED if no pad was linked */ if (!buffers_allocated) { GST_WARNING_OBJECT (self, "Couldn't allocate any buffers because no pad was linked"); ret = GST_FLOW_NOT_LINKED; goto done; } /* deinterleave */ for (srcs = self->srcpads, i = 0; srcs; srcs = srcs->next, i++) { GstPad *pad = (GstPad *) srcs->data; GstMapInfo write_info; in = (guint8 *) read_info.data; in += i * (GST_AUDIO_INFO_WIDTH (&self->audio_info) / 8); if (buffers_out[i]) { gst_buffer_map (buffers_out[i], &write_info, GST_MAP_WRITE); out = (guint8 *) write_info.data; self->func (out, in, channels, nframes); gst_buffer_unmap (buffers_out[i], &write_info); ret = gst_pad_push (pad, buffers_out[i]); buffers_out[i] = NULL; if (ret == GST_FLOW_OK) pads_pushed++; else if (ret == GST_FLOW_NOT_LINKED) ret = GST_FLOW_OK; else goto push_failed; } } /* Return NOT_LINKED if no pad was linked */ if (!pads_pushed) ret = GST_FLOW_NOT_LINKED; GST_DEBUG_OBJECT (self, "Pushed on %d pads", pads_pushed); done: gst_buffer_unmap (buf, &read_info); gst_buffer_unref (buf); g_free (buffers_out); return ret; alloc_buffer_failed: { GST_WARNING ("gst_pad_alloc_buffer() returned %s", gst_flow_get_name (ret)); goto clean_buffers; } alloc_buffer_bad_size: { GST_WARNING ("called alloc_buffer(), but didn't get requested bytes"); ret = GST_FLOW_NOT_NEGOTIATED; goto clean_buffers; } push_failed: { GST_DEBUG ("push() failed, flow = %s", gst_flow_get_name (ret)); goto clean_buffers; } clean_buffers: { gst_buffer_unmap (buf, &read_info); for (i = 0; i < channels; i++) { if (buffers_out[i]) gst_buffer_unref (buffers_out[i]); } gst_buffer_unref (buf); g_free (buffers_out); return ret; } }
static gboolean gst_osx_audio_ring_buffer_acquire (GstAudioRingBuffer * buf, GstAudioRingBufferSpec * spec) { gboolean ret = FALSE, is_passthrough = FALSE; GstOsxAudioRingBuffer *osxbuf; AudioStreamBasicDescription format; osxbuf = GST_OSX_AUDIO_RING_BUFFER (buf); if (RINGBUFFER_IS_SPDIF (spec->type)) { format.mFormatID = kAudioFormat60958AC3; format.mSampleRate = (double) GST_AUDIO_INFO_RATE (&spec->info); format.mChannelsPerFrame = 2; format.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonMixable; format.mBytesPerFrame = 0; format.mBitsPerChannel = 16; format.mBytesPerPacket = 6144; format.mFramesPerPacket = 1536; format.mReserved = 0; spec->segsize = 6144; spec->segtotal = 10; is_passthrough = TRUE; } else { int width, depth; /* Fill out the audio description we're going to be using */ format.mFormatID = kAudioFormatLinearPCM; format.mSampleRate = (double) GST_AUDIO_INFO_RATE (&spec->info); format.mChannelsPerFrame = GST_AUDIO_INFO_CHANNELS (&spec->info); if (GST_AUDIO_INFO_IS_FLOAT (&spec->info)) { format.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; width = depth = GST_AUDIO_INFO_WIDTH (&spec->info); } else { format.mFormatFlags = kAudioFormatFlagIsSignedInteger; width = GST_AUDIO_INFO_WIDTH (&spec->info); depth = GST_AUDIO_INFO_DEPTH (&spec->info); if (width == depth) { format.mFormatFlags |= kAudioFormatFlagIsPacked; } else { format.mFormatFlags |= kAudioFormatFlagIsAlignedHigh; } } if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&spec->info)) { format.mFormatFlags |= kAudioFormatFlagIsBigEndian; } format.mBytesPerFrame = GST_AUDIO_INFO_BPF (&spec->info); format.mBitsPerChannel = depth; format.mBytesPerPacket = GST_AUDIO_INFO_BPF (&spec->info); format.mFramesPerPacket = 1; format.mReserved = 0; spec->segsize = (spec->latency_time * GST_AUDIO_INFO_RATE (&spec->info) / G_USEC_PER_SEC) * GST_AUDIO_INFO_BPF (&spec->info); spec->segtotal = spec->buffer_time / spec->latency_time; is_passthrough = FALSE; } GST_DEBUG_OBJECT (osxbuf, "Format: " CORE_AUDIO_FORMAT, CORE_AUDIO_FORMAT_ARGS (format)); /* gst_audio_ring_buffer_set_channel_positions is not called * since the AUs perform channel reordering themselves. * (see gst_core_audio_set_channel_layout) */ buf->size = spec->segtotal * spec->segsize; buf->memory = g_malloc0 (buf->size); ret = gst_core_audio_initialize (osxbuf->core_audio, format, spec->caps, is_passthrough); if (!ret) { g_free (buf->memory); buf->memory = NULL; buf->size = 0; } osxbuf->segoffset = 0; return ret; }