audio-io fixed hang issue while record audio 63/44463/7 accepted/tizen/mobile/20150724.015336 accepted/tizen/tv/20150724.015343 accepted/tizen/wearable/20150724.015352 submit/tizen/20150723.232735
authorKimJeongYeon <jeongyeon.kim@samsung.com>
Wed, 22 Jul 2015 07:08:51 +0000 (16:08 +0900)
committerKimJeongYeon <jeongyeon.kim@samsung.com>
Thu, 23 Jul 2015 05:49:10 +0000 (14:49 +0900)
[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 <jeongyeon.kim@samsung.com>
Change-Id: I730f54951ffb796ab2fda753848f95f5170facfd

packaging/capi-media-audio-io.spec
src/cpp/CAudioIO.cpp
src/cpp/CAudioInput.cpp
src/cpp/CAudioOutput.cpp
test/audio_io_test.c

index 9b198e6..b568aa1 100644 (file)
@@ -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
index 94bed76..6d33316 100644 (file)
@@ -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();
 }
index 93a5b90..c95b72c 100644 (file)
@@ -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;
     }
 
index e42cb28..2661e13 100644 (file)
@@ -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<const uint8_t*>(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;
 }
index c96771b..548a9bc 100644 (file)
@@ -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);