shithub: openh264

Download patch

ref: c12b88ae43a3a6c2293555b5abaeb9d60904b7f9
parent: 30328b85f2f4bb89d71e38b15148859a3fad14a6
author: Karina <ruil2@cisco.com>
date: Tue Sep 6 08:58:36 EDT 2016

use pthread_condition instead of semaphores on apple platform

--- a/codec/common/inc/WelsThread.h
+++ b/codec/common/inc/WelsThread.h
@@ -58,7 +58,7 @@
   virtual void ExecuteTask() = 0;
   virtual WELS_THREAD_ERROR_CODE Start();
   virtual void Kill();
-
+  WELS_MUTEX          m_hMutex;
  protected:
   static WELS_THREAD_ROUTINE_TYPE  TheThread (void* pParam);
 
--- a/codec/common/inc/WelsThreadLib.h
+++ b/codec/common/inc/WelsThreadLib.h
@@ -79,7 +79,12 @@
 typedef  void* (*LPWELS_THREAD_ROUTINE) (void*);
 
 typedef   pthread_mutex_t           WELS_MUTEX;
+
+#ifdef __APPLE__
+typedef   pthread_cond_t            WELS_EVENT;
+#else
 typedef   sem_t*                    WELS_EVENT;
+#endif
 
 #define   WELS_THREAD_ROUTINE_TYPE         void *
 #define   WELS_THREAD_ROUTINE_RETURN(rc)   return (void*)(intptr_t)rc;
@@ -108,12 +113,10 @@
 WELS_THREAD_ERROR_CODE    WelsEventClose (WELS_EVENT* event, const char* event_name = NULL);
 
 WELS_THREAD_ERROR_CODE    WelsEventSignal (WELS_EVENT* event);
-WELS_THREAD_ERROR_CODE    WelsEventWait (WELS_EVENT* event);
-WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds);
+WELS_THREAD_ERROR_CODE    WelsEventWait (WELS_EVENT* event,WELS_MUTEX *pMutex = NULL);
+WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds,WELS_MUTEX *pMutex = NULL);
 WELS_THREAD_ERROR_CODE    WelsMultipleEventsWaitSingleBlocking (uint32_t nCount, WELS_EVENT* event_list,
-    WELS_EVENT* master_event = NULL);
-WELS_THREAD_ERROR_CODE    WelsMultipleEventsWaitAllBlocking (uint32_t nCount, WELS_EVENT* event_list,
-    WELS_EVENT* master_event = NULL);
+    WELS_EVENT* master_event = NULL,WELS_MUTEX *pMutex = NULL);
 
 WELS_THREAD_ERROR_CODE    WelsThreadCreate (WELS_THREAD_HANDLE* thread,  LPWELS_THREAD_ROUTINE  routine,
     void* arg, WELS_THREAD_ATTR attr);
--- a/codec/common/src/WelsTaskThread.cpp
+++ b/codec/common/src/WelsTaskThread.cpp
@@ -75,9 +75,9 @@
   if (!GetRunning()) {
     return WELS_THREAD_ERROR_GENERAL;
   }
-
+  WelsMutexLock(&m_hMutex);
   m_pTask = pTask;
-
+  WelsMutexUnlock(&m_hMutex);
   SignalThread();
 
   return WELS_THREAD_ERROR_OK;
