opensles: rework on the ringbufffer to properly clear segments

Make the segments bigger (1 second) as it seems to be the minimum size
we need to not introduce noise.
Sink works in my nexus 7 with rates from 8000 to 44100 and some noise
can be noticed on higger sample rates.
This commit is contained in:
Josep Torra 2012-09-20 14:16:25 +02:00 committed by Sebastian Dröge
parent 29334f3233
commit 0291953997
2 changed files with 39 additions and 30 deletions

View file

@ -126,11 +126,11 @@ _opensles_recorder_cb (SLAndroidSimpleBufferQueueItf bufferQueue, void *context)
}
static gboolean
_opensles_recorder_acquire (GstRingBuffer * rb, guint nbuffers,
SLDataFormat_PCM * format)
_opensles_recorder_acquire (GstRingBuffer * rb, GstRingBufferSpec * spec)
{
GstOpenSLESRingBuffer *thiz = GST_OPENSLES_RING_BUFFER_CAST (rb);
SLresult result;
SLDataFormat_PCM format;
/* Configure audio source */
SLDataLocator_IODevice loc_dev =
@ -141,12 +141,16 @@ _opensles_recorder_acquire (GstRingBuffer * rb, guint nbuffers,
/* Configure audio sink */
SLDataLocator_AndroidSimpleBufferQueue loc_bq =
{ SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, nbuffers };
SLDataSink audioSink = { &loc_bq, format };
{ SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
SLDataSink audioSink = { &loc_bq, &format };
/* Create audio recorder (requires the RECORD_AUDIO permission) */
const SLInterfaceID id[1] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
const SLboolean req[1] = { SL_BOOLEAN_TRUE };
/* Define the format in OpenSL ES terms */
_opensles_format (spec, &format);
result = (*thiz->engineEngine)->CreateAudioRecorder (thiz->engineEngine,
&thiz->recorderObject, &audioSrc, &audioSink, 1, id, req);
if (result != SL_RESULT_SUCCESS) {
@ -192,6 +196,10 @@ _opensles_recorder_acquire (GstRingBuffer * rb, guint nbuffers,
goto failed;
}
/* Define our ringbuffer in terms of number of buffers and buffer size. */
spec->segsize = (spec->rate * spec->bytes_per_sample) >> 1;
spec->segtotal = 3;
return TRUE;
failed:
@ -279,27 +287,29 @@ _opensles_player_cb (SLAndroidSimpleBufferQueueItf bufferQueue, void *context)
return;
}
if (thiz->last_readseg >= 0) {
GST_LOG_OBJECT (thiz, "clear segment %d", thiz->last_readseg);
if (G_UNLIKELY (thiz->last_clearseg < 0)) {
thiz->last_clearseg++;
} else {
GST_LOG_OBJECT (thiz, "clear segment %d", thiz->last_clearseg);
/* Clear written samples */
gst_ring_buffer_clear (rb, thiz->last_readseg);
gst_ring_buffer_clear (rb, thiz->last_clearseg);
thiz->last_clearseg = (thiz->last_clearseg + 1) % rb->spec.segtotal;
/* We wrote one segment */
}
gst_ring_buffer_advance (rb, 1);
thiz->last_readseg = readseg;
}
static gboolean
_opensles_player_acquire (GstRingBuffer * rb, guint nbuffers,
SLDataFormat_PCM * format)
_opensles_player_acquire (GstRingBuffer * rb, GstRingBufferSpec * spec)
{
GstOpenSLESRingBuffer *thiz = GST_OPENSLES_RING_BUFFER_CAST (rb);
SLresult result;
SLDataFormat_PCM format;
/* Configure audio source */
SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
{ SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
SLDataSource audioSrc = { &loc_bufq, format };
SLDataSource audioSrc = { &loc_bufq, &format };
/* Configure audio sink */
SLDataLocator_OutputMix loc_outmix =
@ -310,6 +320,9 @@ _opensles_player_acquire (GstRingBuffer * rb, guint nbuffers,
const SLInterfaceID ids[2] = { SL_IID_BUFFERQUEUE, SL_IID_VOLUME };
const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
/* Define the format in OpenSL ES terms */
_opensles_format (spec, &format);
result = (*thiz->engineEngine)->CreateAudioPlayer (thiz->engineEngine,
&thiz->playerObject, &audioSrc, &audioSink, 2, ids, req);
if (result != SL_RESULT_SUCCESS) {
@ -362,6 +375,15 @@ _opensles_player_acquire (GstRingBuffer * rb, guint nbuffers,
goto failed;
}
/* Define our ringbuffer in terms of number of buffers and buffer size. */
spec->segsize = (spec->rate * spec->bytes_per_sample);
spec->segtotal = 4;
/* In the Nexus7 device where I'm testing seems that I need buffers of
* min 1 second of audio.
* Then here we created 4 segments of a second and a queue of 2 buffers
* in order to properly clear the older segment */
thiz->last_clearseg = -3;
return TRUE;
failed:
@ -383,9 +405,9 @@ _opensles_player_start (GstRingBuffer * rb)
return FALSE;
}
/* Enqueue some initial data */
/* Fill the queue by enqueing two buffers */
_opensles_player_cb (NULL, rb);
_opensles_player_cb (NULL, rb);
return TRUE;
}
@ -542,22 +564,11 @@ static gboolean
gst_opensles_ringbuffer_acquire (GstRingBuffer * rb, GstRingBufferSpec * spec)
{
GstOpenSLESRingBuffer *thiz;
SLDataFormat_PCM format;
thiz = GST_OPENSLES_RING_BUFFER_CAST (rb);
/* Define ringbuffer in terms of number of buffers and buffer size */
spec->segsize =
(spec->latency_time * spec->rate / G_USEC_PER_SEC) *
spec->bytes_per_sample;
spec->segtotal = (spec->buffer_time / spec->latency_time) << 4;
thiz->last_readseg = -1;
/* Define the format in OpenSL ES terms */
_opensles_format (spec, &format);
/* Instantiate and configure the OpenSL ES devices */
if (!thiz->acquire (rb, spec->segtotal, &format)) {
/* Instantiate and configure the OpenSL ES interfaces */
if (!thiz->acquire (rb, spec)) {
return FALSE;
}

View file

@ -52,9 +52,7 @@ typedef enum
RB_MODE_LAST
} RingBufferMode;
typedef gboolean (*AcquireFunc) (GstRingBuffer * rb, guint nbuffers,
SLDataFormat_PCM * format);
typedef gboolean (*AcquireFunc) (GstRingBuffer * rb, GstRingBufferSpec * spec);
typedef gboolean (*StateFunc) (GstRingBuffer * rb);
typedef struct _GstOpenSLESRingBuffer GstOpenSLESRingBuffer;
@ -84,7 +82,7 @@ struct _GstOpenSLESRingBuffer
/* buffer queue */
SLAndroidSimpleBufferQueueItf bufferQueue;
gint last_readseg;
gint last_clearseg;
/* vmethods */
AcquireFunc acquire;