From 635eed07fe29426fc63e0b8981ce232c1cd1adad Mon Sep 17 00:00:00 2001 From: KimJeongYeon Date: Wed, 22 Jul 2015 16:08:51 +0900 Subject: [PATCH] audio-io fixed hang issue while record audio [Version] 0.3.9 [Profile] Common [Issue Type] Feature [Dependency module] NA [Dependency commit] NA [Comment] - Hang occurs when getBufferSize() of main thread and peek() of pulse client thread try to lock. - I think some methods doesn't required mutex lock. (need more test) Signed-off-by: KimJeongYeon Change-Id: I730f54951ffb796ab2fda753848f95f5170facfd --- packaging/capi-media-audio-io.spec | 2 +- src/cpp/CAudioIO.cpp | 33 ++++++++++++++------------------- src/cpp/CAudioInput.cpp | 33 ++++++--------------------------- src/cpp/CAudioOutput.cpp | 31 ++++++++++++++----------------- test/audio_io_test.c | 15 ++++++++------- 5 files changed, 43 insertions(+), 71 deletions(-) diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 9b198e6..b568aa1 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.8 +Version: 0.3.9 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/cpp/CAudioIO.cpp b/src/cpp/CAudioIO.cpp index 94bed76..6d33316 100644 --- a/src/cpp/CAudioIO.cpp +++ b/src/cpp/CAudioIO.cpp @@ -67,7 +67,7 @@ void CAudioIO::internalLock() throw (CAudioError) { THROW_ERROR_MSG(CAudioError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); } #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD(COLOR_RED"LOCK"COLOR_END); + AUDIO_IO_LOGD(COLOR_RED "LOCK" COLOR_END); #endif } @@ -80,7 +80,7 @@ void CAudioIO::internalUnlock() throw (CAudioError) { THROW_ERROR_MSG(CAudioError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); } #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD(COLOR_GREEN"UNLOCK"COLOR_END); + AUDIO_IO_LOGD(COLOR_GREEN "UNLOCK" COLOR_END); #endif } @@ -90,7 +90,7 @@ void CAudioIO::internalWait() throw (CAudioError) { } #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD(COLOR_RED"WAIT"COLOR_END); + AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END); #endif pthread_cond_wait(&mCond, &mMutex); @@ -102,7 +102,7 @@ void CAudioIO::internalSignal() throw (CAudioError) { } #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD(COLOR_GREEN"SIGNAL"COLOR_END); + AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END); #endif pthread_cond_signal(&mCond); @@ -157,6 +157,10 @@ void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) { assert(pClient != NULL); assert(length > 0); +#ifdef _AUDIO_IO_DEBUG_TIMING_ + AUDIO_IO_LOGD("mStreamCallback.onStream(%p), pClient(%p), length(%zu)", mStreamCallback.onStream, pClient, length); +#endif + if (mStreamCallback.onStream != NULL) { mStreamCallback.onStream(length, mStreamCallback.mUserData); } @@ -210,6 +214,7 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu } else if (state == FOCUS_IS_ACQUIRED) { // Focus handle(id) of the other application was acquired, do pause if possible internalLock(); + if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::STREAM_DIRECTION_PLAYBACK) { if (mpPulseAudioClient->drain() == false) { AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()"); @@ -241,6 +246,7 @@ void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focu if (state == FOCUS_IS_RELEASED) { // Focus handle(id) was released, do pause here internalLock(); + if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::STREAM_DIRECTION_PLAYBACK) { if (mpPulseAudioClient->drain() == false) { AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()"); @@ -291,12 +297,9 @@ void CAudioIO::prepare() throw (CAudioError) { } try { - internalLock(); AUDIO_IO_LOGD("prepare"); /* Do nothing */ - internalUnlock(); } catch (CAudioError e) { - internalUnlock(); throw e; } } @@ -307,12 +310,9 @@ void CAudioIO::unprepare() throw (CAudioError) { } try { - internalLock(); AUDIO_IO_LOGD("unprepare"); /* Do nothing */ - internalUnlock(); } catch (CAudioError e) { - internalUnlock(); throw e; } } @@ -394,9 +394,7 @@ void CAudioIO::setStreamCallback(SStreamCallback callback) throw (CAudioError) { THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } - internalLock(); mStreamCallback = callback; - internalUnlock(); } CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw (CAudioError) { @@ -412,9 +410,7 @@ void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw (CA THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } - internalLock(); mStateChangedCallback = callback; - internalUnlock(); } CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw (CAudioError) { @@ -447,9 +443,9 @@ void CAudioIO::ignoreSession() throw (CAudioError) { THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); } - internalLock(); - try { + internalLock(); + if (mpPulseAudioClient != NULL && mpPulseAudioClient->isCorked() == false) { THROW_ERROR_MSG(CAudioError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started"); } @@ -459,11 +455,10 @@ void CAudioIO::ignoreSession() throw (CAudioError) { mpAudioSessionHandler->unregisterSound(); mForceIgnore = true; } + + internalUnlock(); } catch (CAudioError e) { internalUnlock(); - throw e; } - - internalUnlock(); } diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index 93a5b90..c95b72c 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -282,16 +282,7 @@ void CAudioInput::resume() throw (CAudioError) { } void CAudioInput::drain() throw (CAudioError) { - if (IsInit() == false || IsReady() == false) { - THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput"); - } - - try{ - CAudioIO::drain(); - } catch (CAudioError e) { - internalUnlock(); - throw e; - } + THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "Did not support drain of CAudioInput"); } void CAudioInput::flush() throw (CAudioError) { @@ -302,7 +293,6 @@ void CAudioInput::flush() throw (CAudioError) { try { CAudioIO::flush(); } catch (CAudioError e) { - internalUnlock(); throw e; } } @@ -320,11 +310,8 @@ int CAudioInput::getBufferSize() throw (CAudioError) { int size = 0; try { - internalLock(); size = mpPulseAudioClient->getBufferSize(); - internalUnlock(); } catch (CAudioError err) { - internalUnlock(); throw err; } @@ -336,7 +323,6 @@ void CAudioInput::setStreamCallback(SStreamCallback callback) throw (CAudioError THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput"); } - internalLock(); if (callback.onStream == NULL) { AUDIO_IO_LOGD("mIsUsedSyncRead = true"); mIsUsedSyncRead = true; @@ -344,7 +330,6 @@ void CAudioInput::setStreamCallback(SStreamCallback callback) throw (CAudioError AUDIO_IO_LOGD("mIsUsedSyncRead = false"); mIsUsedSyncRead = false; } - internalUnlock(); CAudioIO::setStreamCallback(callback); } @@ -363,12 +348,12 @@ size_t CAudioInput::read(void* buffer, size_t length) throw (CAudioError) { THROW_ERROR_MSG(CAudioError::ERROR_INVALID_OPERATION, "Invalid operation of read() if receive stream callback"); } - internalLock(); - size_t lengthIter = length; int ret = 0; try { + internalLock(); + while (lengthIter > 0) { size_t l; @@ -430,14 +415,14 @@ size_t CAudioInput::read(void* buffer, size_t length) throw (CAudioError) { mSyncReadLength = 0; mSyncReadIndex = 0; } - }//end of while (length > 0) + } // End of while (length > 0) + + internalUnlock(); } catch (CAudioError e) { internalUnlock(); throw e; } - internalUnlock(); - return length; } @@ -458,11 +443,8 @@ int CAudioInput::peek(const void** buffer, size_t* length) throw (CAudioError) { int ret = 0; try { - internalLock(); ret = mpPulseAudioClient->peek(buffer, length); - internalUnlock(); } catch (CAudioError e) { - internalUnlock(); throw e; } @@ -482,11 +464,8 @@ int CAudioInput::drop() throw (CAudioError) { int ret = 0; try { - internalLock(); ret = mpPulseAudioClient->drop(); - internalUnlock(); } catch (CAudioError e) { - internalUnlock(); throw e; } diff --git a/src/cpp/CAudioOutput.cpp b/src/cpp/CAudioOutput.cpp index e42cb28..2661e13 100644 --- a/src/cpp/CAudioOutput.cpp +++ b/src/cpp/CAudioOutput.cpp @@ -262,6 +262,7 @@ void CAudioOutput::resume() throw (CAudioError) { internalUnlock(); CAudioIO::resume(); + CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING); } catch (CAudioError e) { internalUnlock(); @@ -277,7 +278,6 @@ void CAudioOutput::drain() throw (CAudioError) { try { CAudioIO::drain(); } catch (CAudioError e) { - internalUnlock(); throw e; } } @@ -290,7 +290,6 @@ void CAudioOutput::flush() throw (CAudioError) { try { CAudioIO::flush(); } catch (CAudioError e) { - internalUnlock(); throw e; } } @@ -308,11 +307,8 @@ int CAudioOutput::getBufferSize() throw (CAudioError) { int size = 0; try { - internalLock(); size = mpPulseAudioClient->getBufferSize(); - internalUnlock(); } catch (CAudioError err) { - internalUnlock(); throw err; } @@ -342,7 +338,7 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw (CAudioError } } - /* When write() is called in PulseAudio callback, bypass a pcm data to PulseAudioClient (For Asynchronous) */ + /* When write() is called in PulseAudio callback, bypass a pcm data to PulseAudioClient (For Asynchronous) */ if (mpPulseAudioClient->isInThread() == true) { int ret = mpPulseAudioClient->write(buffer, length); if (ret == 0) { @@ -350,14 +346,15 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw (CAudioError } } - /* For synchronization */ - internalLock(); + try { + /* For synchronization */ + internalLock(); - // Sets synchronous flag - mIsUsedSyncWrite = true; + // Sets synchronous flag + mIsUsedSyncWrite = true; + + size_t lengthIter = length; - size_t lengthIter = length; - try { while (lengthIter > 0) { size_t l; @@ -383,7 +380,11 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw (CAudioError buffer = static_cast(buffer) + l; lengthIter -= l; - }//end of while (length > 0) + } // End of while (length > 0) + + // Unsets synchronous flag + mIsUsedSyncWrite = false; + internalUnlock(); } catch (CAudioError e) { // Unsets synchronous flag mIsUsedSyncWrite = false; @@ -391,9 +392,5 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw (CAudioError throw e; } - // Unsets synchronous flag - mIsUsedSyncWrite = false; - internalUnlock(); - return length; } diff --git a/test/audio_io_test.c b/test/audio_io_test.c index c96771b..548a9bc 100644 --- a/test/audio_io_test.c +++ b/test/audio_io_test.c @@ -358,14 +358,15 @@ static void interrupted_callback_write(audio_io_interrupted_code_e code, void *u static void _audio_io_stream_read_cb (audio_in_h handle, size_t nbytes, void *user_data) { - const void * buffer = NULL; + const void *buffer = NULL; + unsigned int len = (unsigned int) nbytes; -// printf("_audio_io_stream_read_cb : handle=%p, nbytes=%d, user_data=%p\n", handle, nbytes, user_data); + //printf("_audio_io_stream_read_cb : handle=%p, nbytes=%d, user_data=%p\n", handle, nbytes, user_data); - if (nbytes > 0) { - audio_in_peek (handle, &buffer, &nbytes); + if (len > 0) { + audio_in_peek (handle, &buffer, &len); if (fp_w) { - fwrite(buffer, sizeof(char), nbytes, fp_w); + fwrite(buffer, sizeof(char), len, fp_w); } audio_in_drop (handle); } @@ -377,7 +378,7 @@ static void _audio_io_stream_write_cb (audio_out_h handle, size_t nbytes, void * int ret = 0; int i = 0; -// printf("_audio_io_stream_write_cb : handle=%p, nbytes=%d, user_data=%p\n", handle, nbytes, user_data); + //printf("_audio_io_stream_write_cb : handle=%p, nbytes=%d, user_data=%p\n", handle, nbytes, user_data); if (nbytes > 0) { buffer = (short *) malloc(nbytes); @@ -399,7 +400,7 @@ static void _audio_io_stream_write_cb (audio_out_h handle, size_t nbytes, void * ret = audio_out_write(handle, buffer, nbytes); if(ret > AUDIO_IO_ERROR_NONE) { -// printf("audio write success. buffer(%p), nbytes(%d)\n", buffer, nbytes); + //printf("audio write success. buffer(%p), nbytes(%d)\n", buffer, nbytes); } free (buffer); -- 2.7.4