virtual HRESULT RenderAudioSamples (bool preroll) { guint8 *ptr; gint seg; gint len; gint bpf; guint written, written_sum; HRESULT res; GST_LOG_OBJECT (m_ringbuffer->sink, "Writing audio samples (preroll: %d)", preroll); if (!gst_audio_ring_buffer_prepare_read (GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer), &seg, &ptr, &len)) { GST_WARNING_OBJECT (m_ringbuffer->sink, "No segment available"); return E_FAIL; } bpf = GST_AUDIO_INFO_BPF (&GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer)-> spec.info); len /= bpf; GST_LOG_OBJECT (m_ringbuffer->sink, "Write audio samples: %p size %d segment: %d", ptr, len, seg); written_sum = 0; do { res = m_ringbuffer->output->output->ScheduleAudioSamples (ptr, len, 0, 0, &written); len -= written; ptr += written * bpf; written_sum += written; } while (len > 0 && res == S_OK); GST_LOG_OBJECT (m_ringbuffer->sink, "Wrote %u samples: 0x%08x", written_sum, res); gst_audio_ring_buffer_clear (GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer), seg); gst_audio_ring_buffer_advance (GST_AUDIO_RING_BUFFER_CAST (m_ringbuffer), 1); return res; }
static GstAudioRingBuffer * gst_decklink_audio_sink_create_ringbuffer (GstAudioBaseSink * absink) { GstAudioRingBuffer *ret; GST_DEBUG_OBJECT (absink, "Creating ringbuffer"); ret = GST_AUDIO_RING_BUFFER_CAST (g_object_new (GST_TYPE_DECKLINK_AUDIO_SINK_RING_BUFFER, NULL)); GST_DECKLINK_AUDIO_SINK_RING_BUFFER_CAST (ret)->sink = (GstDecklinkAudioSink *) gst_object_ref (absink); return ret; }
/* this is the callback of jack. This should RT-safe. */ static int jack_process_cb (jack_nframes_t nframes, void *arg) { GstJackAudioSink *sink; GstAudioRingBuffer *buf; gint readseg, len; guint8 *readptr; gint i, j, flen, channels; sample_t *data; buf = GST_AUDIO_RING_BUFFER_CAST (arg); sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); channels = GST_AUDIO_INFO_CHANNELS (&buf->spec.info); /* get target buffers */ for (i = 0; i < channels; i++) { sink->buffers[i] = (sample_t *) jack_port_get_buffer (sink->ports[i], nframes); } if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) { flen = len / channels; /* the number of samples must be exactly the segment size */ if (nframes * sizeof (sample_t) != flen) goto wrong_size; GST_DEBUG_OBJECT (sink, "copy %d frames: %p, %d bytes, %d channels", nframes, readptr, flen, channels); data = (sample_t *) readptr; /* the samples in the ringbuffer have the channels interleaved, we need to * deinterleave into the jack target buffers */ for (i = 0; i < nframes; i++) { for (j = 0; j < channels; j++) { sink->buffers[j][i] = *data++; } } /* clear written samples in the ringbuffer */ gst_audio_ring_buffer_clear (buf, readseg); /* we wrote one segment */ gst_audio_ring_buffer_advance (buf, 1); } else { GST_DEBUG_OBJECT (sink, "write %d frames silence", nframes); /* We are not allowed to read from the ringbuffer, write silence to all * jack output buffers */ for (i = 0; i < channels; i++) { memset (sink->buffers[i], 0, nframes * sizeof (sample_t)); } } return 0; /* ERRORS */ wrong_size: { GST_ERROR_OBJECT (sink, "nbytes (%d) != flen (%d)", (gint) (nframes * sizeof (sample_t)), flen); return 1; } }