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
Родитель 57230defd8
Коммит 0976560f44
1 изменённых файлов: 29 добавлений и 26 удалений

Просмотреть файл

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