--- a/codec/common/src/WelsThread.cpp
+++ b/codec/common/src/WelsThread.cpp
@@ -46,22 +46,21 @@
   m_hThread (0),
   m_bRunning (false),
   m_bEndFlag (false) {
-  WELS_THREAD_ERROR_CODE rc = WelsEventOpen (&m_hEvent);
 
-  if (WELS_THREAD_ERROR_OK != rc) {
-    m_hEvent = NULL;
-  }
+  WelsEventOpen (&m_hEvent);
+  WelsMutexInit(&m_hMutex);
+
 }
 
 CWelsThread::~CWelsThread() {
   Kill();
   WelsEventClose (&m_hEvent);
-  m_hEvent = NULL;
+  WelsMutexDestroy(&m_hMutex);
 }
 
 void CWelsThread::Thread() {
   while (true) {
-    WelsEventWait (&m_hEvent);
+    WelsEventWait (&m_hEvent,&m_hMutex);
 
     if (GetEndFlag()) {
       break;
@@ -74,10 +73,11 @@
 }
 
 WELS_THREAD_ERROR_CODE CWelsThread::Start() {
+#ifndef __APPLE__
   if (NULL == m_hEvent) {
     return WELS_THREAD_ERROR_GENERAL;
   }
-
+#endif
   if (GetRunning()) {
     return WELS_THREAD_ERROR_OK;
   }
--- a/codec/common/src/WelsThreadLib.cpp
+++ b/codec/common/src/WelsThreadLib.cpp
@@ -133,11 +133,10 @@
 
 WELS_THREAD_ERROR_CODE    WelsEventOpen (WELS_EVENT* event, const char* event_name) {
   WELS_EVENT   h = CreateEvent (NULL, FALSE, FALSE, NULL);
-
+  *event = h;
   if (h == NULL) {
     return WELS_THREAD_ERROR_GENERAL;
   }
-  *event = h;
   return WELS_THREAD_ERROR_OK;
 }
 
@@ -148,26 +147,20 @@
   return WELS_THREAD_ERROR_GENERAL;
 }
 
-WELS_THREAD_ERROR_CODE    WelsEventWait (WELS_EVENT* event) {
+WELS_THREAD_ERROR_CODE    WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) {
   return WaitForSingleObject (*event, INFINITE);
 }
 
-WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
+WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds, WELS_MUTEX* pMutex) {
   return WaitForSingleObject (*event, dwMilliseconds);
 }
 
 WELS_THREAD_ERROR_CODE    WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,
-    WELS_EVENT* event_list, WELS_EVENT* master_event) {
+    WELS_EVENT* event_list, WELS_EVENT* master_even, WELS_MUTEX* pMutext) {
   // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
   return WaitForMultipleObjects (nCount, event_list, FALSE, INFINITE);
 }
 
