1031 lines · 43.0 KB · C++
RawDownload
/*! * \copy *     Copyright (c)  2010-2013, Cisco Systems *     All rights reserved. * *     Redistribution and use in source and binary forms, with or without *     modification, are permitted provided that the following conditions *     are met: * *        * Redistributions of source code must retain the above copyright *          notice, this list of conditions and the following disclaimer. * *        * Redistributions in binary form must reproduce the above copyright *          notice, this list of conditions and the following disclaimer in *          the documentation and/or other materials provided with the *          distribution. * *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *     POSSIBILITY OF SUCH DAMAGE. * * * \file    slice_multi_threading.h * * \brief   pSlice based multiple threading * * \date    04/16/2010 Created * ************************************************************************************* */  #include <assert.h>#if !defined(_WIN32)#include <semaphore.h>#include <unistd.h>#endif//!_WIN32#ifndef SEM_NAME_MAX// length of semaphore name should be system constrained at least on mac 10.7#define  SEM_NAME_MAX 32#endif//SEM_NAME_MAX#include "slice_multi_threading.h"#include "mt_defs.h"#include "nal_encap.h"#include "utils.h"#include "encoder.h"#include "svc_encode_slice.h"#include "deblocking.h"#include "svc_enc_golomb.h"#include "crt_util_safe_x.h" // for safe crt like calls#include "rc.h" #include "cpu.h" #include "measure_time.h"#include "wels_task_management.h" #if defined(ENABLE_TRACE_MT)#define MT_TRACE_LOG(pLog, x, ...) WelsLog(pLog, x, __VA_ARGS__)#else#define MT_TRACE_LOG(x, ...)#endif #define WELS_THREAD_SIGNAL_AND_BREAK(CodedEventList, CodedMasterEvent, iEventIdx) {  \    WelsEventSignal(&CodedEventList[iEventIdx]);  \    WelsEventSignal (&CodedMasterEvent);  \    break;  \} namespace WelsEnc {void UpdateMbListNeighborParallel (SDqLayer* pCurDq,                                   SMB* pMbList,                                   const int32_t uiSliceIdc) {  SSliceCtx* pSliceCtx           = &pCurDq->sSliceEncCtx;  SSlice* pUpdateSlice           = pCurDq->ppSliceInLayer[uiSliceIdc];  const int32_t kiMbWidth        = pSliceCtx->iMbWidth;  int32_t iIdx                   = pUpdateSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice;  const int32_t kiEndMbInSlice   = iIdx + pUpdateSlice->iCountMbNumInSlice - 1;   do {    UpdateMbNeighbor (pCurDq, &pMbList[iIdx], kiMbWidth, uiSliceIdc);    ++ iIdx;  } while (iIdx <= kiEndMbInSlice);} void CalcSliceComplexRatio (SDqLayer* pCurDq) {  SSliceCtx* pSliceCtx          = &pCurDq->sSliceEncCtx;  SSlice** ppSliceInLayer       = pCurDq->ppSliceInLayer;  int32_t iSumAv                = 0;  const int32_t kiSliceCount    = pSliceCtx->iSliceNumInFrame;  int32_t iSliceIdx             = 0;  int32_t iAvI[MAX_SLICES_NUM];   WelsEmms();   while (iSliceIdx < kiSliceCount) {    iAvI[iSliceIdx] = WELS_DIV_ROUND (INT_MULTIPLY * ppSliceInLayer[iSliceIdx]->iCountMbNumInSlice,                                      ppSliceInLayer[iSliceIdx]->uiSliceConsumeTime);    MT_TRACE_LOG (NULL, WELS_LOG_DEBUG, "[MT] CalcSliceComplexRatio(), uiSliceConsumeTime[%d]= %d us, slice_run= %d",                  iSliceIdx,                  ppSliceInLayer[iSliceIdx]->uiSliceConsumeTime, ppSliceInLayer[iSliceIdx]->iCountMbNumInSlice);    iSumAv += iAvI[iSliceIdx];     ++ iSliceIdx;  }  while (-- iSliceIdx >= 0) {    ppSliceInLayer[iSliceIdx]->iSliceComplexRatio = WELS_DIV_ROUND (INT_MULTIPLY * iAvI[iSliceIdx], iSumAv);  }} int32_t NeedDynamicAdjust (SSlice** ppSliceInLayer, const int32_t iSliceNum) {  if ( NULL == ppSliceInLayer ) {    return false;  }   uint32_t uiTotalConsume       = 0;  int32_t iSliceIdx             = 0;  int32_t iNeedAdj              = false;   WelsEmms();   while (iSliceIdx < iSliceNum) {    if ( NULL == ppSliceInLayer[iSliceIdx] ) {      return false;    }    uiTotalConsume += ppSliceInLayer[iSliceIdx]->uiSliceConsumeTime;    iSliceIdx ++;  }  if (uiTotalConsume == 0) {    MT_TRACE_LOG (NULL, WELS_LOG_DEBUG,                  "[MT] NeedDynamicAdjust(), herein do no adjust due first picture, iCountSliceNum= %d",                  iSliceNum);    return false;  }   iSliceIdx = 0;  float fThr                    = EPSN; // threshold for various cores cases  float fRmse                   = .0f;  // root mean square error of pSlice consume ratios  const float kfMeanRatio       = 1.0f / iSliceNum;  do {    const float fRatio = 1.0f * ppSliceInLayer[iSliceIdx]->uiSliceConsumeTime / uiTotalConsume;    const float fDiffRatio = fRatio - kfMeanRatio;    fRmse += (fDiffRatio * fDiffRatio);    ++ iSliceIdx;  } while (iSliceIdx + 1 < iSliceNum);  fRmse = sqrtf (fRmse / iSliceNum);  if (iSliceNum >= 8) {    fThr += THRESHOLD_RMSE_CORE8;  } else if (iSliceNum >= 4) {    fThr += THRESHOLD_RMSE_CORE4;  } else if (iSliceNum >= 2) {    fThr += THRESHOLD_RMSE_CORE2;  } else    fThr = 1.0f;  if (fRmse > fThr)    iNeedAdj = true;  MT_TRACE_LOG (NULL, WELS_LOG_DEBUG,                "[MT] NeedDynamicAdjust(), herein adjustment decision is made (iNeedAdj= %d) by: fRmse of pSlice complexity ratios %.6f, the corresponding threshold %.6f, iCountSliceNum %d",                iNeedAdj, fRmse, fThr, iSliceNum);   return iNeedAdj;} void DynamicAdjustSlicing (sWelsEncCtx* pCtx,                           SDqLayer* pCurDqLayer,                           int32_t iCurDid) {  SSliceCtx* pSliceCtx          = &pCurDqLayer->sSliceEncCtx;  SSlice** ppSliceInLayer       = pCurDqLayer->ppSliceInLayer;  const int32_t kiCountSliceNum = pSliceCtx->iSliceNumInFrame;  const int32_t kiCountNumMb    = pSliceCtx->iMbNumInFrame;  int32_t iMinimalMbNum         =    pSliceCtx->iMbWidth;  // in theory we need only 1 SMB, here let it as one SMB row required  int32_t iMaximalMbNum         = 0;    // dynamically assign later  int32_t iMbNumLeft            = kiCountNumMb;  int32_t iRunLen[MAX_THREADS_NUM] = {0};  int32_t iSliceIdx             = 0;   int32_t iNumMbInEachGom = 0;  SWelsSvcRc* pWelsSvcRc = &pCtx->pWelsSvcRc[iCurDid];  if (pCtx->pSvcParam->iRCMode != RC_OFF_MODE) {    iNumMbInEachGom = pWelsSvcRc->iNumberMbGom;     if (iNumMbInEachGom <= 0) {      WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,               "[MT] DynamicAdjustSlicing(), invalid iNumMbInEachGom= %d from RC, iDid= %d, iCountNumMb= %d", iNumMbInEachGom,               iCurDid, kiCountNumMb);      return;    }     // do not adjust in case no extra iNumMbInEachGom based left for slicing adjustment,    // extra MB of non integrated GOM assigned at the last pSlice in default, keep up on early initial result.    if (iNumMbInEachGom * kiCountSliceNum >= kiCountNumMb) {      return;    }    iMinimalMbNum = iNumMbInEachGom;  }   if (kiCountSliceNum < 2 || (kiCountSliceNum & 0x01)) // we need suppose uiSliceNum is even for multiple threading    return;   iMaximalMbNum = kiCountNumMb - (kiCountSliceNum - 1) * iMinimalMbNum;   WelsEmms();   MT_TRACE_LOG (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), iDid= %d, iCountNumMb= %d", iCurDid,                kiCountNumMb);   iSliceIdx = 0;  while (iSliceIdx + 1 < kiCountSliceNum) {    int32_t iNumMbAssigning = WELS_DIV_ROUND (kiCountNumMb * ppSliceInLayer[iSliceIdx]->iSliceComplexRatio, INT_MULTIPLY);     // GOM boundary aligned    if (pCtx->pSvcParam->iRCMode != RC_OFF_MODE) {      iNumMbAssigning = iNumMbAssigning / iNumMbInEachGom * iNumMbInEachGom;    }     // make sure one GOM at least in each pSlice for safe    if (iNumMbAssigning < iMinimalMbNum)      iNumMbAssigning = iMinimalMbNum;    else if (iNumMbAssigning > iMaximalMbNum)      iNumMbAssigning = iMaximalMbNum;     assert (iNumMbAssigning > 0);     iMbNumLeft -= iNumMbAssigning;    if (iMbNumLeft <= 0) { // error due to we can not support slice_skip now yet, do not adjust this time      assert (0);      return;    }    iRunLen[iSliceIdx] = iNumMbAssigning;    MT_TRACE_LOG (& (pCtx->sLogCtx), WELS_LOG_DEBUG,                  "[MT] DynamicAdjustSlicing(), uiSliceIdx= %d, iSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d",                  iSliceIdx, ppSliceInLayer[iSliceIdx]->iSliceComplexRatio * 1.0f / INT_MULTIPLY,                  ppSliceInLayer[iSliceIdx]->iCountMbNumInSlice,                  iNumMbAssigning);    ++ iSliceIdx;    iMaximalMbNum = iMbNumLeft - (kiCountSliceNum - iSliceIdx - 1) * iMinimalMbNum; // get maximal num_mb in left parts  }  iRunLen[iSliceIdx] = iMbNumLeft;  MT_TRACE_LOG (& (pCtx->sLogCtx), WELS_LOG_DEBUG,                "[MT] DynamicAdjustSlicing(), iSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d",                iSliceIdx, ppSliceInLayer[iSliceIdx]->iSliceComplexRatio * 1.0f / INT_MULTIPLY,                ppSliceInLayer[iSliceIdx]->iCountMbNumInSlice, iMbNumLeft);  pCurDqLayer->bNeedAdjustingSlicing = !DynamicAdjustSlicePEncCtxAll (pCurDqLayer, iRunLen);} int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, const int32_t iCountBsLen,                           const int32_t iMaxSliceBufferSize, bool bDynamicSlice) {  CMemoryAlign* pMa             = NULL;  SWelsSvcCodingParam* pPara    = NULL;  SSliceThreading* pSmt         = NULL;  int32_t iNumSpatialLayers     = 0;  int32_t iThreadNum            = 0;  int32_t iIdx                  = 0;  int32_t iReturn               = ENC_RETURN_SUCCESS;  int32_t iMaxSliceNumInThread  = 0;   if (NULL == ppCtx || NULL == pCodingParam || NULL == *ppCtx || iCountBsLen <= 0)    return 1;#if defined(ENABLE_TRACE_MT)  SLogContext* pLogCtx = & ((*ppCtx)->sLogCtx);#endif  pMa                  = (*ppCtx)->pMemAlign;  pPara                = pCodingParam;  iNumSpatialLayers    = pPara->iSpatialLayerNum;  iThreadNum           = pPara->iMultipleThreadIdc;   assert (iThreadNum > 0);  iMaxSliceNumInThread = ((*ppCtx)->iMaxSliceCount / iThreadNum + 1) * 2;  iMaxSliceNumInThread =  WELS_MIN ((*ppCtx)->iMaxSliceCount, (int) iMaxSliceNumInThread);   pSmt = (SSliceThreading*)pMa->WelsMalloc (sizeof (SSliceThreading), "SSliceThreading");  WELS_VERIFY_RETURN_IF (1, (NULL == pSmt))  memset (pSmt, 0, sizeof (SSliceThreading));  (*ppCtx)->pSliceThreading = pSmt;  pSmt->pThreadPEncCtx = (SSliceThreadPrivateData*)pMa->WelsMalloc (sizeof (SSliceThreadPrivateData) * iThreadNum,                         "pThreadPEncCtx");  WELS_VERIFY_RETURN_IF (1, (NULL == pSmt->pThreadPEncCtx)) #ifdef _WIN32  // Dummy event namespace, the windows events don't actually use this  WelsSnprintf (pSmt->eventNamespace, sizeof (pSmt->eventNamespace), "%p", (void*) *ppCtx);#else  WelsSnprintf (pSmt->eventNamespace, sizeof (pSmt->eventNamespace), "%p%x", (void*) *ppCtx, getpid());#endif//!_WIN32 #ifdef MT_DEBUG  // file handle for MT debug  pSmt->pFSliceDiff = NULL;   if (pSmt->pFSliceDiff) {    fclose (pSmt->pFSliceDiff);    pSmt->pFSliceDiff = NULL;  }  pSmt->pFSliceDiff = fopen ("slice_time.txt", "wt+");#endif//MT_DEBUG   MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "encpEncCtx= 0x%p", (void*) *ppCtx);   char name[SEM_NAME_MAX] = {0};  WELS_GCC_UNUSED WELS_THREAD_ERROR_CODE err = 0;   iIdx = 0;  while (iIdx < iThreadNum) {    pSmt->pThreadPEncCtx[iIdx].pWelsPEncCtx   = (void*) *ppCtx;    pSmt->pThreadPEncCtx[iIdx].iSliceIndex    = iIdx;    pSmt->pThreadPEncCtx[iIdx].iThreadIndex   = iIdx;    pSmt->pThreadHandles[iIdx]                = 0;     WelsSnprintf (name, SEM_NAME_MAX, "ee%d%s", iIdx, pSmt->eventNamespace);    err = WelsEventOpen (&pSmt->pExitEncodeEvent[iIdx], name);    MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pExitEncodeEvent%d named(%s) ret%d err%d", iIdx, name, err, errno);    WelsSnprintf (name, SEM_NAME_MAX, "tm%d%s", iIdx, pSmt->eventNamespace);    err = WelsEventOpen (&pSmt->pThreadMasterEvent[iIdx], name);    MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pThreadMasterEvent%d named(%s) ret%d err%d", iIdx, name, err, errno);    // length of semaphore name should be system constrained at least on mac 10.7    WelsSnprintf (name, SEM_NAME_MAX, "ud%d%s", iIdx, pSmt->eventNamespace);    err = WelsEventOpen (&pSmt->pUpdateMbListEvent[iIdx], name);    MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pUpdateMbListEvent%d named(%s) ret%d err%d", iIdx, name, err, errno);    WelsSnprintf (name, SEM_NAME_MAX, "fu%d%s", iIdx, pSmt->eventNamespace);    err = WelsEventOpen (&pSmt->pFinUpdateMbListEvent[iIdx], name);    MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pFinUpdateMbListEvent%d named(%s) ret%d err%d", iIdx, name, err,                  errno);    WelsSnprintf (name, SEM_NAME_MAX, "sc%d%s", iIdx, pSmt->eventNamespace);    err = WelsEventOpen (&pSmt->pSliceCodedEvent[iIdx], name);    MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pSliceCodedEvent%d named(%s) ret%d err%d", iIdx, name, err, errno);    WelsSnprintf (name, SEM_NAME_MAX, "rc%d%s", iIdx, pSmt->eventNamespace);    err = WelsEventOpen (&pSmt->pReadySliceCodingEvent[iIdx], name);    MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pReadySliceCodingEvent%d = 0x%p named(%s) ret%d err%d", iIdx,                  (void*)pSmt->pReadySliceCodingEvent[iIdx], name, err, errno);    ++ iIdx;  }   WelsSnprintf (name, SEM_NAME_MAX, "scm%s", pSmt->eventNamespace);  err = WelsEventOpen (&pSmt->pSliceCodedMasterEvent, name);  MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "[MT] Open pSliceCodedMasterEvent named(%s) ret%d err%d", name, err, errno);   iReturn = WelsMutexInit (&pSmt->mutexSliceNumUpdate);  WELS_VERIFY_RETURN_IF (1, (WELS_THREAD_ERROR_OK != iReturn))   (*ppCtx)->pTaskManage = IWelsTaskManage::CreateTaskManage (*ppCtx, iNumSpatialLayers, bDynamicSlice);  WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pTaskManage))   int32_t iThreadBufferNum = WELS_MIN ((*ppCtx)->pTaskManage->GetThreadPoolThreadNum(), MAX_THREADS_NUM);   for (iIdx = 0; iIdx < iThreadBufferNum; iIdx++) {    pSmt->pThreadBsBuffer[iIdx] = (uint8_t*)pMa->WelsMalloc (iCountBsLen, "pSmt->pThreadBsBuffer");    WELS_VERIFY_RETURN_IF (1, (NULL == pSmt->pThreadBsBuffer[iIdx]))  }  iReturn = WelsMutexInit (&pSmt->mutexThreadBsBufferUsage);  WELS_VERIFY_RETURN_IF (1, (WELS_THREAD_ERROR_OK != iReturn))  iReturn = WelsMutexInit (&pSmt->mutexEvent);  WELS_VERIFY_RETURN_IF (1, (WELS_THREAD_ERROR_OK != iReturn))  iReturn = WelsMutexInit (& (*ppCtx)->mutexEncoderError);  WELS_VERIFY_RETURN_IF (1, (WELS_THREAD_ERROR_OK != iReturn))   MT_TRACE_LOG (pLogCtx, WELS_LOG_INFO, "RequestMtResource(), iThreadNum=%d, iMultipleThreadIdc= %d",                pPara->iMultipleThreadIdc,                (*ppCtx)->iMaxSliceCount);  return 0;} void ReleaseMtResource (sWelsEncCtx** ppCtx) {  SSliceThreading* pSmt                 = NULL;  CMemoryAlign* pMa                     = NULL;  int32_t iIdx                          = 0;  int32_t iThreadNum                    = 0;   if (NULL == ppCtx || NULL == *ppCtx)    return;   pMa           = (*ppCtx)->pMemAlign;  iThreadNum    = (*ppCtx)->pSvcParam->iMultipleThreadIdc;  pSmt          = (*ppCtx)->pSliceThreading;   if (NULL == pSmt)    return;   char ename[SEM_NAME_MAX] = {0};  while (iIdx < iThreadNum) {    // length of semaphore name should be system constrained at least on mac 10.7    WelsSnprintf (ename, SEM_NAME_MAX, "ee%d%s", iIdx, pSmt->eventNamespace);    WelsEventClose (&pSmt->pExitEncodeEvent[iIdx], ename);    WelsSnprintf (ename, SEM_NAME_MAX, "tm%d%s", iIdx, pSmt->eventNamespace);    WelsEventClose (&pSmt->pThreadMasterEvent[iIdx], ename);    WelsSnprintf (ename, SEM_NAME_MAX, "sc%d%s", iIdx, pSmt->eventNamespace);    WelsEventClose (&pSmt->pSliceCodedEvent[iIdx], ename);    WelsSnprintf (ename, SEM_NAME_MAX, "rc%d%s", iIdx, pSmt->eventNamespace);    WelsEventClose (&pSmt->pReadySliceCodingEvent[iIdx], ename);    WelsSnprintf (ename, SEM_NAME_MAX, "ud%d%s", iIdx, pSmt->eventNamespace);    WelsEventClose (&pSmt->pUpdateMbListEvent[iIdx], ename);    WelsSnprintf (ename, SEM_NAME_MAX, "fu%d%s", iIdx, pSmt->eventNamespace);    WelsEventClose (&pSmt->pFinUpdateMbListEvent[iIdx], ename);     ++ iIdx;  }  WelsSnprintf (ename, SEM_NAME_MAX, "scm%s", pSmt->eventNamespace);  WelsEventClose (&pSmt->pSliceCodedMasterEvent, ename);   WelsMutexDestroy (&pSmt->mutexSliceNumUpdate);  WelsMutexDestroy (&pSmt->mutexThreadBsBufferUsage);  WelsMutexDestroy (& ((*ppCtx)->mutexEncoderError));  WelsMutexDestroy (&pSmt->mutexEvent);  if (pSmt->pThreadPEncCtx != NULL) {    pMa->WelsFree (pSmt->pThreadPEncCtx, "pThreadPEncCtx");    pSmt->pThreadPEncCtx = NULL;  }   for (int i = 0; i < MAX_THREADS_NUM; i++) {    if (pSmt->pThreadBsBuffer[i]) {      pMa->WelsFree (pSmt->pThreadBsBuffer[i], "pSmt->pThreadBsBuffer");      pSmt->pThreadBsBuffer[i] = NULL;    }  }  memset (&pSmt->bThreadBsBufferUsage, 0, MAX_THREADS_NUM * sizeof (bool));   if ((*ppCtx)->pTaskManage != NULL) {    WELS_DELETE_OP ((*ppCtx)->pTaskManage);  } #ifdef MT_DEBUG  // file handle for debug  if (pSmt->pFSliceDiff) {    fclose (pSmt->pFSliceDiff);    pSmt->pFSliceDiff = NULL;  }#endif//MT_DEBUG  pMa->WelsFree ((*ppCtx)->pSliceThreading, "SSliceThreading");  (*ppCtx)->pSliceThreading = NULL;} int32_t AppendSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, const int32_t iSliceCount) {  SWelsSvcCodingParam* pCodingParam     = pCtx->pSvcParam;  SSpatialLayerConfig* pDlp             = &pCodingParam->sSpatialLayers[pCtx->uiDependencyId];  SSlice** ppSliceInlayer               = pCtx->pCurDqLayer->ppSliceInLayer;  SWelsSliceBs* pSliceBs                = NULL;  const bool kbIsDynamicSlicingMode     = (pDlp->sSliceArgument.uiSliceMode == SM_SIZELIMITED_SLICE);   int32_t iLayerSize    = 0;  int32_t iNalIdxBase   = pLbi->iNalCount;  int32_t iSliceIdx     = 0;   if (!kbIsDynamicSlicingMode) {    iNalIdxBase   = pLbi->iNalCount = 0;    while (iSliceIdx < iSliceCount) {      pSliceBs    = &ppSliceInlayer[iSliceIdx]->sSliceBs;      if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) {        int32_t iNalIdx = 0;        const int32_t iCountNal = pSliceBs->iNalIndex; #if MT_DEBUG_BS_WR        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;         iLayerSize += pSliceBs->uiBsPos;         while (iNalIdx < iCountNal) {          pLbi->pNalLengthInByte[iNalIdxBase + iNalIdx] = pSliceBs->iNalLen[iNalIdx];          ++ iNalIdx;        }        pLbi->iNalCount += iCountNal;        iNalIdxBase     += iCountNal;      }      ++ iSliceIdx;    }  } else { // for SM_SIZELIMITED_SLICE    const int32_t kiPartitionCnt        = iSliceCount;    int32_t iPartitionIdx               = 0;     // due partition_0 has been written to pFrameBsBuffer    // so iLayerSize need add it    while (iPartitionIdx < kiPartitionCnt) {      const int32_t kiCountSlicesCoded = pCtx->pCurDqLayer->pNumSliceCodedOfPartition[iPartitionIdx];      int32_t iIdx = 0;       iSliceIdx = iPartitionIdx;      while (iIdx < kiCountSlicesCoded) {        pSliceBs = &ppSliceInlayer[iSliceIdx]->sSliceBs;        if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) {          memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage          pCtx->iPosBsBuffer += pSliceBs->uiBsPos;           const int32_t iCountNal = pSliceBs->iNalIndex;          iLayerSize += pSliceBs->uiBsPos;          int32_t iNalIdx = 0;          while (iNalIdx < iCountNal) {            pLbi->pNalLengthInByte[iNalIdxBase + iNalIdx] = pSliceBs->iNalLen[iNalIdx];            ++ iNalIdx;

Lines 1–500 of 1031.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t