Showing the changes to codec/encoder/core/src/slice_multi_threading.cpp (1 of 225 files). Show all
Unified · Split
| @@ -1,1592 +1,1506 @@ | ||
| 1 | −/*! | |
| 2 | − * \copy | |
| 3 | − * Copyright (c) 2010-2013, Cisco Systems | |
| 4 | − * All rights reserved. | |
| 5 | − * | |
| 6 | − * Redistribution and use in source and binary forms, with or without | |
| 7 | − * modification, are permitted provided that the following conditions | |
| 8 | − * are met: | |
| 9 | − * | |
| 10 | − * * Redistributions of source code must retain the above copyright | |
| 11 | − * notice, this list of conditions and the following disclaimer. | |
| 12 | − * | |
| 13 | − * * Redistributions in binary form must reproduce the above copyright | |
| 14 | − * notice, this list of conditions and the following disclaimer in | |
| 15 | − * the documentation and/or other materials provided with the | |
| 16 | − * distribution. | |
| 17 | − * | |
| 18 | − * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 | − * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 | − * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 21 | − * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 22 | − * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 23 | − * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 24 | − * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 25 | − * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 26 | − * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 27 | − * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| 28 | − * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 29 | − * POSSIBILITY OF SUCH DAMAGE. | |
| 30 | − * | |
| 31 | − * | |
| 32 | − * \file slice_multi_threading.h | |
| 33 | − * | |
| 34 | − * \brief pSlice based multiple threading | |
| 35 | − * | |
| 36 | − * \date 04/16/2010 Created | |
| 37 | − * | |
| 38 | − ************************************************************************************* | |
| 39 | − */ | |
| 40 | − | |
| 41 | −#if defined(MT_ENABLED) | |
| 42 | − | |
| 43 | −#include <assert.h> | |
| 44 | −#ifdef __GNUC__ | |
| 45 | −#include <semaphore.h> | |
| 46 | −#ifndef SEM_NAME_MAX | |
| 47 | −// length of semaphore name should be system constrained at least on mac 10.7 | |
| 48 | −#define SEM_NAME_MAX 32 | |
| 49 | −#endif//SEM_NAME_MAX | |
| 50 | −#endif//__GNUC__ | |
| 51 | −#include "slice_multi_threading.h" | |
| 52 | −#include "mt_defs.h" | |
| 53 | −#include "nal_encap.h" | |
| 54 | −#include "utils.h" | |
| 55 | −#include "encoder.h" | |
| 56 | −#include "svc_encode_slice.h" | |
| 57 | −#include "deblocking.h" | |
| 58 | −#include "svc_enc_golomb.h" | |
| 59 | −#include "crt_util_safe_x.h" // for safe crt like calls | |
| 60 | −#include "rc.h" | |
| 61 | − | |
| 62 | −#if defined(X86_ASM) | |
| 63 | −#include "cpu.h" | |
| 64 | −#endif//X86_ASM | |
| 65 | − | |
| 66 | −#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 67 | −#include "measure_time.h" | |
| 68 | −#endif//DYNAMIC_SLICE_ASSIGN | |
| 69 | −namespace WelsSVCEnc { | |
| 70 | −void UpdateMbListNeighborParallel( SSliceCtx *pSliceCtx, | |
| 71 | − SMB *pMbList, | |
| 72 | − const int32_t uiSliceIdc ) | |
| 73 | −{ | |
| 74 | − const uint8_t *kpMbMap = pSliceCtx->pOverallMbMap; | |
| 75 | − const int32_t kiMbWidth = pSliceCtx->iMbWidth; | |
| 76 | − int32_t iIdx = pSliceCtx->pFirstMbInSlice[uiSliceIdc]; | |
| 77 | − const int32_t kiEndMbInSlice = iIdx + pSliceCtx->pCountMbNumInSlice[uiSliceIdc] - 1; | |
| 78 | − | |
| 79 | − do { | |
| 80 | − SMB *pMb = &pMbList[iIdx]; | |
| 81 | − uint32_t uiNeighborAvailFlag = 0; | |
| 82 | − const int32_t kiMbXY = pMb->iMbXY; | |
| 83 | − const int32_t kiMbX = pMb->iMbX; | |
| 84 | − const int32_t kiMbY = pMb->iMbY; | |
| 85 | − BOOL_T bLeft; | |
| 86 | − BOOL_T bTop; | |
| 87 | − BOOL_T bLeftTop; | |
| 88 | − BOOL_T bRightTop; | |
| 89 | − int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; | |
| 90 | − | |
| 91 | − iLeftXY = kiMbXY - 1; | |
| 92 | − iTopXY = kiMbXY - kiMbWidth; | |
| 93 | − iLeftTopXY = iTopXY - 1; | |
| 94 | − iRightTopXY = iTopXY + 1; | |
| 95 | − | |
| 96 | − bLeft = (kiMbX > 0) && (uiSliceIdc == kpMbMap[iLeftXY]); | |
| 97 | − bTop = (kiMbY > 0) && (uiSliceIdc == kpMbMap[iTopXY]); | |
| 98 | − bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == kpMbMap[iLeftTopXY]); | |
| 99 | − bRightTop = (kiMbX < (kiMbWidth-1)) && (kiMbY > 0) && (uiSliceIdc == kpMbMap[iRightTopXY]); | |
| 100 | − | |
| 101 | − if( bLeft ){ | |
| 102 | − uiNeighborAvailFlag |= LEFT_MB_POS; | |
| 103 | − } | |
| 104 | − if( bTop ){ | |
| 105 | − uiNeighborAvailFlag |= TOP_MB_POS; | |
| 106 | − } | |
| 107 | − if( bLeftTop ){ | |
| 108 | − uiNeighborAvailFlag |= TOPLEFT_MB_POS; | |
| 109 | − } | |
| 110 | − if( bRightTop ){ | |
| 111 | − uiNeighborAvailFlag |= TOPRIGHT_MB_POS; | |
| 112 | − } | |
| 113 | − pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag; | |
| 114 | − pMb->uiSliceIdc = uiSliceIdc; | |
| 115 | − | |
| 116 | − ++ iIdx; | |
| 117 | − } while(iIdx <= kiEndMbInSlice); | |
| 118 | −} | |
| 119 | − | |
| 120 | −void CalcSliceComplexRatio( void *pRatio, SSliceCtx *pSliceCtx, uint32_t *pSliceConsume ) | |
| 121 | −{ | |
| 122 | − float *pRatioList = (float *)pRatio; | |
| 123 | − float fAvI[MAX_SLICES_NUM]; | |
| 124 | − float fSumAv = .0f; | |
| 125 | − uint32_t *pSliceTime = (uint32_t *)pSliceConsume; | |
| 126 | − int32_t *pCountMbInSlice = (int32_t *)pSliceCtx->pCountMbNumInSlice; | |
| 127 | − const int32_t kiSliceCount = pSliceCtx->iSliceNumInFrame; | |
| 128 | − int32_t iSliceIdx = 0; | |
| 129 | − | |
| 130 | −#if defined(X86_ASM) | |
| 131 | − WelsEmms(); | |
| 132 | −#endif //X86_ASM | |
| 133 | − | |
| 134 | − while ( iSliceIdx < kiSliceCount ) | |
| 135 | − { | |
| 136 | − fAvI[iSliceIdx] = 1.0f * pCountMbInSlice[iSliceIdx] / pSliceTime[iSliceIdx]; | |
| 137 | −#if defined(ENABLE_TRACE_MT) | |
| 138 | − WelsLog(NULL, WELS_LOG_DEBUG, "[MT] CalcSliceComplexRatio(), pSliceConsumeTime[%d]= %d us, slice_run= %d\n", iSliceIdx, pSliceTime[iSliceIdx], pCountMbInSlice[iSliceIdx]); | |
| 139 | −#endif//ENABLE_TRACE_MT | |
| 140 | − fSumAv += fAvI[iSliceIdx]; | |
| 141 | − | |
| 142 | − ++ iSliceIdx; | |
| 143 | − } | |
| 144 | − while ( -- iSliceIdx >= 0 ) | |
| 145 | − { | |
| 146 | − pRatioList[iSliceIdx] = fAvI[iSliceIdx] / fSumAv; | |
| 147 | − } | |
| 148 | −} | |
| 149 | − | |
| 150 | −#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) && defined(NOT_ABSOLUTE_BALANCING) | |
| 151 | −int32_t NeedDynamicAdjust( void *pConsumeTime, const int32_t iSliceNum ) | |
| 152 | −{ | |
| 153 | −#if !defined(USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING) | |
| 154 | − const float fRatioLower = TOLERANT_BALANCING_RATIO_LOWER( uiSliceNum ); | |
| 155 | − const float fRatioUpper = TOLERANT_BALANCING_RATIO_UPPER( uiSliceNum ); | |
| 156 | −#endif//USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING | |
| 157 | − uint32_t *pSliceConsume = (uint32_t *)pConsumeTime; | |
| 158 | − uint32_t uiTotalConsume = 0; | |
| 159 | − int32_t iSliceIdx = 0; | |
| 160 | − int32_t iNeedAdj = false; | |
| 161 | − | |
| 162 | −#if defined(X86_ASM) | |
| 163 | − WelsEmms(); | |
| 164 | −#endif //X86_ASM | |
| 165 | − | |
| 166 | − while( iSliceIdx < iSliceNum ) | |
| 167 | − { | |
| 168 | − uiTotalConsume += pSliceConsume[iSliceIdx] + pSliceConsume[1+iSliceIdx]; | |
| 169 | − iSliceIdx += 2; | |
| 170 | − } | |
| 171 | − if (uiTotalConsume == 0) | |
| 172 | − { | |
| 173 | −#if defined(ENABLE_TRACE_MT) | |
| 174 | − WelsLog( NULL, WELS_LOG_DEBUG, "[MT] NeedDynamicAdjust(), herein do no adjust due first picture, iCountSliceNum= %d\n", iSliceNum ); | |
| 175 | −#endif//ENABLE_TRACE_MT | |
| 176 | − return false; | |
| 177 | − } | |
| 178 | − | |
| 179 | − iSliceIdx = 0; | |
| 180 | −#if defined(USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING) | |
| 181 | − float fThr = EPSN; // threshold for various cores cases | |
| 182 | − float fRmse = .0f; // root mean square error of pSlice consume ratios | |
| 183 | − const float kfMeanRatio = 1.0f / iSliceNum; | |
| 184 | − do{ | |
| 185 | − const float fRatio = 1.0f * pSliceConsume[iSliceIdx] / uiTotalConsume; | |
| 186 | − const float fDiffRatio = fRatio - kfMeanRatio; | |
| 187 | − fRmse += (fDiffRatio * fDiffRatio); | |
| 188 | − ++ iSliceIdx; | |
| 189 | − } while ( iSliceIdx+1 < iSliceNum ); | |
| 190 | − fRmse = sqrtf(fRmse/iSliceNum); | |
| 191 | − if ( iSliceNum >= 8 ) | |
| 192 | − { | |
| 193 | − fThr += THRESHOLD_RMSE_CORE8; | |
| 194 | − } | |
| 195 | − else if ( iSliceNum >= 4 ) | |
| 196 | − { | |
| 197 | − fThr += THRESHOLD_RMSE_CORE4; | |
| 198 | − } | |
| 199 | − else if ( iSliceNum >= 2 ) | |
| 200 | − { | |
| 201 | − fThr += THRESHOLD_RMSE_CORE2; | |
| 202 | − } | |
| 203 | − else | |
| 204 | − fThr = 1.0f; | |
| 205 | − if ( fRmse > fThr ) | |
| 206 | − iNeedAdj = true; | |
| 207 | −#if defined(ENABLE_TRACE_MT) | |
| 208 | − WelsLog(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\n", | |
| 209 | − iNeedAdj, fRmse, fThr, iSliceNum); | |
| 210 | −#endif//ENABLE_TRACE_MT | |
| 211 | −#else | |
| 212 | − do{ | |
| 213 | − const float kfRatio = 1.0f * pSliceConsume[uiSliceIdx] / uiTotalConsume; | |
| 214 | − if ( kfRatio+EPSN < fRatioLower || kfRatio > ratio_upper+EPSN ) | |
| 215 | − { | |
| 216 | −#if defined(ENABLE_TRACE_MT) | |
| 217 | − WelsLog(NULL, WELS_LOG_DEBUG, "[MT] NeedDynamicAdjust(), herein adjustment decision is made by pSlice consume time not balanced at all, uiSliceIdx= %d, comp_ratio= %.6f, pSliceConsumeTime= %d, total_consume_time= %d, iCountSliceNum= %d\n", | |
| 218 | − uiSliceIdx, kfRatio, pSliceConsume[uiSliceIdx], uiTotalConsume, uiSliceNum); | |
| 219 | −#endif//ENABLE_TRACE_MT | |
| 220 | − iNeedAdj = true; | |
| 221 | − break; | |
| 222 | − } | |
| 223 | − ++ uiSliceIdx; | |
| 224 | − } while ( uiSliceIdx+1 < uiSliceNum ); | |
| 225 | −#endif//USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING | |
| 226 | − | |
| 227 | − return iNeedAdj; | |
| 228 | −} | |
| 229 | −#endif//.. | |
| 230 | − | |
| 231 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 232 | −void DynamicAdjustSlicing( sWelsEncCtx *pCtx, | |
| 233 | − SDqLayer *pCurDqLayer, | |
| 234 | − void *pComplexRatio, | |
| 235 | − int32_t iCurDid ) | |
| 236 | −{ | |
| 237 | − SSliceCtx *pSliceCtx = pCurDqLayer->pSliceEncCtx; | |
| 238 | − const int32_t kiCountSliceNum = pSliceCtx->iSliceNumInFrame; | |
| 239 | − const int32_t kiCountNumMb = pSliceCtx->iMbNumInFrame; | |
| 240 | − int32_t iMinimalMbNum = pSliceCtx->iMbWidth; // in theory we need only 1 SMB, here let it as one SMB row required | |
| 241 | − int32_t iMaximalMbNum = 0; // dynamically assign later | |
| 242 | − float *pSliceComplexRatio = (float *)pComplexRatio; | |
| 243 | − int32_t iMbNumLeft = kiCountNumMb; | |
| 244 | − int32_t iRunLen[MAX_THREADS_NUM] = {0}; | |
| 245 | − int32_t iSliceIdx = 0; | |
| 246 | − | |
| 247 | − int32_t iNumMbInEachGom; | |
| 248 | − SWelsSvcRc *pWelsSvcRc = &pCtx->pWelsSvcRc[iCurDid]; | |
| 249 | − if(pCtx->pSvcParam->bEnableRc) | |
| 250 | − { | |
| 251 | − iNumMbInEachGom = pWelsSvcRc->iNumberMbGom; | |
| 252 | − | |
| 253 | − if ( iNumMbInEachGom <= 0 ) | |
| 254 | − { | |
| 255 | − WelsLog(pCtx, WELS_LOG_ERROR, "[MT] DynamicAdjustSlicing(), invalid iNumMbInEachGom= %d from RC, iDid= %d, iCountNumMb= %d\n", iNumMbInEachGom, iCurDid, kiCountNumMb); | |
| 256 | − return; | |
| 257 | − } | |
| 258 | − | |
| 259 | − // do not adjust in case no extra iNumMbInEachGom based left for slicing adjustment, | |
| 260 | − // extra MB of non integrated GOM assigned at the last pSlice in default, keep up on early initial result. | |
| 261 | − if ( iNumMbInEachGom * kiCountSliceNum >= kiCountNumMb ) | |
| 262 | − { | |
| 263 | − return; | |
| 264 | − } | |
| 265 | − iMinimalMbNum = iNumMbInEachGom; | |
| 266 | − } | |
| 267 | − | |
| 268 | − if ( kiCountSliceNum < 2 || (kiCountSliceNum & 0x01) ) // we need suppose uiSliceNum is even for multiple threading | |
| 269 | − return; | |
| 270 | − | |
| 271 | − iMaximalMbNum = kiCountNumMb - (kiCountSliceNum - 1) * iMinimalMbNum; | |
| 272 | − | |
| 273 | −#if defined(X86_ASM) | |
| 274 | − WelsEmms(); | |
| 275 | −#endif //X86_ASM | |
| 276 | − | |
| 277 | −#if defined(ENABLE_TRACE_MT) | |
| 278 | − WelsLog(pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), iDid= %d, iCountNumMb= %d\n", iCurDid, kiCountNumMb); | |
| 279 | −#endif//ENABLE_TRACE_MT | |
| 280 | − | |
| 281 | − iSliceIdx = 0; | |
| 282 | − while (iSliceIdx+1 < kiCountSliceNum) { | |
| 283 | − int32_t iNumMbAssigning = (int32_t)(kiCountNumMb * pSliceComplexRatio[iSliceIdx] + EPSN); | |
| 284 | − | |
| 285 | − // GOM boundary aligned | |
| 286 | − if(pCtx->pSvcParam->bEnableRc) | |
| 287 | − { | |
| 288 | − iNumMbAssigning=(int32_t)(1.0f * iNumMbAssigning / iNumMbInEachGom + 0.5f + EPSN) * iNumMbInEachGom; | |
| 289 | − } | |
| 290 | − | |
| 291 | − // make sure one GOM at least in each pSlice for safe | |
| 292 | − if ( iNumMbAssigning < iMinimalMbNum ) | |
| 293 | − iNumMbAssigning = iMinimalMbNum; | |
| 294 | − else if ( iNumMbAssigning > iMaximalMbNum ) | |
| 295 | − iNumMbAssigning = iMaximalMbNum; | |
| 296 | − | |
| 297 | − assert( iNumMbAssigning > 0 ); | |
| 298 | − | |
| 299 | − iMbNumLeft -= iNumMbAssigning; | |
| 300 | − if ( iMbNumLeft <= 0 ) // error due to we can not support slice_skip now yet, do not adjust this time | |
| 301 | − { | |
| 302 | − assert( 0 ); | |
| 303 | − return; | |
| 304 | − } | |
| 305 | − iRunLen[iSliceIdx] = iNumMbAssigning; | |
| 306 | −#if defined(ENABLE_TRACE_MT) | |
| 307 | − WelsLog(pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), uiSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n", | |
| 308 | − iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iNumMbAssigning); | |
| 309 | −#endif//ENABLE_TRACE_MT | |
| 310 | − ++ iSliceIdx; | |
| 311 | − iMaximalMbNum = iMbNumLeft - (kiCountSliceNum - iSliceIdx - 1) * iMinimalMbNum; // get maximal num_mb in left parts | |
| 312 | − } | |
| 313 | − iRunLen[iSliceIdx] = iMbNumLeft; | |
| 314 | −#if defined(ENABLE_TRACE_MT) | |
| 315 | − WelsLog(pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), iSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n", | |
| 316 | − iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iMbNumLeft); | |
| 317 | −#endif//ENABLE_TRACE_MT | |
| 318 | − | |
| 319 | − | |
| 320 | − if ( DynamicAdjustSlicePEncCtxAll( pSliceCtx, iRunLen ) == 0 ) | |
| 321 | − { | |
| 322 | − const int32_t kiThreadNum = pCtx->pSvcParam->iCountThreadsNum; | |
| 323 | − int32_t iThreadIdx = 0; | |
| 324 | − do { | |
| 325 | −#ifdef WIN32 | |
| 326 | − WelsEventSignal( &pCtx->pSliceThreading->pUpdateMbListEvent[iThreadIdx] ); | |
| 327 | −#else | |
| 328 | − WelsEventSignal( pCtx->pSliceThreading->pUpdateMbListEvent[iThreadIdx] ); | |
| 329 | −#endif//WIN32 | |
| 330 | − ++ iThreadIdx; | |
| 331 | − } while(iThreadIdx < kiThreadNum); | |
| 332 | − | |
| 333 | − WelsMultipleEventsWaitAllBlocking( kiThreadNum, &pCtx->pSliceThreading->pFinUpdateMbListEvent[0] ); | |
| 334 | − } | |
| 335 | −} | |
| 336 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 337 | − | |
| 338 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 339 | −void ResetEnvMt( sWelsEncCtx *pCtx) | |
| 340 | −{ | |
| 341 | − const int16_t kiSliceCount = pCtx->iMaxSliceCount; | |
| 342 | − int32_t iIdx = 0; | |
| 343 | − | |
| 344 | − while ( iIdx < kiSliceCount ) | |
| 345 | − { | |
| 346 | − SWelsSliceBs *pSliceBs = &pCtx->pSliceBs[iIdx]; | |
| 347 | − pSliceBs->uiBsPos = 0; | |
| 348 | − ++ iIdx; | |
| 349 | − } | |
| 350 | −} | |
| 351 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 352 | − | |
| 353 | −int32_t RequestMtResource( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pCodingParam, const int32_t iCountBsLen, const int32_t iTargetSpatialBsSize ) | |
| 354 | −{ | |
| 355 | − CMemoryAlign *pMa = NULL; | |
| 356 | − SWelsSvcCodingParam *pPara= NULL; | |
| 357 | − SSliceThreading *pSmt = NULL; | |
| 358 | − SWelsSliceBs *pSliceB = NULL; | |
| 359 | − uint8_t *pBsBase = NULL; | |
| 360 | − int32_t iNumSpatialLayers = 0; | |
| 361 | − int32_t iThreadNum = 0; | |
| 362 | − int32_t iIdx = 0; | |
| 363 | − int32_t iSliceBsBufferSize= 0; | |
| 364 | − int16_t iMaxSliceNum = 1; | |
| 365 | − | |
| 366 | − if ( NULL == ppCtx || NULL == pCodingParam || NULL == *ppCtx || iCountBsLen <= 0 ) | |
| 367 | − return 1; | |
| 368 | − | |
| 369 | − pMa = (*ppCtx)->pMemAlign; | |
| 370 | − pPara= pCodingParam; | |
| 371 | − iNumSpatialLayers = pPara->iNumDependencyLayer; | |
| 372 | − iThreadNum = pPara->iCountThreadsNum; | |
| 373 | − iMaxSliceNum = (*ppCtx)->iMaxSliceCount; | |
| 374 | − | |
| 375 | − pSmt = (SSliceThreading *)pMa->WelsMalloc(sizeof(SSliceThreading), "SSliceThreading"); | |
| 376 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt), FreeMemorySvc(ppCtx) ) | |
| 377 | − (*ppCtx)->pSliceThreading = pSmt; | |
| 378 | − pSmt->pThreadPEncCtx = (SSliceThreadPrivateData *)pMa->WelsMalloc( sizeof(SSliceThreadPrivateData) * iThreadNum, "pThreadPEncCtx" ); | |
| 379 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pThreadPEncCtx), FreeMemorySvc(ppCtx) ) | |
| 380 | − pSmt->pThreadHandles = (WELS_THREAD_HANDLE *)pMa->WelsMalloc( sizeof(WELS_THREAD_HANDLE) * iThreadNum, "pThreadHandles" ); | |
| 381 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pThreadHandles), FreeMemorySvc(ppCtx) ) | |
| 382 | − | |
| 383 | −#ifdef WIN32 | |
| 384 | − pSmt->pSliceCodedEvent = (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pSliceCodedEvent" ); | |
| 385 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pSliceCodedEvent), FreeMemorySvc(ppCtx) ) | |
| 386 | − pSmt->pReadySliceCodingEvent = (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pReadySliceCodingEvent" ); | |
| 387 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pReadySliceCodingEvent), FreeMemorySvc(ppCtx) ) | |
| 388 | − pSmt->pFinSliceCodingEvent = (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pFinSliceCodingEvent" ); | |
| 389 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pFinSliceCodingEvent), FreeMemorySvc(ppCtx) ) | |
| 390 | −#endif//WIN32 | |
| 391 | − | |
| 392 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 393 | −#if defined(__GNUC__) | |
| 394 | − pSmt->pUpdateMbListThrdHandles = (WELS_THREAD_HANDLE *)pMa->WelsMalloc( sizeof(WELS_THREAD_HANDLE) * iThreadNum, "pUpdateMbListThrdHandles" ); | |
| 395 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pUpdateMbListThrdHandles), FreeMemorySvc(ppCtx) ) | |
| 396 | −#endif//__GNUC__ | |
| 397 | −#ifdef WIN32 | |
| 398 | − pSmt->pUpdateMbListEvent = (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pUpdateMbListEvent" ); | |
| 399 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pUpdateMbListEvent), FreeMemorySvc(ppCtx) ) | |
| 400 | − pSmt->pFinUpdateMbListEvent = (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pFinUpdateMbListEvent" ); | |
| 401 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pFinUpdateMbListEvent), FreeMemorySvc(ppCtx) ) | |
| 402 | −#endif//WIN32 | |
| 403 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 404 | − | |
| 405 | −#ifdef WIN32 | |
| 406 | − pSmt->pExitEncodeEvent = (WELS_EVENT *)pMa->WelsMalloc( sizeof(WELS_EVENT) * iThreadNum, "pExitEncodeEvent" ); | |
| 407 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pExitEncodeEvent), FreeMemorySvc(ppCtx) ) | |
| 408 | −#endif//WIN32 | |
| 409 | − | |
| 410 | −#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 411 | − iIdx = 0; | |
| 412 | − while ( iIdx < iNumSpatialLayers ) | |
| 413 | − { | |
| 414 | − SMulSliceOption *pMso = &pPara->sDependencyLayers[iIdx].sMso; | |
| 415 | − const int32_t kiSliceNum= pMso->sSliceArgument.iSliceNum; | |
| 416 | − if (pMso->uiSliceMode == SM_FIXEDSLCNUM_SLICE && pPara->iMultipleThreadIdc > 1 && pPara->iMultipleThreadIdc >= kiSliceNum ) | |
| 417 | − { | |
| 418 | − pSmt->pSliceConsumeTime[iIdx] = (uint32_t *)pMa->WelsMallocz( kiSliceNum * sizeof(uint32_t), "pSliceConsumeTime[]" ); | |
| 419 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pSliceConsumeTime[iIdx]), FreeMemorySvc(ppCtx) ) | |
| 420 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 421 | − pSmt->pSliceComplexRatio[iIdx] = (float *)pMa->WelsMalloc( kiSliceNum * sizeof(float), "pSliceComplexRatio[]" ); | |
| 422 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pSliceComplexRatio[iIdx]), FreeMemorySvc(ppCtx) ) | |
| 423 | −#endif//TRY_SLICING_BALANCE | |
| 424 | − } | |
| 425 | − else | |
| 426 | − { | |
| 427 | − pSmt->pSliceConsumeTime[iIdx] = NULL; | |
| 428 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 429 | − pSmt->pSliceComplexRatio[iIdx] = NULL; | |
| 430 | −#endif//TRY_SLICING_BALANCE | |
| 431 | − } | |
| 432 | − ++ iIdx; | |
| 433 | − } | |
| 434 | − // NULL for pSliceConsumeTime[iIdx]: iIdx from iNumSpatialLayers to MAX_DEPENDENCY_LAYERS | |
| 435 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 436 | − | |
| 437 | −#ifdef MT_DEBUG | |
| 438 | − // file handle for MT debug | |
| 439 | − pSmt->pFSliceDiff = NULL; | |
| 440 | − | |
| 441 | − if ( pSmt->pFSliceDiff ) | |
| 442 | − { | |
| 443 | − fclose( pSmt->pFSliceDiff ); | |
| 444 | − pSmt->pFSliceDiff = NULL; | |
| 445 | − } | |
| 446 | −#ifdef WIN32 | |
| 447 | − pSmt->pFSliceDiff = fopen(".\\slice_time.txt", "wt+" ); | |
| 448 | −#else | |
| 449 | − pSmt->pFSliceDiff = fopen("/tmp/slice_time.txt", "wt+" ); | |
| 450 | −#endif//WIN32 | |
| 451 | −#endif//MT_DEBUG | |
| 452 | − | |
| 453 | −#if defined(ENABLE_TRACE_MT) | |
| 454 | − WelsLog((*ppCtx), WELS_LOG_INFO, "encpEncCtx= 0x%p\n", (void *)(*ppCtx)); | |
| 455 | −#endif//ENABLE_TRACE_MT | |
| 456 | − | |
| 457 | − iIdx = 0; | |
| 458 | − while ( iIdx < iThreadNum ) | |
| 459 | − { | |
| 460 | −#ifdef __GNUC__ // for posix threading | |
| 461 | − str_t name[SEM_NAME_MAX] = {0}; | |
| 462 | − int32_t used_len = 0; | |
| 463 | − WELS_THREAD_ERROR_CODE err = 0; | |
| 464 | −#endif//__GNUC__ | |
| 465 | − pSmt->pThreadPEncCtx[iIdx].pWelsPEncCtx = (void *)(*ppCtx); | |
| 466 | − pSmt->pThreadPEncCtx[iIdx].iSliceIndex = iIdx; | |
| 467 | − pSmt->pThreadPEncCtx[iIdx].iThreadIndex = iIdx; | |
| 468 | − pSmt->pThreadHandles[iIdx] = 0; | |
| 469 | − | |
| 470 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 471 | −#ifdef WIN32 | |
| 472 | − WelsEventInit( &pSmt->pUpdateMbListEvent[iIdx] ); | |
| 473 | − WelsEventInit( &pSmt->pFinUpdateMbListEvent[iIdx] ); | |
| 474 | −#else | |
| 475 | − // length of semaphore name should be system constrained at least on mac 10.7 | |
| 476 | − SNPRINTF( name, SEM_NAME_MAX, "ud%d%p", iIdx, (void *)(*ppCtx) ); | |
| 477 | − err = WelsEventOpen( &pSmt->pUpdateMbListEvent[iIdx], name ); | |
| 478 | −#if defined(ENABLE_TRACE_MT) | |
| 479 | − WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pUpdateMbListEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno); | |
| 480 | −#endif | |
| 481 | − used_len = SNPRINTF( name, SEM_NAME_MAX, "fu%d%p", iIdx, (void *)(*ppCtx) ); | |
| 482 | − name[used_len] = '\0'; | |
| 483 | − err = WelsEventOpen( &pSmt->pFinUpdateMbListEvent[iIdx], name ); | |
| 484 | −#if defined(ENABLE_TRACE_MT) | |
| 485 | − WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pFinUpdateMbListEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno); | |
| 486 | −#endif | |
| 487 | −#endif//WIN32 | |
| 488 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 489 | − | |
| 490 | −#ifdef WIN32 | |
| 491 | − WelsEventInit( &pSmt->pSliceCodedEvent[iIdx] ); | |
| 492 | − WelsEventInit( &pSmt->pReadySliceCodingEvent[iIdx] ); | |
| 493 | − WelsEventInit( &pSmt->pFinSliceCodingEvent[iIdx] ); | |
| 494 | − WelsEventInit( &pSmt->pExitEncodeEvent[iIdx] ); | |
| 495 | −#else | |
| 496 | − used_len = SNPRINTF( name, SEM_NAME_MAX, "sc%d%p", iIdx, (void *)(*ppCtx) ); | |
| 497 | − name[used_len] = '\0'; | |
| 498 | − err = WelsEventOpen( &pSmt->pSliceCodedEvent[iIdx], name ); | |
| 499 | −#if defined(ENABLE_TRACE_MT) | |
| 500 | − WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pSliceCodedEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno); | |
| 501 | −#endif | |
| 502 | − used_len = SNPRINTF( name, SEM_NAME_MAX, "rc%d%p", iIdx, (void *)(*ppCtx) ); | |
| 503 | − name[used_len] = '\0'; | |
| 504 | − err = WelsEventOpen( &pSmt->pReadySliceCodingEvent[iIdx], name ); | |
| 505 | −#if defined(ENABLE_TRACE_MT) | |
| 506 | − WelsLog((*ppCtx), WELS_LOG_INFO, "[MT] Open pReadySliceCodingEvent%d = 0x%p named(%s) ret%d err%d\n", iIdx, (void *)pSmt->pReadySliceCodingEvent[iIdx]), (void *)(*ppCtx), err, errno); | |
| 507 | −#endif | |
| 508 | −#endif//WIN32 | |
| 509 | − | |
| 510 | − ++ iIdx; | |
| 511 | − } | |
| 512 | − | |
| 513 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 514 | − pSmt->pCountBsSizeInPartition = (uint32_t *)pMa->WelsMalloc( sizeof(uint32_t) * iThreadNum, "pCountBsSizeInPartition" ); | |
| 515 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSmt->pCountBsSizeInPartition), FreeMemorySvc(ppCtx) ) | |
| 516 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 517 | − | |
| 518 | − WelsMutexInit( &pSmt->mutexSliceNumUpdate ); | |
| 519 | − | |
| 520 | − (*ppCtx)->pSliceBs = (SWelsSliceBs *)pMa->WelsMalloc( sizeof(SWelsSliceBs) * iMaxSliceNum, "pSliceBs" ); | |
| 521 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSliceBs), FreeMemorySvc(ppCtx) ) | |
| 522 | − | |
| 523 | − pBsBase = (*ppCtx)->pFrameBs + iCountBsLen; | |
| 524 | − pSliceB = (*ppCtx)->pSliceBs; | |
| 525 | − iSliceBsBufferSize = iTargetSpatialBsSize; | |
| 526 | − iIdx = 0; | |
| 527 | − while ( iIdx < iMaxSliceNum ) | |
| 528 | − { | |
| 529 | − pSliceB->pBsBuffer = (uint8_t *)pMa->WelsMalloc( iSliceBsBufferSize, "pSliceB->pBsBuffer" ); | |
| 530 | − | |
| 531 | − WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pSliceB->pBsBuffer), FreeMemorySvc(ppCtx) ) | |
| 532 | − pSliceB->uiSize = iSliceBsBufferSize; | |
| 533 | − | |
| 534 | − if ( iIdx > 0 ) | |
| 535 | − { | |
| 536 | − pSliceB->pBs = pBsBase; | |
| 537 | − pSliceB->uiBsPos = 0; | |
| 538 | − pBsBase += iSliceBsBufferSize; | |
| 539 | − } | |
| 540 | − else | |
| 541 | − { | |
| 542 | − pSliceB->pBs = NULL; | |
| 543 | − pSliceB->uiBsPos = 0; | |
| 544 | − } | |
| 545 | − ++ pSliceB; | |
| 546 | − ++ iIdx; | |
| 547 | − } | |
| 548 | − | |
| 549 | −#if defined(ENABLE_TRACE_MT) | |
| 550 | − WelsLog((*ppCtx), WELS_LOG_INFO, "RequestMtResource(), iThreadNum=%d, iCountSliceNum= %d\n", pPara->iCountThreadsNum, iMaxSliceNum); | |
| 551 | −#endif | |
| 552 | − | |
| 553 | − return 0; | |
| 554 | −} | |
| 555 | − | |
| 556 | −void ReleaseMtResource( sWelsEncCtx **ppCtx ) | |
| 557 | −{ | |
| 558 | − SWelsSliceBs *pSliceB = NULL; | |
| 559 | − SWelsSvcCodingParam *pCodingParam = NULL; | |
| 560 | − SSliceThreading *pSmt = NULL; | |
| 561 | − CMemoryAlign *pMa = NULL; | |
| 562 | − int32_t iIdx = 0; | |
| 563 | − int32_t iThreadNum = 0; | |
| 564 | − int16_t uiSliceNum = 0; | |
| 565 | − | |
| 566 | − if ( NULL == ppCtx || NULL == *ppCtx ) | |
| 567 | − return; | |
| 568 | − | |
| 569 | − pMa = (*ppCtx)->pMemAlign; | |
| 570 | − pCodingParam = (*ppCtx)->pSvcParam; | |
| 571 | − uiSliceNum = (*ppCtx)->iMaxSliceCount; | |
| 572 | − iThreadNum = (*ppCtx)->pSvcParam->iCountThreadsNum; | |
| 573 | − pSmt = (*ppCtx)->pSliceThreading; | |
| 574 | − | |
| 575 | − if ( NULL == pSmt ) | |
| 576 | − return; | |
| 577 | − | |
| 578 | − while ( iIdx < iThreadNum) { | |
| 579 | −#ifdef WIN32 | |
| 580 | − if ( pSmt->pThreadHandles != NULL && pSmt->pThreadHandles[iIdx] != NULL ) | |
| 581 | − WelsThreadDestroy( &pSmt->pThreadHandles[iIdx] ); | |
| 582 | − | |
| 583 | − if ( pSmt->pSliceCodedEvent != NULL ) | |
| 584 | − WelsEventDestroy( &pSmt->pSliceCodedEvent[iIdx] ); | |
| 585 | − if ( pSmt->pReadySliceCodingEvent != NULL ) | |
| 586 | − WelsEventDestroy( &pSmt->pReadySliceCodingEvent[iIdx] ); | |
| 587 | − if ( pSmt->pFinSliceCodingEvent != NULL ) | |
| 588 | − WelsEventDestroy( &pSmt->pFinSliceCodingEvent[iIdx] ); | |
| 589 | − if ( pSmt->pExitEncodeEvent != NULL ) | |
| 590 | − WelsEventDestroy( &pSmt->pExitEncodeEvent[iIdx] ); | |
| 591 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 592 | − if ( pSmt->pUpdateMbListEvent != NULL ) | |
| 593 | − WelsEventDestroy( &pSmt->pUpdateMbListEvent[iIdx] ); | |
| 594 | − if ( pSmt->pFinUpdateMbListEvent != NULL ) | |
| 595 | − WelsEventDestroy( &pSmt->pFinUpdateMbListEvent[iIdx] ); | |
| 596 | −#endif//DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE | |
| 597 | −#else | |
| 598 | − str_t ename[SEM_NAME_MAX] = {0}; | |
| 599 | − int32_t used_len = 0; | |
| 600 | − // length of semaphore name should be system constrained at least on mac 10.7 | |
| 601 | − SNPRINTF( ename, SEM_NAME_MAX, "sc%d%p", iIdx, (void *)(*ppCtx) ); | |
| 602 | − WelsEventClose( pSmt->pSliceCodedEvent[iIdx], ename ); | |
| 603 | − used_len = SNPRINTF( ename, SEM_NAME_MAX, "rc%d%p", iIdx, (void *)(*ppCtx) ); | |
| 604 | − ename[used_len] = '\0'; | |
| 605 | − WelsEventClose( pSmt->pReadySliceCodingEvent[iIdx], ename ); | |
| 606 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 607 | − used_len = SNPRINTF( ename, SEM_NAME_MAX, "ud%d%p", iIdx, (void *)(*ppCtx) ); | |
| 608 | − ename[used_len] = '\0'; | |
| 609 | − WelsEventClose( pSmt->pUpdateMbListEvent[iIdx], ename ); | |
| 610 | − used_len = SNPRINTF( ename, SEM_NAME_MAX, "fu%d%p", iIdx, (void *)(*ppCtx) ); | |
| 611 | − ename[used_len] = '\0'; | |
| 612 | − WelsEventClose( pSmt->pFinUpdateMbListEvent[iIdx], ename ); | |
| 613 | −#endif//DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE | |
| 614 | −#endif//WIN32 | |
| 615 | − | |
| 616 | − ++ iIdx; | |
| 617 | − } | |
| 618 | − | |
| 619 | −#ifdef WIN32 | |
| 620 | − if ( pSmt->pExitEncodeEvent != NULL ) | |
| 621 | − { | |
| 622 | − pMa->WelsFree( pSmt->pExitEncodeEvent, "pExitEncodeEvent" ); | |
| 623 | − pSmt->pExitEncodeEvent = NULL; | |
| 624 | − } | |
| 625 | − if ( pSmt->pSliceCodedEvent != NULL ) | |
| 626 | − { | |
| 627 | − pMa->WelsFree( pSmt->pSliceCodedEvent, "pSliceCodedEvent" ); | |
| 628 | − pSmt->pSliceCodedEvent = NULL; | |
| 629 | − } | |
| 630 | − if ( pSmt->pReadySliceCodingEvent != NULL ) | |
| 631 | − { | |
| 632 | − pMa->WelsFree( pSmt->pReadySliceCodingEvent, "pReadySliceCodingEvent" ); | |
| 633 | − pSmt->pReadySliceCodingEvent = NULL; | |
| 634 | − } | |
| 635 | − if ( pSmt->pFinSliceCodingEvent != NULL ) | |
| 636 | − { | |
| 637 | − pMa->WelsFree( pSmt->pFinSliceCodingEvent, "pFinSliceCodingEvent" ); | |
| 638 | − pSmt->pFinSliceCodingEvent = NULL; | |
| 639 | − } | |
| 640 | −#endif//WIN32 | |
| 641 | − | |
| 642 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 643 | − if ( NULL != pSmt->pCountBsSizeInPartition ) | |
| 644 | − { | |
| 645 | − pMa->WelsFree( pSmt->pCountBsSizeInPartition, "pCountBsSizeInPartition" ); | |
| 646 | − pSmt->pCountBsSizeInPartition = NULL; | |
| 647 | − } | |
| 648 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 649 | − WelsMutexDestroy( &pSmt->mutexSliceNumUpdate ); | |
| 650 | − | |
| 651 | − if ( pSmt->pThreadPEncCtx != NULL ) | |
| 652 | − { | |
| 653 | − pMa->WelsFree( pSmt->pThreadPEncCtx, "pThreadPEncCtx" ); | |
| 654 | − pSmt->pThreadPEncCtx = NULL; | |
| 655 | − } | |
| 656 | − if ( pSmt->pThreadHandles != NULL ) | |
| 657 | − { | |
| 658 | − pMa->WelsFree( pSmt->pThreadHandles, "pThreadHandles" ); | |
| 659 | − pSmt->pThreadHandles = NULL; | |
| 660 | − } | |
| 661 | − | |
| 662 | − pSliceB = (*ppCtx)->pSliceBs; | |
| 663 | − iIdx = 0; | |
| 664 | − while ( pSliceB != NULL && iIdx < uiSliceNum ) | |
| 665 | − { | |
| 666 | − if ( pSliceB->pBsBuffer ) | |
| 667 | − { | |
| 668 | − pMa->WelsFree( pSliceB->pBsBuffer, "pSliceB->pBsBuffer" ); | |
| 669 | − pSliceB->pBsBuffer = NULL; | |
| 670 | − pSliceB->uiSize = 0; | |
| 671 | − } | |
| 672 | − ++ iIdx; | |
| 673 | − ++ pSliceB; | |
| 674 | − } | |
| 675 | − if ( (*ppCtx)->pSliceBs != NULL ) | |
| 676 | − { | |
| 677 | − pMa->WelsFree( (*ppCtx)->pSliceBs, "pSliceBs" ); | |
| 678 | − (*ppCtx)->pSliceBs = NULL; | |
| 679 | − } | |
| 680 | −#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 681 | − if ( pSmt->pSliceConsumeTime != NULL ) | |
| 682 | − { | |
| 683 | − iIdx = 0; | |
| 684 | − while (iIdx < pCodingParam->iNumDependencyLayer) | |
| 685 | − { | |
| 686 | − if ( pSmt->pSliceConsumeTime[iIdx] ) | |
| 687 | − { | |
| 688 | − pMa->WelsFree( pSmt->pSliceConsumeTime[iIdx], "pSliceConsumeTime[]" ); | |
| 689 | − pSmt->pSliceConsumeTime[iIdx] = NULL; | |
| 690 | − } | |
| 691 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 692 | − if ( pSmt->pSliceComplexRatio[iIdx] != NULL ) | |
| 693 | − { | |
| 694 | − pMa->WelsFree( pSmt->pSliceComplexRatio[iIdx], "pSliceComplexRatio[]" ); | |
| 695 | − pSmt->pSliceComplexRatio[iIdx] = NULL; | |
| 696 | − } | |
| 697 | −#endif//TRY_SLICING_BALANCE | |
| 698 | − ++ iIdx; | |
| 699 | − } | |
| 700 | − } | |
| 701 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 702 | − | |
| 703 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 704 | − | |
| 705 | −#ifdef WIN32 | |
| 706 | − if ( pSmt->pUpdateMbListEvent != NULL ) | |
| 707 | − { | |
| 708 | − pMa->WelsFree( pSmt->pUpdateMbListEvent, "pUpdateMbListEvent" ); | |
| 709 | − pSmt->pUpdateMbListEvent = NULL; | |
| 710 | − } | |
| 711 | − if ( pSmt->pFinUpdateMbListEvent != NULL ) | |
| 712 | − { | |
| 713 | − pMa->WelsFree( pSmt->pFinUpdateMbListEvent, "pFinUpdateMbListEvent" ); | |
| 714 | − pSmt->pFinUpdateMbListEvent = NULL; | |
| 715 | − } | |
| 716 | −#else | |
| 717 | − if ( pSmt->pUpdateMbListThrdHandles ) | |
| 718 | − { | |
| 719 | − pMa->WelsFree( pSmt->pUpdateMbListThrdHandles, "pUpdateMbListThrdHandles" ); | |
| 720 | − pSmt->pUpdateMbListThrdHandles = NULL; | |
| 721 | − } | |
| 722 | −#endif//WIN32 | |
| 723 | − | |
| 724 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 725 | − | |
| 726 | −#ifdef MT_DEBUG | |
| 727 | − // file handle for debug | |
| 728 | − if ( pSmt->pFSliceDiff ) | |
| 729 | − { | |
| 730 | − fclose( pSmt->pFSliceDiff ); | |
| 731 | − pSmt->pFSliceDiff = NULL; | |
| 732 | − } | |
| 733 | −#endif//MT_DEBUG | |
| 734 | − pMa->WelsFree((*ppCtx)->pSliceThreading, "SSliceThreading"); | |
| 735 | − (*ppCtx)->pSliceThreading = NULL; | |
| 736 | −} | |
| 737 | − | |
| 738 | −int32_t AppendSliceToFrameBs( sWelsEncCtx *pCtx, SLayerBSInfo *pLbi, const int32_t iSliceCount ) | |
| 739 | −{ | |
| 740 | − SWelsSvcCodingParam *pCodingParam = pCtx->pSvcParam; | |
| 741 | − SDLayerParam *pDlp = &pCodingParam->sDependencyLayers[pCtx->uiDependencyId]; | |
| 742 | − SWelsSliceBs *pSliceBs = NULL; | |
| 743 | − const BOOL_T kbIsDynamicSlicingMode = (pDlp->sMso.uiSliceMode == SM_DYN_SLICE); | |
| 744 | − int32_t iLayerSize = 0; | |
| 745 | − int32_t iNalIdxBase = pLbi->iNalCount; | |
| 746 | − int32_t iSliceIdx = 0; | |
| 747 | − | |
| 748 | − if ( !kbIsDynamicSlicingMode ) | |
| 749 | − { | |
| 750 | − pSliceBs = &pCtx->pSliceBs[0]; | |
| 751 | − iLayerSize = pSliceBs->uiBsPos; // assign with base pSlice first | |
| 752 | − iSliceIdx = 1; // pSlice 0 bs has been written to pFrameBs yet by now, so uiSliceIdx base should be 1 | |
| 753 | − while (iSliceIdx < iSliceCount) | |
| 754 | − { | |
| 755 | − ++ pSliceBs; | |
| 756 | − if ( pSliceBs != NULL && pSliceBs->uiBsPos > 0 ) | |
| 757 | − { | |
| 758 | − int32_t iNalIdx = 0; | |
| 759 | − const int32_t iCountNal = pSliceBs->iNalIndex; | |
| 760 | − | |
| 761 | −#if MT_DEBUG_BS_WR | |
| 762 | − assert(pSliceBs->bSliceCodedFlag); | |
| 763 | −#endif//MT_DEBUG_BS_WR | |
| 764 | − | |
| 765 | − memmove(pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage | |
| 766 | − pCtx->iPosBsBuffer += pSliceBs->uiBsPos; | |
| 767 | − | |
| 768 | − iLayerSize += pSliceBs->uiBsPos; | |
| 769 | − | |
| 770 | − while (iNalIdx < iCountNal) | |
| 771 | − { | |
| 772 | − pLbi->iNalLengthInByte[iNalIdxBase+iNalIdx] = pSliceBs->iNalLen[iNalIdx]; | |
| 773 | − ++ iNalIdx; | |
| 774 | − } | |
| 775 | − pLbi->iNalCount += iCountNal; | |
| 776 | − iNalIdxBase += iCountNal; | |
| 777 | − } | |
| 778 | − ++ iSliceIdx; | |
| 779 | − } | |
| 780 | − } | |
| 781 | − else // for SM_DYN_SLICE | |
| 782 | − { | |
| 783 | − const int32_t kiPartitionCnt = iSliceCount; | |
| 784 | − int32_t iPartitionIdx = 0; | |
| 785 | − | |
| 786 | − // due partition_0 has been written to pFrameBsBuffer | |
| 787 | − // so iLayerSize need add it | |
| 788 | − while ( iPartitionIdx < kiPartitionCnt ) | |
| 789 | − { | |
| 790 | − const int32_t kiCountSlicesCoded = pCtx->pCurDqLayer->pNumSliceCodedOfPartition[iPartitionIdx]; | |
| 791 | − int32_t iIdx = 0; | |
| 792 | − | |
| 793 | − iSliceIdx = iPartitionIdx; | |
| 794 | − while(iIdx < kiCountSlicesCoded) | |
| 795 | − { | |
| 796 | − pSliceBs = &pCtx->pSliceBs[iSliceIdx]; | |
| 797 | − if ( pSliceBs != NULL && pSliceBs->uiBsPos > 0 ) | |
| 798 | − { | |
| 799 | − if ( iPartitionIdx > 0 ) | |
| 800 | − { | |
| 801 | − int32_t iNalIdx = 0; | |
| 802 | − const int32_t iCountNal = pSliceBs->iNalIndex; | |
| 803 | − | |
| 804 | − memmove(pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage | |
| 805 | − pCtx->iPosBsBuffer += pSliceBs->uiBsPos; | |
| 806 | − | |
| 807 | − iLayerSize += pSliceBs->uiBsPos; | |
| 808 | − | |
| 809 | − while (iNalIdx < iCountNal) | |
| 810 | − { | |
| 811 | − pLbi->iNalLengthInByte[iNalIdxBase+iNalIdx] = pSliceBs->iNalLen[iNalIdx]; | |
| 812 | − ++ iNalIdx; | |
| 813 | − } | |
| 814 | − pLbi->iNalCount += iCountNal; | |
| 815 | − iNalIdxBase += iCountNal; | |
| 816 | − } | |
| 817 | − else | |
| 818 | − { | |
| 819 | − iLayerSize += pSliceBs->uiBsPos; | |
| 820 | − } | |
| 821 | − } | |
| 822 | − | |
| 823 | − iSliceIdx += kiPartitionCnt; | |
| 824 | − ++ iIdx; | |
| 825 | − } | |
| 826 | − ++ iPartitionIdx; | |
| 827 | − } | |
| 828 | − } | |
| 829 | − | |
| 830 | − return iLayerSize; | |
| 831 | −} | |
| 832 | − | |
| 833 | −int32_t WriteSliceToFrameBs( sWelsEncCtx *pCtx, SLayerBSInfo *pLbi, uint8_t *pFrameBsBuffer, const int32_t iSliceIdx ) | |
| 834 | −{ | |
| 835 | − SWelsSliceBs *pSliceBs = &pCtx->pSliceBs[iSliceIdx]; | |
| 836 | − SNalUnitHeaderExt *pNalHdrExt= &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; | |
| 837 | − uint8_t *pDst = pFrameBsBuffer; | |
| 838 | − int32_t pNalLen[2]; | |
| 839 | − int32_t iSliceSize = 0; | |
| 840 | − const int32_t kiNalCnt = pSliceBs->iNalIndex; | |
| 841 | − int32_t iNalIdx = 0; | |
| 842 | −#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 843 | − const int32_t iFirstSlice = (iSliceIdx == 0); | |
| 844 | − int32_t iNalBase = iFirstSlice ? 0 : pLbi->iNalCount; | |
| 845 | −#else | |
| 846 | − int32_t iNalBase = 0; | |
| 847 | −#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 848 | − | |
| 849 | − while ( iNalIdx < kiNalCnt ) { | |
| 850 | − iSliceSize += WelsEncodeNalExt( &pSliceBs->sNalList[iNalIdx], pNalHdrExt, pDst, &pNalLen[iNalIdx] ); | |
| 851 | − pDst += pNalLen[iNalIdx]; | |
| 852 | − pLbi->iNalLengthInByte[iNalBase+iNalIdx] = pNalLen[iNalIdx]; | |
| 853 | − | |
| 854 | − ++ iNalIdx; | |
| 855 | − } | |
| 856 | − | |
| 857 | −#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 858 | − pSliceBs->uiBsPos = iSliceSize; | |
| 859 | − if ( iFirstSlice ) | |
| 860 | − { | |
| 861 | − // pBsBuffer has been updated at coding_slice_0_in_encoder_mother_thread() | |
| 862 | − pLbi->uiLayerType = VIDEO_CODING_LAYER; | |
| 863 | − pLbi->uiSpatialId = pNalHdrExt->uiDependencyId; | |
| 864 | − pLbi->uiTemporalId = pNalHdrExt->uiTemporalId; | |
| 865 | − pLbi->uiQualityId = 0; | |
| 866 | − pLbi->uiPriorityId = 0; | |
| 867 | − pLbi->iNalCount = kiNalCnt; | |
| 868 | − } | |
| 869 | − else | |
| 870 | − { | |
| 871 | − pLbi->iNalCount += kiNalCnt; | |
| 872 | − } | |
| 873 | −#else | |
| 874 | − pLbi->uiLayerType = VIDEO_CODING_LAYER; | |
| 875 | − pLbi->uiSpatialId = pNalHdrExt->uiDependencyId; | |
| 876 | − pLbi->uiTemporalId = pNalHdrExt->uiTemporalId; | |
| 877 | − pLbi->uiQualityId = 0; | |
| 878 | − pLbi->uiPriorityId = 0; | |
| 879 | − pLbi->iNalCount = kiNalCnt; | |
| 880 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 881 | − | |
| 882 | − return iSliceSize; | |
| 883 | −} | |
| 884 | − | |
| 885 | −int32_t WriteSliceBs( sWelsEncCtx *pCtx, uint8_t *pSliceBsBuf, const int32_t iSliceIdx ) | |
| 886 | −{ | |
| 887 | − SWelsSliceBs *pSliceBs = &pCtx->pSliceBs[iSliceIdx]; | |
| 888 | − SNalUnitHeaderExt *pNalHdrExt= &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; | |
| 889 | − uint8_t *pDst = pSliceBsBuf; | |
| 890 | − int32_t *pNalLen = &pSliceBs->iNalLen[0]; | |
| 891 | − int32_t iSliceSize = 0; | |
| 892 | − const int32_t kiNalCnt = pSliceBs->iNalIndex; | |
| 893 | − int32_t iNalIdx = 0; | |
| 894 | − | |
| 895 | − assert( kiNalCnt <= 2 ); | |
| 896 | − if ( kiNalCnt > 2 ) | |
| 897 | − return 0; | |
| 898 | − | |
| 899 | − while ( iNalIdx < kiNalCnt ) { | |
| 900 | − iSliceSize += WelsEncodeNalExt( &pSliceBs->sNalList[iNalIdx], pNalHdrExt, pDst, &pNalLen[iNalIdx] ); | |
| 901 | − pDst += pNalLen[iNalIdx]; | |
| 902 | − | |
| 903 | − ++ iNalIdx; | |
| 904 | − } | |
| 905 | − pSliceBs->uiBsPos = iSliceSize; | |
| 906 | − | |
| 907 | − return iSliceSize; | |
| 908 | −} | |
| 909 | − | |
| 910 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 911 | −#if defined(__GNUC__) | |
| 912 | −WELS_THREAD_ROUTINE_TYPE UpdateMbListThreadProc( void *arg ) | |
| 913 | −{ | |
| 914 | − SSliceThreadPrivateData *pPrivateData = (SSliceThreadPrivateData *)arg; | |
| 915 | − sWelsEncCtx *pEncPEncCtx = NULL; | |
| 916 | − SDqLayer *pCurDq = NULL; | |
| 917 | − int32_t iSliceIdx = -1; | |
| 918 | − int32_t iEventIdx = -1; | |
| 919 | − WELS_THREAD_ERROR_CODE iWaitRet = WELS_THREAD_ERROR_GENERIAL; | |
| 920 | − uint32_t uiThrdRet = 0; | |
| 921 | − | |
| 922 | − if ( NULL == pPrivateData ) | |
| 923 | − WELS_THREAD_ROUTINE_RETURN(1); | |
| 924 | − | |
| 925 | − pEncPEncCtx = (sWelsEncCtx *)pPrivateData->pWelsPEncCtx; | |
| 926 | − iSliceIdx = pPrivateData->iSliceIndex; | |
| 927 | − iEventIdx = pPrivateData->iThreadIndex; | |
| 928 | − | |
| 929 | − do { | |
| 930 | −#if defined(ENABLE_TRACE_MT) | |
| 931 | − WelsLog(pEncPEncCtx, WELS_LOG_INFO, "[MT] UpdateMbListThreadProc(), try to wait (pUpdateMbListEvent[%d])!\n", iEventIdx); | |
| 932 | −#endif | |
| 933 | − iWaitRet = WelsEventWait( pEncPEncCtx->pSliceThreading->pUpdateMbListEvent[iEventIdx] ); | |
| 934 | − if ( WELS_THREAD_ERROR_WAIT_OBJECT_0 == iWaitRet ) | |
| 935 | − { | |
| 936 | − pCurDq = pEncPEncCtx->pCurDqLayer; | |
| 937 | − UpdateMbListNeighborParallel( pCurDq->pSliceEncCtx, pCurDq->sMbDataP, iSliceIdx ); | |
| 938 | − WelsEventSignal( pEncPEncCtx->pSliceThreading->pFinUpdateMbListEvent[iEventIdx] ); // mean finished update pMb list for this pSlice | |
| 939 | − } | |
| 940 | − else | |
| 941 | − { | |
| 942 | − WelsLog(pEncPEncCtx, WELS_LOG_WARNING, "[MT] UpdateMbListThreadProc(), waiting pUpdateMbListEvent[%d] failed(%d) and thread%d terminated!\n", iEventIdx, iWaitRet, iEventIdx); | |
| 943 | − uiThrdRet = 1; | |
| 944 | − break; | |
| 945 | − } | |
| 946 | − } while(1); | |
| 947 | − | |
| 948 | − WELS_THREAD_ROUTINE_RETURN(uiThrdRet); | |
| 949 | −} | |
| 950 | −#endif//__GNUC__ | |
| 951 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 952 | − | |
| 953 | −// thread process for coding one pSlice | |
| 954 | −WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc( void *arg ) | |
| 955 | −{ | |
| 956 | − SSliceThreadPrivateData *pPrivateData = (SSliceThreadPrivateData *)arg; | |
| 957 | − sWelsEncCtx *pEncPEncCtx = NULL; | |
| 958 | − SDqLayer *pCurDq = NULL; | |
| 959 | − SSlice *pSlice = NULL; | |
| 960 | − SWelsSliceBs *pSliceBs = NULL; | |
| 961 | −#ifdef WIN32 | |
| 962 | − WELS_EVENT pEventsList[3]; | |
| 963 | − int32_t iEventCount = 0; | |
| 964 | −#endif | |
| 965 | − WELS_THREAD_ERROR_CODE iWaitRet = WELS_THREAD_ERROR_GENERIAL; | |
| 966 | − uint32_t uiThrdRet = 0; | |
| 967 | − int32_t iSliceSize = 0; | |
| 968 | − int32_t iSliceIdx = -1; | |
| 969 | − int32_t iThreadIdx = -1; | |
| 970 | − int32_t iEventIdx = -1; | |
| 971 | − bool_t bNeedPrefix = false; | |
| 972 | − EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; | |
| 973 | − EWelsNalRefIdc eNalRefIdc = NRI_PRI_LOWEST; | |
| 974 | − | |
| 975 | − if ( NULL == pPrivateData ) | |
| 976 | − WELS_THREAD_ROUTINE_RETURN(1); | |
| 977 | − | |
| 978 | − WelsSetThreadCancelable(); | |
| 979 | − | |
| 980 | − pEncPEncCtx = (sWelsEncCtx *)pPrivateData->pWelsPEncCtx; | |
| 981 | − | |
| 982 | − iThreadIdx = pPrivateData->iThreadIndex; | |
| 983 | − iEventIdx = iThreadIdx; | |
| 984 | − | |
| 985 | −#ifdef WIN32 | |
| 986 | − pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pReadySliceCodingEvent[iEventIdx]; | |
| 987 | − pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pExitEncodeEvent[iEventIdx]; | |
| 988 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 989 | − pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pUpdateMbListEvent[iEventIdx]; | |
| 990 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 991 | −#endif//WIN32 | |
| 992 | − | |
| 993 | − do { | |
| 994 | −#ifdef WIN32 | |
| 995 | − iWaitRet = WelsMultipleEventsWaitSingleBlocking( iEventCount, | |
| 996 | − &pEventsList[0], | |
| 997 | − (uint32_t)-1 ); // blocking until at least one event is | |
| 998 | −#else | |
| 999 | −#if defined(ENABLE_TRACE_MT) | |
| 1000 | − WelsLog(pEncPEncCtx, WELS_LOG_INFO, "[MT] CodingSliceThreadProc(), try to call WelsEventWait(pReadySliceCodingEvent[%d]= 0x%p), pEncPEncCtx= 0x%p!\n", iEventIdx, (void *)(pEncPEncCtx->pReadySliceCodingEvent[iEventIdx]), (void *)pEncPEncCtx ); | |
| 1001 | −#endif | |
| 1002 | − iWaitRet = WelsEventWait( pEncPEncCtx->pSliceThreading->pReadySliceCodingEvent[iEventIdx] ); | |
| 1003 | −#endif//WIN32 | |
| 1004 | − if ( WELS_THREAD_ERROR_WAIT_OBJECT_0 == iWaitRet ) // start pSlice coding signal waited | |
| 1005 | − { | |
| 1006 | − SLayerBSInfo *pLbi = pPrivateData->pLayerBs; | |
| 1007 | − const int32_t kiCurDid = pEncPEncCtx->uiDependencyId; | |
| 1008 | − const int32_t kiCurTid = pEncPEncCtx->uiTemporalId; | |
| 1009 | − SWelsSvcCodingParam *pCodingParam = pEncPEncCtx->pSvcParam; | |
| 1010 | − SDLayerParam *pParamD = &pCodingParam->sDependencyLayers[kiCurDid]; | |
| 1011 | − | |
| 1012 | − pCurDq = pEncPEncCtx->pCurDqLayer; | |
| 1013 | − eNalType = pEncPEncCtx->eNalType; | |
| 1014 | − eNalRefIdc = pEncPEncCtx->eNalPriority; | |
| 1015 | − bNeedPrefix = pEncPEncCtx->bNeedPrefixNalFlag; | |
| 1016 | − | |
| 1017 | − if ( pParamD->sMso.uiSliceMode != SM_DYN_SLICE ) | |
| 1018 | − { | |
| 1019 | − int64_t iSliceStart = 0; | |
| 1020 | − bool_t bDsaFlag = false; | |
| 1021 | − iSliceIdx = pPrivateData->iSliceIndex; | |
| 1022 | − pSlice = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 1023 | − pSliceBs = &pEncPEncCtx->pSliceBs[iSliceIdx]; | |
| 1024 | − | |
| 1025 | −#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 1026 | − bDsaFlag = (pParamD->sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && | |
| 1027 | − pCodingParam->iMultipleThreadIdc > 1 && | |
| 1028 | − pCodingParam->iMultipleThreadIdc >= pParamD->sMso.sSliceArgument.iSliceNum); | |
| 1029 | − if ( bDsaFlag ) | |
| 1030 | − iSliceStart = WelsTime(); | |
| 1031 | −#endif//DYNAMIC_SLICE_ASSIGN || MT_DEBUG | |
| 1032 | − | |
| 1033 | −#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1034 | − pSliceBs->uiBsPos = 0; | |
| 1035 | −#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1036 | − pSliceBs->iNalIndex = 0; | |
| 1037 | − assert( (void*)(&pSliceBs->sBsWrite) == (void*)pSlice->pSliceBsa ); | |
| 1038 | − InitBits( &pSliceBs->sBsWrite, pSliceBs->pBsBuffer, pSliceBs->uiSize ); | |
| 1039 | − | |
| 1040 | −#if MT_DEBUG_BS_WR | |
| 1041 | − pSliceBs->bSliceCodedFlag = FALSE; | |
| 1042 | −#endif//MT_DEBUG_BS_WR | |
| 1043 | − | |
| 1044 | − if ( bNeedPrefix ) | |
| 1045 | − { | |
| 1046 | − if ( eNalRefIdc != NRI_PRI_LOWEST ) | |
| 1047 | − { | |
| 1048 | − WelsLoadNalForSlice( pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc ); | |
| 1049 | − WelsWriteSVCPrefixNal( &pSliceBs->sBsWrite, eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == eNalType) ); | |
| 1050 | − WelsUnloadNalForSlice( pSliceBs ); | |
| 1051 | − } | |
| 1052 | − else // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension | |
| 1053 | − { | |
| 1054 | − WelsLoadNalForSlice( pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc ); | |
| 1055 | − // No need write any syntax of prefix NAL Unit RBSP here | |
| 1056 | − WelsUnloadNalForSlice( pSliceBs ); | |
| 1057 | − } | |
| 1058 | − } | |
| 1059 | − | |
| 1060 | − WelsLoadNalForSlice( pSliceBs, eNalType, eNalRefIdc ); | |
| 1061 | − | |
| 1062 | − WelsCodeOneSlice( pEncPEncCtx, iSliceIdx, eNalType ); | |
| 1063 | − | |
| 1064 | − WelsUnloadNalForSlice( pSliceBs ); | |
| 1065 | − | |
| 1066 | −#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1067 | − if ( 0 == iSliceIdx ) | |
| 1068 | − { | |
| 1069 | − pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1070 | − iSliceSize = WriteSliceToFrameBs( pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx ); | |
| 1071 | − pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1072 | − } | |
| 1073 | − else | |
| 1074 | − iSliceSize = WriteSliceBs( pEncPEncCtx, pSliceBs->pBs, iSliceIdx ); | |
| 1075 | −#else// PACKING_ONE_SLICE_PER_LAYER | |
| 1076 | − if ( 0 == iSliceIdx ) | |
| 1077 | − { | |
| 1078 | − pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1079 | − iSliceSize = WriteSliceToFrameBs( pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx ); | |
| 1080 | − pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1081 | − } | |
| 1082 | − else | |
| 1083 | − { | |
| 1084 | − pLbi->pBsBuf = pSliceBs->bs + pSliceBs->uiBsPos; | |
| 1085 | − iSliceSize = WriteSliceToFrameBs( pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx ); | |
| 1086 | − pSliceBs->uiBsPos += iSliceSize; | |
| 1087 | − } | |
| 1088 | −#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1089 | − | |
| 1090 | − if ( pCurDq->bDeblockingParallelFlag && pSlice->sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc != 1 | |
| 1091 | −#if !defined(ENABLE_FRAME_DUMP) | |
| 1092 | − && ( eNalRefIdc != NRI_PRI_LOWEST ) && | |
| 1093 | − ( pParamD->iHighestTemporalId == 0 || kiCurTid < pParamD->iHighestTemporalId ) | |
| 1094 | −#endif// !ENABLE_FRAME_DUMP | |
| 1095 | − ) | |
| 1096 | − { | |
| 1097 | − DeblockingFilterSliceAvcbase( pCurDq, pEncPEncCtx->pFuncList, iSliceIdx ); | |
| 1098 | − } | |
| 1099 | − | |
| 1100 | −#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 1101 | − if ( bDsaFlag ) | |
| 1102 | − { | |
| 1103 | − pEncPEncCtx->pSliceThreading->pSliceConsumeTime[pEncPEncCtx->uiDependencyId][iSliceIdx] = (uint32_t)(WelsTime() - iSliceStart); | |
| 1104 | −#if defined(ENABLE_TRACE_MT) | |
| 1105 | − WelsLog(pEncPEncCtx, WELS_LOG_INFO, "[MT] CodingSliceThreadProc(), coding_idx %d, uiSliceIdx %d, pSliceConsumeTime %d, iSliceSize %d, pFirstMbInSlice %d, count_num_mb_in_slice %d\n", | |
| 1106 | − pEncPEncCtx->iCodingIndex, iSliceIdx, pEncPEncCtx->pSliceThreading->pSliceConsumeTime[pEncPEncCtx->uiDependencyId][iSliceIdx], iSliceSize, pCurDq->pSliceEncCtx->pFirstMbInSlice[iSliceIdx], pCurDq->pSliceEncCtx->pCountMbNumInSlice[iSliceIdx]); | |
| 1107 | −#endif//ENABLE_TRACE_MT | |
| 1108 | − } | |
| 1109 | −#endif//DYNAMIC_SLICE_ASSIGN || MT_DEBUG | |
| 1110 | − | |
| 1111 | −#if defined(SLICE_INFO_OUTPUT) | |
| 1112 | − fprintf( stderr, | |
| 1113 | − "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n", | |
| 1114 | − iSliceIdx, | |
| 1115 | − (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'), | |
| 1116 | − eNalRefIdc, | |
| 1117 | − iSliceSize | |
| 1118 | − ); | |
| 1119 | −#endif//SLICE_INFO_OUTPUT | |
| 1120 | − | |
| 1121 | −#if MT_DEBUG_BS_WR | |
| 1122 | − pSliceBs->bSliceCodedFlag = TRUE; | |
| 1123 | −#endif//MT_DEBUG_BS_WR | |
| 1124 | − | |
| 1125 | −#ifdef WIN32 | |
| 1126 | − WelsEventSignal( &pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx] ); // mean finished coding current pSlice | |
| 1127 | −#else | |
| 1128 | − WelsEventSignal( pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx] ); // mean finished coding current pSlice | |
| 1129 | −#endif//WIN32 | |
| 1130 | − } | |
| 1131 | − else // for SM_DYN_SLICE parallelization | |
| 1132 | − { | |
| 1133 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 1134 | − SLayerBSInfo *pLbiPacking = NULL; | |
| 1135 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 1136 | − SSliceCtx *pSliceCtx = pCurDq->pSliceEncCtx; | |
| 1137 | − const int32_t kiPartitionId = iThreadIdx; | |
| 1138 | − const int32_t kiSliceIdxStep = pEncPEncCtx->iActiveThreadsNum; | |
| 1139 | − const int32_t kiFirstMbInPartition = pPrivateData->iStartMbIndex; // inclusive | |
| 1140 | − const int32_t kiEndMbInPartition = pPrivateData->iEndMbIndex; // exclusive | |
| 1141 | − int32_t iAnyMbLeftInPartition = kiEndMbInPartition - kiFirstMbInPartition; | |
| 1142 | − | |
| 1143 | − iSliceIdx = pPrivateData->iSliceIndex; | |
| 1144 | − | |
| 1145 | − pSliceCtx->pFirstMbInSlice[iSliceIdx] = kiFirstMbInPartition; | |
| 1146 | − pCurDq->pNumSliceCodedOfPartition[kiPartitionId] = 1; // one pSlice per partition intialized, dynamic slicing inside | |
| 1147 | − pCurDq->pLastMbIdxOfPartition[kiPartitionId] = kiEndMbInPartition-1; | |
| 1148 | − | |
| 1149 | − pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId] = 0; | |
| 1150 | − | |
| 1151 | − while( iAnyMbLeftInPartition > 0 ) | |
| 1152 | − { | |
| 1153 | − if ( iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint ) | |
| 1154 | − { | |
| 1155 | − // TODO: need exception handler for not large enough of MAX_SLICES_NUM related memory usage | |
| 1156 | − // No idea about its solution due MAX_SLICES_NUM is fixed lenght in relevent pData structure | |
| 1157 | − uiThrdRet = 1; | |
| 1158 | − break; | |
| 1159 | − } | |
| 1160 | − | |
| 1161 | − pSlice = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 1162 | − pSliceBs = &pEncPEncCtx->pSliceBs[iSliceIdx]; | |
| 1163 | − | |
| 1164 | −#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1165 | − pSliceBs->uiBsPos = 0; | |
| 1166 | −#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1167 | − pSliceBs->iNalIndex = 0; | |
| 1168 | − InitBits( &pSliceBs->sBsWrite, pSliceBs->pBsBuffer, pSliceBs->uiSize ); | |
| 1169 | − | |
| 1170 | − if ( bNeedPrefix ) | |
| 1171 | − { | |
| 1172 | − if ( eNalRefIdc != NRI_PRI_LOWEST ) | |
| 1173 | − { | |
| 1174 | − WelsLoadNalForSlice( pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc ); | |
| 1175 | − WelsWriteSVCPrefixNal( &pSliceBs->sBsWrite, eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == eNalType) ); | |
| 1176 | − WelsUnloadNalForSlice( pSliceBs ); | |
| 1177 | − } | |
| 1178 | − else // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension | |
| 1179 | − { | |
| 1180 | − WelsLoadNalForSlice( pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc ); | |
| 1181 | − // No need write any syntax of prefix NAL Unit RBSP here | |
| 1182 | − WelsUnloadNalForSlice( pSliceBs ); | |
| 1183 | − } | |
| 1184 | − } | |
| 1185 | − | |
| 1186 | − WelsLoadNalForSlice( pSliceBs, eNalType, eNalRefIdc ); | |
| 1187 | − | |
| 1188 | − WelsCodeOneSlice( pEncPEncCtx, iSliceIdx, eNalType ); | |
| 1189 | − | |
| 1190 | − WelsUnloadNalForSlice( pSliceBs ); | |
| 1191 | − | |
| 1192 | −#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1193 | − if ( 0 == kiPartitionId ) | |
| 1194 | − { | |
| 1195 | − if ( 0 == iSliceIdx ) | |
| 1196 | − pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1197 | − iSliceSize = WriteSliceToFrameBs( pEncPEncCtx, pLbi, pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer, iSliceIdx ); | |
| 1198 | − pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1199 | − } | |
| 1200 | − else | |
| 1201 | − iSliceSize = WriteSliceBs( pEncPEncCtx, pSliceBs->pBs, iSliceIdx ); | |
| 1202 | −#else// PACKING_ONE_SLICE_PER_LAYER | |
| 1203 | − pLbiPacking = pLbi + (iSliceIdx - kiPartitionId); | |
| 1204 | − | |
| 1205 | − if ( 0 == kiPartitionId ) | |
| 1206 | − { | |
| 1207 | − pLbiPacking->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1208 | − iSliceSize = WriteSliceToFrameBs( pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx ); | |
| 1209 | − pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1210 | − } | |
| 1211 | − else | |
| 1212 | − { | |
| 1213 | − pLbiPacking->pBsBuf = pSliceBs->bs + pSliceBs->uiBsPos; | |
| 1214 | − iSliceSize = WriteSliceToFrameBs( pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx ); | |
| 1215 | − pSliceBs->uiBsPos += iSliceSize; | |
| 1216 | − } | |
| 1217 | − pEncPEncCtx->pSliceThreading->pCountBsSizeInPartition[kiPartitionId] += iSliceSize; | |
| 1218 | −#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1219 | − | |
| 1220 | − if ( pCurDq->bDeblockingParallelFlag && pSlice->sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc != 1 | |
| 1221 | −#if !defined(ENABLE_FRAME_DUMP) | |
| 1222 | − && ( eNalRefIdc != NRI_PRI_LOWEST ) && | |
| 1223 | − ( pParamD->iHighestTemporalId == 0 || kiCurTid < pParamD->iHighestTemporalId ) | |
| 1224 | −#endif// !ENABLE_FRAME_DUMP | |
| 1225 | − ) | |
| 1226 | − { | |
| 1227 | − DeblockingFilterSliceAvcbase( pCurDq, pEncPEncCtx->pFuncList, iSliceIdx ); | |
| 1228 | − } | |
| 1229 | − | |
| 1230 | −#if defined(SLICE_INFO_OUTPUT) | |
| 1231 | − fprintf( stderr, | |
| 1232 | − "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n", | |
| 1233 | − iSliceIdx, | |
| 1234 | − (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'), | |
| 1235 | − eNalRefIdc, | |
| 1236 | − iSliceSize | |
| 1237 | − ); | |
| 1238 | −#endif//SLICE_INFO_OUTPUT | |
| 1239 | − | |
| 1240 | −#if defined(ENABLE_TRACE_MT) | |
| 1241 | − WelsLog(pEncPEncCtx, WELS_LOG_INFO, "[MT] CodingSliceThreadProc(), coding_idx %d, iPartitionId %d, uiSliceIdx %d, iSliceSize %d, count_mb_slice %d, iEndMbInPartition %d, pCurDq->pLastCodedMbIdxOfPartition[%d] %d\n", | |
| 1242 | − pEncPEncCtx->iCodingIndex, kiPartitionId, iSliceIdx, iSliceSize, pCurDq->pSliceEncCtx->pCountMbNumInSlice[iSliceIdx], kiEndMbInPartition, kiPartitionId, pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]); | |
| 1243 | −#endif//ENABLE_TRACE_MT | |
| 1244 | − | |
| 1245 | − iAnyMbLeftInPartition = kiEndMbInPartition - (1 + pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]); | |
| 1246 | − iSliceIdx += kiSliceIdxStep; | |
| 1247 | − } | |
| 1248 | − | |
| 1249 | − if ( uiThrdRet ) // any exception?? | |
| 1250 | − break; | |
| 1251 | − | |
| 1252 | −#ifdef WIN32 | |
| 1253 | − WelsEventSignal( &pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx] ); // mean finished coding current pSlice | |
| 1254 | −#else | |
| 1255 | − WelsEventSignal( pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx] ); // mean finished coding current pSlice | |
| 1256 | −#endif//WIN32 | |
| 1257 | − } | |
| 1258 | − } | |
| 1259 | −#ifdef WIN32 | |
| 1260 | − else if ( WELS_THREAD_ERROR_WAIT_OBJECT_0+1 == iWaitRet ) // exit thread signal | |
| 1261 | − { | |
| 1262 | − uiThrdRet = 0; | |
| 1263 | − break; | |
| 1264 | − } | |
| 1265 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1266 | − else if ( WELS_THREAD_ERROR_WAIT_OBJECT_0+2 == iWaitRet ) // update pMb list singal | |
| 1267 | − { | |
| 1268 | − iSliceIdx = iEventIdx; // pPrivateData->iSliceIndex; old threads can not be terminated, pPrivateData is not correct for applicable | |
| 1269 | − pCurDq = pEncPEncCtx->pCurDqLayer; | |
| 1270 | − UpdateMbListNeighborParallel( pCurDq->pSliceEncCtx, pCurDq->sMbDataP, iSliceIdx ); | |
| 1271 | − WelsEventSignal( &pEncPEncCtx->pSliceThreading->pFinUpdateMbListEvent[iEventIdx] ); // mean finished update pMb list for this pSlice | |
| 1272 | − } | |
| 1273 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1274 | −#endif//WIN32 | |
| 1275 | − else // WELS_THREAD_ERROR_WAIT_TIMEOUT, or WELS_THREAD_ERROR_WAIT_FAILED | |
| 1276 | − { | |
| 1277 | − WelsLog(pEncPEncCtx, WELS_LOG_WARNING, "[MT] CodingSliceThreadProc(), waiting pReadySliceCodingEvent[%d] failed(%d) and thread%d terminated!\n", iEventIdx, iWaitRet, iThreadIdx); | |
| 1278 | − uiThrdRet = 1; | |
| 1279 | − break; | |
| 1280 | − } | |
| 1281 | − } while( 1 ); | |
| 1282 | − | |
| 1283 | −#ifdef WIN32 | |
| 1284 | − WelsEventSignal( &pEncPEncCtx->pSliceThreading->pFinSliceCodingEvent[iEventIdx] ); // notify to mother encoding threading | |
| 1285 | −#endif//WIN32 | |
| 1286 | − | |
| 1287 | − WELS_THREAD_ROUTINE_RETURN(uiThrdRet); | |
| 1288 | −} | |
| 1289 | − | |
| 1290 | −int32_t CreateSliceThreads( sWelsEncCtx *pCtx ) | |
| 1291 | −{ | |
| 1292 | − const int32_t kiThreadCount = pCtx->pSvcParam->iCountThreadsNum; | |
| 1293 | − int32_t iIdx = 0; | |
| 1294 | −#if defined(WIN32) && defined(BIND_CPU_CORES_TO_THREADS) | |
| 1295 | − DWORD dwProcessAffinity; | |
| 1296 | − DWORD dwSystemAffinity; | |
| 1297 | − GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinity, &dwSystemAffinity); | |
| 1298 | −#endif//WIN32 && BIND_CPU_CORES_TO_THREADS | |
| 1299 | − | |
| 1300 | − while ( iIdx < kiThreadCount ) { | |
| 1301 | − WelsThreadCreate( &pCtx->pSliceThreading->pThreadHandles[iIdx], CodingSliceThreadProc, &pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0); | |
| 1302 | −#if defined(WIN32) && defined(BIND_CPU_CORES_TO_THREADS) | |
| 1303 | − if ( dwProcessAffinity > 1 && pCtx->pSliceThreading->pThreadHandles[iIdx] != NULL ) // multiple cores and thread created successfully | |
| 1304 | − { | |
| 1305 | − DWORD dw = 0; | |
| 1306 | − DWORD dwAffinityMask = 1 << iIdx; | |
| 1307 | − if (dwAffinityMask & dwProcessAffinity) // check if cpu is available | |
| 1308 | − { | |
| 1309 | − dw = SetThreadAffinityMask( pCtx->pSliceThreading->pThreadHandles[iIdx], dwAffinityMask ); //1 << iIdx | |
| 1310 | − if ( dw == 0) | |
| 1311 | − { | |
| 1312 | − str_t str[64] = {0}; | |
| 1313 | − SNPRINTF(str, 64, "SetThreadAffinityMask iIdx:%d", iIdx); | |
| 1314 | − } | |
| 1315 | − } | |
| 1316 | − } | |
| 1317 | −#endif//WIN32 && BIND_CPU_CORES_TO_THREADS | |
| 1318 | − // We need extra threads for update_mb_list_proc on __GNUC__ like OS (mac/linux) | |
| 1319 | − // due to WelsMultipleEventsWaitSingleBlocking implememtation can not work well | |
| 1320 | − // in case waiting pUpdateMbListEvent and pReadySliceCodingEvent events at the same time | |
| 1321 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1322 | −#if defined(__GNUC__) | |
| 1323 | − WelsThreadCreate( &pCtx->pSliceThreading->pUpdateMbListThrdHandles[iIdx], UpdateMbListThreadProc, &pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0); | |
| 1324 | −#endif//__GNUC__ | |
| 1325 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1326 | − ++ iIdx; | |
| 1327 | − } | |
| 1328 | −#if defined(ENABLE_TRACE_MT) | |
| 1329 | − WelsLog(pCtx, WELS_LOG_INFO, "CreateSliceThreads() exit..\n"); | |
| 1330 | −#endif | |
| 1331 | − return 0; | |
| 1332 | −} | |
| 1333 | − | |
| 1334 | −#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 1335 | −void ResetCountBsSizeInPartitions( uint32_t *pCountBsSizeList, const int32_t iPartitionCnt ) | |
| 1336 | −{ | |
| 1337 | − if ( pCountBsSizeList != NULL && iPartitionCnt > 0 ) | |
| 1338 | − { | |
| 1339 | − memset(pCountBsSizeList, 0, sizeof(pCountBsSizeList[0]) * iPartitionCnt ); | |
| 1340 | − } | |
| 1341 | −} | |
| 1342 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 1343 | − | |
| 1344 | −#ifdef WIN32 | |
| 1345 | −int32_t FiredSliceThreads( SSliceThreadPrivateData *pPriData, WELS_EVENT *pEventsList, SLayerBSInfo *pLbi, const uint32_t uiNumThreads, SSliceCtx *pSliceCtx, const BOOL_T bIsDynamicSlicingMode ) | |
| 1346 | −#else | |
| 1347 | −int32_t FiredSliceThreads( SSliceThreadPrivateData *pPriData, WELS_EVENT **pEventsList, SLayerBSInfo *pLbi, const uint32_t uiNumThreads, SSliceCtx *pSliceCtx, const BOOL_T bIsDynamicSlicingMode ) | |
| 1348 | −#endif//WIN32 | |
| 1349 | −{ | |
| 1350 | − int32_t iEndMbIdx = 0; | |
| 1351 | − int32_t iIdx = 0; | |
| 1352 | − const int32_t kiEventCnt = uiNumThreads; | |
| 1353 | − | |
| 1354 | − if ( pPriData == NULL || pLbi == NULL || kiEventCnt <= 0 || pEventsList == NULL ) | |
| 1355 | − { | |
| 1356 | − WelsLog( NULL, WELS_LOG_ERROR, "FiredSliceThreads(), fail due pPriData == %p || pLbi == %p || iEventCnt(%d) <= 0 || pEventsList == %p!!\n", (void *)pPriData, (void *)pLbi, uiNumThreads, (void *)pEventsList); | |
| 1357 | − return 1; | |
| 1358 | − } | |
| 1359 | − | |
| 1360 | −#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1361 | − //////////////////////////////////////// | |
| 1362 | − if ( bIsDynamicSlicingMode ) | |
| 1363 | − { | |
| 1364 | − iEndMbIdx = pSliceCtx->iMbNumInFrame; | |
| 1365 | − for (iIdx = kiEventCnt-1; iIdx >= 0; --iIdx) | |
| 1366 | − { | |
| 1367 | − const int32_t kiFirstMbIdx = pSliceCtx->pFirstMbInSlice[iIdx]; | |
| 1368 | − pPriData[iIdx].iStartMbIndex = kiFirstMbIdx; | |
| 1369 | − pPriData[iIdx].iEndMbIndex = iEndMbIdx; | |
| 1370 | − iEndMbIdx = kiFirstMbIdx; | |
| 1371 | − } | |
| 1372 | − } | |
| 1373 | − | |
| 1374 | − iIdx = 0; | |
| 1375 | − while (iIdx < kiEventCnt) { | |
| 1376 | − pPriData[iIdx].pLayerBs = pLbi; | |
| 1377 | − pPriData[iIdx].iSliceIndex = iIdx; | |
| 1378 | −#ifdef WIN32 | |
| 1379 | − if ( pEventsList[iIdx] ) | |
| 1380 | − WelsEventSignal( &pEventsList[iIdx] ); | |
| 1381 | −#else | |
| 1382 | − WelsEventSignal( pEventsList[iIdx] ); | |
| 1383 | −#endif//WIN32 | |
| 1384 | − ++ pLbi; | |
| 1385 | − ++ iIdx; | |
| 1386 | − } | |
| 1387 | − //////////////////////////////////////// | |
| 1388 | −#else | |
| 1389 | − //////////////////////////////////////// | |
| 1390 | − if ( bIsDynamicSlicingMode ) | |
| 1391 | − { | |
| 1392 | − iEndMbIdx = pSliceCtx->iMbNumInFrame; | |
| 1393 | − for (iIdx = kiEventCnt-1; iIdx >= 0; --iIdx) | |
| 1394 | − { | |
| 1395 | − const int32_t iFirstMbIdx = pSliceCtx->pFirstMbInSlice[iIdx]; | |
| 1396 | − pPriData[iIdx].iStartMbIndex = iFirstMbIdx; | |
| 1397 | − pPriData[iIdx].iEndMbIndex = iEndMbIdx; | |
| 1398 | − iEndMbIdx = iFirstMbIdx; | |
| 1399 | − } | |
| 1400 | − } | |
| 1401 | − | |
| 1402 | − iIdx = 0; | |
| 1403 | − while (iIdx < kiEventCnt) { | |
| 1404 | − pPriData[iIdx].pLayerBs = pLbi; | |
| 1405 | − pPriData[iIdx].iSliceIndex = iIdx; | |
| 1406 | −#ifdef WIN32 | |
| 1407 | − if ( pEventsList[iIdx] ) | |
| 1408 | − WelsEventSignal( &pEventsList[iIdx] ); | |
| 1409 | −#else | |
| 1410 | − WelsEventSignal( pEventsList[iIdx] ); | |
| 1411 | −#endif//WIN32 | |
| 1412 | − ++ iIdx; | |
| 1413 | − } | |
| 1414 | − //////////////////////////////////////// | |
| 1415 | −#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 1416 | − | |
| 1417 | − return 0; | |
| 1418 | −} | |
| 1419 | − | |
| 1420 | −int32_t DynamicDetectCpuCores() | |
| 1421 | −{ | |
| 1422 | − WelsLogicalProcessInfo info; | |
| 1423 | − WelsQueryLogicalProcessInfo(&info); | |
| 1424 | − return info.ProcessorCount; | |
| 1425 | −} | |
| 1426 | − | |
| 1427 | −#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) | |
| 1428 | − | |
| 1429 | −int32_t AdjustBaseLayer( sWelsEncCtx *pCtx ) | |
| 1430 | −{ | |
| 1431 | − SDqLayer *pCurDq = pCtx->ppDqLayerList[0]; | |
| 1432 | − int32_t iNeedAdj = 1; | |
| 1433 | −#ifdef MT_DEBUG | |
| 1434 | − int64_t iT0 = WelsTime(); | |
| 1435 | −#endif//MT_DEBUG | |
| 1436 | −#ifdef TRY_SLICING_BALANCE | |
| 1437 | − | |
| 1438 | − pCtx->pCurDqLayer = pCurDq; | |
| 1439 | − | |
| 1440 | −#ifdef NOT_ABSOLUTE_BALANCING | |
| 1441 | − // do not need adjust due to not different at both slices of consumed time | |
| 1442 | − iNeedAdj = NeedDynamicAdjust( pCtx->pSliceThreading->pSliceConsumeTime[0], pCurDq->pSliceEncCtx->iSliceNumInFrame ); | |
| 1443 | − if ( iNeedAdj ) | |
| 1444 | −#endif//NOT_ABSOLUTE_BALANCING | |
| 1445 | − DynamicAdjustSlicing( pCtx, | |
| 1446 | − pCurDq, | |
| 1447 | − pCtx->pSliceThreading->pSliceComplexRatio[0], | |
| 1448 | − 0 ); | |
| 1449 | −#endif//TRY_SLICING_BALANCE | |
| 1450 | −#ifdef MT_DEBUG | |
| 1451 | − iT0 = WelsTime() - iT0; | |
| 1452 | − if ( pCtx->pSliceThreading->pFSliceDiff ) | |
| 1453 | − { | |
| 1454 | − fprintf( pCtx->pSliceThreading->pFSliceDiff, | |
| 1455 | −#ifdef WIN32 | |
| 1456 | − "%6I64d us adjust time at base spatial layer, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1457 | −#else | |
| 1458 | − "%6lld us adjust time at base spatial layer, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1459 | −#endif//WIN32 | |
| 1460 | − iT0, iNeedAdj ); | |
| 1461 | − } | |
| 1462 | −#endif//MT_DEBUG | |
| 1463 | − | |
| 1464 | − return iNeedAdj; | |
| 1465 | −} | |
| 1466 | − | |
| 1467 | −int32_t AdjustEnhanceLayer( sWelsEncCtx *pCtx, int32_t iCurDid ) | |
| 1468 | −{ | |
| 1469 | −#ifdef MT_DEBUG | |
| 1470 | − int64_t iT1 = WelsTime(); | |
| 1471 | −#endif//MT_DEBUG | |
| 1472 | − int32_t iNeedAdj = 1; | |
| 1473 | − // uiSliceMode of referencing spatial should be SM_FIXEDSLCNUM_SLICE | |
| 1474 | − // if using spatial base layer for complexity estimation | |
| 1475 | − const BOOL_T kbModelingFromSpatial = (pCtx->pCurDqLayer->pRefLayer != NULL && iCurDid > 0) | |
| 1476 | − && (pCtx->pSvcParam->sDependencyLayers[iCurDid-1].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pCtx->pSvcParam->iMultipleThreadIdc >= pCtx->pSvcParam->sDependencyLayers[iCurDid-1].sMso.sSliceArgument.iSliceNum); | |
| 1477 | − | |
| 1478 | − if ( kbModelingFromSpatial ) // using spatial base layer for complexity estimation | |
| 1479 | − { | |
| 1480 | −#ifdef TRY_SLICING_BALANCE | |
| 1481 | −#ifdef NOT_ABSOLUTE_BALANCING | |
| 1482 | − // do not need adjust due to not different at both slices of consumed time | |
| 1483 | − iNeedAdj = NeedDynamicAdjust( pCtx->pSliceThreading->pSliceConsumeTime[iCurDid-1], pCtx->pCurDqLayer->pSliceEncCtx->iSliceNumInFrame ); | |
| 1484 | − if ( iNeedAdj ) | |
| 1485 | −#endif//NOT_ABSOLUTE_BALANCING | |
| 1486 | − DynamicAdjustSlicing( pCtx, | |
| 1487 | − pCtx->pCurDqLayer, | |
| 1488 | − pCtx->pSliceThreading->pSliceComplexRatio[iCurDid-1], | |
| 1489 | − iCurDid | |
| 1490 | − ); | |
| 1491 | −#endif//TRY_SLICING_BALANCE | |
| 1492 | − } | |
| 1493 | − else // use temporal layer for complexity estimation | |
| 1494 | − { | |
| 1495 | −#ifdef TRY_SLICING_BALANCE | |
| 1496 | −#ifdef NOT_ABSOLUTE_BALANCING | |
| 1497 | − // do not need adjust due to not different at both slices of consumed time | |
| 1498 | − iNeedAdj = NeedDynamicAdjust( pCtx->pSliceThreading->pSliceConsumeTime[iCurDid], pCtx->pCurDqLayer->pSliceEncCtx->iSliceNumInFrame ); | |
| 1499 | − if ( iNeedAdj ) | |
| 1500 | −#endif//NOT_ABSOLUTE_BALANCING | |
| 1501 | − DynamicAdjustSlicing( pCtx, | |
| 1502 | − pCtx->pCurDqLayer, | |
| 1503 | − pCtx->pSliceThreading->pSliceComplexRatio[iCurDid], | |
| 1504 | − iCurDid | |
| 1505 | − ); | |
| 1506 | −#endif//TRY_SLICING_BALANCE | |
| 1507 | − } | |
| 1508 | − | |
| 1509 | −#ifdef MT_DEBUG | |
| 1510 | − iT1 = WelsTime() - iT1; | |
| 1511 | − if ( pCtx->pSliceThreading->pFSliceDiff ) | |
| 1512 | − { | |
| 1513 | − fprintf( pCtx->pSliceThreading->pFSliceDiff, | |
| 1514 | −#ifdef WIN32 | |
| 1515 | − "%6I64d us adjust time at spatial layer %d, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1516 | −#else | |
| 1517 | − "%6lld us adjust time at spatial layer %d, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1518 | −#endif//WIN32 | |
| 1519 | − iT1, iCurDid, iNeedAdj ); | |
| 1520 | − } | |
| 1521 | −#endif//MT_DEBUG | |
| 1522 | − | |
| 1523 | − return iNeedAdj; | |
| 1524 | −} | |
| 1525 | − | |
| 1526 | −#endif//#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) | |
| 1527 | − | |
| 1528 | −#if defined(MT_ENABLED) | |
| 1529 | − | |
| 1530 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) && defined(MT_DEBUG) | |
| 1531 | −void TrackSliceComplexities( sWelsEncCtx *pCtx, const int32_t iCurDid ) | |
| 1532 | −{ | |
| 1533 | − const int32_t kiCountSliceNum = pCtx->pCurDqLayer->pSliceEncCtx->iSliceNumInFrame; | |
| 1534 | − if ( kiCountSliceNum > 0 ) | |
| 1535 | − { | |
| 1536 | − int32_t iSliceIdx = 0; | |
| 1537 | − do { | |
| 1538 | − fprintf( pCtx->pSliceThreading->pFSliceDiff, "%6.3f complexity pRatio at iDid %d pSlice %d\n", pCtx->pSliceThreading->pSliceComplexRatio[iCurDid][iSliceIdx], iCurDid, iSliceIdx ); | |
| 1539 | − ++ iSliceIdx; | |
| 1540 | − } while(iSliceIdx < kiCountSliceNum); | |
| 1541 | − } | |
| 1542 | −} | |
| 1543 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1544 | − | |
| 1545 | −#if defined(DYNAMIC_SLICE_ASSIGN) && defined(MT_DEBUG) | |
| 1546 | −void TrackSliceConsumeTime( sWelsEncCtx *pCtx, int32_t *pDidList, const int32_t iSpatialNum ) | |
| 1547 | −{ | |
| 1548 | − SWelsSvcCodingParam *pPara = NULL; | |
| 1549 | − int32_t iSpatialIdx = 0; | |
| 1550 | − | |
| 1551 | − if ( iSpatialNum > MAX_DEPENDENCY_LAYER ) | |
| 1552 | − return; | |
| 1553 | − | |
| 1554 | − pPara = pCtx->pSvcParam; | |
| 1555 | − while ( iSpatialIdx < iSpatialNum ) | |
| 1556 | − { | |
| 1557 | − const int32_t kiDid = pDidList[iSpatialIdx]; | |
| 1558 | − SDLayerParam *pDlp = &pPara->sDependencyLayers[kiDid]; | |
| 1559 | − SMulSliceOption *pMso = &pDlp->sMso; | |
| 1560 | − SDqLayer *pCurDq = pCtx->ppDqLayerList[kiDid]; | |
| 1561 | − SSliceCtx *pSliceCtx= pCurDq->pSliceEncCtx; | |
| 1562 | − const uint32_t kuiCountSliceNum = pSliceCtx->iSliceNumInFrame; | |
| 1563 | − if(pCtx->pSliceThreading) | |
| 1564 | − { | |
| 1565 | − if ( pCtx->pSliceThreading->pFSliceDiff && pMso->uiSliceMode == SM_FIXEDSLCNUM_SLICE && pPara->iMultipleThreadIdc > 1 && pPara->iMultipleThreadIdc >= kuiCountSliceNum ) | |
| 1566 | − { | |
| 1567 | − uint32_t i = 0; | |
| 1568 | − uint32_t uiMaxT = 0; | |
| 1569 | − int32_t iMaxI = 0; | |
| 1570 | − while (i < kuiCountSliceNum) { | |
| 1571 | − if ( pCtx->pSliceThreading->pSliceConsumeTime[kiDid] != NULL ) | |
| 1572 | − fprintf( pCtx->pSliceThreading->pFSliceDiff, "%6d us consume_time coding_idx %d iDid %d pSlice %d\n", | |
| 1573 | − pCtx->pSliceThreading->pSliceConsumeTime[kiDid][i], pCtx->iCodingIndex, kiDid, i /*/ 1000*/); | |
| 1574 | − if (pCtx->pSliceThreading->pSliceConsumeTime[kiDid][i] > uiMaxT) | |
| 1575 | − { | |
| 1576 | − uiMaxT = pCtx->pSliceThreading->pSliceConsumeTime[kiDid][i]; | |
| 1577 | − iMaxI = i; | |
| 1578 | − } | |
| 1579 | − ++ i; | |
| 1580 | − } | |
| 1581 | − fprintf( pCtx->pSliceThreading->pFSliceDiff, "%6d us consume_time_max coding_idx %d iDid %d pSlice %d\n", uiMaxT, pCtx->iCodingIndex, kiDid, iMaxI /*/ 1000*/); | |
| 1582 | − } | |
| 1583 | − } | |
| 1584 | − ++ iSpatialIdx; | |
| 1585 | − } | |
| 1586 | −} | |
| 1587 | −#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 1588 | − | |
| 1589 | −#endif//MT_ENABLED | |
| 1590 | −} | |
| 1591 | −#endif//MT_ENABLED | |
| 1592 | − | |
| 1 | +/*! | |
| 2 | + * \copy | |
| 3 | + * Copyright (c) 2010-2013, Cisco Systems | |
| 4 | + * All rights reserved. | |
| 5 | + * | |
| 6 | + * Redistribution and use in source and binary forms, with or without | |
| 7 | + * modification, are permitted provided that the following conditions | |
| 8 | + * are met: | |
| 9 | + * | |
| 10 | + * * Redistributions of source code must retain the above copyright | |
| 11 | + * notice, this list of conditions and the following disclaimer. | |
| 12 | + * | |
| 13 | + * * Redistributions in binary form must reproduce the above copyright | |
| 14 | + * notice, this list of conditions and the following disclaimer in | |
| 15 | + * the documentation and/or other materials provided with the | |
| 16 | + * distribution. | |
| 17 | + * | |
| 18 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 21 | + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 22 | + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 23 | + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 24 | + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 25 | + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 26 | + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 27 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| 28 | + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 29 | + * POSSIBILITY OF SUCH DAMAGE. | |
| 30 | + * | |
| 31 | + * | |
| 32 | + * \file slice_multi_threading.h | |
| 33 | + * | |
| 34 | + * \brief pSlice based multiple threading | |
| 35 | + * | |
| 36 | + * \date 04/16/2010 Created | |
| 37 | + * | |
| 38 | + ************************************************************************************* | |
| 39 | + */ | |
| 40 | + | |
| 41 | +#if defined(MT_ENABLED) | |
| 42 | + | |
| 43 | +#include <assert.h> | |
| 44 | +#ifdef __GNUC__ | |
| 45 | +#include <semaphore.h> | |
| 46 | +#ifndef SEM_NAME_MAX | |
| 47 | +// length of semaphore name should be system constrained at least on mac 10.7 | |
| 48 | +#define SEM_NAME_MAX 32 | |
| 49 | +#endif//SEM_NAME_MAX | |
| 50 | +#endif//__GNUC__ | |
| 51 | +#include "slice_multi_threading.h" | |
| 52 | +#include "mt_defs.h" | |
| 53 | +#include "nal_encap.h" | |
| 54 | +#include "utils.h" | |
| 55 | +#include "encoder.h" | |
| 56 | +#include "svc_encode_slice.h" | |
| 57 | +#include "deblocking.h" | |
| 58 | +#include "svc_enc_golomb.h" | |
| 59 | +#include "crt_util_safe_x.h" // for safe crt like calls | |
| 60 | +#include "rc.h" | |
| 61 | + | |
| 62 | +#if defined(X86_ASM) | |
| 63 | +#include "cpu.h" | |
| 64 | +#endif//X86_ASM | |
| 65 | + | |
| 66 | +#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 67 | +#include "measure_time.h" | |
| 68 | +#endif//DYNAMIC_SLICE_ASSIGN | |
| 69 | +namespace WelsSVCEnc { | |
| 70 | +void UpdateMbListNeighborParallel (SSliceCtx* pSliceCtx, | |
| 71 | + SMB* pMbList, | |
| 72 | + const int32_t uiSliceIdc) { | |
| 73 | + const uint8_t* kpMbMap = pSliceCtx->pOverallMbMap; | |
| 74 | + const int32_t kiMbWidth = pSliceCtx->iMbWidth; | |
| 75 | + int32_t iIdx = pSliceCtx->pFirstMbInSlice[uiSliceIdc]; | |
| 76 | + const int32_t kiEndMbInSlice = iIdx + pSliceCtx->pCountMbNumInSlice[uiSliceIdc] - 1; | |
| 77 | + | |
| 78 | + do { | |
| 79 | + SMB* pMb = &pMbList[iIdx]; | |
| 80 | + uint32_t uiNeighborAvailFlag = 0; | |
| 81 | + const int32_t kiMbXY = pMb->iMbXY; | |
| 82 | + const int32_t kiMbX = pMb->iMbX; | |
| 83 | + const int32_t kiMbY = pMb->iMbY; | |
| 84 | + BOOL_T bLeft; | |
| 85 | + BOOL_T bTop; | |
| 86 | + BOOL_T bLeftTop; | |
| 87 | + BOOL_T bRightTop; | |
| 88 | + int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY; | |
| 89 | + | |
| 90 | + iLeftXY = kiMbXY - 1; | |
| 91 | + iTopXY = kiMbXY - kiMbWidth; | |
| 92 | + iLeftTopXY = iTopXY - 1; | |
| 93 | + iRightTopXY = iTopXY + 1; | |
| 94 | + | |
| 95 | + bLeft = (kiMbX > 0) && (uiSliceIdc == kpMbMap[iLeftXY]); | |
| 96 | + bTop = (kiMbY > 0) && (uiSliceIdc == kpMbMap[iTopXY]); | |
| 97 | + bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == kpMbMap[iLeftTopXY]); | |
| 98 | + bRightTop = (kiMbX < (kiMbWidth - 1)) && (kiMbY > 0) && (uiSliceIdc == kpMbMap[iRightTopXY]); | |
| 99 | + | |
| 100 | + if (bLeft) { | |
| 101 | + uiNeighborAvailFlag |= LEFT_MB_POS; | |
| 102 | + } | |
| 103 | + if (bTop) { | |
| 104 | + uiNeighborAvailFlag |= TOP_MB_POS; | |
| 105 | + } | |
| 106 | + if (bLeftTop) { | |
| 107 | + uiNeighborAvailFlag |= TOPLEFT_MB_POS; | |
| 108 | + } | |
| 109 | + if (bRightTop) { | |
| 110 | + uiNeighborAvailFlag |= TOPRIGHT_MB_POS; | |
| 111 | + } | |
| 112 | + pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag; | |
| 113 | + pMb->uiSliceIdc = uiSliceIdc; | |
| 114 | + | |
| 115 | + ++ iIdx; | |
| 116 | + } while (iIdx <= kiEndMbInSlice); | |
| 117 | +} | |
| 118 | + | |
| 119 | +void CalcSliceComplexRatio (void* pRatio, SSliceCtx* pSliceCtx, uint32_t* pSliceConsume) { | |
| 120 | + float* pRatioList = (float*)pRatio; | |
| 121 | + float fAvI[MAX_SLICES_NUM]; | |
| 122 | + float fSumAv = .0f; | |
| 123 | + uint32_t* pSliceTime = (uint32_t*)pSliceConsume; | |
| 124 | + int32_t* pCountMbInSlice = (int32_t*)pSliceCtx->pCountMbNumInSlice; | |
| 125 | + const int32_t kiSliceCount = pSliceCtx->iSliceNumInFrame; | |
| 126 | + int32_t iSliceIdx = 0; | |
| 127 | + | |
| 128 | +#if defined(X86_ASM) | |
| 129 | + WelsEmms(); | |
| 130 | +#endif //X86_ASM | |
| 131 | + | |
| 132 | + while (iSliceIdx < kiSliceCount) { | |
| 133 | + fAvI[iSliceIdx] = 1.0f * pCountMbInSlice[iSliceIdx] / pSliceTime[iSliceIdx]; | |
| 134 | +#if defined(ENABLE_TRACE_MT) | |
| 135 | + WelsLog (NULL, WELS_LOG_DEBUG, "[MT] CalcSliceComplexRatio(), pSliceConsumeTime[%d]= %d us, slice_run= %d\n", iSliceIdx, | |
| 136 | + pSliceTime[iSliceIdx], pCountMbInSlice[iSliceIdx]); | |
| 137 | +#endif//ENABLE_TRACE_MT | |
| 138 | + fSumAv += fAvI[iSliceIdx]; | |
| 139 | + | |
| 140 | + ++ iSliceIdx; | |
| 141 | + } | |
| 142 | + while (-- iSliceIdx >= 0) { | |
| 143 | + pRatioList[iSliceIdx] = fAvI[iSliceIdx] / fSumAv; | |
| 144 | + } | |
| 145 | +} | |
| 146 | + | |
| 147 | +#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) && defined(NOT_ABSOLUTE_BALANCING) | |
| 148 | +int32_t NeedDynamicAdjust (void* pConsumeTime, const int32_t iSliceNum) { | |
| 149 | +#if !defined(USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING) | |
| 150 | + const float fRatioLower = TOLERANT_BALANCING_RATIO_LOWER (uiSliceNum); | |
| 151 | + const float fRatioUpper = TOLERANT_BALANCING_RATIO_UPPER (uiSliceNum); | |
| 152 | +#endif//USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING | |
| 153 | + uint32_t* pSliceConsume = (uint32_t*)pConsumeTime; | |
| 154 | + uint32_t uiTotalConsume = 0; | |
| 155 | + int32_t iSliceIdx = 0; | |
| 156 | + int32_t iNeedAdj = false; | |
| 157 | + | |
| 158 | +#if defined(X86_ASM) | |
| 159 | + WelsEmms(); | |
| 160 | +#endif //X86_ASM | |
| 161 | + | |
| 162 | + while (iSliceIdx < iSliceNum) { | |
| 163 | + uiTotalConsume += pSliceConsume[iSliceIdx] + pSliceConsume[1 + iSliceIdx]; | |
| 164 | + iSliceIdx += 2; | |
| 165 | + } | |
| 166 | + if (uiTotalConsume == 0) { | |
| 167 | +#if defined(ENABLE_TRACE_MT) | |
| 168 | + WelsLog (NULL, WELS_LOG_DEBUG, "[MT] NeedDynamicAdjust(), herein do no adjust due first picture, iCountSliceNum= %d\n", | |
| 169 | + iSliceNum); | |
| 170 | +#endif//ENABLE_TRACE_MT | |
| 171 | + return false; | |
| 172 | + } | |
| 173 | + | |
| 174 | + iSliceIdx = 0; | |
| 175 | +#if defined(USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING) | |
| 176 | + float fThr = EPSN; // threshold for various cores cases | |
| 177 | + float fRmse = .0f; // root mean square error of pSlice consume ratios | |
| 178 | + const float kfMeanRatio = 1.0f / iSliceNum; | |
| 179 | + do { | |
| 180 | + const float fRatio = 1.0f * pSliceConsume[iSliceIdx] / uiTotalConsume; | |
| 181 | + const float fDiffRatio = fRatio - kfMeanRatio; | |
| 182 | + fRmse += (fDiffRatio * fDiffRatio); | |
| 183 | + ++ iSliceIdx; | |
| 184 | + } while (iSliceIdx + 1 < iSliceNum); | |
| 185 | + fRmse = sqrtf (fRmse / iSliceNum); | |
| 186 | + if (iSliceNum >= 8) { | |
| 187 | + fThr += THRESHOLD_RMSE_CORE8; | |
| 188 | + } else if (iSliceNum >= 4) { | |
| 189 | + fThr += THRESHOLD_RMSE_CORE4; | |
| 190 | + } else if (iSliceNum >= 2) { | |
| 191 | + fThr += THRESHOLD_RMSE_CORE2; | |
| 192 | + } else | |
| 193 | + fThr = 1.0f; | |
| 194 | + if (fRmse > fThr) | |
| 195 | + iNeedAdj = true; | |
| 196 | +#if defined(ENABLE_TRACE_MT) | |
| 197 | + WelsLog (NULL, WELS_LOG_DEBUG, | |
| 198 | + "[MT] NeedDynamicAdjust(), herein adjustment decision is made (iNeedAdj= %d) by: fRmse of pSlice complexity ratios %.6f, the corresponding threshold %.6f, iCountSliceNum %d\n", | |
| 199 | + iNeedAdj, fRmse, fThr, iSliceNum); | |
| 200 | +#endif//ENABLE_TRACE_MT | |
| 201 | +#else | |
| 202 | + do { | |
| 203 | + const float kfRatio = 1.0f * pSliceConsume[uiSliceIdx] / uiTotalConsume; | |
| 204 | + if (kfRatio + EPSN < fRatioLower || kfRatio > ratio_upper + EPSN) { | |
| 205 | +#if defined(ENABLE_TRACE_MT) | |
| 206 | + WelsLog (NULL, WELS_LOG_DEBUG, | |
| 207 | + "[MT] NeedDynamicAdjust(), herein adjustment decision is made by pSlice consume time not balanced at all, uiSliceIdx= %d, comp_ratio= %.6f, pSliceConsumeTime= %d, total_consume_time= %d, iCountSliceNum= %d\n", | |
| 208 | + uiSliceIdx, kfRatio, pSliceConsume[uiSliceIdx], uiTotalConsume, uiSliceNum); | |
| 209 | +#endif//ENABLE_TRACE_MT | |
| 210 | + iNeedAdj = true; | |
| 211 | + break; | |
| 212 | + } | |
| 213 | + ++ uiSliceIdx; | |
| 214 | + } while (uiSliceIdx + 1 < uiSliceNum); | |
| 215 | +#endif//USE_RMSE_SLICE_COMPLEXITY_RATIO_FOR_BALANCING | |
| 216 | + | |
| 217 | + return iNeedAdj; | |
| 218 | +} | |
| 219 | +#endif//.. | |
| 220 | + | |
| 221 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 222 | +void DynamicAdjustSlicing (sWelsEncCtx* pCtx, | |
| 223 | + SDqLayer* pCurDqLayer, | |
| 224 | + void* pComplexRatio, | |
| 225 | + int32_t iCurDid) { | |
| 226 | + SSliceCtx* pSliceCtx = pCurDqLayer->pSliceEncCtx; | |
| 227 | + const int32_t kiCountSliceNum = pSliceCtx->iSliceNumInFrame; | |
| 228 | + const int32_t kiCountNumMb = pSliceCtx->iMbNumInFrame; | |
| 229 | + int32_t iMinimalMbNum = pSliceCtx->iMbWidth; // in theory we need only 1 SMB, here let it as one SMB row required | |
| 230 | + int32_t iMaximalMbNum = 0; // dynamically assign later | |
| 231 | + float* pSliceComplexRatio = (float*)pComplexRatio; | |
| 232 | + int32_t iMbNumLeft = kiCountNumMb; | |
| 233 | + int32_t iRunLen[MAX_THREADS_NUM] = {0}; | |
| 234 | + int32_t iSliceIdx = 0; | |
| 235 | + | |
| 236 | + int32_t iNumMbInEachGom; | |
| 237 | + SWelsSvcRc* pWelsSvcRc = &pCtx->pWelsSvcRc[iCurDid]; | |
| 238 | + if (pCtx->pSvcParam->bEnableRc) { | |
| 239 | + iNumMbInEachGom = pWelsSvcRc->iNumberMbGom; | |
| 240 | + | |
| 241 | + if (iNumMbInEachGom <= 0) { | |
| 242 | + WelsLog (pCtx, WELS_LOG_ERROR, | |
| 243 | + "[MT] DynamicAdjustSlicing(), invalid iNumMbInEachGom= %d from RC, iDid= %d, iCountNumMb= %d\n", iNumMbInEachGom, | |
| 244 | + iCurDid, kiCountNumMb); | |
| 245 | + return; | |
| 246 | + } | |
| 247 | + | |
| 248 | + // do not adjust in case no extra iNumMbInEachGom based left for slicing adjustment, | |
| 249 | + // extra MB of non integrated GOM assigned at the last pSlice in default, keep up on early initial result. | |
| 250 | + if (iNumMbInEachGom * kiCountSliceNum >= kiCountNumMb) { | |
| 251 | + return; | |
| 252 | + } | |
| 253 | + iMinimalMbNum = iNumMbInEachGom; | |
| 254 | + } | |
| 255 | + | |
| 256 | + if (kiCountSliceNum < 2 || (kiCountSliceNum & 0x01)) // we need suppose uiSliceNum is even for multiple threading | |
| 257 | + return; | |
| 258 | + | |
| 259 | + iMaximalMbNum = kiCountNumMb - (kiCountSliceNum - 1) * iMinimalMbNum; | |
| 260 | + | |
| 261 | +#if defined(X86_ASM) | |
| 262 | + WelsEmms(); | |
| 263 | +#endif //X86_ASM | |
| 264 | + | |
| 265 | +#if defined(ENABLE_TRACE_MT) | |
| 266 | + WelsLog (pCtx, WELS_LOG_DEBUG, "[MT] DynamicAdjustSlicing(), iDid= %d, iCountNumMb= %d\n", iCurDid, kiCountNumMb); | |
| 267 | +#endif//ENABLE_TRACE_MT | |
| 268 | + | |
| 269 | + iSliceIdx = 0; | |
| 270 | + while (iSliceIdx + 1 < kiCountSliceNum) { | |
| 271 | + int32_t iNumMbAssigning = (int32_t) (kiCountNumMb * pSliceComplexRatio[iSliceIdx] + EPSN); | |
| 272 | + | |
| 273 | + // GOM boundary aligned | |
| 274 | + if (pCtx->pSvcParam->bEnableRc) { | |
| 275 | + iNumMbAssigning = (int32_t) (1.0f * iNumMbAssigning / iNumMbInEachGom + 0.5f + EPSN) * iNumMbInEachGom; | |
| 276 | + } | |
| 277 | + | |
| 278 | + // make sure one GOM at least in each pSlice for safe | |
| 279 | + if (iNumMbAssigning < iMinimalMbNum) | |
| 280 | + iNumMbAssigning = iMinimalMbNum; | |
| 281 | + else if (iNumMbAssigning > iMaximalMbNum) | |
| 282 | + iNumMbAssigning = iMaximalMbNum; | |
| 283 | + | |
| 284 | + assert (iNumMbAssigning > 0); | |
| 285 | + | |
| 286 | + iMbNumLeft -= iNumMbAssigning; | |
| 287 | + if (iMbNumLeft <= 0) { // error due to we can not support slice_skip now yet, do not adjust this time | |
| 288 | + assert (0); | |
| 289 | + return; | |
| 290 | + } | |
| 291 | + iRunLen[iSliceIdx] = iNumMbAssigning; | |
| 292 | +#if defined(ENABLE_TRACE_MT) | |
| 293 | + WelsLog (pCtx, WELS_LOG_DEBUG, | |
| 294 | + "[MT] DynamicAdjustSlicing(), uiSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n", | |
| 295 | + iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iNumMbAssigning); | |
| 296 | +#endif//ENABLE_TRACE_MT | |
| 297 | + ++ iSliceIdx; | |
| 298 | + iMaximalMbNum = iMbNumLeft - (kiCountSliceNum - iSliceIdx - 1) * iMinimalMbNum; // get maximal num_mb in left parts | |
| 299 | + } | |
| 300 | + iRunLen[iSliceIdx] = iMbNumLeft; | |
| 301 | +#if defined(ENABLE_TRACE_MT) | |
| 302 | + WelsLog (pCtx, WELS_LOG_DEBUG, | |
| 303 | + "[MT] DynamicAdjustSlicing(), iSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n", | |
| 304 | + iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iMbNumLeft); | |
| 305 | +#endif//ENABLE_TRACE_MT | |
| 306 | + | |
| 307 | + | |
| 308 | + if (DynamicAdjustSlicePEncCtxAll (pSliceCtx, iRunLen) == 0) { | |
| 309 | + const int32_t kiThreadNum = pCtx->pSvcParam->iCountThreadsNum; | |
| 310 | + int32_t iThreadIdx = 0; | |
| 311 | + do { | |
| 312 | +#ifdef WIN32 | |
| 313 | + WelsEventSignal (&pCtx->pSliceThreading->pUpdateMbListEvent[iThreadIdx]); | |
| 314 | +#else | |
| 315 | + WelsEventSignal (pCtx->pSliceThreading->pUpdateMbListEvent[iThreadIdx]); | |
| 316 | +#endif//WIN32 | |
| 317 | + ++ iThreadIdx; | |
| 318 | + } while (iThreadIdx < kiThreadNum); | |
| 319 | + | |
| 320 | + WelsMultipleEventsWaitAllBlocking (kiThreadNum, &pCtx->pSliceThreading->pFinUpdateMbListEvent[0]); | |
| 321 | + } | |
| 322 | +} | |
| 323 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 324 | + | |
| 325 | +#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 326 | +void ResetEnvMt (sWelsEncCtx* pCtx) { | |
| 327 | + const int16_t kiSliceCount = pCtx->iMaxSliceCount; | |
| 328 | + int32_t iIdx = 0; | |
| 329 | + | |
| 330 | + while (iIdx < kiSliceCount) { | |
| 331 | + SWelsSliceBs* pSliceBs = &pCtx->pSliceBs[iIdx]; | |
| 332 | + pSliceBs->uiBsPos = 0; | |
| 333 | + ++ iIdx; | |
| 334 | + } | |
| 335 | +} | |
| 336 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 337 | + | |
| 338 | +int32_t RequestMtResource (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, const int32_t iCountBsLen, | |
| 339 | + const int32_t iTargetSpatialBsSize) { | |
| 340 | + CMemoryAlign* pMa = NULL; | |
| 341 | + SWelsSvcCodingParam* pPara = NULL; | |
| 342 | + SSliceThreading* pSmt = NULL; | |
| 343 | + SWelsSliceBs* pSliceB = NULL; | |
| 344 | + uint8_t* pBsBase = NULL; | |
| 345 | + int32_t iNumSpatialLayers = 0; | |
| 346 | + int32_t iThreadNum = 0; | |
| 347 | + int32_t iIdx = 0; | |
| 348 | + int32_t iSliceBsBufferSize = 0; | |
| 349 | + int16_t iMaxSliceNum = 1; | |
| 350 | + | |
| 351 | + if (NULL == ppCtx || NULL == pCodingParam || NULL == *ppCtx || iCountBsLen <= 0) | |
| 352 | + return 1; | |
| 353 | + | |
| 354 | + pMa = (*ppCtx)->pMemAlign; | |
| 355 | + pPara = pCodingParam; | |
| 356 | + iNumSpatialLayers = pPara->iNumDependencyLayer; | |
| 357 | + iThreadNum = pPara->iCountThreadsNum; | |
| 358 | + iMaxSliceNum = (*ppCtx)->iMaxSliceCount; | |
| 359 | + | |
| 360 | + pSmt = (SSliceThreading*)pMa->WelsMalloc (sizeof (SSliceThreading), "SSliceThreading"); | |
| 361 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt), FreeMemorySvc (ppCtx)) | |
| 362 | + (*ppCtx)->pSliceThreading = pSmt; | |
| 363 | + pSmt->pThreadPEncCtx = (SSliceThreadPrivateData*)pMa->WelsMalloc (sizeof (SSliceThreadPrivateData) * iThreadNum, | |
| 364 | + "pThreadPEncCtx"); | |
| 365 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pThreadPEncCtx), FreeMemorySvc (ppCtx)) | |
| 366 | + pSmt->pThreadHandles = (WELS_THREAD_HANDLE*)pMa->WelsMalloc (sizeof (WELS_THREAD_HANDLE) * iThreadNum, | |
| 367 | + "pThreadHandles"); | |
| 368 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pThreadHandles), FreeMemorySvc (ppCtx)) | |
| 369 | + | |
| 370 | +#ifdef WIN32 | |
| 371 | + pSmt->pSliceCodedEvent = (WELS_EVENT*)pMa->WelsMalloc (sizeof (WELS_EVENT) * iThreadNum, "pSliceCodedEvent"); | |
| 372 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pSliceCodedEvent), FreeMemorySvc (ppCtx)) | |
| 373 | + pSmt->pReadySliceCodingEvent = (WELS_EVENT*)pMa->WelsMalloc (sizeof (WELS_EVENT) * iThreadNum, | |
| 374 | + "pReadySliceCodingEvent"); | |
| 375 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pReadySliceCodingEvent), FreeMemorySvc (ppCtx)) | |
| 376 | + pSmt->pFinSliceCodingEvent = (WELS_EVENT*)pMa->WelsMalloc (sizeof (WELS_EVENT) * iThreadNum, "pFinSliceCodingEvent"); | |
| 377 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pFinSliceCodingEvent), FreeMemorySvc (ppCtx)) | |
| 378 | +#endif//WIN32 | |
| 379 | + | |
| 380 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 381 | +#if defined(__GNUC__) | |
| 382 | + pSmt->pUpdateMbListThrdHandles = (WELS_THREAD_HANDLE*)pMa->WelsMalloc (sizeof (WELS_THREAD_HANDLE) * iThreadNum, | |
| 383 | + "pUpdateMbListThrdHandles"); | |
| 384 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pUpdateMbListThrdHandles), FreeMemorySvc (ppCtx)) | |
| 385 | +#endif//__GNUC__ | |
| 386 | +#ifdef WIN32 | |
| 387 | + pSmt->pUpdateMbListEvent = (WELS_EVENT*)pMa->WelsMalloc (sizeof (WELS_EVENT) * iThreadNum, "pUpdateMbListEvent"); | |
| 388 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pUpdateMbListEvent), FreeMemorySvc (ppCtx)) | |
| 389 | + pSmt->pFinUpdateMbListEvent = (WELS_EVENT*)pMa->WelsMalloc (sizeof (WELS_EVENT) * iThreadNum, "pFinUpdateMbListEvent"); | |
| 390 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pFinUpdateMbListEvent), FreeMemorySvc (ppCtx)) | |
| 391 | +#endif//WIN32 | |
| 392 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 393 | + | |
| 394 | +#ifdef WIN32 | |
| 395 | + pSmt->pExitEncodeEvent = (WELS_EVENT*)pMa->WelsMalloc (sizeof (WELS_EVENT) * iThreadNum, "pExitEncodeEvent"); | |
| 396 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pExitEncodeEvent), FreeMemorySvc (ppCtx)) | |
| 397 | +#endif//WIN32 | |
| 398 | + | |
| 399 | +#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 400 | + iIdx = 0; | |
| 401 | + while (iIdx < iNumSpatialLayers) { | |
| 402 | + SMulSliceOption* pMso = &pPara->sDependencyLayers[iIdx].sMso; | |
| 403 | + const int32_t kiSliceNum = pMso->sSliceArgument.iSliceNum; | |
| 404 | + if (pMso->uiSliceMode == SM_FIXEDSLCNUM_SLICE && pPara->iMultipleThreadIdc > 1 | |
| 405 | + && pPara->iMultipleThreadIdc >= kiSliceNum) { | |
| 406 | + pSmt->pSliceConsumeTime[iIdx] = (uint32_t*)pMa->WelsMallocz (kiSliceNum * sizeof (uint32_t), "pSliceConsumeTime[]"); | |
| 407 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pSliceConsumeTime[iIdx]), FreeMemorySvc (ppCtx)) | |
| 408 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 409 | + pSmt->pSliceComplexRatio[iIdx] = (float*)pMa->WelsMalloc (kiSliceNum * sizeof (float), "pSliceComplexRatio[]"); | |
| 410 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pSliceComplexRatio[iIdx]), FreeMemorySvc (ppCtx)) | |
| 411 | +#endif//TRY_SLICING_BALANCE | |
| 412 | + } else { | |
| 413 | + pSmt->pSliceConsumeTime[iIdx] = NULL; | |
| 414 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 415 | + pSmt->pSliceComplexRatio[iIdx] = NULL; | |
| 416 | +#endif//TRY_SLICING_BALANCE | |
| 417 | + } | |
| 418 | + ++ iIdx; | |
| 419 | + } | |
| 420 | + // NULL for pSliceConsumeTime[iIdx]: iIdx from iNumSpatialLayers to MAX_DEPENDENCY_LAYERS | |
| 421 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 422 | + | |
| 423 | +#ifdef MT_DEBUG | |
| 424 | + // file handle for MT debug | |
| 425 | + pSmt->pFSliceDiff = NULL; | |
| 426 | + | |
| 427 | + if (pSmt->pFSliceDiff) { | |
| 428 | + fclose (pSmt->pFSliceDiff); | |
| 429 | + pSmt->pFSliceDiff = NULL; | |
| 430 | + } | |
| 431 | +#ifdef WIN32 | |
| 432 | + pSmt->pFSliceDiff = fopen (".\\slice_time.txt", "wt+"); | |
| 433 | +#else | |
| 434 | + pSmt->pFSliceDiff = fopen ("/tmp/slice_time.txt", "wt+"); | |
| 435 | +#endif//WIN32 | |
| 436 | +#endif//MT_DEBUG | |
| 437 | + | |
| 438 | +#if defined(ENABLE_TRACE_MT) | |
| 439 | + WelsLog ((*ppCtx), WELS_LOG_INFO, "encpEncCtx= 0x%p\n", (void*) (*ppCtx)); | |
| 440 | +#endif//ENABLE_TRACE_MT | |
| 441 | + | |
| 442 | + iIdx = 0; | |
| 443 | + while (iIdx < iThreadNum) { | |
| 444 | +#ifdef __GNUC__ // for posix threading | |
| 445 | + str_t name[SEM_NAME_MAX] = {0}; | |
| 446 | + int32_t used_len = 0; | |
| 447 | + WELS_THREAD_ERROR_CODE err = 0; | |
| 448 | +#endif//__GNUC__ | |
| 449 | + pSmt->pThreadPEncCtx[iIdx].pWelsPEncCtx = (void*) (*ppCtx); | |
| 450 | + pSmt->pThreadPEncCtx[iIdx].iSliceIndex = iIdx; | |
| 451 | + pSmt->pThreadPEncCtx[iIdx].iThreadIndex = iIdx; | |
| 452 | + pSmt->pThreadHandles[iIdx] = 0; | |
| 453 | + | |
| 454 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 455 | +#ifdef WIN32 | |
| 456 | + WelsEventInit (&pSmt->pUpdateMbListEvent[iIdx]); | |
| 457 | + WelsEventInit (&pSmt->pFinUpdateMbListEvent[iIdx]); | |
| 458 | +#else | |
| 459 | + // length of semaphore name should be system constrained at least on mac 10.7 | |
| 460 | + SNPRINTF (name, SEM_NAME_MAX, "ud%d%p", iIdx, (void*) (*ppCtx)); | |
| 461 | + err = WelsEventOpen (&pSmt->pUpdateMbListEvent[iIdx], name); | |
| 462 | +#if defined(ENABLE_TRACE_MT) | |
| 463 | + WelsLog ((*ppCtx), WELS_LOG_INFO, "[MT] Open pUpdateMbListEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno); | |
| 464 | +#endif | |
| 465 | + used_len = SNPRINTF (name, SEM_NAME_MAX, "fu%d%p", iIdx, (void*) (*ppCtx)); | |
| 466 | + name[used_len] = '\0'; | |
| 467 | + err = WelsEventOpen (&pSmt->pFinUpdateMbListEvent[iIdx], name); | |
| 468 | +#if defined(ENABLE_TRACE_MT) | |
| 469 | + WelsLog ((*ppCtx), WELS_LOG_INFO, "[MT] Open pFinUpdateMbListEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno); | |
| 470 | +#endif | |
| 471 | +#endif//WIN32 | |
| 472 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 473 | + | |
| 474 | +#ifdef WIN32 | |
| 475 | + WelsEventInit (&pSmt->pSliceCodedEvent[iIdx]); | |
| 476 | + WelsEventInit (&pSmt->pReadySliceCodingEvent[iIdx]); | |
| 477 | + WelsEventInit (&pSmt->pFinSliceCodingEvent[iIdx]); | |
| 478 | + WelsEventInit (&pSmt->pExitEncodeEvent[iIdx]); | |
| 479 | +#else | |
| 480 | + used_len = SNPRINTF (name, SEM_NAME_MAX, "sc%d%p", iIdx, (void*) (*ppCtx)); | |
| 481 | + name[used_len] = '\0'; | |
| 482 | + err = WelsEventOpen (&pSmt->pSliceCodedEvent[iIdx], name); | |
| 483 | +#if defined(ENABLE_TRACE_MT) | |
| 484 | + WelsLog ((*ppCtx), WELS_LOG_INFO, "[MT] Open pSliceCodedEvent%d named(%s) ret%d err%d\n", iIdx, name, err, errno); | |
| 485 | +#endif | |
| 486 | + used_len = SNPRINTF (name, SEM_NAME_MAX, "rc%d%p", iIdx, (void*) (*ppCtx)); | |
| 487 | + name[used_len] = '\0'; | |
| 488 | + err = WelsEventOpen (&pSmt->pReadySliceCodingEvent[iIdx], name); | |
| 489 | +#if defined(ENABLE_TRACE_MT) | |
| 490 | + WelsLog ((*ppCtx), WELS_LOG_INFO, "[MT] Open pReadySliceCodingEvent%d = 0x%p named(%s) ret%d err%d\n", iIdx, | |
| 491 | + (void*)pSmt->pReadySliceCodingEvent[iIdx]), (void*) (*ppCtx), err, errno); | |
| 492 | +#endif | |
| 493 | +#endif//WIN32 | |
| 494 | + | |
| 495 | + ++ iIdx; | |
| 496 | + } | |
| 497 | + | |
| 498 | +#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 499 | + pSmt->pCountBsSizeInPartition = (uint32_t*)pMa->WelsMalloc (sizeof (uint32_t) * iThreadNum, "pCountBsSizeInPartition"); | |
| 500 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pCountBsSizeInPartition), FreeMemorySvc (ppCtx)) | |
| 501 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 502 | + | |
| 503 | + WelsMutexInit (&pSmt->mutexSliceNumUpdate); | |
| 504 | + | |
| 505 | + (*ppCtx)->pSliceBs = (SWelsSliceBs*)pMa->WelsMalloc (sizeof (SWelsSliceBs) * iMaxSliceNum, "pSliceBs"); | |
| 506 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSliceBs), FreeMemorySvc (ppCtx)) | |
| 507 | + | |
| 508 | + pBsBase = (*ppCtx)->pFrameBs + iCountBsLen; | |
| 509 | + pSliceB = (*ppCtx)->pSliceBs; | |
| 510 | + iSliceBsBufferSize = iTargetSpatialBsSize; | |
| 511 | + iIdx = 0; | |
| 512 | + while (iIdx < iMaxSliceNum) { | |
| 513 | + pSliceB->pBsBuffer = (uint8_t*)pMa->WelsMalloc (iSliceBsBufferSize, "pSliceB->pBsBuffer"); | |
| 514 | + | |
| 515 | + WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSliceB->pBsBuffer), FreeMemorySvc (ppCtx)) | |
| 516 | + pSliceB->uiSize = iSliceBsBufferSize; | |
| 517 | + | |
| 518 | + if (iIdx > 0) { | |
| 519 | + pSliceB->pBs = pBsBase; | |
| 520 | + pSliceB->uiBsPos = 0; | |
| 521 | + pBsBase += iSliceBsBufferSize; | |
| 522 | + } else { | |
| 523 | + pSliceB->pBs = NULL; | |
| 524 | + pSliceB->uiBsPos = 0; | |
| 525 | + } | |
| 526 | + ++ pSliceB; | |
| 527 | + ++ iIdx; | |
| 528 | + } | |
| 529 | + | |
| 530 | +#if defined(ENABLE_TRACE_MT) | |
| 531 | + WelsLog ((*ppCtx), WELS_LOG_INFO, "RequestMtResource(), iThreadNum=%d, iCountSliceNum= %d\n", pPara->iCountThreadsNum, | |
| 532 | + iMaxSliceNum); | |
| 533 | +#endif | |
| 534 | + | |
| 535 | + return 0; | |
| 536 | +} | |
| 537 | + | |
| 538 | +void ReleaseMtResource (sWelsEncCtx** ppCtx) { | |
| 539 | + SWelsSliceBs* pSliceB = NULL; | |
| 540 | + SWelsSvcCodingParam* pCodingParam = NULL; | |
| 541 | + SSliceThreading* pSmt = NULL; | |
| 542 | + CMemoryAlign* pMa = NULL; | |
| 543 | + int32_t iIdx = 0; | |
| 544 | + int32_t iThreadNum = 0; | |
| 545 | + int16_t uiSliceNum = 0; | |
| 546 | + | |
| 547 | + if (NULL == ppCtx || NULL == *ppCtx) | |
| 548 | + return; | |
| 549 | + | |
| 550 | + pMa = (*ppCtx)->pMemAlign; | |
| 551 | + pCodingParam = (*ppCtx)->pSvcParam; | |
| 552 | + uiSliceNum = (*ppCtx)->iMaxSliceCount; | |
| 553 | + iThreadNum = (*ppCtx)->pSvcParam->iCountThreadsNum; | |
| 554 | + pSmt = (*ppCtx)->pSliceThreading; | |
| 555 | + | |
| 556 | + if (NULL == pSmt) | |
| 557 | + return; | |
| 558 | + | |
| 559 | + while (iIdx < iThreadNum) { | |
| 560 | +#ifdef WIN32 | |
| 561 | + if (pSmt->pThreadHandles != NULL && pSmt->pThreadHandles[iIdx] != NULL) | |
| 562 | + WelsThreadDestroy (&pSmt->pThreadHandles[iIdx]); | |
| 563 | + | |
| 564 | + if (pSmt->pSliceCodedEvent != NULL) | |
| 565 | + WelsEventDestroy (&pSmt->pSliceCodedEvent[iIdx]); | |
| 566 | + if (pSmt->pReadySliceCodingEvent != NULL) | |
| 567 | + WelsEventDestroy (&pSmt->pReadySliceCodingEvent[iIdx]); | |
| 568 | + if (pSmt->pFinSliceCodingEvent != NULL) | |
| 569 | + WelsEventDestroy (&pSmt->pFinSliceCodingEvent[iIdx]); | |
| 570 | + if (pSmt->pExitEncodeEvent != NULL) | |
| 571 | + WelsEventDestroy (&pSmt->pExitEncodeEvent[iIdx]); | |
| 572 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 573 | + if (pSmt->pUpdateMbListEvent != NULL) | |
| 574 | + WelsEventDestroy (&pSmt->pUpdateMbListEvent[iIdx]); | |
| 575 | + if (pSmt->pFinUpdateMbListEvent != NULL) | |
| 576 | + WelsEventDestroy (&pSmt->pFinUpdateMbListEvent[iIdx]); | |
| 577 | +#endif//DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE | |
| 578 | +#else | |
| 579 | + str_t ename[SEM_NAME_MAX] = {0}; | |
| 580 | + int32_t used_len = 0; | |
| 581 | + // length of semaphore name should be system constrained at least on mac 10.7 | |
| 582 | + SNPRINTF (ename, SEM_NAME_MAX, "sc%d%p", iIdx, (void*) (*ppCtx)); | |
| 583 | + WelsEventClose (pSmt->pSliceCodedEvent[iIdx], ename); | |
| 584 | + used_len = SNPRINTF (ename, SEM_NAME_MAX, "rc%d%p", iIdx, (void*) (*ppCtx)); | |
| 585 | + ename[used_len] = '\0'; | |
| 586 | + WelsEventClose (pSmt->pReadySliceCodingEvent[iIdx], ename); | |
| 587 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 588 | + used_len = SNPRINTF (ename, SEM_NAME_MAX, "ud%d%p", iIdx, (void*) (*ppCtx)); | |
| 589 | + ename[used_len] = '\0'; | |
| 590 | + WelsEventClose (pSmt->pUpdateMbListEvent[iIdx], ename); | |
| 591 | + used_len = SNPRINTF (ename, SEM_NAME_MAX, "fu%d%p", iIdx, (void*) (*ppCtx)); | |
| 592 | + ename[used_len] = '\0'; | |
| 593 | + WelsEventClose (pSmt->pFinUpdateMbListEvent[iIdx], ename); | |
| 594 | +#endif//DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE | |
| 595 | +#endif//WIN32 | |
| 596 | + | |
| 597 | + ++ iIdx; | |
| 598 | + } | |
| 599 | + | |
| 600 | +#ifdef WIN32 | |
| 601 | + if (pSmt->pExitEncodeEvent != NULL) { | |
| 602 | + pMa->WelsFree (pSmt->pExitEncodeEvent, "pExitEncodeEvent"); | |
| 603 | + pSmt->pExitEncodeEvent = NULL; | |
| 604 | + } | |
| 605 | + if (pSmt->pSliceCodedEvent != NULL) { | |
| 606 | + pMa->WelsFree (pSmt->pSliceCodedEvent, "pSliceCodedEvent"); | |
| 607 | + pSmt->pSliceCodedEvent = NULL; | |
| 608 | + } | |
| 609 | + if (pSmt->pReadySliceCodingEvent != NULL) { | |
| 610 | + pMa->WelsFree (pSmt->pReadySliceCodingEvent, "pReadySliceCodingEvent"); | |
| 611 | + pSmt->pReadySliceCodingEvent = NULL; | |
| 612 | + } | |
| 613 | + if (pSmt->pFinSliceCodingEvent != NULL) { | |
| 614 | + pMa->WelsFree (pSmt->pFinSliceCodingEvent, "pFinSliceCodingEvent"); | |
| 615 | + pSmt->pFinSliceCodingEvent = NULL; | |
| 616 | + } | |
| 617 | +#endif//WIN32 | |
| 618 | + | |
| 619 | +#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 620 | + if (NULL != pSmt->pCountBsSizeInPartition) { | |
| 621 | + pMa->WelsFree (pSmt->pCountBsSizeInPartition, "pCountBsSizeInPartition"); | |
| 622 | + pSmt->pCountBsSizeInPartition = NULL; | |
| 623 | + } | |
| 624 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 625 | + WelsMutexDestroy (&pSmt->mutexSliceNumUpdate); | |
| 626 | + | |
| 627 | + if (pSmt->pThreadPEncCtx != NULL) { | |
| 628 | + pMa->WelsFree (pSmt->pThreadPEncCtx, "pThreadPEncCtx"); | |
| 629 | + pSmt->pThreadPEncCtx = NULL; | |
| 630 | + } | |
| 631 | + if (pSmt->pThreadHandles != NULL) { | |
| 632 | + pMa->WelsFree (pSmt->pThreadHandles, "pThreadHandles"); | |
| 633 | + pSmt->pThreadHandles = NULL; | |
| 634 | + } | |
| 635 | + | |
| 636 | + pSliceB = (*ppCtx)->pSliceBs; | |
| 637 | + iIdx = 0; | |
| 638 | + while (pSliceB != NULL && iIdx < uiSliceNum) { | |
| 639 | + if (pSliceB->pBsBuffer) { | |
| 640 | + pMa->WelsFree (pSliceB->pBsBuffer, "pSliceB->pBsBuffer"); | |
| 641 | + pSliceB->pBsBuffer = NULL; | |
| 642 | + pSliceB->uiSize = 0; | |
| 643 | + } | |
| 644 | + ++ iIdx; | |
| 645 | + ++ pSliceB; | |
| 646 | + } | |
| 647 | + if ((*ppCtx)->pSliceBs != NULL) { | |
| 648 | + pMa->WelsFree ((*ppCtx)->pSliceBs, "pSliceBs"); | |
| 649 | + (*ppCtx)->pSliceBs = NULL; | |
| 650 | + } | |
| 651 | +#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 652 | + if (pSmt->pSliceConsumeTime != NULL) { | |
| 653 | + iIdx = 0; | |
| 654 | + while (iIdx < pCodingParam->iNumDependencyLayer) { | |
| 655 | + if (pSmt->pSliceConsumeTime[iIdx]) { | |
| 656 | + pMa->WelsFree (pSmt->pSliceConsumeTime[iIdx], "pSliceConsumeTime[]"); | |
| 657 | + pSmt->pSliceConsumeTime[iIdx] = NULL; | |
| 658 | + } | |
| 659 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 660 | + if (pSmt->pSliceComplexRatio[iIdx] != NULL) { | |
| 661 | + pMa->WelsFree (pSmt->pSliceComplexRatio[iIdx], "pSliceComplexRatio[]"); | |
| 662 | + pSmt->pSliceComplexRatio[iIdx] = NULL; | |
| 663 | + } | |
| 664 | +#endif//TRY_SLICING_BALANCE | |
| 665 | + ++ iIdx; | |
| 666 | + } | |
| 667 | + } | |
| 668 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 669 | + | |
| 670 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 671 | + | |
| 672 | +#ifdef WIN32 | |
| 673 | + if (pSmt->pUpdateMbListEvent != NULL) { | |
| 674 | + pMa->WelsFree (pSmt->pUpdateMbListEvent, "pUpdateMbListEvent"); | |
| 675 | + pSmt->pUpdateMbListEvent = NULL; | |
| 676 | + } | |
| 677 | + if (pSmt->pFinUpdateMbListEvent != NULL) { | |
| 678 | + pMa->WelsFree (pSmt->pFinUpdateMbListEvent, "pFinUpdateMbListEvent"); | |
| 679 | + pSmt->pFinUpdateMbListEvent = NULL; | |
| 680 | + } | |
| 681 | +#else | |
| 682 | + if (pSmt->pUpdateMbListThrdHandles) { | |
| 683 | + pMa->WelsFree (pSmt->pUpdateMbListThrdHandles, "pUpdateMbListThrdHandles"); | |
| 684 | + pSmt->pUpdateMbListThrdHandles = NULL; | |
| 685 | + } | |
| 686 | +#endif//WIN32 | |
| 687 | + | |
| 688 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 689 | + | |
| 690 | +#ifdef MT_DEBUG | |
| 691 | + // file handle for debug | |
| 692 | + if (pSmt->pFSliceDiff) { | |
| 693 | + fclose (pSmt->pFSliceDiff); | |
| 694 | + pSmt->pFSliceDiff = NULL; | |
| 695 | + } | |
| 696 | +#endif//MT_DEBUG | |
| 697 | + pMa->WelsFree ((*ppCtx)->pSliceThreading, "SSliceThreading"); | |
| 698 | + (*ppCtx)->pSliceThreading = NULL; | |
| 699 | +} | |
| 700 | + | |
| 701 | +int32_t AppendSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, const int32_t iSliceCount) { | |
| 702 | + SWelsSvcCodingParam* pCodingParam = pCtx->pSvcParam; | |
| 703 | + SDLayerParam* pDlp = &pCodingParam->sDependencyLayers[pCtx->uiDependencyId]; | |
| 704 | + SWelsSliceBs* pSliceBs = NULL; | |
| 705 | + const BOOL_T kbIsDynamicSlicingMode = (pDlp->sMso.uiSliceMode == SM_DYN_SLICE); | |
| 706 | + int32_t iLayerSize = 0; | |
| 707 | + int32_t iNalIdxBase = pLbi->iNalCount; | |
| 708 | + int32_t iSliceIdx = 0; | |
| 709 | + | |
| 710 | + if (!kbIsDynamicSlicingMode) { | |
| 711 | + pSliceBs = &pCtx->pSliceBs[0]; | |
| 712 | + iLayerSize = pSliceBs->uiBsPos; // assign with base pSlice first | |
| 713 | + iSliceIdx = 1; // pSlice 0 bs has been written to pFrameBs yet by now, so uiSliceIdx base should be 1 | |
| 714 | + while (iSliceIdx < iSliceCount) { | |
| 715 | + ++ pSliceBs; | |
| 716 | + if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) { | |
| 717 | + int32_t iNalIdx = 0; | |
| 718 | + const int32_t iCountNal = pSliceBs->iNalIndex; | |
| 719 | + | |
| 720 | +#if MT_DEBUG_BS_WR | |
| 721 | + assert (pSliceBs->bSliceCodedFlag); | |
| 722 | +#endif//MT_DEBUG_BS_WR | |
| 723 | + | |
| 724 | + memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage | |
| 725 | + pCtx->iPosBsBuffer += pSliceBs->uiBsPos; | |
| 726 | + | |
| 727 | + iLayerSize += pSliceBs->uiBsPos; | |
| 728 | + | |
| 729 | + while (iNalIdx < iCountNal) { | |
| 730 | + pLbi->iNalLengthInByte[iNalIdxBase + iNalIdx] = pSliceBs->iNalLen[iNalIdx]; | |
| 731 | + ++ iNalIdx; | |
| 732 | + } | |
| 733 | + pLbi->iNalCount += iCountNal; | |
| 734 | + iNalIdxBase += iCountNal; | |
| 735 | + } | |
| 736 | + ++ iSliceIdx; | |
| 737 | + } | |
| 738 | + } else { // for SM_DYN_SLICE | |
| 739 | + const int32_t kiPartitionCnt = iSliceCount; | |
| 740 | + int32_t iPartitionIdx = 0; | |
| 741 | + | |
| 742 | + // due partition_0 has been written to pFrameBsBuffer | |
| 743 | + // so iLayerSize need add it | |
| 744 | + while (iPartitionIdx < kiPartitionCnt) { | |
| 745 | + const int32_t kiCountSlicesCoded = pCtx->pCurDqLayer->pNumSliceCodedOfPartition[iPartitionIdx]; | |
| 746 | + int32_t iIdx = 0; | |
| 747 | + | |
| 748 | + iSliceIdx = iPartitionIdx; | |
| 749 | + while (iIdx < kiCountSlicesCoded) { | |
| 750 | + pSliceBs = &pCtx->pSliceBs[iSliceIdx]; | |
| 751 | + if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) { | |
| 752 | + if (iPartitionIdx > 0) { | |
| 753 | + int32_t iNalIdx = 0; | |
| 754 | + const int32_t iCountNal = pSliceBs->iNalIndex; | |
| 755 | + | |
| 756 | + memmove (pCtx->pFrameBs + pCtx->iPosBsBuffer, pSliceBs->pBs, pSliceBs->uiBsPos); // confirmed_safe_unsafe_usage | |
| 757 | + pCtx->iPosBsBuffer += pSliceBs->uiBsPos; | |
| 758 | + | |
| 759 | + iLayerSize += pSliceBs->uiBsPos; | |
| 760 | + | |
| 761 | + while (iNalIdx < iCountNal) { | |
| 762 | + pLbi->iNalLengthInByte[iNalIdxBase + iNalIdx] = pSliceBs->iNalLen[iNalIdx]; | |
| 763 | + ++ iNalIdx; | |
| 764 | + } | |
| 765 | + pLbi->iNalCount += iCountNal; | |
| 766 | + iNalIdxBase += iCountNal; | |
| 767 | + } else { | |
| 768 | + iLayerSize += pSliceBs->uiBsPos; | |
| 769 | + } | |
| 770 | + } | |
| 771 | + | |
| 772 | + iSliceIdx += kiPartitionCnt; | |
| 773 | + ++ iIdx; | |
| 774 | + } | |
| 775 | + ++ iPartitionIdx; | |
| 776 | + } | |
| 777 | + } | |
| 778 | + | |
| 779 | + return iLayerSize; | |
| 780 | +} | |
| 781 | + | |
| 782 | +int32_t WriteSliceToFrameBs (sWelsEncCtx* pCtx, SLayerBSInfo* pLbi, uint8_t* pFrameBsBuffer, const int32_t iSliceIdx) { | |
| 783 | + SWelsSliceBs* pSliceBs = &pCtx->pSliceBs[iSliceIdx]; | |
| 784 | + SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; | |
| 785 | + uint8_t* pDst = pFrameBsBuffer; | |
| 786 | + int32_t pNalLen[2]; | |
| 787 | + int32_t iSliceSize = 0; | |
| 788 | + const int32_t kiNalCnt = pSliceBs->iNalIndex; | |
| 789 | + int32_t iNalIdx = 0; | |
| 790 | +#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 791 | + const int32_t iFirstSlice = (iSliceIdx == 0); | |
| 792 | + int32_t iNalBase = iFirstSlice ? 0 : pLbi->iNalCount; | |
| 793 | +#else | |
| 794 | + int32_t iNalBase = 0; | |
| 795 | +#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 796 | + | |
| 797 | + while (iNalIdx < kiNalCnt) { | |
| 798 | + iSliceSize += WelsEncodeNalExt (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pDst, &pNalLen[iNalIdx]); | |
| 799 | + pDst += pNalLen[iNalIdx]; | |
| 800 | + pLbi->iNalLengthInByte[iNalBase + iNalIdx] = pNalLen[iNalIdx]; | |
| 801 | + | |
| 802 | + ++ iNalIdx; | |
| 803 | + } | |
| 804 | + | |
| 805 | +#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 806 | + pSliceBs->uiBsPos = iSliceSize; | |
| 807 | + if (iFirstSlice) { | |
| 808 | + // pBsBuffer has been updated at coding_slice_0_in_encoder_mother_thread() | |
| 809 | + pLbi->uiLayerType = VIDEO_CODING_LAYER; | |
| 810 | + pLbi->uiSpatialId = pNalHdrExt->uiDependencyId; | |
| 811 | + pLbi->uiTemporalId = pNalHdrExt->uiTemporalId; | |
| 812 | + pLbi->uiQualityId = 0; | |
| 813 | + pLbi->uiPriorityId = 0; | |
| 814 | + pLbi->iNalCount = kiNalCnt; | |
| 815 | + } else { | |
| 816 | + pLbi->iNalCount += kiNalCnt; | |
| 817 | + } | |
| 818 | +#else | |
| 819 | + pLbi->uiLayerType = VIDEO_CODING_LAYER; | |
| 820 | + pLbi->uiSpatialId = pNalHdrExt->uiDependencyId; | |
| 821 | + pLbi->uiTemporalId = pNalHdrExt->uiTemporalId; | |
| 822 | + pLbi->uiQualityId = 0; | |
| 823 | + pLbi->uiPriorityId = 0; | |
| 824 | + pLbi->iNalCount = kiNalCnt; | |
| 825 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 826 | + | |
| 827 | + return iSliceSize; | |
| 828 | +} | |
| 829 | + | |
| 830 | +int32_t WriteSliceBs (sWelsEncCtx* pCtx, uint8_t* pSliceBsBuf, const int32_t iSliceIdx) { | |
| 831 | + SWelsSliceBs* pSliceBs = &pCtx->pSliceBs[iSliceIdx]; | |
| 832 | + SNalUnitHeaderExt* pNalHdrExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; | |
| 833 | + uint8_t* pDst = pSliceBsBuf; | |
| 834 | + int32_t* pNalLen = &pSliceBs->iNalLen[0]; | |
| 835 | + int32_t iSliceSize = 0; | |
| 836 | + const int32_t kiNalCnt = pSliceBs->iNalIndex; | |
| 837 | + int32_t iNalIdx = 0; | |
| 838 | + | |
| 839 | + assert (kiNalCnt <= 2); | |
| 840 | + if (kiNalCnt > 2) | |
| 841 | + return 0; | |
| 842 | + | |
| 843 | + while (iNalIdx < kiNalCnt) { | |
| 844 | + iSliceSize += WelsEncodeNalExt (&pSliceBs->sNalList[iNalIdx], pNalHdrExt, pDst, &pNalLen[iNalIdx]); | |
| 845 | + pDst += pNalLen[iNalIdx]; | |
| 846 | + | |
| 847 | + ++ iNalIdx; | |
| 848 | + } | |
| 849 | + pSliceBs->uiBsPos = iSliceSize; | |
| 850 | + | |
| 851 | + return iSliceSize; | |
| 852 | +} | |
| 853 | + | |
| 854 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 855 | +#if defined(__GNUC__) | |
| 856 | +WELS_THREAD_ROUTINE_TYPE UpdateMbListThreadProc (void* arg) { | |
| 857 | + SSliceThreadPrivateData* pPrivateData = (SSliceThreadPrivateData*)arg; | |
| 858 | + sWelsEncCtx* pEncPEncCtx = NULL; | |
| 859 | + SDqLayer* pCurDq = NULL; | |
| 860 | + int32_t iSliceIdx = -1; | |
| 861 | + int32_t iEventIdx = -1; | |
| 862 | + WELS_THREAD_ERROR_CODE iWaitRet = WELS_THREAD_ERROR_GENERIAL; | |
| 863 | + uint32_t uiThrdRet = 0; | |
| 864 | + | |
| 865 | + if (NULL == pPrivateData) | |
| 866 | + WELS_THREAD_ROUTINE_RETURN (1); | |
| 867 | + | |
| 868 | + pEncPEncCtx = (sWelsEncCtx*)pPrivateData->pWelsPEncCtx; | |
| 869 | + iSliceIdx = pPrivateData->iSliceIndex; | |
| 870 | + iEventIdx = pPrivateData->iThreadIndex; | |
| 871 | + | |
| 872 | + do { | |
| 873 | +#if defined(ENABLE_TRACE_MT) | |
| 874 | + WelsLog (pEncPEncCtx, WELS_LOG_INFO, "[MT] UpdateMbListThreadProc(), try to wait (pUpdateMbListEvent[%d])!\n", | |
| 875 | + iEventIdx); | |
| 876 | +#endif | |
| 877 | + iWaitRet = WelsEventWait (pEncPEncCtx->pSliceThreading->pUpdateMbListEvent[iEventIdx]); | |
| 878 | + if (WELS_THREAD_ERROR_WAIT_OBJECT_0 == iWaitRet) { | |
| 879 | + pCurDq = pEncPEncCtx->pCurDqLayer; | |
| 880 | + UpdateMbListNeighborParallel (pCurDq->pSliceEncCtx, pCurDq->sMbDataP, iSliceIdx); | |
| 881 | + WelsEventSignal ( | |
| 882 | + pEncPEncCtx->pSliceThreading->pFinUpdateMbListEvent[iEventIdx]); // mean finished update pMb list for this pSlice | |
| 883 | + } else { | |
| 884 | + WelsLog (pEncPEncCtx, WELS_LOG_WARNING, | |
| 885 | + "[MT] UpdateMbListThreadProc(), waiting pUpdateMbListEvent[%d] failed(%d) and thread%d terminated!\n", iEventIdx, | |
| 886 | + iWaitRet, iEventIdx); | |
| 887 | + uiThrdRet = 1; | |
| 888 | + break; | |
| 889 | + } | |
| 890 | + } while (1); | |
| 891 | + | |
| 892 | + WELS_THREAD_ROUTINE_RETURN (uiThrdRet); | |
| 893 | +} | |
| 894 | +#endif//__GNUC__ | |
| 895 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 896 | + | |
| 897 | +// thread process for coding one pSlice | |
| 898 | +WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) { | |
| 899 | + SSliceThreadPrivateData* pPrivateData = (SSliceThreadPrivateData*)arg; | |
| 900 | + sWelsEncCtx* pEncPEncCtx = NULL; | |
| 901 | + SDqLayer* pCurDq = NULL; | |
| 902 | + SSlice* pSlice = NULL; | |
| 903 | + SWelsSliceBs* pSliceBs = NULL; | |
| 904 | +#ifdef WIN32 | |
| 905 | + WELS_EVENT pEventsList[3]; | |
| 906 | + int32_t iEventCount = 0; | |
| 907 | +#endif | |
| 908 | + WELS_THREAD_ERROR_CODE iWaitRet = WELS_THREAD_ERROR_GENERIAL; | |
| 909 | + uint32_t uiThrdRet = 0; | |
| 910 | + int32_t iSliceSize = 0; | |
| 911 | + int32_t iSliceIdx = -1; | |
| 912 | + int32_t iThreadIdx = -1; | |
| 913 | + int32_t iEventIdx = -1; | |
| 914 | + bool_t bNeedPrefix = false; | |
| 915 | + EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; | |
| 916 | + EWelsNalRefIdc eNalRefIdc = NRI_PRI_LOWEST; | |
| 917 | + | |
| 918 | + if (NULL == pPrivateData) | |
| 919 | + WELS_THREAD_ROUTINE_RETURN (1); | |
| 920 | + | |
| 921 | + WelsSetThreadCancelable(); | |
| 922 | + | |
| 923 | + pEncPEncCtx = (sWelsEncCtx*)pPrivateData->pWelsPEncCtx; | |
| 924 | + | |
| 925 | + iThreadIdx = pPrivateData->iThreadIndex; | |
| 926 | + iEventIdx = iThreadIdx; | |
| 927 | + | |
| 928 | +#ifdef WIN32 | |
| 929 | + pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pReadySliceCodingEvent[iEventIdx]; | |
| 930 | + pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pExitEncodeEvent[iEventIdx]; | |
| 931 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 932 | + pEventsList[iEventCount++] = pEncPEncCtx->pSliceThreading->pUpdateMbListEvent[iEventIdx]; | |
| 933 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 934 | +#endif//WIN32 | |
| 935 | + | |
| 936 | + do { | |
| 937 | +#ifdef WIN32 | |
| 938 | + iWaitRet = WelsMultipleEventsWaitSingleBlocking (iEventCount, | |
| 939 | + &pEventsList[0], | |
| 940 | + (uint32_t) - 1); // blocking until at least one event is | |
| 941 | +#else | |
| 942 | +#if defined(ENABLE_TRACE_MT) | |
| 943 | + WelsLog (pEncPEncCtx, WELS_LOG_INFO, | |
| 944 | + "[MT] CodingSliceThreadProc(), try to call WelsEventWait(pReadySliceCodingEvent[%d]= 0x%p), pEncPEncCtx= 0x%p!\n", | |
| 945 | + iEventIdx, (void*) (pEncPEncCtx->pReadySliceCodingEvent[iEventIdx]), (void*)pEncPEncCtx); | |
| 946 | +#endif | |
| 947 | + iWaitRet = WelsEventWait (pEncPEncCtx->pSliceThreading->pReadySliceCodingEvent[iEventIdx]); | |
| 948 | +#endif//WIN32 | |
| 949 | + if (WELS_THREAD_ERROR_WAIT_OBJECT_0 == iWaitRet) { // start pSlice coding signal waited | |
| 950 | + SLayerBSInfo* pLbi = pPrivateData->pLayerBs; | |
| 951 | + const int32_t kiCurDid = pEncPEncCtx->uiDependencyId; | |
| 952 | + const int32_t kiCurTid = pEncPEncCtx->uiTemporalId; | |
| 953 | + SWelsSvcCodingParam* pCodingParam = pEncPEncCtx->pSvcParam; | |
| 954 | + SDLayerParam* pParamD = &pCodingParam->sDependencyLayers[kiCurDid]; | |
| 955 | + | |
| 956 | + pCurDq = pEncPEncCtx->pCurDqLayer; | |
| 957 | + eNalType = pEncPEncCtx->eNalType; | |
| 958 | + eNalRefIdc = pEncPEncCtx->eNalPriority; | |
| 959 | + bNeedPrefix = pEncPEncCtx->bNeedPrefixNalFlag; | |
| 960 | + | |
| 961 | + if (pParamD->sMso.uiSliceMode != SM_DYN_SLICE) { | |
| 962 | + int64_t iSliceStart = 0; | |
| 963 | + bool_t bDsaFlag = false; | |
| 964 | + iSliceIdx = pPrivateData->iSliceIndex; | |
| 965 | + pSlice = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 966 | + pSliceBs = &pEncPEncCtx->pSliceBs[iSliceIdx]; | |
| 967 | + | |
| 968 | +#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 969 | + bDsaFlag = (pParamD->sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && | |
| 970 | + pCodingParam->iMultipleThreadIdc > 1 && | |
| 971 | + pCodingParam->iMultipleThreadIdc >= pParamD->sMso.sSliceArgument.iSliceNum); | |
| 972 | + if (bDsaFlag) | |
| 973 | + iSliceStart = WelsTime(); | |
| 974 | +#endif//DYNAMIC_SLICE_ASSIGN || MT_DEBUG | |
| 975 | + | |
| 976 | +#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 977 | + pSliceBs->uiBsPos = 0; | |
| 978 | +#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 979 | + pSliceBs->iNalIndex = 0; | |
| 980 | + assert ((void*) (&pSliceBs->sBsWrite) == (void*)pSlice->pSliceBsa); | |
| 981 | + InitBits (&pSliceBs->sBsWrite, pSliceBs->pBsBuffer, pSliceBs->uiSize); | |
| 982 | + | |
| 983 | +#if MT_DEBUG_BS_WR | |
| 984 | + pSliceBs->bSliceCodedFlag = FALSE; | |
| 985 | +#endif//MT_DEBUG_BS_WR | |
| 986 | + | |
| 987 | + if (bNeedPrefix) { | |
| 988 | + if (eNalRefIdc != NRI_PRI_LOWEST) { | |
| 989 | + WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc); | |
| 990 | + WelsWriteSVCPrefixNal (&pSliceBs->sBsWrite, eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == eNalType)); | |
| 991 | + WelsUnloadNalForSlice (pSliceBs); | |
| 992 | + } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension | |
| 993 | + WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc); | |
| 994 | + // No need write any syntax of prefix NAL Unit RBSP here | |
| 995 | + WelsUnloadNalForSlice (pSliceBs); | |
| 996 | + } | |
| 997 | + } | |
| 998 | + | |
| 999 | + WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc); | |
| 1000 | + | |
| 1001 | + WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType); | |
| 1002 | + | |
| 1003 | + WelsUnloadNalForSlice (pSliceBs); | |
| 1004 | + | |
| 1005 | +#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1006 | + if (0 == iSliceIdx) { | |
| 1007 | + pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1008 | + iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx); | |
| 1009 | + pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1010 | + } else | |
| 1011 | + iSliceSize = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx); | |
| 1012 | +#else// PACKING_ONE_SLICE_PER_LAYER | |
| 1013 | + if (0 == iSliceIdx) { | |
| 1014 | + pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1015 | + iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx); | |
| 1016 | + pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1017 | + } else { | |
| 1018 | + pLbi->pBsBuf = pSliceBs->bs + pSliceBs->uiBsPos; | |
| 1019 | + iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pLbi->pBsBuf, iSliceIdx); | |
| 1020 | + pSliceBs->uiBsPos += iSliceSize; | |
| 1021 | + } | |
| 1022 | +#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1023 | + | |
| 1024 | + if (pCurDq->bDeblockingParallelFlag && pSlice->sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc != 1 | |
| 1025 | +#if !defined(ENABLE_FRAME_DUMP) | |
| 1026 | + && (eNalRefIdc != NRI_PRI_LOWEST) && | |
| 1027 | + (pParamD->iHighestTemporalId == 0 || kiCurTid < pParamD->iHighestTemporalId) | |
| 1028 | +#endif// !ENABLE_FRAME_DUMP | |
| 1029 | + ) { | |
| 1030 | + DeblockingFilterSliceAvcbase (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx); | |
| 1031 | + } | |
| 1032 | + | |
| 1033 | +#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 1034 | + if (bDsaFlag) { | |
| 1035 | + pEncPEncCtx->pSliceThreading->pSliceConsumeTime[pEncPEncCtx->uiDependencyId][iSliceIdx] = (uint32_t) ( | |
| 1036 | + WelsTime() - iSliceStart); | |
| 1037 | +#if defined(ENABLE_TRACE_MT) | |
| 1038 | + WelsLog (pEncPEncCtx, WELS_LOG_INFO, | |
| 1039 | + "[MT] CodingSliceThreadProc(), coding_idx %d, uiSliceIdx %d, pSliceConsumeTime %d, iSliceSize %d, pFirstMbInSlice %d, count_num_mb_in_slice %d\n", | |
| 1040 | + pEncPEncCtx->iCodingIndex, iSliceIdx, | |
| 1041 | + pEncPEncCtx->pSliceThreading->pSliceConsumeTime[pEncPEncCtx->uiDependencyId][iSliceIdx], iSliceSize, | |
| 1042 | + pCurDq->pSliceEncCtx->pFirstMbInSlice[iSliceIdx], pCurDq->pSliceEncCtx->pCountMbNumInSlice[iSliceIdx]); | |
| 1043 | +#endif//ENABLE_TRACE_MT | |
| 1044 | + } | |
| 1045 | +#endif//DYNAMIC_SLICE_ASSIGN || MT_DEBUG | |
| 1046 | + | |
| 1047 | +#if defined(SLICE_INFO_OUTPUT) | |
| 1048 | + fprintf (stderr, | |
| 1049 | + "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n", | |
| 1050 | + iSliceIdx, | |
| 1051 | + (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'), | |
| 1052 | + eNalRefIdc, | |
| 1053 | + iSliceSize | |
| 1054 | + ); | |
| 1055 | +#endif//SLICE_INFO_OUTPUT | |
| 1056 | + | |
| 1057 | +#if MT_DEBUG_BS_WR | |
| 1058 | + pSliceBs->bSliceCodedFlag = TRUE; | |
| 1059 | +#endif//MT_DEBUG_BS_WR | |
| 1060 | + | |
| 1061 | +#ifdef WIN32 | |
| 1062 | + WelsEventSignal ( | |
| 1063 | + &pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice | |
| 1064 | +#else | |
| 1065 | + WelsEventSignal (pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice | |
| 1066 | +#endif//WIN32 | |
| 1067 | + } else { // for SM_DYN_SLICE parallelization | |
| 1068 | +#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 1069 | + SLayerBSInfo* pLbiPacking = NULL; | |
| 1070 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 1071 | + SSliceCtx* pSliceCtx = pCurDq->pSliceEncCtx; | |
| 1072 | + const int32_t kiPartitionId = iThreadIdx; | |
| 1073 | + const int32_t kiSliceIdxStep = pEncPEncCtx->iActiveThreadsNum; | |
| 1074 | + const int32_t kiFirstMbInPartition = pPrivateData->iStartMbIndex; // inclusive | |
| 1075 | + const int32_t kiEndMbInPartition = pPrivateData->iEndMbIndex; // exclusive | |
| 1076 | + int32_t iAnyMbLeftInPartition = kiEndMbInPartition - kiFirstMbInPartition; | |
| 1077 | + | |
| 1078 | + iSliceIdx = pPrivateData->iSliceIndex; | |
| 1079 | + | |
| 1080 | + pSliceCtx->pFirstMbInSlice[iSliceIdx] = kiFirstMbInPartition; | |
| 1081 | + pCurDq->pNumSliceCodedOfPartition[kiPartitionId] = 1; // one pSlice per partition intialized, dynamic slicing inside | |
| 1082 | + pCurDq->pLastMbIdxOfPartition[kiPartitionId] = kiEndMbInPartition - 1; | |
| 1083 | + | |
| 1084 | + pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId] = 0; | |
| 1085 | + | |
| 1086 | + while (iAnyMbLeftInPartition > 0) { | |
| 1087 | + if (iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint) { | |
| 1088 | + // TODO: need exception handler for not large enough of MAX_SLICES_NUM related memory usage | |
| 1089 | + // No idea about its solution due MAX_SLICES_NUM is fixed lenght in relevent pData structure | |
| 1090 | + uiThrdRet = 1; | |
| 1091 | + break; | |
| 1092 | + } | |
| 1093 | + | |
| 1094 | + pSlice = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx]; | |
| 1095 | + pSliceBs = &pEncPEncCtx->pSliceBs[iSliceIdx]; | |
| 1096 | + | |
| 1097 | +#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1098 | + pSliceBs->uiBsPos = 0; | |
| 1099 | +#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1100 | + pSliceBs->iNalIndex = 0; | |
| 1101 | + InitBits (&pSliceBs->sBsWrite, pSliceBs->pBsBuffer, pSliceBs->uiSize); | |
| 1102 | + | |
| 1103 | + if (bNeedPrefix) { | |
| 1104 | + if (eNalRefIdc != NRI_PRI_LOWEST) { | |
| 1105 | + WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc); | |
| 1106 | + WelsWriteSVCPrefixNal (&pSliceBs->sBsWrite, eNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == eNalType)); | |
| 1107 | + WelsUnloadNalForSlice (pSliceBs); | |
| 1108 | + } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension | |
| 1109 | + WelsLoadNalForSlice (pSliceBs, NAL_UNIT_PREFIX, eNalRefIdc); | |
| 1110 | + // No need write any syntax of prefix NAL Unit RBSP here | |
| 1111 | + WelsUnloadNalForSlice (pSliceBs); | |
| 1112 | + } | |
| 1113 | + } | |
| 1114 | + | |
| 1115 | + WelsLoadNalForSlice (pSliceBs, eNalType, eNalRefIdc); | |
| 1116 | + | |
| 1117 | + WelsCodeOneSlice (pEncPEncCtx, iSliceIdx, eNalType); | |
| 1118 | + | |
| 1119 | + WelsUnloadNalForSlice (pSliceBs); | |
| 1120 | + | |
| 1121 | +#if !defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1122 | + if (0 == kiPartitionId) { | |
| 1123 | + if (0 == iSliceIdx) | |
| 1124 | + pLbi->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1125 | + iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbi, pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer, iSliceIdx); | |
| 1126 | + pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1127 | + } else | |
| 1128 | + iSliceSize = WriteSliceBs (pEncPEncCtx, pSliceBs->pBs, iSliceIdx); | |
| 1129 | +#else// PACKING_ONE_SLICE_PER_LAYER | |
| 1130 | + pLbiPacking = pLbi + (iSliceIdx - kiPartitionId); | |
| 1131 | + | |
| 1132 | + if (0 == kiPartitionId) { | |
| 1133 | + pLbiPacking->pBsBuf = pEncPEncCtx->pFrameBs + pEncPEncCtx->iPosBsBuffer; | |
| 1134 | + iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx); | |
| 1135 | + pEncPEncCtx->iPosBsBuffer += iSliceSize; | |
| 1136 | + } else { | |
| 1137 | + pLbiPacking->pBsBuf = pSliceBs->bs + pSliceBs->uiBsPos; | |
| 1138 | + iSliceSize = WriteSliceToFrameBs (pEncPEncCtx, pLbiPacking, pLbiPacking->pBsBuf, iSliceIdx); | |
| 1139 | + pSliceBs->uiBsPos += iSliceSize; | |
| 1140 | + } | |
| 1141 | + pEncPEncCtx->pSliceThreading->pCountBsSizeInPartition[kiPartitionId] += iSliceSize; | |
| 1142 | +#endif//!PACKING_ONE_SLICE_PER_LAYER | |
| 1143 | + | |
| 1144 | + if (pCurDq->bDeblockingParallelFlag && pSlice->sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc != 1 | |
| 1145 | +#if !defined(ENABLE_FRAME_DUMP) | |
| 1146 | + && (eNalRefIdc != NRI_PRI_LOWEST) && | |
| 1147 | + (pParamD->iHighestTemporalId == 0 || kiCurTid < pParamD->iHighestTemporalId) | |
| 1148 | +#endif// !ENABLE_FRAME_DUMP | |
| 1149 | + ) { | |
| 1150 | + DeblockingFilterSliceAvcbase (pCurDq, pEncPEncCtx->pFuncList, iSliceIdx); | |
| 1151 | + } | |
| 1152 | + | |
| 1153 | +#if defined(SLICE_INFO_OUTPUT) | |
| 1154 | + fprintf (stderr, | |
| 1155 | + "@pSlice=%-6d sliceType:%c idc:%d size:%-6d\n", | |
| 1156 | + iSliceIdx, | |
| 1157 | + (pEncPEncCtx->eSliceType == P_SLICE ? 'P' : 'I'), | |
| 1158 | + eNalRefIdc, | |
| 1159 | + iSliceSize | |
| 1160 | + ); | |
| 1161 | +#endif//SLICE_INFO_OUTPUT | |
| 1162 | + | |
| 1163 | +#if defined(ENABLE_TRACE_MT) | |
| 1164 | + WelsLog (pEncPEncCtx, WELS_LOG_INFO, | |
| 1165 | + "[MT] CodingSliceThreadProc(), coding_idx %d, iPartitionId %d, uiSliceIdx %d, iSliceSize %d, count_mb_slice %d, iEndMbInPartition %d, pCurDq->pLastCodedMbIdxOfPartition[%d] %d\n", | |
| 1166 | + pEncPEncCtx->iCodingIndex, kiPartitionId, iSliceIdx, iSliceSize, pCurDq->pSliceEncCtx->pCountMbNumInSlice[iSliceIdx], | |
| 1167 | + kiEndMbInPartition, kiPartitionId, pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]); | |
| 1168 | +#endif//ENABLE_TRACE_MT | |
| 1169 | + | |
| 1170 | + iAnyMbLeftInPartition = kiEndMbInPartition - (1 + pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]); | |
| 1171 | + iSliceIdx += kiSliceIdxStep; | |
| 1172 | + } | |
| 1173 | + | |
| 1174 | + if (uiThrdRet) // any exception?? | |
| 1175 | + break; | |
| 1176 | + | |
| 1177 | +#ifdef WIN32 | |
| 1178 | + WelsEventSignal (&pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice | |
| 1179 | +#else | |
| 1180 | + WelsEventSignal (pEncPEncCtx->pSliceThreading->pSliceCodedEvent[iEventIdx]); // mean finished coding current pSlice | |
| 1181 | +#endif//WIN32 | |
| 1182 | + } | |
| 1183 | + } | |
| 1184 | +#ifdef WIN32 | |
| 1185 | + else if (WELS_THREAD_ERROR_WAIT_OBJECT_0 + 1 == iWaitRet) { // exit thread signal | |
| 1186 | + uiThrdRet = 0; | |
| 1187 | + break; | |
| 1188 | + } | |
| 1189 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1190 | + else if (WELS_THREAD_ERROR_WAIT_OBJECT_0 + 2 == iWaitRet) { // update pMb list singal | |
| 1191 | + iSliceIdx = | |
| 1192 | + iEventIdx; // pPrivateData->iSliceIndex; old threads can not be terminated, pPrivateData is not correct for applicable | |
| 1193 | + pCurDq = pEncPEncCtx->pCurDqLayer; | |
| 1194 | + UpdateMbListNeighborParallel (pCurDq->pSliceEncCtx, pCurDq->sMbDataP, iSliceIdx); | |
| 1195 | + WelsEventSignal ( | |
| 1196 | + &pEncPEncCtx->pSliceThreading->pFinUpdateMbListEvent[iEventIdx]); // mean finished update pMb list for this pSlice | |
| 1197 | + } | |
| 1198 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1199 | +#endif//WIN32 | |
| 1200 | + else { // WELS_THREAD_ERROR_WAIT_TIMEOUT, or WELS_THREAD_ERROR_WAIT_FAILED | |
| 1201 | + WelsLog (pEncPEncCtx, WELS_LOG_WARNING, | |
| 1202 | + "[MT] CodingSliceThreadProc(), waiting pReadySliceCodingEvent[%d] failed(%d) and thread%d terminated!\n", iEventIdx, | |
| 1203 | + iWaitRet, iThreadIdx); | |
| 1204 | + uiThrdRet = 1; | |
| 1205 | + break; | |
| 1206 | + } | |
| 1207 | + } while (1); | |
| 1208 | + | |
| 1209 | +#ifdef WIN32 | |
| 1210 | + WelsEventSignal (&pEncPEncCtx->pSliceThreading->pFinSliceCodingEvent[iEventIdx]); // notify to mother encoding threading | |
| 1211 | +#endif//WIN32 | |
| 1212 | + | |
| 1213 | + WELS_THREAD_ROUTINE_RETURN (uiThrdRet); | |
| 1214 | +} | |
| 1215 | + | |
| 1216 | +int32_t CreateSliceThreads (sWelsEncCtx* pCtx) { | |
| 1217 | + const int32_t kiThreadCount = pCtx->pSvcParam->iCountThreadsNum; | |
| 1218 | + int32_t iIdx = 0; | |
| 1219 | +#if defined(WIN32) && defined(BIND_CPU_CORES_TO_THREADS) | |
| 1220 | + DWORD dwProcessAffinity; | |
| 1221 | + DWORD dwSystemAffinity; | |
| 1222 | + GetProcessAffinityMask (GetCurrentProcess(), &dwProcessAffinity, &dwSystemAffinity); | |
| 1223 | +#endif//WIN32 && BIND_CPU_CORES_TO_THREADS | |
| 1224 | + | |
| 1225 | + while (iIdx < kiThreadCount) { | |
| 1226 | + WelsThreadCreate (&pCtx->pSliceThreading->pThreadHandles[iIdx], CodingSliceThreadProc, | |
| 1227 | + &pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0); | |
| 1228 | +#if defined(WIN32) && defined(BIND_CPU_CORES_TO_THREADS) | |
| 1229 | + if (dwProcessAffinity > 1 | |
| 1230 | + && pCtx->pSliceThreading->pThreadHandles[iIdx] != NULL) { // multiple cores and thread created successfully | |
| 1231 | + DWORD dw = 0; | |
| 1232 | + DWORD dwAffinityMask = 1 << iIdx; | |
| 1233 | + if (dwAffinityMask & dwProcessAffinity) { // check if cpu is available | |
| 1234 | + dw = SetThreadAffinityMask (pCtx->pSliceThreading->pThreadHandles[iIdx], dwAffinityMask); //1 << iIdx | |
| 1235 | + if (dw == 0) { | |
| 1236 | + str_t str[64] = {0}; | |
| 1237 | + SNPRINTF (str, 64, "SetThreadAffinityMask iIdx:%d", iIdx); | |
| 1238 | + } | |
| 1239 | + } | |
| 1240 | + } | |
| 1241 | +#endif//WIN32 && BIND_CPU_CORES_TO_THREADS | |
| 1242 | + // We need extra threads for update_mb_list_proc on __GNUC__ like OS (mac/linux) | |
| 1243 | + // due to WelsMultipleEventsWaitSingleBlocking implememtation can not work well | |
| 1244 | + // in case waiting pUpdateMbListEvent and pReadySliceCodingEvent events at the same time | |
| 1245 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1246 | +#if defined(__GNUC__) | |
| 1247 | + WelsThreadCreate (&pCtx->pSliceThreading->pUpdateMbListThrdHandles[iIdx], UpdateMbListThreadProc, | |
| 1248 | + &pCtx->pSliceThreading->pThreadPEncCtx[iIdx], 0); | |
| 1249 | +#endif//__GNUC__ | |
| 1250 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1251 | + ++ iIdx; | |
| 1252 | + } | |
| 1253 | +#if defined(ENABLE_TRACE_MT) | |
| 1254 | + WelsLog (pCtx, WELS_LOG_INFO, "CreateSliceThreads() exit..\n"); | |
| 1255 | +#endif | |
| 1256 | + return 0; | |
| 1257 | +} | |
| 1258 | + | |
| 1259 | +#ifdef PACKING_ONE_SLICE_PER_LAYER | |
| 1260 | +void ResetCountBsSizeInPartitions (uint32_t* pCountBsSizeList, const int32_t iPartitionCnt) { | |
| 1261 | + if (pCountBsSizeList != NULL && iPartitionCnt > 0) { | |
| 1262 | + memset (pCountBsSizeList, 0, sizeof (pCountBsSizeList[0]) * iPartitionCnt); | |
| 1263 | + } | |
| 1264 | +} | |
| 1265 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 1266 | + | |
| 1267 | +#ifdef WIN32 | |
| 1268 | +int32_t FiredSliceThreads (SSliceThreadPrivateData* pPriData, WELS_EVENT* pEventsList, SLayerBSInfo* pLbi, | |
| 1269 | + const uint32_t uiNumThreads, SSliceCtx* pSliceCtx, const BOOL_T bIsDynamicSlicingMode) | |
| 1270 | +#else | |
| 1271 | +int32_t FiredSliceThreads (SSliceThreadPrivateData* pPriData, WELS_EVENT** pEventsList, SLayerBSInfo* pLbi, | |
| 1272 | + const uint32_t uiNumThreads, SSliceCtx* pSliceCtx, const BOOL_T bIsDynamicSlicingMode) | |
| 1273 | +#endif//WIN32 | |
| 1274 | +{ | |
| 1275 | + int32_t iEndMbIdx = 0; | |
| 1276 | + int32_t iIdx = 0; | |
| 1277 | + const int32_t kiEventCnt = uiNumThreads; | |
| 1278 | + | |
| 1279 | + if (pPriData == NULL || pLbi == NULL || kiEventCnt <= 0 || pEventsList == NULL) { | |
| 1280 | + WelsLog (NULL, WELS_LOG_ERROR, | |
| 1281 | + "FiredSliceThreads(), fail due pPriData == %p || pLbi == %p || iEventCnt(%d) <= 0 || pEventsList == %p!!\n", | |
| 1282 | + (void*)pPriData, (void*)pLbi, uiNumThreads, (void*)pEventsList); | |
| 1283 | + return 1; | |
| 1284 | + } | |
| 1285 | + | |
| 1286 | +#if defined(PACKING_ONE_SLICE_PER_LAYER) | |
| 1287 | + //////////////////////////////////////// | |
| 1288 | + if (bIsDynamicSlicingMode) { | |
| 1289 | + iEndMbIdx = pSliceCtx->iMbNumInFrame; | |
| 1290 | + for (iIdx = kiEventCnt - 1; iIdx >= 0; --iIdx) { | |
| 1291 | + const int32_t kiFirstMbIdx = pSliceCtx->pFirstMbInSlice[iIdx]; | |
| 1292 | + pPriData[iIdx].iStartMbIndex = kiFirstMbIdx; | |
| 1293 | + pPriData[iIdx].iEndMbIndex = iEndMbIdx; | |
| 1294 | + iEndMbIdx = kiFirstMbIdx; | |
| 1295 | + } | |
| 1296 | + } | |
| 1297 | + | |
| 1298 | + iIdx = 0; | |
| 1299 | + while (iIdx < kiEventCnt) { | |
| 1300 | + pPriData[iIdx].pLayerBs = pLbi; | |
| 1301 | + pPriData[iIdx].iSliceIndex = iIdx; | |
| 1302 | +#ifdef WIN32 | |
| 1303 | + if (pEventsList[iIdx]) | |
| 1304 | + WelsEventSignal (&pEventsList[iIdx]); | |
| 1305 | +#else | |
| 1306 | + WelsEventSignal (pEventsList[iIdx]); | |
| 1307 | +#endif//WIN32 | |
| 1308 | + ++ pLbi; | |
| 1309 | + ++ iIdx; | |
| 1310 | + } | |
| 1311 | + //////////////////////////////////////// | |
| 1312 | +#else | |
| 1313 | + //////////////////////////////////////// | |
| 1314 | + if (bIsDynamicSlicingMode) { | |
| 1315 | + iEndMbIdx = pSliceCtx->iMbNumInFrame; | |
| 1316 | + for (iIdx = kiEventCnt - 1; iIdx >= 0; --iIdx) { | |
| 1317 | + const int32_t iFirstMbIdx = pSliceCtx->pFirstMbInSlice[iIdx]; | |
| 1318 | + pPriData[iIdx].iStartMbIndex = iFirstMbIdx; | |
| 1319 | + pPriData[iIdx].iEndMbIndex = iEndMbIdx; | |
| 1320 | + iEndMbIdx = iFirstMbIdx; | |
| 1321 | + } | |
| 1322 | + } | |
| 1323 | + | |
| 1324 | + iIdx = 0; | |
| 1325 | + while (iIdx < kiEventCnt) { | |
| 1326 | + pPriData[iIdx].pLayerBs = pLbi; | |
| 1327 | + pPriData[iIdx].iSliceIndex = iIdx; | |
| 1328 | +#ifdef WIN32 | |
| 1329 | + if (pEventsList[iIdx]) | |
| 1330 | + WelsEventSignal (&pEventsList[iIdx]); | |
| 1331 | +#else | |
| 1332 | + WelsEventSignal (pEventsList[iIdx]); | |
| 1333 | +#endif//WIN32 | |
| 1334 | + ++ iIdx; | |
| 1335 | + } | |
| 1336 | + //////////////////////////////////////// | |
| 1337 | +#endif//PACKING_ONE_SLICE_PER_LAYER | |
| 1338 | + | |
| 1339 | + return 0; | |
| 1340 | +} | |
| 1341 | + | |
| 1342 | +int32_t DynamicDetectCpuCores() { | |
| 1343 | + WelsLogicalProcessInfo info; | |
| 1344 | + WelsQueryLogicalProcessInfo (&info); | |
| 1345 | + return info.ProcessorCount; | |
| 1346 | +} | |
| 1347 | + | |
| 1348 | +#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) | |
| 1349 | + | |
| 1350 | +int32_t AdjustBaseLayer (sWelsEncCtx* pCtx) { | |
| 1351 | + SDqLayer* pCurDq = pCtx->ppDqLayerList[0]; | |
| 1352 | + int32_t iNeedAdj = 1; | |
| 1353 | +#ifdef MT_DEBUG | |
| 1354 | + int64_t iT0 = WelsTime(); | |
| 1355 | +#endif//MT_DEBUG | |
| 1356 | +#ifdef TRY_SLICING_BALANCE | |
| 1357 | + | |
| 1358 | + pCtx->pCurDqLayer = pCurDq; | |
| 1359 | + | |
| 1360 | +#ifdef NOT_ABSOLUTE_BALANCING | |
| 1361 | + // do not need adjust due to not different at both slices of consumed time | |
| 1362 | + iNeedAdj = NeedDynamicAdjust (pCtx->pSliceThreading->pSliceConsumeTime[0], pCurDq->pSliceEncCtx->iSliceNumInFrame); | |
| 1363 | + if (iNeedAdj) | |
| 1364 | +#endif//NOT_ABSOLUTE_BALANCING | |
| 1365 | + DynamicAdjustSlicing (pCtx, | |
| 1366 | + pCurDq, | |
| 1367 | + pCtx->pSliceThreading->pSliceComplexRatio[0], | |
| 1368 | + 0); | |
| 1369 | +#endif//TRY_SLICING_BALANCE | |
| 1370 | +#ifdef MT_DEBUG | |
| 1371 | + iT0 = WelsTime() - iT0; | |
| 1372 | + if (pCtx->pSliceThreading->pFSliceDiff) { | |
| 1373 | + fprintf (pCtx->pSliceThreading->pFSliceDiff, | |
| 1374 | +#ifdef WIN32 | |
| 1375 | + "%6I64d us adjust time at base spatial layer, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1376 | +#else | |
| 1377 | + "%6lld us adjust time at base spatial layer, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1378 | +#endif//WIN32 | |
| 1379 | + iT0, iNeedAdj); | |
| 1380 | + } | |
| 1381 | +#endif//MT_DEBUG | |
| 1382 | + | |
| 1383 | + return iNeedAdj; | |
| 1384 | +} | |
| 1385 | + | |
| 1386 | +int32_t AdjustEnhanceLayer (sWelsEncCtx* pCtx, int32_t iCurDid) { | |
| 1387 | +#ifdef MT_DEBUG | |
| 1388 | + int64_t iT1 = WelsTime(); | |
| 1389 | +#endif//MT_DEBUG | |
| 1390 | + int32_t iNeedAdj = 1; | |
| 1391 | + // uiSliceMode of referencing spatial should be SM_FIXEDSLCNUM_SLICE | |
| 1392 | + // if using spatial base layer for complexity estimation | |
| 1393 | + const BOOL_T kbModelingFromSpatial = (pCtx->pCurDqLayer->pRefLayer != NULL && iCurDid > 0) | |
| 1394 | + && (pCtx->pSvcParam->sDependencyLayers[iCurDid - 1].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE | |
| 1395 | + && pCtx->pSvcParam->iMultipleThreadIdc >= pCtx->pSvcParam->sDependencyLayers[iCurDid - | |
| 1396 | + 1].sMso.sSliceArgument.iSliceNum); | |
| 1397 | + | |
| 1398 | + if (kbModelingFromSpatial) { // using spatial base layer for complexity estimation | |
| 1399 | +#ifdef TRY_SLICING_BALANCE | |
| 1400 | +#ifdef NOT_ABSOLUTE_BALANCING | |
| 1401 | + // do not need adjust due to not different at both slices of consumed time | |
| 1402 | + iNeedAdj = NeedDynamicAdjust (pCtx->pSliceThreading->pSliceConsumeTime[iCurDid - 1], | |
| 1403 | + pCtx->pCurDqLayer->pSliceEncCtx->iSliceNumInFrame); | |
| 1404 | + if (iNeedAdj) | |
| 1405 | +#endif//NOT_ABSOLUTE_BALANCING | |
| 1406 | + DynamicAdjustSlicing (pCtx, | |
| 1407 | + pCtx->pCurDqLayer, | |
| 1408 | + pCtx->pSliceThreading->pSliceComplexRatio[iCurDid - 1], | |
| 1409 | + iCurDid | |
| 1410 | + ); | |
| 1411 | +#endif//TRY_SLICING_BALANCE | |
| 1412 | + } else { // use temporal layer for complexity estimation | |
| 1413 | +#ifdef TRY_SLICING_BALANCE | |
| 1414 | +#ifdef NOT_ABSOLUTE_BALANCING | |
| 1415 | + // do not need adjust due to not different at both slices of consumed time | |
| 1416 | + iNeedAdj = NeedDynamicAdjust (pCtx->pSliceThreading->pSliceConsumeTime[iCurDid], | |
| 1417 | + pCtx->pCurDqLayer->pSliceEncCtx->iSliceNumInFrame); | |
| 1418 | + if (iNeedAdj) | |
| 1419 | +#endif//NOT_ABSOLUTE_BALANCING | |
| 1420 | + DynamicAdjustSlicing (pCtx, | |
| 1421 | + pCtx->pCurDqLayer, | |
| 1422 | + pCtx->pSliceThreading->pSliceComplexRatio[iCurDid], | |
| 1423 | + iCurDid | |
| 1424 | + ); | |
| 1425 | +#endif//TRY_SLICING_BALANCE | |
| 1426 | + } | |
| 1427 | + | |
| 1428 | +#ifdef MT_DEBUG | |
| 1429 | + iT1 = WelsTime() - iT1; | |
| 1430 | + if (pCtx->pSliceThreading->pFSliceDiff) { | |
| 1431 | + fprintf (pCtx->pSliceThreading->pFSliceDiff, | |
| 1432 | +#ifdef WIN32 | |
| 1433 | + "%6I64d us adjust time at spatial layer %d, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1434 | +#else | |
| 1435 | + "%6lld us adjust time at spatial layer %d, iNeedAdj %d, DynamicAdjustSlicing()\n", | |
| 1436 | +#endif//WIN32 | |
| 1437 | + iT1, iCurDid, iNeedAdj); | |
| 1438 | + } | |
| 1439 | +#endif//MT_DEBUG | |
| 1440 | + | |
| 1441 | + return iNeedAdj; | |
| 1442 | +} | |
| 1443 | + | |
| 1444 | +#endif//#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) | |
| 1445 | + | |
| 1446 | +#if defined(MT_ENABLED) | |
| 1447 | + | |
| 1448 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) && defined(MT_DEBUG) | |
| 1449 | +void TrackSliceComplexities (sWelsEncCtx* pCtx, const int32_t iCurDid) { | |
| 1450 | + const int32_t kiCountSliceNum = pCtx->pCurDqLayer->pSliceEncCtx->iSliceNumInFrame; | |
| 1451 | + if (kiCountSliceNum > 0) { | |
| 1452 | + int32_t iSliceIdx = 0; | |
| 1453 | + do { | |
| 1454 | + fprintf (pCtx->pSliceThreading->pFSliceDiff, "%6.3f complexity pRatio at iDid %d pSlice %d\n", | |
| 1455 | + pCtx->pSliceThreading->pSliceComplexRatio[iCurDid][iSliceIdx], iCurDid, iSliceIdx); | |
| 1456 | + ++ iSliceIdx; | |
| 1457 | + } while (iSliceIdx < kiCountSliceNum); | |
| 1458 | + } | |
| 1459 | +} | |
| 1460 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE) | |
| 1461 | + | |
| 1462 | +#if defined(DYNAMIC_SLICE_ASSIGN) && defined(MT_DEBUG) | |
| 1463 | +void TrackSliceConsumeTime (sWelsEncCtx* pCtx, int32_t* pDidList, const int32_t iSpatialNum) { | |
| 1464 | + SWelsSvcCodingParam* pPara = NULL; | |
| 1465 | + int32_t iSpatialIdx = 0; | |
| 1466 | + | |
| 1467 | + if (iSpatialNum > MAX_DEPENDENCY_LAYER) | |
| 1468 | + return; | |
| 1469 | + | |
| 1470 | + pPara = pCtx->pSvcParam; | |
| 1471 | + while (iSpatialIdx < iSpatialNum) { | |
| 1472 | + const int32_t kiDid = pDidList[iSpatialIdx]; | |
| 1473 | + SDLayerParam* pDlp = &pPara->sDependencyLayers[kiDid]; | |
| 1474 | + SMulSliceOption* pMso = &pDlp->sMso; | |
| 1475 | + SDqLayer* pCurDq = pCtx->ppDqLayerList[kiDid]; | |
| 1476 | + SSliceCtx* pSliceCtx = pCurDq->pSliceEncCtx; | |
| 1477 | + const uint32_t kuiCountSliceNum = pSliceCtx->iSliceNumInFrame; | |
| 1478 | + if (pCtx->pSliceThreading) { | |
| 1479 | + if (pCtx->pSliceThreading->pFSliceDiff && pMso->uiSliceMode == SM_FIXEDSLCNUM_SLICE && pPara->iMultipleThreadIdc > 1 | |
| 1480 | + && pPara->iMultipleThreadIdc >= kuiCountSliceNum) { | |
| 1481 | + uint32_t i = 0; | |
| 1482 | + uint32_t uiMaxT = 0; | |
| 1483 | + int32_t iMaxI = 0; | |
| 1484 | + while (i < kuiCountSliceNum) { | |
| 1485 | + if (pCtx->pSliceThreading->pSliceConsumeTime[kiDid] != NULL) | |
| 1486 | + fprintf (pCtx->pSliceThreading->pFSliceDiff, "%6d us consume_time coding_idx %d iDid %d pSlice %d\n", | |
| 1487 | + pCtx->pSliceThreading->pSliceConsumeTime[kiDid][i], pCtx->iCodingIndex, kiDid, i /*/ 1000*/); | |
| 1488 | + if (pCtx->pSliceThreading->pSliceConsumeTime[kiDid][i] > uiMaxT) { | |
| 1489 | + uiMaxT = pCtx->pSliceThreading->pSliceConsumeTime[kiDid][i]; | |
| 1490 | + iMaxI = i; | |
| 1491 | + } | |
| 1492 | + ++ i; | |
| 1493 | + } | |
| 1494 | + fprintf (pCtx->pSliceThreading->pFSliceDiff, "%6d us consume_time_max coding_idx %d iDid %d pSlice %d\n", uiMaxT, | |
| 1495 | + pCtx->iCodingIndex, kiDid, iMaxI /*/ 1000*/); | |
| 1496 | + } | |
| 1497 | + } | |
| 1498 | + ++ iSpatialIdx; | |
| 1499 | + } | |
| 1500 | +} | |
| 1501 | +#endif//#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG) | |
| 1502 | + | |
| 1503 | +#endif//MT_ENABLED | |
| 1504 | +} | |
| 1505 | +#endif//MT_ENABLED | |
| 1506 | + | |