-WELS_THREAD_ERROR_CODE    WelsMultipleEventsWaitAllBlocking (uint32_t nCount,
-    WELS_EVENT* event_list, WELS_EVENT* master_event) {
-  // Don't need/use the master event for anything, since windows has got WaitForMultipleObjects
-  return WaitForMultipleObjects (nCount, event_list, TRUE, INFINITE);
-}
-
 WELS_THREAD_ERROR_CODE    WelsEventClose (WELS_EVENT* event, const char* event_name) {
   CloseHandle (*event);
 
@@ -278,10 +271,10 @@
 
 WELS_THREAD_ERROR_CODE WelsThreadSetName (const char* thread_name) {
 #ifdef APPLE_IOS
-  pthread_setname_np(thread_name);
+  pthread_setname_np (thread_name);
 #endif
 #if defined(__ANDROID__) && __ANDROID_API__ >= 9
-  pthread_setname_np(pthread_self(), thread_name);
+  pthread_setname_np (pthread_self(), thread_name);
 #endif
   // do nothing
   return WELS_THREAD_ERROR_OK;
@@ -299,27 +292,14 @@
 
 WELS_THREAD_ERROR_CODE    WelsEventOpen (WELS_EVENT* p_event, const char* event_name) {
 #ifdef __APPLE__
-  if (p_event == NULL) {
-    return WELS_THREAD_ERROR_GENERAL;
-  }
-  char    strSuffix[100] = { 0 };
-  if (NULL == event_name) {
-    sprintf (strSuffix, "WelsSem%ld_p%ld", (intptr_t)p_event, (long) (getpid()));
-    event_name = &strSuffix[0];
-  }
-  *p_event = sem_open (event_name, O_CREAT, (S_IRUSR | S_IWUSR)/*0600*/, 0);
-  if (*p_event == (sem_t*)SEM_FAILED) {
-    sem_unlink (event_name);
-    *p_event = NULL;
-    return WELS_THREAD_ERROR_GENERAL;
-  } else {
-    //printf("event_open:%x, %s\n", p_event, event_name);
-    return WELS_THREAD_ERROR_OK;
-  }
+  WELS_THREAD_ERROR_CODE err= pthread_cond_init (p_event, NULL);
+  return err;
 #else
   WELS_EVENT event = (WELS_EVENT) malloc (sizeof (*event));
-  if (event == NULL)
+  if (event == NULL){
+    *p_event = NULL;
     return WELS_THREAD_ERROR_GENERAL;
+  }
   WELS_THREAD_ERROR_CODE err = sem_init (event, 0, 0);
   if (!err) {
     *p_event = event;
@@ -326,6 +306,7 @@
     return err;
   }
   free (event);
+  *p_event = NULL;
   return err;
 #endif
 }
@@ -332,13 +313,12 @@
 WELS_THREAD_ERROR_CODE    WelsEventClose (WELS_EVENT* event, const char* event_name) {
   //printf("event_close:%x, %s\n", event, event_name);
 #ifdef __APPLE__
-  WELS_THREAD_ERROR_CODE err = sem_close (*event); // match with sem_open
-  if (event_name)
-    sem_unlink (event_name);
+  WELS_THREAD_ERROR_CODE err = pthread_cond_destroy (event);
   return err;
 #else
   WELS_THREAD_ERROR_CODE err = sem_destroy (*event); // match with sem_init
   free (*event);
+  *event = NULL;
   return err;
 #endif
 }
@@ -349,37 +329,37 @@
 
 WELS_THREAD_ERROR_CODE   WelsEventSignal (WELS_EVENT* event) {
   WELS_THREAD_ERROR_CODE err = 0;
+#ifdef __APPLE__
+  err = pthread_cond_signal (event);
+#else
 //  int32_t val = 0;
 //  sem_getvalue(event, &val);
 //  fprintf( stderr, "before signal it, val= %d..\n",val );
-  err = sem_post (*event);
+  if (event != NULL)
+    err = sem_post (*event);
 //  sem_getvalue(event, &val);
 //  fprintf( stderr, "after signal it, val= %d..\n",val );
+#endif
   return err;
 }
 
-WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
+WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event, WELS_MUTEX* pMutex) {
+#ifdef __APPLE__
+  return pthread_cond_wait (event, pMutex);
+#else
   return sem_wait (*event); // blocking until signaled
+#endif
 }
 
-WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
+WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds, WELS_MUTEX* pMutex) {
+
   if (dwMilliseconds != (uint32_t) - 1) {
-    return sem_wait (*event);
-  } else {
 #if defined(__APPLE__)
-    int32_t err = 0;
-    int32_t wait_count = 0;
-    do {
-      err = sem_trywait (*event);
-      if (WELS_THREAD_ERROR_OK == err)
-        break;// WELS_THREAD_ERROR_OK;
-      else if (wait_count > 0)
-        break;
-      usleep (dwMilliseconds * 1000);
-      ++ wait_count;
-    } while (1);
-    return err;
+    return pthread_cond_wait (event, pMutex);
 #else
+    return sem_wait (*event);
+#endif
+  } else {
     struct timespec ts;
     struct timeval tv;
 
@@ -389,19 +369,23 @@
     ts.tv_sec = tv.tv_sec + ts.tv_nsec / 1000000000;
     ts.tv_nsec %= 1000000000;
 
+#if defined(__APPLE__)
+    return pthread_cond_timedwait (event, pMutex, &ts);
+#else
     return sem_timedwait (*event, &ts);
-#endif//__APPLE__
+#endif
   }
+
 }
 
 WELS_THREAD_ERROR_CODE    WelsMultipleEventsWaitSingleBlocking (uint32_t nCount,
-    WELS_EVENT* event_list, WELS_EVENT* master_event) {
+    WELS_EVENT* event_list, WELS_EVENT* master_event, WELS_MUTEX* pMutex) {
   uint32_t nIdx = 0;
   uint32_t uiAccessTime = 2; // 2 us once
 
   if (nCount == 0)
     return WELS_THREAD_ERROR_WAIT_FAILED;
-
+#if defined(__APPLE__)
   if (master_event != NULL) {
     // This design relies on the events actually being semaphores;
     // if multiple events in the list have been signalled, the master
@@ -408,7 +392,7 @@
     // event should have a similar count (events in windows can't keep
     // track of the actual count, but the master event isn't needed there
     // since it uses WaitForMultipleObjects).
-    int32_t err = sem_wait (*master_event);
+    int32_t err = pthread_cond_wait (master_event, pMutex);
     if (err != WELS_THREAD_ERROR_OK)
       return err;
     uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled
@@ -425,7 +409,7 @@
        * pthread_cond_timedwait() might be better choice if need
        */
       do {
-        err = sem_trywait (event_list[nIdx]);
+        err = pthread_cond_wait (&event_list[nIdx], pMutex);
         if (WELS_THREAD_ERROR_OK == err)
           return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
         else if (wait_count > 0 || uiAccessTime == 0)
@@ -446,60 +430,53 @@
       uiAccessTime = 2;
     }
   }
+#else
+  if (master_event != NULL) {
+    // This design relies on the events actually being semaphores;
+    // if multiple events in the list have been signalled, the master
+    // event should have a similar count (events in windows can't keep
+    // track of the actual count, but the master event isn't needed there
+    // since it uses WaitForMultipleObjects).
+    int32_t err = sem_wait (*master_event);
+    if (err != WELS_THREAD_ERROR_OK)
+      return err;
+    uiAccessTime = 0; // no blocking, just quickly loop through all to find the one that was signalled
+  }
 
-  return WELS_THREAD_ERROR_WAIT_FAILED;
-}
-
-WELS_THREAD_ERROR_CODE    WelsMultipleEventsWaitAllBlocking (uint32_t nCount,
-    WELS_EVENT* event_list, WELS_EVENT* master_event) {
-  uint32_t nIdx = 0;
-  uint32_t uiCountSignals = 0;
-  uint32_t uiSignalFlag = 0;    // UGLY: suppose maximal event number up to 32
-
-  if (nCount == 0 || nCount > (sizeof (uint32_t) << 3))
-    return WELS_THREAD_ERROR_WAIT_FAILED;
-
   while (1) {
     nIdx = 0; // access each event by order
     while (nIdx < nCount) {
-      const uint32_t kuiBitwiseFlag = (1 << nIdx);
+      int32_t err = 0;
+      int32_t wait_count = 0;
 
-      if ((uiSignalFlag & kuiBitwiseFlag) != kuiBitwiseFlag) { // non-blocking mode
-        int32_t err = 0;
-//        fprintf( stderr, "sem_wait(): start to wait event %d..\n", nIdx );
-        if (master_event == NULL) {
-          err = sem_wait (event_list[nIdx]);
-        } else {
-          err = sem_wait (*master_event);
-          if (err == WELS_THREAD_ERROR_OK) {
-            err = sem_wait (event_list[nIdx]);
-            if (err != WELS_THREAD_ERROR_OK) {
-              // We successfully waited for the master event,
-              // but waiting for the individual event failed (e.g. EINTR?).
-              // Increase the master event count so that the next retry will
-              // work as intended.
-              sem_post (*master_event);
-            }
-          }
-        }
-//        fprintf( stderr, "sem_wait(): wait event %d result %d errno %d..\n", nIdx, err, errno );
-        if (WELS_THREAD_ERROR_OK == err) {
-//          int32_t val = 0;
-//          sem_getvalue(&event_list[nIdx], &val);
-//          fprintf( stderr, "after sem_timedwait(), event_list[%d] semaphore value= %d..\n", nIdx, val);
-
-          uiSignalFlag |= kuiBitwiseFlag;
-          ++ uiCountSignals;
-          if (uiCountSignals >= nCount) {
-            return WELS_THREAD_ERROR_OK;
-          }
-        }
-      }
+      /*
+       * although such interface is not used in __GNUC__ like platform, to use
+       * pthread_cond_timedwait() might be better choice if need
+       */
+      do {
+        err = sem_trywait (event_list[nIdx]);
+        if (WELS_THREAD_ERROR_OK == err)
+          return WELS_THREAD_ERROR_WAIT_OBJECT_0 + nIdx;
+        else if (wait_count > 0 || uiAccessTime == 0)
+          break;
+        usleep (uiAccessTime);
+        ++ wait_count;
+      } while (1);
       // we do need access next event next time
       ++ nIdx;
     }
+    usleep (1); // switch to working threads
+    if (master_event != NULL) {
+      // A master event was used and was signalled, but none of the events in the
+      // list was found to be signalled, thus wait a little more when rechecking
+      // the list to avoid busylooping here.
+      // If we ever hit this codepath it's mostly a bug in the code that signals
+      // the events.
+      uiAccessTime = 2;
+    }
   }
 
+#endif
   return WELS_THREAD_ERROR_WAIT_FAILED;
 }
 
