1 /*!
2 * \copy
3 * Copyright (c) 2009-2013, Cisco Systems
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *
32 * \file svc_encode_slice.c
33 *
34 * \brief svc encoding slice
35 *
36 * \date 2009.07.27 Created
37 *
38 *************************************************************************************
39 */
40
41 #include "ls_defines.h"
42 #include "svc_encode_slice.h"
43 #include "svc_enc_golomb.h"
44 #include "svc_base_layer_md.h"
45 #include "svc_encode_mb.h"
46 #include "svc_set_mb_syn.h"
47 #include "decode_mb_aux.h"
48 #include "svc_mode_decision.h"
49
50 namespace WelsEnc {
51 //#define ENC_TRACE
52
53 typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);
54 typedef void (*PWelsSliceHeaderWriteFunc) (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
55 IWelsParametersetStrategy* pParametersetStrategy);
56
UpdateNonZeroCountCache(SMB * pMb,SMbCache * pMbCache)57 void UpdateNonZeroCountCache (SMB* pMb, SMbCache* pMbCache) {
58 ST32 (&pMbCache->iNonZeroCoeffCount[9], LD32 (&pMb->pNonZeroCount[ 0]));
59 ST32 (&pMbCache->iNonZeroCoeffCount[17], LD32 (&pMb->pNonZeroCount[ 4]));
60 ST32 (&pMbCache->iNonZeroCoeffCount[25], LD32 (&pMb->pNonZeroCount[ 8]));
61 ST32 (&pMbCache->iNonZeroCoeffCount[33], LD32 (&pMb->pNonZeroCount[12]));
62
63 ST16 (&pMbCache->iNonZeroCoeffCount[14], LD16 (&pMb->pNonZeroCount[16]));
64 ST16 (&pMbCache->iNonZeroCoeffCount[38], LD16 (&pMb->pNonZeroCount[18]));
65 ST16 (&pMbCache->iNonZeroCoeffCount[22], LD16 (&pMb->pNonZeroCount[20]));
66 ST16 (&pMbCache->iNonZeroCoeffCount[46], LD16 (&pMb->pNonZeroCount[22]));
67 }
68
WelsSliceHeaderScalExtInit(SDqLayer * pCurLayer,SSlice * pSlice)69 void WelsSliceHeaderScalExtInit (SDqLayer* pCurLayer, SSlice* pSlice) {
70 SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
71 SNalUnitHeaderExt* pNalHeadExt = &pCurLayer->sLayerInfo.sNalHeaderExt;
72
73 uint8_t uiDependencyId = pNalHeadExt->uiDependencyId;
74
75 pSliceHeadExt->bSliceSkipFlag = false;
76
77 if (uiDependencyId > 0) { //spatial EL
78 //bothe adaptive and default flags should equal to 0.
79 pSliceHeadExt->bAdaptiveBaseModeFlag =
80 pSliceHeadExt->bAdaptiveMotionPredFlag =
81 pSliceHeadExt->bAdaptiveResidualPredFlag = false;
82
83 pSliceHeadExt->bDefaultBaseModeFlag =
84 pSliceHeadExt->bDefaultMotionPredFlag =
85 pSliceHeadExt->bDefaultResidualPredFlag = false;
86 }
87 }
88
WelsSliceHeaderExtInit(sWelsEncCtx * pEncCtx,SDqLayer * pCurLayer,SSlice * pSlice)89 void WelsSliceHeaderExtInit (sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice* pSlice) {
90 SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt;
91 SSliceHeader* pCurSliceHeader = &pCurSliceExt->sSliceHeader;
92 SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
93 pCurSliceHeader->eSliceType = pEncCtx->eSliceType;
94
95 pCurSliceExt->bStoreRefBasePicFlag = false;
96
97 pCurSliceHeader->iFrameNum = pParamInternal->iFrameNum;
98 pCurSliceHeader->uiIdrPicId = pParamInternal->uiIdrPicId;
99 pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc; // 0
100
101 if (P_SLICE == pEncCtx->eSliceType) {
102 pCurSliceHeader->uiNumRefIdxL0Active = 1;
103 if (pCurSliceHeader->uiRefCount > 0 &&
104 pCurSliceHeader->uiRefCount <= pCurLayer->sLayerInfo.pSpsP->iNumRefFrames) {
105 pCurSliceHeader->bNumRefIdxActiveOverrideFlag = true;
106 pCurSliceHeader->uiNumRefIdxL0Active = pCurSliceHeader->uiRefCount;
107 }
108 //to solve mismatch between debug&release
109 else {
110 pCurSliceHeader->bNumRefIdxActiveOverrideFlag = false;
111 }
112 }
113
114 pCurSliceHeader->iSliceQpDelta = pEncCtx->iGlobalQp - pCurLayer->sLayerInfo.pPpsP->iPicInitQp;
115
116 //for deblocking initial
117 pCurSliceHeader->uiDisableDeblockingFilterIdc = pCurLayer->iLoopFilterDisableIdc;
118 pCurSliceHeader->iSliceAlphaC0Offset =
119 pCurLayer->iLoopFilterAlphaC0Offset; // need update iSliceAlphaC0Offset & iSliceBetaOffset for pSlice-header if loop_filter_idc != 1
120 pCurSliceHeader->iSliceBetaOffset = pCurLayer->iLoopFilterBetaOffset;
121 pCurSliceExt->uiDisableInterLayerDeblockingFilterIdc = pCurLayer->uiDisableInterLayerDeblockingFilterIdc;
122
123 if (pSlice->bSliceHeaderExtFlag) {
124 WelsSliceHeaderScalExtInit (pCurLayer, pSlice);
125 } else {
126 //both adaptive and default flags should equal to 0.
127 pCurSliceExt->bAdaptiveBaseModeFlag =
128 pCurSliceExt->bAdaptiveMotionPredFlag =
129 pCurSliceExt->bAdaptiveResidualPredFlag = false;
130
131 pCurSliceExt->bDefaultBaseModeFlag =
132 pCurSliceExt->bDefaultMotionPredFlag =
133 pCurSliceExt->bDefaultResidualPredFlag = false;
134 }
135 }
136
137
UpdateMbNeighbor(SDqLayer * pCurDq,SMB * pMb,const int32_t kiMbWidth,uint16_t uiSliceIdc)138 void UpdateMbNeighbor (SDqLayer* pCurDq, SMB* pMb, const int32_t kiMbWidth, uint16_t uiSliceIdc) {
139 uint32_t uiNeighborAvailFlag = 0;
140 const int32_t kiMbXY = pMb->iMbXY;
141 const int32_t kiMbX = pMb->iMbX;
142 const int32_t kiMbY = pMb->iMbY;
143 bool bLeft;
144 bool bTop;
145 bool bLeftTop;
146 bool bRightTop;
147 int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
148
149 pMb->uiSliceIdc = uiSliceIdc;
150 iLeftXY = kiMbXY - 1;
151 iTopXY = kiMbXY - kiMbWidth;
152 iLeftTopXY = iTopXY - 1;
153 iRightTopXY = iTopXY + 1;
154
155 bLeft = (kiMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iLeftXY));
156 bTop = (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iTopXY));
157 bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iLeftTopXY));
158 bRightTop = (kiMbX < (kiMbWidth - 1)) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pCurDq, iRightTopXY));
159
160 if (bLeft) {
161 uiNeighborAvailFlag |= LEFT_MB_POS;
162 }
163 if (bTop) {
164 uiNeighborAvailFlag |= TOP_MB_POS;
165 }
166 if (bLeftTop) {
167 uiNeighborAvailFlag |= TOPLEFT_MB_POS;
168 }
169 if (bRightTop) {
170 uiNeighborAvailFlag |= TOPRIGHT_MB_POS;
171 }
172 pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag;
173 }
174
175 /* count MB types if enabled FRAME_INFO_OUTPUT*/
176 #if defined(MB_TYPES_CHECK)
WelsCountMbType(int32_t (* iMbCount)[18],const EWelsSliceType keSt,const SMB * kpMb)177 void WelsCountMbType (int32_t (*iMbCount)[18], const EWelsSliceType keSt, const SMB* kpMb) {
178 if (NULL == iMbCount)
179 return;
180
181 switch (kpMb->uiMbType) {
182 case MB_TYPE_INTRA4x4:
183 ++ iMbCount[keSt][Intra4x4];
184 break;
185 case MB_TYPE_INTRA16x16:
186 ++ iMbCount[keSt][Intra16x16];
187 break;
188 case MB_TYPE_SKIP:
189 ++ iMbCount[keSt][PSkip];
190 break;
191 case MB_TYPE_16x16:
192 ++ iMbCount[keSt][Inter16x16];
193 break;
194 case MB_TYPE_16x8:
195 ++ iMbCount[keSt][Inter16x8];
196 break;
197 case MB_TYPE_8x16:
198 ++ iMbCount[keSt][Inter8x16];
199 break;
200 case MB_TYPE_8x8:
201 ++ iMbCount[keSt][Inter8x8];
202 break;
203 case MB_TYPE_INTRA_BL:
204 ++ iMbCount[keSt][7];
205 break;
206 default:
207 break;
208 }
209 }
210 #endif//MB_TYPES_CHECK
211
212 /*!
213 * \brief write reference picture list on reordering syntax in Slice header
214 */
WriteReferenceReorder(SBitStringAux * pBs,SSliceHeader * sSliceHeader)215 void WriteReferenceReorder (SBitStringAux* pBs, SSliceHeader* sSliceHeader) {
216 SRefPicListReorderSyntax* pRefOrdering = &sSliceHeader->sRefReordering;
217 uint8_t eSliceType = sSliceHeader->eSliceType % 5;
218 int16_t n = 0;
219
220 if (I_SLICE != eSliceType && SI_SLICE != eSliceType) { // !I && !SI
221 BsWriteOneBit (pBs, true);
222 // {
223 uint16_t uiReorderingOfPicNumsIdc;
224 do {
225 uiReorderingOfPicNumsIdc = pRefOrdering->SReorderingSyntax[n].uiReorderingOfPicNumsIdc;
226 BsWriteUE (pBs, uiReorderingOfPicNumsIdc);
227 if (0 == uiReorderingOfPicNumsIdc || 1 == uiReorderingOfPicNumsIdc)
228 BsWriteUE (pBs, pRefOrdering->SReorderingSyntax[n].uiAbsDiffPicNumMinus1);
229 else if (2 == uiReorderingOfPicNumsIdc)
230 BsWriteUE (pBs, pRefOrdering->SReorderingSyntax[n].iLongTermPicNum);
231
232 n ++;
233 } while (3 != uiReorderingOfPicNumsIdc);
234 // }
235 }
236 }
237
238 /*!
239 * \brief write reference picture marking syntax in pSlice header
240 */
WriteRefPicMarking(SBitStringAux * pBs,SSliceHeader * pSliceHeader,SNalUnitHeaderExt * pNalHdrExt)241 void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUnitHeaderExt* pNalHdrExt) {
242 SRefPicMarking* sRefMarking = &pSliceHeader->sRefMarking;
243 int16_t n = 0;
244
245 if (pNalHdrExt->bIdrFlag) {
246 BsWriteOneBit (pBs, sRefMarking->bNoOutputOfPriorPicsFlag);
247 BsWriteOneBit (pBs, sRefMarking->bLongTermRefFlag);
248 } else {
249 BsWriteOneBit (pBs, sRefMarking->bAdaptiveRefPicMarkingModeFlag);
250
251 if (sRefMarking->bAdaptiveRefPicMarkingModeFlag) {
252 int32_t iMmcoType;
253 do {
254 iMmcoType = sRefMarking->SMmcoRef[n].iMmcoType;
255 BsWriteUE (pBs, iMmcoType);
256 if (1 == iMmcoType || 3 == iMmcoType)
257 BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iDiffOfPicNum - 1);
258
259 if (2 == iMmcoType)
260 BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iLongTermPicNum);
261
262 if (3 == iMmcoType || 6 == iMmcoType)
263 BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iLongTermFrameIdx);
264
265 if (4 == iMmcoType)
266 BsWriteUE (pBs, sRefMarking->SMmcoRef[n].iMaxLongTermFrameIdx + 1);
267
268 n ++;
269 } while (0 != iMmcoType);
270 }
271
272 }
273 }
274
WelsSliceHeaderWrite(sWelsEncCtx * pCtx,SBitStringAux * pBs,SDqLayer * pCurLayer,SSlice * pSlice,IWelsParametersetStrategy * pParametersetStrategy)275 void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
276 IWelsParametersetStrategy* pParametersetStrategy) {
277 SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
278 SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
279 SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
280 SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt;
281
282 BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
283 BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */
284
285 BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pSliceHeader->pPps->iPpsId));
286
287 BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
288
289 if (pNalHead->bIdrFlag) { /* NAL IDR */
290 BsWriteUE (pBs, pSliceHeader->uiIdrPicId);
291 }
292
293 BsWriteBits (pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb);
294
295 if (P_SLICE == pSliceHeader->eSliceType) {
296 BsWriteOneBit (pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag);
297 if (pSliceHeader->bNumRefIdxActiveOverrideFlag) {
298 BsWriteUE (pBs, WELS_CLIP3 (pSliceHeader->uiNumRefIdxL0Active - 1, 0, MAX_REF_PIC_COUNT));
299 }
300 }
301
302 if (!pNalHead->bIdrFlag)
303 WriteReferenceReorder (pBs, pSliceHeader);
304
305 if (pNalHead->sNalUnitHeader.uiNalRefIdc) {
306 WriteRefPicMarking (pBs, pSliceHeader, pNalHead);
307 }
308
309 if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) {
310 BsWriteUE (pBs, pSlice->iCabacInitIdc);
311 }
312 BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */
313
314 if (pPps->bDeblockingFilterControlPresentFlag) {
315 switch (pSliceHeader->uiDisableDeblockingFilterIdc) {
316 case 0:
317 case 3:
318 case 4:
319 case 6:
320 BsWriteUE (pBs, 0);
321 break;
322 case 1:
323 BsWriteUE (pBs, 1);
324 break;
325 case 2:
326 case 5:
327 BsWriteUE (pBs, 2);
328 break;
329 default:
330 WelsLog (&pCtx->sLogCtx, WELS_LOG_ERROR, "Invalid uiDisableDeblockingFilterIdc %d",
331 pSliceHeader->uiDisableDeblockingFilterIdc);
332 break;
333 }
334 if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) {
335 BsWriteSE (pBs, pSliceHeader->iSliceAlphaC0Offset >> 1);
336 BsWriteSE (pBs, pSliceHeader->iSliceBetaOffset >> 1);
337 }
338 }
339 }
340
WelsSliceHeaderExtWrite(sWelsEncCtx * pCtx,SBitStringAux * pBs,SDqLayer * pCurLayer,SSlice * pSlice,IWelsParametersetStrategy * pParametersetStrategy)341 void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
342 IWelsParametersetStrategy* pParametersetStrategy) {
343 SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
344 SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
345 SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
346 SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
347 SSliceHeader* pSliceHeader = &pSliceHeadExt->sSliceHeader;
348 SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt;
349
350 BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
351 BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */
352
353 BsWriteUE (pBs, pSliceHeader->pPps->iPpsId +
354 pParametersetStrategy->GetPpsIdOffset (pSliceHeader->pPps->iPpsId));
355
356 BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
357
358 if (pNalHead->bIdrFlag) { /* NAL IDR */
359 BsWriteUE (pBs, pSliceHeader->uiIdrPicId);
360 }
361
362 BsWriteBits (pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb);
363 // {
364 if (P_SLICE == pSliceHeader->eSliceType) {
365 BsWriteOneBit (pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag);
366 if (pSliceHeader->bNumRefIdxActiveOverrideFlag) {
367 BsWriteUE (pBs, WELS_CLIP3 (pSliceHeader->uiNumRefIdxL0Active - 1, 0, MAX_REF_PIC_COUNT));
368 }
369 }
370
371 if (!pNalHead->bIdrFlag)
372 WriteReferenceReorder (pBs, pSliceHeader);
373
374 if (pNalHead->sNalUnitHeader.uiNalRefIdc) {
375 WriteRefPicMarking (pBs, pSliceHeader, pNalHead);
376
377 if (!pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) {
378 BsWriteOneBit (pBs, pSliceHeadExt->bStoreRefBasePicFlag);
379 }
380 }
381 // }
382
383
384 if (pPps->bEntropyCodingModeFlag && pSliceHeader->eSliceType != I_SLICE) {
385 BsWriteUE (pBs, pSlice->iCabacInitIdc);
386 }
387
388 BsWriteSE (pBs, pSliceHeader->iSliceQpDelta); /* pSlice qp delta */
389
390 if (pPps->bDeblockingFilterControlPresentFlag) {
391 BsWriteUE (pBs, pSliceHeader->uiDisableDeblockingFilterIdc);
392 if (1 != pSliceHeader->uiDisableDeblockingFilterIdc) {
393 BsWriteSE (pBs, pSliceHeader->iSliceAlphaC0Offset >> 1);
394 BsWriteSE (pBs, pSliceHeader->iSliceBetaOffset >> 1);
395 }
396 }
397
398 #if !defined(DISABLE_FMO_FEATURE)
399 if (pPps->uiNumSliceGroups > 1 &&
400 pPps->uiSliceGroupMapType >= 3 &&
401 pPps->uiSliceGroupMapType <= 5) {
402 int32_t iNumBits;
403 if (pPps->uiSliceGroupChangeRate) {
404 iNumBits = WELS_CEILLOG2 (1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate);
405 BsWriteBits (pBs, iNumBits, pSliceHeader->iSliceGroupChangeCycle);
406 }
407 }
408 #endif//!DISABLE_FMO_FEATURE
409
410 if (false) {
411 BsWriteOneBit (pBs, pSliceHeadExt->bSliceSkipFlag);
412 if (pSliceHeadExt->bSliceSkipFlag) {
413 BsWriteUE (pBs, pSliceHeadExt->uiNumMbsInSlice - 1);
414 } else {
415 BsWriteOneBit (pBs, pSliceHeadExt->bAdaptiveBaseModeFlag);
416 if (!pSliceHeadExt->bAdaptiveBaseModeFlag) {
417 BsWriteOneBit (pBs, pSliceHeadExt->bDefaultBaseModeFlag);
418 }
419
420 if (!pSliceHeadExt->bDefaultBaseModeFlag) {
421 BsWriteOneBit (pBs, 0);
422 BsWriteOneBit (pBs, 0);
423 }
424
425 BsWriteOneBit (pBs, pSliceHeadExt->bAdaptiveResidualPredFlag);
426 if (!pSliceHeadExt->bAdaptiveResidualPredFlag) {
427 BsWriteOneBit (pBs, 0);
428 }
429 }
430 if (1 == pSubSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag) {
431 BsWriteOneBit (pBs, pSliceHeadExt->bTcoeffLevelPredFlag);
432 }
433
434 }
435
436 if (!pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag) {
437 BsWriteBits (pBs, 4, 0);
438 BsWriteBits (pBs, 4, 15);
439 }
440 }
441
442 //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
443 //only for inter part
WelsInterMbEncode(sWelsEncCtx * pEncCtx,SSlice * pSlice,SMB * pCurMb)444 void WelsInterMbEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {
445 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
446
447 WelsDctMb (pMbCache->pCoeffLevel, pMbCache->SPicData.pEncMb[0], pEncCtx->pCurDqLayer->iEncStride[0],
448 pMbCache->pMemPredLuma, pEncCtx->pFuncList->pfDctFourT4);
449 WelsEncInterY (pEncCtx->pFuncList, pCurMb, pMbCache);
450 }
451
452
453 //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
454 //only for I SSlice
WelsIMbChromaEncode(sWelsEncCtx * pEncCtx,SMB * pCurMb,SMbCache * pMbCache)455 void WelsIMbChromaEncode (sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache* pMbCache) {
456 SWelsFuncPtrList* pFunc = pEncCtx->pFuncList;
457 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
458 const int32_t kiEncStride = pCurLayer->iEncStride[1];
459 const int32_t kiCsStride = pCurLayer->iCsStride[1];
460 int16_t* pCurRS = pMbCache->pCoeffLevel;
461 uint8_t* pBestPred = pMbCache->pBestPredIntraChroma;
462 uint8_t* pCsCb = pMbCache->SPicData.pCsMb[1];
463 uint8_t* pCsCr = pMbCache->SPicData.pCsMb[2];
464
465 //cb
466 pFunc->pfDctFourT4 (pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8);
467 WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS, 1);
468 pFunc->pfIDctFourT4 (pCsCb, kiCsStride, pBestPred, 8, pCurRS);
469
470 //cr
471 pFunc->pfDctFourT4 (pCurRS + 64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred + 64, 8);
472 WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS + 64, 2);
473 pFunc->pfIDctFourT4 (pCsCr, kiCsStride, pBestPred + 64, 8, pCurRS + 64);
474 }
475
476
477 //only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
478 //for P SSlice (intra part + inter part)
WelsPMbChromaEncode(sWelsEncCtx * pEncCtx,SSlice * pSlice,SMB * pCurMb)479 void WelsPMbChromaEncode (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {
480 SWelsFuncPtrList* pFunc = pEncCtx->pFuncList;
481 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
482 const int32_t kiEncStride = pCurLayer->iEncStride[1];
483 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
484 int16_t* pCurRS = pMbCache->pCoeffLevel + 256;
485 uint8_t* pBestPred = pMbCache->pMemPredChroma;
486
487 pFunc->pfDctFourT4 (pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8);
488 pFunc->pfDctFourT4 (pCurRS + 64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred + 64, 8);
489
490 WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS, 1);
491 WelsEncRecUV (pFunc, pCurMb, pMbCache, pCurRS + 64, 2);
492 }
493
OutputPMbWithoutConstructCsRsNoCopy(sWelsEncCtx * pCtx,SDqLayer * pDq,SSlice * pSlice,SMB * pMb)494 void OutputPMbWithoutConstructCsRsNoCopy (sWelsEncCtx* pCtx, SDqLayer* pDq, SSlice* pSlice, SMB* pMb) {
495 if ((IS_INTER (pMb->uiMbType) && !IS_SKIP (pMb->uiMbType))
496 || IS_I_BL (pMb->uiMbType)) { //intra have been reconstructed, NO COPY from CS to pDecPic--
497 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
498 uint8_t* pDecY = pMbCache->SPicData.pDecMb[0];
499 uint8_t* pDecU = pMbCache->SPicData.pDecMb[1];
500 uint8_t* pDecV = pMbCache->SPicData.pDecMb[2];
501 int16_t* pScaledTcoeff = pMbCache->pCoeffLevel;
502 const int32_t kiDecStrideLuma = pDq->pDecPic->iLineSize[0];
503 const int32_t kiDecStrideChroma = pDq->pDecPic->iLineSize[1];
504 PIDctFunc pfIdctFour4x4 = pCtx->pFuncList->pfIDctFourT4;
505
506 WelsIDctT4RecOnMb (pDecY, kiDecStrideLuma, pDecY, kiDecStrideLuma, pScaledTcoeff, pfIdctFour4x4);
507 pfIdctFour4x4 (pDecU, kiDecStrideChroma, pDecU, kiDecStrideChroma, pScaledTcoeff + 256);
508 pfIdctFour4x4 (pDecV, kiDecStrideChroma, pDecV, kiDecStrideChroma, pScaledTcoeff + 320);
509 }
510 }
511
UpdateQpForOverflow(SMB * pCurMb,uint8_t kuiChromaQpIndexOffset)512 void UpdateQpForOverflow (SMB* pCurMb, uint8_t kuiChromaQpIndexOffset) {
513 pCurMb->uiLumaQp += DELTA_QP;
514 pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
515 }
516 // for intra non-dynamic pSlice
517 //encapsulate two kinds of reconstruction:
518 //first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
519 //second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)
WelsISliceMdEnc(sWelsEncCtx * pEncCtx,SSlice * pSlice)520 int32_t WelsISliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
521 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
522 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
523 SSliceHeaderExt* pSliceHdExt = &pSlice->sSliceHeaderExt;
524 SMB* pMbList = pCurLayer->sMbDataP;
525 SMB* pCurMb = NULL;
526 const int32_t kiSliceFirstMbXY = pSliceHdExt->sSliceHeader.iFirstMbInSlice;
527 int32_t iNextMbIdx = kiSliceFirstMbXY;
528 const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
529 int32_t iCurMbIdx = 0, iNumMbCoded = 0;
530 const int32_t kiSliceIdx = pSlice->iSliceIdx;
531 const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
532
533 SWelsMD sMd;
534 int32_t iEncReturn = ENC_RETURN_SUCCESS;
535 SDynamicSlicingStack sDss;
536 if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
537 WelsInitSliceCabac (pEncCtx, pSlice);
538 sDss.pRestoreBuffer = NULL;
539 sDss.iStartPos = sDss.iCurrentPos = 0;
540 }
541 for (; ;) {
542 if (!pEncCtx->pSvcParam->iEntropyCodingModeFlag)
543 pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, 0);
544 iCurMbIdx = iNextMbIdx;
545 pCurMb = &pMbList[ iCurMbIdx ];
546
547 pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
548 WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
549
550 TRY_REENCODING:
551 sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
552 WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
553 UpdateNonZeroCountCache (pCurMb, pMbCache);
554
555
556 iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
557 if (!pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
558 if ((iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND) && (pCurMb->uiLumaQp < 50)) {
559 pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
560 UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
561 goto TRY_REENCODING;
562 }
563 }
564 if (ENC_RETURN_SUCCESS != iEncReturn)
565 return iEncReturn;
566
567 pCurMb->uiSliceIdc = kiSliceIdx;
568
569 #if defined(MB_TYPES_CHECK)
570 WelsCountMbType (pEncCtx->sPerInfo.iMbCount, I_SLICE, pCurMb);
571 #endif//MB_TYPES_CHECK
572
573 pEncCtx->pFuncList->pfMdBackgroundInfoUpdate (pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag, I_SLICE);
574 pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, sMd.iCostLuma, pSlice);
575
576 ++iNumMbCoded;
577 iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);
578 if (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {
579 break;
580 }
581 }
582
583 return ENC_RETURN_SUCCESS;
584 }
585
586 // Only for intra dynamic slicing
WelsISliceMdEncDynamic(sWelsEncCtx * pEncCtx,SSlice * pSlice)587 int32_t WelsISliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice) { //pMd + encoding
588 SBitStringAux* pBs = pSlice->pSliceBsa;
589 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
590 SSliceCtx* pSliceCtx = &pCurLayer->sSliceEncCtx;
591 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
592 SSliceHeaderExt* pSliceHdExt = &pSlice->sSliceHeaderExt;
593 SMB* pMbList = pCurLayer->sMbDataP;
594 SMB* pCurMb = NULL;
595 const int32_t kiSliceFirstMbXY = pSliceHdExt->sSliceHeader.iFirstMbInSlice;
596 int32_t iNextMbIdx = kiSliceFirstMbXY;
597 const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
598 int32_t iCurMbIdx = 0, iNumMbCoded = 0;
599 const int32_t kiSliceIdx = pSlice->iSliceIdx;
600 const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);
601 const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
602 int32_t iEncReturn = ENC_RETURN_SUCCESS;
603
604 SWelsMD sMd;
605 SDynamicSlicingStack sDss;
606 if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
607 WelsInitSliceCabac (pEncCtx, pSlice);
608 sDss.pRestoreBuffer = pEncCtx->pDynamicBsBuffer[kiPartitionId];
609 sDss.iStartPos = sDss.iCurrentPos = 0;
610 } else {
611 sDss.iStartPos = BsGetBitsPos (pBs);
612 }
613 for (; ;) {
614 iCurMbIdx = iNextMbIdx;
615 pCurMb = &pMbList[ iCurMbIdx ];
616
617 pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, 0);
618 pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
619 // if already reaches the largest number of slices, set QPs to the upper bound
620 if (pSlice->bDynamicSlicingSliceSizeCtrlFlag) {
621 pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;
622 pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
623 }
624 WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
625
626 TRY_REENCODING:
627 sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
628 WelsMdIntraMb (pEncCtx, &sMd, pCurMb, pMbCache);
629 UpdateNonZeroCountCache (pCurMb, pMbCache);
630
631 iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
632 if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND && (pCurMb->uiLumaQp < 50)) {
633 pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
634 UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
635 goto TRY_REENCODING;
636 }
637 if (ENC_RETURN_SUCCESS != iEncReturn)
638 return iEncReturn;
639
640 sDss.iCurrentPos = pEncCtx->pFuncList->pfGetBsPosition (pSlice);
641
642 if (DynSlcJudgeSliceBoundaryStepBack (pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss)) { //islice
643 pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
644 pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx -
645 1; // update LastCodedMbIdxOfPartition, need to -1 due to stepping back
646 ++ pCurLayer->NumSliceCodedOfPartition[kiPartitionId];
647
648 break;
649 }
650
651
652 pCurMb->uiSliceIdc = kiSliceIdx;
653
654 #if defined(MB_TYPES_CHECK)
655 WelsCountMbType (pEncCtx->sPerInfo.iMbCount, I_SLICE, pCurMb);
656 #endif//MB_TYPES_CHECK
657
658 pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, sMd.iCostLuma, pSlice);
659
660 ++iNumMbCoded;
661
662 iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);
663 //whether all of MB in current pSlice encoded or not
664 if (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {
665 pSlice->iCountMbNumInSlice = iCurMbIdx - pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId];
666 pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx;
667 ++ pCurLayer->NumSliceCodedOfPartition[kiPartitionId];
668
669 break;
670 }
671 }
672 return iEncReturn;
673 }
674
675 //encapsulate two kinds of reconstruction:
676 // first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
677 // second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)
WelsPSliceMdEnc(sWelsEncCtx * pEncCtx,SSlice * pSlice,const bool kbIsHighestDlayerFlag)678 int32_t WelsPSliceMdEnc (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag) { //pMd + encoding
679 const SSliceHeaderExt* kpShExt = &pSlice->sSliceHeaderExt;
680 const SSliceHeader* kpSh = &kpShExt->sSliceHeader;
681 const int32_t kiSliceFirstMbXY = kpSh->iFirstMbInSlice;
682 SWelsMD sMd;
683
684 sMd.uiRef = kpSh->uiRefIndex;
685 sMd.bMdUsingSad = (pEncCtx->pSvcParam->iComplexityMode == LOW_COMPLEXITY);
686 if (!pEncCtx->pCurDqLayer->bBaseLayerAvailableFlag || !kbIsHighestDlayerFlag)
687 memset (&sMd.sMe, 0, sizeof (sMd.sMe));
688
689 //pMb loop
690 return WelsMdInterMbLoop (pEncCtx, pSlice, &sMd, kiSliceFirstMbXY);
691 }
692
WelsPSliceMdEncDynamic(sWelsEncCtx * pEncCtx,SSlice * pSlice,const bool kbIsHighestDlayerFlag)693 int32_t WelsPSliceMdEncDynamic (sWelsEncCtx* pEncCtx, SSlice* pSlice, const bool kbIsHighestDlayerFlag) {
694 const SSliceHeaderExt* kpShExt = &pSlice->sSliceHeaderExt;
695 const SSliceHeader* kpSh = &kpShExt->sSliceHeader;
696 const int32_t kiSliceFirstMbXY = kpSh->iFirstMbInSlice;
697 SWelsMD sMd;
698
699 sMd.uiRef = kpSh->uiRefIndex;
700 sMd.bMdUsingSad = (pEncCtx->pSvcParam->iComplexityMode == LOW_COMPLEXITY);
701 if (!pEncCtx->pCurDqLayer->bBaseLayerAvailableFlag || !kbIsHighestDlayerFlag)
702 memset (&sMd.sMe, 0, sizeof (sMd.sMe));
703
704 //mb loop
705 return WelsMdInterMbLoopOverDynamicSlice (pEncCtx, pSlice, &sMd, kiSliceFirstMbXY);
706 }
707
WelsCodePSlice(sWelsEncCtx * pEncCtx,SSlice * pSlice)708 int32_t WelsCodePSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
709 //pSlice-level init should be outside and before this function
710 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
711
712 const bool kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
713 const bool kbHighestSpatial = pEncCtx->pSvcParam->iSpatialLayerNum ==
714 (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1);
715
716 //MD switch
717 if (kbBaseAvail && kbHighestSpatial) {
718 //initial pMd pointer
719 pEncCtx->pFuncList->pfInterMd = WelsMdInterMbEnhancelayer;
720 } else {
721 //initial pMd pointer
722 pEncCtx->pFuncList->pfInterMd = WelsMdInterMb;
723 }
724 return WelsPSliceMdEnc (pEncCtx, pSlice, kbHighestSpatial);
725 }
726
WelsCodePOverDynamicSlice(sWelsEncCtx * pEncCtx,SSlice * pSlice)727 int32_t WelsCodePOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice) {
728 //pSlice-level init should be outside and before this function
729 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
730
731 const bool kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
732 const bool kbHighestSpatial = pEncCtx->pSvcParam->iSpatialLayerNum ==
733 (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1);
734
735 //MD switch
736 if (kbBaseAvail && kbHighestSpatial) {
737 //initial pMd pointer
738 pEncCtx->pFuncList->pfInterMd = WelsMdInterMbEnhancelayer;
739 } else {
740 //initial pMd pointer
741 pEncCtx->pFuncList->pfInterMd = WelsMdInterMb;
742 }
743 return WelsPSliceMdEncDynamic (pEncCtx, pSlice, kbHighestSpatial);
744 }
745
746 // 1st index: 0: for P pSlice; 1: for I pSlice;
747 // 2nd index: 0: for non-dynamic pSlice; 1: for dynamic I pSlice;
748 static const PWelsCodingSliceFunc g_pWelsSliceCoding[2][2] = {
749 { WelsCodePSlice, WelsCodePOverDynamicSlice }, // P SSlice
750 { WelsISliceMdEnc, WelsISliceMdEncDynamic } // I SSlice
751 };
752 static const PWelsSliceHeaderWriteFunc g_pWelsWriteSliceHeader[2] = { // 0: for base; 1: for ext;
753 WelsSliceHeaderWrite,
754 WelsSliceHeaderExtWrite
755 };
756
757 //Allocate slice's MB cache buffer
AllocMbCacheAligned(SMbCache * pMbCache,CMemoryAlign * pMa)758 int32_t AllocMbCacheAligned (SMbCache* pMbCache, CMemoryAlign* pMa) {
759 pMbCache->pMemPredMb = (uint8_t*)pMa->WelsMallocz (2 * 256 * sizeof (uint8_t), "pMbCache->pMemPredMb");
760 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredMb));
761
762 pMbCache->pCoeffLevel = (int16_t*)pMa->WelsMallocz (MB_COEFF_LIST_SIZE * sizeof (int16_t), "pMbCache->pCoeffLevel");
763 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pCoeffLevel));
764 pMbCache->pSkipMb = (uint8_t*)pMa->WelsMallocz (384 * sizeof (uint8_t), "pMbCache->pSkipMb");
765 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pSkipMb));
766 pMbCache->pMemPredBlk4 = (uint8_t*)pMa->WelsMallocz (2 * 16 * sizeof (uint8_t), "pMbCache->pMemPredBlk4");
767 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredBlk4));
768 pMbCache->pBufferInterPredMe = (uint8_t*)pMa->WelsMallocz (4 * 640 * sizeof (uint8_t), "pMbCache->pBufferInterPredMe");
769 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pBufferInterPredMe));
770 pMbCache->pPrevIntra4x4PredModeFlag = (bool*)pMa->WelsMallocz (16 * sizeof (bool),
771 "pMbCache->pPrevIntra4x4PredModeFlag");
772 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pPrevIntra4x4PredModeFlag));
773 pMbCache->pRemIntra4x4PredModeFlag = (int8_t*)pMa->WelsMallocz (16 * sizeof (int8_t),
774 "pMbCache->pRemIntra4x4PredModeFlag");
775 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pRemIntra4x4PredModeFlag));
776 pMbCache->pDct = (SDCTCoeff*)pMa->WelsMallocz (sizeof (SDCTCoeff), "pMbCache->pDct");
777 WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pDct));
778
779 return 0;
780 }
781
782 // Free slice's MB cache buffer
FreeMbCache(SMbCache * pMbCache,CMemoryAlign * pMa)783 void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) {
784 if (NULL != pMbCache->pCoeffLevel) {
785 pMa->WelsFree (pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel");
786 pMbCache->pCoeffLevel = NULL;
787 }
788 if (NULL != pMbCache->pMemPredMb) {
789 pMa->WelsFree (pMbCache->pMemPredMb, "pMbCache->pMemPredMb");
790 pMbCache->pMemPredMb = NULL;
791 }
792 if (NULL != pMbCache->pSkipMb) {
793 pMa->WelsFree (pMbCache->pSkipMb, "pMbCache->pSkipMb");
794 pMbCache->pSkipMb = NULL;
795 }
796 if (NULL != pMbCache->pMemPredBlk4) {
797 pMa->WelsFree (pMbCache->pMemPredBlk4, "pMbCache->pMemPredBlk4");
798 pMbCache->pMemPredBlk4 = NULL;
799 }
800 if (NULL != pMbCache->pBufferInterPredMe) {
801 pMa->WelsFree (pMbCache->pBufferInterPredMe, "pMbCache->pBufferInterPredMe");
802 pMbCache->pBufferInterPredMe = NULL;
803 }
804 if (NULL != pMbCache->pPrevIntra4x4PredModeFlag) {
805 pMa->WelsFree (pMbCache->pPrevIntra4x4PredModeFlag, "pMbCache->pPrevIntra4x4PredModeFlag");
806 pMbCache->pPrevIntra4x4PredModeFlag = NULL;
807 }
808 if (NULL != pMbCache->pRemIntra4x4PredModeFlag) {
809 pMa->WelsFree (pMbCache->pRemIntra4x4PredModeFlag, "pMbCache->pRemIntra4x4PredModeFlag");
810 pMbCache->pRemIntra4x4PredModeFlag = NULL;
811 }
812 if (NULL != pMbCache->pDct) {
813 pMa->WelsFree (pMbCache->pDct, "pMbCache->pDct");
814 pMbCache->pDct = NULL;
815 }
816 }
817
818 //Initialize slice's boundary info)
InitSliceBoundaryInfo(SDqLayer * pCurLayer,SSliceArgument * pSliceArgument,const int32_t kiSliceNumInFrame)819 int32_t InitSliceBoundaryInfo (SDqLayer* pCurLayer,
820 SSliceArgument* pSliceArgument,
821 const int32_t kiSliceNumInFrame) {
822 const int32_t* kpSlicesAssignList = (int32_t*) & (pSliceArgument->uiSliceMbNum[0]);
823 const int32_t kiMBWidth = pCurLayer->iMbWidth;
824 const int32_t kiMBHeight = pCurLayer->iMbHeight;
825 const int32_t kiCountNumMbInFrame = kiMBWidth * kiMBHeight;
826 int32_t iSliceIdx = 0;
827 int32_t iFirstMBInSlice = 0;
828 int32_t iMbNumInSlice = 0;
829
830 for (; iSliceIdx < kiSliceNumInFrame; iSliceIdx++) {
831 if (SM_SINGLE_SLICE == pSliceArgument->uiSliceMode) {
832 iFirstMBInSlice = 0;
833 iMbNumInSlice = kiCountNumMbInFrame;
834
835 } else if ((SM_RASTER_SLICE == pSliceArgument->uiSliceMode) && (0 == pSliceArgument->uiSliceMbNum[0])) {
836 iFirstMBInSlice = iSliceIdx * kiMBWidth;
837 iMbNumInSlice = kiMBWidth;
838 } else if (SM_RASTER_SLICE == pSliceArgument->uiSliceMode ||
839 SM_FIXEDSLCNUM_SLICE == pSliceArgument->uiSliceMode) {
840 int32_t iMbIdx = 0;
841 for (int i = 0; i < iSliceIdx; i++) {
842 iMbIdx += kpSlicesAssignList[i];
843 }
844
845 if (iMbIdx >= kiCountNumMbInFrame) {
846 return ENC_RETURN_UNEXPECTED;
847 }
848
849 iFirstMBInSlice = iMbIdx;
850 iMbNumInSlice = kpSlicesAssignList[iSliceIdx];
851
852 } else if (SM_SIZELIMITED_SLICE == pSliceArgument->uiSliceMode) {
853 iFirstMBInSlice = 0;
854 iMbNumInSlice = kiCountNumMbInFrame;
855
856 } else { // any else uiSliceMode?
857 assert (0);
858 }
859
860 pCurLayer->pCountMbNumInSlice[iSliceIdx] = iMbNumInSlice;
861 pCurLayer->pFirstMbIdxOfSlice[iSliceIdx] = iFirstMBInSlice;
862 }
863
864 return ENC_RETURN_SUCCESS;
865 }
866
SetSliceBoundaryInfo(SDqLayer * pCurLayer,SSlice * pSlice,const int32_t kiSliceIdx)867 int32_t SetSliceBoundaryInfo (SDqLayer* pCurLayer, SSlice* pSlice, const int32_t kiSliceIdx) {
868 if (NULL == pCurLayer || NULL == pSlice ||
869 NULL == pCurLayer->pFirstMbIdxOfSlice ||
870 NULL == pCurLayer->pCountMbNumInSlice) {
871
872 return ENC_RETURN_UNEXPECTED;
873 }
874
875 pSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = pCurLayer->pFirstMbIdxOfSlice[kiSliceIdx];
876 pSlice->iCountMbNumInSlice = pCurLayer->pCountMbNumInSlice[kiSliceIdx];
877
878 return ENC_RETURN_SUCCESS;
879 }
880
881 //Allocate slice's MB info buffer
AllocateSliceMBBuffer(SSlice * pSlice,CMemoryAlign * pMa)882 int32_t AllocateSliceMBBuffer (SSlice* pSlice, CMemoryAlign* pMa) {
883 if (AllocMbCacheAligned (&pSlice->sMbCacheInfo, pMa)) {
884 return ENC_RETURN_MEMALLOCERR;
885 }
886
887 return ENC_RETURN_SUCCESS;
888 }
889
890 // Initialize slice bs buffer info
InitSliceBsBuffer(SSlice * pSlice,SBitStringAux * pBsWrite,bool bIndependenceBsBuffer,const int32_t iMaxSliceBufferSize,CMemoryAlign * pMa)891 int32_t InitSliceBsBuffer (SSlice* pSlice,
892 SBitStringAux* pBsWrite,
893 bool bIndependenceBsBuffer,
894 const int32_t iMaxSliceBufferSize,
895 CMemoryAlign* pMa) {
896 pSlice->sSliceBs.uiSize = iMaxSliceBufferSize;
897 pSlice->sSliceBs.uiBsPos = 0;
898
899 if (bIndependenceBsBuffer) {
900 pSlice->pSliceBsa = &pSlice->sSliceBs.sBsWrite;
901 pSlice->sSliceBs.pBs = (uint8_t*)pMa->WelsMallocz (iMaxSliceBufferSize, "sSliceBs.pBs");
902 if (NULL == pSlice->sSliceBs.pBs) {
903 return ENC_RETURN_MEMALLOCERR;
904 }
905 } else {
906 pSlice->pSliceBsa = pBsWrite;
907 pSlice->sSliceBs.pBs = NULL;
908 }
909 return ENC_RETURN_SUCCESS;
910 }
911
912 //free slice bs buffer
FreeSliceBuffer(SSlice * & pSliceList,const int32_t kiMaxSliceNum,CMemoryAlign * pMa,const char * kpTag)913 void FreeSliceBuffer (SSlice*& pSliceList, const int32_t kiMaxSliceNum, CMemoryAlign* pMa, const char* kpTag) {
914 if (NULL != pSliceList) {
915 int32_t iSliceIdx = 0;
916 while (iSliceIdx < kiMaxSliceNum) {
917 SSlice* pSlice = &pSliceList[iSliceIdx];
918 FreeMbCache (&pSlice->sMbCacheInfo, pMa);
919
920 //slice bs buffer
921 if (NULL != pSlice->sSliceBs.pBs) {
922 pMa->WelsFree (pSlice->sSliceBs.pBs, "sSliceBs.pBs");
923 pSlice->sSliceBs.pBs = NULL;
924 }
925 ++ iSliceIdx;
926 }
927 pMa->WelsFree (pSliceList, kpTag);
928 pSliceList = NULL;
929 }
930 }
931
InitSliceList(SSlice * & pSliceList,SBitStringAux * pBsWrite,const int32_t kiMaxSliceNum,const int32_t kiMaxSliceBufferSize,const bool bIndependenceBsBuffer,CMemoryAlign * pMa)932 int32_t InitSliceList (SSlice*& pSliceList,
933 SBitStringAux* pBsWrite,
934 const int32_t kiMaxSliceNum,
935 const int32_t kiMaxSliceBufferSize,
936 const bool bIndependenceBsBuffer,
937 CMemoryAlign* pMa) {
938 int32_t iSliceIdx = 0;
939 int32_t iRet = 0;
940
941 if (kiMaxSliceBufferSize <= 0) {
942 return ENC_RETURN_UNEXPECTED;
943 }
944
945 while (iSliceIdx < kiMaxSliceNum) {
946 SSlice* pSlice = pSliceList + iSliceIdx;
947 if (NULL == pSlice) {
948 return ENC_RETURN_MEMALLOCERR;
949 }
950
951 pSlice->iSliceIdx = iSliceIdx;
952 pSlice->uiBufferIdx = 0;
953 pSlice->iCountMbNumInSlice = 0;
954 pSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = 0;
955
956 iRet = InitSliceBsBuffer (pSlice,
957 pBsWrite,
958 bIndependenceBsBuffer,
959 kiMaxSliceBufferSize,
960 pMa);
961 if (ENC_RETURN_SUCCESS != iRet) {
962 return iRet;
963 }
964
965 iRet = AllocateSliceMBBuffer (pSlice, pMa);
966
967 if (ENC_RETURN_SUCCESS != iRet) {
968 return iRet;
969 }
970 ++ iSliceIdx;
971 }
972 return ENC_RETURN_SUCCESS;
973 }
974
InitAllSlicesInThread(sWelsEncCtx * pCtx)975 int32_t InitAllSlicesInThread (sWelsEncCtx* pCtx) {
976 SDqLayer* pCurDqLayer = pCtx->pCurDqLayer;
977 int32_t iSliceIdx = 0;
978 int32_t iSlcBuffIdx = 0;
979
980 for (; iSliceIdx < pCurDqLayer->iMaxSliceNum; iSliceIdx++) {
981 if (NULL == pCurDqLayer->ppSliceInLayer[iSliceIdx]) {
982 return ENC_RETURN_UNEXPECTED;
983 }
984
985 pCurDqLayer->ppSliceInLayer[iSliceIdx]->iSliceIdx = -1;
986 }
987
988 for (; iSlcBuffIdx < pCtx->iActiveThreadsNum; iSlcBuffIdx++) {
989 pCurDqLayer->sSliceBufferInfo[iSlcBuffIdx].iCodedSliceNum = 0;
990 }
991
992 return ENC_RETURN_SUCCESS;
993 }
994
InitOneSliceInThread(sWelsEncCtx * pCtx,SSlice * & pSlice,const int32_t kiSlcBuffIdx,const int32_t kiDlayerIdx,const int32_t kiSliceIdx)995 int32_t InitOneSliceInThread (sWelsEncCtx* pCtx,
996 SSlice*& pSlice,
997 const int32_t kiSlcBuffIdx,
998 const int32_t kiDlayerIdx,
999 const int32_t kiSliceIdx) {
1000
1001 if (pCtx->pCurDqLayer->bThreadSlcBufferFlag) {
1002 const int32_t kiCodedNumInThread = pCtx->pCurDqLayer->sSliceBufferInfo[kiSlcBuffIdx].iCodedSliceNum;
1003 assert (kiCodedNumInThread <= pCtx->pCurDqLayer->sSliceBufferInfo[kiSlcBuffIdx].iMaxSliceNum - 1);
1004 pSlice = &pCtx->pCurDqLayer->sSliceBufferInfo [kiSlcBuffIdx].pSliceBuffer[kiCodedNumInThread];
1005 } else {
1006 pSlice = &pCtx->pCurDqLayer->sSliceBufferInfo [0].pSliceBuffer[kiSliceIdx];
1007 }
1008 pSlice->iSliceIdx = kiSliceIdx;
1009 pSlice->uiBufferIdx = kiSlcBuffIdx;
1010
1011 // Initialize slice bs buffer info
1012 pSlice->sSliceBs.uiBsPos = 0;
1013 pSlice->sSliceBs.iNalIndex = 0;
1014 pSlice->sSliceBs.pBsBuffer = pCtx->pSliceThreading->pThreadBsBuffer[kiSlcBuffIdx];
1015
1016 return ENC_RETURN_SUCCESS;
1017 }
1018
InitSliceThreadInfo(sWelsEncCtx * pCtx,SDqLayer * pDqLayer,const int32_t kiDlayerIndex,CMemoryAlign * pMa)1019 int32_t InitSliceThreadInfo (sWelsEncCtx* pCtx,
1020 SDqLayer* pDqLayer,
1021 const int32_t kiDlayerIndex,
1022 CMemoryAlign* pMa) {
1023 int32_t iThreadNum = pCtx->pSvcParam->iMultipleThreadIdc;
1024 int32_t iMaxSliceNum = 0;
1025 int32_t iSlcBufferNum = 0;
1026 int32_t iIdx = 0;
1027 int32_t iRet = 0;
1028
1029 assert (iThreadNum > 0);
1030
1031 //for fixed slice num case, no need to reallocate, so one slice buffer for all thread
1032 if (pDqLayer->bThreadSlcBufferFlag) {
1033 iMaxSliceNum = pDqLayer->iMaxSliceNum / iThreadNum + 1;
1034 iSlcBufferNum = iThreadNum;
1035 } else {
1036 iMaxSliceNum = pDqLayer->iMaxSliceNum;
1037 iSlcBufferNum = 1;
1038 }
1039
1040 while (iIdx < iSlcBufferNum) {
1041 pDqLayer->sSliceBufferInfo[iIdx].iMaxSliceNum = iMaxSliceNum;
1042 pDqLayer->sSliceBufferInfo[iIdx].iCodedSliceNum = 0;
1043 pDqLayer->sSliceBufferInfo[iIdx].pSliceBuffer = (SSlice*)pMa->WelsMallocz (sizeof (SSlice) * iMaxSliceNum,
1044 "pSliceBuffer");
1045 if (NULL == pDqLayer->sSliceBufferInfo[iIdx].pSliceBuffer) {
1046 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
1047 "CWelsH264SVCEncoder::InitSliceThreadInfo: pSliceThreadInfo->pSliceBuffer[iIdx] is NULL");
1048 return ENC_RETURN_MEMALLOCERR;
1049 }
1050 iRet = InitSliceList (pDqLayer->sSliceBufferInfo[iIdx].pSliceBuffer,
1051 &pCtx->pOut->sBsWrite,
1052 iMaxSliceNum,
1053 pCtx->iSliceBufferSize[kiDlayerIndex],
1054 pDqLayer->bSliceBsBufferFlag,
1055 pMa);
1056 if (ENC_RETURN_SUCCESS != iRet) {
1057 return iRet;
1058 }
1059 iIdx++;
1060 }
1061
1062 for (; iIdx < MAX_THREADS_NUM; iIdx++) {
1063 pDqLayer->sSliceBufferInfo[iIdx].iMaxSliceNum = 0;
1064 pDqLayer->sSliceBufferInfo[iIdx].iCodedSliceNum = 0;
1065 pDqLayer->sSliceBufferInfo[iIdx].pSliceBuffer = NULL;
1066 }
1067
1068 return ENC_RETURN_SUCCESS;
1069 }
1070
InitSliceInLayer(sWelsEncCtx * pCtx,SDqLayer * pDqLayer,const int32_t kiDlayerIndex,CMemoryAlign * pMa)1071 int32_t InitSliceInLayer (sWelsEncCtx* pCtx,
1072 SDqLayer* pDqLayer,
1073 const int32_t kiDlayerIndex,
1074 CMemoryAlign* pMa) {
1075 int32_t iRet = 0;
1076 int32_t iSliceIdx = 0;
1077 int32_t iSlcBuffIdx = 0;
1078 int32_t iStartIdx = 0;
1079 int32_t iMaxSliceNum = pDqLayer->iMaxSliceNum;
1080 SSliceArgument* pSliceArgument = & pCtx->pSvcParam->sSpatialLayers[kiDlayerIndex].sSliceArgument;
1081
1082 //SM_SINGLE_SLICE mode using single-thread bs writer pOut->sBsWrite
1083 //even though multi-thread is on for other layers
1084 pDqLayer->bSliceBsBufferFlag = (pCtx->pSvcParam->iMultipleThreadIdc > 1 &&
1085 SM_SINGLE_SLICE != pSliceArgument->uiSliceMode) ? true : false;
1086
1087 pDqLayer->bThreadSlcBufferFlag = (pCtx->pSvcParam->iMultipleThreadIdc > 1 &&
1088 SM_SIZELIMITED_SLICE == pSliceArgument->uiSliceMode) ? true : false;
1089
1090 iRet = InitSliceThreadInfo (pCtx,
1091 pDqLayer,
1092 kiDlayerIndex,
1093 pMa);
1094 if (ENC_RETURN_SUCCESS != iRet) {
1095 return ENC_RETURN_MEMALLOCERR;
1096 }
1097
1098 pDqLayer->iMaxSliceNum = 0;
1099 for (iSlcBuffIdx = 0; iSlcBuffIdx < pCtx->iActiveThreadsNum; iSlcBuffIdx++) {
1100 pDqLayer->iMaxSliceNum += pDqLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum;
1101 }
1102
1103 pDqLayer->ppSliceInLayer = (SSlice**)pMa->WelsMallocz (sizeof (SSlice*) * pDqLayer->iMaxSliceNum, "ppSliceInLayer");
1104 if (NULL == pDqLayer->ppSliceInLayer) {
1105 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::InitSliceInLayer() pDqLayer->ppSliceInLayer is NULL");
1106 return ENC_RETURN_MEMALLOCERR;
1107 }
1108
1109 pDqLayer->pFirstMbIdxOfSlice = (int32_t*)pMa->WelsMallocz (sizeof (int32_t*) * pDqLayer->iMaxSliceNum,
1110 "pFirstMbIdxOfSlice");
1111 if (NULL == pDqLayer->pFirstMbIdxOfSlice) {
1112 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
1113 "CWelsH264SVCEncoder::InitSliceInLayer() pDqLayer->pFirstMbIdxOfSlice is NULL");
1114 return ENC_RETURN_MEMALLOCERR;
1115 }
1116
1117 pDqLayer->pCountMbNumInSlice = (int32_t*)pMa->WelsMallocz (sizeof (int32_t*) * pDqLayer->iMaxSliceNum,
1118 "pCountMbNumInSlice");
1119 if (NULL == pDqLayer->pCountMbNumInSlice) {
1120 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
1121 "CWelsH264SVCEncoder::InitSliceInLayer() pDqLayer->pCountMbNumInSlice is NULL");
1122 return ENC_RETURN_MEMALLOCERR;
1123 }
1124
1125 iRet = InitSliceBoundaryInfo (pDqLayer, pSliceArgument, iMaxSliceNum);
1126 if (ENC_RETURN_SUCCESS != iRet) {
1127 return iRet;
1128 }
1129
1130 iStartIdx = 0;
1131 for (iSlcBuffIdx = 0; iSlcBuffIdx < pCtx->iActiveThreadsNum; iSlcBuffIdx++) {
1132 for (iSliceIdx = 0; iSliceIdx < pDqLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum; iSliceIdx++) {
1133 pDqLayer->ppSliceInLayer[iStartIdx + iSliceIdx] = pDqLayer->sSliceBufferInfo[iSlcBuffIdx].pSliceBuffer + iSliceIdx;
1134 }
1135
1136 iStartIdx += pDqLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum;
1137 }
1138
1139 return ENC_RETURN_SUCCESS;
1140 }
1141
InitSliceHeadWithBase(SSlice * pSlice,SSlice * pBaseSlice)1142 void InitSliceHeadWithBase (SSlice* pSlice, SSlice* pBaseSlice) {
1143 if (NULL == pSlice || NULL == pBaseSlice) {
1144 return;
1145 }
1146
1147 SSliceHeaderExt* pBaseSHExt = &pBaseSlice->sSliceHeaderExt;
1148 SSliceHeaderExt* pSHExt = &pSlice->sSliceHeaderExt;
1149
1150 pSlice->bSliceHeaderExtFlag = pBaseSlice->bSliceHeaderExtFlag;
1151 pSHExt->sSliceHeader.iPpsId = pBaseSHExt->sSliceHeader.iPpsId;
1152 pSHExt->sSliceHeader.pPps = pBaseSHExt->sSliceHeader.pPps;
1153 pSHExt->sSliceHeader.iSpsId = pBaseSHExt->sSliceHeader.iSpsId;
1154 pSHExt->sSliceHeader.pSps = pBaseSHExt->sSliceHeader.pSps;
1155 }
1156
InitSliceRefInfoWithBase(SSlice * pSlice,SSlice * pBaseSlice,const uint8_t kuiRefCount)1157 void InitSliceRefInfoWithBase (SSlice* pSlice, SSlice* pBaseSlice, const uint8_t kuiRefCount) {
1158 if (NULL == pSlice || NULL == pBaseSlice) {
1159 return;
1160 }
1161
1162 SSliceHeaderExt* pBaseSHExt = &pBaseSlice->sSliceHeaderExt;
1163 SSliceHeaderExt* pSHExt = &pSlice->sSliceHeaderExt;
1164
1165 pSHExt->sSliceHeader.uiRefCount = kuiRefCount;
1166 memcpy (&pSHExt->sSliceHeader.sRefMarking, &pBaseSHExt->sSliceHeader.sRefMarking, sizeof (SRefPicMarking));
1167 memcpy (&pSHExt->sSliceHeader.sRefReordering, &pBaseSHExt->sSliceHeader.sRefReordering,
1168 sizeof (SRefPicListReorderSyntax));
1169
1170 }
1171
InitSliceRC(SSlice * pSlice,const int32_t kiGlobalQp)1172 static inline int32_t InitSliceRC (SSlice* pSlice, const int32_t kiGlobalQp) {
1173
1174 if (NULL == pSlice || kiGlobalQp < 0)
1175 return ENC_RETURN_INVALIDINPUT;
1176
1177 pSlice->sSlicingOverRc.iComplexityIndexSlice = 0;
1178 pSlice->sSlicingOverRc.iCalculatedQpSlice = kiGlobalQp;
1179 pSlice->sSlicingOverRc.iTotalQpSlice = 0;
1180 pSlice->sSlicingOverRc.iTotalMbSlice = 0;
1181 pSlice->sSlicingOverRc.iTargetBitsSlice = 0;
1182 pSlice->sSlicingOverRc.iFrameBitsSlice = 0;
1183 pSlice->sSlicingOverRc.iGomBitsSlice = 0;
1184
1185 return ENC_RETURN_SUCCESS;
1186 }
1187
ReallocateSliceList(sWelsEncCtx * pCtx,SSliceArgument * pSliceArgument,SSlice * & pSliceList,const int32_t kiMaxSliceNumOld,const int32_t kiMaxSliceNumNew)1188 int32_t ReallocateSliceList (sWelsEncCtx* pCtx,
1189 SSliceArgument* pSliceArgument,
1190 SSlice*& pSliceList,
1191 const int32_t kiMaxSliceNumOld,
1192 const int32_t kiMaxSliceNumNew) {
1193 CMemoryAlign* pMA = pCtx->pMemAlign;
1194 SSlice* pBaseSlice = NULL;
1195 SSlice* pNewSliceList = NULL;
1196 SSlice* pSlice = NULL;
1197 int32_t iSliceIdx = 0;
1198 int32_t iRet = 0;
1199 const int32_t kiCurDid = pCtx->uiDependencyId;
1200 int32_t iMaxSliceBufferSize = (pCtx)->iSliceBufferSize[kiCurDid];
1201
1202 if (NULL == pSliceList || NULL == pSliceArgument) {
1203 return ENC_RETURN_INVALIDINPUT;
1204 }
1205
1206 bool bIndependenceBsBuffer = (pCtx->pSvcParam->iMultipleThreadIdc > 1 &&
1207 SM_SINGLE_SLICE != pSliceArgument->uiSliceMode) ? true : false;
1208
1209 pNewSliceList = (SSlice*)pMA->WelsMallocz (sizeof (SSlice) * kiMaxSliceNumNew, "pSliceBuffer");
1210 if (NULL == pNewSliceList) {
1211 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::ReallocateSliceList: pNewSliceList is NULL");
1212 return ENC_RETURN_MEMALLOCERR;
1213 }
1214
1215 memcpy (pNewSliceList, pSliceList, sizeof (SSlice) * kiMaxSliceNumOld);
1216
1217 //update Bs writer
1218 for (iSliceIdx = 0; iSliceIdx < kiMaxSliceNumOld; iSliceIdx++) {
1219 pSlice = pNewSliceList + iSliceIdx;
1220 if (NULL == pSlice) {
1221 FreeSliceBuffer (pNewSliceList, kiMaxSliceNumNew, pMA, "pSliceBuffer");
1222 return ENC_RETURN_MEMALLOCERR;
1223 }
1224
1225 if (bIndependenceBsBuffer) {
1226 pSlice->pSliceBsa = &pSlice->sSliceBs.sBsWrite;
1227 }
1228 }
1229
1230 pBaseSlice = &pSliceList[0];
1231 if (NULL == pBaseSlice) {
1232 FreeSliceBuffer (pNewSliceList, kiMaxSliceNumNew, pMA, "ReallocateSliceList()::InitSliceBsBuffer()");
1233 return ENC_RETURN_MEMALLOCERR;
1234 }
1235
1236 for (iSliceIdx = kiMaxSliceNumOld; iSliceIdx < kiMaxSliceNumNew; iSliceIdx++) {
1237 pSlice = pNewSliceList + iSliceIdx;
1238 if (NULL == pSlice) {
1239 FreeSliceBuffer (pNewSliceList, kiMaxSliceNumNew, pMA, "pSliceBuffer");
1240 return ENC_RETURN_MEMALLOCERR;
1241 }
1242
1243 pSlice->iSliceIdx = -1;
1244 pSlice->uiBufferIdx = 0;
1245 pSlice->iCountMbNumInSlice = 0;
1246 pSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = 0;
1247
1248 iRet = InitSliceBsBuffer (pSlice,
1249 & pCtx->pOut->sBsWrite,
1250 bIndependenceBsBuffer,
1251 iMaxSliceBufferSize,
1252 pMA);
1253 if (ENC_RETURN_SUCCESS != iRet) {
1254 FreeSliceBuffer (pNewSliceList, kiMaxSliceNumNew, pMA, "pSliceBuffer");
1255 return iRet;
1256 }
1257
1258 iRet = AllocateSliceMBBuffer (pSlice, pMA);
1259 if (ENC_RETURN_SUCCESS != iRet) {
1260 FreeSliceBuffer (pNewSliceList, kiMaxSliceNumNew, pMA, "pSliceBuffer");
1261 return iRet;
1262 }
1263
1264 InitSliceHeadWithBase (pSlice, pBaseSlice);
1265 InitSliceRefInfoWithBase (pSlice, pBaseSlice, pCtx->iNumRef0);
1266
1267 iRet = InitSliceRC (pSlice, pCtx->iGlobalQp);
1268 if (ENC_RETURN_SUCCESS != iRet) {
1269 FreeSliceBuffer (pNewSliceList, kiMaxSliceNumNew, pMA, "pSliceBuffer");
1270 return iRet;
1271 }
1272 }
1273
1274 pMA->WelsFree (pSliceList, "pSliceBuffer");
1275 pSliceList = pNewSliceList;
1276
1277 return ENC_RETURN_SUCCESS;
1278 }
1279
CalculateNewSliceNum(sWelsEncCtx * pCtx,SSlice * pLastCodedSlice,const int32_t iMaxSliceNumOld,int32_t & iMaxSliceNumNew)1280 int32_t CalculateNewSliceNum (sWelsEncCtx* pCtx,
1281 SSlice* pLastCodedSlice,
1282 const int32_t iMaxSliceNumOld,
1283 int32_t& iMaxSliceNumNew) {
1284 if (NULL == pCtx || NULL == pLastCodedSlice || 0 == iMaxSliceNumOld) {
1285 return ENC_RETURN_INVALIDINPUT;
1286 }
1287
1288 if (1 == pCtx->iActiveThreadsNum) {
1289 iMaxSliceNumNew = iMaxSliceNumOld * SLICE_NUM_EXPAND_COEF;
1290 return ENC_RETURN_SUCCESS;
1291 }
1292
1293 int32_t iPartitionID = pLastCodedSlice->iSliceIdx % pCtx->iActiveThreadsNum;
1294 int32_t iMBNumInPatition = pCtx->pCurDqLayer->EndMbIdxOfPartition[iPartitionID]
1295 - pCtx->pCurDqLayer->FirstMbIdxOfPartition[iPartitionID] + 1;
1296 int32_t iLeftMBNum = pCtx->pCurDqLayer->EndMbIdxOfPartition[iPartitionID]
1297 - pCtx->pCurDqLayer->LastCodedMbIdxOfPartition[iPartitionID] + 1;
1298 int32_t iIncreaseSlicNum = (iLeftMBNum * INT_MULTIPLY / iMBNumInPatition) * iMaxSliceNumOld;
1299
1300 iIncreaseSlicNum = (0 == (iIncreaseSlicNum / INT_MULTIPLY)) ? 1 : (iIncreaseSlicNum / INT_MULTIPLY);
1301 iIncreaseSlicNum = (iIncreaseSlicNum < iMaxSliceNumOld / 2) ? (iMaxSliceNumOld / 2) : iIncreaseSlicNum;
1302 iMaxSliceNumNew = iMaxSliceNumOld + iIncreaseSlicNum;
1303
1304 return ENC_RETURN_SUCCESS;
1305 }
1306
ReallocateSliceInThread(sWelsEncCtx * pCtx,SDqLayer * pDqLayer,const int32_t kiDlayerIdx,const int32_t KiSlcBuffIdx)1307 int32_t ReallocateSliceInThread (sWelsEncCtx* pCtx,
1308 SDqLayer* pDqLayer,
1309 const int32_t kiDlayerIdx,
1310 const int32_t KiSlcBuffIdx) {
1311 int32_t iMaxSliceNum = pDqLayer->sSliceBufferInfo[KiSlcBuffIdx].iMaxSliceNum;
1312 int32_t iCodedSliceNum = pDqLayer->sSliceBufferInfo[KiSlcBuffIdx].iCodedSliceNum;
1313 int32_t iMaxSliceNumNew = 0;
1314 int32_t iRet = 0;
1315 SSlice* pLastCodedSlice = &pDqLayer->sSliceBufferInfo[KiSlcBuffIdx].pSliceBuffer [iCodedSliceNum - 1];
1316 SSliceArgument* pSliceArgument = & pCtx->pSvcParam->sSpatialLayers[kiDlayerIdx].sSliceArgument;
1317
1318 iRet = CalculateNewSliceNum (pCtx,
1319 pLastCodedSlice,
1320 iMaxSliceNum,
1321 iMaxSliceNumNew);
1322 if (ENC_RETURN_SUCCESS != iRet) {
1323 return iRet;
1324 }
1325
1326 iRet = ReallocateSliceList (pCtx,
1327 pSliceArgument,
1328 pDqLayer->sSliceBufferInfo[KiSlcBuffIdx].pSliceBuffer,
1329 iMaxSliceNum,
1330 iMaxSliceNumNew);
1331 if (ENC_RETURN_SUCCESS != iRet) {
1332 return iRet;
1333 }
1334
1335 pDqLayer->sSliceBufferInfo[KiSlcBuffIdx].iMaxSliceNum = iMaxSliceNumNew;
1336
1337 return ENC_RETURN_SUCCESS;
1338 }
1339
ExtendLayerBuffer(sWelsEncCtx * pCtx,const int32_t kiMaxSliceNumOld,const int32_t kiMaxSliceNumNew)1340 int32_t ExtendLayerBuffer (sWelsEncCtx* pCtx,
1341 const int32_t kiMaxSliceNumOld,
1342 const int32_t kiMaxSliceNumNew) {
1343 CMemoryAlign* pMA = pCtx->pMemAlign;
1344 SDqLayer* pCurLayer = pCtx->pCurDqLayer;
1345 SSlice** ppSlice = NULL;
1346 int32_t* pFirstMbIdxOfSlice = NULL;
1347 int32_t* pCountMbNumInSlice = NULL;
1348
1349 // update for ppsliceInlayer
1350 ppSlice = (SSlice**)pMA->WelsMallocz (sizeof (SSlice*) * kiMaxSliceNumNew, "ppSliceInLayer");
1351 if (NULL == ppSlice) {
1352 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::ExtendLayerBuffer: ppSlice is NULL");
1353 return ENC_RETURN_MEMALLOCERR;
1354 }
1355 pMA->WelsFree (pCurLayer->ppSliceInLayer, "ppSliceInLayer");
1356 pCurLayer->ppSliceInLayer = ppSlice;
1357
1358 // update for pFirstMbIdxInSlice
1359 pFirstMbIdxOfSlice = (int32_t*)pMA->WelsMallocz (sizeof (int32_t*) * kiMaxSliceNumNew, "pFirstMbIdxOfSlice");
1360 if (NULL == pFirstMbIdxOfSlice) {
1361 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::ExtendLayerBuffer: pFirstMbIdxOfSlice is NULL");
1362 return ENC_RETURN_MEMALLOCERR;
1363 }
1364 memset (pFirstMbIdxOfSlice, 0, sizeof (int32_t) * kiMaxSliceNumNew);
1365 memcpy (pFirstMbIdxOfSlice, pCurLayer->pFirstMbIdxOfSlice, sizeof (int32_t) * kiMaxSliceNumOld);
1366 pMA->WelsFree (pCurLayer->pFirstMbIdxOfSlice, "pFirstMbIdxOfSlice");
1367 pCurLayer->pFirstMbIdxOfSlice = pFirstMbIdxOfSlice;
1368
1369 // update for pCountMbNumInSlice
1370 pCountMbNumInSlice = (int32_t*)pMA->WelsMallocz (sizeof (int32_t*) * kiMaxSliceNumNew, "pCountMbNumInSlice");
1371 if (NULL == pCountMbNumInSlice) {
1372 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::ExtendLayerBuffer: pCountMbNumInSlice is NULL");
1373 return ENC_RETURN_MEMALLOCERR;
1374 }
1375 memset (pCountMbNumInSlice, 0, sizeof (int32_t) * kiMaxSliceNumNew);
1376 memcpy (pCountMbNumInSlice, pCurLayer->pCountMbNumInSlice, sizeof (int32_t) * kiMaxSliceNumOld);
1377 pMA->WelsFree (pCurLayer->pCountMbNumInSlice, "pCountMbNumInSlice");
1378 pCurLayer->pCountMbNumInSlice = pCountMbNumInSlice;
1379
1380 return ENC_RETURN_SUCCESS;
1381 }
1382
ReallocSliceBuffer(sWelsEncCtx * pCtx)1383 int32_t ReallocSliceBuffer (sWelsEncCtx* pCtx) {
1384
1385 SDqLayer* pCurLayer = pCtx->pCurDqLayer;
1386 int32_t iMaxSliceNumOld = pCurLayer->sSliceBufferInfo[0].iMaxSliceNum;
1387 int32_t iMaxSliceNumNew = 0;
1388 int32_t iRet = 0;
1389 int32_t iSliceIdx = 0;
1390 int32_t iSlcBuffIdx = 0;
1391 int32_t iStartIdx = 0;
1392 const int32_t kiCurDid = pCtx->uiDependencyId;
1393 SSlice* pLastCodedSlice = pCurLayer->sSliceBufferInfo[0].pSliceBuffer + (iMaxSliceNumOld - 1);
1394 SSliceArgument* pSliceArgument = & pCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument;
1395 iRet = CalculateNewSliceNum (pCtx,
1396 pLastCodedSlice,
1397 iMaxSliceNumOld,
1398 iMaxSliceNumNew);
1399
1400 if (ENC_RETURN_SUCCESS != iRet) {
1401 return iRet;
1402 }
1403
1404 iRet = ReallocateSliceList (pCtx,
1405 pSliceArgument,
1406 pCurLayer->sSliceBufferInfo[0].pSliceBuffer,
1407 iMaxSliceNumOld,
1408 iMaxSliceNumNew);
1409 if (ENC_RETURN_SUCCESS != iRet) {
1410 return iRet;
1411 }
1412
1413 pCurLayer->sSliceBufferInfo[0].iMaxSliceNum = iMaxSliceNumNew;
1414
1415 iMaxSliceNumNew = 0;
1416 for (iSlcBuffIdx = 0; iSlcBuffIdx < pCtx->iActiveThreadsNum; iSlcBuffIdx++) {
1417 iMaxSliceNumNew += pCurLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum;
1418 }
1419
1420 iRet = ExtendLayerBuffer (pCtx, pCurLayer->iMaxSliceNum, iMaxSliceNumNew);
1421 if (ENC_RETURN_SUCCESS != iRet) {
1422 return iRet;
1423 }
1424
1425 for (iSlcBuffIdx = 0; iSlcBuffIdx < pCtx->iActiveThreadsNum; iSlcBuffIdx++) {
1426 for (iSliceIdx = 0; iSliceIdx < pCurLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum; iSliceIdx++) {
1427 pCurLayer->ppSliceInLayer[iStartIdx + iSliceIdx] = pCurLayer->sSliceBufferInfo[iSlcBuffIdx].pSliceBuffer + iSliceIdx;
1428 }
1429 iStartIdx += pCurLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum;
1430 }
1431
1432 pCurLayer->iMaxSliceNum = iMaxSliceNumNew;
1433
1434 return ENC_RETURN_SUCCESS;
1435 }
1436
CheckAllSliceBuffer(SDqLayer * pCurLayer,const int32_t kiCodedSliceNum)1437 static inline int32_t CheckAllSliceBuffer (SDqLayer* pCurLayer, const int32_t kiCodedSliceNum) {
1438 int32_t iSliceIdx = 0;
1439 for (; iSliceIdx < kiCodedSliceNum ; iSliceIdx ++) {
1440 if (NULL == pCurLayer->ppSliceInLayer[iSliceIdx]) {
1441 return ENC_RETURN_UNEXPECTED;
1442 }
1443
1444 if (iSliceIdx != pCurLayer->ppSliceInLayer[iSliceIdx]->iSliceIdx) {
1445 return ENC_RETURN_UNEXPECTED;
1446 }
1447 }
1448
1449 return ENC_RETURN_SUCCESS;
1450 }
1451
ReOrderSliceInLayer(sWelsEncCtx * pCtx,const SliceModeEnum kuiSliceMode,const int32_t kiThreadNum)1452 int32_t ReOrderSliceInLayer (sWelsEncCtx* pCtx,
1453 const SliceModeEnum kuiSliceMode,
1454 const int32_t kiThreadNum) {
1455 SDqLayer* pCurLayer = pCtx->pCurDqLayer;
1456 SSlice* pSliceBuffer = NULL;
1457 int32_t iSlcBuffIdx = 0;
1458 int32_t iPartitionIdx = 0;
1459 int32_t iPartitionID = 0;
1460 int32_t iSliceIdx = 0;
1461 int32_t iSliceNumInThread = 0;
1462 int32_t iEncodeSliceNum = 0;
1463 int32_t iActualSliceIdx = 0;
1464 int32_t iNonUsedBufferNum = 0;
1465 int32_t iUsedSliceNum = 0;
1466
1467 int32_t iPartitionNum = 0;
1468 int32_t aiPartitionOffset[MAX_THREADS_NUM] = {0};
1469
1470 //for non-dynamic slice mode, iPartitionNum = 1, iPartitionOffset = 0
1471 iPartitionNum = (SM_SIZELIMITED_SLICE == kuiSliceMode) ? kiThreadNum : 1;
1472 for (iPartitionIdx = 0; iPartitionIdx < iPartitionNum; iPartitionIdx++) {
1473 aiPartitionOffset[iPartitionIdx] = iEncodeSliceNum;
1474 if (SM_SIZELIMITED_SLICE == kuiSliceMode) {
1475 iEncodeSliceNum += pCurLayer->NumSliceCodedOfPartition[iPartitionIdx];
1476 } else {
1477 iEncodeSliceNum = pCurLayer->sSliceEncCtx.iSliceNumInFrame;
1478 }
1479 }
1480
1481 if (iEncodeSliceNum != pCurLayer->sSliceEncCtx.iSliceNumInFrame) {
1482 return ENC_RETURN_UNEXPECTED;
1483 }
1484
1485 //before encode all slices in layer, slices' index are init with -1
1486 //pSliceBuffer->iSliceIdx will be set to actual slice index when encode one slice
1487 for (iSlcBuffIdx = 0; iSlcBuffIdx < kiThreadNum; iSlcBuffIdx++) {
1488 iSliceNumInThread = pCurLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum;
1489
1490 for (iSliceIdx = 0; iSliceIdx < iSliceNumInThread; iSliceIdx++) {
1491 pSliceBuffer = pCurLayer->sSliceBufferInfo[iSlcBuffIdx].pSliceBuffer + iSliceIdx;
1492 if (NULL == pSliceBuffer) {
1493 return ENC_RETURN_UNEXPECTED;
1494 }
1495
1496 if (-1 != pSliceBuffer->iSliceIdx) {
1497 iPartitionID = pSliceBuffer->iSliceIdx % iPartitionNum;
1498 iActualSliceIdx = aiPartitionOffset[iPartitionID] + pSliceBuffer->iSliceIdx / iPartitionNum;
1499 pSliceBuffer->iSliceIdx = iActualSliceIdx;
1500 pCurLayer->ppSliceInLayer[iActualSliceIdx] = pSliceBuffer;
1501 iUsedSliceNum ++;
1502 } else {
1503 pCurLayer->ppSliceInLayer[iEncodeSliceNum + iNonUsedBufferNum] = pSliceBuffer;
1504 iNonUsedBufferNum ++;
1505 }
1506 }
1507 }
1508
1509 if (iUsedSliceNum != iEncodeSliceNum ||
1510 pCurLayer->iMaxSliceNum != (iNonUsedBufferNum + iUsedSliceNum)) {
1511 return ENC_RETURN_UNEXPECTED;
1512 }
1513
1514 if (ENC_RETURN_SUCCESS != CheckAllSliceBuffer (pCurLayer, iEncodeSliceNum)) {
1515 return ENC_RETURN_UNEXPECTED;
1516 }
1517
1518 return ENC_RETURN_SUCCESS;
1519 }
1520
GetCurLayerNalCount(const SDqLayer * pCurDq,const int32_t kiCodedSliceNum)1521 int32_t GetCurLayerNalCount (const SDqLayer* pCurDq, const int32_t kiCodedSliceNum) {
1522 int32_t iTotalNalCount = 0;
1523 int32_t iSliceIdx = 0;
1524 SWelsSliceBs* pSliceBs = NULL;
1525 for (; iSliceIdx < kiCodedSliceNum; iSliceIdx++) {
1526 pSliceBs = &pCurDq->ppSliceInLayer[iSliceIdx]->sSliceBs;
1527 if (pSliceBs != NULL && pSliceBs->uiBsPos > 0) {
1528 iTotalNalCount += pSliceBs->iNalIndex;
1529 }
1530 }
1531
1532 return iTotalNalCount;
1533 }
1534
GetTotalCodedNalCount(SFrameBSInfo * pFbi)1535 int32_t GetTotalCodedNalCount (SFrameBSInfo* pFbi) {
1536 int32_t iTotalCodedNalCount = 0;
1537 for (int32_t iNalIdx = 0; iNalIdx < MAX_LAYER_NUM_OF_FRAME; iNalIdx++) {
1538 iTotalCodedNalCount += pFbi->sLayerInfo[iNalIdx].iNalCount;
1539 }
1540
1541 return iTotalCodedNalCount;
1542 }
1543
FrameBsRealloc(sWelsEncCtx * pCtx,SFrameBSInfo * pFrameBsInfo,SLayerBSInfo * pLayerBsInfo,const int32_t kiMaxSliceNumOld)1544 int32_t FrameBsRealloc (sWelsEncCtx* pCtx,
1545 SFrameBSInfo* pFrameBsInfo,
1546 SLayerBSInfo* pLayerBsInfo,
1547 const int32_t kiMaxSliceNumOld) {
1548 CMemoryAlign* pMA = pCtx->pMemAlign;
1549 int32_t iCountNals = pCtx->pOut->iCountNals;
1550 iCountNals += kiMaxSliceNumOld * (pCtx->pSvcParam->iSpatialLayerNum + pCtx->bNeedPrefixNalFlag);
1551
1552 SWelsNalRaw* pNalList = (SWelsNalRaw*)pMA->WelsMallocz (iCountNals * sizeof (SWelsNalRaw), "pOut->sNalList");
1553 if (NULL == pNalList) {
1554 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::FrameBsRealloc: pNalList is NULL");
1555 return ENC_RETURN_MEMALLOCERR;
1556 }
1557 memcpy (pNalList, pCtx->pOut->sNalList, sizeof (SWelsNalRaw) * pCtx->pOut->iCountNals);
1558 pMA->WelsFree (pCtx->pOut->sNalList, "pOut->sNalList");
1559 pCtx->pOut->sNalList = pNalList;
1560
1561 int32_t* pNalLen = (int32_t*)pMA->WelsMallocz (iCountNals * sizeof (int32_t), "pOut->pNalLen");
1562 if (NULL == pNalLen) {
1563 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "CWelsH264SVCEncoder::FrameBsRealloc: pNalLen is NULL");
1564 return ENC_RETURN_MEMALLOCERR;
1565 }
1566 memcpy (pNalLen, pCtx->pOut->pNalLen, sizeof (int32_t) * pCtx->pOut->iCountNals);
1567 pMA->WelsFree (pCtx->pOut->pNalLen, "pOut->pNalLen");
1568 pCtx->pOut->pNalLen = pNalLen;
1569
1570 pCtx->pOut->iCountNals = iCountNals;
1571 SLayerBSInfo* pLBI1, *pLBI2;
1572 pLBI1 = &pFrameBsInfo->sLayerInfo[0];
1573 pLBI1->pNalLengthInByte = pCtx->pOut->pNalLen;
1574 while (pLBI1 != pLayerBsInfo) {
1575 pLBI2 = pLBI1;
1576 ++ pLBI1;
1577 pLBI1->pNalLengthInByte = pLBI2->pNalLengthInByte + pLBI2->iNalCount;
1578 }
1579
1580 return ENC_RETURN_SUCCESS;
1581 }
1582
SliceLayerInfoUpdate(sWelsEncCtx * pCtx,SFrameBSInfo * pFrameBsInfo,SLayerBSInfo * pLayerBsInfo,const SliceModeEnum kuiSliceMode)1583 int32_t SliceLayerInfoUpdate (sWelsEncCtx* pCtx,
1584 SFrameBSInfo* pFrameBsInfo,
1585 SLayerBSInfo* pLayerBsInfo,
1586 const SliceModeEnum kuiSliceMode) {
1587 int32_t iMaxSliceNum = 0;
1588 int32_t iCodedSliceNum = 0;
1589 int32_t iCodedNalCount = 0;
1590 int32_t iRet = 0;
1591
1592 for (int32_t iSlcBuffIdx = 0; iSlcBuffIdx < pCtx->iActiveThreadsNum; iSlcBuffIdx++) {
1593 iMaxSliceNum += pCtx->pCurDqLayer->sSliceBufferInfo[iSlcBuffIdx].iMaxSliceNum;
1594 }
1595
1596 //reallocate ppSliceInLayer if total encoded slice num exceed max slice num
1597 if (iMaxSliceNum > pCtx->pCurDqLayer->iMaxSliceNum) {
1598 iRet = ExtendLayerBuffer (pCtx, pCtx->pCurDqLayer->iMaxSliceNum, iMaxSliceNum);
1599 if (ENC_RETURN_SUCCESS != iRet) {
1600 return iRet;
1601 }
1602 pCtx->pCurDqLayer->iMaxSliceNum = iMaxSliceNum;
1603 }
1604
1605 //update ppSliceInLayer based on pSliceBuffer, reordering based on slice index
1606 iRet = ReOrderSliceInLayer (pCtx, kuiSliceMode, pCtx->iActiveThreadsNum);
1607 if (ENC_RETURN_SUCCESS != iRet) {
1608 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
1609 "CWelsH264SVCEncoder::SliceLayerInfoUpdate: ReOrderSliceInLayer failed");
1610 return iRet;
1611 }
1612
1613 //Extend NalList buffer if exceed
1614 iCodedSliceNum = GetCurrentSliceNum (pCtx->pCurDqLayer);
1615 pLayerBsInfo->iNalCount = GetCurLayerNalCount (pCtx->pCurDqLayer, iCodedSliceNum);
1616 iCodedNalCount = GetTotalCodedNalCount (pFrameBsInfo);
1617
1618 if (iCodedNalCount > pCtx->pOut->iCountNals) {
1619 iRet = FrameBsRealloc (pCtx, pFrameBsInfo, pLayerBsInfo, pCtx->pCurDqLayer->iMaxSliceNum);
1620 if (ENC_RETURN_SUCCESS != iRet) {
1621 return iRet;
1622 }
1623 }
1624
1625 return ENC_RETURN_SUCCESS;
1626 }
1627
WelsCodeOneSlice(sWelsEncCtx * pEncCtx,SSlice * pCurSlice,const int32_t kiNalType)1628 int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, SSlice* pCurSlice, const int32_t kiNalType) {
1629 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
1630 SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
1631 SNalUnitHeaderExt* pNalHeadExt = &pCurLayer->sLayerInfo.sNalHeaderExt;
1632 SBitStringAux* pBs = pCurSlice->pSliceBsa;
1633 const int32_t kiDynamicSliceFlag =
1634 (pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].sSliceArgument.uiSliceMode
1635 == SM_SIZELIMITED_SLICE);
1636 if (I_SLICE == pEncCtx->eSliceType) {
1637 pNalHeadExt->bIdrFlag = 1;
1638 pCurSlice->sScaleShift = 0;
1639 } else {
1640 const uint32_t kuiTemporalId = pNalHeadExt->uiTemporalId;
1641 pCurSlice->sScaleShift = kuiTemporalId ? (kuiTemporalId - pEncCtx->pRefPic->uiTemporalId) : 0;
1642 }
1643
1644 WelsSliceHeaderExtInit (pEncCtx, pCurLayer, pCurSlice);
1645
1646 //RomRC init slice by slice
1647 if (pWelsSvcRc->bGomRC) {
1648 GomRCInitForOneSlice (pCurSlice, pWelsSvcRc->iBitsPerMb);
1649 }
1650
1651 g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pEncCtx, pBs, pCurLayer, pCurSlice,
1652 pEncCtx->pFuncList->pParametersetStrategy);
1653
1654 pCurSlice->uiLastMbQp = pCurLayer->sLayerInfo.pPpsP->iPicInitQp + pCurSlice->sSliceHeaderExt.sSliceHeader.iSliceQpDelta;
1655
1656 int32_t iEncReturn = g_pWelsSliceCoding[pNalHeadExt->bIdrFlag][kiDynamicSliceFlag] (pEncCtx, pCurSlice);
1657 if (ENC_RETURN_SUCCESS != iEncReturn)
1658 return iEncReturn;
1659
1660 WelsWriteSliceEndSyn (pCurSlice, pEncCtx->pSvcParam->iEntropyCodingModeFlag != 0);
1661
1662 return ENC_RETURN_SUCCESS;
1663 }
1664
1665 //pFunc: UpdateMbNeighbourInfoForNextSlice()
UpdateMbNeighbourInfoForNextSlice(SDqLayer * pCurDq,SMB * pMbList,const int32_t kiFirstMbIdxOfNextSlice,const int32_t kiLastMbIdxInPartition)1666 void UpdateMbNeighbourInfoForNextSlice (SDqLayer* pCurDq,
1667 SMB* pMbList,
1668 const int32_t kiFirstMbIdxOfNextSlice,
1669 const int32_t kiLastMbIdxInPartition) {
1670 SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
1671 const int32_t kiMbWidth = pSliceCtx->iMbWidth;
1672 int32_t iIdx = kiFirstMbIdxOfNextSlice;
1673 int32_t iNextSliceFirstMbIdxRowStart = ((kiFirstMbIdxOfNextSlice % kiMbWidth) ? 1 : 0);
1674 int32_t iCountMbUpdate = kiMbWidth +
1675 iNextSliceFirstMbIdxRowStart; //need to update MB(iMbXY+1) to MB(iMbXY+1+row) in common case
1676 const int32_t kiEndMbNeedUpdate = kiFirstMbIdxOfNextSlice + iCountMbUpdate;
1677 SMB* pMb = &pMbList[iIdx];
1678
1679 do {
1680 UpdateMbNeighbor (pCurDq, pMb, kiMbWidth, WelsMbToSliceIdc (pCurDq, pMb->iMbXY));
1681 ++ pMb;
1682 ++ iIdx;
1683 } while ((iIdx < kiEndMbNeedUpdate) &&
1684 (iIdx <= kiLastMbIdxInPartition));
1685 }
1686
AddSliceBoundary(sWelsEncCtx * pEncCtx,SSlice * pCurSlice,SSliceCtx * pSliceCtx,SMB * pCurMb,int32_t iFirstMbIdxOfNextSlice,const int32_t kiLastMbIdxInPartition)1687 void AddSliceBoundary (sWelsEncCtx* pEncCtx, SSlice* pCurSlice, SSliceCtx* pSliceCtx, SMB* pCurMb,
1688 int32_t iFirstMbIdxOfNextSlice, const int32_t kiLastMbIdxInPartition) {
1689 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
1690 SSlice* pSliceBuffer = pCurLayer->sSliceBufferInfo[pCurSlice->uiBufferIdx].pSliceBuffer;
1691 int32_t iCodedSliceNum = pCurLayer->sSliceBufferInfo[pCurSlice->uiBufferIdx].iCodedSliceNum;
1692 int32_t iCurMbIdx = pCurMb->iMbXY;
1693 uint16_t iCurSliceIdc = pSliceCtx->pOverallMbMap[ iCurMbIdx ];
1694 const int32_t kiSliceIdxStep = pEncCtx->iActiveThreadsNum;
1695 uint16_t iNextSliceIdc = iCurSliceIdc + kiSliceIdxStep;
1696 SSlice* pNextSlice = NULL;
1697
1698 SMB* pMbList = pCurLayer->sMbDataP;
1699
1700 //update cur pSlice info
1701 pCurSlice->sSliceHeaderExt.uiNumMbsInSlice = 1 + iCurMbIdx - pCurSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice;
1702
1703 //pNextSlice pointer/initialization
1704 if (pEncCtx->iActiveThreadsNum > 1) {
1705 pNextSlice = &pSliceBuffer[ iCodedSliceNum + 1 ];
1706 } else {
1707 pNextSlice = &pSliceBuffer[ iNextSliceIdc ];
1708 }
1709
1710 #if _DEBUG
1711 assert (NULL != pNextSlice);
1712 #endif
1713
1714 //init next pSlice info
1715 pNextSlice->bSliceHeaderExtFlag =
1716 (NAL_UNIT_CODED_SLICE_EXT == pCurLayer->sLayerInfo.sNalHeaderExt.sNalUnitHeader.eNalUnitType);
1717 memcpy (&pNextSlice->sSliceHeaderExt, &pCurSlice->sSliceHeaderExt,
1718 sizeof (SSliceHeaderExt)); // confirmed_safe_unsafe_usage
1719 pNextSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = iFirstMbIdxOfNextSlice;
1720 WelsSetMemMultiplebytes_c (pSliceCtx->pOverallMbMap + iFirstMbIdxOfNextSlice, iNextSliceIdc,
1721 (kiLastMbIdxInPartition - iFirstMbIdxOfNextSlice + 1), sizeof (uint16_t));
1722
1723 //DYNAMIC_SLICING_ONE_THREAD: update pMbList slice_neighbor_info
1724 UpdateMbNeighbourInfoForNextSlice (pCurLayer, pMbList, iFirstMbIdxOfNextSlice, kiLastMbIdxInPartition);
1725 }
1726
DynSlcJudgeSliceBoundaryStepBack(void * pCtx,void * pSlice,SSliceCtx * pSliceCtx,SMB * pCurMb,SDynamicSlicingStack * pDss)1727 bool DynSlcJudgeSliceBoundaryStepBack (void* pCtx, void* pSlice, SSliceCtx* pSliceCtx, SMB* pCurMb,
1728 SDynamicSlicingStack* pDss) {
1729 sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
1730 SSlice* pCurSlice = (SSlice*)pSlice;
1731 int32_t iCurMbIdx = pCurMb->iMbXY;
1732 uint32_t uiLen = 0;
1733 int32_t iPosBitOffset = 0;
1734 const int32_t kiActiveThreadsNum = pEncCtx->iActiveThreadsNum;
1735 const int32_t kiPartitaionId = pCurSlice->iSliceIdx % kiActiveThreadsNum;
1736 const int32_t kiEndMbIdxOfPartition = pEncCtx->pCurDqLayer->EndMbIdxOfPartition[kiPartitaionId];
1737 const bool kbCurMbNotFirstMbOfCurSlice = ((iCurMbIdx > 0) && (pSliceCtx->pOverallMbMap[iCurMbIdx] ==
1738 pSliceCtx->pOverallMbMap[iCurMbIdx - 1]));
1739 const bool kbCurMbNotLastMbOfCurPartition = iCurMbIdx < kiEndMbIdxOfPartition;
1740
1741 if (pCurSlice->bDynamicSlicingSliceSizeCtrlFlag)
1742 return false;
1743
1744 iPosBitOffset = (pDss->iCurrentPos - pDss->iStartPos);
1745 #if _DEBUG
1746 assert (iPosBitOffset >= 0);
1747 #endif
1748 uiLen = ((iPosBitOffset >> 3) + ((iPosBitOffset & 0x07) ? 1 : 0));
1749
1750 if ((kbCurMbNotFirstMbOfCurSlice
1751 && JUMPPACKETSIZE_JUDGE (uiLen, iCurMbIdx, pSliceCtx->uiSliceSizeConstraint)) /*jump_avoiding_pack_exceed*/
1752 && kbCurMbNotLastMbOfCurPartition) { //decide to add new pSlice
1753
1754 WelsLog (&pEncCtx->sLogCtx, WELS_LOG_DETAIL,
1755 "DynSlcJudgeSliceBoundaryStepBack: AddSliceBoundary: iCurMbIdx=%d, uiLen=%d, iSliceIdx=%d", iCurMbIdx, uiLen,
1756 pCurSlice->iSliceIdx);
1757
1758 if (pEncCtx->pSvcParam->iMultipleThreadIdc > 1) {
1759 WelsMutexLock (&pEncCtx->pSliceThreading->mutexSliceNumUpdate);
1760 //lock the acessing to this variable: pSliceCtx->iSliceNumInFrame
1761 }
1762 //tmp choice to avoid complex memory operation, 100520, to be modify
1763 //TODO: pSliceCtx->iSliceNumInFrame should match max slice num limitation in given profile based on standard
1764 // current change is tmp solution which equal to origin design,
1765 // as iMaxSliceNum is always equal to iMaxSliceNumConstraint in origin design
1766 // and will also extend when reallocated,
1767 // tmp change is: iMaxSliceNumConstraint is alway set to be MAXSLICENUM, will not change even reallocate
1768 AddSliceBoundary (pEncCtx, pCurSlice, pSliceCtx, pCurMb, iCurMbIdx, kiEndMbIdxOfPartition);
1769 ++ pSliceCtx->iSliceNumInFrame;
1770
1771 if (pEncCtx->pSvcParam->iMultipleThreadIdc > 1) {
1772 WelsMutexUnlock (&pEncCtx->pSliceThreading->mutexSliceNumUpdate);
1773 }
1774
1775 return true;
1776 }
1777
1778 return false;
1779 }
1780
1781 ///////////////
1782 // pMb loop
1783 ///////////////
WelsInitInterMDStruc(const SMB * pCurMb,uint16_t * pMvdCostTable,const int32_t kiMvdInterTableStride,SWelsMD * pMd)1784 inline void WelsInitInterMDStruc (const SMB* pCurMb, uint16_t* pMvdCostTable, const int32_t kiMvdInterTableStride,
1785 SWelsMD* pMd) {
1786 pMd->iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
1787 pMd->pMvdCost = &pMvdCostTable[pCurMb->uiLumaQp * kiMvdInterTableStride];
1788 pMd-> iMbPixX = (pCurMb->iMbX << 4);
1789 pMd-> iMbPixY = (pCurMb->iMbY << 4);
1790 memset (&pMd->iBlock8x8StaticIdc[0], 0, sizeof (pMd->iBlock8x8StaticIdc));
1791 }
1792 // for inter non-dynamic pSlice
WelsMdInterMbLoop(sWelsEncCtx * pEncCtx,SSlice * pSlice,void * pWelsMd,const int32_t kiSliceFirstMbXY)1793 int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY) {
1794 SWelsMD* pMd = (SWelsMD*)pWelsMd;
1795 SBitStringAux* pBs = pSlice->pSliceBsa;
1796 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
1797 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
1798 SMB* pMbList = pCurLayer->sMbDataP;
1799 SMB* pCurMb = NULL;
1800 int32_t iNumMbCoded = 0;
1801 int32_t iNextMbIdx = kiSliceFirstMbXY;
1802 int32_t iCurMbIdx = -1;
1803 const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
1804 const int32_t kiMvdInterTableStride = pEncCtx->iMvdCostTableStride;
1805 uint16_t* pMvdCostTable = &pEncCtx->pMvdCostTable[pEncCtx->iMvdCostTableSize];
1806 const int32_t kiSliceIdx = pSlice->iSliceIdx;
1807 const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
1808 int32_t iEncReturn = ENC_RETURN_SUCCESS;
1809 SDynamicSlicingStack sDss;
1810 if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
1811 WelsInitSliceCabac (pEncCtx, pSlice);
1812 sDss.pRestoreBuffer = NULL;
1813 sDss.iStartPos = sDss.iCurrentPos = 0;
1814 }
1815 pSlice->iMbSkipRun = 0;
1816 for (;;) {
1817 if (!pEncCtx->pSvcParam->iEntropyCodingModeFlag)
1818 pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, pSlice->iMbSkipRun);
1819 //point to current pMb
1820 iCurMbIdx = iNextMbIdx;
1821 pCurMb = &pMbList[ iCurMbIdx ];
1822
1823
1824 //step(1): set QP for the current MB
1825 pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
1826
1827 //step (2). save some vale for future use, initial pWelsMd
1828 WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
1829 WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);
1830
1831 TRY_REENCODING:
1832 WelsInitInterMDStruc (pCurMb, pMvdCostTable, kiMvdInterTableStride, pMd);
1833 pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);
1834 //mb_qp
1835
1836 //step (4): save from the MD process from future use
1837 WelsMdInterSaveSadAndRefMbType ((pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);
1838
1839 pEncCtx->pFuncList->pfMdBackgroundInfoUpdate (pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag,
1840 pEncCtx->pRefPic->iPictureType);
1841
1842 //step (5): update cache
1843 UpdateNonZeroCountCache (pCurMb, pMbCache);
1844
1845 //step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
1846
1847 iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
1848 if (!pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
1849 if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND && (pCurMb->uiLumaQp < 50)) {
1850 pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
1851 UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
1852 goto TRY_REENCODING;
1853 }
1854 }
1855 if (ENC_RETURN_SUCCESS != iEncReturn)
1856 return iEncReturn;
1857
1858
1859 //step (7): reconstruct current MB
1860 pCurMb->uiSliceIdc = kiSliceIdx;
1861 OutputPMbWithoutConstructCsRsNoCopy (pEncCtx, pCurLayer, pSlice, pCurMb);
1862
1863 #if defined(MB_TYPES_CHECK)
1864 WelsCountMbType (pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb);
1865 #endif//MB_TYPES_CHECK
1866
1867 //step (8): update status and other parameters
1868 pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, pMd->iCostLuma, pSlice);
1869
1870 /*judge if all pMb in cur pSlice has been encoded*/
1871 ++ iNumMbCoded;
1872 iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);
1873 //whether all of MB in current pSlice encoded or not
1874 if (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {
1875 break;
1876 }
1877 }
1878
1879 if (pSlice->iMbSkipRun) {
1880 BsWriteUE (pBs, pSlice->iMbSkipRun);
1881 }
1882
1883 return iEncReturn;
1884 }
1885
1886 // Only for inter dynamic slicing
WelsMdInterMbLoopOverDynamicSlice(sWelsEncCtx * pEncCtx,SSlice * pSlice,void * pWelsMd,const int32_t kiSliceFirstMbXY)1887 int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,
1888 const int32_t kiSliceFirstMbXY) {
1889 SWelsMD* pMd = (SWelsMD*)pWelsMd;
1890 SBitStringAux* pBs = pSlice->pSliceBsa;
1891 SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
1892 SSliceCtx* pSliceCtx = &pCurLayer->sSliceEncCtx;
1893 SMbCache* pMbCache = &pSlice->sMbCacheInfo;
1894 SMB* pMbList = pCurLayer->sMbDataP;
1895 SMB* pCurMb = NULL;
1896 int32_t iNumMbCoded = 0;
1897 const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
1898 int32_t iNextMbIdx = kiSliceFirstMbXY;
1899 int32_t iCurMbIdx = -1;
1900 const int32_t kiMvdInterTableStride = pEncCtx->iMvdCostTableStride;
1901 uint16_t* pMvdCostTable = &pEncCtx->pMvdCostTable[pEncCtx->iMvdCostTableSize];
1902 const int32_t kiSliceIdx = pSlice->iSliceIdx;
1903 const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);
1904 const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
1905 int32_t iEncReturn = ENC_RETURN_SUCCESS;
1906
1907 SDynamicSlicingStack sDss;
1908 if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {
1909 WelsInitSliceCabac (pEncCtx, pSlice);
1910 sDss.iStartPos = sDss.iCurrentPos = 0;
1911 sDss.pRestoreBuffer = pEncCtx->pDynamicBsBuffer[kiPartitionId];
1912 } else {
1913 sDss.iStartPos = BsGetBitsPos (pBs);
1914 }
1915 pSlice->iMbSkipRun = 0;
1916 for (;;) {
1917 //DYNAMIC_SLICING_ONE_THREAD - MultiD
1918 //stack pBs pointer
1919 pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, pSlice->iMbSkipRun);
1920
1921 //point to current pMb
1922 iCurMbIdx = iNextMbIdx;
1923 pCurMb = &pMbList[ iCurMbIdx ];
1924
1925 //step(1): set QP for the current MB
1926 pEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);
1927 // if already reaches the largest number of slices, set QPs to the upper bound
1928 if (pSlice->bDynamicSlicingSliceSizeCtrlFlag) {
1929 //a clearer logic may be:
1930 //if there is no need from size control from the pSlice size, the QP will be decided by RC; else it will be set to the max QP
1931 // however, there are some parameter updating in the rc_mb_init() function, so it cannot be skipped?
1932 pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;
1933 pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
1934 }
1935
1936 //step (2). save some vale for future use, initial pWelsMd
1937 WelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
1938 WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);
1939
1940 TRY_REENCODING:
1941 WelsInitInterMDStruc (pCurMb, pMvdCostTable, kiMvdInterTableStride, pMd);
1942 pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);
1943 //mb_qp
1944
1945 //step (4): save from the MD process from future use
1946 WelsMdInterSaveSadAndRefMbType ((pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);
1947
1948 pEncCtx->pFuncList->pfMdBackgroundInfoUpdate (pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag,
1949 pEncCtx->pRefPic->iPictureType);
1950
1951 //step (5): update cache
1952 UpdateNonZeroCountCache (pCurMb, pMbCache);
1953
1954 //step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
1955
1956
1957
1958 iEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);
1959 if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND && (pCurMb->uiLumaQp < 50)) {
1960 pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
1961 UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);
1962 goto TRY_REENCODING;
1963 }
1964 if (ENC_RETURN_SUCCESS != iEncReturn)
1965 return iEncReturn;
1966
1967
1968 //DYNAMIC_SLICING_ONE_THREAD - MultiD
1969 sDss.iCurrentPos = pEncCtx->pFuncList->pfGetBsPosition (pSlice);
1970 if (DynSlcJudgeSliceBoundaryStepBack (pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss)) {
1971 pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);
1972 pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx -
1973 1; // update LastCodedMbIdxOfPartition, need to -1 due to stepping back
1974 ++ pCurLayer->NumSliceCodedOfPartition[kiPartitionId];
1975
1976 break;
1977 }
1978
1979 //step (7): reconstruct current MB
1980 pCurMb->uiSliceIdc = kiSliceIdx;
1981 OutputPMbWithoutConstructCsRsNoCopy (pEncCtx, pCurLayer, pSlice, pCurMb);
1982
1983 #if defined(MB_TYPES_CHECK)
1984 WelsCountMbType (pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb);
1985 #endif//MB_TYPES_CHECK
1986
1987 //step (8): update status and other parameters
1988 pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, pMd->iCostLuma, pSlice);
1989
1990 /*judge if all pMb in cur pSlice has been encoded*/
1991 ++ iNumMbCoded;
1992 iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);
1993 //whether all of MB in current pSlice encoded or not
1994 if (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {
1995 pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx;
1996 ++ pCurLayer->NumSliceCodedOfPartition[kiPartitionId];
1997
1998 break;
1999 }
2000 }
2001
2002 if (pSlice->iMbSkipRun) {
2003 BsWriteUE (pBs, pSlice->iMbSkipRun);
2004 }
2005
2006 return iEncReturn;
2007 }
2008
2009 }//namespace WelsEnc
2010