mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-22 02:13:46 +00:00
gst-libs/gst/audio/gstbaseaudiosink.c: Answer latency query.
Original commit message from CVS: * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_class_init), (gst_base_audio_sink_query), (gst_base_audio_sink_render), (gst_base_audio_sink_callback), (gst_base_audio_sink_async_play), (gst_base_audio_sink_change_state): Answer latency query. Use configured latency when syncing. Fix clock slaving. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_class_init), (gst_base_audio_src_dispose), (gst_base_audio_src_query), (gst_base_audio_src_change_state): Fix possible memleak. Implement latency query. Small cleanups.
This commit is contained in:
parent
70e52caf04
commit
a43d0f57eb
3 changed files with 214 additions and 25 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
2007-02-15 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst-libs/gst/audio/gstbaseaudiosink.c:
|
||||||
|
(gst_base_audio_sink_class_init), (gst_base_audio_sink_query),
|
||||||
|
(gst_base_audio_sink_render), (gst_base_audio_sink_callback),
|
||||||
|
(gst_base_audio_sink_async_play),
|
||||||
|
(gst_base_audio_sink_change_state):
|
||||||
|
Answer latency query.
|
||||||
|
Use configured latency when syncing.
|
||||||
|
Fix clock slaving.
|
||||||
|
|
||||||
|
* gst-libs/gst/audio/gstbaseaudiosrc.c:
|
||||||
|
(gst_base_audio_src_class_init), (gst_base_audio_src_dispose),
|
||||||
|
(gst_base_audio_src_query), (gst_base_audio_src_change_state):
|
||||||
|
Fix possible memleak.
|
||||||
|
Implement latency query.
|
||||||
|
Small cleanups.
|
||||||
|
|
||||||
2007-02-15 Wim Taymans <wim@fluendo.com>
|
2007-02-15 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* ext/alsa/gstalsasink.c: (gst_alsasink_reset):
|
* ext/alsa/gstalsasink.c: (gst_alsasink_reset):
|
||||||
|
|
|
@ -87,6 +87,8 @@ static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement *
|
||||||
element, GstStateChange transition);
|
element, GstStateChange transition);
|
||||||
static gboolean gst_base_audio_sink_activate_pull (GstBaseSink * basesink,
|
static gboolean gst_base_audio_sink_activate_pull (GstBaseSink * basesink,
|
||||||
gboolean active);
|
gboolean active);
|
||||||
|
static gboolean gst_base_audio_sink_query (GstElement * element, GstQuery *
|
||||||
|
query);
|
||||||
|
|
||||||
static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem);
|
static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem);
|
||||||
static GstClockTime gst_base_audio_sink_get_time (GstClock * clock,
|
static GstClockTime gst_base_audio_sink_get_time (GstClock * clock,
|
||||||
|
@ -149,6 +151,7 @@ gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
|
GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
|
||||||
gstelement_class->provide_clock =
|
gstelement_class->provide_clock =
|
||||||
GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
|
GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
|
||||||
|
gstelement_class->query = GST_DEBUG_FUNCPTR (gst_base_audio_sink_query);
|
||||||
|
|
||||||
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event);
|
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event);
|
||||||
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll);
|
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll);
|
||||||
|
@ -235,6 +238,62 @@ clock_disabled:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_base_audio_sink_query (GstElement * element, GstQuery * query)
|
||||||
|
{
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
|
GstBaseAudioSink *basesink = GST_BASE_AUDIO_SINK (element);
|
||||||
|
|
||||||
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
case GST_QUERY_LATENCY:
|
||||||
|
{
|
||||||
|
gboolean live, us_live;
|
||||||
|
GstClockTime min_l, max_l;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (basesink, "latency query");
|
||||||
|
|
||||||
|
/* ask parent first, it will do an upstream query for us. */
|
||||||
|
if ((res =
|
||||||
|
gst_base_sink_query_latency (GST_BASE_SINK_CAST (basesink), &live,
|
||||||
|
&us_live, &min_l, &max_l))) {
|
||||||
|
GstClockTime min_latency, max_latency;
|
||||||
|
|
||||||
|
/* we and upstream are both live, adjust the min_latency */
|
||||||
|
if (live && us_live && basesink->ringbuffer
|
||||||
|
&& basesink->ringbuffer->spec.rate) {
|
||||||
|
GstRingBufferSpec *spec;
|
||||||
|
|
||||||
|
spec = &basesink->ringbuffer->spec;
|
||||||
|
|
||||||
|
max_latency =
|
||||||
|
spec->segtotal * spec->segsize * GST_SECOND / (spec->rate *
|
||||||
|
spec->bytes_per_sample);
|
||||||
|
min_latency = MAX (max_latency, min_l);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (basesink,
|
||||||
|
"peer min %" GST_TIME_FORMAT ", our min latency: %"
|
||||||
|
GST_TIME_FORMAT, GST_TIME_ARGS (min_l),
|
||||||
|
GST_TIME_ARGS (min_latency));
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (basesink,
|
||||||
|
"peer or we are not live, don't care about latency");
|
||||||
|
min_latency = 0;
|
||||||
|
max_latency = -1;
|
||||||
|
}
|
||||||
|
gst_query_set_latency (query, live, min_latency, max_latency);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
res = GST_ELEMENT_CLASS (parent_class)->query (element, query);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static GstClockTime
|
static GstClockTime
|
||||||
gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
|
gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
|
||||||
{
|
{
|
||||||
|
@ -550,7 +609,7 @@ gst_base_audio_sink_get_offset (GstBaseAudioSink * sink)
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
guint64 in_offset, clock_offset;
|
guint64 in_offset;
|
||||||
GstClockTime time, stop, render_start, render_stop, sample_offset;
|
GstClockTime time, stop, render_start, render_stop, sample_offset;
|
||||||
GstBaseAudioSink *sink;
|
GstBaseAudioSink *sink;
|
||||||
GstRingBuffer *ringbuf;
|
GstRingBuffer *ringbuf;
|
||||||
|
@ -563,9 +622,9 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
GstClockTime crate_num;
|
GstClockTime crate_num;
|
||||||
GstClockTime crate_denom;
|
GstClockTime crate_denom;
|
||||||
gint out_samples;
|
gint out_samples;
|
||||||
GstClockTime cinternal, cexternal;
|
GstClockTime base_time, cinternal, cexternal, latency;
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
gboolean sync;
|
gboolean sync, slaved;
|
||||||
|
|
||||||
sink = GST_BASE_AUDIO_SINK (bsink);
|
sink = GST_BASE_AUDIO_SINK (bsink);
|
||||||
|
|
||||||
|
@ -663,29 +722,62 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
"running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
|
"running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
|
GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
|
||||||
|
|
||||||
/* get calibration parameters to compensate for speed and offset differences
|
base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bsink));
|
||||||
* when we are slaved */
|
|
||||||
gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
|
|
||||||
&crate_num, &crate_denom);
|
|
||||||
|
|
||||||
clock_offset =
|
GST_DEBUG_OBJECT (sink, "base_time %" GST_TIME_FORMAT,
|
||||||
(gst_element_get_base_time (GST_ELEMENT_CAST (bsink)) - cexternal) +
|
GST_TIME_ARGS (base_time));
|
||||||
cinternal;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (sink, "clock offset %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
|
/* add base time to sync against the clock */
|
||||||
"/%" G_GUINT64_FORMAT, GST_TIME_ARGS (clock_offset), crate_num,
|
render_start += base_time;
|
||||||
crate_denom);
|
render_stop += base_time;
|
||||||
|
|
||||||
/* and bring the time to the rate corrected offset in the buffer */
|
slaved = clock != sink->provided_clock;
|
||||||
render_start = gst_util_uint64_scale_int (render_start + clock_offset,
|
if (slaved) {
|
||||||
ringbuf->spec.rate, GST_SECOND);
|
/* get calibration parameters to compensate for speed and offset differences
|
||||||
render_stop = gst_util_uint64_scale_int (render_stop + clock_offset,
|
* when we are slaved */
|
||||||
ringbuf->spec.rate, GST_SECOND);
|
gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
|
||||||
|
&crate_num, &crate_denom);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (sink, "internal %" GST_TIME_FORMAT " external %"
|
||||||
|
GST_TIME_FORMAT " %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f",
|
||||||
|
GST_TIME_ARGS (cinternal), GST_TIME_ARGS (cexternal), crate_num,
|
||||||
|
crate_denom, (gdouble) crate_num / crate_denom);
|
||||||
|
|
||||||
|
/* bring to our slaved clock time */
|
||||||
|
if (render_start >= cexternal)
|
||||||
|
render_start =
|
||||||
|
gst_util_uint64_scale (render_start - cexternal, crate_denom,
|
||||||
|
crate_num) + cinternal;
|
||||||
|
else
|
||||||
|
render_start =
|
||||||
|
cinternal - gst_util_uint64_scale (cexternal - render_start,
|
||||||
|
crate_denom, crate_num);
|
||||||
|
|
||||||
|
if (render_stop >= cexternal)
|
||||||
|
render_stop =
|
||||||
|
gst_util_uint64_scale (render_stop - cexternal, crate_denom,
|
||||||
|
crate_num) + cinternal;
|
||||||
|
else
|
||||||
|
render_stop =
|
||||||
|
cinternal - gst_util_uint64_scale (cexternal - render_stop,
|
||||||
|
crate_denom, crate_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compensate for latency */
|
||||||
|
latency = gst_base_sink_get_latency (bsink);
|
||||||
|
render_start += latency;
|
||||||
|
render_stop += latency;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (sink,
|
GST_DEBUG_OBJECT (sink,
|
||||||
"render: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
|
"render: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
|
GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
|
||||||
|
|
||||||
|
/* and bring the time to the rate corrected offset in the buffer */
|
||||||
|
render_start = gst_util_uint64_scale_int (render_start,
|
||||||
|
ringbuf->spec.rate, GST_SECOND);
|
||||||
|
render_stop = gst_util_uint64_scale_int (render_stop,
|
||||||
|
ringbuf->spec.rate, GST_SECOND);
|
||||||
|
|
||||||
/* always resync after a discont */
|
/* always resync after a discont */
|
||||||
if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) {
|
if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) {
|
||||||
GST_DEBUG_OBJECT (sink, "resync after discont");
|
GST_DEBUG_OBJECT (sink, "resync after discont");
|
||||||
|
@ -736,7 +828,7 @@ gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
render_start += align;
|
render_start += align;
|
||||||
|
|
||||||
/* only align stop if we are not slaved */
|
/* only align stop if we are not slaved */
|
||||||
if (clock != sink->provided_clock) {
|
if (slaved) {
|
||||||
GST_DEBUG_OBJECT (sink, "no stop time align needed: we are slaved");
|
GST_DEBUG_OBJECT (sink, "no stop time align needed: we are slaved");
|
||||||
goto no_align;
|
goto no_align;
|
||||||
}
|
}
|
||||||
|
@ -878,7 +970,8 @@ gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
|
||||||
|
|
||||||
/* would be nice to arrange for pad_alloc_buffer to return data -- as it is we
|
/* would be nice to arrange for pad_alloc_buffer to return data -- as it is we
|
||||||
will copy twice, once into data, once into DMA */
|
will copy twice, once into data, once into DMA */
|
||||||
GST_LOG_OBJECT (basesink, "pulling %d bytes to fill audio buffer", len);
|
GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT
|
||||||
|
" to fill audio buffer", len, basesink->offset);
|
||||||
ret = gst_pad_pull_range (basesink->sinkpad, basesink->offset, len, &buf);
|
ret = gst_pad_pull_range (basesink->sinkpad, basesink->offset, len, &buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -944,6 +1037,8 @@ gst_base_audio_sink_async_play (GstBaseSink * basesink)
|
||||||
}
|
}
|
||||||
|
|
||||||
no_clock:
|
no_clock:
|
||||||
|
gst_ring_buffer_start (sink->ringbuffer);
|
||||||
|
|
||||||
return GST_STATE_CHANGE_SUCCESS;
|
return GST_STATE_CHANGE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,7 +1104,6 @@ gst_base_audio_sink_change_state (GstElement * element,
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
gst_ring_buffer_release (sink->ringbuffer);
|
gst_ring_buffer_release (sink->ringbuffer);
|
||||||
gst_pad_set_caps (GST_BASE_SINK_PAD (sink), NULL);
|
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
gst_ring_buffer_close_device (sink->ringbuffer);
|
gst_ring_buffer_close_device (sink->ringbuffer);
|
||||||
|
|
|
@ -66,6 +66,7 @@ static void gst_base_audio_src_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_base_audio_src_get_property (GObject * object, guint prop_id,
|
static void gst_base_audio_src_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_base_audio_src_dispose (GObject * object);
|
||||||
|
|
||||||
static GstStateChangeReturn gst_base_audio_src_change_state (GstElement *
|
static GstStateChangeReturn gst_base_audio_src_change_state (GstElement *
|
||||||
element, GstStateChange transition);
|
element, GstStateChange transition);
|
||||||
|
@ -84,6 +85,7 @@ static gboolean gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event);
|
||||||
static void gst_base_audio_src_get_times (GstBaseSrc * bsrc,
|
static void gst_base_audio_src_get_times (GstBaseSrc * bsrc,
|
||||||
GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
|
GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
|
||||||
static gboolean gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
|
static gboolean gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
|
||||||
|
static gboolean gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query);
|
||||||
static void gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
|
static void gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
|
||||||
|
|
||||||
/* static guint gst_base_audio_src_signals[LAST_SIGNAL] = { 0 }; */
|
/* static guint gst_base_audio_src_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
@ -110,6 +112,7 @@ gst_base_audio_src_class_init (GstBaseAudioSrcClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_base_audio_src_set_property);
|
GST_DEBUG_FUNCPTR (gst_base_audio_src_set_property);
|
||||||
gobject_class->get_property =
|
gobject_class->get_property =
|
||||||
GST_DEBUG_FUNCPTR (gst_base_audio_src_get_property);
|
GST_DEBUG_FUNCPTR (gst_base_audio_src_get_property);
|
||||||
|
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_src_dispose);
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
|
g_object_class_install_property (gobject_class, PROP_BUFFER_TIME,
|
||||||
g_param_spec_int64 ("buffer-time", "Buffer Time",
|
g_param_spec_int64 ("buffer-time", "Buffer Time",
|
||||||
|
@ -130,6 +133,7 @@ gst_base_audio_src_class_init (GstBaseAudioSrcClass * klass)
|
||||||
|
|
||||||
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_src_setcaps);
|
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_src_setcaps);
|
||||||
gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_src_event);
|
gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_src_event);
|
||||||
|
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_base_audio_src_query);
|
||||||
gstbasesrc_class->get_times =
|
gstbasesrc_class->get_times =
|
||||||
GST_DEBUG_FUNCPTR (gst_base_audio_src_get_times);
|
GST_DEBUG_FUNCPTR (gst_base_audio_src_get_times);
|
||||||
gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_base_audio_src_create);
|
gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_base_audio_src_create);
|
||||||
|
@ -157,6 +161,25 @@ gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc,
|
||||||
gst_base_src_set_format (GST_BASE_SRC (baseaudiosrc), GST_FORMAT_TIME);
|
gst_base_src_set_format (GST_BASE_SRC (baseaudiosrc), GST_FORMAT_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_base_audio_src_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
GstBaseAudioSrc *src;
|
||||||
|
|
||||||
|
src = GST_BASE_AUDIO_SRC (object);
|
||||||
|
|
||||||
|
if (src->clock)
|
||||||
|
gst_object_unref (src->clock);
|
||||||
|
src->clock = NULL;
|
||||||
|
|
||||||
|
if (src->ringbuffer) {
|
||||||
|
gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer));
|
||||||
|
src->ringbuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_audio_src_set_clock (GstElement * elem, GstClock * clock)
|
gst_base_audio_src_set_clock (GstElement * elem, GstClock * clock)
|
||||||
{
|
{
|
||||||
|
@ -378,6 +401,50 @@ gst_base_audio_src_get_times (GstBaseSrc * bsrc, GstBuffer * buffer,
|
||||||
*end = GST_CLOCK_TIME_NONE;
|
*end = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
|
{
|
||||||
|
GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc);
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
case GST_QUERY_LATENCY:
|
||||||
|
{
|
||||||
|
GstClockTime min_latency, max_latency;
|
||||||
|
GstRingBufferSpec *spec;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (src->ringbuffer == NULL
|
||||||
|
|| src->ringbuffer->spec.rate == 0))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
spec = &src->ringbuffer->spec;
|
||||||
|
|
||||||
|
min_latency =
|
||||||
|
gst_util_uint64_scale_int (spec->segsize, GST_SECOND,
|
||||||
|
spec->rate * spec->bytes_per_sample);
|
||||||
|
max_latency =
|
||||||
|
gst_util_uint64_scale_int (spec->segtotal * spec->segsize, GST_SECOND,
|
||||||
|
spec->rate * spec->bytes_per_sample);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src,
|
||||||
|
"report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
|
||||||
|
|
||||||
|
/* we are always live, the min latency is 1 segment and the max latency is
|
||||||
|
* the complete buffer of segments. */
|
||||||
|
gst_query_set_latency (query, TRUE, min_latency, max_latency);
|
||||||
|
|
||||||
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
|
gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event)
|
||||||
{
|
{
|
||||||
|
@ -588,15 +655,18 @@ gst_base_audio_src_change_state (GstElement * element,
|
||||||
src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
|
src->ringbuffer = gst_base_audio_src_create_ringbuffer (src);
|
||||||
}
|
}
|
||||||
if (!gst_ring_buffer_open_device (src->ringbuffer))
|
if (!gst_ring_buffer_open_device (src->ringbuffer))
|
||||||
return GST_STATE_CHANGE_FAILURE;
|
goto open_failed;
|
||||||
src->next_sample = -1;
|
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
|
src->next_sample = -1;
|
||||||
gst_ring_buffer_set_flushing (src->ringbuffer, FALSE);
|
gst_ring_buffer_set_flushing (src->ringbuffer, FALSE);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
gst_ring_buffer_may_start (src->ringbuffer, TRUE);
|
gst_ring_buffer_may_start (src->ringbuffer, TRUE);
|
||||||
break;
|
break;
|
||||||
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
gst_ring_buffer_set_flushing (src->ringbuffer, TRUE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -609,9 +679,7 @@ gst_base_audio_src_change_state (GstElement * element,
|
||||||
gst_ring_buffer_pause (src->ringbuffer);
|
gst_ring_buffer_pause (src->ringbuffer);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
gst_ring_buffer_set_flushing (src->ringbuffer, TRUE);
|
|
||||||
gst_ring_buffer_release (src->ringbuffer);
|
gst_ring_buffer_release (src->ringbuffer);
|
||||||
src->next_sample = -1;
|
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
gst_ring_buffer_close_device (src->ringbuffer);
|
gst_ring_buffer_close_device (src->ringbuffer);
|
||||||
|
@ -623,4 +691,13 @@ gst_base_audio_src_change_state (GstElement * element,
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
open_failed:
|
||||||
|
{
|
||||||
|
/* subclass must post a meaningfull error message */
|
||||||
|
GST_DEBUG_OBJECT (src, "open failed");
|
||||||
|
return GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue