nas: Rework nassink a little

Based on patch from <ole.hellqvist at spray.se>
Create and destroy flow in prepare/unprepare
Remove some duplicate code from close and prepare that is now in unprepare.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=674130
This commit is contained in:
Wim Taymans 2012-04-20 12:09:08 +02:00
parent 529f90c29d
commit 5da5fef960

View file

@ -86,7 +86,6 @@ static void NAS_sendData (GstNasSink * sink, AuUint32 numBytes);
static AuBool NAS_EventHandler (AuServer * aud, AuEvent * ev,
AuEventHandlerRec * handler);
static AuDeviceID NAS_getDevice (AuServer * aud, int numTracks);
static int NAS_createFlow (GstNasSink * sink, GstRingBufferSpec * spec);
GST_BOILERPLATE (GstNasSink, gst_nas_sink, GstAudioSink, GST_TYPE_AUDIO_SINK);
@ -199,33 +198,148 @@ gst_nas_sink_getcaps (GstBaseSink * bsink)
return caps;
}
static gint
gst_nas_sink_sink_get_format (const GstRingBufferSpec * spec)
{
gint result;
switch (spec->format) {
case GST_U8:
result = AuFormatLinearUnsigned8;
break;
case GST_S8:
result = AuFormatLinearSigned8;
break;
case GST_S16_LE:
result = AuFormatLinearSigned16LSB;
break;
case GST_S16_BE:
result = AuFormatLinearSigned16MSB;
break;
case GST_U16_LE:
result = AuFormatLinearUnsigned16LSB;
break;
case GST_U16_BE:
result = AuFormatLinearUnsigned16MSB;
break;
default:
result = 0;
break;
}
return result;
}
static gboolean
gst_nas_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
{
GstNasSink *sink = GST_NAS_SINK (asink);
AuElement elements[2];
AuUint32 buf_samples;
unsigned char format;
/*spec->bytes_per_sample = sink->rate * NAS_SOUND_PORT_DURATION; */
/*spec->bytes_per_sample = (spec->width / 8) * spec->channels; */
memset (spec->silence_sample, 0, spec->bytes_per_sample);
GST_DEBUG_OBJECT (sink, "Sample %d", spec->bytes_per_sample);
format = gst_nas_sink_sink_get_format (spec);
if (format == 0) {
GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
("Unable to get format %d", spec->format));
return FALSE;
}
GST_DEBUG_OBJECT (sink, "Format: %d %d\n", spec->format, format);
if (sink->audio == NULL)
return TRUE;
if (sink->flow != AuNone) {
GST_DEBUG_OBJECT (sink, "flushing buffer");
NAS_flush (sink);
AuStopFlow (sink->audio, sink->flow, NULL);
AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
sink->flow = AuNone;
sink->flow = AuGetScratchFlow (sink->audio, NULL);
if (sink->flow == 0) {
GST_DEBUG_OBJECT (sink, "couldn't get flow");
return FALSE;
}
return NAS_createFlow (sink, spec);
buf_samples = spec->rate * NAS_SOUND_PORT_DURATION;
/*
spec->segsize = gst_util_uint64_scale (buf_samples * spec->bytes_per_sample,
spec->latency_time, GST_SECOND / GST_USECOND);
spec->segsize -= spec->segsize % spec->bytes_per_sample;
spec->segtotal = spec->buffer_time / spec->latency_time;
*/
spec->segsize = buf_samples * spec->bytes_per_sample;
spec->segtotal = 1;
memset (spec->silence_sample, 0, spec->bytes_per_sample);
GST_DEBUG_OBJECT (sink, "Bytes per sample %d", spec->bytes_per_sample);
GST_DEBUG_OBJECT (sink, "Rate %d Format %d tracks %d bufs %d %d/%d w %d",
spec->rate, format, spec->channels, (gint) buf_samples, spec->segsize,
spec->segtotal, spec->width);
AuMakeElementImportClient (&elements[0], /* element */
spec->rate, /* rate */
format, /* format */
spec->channels, /* number of tracks */
AuTrue, /* discart */
buf_samples, /* max samples */
(AuUint32) (buf_samples / 100 * AuSoundPortLowWaterMark),
/* low water mark */
0, /* num actions */
NULL);
sink->device = NAS_getDevice (sink->audio, spec->channels);
if (sink->device == AuNone) {
GST_DEBUG_OBJECT (sink, "no device with %i tracks found", spec->channels);
return FALSE;
}
AuMakeElementExportDevice (&elements[1], /* element */
0, /* input */
sink->device, /* device */
spec->rate, /* rate */
AuUnlimitedSamples, /* num samples */
0, /* num actions */
NULL); /* actions */
AuSetElements (sink->audio, /* server */
sink->flow, /* flow ID */
AuTrue, /* clocked */
2, /* num elements */
elements, /* elements */
NULL);
AuRegisterEventHandler (sink->audio, /* server */
AuEventHandlerIDMask, /* value mask */
0, /* type */
sink->flow, /* flow ID */
NAS_EventHandler, /* callback */
(AuPointer) sink); /* data */
AuStartFlow (sink->audio, sink->flow, NULL);
return TRUE;
}
static gboolean
gst_nas_sink_unprepare (GstAudioSink * asink)
{
GstNasSink *sink = GST_NAS_SINK (asink);
if (sink->flow != AuNone) {
AuBool clocked;
int num_elements;
AuStatus status;
AuElement *oldelems;
GST_DEBUG_OBJECT (sink, "flushing buffer");
NAS_flush (sink);
oldelems =
AuGetElements (sink->audio, sink->flow, &clocked, &num_elements,
&status);
if (num_elements > 0) {
GST_DEBUG_OBJECT (sink, "GetElements status: %i", status);
if (oldelems)
AuFreeElements (sink->audio, num_elements, oldelems);
}
AuStopFlow (sink->audio, sink->flow, NULL);
AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
sink->flow = AuNone;
}
sink->need_data = 0;
return TRUE;
}
@ -243,7 +357,8 @@ gst_nas_sink_reset (GstAudioSink * asink)
GST_DEBUG_OBJECT (sink, "reset");
NAS_flush (sink);
if (sink->flow != AuNone)
AuStopFlow (sink->audio, sink->flow, NULL);
}
static guint
@ -342,22 +457,11 @@ gst_nas_sink_close (GstAudioSink * asink)
{
GstNasSink *sink = GST_NAS_SINK (asink);
if (sink->audio == NULL)
return TRUE;
if (sink->flow != AuNone) {
NAS_flush (sink);
AuStopFlow (sink->audio, sink->flow, NULL);
AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
sink->flow = AuNone;
if (sink->audio) {
AuCloseServer (sink->audio);
sink->audio = NULL;
}
sink->need_data = 0;
AuCloseServer (sink->audio);
sink->audio = NULL;
GST_DEBUG_OBJECT (sink, "closed audio device");
return TRUE;
}
@ -460,163 +564,6 @@ NAS_getDevice (AuServer * aud, int numTracks)
return AuNone;
}
static gint
gst_nas_sink_sink_get_format (const GstRingBufferSpec * spec)
{
gint result;
switch (spec->format) {
case GST_U8:
result = AuFormatLinearUnsigned8;
break;
case GST_S8:
result = AuFormatLinearSigned8;
break;
case GST_S16_LE:
result = AuFormatLinearSigned16LSB;
break;
case GST_S16_BE:
result = AuFormatLinearSigned16MSB;
break;
case GST_U16_LE:
result = AuFormatLinearUnsigned16LSB;
break;
case GST_U16_BE:
result = AuFormatLinearUnsigned16MSB;
break;
default:
result = 0;
break;
}
return result;
}
static gboolean
NAS_createFlow (GstNasSink * sink, GstRingBufferSpec * spec)
{
AuElement elements[2];
AuUint32 buf_samples;
unsigned char format;
format = gst_nas_sink_sink_get_format (spec);
if (format == 0) {
GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
("Unable to get format %d", spec->format));
return FALSE;
}
GST_DEBUG_OBJECT (sink, "Format: %d %d\n", spec->format, format);
sink->flow = AuGetScratchFlow (sink->audio, NULL);
if (sink->flow == 0) {
GST_DEBUG_OBJECT (sink, "couldn't get flow");
return FALSE;
}
/* free old Elements and reconnet to server, needed to change samplerate */
{
AuBool clocked;
int num_elements;
AuStatus status;
AuElement *oldelems;
oldelems =
AuGetElements (sink->audio, sink->flow, &clocked, &num_elements,
&status);
if (num_elements > 0) {
GST_DEBUG_OBJECT (sink, "GetElements status: %i", status);
if (oldelems)
AuFreeElements (sink->audio, num_elements, oldelems);
gst_nas_sink_close (GST_AUDIO_SINK (sink));
gst_nas_sink_open (GST_AUDIO_SINK (sink));
sink->flow = AuGetScratchFlow (sink->audio, NULL);
if (sink->flow == 0) {
GST_DEBUG_OBJECT (sink, "couldn't get flow");
return FALSE;
}
}
}
/* free old Elements and reconnet to server, needed to change samplerate */
{
AuBool clocked;
int num_elements;
AuStatus status;
AuElement *oldelems;
oldelems =
AuGetElements (sink->audio, sink->flow, &clocked, &num_elements,
&status);
if (num_elements > 0) {
GST_DEBUG_OBJECT (sink, "GetElements status: %i", status);
if (oldelems)
AuFreeElements (sink->audio, num_elements, oldelems);
gst_nas_sink_close (GST_AUDIO_SINK (sink));
gst_nas_sink_open (GST_AUDIO_SINK (sink));
sink->flow = AuGetScratchFlow (sink->audio, NULL);
if (sink->flow == 0) {
GST_DEBUG_OBJECT (sink, "couldn't get flow");
return FALSE;
}
}
}
buf_samples = spec->rate * NAS_SOUND_PORT_DURATION;
/*
spec->segsize = gst_util_uint64_scale (buf_samples * spec->bytes_per_sample,
spec->latency_time, GST_SECOND / GST_USECOND);
spec->segsize -= spec->segsize % spec->bytes_per_sample;
spec->segtotal = spec->buffer_time / spec->latency_time;
*/
spec->segsize = buf_samples * spec->bytes_per_sample;
spec->segtotal = 1;
GST_DEBUG_OBJECT (sink, "Rate %d Format %d tracks %d bufs %d %d/%d w %d",
spec->rate, format, spec->channels, (gint) buf_samples, spec->segsize,
spec->segtotal, spec->width);
AuMakeElementImportClient (&elements[0], /* element */
spec->rate, /* rate */
format, /* format */
spec->channels, /* number of tracks */
AuTrue, /* discart */
buf_samples, /* max samples */
(AuUint32) (buf_samples / 100 * AuSoundPortLowWaterMark),
/* low water mark */
0, /* num actions */
NULL);
sink->device = NAS_getDevice (sink->audio, spec->channels);
if (sink->device == AuNone) {
GST_DEBUG_OBJECT (sink, "no device with %i tracks found", spec->channels);
return FALSE;
}
AuMakeElementExportDevice (&elements[1], /* element */
0, /* input */
sink->device, /* device */
spec->rate, /* rate */
AuUnlimitedSamples, /* num samples */
0, /* num actions */
NULL); /* actions */
AuSetElements (sink->audio, /* server */
sink->flow, /* flow ID */
AuTrue, /* clocked */
2, /* num elements */
elements, /* elements */
NULL);
AuRegisterEventHandler (sink->audio, /* server */
AuEventHandlerIDMask, /* value mask */
0, /* type */
sink->flow, /* flow ID */
NAS_EventHandler, /* callback */
(AuPointer) sink); /* data */
AuStartFlow (sink->audio, sink->flow, NULL);
return TRUE;
}
static gboolean
plugin_init (GstPlugin * plugin)
{