@@ -519,7 +496,7 @@
 #else
     int32_t count = 0;
     for (int i = 0; i < CPU_SETSIZE; i++) {
-      if (CPU_ISSET(i, &cpuset)) {
+      if (CPU_ISSET (i, &cpuset)) {
         count++;
       }
     }
--- a/codec/encoder/core/inc/mt_defs.h
+++ b/codec/encoder/core/inc/mt_defs.h
@@ -89,7 +89,7 @@
 uint8_t*                        pThreadBsBuffer[MAX_THREADS_NUM]; //actual memory for slice buffer
 bool                            bThreadBsBufferUsage[MAX_THREADS_NUM];
 WELS_MUTEX                      mutexThreadBsBufferUsage;
-
+WELS_MUTEX                      mutexEvent;
 } SSliceThreading;
 
 #endif//MULTIPLE_THREADING_DEFINES_H__
--- a/codec/encoder/core/inc/wels_task_management.h
+++ b/codec/encoder/core/inc/wels_task_management.h
@@ -105,7 +105,7 @@
 
   int32_t          m_iWaitTaskNum;
   WELS_EVENT       m_hTaskEvent;
-
+  WELS_MUTEX       m_hEventMutex;
   WelsCommon::CWelsLock  m_cWaitTaskNumLock;
 
  private:
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -3804,24 +3804,6 @@
       else if ((SM_SIZELIMITED_SLICE == pParam->sSliceArgument.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1)) {
         const int32_t kiPartitionCnt = pCtx->iActiveThreadsNum;
 
-#if 0 //TODO: temporarily use this to keep old codes for a while, will remove old codes later
-        int32_t iRet = 0;
-        // to fire slice coding threads
-        iRet = FiredSliceThreads (pCtx, &pCtx->pSliceThreading->pThreadPEncCtx[0],
-                                  &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
-                                  &pCtx->pSliceThreading->pThreadMasterEvent[0],
-                                  pFbi, kiPartitionCnt, &pCtx->pCurDqLayer->sSliceEncCtx, true);
-        if (iRet) {
-          WelsLog (pLogCtx, WELS_LOG_ERROR,
-                   "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!",
-                   iRet, iSliceCount, pParam->sSliceArgument.uiSliceMode, pSvcParam->iMultipleThreadIdc);
-          return ENC_RETURN_UNEXPECTED;
-        }
-
-        WelsMultipleEventsWaitAllBlocking (kiPartitionCnt, &pCtx->pSliceThreading->pSliceCodedEvent[0],
-                                           &pCtx->pSliceThreading->pSliceCodedMasterEvent);
-        WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
-#else
         int32_t iEndMbIdx = pCtx->pCurDqLayer->sSliceEncCtx.iMbNumInFrame;
         for (int32_t iIdx = kiPartitionCnt - 1; iIdx >= 0; --iIdx) {
           const int32_t iFirstMbIdx         =
@@ -3857,7 +3839,6 @@
                    pParam->sSliceArgument.uiSliceMode, pCtx->iEncoderError);
           return pCtx->iEncoderError;
         }
