mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
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:
parent
529f90c29d
commit
5da5fef960
1 changed files with 134 additions and 187 deletions
|
@ -86,7 +86,6 @@ static void NAS_sendData (GstNasSink * sink, AuUint32 numBytes);
|
||||||
static AuBool NAS_EventHandler (AuServer * aud, AuEvent * ev,
|
static AuBool NAS_EventHandler (AuServer * aud, AuEvent * ev,
|
||||||
AuEventHandlerRec * handler);
|
AuEventHandlerRec * handler);
|
||||||
static AuDeviceID NAS_getDevice (AuServer * aud, int numTracks);
|
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);
|
GST_BOILERPLATE (GstNasSink, gst_nas_sink, GstAudioSink, GST_TYPE_AUDIO_SINK);
|
||||||
|
|
||||||
|
@ -199,33 +198,148 @@ gst_nas_sink_getcaps (GstBaseSink * bsink)
|
||||||
return caps;
|
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
|
static gboolean
|
||||||
gst_nas_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
|
gst_nas_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
|
||||||
{
|
{
|
||||||
GstNasSink *sink = GST_NAS_SINK (asink);
|
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; */
|
format = gst_nas_sink_sink_get_format (spec);
|
||||||
/*spec->bytes_per_sample = (spec->width / 8) * spec->channels; */
|
if (format == 0) {
|
||||||
memset (spec->silence_sample, 0, spec->bytes_per_sample);
|
GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
|
||||||
GST_DEBUG_OBJECT (sink, "Sample %d", spec->bytes_per_sample);
|
("Unable to get format %d", spec->format));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (sink, "Format: %d %d\n", spec->format, format);
|
||||||
|
|
||||||
if (sink->audio == NULL)
|
sink->flow = AuGetScratchFlow (sink->audio, NULL);
|
||||||
return TRUE;
|
if (sink->flow == 0) {
|
||||||
|
GST_DEBUG_OBJECT (sink, "couldn't get flow");
|
||||||
if (sink->flow != AuNone) {
|
return FALSE;
|
||||||
GST_DEBUG_OBJECT (sink, "flushing buffer");
|
|
||||||
NAS_flush (sink);
|
|
||||||
AuStopFlow (sink->audio, sink->flow, NULL);
|
|
||||||
AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
|
|
||||||
sink->flow = AuNone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
static gboolean
|
||||||
gst_nas_sink_unprepare (GstAudioSink * asink)
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +357,8 @@ gst_nas_sink_reset (GstAudioSink * asink)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (sink, "reset");
|
GST_DEBUG_OBJECT (sink, "reset");
|
||||||
|
|
||||||
NAS_flush (sink);
|
if (sink->flow != AuNone)
|
||||||
|
AuStopFlow (sink->audio, sink->flow, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
|
@ -342,22 +457,11 @@ gst_nas_sink_close (GstAudioSink * asink)
|
||||||
{
|
{
|
||||||
GstNasSink *sink = GST_NAS_SINK (asink);
|
GstNasSink *sink = GST_NAS_SINK (asink);
|
||||||
|
|
||||||
if (sink->audio == NULL)
|
if (sink->audio) {
|
||||||
return TRUE;
|
AuCloseServer (sink->audio);
|
||||||
|
sink->audio = NULL;
|
||||||
if (sink->flow != AuNone) {
|
|
||||||
NAS_flush (sink);
|
|
||||||
|
|
||||||
AuStopFlow (sink->audio, sink->flow, NULL);
|
|
||||||
AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
|
|
||||||
sink->flow = AuNone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sink->need_data = 0;
|
|
||||||
|
|
||||||
AuCloseServer (sink->audio);
|
|
||||||
sink->audio = NULL;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (sink, "closed audio device");
|
GST_DEBUG_OBJECT (sink, "closed audio device");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -460,163 +564,6 @@ NAS_getDevice (AuServer * aud, int numTracks)
|
||||||
return AuNone;
|
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
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue