shithub: openh264

Download patch

ref: 47dcacee83ccc3f5718f89e421963d7b7bb2633a
parent: 6b503843ec8ae27185180089365dd252e647ac7e
parent: 9aafb779ebf22b50156f531809a7da6927512632
author: HaiboZhu <haibozhu@cisco.com>
date: Wed Aug 5 05:28:13 EDT 2015

Merge pull request #2059 from sijchen/mt52

[Encoder] multi-threading refactoring

--- a/codec/encoder/core/inc/slice_multi_threading.h
+++ b/codec/encoder/core/inc/slice_multi_threading.h
@@ -70,8 +70,6 @@
 void ReleaseMtResource (sWelsEncCtx** ppCtx);
 
 int32_t AppendSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, const int32_t kiSliceCount);
-int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t iSliceIdx,
-                             int32_t& iSliceSize);
 
 #if !defined(_WIN32)
 WELS_THREAD_ROUTINE_TYPE UpdateMbListThreadProc (void* arg);
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -560,9 +560,9 @@
   if (!kbIsDynamicSlicingMode) {
     pSliceBs    = &pCtx->pSliceBs[0];
     iLayerSize  = pSliceBs->uiBsPos;    // assign with base pSlice first
-    iSliceIdx   = 1;                    // pSlice 0 bs has been written to pFrameBs yet by now, so uiSliceIdx base should be 1
+    iSliceIdx   = 0;
+    iNalIdxBase   = pLbi->iNalCount = 0;
     while (iSliceIdx < iSliceCount) {
-      ++ pSliceBs;
       if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) {
         int32_t iNalIdx = 0;
         const int32_t iCountNal = pSliceBs->iNalIndex;
@@ -571,11 +571,13 @@
         assert (pSliceBs->bSliceCodedFlag);
 #endif//MT_DEBUG_BS_WR
 
-        memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage
-        pCtx->iPosBsBuffer += pSliceBs->uiBsPos;
+        if (iSliceIdx > 0) {
+          // pSlice 0 bs has been written to pFrameBs yet by now, so uiSliceIdx base should be 1
+          memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage
+          pCtx->iPosBsBuffer += pSliceBs->uiBsPos;
 
-        iLayerSize += pSliceBs->uiBsPos;
-
+          iLayerSize += pSliceBs->uiBsPos;
+        }
         while (iNalIdx < iCountNal) {
           pLbi->pNalLengthInByte[iNalIdxBase + iNalIdx] = pSliceBs->iNalLen[iNalIdx];
           ++ iNalIdx;
@@ -584,6 +586,7 @@
         iNalIdxBase     += iCountNal;
       }
       ++ iSliceIdx;
+      ++ pSliceBs;
     }
   } else { // for SM_DYN_SLICE
     const int32_t kiPartitionCnt        = iSliceCount;
@@ -629,58 +632,18 @@
   return iLayerSize;
 }
 
