History

Pretty printed the C++ code with astyle

Ethan Hugg committed 12 years ago

Commit ff6b6691 parent 063709c225 files · +48457 −51954Browse files

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

Unified · Split

codec/encoder/core/src/encoder_ext.cpp+4032−4250
@@ -1,4250 +1,4032 @@
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
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+ float fMaxFrameRate = 0.0f;
98+ const float fEpsn = 0.000001f;
99+ int32_t i = 0;
100+ int32_t iLastSpatialWidth = 0;
101+ int32_t iLastSpatialHeight = 0;
102+ float fLastFrameRateIn = 0.0f;
103+ float fLastFrameRateOut = 0.0f;
104+ SDLayerParam* pLastSpatialParam = NULL;
105+
106+ assert (pCfg != NULL);
107+
108+ for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) {
109+ SDLayerParam* fDlp = &pCfg->sDependencyLayers[i];
110+ if (fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn
111+ && fDlp->fInputFrameRate <= fEpsn)
112+ || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn)) {
113+#if defined (_DEBUG)
114+ fprintf (stderr, "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n",
115+ fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
116+#endif
117+ return 1;
118+ }
119+ if (UINT_MAX == GetLogFactor (fDlp->fOutputFrameRate, fDlp->fInputFrameRate)) {
120+#if defined (_DEBUG)
121+ fprintf (stderr,
122+ "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",
123+ fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
124+#endif
125+ return 1;
126+ }
127+ }
128+
129+ for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) {
130+ SDLayerParam* fDlp = &pCfg->sDependencyLayers[i];
131+ if (fDlp->fInputFrameRate > fMaxFrameRate)
132+ fMaxFrameRate = fDlp->fInputFrameRate;
133+ }
134+
135+ if (fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn
136+ || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn)) {
137+ pCfg->fMaxFrameRate = fMaxFrameRate;
138+ }
139+
140+ for (i = 0; i < pCfg->iNumDependencyLayer; ++ i) {
141+ SDLayerParam* fDlp = &pCfg->sDependencyLayers[i];
142+
143+ pLastSpatialParam = fDlp;
144+ iLastSpatialWidth = fDlp->iFrameWidth;
145+ iLastSpatialHeight = fDlp->iFrameHeight;
146+ fLastFrameRateIn = fDlp->fInputFrameRate;
147+ fLastFrameRateOut = fDlp->fOutputFrameRate;
148+ }
149+
150+ return 0;
151+}
152+
153+int32_t ParamValidationExt (void* pParam) {
154+ SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)pParam;
155+ int8_t i = 0;
156+ int32_t iIdx = 0;
157+
158+ assert (pCodingParam != NULL);
159+ if (NULL == pCodingParam)
160+ return 1;
161+
162+ if (pCodingParam->iNumDependencyLayer < 1 || pCodingParam->iNumDependencyLayer > MAX_DEPENDENCY_LAYER) {
163+#if defined (_DEBUG)
164+ fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumDependencyLayer: %d!\n",
165+ pCodingParam->iNumDependencyLayer);
166+#endif//#if _DEBUG
167+
168+ return 1;
169+ }
170+
171+ if (pCodingParam->iNumTemporalLayer < 1 || pCodingParam->iNumTemporalLayer > MAX_TEMPORAL_LEVEL) {
172+#if defined (_DEBUG)
173+ fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->iNumTemporalLayer: %d!\n",
174+ pCodingParam->iNumTemporalLayer);
175+#endif//#if _DEBUG
176+ return 1;
177+ }
178+
179+ if (pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE) {
180+#if defined (_DEBUG)
181+ fprintf (stderr, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!\n", pCodingParam->uiGopSize);
182+#endif//#if _DEBUG
183+ return 1;
184+ }
185+
186+
187+ if (pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize) {
188+#if defined (_DEBUG)
189+ fprintf (stderr,
190+ "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!\n",
191+ pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
192+#endif//#if _DEBUG
193+ return 1;
194+ }
195+
196+ if (pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize - 1)) != 0) {
197+#if defined (_DEBUG)
198+ fprintf (stderr, "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!\n",
199+ pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
200+#endif//#if _DEBUG
201+ return 1;
202+ }
203+
204+
205+#ifdef MT_ENABLED
206+ //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode
207+ // (1) Single Thread
208+ // if (THREAD==1)//single thread
209+ // no parallel_deblocking: bDeblockingParallelFlag = 0;
210+ // (2) Multi Thread: see uiSliceMode decision
211+ if (pCodingParam->iMultipleThreadIdc == 1) {
212+ //now is single thread. no parallel deblocking, set flag=0
213+ pCodingParam->bDeblockingParallelFlag = false;
214+ } else {
215+ pCodingParam->bDeblockingParallelFlag = true;
216+ }
217+#else
218+ pCodingParam->bDeblockingParallelFlag = false;
219+#endif//MT_ENABLED
220+
221+ for (i = 0; i < pCodingParam->iNumDependencyLayer; ++ i) {
222+ SDLayerParam* fDlp = &pCodingParam->sDependencyLayers[i];
223+ const int32_t kiPicWidth = fDlp->iFrameWidth;
224+ const int32_t kiPicHeight = fDlp->iFrameHeight;
225+ int32_t iMbWidth = 0;
226+ int32_t iMbHeight = 0;
227+ int32_t iMbNumInFrame = 0;
228+ int32_t iMaxSliceNum = MAX_SLICES_NUM;
229+ if (kiPicWidth <= 0 || kiPicHeight <= 0) {
230+#if defined (_DEBUG)
231+ fprintf (stderr, "ParamValidationExt(), invalid %d x %d in dependency layer settings!\n", kiPicWidth, kiPicHeight);
232+#endif//#if _DEBUG
233+ return 1;
234+ }
235+ if ((kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0) {
236+#if defined (_DEBUG)
237+ fprintf (stderr,
238+ "ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!\n",
239+ i, kiPicWidth, kiPicHeight);
240+#endif//#if _DEBUG
241+ return 1;
242+ }
243+
244+ if (fDlp->sMso.uiSliceMode >= SM_RESERVED) {
245+#if defined (_DEBUG)
246+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n", fDlp->sMso.uiSliceMode);
247+#endif//#if _DEBUG
248+ return 1;
249+ }
250+
251+ //check pSlice settings under multi-pSlice
252+ if (kiPicWidth <= 16 && kiPicHeight <= 16) {
253+ //only have one MB, set to single_slice
254+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
255+ }
256+ switch (fDlp->sMso.uiSliceMode) {
257+ case SM_SINGLE_SLICE:
258+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
259+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
260+ fDlp->sMso.sSliceArgument.iSliceNum = 0;
261+ for (iIdx = 0; iIdx < MAX_SLICES_NUM; iIdx++) {
262+ fDlp->sMso.sSliceArgument.uiSliceMbNum[iIdx] = 0;
263+ }
264+ break;
265+ case SM_FIXEDSLCNUM_SLICE: {
266+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
267+
268+ iMbWidth = (kiPicWidth + 15) >> 4;
269+ iMbHeight = (kiPicHeight + 15) >> 4;
270+ iMbNumInFrame = iMbWidth * iMbHeight;
271+ iMaxSliceNum = MAX_SLICES_NUM;
272+ if (fDlp->sMso.sSliceArgument.iSliceNum <= 0
273+ || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum) {
274+#if defined (_DEBUG)
275+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum);
276+#endif//#if _DEBUG
277+ return 1;
278+ }
279+ if (fDlp->sMso.sSliceArgument.iSliceNum == 1) {
280+#if defined (_DEBUG)
281+ fprintf (stderr,
282+ "ParamValidationExt(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!\n",
283+ fDlp->sMso.sSliceArgument.iSliceNum);
284+#endif//#if _DEBUG
285+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
286+ break;
287+ }
288+ if (pCodingParam->bEnableRc) { // multiple slices verify with gom
289+ //check uiSliceNum
290+ GomValidCheckSliceNum (iMbWidth, iMbHeight, (int32_t*)&fDlp->sMso.sSliceArgument.iSliceNum);
291+ assert (fDlp->sMso.sSliceArgument.iSliceNum > 1);
292+ //set uiSliceMbNum with current uiSliceNum
293+ GomValidCheckSliceMbNum (iMbWidth, iMbHeight, &fDlp->sMso.sSliceArgument);
294+ } else if (!CheckFixedSliceNumMultiSliceSetting (iMbNumInFrame,
295+ &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings
296+ //check uiSliceMbNum with current uiSliceNum
297+#if defined (_DEBUG)
298+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
299+ fDlp->sMso.sSliceArgument.uiSliceMbNum[0]);
300+#endif//#if _DEBUG
301+ return 1;
302+ }
303+ // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
304+ if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) {
305+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
306+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
307+ break;
308+ }
309+ }
310+ break;
311+ case SM_RASTER_SLICE: {
312+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
313+
314+ iMbWidth = (kiPicWidth + 15) >> 4;
315+ iMbHeight = (kiPicHeight + 15) >> 4;
316+ iMbNumInFrame = iMbWidth * iMbHeight;
317+ iMaxSliceNum = MAX_SLICES_NUM;
318+ if (fDlp->sMso.sSliceArgument.uiSliceMbNum[0] <= 0) {
319+#if defined (_DEBUG)
320+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
321+ fDlp->sMso.sSliceArgument.uiSliceMbNum[0]);
322+#endif//#if _DEBUG
323+ return 1;
324+ }
325+
326+ if (!CheckRasterMultiSliceSetting (iMbNumInFrame, &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings
327+#if defined (_DEBUG)
328+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
329+ fDlp->sMso.sSliceArgument.uiSliceMbNum[0]);
330+#endif//#if _DEBUG
331+ return 1;
332+ }
333+ if (fDlp->sMso.sSliceArgument.iSliceNum <= 0
334+ || fDlp->sMso.sSliceArgument.iSliceNum > iMaxSliceNum) { // verify interleave mode settings
335+#if defined (_DEBUG)
336+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!\n",
337+ fDlp->sMso.sSliceArgument.iSliceNum);
338+#endif//#if _DEBUG
339+ return 1;
340+ }
341+ if (fDlp->sMso.sSliceArgument.iSliceNum == 1) {
342+#if defined (_DEBUG)
343+ fprintf (stderr, "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!\n");
344+#endif//#if _DEBUG
345+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
346+ break;
347+ }
348+#ifdef MT_ENABLED
349+ if (pCodingParam->bEnableRc && fDlp->sMso.sSliceArgument.iSliceNum > 1) {
350+#if defined (_DEBUG)
351+ fprintf (stderr, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!\n");
352+#endif//#if _DEBUG
353+ }
354+#endif
355+ // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
356+ if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) {
357+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
358+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
359+ break;
360+ }
361+ }
362+ break;
363+ case SM_ROWMB_SLICE: {
364+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint = 0;
365+
366+ iMbWidth = (kiPicWidth + 15) >> 4;
367+ iMbHeight = (kiPicHeight + 15) >> 4;
368+ iMaxSliceNum = MAX_SLICES_NUM;
369+ if (iMbHeight > iMaxSliceNum) {
370+#if defined (_DEBUG)
371+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX!\n", iMbHeight);
372+#endif//#if _DEBUG
373+ return 1;
374+ }
375+ fDlp->sMso.sSliceArgument.iSliceNum = iMbHeight;
376+
377+ if (fDlp->sMso.sSliceArgument.iSliceNum <= 0) {
378+#if defined (_DEBUG)
379+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceNum (%d) settings!\n", fDlp->sMso.sSliceArgument.iSliceNum);
380+#endif//#if _DEBUG
381+ return 1;
382+ }
383+ if (!CheckRowMbMultiSliceSetting (iMbWidth, &fDlp->sMso.sSliceArgument)) { // verify interleave mode settings
384+#if defined (_DEBUG)
385+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!\n",
386+ fDlp->sMso.sSliceArgument.uiSliceMbNum[0]);
387+#endif//#if _DEBUG
388+ return 1;
389+ }
390+ }
391+ break;
392+ case SM_DYN_SLICE: {
393+ iMbWidth = (kiPicWidth + 15) >> 4;
394+ iMbHeight = (kiPicHeight + 15) >> 4;
395+ if (fDlp->sMso.sSliceArgument.uiSliceSizeConstraint <= 0) {
396+#if defined (_DEBUG)
397+ fprintf (stderr, "ParamValidationExt(), invalid iSliceSize (%d) settings!\n",
398+ fDlp->sMso.sSliceArgument.uiSliceSizeConstraint);
399+#endif//#if _DEBUG
400+ return 1;
401+ }
402+ // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
403+ if (iMbWidth * iMbHeight <= MIN_NUM_MB_PER_SLICE) {
404+ fDlp->sMso.uiSliceMode = SM_SINGLE_SLICE;
405+ fDlp->sMso.sSliceArgument.iSliceNum = 1;
406+ break;
407+ }
408+ }
409+ break;
410+ default: {
411+
412+#if defined (_DEBUG)
413+ fprintf (stderr, "ParamValidationExt(), invalid uiSliceMode (%d) settings!\n",
414+ pCodingParam->sDependencyLayers[0].sMso.uiSliceMode);
415+#endif//#if _DEBUG
416+ return 1;
417+
418+ }
419+ break;
420+ }
421+ }
422+
423+ return ParamValidation (pCodingParam);
424+}
425+
426+/*!
427+ * \brief acquire count number of layers and NALs based on configurable paramters dependency
428+ * \pParam pCtx sWelsEncCtx*
429+ * \pParam pParam SWelsSvcCodingParam*
430+ * \pParam pCountLayers pointer of count number of layers indeed
431+ * \pParam iCountNals pointer of count number of nals indeed
432+ * \return 0 - successful; otherwise failed
433+ */
434+static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, int32_t* pCountLayers,
435+ int32_t* pCountNals) {
436+ int32_t iCountNumLayers = 0;
437+ int32_t iCountNumNals = 0;
438+ int32_t iNumDependencyLayers = 0;
439+ int32_t iDIndex = 0;
440+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
441+ int32_t iNumLayersPack = 0;
442+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
443+
444+ if (NULL == pParam || NULL == ppCtx || NULL == *ppCtx)
445+ return 1;
446+
447+ iNumDependencyLayers = pParam->iNumDependencyLayer;
448+
449+ do {
450+ SDLayerParam* pDLayer = &pParam->sDependencyLayers[iDIndex];
451+// pDLayer->ptr_cfg = pParam;
452+ int32_t iOrgNumNals = iCountNumNals;
453+
454+ //Note: Sep. 2010
455+ //Review this part and suggest no change, since the memory over-use
456+ //(1) counts little to the overall performance
457+ //(2) should not be critial even under mobile case
458+ if (SM_DYN_SLICE == pDLayer->sMso.uiSliceMode) {
459+ iCountNumNals += MAX_SLICES_NUM;
460+ // plus prefix NALs
461+ if (iDIndex == 0)
462+ iCountNumNals += MAX_SLICES_NUM;
463+ // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h
464+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
465+ assert (MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME);
466+ // iNumLayersPack += MAX_SLICES_NUM; // do not count it for dynamic slicing mode
467+#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER
468+ assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER);
469+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
470+ } else { /*if ( SM_SINGLE_SLICE != pDLayer->sMso.uiSliceMode )*/
471+ const int32_t kiNumOfSlice = GetInitialSliceNum ((pDLayer->iFrameWidth + 0x0f) >> 4,
472+ (pDLayer->iFrameHeight + 0x0f) >> 4,
473+ &pDLayer->sMso);
474+
475+ // NEED check iCountNals value in case multiple slices is used
476+ iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs
477+ // plus prefix NALs
478+ if (iDIndex == 0)
479+ iCountNumNals += kiNumOfSlice;
480+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
481+ assert (num_of_slice <= MAX_SLICES_NUM && MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME);
482+ iNumLayersPack += num_of_slice;
483+#else//!MT_ENABLED || !PACKING_ONE_SLICE_PER_LAYER
484+ assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER);
485+#endif//MT_ENALBED && PACKING_ONE_SLICE_PER_LAYER
486+ if (kiNumOfSlice > MAX_SLICES_NUM) {
487+ WelsLog (*ppCtx, WELS_LOG_ERROR,
488+ "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!\n",
489+ kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0);
490+ return 1;
491+ }
492+ }
493+#if !defined(MT_ENABLED) || !defined(PACKING_ONE_SLICE_PER_LAYER)
494+ if (iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER) {
495+ WelsLog (*ppCtx, WELS_LOG_ERROR,
496+ "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!\n",
497+ (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0);
498+ return 1;
499+ }
500+#endif//!MT_ENABLED) || !PACKING_ONE_SLICE_PER_LAYER
501+
502+ iCountNumLayers ++;
503+
504+ ++ iDIndex;
505+ } while (iDIndex < iNumDependencyLayers);
506+
507+ iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
508+ iCountNumLayers; // plus iCountNumLayers for reserved application
509+#if defined(MT_ENABLED) && defined(PACKING_ONE_SLICE_PER_LAYER)
510+ iNumLayersPack += 1 + iNumDependencyLayers + (iCountNumLayers << 1);
511+#endif//MT_ENABLED && PACKING_ONE_SLICE_PER_LAYER
512+
513+ // to check number of layers / nals / slices dependencies, 12/8/2010
514+#if !defined(MT_ENABLED)
515+ if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
516+ WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
517+ iCountNumLayers, MAX_LAYER_NUM_OF_FRAME);
518+ return 1;
519+ }
520+#else//MT_ENABLED
521+#if defined(PACKING_ONE_SLICE_PER_LAYER)
522+ if (iNumLayersPack > MAX_LAYER_NUM_OF_FRAME) {
523+ WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), num_layers_pack_overall(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
524+ iNumLayersPack, MAX_LAYER_NUM_OF_FRAME);
525+ return 1;
526+ }
527+#else//!PACKING_ONE_SLICE_PER_LAYER
528+ if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
529+ WelsLog (*ppCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
530+ iCountNumLayers, MAX_LAYER_NUM_OF_FRAME);
531+ return 1;
532+ }
533+#endif//PACKING_ONE_SLICE_PER_LAYER
534+#endif//!MT_ENABLED
535+
536+ if (NULL != pCountLayers)
537+ *pCountLayers = iCountNumLayers;
538+ if (NULL != pCountNals)
539+ *pCountNals = iCountNumNals;
540+ return 0;
541+}
542+
543+/*!
544+ * \brief alloc spatial layers pictures (I420 based source pictures)
545+ */
546+int32_t AllocSpatialPictures (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam) {
547+ CMemoryAlign* pMa = (*ppCtx)->pMemAlign;
548+ const int32_t kiDlayerCount = pParam->iNumDependencyLayer;
549+ int32_t iDlayerIndex = 0;
550+
551+ // spatial pictures
552+ iDlayerIndex = 0;
553+ do {
554+ const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth;
555+ const int32_t kiPicHeight = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight;
556+ const uint8_t kuiLayerInTemporal = 2 + WELS_MAX (pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1);
557+ const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum;
558+ uint8_t i = 0;
559+
560+ do {
561+ SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false);
562+ WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pPic), FreeMemorySvc (ppCtx); *ppCtx = NULL)
563+ (*ppCtx)->pSpatialPic[iDlayerIndex][i] = pPic;
564+ ++ i;
565+ } while (i < kuiRefNumInTemporal);
566+
567+ (*ppCtx)->uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal;
568+ (*ppCtx)->uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal;
569+ ++ iDlayerIndex;
570+ } while (iDlayerIndex < kiDlayerCount);
571+
572+ return 0;
573+}
574+
575+void FreeSpatialPictures (sWelsEncCtx* pCtx) {
576+ CMemoryAlign* pMa = pCtx->pMemAlign;
577+ int32_t j = 0;
578+ while (j < pCtx->pSvcParam->iNumDependencyLayer) {
579+ uint8_t i = 0;
580+ uint8_t uiRefNumInTemporal = pCtx->uiSpatialPicNum[j];
581+
582+ while (i < uiRefNumInTemporal) {
583+ if (NULL != pCtx->pSpatialPic[j][i]) {
584+ FreePicture (pMa, &pCtx->pSpatialPic[j][i]);
585+ }
586+ ++ i;
587+ }
588+ pCtx->uiSpatialLayersInTemporal[j] = 0;
589+ ++ j;
590+ }
591+
592+}
593+
594+static void InitMbInfo (sWelsEncCtx* pEnc, SMB* pList, SDqLayer* pLayer, const int32_t kiDlayerId,
595+ const int32_t kiMaxMbNum) {
596+ int32_t iMbWidth = pLayer->iMbWidth;
597+ int32_t iMbHeight = pLayer->iMbHeight;
598+ int32_t iIdx;
599+ int32_t iMbNum = iMbWidth * iMbHeight;
600+ SSliceCtx* pSliceCtx = pLayer->pSliceEncCtx;
601+ uint32_t uiNeighborAvail;
602+ const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum;
603+ SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY (*)[MB_BLOCK4x4_NUM]) (
604+ &pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM * kiOffset]);
605+ int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t (*)[MB_BLOCK8x8_NUM]) (
606+ &pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM * kiOffset]);
607+
608+ for (iIdx = 0; iIdx < iMbNum; iIdx++) {
609+ BOOL_T bLeft;
610+ BOOL_T bTop;
611+ BOOL_T bLeftTop;
612+ BOOL_T bRightTop;
613+ int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
614+ uint8_t uiSliceIdc;
615+
616+ pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx];
617+ pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx];
618+ pList[iIdx].iMbXY = iIdx;
619+
620+ uiSliceIdc = WelsMbToSliceIdc (pSliceCtx, iIdx);
621+ iLeftXY = iIdx - 1;
622+ iTopXY = iIdx - iMbWidth;
623+ iLeftTopXY = iTopXY - 1;
624+ iRightTopXY = iTopXY + 1;
625+
626+ bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pSliceCtx, iLeftXY));
627+ bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pSliceCtx, iTopXY));
628+ bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc ==
629+ WelsMbToSliceIdc (pSliceCtx, iLeftTopXY));
630+ bRightTop = (pList[iIdx].iMbX < (iMbWidth - 1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc ==
631+ WelsMbToSliceIdc (pSliceCtx, iRightTopXY));
632+
633+ uiNeighborAvail = 0;
634+ if (bLeft) {
635+ uiNeighborAvail |= LEFT_MB_POS;
636+ }
637+ if (bTop) {
638+ uiNeighborAvail |= TOP_MB_POS;
639+ }
640+ if (bLeftTop) {
641+ uiNeighborAvail |= TOPLEFT_MB_POS;
642+ }
643+ if (bRightTop) {
644+ uiNeighborAvail |= TOPRIGHT_MB_POS;
645+ }
646+ pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding
647+ pList[iIdx].uiNeighborAvail = uiNeighborAvail;
648+ uiNeighborAvail = 0;
649+ if (pList[iIdx].iMbX >= BASE_MV_MB_NMB)
650+ uiNeighborAvail |= LEFT_MB_POS;
651+ if (pList[iIdx].iMbX <= (iMbWidth - 1 - BASE_MV_MB_NMB))
652+ uiNeighborAvail |= RIGHT_MB_POS;
653+ if (pList[iIdx].iMbY >= BASE_MV_MB_NMB)
654+ uiNeighborAvail |= TOP_MB_POS;
655+ if (pList[iIdx].iMbY <= (iMbHeight - 1 - BASE_MV_MB_NMB))
656+ uiNeighborAvail |= BOTTOM_MB_POS;
657+
658+ pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx];
659+ pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx];
660+ pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx];
661+ pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx * INTRA_4x4_MODE_NUM];
662+ pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx * MB_LUMA_CHROMA_BLOCK4x4_NUM];
663+ }
664+}
665+
666+
667+int32_t InitMbListD (sWelsEncCtx** ppCtx) {
668+ int32_t iNumDlayer = (*ppCtx)->pSvcParam->iNumDependencyLayer;
669+ int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 };
670+ int32_t iOverallMbNum = 0;
671+ int32_t iMbWidth = 0;
672+ int32_t iMbHeight = 0;
673+ int32_t i;
674+
675+ if (iNumDlayer > MAX_DEPENDENCY_LAYER)
676+ return 1;
677+
678+ for (i = 0; i < iNumDlayer; i++) {
679+ iMbWidth = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameWidth + 15) >> 4;
680+ iMbHeight = ((*ppCtx)->pSvcParam->sDependencyLayers[i].iFrameHeight + 15) >> 4;
681+ iMbSize[i] = iMbWidth * iMbHeight;
682+ iOverallMbNum += iMbSize[i];
683+ }
684+
685+ (*ppCtx)->ppMbListD = static_cast<SMB**> ((*ppCtx)->pMemAlign->WelsMalloc (iNumDlayer * sizeof (SMB*), "ppMbListD"));
686+ (*ppCtx)->ppMbListD[0] = NULL;
687+ WELS_VERIFY_RETURN_PROC_IF (1, (*ppCtx)->ppMbListD == NULL, FreeMemorySvc (ppCtx));
688+ (*ppCtx)->ppMbListD[0] = static_cast<SMB*> ((*ppCtx)->pMemAlign->WelsMallocz (iOverallMbNum * sizeof (SMB),
689+ "ppMbListD[0]"));
690+ WELS_VERIFY_RETURN_PROC_IF (1, (*ppCtx)->ppMbListD[0] == NULL, FreeMemorySvc (ppCtx));
691+ (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0];
692+ InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer - 1]);
693+ for (i = 1; i < iNumDlayer; i++) {
694+ (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i - 1] + iMbSize[i - 1];
695+ (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i];
696+ InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer - 1]);
697+ }
698+
699+ return 0;
700+}
701+
702+int32_t AllocMbCacheAligned (SMbCache* pMbCache, CMemoryAlign* pMa) {
703+ pMbCache->pCoeffLevel = (int16_t*)pMa->WelsMalloc (MB_COEFF_LIST_SIZE * sizeof (int16_t), "pMbCache->pCoeffLevel");
704+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pCoeffLevel));
705+ pMbCache->pMemPredMb = (uint8_t*)pMa->WelsMalloc (2 * 256 * sizeof (uint8_t), "pMbCache->pMemPredMb");
706+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredMb));
707+ pMbCache->pSkipMb = (uint8_t*)pMa->WelsMalloc (384 * sizeof (uint8_t), "pMbCache->pSkipMb");
708+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pSkipMb));
709+ pMbCache->pMemPredBlk4 = (uint8_t*)pMa->WelsMalloc (2 * 16 * sizeof (uint8_t), "pMbCache->pMemPredBlk4");
710+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pMemPredBlk4));
711+ pMbCache->pBufferInterPredMe = (uint8_t*)pMa->WelsMalloc (4 * 640 * sizeof (uint8_t), "pMbCache->pBufferInterPredMe");
712+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pBufferInterPredMe));
713+ pMbCache->pPrevIntra4x4PredModeFlag = (bool_t*)pMa->WelsMalloc (16 * sizeof (bool_t),
714+ "pMbCache->pPrevIntra4x4PredModeFlag");
715+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pPrevIntra4x4PredModeFlag));
716+ pMbCache->pRemIntra4x4PredModeFlag = (int8_t*)pMa->WelsMalloc (16 * sizeof (int8_t),
717+ "pMbCache->pRemIntra4x4PredModeFlag");
718+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pRemIntra4x4PredModeFlag));
719+ pMbCache->pDct = (SDCTCoeff*)pMa->WelsMalloc (sizeof (SDCTCoeff), "pMbCache->pDct");
720+ WELS_VERIFY_RETURN_IF (1, (NULL == pMbCache->pDct));
721+ return 0;
722+}
723+
724+void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) {
725+ if (NULL != pMbCache->pCoeffLevel) {
726+ pMa->WelsFree (pMbCache->pCoeffLevel, "pMbCache->pCoeffLevel");
727+ pMbCache->pCoeffLevel = NULL;
728+ }
729+ if (NULL != pMbCache->pMemPredMb) {
730+ pMa->WelsFree (pMbCache->pMemPredMb, "pMbCache->pMemPredMb");
731+ pMbCache->pMemPredMb = NULL;
732+ }
733+ if (NULL != pMbCache->pSkipMb) {
734+ pMa->WelsFree (pMbCache->pSkipMb, "pMbCache->pSkipMb");
735+ pMbCache->pSkipMb = NULL;
736+ }
737+ if (NULL != pMbCache->pMemPredBlk4) {
738+ pMa->WelsFree (pMbCache->pMemPredBlk4, "pMbCache->pMemPredBlk4");
739+ pMbCache->pMemPredBlk4 = NULL;
740+ }
741+ if (NULL != pMbCache->pBufferInterPredMe) {
742+ pMa->WelsFree (pMbCache->pBufferInterPredMe, "pMbCache->pBufferInterPredMe");
743+ pMbCache->pBufferInterPredMe = NULL;
744+ }
745+ if (NULL != pMbCache->pPrevIntra4x4PredModeFlag) {
746+ pMa->WelsFree (pMbCache->pPrevIntra4x4PredModeFlag, "pMbCache->pPrevIntra4x4PredModeFlag");
747+ pMbCache->pPrevIntra4x4PredModeFlag = NULL;
748+ }
749+ if (NULL != pMbCache->pRemIntra4x4PredModeFlag) {

3283 more lines aren’t shown here.

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