History

Pretty printed the C++ code with astyle

Ethan Hugg committed 12 years ago

Commit ff6b6691 parent 063709c225 files · +48457 −51954Browse files

Showing the changes to codec/encoder/core/src/slice_multi_threading.cpp (1 of 225 files). Show all

Unified · Split

codec/encoder/core/src/slice_multi_threading.cpp+1506−1592
@@ -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+

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

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

Repository code

Go to file
t