libpulseaudio: handle unlink properly (#2693)

Also clean up some more garbage.
This commit is contained in:
tomty89 2018-08-01 03:19:39 +08:00 committed by Fredrik Fornwall
parent d72aa90221
commit 6be3fd61e0

View File

@ -42,25 +42,6 @@
#include <pulsecore/rtpoll.h> #include <pulsecore/rtpoll.h>
#include <SLES/OpenSLES.h> #include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#define USE_ANDROID_SIMPLE_BUFFER_QUEUE
#ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE
#define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
#define IID_BUFFERQUEUE SL_IID_ANDROIDSIMPLEBUFFERQUEUE
#define BufferQueueItf SLAndroidSimpleBufferQueueItf
#define BufferQueueState SLAndroidSimpleBufferQueueState
#define IID_BUFFERQUEUE_USED SL_IID_ANDROIDSIMPLEBUFFERQUEUE
#define INDEX index
#else
#define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_BUFFERQUEUE
#define IID_BUFFERQUEUE SL_IID_BUFFERQUEUE
#define BufferQueueItf SLBufferQueueItf
#define BufferQueueState SLBufferQueueState
#define IID_BUFFERQUEUE_USED IID_BUFFERQUEUE
#define INDEX playIndex
#endif
PA_MODULE_AUTHOR("Lennart Poettering, Nathan Martynov"); PA_MODULE_AUTHOR("Lennart Poettering, Nathan Martynov");
PA_MODULE_DESCRIPTION("Android OpenSL ES sink"); PA_MODULE_DESCRIPTION("Android OpenSL ES sink");
@ -98,7 +79,7 @@ struct userdata {
// buffer queue player interfaces // buffer queue player interfaces
SLObjectItf bqPlayerObject; SLObjectItf bqPlayerObject;
SLPlayItf bqPlayerPlay; SLPlayItf bqPlayerPlay;
BufferQueueItf bqPlayerBufferQueue; SLBufferQueueItf bqPlayerBufferQueue;
}; };
static const char* const valid_modargs[] = { static const char* const valid_modargs[] = {
@ -109,36 +90,28 @@ static const char* const valid_modargs[] = {
NULL NULL
}; };
static void process_render(BufferQueueItf bq, void *userdata) { static void process_render(SLBufferQueueItf bq, void *userdata) {
struct userdata* u = userdata; struct userdata* u = userdata;
void *p; void *p;
pa_assert(u); pa_assert(u);
//pa_log_debug("Called\n");
if (!pa_thread_mq_get()) { if (!pa_thread_mq_get()) {
pa_log_debug("Thread starting up"); pa_log_debug("Thread starting up");
pa_thread_mq_install(&u->thread_mq); pa_thread_mq_install(&u->thread_mq);
} }
if (u->memchunk.memblock) { if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock); pa_memblock_unref(u->memchunk.memblock);
//pa_log_debug("Unrefed\n");
}
if (PA_SINK_IS_LINKED(u->sink->thread_info.state) &&
PA_UNLIKELY(u->sink->thread_info.rewind_requested)) {
//pa_log_debug("Rewinded\n");
pa_sink_process_rewind(u->sink, 0);
}
if (PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
pa_sink_render(u->sink, u->sink->thread_info.max_request, &u->memchunk); pa_sink_render(u->sink, u->sink->thread_info.max_request, &u->memchunk);
p = pa_memblock_acquire_chunk(&u->memchunk); p = pa_memblock_acquire_chunk(&u->memchunk);
(*bq)->Enqueue(bq, p, u->memchunk.length); (*bq)->Enqueue(bq, p, u->memchunk.length);
//pa_log_debug("Written: %zu\n", u->memchunk.length);
pa_memblock_release(u->memchunk.memblock); pa_memblock_release(u->memchunk.memblock);
} }
static void process_rewind(pa_sink *s) {
pa_sink_process_rewind(s, 0);
} }
#define CHK(stmt) { \ #define CHK(stmt) { \
@ -170,7 +143,7 @@ static int pa_init_sles_player(struct userdata *u, SLint32 sl_rate)
locator_outputmix.outputMix = u->outputMixObject; locator_outputmix.outputMix = u->outputMixObject;
SLDataLocator_BufferQueue locator_bufferqueue; SLDataLocator_BufferQueue locator_bufferqueue;
locator_bufferqueue.locatorType = DATALOCATOR_BUFFERQUEUE; locator_bufferqueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
locator_bufferqueue.numBuffers = 1; locator_bufferqueue.numBuffers = 1;
if (sl_rate < 8000 || sl_rate > 192000) { if (sl_rate < 8000 || sl_rate > 192000) {
@ -195,18 +168,16 @@ static int pa_init_sles_player(struct userdata *u, SLint32 sl_rate)
audiosnk.pLocator = &locator_outputmix; audiosnk.pLocator = &locator_outputmix;
audiosnk.pFormat = NULL; audiosnk.pFormat = NULL;
SLInterfaceID ids[1] = {IID_BUFFERQUEUE}; SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};
SLboolean flags[1] = {SL_BOOLEAN_TRUE}; SLboolean flags[1] = {SL_BOOLEAN_TRUE};
CHK((*u->engineEngine)->CreateAudioPlayer(u->engineEngine, &u->bqPlayerObject, &audiosrc, &audiosnk, 1, ids, flags)); CHK((*u->engineEngine)->CreateAudioPlayer(u->engineEngine, &u->bqPlayerObject, &audiosrc, &audiosnk, 1, ids, flags));
CHK((*u->bqPlayerObject)->Realize(u->bqPlayerObject, SL_BOOLEAN_FALSE)); CHK((*u->bqPlayerObject)->Realize(u->bqPlayerObject, SL_BOOLEAN_FALSE));
CHK((*u->bqPlayerObject)->GetInterface(u->bqPlayerObject, SL_IID_PLAY, &u->bqPlayerPlay)); CHK((*u->bqPlayerObject)->GetInterface(u->bqPlayerObject, SL_IID_PLAY, &u->bqPlayerPlay));
CHK((*u->bqPlayerObject)->GetInterface(u->bqPlayerObject, IID_BUFFERQUEUE_USED, &u->bqPlayerBufferQueue)); CHK((*u->bqPlayerObject)->GetInterface(u->bqPlayerObject, SL_IID_BUFFERQUEUE, &u->bqPlayerBufferQueue));
CHK((*u->bqPlayerBufferQueue)->RegisterCallback(u->bqPlayerBufferQueue, process_render, u)); CHK((*u->bqPlayerBufferQueue)->RegisterCallback(u->bqPlayerBufferQueue, process_render, u));
CHK((*u->bqPlayerPlay)->SetPlayState(u->bqPlayerPlay, SL_PLAYSTATE_PLAYING));
return 0; return 0;
fail: fail:
@ -217,7 +188,6 @@ fail:
static void pa_destroy_sles_player(struct userdata *u){ static void pa_destroy_sles_player(struct userdata *u){
if (u == NULL) return; if (u == NULL) return;
(*u->bqPlayerPlay)->SetPlayState(u->bqPlayerPlay, SL_PLAYSTATE_STOPPED);
(*u->bqPlayerObject)->Destroy(u->bqPlayerObject); (*u->bqPlayerObject)->Destroy(u->bqPlayerObject);
(*u->outputMixObject)->Destroy(u->outputMixObject); (*u->outputMixObject)->Destroy(u->outputMixObject);
(*u->engineObject)->Destroy(u->engineObject); (*u->engineObject)->Destroy(u->engineObject);
@ -270,13 +240,12 @@ static int state_func(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t susp
struct userdata *u = s->userdata; struct userdata *u = s->userdata;
int r = 0; int r = 0;
if (PA_SINK_IS_OPENED(s->state) && state == PA_SINK_SUSPENDED) { if ((PA_SINK_IS_OPENED(s->state) && state == PA_SINK_SUSPENDED) ||
(PA_SINK_IS_LINKED(s->state) && state == PA_SINK_UNLINKED))
r = (*u->bqPlayerPlay)->SetPlayState(u->bqPlayerPlay, SL_PLAYSTATE_STOPPED); r = (*u->bqPlayerPlay)->SetPlayState(u->bqPlayerPlay, SL_PLAYSTATE_STOPPED);
//pa_log_debug("Suspended on idle\n"); else if ((s->state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
} else if (s->state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) { (s->state == PA_SINK_INIT && PA_SINK_IS_LINKED(state)))
r = (*u->bqPlayerPlay)->SetPlayState(u->bqPlayerPlay, SL_PLAYSTATE_PLAYING); r = (*u->bqPlayerPlay)->SetPlayState(u->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
//pa_log_debug("Resume from suspension\n");
}
return r; return r;
} }
@ -341,6 +310,7 @@ int pa__init(pa_module*m) {
u->sink->parent.process_msg = pa_sink_process_msg; u->sink->parent.process_msg = pa_sink_process_msg;
u->sink->set_state_in_main_thread = state_func; u->sink->set_state_in_main_thread = state_func;
u->sink->request_rewind = process_rewind;
u->sink->userdata = u; u->sink->userdata = u;
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);