mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
ext/alsa/: - add debugging info
Original commit message from CVS: * ext/alsa/gstalsa.c: (gst_alsa_drain_audio): * ext/alsa/gstalsasink.c: (gst_alsa_sink_flush_one_pad), (gst_alsa_sink_check_event), (gst_alsa_sink_mmap), (gst_alsa_sink_write), (gst_alsa_sink_loop): * ext/alsa/gstalsasink.h: - add debugging info - clean up schizophrenia of data/buffer/event - fix double event unref error
This commit is contained in:
parent
ca95579d23
commit
253c4e7267
4 changed files with 77 additions and 43 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2004-07-08 Thomas Vander Stichele <thomas (at) apestaart (dot) org>
|
||||
|
||||
* ext/alsa/gstalsa.c: (gst_alsa_drain_audio):
|
||||
* ext/alsa/gstalsasink.c: (gst_alsa_sink_flush_one_pad),
|
||||
(gst_alsa_sink_check_event), (gst_alsa_sink_mmap),
|
||||
(gst_alsa_sink_write), (gst_alsa_sink_loop):
|
||||
* ext/alsa/gstalsasink.h:
|
||||
- add debugging info
|
||||
- clean up schizophrenia of data/buffer/event
|
||||
- fix double event unref error
|
||||
|
||||
2004-07-08 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/playback/Makefile.am:
|
||||
|
|
|
@ -1579,6 +1579,7 @@ gst_alsa_drain_audio (GstAlsa * this)
|
|||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG ("stopped alsa");
|
||||
GST_FLAG_UNSET (this, GST_ALSA_RUNNING);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -160,18 +160,21 @@ gst_alsa_sink_init (GstAlsaSink * sink)
|
|||
static inline void
|
||||
gst_alsa_sink_flush_one_pad (GstAlsaSink * sink, gint i)
|
||||
{
|
||||
GST_DEBUG_OBJECT (sink, "flushing pad %d", i);
|
||||
switch (sink->behaviour[i]) {
|
||||
case 0:
|
||||
if (sink->buf[i])
|
||||
gst_data_unref (GST_DATA (sink->buf[i]));
|
||||
sink->buf[i] = NULL;
|
||||
sink->data[i] = NULL;
|
||||
if (sink->gst_data[i]) {
|
||||
GST_DEBUG_OBJECT (sink, "unreffing gst data %p", sink->gst_data[i]);
|
||||
gst_data_unref (GST_DATA (sink->gst_data[i]));
|
||||
}
|
||||
sink->gst_data[i] = NULL;
|
||||
sink->buf_data[i] = NULL;
|
||||
sink->behaviour[i] = 0;
|
||||
sink->size[i] = 0;
|
||||
break;
|
||||
case 1:
|
||||
g_free (sink->data[i]);
|
||||
sink->data[i] = NULL;
|
||||
g_free (sink->buf_data[i]);
|
||||
sink->buf_data[i] = NULL;
|
||||
sink->behaviour[i] = 0;
|
||||
sink->size[i] = 0;
|
||||
break;
|
||||
|
@ -196,9 +199,14 @@ static gboolean
|
|||
gst_alsa_sink_check_event (GstAlsaSink * sink, gint pad_nr)
|
||||
{
|
||||
gboolean cont = TRUE;
|
||||
GstEvent *event = GST_EVENT (sink->buf[pad_nr]);
|
||||
GstEvent *event;
|
||||
GstAlsa *this = GST_ALSA (sink);
|
||||
|
||||
/* we get the event from our internal buffer and clear the internal one */
|
||||
event = GST_EVENT (sink->gst_data[pad_nr]);
|
||||
sink->gst_data[pad_nr] = 0;
|
||||
GST_LOG_OBJECT (sink, "checking event %p of type %d on sink pad %d",
|
||||
event, GST_EVENT_TYPE (event), pad_nr);
|
||||
if (event) {
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
|
@ -241,8 +249,10 @@ gst_alsa_sink_check_event (GstAlsaSink * sink, gint pad_nr)
|
|||
GST_EVENT_TYPE (event));
|
||||
break;
|
||||
}
|
||||
GST_LOG_OBJECT (sink, "unreffing event %p of type %d with refcount %d",
|
||||
event, GST_EVENT_TYPE (event), GST_DATA_REFCOUNT (event));
|
||||
gst_event_unref (event);
|
||||
sink->buf[pad_nr] = NULL;
|
||||
sink->gst_data[pad_nr] = NULL;
|
||||
} else {
|
||||
/* the element at the top of the chain did not emit an event. */
|
||||
g_assert_not_reached ();
|
||||
|
@ -266,14 +276,14 @@ gst_alsa_sink_mmap (GstAlsa * this, snd_pcm_sframes_t * avail)
|
|||
if (((GstElement *) this)->numpads == 1) {
|
||||
/* interleaved */
|
||||
for (i = 0; i < this->format->channels; i++) {
|
||||
src[i].addr = sink->data[0];
|
||||
src[i].addr = sink->buf_data[0];
|
||||
src[i].first = i * width;
|
||||
src[i].step = this->format->channels * width;
|
||||
}
|
||||
} else {
|
||||
/* noninterleaved */
|
||||
for (i = 0; i < this->format->channels; i++) {
|
||||
src[i].addr = sink->data[i];
|
||||
src[i].addr = sink->buf_data[i];
|
||||
src[i].first = 0;
|
||||
src[i].step = width;
|
||||
}
|
||||
|
@ -309,11 +319,11 @@ gst_alsa_sink_write (GstAlsa * this, snd_pcm_sframes_t * avail)
|
|||
|
||||
if (((GstElement *) this)->numpads == 1) {
|
||||
/* interleaved */
|
||||
err = snd_pcm_writei (this->handle, sink->data[0], *avail);
|
||||
err = snd_pcm_writei (this->handle, sink->buf_data[0], *avail);
|
||||
} else {
|
||||
/* noninterleaved */
|
||||
for (i = 0; i < this->format->channels; i++) {
|
||||
channels[i] = sink->data[i];
|
||||
channels[i] = sink->buf_data[i];
|
||||
}
|
||||
err = snd_pcm_writen (this->handle, channels, *avail);
|
||||
}
|
||||
|
@ -354,36 +364,47 @@ sink_restart:
|
|||
}
|
||||
|
||||
/* check how many bytes we still have in all our bytestreams */
|
||||
/* initialize this value to a somewhat sane state, we might alloc this much data below (which would be a bug, but who knows)... */
|
||||
/* initialize this value to a somewhat sane state, we might alloc
|
||||
* this much data below (which would be a bug, but who knows)... */
|
||||
bytes = this->period_size * this->period_count * element->numpads * 8; /* must be > max sample size in bytes */
|
||||
for (i = 0; i < element->numpads; i++) {
|
||||
GstBuffer *buf;
|
||||
|
||||
g_assert (this->pad[i] != NULL);
|
||||
while (sink->size[i] == 0) {
|
||||
if (!sink->buf[i])
|
||||
sink->buf[i] = GST_BUFFER (gst_pad_pull (this->pad[i]));
|
||||
if (GST_IS_EVENT (sink->buf[i])) {
|
||||
if (!sink->gst_data[i]) {
|
||||
sink->gst_data[i] = gst_pad_pull (this->pad[i]);
|
||||
GST_LOG_OBJECT (sink, "pulled data %p from pad %d",
|
||||
sink->gst_data[i], i);
|
||||
}
|
||||
|
||||
if (GST_IS_EVENT (sink->gst_data[i])) {
|
||||
GST_LOG_OBJECT (sink, "pulled data %p is an event, checking",
|
||||
sink->gst_data[i]);
|
||||
if (gst_alsa_sink_check_event (sink, i))
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
/* caps nego failed somewhere */
|
||||
/* it's a buffer */
|
||||
g_return_if_fail (GST_IS_BUFFER (sink->gst_data[i]));
|
||||
buf = GST_BUFFER (sink->gst_data[i]);
|
||||
/* check if caps nego failed somewhere */
|
||||
if (this->format == NULL) {
|
||||
GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL),
|
||||
("ALSA format not negotiated"));
|
||||
}
|
||||
samplestamp =
|
||||
gst_alsa_timestamp_to_samples (this,
|
||||
GST_BUFFER_TIMESTAMP (sink->buf[i]));
|
||||
samplestamp = gst_alsa_timestamp_to_samples (this,
|
||||
GST_BUFFER_TIMESTAMP (buf));
|
||||
max_discont = gst_alsa_timestamp_to_samples (this, this->max_discont);
|
||||
/* optimization: check if we're using our own clock
|
||||
* This optimization is important because if we're using our own clock
|
||||
* gst_element_get_time calls snd_pcm_delay and the following code assumes
|
||||
* that both calls return the same value. However they can be wildly
|
||||
* different, since snd_pcm_delay goes deep into the kernel.
|
||||
* This optimization is important because if we're using our own clock
|
||||
* gst_element_get_time calls snd_pcm_delay and the following code
|
||||
* assumes that both calls return the same value. However they can be
|
||||
* wildly different, since snd_pcm_delay goes deep into the kernel.
|
||||
*/
|
||||
if (gst_element_get_clock (element) == GST_CLOCK (this->clock)) {
|
||||
/* FIXME: this is ugly because of the variables it uses but I don't know a
|
||||
* better way to get this info */
|
||||
/* FIXME: this is ugly because of the variables it uses but I
|
||||
* don't know a better way to get this info */
|
||||
if (element->base_time > this->clock->start_time) {
|
||||
expected =
|
||||
this->played - gst_alsa_timestamp_to_samples (this,
|
||||
|
@ -404,13 +425,13 @@ sink_restart:
|
|||
}
|
||||
sample_diff = samplestamp - expected;
|
||||
|
||||
if ((!GST_BUFFER_TIMESTAMP_IS_VALID (sink->buf[i])) ||
|
||||
if ((!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) ||
|
||||
(-max_discont <= sample_diff && sample_diff <= max_discont)) {
|
||||
|
||||
/* difference between expected and current is < GST_ALSA_DEVIATION */
|
||||
no_difference:
|
||||
sink->size[i] = sink->buf[i]->size;
|
||||
sink->data[i] = sink->buf[i]->data;
|
||||
sink->size[i] = GST_BUFFER_SIZE (buf);
|
||||
sink->buf_data[i] = GST_BUFFER_DATA (buf);
|
||||
sink->behaviour[i] = 0;
|
||||
} else if (sample_diff > 0) {
|
||||
/* there are empty samples in front of us, fill them with silence */
|
||||
|
@ -422,28 +443,28 @@ sink_restart:
|
|||
GST_INFO_OBJECT (this,
|
||||
"Allocating %d bytes (%ld samples) now to resync: sample %lu expected, but got %ld",
|
||||
size, MIN (bytes, sample_diff), expected, samplestamp);
|
||||
sink->data[i] = g_try_malloc (size);
|
||||
if (!sink->data[i]) {
|
||||
sink->buf_data[i] = g_try_malloc (size);
|
||||
if (!sink->buf_data[i]) {
|
||||
GST_WARNING_OBJECT (this,
|
||||
"error allocating %d bytes, buffers unsynced now.", size);
|
||||
goto no_difference;
|
||||
}
|
||||
sink->size[i] = size;
|
||||
if (0 != snd_pcm_format_set_silence (this->format->format,
|
||||
sink->data[i], samples)) {
|
||||
sink->buf_data[i], samples)) {
|
||||
GST_WARNING_OBJECT (this,
|
||||
"error silencing buffer, enjoy the noise.");
|
||||
}
|
||||
sink->behaviour[i] = 1;
|
||||
} else if (gst_alsa_samples_to_bytes (this,
|
||||
-sample_diff) >= sink->buf[i]->size) {
|
||||
} else if (gst_alsa_samples_to_bytes (this, -sample_diff) >=
|
||||
GST_BUFFER_SIZE (buf)) {
|
||||
GST_INFO_OBJECT (this,
|
||||
"Skipping %lu samples to resync (complete buffer): sample %lu expected, but got %ld",
|
||||
gst_alsa_bytes_to_samples (this, sink->buf[i]->size), expected,
|
||||
gst_alsa_bytes_to_samples (this, GST_BUFFER_SIZE (buf)), expected,
|
||||
samplestamp);
|
||||
/* this buffer is way behind */
|
||||
gst_buffer_unref (sink->buf[i]);
|
||||
sink->buf[i] = NULL;
|
||||
gst_buffer_unref (buf);
|
||||
sink->gst_data[i] = NULL;
|
||||
continue;
|
||||
} else if (sample_diff < 0) {
|
||||
gint difference = gst_alsa_samples_to_bytes (this, -sample_diff);
|
||||
|
@ -452,8 +473,8 @@ sink_restart:
|
|||
"Skipping %lu samples to resync: sample %lu expected, but got %ld",
|
||||
(gulong) - sample_diff, expected, samplestamp);
|
||||
/* this buffer is only a bit behind */
|
||||
sink->size[i] = sink->buf[i]->size - difference;
|
||||
sink->data[i] = sink->buf[i]->data + difference;
|
||||
sink->size[i] = GST_BUFFER_SIZE (buf) - difference;
|
||||
sink->buf_data[i] = GST_BUFFER_DATA (buf) + difference;
|
||||
sink->behaviour[i] = 0;
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
|
@ -479,7 +500,8 @@ sink_restart:
|
|||
return;
|
||||
}
|
||||
|
||||
/* FIXME: lotsa stuff can have happened while fetching data. Do we need to check something? */
|
||||
/* FIXME: lotsa stuff can have happened while fetching data.
|
||||
* Do we need to check something? */
|
||||
|
||||
/* put this data into alsa */
|
||||
if ((copied = this->transmit (this, &avail)) < 0)
|
||||
|
@ -495,7 +517,7 @@ sink_restart:
|
|||
}
|
||||
g_assert (sink->size[i] > 0);
|
||||
if (sink->behaviour[i] != 1)
|
||||
sink->data[i] += bytes;
|
||||
sink->buf_data[i] += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ struct _GstAlsaSink {
|
|||
GstAlsaMixer parent;
|
||||
|
||||
/* array of the data on the channels */
|
||||
guint8 *data[GST_ALSA_MAX_TRACKS]; /* pointer into buffer */
|
||||
guint8 *buf_data[GST_ALSA_MAX_TRACKS]; /* pointer into buffer */
|
||||
guint size[GST_ALSA_MAX_TRACKS]; /* sink: bytes left in buffer */
|
||||
GstBuffer *buf[GST_ALSA_MAX_TRACKS]; /* current buffer */
|
||||
GstData *gst_data[GST_ALSA_MAX_TRACKS]; /* current data */
|
||||
guint behaviour[GST_ALSA_MAX_TRACKS]; /* 0 = data points into buffer (so unref when size == 0),
|
||||
1 = data should be freed, use buffer after that */
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue