pa_stream *stream;
pa_sample_spec sample_spec;
+ gint64 offset;
gboolean corked;
gboolean in_commit;
/* Make sure we don't get any further callbacks */
pa_stream_set_state_callback (pbuf->stream, NULL, NULL);
pa_stream_set_write_callback (pbuf->stream, NULL, NULL);
- pa_stream_set_latency_update_callback (pbuf->stream, NULL, NULL);
pa_stream_unref (pbuf->stream);
pbuf->stream = NULL;
}
}
-static void
-gst_pulsering_stream_latency_update_cb (pa_stream * s, void *userdata)
-{
- GstPulseSink *psink;
- GstPulseRingBuffer *pbuf;
-
- pbuf = GST_PULSERING_BUFFER_CAST (userdata);
- psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
-
- GST_LOG_OBJECT (psink, "got latency update callback");
-
- pa_threaded_mainloop_signal (psink->mainloop, 0);
-}
-
/* This method should create a new stream of the given @spec. No playback should
* start yet so we start in the corked state. */
static gboolean
pa_cvolume v, *pv;
pa_stream_flags_t flags;
const gchar *name;
+ GstAudioClock *clock;
+ gint64 time_offset;
psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
pbuf = GST_PULSERING_BUFFER_CAST (buf);
gst_pulsering_stream_state_cb, pbuf);
pa_stream_set_write_callback (pbuf->stream,
gst_pulsering_stream_request_cb, pbuf);
- pa_stream_set_latency_update_callback (pbuf->stream,
- gst_pulsering_stream_latency_update_cb, pbuf);
/* buffering requirements */
memset (&buf_attr, 0, sizeof (buf_attr));
}
/* construct the flags */
- flags = PA_STREAM_INTERPOLATE_TIMING |
- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_NOT_MONOTONOUS |
+ flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
#if HAVE_PULSE_0_9_11
PA_STREAM_ADJUST_LATENCY |
#endif
pa_threaded_mainloop_wait (psink->mainloop);
}
+ /* our clock will now start from 0 again */
+ clock = GST_AUDIO_CLOCK (GST_BASE_AUDIO_SINK (psink)->provided_clock);
+ gst_audio_clock_reset (clock, 0);
+ time_offset = clock->abidata.ABI.time_offset;
+
+ GST_LOG_OBJECT (psink, "got time offset %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (time_offset));
+
+ /* calculate the sample offset for 0 */
+ if (time_offset > 0)
+ pbuf->offset = gst_util_uint64_scale_int (time_offset,
+ pbuf->sample_spec.rate, GST_SECOND);
+ else
+ pbuf->offset = -gst_util_uint64_scale_int (-time_offset,
+ pbuf->sample_spec.rate, GST_SECOND);
+ GST_LOG_OBJECT (psink, "sample offset %" G_GINT64_FORMAT, pbuf->offset);
+
+
GST_LOG_OBJECT (psink, "stream is acquired now");
/* get the actual buffering properties now */
return TRUE;
}
+static void
+gst_pulsering_success_cb (pa_stream * s, int success, void *userdata)
+{
+ GstPulseRingBuffer *pbuf;
+ GstPulseSink *psink;
+
+ pbuf = GST_PULSERING_BUFFER_CAST (userdata);
+ psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
+
+ pa_threaded_mainloop_signal (psink->mainloop, 0);
+}
+
/* update the corked state of a stream, must be called with the mainloop
* lock */
static gboolean
GST_DEBUG_OBJECT (psink, "setting corked state to %d", corked);
if (pbuf->corked != corked) {
- if (!(o = pa_stream_cork (pbuf->stream, corked, NULL, NULL)))
+ if (!(o = pa_stream_cork (pbuf->stream, corked,
+ gst_pulsering_success_cb, pbuf)))
goto cork_failed;
while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
return res;
}
-static void
-gst_pulsering_success_cb (pa_stream * s, int success, void *userdata)
-{
- GstPulseRingBuffer *pbuf;
- GstPulseSink *psink;
-
- pbuf = GST_PULSERING_BUFFER_CAST (userdata);
- psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
-
- pa_threaded_mainloop_signal (psink->mainloop, 0);
-}
-
/* stop playback, we flush everything. */
static gboolean
gst_pulseringbuffer_stop (GstRingBuffer * buf)
if (avail > out_samples)
avail = out_samples;
- GST_LOG_OBJECT (psink, "writing %d samples at offset %" G_GUINT64_FORMAT,
- avail, *sample);
-
- offset = *sample * bps;
+ /* correct for sample offset against the internal clock */
+ offset = *sample;
+ if (pbuf->offset >= 0) {
+ if (offset > pbuf->offset)
+ offset -= pbuf->offset;
+ else
+ offset = 0;
+ } else {
+ if (offset > -pbuf->offset)
+ offset += pbuf->offset;
+ else
+ offset = 0;
+ }
+ offset *= bps;
towrite = avail * bps;
+ GST_LOG_OBJECT (psink, "writing %d samples at offset %" G_GUINT64_FORMAT,
+ avail, offset);
+
if (G_LIKELY (inr == outr && !reverse)) {
/* no rate conversion, simply write out the samples */
if (pa_stream_write (pbuf->stream, data, towrite, NULL, offset,
psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
pa_threaded_mainloop_lock (psink->mainloop);
- /* if we don't have enough data to get a timestamp, just return 0 */
- if (pa_stream_get_time (pbuf->stream, &time) < 0)
- time = 0;
- pa_threaded_mainloop_unlock (psink->mainloop);
- time *= 1000;
+ /* if we don't have enough data to get a timestamp, just return NONE, which
+ * will return the last reported time */
+ if (pa_stream_get_time (pbuf->stream, &time) < 0) {
+ GST_DEBUG_OBJECT (psink, "could not get time");
+ time = GST_CLOCK_TIME_NONE;
+ } else
+ time *= 1000;
+ pa_threaded_mainloop_unlock (psink->mainloop);
GST_LOG_OBJECT (psink, "current time is %" GST_TIME_FORMAT,
GST_TIME_ARGS (time));
g_assert ((pulsesink->mainloop = pa_threaded_mainloop_new ()));
g_assert (pa_threaded_mainloop_start (pulsesink->mainloop) == 0);
+// GST_BASE_SINK (pulsesink)->can_activate_pull = TRUE;
+
pulsesink->probe = gst_pulseprobe_new (G_OBJECT (pulsesink), G_OBJECT_GET_CLASS (pulsesink), PROP_DEVICE, pulsesink->device, TRUE, FALSE); /* TRUE for sinks, FALSE for sources */
/* override with a custom clock */