From 57a6e11523a6bf3ae61c38370774edfc406f71e7 Mon Sep 17 00:00:00 2001 From: KimJeongYeon Date: Thu, 19 Jan 2017 14:02:11 +0900 Subject: [PATCH] audio-io fixed no callback issue at start Changes: * In case of asyncronous write, never callback will be invoked when application has wrote less than prebuf(-1) at first callback. To avoid deadlock between applicaiton and pulseaudio, audio-io ensure to write at least size of prebuf. * Need to move enabling __mIsInit flag to state changed callback. Because of some audio-io APIs rejected at first stream callback. (e.g audio_out_drain, audio_out_flush, ...) [Version] 0.3.56 [Profile] Common [Issue Type] Compatibility Signed-off-by: KimJeongYeon Change-Id: I64e43913c6a22ab2003615b40b9e616c59423628 --- include/CPulseAudioClient.h | 1 + packaging/capi-media-audio-io.spec | 2 +- src/cpp/CPulseAudioClient.cpp | 28 +++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/CPulseAudioClient.h b/include/CPulseAudioClient.h index af3f0c5..b2778a3 100644 --- a/include/CPulseAudioClient.h +++ b/include/CPulseAudioClient.h @@ -98,6 +98,7 @@ namespace tizen_media_audio { size_t __mSyncReadIndex; size_t __mSyncReadLength; bool __mIsUsedSyncRead; + bool __mIsFirstStream; /* Static Methods */ diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 1e528e2..5ea5a53 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,6 +1,6 @@ Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.3.55 +Version: 0.3.56 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/cpp/CPulseAudioClient.cpp b/src/cpp/CPulseAudioClient.cpp index fe28ea9..d0a0e0d 100644 --- a/src/cpp/CPulseAudioClient.cpp +++ b/src/cpp/CPulseAudioClient.cpp @@ -46,7 +46,8 @@ CPulseAudioClient::CPulseAudioClient( __mpSyncReadDataPtr(NULL), __mSyncReadIndex(0), __mSyncReadLength(0), - __mIsUsedSyncRead(false) { + __mIsUsedSyncRead(false), + __mIsFirstStream(false) { } CPulseAudioClient::~CPulseAudioClient() { @@ -118,6 +119,9 @@ void CPulseAudioClient::__streamStateChangeCb(pa_stream* s, void* user_data) { case PA_STREAM_READY: AUDIO_IO_LOGD("The stream is ready"); pClient->__mpListener->onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING); + if (pClient->__mDirection == EStreamDirection::STREAM_DIRECTION_PLAYBACK) + pClient->__mIsFirstStream = true; + pClient->__mIsInit = true; pa_threaded_mainloop_signal(pClient->__mpMainloop, 0); break; @@ -346,7 +350,7 @@ void CPulseAudioClient::initialize() throw(CAudioError) { // End of synchronous pa_threaded_mainloop_unlock(__mpMainloop); - __mIsInit = true; + // __mIsInit = true; // Moved to __streamStateChangeCb() } catch (CAudioError e) { finalize(); throw e; @@ -575,6 +579,20 @@ int CPulseAudioClient::write(const void* data, size_t length) throw(CAudioError) ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE); pa_threaded_mainloop_unlock(__mpMainloop); } else { + if (__mIsFirstStream) { + const pa_buffer_attr* attr = pa_stream_get_buffer_attr(__mpStream); + uint32_t prebuf = attr->prebuf; + // Compensate amount of prebuf in first stream callback when audio-io use prebuf(-1) + // Because a stream will never start when an application wrote less than prebuf at first + if (length < prebuf) { + char* dummy = new char[prebuf - length]; + memset(dummy, 0, prebuf - length); + pa_stream_write(__mpStream, dummy, prebuf - length, NULL, 0LL, PA_SEEK_RELATIVE); + delete [] dummy; + } + __mIsFirstStream = false; + AUDIO_IO_LOGD("FIRST STREAM CALLBACK : length[%d], prebuf[%d], dummy[%d]", length, prebuf, (length < prebuf) ? prebuf - length : 0); + } ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE); } @@ -598,6 +616,10 @@ void CPulseAudioClient::cork(bool cork) throw(CAudioError) { checkRunningState(); + // Set __mIsFirstStream flag when uncork(resume) stream, because prebuf will be enable again + if (cork == false) + __mIsFirstStream = true; + if (isInThread() == false) { pa_threaded_mainloop_lock(__mpMainloop); pa_operation_unref(pa_stream_cork(__mpStream, static_cast(cork), __successStreamCb, this)); @@ -701,7 +723,7 @@ void CPulseAudioClient::checkRunningState() throw(CAudioError) { if (__mpStream == NULL || PA_STREAM_IS_GOOD(pa_stream_get_state(__mpStream)) == 0) { THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_INITIALIZED, "The stream[%p] is not created or not good state", __mpStream); } - if (pa_context_get_state(__mpContext) != PA_CONTEXT_READY || pa_stream_get_state(__mpStream) != PA_STREAM_READY) { + if (pa_context_get_state(__mpContext) != PA_CONTEXT_READY || pa_stream_get_state(__mpStream) != PA_STREAM_READY) { THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_INITIALIZED, "The context[%p] or stream[%p] state is not ready", __mpContext, __mpStream); } -- 2.7.4