History

Initial Commit

Ethan Hugg committed 12 years ago

Commit 70e5e621 parent bd509b2308 files · +97095 −-5Browse files

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

Unified · Split

codec/encoder/core/src/svc_encode_slice.cpp+1194−0
@@ -0,0 +1,1194 @@
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 <string.h>
42+#include <assert.h>
43+#include "ls_defines.h"
44+#include "svc_encode_slice.h"
45+#include "svc_enc_golomb.h"
46+#include "svc_base_layer_md.h"
47+#include "svc_encode_mb.h"
48+#include "mv_pred.h"
49+#include "svc_set_mb_syn_cavlc.h"
50+#include "encode_mb_aux.h"
51+#include "decode_mb_aux.h"
52+#include "svc_mode_decision.h"
53+#include "cpu_core.h"
54+#include "svc_motion_estimate.h"
55+#include "sample.h"
56+#include "wels_func_ptr_def.h"
57+#include "utils.h"
58+
59+namespace WelsSVCEnc {
60+//#define ENC_TRACE
61+
62+typedef void (*PWelsCodingSliceFunc)( sWelsEncCtx *pCtx, SSlice *pSlice );
63+typedef void (*PWelsSliceHeaderWriteFunc)( SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice *pSlice, int32_t* pPpsIdDelta );
64+
65+void UpdateNonZeroCountCache(SMB *pMb, SMbCache *pMbCache)
66+{
67+ ST32(&pMbCache->iNonZeroCoeffCount[9], LD32(&pMb->pNonZeroCount[ 0]));
68+ ST32(&pMbCache->iNonZeroCoeffCount[17], LD32(&pMb->pNonZeroCount[ 4]));
69+ ST32(&pMbCache->iNonZeroCoeffCount[25], LD32(&pMb->pNonZeroCount[ 8]));
70+ ST32(&pMbCache->iNonZeroCoeffCount[33], LD32(&pMb->pNonZeroCount[12]));
71+
72+ ST16(&pMbCache->iNonZeroCoeffCount[14], LD16(&pMb->pNonZeroCount[16]));
73+ ST16(&pMbCache->iNonZeroCoeffCount[38], LD16(&pMb->pNonZeroCount[18]));
74+ ST16(&pMbCache->iNonZeroCoeffCount[22], LD16(&pMb->pNonZeroCount[20]));
75+ ST16(&pMbCache->iNonZeroCoeffCount[46], LD16(&pMb->pNonZeroCount[22]));
76+}
77+
78+void WelsSliceHeaderScalExtInit( SDqLayer* pCurLayer, SSlice *pSlice )
79+{
80+ SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
81+ SNalUnitHeaderExt* pNalHeadExt= &pCurLayer->sLayerInfo.sNalHeaderExt;
82+
83+ uint8_t uiDependencyId = pNalHeadExt->uiDependencyId;
84+
85+ pSliceHeadExt->bSliceSkipFlag = false;
86+
87+ if ( uiDependencyId > 0 ) //spatial EL
88+ {
89+ //bothe adaptive and default flags should equal to 0.
90+ pSliceHeadExt->bAdaptiveBaseModeFlag =
91+ pSliceHeadExt->bAdaptiveMotionPredFlag =
92+ pSliceHeadExt->bAdaptiveResidualPredFlag = false;
93+
94+ pSliceHeadExt->bDefaultBaseModeFlag =
95+ pSliceHeadExt->bDefaultMotionPredFlag =
96+ pSliceHeadExt->bDefaultResidualPredFlag = false;
97+ }
98+}
99+
100+void WelsSliceHeaderExtInit( sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice *pSlice )
101+{
102+ SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt;
103+ SSliceHeader* pCurSliceHeader = &pCurSliceExt->sSliceHeader;
104+
105+ pCurSliceHeader->eSliceType = pEncCtx->eSliceType;
106+
107+ pCurSliceExt->bStoreRefBasePicFlag = false;
108+
109+ pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice( pCurLayer->pSliceEncCtx, pSlice->uiSliceIdx );
110+
111+ pCurSliceHeader->iFrameNum = pEncCtx->iFrameNum;
112+ pCurSliceHeader->uiIdrPicId = pEncCtx->sPSOVector.uiIdrPicId; //??
113+
114+ pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc; // 0
115+
116+ if ( P_SLICE == pEncCtx->eSliceType )
117+ {
118+ pCurSliceHeader->uiNumRefIdxL0Active = 1;
119+ if ( pCurSliceHeader->uiRefCount > 0 &&
120+ pCurSliceHeader->uiRefCount < pCurLayer->sLayerInfo.pSpsP->iNumRefFrames )
121+ {
122+ pCurSliceHeader->bNumRefIdxActiveOverrideFlag = true;
123+ pCurSliceHeader->uiNumRefIdxL0Active = pCurSliceHeader->uiRefCount;
124+ }
125+ //to solve mismatch between debug&release
126+ else
127+ {
128+ pCurSliceHeader->bNumRefIdxActiveOverrideFlag = false;
129+ }
130+ }
131+
132+ pCurSliceHeader->iSliceQpDelta = pEncCtx->iGlobalQp - pCurLayer->sLayerInfo.pPpsP->iPicInitQp;
133+
134+ //for deblocking initial
135+ pCurSliceHeader->uiDisableDeblockingFilterIdc = pCurLayer->iLoopFilterDisableIdc;
136+ pCurSliceHeader->iSliceAlphaC0Offset = pCurLayer->iLoopFilterAlphaC0Offset; // need update iSliceAlphaC0Offset & iSliceBetaOffset for pSlice-header if loop_filter_idc != 1
137+ pCurSliceHeader->iSliceBetaOffset = pCurLayer->iLoopFilterBetaOffset;
138+ pCurSliceExt->uiDisableInterLayerDeblockingFilterIdc = pCurLayer->uiDisableInterLayerDeblockingFilterIdc;
139+
140+ if ( pSlice->bSliceHeaderExtFlag )
141+ {
142+ WelsSliceHeaderScalExtInit( pCurLayer, pSlice );
143+ }
144+ else
145+ {
146+ //both adaptive and default flags should equal to 0.
147+ pCurSliceExt->bAdaptiveBaseModeFlag =
148+ pCurSliceExt->bAdaptiveMotionPredFlag =
149+ pCurSliceExt->bAdaptiveResidualPredFlag = false;
150+
151+ pCurSliceExt->bDefaultBaseModeFlag =
152+ pCurSliceExt->bDefaultMotionPredFlag =
153+ pCurSliceExt->bDefaultResidualPredFlag = false;
154+ }
155+}
156+
157+/* count MB types if enabled FRAME_INFO_OUTPUT*/
158+#if defined(MB_TYPES_CHECK)
159+void WelsCountMbType(int32_t (*iMbCount)[18], const EWelsSliceType keSt, const SMB* kpMb)
160+{
161+ if (NULL == iMbCount)
162+ return;
163+
164+ switch( kpMb->uiMbType ) {
165+ case MB_TYPE_INTRA4x4:
166+ ++ iMbCount[keSt][Intra4x4];
167+ break;
168+ case MB_TYPE_INTRA16x16:
169+ ++ iMbCount[keSt][Intra16x16];
170+ break;
171+ case MB_TYPE_SKIP:
172+ ++ iMbCount[keSt][PSkip];
173+ break;
174+ case MB_TYPE_16x16:
175+ ++ iMbCount[keSt][Inter16x16];
176+ break;
177+ case MB_TYPE_16x8:
178+ ++ iMbCount[keSt][Inter16x8];
179+ break;
180+ case MB_TYPE_8x16:
181+ ++ iMbCount[eSt][Inter8x16];
182+ break;
183+ case MB_TYPE_8x8:
184+ ++ iMbCount[keSt][Inter8x8];
185+ break;
186+ case MB_TYPE_INTRA_BL:
187+ ++ iMbCount[keSt][7];
188+ break;
189+ default:
190+ break;
191+ }
192+}
193+#endif//MB_TYPES_CHECK
194+
195+/*!
196+* \brief write reference picture list on reordering syntax in Slice header
197+*/
198+void WriteReferenceReorder( SBitStringAux *pBs, SSliceHeader *sSliceHeader )
199+{
200+ SRefPicListReorderSyntax *pRefOrdering = &sSliceHeader->sRefReordering;
201+ uint8_t eSliceType = sSliceHeader->eSliceType % 5;
202+ int16_t n = 0;
203+
204+ if ( I_SLICE != eSliceType && SI_SLICE != eSliceType ) // !I && !SI
205+ {
206+ BsWriteOneBit( pBs, true );
207+// {
208+ uint16_t uiReorderingOfPicNumsIdc;
209+ do
210+ {
211+ uiReorderingOfPicNumsIdc = pRefOrdering->SReorderingSyntax[n].uiReorderingOfPicNumsIdc;
212+ BsWriteUE( pBs, uiReorderingOfPicNumsIdc );
213+ if ( 0 == uiReorderingOfPicNumsIdc || 1 == uiReorderingOfPicNumsIdc )
214+ BsWriteUE( pBs, pRefOrdering->SReorderingSyntax[n].uiAbsDiffPicNumMinus1 );
215+ else if ( 2 == uiReorderingOfPicNumsIdc )
216+ BsWriteUE( pBs, pRefOrdering->SReorderingSyntax[n].iLongTermPicNum );
217+
218+ n ++;
219+ } while ( 3 != uiReorderingOfPicNumsIdc );
220+// }
221+ }
222+}
223+
224+/*!
225+* \brief write reference picture marking syntax in pSlice header
226+*/
227+void WriteRefPicMarking( SBitStringAux *pBs, SSliceHeader *pSliceHeader, SNalUnitHeaderExt *pNalHdrExt )
228+{
229+ SRefPicMarking *sRefMarking = &pSliceHeader->sRefMarking;
230+ int16_t n = 0;
231+
232+ if ( pNalHdrExt->bIdrFlag )
233+ {
234+ BsWriteOneBit( pBs, sRefMarking->bNoOutputOfPriorPicsFlag );
235+ BsWriteOneBit( pBs, sRefMarking->bLongTermRefFlag );
236+ }
237+ else
238+ {
239+ BsWriteOneBit( pBs, sRefMarking->bAdaptiveRefPicMarkingModeFlag );
240+
241+ if ( sRefMarking->bAdaptiveRefPicMarkingModeFlag )
242+ {
243+ int32_t iMmcoType;
244+ do
245+ {
246+ iMmcoType = sRefMarking->SMmcoRef[n].iMmcoType;
247+ BsWriteUE( pBs, iMmcoType );
248+ if ( 1 == iMmcoType || 3 == iMmcoType )
249+ BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iDiffOfPicNum - 1 );
250+
251+ if ( 2 == iMmcoType )
252+ BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iLongTermPicNum );
253+
254+ if ( 3 == iMmcoType || 6 == iMmcoType )
255+ BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iLongTermFrameIdx );
256+
257+ if ( 4 == iMmcoType )
258+ BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iMaxLongTermFrameIdx + 1 );
259+
260+ n ++;
261+ } while ( 0 != iMmcoType );
262+ }
263+
264+ }
265+}
266+
267+void WelsSliceHeaderWrite( SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice *pSlice, int32_t* pPpsIdDelta )
268+{
269+ SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
270+ SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
271+ SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
272+ SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt;
273+
274+ BsWriteUE( pBs, pSliceHeader->iFirstMbInSlice );
275+ BsWriteUE( pBs, pSliceHeader->eSliceType ); /* same type things */
276+
277+ BsWriteUE( pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId] );
278+
279+ BsWriteBits( pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum );
280+
281+ if( pNalHead->bIdrFlag ) /* NAL IDR */
282+ {
283+ BsWriteUE( pBs, pSliceHeader->uiIdrPicId );
284+ }
285+
286+ BsWriteBits( pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb );
287+
288+ if ( P_SLICE == pSliceHeader->eSliceType )
289+ {
290+ BsWriteOneBit( pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag );
291+ if ( pSliceHeader->bNumRefIdxActiveOverrideFlag )
292+ {
293+ BsWriteUE( pBs, pSliceHeader->uiNumRefIdxL0Active - 1 );
294+ }
295+ }
296+
297+ if ( !pNalHead->bIdrFlag )
298+ WriteReferenceReorder( pBs, pSliceHeader );
299+
300+ if ( pNalHead->sNalHeader.uiNalRefIdc )
301+ {
302+ WriteRefPicMarking( pBs, pSliceHeader, pNalHead );
303+ }
304+
305+ BsWriteSE( pBs, pSliceHeader->iSliceQpDelta ); /* pSlice qp delta */
306+
307+ if( pPps->bDeblockingFilterControlPresentFlag )
308+ {
309+ switch( pSliceHeader->uiDisableDeblockingFilterIdc )
310+ {
311+ case 0:
312+ case 3:
313+ case 4:
314+ case 6:
315+ BsWriteUE( pBs, 0 );
316+ break;
317+ case 1:
318+ BsWriteUE( pBs, 1 );
319+ break;
320+ case 2:
321+ case 5:
322+ BsWriteUE( pBs, 2 );
323+ break;
324+ default :
325+ fprintf( stderr, "pData error for deblocking" );
326+ break;
327+ }
328+ if ( 1 != pSliceHeader->uiDisableDeblockingFilterIdc )
329+ {
330+ BsWriteSE( pBs, pSliceHeader->iSliceAlphaC0Offset >> 1 );
331+ BsWriteSE( pBs, pSliceHeader->iSliceBetaOffset >> 1 );
332+ }
333+ }
334+}
335+
336+void WelsSliceHeaderExtWrite( SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice *pSlice, int32_t *pPpsIdDelta )
337+{
338+ SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
339+ SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
340+ SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
341+ SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
342+ SSliceHeader* pSliceHeader = &pSliceHeadExt->sSliceHeader;
343+ SNalUnitHeaderExt* pNalHead = &pCurLayer->sLayerInfo.sNalHeaderExt;
344+
345+ BsWriteUE( pBs, pSliceHeader->iFirstMbInSlice );
346+ BsWriteUE( pBs, pSliceHeader->eSliceType ); /* same type things */
347+
348+ BsWriteUE( pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId] );
349+
350+ BsWriteBits( pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum );
351+
352+ if( pNalHead->bIdrFlag ) /* NAL IDR */
353+ {
354+ BsWriteUE( pBs, pSliceHeader->uiIdrPicId );
355+ }
356+
357+ BsWriteBits( pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb );
358+// {
359+ if ( P_SLICE == pSliceHeader->eSliceType )
360+ {
361+ BsWriteOneBit( pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag );
362+ if ( pSliceHeader->bNumRefIdxActiveOverrideFlag )
363+ {
364+ BsWriteUE( pBs, pSliceHeader->uiNumRefIdxL0Active - 1 );
365+ }
366+ }
367+
368+ if ( !pNalHead->bIdrFlag )
369+ WriteReferenceReorder( pBs, pSliceHeader );
370+
371+ if ( pNalHead->sNalHeader.uiNalRefIdc )
372+ {
373+ WriteRefPicMarking( pBs, pSliceHeader, pNalHead );
374+
375+ if ( !pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag )
376+ {
377+ BsWriteOneBit( pBs, pSliceHeadExt->bStoreRefBasePicFlag );
378+ }
379+ }
380+// }
381+
382+ BsWriteSE( pBs, pSliceHeader->iSliceQpDelta ); /* pSlice qp delta */
383+
384+ if( pPps->bDeblockingFilterControlPresentFlag )
385+ {
386+ BsWriteUE( pBs, pSliceHeader->uiDisableDeblockingFilterIdc );
387+ if ( 1 != pSliceHeader->uiDisableDeblockingFilterIdc )
388+ {
389+ BsWriteSE( pBs, pSliceHeader->iSliceAlphaC0Offset >> 1 );
390+ BsWriteSE( pBs, pSliceHeader->iSliceBetaOffset >> 1 );
391+ }
392+ }
393+
394+#if !defined(DISABLE_FMO_FEATURE)
395+ if ( pPps->uiNumSliceGroups > 1 &&
396+ pPps->uiSliceGroupMapType >= 3 &&
397+ pPps->uiSliceGroupMapType <= 5 )
398+ {
399+ int32_t iNumBits;
400+ if ( pPps->uiSliceGroupChangeRate )
401+ {
402+ iNumBits = WELS_CEILLOG2(1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate);
403+ BsWriteBits( pBs, iNumBits, pSliceHeader->iSliceGroupChangeCycle );
404+ }
405+ }
406+#endif//!DISABLE_FMO_FEATURE
407+
408+ if ( false )
409+ {
410+ BsWriteOneBit( pBs, pSliceHeadExt->bSliceSkipFlag );
411+ if ( pSliceHeadExt->bSliceSkipFlag )
412+ {
413+ BsWriteUE( pBs, pSliceHeadExt->uiNumMbsInSlice - 1 );
414+ }
415+ else
416+ {
417+ BsWriteOneBit( pBs, pSliceHeadExt->bAdaptiveBaseModeFlag );
418+ if ( !pSliceHeadExt->bAdaptiveBaseModeFlag )
419+ {
420+ BsWriteOneBit( pBs, pSliceHeadExt->bDefaultBaseModeFlag );
421+ }
422+
423+ if ( !pSliceHeadExt->bDefaultBaseModeFlag )
424+ {
425+ BsWriteOneBit( pBs, 0 );
426+ BsWriteOneBit( pBs, 0 );
427+ }
428+
429+ BsWriteOneBit( pBs, pSliceHeadExt->bAdaptiveResidualPredFlag );
430+ if ( !pSliceHeadExt->bAdaptiveResidualPredFlag )
431+ {
432+ BsWriteOneBit( pBs, 0);
433+ }
434+ }
435+ if ( 1 == pSubSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag )
436+ {
437+ BsWriteOneBit( pBs, pSliceHeadExt->bTcoeffLevelPredFlag );
438+ }
439+
440+ }
441+
442+ if ( !pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag )
443+ {
444+ BsWriteBits( pBs, 4, 0 );
445+ BsWriteBits( pBs, 4, 15 );
446+ }
447+}
448+
449+//only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
450+//only for inter part
451+void WelsInterMbEncode( sWelsEncCtx* pEncCtx, SSlice *pSlice, SMB* pCurMb )
452+{
453+ SMbCache* pMbCache = &pSlice->sMbCacheInfo;
454+
455+ WelsDctMb(pMbCache->pCoeffLevel, pMbCache->SPicData.pEncMb[0], pEncCtx->pCurDqLayer->iEncStride[0], pMbCache->pMemPredLuma, pEncCtx->pFuncList->pfDctFourT4 );
456+ WelsEncInterY( pEncCtx->pFuncList, pCurMb, pMbCache );
457+}
458+
459+
460+//only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
461+//only for I SSlice
462+void WelsIMbChromaEncode( sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache *pMbCache )
463+{
464+ SWelsFuncPtrList *pFunc = pEncCtx->pFuncList;
465+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
466+ const int32_t kiEncStride = pCurLayer->iEncStride[1];
467+ const int32_t kiCsStride = pCurLayer->iCsStride[1];
468+ int16_t *pCurRS = pMbCache->pCoeffLevel;
469+ uint8_t* pBestPred = pMbCache->pBestPredIntraChroma;
470+ uint8_t* pCsCb = pMbCache->SPicData.pCsMb[1];
471+ uint8_t* pCsCr = pMbCache->SPicData.pCsMb[2];
472+
473+ //cb
474+ pFunc->pfDctFourT4( pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8);
475+ WelsEncRecUV( pFunc, pCurMb, pMbCache, pCurRS, 1 );
476+ pFunc->pfIDctFourT4( pCsCb, kiCsStride, pBestPred, 8, pCurRS );
477+
478+ //cr
479+ pFunc->pfDctFourT4( pCurRS+64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred+64, 8);
480+ WelsEncRecUV( pFunc, pCurMb, pMbCache, pCurRS+64, 2 );
481+ pFunc->pfIDctFourT4( pCsCr, kiCsStride, pBestPred+64, 8, pCurRS+64 );
482+}
483+
484+
485+//only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
486+//for P SSlice (intra part + inter part)
487+void WelsPMbChromaEncode( sWelsEncCtx* pEncCtx, SSlice *pSlice, SMB* pCurMb )
488+{
489+ SWelsFuncPtrList *pFunc = pEncCtx->pFuncList;
490+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
491+ const int32_t kiEncStride = pCurLayer->iEncStride[1];
492+ SMbCache* pMbCache = &pSlice->sMbCacheInfo;
493+ int16_t *pCurRS = pMbCache->pCoeffLevel+256;
494+ uint8_t* pBestPred = pMbCache->pMemPredChroma;
495+
496+ pFunc->pfDctFourT4(pCurRS, pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred, 8);
497+ pFunc->pfDctFourT4(pCurRS+64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred+64, 8);
498+
499+ WelsEncRecUV(pFunc, pCurMb, pMbCache, pCurRS, 1);
500+ WelsEncRecUV(pFunc, pCurMb, pMbCache, pCurRS+64, 2);
501+}
502+
503+void OutputPMbWithoutConstructCsRsNoCopy( sWelsEncCtx *pCtx, SDqLayer* pDq, SSlice *pSlice, SMB* pMb )
504+{
505+ if ( IS_INTER( pMb->uiMbType ) || IS_I_BL(pMb->uiMbType) ) //intra have been reconstructed, NO COPY from CS to pDecPic--
506+ {
507+ SMbCache* pMbCache = &pSlice->sMbCacheInfo;
508+ uint8_t* pDecY = pMbCache->SPicData.pDecMb[0];
509+ uint8_t* pDecU = pMbCache->SPicData.pDecMb[1];
510+ uint8_t* pDecV = pMbCache->SPicData.pDecMb[2];
511+ int16_t *pScaledTcoeff = pMbCache->pCoeffLevel;
512+ const int32_t kiDecStrideLuma = pDq->pDecPic->iLineSize[0];
513+ const int32_t kiDecStrideChroma = pDq->pDecPic->iLineSize[1];
514+ PIDctFunc pfIdctFour4x4 = pCtx->pFuncList->pfIDctFourT4;
515+
516+ WelsIDctT4RecOnMb( pDecY, kiDecStrideLuma, pDecY, kiDecStrideLuma, pScaledTcoeff, pfIdctFour4x4 );
517+ pfIdctFour4x4( pDecU, kiDecStrideChroma, pDecU, kiDecStrideChroma, pScaledTcoeff + 256 );
518+ pfIdctFour4x4( pDecV, kiDecStrideChroma, pDecV, kiDecStrideChroma, pScaledTcoeff + 320 );
519+ }
520+}
521+
522+// for intra non-dynamic pSlice
523+//encapsulate two kinds of reconstruction:
524+//first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
525+//second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)
526+void WelsISliceMdEnc( sWelsEncCtx* pEncCtx, SSlice *pSlice ) //pMd + encoding
527+{
528+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
529+ SSliceCtx* pSliceCtx = pCurLayer->pSliceEncCtx;
530+ SMbCache *pMbCache = &pSlice->sMbCacheInfo;
531+ SSliceHeaderExt *pSliceHdExt = &pSlice->sSliceHeaderExt;
532+ SMB* pMbList = pCurLayer->sMbDataP;
533+ SMB* pCurMb = NULL;
534+ const int32_t kiSliceFirstMbXY = pSliceHdExt->sSliceHeader.iFirstMbInSlice;
535+ int32_t iNextMbIdx = kiSliceFirstMbXY;
536+ const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
537+ int32_t iCurMbIdx = 0, iNumMbCoded = 0;
538+ const int32_t kiSliceIdx = pSlice->uiSliceIdx;
539+ const uint8_t kuiChromaQpIndexOffset= pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
540+ SWelsMD sMd;
541+
542+ for ( ; ; )
543+ {
544+ iCurMbIdx = iNextMbIdx;
545+ pCurMb = &pMbList[ iCurMbIdx ];
546+ pCurMb->uiLumaQp = pEncCtx->iGlobalQp;
547+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51(pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
548+
549+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInit(pEncCtx, pCurMb, pSlice);
550+
551+ sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
552+
553+ WelsMdIntraInit( pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY );
554+ WelsMdIntraMb( pEncCtx, &sMd, pCurMb, pMbCache );
555+ UpdateNonZeroCountCache( pCurMb, pMbCache );
556+
557+ WelsSpatialWriteMbSyn( pEncCtx, pSlice, pCurMb );
558+
559+ pCurMb->uiSliceIdc = kiSliceIdx;
560+
561+ #if defined(MB_TYPES_CHECK)
562+ WelsCountMbType( pEncCtx->sPerInfo.iMbCount, I_SLICE, pCurMb );
563+ #endif//MB_TYPES_CHECK
564+
565+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate(pEncCtx,pCurMb,sMd.iCostLuma,pSlice);
566+
567+ ++iNumMbCoded;
568+
569+ iNextMbIdx = WelsGetNextMbOfSlice( pSliceCtx, iCurMbIdx );
570+ if ( iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb )
571+ {
572+ break;
573+ }
574+ }
575+}
576+
577+// Only for intra dynamic slicing
578+void WelsISliceMdEncDynamic( sWelsEncCtx* pEncCtx, SSlice *pSlice ) //pMd + encoding
579+{
580+ SBitStringAux* pBs = pSlice->pSliceBsa;
581+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
582+ SSliceCtx* pSliceCtx = pCurLayer->pSliceEncCtx;
583+ SMbCache *pMbCache = &pSlice->sMbCacheInfo;
584+ SSliceHeaderExt *pSliceHdExt = &pSlice->sSliceHeaderExt;
585+ SMB* pMbList = pCurLayer->sMbDataP;
586+ SMB* pCurMb = NULL;
587+ const int32_t kiSliceFirstMbXY = pSliceHdExt->sSliceHeader.iFirstMbInSlice;
588+ int32_t iNextMbIdx = kiSliceFirstMbXY;
589+ const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
590+ int32_t iCurMbIdx = 0, iNumMbCoded = 0;
591+ const int32_t kiSliceIdx = pSlice->uiSliceIdx;
592+ const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);
593+ const uint8_t kuiChromaQpIndexOffset= pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
594+
595+ SWelsMD sMd;
596+ SDynamicSlicingStack sDss;
597+ sDss.iStartPos = BsGetBitsPos(pBs);
598+
599+ for ( ; ; )
600+ {
601+ iCurMbIdx = iNextMbIdx;
602+ pCurMb = &pMbList[ iCurMbIdx ];
603+ pCurMb->uiLumaQp = pEncCtx->iGlobalQp;
604+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51(pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
605+
606+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInit(pEncCtx, pCurMb, pSlice);
607+ // if already reaches the largest number of slices, set QPs to the upper bound
608+ if (pSlice->bDynamicSlicingSliceSizeCtrlFlag)
609+ {
610+ pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;
611+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51(pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
612+ }
613+
614+ sMd.iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
615+
616+ WelsMdIntraInit( pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY );
617+ WelsMdIntraMb( pEncCtx, &sMd, pCurMb, pMbCache );
618+ UpdateNonZeroCountCache( pCurMb, pMbCache );
619+ //stack pBs pointer
620+ sDss.pBsStackBufPtr = pBs->pBufPtr;
621+ sDss.uiBsStackCurBits = pBs->uiCurBits;
622+ sDss.iBsStackLeftBits = pBs->iLeftBits;
623+
624+ WelsSpatialWriteMbSyn( pEncCtx, pSlice, pCurMb );
625+
626+ sDss.iCurrentPos = BsGetBitsPos(pBs);
627+
628+ if ( DynSlcJudgeSliceBoundaryStepBack( pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss ) )//islice
629+ {
630+ //stack pBs pointer
631+ pBs->pBufPtr = sDss.pBsStackBufPtr;
632+ pBs->uiCurBits = sDss.uiBsStackCurBits;
633+ pBs->iLeftBits = sDss.iBsStackLeftBits;
634+
635+ pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx-1; // update pLastCodedMbIdxOfPartition, need to -1 due to stepping back
636+ ++ pCurLayer->pNumSliceCodedOfPartition[kiPartitionId];
637+
638+ break;
639+ }
640+
641+ pCurMb->uiSliceIdc = kiSliceIdx;
642+
643+#if defined(MB_TYPES_CHECK)
644+ WelsCountMbType( pEncCtx->sPerInfo.iMbCount, I_SLICE, pCurMb );
645+#endif//MB_TYPES_CHECK
646+
647+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate(pEncCtx,pCurMb,sMd.iCostLuma,pSlice);
648+
649+ ++iNumMbCoded;
650+
651+ iNextMbIdx = WelsGetNextMbOfSlice( pSliceCtx, iCurMbIdx );
652+ //whether all of MB in current pSlice encoded or not
653+ if ( iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb )
654+ {
655+ pSliceCtx->pCountMbNumInSlice[kiSliceIdx] = iCurMbIdx - pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId];
656+ pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx; // update pLastCodedMbIdxOfPartition, finish coding, use iCurMbIdx directly
657+ break;
658+ }
659+ }
660+}
661+
662+//encapsulate two kinds of reconstruction:
663+// first. store base or highest Dependency Layer with only one quality (without CS RS reconstruction)
664+// second. lower than highest Dependency Layer, and for every Dependency Layer with one quality layer(single layer)
665+void WelsPSliceMdEnc( sWelsEncCtx* pEncCtx, SSlice *pSlice, const bool_t kbIsHighestDlayerFlag ) //pMd + encoding
666+{
667+ const SSliceHeaderExt *kpShExt = &pSlice->sSliceHeaderExt;
668+ const SSliceHeader *kpSh = &kpShExt->sSliceHeader;
669+ const int32_t kiSliceFirstMbXY = kpSh->iFirstMbInSlice;
670+ SWelsMD sMd;
671+
672+ sMd.uiRef = kpSh->uiRefIndex;
673+ sMd.bMdUsingSad = kbIsHighestDlayerFlag;
674+ if (!pEncCtx->pCurDqLayer->bBaseLayerAvailableFlag || !kbIsHighestDlayerFlag)
675+ memset( &sMd.sMe, 0, sizeof(sMd.sMe) );
676+
677+ //pMb loop
678+ WelsMdInterMbLoop( pEncCtx, pSlice, &sMd, kiSliceFirstMbXY );
679+}
680+
681+void WelsPSliceMdEncDynamic( sWelsEncCtx* pEncCtx, SSlice *pSlice, const bool_t kbIsHighestDlayerFlag )
682+{
683+ const SSliceHeaderExt *kpShExt = &pSlice->sSliceHeaderExt;
684+ const SSliceHeader *kpSh = &kpShExt->sSliceHeader;
685+ const int32_t kiSliceFirstMbXY = kpSh->iFirstMbInSlice;
686+ SWelsMD sMd;
687+
688+ sMd.uiRef = kpSh->uiRefIndex;
689+ sMd.bMdUsingSad = kbIsHighestDlayerFlag;
690+ if (!pEncCtx->pCurDqLayer->bBaseLayerAvailableFlag || !kbIsHighestDlayerFlag)
691+ memset( &sMd.sMe, 0, sizeof(sMd.sMe) );
692+
693+ //mb loop
694+ WelsMdInterMbLoopOverDynamicSlice( pEncCtx, pSlice, &sMd, kiSliceFirstMbXY );
695+}
696+
697+void WelsCodePSlice( sWelsEncCtx* pEncCtx, SSlice *pSlice )
698+{
699+ //pSlice-level init should be outside and before this function
700+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
701+ const bool_t kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
702+ const bool_t kbHighestSpatial= pEncCtx->pSvcParam->iNumDependencyLayer == (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1);
703+
704+ //MD switch
705+ if ( kbBaseAvail && kbHighestSpatial )
706+ {
707+ //initial pMd pointer
708+ pEncCtx->pFuncList->pfInterMd = (PInterMdFunc)WelsMdInterMbEnhancelayer;
709+ }
710+ else
711+ {
712+ //initial pMd pointer
713+ pEncCtx->pFuncList->pfInterMd = (PInterMdFunc)WelsMdInterMb;
714+ }
715+ WelsPSliceMdEnc( pEncCtx, pSlice, kbHighestSpatial );
716+}
717+
718+void WelsCodePOverDynamicSlice( sWelsEncCtx* pEncCtx, SSlice *pSlice )
719+{
720+ //pSlice-level init should be outside and before this function
721+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
722+ const bool_t kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
723+ const bool_t kbHighestSpatial= pEncCtx->pSvcParam->iNumDependencyLayer == (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1);
724+
725+ //MD switch
726+ if ( kbBaseAvail && kbHighestSpatial )
727+ {
728+ //initial pMd pointer
729+ pEncCtx->pFuncList->pfInterMd = (PInterMdFunc)WelsMdInterMbEnhancelayer;
730+ }
731+ else
732+ {
733+ //initial pMd pointer
734+ pEncCtx->pFuncList->pfInterMd = (PInterMdFunc)WelsMdInterMb;
735+ }
736+ WelsPSliceMdEncDynamic( pEncCtx, pSlice, kbHighestSpatial );
737+}
738+
739+// 1st index: 0: for P pSlice; 1: for I pSlice;
740+// 2nd index: 0: for non-dynamic pSlice; 1: for dynamic I pSlice;
741+PWelsCodingSliceFunc g_pWelsSliceCoding[2][2] =
742+{
743+ { WelsCodePSlice, WelsCodePOverDynamicSlice }, // P SSlice
744+ { WelsISliceMdEnc, WelsISliceMdEncDynamic } // I SSlice
745+};
746+PWelsSliceHeaderWriteFunc g_pWelsWriteSliceHeader[2] = // 0: for base; 1: for ext;
747+{
748+ WelsSliceHeaderWrite,
749+ WelsSliceHeaderExtWrite
750+};
751+
752+
753+void WelsCodeOneSlice( sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const int32_t kiNalType )
754+{
755+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
756+ SNalUnitHeaderExt* pNalHeadExt = &pCurLayer->sLayerInfo.sNalHeaderExt;
757+ SSlice *pCurSlice = &pCurLayer->sLayerInfo.pSliceInLayer[kiSliceIdx];
758+ SBitStringAux* pBs = pCurSlice->pSliceBsa;
759+ const int32_t kiDynamicSliceFlag = (pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId].sMso.uiSliceMode == SM_DYN_SLICE);
760+
761+ assert( kiSliceIdx == pCurSlice->uiSliceIdx );
762+
763+ if ( I_SLICE == pEncCtx->eSliceType )
764+ {
765+ pNalHeadExt->bIdrFlag = 1;
766+ pCurSlice->sScaleShift = 0;
767+ }
768+ else
769+ {
770+ const uint32_t kuiTemporalId = pNalHeadExt->uiTemporalId;
771+ pCurSlice->sScaleShift = kuiTemporalId ? (kuiTemporalId - pEncCtx->pRefPic->uiTemporalId) : 0;
772+ }
773+
774+ WelsSliceHeaderExtInit( pEncCtx, pCurLayer, pCurSlice );
775+
776+
777+ g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag]( pBs, pCurLayer, pCurSlice, &(pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0]) );
778+#if _DEBUG
779+ if ( pEncCtx->sPSOVector.bEnableSpsPpsIdAddition )
780+ {
781+ const int32_t kiEncoderPpsId = pCurSlice->sSliceHeaderExt.sSliceHeader.pPps->iPpsId;
782+ const int32_t kiTmpPpsIdInBs = kiEncoderPpsId + pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiEncoderPpsId ];
783+ assert ( MAX_PPS_COUNT > kiTmpPpsIdInBs );
784+
785+ //when activated need to sure there is avialable PPS
786+ assert ( pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].bUsedParaSetIdInBs[kiTmpPpsIdInBs] );
787+ }
788+#endif
789+
790+ pCurSlice->uiLastMbQp = pCurLayer->sLayerInfo.pPpsP->iPicInitQp + pCurSlice->sSliceHeaderExt.sSliceHeader.iSliceQpDelta;
791+
792+ g_pWelsSliceCoding[pNalHeadExt->bIdrFlag][kiDynamicSliceFlag]( pEncCtx, pCurSlice );
793+
794+ BsRbspTrailingBits( pBs );
795+
796+ BsFlush( pBs );
797+}
798+
799+//pFunc: UpdateMbNeighbourInfoForNextSlice()
800+void UpdateMbNeighbourInfoForNextSlice( SSliceCtx *pSliceCtx,
801+ SMB *pMbList,
802+ const int32_t kiFirstMbIdxOfNextSlice,
803+ const int32_t kiLastMbIdxInPartition )
804+{
805+ const int32_t kiMbWidth = pSliceCtx->iMbWidth;
806+ int32_t iIdx = kiFirstMbIdxOfNextSlice;
807+ int32_t iNextSliceFirstMbIdxRowStart= (( kiFirstMbIdxOfNextSlice % kiMbWidth ) ? 1:0);
808+ int32_t iCountMbUpdate = kiMbWidth + iNextSliceFirstMbIdxRowStart; //need to update MB(iMbXY+1) to MB(iMbXY+1+row) in common case
809+ const int32_t kiEndMbNeedUpdate = kiFirstMbIdxOfNextSlice + iCountMbUpdate;
810+ SMB *pMb = &pMbList[iIdx];
811+
812+ do {
813+ uint32_t uiNeighborAvailFlag = 0;
814+ const int32_t kiMbXY = pMb->iMbXY;
815+ const int32_t kiMbX = pMb->iMbX;
816+ const int32_t kiMbY = pMb->iMbY;
817+ BOOL_T bLeft;
818+ BOOL_T bTop;
819+ BOOL_T bLeftTop;
820+ BOOL_T bRightTop;
821+ int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
822+ const uint8_t kuiSliceIdc = WelsMbToSliceIdc(pSliceCtx, kiMbXY);
823+
824+ pMb->uiSliceIdc = kuiSliceIdc;
825+ iLeftXY = kiMbXY - 1;
826+ iTopXY = kiMbXY - kiMbWidth;
827+ iLeftTopXY = iTopXY - 1;
828+ iRightTopXY = iTopXY + 1;
829+
830+ bLeft = (kiMbX > 0) && (kuiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftXY));
831+ bTop = (kiMbY > 0) && (kuiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iTopXY));
832+ bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (kuiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftTopXY));
833+ bRightTop = (kiMbX < (kiMbWidth-1)) && (kiMbY > 0) && (kuiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iRightTopXY));
834+
835+ if( bLeft ){
836+ uiNeighborAvailFlag |= LEFT_MB_POS;
837+ }
838+ if( bTop ){
839+ uiNeighborAvailFlag |= TOP_MB_POS;
840+ }
841+ if( bLeftTop ){
842+ uiNeighborAvailFlag |= TOPLEFT_MB_POS;
843+ }
844+ if( bRightTop ){
845+ uiNeighborAvailFlag |= TOPRIGHT_MB_POS;
846+ }
847+ pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag;
848+
849+ ++ pMb;
850+ ++ iIdx;
851+ }while ( ( iIdx < kiEndMbNeedUpdate) &&
852+ ( iIdx <= kiLastMbIdxInPartition ) );
853+}
854+
855+
856+void AddSliceBoundary(sWelsEncCtx* pEncCtx, SSlice * pCurSlice, SSliceCtx *pSliceCtx, SMB* pCurMb, int32_t iFirstMbIdxOfNextSlice, const int32_t kiLastMbIdxInPartition )
857+{
858+ SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
859+ int32_t iCurMbIdx = pCurMb->iMbXY;
860+ int32_t iCurSliceIdc = pSliceCtx->pOverallMbMap[ iCurMbIdx ];
861+ const int32_t kiSliceIdxStep= pEncCtx->iActiveThreadsNum;
862+ int32_t iNextSliceIdc = iCurSliceIdc + kiSliceIdxStep;
863+ SSlice *pNextSlice = NULL;
864+
865+ SMB *pMbList = pCurLayer->sMbDataP;
866+
867+ //update cur pSlice info
868+ pCurSlice->sSliceHeaderExt.uiNumMbsInSlice = 1 + iCurMbIdx - pCurSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice;
869+
870+ //pNextSlice pointer/initialization
871+ pNextSlice = &( pCurLayer->sLayerInfo.pSliceInLayer[ iNextSliceIdc ] );
872+
873+#if _DEBUG
874+ assert( NULL != pNextSlice );
875+ // now ( pSliceCtx->iSliceNumInFrame < pSliceCtx->iMaxSliceNumConstraint ) always true by the call of this pFunc
876+#endif
877+
878+ //init next pSlice info
879+ pNextSlice->bSliceHeaderExtFlag =
880+ (NAL_UNIT_CODED_SLICE_EXT == pCurLayer->sLayerInfo.sNalHeaderExt.sNalHeader.eNalUnitType);
881+ memcpy( &pNextSlice->sSliceHeaderExt, &pCurSlice->sSliceHeaderExt, sizeof(SSliceHeaderExt) ); // confirmed_safe_unsafe_usage
882+
883+ pSliceCtx->pFirstMbInSlice[iNextSliceIdc] = iFirstMbIdxOfNextSlice;
884+
885+#if !defined(MT_ENABLED)
886+ pNextSlice->uiSliceIdx = iNextSliceIdc;
887+ pNextSlice->pSliceBsa = &(pEncCtx->pOut->sBsWrite);
888+#endif//!MT_ENABLED
889+
890+ memset(pSliceCtx->pOverallMbMap+iFirstMbIdxOfNextSlice, (uint8_t)iNextSliceIdc, (kiLastMbIdxInPartition-iFirstMbIdxOfNextSlice+1)*sizeof(uint8_t));
891+
892+ //DYNAMIC_SLICING_ONE_THREAD: update pMbList slice_neighbor_info
893+ UpdateMbNeighbourInfoForNextSlice( pSliceCtx, pMbList, iFirstMbIdxOfNextSlice, kiLastMbIdxInPartition );
894+}
895+
896+BOOL_T DynSlcJudgeSliceBoundaryStepBack(void* pCtx, void *pSlice, SSliceCtx *pSliceCtx, SMB* pCurMb, SDynamicSlicingStack* pDss )
897+{
898+ sWelsEncCtx *pEncCtx = (sWelsEncCtx*)pCtx;
899+ SSlice * pCurSlice = (SSlice *)pSlice;
900+ int32_t iCurMbIdx = pCurMb->iMbXY;
901+ uint32_t uiLen = 0;
902+ int32_t iPosBitOffset = 0;
903+ const int32_t kiActiveThreadsNum = pEncCtx->iActiveThreadsNum;
904+ const int32_t kiPartitaionId = pCurSlice->uiSliceIdx % kiActiveThreadsNum;
905+ const int32_t kiLastMbIdxInPartition = pEncCtx->pCurDqLayer->pLastMbIdxOfPartition[kiPartitaionId];
906+
907+ const BOOL_T kbCurMbNotFirstMbOfCurSlice = (pSliceCtx->pOverallMbMap[iCurMbIdx] == pSliceCtx->pOverallMbMap[iCurMbIdx-1]);
908+ const BOOL_T kbCurMbNotLastMbOfCurPartition = iCurMbIdx < kiLastMbIdxInPartition;
909+ const BOOL_T kbSliceNumNotExceedConstraint = pSliceCtx->iSliceNumInFrame < pSliceCtx->iMaxSliceNumConstraint; /*tmp choice to avoid complex memory operation, 100520, to be modify*/
910+ const BOOL_T kbSliceNumReachConstraint = (pSliceCtx->iSliceNumInFrame == pSliceCtx->iMaxSliceNumConstraint);
911+
912+ if ( pCurSlice->bDynamicSlicingSliceSizeCtrlFlag )
913+ return false;
914+
915+ iPosBitOffset = ( pDss->iCurrentPos - pDss->iStartPos );
916+#if _DEBUG
917+ assert(iPosBitOffset>=0);
918+#endif
919+ uiLen = ( ( iPosBitOffset>>3 ) + (( iPosBitOffset & 0x07 )? 1: 0) );
920+
921+#ifdef MT_ENABLED
922+ if ( pEncCtx->pSvcParam->iMultipleThreadIdc > 1 )
923+ WelsMutexLock( &pEncCtx->pSliceThreading->mutexSliceNumUpdate );
924+#endif//MT_ENABLED
925+
926+ //DYNAMIC_SLICING_ONE_THREAD: judge jump_avoiding_pack_exceed
927+ if (
928+ ( ( kbCurMbNotFirstMbOfCurSlice
929+ && JUMPPACKETSIZE_JUDGE(uiLen,iCurMbIdx,pSliceCtx->uiSliceSizeConstraint) )/*jump_avoiding_pack_exceed*/
930+ && kbCurMbNotLastMbOfCurPartition )//decide to add new pSlice
931+ && ( kbSliceNumNotExceedConstraint
932+#ifdef MT_ENABLED
933+ && ( ( pCurSlice->uiSliceIdx + kiActiveThreadsNum ) < pSliceCtx->iMaxSliceNumConstraint )
934+#endif//MT_ENABLED
935+ )//able to add new pSlice
936+
937+ )
938+ {
939+
940+ AddSliceBoundary( pEncCtx, pCurSlice, pSliceCtx, pCurMb, iCurMbIdx, kiLastMbIdxInPartition );
941+
942+ ++ pSliceCtx->iSliceNumInFrame;
943+
944+#ifdef MT_ENABLED
945+ if (pEncCtx->pSvcParam->iMultipleThreadIdc > 1)
946+ WelsMutexUnlock( &pEncCtx->pSliceThreading->mutexSliceNumUpdate );
947+#endif//MT_ENABLED
948+
949+ return TRUE;
950+ }
951+
952+ if (
953+ ( kbSliceNumReachConstraint
954+#ifdef MT_ENABLED
955+ || ( ( pCurSlice->uiSliceIdx + kiActiveThreadsNum ) >= pSliceCtx->iMaxSliceNumConstraint )
956+#endif//MT_ENABLED
957+ )
958+ && ( ( JUMPPACKETSIZE_JUDGE(uiLen, iCurMbIdx,
959+ pSliceCtx->uiSliceSizeConstraint - ( ( kiLastMbIdxInPartition - iCurMbIdx ) << ( pCurSlice->uiAssumeLog2BytePerMb ) /* assume each MB consumes two byte under largest QP */) ) )
960+ && kbCurMbNotLastMbOfCurPartition )//risk of exceeding the size constraint when pSlice num reaches constraint
961+ )
962+ {
963+ pCurSlice->bDynamicSlicingSliceSizeCtrlFlag = true;
964+ }
965+
966+#ifdef MT_ENABLED
967+ if (pEncCtx->pSvcParam->iMultipleThreadIdc > 1)
968+ WelsMutexUnlock( &pEncCtx->pSliceThreading->mutexSliceNumUpdate );
969+#endif//MT_ENABLED
970+
971+ return FALSE;
972+}
973+
974+///////////////
975+// pMb loop
976+///////////////
977+// for inter non-dynamic pSlice
978+void WelsMdInterMbLoop( sWelsEncCtx* pEncCtx, SSlice *pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY )
979+{
980+ SWelsMD* pMd = (SWelsMD*)pWelsMd;
981+ SBitStringAux* pBs = pSlice->pSliceBsa;
982+ SDqLayer *pCurLayer = pEncCtx->pCurDqLayer;
983+ SSliceCtx *pSliceCtx = pCurLayer->pSliceEncCtx;
984+ SMbCache *pMbCache = &pSlice->sMbCacheInfo;
985+ SMB *pMbList = pCurLayer->sMbDataP;
986+ SMB *pCurMb = NULL;
987+ int32_t iNumMbCoded = 0;
988+ int32_t iNextMbIdx = kiSliceFirstMbXY;
989+ int32_t iCurMbIdx = -1;
990+ int32_t iMbSkipRun = 0;
991+ const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
992+ const int32_t kiMvdInterTableSize = (pEncCtx->pSvcParam->iNumDependencyLayer == 1 ? 648: 972);
993+ const int32_t kiMvdInterTableStride= 1+(kiMvdInterTableSize<<1);
994+ uint16_t *pMvdCostTableInter = &pEncCtx->pMvdCostTableInter[kiMvdInterTableSize];
995+ const int32_t kiSliceIdx = pSlice->uiSliceIdx;
996+ const uint8_t kuiChromaQpIndexOffset= pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
997+
998+ for(;;)
999+ {
1000+ //point to current pMb
1001+ iCurMbIdx = iNextMbIdx;
1002+ pCurMb = &pMbList[ iCurMbIdx ];
1003+
1004+ //step(1): set QP for the current MB
1005+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInit(pEncCtx, pCurMb, pSlice);
1006+
1007+ //step (2). save some vale for future use, initial pWelsMd
1008+ pMd->iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
1009+ pMd->pMvdCost = &pMvdCostTableInter[pCurMb->uiLumaQp*kiMvdInterTableStride];
1010+ WelsMdIntraInit(pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
1011+ WelsMdInterInit(pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);
1012+ pEncCtx->pFuncList->pfInterMd(pEncCtx, pMd, pSlice, pCurMb, pMbCache);
1013+ //mb_qp
1014+
1015+ //step (4): save from the MD process from future use
1016+ WelsMdInterSaveSadAndRefMbType( (pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);
1017+
1018+ pEncCtx->pFuncList->pfInterMdBackgroundInfoUpdate( pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag, pEncCtx->pRefPic->iPictureType );
1019+
1020+ //step (5): update cache
1021+ UpdateNonZeroCountCache( pCurMb, pMbCache );
1022+
1023+ //step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
1024+ if( IS_SKIP (pCurMb->uiMbType) )
1025+ {
1026+ pCurMb->uiLumaQp = pSlice->uiLastMbQp;
1027+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51(pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
1028+
1029+ iMbSkipRun++;
1030+ }
1031+ else
1032+ {
1033+ BsWriteUE( pBs, iMbSkipRun );
1034+ iMbSkipRun = 0;
1035+ WelsSpatialWriteMbSyn( pEncCtx, pSlice, pCurMb );
1036+ }
1037+
1038+ //step (7): reconstruct current MB
1039+ pCurMb->uiSliceIdc = kiSliceIdx;
1040+ OutputPMbWithoutConstructCsRsNoCopy( pEncCtx, pCurLayer, pSlice, pCurMb );
1041+
1042+ #if defined(MB_TYPES_CHECK)
1043+ WelsCountMbType( pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb );
1044+ #endif//MB_TYPES_CHECK
1045+
1046+ //step (8): update status and other parameters
1047+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate(pEncCtx,pCurMb,pMd->iCostLuma,pSlice);
1048+
1049+ /*judge if all pMb in cur pSlice has been encoded*/
1050+ ++ iNumMbCoded;
1051+ iNextMbIdx = WelsGetNextMbOfSlice( pSliceCtx, iCurMbIdx );
1052+ //whether all of MB in current pSlice encoded or not
1053+ if ( iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb )
1054+ {
1055+ break;
1056+ }
1057+ }
1058+
1059+ if ( iMbSkipRun )
1060+ {
1061+ BsWriteUE( pBs, iMbSkipRun );
1062+ }
1063+}
1064+
1065+// Only for inter dynamic slicing
1066+void WelsMdInterMbLoopOverDynamicSlice( sWelsEncCtx* pEncCtx, SSlice *pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY )
1067+{
1068+ SWelsMD* pMd = (SWelsMD*)pWelsMd;
1069+ SBitStringAux* pBs = pSlice->pSliceBsa;
1070+ SDqLayer *pCurLayer = pEncCtx->pCurDqLayer;
1071+ SSliceCtx *pSliceCtx = pCurLayer->pSliceEncCtx;
1072+ SMbCache *pMbCache = &pSlice->sMbCacheInfo;
1073+ SMB *pMbList = pCurLayer->sMbDataP;
1074+ SMB *pCurMb = NULL;
1075+ int32_t iNumMbCoded = 0;
1076+ const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;
1077+ int32_t iNextMbIdx = kiSliceFirstMbXY;
1078+ int32_t iCurMbIdx = -1;
1079+ int32_t iMbSkipRun = 0;
1080+ const int32_t kiMvdInterTableSize = (pEncCtx->pSvcParam->iNumDependencyLayer == 1 ? 648: 972);
1081+ const int32_t kiMvdInterTableStride= 1+(kiMvdInterTableSize<<1);
1082+ uint16_t *pMvdCostTableInter = &pEncCtx->pMvdCostTableInter[kiMvdInterTableSize];
1083+ const int32_t kiSliceIdx = pSlice->uiSliceIdx;
1084+ const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);
1085+ const uint8_t kuiChromaQpIndexOffset= pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
1086+
1087+ SDynamicSlicingStack sDss;
1088+ sDss.iStartPos = BsGetBitsPos(pBs);
1089+ for(;;)
1090+ {
1091+ //point to current pMb
1092+ iCurMbIdx = iNextMbIdx;
1093+ pCurMb = &pMbList[ iCurMbIdx ];
1094+
1095+ //step(1): set QP for the current MB
1096+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInit(pEncCtx, pCurMb, pSlice);
1097+ // if already reaches the largest number of slices, set QPs to the upper bound
1098+ if (pSlice->bDynamicSlicingSliceSizeCtrlFlag)
1099+ {
1100+ //a clearer logic may be:
1101+ //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
1102+ // however, there are some parameter updating in the rc_mb_init() function, so it cannot be skipped?
1103+ pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;
1104+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51(pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
1105+ }
1106+
1107+ //step (2). save some vale for future use, initial pWelsMd
1108+ pMd->iLambda = g_kiQpCostTable[pCurMb->uiLumaQp];
1109+ pMd->pMvdCost = &pMvdCostTableInter[pCurMb->uiLumaQp*kiMvdInterTableStride];
1110+
1111+ WelsMdIntraInit(pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);
1112+ WelsMdInterInit(pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);
1113+ pEncCtx->pFuncList->pfInterMd(pEncCtx, pMd, pSlice, pCurMb, pMbCache);
1114+ //mb_qp
1115+
1116+ //step (4): save from the MD process from future use
1117+ WelsMdInterSaveSadAndRefMbType( (pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);
1118+
1119+ pEncCtx->pFuncList->pfInterMdBackgroundInfoUpdate( pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag, pEncCtx->pRefPic->iPictureType );
1120+
1121+ //step (5): update cache
1122+ UpdateNonZeroCountCache( pCurMb, pMbCache );
1123+
1124+ //step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skipped
1125+
1126+ //DYNAMIC_SLICING_ONE_THREAD - MultiD
1127+ //stack pBs pointer
1128+ sDss.pBsStackBufPtr = pBs->pBufPtr;
1129+ sDss.uiBsStackCurBits = pBs->uiCurBits;
1130+ sDss.iBsStackLeftBits = pBs->iLeftBits;
1131+ //stack Pskip status
1132+ sDss.iMbSkipRunStack = iMbSkipRun;
1133+ //DYNAMIC_SLICING_ONE_THREAD - MultiD
1134+
1135+ if( IS_SKIP (pCurMb->uiMbType) )
1136+ {
1137+ pCurMb->uiLumaQp = pSlice->uiLastMbQp;
1138+ pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51(pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
1139+
1140+ iMbSkipRun++;
1141+ }
1142+ else
1143+ {
1144+ BsWriteUE( pBs, iMbSkipRun );
1145+ iMbSkipRun = 0;
1146+ WelsSpatialWriteMbSyn( pEncCtx, pSlice, pCurMb );
1147+ }
1148+
1149+ //DYNAMIC_SLICING_ONE_THREAD - MultiD
1150+ sDss.iCurrentPos = BsGetBitsPos(pBs);
1151+ if ( DynSlcJudgeSliceBoundaryStepBack( pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss ) )
1152+ {
1153+ //stack pBs pointer
1154+ pBs->pBufPtr = sDss.pBsStackBufPtr;
1155+ pBs->uiCurBits = sDss.uiBsStackCurBits;
1156+ pBs->iLeftBits = sDss.iBsStackLeftBits;
1157+
1158+ iMbSkipRun = sDss.iMbSkipRunStack;
1159+
1160+ pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx-1; // update pLastCodedMbIdxOfPartition, need to -1 due to stepping back
1161+ ++ pCurLayer->pNumSliceCodedOfPartition[kiPartitionId];
1162+
1163+ break;
1164+ }
1165+
1166+ //step (7): reconstruct current MB
1167+ pCurMb->uiSliceIdc = kiSliceIdx;
1168+ OutputPMbWithoutConstructCsRsNoCopy( pEncCtx, pCurLayer, pSlice, pCurMb );
1169+
1170+#if defined(MB_TYPES_CHECK)
1171+ WelsCountMbType( pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb );
1172+#endif//MB_TYPES_CHECK
1173+
1174+ //step (8): update status and other parameters
1175+ pEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate(pEncCtx,pCurMb,pMd->iCostLuma,pSlice);
1176+
1177+ /*judge if all pMb in cur pSlice has been encoded*/
1178+ ++ iNumMbCoded;
1179+ iNextMbIdx = WelsGetNextMbOfSlice( pSliceCtx, iCurMbIdx );
1180+ //whether all of MB in current pSlice encoded or not
1181+ if ( iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb )
1182+ {
1183+ pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx; // update pLastCodedMbIdxOfPartition, finish coding, use pCurMb_idx directly
1184+ break;
1185+ }
1186+ }
1187+
1188+ if ( iMbSkipRun )
1189+ {
1190+ BsWriteUE( pBs, iMbSkipRun );
1191+ }
1192+}
1193+
1194+}//namespace WelsSVCEnc

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

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

Repository code

Go to file
t