GstClockTime eos_time;
- gboolean do_time_offset;
/* number of microseconds we alow timestamps or clock slaving to drift
* before resyncing */
guint64 drift_tolerance;
}
-#define _do_init(bla) \
+#define _do_init \
GST_DEBUG_CATEGORY_INIT (gst_base_audio_sink_debug, "baseaudiosink", 0, "baseaudiosink element");
-
-GST_BOILERPLATE_FULL (GstBaseAudioSink, gst_base_audio_sink, GstBaseSink,
+#define gst_base_audio_sink_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstBaseAudioSink, gst_base_audio_sink,
GST_TYPE_BASE_SINK, _do_init);
static void gst_base_audio_sink_dispose (GObject * object);
static void gst_base_audio_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+#if 0
static GstStateChangeReturn gst_base_audio_sink_async_play (GstBaseSink *
basesink);
+#endif
static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement *
element, GstStateChange transition);
static gboolean gst_base_audio_sink_activate_pull (GstBaseSink * basesink,
/* static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 }; */
static void
-gst_base_audio_sink_base_init (gpointer g_class)
-{
-}
-
-static void
gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
{
GObjectClass *gobject_class;
GST_DEBUG_FUNCPTR (gst_base_audio_sink_get_times);
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_sink_setcaps);
gstbasesink_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_sink_fixate);
+#if 0
gstbasesink_class->async_play =
GST_DEBUG_FUNCPTR (gst_base_audio_sink_async_play);
+#endif
gstbasesink_class->activate_pull =
GST_DEBUG_FUNCPTR (gst_base_audio_sink_activate_pull);
}
static void
-gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
- GstBaseAudioSinkClass * g_class)
+gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink)
{
- GstPluginFeature *feature;
GstBaseSink *basesink;
baseaudiosink->priv = GST_BASE_AUDIO_SINK_GET_PRIVATE (baseaudiosink);
/* install some custom pad_query functions */
gst_pad_set_query_function (GST_BASE_SINK_PAD (baseaudiosink),
GST_DEBUG_FUNCPTR (gst_base_audio_sink_query_pad));
-
- baseaudiosink->priv->do_time_offset = TRUE;
-
- /* check the factory, pulsesink < 0.10.17 does the timestamp offset itself so
- * we should not do ourselves */
- feature =
- GST_PLUGIN_FEATURE_CAST (GST_ELEMENT_CLASS (g_class)->elementfactory);
- GST_DEBUG ("created from factory %p", feature);
-
- /* HACK for old pulsesink that did the time_offset themselves */
- if (feature) {
- if (strcmp (gst_plugin_feature_get_name (feature), "pulsesink") == 0) {
- if (!gst_plugin_feature_check_version (feature, 0, 10, 17)) {
- /* we're dealing with an old pulsesink, we need to disable time corection */
- GST_DEBUG ("disable time offset");
- baseaudiosink->priv->do_time_offset = FALSE;
- }
- }
- }
}
static void
GST_DEBUG_OBJECT (sink, "release old ringbuffer");
- /* get current time, updates the last_time */
+ /* get current time, updates the last_time. When the subclass has a clock that
+ * restarts from 0 when a new format is negotiated, it will call
+ * gst_audio_clock_reset() which will use this last_time to create an offset
+ * so that time from the clock keeps on increasing monotonically. */
now = gst_clock_get_time (sink->provided_clock);
GST_DEBUG_OBJECT (sink, "time was %" GST_TIME_FORMAT, GST_TIME_ARGS (now));
/* now wait till we played everything */
gst_base_audio_sink_drain (sink);
break;
- case GST_EVENT_NEWSEGMENT:
- {
- gdouble rate;
-
- /* we only need the rate */
- gst_event_parse_new_segment_full (event, NULL, &rate, NULL, NULL,
- NULL, NULL, NULL);
-
- GST_DEBUG_OBJECT (sink, "new segment rate of %f", rate);
- break;
- }
default:
break;
}
G_GINT64_FORMAT, align, maxdrift);
} else {
/* calculate sample diff in seconds for error message */
- gint64 diff_s = gst_util_uint64_scale_int (diff, GST_SECOND,
- ringbuf->spec.rate);
+ gint64 diff_s =
+ gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate);
/* timestamps drifted apart from previous samples too much, we need to
* resync. We log this as an element warning. */
GST_WARNING_OBJECT (sink,
GstBaseAudioSinkClass *bclass;
GstBaseAudioSink *sink;
GstRingBuffer *ringbuf;
- gint64 diff, align, ctime, cstop;
+ gint64 diff, align;
+ guint64 ctime, cstop;
+ gsize offset;
guint8 *data;
- guint size;
+ gsize size;
guint samples, written;
gint bps;
gint accum;
bps = ringbuf->spec.bytes_per_sample;
- size = GST_BUFFER_SIZE (buf);
+ size = gst_buffer_get_size (buf);
if (G_UNLIKELY (size % bps) != 0)
goto wrong_size;
GST_TIME_FORMAT ", samples %u", GST_TIME_ARGS (time), in_offset,
GST_TIME_ARGS (bsink->segment.start), samples);
- data = GST_BUFFER_DATA (buf);
+ offset = 0;
/* if not valid timestamp or we can't clip or sync, try to play
* sample ASAP */
render_stop = render_start + samples;
GST_DEBUG_OBJECT (sink,
"Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT,
- GST_BUFFER_SIZE (buf), render_start);
+ size, render_start);
/* we don't have a start so we don't know stop either */
stop = -1;
goto no_sync;
GST_DEBUG_OBJECT (sink, "clipping start to %" GST_TIME_FORMAT " %"
G_GUINT64_FORMAT " samples", GST_TIME_ARGS (ctime), diff);
samples -= diff;
- data += diff * bps;
+ offset += diff * bps;
time = ctime;
}
diff = stop - cstop;
GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop));
/* bring to position in the ringbuffer */
- if (sink->priv->do_time_offset) {
- time_offset =
- GST_AUDIO_CLOCK_CAST (sink->provided_clock)->abidata.ABI.time_offset;
- GST_DEBUG_OBJECT (sink,
- "time offset %" GST_TIME_FORMAT, GST_TIME_ARGS (time_offset));
- if (render_start > time_offset)
- render_start -= time_offset;
- else
- render_start = 0;
- if (render_stop > time_offset)
- render_stop -= time_offset;
- else
- render_stop = 0;
- }
+ time_offset =
+ GST_AUDIO_CLOCK_CAST (sink->provided_clock)->abidata.ABI.time_offset;
+ GST_DEBUG_OBJECT (sink,
+ "time offset %" GST_TIME_FORMAT, GST_TIME_ARGS (time_offset));
+ if (render_start > time_offset)
+ render_start -= time_offset;
+ else
+ render_start = 0;
+ if (render_stop > time_offset)
+ render_stop -= time_offset;
+ else
+ render_stop = 0;
/* and bring the time to the rate corrected offset in the buffer */
render_start = gst_util_uint64_scale_int (render_start,
/* we need to accumulate over different runs for when we get interrupted */
accum = 0;
align_next = TRUE;
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
do {
written =
- gst_ring_buffer_commit_full (ringbuf, &sample_offset, data, samples,
- out_samples, &accum);
+ gst_ring_buffer_commit_full (ringbuf, &sample_offset, data + offset,
+ samples, out_samples, &accum);
GST_DEBUG_OBJECT (sink, "wrote %u of %u", written, samples);
/* if we wrote all, we're done */
break;
samples -= written;
- data += written * bps;
+ offset += written * bps;
} while (TRUE);
+ gst_buffer_unmap (buf, data, size);
if (align_next)
sink->next_sample = sample_offset;
{
GST_DEBUG_OBJECT (sink, "preroll got interrupted: %d (%s)", ret,
gst_flow_get_name (ret));
+ gst_buffer_unmap (buf, data, size);
goto done;
}
sync_latency_failed:
GstBaseAudioSink *sink;
GstBuffer *buf;
GstFlowReturn ret;
+ gsize size;
basesink = GST_BASE_SINK (user_data);
sink = GST_BASE_AUDIO_SINK (user_data);
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->segment.last_stop, len,
+ gst_pad_pull_range (basesink->sinkpad, basesink->segment.position, len,
&buf);
if (ret != GST_FLOW_OK) {
goto error;
}
- GST_PAD_PREROLL_LOCK (basesink->sinkpad);
+ GST_BASE_SINK_PREROLL_LOCK (basesink);
if (basesink->flushing)
goto flushing;
if (ret != GST_FLOW_OK)
goto preroll_error;
- if (len != GST_BUFFER_SIZE (buf)) {
+ size = gst_buffer_get_size (buf);
+
+ if (len != size) {
GST_INFO_OBJECT (basesink,
- "got different size than requested from sink pad: %u != %u", len,
- GST_BUFFER_SIZE (buf));
- len = MIN (GST_BUFFER_SIZE (buf), len);
+ "got different size than requested from sink pad: %u != %u", len, size);
+ len = MIN (size, len);
}
- basesink->segment.last_stop += len;
+ basesink->segment.position += len;
- memcpy (data, GST_BUFFER_DATA (buf), len);
- GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+ gst_buffer_extract (buf, 0, data, len);
+ GST_BASE_SINK_PREROLL_UNLOCK (basesink);
GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
{
GST_DEBUG_OBJECT (sink, "we are flushing");
gst_ring_buffer_pause (rbuf);
- GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+ GST_BASE_SINK_PREROLL_UNLOCK (basesink);
GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
return;
}
{
GST_DEBUG_OBJECT (sink, "error %s", gst_flow_get_name (ret));
gst_ring_buffer_pause (rbuf);
- GST_PAD_PREROLL_UNLOCK (basesink->sinkpad);
+ GST_BASE_SINK_PREROLL_UNLOCK (basesink);
GST_PAD_STREAM_UNLOCK (basesink->sinkpad);
return;
}
return ret;
}
+#if 0
/* should be called with the LOCK */
static GstStateChangeReturn
gst_base_audio_sink_async_play (GstBaseSink * basesink)
return GST_STATE_CHANGE_SUCCESS;
}
+#endif
static GstStateChangeReturn
gst_base_audio_sink_change_state (GstElement * element,