-int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t iSliceIdx,
-                             int32_t& iSliceSize) {
+int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pDst,
+                      int32_t* pNalLen,
+                      int32_t iTotalLeftLength,
+                      const int32_t iSliceIdx,
+                      int32_t& iSliceSize) {
   SWelsSliceBs* pSliceBs        = &pCtx->pSliceBs[iSliceIdx];
   SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
-  uint8_t* pDst                 = pFrameBsBuffer;
-  const int32_t kiNalCnt        = pSliceBs->iNalIndex;
-  int32_t iNalIdx               = 0;
-  int32_t iNalSize = 0;
-  const int32_t iFirstSlice     = (iSliceIdx == 0);
-  int32_t iNalBase              = iFirstSlice ? 0 : pLbi->iNalCount;
-  int32_t iReturn = ENC_RETURN_SUCCESS;
-  const int32_t kiWrittenLength = pCtx->iPosBsBuffer;
-  iSliceSize                    = 0;
 
-  while (iNalIdx < kiNalCnt) {
-    iNalSize = 0;
-    iReturn = WelsEncodeNal (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pCtx->iFrameBsSize - kiWrittenLength - iSliceSize,
-                             pDst, &iNalSize);
-    WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
-    iSliceSize += iNalSize;
-    pDst += iNalSize;
-    pLbi->pNalLengthInByte[iNalBase + iNalIdx] = iNalSize;
-
-    ++ iNalIdx;
-  }
-
-  pSliceBs->uiBsPos = iSliceSize;
-  if (iFirstSlice) {
-    // pBsBuffer has been updated at coding_slice_0_in_encoder_mother_thread()
-    pLbi->uiLayerType   = VIDEO_CODING_LAYER;
-    pLbi->uiSpatialId   = pNalHdrExt->uiDependencyId;
-    pLbi->uiTemporalId  = pNalHdrExt->uiTemporalId;
-    pLbi->uiQualityId   = 0;
-    pLbi->iNalCount     = kiNalCnt;
-  } else {
-    pLbi->iNalCount    += kiNalCnt;
-  }
-
-  return ENC_RETURN_SUCCESS;
-}
-
-int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pSliceBsBuf, const int32_t iSliceIdx, int32_t& iSliceSize) {
-  SWelsSliceBs* pSliceBs        = &pCtx->pSliceBs[iSliceIdx];
-  SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt;
-  uint8_t* pDst                 = pSliceBsBuf;
-  int32_t* pNalLen              = &pSliceBs->iNalLen[0];
   const int32_t kiNalCnt        = pSliceBs->iNalIndex;
   int32_t iNalIdx               = 0;
   int32_t iNalSize              = 0;
   int32_t iReturn = ENC_RETURN_SUCCESS;
-  const int32_t kiWrittenLength = (int32_t) (pSliceBs->sBsWrite.pCurBuf - pSliceBs->sBsWrite.pStartBuf);
-
   iSliceSize = 0;
   assert (kiNalCnt <= 2);
   if (kiNalCnt > 2)
@@ -688,7 +651,7 @@
 
   while (iNalIdx < kiNalCnt) {
     iNalSize = 0;
-    iReturn = WelsEncodeNal (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pSliceBs->uiSize - kiWrittenLength - iSliceSize,
+    iReturn = WelsEncodeNal (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, iTotalLeftLength - iSliceSize,
                              pDst, &iNalSize);
     WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
     pNalLen[iNalIdx] = iNalSize;
@@ -793,31 +756,28 @@
         iReturn = WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType);
         if (ENC_RETURN_SUCCESS != iReturn) {
           uiThrdRet = iReturn;
-          WELS_THREAD_SIGNAL_AND_BREAK(pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
-                                       pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
-                                       iEventIdx);
+          WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
+                                        pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
+                                        iEventIdx);
         }
 
         WelsUnloadNalForSlice (pSliceBs);
 
+        int32_t iLeftBufferSize = (iSliceIdx > 0) ?
+                                  (pSliceBs->uiSize - (int32_t) (pSliceBs->sBsWrite.pCurBuf - pSliceBs->sBsWrite.pStartBuf))
+                                  : (pEncPEncCtx->iFrameBsSize - pEncPEncCtx->iPosBsBuffer);
+        iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs,
+                                &pSliceBs->iNalLen[0],
+                                iLeftBufferSize,
+                                iSliceIdx, iSliceSize);
+        if (ENC_RETURN_SUCCESS != iReturn) {
+          uiThrdRet = iReturn;
+          WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
+                                        pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
+                                        iEventIdx);
+        }
         if (0 == iSliceIdx) {
-          pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer;
-          iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx, iSliceSize);
-          if (ENC_RETURN_SUCCESS != iReturn) {
-            uiThrdRet = iReturn;
-            WELS_THREAD_SIGNAL_AND_BREAK(pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
-                                         pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
-                                         iEventIdx);
-          }
           pEncPEncCtx->iPosBsBuffer += iSliceSize;
-        } else {
-          iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx, iSliceSize);
-          if (ENC_RETURN_SUCCESS != iReturn) {
-            uiThrdRet = iReturn;
-            WELS_THREAD_SIGNAL_AND_BREAK(pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
-                                         pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
-                                         iEventIdx);
-          }
         }
 
         pEncPEncCtx->pFuncList->pfDeblocking.pfDeblockingFilterSlice (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx);
