Bug 788402 - Improve queue handling in opensl backend, r=kinetik

This commit is contained in:
Michael Wu 2012-09-13 14:34:54 -04:00
parent 57230defd8
commit 0976560f44

View File

@ -28,6 +28,7 @@ struct cubeb_stream {
long queuebuf_len;
long bytespersec;
long framesize;
int draining;
cubeb_data_callback data_callback;
cubeb_state_callback state_callback;
@ -37,24 +38,38 @@ struct cubeb_stream {
static void
bufferqueue_callback(SLBufferQueueItf caller, struct cubeb_stream *stm)
{
void *buf = stm->queuebuf[stm->queuebuf_idx];
SLBufferQueueState state;
(*stm->bufq)->GetState(stm->bufq, &state);
long written = stm->data_callback(stm, stm->user_ptr,
buf, stm->queuebuf_len / stm->framesize);
if (written <= 0)
if (stm->draining) {
if (!state.count) {
stm->draining = 0;
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
}
return;
}
if (state.count > 1)
return;
(*stm->bufq)->Enqueue(stm->bufq, buf, written * stm->framesize);
SLuint32 i;
for (i = state.count; i < NBUFS; i++) {
void *buf = stm->queuebuf[stm->queuebuf_idx];
long written = stm->data_callback(stm, stm->user_ptr,
buf, stm->queuebuf_len / stm->framesize);
if (written == CUBEB_ERROR) {
(*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_STOPPED);
return;
}
stm->queuebuf_idx = (stm->queuebuf_idx + 1) % NBUFS;
// XXX handle error
}
(*stm->bufq)->Enqueue(stm->bufq, buf, written * stm->framesize);
stm->queuebuf_idx = (stm->queuebuf_idx + 1) % NBUFS;
static void
play_callback(SLPlayItf caller, struct cubeb_stream *stm, SLuint32 event)
{
if (event & SL_PLAYEVENT_HEADSTALLED)
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
if ((written * stm->framesize) < stm->queuebuf_len) {
stm->draining = 1;
return;
}
}
}
int
@ -228,18 +243,6 @@ cubeb_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
return CUBEB_ERROR;
}
res = (*stm->play)->RegisterCallback(stm->play, play_callback, stm);
if (res != SL_RESULT_SUCCESS) {
cubeb_stream_destroy(stm);
return CUBEB_ERROR;
}
res = (*stm->play)->SetCallbackEventsMask(stm->play, SL_PLAYEVENT_HEADSTALLED);
if (res != SL_RESULT_SUCCESS) {
cubeb_stream_destroy(stm);
return CUBEB_ERROR;
}
*stream = stm;
return CUBEB_OK;
@ -283,7 +286,7 @@ cubeb_stream_get_position(cubeb_stream * stm, uint64_t * position)
SLresult res = (*stm->play)->GetPosition(stm->play, &msec);
if (res != SL_RESULT_SUCCESS)
return CUBEB_ERROR;
*position = (stm->bytespersec * msec) / (1000 * stm->framesize);
*position = (stm->bytespersec / (1000 * stm->framesize)) * msec;
return CUBEB_OK;
}