diff --git a/media/libcubeb/src/cubeb_opensl.c b/media/libcubeb/src/cubeb_opensl.c index 8e492041e8bd..1861dcc0815e 100644 --- a/media/libcubeb/src/cubeb_opensl.c +++ b/media/libcubeb/src/cubeb_opensl.c @@ -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; }