@@ -909,10 +869,11 @@
           WelsUnloadNalForSlice (pSliceBs);
 
           if (0 == kiPartitionId) {
-            if (0 == iSliceIdx)
-              pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer;
-            iReturn = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer, iSliceIdx,
-                                           iSliceSize);
+            iReturn = WriteSliceBs (pEncPEncCtx, pLbi->pBsBuf,
+                                           &pLbi->pNalLengthInByte[pLbi->iNalCount],
+                                           pEncPEncCtx->iFrameBsSize - pEncPEncCtx->iPosBsBuffer,
+                                           iSliceIdx, iSliceSize);
+            pLbi->iNalCount    += pSliceBs->iNalIndex;
             if (ENC_RETURN_SUCCESS != iReturn) {
               uiThrdRet = iReturn;
               WELS_THREAD_SIGNAL_AND_BREAK(pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
@@ -921,7 +882,9 @@
             }
             pEncPEncCtx->iPosBsBuffer += iSliceSize;
           } else {
-            iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx, iSliceSize);
+            iReturn = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, &pSliceBs->iNalLen[0],
+                                    pSliceBs->uiSize - (int32_t) (pSliceBs->sBsWrite.pCurBuf - pSliceBs->sBsWrite.pStartBuf),
+                                    iSliceIdx, iSliceSize);
             if (ENC_RETURN_SUCCESS != iReturn) {
               uiThrdRet = iReturn;
               WELS_THREAD_SIGNAL_AND_BREAK(pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
@@ -1029,6 +992,14 @@
       iEndMbIdx                         = iFirstMbIdx;
     }
   }
+
+  pLbi->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
+  pLbi->uiLayerType   = VIDEO_CODING_LAYER;
+  pLbi->uiSpatialId   = pCtx->uiDependencyId;
+  pLbi->uiTemporalId  = pCtx->uiTemporalId;
+  pLbi->uiQualityId   = 0;
+  pLbi->iNalCount     = 0;
+  pCtx->pSliceBs[0].pBs = pLbi->pBsBuf;
 
   iIdx = 0;
   while (iIdx < kiEventCnt) {
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -3474,6 +3474,8 @@
   {false, true, false, 30, 104, 416, 44, SM_DYN_SLICE, 500, 7.5, 2, ""},
   {false, true, false, 30, 16, 16, 2, SM_DYN_SLICE, 500, 7.5, 3, ""},
   {false, true, false, 30, 32, 16, 2, SM_DYN_SLICE, 500, 7.5, 3, ""},
+  {false, false, true, 30, 600, 460, 1, SM_FIXEDSLCNUM_SLICE, 0, 15.0, 4, ""},
+  {false, false, true, 30, 600, 460, 1, SM_AUTO_SLICE, 0, 15.0, 4, ""},
 };
 
 class EncodeTestAPI : public ::testing::TestWithParam<EncodeOptionParam>, public ::EncodeDecodeTestAPIBase {
@@ -3494,9 +3496,9 @@
     }
     int rv = encoder_->EncodeFrame (&EncPic, &info);
     if (0 == iCheckTypeIndex)
-      ASSERT_TRUE (rv == cmResultSuccess);
+      ASSERT_TRUE (rv == cmResultSuccess) << "rv=" << rv;
     else if (1 == iCheckTypeIndex)
-      ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
+      ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason) << "rv=" << rv;
   }
 };
 
@@ -3525,6 +3527,9 @@
   param_.sSpatialLayers[0].iVideoHeight = p.iHeight;
   param_.sSpatialLayers[0].fFrameRate = p.fFramerate;
   param_.sSpatialLayers[0].sSliceCfg.uiSliceMode = p.eSliceMode;
+  if (SM_AUTO_SLICE == p.eSliceMode || SM_FIXEDSLCNUM_SLICE == p.eSliceMode ) {
+    param_.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = 8;
+  }
 
   encoder_->Uninitialize();
   int rv = encoder_->InitializeExt (&param_);