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

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