gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
guint64 render_offset, in_offset;
- GstClockTime time, render_time;
+ GstClockTime time, render_time, duration;
GstClockTimeDiff render_diff;
- GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
+ GstBaseAudioSink *sink;
+ GstRingBuffer *ringbuf;
gint64 diff;
guint8 *data;
guint size;
+ guint samples;
+ gint bps;
+
+ sink = GST_BASE_AUDIO_SINK (bsink);
+
+ ringbuf = sink->ringbuffer;
/* can't do anything when we don't have the device */
- if (!gst_ring_buffer_is_acquired (sink->ringbuffer))
+ if (!gst_ring_buffer_is_acquired (ringbuf))
goto wrong_state;
+ bps = ringbuf->spec.bytes_per_sample;
+
+ size = GST_BUFFER_SIZE (buf);
+ if (size % bps != 0)
+ goto wrong_size;
+
+ samples = size / bps;
+
in_offset = GST_BUFFER_OFFSET (buf);
time = GST_BUFFER_TIMESTAMP (buf);
+ duration = GST_BUFFER_DURATION (buf);
data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
GST_DEBUG ("time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT,
GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->segment_start));
/* add base time to get absolute clock time */
render_time += gst_element_get_base_time (GST_ELEMENT (bsink));
/* and bring the time to the offset in the buffer */
- render_offset = render_time * sink->ringbuffer->spec.rate / GST_SECOND;
+ render_offset = render_time * ringbuf->spec.rate / GST_SECOND;
/* roundoff errors in timestamp conversion */
if (sink->next_sample != -1)
diff = ABS ((gint64) render_offset - (gint64) sink->next_sample);
else
- diff = sink->ringbuffer->spec.rate;
+ diff = ringbuf->spec.rate;
GST_DEBUG ("render time %" GST_TIME_FORMAT
- ", render offset %llu, diff %lld, size %lu", GST_TIME_ARGS (render_time),
- render_offset, diff, size);
+ ", render offset %llu, diff %lld, samples %lu",
+ GST_TIME_ARGS (render_time), render_offset, diff, samples);
/* we tollerate a 10th of a second diff before we start resyncing. This
* should be enough to compensate for various rounding errors in the timestamp
* and sample offset position. */
- if (diff < sink->ringbuffer->spec.rate / DIFF_TOLERANCE) {
+ if (diff < ringbuf->spec.rate / DIFF_TOLERANCE) {
GST_DEBUG ("align with prev sample, %" G_GINT64_FORMAT " < %lu", diff,
- sink->ringbuffer->spec.rate / DIFF_TOLERANCE);
+ ringbuf->spec.rate / DIFF_TOLERANCE);
/* just align with previous sample then */
render_offset = sink->next_sample;
} else {
GST_DEBUG ("resync");
}
- gst_ring_buffer_commit (sink->ringbuffer, render_offset, data, size);
+
+ /* clip length based on rate */
+ samples /= ABS (bsink->segment_rate);
/* the next sample should be current sample and its length */
- sink->next_sample =
- render_offset + size / sink->ringbuffer->spec.bytes_per_sample;
+ sink->next_sample = render_offset + samples;
+
+ gst_ring_buffer_commit (ringbuf, render_offset, data, samples);
+
+ if (time + duration >= bsink->segment_stop) {
+ GST_DEBUG ("start playback because we are at the end of segment");
+ gst_ring_buffer_start (ringbuf);
+ }
return GST_FLOW_OK;
("sink not negotiated."), ("sink not negotiated."));
return GST_FLOW_NOT_NEGOTIATED;
}
+wrong_size:
+ {
+ GST_DEBUG ("wrong size");
+ GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
+ ("sink received buffer of wrong size."),
+ ("sink received buffer of wrong size."));
+ return GST_FLOW_ERROR;
+ }
}
GstRingBuffer *
* @buf: the #GstRingBuffer to commit
* @sample: the sample position of the data
* @data: the data to commit
- * @len: the length of the data to commit
+ * @len: the number of samples in the data to commit
*
* Commit @len samples pointed to by @data to the ringbuffer
* @buf. The first sample should be written at position @sample in
bps = buf->spec.bytes_per_sample;
sps = buf->samples_per_seg;
- /* write out all bytes */
+ /* write out all samples */
while (len > 0) {
- gint writelen;
- gint writeseg, writeoff;
+ gint sampleslen;
+ gint writeseg, sampleoff;
/* figure out the segment and the offset inside the segment where
* the sample should be written. */
writeseg = sample / sps;
- writeoff = (sample % sps) * bps;
+ sampleoff = (sample % sps);
while (TRUE) {
gint diff;
GST_DEBUG
("pointer at %d, sample %llu, write to %d-%d, len %d, diff %d, segtotal %d, segsize %d",
- segdone, sample, writeseg, writeoff, len, diff, segtotal, segsize);
+ segdone, sample, writeseg, sampleoff, len, diff, segtotal, sps);
/* segment too far ahead, we need to drop */
if (diff < 0) {
/* we need to drop one segment at a time, pretend we wrote a
* segment. */
- writelen = MIN (segsize, len);
+ sampleslen = MIN (sps, len);
goto next;
}
/* we can write now */
writeseg = writeseg % segtotal;
- writelen = MIN (segsize - writeoff, len);
+ sampleslen = MIN (sps - sampleoff, len);
GST_DEBUG ("write @%p seg %d, off %d, len %d",
- dest + writeseg * segsize, writeseg, writeoff, writelen);
+ dest + writeseg * segsize, writeseg, sampleoff, sampleslen);
- memcpy (dest + writeseg * segsize + writeoff, data, writelen);
+ memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data,
+ (sampleslen * bps));
next:
- len -= writelen;
- data += writelen;
- sample += writelen / bps;
+ len -= sampleslen;
+ sample += sampleslen;
+ data += sampleslen * bps;
}
return len;
* @buf: the #GstRingBuffer to read from
* @sample: the sample position of the data
* @data: where the data should be read
- * @len: the length of the data to read
+ * @len: the number of samples in data to read
*
- * Read @length samples from the ringbuffer into the memory pointed
+ * Read @len samples from the ringbuffer into the memory pointed
* to by @data.
* The first sample should be read from position @sample in
* the ringbuffer.
bps = buf->spec.bytes_per_sample;
sps = buf->samples_per_seg;
- /* read enough bytes */
+ /* read enough samples */
while (len > 0) {
- gint readlen;
- gint readseg, readoff;
+ gint sampleslen;
+ gint readseg, sampleoff;
/* figure out the segment and the offset inside the segment where
* the sample should be written. */
readseg = sample / sps;
- readoff = (sample % sps) * bps;
+ sampleoff = (sample % sps);
while (TRUE) {
gint diff;
GST_DEBUG
("pointer at %d, sample %llu, read from %d-%d, len %d, diff %d, segtotal %d, segsize %d",
- segdone, sample, readseg, readoff, len, diff, segtotal, segsize);
+ segdone, sample, readseg, sampleoff, len, diff, segtotal, segsize);
/* segment too far ahead, we need to drop */
if (diff < 0) {
/* we need to drop one segment at a time, pretend we read an
* empty segment. */
- readlen = MIN (segsize, len);
- memcpy (data, buf->empty_seg, readlen);
+ sampleslen = MIN (sps, len);
+ memcpy (data, buf->empty_seg, sampleslen * bps);
goto next;
}
/* we can read now */
readseg = readseg % segtotal;
- readlen = MIN (segsize - readoff, len);
+ sampleslen = MIN (sps - sampleoff, len);
GST_DEBUG ("read @%p seg %d, off %d, len %d",
- dest + readseg * segsize, readseg, readoff, readlen);
+ dest + readseg * segsize, readseg, sampleoff, sampleslen);
- memcpy (data, dest + readseg * segsize + readoff, readlen);
+ memcpy (data, dest + (readseg * segsize) + (sampleoff * bps),
+ (sampleslen * bps));
next:
- len -= readlen;
- data += readlen;
- sample += readlen / bps;
+ len -= sampleslen;
+ sample += sampleslen;
+ data += sampleslen * bps;
}
return len;