• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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