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/encoder_ext.cpp (1 of 308 files). Show all

Unified · Split

codec/encoder/core/src/encoder_ext.cpp+4250−0
@@ -0,0 +1,4250 @@
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 encoder_ext.c
33+ *
34+ * \brief core encoder for SVC
35+ *
36+ * \date 7/24/2009 Created
37+ *
38+ *************************************************************************************
39+ */
40+#include <string.h>
41+#include <stdlib.h>
42+#include <assert.h>
43+
44+#include "encoder.h"
45+#include "extern.h"
46+#include "encoder_context.h"
47+#include "typedefs.h"
48+#include "wels_const.h"
49+#include "wels_common_basis.h"
50+#include "codec_def.h"
51+#include "param_svc.h"
52+#include "cpu_core.h"
53+#include "cpu.h"
54+#include "utils.h"
55+#include "svc_enc_frame.h"
56+#include "svc_enc_golomb.h"
57+#include "svc_enc_slice_segment.h"
58+#include "au_set.h"
59+#include "picture_handle.h"
60+#include "codec_app_def.h"
61+#include "svc_base_layer_md.h"
62+#include "svc_encode_slice.h"
63+#include "decode_mb_aux.h"
64+#include "deblocking.h"
65+#include "rc.h"
66+#include "ref_list_mgr_svc.h"
67+#include "md.h"
68+#include "ls_defines.h"
69+#include "set_mb_syn_cavlc.h"
70+#include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms
71+#include "array_stack_align.h"
72+// for MT, 4/22/2010
73+#include "slice_multi_threading.h"
74+#if defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG)
75+#include "measure_time.h"
76+#endif//DYNAMIC_SLICE_ASSIGN
77+
78+namespace WelsSVCEnc {
79+
80+
81+int32_t WelsCodeOnePicPartition( sWelsEncCtx *pCtx,
82+ SLayerBSInfo *pLbi,
83+ int32_t *pNalIdxInLayer,
84+ int32_t* pLayerSize,
85+ int32_t iFirstMbInPartition, // first mb inclusive in partition
86+ int32_t iEndMbInPartition, // end mb exclusive in partition
87+ int32_t iStartSliceIdx
88+ );
89+
90+
91+/*!
92+ * \brief validate checking in parameter configuration
93+ * \pParam pParam SWelsSvcCodingParam*
94+ * \return successful - 0; otherwise none 0 for failed
95+ */
96+int32_t ParamValidation( SWelsSvcCodingParam *pCfg )
97+{
98+ float fMaxFrameRate = 0.0f;
99+ const float fEpsn = 0.000001f;
100+ int32_t i = 0;
101+ int32_t iLastSpatialWidth = 0;
102+ int32_t iLastSpatialHeight = 0;
103+ float fLastFrameRateIn = 0.0f;
104+ float fLastFrameRateOut = 0.0f;
105+ SDLayerParam *pLastSpatialParam = NULL;
106+
107+ assert( pCfg != NULL );
108+
109+ for (i = 0; i < pCfg->iNumDependencyLayer; ++ i)
110+ {
111+ SDLayerParam *fDlp = &pCfg->sDependencyLayers[i];
112+ if ( fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn && fDlp->fInputFrameRate <= fEpsn)
113+ || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn) )
114+ {
115+#if defined (_DEBUG)
116+ fprintf(stderr, "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n",
117+ fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
118+#endif
119+ return 1;
120+ }
121+ if ( UINT_MAX == GetLogFactor(fDlp->fOutputFrameRate, fDlp->fInputFrameRate) )
122+ {
123+#if defined (_DEBUG)
124+ fprintf(stderr, "Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n)..\n",
125+ fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
126+#endif
127+ return 1;
128+ }
129+ }
130+
131+ for (i = 0; i < pCfg->iNumDependencyLayer; ++ i)
132+ {
133+ SDLayerParam *fDlp = &pCfg->sDependencyLayers[i];
134+ if ( fDlp->fInputFrameRate > fMaxFrameRate )
135+ fMaxFrameRate = fDlp->fInputFrameRate;
136+ }
137+
138+ if ( fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn) )
139+ {
140+ pCfg->fMaxFrameRate = fMaxFrameRate;
141+ }
142+
143+ for (i = 0; i < pCfg->iNumDependencyLayer; ++ i)
144+ {
145+ SDLayerParam *fDlp = &pCfg->sDependencyLayers[i];
146+
147+ pLastSpatialParam = fDlp;
148+ iLastSpatialWidth = fDlp->iFrameWidth;
149+ iLastSpatialHeight = fDlp->iFrameHeight;
150+ fLastFrameRateIn = fDlp->fInputFrameRate;
151+ fLastFrameRateOut = fDlp->fOutputFrameRate;
152+ }
153+
154+ return 0;
155+}
156+
157+int32_t ParamValidationExt( void *pParam )
158+{
159+ SWelsSvcCodingParam *pCodingParam = (SWelsSvcCodingParam *)pParam;
160+ int8_t i = 0;
161+ int32_t iIdx = 0;
162+
163+ assert ( pCodingParam != NULL );
164+ if ( NULL == pCodingParam )
165+ return 1;
166+
167+ if ( pCodingParam->iNumDependencyLayer < 1 || pCodingParam->iNumDependencyLayer > MAX_DEPENDENCY_LAYER ){
168+#if defined (_DEBUG)
169+ fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumDependencyLayer: %d!\n", pCodingParam->iNumDependencyLayer);
170+#endif//#if _DEBUG
171+
172+ return 1;
173+ }
174+
175+ if ( pCodingParam->iNumTemporalLayer < 1 || pCodingParam->iNumTemporalLayer > MAX_TEMPORAL_LEVEL ){
176+#if defined (_DEBUG)
177+ fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumTemporalLayer: %d!\n", pCodingParam->iNumTemporalLayer);
178+#endif//#if _DEBUG
179+ return 1;
180+ }
181+
182+ if ( pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE ){
183+#if defined (_DEBUG)
184+ fprintf(stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize);
185+#endif//#if _DEBUG
186+ return 1;
187+ }
188+
189+
190+ if ( pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize )
191+ {
192+#if defined (_DEBUG)
193+ fprintf(stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n",
194+ pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
195+#endif//#if _DEBUG
196+ return 1;
197+ }
198+
199+ if ( pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize-1)) != 0 )
200+ {
201+#if defined (_DEBUG)
202+ fprintf(stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n",
203+ pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
204+#endif//#if _DEBUG
205+ return 1;
206+ }
207+
208+
209+#ifdef MT_ENABLED
210+ //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode
211+ // (1) Single Thread
212+ // if (THREAD==1)//single thread
213+ // no parallel_deblocking: bDeblockingParallelFlag = 0;
214+ // (2) Multi Thread: see uiSliceMode decision
215+ if ( pCodingParam->iMultipleThreadIdc == 1 )
216+ {
217+ //now is single thread. no parallel deblocking, set flag=0
218+ pCodingParam->bDeblockingParallelFlag = false;
219+ }
220+ else
221+ {
222+ pCodingParam->bDeblockingParallelFlag = true;
223+ }
224+#else
225+ pCodingParam->bDeblockingParallelFlag = false;
226+#endif//MT_ENABLED
227+
228+ for ( i = 0; i < pCodingParam->iNumDependencyLayer; ++ i ){
229+ SDLayerParam *fDlp = &pCodingParam->sDependencyLayers[i];
230+ const int32_t kiPicWidth = fDlp->iFrameWidth;
231+ const int32_t kiPicHeight= fDlp->iFrameHeight;
232+ int32_t iMbWidth = 0;
233+ int32_t iMbHeight = 0;
234+ int32_t iMbNumInFrame = 0;
235+ int32_t iMaxSliceNum = MAX_SLICES_NUM;
236+ if ( kiPicWidth <= 0 || kiPicHeight <= 0 ){
237+#if defined (_DEBUG)
238+ fprintf(stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight);
239+#endif//#if _DEBUG
240+ return 1;
241+ }
242+ if ( (kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0 ){
243+#if defined (_DEBUG)
244+ fprintf(stderr, "ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!\n", i, kiPicWidth, kiPicHeight);
245+#endif//#if _DEBUG
246+ return 1;
247+ }
248+
249+ if ( fDlp->sMso.uiSliceMode >= SM_RESERVED ){
250+#if defined (_DEBUG)
251+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sMso.uiSliceMode );
252+#endif//#if _DEBUG
253+ return 1;
254+ }
255+
256+ //check pSlice settings under multi-pSlice
257+ if ( kiPicWidth<=16 && kiPicHeight<=16 ){
258+ //only have one MB, set to single_slice
259+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
260+ }
261+ switch ( fDlp->sMso.uiSliceMode )
262+ {
263+ case SM_SINGLE_SLICE:
264+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
265+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
266+ fDlp->sMso.sSliceArgument.iSliceNum = 0;
267+ for (iIdx=0; iIdx<MAX_SLICES_NUM;iIdx++)
268+ {
269+ fDlp->sMso.sSliceArgument.uiSliceMbNum[iIdx] = 0;
270+ }
271+ break;
272+ case SM_FIXEDSLCNUM_SLICE:
273+ {
274+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
275+
276+ iMbWidth = (kiPicWidth+15)>>4;
277+ iMbHeight = (kiPicHeight+15)>>4;
278+ iMbNumInFrame = iMbWidth * iMbHeight;
279+ iMaxSliceNum = MAX_SLICES_NUM;
280+ if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0
281+ || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum )
282+ {
283+#if defined (_DEBUG)
284+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum );
285+#endif//#if _DEBUG
286+ return 1;
287+ }
288+ if (fDlp->sMso.sSliceArgument.iSliceNum == 1)
289+ {
290+#if defined (_DEBUG)
291+ fprintf(stderr, "ParamValidationExt(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!\n", fDlp->sMso.sSliceArgument.iSliceNum );
292+#endif//#if _DEBUG
293+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
294+ break;
295+ }
296+ if (pCodingParam->bEnableRc) // multiple slices verify with gom
297+ {
298+ //check uiSliceNum
299+ GomValidCheckSliceNum( iMbWidth, iMbHeight, (int32_t*)&fDlp->sMso.sSliceArgument.iSliceNum );
300+ assert(fDlp->sMso.sSliceArgument.iSliceNum > 1);
301+ //set uiSliceMbNum with current uiSliceNum
302+ GomValidCheckSliceMbNum( iMbWidth, iMbHeight, &fDlp->sMso.sSliceArgument );
303+ }
304+ else if ( !CheckFixedSliceNumMultiSliceSetting( iMbNumInFrame, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings
305+ {//check uiSliceMbNum with current uiSliceNum
306+#if defined (_DEBUG)
307+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] );
308+#endif//#if _DEBUG
309+ return 1;
310+ }
311+ // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
312+ if ( iMbNumInFrame <= MIN_NUM_MB_PER_SLICE )
313+ {
314+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
315+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
316+ break;
317+ }
318+ }
319+ break;
320+ case SM_RASTER_SLICE:
321+ {
322+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
323+
324+ iMbWidth = (kiPicWidth+15)>>4;
325+ iMbHeight = (kiPicHeight+15)>>4;
326+ iMbNumInFrame = iMbWidth * iMbHeight;
327+ iMaxSliceNum = MAX_SLICES_NUM;
328+ if ( fDlp->sMso.sSliceArgument.uiSliceMbNum[0] <= 0 )
329+ {
330+#if defined (_DEBUG)
331+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] );
332+#endif//#if _DEBUG
333+ return 1;
334+ }
335+
336+ if ( !CheckRasterMultiSliceSetting( iMbNumInFrame, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings
337+ {
338+#if defined (_DEBUG)
339+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] );
340+#endif//#if _DEBUG
341+ return 1;
342+ }
343+ if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum ) // verify interleave mode settings
344+ {
345+#if defined (_DEBUG)
346+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n", fDlp->sMso.sSliceArgument.iSliceNum );
347+#endif//#if _DEBUG
348+ return 1;
349+ }
350+ if (fDlp->sMso.sSliceArgument.iSliceNum == 1)
351+ {
352+#if defined (_DEBUG)
353+ fprintf(stderr, "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!\n" );
354+#endif//#if _DEBUG
355+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
356+ break;
357+ }
358+#ifdef MT_ENABLED
359+ if (pCodingParam->bEnableRc && fDlp->sMso.sSliceArgument.iSliceNum > 1)
360+ {
361+#if defined (_DEBUG)
362+ fprintf(stderr, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!\n" );
363+#endif//#if _DEBUG
364+ }
365+#endif
366+ // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
367+ if ( iMbNumInFrame <= MIN_NUM_MB_PER_SLICE )
368+ {
369+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
370+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
371+ break;
372+ }
373+ }
374+ break;
375+ case SM_ROWMB_SLICE:
376+ {
377+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
378+
379+ iMbWidth = (kiPicWidth+15)>>4;
380+ iMbHeight = (kiPicHeight+15)>>4;
381+ iMaxSliceNum = MAX_SLICES_NUM;
382+ if ( iMbHeight > iMaxSliceNum )
383+ {
384+#if defined (_DEBUG)
385+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight );
386+#endif//#if _DEBUG
387+ return 1;
388+ }
389+ fDlp->sMso.sSliceArgument.iSliceNum = iMbHeight;
390+
391+ if ( fDlp->sMso.sSliceArgument.iSliceNum <= 0 )
392+ {
393+#if defined (_DEBUG)
394+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum );
395+#endif//#if _DEBUG
396+ return 1;
397+ }
398+ if ( !CheckRowMbMultiSliceSetting( iMbWidth, &fDlp->sMso.sSliceArgument ) ) // verify interleave mode settings
399+ {
400+#if defined (_DEBUG)
401+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceMbNum[0] );
402+#endif//#if _DEBUG
403+ return 1;
404+ }
405+ }
406+ break;
407+ case SM_DYN_SLICE:
408+ {
409+ iMbWidth = (kiPicWidth+15)>>4;
410+ iMbHeight = (kiPicHeight+15)>>4;
411+ if ( fDlp->sMso.sSliceArgument.uiSliceSizeConstraint <= 0 )
412+ {
413+#if defined (_DEBUG)
414+ fprintf(stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n", fDlp->sMso.sSliceArgument.uiSliceSizeConstraint );
415+#endif//#if _DEBUG
416+ return 1;
417+ }
418+ // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
419+ if ( iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE )
420+ {
421+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
422+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
423+ break;
424+ }
425+ }
426+ break;
427+ default:
428+ {
429+
430+#if defined (_DEBUG)
431+ fprintf(stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", pCodingParam->sDependencyLayers[0].sMso.uiSliceMode );
432+#endif//#if _DEBUG
433+ return 1;
434+
435+ }
436+ break;
437+ }
438+ }
439+
440+ return ParamValidation(pCodingParam);
441+}
442+
443+/*!
444+ * \brief acquire count number of layers and NALs based on configurable paramters dependency
445+ * \pParam pCtx sWelsEncCtx*
446+ * \pParam pParam SWelsSvcCodingParam*
447+ * \pParam pCountLayers pointer of count number of layers indeed
448+ * \pParam iCountNals pointer of count number of nals indeed
449+ * \return 0 - successful; otherwise failed
450+ */
451+static inline int32_t AcquireLayersNals( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pParam, int32_t *pCountLayers, int32_t *pCountNals )
452+{
453+ int32_t iCountNumLayers = 0;
454+ int32_t iCountNumNals = 0;
455+ int32_t iNumDependencyLayers = 0;
456+ int32_t iDIndex = 0;
457+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
458+ int32_t iNumLayersPack = 0;
459+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
460+
461+ if ( NULL == pParam || NULL == ppCtx || NULL == *ppCtx )
462+ return 1;
463+
464+ iNumDependencyLayers = pParam->iNumDependencyLayer;
465+
466+ do {
467+ SDLayerParam *pDLayer = &pParam->sDependencyLayers[iDIndex];
468+// pDLayer->ptr_cfg = pParam;
469+ int32_t iOrgNumNals = iCountNumNals;
470+
471+ //Note: Sep. 2010
472+ //Review this part and suggest no change, since the memory over-use
473+ //(1) counts little to the overall performance
474+ //(2) should not be critial even under mobile case
475+ if ( SM_DYN_SLICE == pDLayer->sMso.uiSliceMode )
476+ {
477+ iCountNumNals += MAX_SLICES_NUM;
478+ // plus prefix NALs
479+ if ( iDIndex == 0 )
480+ iCountNumNals += MAX_SLICES_NUM;
481+ // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h
482+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
483+ assert(MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME);
484+ // iNumLayersPack += MAX_SLICES_NUM; // do not count it for dynamic slicing mode
485+#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER
486+ assert(iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER );
487+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
488+ }
489+ else /*if ( SM_SINGLE_SLICE != pDLayer->sMso.uiSliceMode )*/
490+ {
491+ const int32_t kiNumOfSlice = GetInitialSliceNum( (pDLayer->iFrameWidth+0x0f)>>4,
492+ (pDLayer->iFrameHeight+0x0f)>>4,
493+ &pDLayer->sMso );
494+
495+ // NEED check iCountNals value in case multiple slices is used
496+ iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs
497+ // plus prefix NALs
498+ if ( iDIndex == 0 )
499+ iCountNumNals += kiNumOfSlice;
500+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
501+ assert(num_of_slice <= MAX_SLICES_NUM && MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME);
502+ iNumLayersPack += num_of_slice;
503+#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER
504+ assert(iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER );
505+#endif//MT_ENALBED && PACKING_ONE_SLICE_PER_LAYER
506+ if ( kiNumOfSlice > MAX_SLICES_NUM )
507+ {
508+ WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!\n",
509+ kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0 );
510+ return 1;
511+ }
512+ }
513+#if !defined(MT_ENABLED) || !defined(PACKING_ONE_SLICE_PER_LAYER)
514+ if ( iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER )
515+ {
516+ WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!\n",
517+ (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0 );
518+ return 1;
519+ }
520+#endif//!MT_ENABLED) || !PACKING_ONE_SLICE_PER_LAYER
521+
522+ iCountNumLayers ++;
523+
524+ ++ iDIndex;
525+ } while(iDIndex < iNumDependencyLayers);
526+
527+ iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers<<1) + iCountNumLayers; // plus iCountNumLayers for reserved application
528+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
529+ iNumLayersPack += 1 + iNumDependencyLayers + (iCountNumLayers<<1);
530+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
531+
532+ // to check number of layers / nals / slices dependencies, 12/8/2010
533+#if !defined(MT_ENABLED)
534+ if ( iCountNumLayers > MAX_LAYER_NUM_OF_FRAME )
535+ {
536+ WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iCountNumLayers, MAX_LAYER_NUM_OF_FRAME );
537+ return 1;
538+ }
539+#else//MT_ENABLED
540+#if defined(PACKING_ONE_SLICE_PER_LAYER)
541+ if ( iNumLayersPack > MAX_LAYER_NUM_OF_FRAME )
542+ {
543+ WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_layers_pack_overall(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iNumLayersPack, MAX_LAYER_NUM_OF_FRAME );
544+ return 1;
545+ }
546+#else//!PACKING_ONE_SLICE_PER_LAYER
547+ if ( iCountNumLayers > MAX_LAYER_NUM_OF_FRAME )
548+ {
549+ WelsLog( *ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", iCountNumLayers, MAX_LAYER_NUM_OF_FRAME );
550+ return 1;
551+ }
552+#endif//PACKING_ONE_SLICE_PER_LAYER
553+#endif//!MT_ENABLED
554+
555+ if ( NULL != pCountLayers )
556+ *pCountLayers = iCountNumLayers;
557+ if ( NULL != pCountNals )
558+ *pCountNals = iCountNumNals;
559+ return 0;
560+}
561+
562+/*!
563+ * \brief alloc spatial layers pictures (I420 based source pictures)
564+ */
565+int32_t AllocSpatialPictures( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pParam )
566+{
567+ CMemoryAlign *pMa = (*ppCtx)->pMemAlign;
568+ const int32_t kiDlayerCount = pParam->iNumDependencyLayer;
569+ int32_t iDlayerIndex = 0;
570+
571+ // spatial pictures
572+ iDlayerIndex = 0;
573+ do {
574+ const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth;
575+ const int32_t kiPicHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight;
576+ const uint8_t kuiLayerInTemporal = 2 + WELS_MAX(pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1);
577+ const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum;
578+ uint8_t i = 0;
579+
580+ do {
581+ SPicture *pPic = AllocPicture( pMa, kiPicWidth, kiPicHeight, false );
582+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pPic), FreeMemorySvc(ppCtx); *ppCtx = NULL )
583+ (*ppCtx)->pSpatialPic[iDlayerIndex][i] = pPic;
584+ ++ i;
585+ } while( i < kuiRefNumInTemporal);
586+
587+ (*ppCtx)->uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal;
588+ (*ppCtx)->uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal;
589+ ++ iDlayerIndex;
590+ } while( iDlayerIndex < kiDlayerCount );
591+
592+ return 0;
593+}
594+
595+void FreeSpatialPictures( sWelsEncCtx *pCtx )
596+{
597+ CMemoryAlign *pMa = pCtx->pMemAlign;
598+ int32_t j = 0;
599+ while( j < pCtx->pSvcParam->iNumDependencyLayer )
600+ {
601+ uint8_t i = 0;
602+ uint8_t uiRefNumInTemporal = pCtx->uiSpatialPicNum[j];
603+
604+ while( i < uiRefNumInTemporal )
605+ {
606+ if ( NULL != pCtx->pSpatialPic[j][i] )
607+ {
608+ FreePicture( pMa, &pCtx->pSpatialPic[j][i] );
609+ }
610+ ++ i;
611+ }
612+ pCtx->uiSpatialLayersInTemporal[j] = 0;
613+ ++ j;
614+ }
615+
616+}
617+
618+static void InitMbInfo(sWelsEncCtx * pEnc, SMB * pList, SDqLayer * pLayer, const int32_t kiDlayerId, const int32_t kiMaxMbNum )
619+{
620+ int32_t iMbWidth = pLayer->iMbWidth;
621+ int32_t iMbHeight = pLayer->iMbHeight;
622+ int32_t iIdx;
623+ int32_t iMbNum = iMbWidth * iMbHeight;
624+ SSliceCtx *pSliceCtx= pLayer->pSliceEncCtx;
625+ uint32_t uiNeighborAvail;
626+ const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum;
627+ SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY(*)[MB_BLOCK4x4_NUM])(&pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM*kiOffset]);
628+ int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t(*)[MB_BLOCK8x8_NUM])(&pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM*kiOffset]);
629+
630+ for( iIdx = 0; iIdx<iMbNum; iIdx++ ){
631+ BOOL_T bLeft;
632+ BOOL_T bTop;
633+ BOOL_T bLeftTop;
634+ BOOL_T bRightTop;
635+ int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
636+ uint8_t uiSliceIdc;
637+
638+ pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx];
639+ pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx];
640+ pList[iIdx].iMbXY = iIdx;
641+
642+ uiSliceIdc = WelsMbToSliceIdc(pSliceCtx, iIdx);
643+ iLeftXY = iIdx - 1;
644+ iTopXY = iIdx - iMbWidth;
645+ iLeftTopXY = iTopXY - 1;
646+ iRightTopXY = iTopXY + 1;
647+
648+ bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftXY));
649+ bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iTopXY));
650+ bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc ==
651+ WelsMbToSliceIdc(pSliceCtx, iLeftTopXY));
652+ bRightTop = (pList[iIdx].iMbX < (iMbWidth-1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc ==
653+ WelsMbToSliceIdc(pSliceCtx, iRightTopXY));
654+
655+ uiNeighborAvail = 0;
656+ if( bLeft ){
657+ uiNeighborAvail |= LEFT_MB_POS;
658+ }
659+ if( bTop ){
660+ uiNeighborAvail |= TOP_MB_POS;
661+ }
662+ if( bLeftTop ){
663+ uiNeighborAvail |= TOPLEFT_MB_POS;
664+ }
665+ if( bRightTop ){
666+ uiNeighborAvail |= TOPRIGHT_MB_POS;
667+ }
668+ pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding
669+ pList[iIdx].uiNeighborAvail = uiNeighborAvail;
670+ uiNeighborAvail = 0;
671+ if(pList[iIdx].iMbX >= BASE_MV_MB_NMB)
672+ uiNeighborAvail |= LEFT_MB_POS;
673+ if(pList[iIdx].iMbX <= (iMbWidth-1-BASE_MV_MB_NMB))
674+ uiNeighborAvail |= RIGHT_MB_POS;
675+ if (pList[iIdx].iMbY >= BASE_MV_MB_NMB)
676+ uiNeighborAvail |= TOP_MB_POS;
677+ if(pList[iIdx].iMbY <= (iMbHeight-1-BASE_MV_MB_NMB))
678+ uiNeighborAvail |= BOTTOM_MB_POS;
679+
680+ pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx];
681+ pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx];
682+ pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx];
683+ pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx*INTRA_4x4_MODE_NUM];
684+ pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx*MB_LUMA_CHROMA_BLOCK4x4_NUM];
685+ }
686+}
687+
688+
689+int32_t InitMbListD( sWelsEncCtx ** ppCtx)
690+{
691+ int32_t iNumDlayer = (*ppCtx)->pSvcParam->iNumDependencyLayer;
692+ int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 };
693+ int32_t iOverallMbNum = 0;
694+ int32_t iMbWidth = 0;
695+ int32_t iMbHeight= 0;
696+ int32_t i;
697+
698+ if ( iNumDlayer > MAX_DEPENDENCY_LAYER )
699+ return 1;
700+
701+ for( i=0;i<iNumDlayer;i++ ){
702+ iMbWidth = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameWidth + 15)>>4;
703+ iMbHeight = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameHeight + 15)>>4;
704+ iMbSize[i] = iMbWidth * iMbHeight;
705+ iOverallMbNum += iMbSize[i];
706+ }
707+
708+ (*ppCtx)->ppMbListD = static_cast<SMB **>((*ppCtx)->pMemAlign->WelsMalloc(iNumDlayer * sizeof(SMB *), "ppMbListD"));
709+ (*ppCtx)->ppMbListD[0] = NULL;
710+ WELS_VERIFY_RETURN_PROC_IF(1, (*ppCtx)->ppMbListD==NULL, FreeMemorySvc(ppCtx));
711+ (*ppCtx)->ppMbListD[0] = static_cast<SMB*>((*ppCtx)->pMemAlign->WelsMallocz(iOverallMbNum * sizeof(SMB), "ppMbListD[0]"));
712+ WELS_VERIFY_RETURN_PROC_IF(1, (*ppCtx)->ppMbListD[0]==NULL, FreeMemorySvc(ppCtx));
713+ (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0];
714+ InitMbInfo(*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer-1]);
715+ for( i=1;i<iNumDlayer;i++ ){
716+ (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i-1] + iMbSize[i-1];
717+ (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i];
718+ InitMbInfo(*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer-1]);
719+ }
720+
721+ return 0;
722+}
723+
724+int32_t AllocMbCacheAligned( SMbCache *pMbCache, CMemoryAlign *pMa )
725+{
726+ pMbCache->pCoeffLevel = (int16_t *)pMa->WelsMalloc(MB_COEFF_LIST_SIZE*sizeof(int16_t), "pMbCache->pCoeffLevel");
727+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pCoeffLevel));
728+ pMbCache->pMemPredMb = (uint8_t *)pMa->WelsMalloc(2*256*sizeof(uint8_t), "pMbCache->pMemPredMb");
729+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pMemPredMb));
730+ pMbCache->pSkipMb = (uint8_t *)pMa->WelsMalloc(384*sizeof(uint8_t), "pMbCache->pSkipMb");
731+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pSkipMb));
732+ pMbCache->pMemPredBlk4 = (uint8_t *)pMa->WelsMalloc(2*16*sizeof(uint8_t), "pMbCache->pMemPredBlk4");
733+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pMemPredBlk4));
734+ pMbCache->pBufferInterPredMe = (uint8_t *)pMa->WelsMalloc(4*640*sizeof(uint8_t), "pMbCache->pBufferInterPredMe");
735+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pBufferInterPredMe));
736+ pMbCache->pPrevIntra4x4PredModeFlag = (bool_t *)pMa->WelsMalloc(16*sizeof(bool_t), "pMbCache->pPrevIntra4x4PredModeFlag");
737+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pPrevIntra4x4PredModeFlag));
738+ pMbCache->pRemIntra4x4PredModeFlag = (int8_t *)pMa->WelsMalloc(16*sizeof(int8_t), "pMbCache->pRemIntra4x4PredModeFlag");
739+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pRemIntra4x4PredModeFlag));
740+ pMbCache->pDct = (SDCTCoeff *)pMa->WelsMalloc(sizeof(SDCTCoeff), "pMbCache->pDct");
741+ WELS_VERIFY_RETURN_IF(1, (NULL==pMbCache->pDct));
742+ return 0;
743+}
744+
745+void FreeMbCache( SMbCache *pMbCache, CMemoryAlign *pMa )
746+{
747+ if ( NULL != pMbCache->pCoeffLevel )
748+ {
749+ pMa->WelsFree( pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel" );
750+ pMbCache->pCoeffLevel = NULL;
751+ }
752+ if ( NULL != pMbCache->pMemPredMb )
753+ {
754+ pMa->WelsFree( pMbCache->pMemPredMb, "pMbCache->pMemPredMb" );
755+ pMbCache->pMemPredMb = NULL;
756+ }
757+ if ( NULL != pMbCache->pSkipMb )
758+ {
759+ pMa->WelsFree( pMbCache->pSkipMb, "pMbCache->pSkipMb" );
760+ pMbCache->pSkipMb = NULL;
761+ }
762+ if ( NULL != pMbCache->pMemPredBlk4 )
763+ {
764+ pMa->WelsFree( pMbCache->pMemPredBlk4, "pMbCache->pMemPredBlk4" );
765+ pMbCache->pMemPredBlk4 = NULL;
766+ }
767+ if ( NULL != pMbCache->pBufferInterPredMe )
768+ {
769+ pMa->WelsFree( pMbCache->pBufferInterPredMe, "pMbCache->pBufferInterPredMe" );
770+ pMbCache->pBufferInterPredMe = NULL;
771+ }
772+ if ( NULL != pMbCache->pPrevIntra4x4PredModeFlag )
773+ {
774+ pMa->WelsFree( pMbCache->pPrevIntra4x4PredModeFlag, "pMbCache->pPrevIntra4x4PredModeFlag" );
775+ pMbCache->pPrevIntra4x4PredModeFlag = NULL;
776+ }
777+ if ( NULL != pMbCache->pRemIntra4x4PredModeFlag )
778+ {
779+ pMa->WelsFree( pMbCache->pRemIntra4x4PredModeFlag, "pMbCache->pRemIntra4x4PredModeFlag" );
780+ pMbCache->pRemIntra4x4PredModeFlag = NULL;
781+ }
782+ if ( NULL != pMbCache->pDct )
783+ {
784+ pMa->WelsFree( pMbCache->pDct, "pMbCache->pDct" );
785+ pMbCache->pDct = NULL;
786+ }
787+}
788+
789+
790+/*!
791+ * \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available
792+ * \pParam pCtx sWelsEncCtx*
793+ * \return 0 - successful; otherwise failed
794+ */
795+static inline int32_t InitDqLayers( sWelsEncCtx **ppCtx )
796+{
797+ SWelsSvcCodingParam *pParam = NULL;
798+ SWelsSPS *pSps = NULL;
799+ SSubsetSps *pSubsetSps = NULL;
800+ SWelsPPS *pPps = NULL;
801+ CMemoryAlign *pMa = NULL;
802+ SStrideTables *pStrideTab = NULL;
803+ int32_t iDlayerCount = 0;
804+ int32_t iDlayerIndex = 0;
805+ uint32_t iSpsId = 0;
806+ uint32_t iPpsId = 0;
807+ uint32_t iNumRef = 0;
808+ int32_t iResult = 0;
809+
810+ if ( NULL == ppCtx || NULL == *ppCtx )
811+ return 1;
812+
813+ pMa = (*ppCtx)->pMemAlign;
814+ pParam = (*ppCtx)->pSvcParam;
815+ iDlayerCount = pParam->iNumDependencyLayer;
816+ iNumRef = pParam->iNumRefFrame;
817+// highest_layers_in_temporal = 1 + WELS_MAX(pParam->iDecompStages, 1);
818+ pStrideTab = (*ppCtx)->pStrideTab;
819+
820+ iDlayerIndex = 0;
821+ while (iDlayerIndex < iDlayerCount)
822+ {
823+ SRefList *pRefList = NULL;
824+ uint32_t i = 0;
825+ const int32_t kiWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth;
826+ const int32_t kiHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight;
827+ int32_t iPicWidth = WELS_ALIGN(kiWidth, MB_WIDTH_LUMA) + (PADDING_LENGTH<<1); // with iWidth of horizon
828+ int32_t iPicChromaWidth = iPicWidth >> 1;
829+
830+ iPicWidth = WELS_ALIGN( iPicWidth, 32 ); // 32(or 16 for chroma below) to match original imp. here instead of iCacheLineSize
831+ iPicChromaWidth = WELS_ALIGN( iPicChromaWidth, 16 );
832+
833+ WelsGetEncBlockStrideOffset( (*ppCtx)->pStrideTab->pStrideEncBlockOffset[iDlayerIndex], iPicWidth, iPicChromaWidth);
834+
835+ // pRef list
836+ pRefList = (SRefList *)pMa->WelsMallocz( sizeof(SRefList), "pRefList" );
837+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pRefList), FreeMemorySvc(ppCtx) )
838+
839+ do {
840+ pRefList->pRef[i] = AllocPicture( pMa, kiWidth, kiHeight, true ); // to use actual size of current layer
841+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pRefList->pRef[i]), FreeMemorySvc(ppCtx) )
842+ ++ i;
843+ } while(i < 1 + iNumRef);
844+
845+ pRefList->pNextBuffer = pRefList->pRef[0];
846+ (*ppCtx)->ppRefPicListExt[iDlayerIndex] = pRefList;
847+ ++ iDlayerIndex;
848+ }
849+
850+ // for I420 based source spatial pictures
851+ if ( AllocSpatialPictures( ppCtx, pParam ) )
852+ {
853+ FreeMemorySvc( ppCtx );
854+ return 1;
855+ }
856+
857+ iDlayerIndex = 0;
858+ while (iDlayerIndex < iDlayerCount) {
859+ SDqLayer *pDqLayer = NULL;
860+ SDLayerParam *pDlayer = &pParam->sDependencyLayers[iDlayerIndex];
861+ const int32_t kiMbW = (pDlayer->iFrameWidth + 0x0f) >> 4;
862+ const int32_t kiMbH = (pDlayer->iFrameHeight + 0x0f) >> 4;
863+ int32_t iMaxSliceNum = 1;
864+ const int32_t kiSliceNum = GetInitialSliceNum( kiMbW, kiMbH, &pDlayer->sMso );
865+ if ( iMaxSliceNum < kiSliceNum )
866+ iMaxSliceNum = kiSliceNum;
867+
868+ // pDq layers list
869+ pDqLayer = (SDqLayer *)pMa->WelsMallocz( sizeof(SDqLayer), "pDqLayer" );
870+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pDqLayer), FreeMemorySvc(ppCtx) )
871+
872+ // for dynamic slicing mode
873+ if ( SM_DYN_SLICE == pDlayer->sMso.uiSliceMode )
874+ {
875+ const int32_t iSize = pParam->iCountThreadsNum * sizeof(int32_t);
876+
877+ pDqLayer->pNumSliceCodedOfPartition = (int32_t *)pMa->WelsMallocz( iSize, "pNumSliceCodedOfPartition" );
878+ pDqLayer->pLastCodedMbIdxOfPartition = (int32_t *)pMa->WelsMallocz( iSize, "pLastCodedMbIdxOfPartition" );
879+ pDqLayer->pLastMbIdxOfPartition = (int32_t *)pMa->WelsMallocz( iSize, "pLastMbIdxOfPartition" );
880+
881+ WELS_VERIFY_RETURN_PROC_IF( 1,
882+ (NULL == pDqLayer->pNumSliceCodedOfPartition ||
883+ NULL == pDqLayer->pLastCodedMbIdxOfPartition ||
884+ NULL == pDqLayer->pLastMbIdxOfPartition),
885+ FreeMemorySvc(ppCtx) )
886+ }
887+
888+ pDqLayer->iMbWidth = kiMbW;
889+ pDqLayer->iMbHeight = kiMbH;
890+#ifndef MT_ENABLED
891+ if ( SM_DYN_SLICE == pDlayer->sMso.uiSliceMode )//wmalloc pSliceInLayer
892+ {
893+ SSlice *pSlice = NULL;
894+ int32_t iSliceIdx = 0;
895+ //wmalloc AVERSLICENUM_CONSTANT of pDqLayer->sLayerInfo.pSliceInLayer,
896+ //wmalloc AVERSLICENUM_CONSTANT num of pSlice as initialization
897+ //only set value for the first pSlice
898+ pDqLayer->sLayerInfo.pSliceInLayer = (SSlice *)pMa->WelsMallocz( sizeof(SSlice) * iMaxSliceNum, "pSliceInLayer" );
899+
900+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pDqLayer->sLayerInfo.pSliceInLayer), FreeMemorySvc(ppCtx) )
901+ {
902+ pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[0];
903+ pSlice->uiSliceIdx = 0;
904+ pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite;
905+ }
906+
907+ while(iSliceIdx < iMaxSliceNum)
908+ {
909+ pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[iSliceIdx];
910+ if ( AllocMbCacheAligned(&pSlice->sMbCacheInfo, pMa) )
911+ {
912+ FreeMemorySvc(ppCtx);
913+ return 1;
914+ }
915+ ++ iSliceIdx;
916+ }
917+ }
918+ else
919+#endif//!MT_ENABLED
920+ {
921+ int32_t iSliceIdx = 0;
922+ pDqLayer->sLayerInfo.pSliceInLayer = (SSlice *)pMa->WelsMallocz( sizeof(SSlice) * iMaxSliceNum, "pSliceInLayer" );
923+
924+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pDqLayer->sLayerInfo.pSliceInLayer), FreeMemorySvc(ppCtx) )
925+ if ( iMaxSliceNum > 1 )
926+ {
927+ while (iSliceIdx < iMaxSliceNum) {
928+ SSlice *pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[iSliceIdx];
929+ pSlice->uiSliceIdx = iSliceIdx;
930+#ifdef MT_ENABLED
931+ if ( pParam->iMultipleThreadIdc > 1 )
932+ pSlice->pSliceBsa = &(*ppCtx)->pSliceBs[iSliceIdx].sBsWrite;
933+ else
934+ pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite;
935+#else
936+ pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite;
937+#endif//MT_ENABLED
938+ if ( AllocMbCacheAligned(&pSlice->sMbCacheInfo, pMa) )
939+ {
940+ FreeMemorySvc(ppCtx);
941+ return 1;
942+ }
943+ ++ iSliceIdx;
944+ }
945+ }
946+ // fix issue in case single pSlice coding might be inclusive exist in variant spatial layer setting, also introducing multi-pSlice modes
947+ else // only one pSlice
948+ {
949+ SSlice *pSlice = &pDqLayer->sLayerInfo.pSliceInLayer[0];
950+ pSlice->uiSliceIdx = 0;
951+ pSlice->pSliceBsa = &(*ppCtx)->pOut->sBsWrite;
952+ if ( AllocMbCacheAligned(&pSlice->sMbCacheInfo, pMa) )
953+ {
954+ FreeMemorySvc(ppCtx);
955+ return 1;
956+ }
957+ }
958+ }
959+
960+ //deblocking parameters initialization
961+ //target-layer deblocking
962+ pDqLayer->iLoopFilterDisableIdc = pParam->iLoopFilterDisableIdc;
963+ pDqLayer->iLoopFilterAlphaC0Offset = (pParam->iLoopFilterAlphaC0Offset)<<1;
964+ pDqLayer->iLoopFilterBetaOffset = (pParam->iLoopFilterBetaOffset)<<1;
965+ //inter-layer deblocking
966+ pDqLayer->uiDisableInterLayerDeblockingFilterIdc = pParam->iInterLayerLoopFilterDisableIdc;
967+ pDqLayer->iInterLayerSliceAlphaC0Offset = (pParam->iInterLayerLoopFilterAlphaC0Offset)<<1;
968+ pDqLayer->iInterLayerSliceBetaOffset = (pParam->iInterLayerLoopFilterBetaOffset)<<1;
969+ //parallel deblocking
970+ pDqLayer->bDeblockingParallelFlag = pParam->bDeblockingParallelFlag;
971+
972+ //deblocking parameter adjustment
973+ if ( SM_SINGLE_SLICE == pDlayer->sMso.uiSliceMode )
974+ {
975+ //iLoopFilterDisableIdc: will be 0 or 1 under single_slice
976+ if ( 2 == pParam->iLoopFilterDisableIdc )
977+ {
978+ pDqLayer->iLoopFilterDisableIdc = 0;
979+ }
980+ //bDeblockingParallelFlag
981+ pDqLayer->bDeblockingParallelFlag = false;
982+ }
983+ else
984+ {//multi-pSlice
985+#ifdef MT_ENABLED
986+ if ( 0 == pDqLayer->iLoopFilterDisableIdc )
987+ {
988+ pDqLayer->bDeblockingParallelFlag = false;
989+ }
990+#endif
991+ }
992+
993+ (*ppCtx)->ppDqLayerList[iDlayerIndex] = pDqLayer;
994+
995+ ++ iDlayerIndex;
996+ }
997+
998+ // for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
999+ if ( &(*ppCtx)->pSvcParam->bMgsT0OnlyStrategy )
1000+ {
1001+ (*ppCtx)->pPPSArray = (SWelsPPS *)pMa->WelsMalloc( (1+iDlayerCount) * sizeof(SWelsPPS), "pPPSArray" );
1002+ }
1003+ else
1004+ {
1005+ (*ppCtx)->pPPSArray = (SWelsPPS *)pMa->WelsMalloc( iDlayerCount * sizeof(SWelsPPS), "pPPSArray" );
1006+ }
1007+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc(ppCtx) )
1008+
1009+ (*ppCtx)->pSpsArray = (SWelsSPS *)pMa->WelsMalloc( sizeof(SWelsSPS), "pSpsArray" );
1010+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc(ppCtx) )
1011+ if ( iDlayerCount > 1 )
1012+ {
1013+ (*ppCtx)->pSubsetArray = (SSubsetSps *)pMa->WelsMalloc( (iDlayerCount-1) * sizeof(SSubsetSps), "pSubsetArray" );
1014+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc(ppCtx) )
1015+ }
1016+
1017+ (*ppCtx)->pDqIdcMap = (SDqIdc *)pMa->WelsMallocz( iDlayerCount * sizeof(SDqIdc), "pDqIdcMap" );
1018+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pDqIdcMap), FreeMemorySvc(ppCtx) )
1019+
1020+ iDlayerIndex = 0;
1021+ while (iDlayerIndex < iDlayerCount) {
1022+ SDqIdc *pDqIdc = &(*ppCtx)->pDqIdcMap[iDlayerIndex];
1023+ const bool_t bUseSubsetSps = (iDlayerIndex > BASE_DEPENDENCY_ID);
1024+ SDLayerParam *pDlayerParam = &pParam->sDependencyLayers[iDlayerIndex];
1025+
1026+ pDqIdc->uiSpatialId = iDlayerIndex;
1027+ pPps = &(*ppCtx)->pPPSArray[iPpsId];
1028+ if ( !bUseSubsetSps )
1029+ {
1030+ pSps = &(*ppCtx)->pSpsArray[iSpsId];
1031+ }
1032+ else
1033+ {
1034+ pSubsetSps = &(*ppCtx)->pSubsetArray[iSpsId];
1035+ pSps = &pSubsetSps->pSps;
1036+ }
1037+
1038+ // Need port pSps/pPps initialization due to spatial scalability changed
1039+ if ( !bUseSubsetSps )
1040+ {
1041+ WelsInitSps( pSps, pDlayerParam, pParam->uiIntraPeriod, pParam->iNumRefFrame, iSpsId,
1042+ pParam->bEnableFrameCroppingFlag, pParam->bEnableRc );
1043+
1044+ if( iDlayerCount > 1 )
1045+ {
1046+ pSps->bConstraintSet0Flag = true;
1047+ pSps->bConstraintSet1Flag = true;
1048+ pSps->bConstraintSet2Flag = true;
1049+ }
1050+ }
1051+ else
1052+ {
1053+ WelsInitSubsetSps( pSubsetSps, pDlayerParam, pParam->uiIntraPeriod, pParam->iNumRefFrame, iSpsId,
1054+ pParam->bEnableFrameCroppingFlag, pParam->bEnableRc );
1055+ }
1056+
1057+ // initialize pPps
1058+ WelsInitPps( pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps );
1059+
1060+ // Not using FMO in SVC coding so far, come back if need FMO
1061+ {
1062+ iResult = InitSlicePEncCtx( &(*ppCtx)->pSliceCtxList[iDlayerIndex],
1063+ (*ppCtx)->pMemAlign,
1064+ false,
1065+ pSps->iMbWidth,
1066+ pSps->iMbHeight,
1067+ &(pDlayerParam->sMso),
1068+ pPps );
1069+ if ( iResult )
1070+ {
1071+ WelsLog( *ppCtx, WELS_LOG_WARNING, "InitDqLayers(), InitSlicePEncCtx failed(%d)!", iResult );
1072+ FreeMemorySvc( ppCtx );
1073+ return 1;
1074+ }
1075+ (*ppCtx)->ppDqLayerList[iDlayerIndex]->pSliceEncCtx = &(*ppCtx)->pSliceCtxList[iDlayerIndex];
1076+ }
1077+ pDqIdc->iSpsId = iSpsId;
1078+ pDqIdc->iPpsId = iPpsId;
1079+
1080+ (*ppCtx)->sPSOVector.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps;
1081+
1082+ if ( bUseSubsetSps )
1083+ ++ iSpsId;
1084+ ++ iPpsId;
1085+ ++ (*ppCtx)->iSpsNum;
1086+ ++ (*ppCtx)->iPpsNum;
1087+
1088+ ++ iDlayerIndex;
1089+ }
1090+ return 0;
1091+}
1092+
1093+int32_t AllocStrideTables( sWelsEncCtx **ppCtx, const int32_t kiNumSpatialLayers )
1094+{
1095+ CMemoryAlign *pMa = (*ppCtx)->pMemAlign;
1096+ SWelsSvcCodingParam *pParam = (*ppCtx)->pSvcParam;
1097+ SStrideTables *pPtr = NULL;
1098+ int16_t *pTmpRow = NULL, *pRowX = NULL, *pRowY = NULL, *p = NULL;
1099+ uint8_t *pBase = NULL;
1100+ uint8_t *pBaseDec = NULL, *pBaseEnc = NULL, *pBaseMbX = NULL, *pBaseMbY = NULL;
1101+ struct {
1102+ int32_t iMbWidth;
1103+ int32_t iCountMbNum; // count number of SMB in each spatial
1104+ int32_t iSizeAllMbAlignCache; // cache line size aligned in each spatial
1105+ } sMbSizeMap[MAX_DEPENDENCY_LAYER] = {0};
1106+ int32_t iLineSizeY[MAX_DEPENDENCY_LAYER][2] = {0};
1107+ int32_t iLineSizeUV[MAX_DEPENDENCY_LAYER][2]= {0};
1108+ int32_t iMapSpatialIdx[MAX_DEPENDENCY_LAYER][2] = {0};
1109+ int32_t iSizeDec = 0;
1110+ int32_t iSizeEnc = 0;
1111+ int32_t iCountLayersNeedCs[2] = {0};
1112+ const int32_t kiUnit1Size = 24 * sizeof(int32_t);
1113+ int32_t iUnit2Size = 0;
1114+ int32_t iNeedAllocSize = 0;
1115+ int32_t iRowSize = 0;
1116+ int16_t iMaxMbWidth = 0;
1117+ int16_t iMaxMbHeight = 0;
1118+ int32_t i = 0;
1119+ int32_t iSpatialIdx = 0;
1120+ int32_t iTemporalIdx = 0;
1121+ int32_t iCntTid = 0;
1122+
1123+ if ( kiNumSpatialLayers <= 0 || kiNumSpatialLayers > MAX_DEPENDENCY_LAYER)
1124+ return 1;
1125+
1126+ pPtr = (SStrideTables *)pMa->WelsMalloc(sizeof(SStrideTables), "SStrideTables");
1127+ if (NULL == pPtr)
1128+ return 1;
1129+ (*ppCtx)->pStrideTab = pPtr;
1130+
1131+ iCntTid = pParam->iNumTemporalLayer > 1 ? 2 : 1;
1132+
1133+ iSpatialIdx = 0;
1134+ while (iSpatialIdx < kiNumSpatialLayers) {
1135+ const int32_t kiTmpWidth = (pParam->sDependencyLayers[iSpatialIdx].iFrameWidth + 15) >> 4;
1136+ const int32_t kiTmpHeight= (pParam->sDependencyLayers[iSpatialIdx].iFrameHeight + 15) >> 4;
1137+ int32_t iNumMb = kiTmpWidth * kiTmpHeight;
1138+
1139+ sMbSizeMap[iSpatialIdx].iMbWidth = kiTmpWidth;
1140+ sMbSizeMap[iSpatialIdx].iCountMbNum = iNumMb;
1141+
1142+ iNumMb *= sizeof(int16_t);
1143+ sMbSizeMap[iSpatialIdx].iSizeAllMbAlignCache = iNumMb;
1144+ iUnit2Size += iNumMb;
1145+
1146+ ++ iSpatialIdx;
1147+ }
1148+
1149+ // Adaptive size_cs, size_fdec by implementation dependency
1150+ iTemporalIdx= 0;
1151+ while ( iTemporalIdx < iCntTid )
1152+ {
1153+ const bool_t kbBaseTemporalFlag = (iTemporalIdx == 0);
1154+
1155+ iSpatialIdx = 0;
1156+ while ( iSpatialIdx < kiNumSpatialLayers )
1157+ {
1158+ SDLayerParam *fDlp = &pParam->sDependencyLayers[iSpatialIdx];
1159+
1160+ const int32_t kiWidthPad = WELS_ALIGN( fDlp->iFrameWidth, 16 ) + (PADDING_LENGTH<<1);
1161+ iLineSizeY[iSpatialIdx][kbBaseTemporalFlag] = WELS_ALIGN( kiWidthPad, 32 );
1162+ iLineSizeUV[iSpatialIdx][kbBaseTemporalFlag]= WELS_ALIGN( (kiWidthPad>>1), 16 );
1163+
1164+ iMapSpatialIdx[iCountLayersNeedCs[kbBaseTemporalFlag]][kbBaseTemporalFlag] = iSpatialIdx;
1165+ ++ iCountLayersNeedCs[kbBaseTemporalFlag];
1166+ ++ iSpatialIdx;
1167+ }
1168+ ++ iTemporalIdx;
1169+ }
1170+ iSizeDec= kiUnit1Size * (iCountLayersNeedCs[0] + iCountLayersNeedCs[1]);
1171+ iSizeEnc= kiUnit1Size * kiNumSpatialLayers;
1172+
1173+ iNeedAllocSize = iSizeDec + iSizeEnc + (iUnit2Size << 1);
1174+
1175+ pBase = (uint8_t *)pMa->WelsMalloc( iNeedAllocSize, "pBase" );
1176+ if ( NULL == pBase )
1177+ {
1178+ return 1;
1179+ }
1180+
1181+ pBaseDec= pBase; // iCountLayersNeedCs
1182+ pBaseEnc= pBaseDec + iSizeDec; // iNumSpatialLayers
1183+ pBaseMbX = pBaseEnc + iSizeEnc; // iNumSpatialLayers
1184+ pBaseMbY = pBaseMbX + iUnit2Size; // iNumSpatialLayers
1185+
1186+ iTemporalIdx= 0;
1187+ while ( iTemporalIdx < iCntTid )
1188+ {
1189+ const bool_t kbBaseTemporalFlag = (iTemporalIdx == 0);
1190+
1191+ iSpatialIdx = 0;
1192+ while ( iSpatialIdx < iCountLayersNeedCs[kbBaseTemporalFlag] )
1193+ {
1194+ const int32_t kiActualSpatialIdx = iMapSpatialIdx[iSpatialIdx][kbBaseTemporalFlag];
1195+ const int32_t kiLumaWidth = iLineSizeY[kiActualSpatialIdx][kbBaseTemporalFlag];
1196+ const int32_t kiChromaWidth = iLineSizeUV[kiActualSpatialIdx][kbBaseTemporalFlag];
1197+
1198+ WelsGetEncBlockStrideOffset( (int32_t *)pBaseDec, kiLumaWidth, kiChromaWidth );
1199+
1200+ pPtr->pStrideDecBlockOffset[kiActualSpatialIdx][kbBaseTemporalFlag] = (int32_t *)pBaseDec;
1201+ pBaseDec+= kiUnit1Size;
1202+
1203+ ++ iSpatialIdx;
1204+ }
1205+ ++ iTemporalIdx;
1206+ }
1207+ iTemporalIdx= 0;
1208+ while ( iTemporalIdx < iCntTid )
1209+ {
1210+ const bool_t kbBaseTemporalFlag = (iTemporalIdx == 0);
1211+
1212+ iSpatialIdx = 0;
1213+ while (iSpatialIdx < kiNumSpatialLayers)
1214+ {
1215+ int32_t iMatchIndex = 0;
1216+ bool_t bInMap = false;
1217+ bool_t bMatchFlag = false;
1218+
1219+ i = 0;
1220+ while ( i < iCountLayersNeedCs[kbBaseTemporalFlag] )
1221+ {
1222+ const int32_t kiActualIdx = iMapSpatialIdx[i][kbBaseTemporalFlag];
1223+ if ( kiActualIdx == iSpatialIdx )
1224+ {
1225+ bInMap = true;
1226+ break;
1227+ }
1228+ if ( !bMatchFlag )
1229+ {
1230+ iMatchIndex = kiActualIdx;
1231+ bMatchFlag = true;
1232+ }
1233+ ++ i;
1234+ }
1235+
1236+ if ( bInMap )
1237+ {
1238+ ++ iSpatialIdx;
1239+ continue;
1240+ }
1241+
1242+ // not in spatial map and assign match one to it
1243+ pPtr->pStrideDecBlockOffset[iSpatialIdx][kbBaseTemporalFlag] = pPtr->pStrideDecBlockOffset[iMatchIndex][kbBaseTemporalFlag];
1244+
1245+ ++ iSpatialIdx;
1246+ }
1247+ ++ iTemporalIdx;
1248+ }
1249+
1250+ iSpatialIdx = 0;
1251+ while ( iSpatialIdx < kiNumSpatialLayers )
1252+ {
1253+ const int32_t kiAllocMbSize = sMbSizeMap[iSpatialIdx].iSizeAllMbAlignCache;
1254+
1255+ pPtr->pStrideEncBlockOffset[iSpatialIdx] = (int32_t *)pBaseEnc;
1256+
1257+ pPtr->pMbIndexX[iSpatialIdx] = (int16_t *)pBaseMbX;
1258+ pPtr->pMbIndexY[iSpatialIdx] = (int16_t *)pBaseMbY;
1259+
1260+ pBaseEnc += kiUnit1Size;
1261+ pBaseMbX += kiAllocMbSize;
1262+ pBaseMbY += kiAllocMbSize;
1263+
1264+ ++ iSpatialIdx;
1265+ }
1266+
1267+ while ( iSpatialIdx < MAX_DEPENDENCY_LAYER )
1268+ {
1269+ pPtr->pStrideDecBlockOffset[iSpatialIdx][0] = NULL;
1270+ pPtr->pStrideDecBlockOffset[iSpatialIdx][1] = NULL;
1271+ pPtr->pStrideEncBlockOffset[iSpatialIdx] = NULL;
1272+ pPtr->pMbIndexX[iSpatialIdx] = NULL;
1273+ pPtr->pMbIndexY[iSpatialIdx] = NULL;
1274+
1275+ ++ iSpatialIdx;
1276+ }
1277+
1278+ // initialize pMbIndexX and pMbIndexY tables as below
1279+
1280+ iMaxMbWidth = sMbSizeMap[kiNumSpatialLayers-1].iMbWidth;
1281+ iMaxMbWidth = WELS_ALIGN(iMaxMbWidth, 4); // 4 loops for int16_t required introduced as below
1282+ iRowSize = iMaxMbWidth * sizeof(int16_t);
1283+
1284+ pTmpRow = (int16_t*)pMa->WelsMalloc( iRowSize, "pTmpRow" );
1285+ if ( NULL == pTmpRow )
1286+ {
1287+ return 1;
1288+ }
1289+ pRowX = pTmpRow;
1290+ pRowY = pRowX;
1291+ // initialize pRowX & pRowY
1292+ i = 0;
1293+ p = pRowX;
1294+ while ( i < iMaxMbWidth )
1295+ {
1296+ *p = i;
1297+ *(p+1) = 1+i;
1298+ *(p+2) = 2+i;
1299+ *(p+3) = 3+i;
1300+
1301+ p += 4;
1302+ i += 4;
1303+ }
1304+
1305+ iSpatialIdx = kiNumSpatialLayers;
1306+ while ( --iSpatialIdx >= 0 )
1307+ {
1308+ int16_t *pMbIndexX = pPtr->pMbIndexX[iSpatialIdx];
1309+ const int32_t kiMbWidth = sMbSizeMap[iSpatialIdx].iMbWidth;
1310+ const int32_t kiMbHeight = sMbSizeMap[iSpatialIdx].iCountMbNum / kiMbWidth;
1311+ const int32_t kiLineSize = kiMbWidth * sizeof(int16_t);
1312+
1313+ i = 0;
1314+ while ( i < kiMbHeight )
1315+ {
1316+ memcpy( pMbIndexX, pRowX, kiLineSize ); // confirmed_safe_unsafe_usage
1317+
1318+ pMbIndexX += kiMbWidth;
1319+ ++ i;
1320+ }
1321+ }
1322+
1323+ memset(pRowY, 0, iRowSize);
1324+ iMaxMbHeight = sMbSizeMap[kiNumSpatialLayers-1].iCountMbNum / sMbSizeMap[kiNumSpatialLayers-1].iMbWidth;
1325+ i = 0;
1326+ for (;;)
1327+ {
1328+ ENFORCE_STACK_ALIGN_1D(int16_t, t, 4, 16)
1329+
1330+ int32_t t32 = 0;
1331+ int16_t j = 0;
1332+
1333+ for ( iSpatialIdx = kiNumSpatialLayers-1; iSpatialIdx >= 0; -- iSpatialIdx )
1334+ {
1335+ const int32_t kiMbWidth = sMbSizeMap[iSpatialIdx].iMbWidth;
1336+ const int32_t kiMbHeight = sMbSizeMap[iSpatialIdx].iCountMbNum / kiMbWidth;
1337+ const int32_t kiLineSize = kiMbWidth * sizeof(int16_t);
1338+ int16_t *pMbIndexY = pPtr->pMbIndexY[iSpatialIdx] + i * kiMbWidth;
1339+
1340+ if ( i < kiMbHeight )
1341+ {
1342+ memcpy( pMbIndexY, pRowY, kiLineSize ); // confirmed_safe_unsafe_usage
1343+ }
1344+ }
1345+ ++ i;
1346+ if (i >= iMaxMbHeight)
1347+ break;
1348+
1349+ t32 = i | (i << 16);
1350+ ST32( t , t32 );
1351+ ST32( t+2, t32 );
1352+
1353+ p = pRowY;
1354+ while ( j < iMaxMbWidth )
1355+ {
1356+ ST64( p, LD64(t) );
1357+
1358+ p += 4;
1359+ j += 4;
1360+ }
1361+ }
1362+
1363+ pMa->WelsFree( pTmpRow, "pTmpRow" );
1364+ pTmpRow = NULL;
1365+
1366+ return 0;
1367+}
1368+
1369+/*!
1370+ * \brief request specific memory for SVC
1371+ * \pParam pEncCtx sWelsEncCtx*
1372+ * \return successful - 0; otherwise none 0 for failed
1373+ */
1374+int32_t RequestMemorySvc( sWelsEncCtx **ppCtx )
1375+{
1376+ SWelsSvcCodingParam *pParam = (*ppCtx)->pSvcParam;
1377+ CMemoryAlign *pMa = (*ppCtx)->pMemAlign;
1378+ SDLayerParam *pFinalSpatial = NULL;
1379+ int32_t iCountBsLen = 0;
1380+ int32_t iCountNals = 0;
1381+ int32_t iMaxPicWidth = 0;
1382+ int32_t iMaxPicHeight = 0;
1383+ int32_t iCountMaxMbNum = 0;
1384+ int32_t iIndex = 0;
1385+ int32_t iCountLayers = 0;
1386+ int32_t iResult = 0;
1387+ float fCompressRatioThr = .5f;
1388+ const int32_t kiNumDependencyLayers = pParam->iNumDependencyLayer;
1389+ const uint32_t kuiMvdInterTableSize = ( kiNumDependencyLayers == 1 ? (1 + (648 << 1)) : (1 + (972 << 1)) );
1390+ const uint32_t kuiMvdCacheAlginedSize = kuiMvdInterTableSize * sizeof(uint16_t);
1391+ int32_t iVclLayersBsSizeCount = 0;
1392+ int32_t iNonVclLayersBsSizeCount = 0;
1393+#if defined(MT_ENABLED)
1394+ int32_t iTargetSpatialBsSize = 0;
1395+#endif//MT_ENABLED
1396+
1397+ if ( kiNumDependencyLayers < 1 || kiNumDependencyLayers > MAX_DEPENDENCY_LAYER )
1398+ {
1399+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc() failed due to invalid iNumDependencyLayers(%d)!\n", kiNumDependencyLayers);
1400+ FreeMemorySvc( ppCtx );
1401+ return 1;
1402+ }
1403+
1404+ if ( pParam->uiGopSize == 0 || ( pParam->uiIntraPeriod && ((pParam->uiIntraPeriod % pParam->uiGopSize) != 0)) )
1405+ {
1406+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc() failed due to invalid uiIntraPeriod(%d) (=multipler of uiGopSize(%d)!",
1407+ pParam->uiIntraPeriod, pParam->uiGopSize);
1408+ FreeMemorySvc( ppCtx );
1409+ return 1;
1410+ }
1411+
1412+ pFinalSpatial = &pParam->sDependencyLayers[kiNumDependencyLayers - 1];
1413+ iMaxPicWidth = pFinalSpatial->iFrameWidth;
1414+ iMaxPicHeight = pFinalSpatial->iFrameHeight;
1415+ iCountMaxMbNum= ((15+iMaxPicWidth)>>4) * ((15+iMaxPicHeight)>>4);
1416+
1417+ iResult = AcquireLayersNals( ppCtx, pParam, &iCountLayers, &iCountNals );
1418+ if ( iResult )
1419+ {
1420+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), AcquireLayersNals failed(%d)!", iResult);
1421+ FreeMemorySvc( ppCtx );
1422+ return 1;
1423+ }
1424+
1425+ iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + pParam->iNumDependencyLayer * SPS_BUFFER_SIZE + (1+pParam->iNumDependencyLayer) * PPS_BUFFER_SIZE;
1426+
1427+ int32_t iLayerBsSize = 0;
1428+ iIndex = 0;
1429+ while(iIndex < pParam->iNumDependencyLayer)
1430+ {
1431+ SDLayerParam *fDlp = &pParam->sDependencyLayers[iIndex];
1432+
1433+ fCompressRatioThr = COMPRESS_RATIO_DECIDED_BY_RESOLUTION(fDlp->iFrameWidth, fDlp->iFrameHeight);
1434+
1435+ iLayerBsSize = WELS_ROUND( ( (3 * fDlp->iFrameWidth * fDlp->iFrameHeight)>>1) * fCompressRatioThr);
1436+ iLayerBsSize = WELS_ALIGN(iLayerBsSize, 4); // 4 bytes alinged
1437+ iVclLayersBsSizeCount += iLayerBsSize;
1438+ ++ iIndex;
1439+ }
1440+#if defined(MT_ENABLED)
1441+ iTargetSpatialBsSize = iLayerBsSize;
1442+#endif//MT_ENABLED
1443+ iCountBsLen = iNonVclLayersBsSizeCount + iVclLayersBsSizeCount;
1444+
1445+ pParam->iNumRefFrame = WELS_CLIP3(pParam->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
1446+
1447+ // Output
1448+ (*ppCtx)->pOut = (SWelsEncoderOutput *)pMa->WelsMalloc( sizeof(SWelsEncoderOutput), "SWelsEncoderOutput" );
1449+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pOut), FreeMemorySvc(ppCtx) )
1450+ (*ppCtx)->pOut->pBsBuffer = (uint8_t *)pMa->WelsMalloc( iCountBsLen, "pOut->pBsBuffer" );
1451+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pOut->pBsBuffer), FreeMemorySvc(ppCtx) )
1452+ (*ppCtx)->pOut->uiSize = iCountBsLen;
1453+ (*ppCtx)->pOut->sNalList = (SWelsNalRaw *)pMa->WelsMalloc( iCountNals * sizeof(SWelsNalRaw), "pOut->sNalList" );
1454+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pOut->sNalList), FreeMemorySvc(ppCtx) )
1455+ (*ppCtx)->pOut->iCountNals = iCountNals;
1456+ (*ppCtx)->pOut->iNalIndex = 0;
1457+
1458+#ifdef MT_ENABLED
1459+ if ( pParam->iMultipleThreadIdc > 1 )
1460+ {
1461+ (*ppCtx)->pFrameBs = (uint8_t *)pMa->WelsMalloc( iCountBsLen + (iTargetSpatialBsSize * ((*ppCtx)->iMaxSliceCount-1)), "pFrameBs" );
1462+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pFrameBs), FreeMemorySvc(ppCtx) )
1463+ (*ppCtx)->iFrameBsSize = iCountBsLen * (*ppCtx)->iMaxSliceCount;
1464+ }
1465+ else
1466+#endif//MT_ENABLED
1467+ {
1468+ (*ppCtx)->pFrameBs = (uint8_t *)pMa->WelsMalloc( iCountBsLen, "pFrameBs" );
1469+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pFrameBs), FreeMemorySvc(ppCtx) )
1470+ (*ppCtx)->iFrameBsSize = iCountBsLen;
1471+ }
1472+ (*ppCtx)->iPosBsBuffer = 0;
1473+
1474+#ifdef MT_ENABLED
1475+ // for pSlice bs buffers
1476+ if ( pParam->iMultipleThreadIdc > 1 && RequestMtResource( ppCtx, pParam, iCountBsLen, iTargetSpatialBsSize ) )
1477+ {
1478+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), RequestMtResource failed!");
1479+ FreeMemorySvc( ppCtx );
1480+ return 1;
1481+ }
1482+#endif
1483+
1484+ (*ppCtx)->pIntra4x4PredModeBlocks = static_cast<int8_t*>
1485+ (pMa->WelsMallocz( iCountMaxMbNum * INTRA_4x4_MODE_NUM, "pIntra4x4PredModeBlocks" ));
1486+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pIntra4x4PredModeBlocks), FreeMemorySvc(ppCtx) )
1487+
1488+ (*ppCtx)->pNonZeroCountBlocks = static_cast<int8_t*>
1489+ (pMa->WelsMallocz( iCountMaxMbNum * MB_LUMA_CHROMA_BLOCK4x4_NUM, "pNonZeroCountBlocks" ));
1490+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pNonZeroCountBlocks), FreeMemorySvc(ppCtx) )
1491+
1492+ (*ppCtx)->pMvUnitBlock4x4 = static_cast<SMVUnitXY*>
1493+ (pMa->WelsMallocz( iCountMaxMbNum * 2 * MB_BLOCK4x4_NUM * sizeof(SMVUnitXY), "pMvUnitBlock4x4" ));
1494+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pMvUnitBlock4x4), FreeMemorySvc(ppCtx) )
1495+
1496+ (*ppCtx)->pRefIndexBlock4x4 = static_cast<int8_t*>
1497+ (pMa->WelsMallocz( iCountMaxMbNum * 2 * MB_BLOCK8x8_NUM * sizeof(int8_t), "pRefIndexBlock4x4" ));
1498+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pRefIndexBlock4x4), FreeMemorySvc(ppCtx) )
1499+
1500+ (*ppCtx)->pSadCostMb = static_cast<int32_t*>
1501+ (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pSadCostMb" ));
1502+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSadCostMb), FreeMemorySvc(ppCtx))
1503+
1504+ (*ppCtx)->bEncCurFrmAsIdrFlag = true; // make sure first frame is IDR
1505+ (*ppCtx)->iGlobalQp = 26; // global qp in default
1506+
1507+ (*ppCtx)->pLtr = (SLTRState *)pMa->WelsMalloc( kiNumDependencyLayers*sizeof(SLTRState), "SLTRState" );
1508+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pLtr), FreeMemorySvc(ppCtx) )
1509+ int32_t i = 0;
1510+ for( i = 0; i < kiNumDependencyLayers; i++ )
1511+ {
1512+ ResetLtrState( &(*ppCtx)->pLtr[i] );
1513+ }
1514+
1515+ (*ppCtx)->ppRefPicListExt = (SRefList**)pMa->WelsMalloc( kiNumDependencyLayers * sizeof(SRefList *), "ppRefPicListExt" );
1516+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->ppRefPicListExt), FreeMemorySvc(ppCtx) )
1517+
1518+ // pSlice context list
1519+ (*ppCtx)->pSliceCtxList = (SSliceCtx *)pMa->WelsMallocz( kiNumDependencyLayers * sizeof(SSliceCtx), "pSliceCtxList" );
1520+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pSliceCtxList), FreeMemorySvc(ppCtx) )
1521+
1522+ (*ppCtx)->ppDqLayerList = (SDqLayer **)pMa->WelsMalloc( kiNumDependencyLayers * sizeof(SDqLayer *), "ppDqLayerList" );
1523+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->ppDqLayerList), FreeMemorySvc(ppCtx) )
1524+
1525+ // stride tables
1526+ if ( AllocStrideTables( ppCtx, kiNumDependencyLayers ) )
1527+ {
1528+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), AllocStrideTables failed!");
1529+ FreeMemorySvc( ppCtx );
1530+ return 1;
1531+ }
1532+
1533+ //Rate control module memory allocation
1534+ // only malloc once for RC pData, 12/14/2009
1535+ (*ppCtx)->pWelsSvcRc = (SWelsSvcRc *)pMa->WelsMallocz( kiNumDependencyLayers * sizeof(SWelsSvcRc), "pWelsSvcRc" );
1536+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pWelsSvcRc), FreeMemorySvc(ppCtx) )
1537+ //End of Rate control module memory allocation
1538+
1539+ //pVaa memory allocation
1540+ (*ppCtx)->pVaa = (SVAAFrameInfo *)pMa->WelsMallocz( sizeof(SVAAFrameInfo), "pVaa" );
1541+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa), FreeMemorySvc(ppCtx) )
1542+
1543+ if((*ppCtx)->pSvcParam->bEnableAdaptiveQuant)//malloc mem
1544+ {
1545+ (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureUnit = static_cast<SMotionTextureUnit*>
1546+ (pMa->WelsMallocz( iCountMaxMbNum * sizeof(SMotionTextureUnit), "pVaa->sAdaptiveQuantParam.pMotionTextureUnit" ));
1547+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureUnit), FreeMemorySvc(ppCtx) )
1548+ (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp = static_cast<int8_t*>
1549+ (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int8_t), "pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp" ));
1550+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp), FreeMemorySvc(ppCtx) )
1551+ }
1552+
1553+ (*ppCtx)->pVaa->pVaaBackgroundMbFlag = (int8_t *)pMa->WelsMallocz( iCountMaxMbNum * sizeof(int8_t), "pVaa->vaa_skip_mb_flag" );
1554+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->pVaaBackgroundMbFlag), FreeMemorySvc(ppCtx) )
1555+
1556+ (*ppCtx)->pVaa->sVaaCalcInfo.pSad8x8 = static_cast<int32_t(*)[4]>
1557+ (pMa->WelsMallocz( iCountMaxMbNum * 4 * sizeof(int32_t), "pVaa->sVaaCalcInfo.sad8x8" ));
1558+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSad8x8), FreeMemorySvc(ppCtx) )
1559+ (*ppCtx)->pVaa->sVaaCalcInfo.pSsd16x16 = static_cast<int32_t*>
1560+ (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pVaa->sVaaCalcInfo.pSsd16x16" ));
1561+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSsd16x16), FreeMemorySvc(ppCtx) )
1562+ (*ppCtx)->pVaa->sVaaCalcInfo.pSum16x16 = static_cast<int32_t*>
1563+ (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pVaa->sVaaCalcInfo.pSum16x16" ));
1564+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSum16x16), FreeMemorySvc(ppCtx) )
1565+ (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfSquare16x16 = static_cast<int32_t*>
1566+ (pMa->WelsMallocz( iCountMaxMbNum * sizeof(int32_t), "pVaa->sVaaCalcInfo.pSumOfSquare16x16" ));
1567+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfSquare16x16), FreeMemorySvc(ppCtx) )
1568+
1569+ if ((*ppCtx)->pSvcParam->bEnableBackgroundDetection) //BGD control
1570+ {
1571+ (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfDiff8x8 = static_cast<int32_t(*)[4]>
1572+ (pMa->WelsMallocz( iCountMaxMbNum * 4 * sizeof(int32_t), "pVaa->sVaaCalcInfo.sd_16x16" ));
1573+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfDiff8x8), FreeMemorySvc(ppCtx) )
1574+ (*ppCtx)->pVaa->sVaaCalcInfo.pMad8x8 = static_cast<uint8_t(*)[4]>
1575+ (pMa->WelsMallocz( iCountMaxMbNum * 4 * sizeof(uint8_t), "pVaa->sVaaCalcInfo.mad_16x16" ));
1576+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pMad8x8), FreeMemorySvc(ppCtx) )
1577+ }
1578+
1579+ //End of pVaa memory allocation
1580+
1581+ iResult = InitDqLayers( ppCtx );
1582+ if ( iResult )
1583+ {
1584+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitDqLayers failed(%d)!", iResult );
1585+ FreeMemorySvc( ppCtx );
1586+ return iResult;
1587+ }
1588+
1589+ if( InitMbListD( ppCtx ) )
1590+ {
1591+ WelsLog( *ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitMbListD failed!" );
1592+ FreeMemorySvc( ppCtx );
1593+ return 1;
1594+ }
1595+
1596+ (*ppCtx)->pMvdCostTableInter = (uint16_t *)pMa->WelsMallocz( 52 * kuiMvdCacheAlginedSize, "pMvdCostTableInter" );
1597+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == (*ppCtx)->pMvdCostTableInter), FreeMemorySvc(ppCtx) )
1598+ MvdCostInit( (*ppCtx)->pMvdCostTableInter, kuiMvdInterTableSize ); //should put to a better place?
1599+
1600+ if ( (*ppCtx)->ppRefPicListExt[0] != NULL && (*ppCtx)->ppRefPicListExt[0]->pRef[0] != NULL )
1601+ (*ppCtx)->pDecPic = (*ppCtx)->ppRefPicListExt[0]->pRef[0];
1602+ else
1603+ (*ppCtx)->pDecPic = NULL; // error here
1604+
1605+ (*ppCtx)->pSps = &(*ppCtx)->pSpsArray[0];
1606+ (*ppCtx)->pPps = &(*ppCtx)->pPPSArray[0];
1607+
1608+ return 0;
1609+}
1610+
1611+
1612+/*!
1613+ * \brief free memory in SVC core encoder
1614+ * \pParam pEncCtx sWelsEncCtx*
1615+ * \return none
1616+ */
1617+void FreeMemorySvc( sWelsEncCtx **ppCtx )
1618+{
1619+ if ( NULL != *ppCtx )
1620+ {
1621+ sWelsEncCtx *pCtx = *ppCtx;
1622+ CMemoryAlign *pMa = pCtx->pMemAlign;
1623+ SWelsSvcCodingParam *pParam= pCtx->pSvcParam;
1624+ int32_t ilayer = 0;
1625+
1626+ // SStrideTables
1627+ if ( NULL != pCtx->pStrideTab )
1628+ {
1629+ if ( NULL != pCtx->pStrideTab->pStrideDecBlockOffset[0][1] )
1630+ {
1631+ pMa->WelsFree( pCtx->pStrideTab->pStrideDecBlockOffset[0][1], "pBase" );
1632+ pCtx->pStrideTab->pStrideDecBlockOffset[0][1] = NULL;
1633+ }
1634+ pMa->WelsFree(pCtx->pStrideTab, "SStrideTables");
1635+ pCtx->pStrideTab = NULL;
1636+ }
1637+ // pDq idc map
1638+ if ( NULL != pCtx->pDqIdcMap )
1639+ {
1640+ pMa->WelsFree( pCtx->pDqIdcMap, "pDqIdcMap" );
1641+ pCtx->pDqIdcMap = NULL;
1642+ }
1643+
1644+ if ( NULL != pCtx->pOut )
1645+ {
1646+ // bs pBuffer
1647+ if ( NULL != pCtx->pOut->pBsBuffer )
1648+ {
1649+ pMa->WelsFree( pCtx->pOut->pBsBuffer, "pOut->pBsBuffer" );
1650+ pCtx->pOut->pBsBuffer = NULL;
1651+ }
1652+ // NALs list
1653+ if ( NULL != pCtx->pOut->sNalList )
1654+ {
1655+ pMa->WelsFree( pCtx->pOut->sNalList, "pOut->sNalList" );
1656+ pCtx->pOut->sNalList = NULL;
1657+ }
1658+ pMa->WelsFree( pCtx->pOut, "SWelsEncoderOutput" );
1659+ pCtx->pOut = NULL;
1660+ }
1661+
1662+#ifdef MT_ENABLED
1663+ if ( pParam != NULL && pParam->iMultipleThreadIdc > 1 )
1664+ ReleaseMtResource( ppCtx );
1665+#endif//MT_ENABLED
1666+
1667+ // frame bitstream pBuffer
1668+ if ( NULL != pCtx->pFrameBs )
1669+ {
1670+ pMa->WelsFree( pCtx->pFrameBs, "pFrameBs" );
1671+ pCtx->pFrameBs = NULL;
1672+ }
1673+
1674+ // pSpsArray
1675+ if ( NULL != pCtx->pSpsArray )
1676+ {
1677+ pMa->WelsFree( pCtx->pSpsArray, "pSpsArray" );
1678+ pCtx->pSpsArray = NULL;
1679+ }
1680+ // pPPSArray
1681+ if ( NULL != pCtx->pPPSArray )
1682+ {
1683+ pMa->WelsFree( pCtx->pPPSArray, "pPPSArray" );
1684+ pCtx->pPPSArray = NULL;
1685+ }
1686+ // subset_sps_array
1687+ if ( NULL != pCtx->pSubsetArray )
1688+ {
1689+ pMa->WelsFree( pCtx->pSubsetArray, "pSubsetArray" );
1690+ pCtx->pSubsetArray = NULL;
1691+ }
1692+
1693+ if( NULL != pCtx->pIntra4x4PredModeBlocks ){
1694+ pMa->WelsFree( pCtx->pIntra4x4PredModeBlocks, "pIntra4x4PredModeBlocks" );
1695+ pCtx->pIntra4x4PredModeBlocks = NULL;
1696+ }
1697+
1698+ if( NULL != pCtx->pNonZeroCountBlocks ){
1699+ pMa->WelsFree( pCtx->pNonZeroCountBlocks, "pNonZeroCountBlocks" );
1700+ pCtx->pNonZeroCountBlocks = NULL;
1701+ }
1702+
1703+ if ( NULL != pCtx->pMvUnitBlock4x4)
1704+ {
1705+ pMa->WelsFree( pCtx->pMvUnitBlock4x4, "pMvUnitBlock4x4" );
1706+ pCtx->pMvUnitBlock4x4 = NULL;
1707+ }
1708+
1709+ if ( NULL != pCtx->pRefIndexBlock4x4)
1710+ {
1711+ pMa->WelsFree( pCtx->pRefIndexBlock4x4, "pRefIndexBlock4x4" );
1712+ pCtx->pRefIndexBlock4x4 = NULL;
1713+ }
1714+
1715+ if ( NULL != pCtx->ppMbListD )
1716+ {
1717+ if( NULL != pCtx->ppMbListD[0] ){
1718+ pMa->WelsFree( pCtx->ppMbListD[0], "ppMbListD[0]" );
1719+ (*ppCtx)->ppMbListD[0] = NULL;
1720+ }
1721+ pMa->WelsFree( pCtx->ppMbListD, "ppMbListD" );
1722+ pCtx->ppMbListD = NULL;
1723+ }
1724+
1725+ if ( NULL != pCtx->pSadCostMb)
1726+ {
1727+ pMa->WelsFree( pCtx->pSadCostMb, "pSadCostMb" );
1728+ pCtx->pSadCostMb = NULL;
1729+ }
1730+
1731+ // SLTRState
1732+ if ( NULL != pCtx->pLtr )
1733+ {
1734+ pMa->WelsFree( pCtx->pLtr, "SLTRState" );
1735+ pCtx->pLtr = NULL;
1736+ }
1737+
1738+ // pDq layers list
1739+ ilayer = 0;
1740+ if ( NULL != pCtx->ppDqLayerList && pParam != NULL )
1741+ {
1742+ while (ilayer < pParam->iNumDependencyLayer) {
1743+ SDqLayer *pDq = pCtx->ppDqLayerList[ilayer];
1744+ SDLayerParam *pDlp = &pCtx->pSvcParam->sDependencyLayers[ilayer];
1745+ const BOOL_T kbIsDynamicSlicing = (SM_DYN_SLICE == pDlp->sMso.uiSliceMode);
1746+
1747+ // pDq layers
1748+ if ( NULL != pDq )
1749+ {
1750+ if ( NULL != pDq->sLayerInfo.pSliceInLayer )
1751+ {
1752+ int32_t iSliceIdx = 0;
1753+ int32_t iSliceNum = GetInitialSliceNum( pDq->iMbWidth, pDq->iMbHeight, &pDlp->sMso );
1754+ if (iSliceNum < 1)
1755+ iSliceNum = 1;
1756+ while(iSliceIdx < iSliceNum)
1757+ {
1758+ SSlice *pSlice = &pDq->sLayerInfo.pSliceInLayer[iSliceIdx];
1759+ FreeMbCache(&pSlice->sMbCacheInfo, pMa);
1760+ ++ iSliceIdx;
1761+ }
1762+ pMa->WelsFree( pDq->sLayerInfo.pSliceInLayer, "pSliceInLayer" );
1763+ pDq->sLayerInfo.pSliceInLayer = NULL;
1764+ }
1765+ if ( kbIsDynamicSlicing )
1766+ {
1767+ pMa->WelsFree( pDq->pNumSliceCodedOfPartition, "pNumSliceCodedOfPartition" );
1768+ pDq->pNumSliceCodedOfPartition = NULL;
1769+ pMa->WelsFree( pDq->pLastCodedMbIdxOfPartition, "pLastCodedMbIdxOfPartition" );
1770+ pDq->pLastCodedMbIdxOfPartition = NULL;
1771+ pMa->WelsFree( pDq->pLastMbIdxOfPartition, "pLastMbIdxOfPartition" );
1772+ pDq->pLastMbIdxOfPartition = NULL;
1773+ }
1774+
1775+ pMa->WelsFree( pDq, "pDq" );
1776+ pDq = NULL;
1777+ pCtx->ppDqLayerList[ilayer] = NULL;
1778+ }
1779+ ++ ilayer;
1780+ }
1781+ pMa->WelsFree( pCtx->ppDqLayerList, "ppDqLayerList" );
1782+ pCtx->ppDqLayerList = NULL;
1783+ }
1784+ FreeSpatialPictures( pCtx );
1785+
1786+ // reference picture list extension
1787+ if ( NULL != pCtx->ppRefPicListExt && pParam != NULL )
1788+ {
1789+ ilayer = 0;
1790+ while (ilayer < pParam->iNumDependencyLayer) {
1791+ SRefList *pRefList = pCtx->ppRefPicListExt[ilayer];
1792+ if ( NULL != pRefList )
1793+ {
1794+ int32_t iRef = 0;
1795+ do {
1796+ if ( pRefList->pRef[iRef] != NULL )
1797+ {
1798+ FreePicture( pMa, &pRefList->pRef[iRef] );
1799+ }
1800+ ++ iRef;
1801+ } while(iRef < 1 + pParam->iNumRefFrame);
1802+
1803+ pMa->WelsFree( pCtx->ppRefPicListExt[ilayer], "ppRefPicListExt[]" );
1804+ pCtx->ppRefPicListExt[ilayer] = NULL;
1805+ }
1806+ ++ ilayer;
1807+ }
1808+
1809+ pMa->WelsFree( pCtx->ppRefPicListExt, "ppRefPicListExt" );
1810+ pCtx->ppRefPicListExt = NULL;
1811+ }
1812+
1813+ // pSlice context list
1814+ if ( NULL != pCtx->pSliceCtxList && pParam != NULL )
1815+ {
1816+ ilayer = 0;
1817+ while (ilayer < pParam->iNumDependencyLayer) {
1818+ SSliceCtx *pSliceCtx = &pCtx->pSliceCtxList[ilayer];
1819+ if ( NULL != pSliceCtx )
1820+ UninitSlicePEncCtx( pSliceCtx, pMa );
1821+ ++ ilayer;
1822+ }
1823+ pMa->WelsFree( pCtx->pSliceCtxList, "pSliceCtxList" );
1824+ pCtx->pSliceCtxList = NULL;
1825+ }
1826+
1827+ // VAA
1828+ if ( NULL != pCtx->pVaa )
1829+ {
1830+ if(pCtx->pSvcParam->bEnableAdaptiveQuant)//free mem
1831+ {
1832+ pMa->WelsFree( pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureUnit, "pVaa->sAdaptiveQuantParam.pMotionTextureUnit" );
1833+ pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureUnit = NULL;
1834+ pMa->WelsFree( pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp, "pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp" );
1835+ pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp = NULL;
1836+ }
1837+
1838+ pMa->WelsFree( pCtx->pVaa->pVaaBackgroundMbFlag, "pVaa->pVaaBackgroundMbFlag");
1839+ pCtx->pVaa->pVaaBackgroundMbFlag = NULL;
1840+ pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSad8x8, "pVaa->sVaaCalcInfo.sad8x8" );
1841+ pCtx->pVaa->sVaaCalcInfo.pSad8x8 = NULL;
1842+ pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSsd16x16, "pVaa->sVaaCalcInfo.pSsd16x16" );
1843+ pCtx->pVaa->sVaaCalcInfo.pSsd16x16 = NULL;
1844+ pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSum16x16, "pVaa->sVaaCalcInfo.pSum16x16" );
1845+ pCtx->pVaa->sVaaCalcInfo.pSum16x16 = NULL;
1846+ pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSumOfSquare16x16, "pVaa->sVaaCalcInfo.pSumOfSquare16x16" );
1847+ pCtx->pVaa->sVaaCalcInfo.pSumOfSquare16x16 = NULL;
1848+
1849+ if (pCtx->pSvcParam->bEnableBackgroundDetection) //BGD control
1850+ {
1851+ pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pSumOfDiff8x8, "pVaa->sVaaCalcInfo.pSumOfDiff8x8" );
1852+ pCtx->pVaa->sVaaCalcInfo.pSumOfDiff8x8 = NULL;
1853+ pMa->WelsFree( pCtx->pVaa->sVaaCalcInfo.pMad8x8, "pVaa->sVaaCalcInfo.pMad8x8" );
1854+ pCtx->pVaa->sVaaCalcInfo.pMad8x8 = NULL;
1855+ }
1856+
1857+ pMa->WelsFree( pCtx->pVaa, "pVaa" );
1858+ pCtx->pVaa = NULL;
1859+ }
1860+
1861+ WelsRcFreeMemory(pCtx);
1862+ // rate control module memory free
1863+ if ( NULL != pCtx->pWelsSvcRc )
1864+ {
1865+ pMa->WelsFree( pCtx->pWelsSvcRc, "pWelsSvcRc" );
1866+ pCtx->pWelsSvcRc = NULL;
1867+ }
1868+
1869+ /* MVD cost tables for Inter */
1870+ if ( NULL != pCtx->pMvdCostTableInter )
1871+ {
1872+ pMa->WelsFree( pCtx->pMvdCostTableInter, "pMvdCostTableInter" );
1873+ pCtx->pMvdCostTableInter = NULL;
1874+ }
1875+
1876+#ifdef ENABLE_TRACE_FILE
1877+ if ( NULL != pCtx->pFileLog )
1878+ {
1879+ fclose( pCtx->pFileLog );
1880+ pCtx->pFileLog = NULL;
1881+ }
1882+ pCtx->uiSizeLog = 0;
1883+#endif//ENABLE_TRACE_FILE
1884+
1885+ FreeCodingParam( &pCtx->pSvcParam, pMa );
1886+ if ( NULL != pCtx->pFuncList )
1887+ {
1888+ pMa->WelsFree(pCtx->pFuncList, "SWelsFuncPtrList");
1889+ pCtx->pFuncList = NULL;
1890+ }
1891+
1892+#if defined(MEMORY_MONITOR)
1893+ assert(pMa->WelsGetMemoryUsage() == 0); // ensure all memory free well
1894+#endif//MEMORY_MONITOR
1895+
1896+ if ( (*ppCtx)->pMemAlign != NULL )
1897+ {
1898+ WelsLog( NULL, WELS_LOG_INFO, "FreeMemorySvc(), verify memory usage (%d bytes) after free..\n", (*ppCtx)->pMemAlign->WelsGetMemoryUsage() );
1899+ delete (*ppCtx)->pMemAlign;
1900+ (*ppCtx)->pMemAlign = NULL;
1901+ }
1902+
1903+ free(*ppCtx);
1904+ *ppCtx = NULL;
1905+ }
1906+}
1907+
1908+int32_t InitSliceSettings( SWelsSvcCodingParam *pCodingParam, const int32_t kiCpuCores, int16_t *pMaxSliceCount )
1909+{
1910+ int32_t iSpatialIdx = 0, iSpatialNum = pCodingParam->iNumDependencyLayer;
1911+ int16_t iMaxSliceCount = 0;
1912+
1913+ do {
1914+ SDLayerParam *pDlp = &pCodingParam->sDependencyLayers[iSpatialIdx];
1915+ SMulSliceOption *pMso = &pDlp->sMso;
1916+ SSliceArgument *pSlcArg = &pMso->sSliceArgument;
1917+ const int32_t kiMbWidth = (pDlp->iFrameWidth+15)>>4;
1918+ const int32_t kiMbHeight = (pDlp->iFrameHeight+15)>>4;
1919+ const int32_t kiMbNumInFrame = kiMbWidth * kiMbHeight;
1920+#if defined(MT_ENABLED)
1921+#if defined(DYNAMIC_SLICE_ASSIGN)
1922+ int32_t iSliceNum = (SM_FIXEDSLCNUM_SLICE == pMso->uiSliceMode || SM_DYN_SLICE == pMso->uiSliceMode) ? kiCpuCores : pSlcArg->iSliceNum; // uiSliceNum per input has been validated at ParamValidationExt()
1923+#else//!DYNAMIC_SLICE_ASSIGN
1924+ int32_t iSliceNum = (SM_DYN_SLICE == pMso->uiSliceMode) ? kiCpuCores : pSlcArg->uiSliceNum; // uiSliceNum per input has been validated at ParamValidationExt()
1925+#endif//DYNAMIC_SLICE_ASSIGN
1926+#else//!MT_ENABLED
1927+ int16_t iSliceNum = pSlcArg->iSliceNum; // uiSliceNum per input has been validated at ParamValidationExt()
1928+#endif//MT_ENABLED
1929+
1930+ // NOTE: Per design, in case MT/DYNAMIC_SLICE_ASSIGN enabled, for SM_FIXEDSLCNUM_SLICE mode,
1931+ // uiSliceNum of current spatial layer settings equals to uiCpuCores number; SM_DYN_SLICE mode,
1932+ // uiSliceNum intials as uiCpuCores also, stay tuned dynamically slicing in future
1933+ pSlcArg->iSliceNum = iSliceNum; // used fixed one
1934+
1935+ switch(pMso->uiSliceMode)
1936+ {
1937+ case SM_DYN_SLICE:
1938+ iMaxSliceCount = AVERSLICENUM_CONSTRAINT;
1939+//#ifndef MT_ENABLED
1940+ break; // go through for MT_ENABLED & SM_DYN_SLICE?
1941+//#endif//MT_ENABLED
1942+ case SM_FIXEDSLCNUM_SLICE:
1943+ if ( iSliceNum > iMaxSliceCount )
1944+ iMaxSliceCount = iSliceNum;
1945+ // need perform check due uiSliceNum might change, although has been initialized somewhere outside
1946+ if (pCodingParam->bEnableRc)
1947+ {
1948+ GomValidCheckSliceMbNum( kiMbWidth, kiMbHeight, pSlcArg );
1949+ }
1950+ else
1951+ {
1952+ CheckFixedSliceNumMultiSliceSetting( kiMbNumInFrame, pSlcArg );
1953+ }
1954+ break;
1955+ case SM_SINGLE_SLICE:
1956+ if ( iSliceNum > iMaxSliceCount )
1957+ iMaxSliceCount = iSliceNum;
1958+ break;
1959+ case SM_RASTER_SLICE:
1960+ if ( iSliceNum > iMaxSliceCount )
1961+ iMaxSliceCount = iSliceNum;
1962+ break;
1963+ case SM_ROWMB_SLICE:
1964+ if ( iSliceNum > iMaxSliceCount )
1965+ iMaxSliceCount = iSliceNum;
1966+ break;
1967+ default:
1968+ break;
1969+ }
1970+
1971+ ++ iSpatialIdx;
1972+ } while(iSpatialIdx < iSpatialNum);
1973+
1974+#ifdef MT_ENABLED
1975+ pCodingParam->iCountThreadsNum = WELS_MIN(kiCpuCores, iMaxSliceCount);
1976+ pCodingParam->iMultipleThreadIdc = pCodingParam->iCountThreadsNum;
1977+#else
1978+ pCodingParam->iMultipleThreadIdc = 1;
1979+ pCodingParam->iCountThreadsNum = 1;
1980+#endif//MT_ENABLED
1981+
1982+#ifndef WELS_TESTBED // for product release and non-SGE testing
1983+
1984+ if ( kiCpuCores < 2 ) // single CPU core, make no sense for MT parallelization
1985+ {
1986+ pCodingParam->iMultipleThreadIdc = 1;
1987+ pCodingParam->iCountThreadsNum = 1;
1988+ }
1989+#endif
1990+
1991+ *pMaxSliceCount = iMaxSliceCount;
1992+
1993+ return 0;
1994+}
1995+
1996+/*!
1997+ * \brief log output for cpu features/capabilities
1998+ */
1999+void OutputCpuFeaturesLog( uint32_t uiCpuFeatureFlags, uint32_t uiCpuCores, int32_t iCacheLineSize )
2000+{
2001+ // welstracer output
2002+ WelsLog(NULL, WELS_LOG_INFO, "WELS CPU features/capacities (0x%x) detected: \t" \
2003+ "HTT: %c, " \
2004+ "MMX: %c, " \
2005+ "MMXEX: %c, " \
2006+ "SSE: %c, " \
2007+ "SSE2: %c, " \
2008+ "SSE3: %c, " \
2009+ "SSSE3: %c, " \
2010+ "SSE4.1: %c, " \
2011+ "SSE4.2: %c, " \
2012+ "AVX: %c, " \
2013+ "FMA: %c, " \
2014+ "X87-FPU: %c, " \
2015+ "3DNOW: %c, " \
2016+ "3DNOWEX: %c, " \
2017+ "ALTIVEC: %c, " \
2018+ "CMOV: %c, " \
2019+ "MOVBE: %c, " \
2020+ "AES: %c, " \
2021+ "NUMBER OF LOGIC PROCESSORS ON CHIP: %d, " \
2022+ "CPU CACHE LINE SIZE (BYTES): %d\n",
2023+ uiCpuFeatureFlags,
2024+ (uiCpuFeatureFlags & WELS_CPU_HTT) ? 'Y' : 'N',
2025+ (uiCpuFeatureFlags & WELS_CPU_MMX) ? 'Y' : 'N',
2026+ (uiCpuFeatureFlags & WELS_CPU_MMXEXT) ? 'Y' : 'N',
2027+ (uiCpuFeatureFlags & WELS_CPU_SSE) ? 'Y' : 'N',
2028+ (uiCpuFeatureFlags & WELS_CPU_SSE2) ? 'Y' : 'N',
2029+ (uiCpuFeatureFlags & WELS_CPU_SSE3) ? 'Y' : 'N',
2030+ (uiCpuFeatureFlags & WELS_CPU_SSSE3) ? 'Y' : 'N',
2031+ (uiCpuFeatureFlags & WELS_CPU_SSE41) ? 'Y' : 'N',
2032+ (uiCpuFeatureFlags & WELS_CPU_SSE42) ? 'Y' : 'N',
2033+ (uiCpuFeatureFlags & WELS_CPU_AVX) ? 'Y' : 'N',
2034+ (uiCpuFeatureFlags & WELS_CPU_FMA) ? 'Y' : 'N',
2035+ (uiCpuFeatureFlags & WELS_CPU_FPU) ? 'Y' : 'N',
2036+ (uiCpuFeatureFlags & WELS_CPU_3DNOW) ? 'Y' : 'N',
2037+ (uiCpuFeatureFlags & WELS_CPU_3DNOWEXT) ? 'Y' : 'N',
2038+ (uiCpuFeatureFlags & WELS_CPU_ALTIVEC) ? 'Y' : 'N',
2039+ (uiCpuFeatureFlags & WELS_CPU_CMOV) ? 'Y' : 'N',
2040+ (uiCpuFeatureFlags & WELS_CPU_MOVBE) ? 'Y' : 'N',
2041+ (uiCpuFeatureFlags & WELS_CPU_AES) ? 'Y' : 'N',
2042+ uiCpuCores,
2043+ iCacheLineSize );
2044+
2045+#ifdef _DEBUG // output at console & _debug
2046+ fprintf( stderr, "WELS CPU features/capacities (0x%x) detected: \n" \
2047+ "HTT: %c, " \
2048+ "MMX: %c, " \
2049+ "MMXEX: %c, " \
2050+ "SSE: %c, " \
2051+ "SSE2: %c, " \
2052+ "SSE3: %c, " \
2053+ "SSSE3: %c, " \
2054+ "SSE4.1: %c, " \
2055+ "SSE4.2: %c, " \
2056+ "AVX: %c, " \
2057+ "FMA: %c, " \
2058+ "X87-FPU: %c, " \
2059+ "3DNOW: %c, " \
2060+ "3DNOWEX: %c, " \
2061+ "ALTIVEC: %c, " \
2062+ "CMOV: %c, " \
2063+ "MOVBE: %c, " \
2064+ "AES: %c, " \
2065+ "NUMBER OF LOGIC PROCESSORS ON CHIP: %d, " \
2066+ "CPU CACHE LINE SIZE (BYTES): %d\n",
2067+ uiCpuFeatureFlags,
2068+ (uiCpuFeatureFlags & WELS_CPU_HTT) ? 'Y' : 'N',
2069+ (uiCpuFeatureFlags & WELS_CPU_MMX) ? 'Y' : 'N',
2070+ (uiCpuFeatureFlags & WELS_CPU_MMXEXT) ? 'Y' : 'N',
2071+ (uiCpuFeatureFlags & WELS_CPU_SSE) ? 'Y' : 'N',
2072+ (uiCpuFeatureFlags & WELS_CPU_SSE2) ? 'Y' : 'N',
2073+ (uiCpuFeatureFlags & WELS_CPU_SSE3) ? 'Y' : 'N',
2074+ (uiCpuFeatureFlags & WELS_CPU_SSSE3) ? 'Y' : 'N',
2075+ (uiCpuFeatureFlags & WELS_CPU_SSE41) ? 'Y' : 'N',
2076+ (uiCpuFeatureFlags & WELS_CPU_SSE42) ? 'Y' : 'N',
2077+ (uiCpuFeatureFlags & WELS_CPU_AVX) ? 'Y' : 'N',
2078+ (uiCpuFeatureFlags & WELS_CPU_FMA) ? 'Y' : 'N',
2079+ (uiCpuFeatureFlags & WELS_CPU_FPU) ? 'Y' : 'N',
2080+ (uiCpuFeatureFlags & WELS_CPU_3DNOW) ? 'Y' : 'N',
2081+ (uiCpuFeatureFlags & WELS_CPU_3DNOWEXT) ? 'Y' : 'N',
2082+ (uiCpuFeatureFlags & WELS_CPU_ALTIVEC) ? 'Y' : 'N',
2083+ (uiCpuFeatureFlags & WELS_CPU_CMOV) ? 'Y' : 'N',
2084+ (uiCpuFeatureFlags & WELS_CPU_MOVBE) ? 'Y' : 'N',
2085+ (uiCpuFeatureFlags & WELS_CPU_AES) ? 'Y' : 'N',
2086+ uiCpuCores,
2087+ iCacheLineSize );
2088+#endif//_DEBUG
2089+}
2090+
2091+/*!
2092+ * \brief initialize Wels avc encoder core library
2093+ * \pParam ppCtx sWelsEncCtx**
2094+ * \pParam pParam SWelsSvcCodingParam*
2095+ * \return successful - 0; otherwise none 0 for failed
2096+ */
2097+int32_t WelsInitEncoderExt( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pCodingParam )
2098+{
2099+ sWelsEncCtx *pCtx = NULL;
2100+ int32_t iRet = 0;
2101+ uint32_t uiCpuFeatureFlags = 0; // CPU features
2102+ int32_t uiCpuCores = 1; // number of logic processors on physical processor package, one logic processor means HTT not supported
2103+ int32_t iCacheLineSize = 16; // on chip cache line size in byte
2104+ int16_t iSliceNum = 1; // number of slices used
2105+
2106+ if ( NULL == ppCtx || NULL == pCodingParam )
2107+ {
2108+ WelsLog(NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), NULL == ppCtx(0x%p) or NULL == pCodingParam(0x%p).\n", (void *)ppCtx, (void *)pCodingParam);
2109+ return 1;
2110+ }
2111+
2112+ iRet = ParamValidationExt( pCodingParam );
2113+ if ( iRet != 0 )
2114+ {
2115+ WelsLog(NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), ParamValidationExt failed return %d.\n", iRet);
2116+ return iRet;
2117+ }
2118+
2119+ // for cpu features detection, Only detect once??
2120+#ifdef X86_ASM
2121+ uiCpuFeatureFlags = WelsCPUFeatureDetect( &uiCpuCores ); // detect cpu capacity features
2122+ if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_128 )
2123+ iCacheLineSize = 128;
2124+ else if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_64 )
2125+ iCacheLineSize = 64;
2126+ else if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_32 )
2127+ iCacheLineSize = 32;
2128+ else if ( uiCpuFeatureFlags & WELS_CPU_CACHELINE_16 )
2129+ iCacheLineSize = 16;
2130+ OutputCpuFeaturesLog( uiCpuFeatureFlags, uiCpuCores, iCacheLineSize );
2131+#else
2132+ iCacheLineSize = 16; // 16 bytes aligned in default
2133+#endif//X86_ASM
2134+
2135+#ifndef WELS_TESTBED
2136+
2137+#if defined(MT_ENABLED) && defined(DYNAMIC_DETECT_CPU_CORES)
2138+ if ( pCodingParam->iMultipleThreadIdc > 0 )
2139+ uiCpuCores = pCodingParam->iMultipleThreadIdc;
2140+ else
2141+ {
2142+ if ( uiCpuFeatureFlags == 0 ) // cpuid not supported, use high level system API as followed to detect number of pysical/logic processor
2143+ uiCpuCores = DynamicDetectCpuCores();
2144+ // So far so many cpu cores up to MAX_THREADS_NUM mean for server platforms,
2145+ // for client application here it is constrained by maximal to MAX_THREADS_NUM
2146+ if ( uiCpuCores > MAX_THREADS_NUM ) // MAX_THREADS_NUM
2147+ uiCpuCores = MAX_THREADS_NUM; // MAX_THREADS_NUM
2148+ else if ( uiCpuCores < 1 ) // just for safe
2149+ uiCpuCores = 1;
2150+ }
2151+#endif//MT_ENABLED && DYNAMIC_DETECT_CPU_CORES
2152+
2153+#else//WELS_TESTBED
2154+
2155+ uiCpuCores = pCodingParam->iMultipleThreadIdc; // assigned uiCpuCores from iMultipleThreadIdc from SGE testing
2156+
2157+#endif//WELS_TESTBED
2158+
2159+ uiCpuCores = WELS_CLIP3(uiCpuCores, 1, MAX_THREADS_NUM);
2160+
2161+ if ( InitSliceSettings(pCodingParam, uiCpuCores, &iSliceNum ) )
2162+ {
2163+ WelsLog(NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), InitSliceSettings failed.\n");
2164+ return 1;
2165+ }
2166+
2167+ *ppCtx = NULL;
2168+
2169+ pCtx = static_cast<sWelsEncCtx*>(malloc( sizeof(sWelsEncCtx) ));
2170+
2171+ WELS_VERIFY_RETURN_IF(1, (NULL == pCtx))
2172+ memset( pCtx, 0, sizeof(sWelsEncCtx) );
2173+
2174+ pCtx->pMemAlign = new CMemoryAlign( iCacheLineSize );
2175+ WELS_VERIFY_RETURN_PROC_IF( 1, (NULL == pCtx->pMemAlign), FreeMemorySvc(&pCtx) )
2176+
2177+ // for logs
2178+#ifdef ENABLE_TRACE_FILE
2179+ if (wlog == WelsLogDefault)
2180+ {
2181+ str_t fname[MAX_FNAME_LEN] = {0};
2182+
2183+#if defined (_MSC_VER)
2184+#if _MSC_VER>=1500
2185+ SNPRINTF(fname, MAX_FNAME_LEN, MAX_FNAME_LEN, "%swels_svc_encoder_trace.txt", pCodingParam->sTracePath ); // confirmed_safe_unsafe_usage
2186+#else
2187+ SNPRINTF(fname, MAX_FNAME_LEN, "%swels_svc_encoder_trace.txt", pCodingParam->sTracePath ); // confirmed_safe_unsafe_usage
2188+#endif//_MSC_VER>=1500
2189+#else
2190+ //GNUC/
2191+ SNPRINTF(fname, MAX_FNAME_LEN, "%swels_svc_encoder_trace.txt", pCodingParam->sTracePath ); // confirmed_safe_unsafe_usage
2192+#endif//_MSC_VER
2193+
2194+
2195+#if defined(__GNUC__)
2196+ pCtx->pFileLog = FOPEN(fname, "wt+");
2197+#else//WIN32
2198+#if defined(WIN32) && defined(_MSC_VER)
2199+#if _MSC_VER >= 1500
2200+ FOPEN(&pCtx->pFileLog,fname, "wt+");
2201+#else
2202+ pCtx->pFileLog = FOPEN(fname, "wt+");
2203+#endif//_MSC_VER>=1500
2204+#endif//WIN32 && _MSC_VER
2205+#endif//__GNUC__
2206+ pCtx->uiSizeLog = 0;
2207+ }
2208+#endif//ENABLE_TRACE_FILE
2209+
2210+ pCodingParam->DetermineTemporalSettings();
2211+ iRet = AllocCodingParam( &pCtx->pSvcParam, pCtx->pMemAlign, pCodingParam->iNumDependencyLayer );
2212+ if ( iRet != 0 )
2213+ {
2214+ FreeMemorySvc( &pCtx );
2215+ return iRet;
2216+ }
2217+ memcpy( pCtx->pSvcParam, pCodingParam, sizeof(SWelsSvcCodingParam) ); // confirmed_safe_unsafe_usage
2218+
2219+ pCtx->pFuncList = (SWelsFuncPtrList *)pCtx->pMemAlign->WelsMalloc(sizeof(SWelsFuncPtrList), "SWelsFuncPtrList");
2220+ if ( NULL == pCtx->pFuncList )
2221+ {
2222+ FreeMemorySvc( &pCtx );
2223+ return 1;
2224+ }
2225+ InitFunctionPointers( pCtx->pFuncList, pCtx->pSvcParam, uiCpuFeatureFlags );
2226+
2227+ pCtx->iActiveThreadsNum = pCodingParam->iCountThreadsNum;
2228+ pCtx->iMaxSliceCount = iSliceNum;
2229+ iRet = RequestMemorySvc( &pCtx );
2230+ if ( iRet != 0 )
2231+ {
2232+ WelsLog(pCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), RequestMemorySvc failed return %d.\n", iRet);
2233+ FreeMemorySvc( &pCtx );
2234+ return iRet;
2235+ }
2236+
2237+#ifdef MT_ENABLED
2238+ if ( pCodingParam->iMultipleThreadIdc > 1 )
2239+ iRet = CreateSliceThreads( pCtx);
2240+#endif
2241+
2242+ WelsRcInitModule( pCtx, pCtx->pSvcParam->bEnableRc ? WELS_RC_GOM : WELS_RC_DISABLE);
2243+
2244+ pCtx->pVpp = new CWelsPreProcess((void *)pCtx);
2245+ if ( pCtx->pVpp == NULL )
2246+ {
2247+ WelsLog(pCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), pOut of memory in case new CWelsPreProcess().\n");
2248+ FreeMemorySvc( &pCtx );
2249+ return iRet;
2250+ }
2251+
2252+#if defined(MEMORY_MONITOR)
2253+ WelsLog(pCtx, WELS_LOG_INFO, "WelsInitEncoderExt() exit, overall memory usage: %lu bytes\n", sizeof(sWelsEncCtx) /* requested size from malloc() or new operator */
2254+ + pCtx->pMemAlign->WelsGetMemoryUsage() /* requested size from CMemoryAlign::WelsMalloc() */
2255+ );
2256+#endif//MEMORY_MONITOR
2257+
2258+ *ppCtx = pCtx;
2259+
2260+ WelsLog(pCtx, WELS_LOG_DEBUG, "WelsInitEncoderExt(), pCtx= 0x%p.\n", (void *)pCtx);
2261+
2262+ return 0;
2263+}
2264+/*
2265+ *
2266+ * status information output
2267+ */
2268+#if defined(STAT_OUTPUT)
2269+void StatOverallEncodingExt(sWelsEncCtx *pCtx)
2270+{
2271+ int8_t i = 0;
2272+ int8_t j = 0;
2273+ for (i = 0;i<pCtx->pSvcParam->iNumDependencyLayer;i++)
2274+ {
2275+ fprintf( stdout,"\nDependency layer : %d\n",i);
2276+ fprintf( stdout,"Quality layer : %d\n",j);
2277+ {
2278+ const int32_t iCount = pCtx->sStatData[i][j].sSliceData.iSliceCount[I_SLICE] +
2279+ pCtx->sStatData[i][j].sSliceData.iSliceCount[P_SLICE] +
2280+ pCtx->sStatData[i][j].sSliceData.iSliceCount[B_SLICE];
2281+#if defined(MB_TYPES_CHECK)
2282+ if (iCount > 0){
2283+ int32_t iCountNumIMb = pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra4x4] + pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra16x16]+ pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][7];
2284+ int32_t iCountNumPMb = pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra4x4] +
2285+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra16x16] +
2286+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][7] +
2287+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] +
2288+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] +
2289+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] +
2290+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] +
2291+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10] +
2292+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][PSkip];
2293+ int32_t count_p_mbL0 = pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] +
2294+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] +
2295+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] +
2296+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] +
2297+ pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10];
2298+
2299+ int32_t iMbCount = iCountNumIMb + iCountNumPMb;
2300+ if ( iMbCount > 0 ){
2301+ fprintf( stderr,
2302+ "SVC: overall Slices MBs: %d Avg\nI4x4: %.3f%% I16x16: %.3f%% IBL: %.3f%%\nP16x16: %.3f%% P16x8: %.3f%% P8x16: %.3f%% P8x8: %.3f%% SUBP8x8: %.3f%% PSKIP: %.3f%%\nILP(All): %.3f%% ILP(PL0): %.3f%% BLSKIP(PL0): %.3f%% RP(PL0): %.3f%%\n",
2303+ iMbCount,
2304+ (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra4x4] + pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra4x4]) / iMbCount),
2305+ (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra16x16] + pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra16x16]) / iMbCount),
2306+ (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][7] + pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][7]) / iMbCount),
2307+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] / iMbCount ),
2308+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] / iMbCount ),
2309+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] / iMbCount ),
2310+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] / iMbCount),
2311+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10] / iMbCount),
2312+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][PSkip] / iMbCount),
2313+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][11] / iMbCount),
2314+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][11] / count_p_mbL0),
2315+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][8] / count_p_mbL0),
2316+ (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][9] / count_p_mbL0)
2317+ );
2318+ }
2319+ }
2320+#endif //#if defined(MB_TYPES_CHECK)
2321+
2322+ if (iCount > 0){
2323+ fprintf( stdout, "SVC: overall PSNR Y: %2.3f U: %2.3f V: %2.3f kb/s: %.1f fps: %.3f\n\n",
2324+ (pCtx->sStatData[i][j].sQualityStat.rYPsnr[I_SLICE]+pCtx->sStatData[i][j].sQualityStat.rYPsnr[P_SLICE]+pCtx->sStatData[i][j].sQualityStat.rYPsnr[B_SLICE]) / (float)(iCount),
2325+ (pCtx->sStatData[i][j].sQualityStat.rUPsnr[I_SLICE]+pCtx->sStatData[i][j].sQualityStat.rUPsnr[P_SLICE]+pCtx->sStatData[i][j].sQualityStat.rUPsnr[B_SLICE]) / (float)(iCount),
2326+ (pCtx->sStatData[i][j].sQualityStat.rVPsnr[I_SLICE]+pCtx->sStatData[i][j].sQualityStat.rVPsnr[P_SLICE]+pCtx->sStatData[i][j].sQualityStat.rVPsnr[B_SLICE]) / (float)(iCount),
2327+ 1.0f * pCtx->pSvcParam->sDependencyLayers[i].fOutputFrameRate *(pCtx->sStatData[i][j].sSliceData.iSliceSize[I_SLICE] +pCtx->sStatData[i][j].sSliceData.iSliceSize[P_SLICE] +pCtx->sStatData[i][j].sSliceData.iSliceSize[B_SLICE] ) / (float)(iCount+pCtx->pWelsSvcRc[i].iSkipFrameNum)/1000,
2328+ 1.0f * pCtx->pSvcParam->sDependencyLayers[i].fOutputFrameRate );
2329+
2330+ }
2331+
2332+ }
2333+
2334+ }
2335+}
2336+#endif
2337+/*!
2338+ * \brief uninitialize Wels encoder core library
2339+ * \pParam pEncCtx sWelsEncCtx*
2340+ * \return none
2341+ */
2342+void WelsUninitEncoderExt( sWelsEncCtx **ppCtx )
2343+{
2344+ if ( NULL == ppCtx || NULL == *ppCtx )
2345+ return;
2346+
2347+ WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pCtx= %p, iThreadCount= %d, iMultipleThreadIdc= %d.\n", (void *)(*ppCtx), (*ppCtx)->pSvcParam->iCountThreadsNum, (*ppCtx)->pSvcParam->iMultipleThreadIdc );
2348+
2349+#if defined(STAT_OUTPUT)
2350+ StatOverallEncodingExt( *ppCtx );
2351+#endif
2352+
2353+#if defined(MT_ENABLED)
2354+ if ( (*ppCtx)->pSvcParam->iMultipleThreadIdc > 1 && (*ppCtx)->pSliceThreading != NULL )
2355+ {
2356+ const int32_t iThreadCount = (*ppCtx)->pSvcParam->iCountThreadsNum;
2357+ int32_t iThreadIdx = 0;
2358+
2359+#if defined(WIN32)
2360+ if ( (*ppCtx)->pSliceThreading->pExitEncodeEvent != NULL )
2361+ {
2362+ do {
2363+ if ( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] != NULL ) // iThreadIdx is already created successfully
2364+ WelsEventSignal( &(*ppCtx)->pSliceThreading->pExitEncodeEvent[iThreadIdx] );
2365+ ++ iThreadIdx;
2366+ } while(iThreadIdx < iThreadCount);
2367+
2368+ WelsMultipleEventsWaitAllBlocking( iThreadCount, &(*ppCtx)->pSliceThreading->pFinSliceCodingEvent[0] );
2369+
2370+ }
2371+#elif defined(__GNUC__)
2372+ while ( iThreadIdx < iThreadCount )
2373+ {
2374+ int res = 0;
2375+ if ( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] )
2376+ {
2377+ res = WelsThreadCancel( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] );
2378+ WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), WelsThreadCancel(pThreadHandles%d) return %d..\n", iThreadIdx, res);
2379+ res = WelsThreadJoin( (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] ); // waiting thread exit
2380+ WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pthread_join(pThreadHandles%d) return %d..\n", iThreadIdx, res);
2381+ (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] = 0;
2382+ }
2383+#if defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
2384+ if ( (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] )
2385+ {
2386+ res = WelsThreadCancel( (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] );
2387+ WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), WelsThreadCancel(pUpdateMbListThrdHandles%d) return %d..\n", iThreadIdx, res);
2388+ res = WelsThreadJoin( (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] ); // waiting thread exit
2389+ WelsLog( *ppCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pthread_join(pUpdateMbListThrdHandles%d) return %d..\n", iThreadIdx, res);
2390+ (*ppCtx)->pSliceThreading->pUpdateMbListThrdHandles[iThreadIdx] = 0;
2391+ }
2392+#endif//DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE
2393+ ++ iThreadIdx;
2394+ }
2395+#endif//WIN32
2396+ }
2397+#endif//MT_ENABLED
2398+
2399+ if ((*ppCtx)->pVpp)
2400+ {
2401+ delete (*ppCtx)->pVpp;
2402+ (*ppCtx)->pVpp = NULL;
2403+ }
2404+ FreeMemorySvc( ppCtx );
2405+ *ppCtx = NULL;
2406+}
2407+
2408+/*!
2409+ * \brief get temporal level due to configuration and coding context
2410+ */
2411+static inline int32_t GetTemporalLevel( SDLayerParam *fDlp, const int32_t kiFrameNum, const int32_t kiGopSize )
2412+{
2413+ const int32_t kiCodingIdx = kiFrameNum & (kiGopSize-1);
2414+
2415+ return fDlp->uiCodingIdx2TemporalId[kiCodingIdx];
2416+}
2417+
2418+void DynslcUpdateMbNeighbourInfoListForAllSlices( SSliceCtx *pSliceCtx, SMB *pMbList )
2419+{
2420+ const int32_t kiMbWidth = pSliceCtx->iMbWidth;
2421+ const int32_t kiEndMbInSlice = pSliceCtx->iMbNumInFrame - 1;
2422+ int32_t iIdx = 0;
2423+
2424+ do {
2425+ SMB *pMb = &pMbList[iIdx];
2426+ uint32_t uiNeighborAvailFlag = 0;
2427+ const int32_t kiMbXY = pMb->iMbXY;
2428+ const int32_t kiMbX = pMb->iMbX;
2429+ const int32_t kiMbY = pMb->iMbY;
2430+ BOOL_T bLeft;
2431+ BOOL_T bTop;
2432+ BOOL_T bLeftTop;
2433+ BOOL_T bRightTop;
2434+ int32_t uiSliceIdc;
2435+ int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
2436+
2437+ uiSliceIdc = WelsMbToSliceIdc(pSliceCtx, kiMbXY);
2438+ pMb->uiSliceIdc = uiSliceIdc;
2439+ iLeftXY = kiMbXY - 1;
2440+ iTopXY = kiMbXY - kiMbWidth;
2441+ iLeftTopXY = iTopXY - 1;
2442+ iRightTopXY = iTopXY + 1;
2443+
2444+ bLeft = (kiMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftXY));
2445+ bTop = (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iTopXY));
2446+ bLeftTop = (kiMbX > 0) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iLeftTopXY));
2447+ bRightTop = (kiMbX < (kiMbWidth-1)) && (kiMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc(pSliceCtx, iRightTopXY));
2448+
2449+ if( bLeft ){
2450+ uiNeighborAvailFlag |= LEFT_MB_POS;
2451+ }
2452+ if( bTop ){
2453+ uiNeighborAvailFlag |= TOP_MB_POS;
2454+ }
2455+ if( bLeftTop ){
2456+ uiNeighborAvailFlag |= TOPLEFT_MB_POS;
2457+ }
2458+ if( bRightTop ){
2459+ uiNeighborAvailFlag |= TOPRIGHT_MB_POS;
2460+ }
2461+ pMb->uiNeighborAvail = (uint8_t)uiNeighborAvailFlag;
2462+
2463+ ++ iIdx;
2464+ } while(iIdx <= kiEndMbInSlice);
2465+}
2466+
2467+/*
2468+ * TUNE back if number of picture partition decision algorithm based on past if available
2469+ */
2470+int32_t PicPartitionNumDecision( sWelsEncCtx *pCtx )
2471+{
2472+ int32_t iPartitionNum = 1;
2473+#ifdef MT_ENABLED
2474+ if ( pCtx->pSvcParam->iMultipleThreadIdc > 1 )
2475+ {
2476+ iPartitionNum = pCtx->pSvcParam->iCountThreadsNum;
2477+#if !defined(FIXED_PARTITION_ASSIGN)
2478+ if ( P_SLICE == pCtx->eSliceType )
2479+ iPartitionNum = 1;
2480+#endif//!FIXED_PARTITION_ASSIGN
2481+ }
2482+ return iPartitionNum;
2483+#else
2484+ return iPartitionNum;
2485+#endif//MT_ENABLED
2486+}
2487+
2488+#if defined(MT_ENABLED)
2489+void WelsInitCurrentQBLayerMltslc( sWelsEncCtx *pCtx )
2490+{
2491+ //pData init
2492+ SDqLayer* pCurDq = pCtx->pCurDqLayer;
2493+ SSliceCtx* pSliceCtx = (pCurDq->pSliceEncCtx);
2494+
2495+ //mb_neighbor
2496+ DynslcUpdateMbNeighbourInfoListForAllSlices( pSliceCtx, pCurDq->sMbDataP );
2497+}
2498+
2499+void UpdateSlicepEncCtxWithPartition( SSliceCtx *pSliceCtx, int32_t iPartitionNum )
2500+{
2501+ const int32_t kiMbNumInFrame = pSliceCtx->iMbNumInFrame;
2502+ int32_t iCountMbNumPerPartition = kiMbNumInFrame;
2503+ int32_t iAssignableMbLeft = kiMbNumInFrame;
2504+ int32_t iFirstMbIdx = 0;
2505+ int32_t i/*, j*/;
2506+
2507+ if ( iPartitionNum <= 0 )
2508+ iPartitionNum = 1;
2509+ else if ( iPartitionNum > AVERSLICENUM_CONSTRAINT )
2510+ iPartitionNum = AVERSLICENUM_CONSTRAINT; // AVERSLICENUM_CONSTRAINT might be variable, however not fixed by MACRO
2511+ iCountMbNumPerPartition /= iPartitionNum;
2512+ pSliceCtx->iSliceNumInFrame = iPartitionNum;
2513+ i = 0;
2514+ while( i < iPartitionNum )
2515+ {
2516+ if ( i + 1 == iPartitionNum )
2517+ {
2518+ pSliceCtx->pCountMbNumInSlice[i] = iAssignableMbLeft;
2519+ }
2520+ else
2521+ {
2522+ pSliceCtx->pCountMbNumInSlice[i] = iCountMbNumPerPartition;
2523+ }
2524+ pSliceCtx->pFirstMbInSlice[i] = iFirstMbIdx;
2525+
2526+ memset( pSliceCtx->pOverallMbMap+iFirstMbIdx, (uint8_t)i, pSliceCtx->pCountMbNumInSlice[i]*sizeof(uint8_t) );
2527+
2528+ // for next partition(or pSlice)
2529+ iFirstMbIdx += pSliceCtx->pCountMbNumInSlice[i];
2530+ iAssignableMbLeft -= pSliceCtx->pCountMbNumInSlice[i];
2531+ ++ i;
2532+ }
2533+}
2534+
2535+void WelsInitCurrentDlayerMltslc( sWelsEncCtx *pCtx, int32_t iPartitionNum )
2536+{
2537+ SDqLayer* pCurDq = pCtx->pCurDqLayer;
2538+ SSliceCtx* pSliceCtx = pCurDq->pSliceEncCtx;
2539+
2540+ UpdateSlicepEncCtxWithPartition( pSliceCtx, iPartitionNum );
2541+
2542+ if ( I_SLICE == pCtx->eSliceType )//check if uiSliceSizeConstraint too small
2543+ {
2544+#define byte_complexIMBat26 (60)
2545+ uint8_t iCurDid = pCtx->uiDependencyId;
2546+ uint32_t uiFrmByte = 0;
2547+
2548+ if ( pCtx->pSvcParam->bEnableRc )
2549+ {//RC case
2550+ uiFrmByte = (
2551+ ( (uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].iSpatialBitrate)
2552+ /(uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].fInputFrameRate) ) >> 3 );
2553+ }
2554+ else
2555+ {//fixed QP case
2556+ const int32_t iTtlMbNumInFrame = pSliceCtx->iMbNumInFrame;
2557+ int32_t iQDeltaTo26 = ( 26 - pCtx->pSvcParam->sDependencyLayers[iCurDid].iDLayerQp );
2558+
2559+ uiFrmByte = (iTtlMbNumInFrame * byte_complexIMBat26);
2560+ if ( iQDeltaTo26 > 0 )
2561+ {
2562+ //smaller QP than 26
2563+ uiFrmByte = (uint32_t)( uiFrmByte * ( (float)iQDeltaTo26 / 4 ) );
2564+ }
2565+ else if ( iQDeltaTo26 < 0 )
2566+ {
2567+ //larger QP than 26
2568+ iQDeltaTo26 = ( (-iQDeltaTo26) >> 2 ); //delta mod 4
2569+ uiFrmByte = ( uiFrmByte >> (iQDeltaTo26) ); //if delta 4, byte /2
2570+ }
2571+ }
2572+
2573+ //MINPACKETSIZE_CONSTRAINT
2574+ if ( pSliceCtx->uiSliceSizeConstraint
2575+ <
2576+ (uint32_t)( uiFrmByte//suppose 16 byte per mb at average
2577+ / ( pSliceCtx->iMaxSliceNumConstraint ) )
2578+ )
2579+ {
2580+
2581+ WelsLog( pCtx,
2582+ WELS_LOG_WARNING,
2583+ "Set-SliceConstraint(%d) too small for current resolution (MB# %d) under QP/BR!\n",
2584+ pSliceCtx->uiSliceSizeConstraint,
2585+ pSliceCtx->iMbNumInFrame
2586+ );
2587+ }
2588+ }
2589+
2590+ WelsInitCurrentQBLayerMltslc( pCtx );
2591+}
2592+#else
2593+void WelsInitCurrentQBLayerMltslc( sWelsEncCtx *pCtx )
2594+{
2595+ //pData init
2596+ SDqLayer* pCurDq = pCtx->pCurDqLayer;
2597+ SSliceCtx* pSliceCtx = (pCurDq->pSliceEncCtx);
2598+ SSlice * pSlice = &pCurDq->sLayerInfo.pSliceInLayer[0];
2599+ int32_t iTtlMbNumInFrame = pSliceCtx->iMbNumInFrame;
2600+
2601+ //pSliceCtx
2602+ memset( pSliceCtx->pOverallMbMap, 0, iTtlMbNumInFrame * sizeof(uint8_t) );
2603+ memset( pSliceCtx->pCountMbNumInSlice, 0, pSliceCtx->iSliceNumInFrame * sizeof(int32_t) );
2604+ memset( pSliceCtx->pFirstMbInSlice, 0, pSliceCtx->iSliceNumInFrame * sizeof(int16_t) );
2605+ pSliceCtx->iSliceNumInFrame = 1;//
2606+ pSliceCtx->pCountMbNumInSlice[0] = iTtlMbNumInFrame;
2607+
2608+ //mb_neighbor
2609+ DynslcUpdateMbNeighbourInfoListForAllSlices( pSliceCtx, pCurDq->sMbDataP );
2610+
2611+ //pSlice init
2612+ pSlice->uiSliceIdx = 0;
2613+ pSlice->pSliceBsa = &pCtx->pOut->sBsWrite;
2614+ pSlice->bDynamicSlicingSliceSizeCtrlFlag = false;
2615+ pSlice->uiAssumeLog2BytePerMb = ( pCtx->eSliceType == P_SLICE ) ? 0 : 1;
2616+}
2617+
2618+void WelsInitCurrentDlayerMltslc( sWelsEncCtx *pCtx, int32_t iPartitionNum )
2619+{
2620+ SDqLayer* pCurDq = pCtx->pCurDqLayer;
2621+ SSliceCtx* pSliceCtx = ( pCurDq->pSliceEncCtx );
2622+ int32_t iTtlMbNumInFrame = pCurDq->iMbHeight*pCurDq->iMbWidth;
2623+
2624+ pSliceCtx->iMbNumInFrame
2625+ = pSliceCtx->pCountMbNumInSlice[0] = iTtlMbNumInFrame;
2626+
2627+ if ( I_SLICE == pCtx->eSliceType )//check if uiSliceSizeConstraint too small
2628+ {
2629+#define byte_complexIMBat26 (60)
2630+ uint8_t iCurDid = pCtx->uiDependencyId;
2631+ uint32_t uiFrmByte = 0;
2632+
2633+ if ( pCtx->pSvcParam->bEnableRc )
2634+ {//RC case
2635+ uiFrmByte = (
2636+ ( (uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].iSpatialBitrate)
2637+ /(uint32_t)(pCtx->pSvcParam->sDependencyLayers[iCurDid].fInputFrameRate) ) >> 3 );
2638+ }
2639+ else
2640+ {//fixed QP case
2641+ int32_t iQDeltaTo26 = ( 26 - pCtx->pSvcParam->sDependencyLayers[iCurDid].iDLayerQp );
2642+
2643+ uiFrmByte = (iTtlMbNumInFrame * byte_complexIMBat26);
2644+ if ( iQDeltaTo26 > 0 )
2645+ {
2646+ //smaller QP than 26
2647+ uiFrmByte = (uint32_t)( uiFrmByte * ( (float)iQDeltaTo26 / 4 ) );
2648+ }
2649+ else if ( iQDeltaTo26 < 0 )
2650+ {
2651+ //larger QP than 26
2652+ iQDeltaTo26 = ( (-iQDeltaTo26) >> 2 ); //delta mod 4
2653+ uiFrmByte = ( uiFrmByte >> (iQDeltaTo26) ); //if delta 4, byte /2
2654+ }
2655+ }
2656+
2657+ //MINPACKETSIZE_CONSTRAINT
2658+ if ( pSliceCtx->uiSliceSizeConstraint
2659+ <
2660+ (uint32_t)( uiFrmByte//suppose 16 byte per mb at average
2661+ / ( pSliceCtx->iMaxSliceNumConstraint ) )
2662+ )
2663+ {
2664+
2665+ WelsLog( pCtx,
2666+ WELS_LOG_WARNING,
2667+ "Set-SliceConstraint(%d) too small for current resolution (MB# %d) under QP/BR!\n",
2668+ pSliceCtx->uiSliceSizeConstraint,
2669+ pSliceCtx->iMbNumInFrame
2670+ );
2671+ }
2672+ }
2673+
2674+ WelsInitCurrentQBLayerMltslc( pCtx );
2675+}
2676+#endif
2677+
2678+/*!
2679+ * \brief initialize current layer
2680+ */
2681+void WelsInitCurrentLayer( sWelsEncCtx *pCtx,
2682+ const int32_t kiWidth,
2683+ const int32_t kiHeight )
2684+{
2685+ SWelsSvcCodingParam *pParam = pCtx->pSvcParam;
2686+ SPicture *pEncPic = pCtx->pEncPic;
2687+ SPicture *pDecPic = pCtx->pDecPic;
2688+ SDqLayer *pCurDq = pCtx->pCurDqLayer;
2689+ SSlice *pBaseSlice = &pCurDq->sLayerInfo.pSliceInLayer[0];
2690+ SSlice *pSlice = NULL;
2691+ const uint8_t kiCurDid = pCtx->uiDependencyId;
2692+ const bool_t kbUseSubsetSpsFlag= (kiCurDid > BASE_DEPENDENCY_ID);
2693+ SDLayerParam *fDlp = &pParam->sDependencyLayers[kiCurDid];
2694+ SNalUnitHeaderExt *pNalHdExt = &pCurDq->sLayerInfo.sNalHeaderExt;
2695+ SNalUnitHeader *pNalHd = &pNalHdExt->sNalHeader;
2696+ SDqIdc *pDqIdc = &pCtx->pDqIdcMap[kiCurDid];
2697+ int32_t iIdx = 0;
2698+ int32_t iSliceCount = 0;
2699+
2700+ if ( NULL == pCurDq )
2701+ return;
2702+
2703+ pCurDq->pDecPic = pDecPic;
2704+
2705+ if ( fDlp->sMso.uiSliceMode == SM_DYN_SLICE ) // need get extra slices for update
2706+ iSliceCount = GetInitialSliceNum( pCurDq->iMbWidth, pCurDq->iMbHeight, &fDlp->sMso );
2707+ else
2708+ iSliceCount = GetCurrentSliceNum( pCurDq->pSliceEncCtx );
2709+ assert( iSliceCount > 0 );
2710+
2711+ pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = pDqIdc->iPpsId;
2712+ pCurDq->sLayerInfo.pPpsP =
2713+ pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId];
2714+ pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = pDqIdc->iSpsId;
2715+ if ( kbUseSubsetSpsFlag )
2716+ {
2717+ pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[pDqIdc->iSpsId];
2718+ pCurDq->sLayerInfo.pSpsP =
2719+ pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCurDq->sLayerInfo.pSubsetSpsP->pSps;
2720+ }
2721+ else
2722+ {
2723+ pCurDq->sLayerInfo.pSubsetSpsP = NULL;
2724+ pCurDq->sLayerInfo.pSpsP =
2725+ pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId];
2726+ }
2727+
2728+ pSlice = pBaseSlice;
2729+ iIdx = 1;
2730+ while ( iIdx < iSliceCount ) {
2731+ ++ pSlice;
2732+ pSlice->sSliceHeaderExt.sSliceHeader.iPpsId = pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId;
2733+ pSlice->sSliceHeaderExt.sSliceHeader.pPps = pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps;
2734+ pSlice->sSliceHeaderExt.sSliceHeader.iSpsId = pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId;
2735+ pSlice->sSliceHeaderExt.sSliceHeader.pSps = pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps;
2736+ ++ iIdx;
2737+ }
2738+
2739+ memset( pNalHdExt, 0, sizeof(SNalUnitHeaderExt) );
2740+ pNalHd->uiNalRefIdc = pCtx->eNalPriority;
2741+ pNalHd->eNalUnitType = pCtx->eNalType;
2742+
2743+ pNalHdExt->uiDependencyId = kiCurDid;
2744+ pNalHdExt->bDiscardableFlag = (pCtx->bNeedPrefixNalFlag) ? (pNalHd->uiNalRefIdc == NRI_PRI_LOWEST) : false;
2745+ pNalHdExt->bIdrFlag = (pCtx->iFrameNum == 0) && ((pCtx->eNalType == NAL_UNIT_CODED_SLICE_IDR) || (pCtx->eSliceType == I_SLICE));
2746+ pNalHdExt->uiTemporalId = pCtx->uiTemporalId;
2747+
2748+ pBaseSlice->bSliceHeaderExtFlag = (NAL_UNIT_CODED_SLICE_EXT == pNalHd->eNalUnitType);
2749+
2750+ pSlice = pBaseSlice;
2751+ iIdx = 1;
2752+ while (iIdx < iSliceCount) {
2753+ ++ pSlice;
2754+ pSlice->bSliceHeaderExtFlag = pBaseSlice->bSliceHeaderExtFlag;
2755+ ++ iIdx;
2756+ }
2757+
2758+ // pEncPic pData
2759+ pCurDq->pEncData[0] = pEncPic->pData[0];
2760+ pCurDq->pEncData[1] = pEncPic->pData[1];
2761+ pCurDq->pEncData[2] = pEncPic->pData[2];
2762+ pCurDq->iEncStride[0] = pEncPic->iLineSize[0];
2763+ pCurDq->iEncStride[1] = pEncPic->iLineSize[1];
2764+ pCurDq->iEncStride[2] = pEncPic->iLineSize[2];
2765+ // cs pData
2766+ pCurDq->pCsData[0] = pDecPic->pData[0];
2767+ pCurDq->pCsData[1] = pDecPic->pData[1];
2768+ pCurDq->pCsData[2] = pDecPic->pData[2];
2769+ pCurDq->iCsStride[0] = pDecPic->iLineSize[0];
2770+ pCurDq->iCsStride[1] = pDecPic->iLineSize[1];
2771+ pCurDq->iCsStride[2] = pDecPic->iLineSize[2];
2772+
2773+ if ( pCurDq->pRefLayer != NULL )
2774+ {
2775+ pCurDq->bBaseLayerAvailableFlag = true;
2776+ }
2777+ else
2778+ {
2779+ pCurDq->bBaseLayerAvailableFlag = false;
2780+ }
2781+}
2782+
2783+void PreprocessSliceCoding( sWelsEncCtx *pCtx )
2784+{
2785+ SDqLayer *pCurLayer = pCtx->pCurDqLayer;
2786+ const bool_t kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
2787+
2788+ /* function pointers conditional assignment under sWelsEncCtx, layer_mb_enc_rec (in stack) is exclusive */
2789+
2790+ if ( P_SLICE == pCtx->eSliceType )
2791+ {
2792+ if ( kbBaseAvail )
2793+ {
2794+ if ( pCtx->pSvcParam->iNumDependencyLayer == (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1) ) //
2795+ {
2796+ pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSad;
2797+ pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
2798+ pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa;
2799+ pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa;
2800+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad;
2801+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad;
2802+ pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad;
2803+ }
2804+ else
2805+ {
2806+ pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSatd;
2807+ pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
2808+ pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition;
2809+ pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartition;
2810+ pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
2811+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd;
2812+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd;
2813+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd;
2814+ }
2815+ pCtx->pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
2816+ }
2817+ else
2818+ {
2819+ //case 3: pBase layer MD + encoding
2820+ if ( pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId+1 == pCtx->pSvcParam->iNumDependencyLayer )
2821+ {
2822+ pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSad;
2823+ pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
2824+ pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa;
2825+ pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa;
2826+ pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad;
2827+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad;
2828+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad;
2829+ }
2830+ else
2831+ {
2832+ pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSatd;
2833+ pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
2834+ pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition;
2835+ pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartition;
2836+ pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
2837+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd;
2838+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd;
2839+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd;
2840+ }
2841+ pCtx->pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
2842+ }
2843+ }
2844+ else if ( I_SLICE == pCtx->eSliceType )
2845+ {
2846+ if ( pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId+1 == pCtx->pSvcParam->iNumDependencyLayer )
2847+ {
2848+ pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad;
2849+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad;
2850+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad;
2851+ pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa;
2852+ }
2853+ else
2854+ {
2855+ pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
2856+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd;
2857+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd;
2858+ pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd;
2859+ pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition;
2860+ }
2861+ }
2862+}
2863+
2864+/*!
2865+ * \brief swap pDq layers between current pDq layer and reference pDq layer
2866+ */
2867+
2868+static inline void WelsSwapDqLayers( sWelsEncCtx *pCtx )
2869+{
2870+ // swap and assign reference
2871+ const int32_t kiDid = pCtx->uiDependencyId;
2872+ const int32_t kiNextDqIdx = 1 + kiDid;
2873+
2874+ SDqLayer *pTmpLayer = pCtx->ppDqLayerList[kiNextDqIdx];
2875+ SDqLayer *pRefLayer = pCtx->pCurDqLayer;
2876+ pCtx->pCurDqLayer = pTmpLayer;
2877+ pCtx->pCurDqLayer->pRefLayer = pRefLayer;
2878+}
2879+
2880+/*!
2881+ * \brief prefetch reference picture after WelsBuildRefList
2882+ */
2883+static inline void PrefetchReferencePicture( sWelsEncCtx *pCtx, const EFrameType keFrameType )
2884+{
2885+ SSlice *pSliceBase = &pCtx->pCurDqLayer->sLayerInfo.pSliceInLayer[0];
2886+ const int32_t kiSliceCount = GetCurrentSliceNum( pCtx->pCurDqLayer->pSliceEncCtx );
2887+ int32_t iIdx = 0;
2888+ uint8_t uiRefIdx = -1;
2889+
2890+ assert( kiSliceCount > 0 );
2891+ if ( keFrameType != WELS_FRAME_TYPE_IDR )
2892+ {
2893+ assert( pCtx->iNumRef0 > 0 );
2894+ pCtx->pRefPic = pCtx->pRefList0[0]; // always get item 0 due to reordering done
2895+ pCtx->pCurDqLayer->pRefPic = pCtx->pRefPic;
2896+ uiRefIdx = 0; // reordered reference iIndex
2897+ }
2898+ else // safe for IDR coding
2899+ {
2900+ pCtx->pRefPic = NULL;
2901+ pCtx->pCurDqLayer->pRefPic = NULL;
2902+ }
2903+
2904+ iIdx = 0;
2905+ while (iIdx < kiSliceCount) {
2906+ pSliceBase->sSliceHeaderExt.sSliceHeader.uiRefIndex = uiRefIdx;
2907+ ++ pSliceBase;
2908+ ++ iIdx;
2909+ }
2910+}
2911+
2912+
2913+void ParasetIdAdditionIdAdjust( SParaSetOffsetVariable *sParaSetOffsetVariable, const int32_t kiCurEncoderParaSetId, const uint32_t kuiMaxIdInBs )//paraset_type = 0: SPS; =1: PPS
2914+{
2915+ //SPS_ID in avc_sps and pSubsetSps will be different using this
2916+ //SPS_ID case example:
2917+ //1st enter: next_spsid_in_bs == 0; spsid == 0; delta==0; //actual spsid_in_bs == 0
2918+ //1st finish: next_spsid_in_bs == 1;
2919+ //2nd enter: next_spsid_in_bs == 1; spsid == 0; delta==1; //actual spsid_in_bs == 1
2920+ //2nd finish: next_spsid_in_bs == 2;
2921+ //31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29; //actual spsid_in_bs == 31
2922+ //31st finish: next_spsid_in_bs == 0;
2923+ //31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0; //actual spsid_in_bs == 0
2924+ //31st finish: next_spsid_in_bs == 1;
2925+
2926+ const int32_t kiEncId = kiCurEncoderParaSetId;
2927+ const uint32_t kuiPrevIdInBs = sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] + kiEncId;//mark current_id
2928+ const bool_t *kpUsedIdPointer = &sParaSetOffsetVariable->bUsedParaSetIdInBs[0];
2929+ uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs;
2930+
2931+#if _DEBUG
2932+ if ( 0 != sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] )
2933+ assert ( sParaSetOffsetVariable->bUsedParaSetIdInBs[kuiPrevIdInBs] ); //sure the prev-used one was marked activated correctly
2934+#endif
2935+ //update current layer's pCodingParam
2936+ sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs - kiEncId; //for current parameter set, change its id_delta
2937+ //write pso pData for next update:
2938+ sParaSetOffsetVariable->bUsedParaSetIdInBs[kuiPrevIdInBs] = false; //
2939+ sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; // update current used_id
2940+
2941+ //prepare for next update:
2942+ // find the next avaibable iId
2943+ do
2944+ {
2945+ ++uiNextIdInBs;
2946+ if (uiNextIdInBs >= kuiMaxIdInBs )
2947+ {
2948+ uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT
2949+ }
2950+ }while ( kpUsedIdPointer[uiNextIdInBs] );
2951+
2952+ // update next_id
2953+ sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs;
2954+
2955+#if _DEBUG
2956+ assert ( !sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] ); //sure the next-to-use one is marked activated correctly
2957+#endif
2958+
2959+}
2960+
2961+/*!
2962+ * \brief write all parameter sets introduced in SVC extension
2963+ * \return size in bytes of bitstream wrote
2964+ */
2965+int32_t WelsWriteParameterSets( sWelsEncCtx *pCtx, int32_t *pNalLen, int32_t *pNumNal )
2966+{
2967+ int32_t iSize = 0;
2968+ int32_t iNal = 0;
2969+ int32_t iIdx = 0;
2970+ int32_t iId = 0;
2971+ int32_t iCountNal = 0;
2972+
2973+ if ( NULL == pCtx || NULL == pNalLen || NULL == pNumNal )
2974+ return 0;
2975+
2976+ /* write all SPS */
2977+ iIdx = 0;
2978+ while (iIdx < pCtx->iSpsNum) {
2979+ SDqIdc *pDqIdc = &pCtx->pDqIdcMap[iIdx];
2980+ const int32_t kiDid = pDqIdc->uiSpatialId;
2981+ const bool_t kbUsingSubsetSps = (kiDid > BASE_DEPENDENCY_ID);
2982+
2983+ iNal = pCtx->pOut->iNalIndex;
2984+
2985+ if ( pCtx->pSvcParam->bEnableSpsPpsIdAddition )
2986+ {
2987+#if _DEBUG
2988+ pCtx->sPSOVector.bEnableSpsPpsIdAddition = 1;
2989+ assert(kiDid < MAX_DEPENDENCY_LAYER);
2990+ assert(iIdx < MAX_DQ_LAYER_NUM);
2991+#endif
2992+
2993+ ParasetIdAdditionIdAdjust( &(pCtx->sPSOVector.sParaSetOffsetVariable[kbUsingSubsetSps ? PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS]),
2994+ (kbUsingSubsetSps)?(pCtx->pSubsetArray[iIdx - 1].pSps.uiSpsId):(pCtx->pSpsArray[0].uiSpsId ),
2995+ MAX_SPS_COUNT );
2996+ }
2997+ else
2998+ {
2999+ memset(&(pCtx->sPSOVector), 0, sizeof(pCtx->sPSOVector) );
3000+ }
3001+
3002+ if ( kbUsingSubsetSps ){
3003+ iId = iIdx - 1;
3004+
3005+ /* generate Subset SPS */
3006+ WelsLoadNal( pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST );
3007+
3008+ WelsWriteSubsetSpsSyntax( &pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite, &(pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]) );
3009+ WelsUnloadNal( pCtx->pOut );
3010+ }
3011+ else{
3012+ iId = 0;
3013+
3014+ /* generate sequence parameters set */
3015+ WelsLoadNal( pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST );
3016+ WelsWriteSpsNal( &pCtx->pSpsArray[0], &pCtx->pOut->sBsWrite, &(pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]) );
3017+ WelsUnloadNal( pCtx->pOut );
3018+ }
3019+
3020+ pNalLen[iCountNal] = WelsEncodeNal( &pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &pNalLen[iCountNal] );
3021+
3022+ pCtx->iPosBsBuffer += pNalLen[iCountNal];
3023+ iSize += pNalLen[iCountNal];
3024+
3025+ ++ iIdx;
3026+ ++ iCountNal;
3027+ }
3028+
3029+ /* write all PPS */
3030+ iIdx = 0;
3031+ while (iIdx < pCtx->iPpsNum) {
3032+ if ( pCtx->pSvcParam->bEnableSpsPpsIdAddition )
3033+ {
3034+ //para_set_type = 2: PPS, use MAX_PPS_COUNT
3035+ ParasetIdAdditionIdAdjust( &pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS], pCtx->pPPSArray[iIdx].iPpsId, MAX_PPS_COUNT );
3036+ }
3037+
3038+ iNal = pCtx->pOut->iNalIndex;
3039+ /* generate picture parameter set */
3040+ WelsLoadNal( pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST );
3041+ WelsWritePpsSyntax( &pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite, &(pCtx->sPSOVector) );
3042+ WelsUnloadNal( pCtx->pOut );
3043+
3044+ pNalLen[iCountNal] = WelsEncodeNal( &pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &pNalLen[iCountNal] );
3045+
3046+ pCtx->iPosBsBuffer += pNalLen[iCountNal];
3047+ iSize += pNalLen[iCountNal];
3048+
3049+ ++ iIdx;
3050+ ++ iCountNal;
3051+ }
3052+
3053+ *pNumNal = iCountNal;
3054+
3055+ return iSize;
3056+}
3057+
3058+static inline int32_t AddPrefixNal( sWelsEncCtx *pCtx,
3059+ SLayerBSInfo *pLayerBsInfo,
3060+ int32_t *pNalLen,
3061+ int32_t *pNalIdxInLayer,
3062+ const EWelsNalUnitType keNalType,
3063+ const EWelsNalRefIdc keNalRefIdc )
3064+{
3065+ int32_t iPayloadSize = 0;
3066+
3067+ if ( keNalRefIdc != NRI_PRI_LOWEST )
3068+ {
3069+ WelsLoadNal( pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc );
3070+
3071+ WelsWriteSVCPrefixNal( &pCtx->pOut->sBsWrite, keNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == keNalType) );
3072+
3073+ WelsUnloadNal( pCtx->pOut );
3074+
3075+ iPayloadSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1],
3076+ &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
3077+ pCtx->pFrameBs + pCtx->iPosBsBuffer,
3078+ &pNalLen[*pNalIdxInLayer] );
3079+
3080+ pCtx->iPosBsBuffer += iPayloadSize;
3081+ pLayerBsInfo->iNalLengthInByte[*pNalIdxInLayer] = iPayloadSize;
3082+
3083+ (*pNalIdxInLayer) ++;
3084+ }
3085+ else // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension
3086+ {
3087+ WelsLoadNal( pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc );
3088+ // No need write any syntax of prefix NAL Unit RBSP here
3089+ WelsUnloadNal( pCtx->pOut );
3090+
3091+ iPayloadSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1],
3092+ &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
3093+ pCtx->pFrameBs + pCtx->iPosBsBuffer,
3094+ &pNalLen[*pNalIdxInLayer] );
3095+
3096+ pCtx->iPosBsBuffer += iPayloadSize;
3097+ pLayerBsInfo->iNalLengthInByte[*pNalIdxInLayer] = iPayloadSize;
3098+
3099+ (*pNalIdxInLayer) ++;
3100+ }
3101+
3102+ return iPayloadSize;
3103+}
3104+
3105+int32_t WritePadding(sWelsEncCtx *pCtx, int32_t iLen)
3106+{
3107+ int32_t i=0;
3108+ int32_t iNal = 0;
3109+ SBitStringAux *pBs = NULL;
3110+ int32_t iNalLen;
3111+ int32_t iSize=0;
3112+
3113+ iNal = pCtx->pOut->iNalIndex;
3114+ pBs = &pCtx->pOut->sBsWrite; // SBitStringAux instance for non VCL NALs decoding
3115+
3116+ if((pBs->pBufEnd - pBs->pBufPtr) < iLen || iNal >= pCtx->pOut->iCountNals)
3117+ {
3118+#if GOM_TRACE_FLAG
3119+ WelsLog( pCtx, WELS_LOG_ERROR,"[RC] paddingcal pBuffer overflow, bufferlen=%d, paddinglen=%d, iNalIdx= %d, iCountNals= %d\n",
3120+ (pBs->pBufEnd-pBs->pBufPtr), iLen, iNal, pCtx->pOut->iCountNals);
3121+#endif
3122+ return 0;
3123+ }
3124+
3125+ WelsLoadNal( pCtx->pOut, NAL_UNIT_FILLER_DATA, NRI_PRI_LOWEST );
3126+
3127+ for(i=0;i<iLen;i++)
3128+ {
3129+ BsWriteBits( pBs, 8, 0xff);
3130+ }
3131+
3132+ BsRbspTrailingBits( pBs );
3133+
3134+ BsFlush( pBs );
3135+
3136+ WelsUnloadNal( pCtx->pOut );
3137+ iNalLen = WelsEncodeNal( &pCtx->pOut->sNalList[iNal], pCtx->pFrameBs + pCtx->iPosBsBuffer, &iNalLen );
3138+
3139+ pCtx->iPosBsBuffer += iNalLen;
3140+ iSize += iNalLen;
3141+
3142+ return iSize;
3143+}
3144+
3145+/*
3146+ * post process of dynamic slicing bs writing in case PACKING_ONE_SLICE_PER_LAYER
3147+ * include: count bs size of over all the slices in layer,
3148+ * return: count number of slices in layer
3149+ */
3150+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
3151+int32_t PostProcDynamicSlicingBsWriting( sWelsEncCtx *pCtx, SLayerBSInfo *pLayerBsInfo, int32_t *pLayerSize, const int32_t kiPartitionCnt )
3152+{
3153+ SDqLayer *pCurDq = pCtx->pCurDqLayer;
3154+ int32_t iPartitionIdx = 0;
3155+ int32_t iCheckingIdx = 0;
3156+ int32_t iSwappingIdx = -1;
3157+ int32_t iSliceCount = 0;
3158+ int32_t iLayerSize = 0;
3159+
3160+ // count number of slices in layer and layer size
3161+ while(iPartitionIdx < kiPartitionCnt)
3162+ {
3163+ const int32_t coded_slice_cnt = pCurDq->pNumSliceCodedOfPartition[iPartitionIdx];
3164+ iLayerSize += pCtx->pSliceThreading->pCountBsSizeInPartition[iPartitionIdx];
3165+ iSliceCount += coded_slice_cnt;
3166+ ++ iPartitionIdx;
3167+ }
3168+ *pLayerSize = iLayerSize;
3169+
3170+ // reordering pLayerBs pointers, but do not ensure raster scan order of picture
3171+ // just maintain discontinuous items,i.e,
3172+ // input:
3173+ // partition 1: uiSliceIdx: 0 2 4 6
3174+ // partition 2: uiSliceIdx: 1 3 5 7 9 11 13
3175+ // output:
3176+ // uiSliceIdx: 0 1 2 3 4 5 6 7 8 9 10
3177+ iCheckingIdx = 0;
3178+ while(true)
3179+ {
3180+ bool_t bMatchFlag = false;
3181+ iPartitionIdx = 0;
3182+ while(iPartitionIdx < kiPartitionCnt)
3183+ {
3184+ const int32_t coded_slice_cnt = pCurDq->pNumSliceCodedOfPartition[iPartitionIdx];
3185+ // iCheckingIdx need convert to iIndex of iPartitionIdx based to avoid linear searching
3186+ // belong this partition and not exceed the number of slices coded in partition
3187+ if ( iPartitionIdx == (iCheckingIdx % kiPartitionCnt)
3188+ && iCheckingIdx / kiPartitionCnt < coded_slice_cnt )
3189+ {
3190+ if ( iSwappingIdx >= 0 )
3191+ {
3192+ // memory swapping
3193+ memmove(pLayerBsInfo+iSwappingIdx, LayerBsInfo+iCheckingIdx, sizeof(SLayerBSInfo)); // confirmed_safe_unsafe_usage
3194+ ++ iSwappingIdx; // record iSwappingIdx
3195+ }
3196+ ++ iCheckingIdx;
3197+ bMatchFlag = true;
3198+ break;
3199+ }
3200+ ++ iPartitionIdx;
3201+ }
3202+ if ( !bMatchFlag )
3203+ {
3204+ if ( iSwappingIdx < 0 )
3205+ iSwappingIdx = iCheckingIdx;
3206+ ++ iCheckingIdx;
3207+ }
3208+ if ( iSwappingIdx >= iSliceCount )
3209+ break;
3210+ }
3211+
3212+ return iSliceCount;
3213+}
3214+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
3215+
3216+/*
3217+ * Force coding IDR as follows
3218+ */
3219+int32_t ForceCodingIDR( sWelsEncCtx *pCtx )
3220+{
3221+ if ( NULL == pCtx )
3222+ return 1;
3223+
3224+ pCtx->bEncCurFrmAsIdrFlag = true;
3225+ pCtx->iCodingIndex = 0;
3226+
3227+ return 0;
3228+}
3229+
3230+/*!
3231+ * \brief core svc encoding process
3232+ *
3233+ * \pParam pCtx sWelsEncCtx*, encoder context
3234+ * \pParam pDst FrameBSInfo*
3235+ * \pParam pSrc SSourcePicture* for need_ds = true or SSourcePicture** for need_ds = false
3236+ * \pParam iConfiguredLayerNum =1 in case need_ds = true or >1 in case need_ds = false
3237+ * \pParam need_ds Indicate whether need down sampling desired
3238+ * [NO in picture list case, YES in console aplication based]
3239+ * \return EFrameType (WELS_FRAME_TYPE_IDR/WELS_FRAME_TYPE_I/WELS_FRAME_TYPE_P)
3240+ */
3241+int32_t WelsEncoderEncodeExt( sWelsEncCtx *pCtx, void *pDst, const SSourcePicture **ppSrcList, const int32_t iConfiguredLayerNum )
3242+{
3243+ SFrameBSInfo *pFbi = (SFrameBSInfo *)pDst;
3244+ SLayerBSInfo *pLayerBsInfo = &pFbi->sLayerInfo[0];
3245+ SWelsSvcCodingParam *pSvcParam = pCtx->pSvcParam;
3246+ SSpatialPicIndex *pSpatialIndexMap= &pCtx->sSpatialIndexMap[0];
3247+#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
3248+ SPicture *fsnr = NULL;
3249+#endif//ENABLE_FRAME_DUMP || ENABLE_PSNR_CALC
3250+ SPicture *pEncPic = NULL; // to be decided later
3251+#if defined(MT_ENABLED) && (defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG))
3252+ int32_t did_list[MAX_DEPENDENCY_LAYER] = {0};
3253+#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN
3254+ int32_t iLayerNum = 0;
3255+ int32_t iLayerSize = 0;
3256+ int32_t iSpatialNum = 0; // available count number of spatial layers due to frame size changed in this given frame
3257+ int32_t iSpatialIdx = 0; // iIndex of spatial layers due to frame size changed in this given frame
3258+ int32_t iFrameSize = 0;
3259+ int32_t iNalLen[128] = {0};
3260+ int32_t iNalIdxInLayer = 0;
3261+ int32_t iCountNal = 0;
3262+ EFrameType eFrameType = WELS_FRAME_TYPE_AUTO;
3263+ int32_t iCurWidth = 0;
3264+ int32_t iCurHeight = 0;
3265+ EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0;
3266+ EWelsNalRefIdc eNalRefIdc = NRI_PRI_LOWEST;
3267+ int8_t iCurDid = 0;
3268+ int8_t iCurTid = 0;
3269+ bool_t bAvcBased = false;
3270+#if defined(ENABLE_PSNR_CALC)
3271+ real32_t snr_y = .0f, snr_u = .0f, snr_v = .0f;
3272+#endif//ENABLE_PSNR_CALC
3273+
3274+#if defined(_DEBUG)
3275+ int32_t i = 0, j = 0, k = 0;
3276+#endif//_DEBUG
3277+
3278+ pFbi->iLayerNum = 0; // for initialization
3279+
3280+ // perform csc/denoise/downsample/padding, generate spatial layers
3281+ iSpatialNum = pCtx->pVpp->WelsPreprocessStep1(pCtx, ppSrcList, iConfiguredLayerNum);
3282+ if ( iSpatialNum < 1 ) // skip due to temporal layer settings (different frame rate)
3283+ {
3284+ ++ pCtx->iCodingIndex;
3285+ return WELS_FRAME_TYPE_SKIP;
3286+ }
3287+
3288+ eFrameType = DecideFrameType( pCtx, iSpatialNum );
3289+ if (eFrameType == WELS_FRAME_TYPE_SKIP)
3290+ return eFrameType;
3291+
3292+ InitFrameCoding( pCtx, eFrameType );
3293+
3294+ iCurTid = GetTemporalLevel( &pSvcParam->sDependencyLayers[pSpatialIndexMap->iDid], pCtx->iCodingIndex, pSvcParam->uiGopSize );
3295+ pCtx->uiTemporalId = iCurTid;
3296+
3297+ pLayerBsInfo->pBsBuf = pCtx->pFrameBs ;
3298+
3299+ if ( eFrameType == WELS_FRAME_TYPE_IDR )
3300+ {
3301+ ++ pCtx->sPSOVector.uiIdrPicId;
3302+ //if ( pSvcParam->bEnableSSEI )
3303+
3304+ // write parameter sets bitstream here
3305+ WelsWriteParameterSets( pCtx, &iNalLen[0], &iCountNal );
3306+
3307+ pLayerBsInfo->uiPriorityId = 0;
3308+ pLayerBsInfo->uiSpatialId = 0;
3309+ pLayerBsInfo->uiTemporalId = 0;
3310+ pLayerBsInfo->uiQualityId = 0;
3311+ pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3312+ pLayerBsInfo->iNalCount = iCountNal;
3313+ for (int32_t iNalIndex = 0; iNalIndex < iCountNal; ++ iNalIndex)
3314+ {
3315+ pLayerBsInfo->iNalLengthInByte[iNalIndex] = iNalLen[iNalIndex];
3316+ }
3317+
3318+ ++ pLayerBsInfo;
3319+ pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3320+ ++ iLayerNum;
3321+ }
3322+
3323+ pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid];
3324+ pCtx->pCurDqLayer->pRefLayer = NULL;
3325+
3326+ while ( iSpatialIdx < iSpatialNum )
3327+ {
3328+ const int32_t d_idx = (pSpatialIndexMap+iSpatialIdx)->iDid; // get iDid
3329+ SDLayerParam *param_d = &pSvcParam->sDependencyLayers[d_idx];
3330+
3331+ pCtx->uiDependencyId = iCurDid = (int8_t)d_idx;
3332+ pCtx->pVpp->WelsPreprocessStep3(pCtx, d_idx);
3333+
3334+ pCtx->pEncPic = pEncPic = (pSpatialIndexMap+iSpatialIdx)->pSrc;
3335+ pCtx->pEncPic->iPictureType = pCtx->eSliceType;
3336+ pCtx->pEncPic->iFramePoc = pCtx->iPOC;
3337+
3338+ iCurWidth = param_d->iFrameWidth;
3339+ iCurHeight = param_d->iFrameHeight;
3340+
3341+#if defined(MT_ENABLED) && (defined(DYNAMIC_SLICE_ASSIGN) || defined(MT_DEBUG))
3342+ did_list[iSpatialIdx] = iCurDid;
3343+#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN
3344+
3345+ // Encoding this picture might mulitiple sQualityStat layers potentially be encoded as followed
3346+
3347+ switch ( param_d->sMso.uiSliceMode )
3348+ {
3349+ case SM_FIXEDSLCNUM_SLICE:
3350+ {
3351+#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN)
3352+ if ( (iCurDid > 0) && (pSvcParam->iMultipleThreadIdc > 1) &&
3353+ (pSvcParam->sDependencyLayers[iCurDid].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc >= pSvcParam->sDependencyLayers[iCurDid].sMso.sSliceArgument.iSliceNum )
3354+ )
3355+ AdjustEnhanceLayer( pCtx, iCurDid );
3356+#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN
3357+ break;
3358+ }
3359+ case SM_DYN_SLICE:
3360+ {
3361+ int32_t iPicIPartitionNum = PicPartitionNumDecision( pCtx );
3362+ // MT compatibility
3363+ pCtx->iActiveThreadsNum = iPicIPartitionNum; // we try to active number of threads, equal to number of picture partitions
3364+ WelsInitCurrentDlayerMltslc( pCtx, iPicIPartitionNum );
3365+ break;
3366+ }
3367+ default:
3368+ {
3369+ break;
3370+ }
3371+ }
3372+
3373+ /* coding each spatial layer, only one sQualityStat layer within spatial support */
3374+ int32_t iSliceCount = 1;
3375+ if ( iLayerNum >= MAX_LAYER_NUM_OF_FRAME ) // check available layer_bs_info writing as follows
3376+ {
3377+ WelsLog( pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d)!", iLayerNum, MAX_LAYER_NUM_OF_FRAME);
3378+ return -1;
3379+ }
3380+
3381+ iNalIdxInLayer = 0;
3382+ bAvcBased = (iCurDid == BASE_DEPENDENCY_ID);
3383+ pCtx->bNeedPrefixNalFlag = (bAvcBased &&
3384+ (pSvcParam->bPrefixNalAddingCtrl ||
3385+ (pSvcParam->iNumDependencyLayer > 1) ));
3386+
3387+ if ( eFrameType == WELS_FRAME_TYPE_P )
3388+ {
3389+ eNalType = bAvcBased ? NAL_UNIT_CODED_SLICE : NAL_UNIT_CODED_SLICE_EXT;
3390+ }
3391+ else if ( eFrameType == WELS_FRAME_TYPE_IDR )
3392+ {
3393+ eNalType = bAvcBased ? NAL_UNIT_CODED_SLICE_IDR : NAL_UNIT_CODED_SLICE_EXT;
3394+ }
3395+ if ( iCurTid == 0 || pCtx->eSliceType == I_SLICE )
3396+ eNalRefIdc = NRI_PRI_HIGHEST;
3397+ else if ( iCurTid == pSvcParam->iDecompStages )
3398+ eNalRefIdc = NRI_PRI_LOWEST;
3399+ else if ( 1 + iCurTid == pSvcParam->iDecompStages )
3400+ eNalRefIdc = NRI_PRI_LOW;
3401+ else // more details for other temporal layers?
3402+ eNalRefIdc = NRI_PRI_HIGHEST;
3403+ pCtx->eNalType = eNalType;
3404+ pCtx->eNalPriority = eNalRefIdc;
3405+
3406+ pCtx->pDecPic = pCtx->ppRefPicListExt[iCurDid]->pNextBuffer;
3407+#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
3408+ fsnr = pCtx->pDecPic;
3409+#endif//#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
3410+ pCtx->pDecPic->iPictureType = pCtx->eSliceType;
3411+ pCtx->pDecPic->iFramePoc = pCtx->iPOC;
3412+
3413+ WelsInitCurrentLayer( pCtx, iCurWidth, iCurHeight );
3414+
3415+ WelsMarkPic(pCtx);
3416+ if ( !WelsBuildRefList( pCtx, pCtx->iPOC ) )
3417+ {
3418+ // Force coding IDR as followed
3419+ ForceCodingIDR( pCtx );
3420+ WelsLog(pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d.\n", pCtx->iNumRef0);
3421+ return -1;
3422+ }
3423+#ifdef LONG_TERM_REF_DUMP
3424+ dump_ref(pCtx);
3425+#endif
3426+ WelsUpdateRefSyntax(pCtx, pCtx->iPOC, eFrameType); //get reordering syntax used for writing slice header and transmit to encoder.
3427+ PrefetchReferencePicture( pCtx, eFrameType ); // update reference picture for current pDq layer
3428+
3429+ pCtx->pFuncList->pfRc.pfWelsRcPictureInit(pCtx);
3430+ PreprocessSliceCoding( pCtx ); // MUST be called after pfWelsRcPictureInit() and WelsInitCurrentLayer()
3431+
3432+ iLayerSize = 0;
3433+ if ( SM_SINGLE_SLICE == param_d->sMso.uiSliceMode ) // only one slice within a sQualityStat layer
3434+ {
3435+ int32_t iSliceSize = 0;
3436+
3437+ if ( pCtx->bNeedPrefixNalFlag )
3438+ {
3439+ iLayerSize += AddPrefixNal( pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc );
3440+ }
3441+
3442+ WelsLoadNal( pCtx->pOut, eNalType, eNalRefIdc );
3443+
3444+ WelsCodeOneSlice( pCtx, 0, eNalType );
3445+
3446+ WelsUnloadNal( pCtx->pOut );
3447+
3448+ iSliceSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1],
3449+ &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
3450+ pCtx->pFrameBs + pCtx->iPosBsBuffer,
3451+ &iNalLen[iNalIdxInLayer] );
3452+ iLayerSize += iSliceSize;
3453+ pCtx->iPosBsBuffer += iSliceSize;
3454+ pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
3455+ pLayerBsInfo->uiSpatialId = iCurDid;
3456+ pLayerBsInfo->uiTemporalId = iCurTid;
3457+ pLayerBsInfo->uiQualityId = 0;
3458+ pLayerBsInfo->uiPriorityId = 0;
3459+ pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize;
3460+ pLayerBsInfo->iNalCount = ++ iNalIdxInLayer;
3461+ }
3462+ // for dynamic slicing single threading..
3463+#ifndef MT_ENABLED
3464+ else if ( SM_DYN_SLICE == param_d->sMso.uiSliceMode )
3465+#else // MT_ENABLED
3466+ else if ( (SM_DYN_SLICE == param_d->sMso.uiSliceMode) && (pSvcParam->iMultipleThreadIdc <= 1) )
3467+#endif//MT_ENABLED
3468+ {
3469+ const int32_t kiLastMbInFrame = pCtx->pCurDqLayer->pSliceEncCtx->iMbNumInFrame;
3470+ WelsCodeOnePicPartition( pCtx, pLayerBsInfo, &iNalIdxInLayer, &iLayerSize, 0, kiLastMbInFrame, 0 );
3471+ }
3472+ else
3473+ {//other multi-slice uiSliceMode
3474+#if defined(MT_ENABLED)
3475+ int err = 0;
3476+ // THREAD_FULLY_FIRE_MODE/THREAD_PICK_UP_MODE for any mode of non-SM_DYN_SLICE
3477+ if ( (SM_DYN_SLICE != param_d->sMso.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1) )
3478+ {
3479+ iSliceCount = GetCurrentSliceNum( pCtx->pCurDqLayer->pSliceEncCtx );
3480+ if ( iLayerNum +
3481+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3482+ iSliceCount
3483+#else
3484+ 1
3485+#endif//PACKING_ONE_SLICE_PER_LAYER
3486+ >= MAX_LAYER_NUM_OF_FRAME ) // check available layer_bs_info for further writing as followed
3487+ {
3488+ WelsLog( pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d) at iDid= %d uiSliceMode= %d, iSliceCount= %d!",
3489+ iLayerNum, MAX_LAYER_NUM_OF_FRAME, iCurDid, param_d->sMso.uiSliceMode, iSliceCount );
3490+ return -1;
3491+ }
3492+ if ( iSliceCount <= 1 )
3493+ {
3494+ WelsLog( pCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iSliceCount(%d) from GetCurrentSliceNum() is untrusted due stack/heap crupted!\n", iSliceCount );
3495+ return -1;
3496+ }
3497+
3498+ if ( pSvcParam->iCountThreadsNum >= iSliceCount ) //THREAD_FULLY_FIRE_MODE
3499+ {
3500+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3501+ int32_t iSliceIdx = 1;
3502+ int32_t iOrgSlicePos[MAX_SLICES_NUM] = {0};
3503+ iOrgSlicePos[0] = pCtx->iPosBsBuffer;
3504+ while (uiSliceIdx < iSliceCount)
3505+ {
3506+ iOrgSlicePos[uiSliceIdx] = pCtx->pSliceBs[uiSliceIdx].uiBsPos;
3507+ ++ uiSliceIdx;
3508+ }
3509+#elif defined(MT_DEBUG)
3510+ int64_t t_bs_append = 0;
3511+#endif//PACKING_ONE_SLICE_PER_LAYER
3512+
3513+ pCtx->iActiveThreadsNum = iSliceCount;
3514+ // to fire slice coding threads
3515+ err = FiredSliceThreads( &pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0], pLayerBsInfo, iSliceCount, pCtx->pCurDqLayer->pSliceEncCtx, FALSE );
3516+ if ( err )
3517+ {
3518+ WelsLog( pCtx, WELS_LOG_ERROR, "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n",
3519+ err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sMso.uiSliceMode, pSvcParam->iMultipleThreadIdc );
3520+ return -1;
3521+ }
3522+
3523+ WelsMultipleEventsWaitAllBlocking( iSliceCount, &pCtx->pSliceThreading->pSliceCodedEvent[0] );
3524+
3525+
3526+ // all slices are finished coding here
3527+ // append exclusive slice 0 bs to pFrameBs
3528+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3529+ iLayerSize = pCtx->iPosBsBuffer - iOrgSlicePos[0];
3530+ uiSliceIdx = 1;
3531+ while (uiSliceIdx < iSliceCount)
3532+ {
3533+ iLayerSize += pCtx->pSliceBs[uiSliceIdx].uiBsPos - iOrgSlicePos[uiSliceIdx];
3534+ ++ uiSliceIdx;
3535+ }
3536+ iLayerNum += iSliceCount; // each slice stickly output as layer info for performance improvement directly
3537+ pLayerBsInfo += iSliceCount;
3538+#else
3539+#if defined(MT_DEBUG)
3540+ t_bs_append = WelsTime();
3541+#endif//MT_DEBUG
3542+ iLayerSize = AppendSliceToFrameBs( pCtx, pLayerBsInfo, iSliceCount );
3543+#if defined(MT_DEBUG)
3544+ t_bs_append = WelsTime() - t_bs_append;
3545+ if ( pCtx->pSliceThreading->pFSliceDiff )
3546+ {
3547+ fprintf(pCtx->pSliceThreading->pFSliceDiff,
3548+#if defined(WIN32)
3549+ "%6I64d us consumed at AppendSliceToFrameBs() for coding_idx: %d iDid: %d qid: %d\n",
3550+#else
3551+ "%6lld us consumed at AppendSliceToFrameBs() for coding_idx: %d iDid: %d qid: %d\n",
3552+#endif//WIN32
3553+ t_bs_append, pCtx->iCodingIndex, iCurDid, 0 );
3554+ }
3555+#endif//MT_DEBUG
3556+#endif//PACKING_ONE_SLICE_PER_LAYER
3557+ }
3558+ else //THREAD_PICK_UP_MODE
3559+ {
3560+ int32_t iNumThreadsRunning = 0;
3561+ int32_t iNumThreadsScheduled = 0;
3562+ int32_t iIndexOfSliceToBeCoded = 0;
3563+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3564+ int32_t iSliceIdx = 1;
3565+ int32_t iOrgSlicePos[MAX_SLICES_NUM] = {0};
3566+ iOrgSlicePos[0] = pCtx->iPosBsBuffer;
3567+ while (uiSliceIdx < iSliceCount)
3568+ {
3569+ iOrgSlicePos[uiSliceIdx] = pCtx->pSliceBs[uiSliceIdx].uiBsPos;
3570+ ++ uiSliceIdx;
3571+ }
3572+#endif//PACKING_ONE_SLICE_PER_LAYER
3573+
3574+ pCtx->iActiveThreadsNum = pSvcParam->iCountThreadsNum;
3575+ iNumThreadsScheduled = pCtx->iActiveThreadsNum;
3576+ iNumThreadsRunning = iNumThreadsScheduled;
3577+ // to fire slice coding threads
3578+ err = FiredSliceThreads( &pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0], pLayerBsInfo, iNumThreadsRunning, pCtx->pCurDqLayer->pSliceEncCtx, FALSE );
3579+ if ( err )
3580+ {
3581+ WelsLog( pCtx, WELS_LOG_ERROR, "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n",
3582+ err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sMso.uiSliceMode, pSvcParam->iMultipleThreadIdc );
3583+ return -1;
3584+ }
3585+
3586+ iIndexOfSliceToBeCoded = iNumThreadsRunning;
3587+ while (1)
3588+ {
3589+ if ( iIndexOfSliceToBeCoded >= iSliceCount && iNumThreadsRunning <= 0 )
3590+ break;
3591+#ifdef WIN32
3592+ WELS_THREAD_ERROR_CODE lwait = 0;
3593+ int32_t iEventId = -1;
3594+
3595+ lwait = WelsMultipleEventsWaitSingleBlocking( iNumThreadsScheduled,
3596+ &pCtx->pSliceThreading->pSliceCodedEvent[0],
3597+ 2 ); // 2 ms for one tick
3598+ iEventId = (int32_t)(lwait - WELS_THREAD_ERROR_WAIT_OBJECT_0);
3599+ if ( iEventId >= 0 && iEventId < iNumThreadsScheduled )
3600+ {
3601+ if ( iIndexOfSliceToBeCoded < iSliceCount )
3602+ {
3603+ // pick up succeeding slice for threading
3604+ // thread_id equal to iEventId per implementation here
3605+ pCtx->pSliceThreading->pThreadPEncCtx[iEventId].iSliceIndex = iIndexOfSliceToBeCoded;
3606+#ifdef PACKING_ONE_SLICE_PER_LAYER
3607+ pCtx->pSliceThreading->pThreadPEncCtx[iEventId].pLayerBs = pLayerBsInfo+iIndexOfSliceToBeCoded;
3608+#endif//PACKING_ONE_SLICE_PER_LAYER
3609+ WelsEventSignal( &pCtx->pSliceThreading->pReadySliceCodingEvent[iEventId] );
3610+
3611+ ++ iIndexOfSliceToBeCoded;
3612+ }
3613+ else // no other slices left for coding
3614+ {
3615+ -- iNumThreadsRunning;
3616+ }
3617+ }
3618+ else
3619+ {
3620+ WelsSleep(1);
3621+ }
3622+#else//__GNUC__
3623+ // TODO for pthread platforms
3624+ // alternate implementation using blocking due non-blocking with timeout mode not support at wels thread lib, tune back if available
3625+ WelsMultipleEventsWaitAllBlocking( iNumThreadsRunning, &pCtx->pSliceThreading->pSliceCodedEvent[0] );
3626+ if ( iIndexOfSliceToBeCoded < iSliceCount )
3627+ {
3628+ int32_t iThreadIdx = 0;
3629+ // pick up succeeding slices for threading if left
3630+ while ( iThreadIdx < iNumThreadsScheduled )
3631+ {
3632+ if ( iIndexOfSliceToBeCoded >= iSliceCount )
3633+ break;
3634+ pCtx->pSliceThreading->pThreadPEncCtx[iThreadIdx].iSliceIndex = iIndexOfSliceToBeCoded;
3635+#ifdef PACKING_ONE_SLICE_PER_LAYER
3636+ pCtx->pSliceThreading->pThreadPEncCtx[iThreadIdx].pLayerBs = pLayerBsInfo+iIndexOfSliceToBeCoded;
3637+#endif//PACKING_ONE_SLICE_PER_LAYER
3638+ WelsEventSignal( pCtx->pSliceThreading->pReadySliceCodingEvent[iThreadIdx] );
3639+
3640+ ++ iIndexOfSliceToBeCoded;
3641+ ++ iThreadIdx;
3642+ }
3643+ // update iNumThreadsRunning
3644+ iNumThreadsRunning = iThreadIdx;
3645+ }
3646+ else
3647+ {
3648+ iNumThreadsRunning = 0;
3649+ }
3650+#endif//WIN32
3651+ }//while(1)
3652+
3653+// all slices are finished coding here
3654+ // append exclusive slice 0 bs to pFrameBs
3655+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3656+ iLayerSize = pCtx->iPosBsBuffer - iOrgSlicePos[0];
3657+ uiSliceIdx = 1;
3658+ while (uiSliceIdx < iSliceCount)
3659+ {
3660+ iLayerSize += pCtx->pSliceBs[uiSliceIdx].uiBsPos - iOrgSlicePos[uiSliceIdx];
3661+ ++ uiSliceIdx;
3662+ }
3663+ iLayerNum += iSliceCount; // each slice stickly output as layer info for performance improvement directly
3664+ pLayerBsInfo += iSliceCount;
3665+#else
3666+ iLayerSize = AppendSliceToFrameBs( pCtx, pLayerBsInfo, iSliceCount );
3667+#endif//PACKING_ONE_SLICE_PER_LAYER
3668+ }
3669+ }
3670+ // THREAD_FULLY_FIRE_MODE && SM_DYN_SLICE
3671+ else if ( (SM_DYN_SLICE == param_d->sMso.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1) )
3672+ {
3673+ const int32_t kiPartitionCnt = pCtx->iActiveThreadsNum; //pSvcParam->iCountThreadsNum;
3674+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3675+ ResetCountBsSizeInPartitions( pCtx->pSliceThreading->pCountBsSizeInPartition, kiPartitionCnt );
3676+ pCtx->pCurDqLayer->pSliceEncCtx->iMaxSliceNumConstraint = WELS_MIN ( MAX_SLICES_NUM, DynamicMaxSliceNumConstraint( MAX_LAYER_NUM_OF_FRAME, iLayerNum, 1 + /*( num_qlayer - 1) +*/ ( ( (iCurDid==0) && ( pSvcParam->uiGopSize>1 ) ) ? 1: 0 ) ) );
3677+#endif//PACKING_ONE_SLICE_PER_LAYER
3678+
3679+ // to fire slice coding threads
3680+ err = FiredSliceThreads( &pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0], pLayerBsInfo, kiPartitionCnt, pCtx->pCurDqLayer->pSliceEncCtx, TRUE );
3681+ if ( err )
3682+ {
3683+ WelsLog( pCtx, WELS_LOG_ERROR, "[MT] WelsEncoderEncodeExt(), FiredSliceThreads return(%d) failed and exit encoding frame, iCountThreadsNum= %d, iSliceCount= %d, uiSliceMode= %d, iMultipleThreadIdc= %d!!\n",
3684+ err, pSvcParam->iCountThreadsNum, iSliceCount, param_d->sMso.uiSliceMode, pSvcParam->iMultipleThreadIdc );
3685+ return -1;
3686+ }
3687+
3688+ WelsMultipleEventsWaitAllBlocking( kiPartitionCnt, &pCtx->pSliceThreading->pSliceCodedEvent[0] );
3689+
3690+#if defined(PACKING_ONE_SLICE_PER_LAYER)
3691+ iSliceCount = PostProcDynamicSlicingBsWriting( pCtx, pLayerBsInfo, &iLayerSize, kiPartitionCnt );
3692+ assert(iLayerNum + iSliceCount < MAX_LAYER_NUM_OF_FRAME);
3693+ pLayerBsInfo += iSliceCount;
3694+ iLayerNum += iSliceCount;
3695+#else
3696+ iLayerSize = AppendSliceToFrameBs( pCtx, pLayerBsInfo, kiPartitionCnt );
3697+#endif//PACKING_ONE_SLICE_PER_LAYER
3698+ }
3699+ else // for non-dynamic-slicing mode single threading branch..
3700+#endif//MT_ENABLED
3701+ {
3702+ const bool_t bNeedPrefix = pCtx->bNeedPrefixNalFlag;
3703+ int32_t iSliceIdx = 0;
3704+
3705+ iSliceCount = GetCurrentSliceNum( pCtx->pCurDqLayer->pSliceEncCtx );
3706+ while (iSliceIdx < iSliceCount)
3707+ {
3708+ int32_t iSliceSize = 0;
3709+
3710+ if ( bNeedPrefix )
3711+ {
3712+ iLayerSize += AddPrefixNal( pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, eNalType, eNalRefIdc );
3713+ }
3714+
3715+ WelsLoadNal( pCtx->pOut, eNalType, eNalRefIdc );
3716+ WelsCodeOneSlice( pCtx, iSliceIdx, eNalType );
3717+ WelsUnloadNal( pCtx->pOut );
3718+
3719+ iSliceSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1],
3720+ &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
3721+ pCtx->pFrameBs + pCtx->iPosBsBuffer,
3722+ &iNalLen[iNalIdxInLayer] );
3723+ pCtx->iPosBsBuffer += iSliceSize;
3724+ iLayerSize += iSliceSize;
3725+ pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize;
3726+
3727+#if defined(SLICE_INFO_OUTPUT)
3728+ fprintf( stderr,
3729+ "@slice=%-6d sliceType:%c idc:%d size:%-6d\n",
3730+ iSliceIdx,
3731+ (pCtx->eSliceType == P_SLICE ? 'P' : 'I'),
3732+ eNalRefIdc,
3733+ iSliceSize );
3734+#endif//SLICE_INFO_OUTPUT
3735+ ++ iNalIdxInLayer;
3736+ ++ iSliceIdx;
3737+ }
3738+
3739+ pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
3740+ pLayerBsInfo->uiSpatialId = iCurDid;
3741+ pLayerBsInfo->uiTemporalId = iCurTid;
3742+ pLayerBsInfo->uiQualityId = 0;
3743+ pLayerBsInfo->uiPriorityId = 0;
3744+ pLayerBsInfo->iNalCount = iNalIdxInLayer;
3745+ }
3746+ }
3747+
3748+ // deblocking filter
3749+ if (
3750+#if defined(MT_ENABLED)
3751+ (!pCtx->pCurDqLayer->bDeblockingParallelFlag) &&
3752+#endif//MT_ENABLED
3753+#if !defined(ENABLE_FRAME_DUMP)
3754+ ( (eNalRefIdc != NRI_PRI_LOWEST) && (param_d->iHighestTemporalId == 0 || iCurTid < param_d->iHighestTemporalId) ) &&
3755+#endif//!ENABLE_FRAME_DUMP
3756+ true
3757+ )
3758+ {
3759+ PerformDeblockingFilter( pCtx );
3760+ }
3761+
3762+ // reference picture list update
3763+ if ( eNalRefIdc != NRI_PRI_LOWEST )
3764+ {
3765+ if ( !WelsUpdateRefList( pCtx ) )
3766+ {
3767+ // Force coding IDR as followed
3768+ ForceCodingIDR( pCtx );
3769+ WelsLog(pCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsUpdateRefList failed.\n");
3770+ return -1;
3771+ }
3772+ }
3773+
3774+ iFrameSize += iLayerSize;
3775+
3776+ pCtx->pFuncList->pfRc.pfWelsRcPictureInfoUpdate(pCtx, iLayerSize);
3777+
3778+#ifdef ENABLE_FRAME_DUMP
3779+ // Dump reconstruction picture for each sQualityStat layer
3780+ if ( iCurDid+1 < pSvcParam->iNumDependencyLayer )
3781+ DumpDependencyRec( fsnr, &param_d->sRecFileName[0], iCurDid );
3782+#endif//ENABLE_FRAME_DUMP
3783+
3784+#if defined(ENABLE_PSNR_CALC)
3785+ snr_y = WelsCalcPsnr( fsnr->pData[0],
3786+ fsnr->iLineSize[0],
3787+ pEncPic->pData[0],
3788+ pEncPic->iLineSize[0],
3789+ iCurWidth,
3790+ iCurHeight );
3791+ snr_u = WelsCalcPsnr( fsnr->pData[1],
3792+ fsnr->iLineSize[1],
3793+ pEncPic->pData[1],
3794+ pEncPic->iLineSize[1],
3795+ (iCurWidth>>1),
3796+ (iCurHeight>>1) );
3797+ snr_v = WelsCalcPsnr( fsnr->pData[2],
3798+ fsnr->iLineSize[2],
3799+ pEncPic->pData[2],
3800+ pEncPic->iLineSize[2],
3801+ (iCurWidth>>1),
3802+ (iCurHeight>>1) );
3803+#endif//ENABLE_PSNR_CALC
3804+
3805+#if defined(LAYER_INFO_OUTPUT)
3806+ fprintf( stderr, "%2s %5d: %-5d %2s T%1d D%1d Q%-2d QP%3d Y%2.2f U%2.2f V%2.2f %8d bits\n",
3807+ (iSpatialIdx == 0) ? "#AU" : " ",
3808+ pCtx->iPOC,
3809+ pCtx->iFrameNum,
3810+ (uiFrameType == WELS_FRAME_TYPE_I || uiFrameType == WELS_FRAME_TYPE_IDR) ? "I": "P",
3811+ iCurTid,
3812+ iCurDid,
3813+ 0,
3814+ pCtx->pWelsSvcRc[pCtx->uiDependencyId].iAverageFrameQp,
3815+ snr_y,
3816+ snr_u,
3817+ snr_v,
3818+ (iLayerSize<<3) );
3819+#endif//LAYER_INFO_OUTPUT
3820+
3821+#if defined(STAT_OUTPUT)
3822+
3823+#if defined(ENABLE_PSNR_CALC)
3824+ {
3825+ pCtx->sStatData[iCurDid][0].sQualityStat.rYPsnr[pCtx->eSliceType] += snr_y;
3826+ pCtx->sStatData[iCurDid][0].sQualityStat.rUPsnr[pCtx->eSliceType] += snr_u;
3827+ pCtx->sStatData[iCurDid][0].sQualityStat.rVPsnr[pCtx->eSliceType] += snr_v;
3828+ }
3829+#endif//ENABLE_PSNR_CALC
3830+
3831+#if defined(MB_TYPES_CHECK) //091025, frame output
3832+ if (pCtx->eSliceType == P_SLICE)
3833+ {
3834+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Intra4x4] += pCtx->sPerInfo.iMbCount[P_SLICE][Intra4x4];
3835+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Intra16x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Intra16x16];
3836+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter16x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter16x16];
3837+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter16x8] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter16x8];
3838+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter8x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter8x16];
3839+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter8x8] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter8x8];
3840+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][PSkip] += pCtx->sPerInfo.iMbCount[P_SLICE][PSkip];
3841+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][8] += pCtx->sPerInfo.iMbCount[P_SLICE][8];
3842+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][9] += pCtx->sPerInfo.iMbCount[P_SLICE][9];
3843+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][10] += pCtx->sPerInfo.iMbCount[P_SLICE][10];
3844+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][11] += pCtx->sPerInfo.iMbCount[P_SLICE][11];
3845+ }
3846+ else if (pCtx->eSliceType == I_SLICE)
3847+ {
3848+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][Intra4x4] += pCtx->sPerInfo.iMbCount[I_SLICE][Intra4x4];
3849+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][Intra16x16] += pCtx->sPerInfo.iMbCount[I_SLICE][Intra16x16];
3850+ pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][7] += pCtx->sPerInfo.iMbCount[I_SLICE][7];
3851+ }
3852+
3853+ memset(pCtx->sPerInfo.iMbCount[P_SLICE], 0, 18*sizeof( int32_t ));
3854+ memset(pCtx->sPerInfo.iMbCount[I_SLICE], 0, 18*sizeof( int32_t ));
3855+
3856+#endif//MB_TYPES_CHECK
3857+ {
3858+ //no pCtx->pSvcParam->bMgsT0OnlyStrategy
3859+ ++ pCtx->sStatData[iCurDid][0].sSliceData.iSliceCount[pCtx->eSliceType]; // for multiple slices coding
3860+ pCtx->sStatData[iCurDid][0].sSliceData.iSliceSize[pCtx->eSliceType] += (iLayerSize<<3); // bits
3861+ }
3862+#endif//STAT_OUTPUT
3863+
3864+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
3865+ if ( pSvcParam->iMultipleThreadIdc <= 1 || SM_SINGLE_SLICE == param_d->sMso.uiSliceMode ) // sigle thread actually used
3866+#else
3867+ if ( 1 )
3868+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
3869+ {
3870+ ++ iLayerNum;
3871+ ++ pLayerBsInfo;
3872+ }
3873+
3874+
3875+ pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3876+
3877+ if( pSvcParam->iPaddingFlag && pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize > 0 )
3878+ {
3879+ const int32_t kiPaddingNalSize = WritePadding(pCtx, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize);
3880+
3881+#if GOM_TRACE_FLAG
3882+ WelsLog( pCtx, WELS_LOG_INFO,"[RC] encoding_qp%d Padding: %d\n",pCtx->uiDependencyId, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize);
3883+#endif
3884+ if ( kiPaddingNalSize <= 0 )
3885+ return -1;
3886+
3887+ pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingBitrateStat += pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize;
3888+
3889+ pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize=0;
3890+
3891+ pLayerBsInfo->uiPriorityId = 0;
3892+ pLayerBsInfo->uiSpatialId = 0;
3893+ pLayerBsInfo->uiTemporalId = 0;
3894+ pLayerBsInfo->uiQualityId = 0;
3895+ pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3896+ pLayerBsInfo->iNalCount = 1;
3897+ pLayerBsInfo->iNalLengthInByte[0] = kiPaddingNalSize;
3898+ ++ pLayerBsInfo;
3899+ pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3900+ ++ iLayerNum;
3901+ }
3902+
3903+#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN) && defined(TRY_SLICING_BALANCE)
3904+ if ( param_d->sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc > 1 &&
3905+ pSvcParam->iMultipleThreadIdc >= param_d->sMso.sSliceArgument.iSliceNum )
3906+ {
3907+ CalcSliceComplexRatio( pCtx->pSliceThreading->pSliceComplexRatio[iCurDid], pCtx->pCurDqLayer->pSliceEncCtx, pCtx->pSliceThreading->pSliceConsumeTime[iCurDid] );
3908+#if defined(MT_DEBUG)
3909+ TrackSliceComplexities( pCtx, iCurDid );
3910+#endif//#if defined(MT_DEBUG)
3911+ }
3912+#endif//MT_ENABLED && DYNAMIC_SLICE_ASSIGN && TRY_SLICING_BALANCE
3913+
3914+ ++ iSpatialIdx;
3915+
3916+ if ( iCurDid+1 < pSvcParam->iNumDependencyLayer )
3917+ {
3918+ WelsSwapDqLayers( pCtx );
3919+ }
3920+
3921+ if ( pSvcParam->bEnableLongTermReference && (pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DELAY_MARK)))
3922+ {
3923+ pCtx->bLongTermRefFlag[d_idx][0] = true;
3924+ }
3925+
3926+ if ( iCurTid < pCtx->uiSpatialLayersInTemporal[d_idx] - 1 || pSvcParam->iDecompStages == 0 )
3927+ {
3928+ if ( (iCurTid >= MAX_TEMPORAL_LEVEL)||(pCtx->uiSpatialLayersInTemporal[d_idx]-1>= MAX_TEMPORAL_LEVEL))
3929+ {
3930+ ForceCodingIDR( pCtx ); // some logic error
3931+ return -1;
3932+ }
3933+
3934+ if ( pSvcParam->bEnableLongTermReference && pCtx->bLongTermRefFlag[d_idx][iCurTid] )
3935+ {
3936+ SPicture *tmp = pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]+pCtx->pVaa->uiMarkLongTermPicIdx];
3937+ pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]+pCtx->pVaa->uiMarkLongTermPicIdx] = pCtx->pSpatialPic[d_idx][iCurTid];
3938+ pCtx->pSpatialPic[d_idx][iCurTid] = pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]-1];
3939+ pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]-1] = tmp;
3940+ pCtx->bLongTermRefFlag[d_idx][iCurTid] = false;
3941+ }
3942+ else
3943+ {
3944+ WelsExchangeSpatialPictures( &pCtx->pSpatialPic[d_idx][pCtx->uiSpatialLayersInTemporal[d_idx]-1], &pCtx->pSpatialPic[d_idx][iCurTid] );
3945+ }
3946+ }
3947+
3948+ if ( pSvcParam->bEnableLongTermReference && ((pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == WELS_FRAME_TYPE_IDR))
3949+ {
3950+ pCtx->bLongTermRefFlag[d_idx][iCurTid] = true;
3951+ }
3952+ }
3953+
3954+#if defined(MT_ENABLED) && defined(MT_DEBUG)
3955+ TrackSliceConsumeTime( pCtx, did_list, iSpatialNum );
3956+#endif//MT_ENABLED && MT_DEBUG
3957+
3958+#if defined(MT_ENABLED) && defined(DYNAMIC_SLICE_ASSIGN)
3959+ if ( pSvcParam->iMultipleThreadIdc > 1 && did_list[0] == BASE_DEPENDENCY_ID
3960+ && pSvcParam->sDependencyLayers[0].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc >= pSvcParam->sDependencyLayers[0].sMso.sSliceArgument.iSliceNum
3961+ && pSvcParam->sDependencyLayers[did_list[iSpatialNum-1]].sMso.uiSliceMode == SM_FIXEDSLCNUM_SLICE && pSvcParam->iMultipleThreadIdc >= pSvcParam->sDependencyLayers[did_list[iSpatialNum-1]].sMso.sSliceArgument.iSliceNum )
3962+ {
3963+ AdjustBaseLayer( pCtx );
3964+ }
3965+#endif//DYNAMIC_SLICE_ASSIGN
3966+
3967+#ifdef ENABLE_FRAME_DUMP
3968+ DumpRecFrame( fsnr, &pSvcParam->sDependencyLayers[pSvcParam->iNumDependencyLayer-1].sRecFileName[0] ); // pDecPic: final reconstruction output
3969+#endif//ENABLE_FRAME_DUMP
3970+
3971+ ++ pCtx->iCodingIndex;
3972+ pCtx->eLastNalPriority = eNalRefIdc;
3973+ pFbi->iLayerNum = iLayerNum;
3974+
3975+#if defined(X86_ASM)
3976+ WelsEmms();
3977+#endif //X86_ASM
3978+
3979+ return eFrameType;
3980+}
3981+
3982+/*!
3983+ * \brief Wels SVC encoder parameters adjustment
3984+ * SVC adjustment results in new requirement in memory blocks adjustment
3985+ */
3986+int32_t WelsEncoderParamAdjust( sWelsEncCtx **ppCtx, SWelsSvcCodingParam *pNewParam )
3987+{
3988+ SWelsSvcCodingParam *pOldParam = NULL;
3989+ int32_t iReturn = 0;
3990+ int8_t iIndexD= 0;
3991+ bool_t bNeedReset = false;
3992+
3993+ if ( NULL == ppCtx || NULL == *ppCtx || NULL == pNewParam ) return 1;
3994+
3995+ /* Check validation in new parameters */
3996+ iReturn = ParamValidationExt( pNewParam );
3997+ if ( iReturn != 0 ) return iReturn;
3998+
3999+ pOldParam = (*ppCtx)->pSvcParam;
4000+
4001+ /* Decide whether need reset for IDR frame based on adjusting prarameters changed */
4002+ /* Temporal levels, spatial settings and/ or quality settings changed need update parameter sets related. */
4003+ bNeedReset = (pOldParam == NULL ) ||
4004+ (pOldParam->iNumTemporalLayer != pNewParam->iNumTemporalLayer) ||
4005+ (pOldParam->uiGopSize != pNewParam->uiGopSize) ||
4006+ (pOldParam->iNumDependencyLayer != pNewParam->iNumDependencyLayer) ||
4007+ (pOldParam->iDecompStages != pNewParam->iDecompStages) ||
4008+ (pOldParam->iActualPicWidth != pNewParam->iActualPicWidth || pOldParam->iActualPicHeight != pNewParam->iActualPicHeight) ||
4009+ (pOldParam->SUsedPicRect.iWidth != pNewParam->SUsedPicRect.iWidth || pOldParam->SUsedPicRect.iHeight != pNewParam->SUsedPicRect.iHeight) ||
4010+ (pOldParam->bEnableLongTermReference != pNewParam->bEnableLongTermReference);
4011+ if ( !bNeedReset ){ // Check its picture resolutions/quality settings respectively in each dependency layer
4012+ iIndexD = 0;
4013+ assert( pOldParam->iNumDependencyLayer == pNewParam->iNumDependencyLayer );
4014+ do
4015+ {
4016+ const SDLayerParam *kpOldDlp = &pOldParam->sDependencyLayers[iIndexD];
4017+ const SDLayerParam *kpNewDlp = &pNewParam->sDependencyLayers[iIndexD];
4018+ float fT1 = .0f;
4019+ float fT2 = .0f;
4020+
4021+ // check frame size settings
4022+ if ( kpOldDlp->iFrameWidth != kpNewDlp->iFrameWidth ||
4023+ kpOldDlp->iFrameHeight != kpNewDlp->iFrameHeight ||
4024+ kpOldDlp->iActualWidth != kpNewDlp->iActualWidth ||
4025+ kpOldDlp->iActualHeight != kpNewDlp->iActualHeight ){
4026+ bNeedReset = true;
4027+ break;
4028+ }
4029+
4030+ if ( kpOldDlp->sMso.uiSliceMode != kpNewDlp->sMso.uiSliceMode ||
4031+ kpOldDlp->sMso.sSliceArgument.iSliceNum != kpNewDlp->sMso.sSliceArgument.iSliceNum )
4032+ {
4033+ bNeedReset = true;
4034+ break;
4035+ }
4036+
4037+ // check frame rate
4038+ // we can not check whether corresponding fFrameRate is equal or not,
4039+ // only need to check d_max/d_min and max_fr/d_max whether it is equal or not
4040+ if ( kpNewDlp->fInputFrameRate > EPSN && kpOldDlp->fInputFrameRate > EPSN )
4041+ fT1 = kpNewDlp->fOutputFrameRate/kpNewDlp->fInputFrameRate - kpOldDlp->fOutputFrameRate/kpOldDlp->fInputFrameRate;
4042+ if ( kpNewDlp->fOutputFrameRate > EPSN && kpOldDlp->fOutputFrameRate > EPSN )
4043+ fT2 = pNewParam->fMaxFrameRate/kpNewDlp->fOutputFrameRate - pOldParam->fMaxFrameRate/kpOldDlp->fOutputFrameRate;
4044+ if ( fT1 > EPSN || fT1 < -EPSN || fT2 > EPSN || fT2 < -EPSN )
4045+ {
4046+ bNeedReset = true;
4047+ break;
4048+ }
4049+
4050+ if ( kpOldDlp->iHighestTemporalId != kpNewDlp->iHighestTemporalId )
4051+ {
4052+ bNeedReset = true;
4053+ break;
4054+ }
4055+
4056+ ++ iIndexD;
4057+ } while (iIndexD < pOldParam->iNumDependencyLayer);
4058+ }
4059+
4060+ if ( bNeedReset ){
4061+ SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
4062+ uint16_t uiTmpIdrPicId;//this is for LTR!
4063+ memcpy( sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable, (PARA_SET_TYPE)*sizeof(SParaSetOffsetVariable) );// confirmed_safe_unsafe_usage
4064+ uiTmpIdrPicId = (*ppCtx)->sPSOVector.uiIdrPicId;
4065+
4066+ WelsUninitEncoderExt( ppCtx );
4067+
4068+ /* Update new parameters */
4069+ if ( WelsInitEncoderExt( ppCtx, pNewParam ) )
4070+ return 1;
4071+
4072+ // reset the scaled spatial picture size
4073+ (*ppCtx)->pVpp->WelsPreprocessReset(*ppCtx);
4074+ //if WelsInitEncoderExt succeed
4075+
4076+ //for FLEXIBLE_PARASET_ID
4077+ memcpy( (*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable, (PARA_SET_TYPE)*sizeof(SParaSetOffsetVariable) );// confirmed_safe_unsafe_usage
4078+ (*ppCtx)->sPSOVector.uiIdrPicId = uiTmpIdrPicId;
4079+ }
4080+ else{
4081+ /* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */
4082+ pNewParam->iNumRefFrame = WELS_CLIP3(pNewParam->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
4083+ pNewParam->iLoopFilterDisableIdc = WELS_CLIP3(pNewParam->iLoopFilterDisableIdc, 0, 6);
4084+ pNewParam->iLoopFilterAlphaC0Offset = WELS_CLIP3(pNewParam->iLoopFilterAlphaC0Offset, -6, 6);
4085+ pNewParam->iLoopFilterBetaOffset = WELS_CLIP3(pNewParam->iLoopFilterBetaOffset, -6, 6);
4086+ pNewParam->iInterLayerLoopFilterDisableIdc = WELS_CLIP3(pNewParam->iInterLayerLoopFilterDisableIdc, 0, 6);
4087+ pNewParam->iInterLayerLoopFilterAlphaC0Offset = WELS_CLIP3(pNewParam->iInterLayerLoopFilterAlphaC0Offset, -6, 6);
4088+ pNewParam->iInterLayerLoopFilterBetaOffset = WELS_CLIP3(pNewParam->iInterLayerLoopFilterBetaOffset, -6, 6);
4089+ pNewParam->fMaxFrameRate = WELS_CLIP3(pNewParam->fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
4090+
4091+ // we can not use direct struct based memcpy due some fields need keep unchanged as before
4092+ pOldParam->fMaxFrameRate = pNewParam->fMaxFrameRate; // maximal frame rate [Hz / fps]
4093+ pOldParam->iInputCsp = pNewParam->iInputCsp; // color space of input sequence
4094+ pOldParam->uiIntraPeriod = pNewParam->uiIntraPeriod; // intra period (multiple of GOP size as desired)
4095+ pOldParam->bEnableSpsPpsIdAddition = pNewParam->bEnableSpsPpsIdAddition;
4096+ pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl;
4097+ pOldParam->iNumRefFrame = pNewParam->iNumRefFrame; // number of reference frame used
4098+
4099+ /* denoise control */
4100+ pOldParam->bEnableDenoise = pNewParam->bEnableDenoise;
4101+
4102+ /* background detection control */
4103+ pOldParam->bEnableBackgroundDetection = pNewParam->bEnableBackgroundDetection;
4104+
4105+ /* adaptive quantization control */
4106+ pOldParam->bEnableAdaptiveQuant = pNewParam->bEnableAdaptiveQuant;
4107+
4108+ /* int32_t term reference control */
4109+ pOldParam->bEnableLongTermReference = pNewParam->bEnableLongTermReference;
4110+ pOldParam->uiLtrMarkPeriod = pNewParam->uiLtrMarkPeriod;
4111+
4112+ // keep below values unchanged as before
4113+ pOldParam->bEnableSSEI = pNewParam->bEnableSSEI;
4114+ pOldParam->bEnableFrameCroppingFlag = pNewParam->bEnableFrameCroppingFlag; // enable frame cropping flag
4115+
4116+ /* Motion search */
4117+
4118+ /* Deblocking loop filter */
4119+ pOldParam->iLoopFilterDisableIdc = pNewParam->iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries
4120+ pOldParam->iLoopFilterAlphaC0Offset = pNewParam->iLoopFilterAlphaC0Offset;// AlphaOffset: valid range [-6, 6], default 0
4121+ pOldParam->iLoopFilterBetaOffset = pNewParam->iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0
4122+ pOldParam->iInterLayerLoopFilterDisableIdc = pNewParam->iInterLayerLoopFilterDisableIdc; // Employed based upon inter-layer, same comment as above
4123+ pOldParam->iInterLayerLoopFilterAlphaC0Offset = pNewParam->iInterLayerLoopFilterAlphaC0Offset; // InterLayerLoopFilterAlphaC0Offset
4124+ pOldParam->iInterLayerLoopFilterBetaOffset = pNewParam->iInterLayerLoopFilterBetaOffset; // InterLayerLoopFilterBetaOffset
4125+
4126+ /* Rate Control */
4127+ pOldParam->bEnableRc = pNewParam->bEnableRc;
4128+ pOldParam->iRCMode = pNewParam->iRCMode;
4129+ pOldParam->iTargetBitrate = pNewParam->iTargetBitrate; // overall target bitrate introduced in RC module
4130+ pOldParam->iPaddingFlag = pNewParam->iPaddingFlag;
4131+
4132+ /* Layer definition */
4133+ pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl;
4134+
4135+ // d
4136+ iIndexD = 0;
4137+ do
4138+ {
4139+ SDLayerParam *pOldDlp = &pOldParam->sDependencyLayers[iIndexD];
4140+ SDLayerParam *pNewDlp = &pNewParam->sDependencyLayers[iIndexD];
4141+
4142+ pOldDlp->fInputFrameRate = pNewDlp->fInputFrameRate; // input frame rate
4143+ pOldDlp->fOutputFrameRate = pNewDlp->fOutputFrameRate; // output frame rate
4144+ pOldDlp->iSpatialBitrate = pNewDlp->iSpatialBitrate;
4145+
4146+ pOldDlp->uiProfileIdc = pNewDlp->uiProfileIdc; // value of profile IDC (0 for auto-detection)
4147+
4148+ /* Derived variants below */
4149+ pOldDlp->iTemporalResolution = pNewDlp->iTemporalResolution;
4150+ pOldDlp->iDecompositionStages = pNewDlp->iDecompositionStages;
4151+
4152+ memcpy(pOldDlp->uiCodingIdx2TemporalId, pNewDlp->uiCodingIdx2TemporalId, sizeof(pOldDlp->uiCodingIdx2TemporalId)); // confirmed_safe_unsafe_usage
4153+
4154+ ++ iIndexD;
4155+ } while (iIndexD < pOldParam->iNumDependencyLayer);
4156+ }
4157+
4158+ /* Any else initialization/reset for rate control here? */
4159+
4160+ return 0;
4161+}
4162+
4163+
4164+int32_t WelsCodeOnePicPartition( sWelsEncCtx *pCtx,
4165+ SLayerBSInfo *pLayerBsInfo,
4166+ int32_t *pNalIdxInLayer,
4167+ int32_t* pLayerSize,
4168+ int32_t iFirstMbInPartition, // first mb inclusive in partition
4169+ int32_t iEndMbInPartition, // end mb exclusive in partition
4170+ int32_t iStartSliceIdx
4171+ )
4172+{
4173+
4174+ SDqLayer * pCurLayer = pCtx->pCurDqLayer;
4175+ SSliceCtx * pSliceCtx = pCurLayer->pSliceEncCtx;
4176+ int32_t iNalLen[MAX_NAL_UNITS_IN_LAYER] = {0};
4177+ int32_t iNalIdxInLayer = *pNalIdxInLayer;
4178+ int32_t iSliceIdx = iStartSliceIdx;
4179+ const int32_t kiSliceStep = pCtx->iActiveThreadsNum;
4180+ const int32_t kiPartitionId = iStartSliceIdx % kiSliceStep;
4181+ int32_t iPartitionBsSize = 0;
4182+ int32_t iAnyMbLeftInPartition= iEndMbInPartition - iFirstMbInPartition;
4183+ const EWelsNalUnitType keNalType = pCtx->eNalType;
4184+ const EWelsNalRefIdc keNalRefIdc = pCtx->eNalPriority;
4185+ const bool_t kbNeedPrefix = pCtx->bNeedPrefixNalFlag;
4186+
4187+ //init
4188+ {
4189+ pSliceCtx->pFirstMbInSlice[iSliceIdx] = iFirstMbInPartition;
4190+ pCurLayer->pNumSliceCodedOfPartition[kiPartitionId] = 1; // one slice per partition intialized, dynamic slicing inside
4191+ pCurLayer->pLastMbIdxOfPartition[kiPartitionId] = iEndMbInPartition-1;
4192+ }
4193+ pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId] = 0;
4194+
4195+ while ( iAnyMbLeftInPartition > 0 )
4196+ {
4197+ int32_t iSliceSize = 0;
4198+
4199+ if ( iSliceIdx >= pSliceCtx->iMaxSliceNumConstraint ) // insufficient memory in pSliceInLayer[]
4200+ {
4201+ // TODO: need exception handler for not large enough of MAX_SLICES_NUM related memory usage
4202+ // No idea about its solution due MAX_SLICES_NUM is fixed lenght in relevent pData structure
4203+ return 1;
4204+ }
4205+
4206+ if ( kbNeedPrefix )
4207+ {
4208+ iPartitionBsSize += AddPrefixNal( pCtx, pLayerBsInfo, &iNalLen[0], &iNalIdxInLayer, keNalType, keNalRefIdc );
4209+ }
4210+
4211+ WelsLoadNal( pCtx->pOut, keNalType, keNalRefIdc );
4212+ WelsCodeOneSlice( pCtx, iSliceIdx, keNalType );
4213+ WelsUnloadNal( pCtx->pOut );
4214+
4215+ iSliceSize = WelsEncodeNalExt( &pCtx->pOut->sNalList[pCtx->pOut->iNalIndex-1],
4216+ &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
4217+ pCtx->pFrameBs + pCtx->iPosBsBuffer,
4218+ &iNalLen[iNalIdxInLayer] );
4219+ pCtx->iPosBsBuffer += iSliceSize;
4220+ iPartitionBsSize += iSliceSize;
4221+ pLayerBsInfo->iNalLengthInByte[iNalIdxInLayer] = iSliceSize;
4222+
4223+#if defined(SLICE_INFO_OUTPUT)
4224+ fprintf( stderr,
4225+ "@slice=%-6d sliceType:%c idc:%d size:%-6d\n",
4226+ iSliceIdx,
4227+ (pCtx->eSliceType == P_SLICE ? 'P' : 'I'),
4228+ eNalRefIdc,
4229+ iSliceSize );
4230+#endif//SLICE_INFO_OUTPUT
4231+
4232+ ++ iNalIdxInLayer;
4233+ iSliceIdx += kiSliceStep; //if uiSliceIdx is not continuous
4234+ iAnyMbLeftInPartition = iEndMbInPartition - (1 + pCurLayer->pLastCodedMbIdxOfPartition[kiPartitionId]);
4235+ }
4236+
4237+ *pLayerSize = iPartitionBsSize;
4238+ *pNalIdxInLayer = iNalIdxInLayer;
4239+
4240+ // slice based packing???
4241+ pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
4242+ pLayerBsInfo->uiSpatialId = pCtx->uiDependencyId;
4243+ pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId;
4244+ pLayerBsInfo->uiQualityId = 0;
4245+ pLayerBsInfo->uiPriorityId = 0;
4246+ pLayerBsInfo->iNalCount = iNalIdxInLayer;
4247+
4248+ return 0;
4249+}
4250+} // 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