-#endif
 
         iLayerSize = AppendSliceToFrameBs (pCtx, pLayerBsInfo, kiPartitionCnt);
       } else { // for non-dynamic-slicing mode single threading branch..
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -361,7 +361,8 @@
   memset (&pSmt->bThreadBsBufferUsage, 0, MAX_THREADS_NUM * sizeof (bool));
   iReturn = WelsMutexInit (&pSmt->mutexThreadBsBufferUsage);
   WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
-
+  iReturn = WelsMutexInit (&pSmt->mutexEvent);
+  WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx));
   iReturn = WelsMutexInit (& (*ppCtx)->mutexEncoderError);
   WELS_VERIFY_RETURN_PROC_IF (1, (WELS_THREAD_ERROR_OK != iReturn), FreeMemorySvc (ppCtx))
 
@@ -411,7 +412,7 @@
   WelsMutexDestroy (&pSmt->mutexSliceNumUpdate);
   WelsMutexDestroy (&pSmt->mutexThreadBsBufferUsage);
   WelsMutexDestroy (& ((*ppCtx)->mutexEncoderError));
-
+  WelsMutexDestroy (&pSmt->mutexEvent);
   if (pSmt->pThreadPEncCtx != NULL) {
     pMa->WelsFree (pSmt->pThreadPEncCtx, "pThreadPEncCtx");
     pSmt->pThreadPEncCtx = NULL;
@@ -585,7 +586,7 @@
                   pEventsList[0], pEventsList[1], pEventsList[1], (void*)pEncPEncCtx);
     iWaitRet = WelsMultipleEventsWaitSingleBlocking (iEventCount,
                &pEventsList[0],
-               &pEncPEncCtx->pSliceThreading->pThreadMasterEvent[iEventIdx]); // blocking until at least one event is signalled
+               &pEncPEncCtx->pSliceThreading->pThreadMasterEvent[iEventIdx],&pEncPEncCtx->pSliceThreading->mutexEvent); // blocking until at least one event is signalled
     if (WELS_THREAD_ERROR_WAIT_OBJECT_0 == iWaitRet) { // start pSlice coding signal waited
       //int             iLayerIndex  = pEncPEncCtx->pOut->iLayerBsIndex;
       //SFrameBSInfo*   pFrameBsInfo = pPrivateData->pFrameBsInfo;
@@ -877,10 +878,8 @@
     pPriData[iIdx].pFrameBsInfo = pFrameBsInfo;
     pPriData[iIdx].iSliceIndex  = iIdx;
     SetOneSliceBsBufferUnderMultithread (pCtx, iIdx, iIdx);
-    if (pEventsList[iIdx])
-      WelsEventSignal (&pEventsList[iIdx]);
-    if (pMasterEventsList[iIdx])
-      WelsEventSignal (&pMasterEventsList[iIdx]);
+    WelsEventSignal (&pEventsList[iIdx]);
+    WelsEventSignal (&pMasterEventsList[iIdx]);
     ++ iIdx;
   }
 
--- a/codec/encoder/core/src/wels_task_management.cpp
+++ b/codec/encoder/core/src/wels_task_management.cpp
@@ -85,6 +85,7 @@
   }
 
   WelsEventOpen (&m_hTaskEvent);
+  WelsMutexInit(&m_hEventMutex);
 }
 
 CWelsTaskManageBase::~CWelsTaskManageBase() {
@@ -131,6 +132,7 @@
     WELS_DELETE_OP(m_cPreEncodingTaskList[iDid]);
   }
   WelsEventClose (&m_hTaskEvent);
+  WelsMutexDestroy(&m_hEventMutex);
 }
 
 WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiCurDid) {
@@ -225,7 +227,7 @@
     m_pThreadPool->QueueTask (pTargetTaskList->GetIndexNode (iIdx));
     iIdx ++;
   }
-  WelsEventWait (&m_hTaskEvent);
+  WelsEventWait (&m_hTaskEvent,&m_hEventMutex);
 
   return ENC_RETURN_SUCCESS;
 }