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
41 #include "encoder.h"
42 #include "cpu.h"
43 #include "utils.h"
44 #include "svc_enc_golomb.h"
45 #include "au_set.h"
46 #include "picture_handle.h"
47 #include "svc_base_layer_md.h"
48 #include "svc_encode_slice.h"
49 #include "svc_mode_decision.h"
50 #include "decode_mb_aux.h"
51 #include "deblocking.h"
52 #include "ref_list_mgr_svc.h"
53 #include "ls_defines.h"
54 #include "crt_util_safe_x.h" // Safe CRT routines like utils for cross platforms
55 #include "slice_multi_threading.h"
56 #include "measure_time.h"
57 #include "svc_set_mb_syn.h"
58
59 namespace WelsEnc {
60
61
62 int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
63 SFrameBSInfo* pFrameBsInfo,
64 SLayerBSInfo* pLayerBsInfo,
65 int32_t* pNalIdxInLayer,
66 int32_t* pLayerSize,
67 int32_t iFirstMbIdxInPartition,
68 int32_t iEndMbIdxInPartition,
69 int32_t iStartSliceIdx
70 );
71
72
WelsBitRateVerification(SLogContext * pLogCtx,SSpatialLayerConfig * pLayerParam,int32_t iLayerId)73 int32_t WelsBitRateVerification (SLogContext* pLogCtx, SSpatialLayerConfig* pLayerParam, int32_t iLayerId) {
74 if ((pLayerParam->iSpatialBitrate <= 0)
75 || (static_cast<float> (pLayerParam->iSpatialBitrate) < pLayerParam->fFrameRate)) {
76 WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid bitrate settings in layer %d, bitrate= %d at FrameRate(%f)", iLayerId,
77 pLayerParam->iSpatialBitrate, pLayerParam->fFrameRate);
78 return ENC_RETURN_UNSUPPORTED_PARA;
79 }
80
81 // deal with LEVEL_MAX_BR and MAX_BR setting
82 const SLevelLimits* pCurLevelLimit = g_ksLevelLimits;
83 while ((pCurLevelLimit->uiLevelIdc != LEVEL_5_2) && (pCurLevelLimit->uiLevelIdc != pLayerParam->uiLevelIdc))
84 pCurLevelLimit++;
85 const int32_t iLevelMaxBitrate = pCurLevelLimit->uiMaxBR * CpbBrNalFactor;
86 const int32_t iLevel52MaxBitrate = g_ksLevelLimits[LEVEL_NUMBER - 1].uiMaxBR * CpbBrNalFactor;
87 if (UNSPECIFIED_BIT_RATE != iLevelMaxBitrate) {
88 if ((pLayerParam->iMaxSpatialBitrate == UNSPECIFIED_BIT_RATE)
89 || (pLayerParam->iMaxSpatialBitrate > iLevel52MaxBitrate)) {
90 pLayerParam->iMaxSpatialBitrate = iLevelMaxBitrate;
91 WelsLog (pLogCtx, WELS_LOG_INFO,
92 "Current MaxSpatialBitrate is invalid (UNSPECIFIED_BIT_RATE or larger than LEVEL5_2) but level setting is valid, set iMaxSpatialBitrate to %d from level (%d)",
93 pLayerParam->iMaxSpatialBitrate, pLayerParam->uiLevelIdc);
94 } else if (pLayerParam->iMaxSpatialBitrate > iLevelMaxBitrate) {
95 ELevelIdc iCurLevel = pLayerParam->uiLevelIdc;
96 WelsAdjustLevel (pLayerParam, pCurLevelLimit);
97 WelsLog (pLogCtx, WELS_LOG_INFO,
98 "LevelIdc is changed from (%d) to (%d) according to the iMaxSpatialBitrate(%d)",
99 iCurLevel, pLayerParam->uiLevelIdc, pLayerParam->iMaxSpatialBitrate);
100 }
101 } else if ((pLayerParam->iMaxSpatialBitrate != UNSPECIFIED_BIT_RATE)
102 && (pLayerParam->iMaxSpatialBitrate > iLevel52MaxBitrate)) {
103 // no level limitation, just need to check if iMaxSpatialBitrate is too big from reasonable
104 WelsLog (pLogCtx, WELS_LOG_WARNING,
105 "No LevelIdc setting and iMaxSpatialBitrate (%d) is considered too big to be valid, changed to UNSPECIFIED_BIT_RATE",
106 pLayerParam->iMaxSpatialBitrate);
107 pLayerParam->iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
108 }
109
110 // deal with iSpatialBitrate and iMaxSpatialBitrate setting
111 if (pLayerParam->iMaxSpatialBitrate != UNSPECIFIED_BIT_RATE) {
112 if (pLayerParam->iMaxSpatialBitrate == pLayerParam->iSpatialBitrate) {
113 WelsLog (pLogCtx, WELS_LOG_INFO,
114 "Setting MaxSpatialBitrate (%d) the same at SpatialBitrate (%d) will make the actual bit rate lower than SpatialBitrate",
115 pLayerParam->iMaxSpatialBitrate, pLayerParam->iSpatialBitrate);
116 } else if (pLayerParam->iMaxSpatialBitrate < pLayerParam->iSpatialBitrate) {
117 WelsLog (pLogCtx, WELS_LOG_ERROR,
118 "MaxSpatialBitrate (%d) should be larger than SpatialBitrate (%d), considering it as error setting",
119 pLayerParam->iMaxSpatialBitrate, pLayerParam->iSpatialBitrate);
120 return ENC_RETURN_UNSUPPORTED_PARA;
121 }
122 }
123 return ENC_RETURN_SUCCESS;
124 }
125
CheckProfileSetting(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam,int32_t iLayer,EProfileIdc uiProfileIdc)126 void CheckProfileSetting (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer, EProfileIdc uiProfileIdc) {
127 SSpatialLayerConfig* pLayerInfo = &pParam->sSpatialLayers[iLayer];
128 pLayerInfo->uiProfileIdc = uiProfileIdc;
129 if (pParam->bSimulcastAVC) {
130 if ((uiProfileIdc != PRO_BASELINE) && (uiProfileIdc != PRO_MAIN) && (uiProfileIdc != PRO_HIGH)) {
131 WelsLog (pLogCtx, WELS_LOG_WARNING, "layerId(%d) doesn't support profile(%d), change to UNSPECIFIC profile", iLayer,
132 uiProfileIdc);
133 pLayerInfo->uiProfileIdc = PRO_UNKNOWN;
134 }
135 } else {
136 if (iLayer == SPATIAL_LAYER_0) {
137 if ((uiProfileIdc != PRO_BASELINE) && (uiProfileIdc != PRO_MAIN) && (uiProfileIdc != PRO_HIGH)) {
138 WelsLog (pLogCtx, WELS_LOG_WARNING, "layerId(%d) doesn't support profile(%d), change to UNSPECIFIC profile", iLayer,
139 uiProfileIdc);
140 pLayerInfo->uiProfileIdc = PRO_UNKNOWN;
141 }
142 } else {
143 if ((uiProfileIdc != PRO_SCALABLE_BASELINE) && (uiProfileIdc != PRO_SCALABLE_HIGH)) {
144 pLayerInfo->uiProfileIdc = PRO_SCALABLE_BASELINE;
145 WelsLog (pLogCtx, WELS_LOG_WARNING, "layerId(%d) doesn't support profile(%d), change to scalable baseline profile",
146 iLayer, uiProfileIdc);
147 }
148 }
149 }
150 }
CheckLevelSetting(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam,int32_t iLayer,ELevelIdc uiLevelIdc)151 void CheckLevelSetting (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer, ELevelIdc uiLevelIdc) {
152 SSpatialLayerConfig* pLayerInfo = &pParam->sSpatialLayers[iLayer];
153 pLayerInfo->uiLevelIdc = LEVEL_UNKNOWN;
154 int32_t iLevelIdx = LEVEL_NUMBER - 1;
155 do {
156 if (g_ksLevelLimits[iLevelIdx].uiLevelIdc == uiLevelIdc) {
157 pLayerInfo->uiLevelIdc = uiLevelIdc;
158 break;
159 }
160 iLevelIdx--;
161 } while (iLevelIdx >= 0);
162 }
CheckReferenceNumSetting(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam,int32_t iNumRef)163 void CheckReferenceNumSetting (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iNumRef) {
164 int32_t iRefUpperBound = (pParam->iUsageType == CAMERA_VIDEO_REAL_TIME) ?
165 MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA : MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN;
166 pParam->iNumRefFrame = iNumRef;
167 if ((iNumRef < MIN_REF_PIC_COUNT) || (iNumRef > iRefUpperBound)) {
168 pParam->iNumRefFrame = AUTO_REF_PIC_COUNT;
169 WelsLog (pLogCtx, WELS_LOG_WARNING,
170 "doesn't support the number of reference frame(%d) change to auto select mode", iNumRef);
171 }
172 }
173
SliceArgumentValidationFixedSliceMode(SLogContext * pLogCtx,SSliceArgument * pSliceArgument,const RC_MODES kiRCMode,const int32_t kiPicWidth,const int32_t kiPicHeight)174 int32_t SliceArgumentValidationFixedSliceMode (SLogContext* pLogCtx,
175 SSliceArgument* pSliceArgument, const RC_MODES kiRCMode,
176 const int32_t kiPicWidth, const int32_t kiPicHeight) {
177 int32_t iCpuCores = 0;
178 int32_t iIdx = 0;
179 const int32_t iMbWidth = (kiPicWidth + 15) >> 4;
180 const int32_t iMbHeight = (kiPicHeight + 15) >> 4;
181 const int32_t iMbNumInFrame = iMbWidth * iMbHeight;
182 bool bSingleMode = false;
183
184 pSliceArgument->uiSliceSizeConstraint = 0;
185
186 if (pSliceArgument->uiSliceNum == 0) {
187 WelsCPUFeatureDetect (&iCpuCores);
188 if (0 == iCpuCores) {
189 // cpuid not supported or doesn't expose the number of cores,
190 // use high level system API as followed to detect number of pysical/logic processor
191 iCpuCores = DynamicDetectCpuCores();
192 }
193 pSliceArgument->uiSliceNum = iCpuCores;
194 }
195
196 if (pSliceArgument->uiSliceNum <= 1) {
197 WelsLog (pLogCtx, WELS_LOG_INFO,
198 "SliceArgumentValidationFixedSliceMode(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type!",
199 pSliceArgument->uiSliceNum);
200 bSingleMode = true;
201 }
202
203 // considering the coding efficient and performance,
204 // iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
205 if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) {
206 WelsLog (pLogCtx, WELS_LOG_INFO,
207 "SliceArgumentValidationFixedSliceMode(), uiSliceNum(%d) you set for SM_FIXEDSLCNUM_SLICE, now turn to SM_SINGLE_SLICE type as CountMbNum less than MIN_NUM_MB_PER_SLICE!",
208 pSliceArgument->uiSliceNum);
209 bSingleMode = true;
210 }
211
212 if (bSingleMode) {
213 pSliceArgument->uiSliceMode = SM_SINGLE_SLICE;
214 pSliceArgument->uiSliceNum = 1;
215 for (iIdx = 0; iIdx < MAX_SLICES_NUM; iIdx++) {
216 pSliceArgument->uiSliceMbNum[iIdx] = 0;
217 }
218 return ENC_RETURN_SUCCESS;
219 }
220
221 if (pSliceArgument->uiSliceNum > MAX_SLICES_NUM) {
222 pSliceArgument->uiSliceNum = MAX_SLICES_NUM;
223 WelsLog (pLogCtx, WELS_LOG_WARNING,
224 "SliceArgumentValidationFixedSliceMode(), uiSliceNum exceed MAX_SLICES_NUM! So setting slice num eqaul to MAX_SLICES_NUM(%d)!",
225 pSliceArgument->uiSliceNum);
226 }
227
228 if (kiRCMode != RC_OFF_MODE) { // multiple slices verify with gom
229 //check uiSliceNum and set uiSliceMbNum with current uiSliceNum
230 if (!GomValidCheckSliceNum (iMbWidth, iMbHeight, &pSliceArgument->uiSliceNum)) {
231 WelsLog (pLogCtx, WELS_LOG_WARNING,
232 "SliceArgumentValidationFixedSliceMode(), unsupported setting with Resolution and uiSliceNum combination under RC on! So uiSliceNum is changed to %d!",
233 pSliceArgument->uiSliceNum);
234 }
235
236 if (pSliceArgument->uiSliceNum <= 1 ||
237 !GomValidCheckSliceMbNum (iMbWidth, iMbHeight, pSliceArgument)) {
238 WelsLog (pLogCtx, WELS_LOG_ERROR,
239 "SliceArgumentValidationFixedSliceMode(), unsupported setting with Resolution and uiSliceNum (%d) combination under RC on! Consider setting single slice with this resolution!",
240 pSliceArgument->uiSliceNum);
241 return ENC_RETURN_UNSUPPORTED_PARA;
242 }
243 } else if (!CheckFixedSliceNumMultiSliceSetting (iMbNumInFrame, pSliceArgument)) {
244 //check uiSliceMbNum with current uiSliceNum
245 WelsLog (pLogCtx, WELS_LOG_ERROR,
246 "SliceArgumentValidationFixedSliceMode(), invalid uiSliceMbNum (%d) settings!,now turn to SM_SINGLE_SLICE type",
247 pSliceArgument->uiSliceMbNum[0]);
248 pSliceArgument->uiSliceMode = SM_SINGLE_SLICE;
249 pSliceArgument->uiSliceNum = 1;
250 for (iIdx = 0; iIdx < MAX_SLICES_NUM; iIdx++) {
251 pSliceArgument->uiSliceMbNum[iIdx] = 0;
252 }
253 }
254
255 return ENC_RETURN_SUCCESS;
256 }
257
258
259 /*!
260 * \brief validate checking in parameter configuration
261 * \pParam pParam SWelsSvcCodingParam*
262 * \return successful - 0; otherwise none 0 for failed
263 */
ParamValidation(SLogContext * pLogCtx,SWelsSvcCodingParam * pCfg)264 int32_t ParamValidation (SLogContext* pLogCtx, SWelsSvcCodingParam* pCfg) {
265 const float fEpsn = 0.000001f;
266 int32_t i = 0;
267
268 assert (pCfg != NULL);
269
270 if (! (pCfg->iUsageType < INPUT_CONTENT_TYPE_ALL)) {
271 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidation(),Invalid usage type = %d", pCfg->iUsageType);
272 return ENC_RETURN_UNSUPPORTED_PARA;
273 }
274 if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) {
275 if (pCfg->iSpatialLayerNum > 1) {
276 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidation(),Invalid the number of Spatial layer(%d)for screen content",
277 pCfg->iSpatialLayerNum);
278 return ENC_RETURN_UNSUPPORTED_PARA;
279 }
280 if (pCfg->bEnableAdaptiveQuant) {
281 WelsLog (pLogCtx, WELS_LOG_WARNING,
282 "ParamValidation(), AdaptiveQuant(%d) is not supported yet for screen content, auto turned off",
283 pCfg->bEnableAdaptiveQuant);
284 pCfg->bEnableAdaptiveQuant = false;
285 }
286 if (pCfg->bEnableBackgroundDetection) {
287 WelsLog (pLogCtx, WELS_LOG_WARNING,
288 "ParamValidation(), BackgroundDetection(%d) is not supported yet for screen content, auto turned off",
289 pCfg->bEnableBackgroundDetection);
290 pCfg->bEnableBackgroundDetection = false;
291 }
292 if (pCfg->bEnableSceneChangeDetect == false) {
293 pCfg->bEnableSceneChangeDetect = true;
294 WelsLog (pLogCtx, WELS_LOG_WARNING,
295 "ParamValidation(), screen change detection should be turned on, change bEnableSceneChangeDetect as true");
296 }
297
298 }
299
300 //turn off adaptive quant now, algorithms needs to be refactored
301 pCfg->bEnableAdaptiveQuant = false;
302
303 if (pCfg->iSpatialLayerNum > 1) {
304 for (i = pCfg->iSpatialLayerNum - 1; i > 0; i--) {
305 SSpatialLayerConfig* fDlpUp = &pCfg->sSpatialLayers[i];
306 SSpatialLayerConfig* fDlp = &pCfg->sSpatialLayers[i - 1];
307 if ((fDlp->iVideoWidth > fDlpUp->iVideoWidth) || (fDlp->iVideoHeight > fDlpUp->iVideoHeight)) {
308 WelsLog (pLogCtx, WELS_LOG_ERROR,
309 "ParamValidation,Invalid resolution layer(%d) resolution(%d x %d) should be less than the upper spatial layer resolution(%d x %d) ",
310 i, fDlp->iVideoWidth, fDlp->iVideoHeight, fDlpUp->iVideoWidth, fDlpUp->iVideoHeight);
311 return ENC_RETURN_UNSUPPORTED_PARA;
312 }
313 }
314 }
315
316 if (!CheckInRangeCloseOpen (pCfg->iLoopFilterDisableIdc, DEBLOCKING_IDC_0, DEBLOCKING_IDC_2 + 1) ||
317 !CheckInRangeCloseOpen (pCfg->iLoopFilterAlphaC0Offset, DEBLOCKING_OFFSET_MINUS, DEBLOCKING_OFFSET + 1) ||
318 !CheckInRangeCloseOpen (pCfg->iLoopFilterBetaOffset, DEBLOCKING_OFFSET_MINUS, DEBLOCKING_OFFSET + 1)) {
319 WelsLog (pLogCtx, WELS_LOG_ERROR,
320 "ParamValidation, Invalid iLoopFilterDisableIdc(%d) or iLoopFilterAlphaC0Offset(%d) or iLoopFilterBetaOffset(%d)!",
321 pCfg->iLoopFilterDisableIdc, pCfg->iLoopFilterAlphaC0Offset, pCfg->iLoopFilterBetaOffset);
322 return ENC_RETURN_UNSUPPORTED_PARA;
323 }
324
325 for (i = 0; i < pCfg->iSpatialLayerNum; ++ i) {
326 SSpatialLayerInternal* fDlp = &pCfg->sDependencyLayers[i];
327 SSpatialLayerConfig* pConfig = &pCfg->sSpatialLayers[i];
328 if (fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn
329 && fDlp->fInputFrameRate <= fEpsn)
330 || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn)) {
331 WelsLog (pLogCtx, WELS_LOG_ERROR,
332 "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..",
333 fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
334 return ENC_RETURN_INVALIDINPUT;
335 }
336 if (UINT_MAX == GetLogFactor (fDlp->fOutputFrameRate, fDlp->fInputFrameRate)) {
337 WelsLog (pLogCtx, WELS_LOG_WARNING,
338 "AUTO CORRECT: 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 Auto correcting Output Framerate to Input Framerate %f!\n",
339 fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i, fDlp->fInputFrameRate);
340 fDlp->fOutputFrameRate = fDlp->fInputFrameRate;
341 pConfig->fFrameRate = fDlp->fOutputFrameRate;
342 }
343 }
344
345 if ((pCfg->iRCMode != RC_OFF_MODE) && (pCfg->iRCMode != RC_QUALITY_MODE) && (pCfg->iRCMode != RC_BUFFERBASED_MODE)
346 && (pCfg->iRCMode != RC_BITRATE_MODE) && (pCfg->iRCMode != RC_TIMESTAMP_MODE)) {
347 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidation(),Invalid iRCMode = %d", pCfg->iRCMode);
348 return ENC_RETURN_UNSUPPORTED_PARA;
349 }
350 //bitrate setting validation
351 if (pCfg->iRCMode != RC_OFF_MODE) {
352 int32_t iTotalBitrate = 0;
353 if (pCfg->iTargetBitrate <= 0) {
354 WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid bitrate settings in total configure, bitrate= %d", pCfg->iTargetBitrate);
355 return ENC_RETURN_INVALIDINPUT;
356 }
357 for (i = 0; i < pCfg->iSpatialLayerNum; ++ i) {
358 SSpatialLayerConfig* pSpatialLayer = &pCfg->sSpatialLayers[i];
359 iTotalBitrate += pSpatialLayer->iSpatialBitrate;
360
361 if (WelsBitRateVerification (pLogCtx, pSpatialLayer, i) != ENC_RETURN_SUCCESS)
362 return ENC_RETURN_INVALIDINPUT;
363 }
364 if (iTotalBitrate > pCfg->iTargetBitrate) {
365 WelsLog (pLogCtx, WELS_LOG_ERROR,
366 "Invalid settings in bitrate. the sum of each layer bitrate(%d) is larger than total bitrate setting(%d)",
367 iTotalBitrate, pCfg->iTargetBitrate);
368 return ENC_RETURN_INVALIDINPUT;
369 }
370 if ((pCfg->iRCMode == RC_QUALITY_MODE) || (pCfg->iRCMode == RC_BITRATE_MODE) || (pCfg->iRCMode == RC_TIMESTAMP_MODE))
371 if (!pCfg->bEnableFrameSkip)
372 WelsLog (pLogCtx, WELS_LOG_WARNING,
373 "bEnableFrameSkip = %d,bitrate can't be controlled for RC_QUALITY_MODE,RC_BITRATE_MODE and RC_TIMESTAMP_MODE without enabling skip frame.",
374 pCfg->bEnableFrameSkip);
375 if ((pCfg->iMaxQp <= 0) || (pCfg->iMinQp <= 0)) {
376 if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) {
377 WelsLog (pLogCtx, WELS_LOG_INFO, "Change QP Range from(%d,%d) to (%d,%d)", pCfg->iMinQp, pCfg->iMaxQp, MIN_SCREEN_QP,
378 MAX_SCREEN_QP);
379 pCfg->iMinQp = MIN_SCREEN_QP;
380 pCfg->iMaxQp = MAX_SCREEN_QP;
381 } else {
382 WelsLog (pLogCtx, WELS_LOG_INFO, "Change QP Range from(%d,%d) to (%d,%d)", pCfg->iMinQp, pCfg->iMaxQp,
383 GOM_MIN_QP_MODE, MAX_LOW_BR_QP);
384 pCfg->iMinQp = GOM_MIN_QP_MODE;
385 pCfg->iMaxQp = MAX_LOW_BR_QP;
386 }
387
388 }
389 pCfg->iMinQp = WELS_CLIP3 (pCfg->iMinQp, GOM_MIN_QP_MODE, QP_MAX_VALUE);
390 pCfg->iMaxQp = WELS_CLIP3 (pCfg->iMaxQp, pCfg->iMinQp, QP_MAX_VALUE);
391 }
392 // ref-frames validation
393 if (((pCfg->iUsageType == CAMERA_VIDEO_REAL_TIME) || (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME))
394 ? WelsCheckRefFrameLimitationNumRefFirst (pLogCtx, pCfg)
395 : WelsCheckRefFrameLimitationLevelIdcFirst (pLogCtx, pCfg)) {
396 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsCheckRefFrameLimitation failed");
397 return ENC_RETURN_INVALIDINPUT;
398 }
399 return ENC_RETURN_SUCCESS;
400 }
401
402
ParamValidationExt(SLogContext * pLogCtx,SWelsSvcCodingParam * pCodingParam)403 int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingParam) {
404 int8_t i = 0;
405 int32_t iIdx = 0;
406
407 assert (pCodingParam != NULL);
408 if (NULL == pCodingParam)
409 return ENC_RETURN_INVALIDINPUT;
410
411 if ((pCodingParam->iUsageType != CAMERA_VIDEO_REAL_TIME) && (pCodingParam->iUsageType != SCREEN_CONTENT_REAL_TIME)) {
412 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(),Invalid usage type = %d", pCodingParam->iUsageType);
413 return ENC_RETURN_UNSUPPORTED_PARA;
414 }
415 if ((pCodingParam->iUsageType == SCREEN_CONTENT_REAL_TIME) && (!pCodingParam->bIsLosslessLink
416 && pCodingParam->bEnableLongTermReference)) {
417 WelsLog (pLogCtx, WELS_LOG_WARNING,
418 "ParamValidationExt(), setting lossy link for LTR under screen, which is not supported yet! Auto disabled LTR!");
419 pCodingParam->bEnableLongTermReference = false;
420 }
421 if (pCodingParam->iSpatialLayerNum < 1 || pCodingParam->iSpatialLayerNum > MAX_DEPENDENCY_LAYER) {
422 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), monitor invalid pCodingParam->iSpatialLayerNum: %d!",
423 pCodingParam->iSpatialLayerNum);
424 return ENC_RETURN_UNSUPPORTED_PARA;
425 }
426
427 if (pCodingParam->iTemporalLayerNum < 1 || pCodingParam->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) {
428 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), monitor invalid pCodingParam->iTemporalLayerNum: %d!",
429 pCodingParam->iTemporalLayerNum);
430 return ENC_RETURN_UNSUPPORTED_PARA;
431 }
432
433 if (pCodingParam->uiGopSize < 1 || pCodingParam->uiGopSize > MAX_GOP_SIZE) {
434 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), monitor invalid pCodingParam->uiGopSize: %d!",
435 pCodingParam->uiGopSize);
436 return ENC_RETURN_UNSUPPORTED_PARA;
437 }
438
439
440 if (pCodingParam->uiIntraPeriod && pCodingParam->uiIntraPeriod < pCodingParam->uiGopSize) {
441 WelsLog (pLogCtx, WELS_LOG_ERROR,
442 "ParamValidationExt(), uiIntraPeriod(%d) should be not less than that of uiGopSize(%d) or -1 specified!",
443 pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
444 return ENC_RETURN_UNSUPPORTED_PARA;
445 }
446
447 if (pCodingParam->uiIntraPeriod && (pCodingParam->uiIntraPeriod & (pCodingParam->uiGopSize - 1)) != 0) {
448 WelsLog (pLogCtx, WELS_LOG_ERROR,
449 "ParamValidationExt(), uiIntraPeriod(%d) should be multiple of uiGopSize(%d) or -1 specified!",
450 pCodingParam->uiIntraPeriod, pCodingParam->uiGopSize);
451 return ENC_RETURN_UNSUPPORTED_PARA;
452 }
453
454 //about iMultipleThreadIdc, bDeblockingParallelFlag, iLoopFilterDisableIdc, & uiSliceMode
455 // (1) Single Thread
456 // if (THREAD==1)//single thread
457 // no parallel_deblocking: bDeblockingParallelFlag = 0;
458 // (2) Multi Thread: see uiSliceMode decision
459 if (pCodingParam->iMultipleThreadIdc == 1) {
460 //now is single thread. no parallel deblocking, set flag=0
461 pCodingParam->bDeblockingParallelFlag = false;
462 } else {
463 pCodingParam->bDeblockingParallelFlag = true;
464 }
465
466 // eSpsPpsIdStrategy checkings
467 if (pCodingParam->iSpatialLayerNum > 1 && (!pCodingParam->bSimulcastAVC)
468 && (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
469 WelsLog (pLogCtx, WELS_LOG_WARNING,
470 "ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple svc SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
471 pCodingParam->eSpsPpsIdStrategy, pCodingParam->iSpatialLayerNum);
472 pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
473 }
474 if (pCodingParam->iUsageType == SCREEN_CONTENT_REAL_TIME && (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
475 WelsLog (pLogCtx, WELS_LOG_WARNING,
476 "ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with iUsageType (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
477 pCodingParam->eSpsPpsIdStrategy, pCodingParam->iUsageType);
478 pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
479 }
480
481 if (pCodingParam->bSimulcastAVC && (SPS_LISTING & pCodingParam->eSpsPpsIdStrategy)) {
482 WelsLog (pLogCtx, WELS_LOG_INFO,
483 "ParamValidationExt(), eSpsPpsIdStrategy(%d) under bSimulcastAVC(%d) not supported yet, adjusted to INCREASING_ID",
484 pCodingParam->eSpsPpsIdStrategy, pCodingParam->bSimulcastAVC);
485 pCodingParam->eSpsPpsIdStrategy = INCREASING_ID;
486 }
487
488 if (pCodingParam->bSimulcastAVC && pCodingParam->bPrefixNalAddingCtrl) {
489 WelsLog (pLogCtx, WELS_LOG_INFO,
490 "ParamValidationExt(), bSimulcastAVC(%d) is not compatible with bPrefixNalAddingCtrl(%d) true, adjusted bPrefixNalAddingCtrl to false",
491 pCodingParam->eSpsPpsIdStrategy, pCodingParam->bSimulcastAVC);
492 pCodingParam->bPrefixNalAddingCtrl = false;
493 }
494
495 for (i = 0; i < pCodingParam->iSpatialLayerNum; ++ i) {
496 SSpatialLayerConfig* pSpatialLayer = &pCodingParam->sSpatialLayers[i];
497 int32_t kiPicWidth = pSpatialLayer->iVideoWidth;
498 int32_t kiPicHeight = pSpatialLayer->iVideoHeight;
499 uint32_t iMbWidth = 0;
500 uint32_t iMbHeight = 0;
501 int32_t iMbNumInFrame = 0;
502 uint32_t iMaxSliceNum = MAX_SLICES_NUM;
503 int32_t iReturn = 0;
504
505 if ((pCodingParam->iPicWidth > 0) && (pCodingParam->iPicHeight > 0)
506 && (kiPicWidth == 0) && (kiPicHeight == 0)
507 && (pCodingParam->iSpatialLayerNum == 1)) {
508 kiPicWidth = pSpatialLayer->iVideoWidth = pCodingParam->iPicWidth;
509 kiPicHeight = pSpatialLayer->iVideoHeight = pCodingParam->iPicHeight;
510 WelsLog (pLogCtx, WELS_LOG_DEBUG,
511 "ParamValidationExt(), layer resolution is not set, set to general resolution %d x %d",
512 pSpatialLayer->iVideoWidth, pSpatialLayer->iVideoHeight);
513 }
514
515 if ((kiPicWidth <= 0) || (kiPicHeight <= 0) || (kiPicWidth * kiPicHeight > (MAX_MBS_PER_FRAME << 8))) {
516 WelsLog (pLogCtx, WELS_LOG_ERROR,
517 "ParamValidationExt(), width > 0, height > 0, width * height <= %d, invalid %d x %d in dependency layer settings!",
518 (MAX_MBS_PER_FRAME << 8), kiPicWidth, kiPicHeight);
519 return ENC_RETURN_UNSUPPORTED_PARA;
520 }
521 if ((kiPicWidth & 0x0F) != 0 || (kiPicHeight & 0x0F) != 0) {
522 WelsLog (pLogCtx, WELS_LOG_ERROR,
523 "ParamValidationExt(), in layer #%d iWidth x iHeight(%d x %d) both should be multiple of 16, can not support with arbitrary size currently!",
524 i, kiPicWidth, kiPicHeight);
525 return ENC_RETURN_UNSUPPORTED_PARA;
526 }
527
528 if (pSpatialLayer->sSliceArgument.uiSliceMode >= SM_RESERVED) {
529 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceMode (%d) settings!",
530 pSpatialLayer->sSliceArgument.uiSliceMode);
531 return ENC_RETURN_UNSUPPORTED_PARA;
532 }
533 if ((pCodingParam->uiMaxNalSize != 0) && (pSpatialLayer->sSliceArgument.uiSliceMode != SM_SIZELIMITED_SLICE)) {
534 WelsLog (pLogCtx, WELS_LOG_WARNING,
535 "ParamValidationExt(), current layer %d uiSliceMode (%d) settings may not fulfill MaxNalSize = %d", i,
536 pSpatialLayer->sSliceArgument.uiSliceMode, pCodingParam->uiMaxNalSize);
537 }
538 CheckProfileSetting (pLogCtx, pCodingParam, i, pSpatialLayer->uiProfileIdc);
539 CheckLevelSetting (pLogCtx, pCodingParam, i, pSpatialLayer->uiLevelIdc);
540 //check pSlice settings under multi-pSlice
541 if (kiPicWidth <= 16 && kiPicHeight <= 16) {
542 //only have one MB, set to single_slice
543 pSpatialLayer->sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
544 }
545 switch (pSpatialLayer->sSliceArgument.uiSliceMode) {
546 case SM_SINGLE_SLICE:
547 pSpatialLayer->sSliceArgument.uiSliceNum = 1;
548 pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = 0;
549 for (iIdx = 0; iIdx < MAX_SLICES_NUM; iIdx++) {
550 pSpatialLayer->sSliceArgument.uiSliceMbNum[iIdx] = 0;
551 }
552 break;
553 case SM_FIXEDSLCNUM_SLICE: {
554 iReturn = SliceArgumentValidationFixedSliceMode (pLogCtx, &pSpatialLayer->sSliceArgument, pCodingParam->iRCMode,
555 kiPicWidth, kiPicHeight);
556 if (iReturn)
557 return ENC_RETURN_UNSUPPORTED_PARA;
558 }
559 break;
560 case SM_RASTER_SLICE: {
561 pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = 0;
562
563 iMbWidth = (kiPicWidth + 15) >> 4;
564 iMbHeight = (kiPicHeight + 15) >> 4;
565 iMbNumInFrame = iMbWidth * iMbHeight;
566 iMaxSliceNum = MAX_SLICES_NUM;
567 if (pSpatialLayer->sSliceArgument.uiSliceMbNum[0] == 0) {
568 if (iMbHeight > iMaxSliceNum) {
569 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceNum (%d) settings more than MAX(%d)!",
570 iMbHeight, MAX_SLICES_NUM);
571 return ENC_RETURN_UNSUPPORTED_PARA;
572 }
573 pSpatialLayer->sSliceArgument.uiSliceNum = iMbHeight;
574 for (uint32_t j = 0; j < iMbHeight; j++) {
575 pSpatialLayer->sSliceArgument.uiSliceMbNum[j] = iMbWidth;
576 }
577 if (!CheckRowMbMultiSliceSetting (iMbWidth,
578 &pSpatialLayer->sSliceArgument)) { // verify interleave mode settings
579 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!",
580 pSpatialLayer->sSliceArgument.uiSliceMbNum[0]);
581 return ENC_RETURN_UNSUPPORTED_PARA;
582 }
583 break;
584 }
585
586 if (!CheckRasterMultiSliceSetting (iMbNumInFrame,
587 &pSpatialLayer->sSliceArgument)) { // verify interleave mode settings
588 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceMbNum (%d) settings!",
589 pSpatialLayer->sSliceArgument.uiSliceMbNum[0]);
590 return ENC_RETURN_UNSUPPORTED_PARA;
591 }
592 if (pSpatialLayer->sSliceArgument.uiSliceNum <= 0
593 || pSpatialLayer->sSliceArgument.uiSliceNum > iMaxSliceNum) { // verify interleave mode settings
594 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceNum (%d) in SM_RASTER_SLICE settings!",
595 pSpatialLayer->sSliceArgument.uiSliceNum);
596 return ENC_RETURN_UNSUPPORTED_PARA;
597 }
598 if (pSpatialLayer->sSliceArgument.uiSliceNum == 1) {
599 WelsLog (pLogCtx, WELS_LOG_WARNING,
600 "ParamValidationExt(), pSlice setting for SM_RASTER_SLICE now turn to SM_SINGLE_SLICE!");
601 pSpatialLayer->sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
602 break;
603 }
604 if ((pCodingParam->iRCMode != RC_OFF_MODE) && pSpatialLayer->sSliceArgument.uiSliceNum > 1) {
605 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), WARNING: GOM based RC do not support SM_RASTER_SLICE!");
606 }
607 // considering the coding efficient and performance, iCountMbNum constraint by MIN_NUM_MB_PER_SLICE condition of multi-pSlice mode settting
608 if (iMbNumInFrame <= MIN_NUM_MB_PER_SLICE) {
609 pSpatialLayer->sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
610 pSpatialLayer->sSliceArgument.uiSliceNum = 1;
611 break;
612 }
613 }
614 break;
615 case SM_SIZELIMITED_SLICE: {
616 iMbWidth = (kiPicWidth + 15) >> 4;
617 iMbHeight = (kiPicHeight + 15) >> 4;
618 if (pSpatialLayer->sSliceArgument.uiSliceSizeConstraint <= MAX_MACROBLOCK_SIZE_IN_BYTE) {
619 WelsLog (pLogCtx, WELS_LOG_ERROR,
620 "ParamValidationExt(), invalid iSliceSize (%d) settings!should be larger than MAX_MACROBLOCK_SIZE_IN_BYTE(%d)",
621 pSpatialLayer->sSliceArgument.uiSliceSizeConstraint, MAX_MACROBLOCK_SIZE_IN_BYTE);
622 return ENC_RETURN_UNSUPPORTED_PARA;
623 }
624
625 if (pCodingParam->uiMaxNalSize > 0) {
626 if (pCodingParam->uiMaxNalSize < (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE)) {
627 WelsLog (pLogCtx, WELS_LOG_ERROR,
628 "ParamValidationExt(), invalid uiMaxNalSize (%d) settings! should be larger than (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE)(%d)",
629 pCodingParam->uiMaxNalSize, (NAL_HEADER_ADD_0X30BYTES + MAX_MACROBLOCK_SIZE_IN_BYTE));
630 return ENC_RETURN_UNSUPPORTED_PARA;
631 }
632
633 if (pSpatialLayer->sSliceArgument.uiSliceSizeConstraint > (pCodingParam->uiMaxNalSize -
634 NAL_HEADER_ADD_0X30BYTES)) {
635 WelsLog (pLogCtx, WELS_LOG_WARNING,
636 "ParamValidationExt(), slice mode = SM_SIZELIMITED_SLICE, uiSliceSizeConstraint = %d ,uiMaxNalsize = %d, will take uiMaxNalsize!",
637 pSpatialLayer->sSliceArgument.uiSliceSizeConstraint, pCodingParam->uiMaxNalSize);
638 pSpatialLayer->sSliceArgument.uiSliceSizeConstraint = pCodingParam->uiMaxNalSize - NAL_HEADER_ADD_0X30BYTES;
639 }
640 }
641 pSpatialLayer->sSliceArgument.uiSliceSizeConstraint -= NAL_HEADER_ADD_0X30BYTES;
642 }
643 break;
644 default: {
645 WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), invalid uiSliceMode (%d) settings!",
646 pCodingParam->sSpatialLayers[0].sSliceArgument.uiSliceMode);
647 return ENC_RETURN_UNSUPPORTED_PARA;
648
649 }
650 break;
651 }
652 }
653 for (i = 0; i < pCodingParam->iSpatialLayerNum; ++ i) {
654 SSpatialLayerConfig* pLayerInfo = &pCodingParam->sSpatialLayers[i];
655 if ((pLayerInfo->uiProfileIdc == PRO_BASELINE) || (pLayerInfo->uiProfileIdc == PRO_SCALABLE_BASELINE)) {
656 if (pCodingParam->iEntropyCodingModeFlag != 0) {
657 pCodingParam->iEntropyCodingModeFlag = 0;
658 WelsLog (pLogCtx, WELS_LOG_WARNING, "layerId(%d) Profile is baseline, Change CABAC to CAVLC", i);
659 }
660 } else if (pLayerInfo->uiProfileIdc == PRO_UNKNOWN) {
661 if ((i == 0) || pCodingParam->bSimulcastAVC) {
662 pLayerInfo->uiProfileIdc = (pCodingParam->iEntropyCodingModeFlag) ? PRO_HIGH : PRO_BASELINE;
663 } else {
664 pLayerInfo->uiProfileIdc = PRO_SCALABLE_BASELINE;
665 }
666 }
667 }
668 return ParamValidation (pLogCtx, pCodingParam);
669 }
670
671
WelsEncoderApplyFrameRate(SWelsSvcCodingParam * pParam)672 void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam) {
673 SSpatialLayerInternal* pLayerParamInternal;
674 SSpatialLayerConfig* pLayerParam;
675 const float kfEpsn = 0.000001f;
676 const int32_t kiNumLayer = pParam->iSpatialLayerNum;
677 int32_t i;
678 const float kfMaxFrameRate = pParam->fMaxFrameRate;
679 float fRatio;
680 float fTargetOutputFrameRate;
681
682 //set input frame rate to each layer
683 for (i = 0; i < kiNumLayer; i++) {
684 pLayerParamInternal = & (pParam->sDependencyLayers[i]);
685 pLayerParam = & (pParam->sSpatialLayers[i]);
686 fRatio = pLayerParamInternal->fOutputFrameRate / pLayerParamInternal->fInputFrameRate;
687 if ((kfMaxFrameRate - pLayerParamInternal->fInputFrameRate) > kfEpsn
688 || (kfMaxFrameRate - pLayerParamInternal->fInputFrameRate) < -kfEpsn) {
689 pLayerParamInternal->fInputFrameRate = kfMaxFrameRate;
690 fTargetOutputFrameRate = kfMaxFrameRate * fRatio;
691 pLayerParamInternal->fOutputFrameRate = (fTargetOutputFrameRate >= 6) ? fTargetOutputFrameRate :
692 (pLayerParamInternal->fInputFrameRate);
693 pLayerParam->fFrameRate = pLayerParamInternal->fOutputFrameRate;
694 //TODO:{Sijia} from design, there is no sense to have temporal layer when under 6fps even with such setting?
695 }
696 }
697 }
698
WelsEncoderApplyBitRate(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam,int iLayer)699 int32_t WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int iLayer) {
700 //TODO (Sijia): this is a temporary solution which keep the ratio between layers
701 //but it is also possible to fulfill the bitrate of lower layer first
702
703 SSpatialLayerConfig* pLayerParam;
704 const int32_t iNumLayers = pParam->iSpatialLayerNum;
705 int32_t i, iOrigTotalBitrate = 0;
706 if (iLayer == SPATIAL_LAYER_ALL) {
707 //read old BR
708 for (i = 0; i < iNumLayers; i++) {
709 iOrigTotalBitrate += pParam->sSpatialLayers[i].iSpatialBitrate;
710 }
711 //write new BR
712 float fRatio = 0.0;
713 for (i = 0; i < iNumLayers; i++) {
714 pLayerParam = & (pParam->sSpatialLayers[i]);
715 fRatio = pLayerParam->iSpatialBitrate / (static_cast<float> (iOrigTotalBitrate));
716 pLayerParam->iSpatialBitrate = static_cast<int32_t> (pParam->iTargetBitrate * fRatio);
717
718 if (WelsBitRateVerification (pLogCtx, pLayerParam, i) != ENC_RETURN_SUCCESS)
719 return ENC_RETURN_UNSUPPORTED_PARA;
720 }
721 } else {
722 return WelsBitRateVerification (pLogCtx, & (pParam->sSpatialLayers[iLayer]), iLayer);
723 }
724 return ENC_RETURN_SUCCESS;
725 }
WelsEncoderApplyBitVaryRang(SLogContext * pLogCtx,SWelsSvcCodingParam * pParam,int32_t iRang)726 int32_t WelsEncoderApplyBitVaryRang (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iRang) {
727 SSpatialLayerConfig* pLayerParam;
728 const int32_t iNumLayers = pParam->iSpatialLayerNum;
729 for (int32_t i = 0; i < iNumLayers; i++) {
730 pLayerParam = & (pParam->sSpatialLayers[i]);
731 pLayerParam->iMaxSpatialBitrate = WELS_MIN ((int) (pLayerParam->iSpatialBitrate * (1 + iRang / 100.0)),
732 pLayerParam->iMaxSpatialBitrate);
733 if (WelsBitRateVerification (pLogCtx, pLayerParam, i) != ENC_RETURN_SUCCESS)
734 return ENC_RETURN_UNSUPPORTED_PARA;
735 WelsLog (pLogCtx, WELS_LOG_INFO,
736 "WelsEncoderApplyBitVaryRang:UpdateMaxBitrate layerId= %d,iMaxSpatialBitrate = %d", i, pLayerParam->iMaxSpatialBitrate);
737 }
738 return ENC_RETURN_SUCCESS;
739 }
740
741 /*!
742 * \brief acquire count number of layers and NALs based on configurable paramters dependency
743 * \pParam pCtx sWelsEncCtx*
744 * \pParam pParam SWelsSvcCodingParam*
745 * \pParam pCountLayers pointer of count number of layers indeed
746 * \pParam iCountNals pointer of count number of nals indeed
747 * \return 0 - successful; otherwise failed
748 */
AcquireLayersNals(sWelsEncCtx ** ppCtx,SWelsSvcCodingParam * pParam,int32_t * pCountLayers,int32_t * pCountNals)749 int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pParam, int32_t* pCountLayers,
750 int32_t* pCountNals) {
751 int32_t iCountNumLayers = 0;
752 int32_t iCountNumNals = 0;
753 int32_t iNumDependencyLayers = 0;
754 int32_t iDIndex = 0;
755
756 if (NULL == pParam || NULL == ppCtx || NULL == *ppCtx)
757 return 1;
758
759 iNumDependencyLayers = pParam->iSpatialLayerNum;
760
761 do {
762 SSpatialLayerConfig* pDLayer = &pParam->sSpatialLayers[iDIndex];
763 // pDLayer->ptr_cfg = pParam;
764 int32_t iOrgNumNals = iCountNumNals;
765
766 //Note: Sep. 2010
767 //Review this part and suggest no change, since the memory over-use
768 //(1) counts little to the overall performance
769 //(2) should not be critial even under mobile case
770 if (SM_SIZELIMITED_SLICE == pDLayer->sSliceArgument.uiSliceMode) {
771 iCountNumNals += MAX_SLICES_NUM;
772 // plus prefix NALs
773 if (iDIndex == 0)
774 iCountNumNals += MAX_SLICES_NUM;
775 // MAX_SLICES_NUM < MAX_LAYER_NUM_OF_FRAME ensured at svc_enc_slice_segment.h
776 if (iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER) {
777 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
778 "AcquireLayersNals(), num_of_slice(%d) > existing slice(%d) at (iDid= %d), max=%d",
779 iCountNumNals, iOrgNumNals, iDIndex, MAX_NAL_UNITS_IN_LAYER);
780 return 1;
781 }
782 } else { /*if ( SM_SINGLE_SLICE != pDLayer->sSliceArgument.uiSliceMode )*/
783 const int32_t kiNumOfSlice = GetInitialSliceNum (&pDLayer->sSliceArgument);
784
785 // NEED check iCountNals value in case multiple slices is used
786 iCountNumNals += kiNumOfSlice; // for pSlice VCL NALs
787 // plus prefix NALs
788 if (iDIndex == 0)
789 iCountNumNals += kiNumOfSlice;
790 assert (iCountNumNals - iOrgNumNals <= MAX_NAL_UNITS_IN_LAYER);
791 if (kiNumOfSlice > MAX_SLICES_NUM) {
792 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
793 "AcquireLayersNals(), num_of_slice(%d) > MAX_SLICES_NUM(%d) per (iDid= %d, qid= %d) settings!",
794 kiNumOfSlice, MAX_SLICES_NUM, iDIndex, 0);
795 return 1;
796 }
797 }
798
799 if (iCountNumNals - iOrgNumNals > MAX_NAL_UNITS_IN_LAYER) {
800 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
801 "AcquireLayersNals(), num_of_nals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) per (iDid= %d, qid= %d) settings!",
802 (iCountNumNals - iOrgNumNals), MAX_NAL_UNITS_IN_LAYER, iDIndex, 0);
803 return 1;
804 }
805
806 iCountNumLayers ++;
807
808 ++ iDIndex;
809 } while (iDIndex < iNumDependencyLayers);
810
811 if (NULL == (*ppCtx)->pFuncList || NULL == (*ppCtx)->pFuncList->pParametersetStrategy) {
812 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
813 "AcquireLayersNals(), pFuncList and pParametersetStrategy needed to be initialized first!");
814 return 1;
815 }
816 // count parasets
817 iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
818 iCountNumLayers // plus iCountNumLayers for reserved application
819 + (*ppCtx)->pFuncList->pParametersetStrategy->GetAllNeededParasetNum();
820
821 // to check number of layers / nals / slices dependencies, 12/8/2010
822 if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
823 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR, "AcquireLayersNals(), iCountNumLayers(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
824 iCountNumLayers, MAX_LAYER_NUM_OF_FRAME);
825 return 1;
826 }
827
828 if (NULL != pCountLayers)
829 *pCountLayers = iCountNumLayers;
830 if (NULL != pCountNals)
831 *pCountNals = iCountNumNals;
832 return 0;
833 }
834
InitMbInfo(sWelsEncCtx * pEnc,SMB * pList,SDqLayer * pLayer,const int32_t kiDlayerId,const int32_t kiMaxMbNum)835 static void InitMbInfo (sWelsEncCtx* pEnc, SMB* pList, SDqLayer* pLayer, const int32_t kiDlayerId,
836 const int32_t kiMaxMbNum) {
837 int32_t iMbWidth = pLayer->iMbWidth;
838 int32_t iMbHeight = pLayer->iMbHeight;
839 int32_t iIdx;
840 int32_t iMbNum = iMbWidth * iMbHeight;
841 uint32_t uiNeighborAvail;
842 const int32_t kiOffset = (kiDlayerId & 0x01) * kiMaxMbNum;
843 SMVUnitXY (*pLayerMvUnitBlock4x4)[MB_BLOCK4x4_NUM] = (SMVUnitXY (*)[MB_BLOCK4x4_NUM]) (
844 &pEnc->pMvUnitBlock4x4[MB_BLOCK4x4_NUM * kiOffset]);
845 int8_t (*pLayerRefIndexBlock8x8)[MB_BLOCK8x8_NUM] = (int8_t (*)[MB_BLOCK8x8_NUM]) (
846 &pEnc->pRefIndexBlock4x4[MB_BLOCK8x8_NUM * kiOffset]);
847
848 for (iIdx = 0; iIdx < iMbNum; iIdx++) {
849 bool bLeft;
850 bool bTop;
851 bool bLeftTop;
852 bool bRightTop;
853 int32_t iLeftXY, iTopXY, iLeftTopXY, iRightTopXY;
854 uint16_t uiSliceIdc; //[0..65535] > 36864 of LEVEL5.2
855
856 pList[iIdx].iMbX = pEnc->pStrideTab->pMbIndexX[kiDlayerId][iIdx];
857 pList[iIdx].iMbY = pEnc->pStrideTab->pMbIndexY[kiDlayerId][iIdx];
858 pList[iIdx].iMbXY = iIdx;
859
860 uiSliceIdc = WelsMbToSliceIdc (pLayer, iIdx);
861 iLeftXY = iIdx - 1;
862 iTopXY = iIdx - iMbWidth;
863 iLeftTopXY = iTopXY - 1;
864 iRightTopXY = iTopXY + 1;
865
866 bLeft = (pList[iIdx].iMbX > 0) && (uiSliceIdc == WelsMbToSliceIdc (pLayer, iLeftXY));
867 bTop = (pList[iIdx].iMbY > 0) && (uiSliceIdc == WelsMbToSliceIdc (pLayer, iTopXY));
868 bLeftTop = (pList[iIdx].iMbX > 0) && (pList[iIdx].iMbY > 0) && (uiSliceIdc ==
869 WelsMbToSliceIdc (pLayer, iLeftTopXY));
870 bRightTop = (pList[iIdx].iMbX < (iMbWidth - 1)) && (pList[iIdx].iMbY > 0) && (uiSliceIdc ==
871 WelsMbToSliceIdc (pLayer, iRightTopXY));
872
873 uiNeighborAvail = 0;
874 if (bLeft) {
875 uiNeighborAvail |= LEFT_MB_POS;
876 }
877 if (bTop) {
878 uiNeighborAvail |= TOP_MB_POS;
879 }
880 if (bLeftTop) {
881 uiNeighborAvail |= TOPLEFT_MB_POS;
882 }
883 if (bRightTop) {
884 uiNeighborAvail |= TOPRIGHT_MB_POS;
885 }
886 pList[iIdx].uiSliceIdc = uiSliceIdc; // merge from svc_hd_opt_b for multiple slices coding
887 pList[iIdx].uiNeighborAvail = uiNeighborAvail;
888 uiNeighborAvail = 0;
889 if (pList[iIdx].iMbX >= BASE_MV_MB_NMB)
890 uiNeighborAvail |= LEFT_MB_POS;
891 if (pList[iIdx].iMbX <= (iMbWidth - 1 - BASE_MV_MB_NMB))
892 uiNeighborAvail |= RIGHT_MB_POS;
893 if (pList[iIdx].iMbY >= BASE_MV_MB_NMB)
894 uiNeighborAvail |= TOP_MB_POS;
895 if (pList[iIdx].iMbY <= (iMbHeight - 1 - BASE_MV_MB_NMB))
896 uiNeighborAvail |= BOTTOM_MB_POS;
897
898 pList[iIdx].sMv = pLayerMvUnitBlock4x4[iIdx];
899 pList[iIdx].pRefIndex = pLayerRefIndexBlock8x8[iIdx];
900 pList[iIdx].pSadCost = &pEnc->pSadCostMb[iIdx];
901 pList[iIdx].pIntra4x4PredMode = &pEnc->pIntra4x4PredModeBlocks[iIdx * INTRA_4x4_MODE_NUM];
902 pList[iIdx].pNonZeroCount = &pEnc->pNonZeroCountBlocks[iIdx * MB_LUMA_CHROMA_BLOCK4x4_NUM];
903 }
904 }
905
906
InitMbListD(sWelsEncCtx ** ppCtx)907 int32_t InitMbListD (sWelsEncCtx** ppCtx) {
908 int32_t iNumDlayer = (*ppCtx)->pSvcParam->iSpatialLayerNum;
909 int32_t iMbSize[MAX_DEPENDENCY_LAYER] = { 0 };
910 int32_t iOverallMbNum = 0;
911 int32_t iMbWidth = 0;
912 int32_t iMbHeight = 0;
913 int32_t i;
914
915 if (iNumDlayer > MAX_DEPENDENCY_LAYER)
916 return 1;
917
918 for (i = 0; i < iNumDlayer; i++) {
919 iMbWidth = ((*ppCtx)->pSvcParam->sSpatialLayers[i].iVideoWidth + 15) >> 4;
920 iMbHeight = ((*ppCtx)->pSvcParam->sSpatialLayers[i].iVideoHeight + 15) >> 4;
921 iMbSize[i] = iMbWidth * iMbHeight;
922 iOverallMbNum += iMbSize[i];
923 }
924
925 (*ppCtx)->ppMbListD = static_cast<SMB**> ((*ppCtx)->pMemAlign->WelsMallocz (iNumDlayer * sizeof (SMB*), "ppMbListD"));
926 (*ppCtx)->ppMbListD[0] = NULL;
927 WELS_VERIFY_RETURN_IF (1, (*ppCtx)->ppMbListD == NULL)
928 (*ppCtx)->ppMbListD[0] = static_cast<SMB*> ((*ppCtx)->pMemAlign->WelsMallocz (iOverallMbNum * sizeof (SMB),
929 "ppMbListD[0]"));
930 WELS_VERIFY_RETURN_IF (1, (*ppCtx)->ppMbListD[0] == NULL)
931 (*ppCtx)->ppDqLayerList[0]->sMbDataP = (*ppCtx)->ppMbListD[0];
932 InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[0], (*ppCtx)->ppDqLayerList[0], 0, iMbSize[iNumDlayer - 1]);
933 for (i = 1; i < iNumDlayer; i++) {
934 (*ppCtx)->ppMbListD[i] = (*ppCtx)->ppMbListD[i - 1] + iMbSize[i - 1];
935 (*ppCtx)->ppDqLayerList[i]->sMbDataP = (*ppCtx)->ppMbListD[i];
936 InitMbInfo (*ppCtx, (*ppCtx)->ppMbListD[i], (*ppCtx)->ppDqLayerList[i], i, iMbSize[iNumDlayer - 1]);
937 }
938
939 return 0;
940 }
941
FreeSliceInLayer(SDqLayer * pDq,CMemoryAlign * pMa)942 void FreeSliceInLayer (SDqLayer* pDq, CMemoryAlign* pMa) {
943 int32_t iIdx = 0;
944 for (; iIdx < MAX_THREADS_NUM; iIdx ++) {
945 FreeSliceBuffer (pDq->sSliceBufferInfo[iIdx].pSliceBuffer,
946 pDq->sSliceBufferInfo[iIdx].iMaxSliceNum,
947 pMa, "pSliceBuffer");
948 }
949 }
950
FreeDqLayer(SDqLayer * & pDq,CMemoryAlign * pMa)951 void FreeDqLayer (SDqLayer*& pDq, CMemoryAlign* pMa) {
952 if (NULL == pDq) {
953 return;
954 }
955
956 FreeSliceInLayer (pDq, pMa);
957
958 if (pDq->ppSliceInLayer) {
959 pMa->WelsFree (pDq->ppSliceInLayer, "ppSliceInLayer");
960 pDq->ppSliceInLayer = NULL;
961 }
962
963 if (pDq->pFirstMbIdxOfSlice) {
964 pMa->WelsFree (pDq->pFirstMbIdxOfSlice, "pFirstMbIdxOfSlice");
965 pDq->pFirstMbIdxOfSlice = NULL;
966 }
967
968 if (pDq->pCountMbNumInSlice) {
969 pMa->WelsFree (pDq->pCountMbNumInSlice, "pCountMbNumInSlice");
970 pDq->pCountMbNumInSlice = NULL;
971 }
972
973 if (pDq->pFeatureSearchPreparation) {
974 ReleaseFeatureSearchPreparation (pMa, pDq->pFeatureSearchPreparation->pFeatureOfBlock);
975 pMa->WelsFree (pDq->pFeatureSearchPreparation, "pFeatureSearchPreparation");
976 pDq->pFeatureSearchPreparation = NULL;
977 }
978
979 UninitSlicePEncCtx (pDq, pMa);
980 pDq->iMaxSliceNum = 0;
981
982 pMa->WelsFree (pDq, "pDqLayer");
983 pDq = NULL;
984 }
985
FreeRefList(SRefList * & pRefList,CMemoryAlign * pMa,const int iMaxNumRefFrame)986 void FreeRefList (SRefList*& pRefList, CMemoryAlign* pMa, const int iMaxNumRefFrame) {
987 if (NULL == pRefList) {
988 return;
989 }
990
991 int32_t iRef = 0;
992 do {
993 if (pRefList->pRef[iRef] != NULL) {
994 FreePicture (pMa, &pRefList->pRef[iRef]);
995 }
996 ++ iRef;
997 } while (iRef < 1 + iMaxNumRefFrame);
998
999 pMa->WelsFree (pRefList, "pRefList");
1000 pRefList = NULL;
1001 }
1002
1003 /*!
1004 * \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available
1005 * \pParam pCtx sWelsEncCtx*
1006 * \return 0 - successful; otherwise failed
1007 */
InitDqLayers(sWelsEncCtx ** ppCtx,SExistingParasetList * pExistingParasetList)1008 static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList) {
1009 SWelsSvcCodingParam* pParam = NULL;
1010 SWelsSPS* pSps = NULL;
1011 SSubsetSps* pSubsetSps = NULL;
1012 SWelsPPS* pPps = NULL;
1013 CMemoryAlign* pMa = NULL;
1014 int32_t iDlayerCount = 0;
1015 int32_t iDlayerIndex = 0;
1016 int32_t iSpsId = 0;
1017 uint32_t iPpsId = 0;
1018 uint32_t iNumRef = 0;
1019 int32_t iResult = 0;
1020
1021 if (NULL == ppCtx || NULL == *ppCtx)
1022 return 1;
1023
1024 pMa = (*ppCtx)->pMemAlign;
1025 pParam = (*ppCtx)->pSvcParam;
1026 iDlayerCount = pParam->iSpatialLayerNum;
1027 iNumRef = pParam->iMaxNumRefFrame;
1028
1029 const int32_t kiFeatureStrategyIndex = FME_DEFAULT_FEATURE_INDEX;
1030 const int32_t kiMe16x16 = ME_DIA_CROSS;
1031 const int32_t kiMe8x8 = ME_DIA_CROSS_FME;
1032 const int32_t kiNeedFeatureStorage = (pParam->iUsageType != SCREEN_CONTENT_REAL_TIME) ? 0 :
1033 ((kiFeatureStrategyIndex << 16) + ((kiMe16x16 & 0x00FF) << 8) + (kiMe8x8 & 0x00FF));
1034
1035 iDlayerIndex = 0;
1036 while (iDlayerIndex < iDlayerCount) {
1037 SRefList* pRefList = NULL;
1038 uint32_t i = 0;
1039 const int32_t kiWidth = pParam->sSpatialLayers[iDlayerIndex].iVideoWidth;
1040 const int32_t kiHeight = pParam->sSpatialLayers[iDlayerIndex].iVideoHeight;
1041 int32_t iPicWidth = WELS_ALIGN (kiWidth, MB_WIDTH_LUMA) + (PADDING_LENGTH << 1); // with iWidth of horizon
1042 int32_t iPicChromaWidth = iPicWidth >> 1;
1043
1044 iPicWidth = WELS_ALIGN (iPicWidth,
1045 32); // 32(or 16 for chroma below) to match original imp. here instead of iCacheLineSize
1046 iPicChromaWidth = WELS_ALIGN (iPicChromaWidth, 16);
1047
1048 WelsGetEncBlockStrideOffset ((*ppCtx)->pStrideTab->pStrideEncBlockOffset[iDlayerIndex], iPicWidth, iPicChromaWidth);
1049
1050 // pRef list
1051 pRefList = (SRefList*)pMa->WelsMallocz (sizeof (SRefList), "pRefList");
1052 WELS_VERIFY_RETURN_IF (1, (NULL == pRefList))
1053 do {
1054 pRefList->pRef[i] = AllocPicture (pMa, kiWidth, kiHeight, true,
1055 (iDlayerIndex == iDlayerCount - 1) ? kiNeedFeatureStorage : 0); // to use actual size of current layer
1056 WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pRefList->pRef[i]), FreeRefList (pRefList, pMa, iNumRef))
1057 ++ i;
1058 } while (i < 1 + iNumRef);
1059
1060 pRefList->pNextBuffer = pRefList->pRef[0];
1061 (*ppCtx)->ppRefPicListExt[iDlayerIndex] = pRefList;
1062 ++ iDlayerIndex;
1063 }
1064
1065 iDlayerIndex = 0;
1066 while (iDlayerIndex < iDlayerCount) {
1067 SDqLayer* pDqLayer = NULL;
1068 SSpatialLayerConfig* pDlayer = &pParam->sSpatialLayers[iDlayerIndex];
1069 SSpatialLayerInternal* pParamInternal = &pParam->sDependencyLayers[iDlayerIndex];
1070 const int32_t kiMbW = (pDlayer->iVideoWidth + 0x0f) >> 4;
1071 const int32_t kiMbH = (pDlayer->iVideoHeight + 0x0f) >> 4;
1072
1073 pParamInternal->iCodingIndex = 0;
1074 pParamInternal->iFrameIndex = 0;
1075 pParamInternal->iFrameNum = 0;
1076 pParamInternal->iPOC = 0;
1077 pParamInternal->uiIdrPicId = 0;
1078 pParamInternal->bEncCurFrmAsIdrFlag = true; // make sure first frame is IDR
1079 // pDq layers list
1080 pDqLayer = (SDqLayer*)pMa->WelsMallocz (sizeof (SDqLayer), "pDqLayer");
1081 WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pDqLayer), FreeDqLayer (pDqLayer, pMa))
1082
1083 pDqLayer->bNeedAdjustingSlicing = false;
1084
1085 pDqLayer->iMbWidth = kiMbW;
1086 pDqLayer->iMbHeight = kiMbH;
1087
1088 int32_t iMaxSliceNum = 1;
1089 const int32_t kiSliceNum = GetInitialSliceNum (&pDlayer->sSliceArgument);
1090 if (iMaxSliceNum < kiSliceNum)
1091 iMaxSliceNum = kiSliceNum;
1092 pDqLayer->iMaxSliceNum = iMaxSliceNum;
1093
1094 iResult = InitSliceInLayer (*ppCtx, pDqLayer, iDlayerIndex, pMa);
1095 if (iResult) {
1096 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "InitDqLayers(), InitSliceInLayer failed(%d)!", iResult);
1097 FreeDqLayer (pDqLayer, pMa);
1098 return iResult;
1099 }
1100
1101 //deblocking parameters initialization
1102 //target-layer deblocking
1103 pDqLayer->iLoopFilterDisableIdc = pParam->iLoopFilterDisableIdc;
1104 pDqLayer->iLoopFilterAlphaC0Offset = (pParam->iLoopFilterAlphaC0Offset) << 1;
1105 pDqLayer->iLoopFilterBetaOffset = (pParam->iLoopFilterBetaOffset) << 1;
1106 //parallel deblocking
1107 pDqLayer->bDeblockingParallelFlag = pParam->bDeblockingParallelFlag;
1108
1109 //deblocking parameter adjustment
1110 if (SM_SINGLE_SLICE == pDlayer->sSliceArgument.uiSliceMode) {
1111 //iLoopFilterDisableIdc: will be 0 or 1 under single_slice
1112 if (2 == pParam->iLoopFilterDisableIdc) {
1113 pDqLayer->iLoopFilterDisableIdc = 0;
1114 }
1115 //bDeblockingParallelFlag
1116 pDqLayer->bDeblockingParallelFlag = false;
1117 } else {
1118 //multi-pSlice
1119 if (0 == pDqLayer->iLoopFilterDisableIdc) {
1120 pDqLayer->bDeblockingParallelFlag = false;
1121 }
1122 }
1123
1124 //
1125 if (kiNeedFeatureStorage && iDlayerIndex == iDlayerCount - 1) {
1126 pDqLayer->pFeatureSearchPreparation = static_cast<SFeatureSearchPreparation*> (pMa->WelsMallocz (sizeof (
1127 SFeatureSearchPreparation), "pFeatureSearchPreparation"));
1128 WELS_VERIFY_RETURN_IF (1, NULL == pDqLayer->pFeatureSearchPreparation)
1129 int32_t iReturn = RequestFeatureSearchPreparation (pMa, pDlayer->iVideoWidth, pDlayer->iVideoHeight,
1130 kiNeedFeatureStorage,
1131 pDqLayer->pFeatureSearchPreparation);
1132 WELS_VERIFY_RETURN_IF (1, ENC_RETURN_SUCCESS != iReturn)
1133 } else {
1134 pDqLayer->pFeatureSearchPreparation = NULL;
1135 }
1136
1137 (*ppCtx)->ppDqLayerList[iDlayerIndex] = pDqLayer;
1138
1139 ++ iDlayerIndex;
1140 }
1141
1142 // for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
1143 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pFuncList))
1144 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pFuncList->pParametersetStrategy))
1145 const int32_t kiNeededSpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSpsNum();
1146 const int32_t kiNeededSubsetSpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSubsetSpsNum();
1147 (*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMallocz (kiNeededSpsNum * sizeof (SWelsSPS), "pSpsArray");
1148 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pSpsArray))
1149 if (kiNeededSubsetSpsNum > 0) {
1150 (*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMallocz (kiNeededSubsetSpsNum * sizeof (SSubsetSps), "pSubsetArray");
1151 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pSubsetArray))
1152 } else {
1153 (*ppCtx)->pSubsetArray = NULL;
1154 }
1155
1156 // PPS
1157 const int32_t kiNeededPpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededPpsNum();
1158 (*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMallocz (kiNeededPpsNum * sizeof (SWelsPPS), "pPPSArray");
1159 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pPPSArray))
1160
1161 (*ppCtx)->pFuncList->pParametersetStrategy->LoadPrevious (pExistingParasetList, (*ppCtx)->pSpsArray,
1162 (*ppCtx)->pSubsetArray, (*ppCtx)->pPPSArray);
1163
1164
1165 (*ppCtx)->pDqIdcMap = (SDqIdc*)pMa->WelsMallocz (iDlayerCount * sizeof (SDqIdc), "pDqIdcMap");
1166 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pDqIdcMap))
1167
1168 iDlayerIndex = 0;
1169 while (iDlayerIndex < iDlayerCount) {
1170 SDqIdc* pDqIdc = & (*ppCtx)->pDqIdcMap[iDlayerIndex];
1171 const bool bUseSubsetSps = (!pParam->bSimulcastAVC) && (iDlayerIndex > BASE_DEPENDENCY_ID);
1172 SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
1173 bool bSvcBaselayer = (!pParam->bSimulcastAVC) && (iDlayerCount > BASE_DEPENDENCY_ID)
1174 && (iDlayerIndex == BASE_DEPENDENCY_ID);
1175 pDqIdc->uiSpatialId = iDlayerIndex;
1176
1177 iSpsId = (*ppCtx)->pFuncList->pParametersetStrategy->GenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
1178 iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
1179 WELS_VERIFY_RETURN_IF (ENC_RETURN_UNSUPPORTED_PARA, (0 > iSpsId))
1180 if (!bUseSubsetSps) {
1181 pSps = & ((*ppCtx)->pSpsArray[iSpsId]);
1182 } else {
1183 pSubsetSps = & ((*ppCtx)->pSubsetArray[iSpsId]);
1184 }
1185
1186 iPpsId = (*ppCtx)->pFuncList->pParametersetStrategy->InitPps ((*ppCtx), iSpsId, pSps, pSubsetSps, iPpsId, true,
1187 bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
1188 pPps = & ((*ppCtx)->pPPSArray[iPpsId]);
1189
1190 // Not using FMO in SVC coding so far, come back if need FMO
1191 {
1192 iResult = InitSlicePEncCtx ((*ppCtx)->ppDqLayerList[iDlayerIndex],
1193 (*ppCtx)->pMemAlign,
1194 false,
1195 pSps->iMbWidth,
1196 pSps->iMbHeight,
1197 & (pDlayerParam->sSliceArgument),
1198 pPps);
1199 if (iResult) {
1200 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "InitDqLayers(), InitSlicePEncCtx failed(%d)!", iResult);
1201 return iResult;
1202 }
1203 }
1204 pDqIdc->iSpsId = iSpsId;
1205 pDqIdc->iPpsId = iPpsId;
1206
1207 if ((pParam->bSimulcastAVC) || (bUseSubsetSps))
1208 ++ iSpsId;
1209 ++ iPpsId;
1210 if (bUseSubsetSps) {
1211 ++ (*ppCtx)->iSubsetSpsNum;
1212 } else {
1213 ++ (*ppCtx)->iSpsNum;
1214 }
1215 ++ (*ppCtx)->iPpsNum;
1216
1217 ++ iDlayerIndex;
1218 }
1219
1220 (*ppCtx)->pFuncList->pParametersetStrategy->UpdateParaSetNum ((*ppCtx));
1221 return ENC_RETURN_SUCCESS;
1222 }
1223
AllocStrideTables(sWelsEncCtx ** ppCtx,const int32_t kiNumSpatialLayers)1224 int32_t AllocStrideTables (sWelsEncCtx** ppCtx, const int32_t kiNumSpatialLayers) {
1225 CMemoryAlign* pMa = (*ppCtx)->pMemAlign;
1226 SWelsSvcCodingParam* pParam = (*ppCtx)->pSvcParam;
1227 SStrideTables* pPtr = NULL;
1228 int16_t* pTmpRow = NULL, *pRowX = NULL, *pRowY = NULL, *p = NULL;
1229 uint8_t* pBase = NULL;
1230 uint8_t* pBaseDec = NULL, *pBaseEnc = NULL, *pBaseMbX = NULL, *pBaseMbY = NULL;
1231 struct {
1232 int32_t iMbWidth;
1233 int32_t iCountMbNum; // count number of SMB in each spatial
1234 int32_t iSizeAllMbAlignCache; // cache line size aligned in each spatial
1235 } sMbSizeMap[MAX_DEPENDENCY_LAYER] = {{ 0 }};
1236 int32_t iLineSizeY[MAX_DEPENDENCY_LAYER][2] = {{ 0 }};
1237 int32_t iLineSizeUV[MAX_DEPENDENCY_LAYER][2] = {{ 0 }};
1238 int32_t iMapSpatialIdx[MAX_DEPENDENCY_LAYER][2] = {{ 0 }};
1239 int32_t iSizeDec = 0;
1240 int32_t iSizeEnc = 0;
1241 int32_t iCountLayersNeedCs[2] = {0};
1242 const int32_t kiUnit1Size = 24 * sizeof (int32_t);
1243 int32_t iUnit2Size = 0;
1244 int32_t iNeedAllocSize = 0;
1245 int32_t iRowSize = 0;
1246 int16_t iMaxMbWidth = 0;
1247 int16_t iMaxMbHeight = 0;
1248 int32_t i = 0;
1249 int32_t iSpatialIdx = 0;
1250 int32_t iTemporalIdx = 0;
1251 int32_t iCntTid = 0;
1252
1253 if (kiNumSpatialLayers <= 0 || kiNumSpatialLayers > MAX_DEPENDENCY_LAYER)
1254 return 1;
1255
1256 pPtr = (SStrideTables*)pMa->WelsMallocz (sizeof (SStrideTables), "SStrideTables");
1257 if (NULL == pPtr)
1258 return 1;
1259 (*ppCtx)->pStrideTab = pPtr;
1260
1261 iCntTid = pParam->iTemporalLayerNum > 1 ? 2 : 1;
1262
1263 iSpatialIdx = 0;
1264 while (iSpatialIdx < kiNumSpatialLayers) {
1265 const int32_t kiTmpWidth = (pParam->sSpatialLayers[iSpatialIdx].iVideoWidth + 15) >> 4;
1266 const int32_t kiTmpHeight = (pParam->sSpatialLayers[iSpatialIdx].iVideoHeight + 15) >> 4;
1267 int32_t iNumMb = kiTmpWidth * kiTmpHeight;
1268
1269 sMbSizeMap[iSpatialIdx].iMbWidth = kiTmpWidth;
1270 sMbSizeMap[iSpatialIdx].iCountMbNum = iNumMb;
1271
1272 iNumMb *= sizeof (int16_t);
1273 sMbSizeMap[iSpatialIdx].iSizeAllMbAlignCache = iNumMb;
1274 iUnit2Size += iNumMb;
1275
1276 ++ iSpatialIdx;
1277 }
1278
1279 // Adaptive size_cs, size_fdec by implementation dependency
1280 iTemporalIdx = 0;
1281 while (iTemporalIdx < iCntTid) {
1282 const bool kbBaseTemporalFlag = (iTemporalIdx == 0);
1283
1284 iSpatialIdx = 0;
1285 while (iSpatialIdx < kiNumSpatialLayers) {
1286 SSpatialLayerConfig* fDlp = &pParam->sSpatialLayers[iSpatialIdx];
1287
1288 const int32_t kiWidthPad = WELS_ALIGN (fDlp->iVideoWidth, 16) + (PADDING_LENGTH << 1);
1289 iLineSizeY[iSpatialIdx][kbBaseTemporalFlag] = WELS_ALIGN (kiWidthPad, 32);
1290 iLineSizeUV[iSpatialIdx][kbBaseTemporalFlag] = WELS_ALIGN ((kiWidthPad >> 1), 16);
1291
1292 iMapSpatialIdx[iCountLayersNeedCs[kbBaseTemporalFlag]][kbBaseTemporalFlag] = iSpatialIdx;
1293 ++ iCountLayersNeedCs[kbBaseTemporalFlag];
1294 ++ iSpatialIdx;
1295 }
1296 ++ iTemporalIdx;
1297 }
1298 iSizeDec = kiUnit1Size * (iCountLayersNeedCs[0] + iCountLayersNeedCs[1]);
1299 iSizeEnc = kiUnit1Size * kiNumSpatialLayers;
1300
1301 iNeedAllocSize = iSizeDec + iSizeEnc + (iUnit2Size << 1);
1302
1303 pBase = (uint8_t*)pMa->WelsMallocz (iNeedAllocSize, "pBase");
1304 if (NULL == pBase) {
1305 return 1;
1306 }
1307
1308 pBaseDec = pBase; // iCountLayersNeedCs
1309 pBaseEnc = pBaseDec + iSizeDec; // iNumSpatialLayers
1310 pBaseMbX = pBaseEnc + iSizeEnc; // iNumSpatialLayers
1311 pBaseMbY = pBaseMbX + iUnit2Size; // iNumSpatialLayers
1312
1313 iTemporalIdx = 0;
1314 while (iTemporalIdx < iCntTid) {
1315 const bool kbBaseTemporalFlag = (iTemporalIdx == 0);
1316
1317 iSpatialIdx = 0;
1318 while (iSpatialIdx < iCountLayersNeedCs[kbBaseTemporalFlag]) {
1319 const int32_t kiActualSpatialIdx = iMapSpatialIdx[iSpatialIdx][kbBaseTemporalFlag];
1320 const int32_t kiLumaWidth = iLineSizeY[kiActualSpatialIdx][kbBaseTemporalFlag];
1321 const int32_t kiChromaWidth = iLineSizeUV[kiActualSpatialIdx][kbBaseTemporalFlag];
1322
1323 WelsGetEncBlockStrideOffset ((int32_t*)pBaseDec, kiLumaWidth, kiChromaWidth);
1324
1325 pPtr->pStrideDecBlockOffset[kiActualSpatialIdx][kbBaseTemporalFlag] = (int32_t*)pBaseDec;
1326 pBaseDec += kiUnit1Size;
1327
1328 ++ iSpatialIdx;
1329 }
1330 ++ iTemporalIdx;
1331 }
1332 iTemporalIdx = 0;
1333 while (iTemporalIdx < iCntTid) {
1334 const bool kbBaseTemporalFlag = (iTemporalIdx == 0);
1335
1336 iSpatialIdx = 0;
1337 while (iSpatialIdx < kiNumSpatialLayers) {
1338 int32_t iMatchIndex = 0;
1339 bool bInMap = false;
1340 bool bMatchFlag = false;
1341
1342 i = 0;
1343 while (i < iCountLayersNeedCs[kbBaseTemporalFlag]) {
1344 const int32_t kiActualIdx = iMapSpatialIdx[i][kbBaseTemporalFlag];
1345 if (kiActualIdx == iSpatialIdx) {
1346 bInMap = true;
1347 break;
1348 }
1349 if (!bMatchFlag) {
1350 iMatchIndex = kiActualIdx;
1351 bMatchFlag = true;
1352 }
1353 ++ i;
1354 }
1355
1356 if (bInMap) {
1357 ++ iSpatialIdx;
1358 continue;
1359 }
1360
1361 // not in spatial map and assign match one to it
1362 pPtr->pStrideDecBlockOffset[iSpatialIdx][kbBaseTemporalFlag] =
1363 pPtr->pStrideDecBlockOffset[iMatchIndex][kbBaseTemporalFlag];
1364
1365 ++ iSpatialIdx;
1366 }
1367 ++ iTemporalIdx;
1368 }
1369
1370 iSpatialIdx = 0;
1371 while (iSpatialIdx < kiNumSpatialLayers) {
1372 const int32_t kiAllocMbSize = sMbSizeMap[iSpatialIdx].iSizeAllMbAlignCache;
1373
1374 pPtr->pStrideEncBlockOffset[iSpatialIdx] = (int32_t*)pBaseEnc;
1375
1376 pPtr->pMbIndexX[iSpatialIdx] = (int16_t*)pBaseMbX;
1377 pPtr->pMbIndexY[iSpatialIdx] = (int16_t*)pBaseMbY;
1378
1379 pBaseEnc += kiUnit1Size;
1380 pBaseMbX += kiAllocMbSize;
1381 pBaseMbY += kiAllocMbSize;
1382
1383 ++ iSpatialIdx;
1384 }
1385
1386 while (iSpatialIdx < MAX_DEPENDENCY_LAYER) {
1387 pPtr->pStrideDecBlockOffset[iSpatialIdx][0] = NULL;
1388 pPtr->pStrideDecBlockOffset[iSpatialIdx][1] = NULL;
1389 pPtr->pStrideEncBlockOffset[iSpatialIdx] = NULL;
1390 pPtr->pMbIndexX[iSpatialIdx] = NULL;
1391 pPtr->pMbIndexY[iSpatialIdx] = NULL;
1392
1393 ++ iSpatialIdx;
1394 }
1395
1396 // initialize pMbIndexX and pMbIndexY tables as below
1397
1398 iMaxMbWidth = sMbSizeMap[kiNumSpatialLayers - 1].iMbWidth;
1399 iMaxMbWidth = WELS_ALIGN (iMaxMbWidth, 4); // 4 loops for int16_t required introduced as below
1400 iRowSize = iMaxMbWidth * sizeof (int16_t);
1401
1402 pTmpRow = (int16_t*)pMa->WelsMallocz (iRowSize, "pTmpRow");
1403 if (NULL == pTmpRow) {
1404 return 1;
1405 }
1406 pRowX = pTmpRow;
1407 pRowY = pRowX;
1408 // initialize pRowX & pRowY
1409 i = 0;
1410 p = pRowX;
1411 while (i < iMaxMbWidth) {
1412 *p = i;
1413 * (p + 1) = 1 + i;
1414 * (p + 2) = 2 + i;
1415 * (p + 3) = 3 + i;
1416
1417 p += 4;
1418 i += 4;
1419 }
1420
1421 iSpatialIdx = kiNumSpatialLayers;
1422 while (--iSpatialIdx >= 0) {
1423 int16_t* pMbIndexX = pPtr->pMbIndexX[iSpatialIdx];
1424 const int32_t kiMbWidth = sMbSizeMap[iSpatialIdx].iMbWidth;
1425 const int32_t kiMbHeight = sMbSizeMap[iSpatialIdx].iCountMbNum / kiMbWidth;
1426 const int32_t kiLineSize = kiMbWidth * sizeof (int16_t);
1427
1428 i = 0;
1429 while (i < kiMbHeight) {
1430 memcpy (pMbIndexX, pRowX, kiLineSize); // confirmed_safe_unsafe_usage
1431
1432 pMbIndexX += kiMbWidth;
1433 ++ i;
1434 }
1435 }
1436
1437 memset (pRowY, 0, iRowSize);
1438 iMaxMbHeight = sMbSizeMap[kiNumSpatialLayers - 1].iCountMbNum / sMbSizeMap[kiNumSpatialLayers - 1].iMbWidth;
1439 i = 0;
1440 for (;;) {
1441 ENFORCE_STACK_ALIGN_1D (int16_t, t, 4, 16)
1442
1443 int32_t t32 = 0;
1444 int16_t j = 0;
1445
1446 for (iSpatialIdx = kiNumSpatialLayers - 1; iSpatialIdx >= 0; -- iSpatialIdx) {
1447 const int32_t kiMbWidth = sMbSizeMap[iSpatialIdx].iMbWidth;
1448 const int32_t kiMbHeight = sMbSizeMap[iSpatialIdx].iCountMbNum / kiMbWidth;
1449 const int32_t kiLineSize = kiMbWidth * sizeof (int16_t);
1450 int16_t* pMbIndexY = pPtr->pMbIndexY[iSpatialIdx] + i * kiMbWidth;
1451
1452 if (i < kiMbHeight) {
1453 memcpy (pMbIndexY, pRowY, kiLineSize); // confirmed_safe_unsafe_usage
1454 }
1455 }
1456 ++ i;
1457 if (i >= iMaxMbHeight)
1458 break;
1459
1460 t32 = i | (i << 16);
1461 ST32 (t, t32);
1462 ST32 (t + 2, t32);
1463
1464 p = pRowY;
1465 while (j < iMaxMbWidth) {
1466 ST64 (p, LD64 (t));
1467
1468 p += 4;
1469 j += 4;
1470 }
1471 }
1472
1473 pMa->WelsFree (pTmpRow, "pTmpRow");
1474 pTmpRow = NULL;
1475
1476 return 0;
1477 }
RequestMemoryVaaScreen(SVAAFrameInfo * pVaa,CMemoryAlign * pMa,const int32_t iNumRef,const int32_t iCountMax8x8BNum)1478 int32_t RequestMemoryVaaScreen (SVAAFrameInfo* pVaa, CMemoryAlign* pMa, const int32_t iNumRef,
1479 const int32_t iCountMax8x8BNum) {
1480 SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pVaa);
1481
1482 pVaaExt->pVaaBlockStaticIdc[0] = (static_cast<uint8_t*> (pMa->WelsMallocz (iNumRef * iCountMax8x8BNum * sizeof (
1483 uint8_t), "pVaa->pVaaBlockStaticIdc[0]")));
1484 if (NULL == pVaaExt->pVaaBlockStaticIdc[0]) {
1485 return 1;
1486 }
1487
1488 for (int32_t idx = 1; idx < iNumRef; idx++) {
1489 pVaaExt->pVaaBlockStaticIdc[idx] = pVaaExt->pVaaBlockStaticIdc[idx - 1] + iCountMax8x8BNum;
1490 }
1491 return 0;
1492 }
ReleaseMemoryVaaScreen(SVAAFrameInfo * pVaa,CMemoryAlign * pMa,const int32_t iNumRef)1493 void ReleaseMemoryVaaScreen (SVAAFrameInfo* pVaa, CMemoryAlign* pMa, const int32_t iNumRef) {
1494 SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pVaa);
1495 if (pVaaExt && pMa && pVaaExt->pVaaBlockStaticIdc[0]) {
1496 pMa->WelsFree (pVaaExt->pVaaBlockStaticIdc[0], "pVaa->pVaaBlockStaticIdc[0]");
1497
1498 for (int32_t idx = 0; idx < iNumRef; idx++) {
1499 pVaaExt->pVaaBlockStaticIdc[idx] = NULL;
1500 }
1501 }
1502 }
1503 /*!
1504 * \brief request specific memory for SVC
1505 * \pParam pEncCtx sWelsEncCtx*
1506 * \return successful - 0; otherwise none 0 for failed
1507 */
GetMvMvdRange(SWelsSvcCodingParam * pParam,int32_t & iMvRange,int32_t & iMvdRange)1508 void GetMvMvdRange (SWelsSvcCodingParam* pParam, int32_t& iMvRange, int32_t& iMvdRange) {
1509 ELevelIdc iMinLevelIdc = LEVEL_5_2;
1510 int32_t iMinMv = 0;
1511 int32_t iMaxMv = 0;
1512 int32_t iFixMvRange = pParam->iUsageType ? EXPANDED_MV_RANGE : CAMERA_STARTMV_RANGE;
1513 int32_t iFixMvdRange = (pParam->iUsageType ? EXPANDED_MVD_RANGE : ((pParam->iSpatialLayerNum == 1) ? CAMERA_MVD_RANGE :
1514 CAMERA_HIGHLAYER_MVD_RANGE));
1515 for (int32_t iLayer = 0; iLayer < pParam->iSpatialLayerNum; iLayer++) {
1516 if (pParam->sSpatialLayers[iLayer].uiLevelIdc < iMinLevelIdc)
1517 iMinLevelIdc = pParam->sSpatialLayers[iLayer].uiLevelIdc;
1518 }
1519 const SLevelLimits* pLevelLimit = g_ksLevelLimits;
1520 while ((pLevelLimit->uiLevelIdc != LEVEL_5_2) && (pLevelLimit->uiLevelIdc != iMinLevelIdc))
1521 pLevelLimit++;
1522 iMinMv = (pLevelLimit->iMinVmv) >> 2;
1523 iMaxMv = (pLevelLimit->iMaxVmv) >> 2;
1524
1525 iMvRange = WELS_MIN (WELS_ABS (iMinMv), iMaxMv);
1526
1527 iMvRange = WELS_MIN (iMvRange, iFixMvRange);
1528
1529 iMvdRange = (iMvRange + 1) << 1;
1530
1531 iMvdRange = WELS_MIN (iMvdRange, iFixMvdRange);
1532 }
RequestMemorySvc(sWelsEncCtx ** ppCtx,SExistingParasetList * pExistingParasetList)1533 int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList) {
1534 SWelsSvcCodingParam* pParam = (*ppCtx)->pSvcParam;
1535 CMemoryAlign* pMa = (*ppCtx)->pMemAlign;
1536 SSpatialLayerConfig* pFinalSpatial = NULL;
1537 int32_t iCountBsLen = 0;
1538 int32_t iCountNals = 0;
1539 int32_t iMaxPicWidth = 0;
1540 int32_t iMaxPicHeight = 0;
1541 int32_t iCountMaxMbNum = 0;
1542 int32_t iIndex = 0;
1543 int32_t iCountLayers = 0;
1544 int32_t iResult = 0;
1545 float fCompressRatioThr = .5f;
1546 const int32_t kiNumDependencyLayers = pParam->iSpatialLayerNum;
1547 int32_t iVclLayersBsSizeCount = 0;
1548 int32_t iNonVclLayersBsSizeCount = 0;
1549 int32_t iTargetSpatialBsSize = 0;
1550
1551 if (kiNumDependencyLayers < 1 || kiNumDependencyLayers > MAX_DEPENDENCY_LAYER) {
1552 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc() failed due to invalid iNumDependencyLayers(%d)!",
1553 kiNumDependencyLayers);
1554 return 1;
1555 }
1556
1557 if (pParam->uiGopSize == 0 || (pParam->uiIntraPeriod && ((pParam->uiIntraPeriod % pParam->uiGopSize) != 0))) {
1558 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING,
1559 "RequestMemorySvc() failed due to invalid uiIntraPeriod(%d) (=multipler of uiGopSize(%d)!",
1560 pParam->uiIntraPeriod, pParam->uiGopSize);
1561 return 1;
1562 }
1563
1564 pFinalSpatial = &pParam->sSpatialLayers[kiNumDependencyLayers - 1];
1565 iMaxPicWidth = pFinalSpatial->iVideoWidth;
1566 iMaxPicHeight = pFinalSpatial->iVideoHeight;
1567 iCountMaxMbNum = ((15 + iMaxPicWidth) >> 4) * ((15 + iMaxPicHeight) >> 4);
1568
1569 iResult = AcquireLayersNals (ppCtx, pParam, &iCountLayers, &iCountNals);
1570 if (iResult) {
1571 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), AcquireLayersNals failed(%d)!", iResult);
1572 return 1;
1573 }
1574
1575 const int32_t kiSpsSize = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSpsNum() * SPS_BUFFER_SIZE;
1576 const int32_t kiPpsSize = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededPpsNum() * PPS_BUFFER_SIZE;
1577 iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + kiSpsSize + kiPpsSize;
1578
1579 bool bDynamicSlice = false;
1580 uint32_t uiMaxSliceNumEstimation = 0;
1581 int32_t iSliceBufferSize = 0;
1582 int32_t iMaxSliceBufferSize = 0;
1583 int32_t iTotalLength = 0;
1584 int32_t iLayerBsSize = 0;
1585 iIndex = 0;
1586 while (iIndex < pParam->iSpatialLayerNum) {
1587 SSpatialLayerConfig* fDlp = &pParam->sSpatialLayers[iIndex];
1588
1589 fCompressRatioThr = COMPRESS_RATIO_THR;
1590
1591 iLayerBsSize = WELS_ROUND (((3 * fDlp->iVideoWidth * fDlp->iVideoHeight) >> 1) * fCompressRatioThr) +
1592 MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
1593 iLayerBsSize = WELS_ALIGN (iLayerBsSize, 4); // 4 bytes alinged
1594 iVclLayersBsSizeCount += iLayerBsSize;
1595
1596 SSliceArgument* pSliceArgument = & (fDlp->sSliceArgument);
1597 if (pSliceArgument->uiSliceMode == SM_SIZELIMITED_SLICE) {
1598 bDynamicSlice = true;
1599 uiMaxSliceNumEstimation = WELS_MIN (AVERSLICENUM_CONSTRAINT,
1600 (iLayerBsSize / pSliceArgument->uiSliceSizeConstraint) + 1);
1601 (*ppCtx)->iMaxSliceCount = WELS_MAX ((*ppCtx)->iMaxSliceCount, (int) uiMaxSliceNumEstimation);
1602 iSliceBufferSize = (WELS_MAX (pSliceArgument->uiSliceSizeConstraint,
1603 iLayerBsSize / uiMaxSliceNumEstimation) << 1) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
1604 } else {
1605 (*ppCtx)->iMaxSliceCount = WELS_MAX ((*ppCtx)->iMaxSliceCount, (int) pSliceArgument->uiSliceNum);
1606 iSliceBufferSize = ((iLayerBsSize / pSliceArgument->uiSliceNum) << 1) + MAX_MACROBLOCK_SIZE_IN_BYTE_x2;
1607 }
1608 iMaxSliceBufferSize = WELS_MAX (iMaxSliceBufferSize, iSliceBufferSize);
1609 (*ppCtx)->iSliceBufferSize[iIndex] = iSliceBufferSize;
1610 ++ iIndex;
1611 }
1612 iTargetSpatialBsSize = iLayerBsSize;
1613 iCountBsLen = iNonVclLayersBsSizeCount + iVclLayersBsSizeCount;
1614
1615 iMaxSliceBufferSize = WELS_MIN (iMaxSliceBufferSize, iTargetSpatialBsSize);
1616 iTotalLength = iCountBsLen;
1617
1618 pParam->iNumRefFrame = WELS_CLIP3 (pParam->iNumRefFrame, MIN_REF_PIC_COUNT,
1619 (pParam->iUsageType == CAMERA_VIDEO_REAL_TIME ? MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA :
1620 MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN));
1621
1622 // Output
1623 (*ppCtx)->pOut = (SWelsEncoderOutput*)pMa->WelsMallocz (sizeof (SWelsEncoderOutput), "SWelsEncoderOutput");
1624 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pOut))
1625 (*ppCtx)->pOut->pBsBuffer = (uint8_t*)pMa->WelsMallocz (iCountBsLen, "pOut->pBsBuffer");
1626 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pOut->pBsBuffer))
1627 (*ppCtx)->pOut->uiSize = iCountBsLen;
1628 (*ppCtx)->pOut->sNalList = (SWelsNalRaw*)pMa->WelsMallocz (iCountNals * sizeof (SWelsNalRaw), "pOut->sNalList");
1629 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pOut->sNalList))
1630 (*ppCtx)->pOut->pNalLen = (int32_t*)pMa->WelsMallocz (iCountNals * sizeof (int32_t), "pOut->pNalLen");
1631 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pOut->pNalLen))
1632 (*ppCtx)->pOut->iCountNals = iCountNals;
1633 (*ppCtx)->pOut->iNalIndex = 0;
1634 (*ppCtx)->pOut->iLayerBsIndex = 0;
1635
1636 (*ppCtx)->pFrameBs = (uint8_t*)pMa->WelsMalloc (iTotalLength, "pFrameBs");
1637 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pFrameBs))
1638 (*ppCtx)->iFrameBsSize = iTotalLength;
1639 (*ppCtx)->iPosBsBuffer = 0;
1640
1641 // for dynamic slice mode&& CABAC,allocate slice buffer to restore slice data
1642 if (bDynamicSlice && pParam->iEntropyCodingModeFlag) {
1643 for (int32_t iIdx = 0; iIdx < MAX_THREADS_NUM; iIdx++) {
1644 (*ppCtx)->pDynamicBsBuffer[iIdx] = (uint8_t*)pMa->WelsMalloc (iMaxSliceBufferSize, "DynamicSliceBs");
1645 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pDynamicBsBuffer[iIdx]))
1646 }
1647 }
1648 // for pSlice bs buffers
1649 if (pParam->iMultipleThreadIdc > 1
1650 && RequestMtResource (ppCtx, pParam, iCountBsLen, iMaxSliceBufferSize, bDynamicSlice)) {
1651 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), RequestMtResource failed!");
1652 return 1;
1653 }
1654
1655 (*ppCtx)->pReferenceStrategy = IWelsReferenceStrategy::CreateReferenceStrategy ((*ppCtx), pParam->iUsageType,
1656 pParam->bEnableLongTermReference);
1657 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pReferenceStrategy))
1658
1659 (*ppCtx)->pIntra4x4PredModeBlocks = static_cast<int8_t*>
1660 (pMa->WelsMallocz (iCountMaxMbNum * INTRA_4x4_MODE_NUM, "pIntra4x4PredModeBlocks"));
1661 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pIntra4x4PredModeBlocks))
1662
1663 (*ppCtx)->pNonZeroCountBlocks = static_cast<int8_t*>
1664 (pMa->WelsMallocz (iCountMaxMbNum * MB_LUMA_CHROMA_BLOCK4x4_NUM, "pNonZeroCountBlocks"));
1665 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pNonZeroCountBlocks))
1666
1667 (*ppCtx)->pMvUnitBlock4x4 = static_cast<SMVUnitXY*>
1668 (pMa->WelsMallocz (iCountMaxMbNum * 2 * MB_BLOCK4x4_NUM * sizeof (SMVUnitXY), "pMvUnitBlock4x4"));
1669 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pMvUnitBlock4x4))
1670
1671 (*ppCtx)->pRefIndexBlock4x4 = static_cast<int8_t*>
1672 (pMa->WelsMallocz (iCountMaxMbNum * 2 * MB_BLOCK8x8_NUM * sizeof (int8_t), "pRefIndexBlock4x4"));
1673 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pRefIndexBlock4x4))
1674
1675 (*ppCtx)->pSadCostMb = static_cast<int32_t*>
1676 (pMa->WelsMallocz (iCountMaxMbNum * sizeof (int32_t), "pSadCostMb"));
1677 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pSadCostMb))
1678
1679 (*ppCtx)->iGlobalQp = 26; // global qp in default
1680
1681 (*ppCtx)->pLtr = (SLTRState*)pMa->WelsMallocz (kiNumDependencyLayers * sizeof (SLTRState), "SLTRState");
1682 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pLtr))
1683 int32_t i = 0;
1684 for (i = 0; i < kiNumDependencyLayers; i++) {
1685 ResetLtrState (& (*ppCtx)->pLtr[i]);
1686 }
1687
1688 // stride tables
1689 if (AllocStrideTables (ppCtx, kiNumDependencyLayers)) {
1690 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), AllocStrideTables failed!");
1691 return 1;
1692 }
1693
1694 //Rate control module memory allocation
1695 // only malloc once for RC pData, 12/14/2009
1696 (*ppCtx)->pWelsSvcRc = (SWelsSvcRc*)pMa->WelsMallocz (kiNumDependencyLayers * sizeof (SWelsSvcRc), "pWelsSvcRc");
1697 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pWelsSvcRc))
1698 //End of Rate control module memory allocation
1699
1700 //pVaa memory allocation
1701 if (pParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
1702 (*ppCtx)->pVaa = (SVAAFrameInfoExt*)pMa->WelsMallocz (sizeof (SVAAFrameInfoExt), "pVaa");
1703 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa))
1704 if (RequestMemoryVaaScreen ((*ppCtx)->pVaa, pMa, (*ppCtx)->pSvcParam->iMaxNumRefFrame, iCountMaxMbNum << 2)) {
1705 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), RequestMemoryVaaScreen failed!");
1706 return 1;
1707 }
1708 } else {
1709 (*ppCtx)->pVaa = (SVAAFrameInfo*)pMa->WelsMallocz (sizeof (SVAAFrameInfo), "pVaa");
1710 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa))
1711 }
1712
1713 if ((*ppCtx)->pSvcParam->bEnableAdaptiveQuant) { //malloc mem
1714 (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureUnit = static_cast<SMotionTextureUnit*>
1715 (pMa->WelsMallocz (iCountMaxMbNum * sizeof (SMotionTextureUnit), "pVaa->sAdaptiveQuantParam.pMotionTextureUnit"));
1716 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureUnit))
1717 (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp = static_cast<int8_t*>
1718 (pMa->WelsMallocz (iCountMaxMbNum * sizeof (int8_t), "pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp"));
1719 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp))
1720 }
1721
1722 (*ppCtx)->pVaa->pVaaBackgroundMbFlag = (int8_t*)pMa->WelsMallocz (iCountMaxMbNum * sizeof (int8_t),
1723 "pVaa->pVaaBackgroundMbFlag");
1724 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->pVaaBackgroundMbFlag))
1725
1726 (*ppCtx)->pVaa->sVaaCalcInfo.pSad8x8 = static_cast<int32_t (*)[4]>
1727 (pMa->WelsMallocz (iCountMaxMbNum * 4 * sizeof (int32_t), "pVaa->sVaaCalcInfo.sad8x8"));
1728 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSad8x8))
1729 (*ppCtx)->pVaa->sVaaCalcInfo.pSsd16x16 = static_cast<int32_t*>
1730 (pMa->WelsMallocz (iCountMaxMbNum * sizeof (int32_t), "pVaa->sVaaCalcInfo.pSsd16x16"));
1731 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSsd16x16))
1732 (*ppCtx)->pVaa->sVaaCalcInfo.pSum16x16 = static_cast<int32_t*>
1733 (pMa->WelsMallocz (iCountMaxMbNum * sizeof (int32_t), "pVaa->sVaaCalcInfo.pSum16x16"));
1734 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSum16x16))
1735 (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfSquare16x16 = static_cast<int32_t*>
1736 (pMa->WelsMallocz (iCountMaxMbNum * sizeof (int32_t), "pVaa->sVaaCalcInfo.pSumOfSquare16x16"));
1737 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfSquare16x16))
1738
1739 if ((*ppCtx)->pSvcParam->bEnableBackgroundDetection) { //BGD control
1740 (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfDiff8x8 = static_cast<int32_t (*)[4]>
1741 (pMa->WelsMallocz (iCountMaxMbNum * 4 * sizeof (int32_t), "pVaa->sVaaCalcInfo.pSumOfDiff8x8"));
1742 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pSumOfDiff8x8))
1743 (*ppCtx)->pVaa->sVaaCalcInfo.pMad8x8 = static_cast<uint8_t (*)[4]>
1744 (pMa->WelsMallocz (iCountMaxMbNum * 4 * sizeof (uint8_t), "pVaa->sVaaCalcInfo.pMad8x8"));
1745 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pVaa->sVaaCalcInfo.pMad8x8))
1746 }
1747
1748 //End of pVaa memory allocation
1749
1750 (*ppCtx)->ppRefPicListExt = (SRefList**)pMa->WelsMallocz (kiNumDependencyLayers * sizeof (SRefList*),
1751 "ppRefPicListExt");
1752 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->ppRefPicListExt))
1753
1754 (*ppCtx)->ppDqLayerList = (SDqLayer**)pMa->WelsMallocz (kiNumDependencyLayers * sizeof (SDqLayer*), "ppDqLayerList");
1755 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->ppDqLayerList))
1756
1757 iResult = InitDqLayers (ppCtx, pExistingParasetList);
1758 if (iResult) {
1759 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitDqLayers failed(%d)!", iResult);
1760 return iResult;
1761 }
1762
1763 if (InitMbListD (ppCtx)) {
1764 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitMbListD failed!");
1765 return 1;
1766 }
1767
1768 int32_t iMvdRange = 0;
1769 GetMvMvdRange (pParam, (*ppCtx)->iMvRange, iMvdRange);
1770 const uint32_t kuiMvdInterTableSize = (iMvdRange << 2); //intepel*4=qpel
1771 const uint32_t kuiMvdInterTableStride = 1 + (kuiMvdInterTableSize << 1);//qpel_mv_range*2=(+/-);
1772 const uint32_t kuiMvdCacheAlignedSize = kuiMvdInterTableStride * sizeof (uint16_t);
1773
1774 (*ppCtx)->iMvdCostTableSize = kuiMvdInterTableSize;
1775 (*ppCtx)->iMvdCostTableStride = kuiMvdInterTableStride;
1776 (*ppCtx)->pMvdCostTable = (uint16_t*)pMa->WelsMallocz (52 * kuiMvdCacheAlignedSize, "pMvdCostTable");
1777 WELS_VERIFY_RETURN_IF (1, (NULL == (*ppCtx)->pMvdCostTable))
1778 MvdCostInit ((*ppCtx)->pMvdCostTable, kuiMvdInterTableStride); //should put to a better place?
1779
1780 if ((*ppCtx)->ppRefPicListExt[0] != NULL && (*ppCtx)->ppRefPicListExt[0]->pRef[0] != NULL)
1781 (*ppCtx)->pDecPic = (*ppCtx)->ppRefPicListExt[0]->pRef[0];
1782 else
1783 (*ppCtx)->pDecPic = NULL; // error here
1784
1785 (*ppCtx)->pSps = & (*ppCtx)->pSpsArray[0];
1786 (*ppCtx)->pPps = & (*ppCtx)->pPPSArray[0];
1787
1788 return 0;
1789 }
1790
1791
1792 /*!
1793 * \brief free memory in SVC core encoder
1794 * \pParam pEncCtx sWelsEncCtx*
1795 * \return none
1796 */
FreeMemorySvc(sWelsEncCtx ** ppCtx)1797 void FreeMemorySvc (sWelsEncCtx** ppCtx) {
1798 if (NULL != *ppCtx) {
1799 sWelsEncCtx* pCtx = *ppCtx;
1800 CMemoryAlign* pMa = pCtx->pMemAlign;
1801 SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
1802 int32_t ilayer = 0;
1803
1804 // SStrideTables
1805 if (NULL != pCtx->pStrideTab) {
1806 if (NULL != pCtx->pStrideTab->pStrideDecBlockOffset[0][1]) {
1807 pMa->WelsFree (pCtx->pStrideTab->pStrideDecBlockOffset[0][1], "pBase");
1808 pCtx->pStrideTab->pStrideDecBlockOffset[0][1] = NULL;
1809 }
1810 pMa->WelsFree (pCtx->pStrideTab, "SStrideTables");
1811 pCtx->pStrideTab = NULL;
1812 }
1813 // pDq idc map
1814 if (NULL != pCtx->pDqIdcMap) {
1815 pMa->WelsFree (pCtx->pDqIdcMap, "pDqIdcMap");
1816 pCtx->pDqIdcMap = NULL;
1817 }
1818
1819 if (NULL != pCtx->pOut) {
1820 // bs pBuffer
1821 if (NULL != pCtx->pOut->pBsBuffer) {
1822 pMa->WelsFree (pCtx->pOut->pBsBuffer, "pOut->pBsBuffer");
1823 pCtx->pOut->pBsBuffer = NULL;
1824 }
1825 // NALs list
1826 if (NULL != pCtx->pOut->sNalList) {
1827 pMa->WelsFree (pCtx->pOut->sNalList, "pOut->sNalList");
1828 pCtx->pOut->sNalList = NULL;
1829 }
1830 // NALs len
1831 if (NULL != pCtx->pOut->pNalLen) {
1832 pMa->WelsFree (pCtx->pOut->pNalLen, "pOut->pNalLen");
1833 pCtx->pOut->pNalLen = NULL;
1834 }
1835 pMa->WelsFree (pCtx->pOut, "SWelsEncoderOutput");
1836 pCtx->pOut = NULL;
1837 }
1838
1839 if (pParam != NULL && pParam->iMultipleThreadIdc > 1)
1840 ReleaseMtResource (ppCtx);
1841
1842 if (NULL != pCtx->pReferenceStrategy) {
1843 WELS_DELETE_OP (pCtx->pReferenceStrategy);
1844 }
1845
1846 // frame bitstream pBuffer
1847 if (NULL != pCtx->pFrameBs) {
1848 pMa->WelsFree (pCtx->pFrameBs, "pFrameBs");
1849 pCtx->pFrameBs = NULL;
1850 }
1851 for (int32_t iIdx = 0; iIdx < MAX_THREADS_NUM; iIdx++) {
1852 pMa->WelsFree (pCtx->pDynamicBsBuffer[iIdx], "DynamicSliceBs");
1853 pCtx->pDynamicBsBuffer[iIdx] = NULL;
1854
1855 }
1856 // pSpsArray
1857 if (NULL != pCtx->pSpsArray) {
1858 pMa->WelsFree (pCtx->pSpsArray, "pSpsArray");
1859 pCtx->pSpsArray = NULL;
1860 }
1861 // pPPSArray
1862 if (NULL != pCtx->pPPSArray) {
1863 pMa->WelsFree (pCtx->pPPSArray, "pPPSArray");
1864 pCtx->pPPSArray = NULL;
1865 }
1866 // subset_sps_array
1867 if (NULL != pCtx->pSubsetArray) {
1868 pMa->WelsFree (pCtx->pSubsetArray, "pSubsetArray");
1869 pCtx->pSubsetArray = NULL;
1870 }
1871
1872 if (NULL != pCtx->pIntra4x4PredModeBlocks) {
1873 pMa->WelsFree (pCtx->pIntra4x4PredModeBlocks, "pIntra4x4PredModeBlocks");
1874 pCtx->pIntra4x4PredModeBlocks = NULL;
1875 }
1876
1877 if (NULL != pCtx->pNonZeroCountBlocks) {
1878 pMa->WelsFree (pCtx->pNonZeroCountBlocks, "pNonZeroCountBlocks");
1879 pCtx->pNonZeroCountBlocks = NULL;
1880 }
1881
1882 if (NULL != pCtx->pMvUnitBlock4x4) {
1883 pMa->WelsFree (pCtx->pMvUnitBlock4x4, "pMvUnitBlock4x4");
1884 pCtx->pMvUnitBlock4x4 = NULL;
1885 }
1886
1887 if (NULL != pCtx->pRefIndexBlock4x4) {
1888 pMa->WelsFree (pCtx->pRefIndexBlock4x4, "pRefIndexBlock4x4");
1889 pCtx->pRefIndexBlock4x4 = NULL;
1890 }
1891
1892 if (NULL != pCtx->ppMbListD) {
1893 if (NULL != pCtx->ppMbListD[0]) {
1894 pMa->WelsFree (pCtx->ppMbListD[0], "ppMbListD[0]");
1895 (*ppCtx)->ppMbListD[0] = NULL;
1896 }
1897 pMa->WelsFree (pCtx->ppMbListD, "ppMbListD");
1898 pCtx->ppMbListD = NULL;
1899 }
1900
1901 if (NULL != pCtx->pSadCostMb) {
1902 pMa->WelsFree (pCtx->pSadCostMb, "pSadCostMb");
1903 pCtx->pSadCostMb = NULL;
1904 }
1905
1906 // SLTRState
1907 if (NULL != pCtx->pLtr) {
1908 pMa->WelsFree (pCtx->pLtr, "SLTRState");
1909 pCtx->pLtr = NULL;
1910 }
1911
1912 // pDq layers list
1913 ilayer = 0;
1914 if (NULL != pCtx->ppDqLayerList && pParam != NULL) {
1915 while (ilayer < pParam->iSpatialLayerNum) {
1916 SDqLayer* pDq = pCtx->ppDqLayerList[ilayer];
1917 // pDq layers
1918 if (NULL != pDq) {
1919 FreeDqLayer (pDq, pMa);
1920 pCtx->ppDqLayerList[ilayer] = NULL;
1921 }
1922 ++ ilayer;
1923 }
1924 pMa->WelsFree (pCtx->ppDqLayerList, "ppDqLayerList");
1925 pCtx->ppDqLayerList = NULL;
1926 }
1927 // reference picture list extension
1928 if (NULL != pCtx->ppRefPicListExt && pParam != NULL) {
1929 ilayer = 0;
1930 while (ilayer < pParam->iSpatialLayerNum) {
1931 FreeRefList (pCtx->ppRefPicListExt[ilayer], pMa, pParam->iMaxNumRefFrame);
1932 pCtx->ppRefPicListExt[ilayer] = NULL;
1933 ++ ilayer;
1934 }
1935
1936 pMa->WelsFree (pCtx->ppRefPicListExt, "ppRefPicListExt");
1937 pCtx->ppRefPicListExt = NULL;
1938 }
1939
1940 // VAA
1941 if (NULL != pCtx->pVaa) {
1942 if (pCtx->pSvcParam->bEnableAdaptiveQuant) { //free mem
1943 pMa->WelsFree (pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureUnit, "pVaa->sAdaptiveQuantParam.pMotionTextureUnit");
1944 pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureUnit = NULL;
1945 pMa->WelsFree (pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp,
1946 "pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp");
1947 pCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp = NULL;
1948 }
1949
1950 pMa->WelsFree (pCtx->pVaa->pVaaBackgroundMbFlag, "pVaa->pVaaBackgroundMbFlag");
1951 pCtx->pVaa->pVaaBackgroundMbFlag = NULL;
1952 pMa->WelsFree (pCtx->pVaa->sVaaCalcInfo.pSad8x8, "pVaa->sVaaCalcInfo.sad8x8");
1953 pCtx->pVaa->sVaaCalcInfo.pSad8x8 = NULL;
1954 pMa->WelsFree (pCtx->pVaa->sVaaCalcInfo.pSsd16x16, "pVaa->sVaaCalcInfo.pSsd16x16");
1955 pCtx->pVaa->sVaaCalcInfo.pSsd16x16 = NULL;
1956 pMa->WelsFree (pCtx->pVaa->sVaaCalcInfo.pSum16x16, "pVaa->sVaaCalcInfo.pSum16x16");
1957 pCtx->pVaa->sVaaCalcInfo.pSum16x16 = NULL;
1958 pMa->WelsFree (pCtx->pVaa->sVaaCalcInfo.pSumOfSquare16x16, "pVaa->sVaaCalcInfo.pSumOfSquare16x16");
1959 pCtx->pVaa->sVaaCalcInfo.pSumOfSquare16x16 = NULL;
1960
1961 if (pCtx->pSvcParam->bEnableBackgroundDetection) { //BGD control
1962 pMa->WelsFree (pCtx->pVaa->sVaaCalcInfo.pSumOfDiff8x8, "pVaa->sVaaCalcInfo.pSumOfDiff8x8");
1963 pCtx->pVaa->sVaaCalcInfo.pSumOfDiff8x8 = NULL;
1964 pMa->WelsFree (pCtx->pVaa->sVaaCalcInfo.pMad8x8, "pVaa->sVaaCalcInfo.pMad8x8");
1965 pCtx->pVaa->sVaaCalcInfo.pMad8x8 = NULL;
1966 }
1967 if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME)
1968 ReleaseMemoryVaaScreen (pCtx->pVaa, pMa, pCtx->pSvcParam->iMaxNumRefFrame);
1969 pMa->WelsFree (pCtx->pVaa, "pVaa");
1970 pCtx->pVaa = NULL;
1971 }
1972
1973 // rate control module memory free
1974 if (NULL != pCtx->pWelsSvcRc) {
1975 WelsRcFreeMemory (pCtx);
1976 pMa->WelsFree (pCtx->pWelsSvcRc, "pWelsSvcRc");
1977 pCtx->pWelsSvcRc = NULL;
1978 }
1979
1980 /* MVD cost tables for Inter */
1981 if (NULL != pCtx->pMvdCostTable) {
1982 pMa->WelsFree (pCtx->pMvdCostTable, "pMvdCostTable");
1983 pCtx->pMvdCostTable = NULL;
1984 }
1985
1986 FreeCodingParam (&pCtx->pSvcParam, pMa);
1987 if (NULL != pCtx->pFuncList) {
1988 if (NULL != pCtx->pFuncList->pParametersetStrategy) {
1989 WELS_DELETE_OP (pCtx->pFuncList->pParametersetStrategy);
1990 }
1991
1992 pMa->WelsFree (pCtx->pFuncList, "SWelsFuncPtrList");
1993 pCtx->pFuncList = NULL;
1994 }
1995
1996 #if defined(MEMORY_MONITOR)
1997 assert (pMa->WelsGetMemoryUsage() == 0); // ensure all memory free well
1998 #endif//MEMORY_MONITOR
1999
2000 if ((*ppCtx)->pMemAlign != NULL) {
2001 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO, "FreeMemorySvc(), verify memory usage (%d bytes) after free..",
2002 (*ppCtx)->pMemAlign->WelsGetMemoryUsage());
2003 WELS_DELETE_OP ((*ppCtx)->pMemAlign);
2004 }
2005
2006 free (*ppCtx);
2007 *ppCtx = NULL;
2008 }
2009 }
2010
InitSliceSettings(SLogContext * pLogCtx,SWelsSvcCodingParam * pCodingParam,const int32_t kiCpuCores,int16_t * pMaxSliceCount)2011 int32_t InitSliceSettings (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingParam,
2012 const int32_t kiCpuCores, int16_t* pMaxSliceCount) {
2013 int32_t iSpatialIdx = 0, iSpatialNum = pCodingParam->iSpatialLayerNum;
2014 uint16_t iMaxSliceCount = 0;
2015
2016 do {
2017 SSpatialLayerConfig* pDlp = &pCodingParam->sSpatialLayers[iSpatialIdx];
2018 SSliceArgument* pSliceArgument = &pDlp->sSliceArgument;
2019 int32_t iReturn = 0;
2020
2021 switch (pSliceArgument->uiSliceMode) {
2022 case SM_SIZELIMITED_SLICE:
2023 iMaxSliceCount = AVERSLICENUM_CONSTRAINT;
2024 break; // go through for SM_SIZELIMITED_SLICE?
2025 case SM_FIXEDSLCNUM_SLICE: {
2026 iReturn = SliceArgumentValidationFixedSliceMode (pLogCtx, &pDlp->sSliceArgument, pCodingParam->iRCMode,
2027 pDlp->iVideoWidth, pDlp->iVideoHeight);
2028 if (iReturn)
2029 return ENC_RETURN_UNSUPPORTED_PARA;
2030
2031 if (pSliceArgument->uiSliceNum > iMaxSliceCount) {
2032 iMaxSliceCount = pSliceArgument->uiSliceNum;
2033 }
2034 }
2035 break;
2036 case SM_SINGLE_SLICE:
2037 if (pSliceArgument->uiSliceNum > iMaxSliceCount)
2038 iMaxSliceCount = pSliceArgument->uiSliceNum;
2039 break;
2040 case SM_RASTER_SLICE:
2041 if (pSliceArgument->uiSliceNum > iMaxSliceCount)
2042 iMaxSliceCount = pSliceArgument->uiSliceNum;
2043 break;
2044 default:
2045 break;
2046 }
2047
2048 ++ iSpatialIdx;
2049 } while (iSpatialIdx < iSpatialNum);
2050
2051 pCodingParam->iMultipleThreadIdc = WELS_MIN (kiCpuCores, iMaxSliceCount);
2052 if (pCodingParam->iLoopFilterDisableIdc == 0
2053 && pCodingParam->iMultipleThreadIdc != 1) // Loop filter requested to be enabled, with threading enabled
2054 pCodingParam->iLoopFilterDisableIdc =
2055 2; // Disable loop filter on slice boundaries since that's not allowed with multithreading
2056 *pMaxSliceCount = iMaxSliceCount;
2057
2058 return ENC_RETURN_SUCCESS;
2059 }
2060
2061 /*!
2062 * \brief log output for cpu features/capabilities
2063 */
OutputCpuFeaturesLog(SLogContext * pLogCtx,uint32_t uiCpuFeatureFlags,uint32_t uiCpuCores,int32_t iCacheLineSize)2064 void OutputCpuFeaturesLog (SLogContext* pLogCtx, uint32_t uiCpuFeatureFlags, uint32_t uiCpuCores,
2065 int32_t iCacheLineSize) {
2066 // welstracer output
2067 WelsLog (pLogCtx, WELS_LOG_INFO, "WELS CPU features/capacities (0x%x) detected: \t"
2068 "HTT: %c, "
2069 "MMX: %c, "
2070 "MMXEX: %c, "
2071 "SSE: %c, "
2072 "SSE2: %c, "
2073 "SSE3: %c, "
2074 "SSSE3: %c, "
2075 "SSE4.1: %c, "
2076 "SSE4.2: %c, "
2077 "AVX: %c, "
2078 "FMA: %c, "
2079 "X87-FPU: %c, "
2080 "3DNOW: %c, "
2081 "3DNOWEX: %c, "
2082 "ALTIVEC: %c, "
2083 "CMOV: %c, "
2084 "MOVBE: %c, "
2085 "AES: %c, "
2086 "NUMBER OF LOGIC PROCESSORS ON CHIP: %d, "
2087 "CPU CACHE LINE SIZE (BYTES): %d",
2088 uiCpuFeatureFlags,
2089 (uiCpuFeatureFlags & WELS_CPU_HTT) ? 'Y' : 'N',
2090 (uiCpuFeatureFlags & WELS_CPU_MMX) ? 'Y' : 'N',
2091 (uiCpuFeatureFlags & WELS_CPU_MMXEXT) ? 'Y' : 'N',
2092 (uiCpuFeatureFlags & WELS_CPU_SSE) ? 'Y' : 'N',
2093 (uiCpuFeatureFlags & WELS_CPU_SSE2) ? 'Y' : 'N',
2094 (uiCpuFeatureFlags & WELS_CPU_SSE3) ? 'Y' : 'N',
2095 (uiCpuFeatureFlags & WELS_CPU_SSSE3) ? 'Y' : 'N',
2096 (uiCpuFeatureFlags & WELS_CPU_SSE41) ? 'Y' : 'N',
2097 (uiCpuFeatureFlags & WELS_CPU_SSE42) ? 'Y' : 'N',
2098 (uiCpuFeatureFlags & WELS_CPU_AVX) ? 'Y' : 'N',
2099 (uiCpuFeatureFlags & WELS_CPU_FMA) ? 'Y' : 'N',
2100 (uiCpuFeatureFlags & WELS_CPU_FPU) ? 'Y' : 'N',
2101 (uiCpuFeatureFlags & WELS_CPU_3DNOW) ? 'Y' : 'N',
2102 (uiCpuFeatureFlags & WELS_CPU_3DNOWEXT) ? 'Y' : 'N',
2103 (uiCpuFeatureFlags & WELS_CPU_ALTIVEC) ? 'Y' : 'N',
2104 (uiCpuFeatureFlags & WELS_CPU_CMOV) ? 'Y' : 'N',
2105 (uiCpuFeatureFlags & WELS_CPU_MOVBE) ? 'Y' : 'N',
2106 (uiCpuFeatureFlags & WELS_CPU_AES) ? 'Y' : 'N',
2107 uiCpuCores,
2108 iCacheLineSize);
2109 }
2110 /*
2111 *
2112 * status information output
2113 */
2114 #if defined(STAT_OUTPUT)
StatOverallEncodingExt(sWelsEncCtx * pCtx)2115 void StatOverallEncodingExt (sWelsEncCtx* pCtx) {
2116 int8_t i = 0;
2117 int8_t j = 0;
2118 for (i = 0; i < pCtx->pSvcParam->iSpatialLayerNum; i++) {
2119 fprintf (stdout, "\nDependency layer : %d\n", i);
2120 fprintf (stdout, "Quality layer : %d\n", j);
2121 {
2122 const int32_t iCount = pCtx->sStatData[i][j].sSliceData.iSliceCount[I_SLICE] +
2123 pCtx->sStatData[i][j].sSliceData.iSliceCount[P_SLICE] +
2124 pCtx->sStatData[i][j].sSliceData.iSliceCount[B_SLICE];
2125 #if defined(MB_TYPES_CHECK)
2126 if (iCount > 0) {
2127 int32_t iCountNumIMb = pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra4x4] +
2128 pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra16x16] + pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][7];
2129 int32_t iCountNumPMb = pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra4x4] +
2130 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra16x16] +
2131 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][7] +
2132 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] +
2133 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] +
2134 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] +
2135 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] +
2136 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10] +
2137 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][PSkip];
2138 int32_t count_p_mbL0 = pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] +
2139 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] +
2140 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] +
2141 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] +
2142 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10];
2143
2144 int32_t iMbCount = iCountNumIMb + iCountNumPMb;
2145 if (iMbCount > 0) {
2146 fprintf (stderr,
2147 "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",
2148 iMbCount,
2149 (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra4x4] +
2150 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra4x4]) / iMbCount),
2151 (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][Intra16x16] +
2152 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Intra16x16]) / iMbCount),
2153 (100.0f * (pCtx->sStatData[i][j].sSliceData.iMbCount[I_SLICE][7] +
2154 pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][7]) / iMbCount),
2155 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x16] / iMbCount),
2156 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter16x8] / iMbCount),
2157 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x16] / iMbCount),
2158 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][Inter8x8] / iMbCount),
2159 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][10] / iMbCount),
2160 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][PSkip] / iMbCount),
2161 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][11] / iMbCount),
2162 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][11] / count_p_mbL0),
2163 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][8] / count_p_mbL0),
2164 (100.0f * pCtx->sStatData[i][j].sSliceData.iMbCount[P_SLICE][9] / count_p_mbL0)
2165 );
2166 }
2167 }
2168 #endif //#if defined(MB_TYPES_CHECK)
2169
2170 if (iCount > 0) {
2171 fprintf (stdout, "SVC: overall PSNR Y: %2.3f U: %2.3f V: %2.3f kb/s: %.1f fps: %.3f\n\n",
2172 (pCtx->sStatData[i][j].sQualityStat.rYPsnr[I_SLICE] + pCtx->sStatData[i][j].sQualityStat.rYPsnr[P_SLICE] +
2173 pCtx->sStatData[i][j].sQualityStat.rYPsnr[B_SLICE]) / (float) (iCount),
2174 (pCtx->sStatData[i][j].sQualityStat.rUPsnr[I_SLICE] + pCtx->sStatData[i][j].sQualityStat.rUPsnr[P_SLICE] +
2175 pCtx->sStatData[i][j].sQualityStat.rUPsnr[B_SLICE]) / (float) (iCount),
2176 (pCtx->sStatData[i][j].sQualityStat.rVPsnr[I_SLICE] + pCtx->sStatData[i][j].sQualityStat.rVPsnr[P_SLICE] +
2177 pCtx->sStatData[i][j].sQualityStat.rVPsnr[B_SLICE]) / (float) (iCount),
2178 1.0f * pCtx->pSvcParam->sDependencyLayers[i].fOutputFrameRate * (pCtx->sStatData[i][j].sSliceData.iSliceSize[I_SLICE] +
2179 pCtx->sStatData[i][j].sSliceData.iSliceSize[P_SLICE] + pCtx->sStatData[i][j].sSliceData.iSliceSize[B_SLICE]) / (float) (
2180 iCount + pCtx->pWelsSvcRc[i].iSkipFrameNum) / 1000,
2181 1.0f * pCtx->pSvcParam->sDependencyLayers[i].fOutputFrameRate);
2182
2183 }
2184
2185 }
2186
2187 }
2188 }
2189 #endif
2190
2191
GetMultipleThreadIdc(SLogContext * pLogCtx,SWelsSvcCodingParam * pCodingParam,int16_t & iSliceNum,int32_t & iCacheLineSize,uint32_t & uiCpuFeatureFlags)2192 int32_t GetMultipleThreadIdc (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingParam, int16_t& iSliceNum,
2193 int32_t& iCacheLineSize, uint32_t& uiCpuFeatureFlags) {
2194 // for cpu features detection, Only detect once??
2195 int32_t uiCpuCores =
2196 0; // number of logic processors on physical processor package, zero logic processors means HTT not supported
2197 uiCpuFeatureFlags = WelsCPUFeatureDetect (&uiCpuCores); // detect cpu capacity features
2198
2199 #ifdef X86_ASM
2200 if (uiCpuFeatureFlags & WELS_CPU_CACHELINE_128)
2201 iCacheLineSize = 128;
2202 else if (uiCpuFeatureFlags & WELS_CPU_CACHELINE_64)
2203 iCacheLineSize = 64;
2204 else if (uiCpuFeatureFlags & WELS_CPU_CACHELINE_32)
2205 iCacheLineSize = 32;
2206 else if (uiCpuFeatureFlags & WELS_CPU_CACHELINE_16)
2207 iCacheLineSize = 16;
2208 OutputCpuFeaturesLog (pLogCtx, uiCpuFeatureFlags, uiCpuCores, iCacheLineSize);
2209 #else
2210 iCacheLineSize = 16; // 16 bytes aligned in default
2211 #endif//X86_ASM
2212
2213 if (0 == pCodingParam->iMultipleThreadIdc && uiCpuCores == 0) {
2214 // cpuid not supported or doesn't expose the number of cores,
2215 // use high level system API as followed to detect number of pysical/logic processor
2216 uiCpuCores = DynamicDetectCpuCores();
2217 }
2218
2219 if (0 == pCodingParam->iMultipleThreadIdc)
2220 pCodingParam->iMultipleThreadIdc = (uiCpuCores > 0) ? uiCpuCores : 1;
2221
2222 // So far so many cpu cores up to MAX_THREADS_NUM mean for server platforms,
2223 // for client application here it is constrained by maximal to MAX_THREADS_NUM
2224 pCodingParam->iMultipleThreadIdc = WELS_CLIP3 (pCodingParam->iMultipleThreadIdc, 1, MAX_THREADS_NUM);
2225 uiCpuCores = pCodingParam->iMultipleThreadIdc;
2226
2227 if (InitSliceSettings (pLogCtx, pCodingParam, uiCpuCores, &iSliceNum)) {
2228 WelsLog (pLogCtx, WELS_LOG_ERROR, "GetMultipleThreadIdc(), InitSliceSettings failed.");
2229 return 1;
2230 }
2231 return 0;
2232 }
2233
2234 /*!
2235 * \brief uninitialize Wels encoder core library
2236 * \pParam pEncCtx sWelsEncCtx*
2237 * \return none
2238 */
WelsUninitEncoderExt(sWelsEncCtx ** ppCtx)2239 void WelsUninitEncoderExt (sWelsEncCtx** ppCtx) {
2240 if (NULL == ppCtx || NULL == *ppCtx)
2241 return;
2242
2243 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
2244 "WelsUninitEncoderExt(), pCtx= %p, iMultipleThreadIdc= %d.",
2245 (void*) (*ppCtx), (*ppCtx)->pSvcParam->iMultipleThreadIdc);
2246
2247 #if defined(STAT_OUTPUT)
2248 StatOverallEncodingExt (*ppCtx);
2249 #endif
2250
2251 if ((*ppCtx)->pSvcParam->iMultipleThreadIdc > 1 && (*ppCtx)->pSliceThreading != NULL) {
2252 const int32_t iThreadCount = (*ppCtx)->pSvcParam->iMultipleThreadIdc;
2253 int32_t iThreadIdx = 0;
2254
2255 while (iThreadIdx < iThreadCount) {
2256 int res = 0;
2257 if ((*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx]) {
2258
2259 res = WelsThreadJoin ((*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx]); // waiting thread exit
2260 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pthread_join(pThreadHandles%d) return %d..",
2261 iThreadIdx,
2262 res);
2263 (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] = 0;
2264 }
2265 ++ iThreadIdx;
2266 }
2267 }
2268
2269 if ((*ppCtx)->pVpp) {
2270 (*ppCtx)->pVpp->FreeSpatialPictures (*ppCtx);
2271 WELS_DELETE_OP ((*ppCtx)->pVpp);
2272 }
2273 FreeMemorySvc (ppCtx);
2274 *ppCtx = NULL;
2275 }
2276
2277 /*!
2278 * \brief initialize Wels avc encoder core library
2279 * \pParam ppCtx sWelsEncCtx**
2280 * \pParam pParam SWelsSvcCodingParam*
2281 * \return successful - 0; otherwise none 0 for failed
2282 */
WelsInitEncoderExt(sWelsEncCtx ** ppCtx,SWelsSvcCodingParam * pCodingParam,SLogContext * pLogCtx,SExistingParasetList * pExistingParasetList)2283 int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx,
2284 SExistingParasetList* pExistingParasetList) {
2285 sWelsEncCtx* pCtx = NULL;
2286 int32_t iRet = 0;
2287 int16_t iSliceNum = 1; // number of slices used
2288 int32_t iCacheLineSize = 16; // on chip cache line size in byte
2289 uint32_t uiCpuFeatureFlags = 0;
2290 if (NULL == ppCtx || NULL == pCodingParam) {
2291 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), NULL == ppCtx(0x%p) or NULL == pCodingParam(0x%p).",
2292 (void*)ppCtx, (void*)pCodingParam);
2293 return 1;
2294 }
2295
2296 iRet = ParamValidationExt (pLogCtx, pCodingParam);
2297 if (iRet != 0) {
2298 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), ParamValidationExt failed return %d.", iRet);
2299 return iRet;
2300 }
2301 iRet = pCodingParam->DetermineTemporalSettings();
2302 if (iRet != ENC_RETURN_SUCCESS) {
2303 WelsLog (pLogCtx, WELS_LOG_ERROR,
2304 "WelsInitEncoderExt(), DetermineTemporalSettings failed return %d (check in/out frame rate and temporal layer setting! -- in/out = 2^x, x <= temppral_layer_num)",
2305 iRet);
2306 return iRet;
2307 }
2308 iRet = GetMultipleThreadIdc (pLogCtx, pCodingParam, iSliceNum, iCacheLineSize, uiCpuFeatureFlags);
2309 if (iRet != 0) {
2310 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), GetMultipleThreadIdc failed return %d.", iRet);
2311 return iRet;
2312 }
2313
2314
2315 *ppCtx = NULL;
2316
2317 pCtx = static_cast<sWelsEncCtx*> (malloc (sizeof (sWelsEncCtx)));
2318
2319 WELS_VERIFY_RETURN_IF (1, (NULL == pCtx))
2320 memset (pCtx, 0, sizeof (sWelsEncCtx));
2321
2322 pCtx->sLogCtx = *pLogCtx;
2323
2324 pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);
2325 WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pCtx->pMemAlign), WelsUninitEncoderExt (&pCtx))
2326
2327 iRet = AllocCodingParam (&pCtx->pSvcParam, pCtx->pMemAlign);
2328 if (iRet != 0) {
2329 WelsUninitEncoderExt (&pCtx);
2330 return iRet;
2331 }
2332 memcpy (pCtx->pSvcParam, pCodingParam, sizeof (SWelsSvcCodingParam)); // confirmed_safe_unsafe_usage
2333
2334 pCtx->pFuncList = (SWelsFuncPtrList*)pCtx->pMemAlign->WelsMallocz (sizeof (SWelsFuncPtrList), "SWelsFuncPtrList");
2335 if (NULL == pCtx->pFuncList) {
2336 WelsUninitEncoderExt (&pCtx);
2337 return 1;
2338 }
2339 InitFunctionPointers (pCtx, pCtx->pSvcParam, uiCpuFeatureFlags);
2340
2341 pCtx->iActiveThreadsNum = pCodingParam->iMultipleThreadIdc;
2342 pCtx->iMaxSliceCount = iSliceNum;
2343 iRet = RequestMemorySvc (&pCtx, pExistingParasetList);
2344 if (iRet != 0) {
2345 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), RequestMemorySvc failed return %d.", iRet);
2346 WelsUninitEncoderExt (&pCtx);
2347 return iRet;
2348 }
2349
2350 if (pCodingParam->iEntropyCodingModeFlag)
2351 WelsCabacInit (pCtx);
2352 WelsRcInitModule (pCtx, pCtx->pSvcParam->iRCMode);
2353
2354 pCtx->pVpp = CWelsPreProcess::CreatePreProcess (pCtx);
2355 if (pCtx->pVpp == NULL) {
2356 iRet = 1;
2357 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), pOut of memory in case new CWelsPreProcess().");
2358 WelsUninitEncoderExt (&pCtx);
2359 return iRet;
2360 }
2361 if ((iRet = pCtx->pVpp->AllocSpatialPictures (pCtx, pCtx->pSvcParam)) != 0) {
2362 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), pVPP alloc spatial pictures failed");
2363 WelsUninitEncoderExt (&pCtx);
2364 return iRet;
2365 }
2366
2367 #if defined(MEMORY_MONITOR)
2368 WelsLog (pLogCtx, WELS_LOG_INFO, "WelsInitEncoderExt() exit, overall memory usage: %llu bytes",
2369 static_cast<unsigned long long> (sizeof (sWelsEncCtx) /* requested size from malloc() or new operator */
2370 + pCtx->pMemAlign->WelsGetMemoryUsage()) /* requested size from CMemoryAlign::WelsMalloc() */
2371 );
2372 #endif//MEMORY_MONITOR
2373
2374 pCtx->iStatisticsLogInterval = STATISTICS_LOG_INTERVAL_MS;
2375 pCtx->uiLastTimestamp = -1;
2376 pCtx->bDeliveryFlag = true;
2377 *ppCtx = pCtx;
2378
2379 WelsLog (pLogCtx, WELS_LOG_INFO, "WelsInitEncoderExt(), pCtx= 0x%p.", (void*)pCtx);
2380
2381 return 0;
2382 }
2383 /*!
2384 * \brief get temporal level due to configuration and coding context
2385 */
GetTemporalLevel(SSpatialLayerInternal * fDlp,const int32_t kiFrameNum,const int32_t kiGopSize)2386 int32_t GetTemporalLevel (SSpatialLayerInternal* fDlp, const int32_t kiFrameNum, const int32_t kiGopSize) {
2387 const int32_t kiCodingIdx = kiFrameNum & (kiGopSize - 1);
2388
2389 return fDlp->uiCodingIdx2TemporalId[kiCodingIdx];
2390 }
2391
DynslcUpdateMbNeighbourInfoListForAllSlices(SDqLayer * pCurDq,SMB * pMbList)2392 void DynslcUpdateMbNeighbourInfoListForAllSlices (SDqLayer* pCurDq, SMB* pMbList) {
2393 SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
2394 const int32_t kiMbWidth = pSliceCtx->iMbWidth;
2395 const int32_t kiEndMbInSlice = pSliceCtx->iMbNumInFrame - 1;
2396 int32_t iIdx = 0;
2397
2398 do {
2399 SMB* pMb = &pMbList[iIdx];
2400 UpdateMbNeighbor (pCurDq, pMb, kiMbWidth, WelsMbToSliceIdc (pCurDq, pMb->iMbXY));
2401 ++ iIdx;
2402 } while (iIdx <= kiEndMbInSlice);
2403 }
2404
2405 /*
2406 * TUNE back if number of picture partition decision algorithm based on past if available
2407 */
PicPartitionNumDecision(sWelsEncCtx * pCtx)2408 int32_t PicPartitionNumDecision (sWelsEncCtx* pCtx) {
2409 int32_t iPartitionNum = 1;
2410 if (pCtx->pSvcParam->iMultipleThreadIdc > 1) {
2411 iPartitionNum = pCtx->pSvcParam->iMultipleThreadIdc;
2412 }
2413 return iPartitionNum;
2414 }
2415
WelsInitCurrentQBLayerMltslc(sWelsEncCtx * pCtx)2416 void WelsInitCurrentQBLayerMltslc (sWelsEncCtx* pCtx) {
2417 //pData init
2418 SDqLayer* pCurDq = pCtx->pCurDqLayer;
2419 //mb_neighbor
2420 DynslcUpdateMbNeighbourInfoListForAllSlices (pCurDq, pCurDq->sMbDataP);
2421 }
2422
UpdateSlicepEncCtxWithPartition(SDqLayer * pCurDq,int32_t iPartitionNum)2423 void UpdateSlicepEncCtxWithPartition (SDqLayer* pCurDq, int32_t iPartitionNum) {
2424 SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
2425 const int32_t kiMbNumInFrame = pSliceCtx->iMbNumInFrame;
2426 int32_t iCountMbNumPerPartition = kiMbNumInFrame;
2427 int32_t iAssignableMbLeft = kiMbNumInFrame;
2428 int32_t iCountMbNumInPartition = 0;
2429 int32_t iFirstMbIdx = 0;
2430 int32_t i/*, j*/;
2431
2432 if (iPartitionNum <= 0)
2433 iPartitionNum = 1;
2434 else if (iPartitionNum > AVERSLICENUM_CONSTRAINT)
2435 iPartitionNum = AVERSLICENUM_CONSTRAINT; // AVERSLICENUM_CONSTRAINT might be variable, however not fixed by MACRO
2436 iCountMbNumPerPartition /= iPartitionNum;
2437 if (iCountMbNumPerPartition == 0 || iCountMbNumPerPartition == 1) {
2438 iCountMbNumPerPartition = kiMbNumInFrame;
2439 iPartitionNum = 1;
2440 }
2441
2442 pSliceCtx->iSliceNumInFrame = iPartitionNum;
2443
2444 i = 0;
2445 while (i < iPartitionNum) {
2446 if (i + 1 == iPartitionNum) {
2447 iCountMbNumInPartition = iAssignableMbLeft;
2448 } else {
2449 iCountMbNumInPartition = iCountMbNumPerPartition;
2450 }
2451
2452 pCurDq->FirstMbIdxOfPartition[i] = iFirstMbIdx;
2453 pCurDq->EndMbIdxOfPartition[i] = iFirstMbIdx + iCountMbNumInPartition - 1;
2454 pCurDq->LastCodedMbIdxOfPartition[i] = 0;
2455 pCurDq->NumSliceCodedOfPartition[i] = 0;
2456
2457 WelsSetMemMultiplebytes_c (pSliceCtx->pOverallMbMap + iFirstMbIdx, i,
2458 iCountMbNumInPartition, sizeof (uint16_t));
2459
2460 // for next partition(or pSlice)
2461 iFirstMbIdx += iCountMbNumInPartition;
2462 iAssignableMbLeft -= iCountMbNumInPartition;
2463 ++ i;
2464 }
2465
2466 while (i < MAX_THREADS_NUM) {
2467 pCurDq->FirstMbIdxOfPartition[i] = 0;
2468 pCurDq->EndMbIdxOfPartition[i] = 0;
2469 pCurDq->LastCodedMbIdxOfPartition[i] = 0;
2470 pCurDq->NumSliceCodedOfPartition[i] = 0;
2471 ++ i;
2472 }
2473 }
2474
WelsInitCurrentDlayerMltslc(sWelsEncCtx * pCtx,int32_t iPartitionNum)2475 void WelsInitCurrentDlayerMltslc (sWelsEncCtx* pCtx, int32_t iPartitionNum) {
2476 SDqLayer* pCurDq = pCtx->pCurDqLayer;
2477 SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
2478 uint32_t uiMiniPacketSize = 0;
2479
2480 UpdateSlicepEncCtxWithPartition (pCurDq, iPartitionNum);
2481
2482 if (I_SLICE == pCtx->eSliceType) { //check if uiSliceSizeConstraint too small
2483 #define byte_complexIMBat26 (60)
2484 uint8_t iCurDid = pCtx->uiDependencyId;
2485 uint32_t uiFrmByte = 0;
2486
2487 if (pCtx->pSvcParam->iRCMode != RC_OFF_MODE) {
2488 //RC case
2489 uiFrmByte = (
2490 ((uint32_t) (pCtx->pSvcParam->sSpatialLayers[iCurDid].iSpatialBitrate)
2491 / (uint32_t) (pCtx->pSvcParam->sDependencyLayers[iCurDid].fInputFrameRate)) >> 3);
2492 } else {
2493 //fixed QP case
2494 const int32_t iTtlMbNumInFrame = pSliceCtx->iMbNumInFrame;
2495 int32_t iQDeltaTo26 = (26 - pCtx->pSvcParam->sSpatialLayers[iCurDid].iDLayerQp);
2496
2497 uiFrmByte = (iTtlMbNumInFrame * byte_complexIMBat26);
2498 if (iQDeltaTo26 > 0) {
2499 //smaller QP than 26
2500 uiFrmByte = (uint32_t) (uiFrmByte * ((float)iQDeltaTo26 / 4));
2501 } else if (iQDeltaTo26 < 0) {
2502 //larger QP than 26
2503 iQDeltaTo26 = ((-iQDeltaTo26) >> 2); //delta mod 4
2504 uiFrmByte = (uiFrmByte >> (iQDeltaTo26)); //if delta 4, byte /2
2505 }
2506 }
2507
2508 //MINPACKETSIZE_CONSTRAINT
2509 //suppose 16 byte per mb at average
2510 uiMiniPacketSize = (uint32_t) (uiFrmByte / pSliceCtx->iMaxSliceNumConstraint);
2511 if (pSliceCtx->uiSliceSizeConstraint < uiMiniPacketSize) {
2512 WelsLog (& (pCtx->sLogCtx),
2513 WELS_LOG_WARNING,
2514 "Set-SliceConstraint(%d) too small for current resolution (MB# %d) under QP/BR!",
2515 pSliceCtx->uiSliceSizeConstraint,
2516 pSliceCtx->iMbNumInFrame
2517 );
2518 }
2519 }
2520
2521 WelsInitCurrentQBLayerMltslc (pCtx);
2522 }
2523
2524 /*!
2525 * \brief initialize current layer
2526 */
WelsInitCurrentLayer(sWelsEncCtx * pCtx,const int32_t kiWidth,const int32_t kiHeight)2527 void WelsInitCurrentLayer (sWelsEncCtx* pCtx,
2528 const int32_t kiWidth,
2529 const int32_t kiHeight) {
2530 SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
2531 SPicture* pEncPic = pCtx->pEncPic;
2532 SPicture* pDecPic = pCtx->pDecPic;
2533 SDqLayer* pCurDq = pCtx->pCurDqLayer;
2534 SSlice* pBaseSlice = pCurDq->ppSliceInLayer[0];
2535 const uint8_t kiCurDid = pCtx->uiDependencyId;
2536 const bool kbUseSubsetSpsFlag = (!pParam->bSimulcastAVC) && (kiCurDid > BASE_DEPENDENCY_ID);
2537 SNalUnitHeaderExt* pNalHdExt = &pCurDq->sLayerInfo.sNalHeaderExt;
2538 SNalUnitHeader* pNalHd = &pNalHdExt->sNalUnitHeader;
2539 SDqIdc* pDqIdc = &pCtx->pDqIdcMap[kiCurDid];
2540 int32_t iIdx = 0;
2541 int32_t iSliceCount = pCurDq->iMaxSliceNum;
2542 SSpatialLayerInternal* pParamInternal = &pParam->sDependencyLayers[kiCurDid];
2543 if (NULL == pCurDq || NULL == pBaseSlice)
2544 return;
2545
2546 pCurDq->pDecPic = pDecPic;
2547
2548 assert (iSliceCount > 0);
2549
2550 int32_t iCurPpsId = pDqIdc->iPpsId;
2551 int32_t iCurSpsId = pDqIdc->iSpsId;
2552
2553 iCurPpsId = pCtx->pFuncList->pParametersetStrategy->GetCurrentPpsId (iCurPpsId,
2554 WELS_ABS (pParamInternal->uiIdrPicId - 1) % MAX_PPS_COUNT);
2555
2556 pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = iCurPpsId;
2557 pCurDq->sLayerInfo.pPpsP =
2558 pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[iCurPpsId];
2559
2560 pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = iCurSpsId;
2561 if (kbUseSubsetSpsFlag) {
2562 pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[iCurSpsId];
2563 pCurDq->sLayerInfo.pSpsP =
2564 pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCurDq->sLayerInfo.pSubsetSpsP->pSps;
2565 } else {
2566 pCurDq->sLayerInfo.pSubsetSpsP = NULL;
2567 pCurDq->sLayerInfo.pSpsP =
2568 pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[iCurSpsId];
2569 }
2570
2571 pBaseSlice->bSliceHeaderExtFlag = (NAL_UNIT_CODED_SLICE_EXT == pCtx->eNalType);
2572
2573 iIdx = 1;
2574 while (iIdx < iSliceCount) {
2575 InitSliceHeadWithBase (pCurDq->ppSliceInLayer[iIdx], pBaseSlice);
2576 ++ iIdx;
2577 }
2578
2579 memset (pNalHdExt, 0, sizeof (SNalUnitHeaderExt));
2580 pNalHd->uiNalRefIdc = pCtx->eNalPriority;
2581 pNalHd->eNalUnitType = pCtx->eNalType;
2582
2583 pNalHdExt->uiDependencyId = kiCurDid;
2584 pNalHdExt->bDiscardableFlag = (pCtx->bNeedPrefixNalFlag) ? (pNalHd->uiNalRefIdc == NRI_PRI_LOWEST) : false;
2585 pNalHdExt->bIdrFlag = (pParamInternal->iFrameNum == 0)
2586 && ((pCtx->eNalType == NAL_UNIT_CODED_SLICE_IDR)
2587 || (pCtx->eSliceType == I_SLICE));
2588 pNalHdExt->uiTemporalId = pCtx->uiTemporalId;
2589
2590 // pEncPic pData
2591 pCurDq->pEncData[0] = pEncPic->pData[0];
2592 pCurDq->pEncData[1] = pEncPic->pData[1];
2593 pCurDq->pEncData[2] = pEncPic->pData[2];
2594 pCurDq->iEncStride[0] = pEncPic->iLineSize[0];
2595 pCurDq->iEncStride[1] = pEncPic->iLineSize[1];
2596 pCurDq->iEncStride[2] = pEncPic->iLineSize[2];
2597 // cs pData
2598 pCurDq->pCsData[0] = pDecPic->pData[0];
2599 pCurDq->pCsData[1] = pDecPic->pData[1];
2600 pCurDq->pCsData[2] = pDecPic->pData[2];
2601 pCurDq->iCsStride[0] = pDecPic->iLineSize[0];
2602 pCurDq->iCsStride[1] = pDecPic->iLineSize[1];
2603 pCurDq->iCsStride[2] = pDecPic->iLineSize[2];
2604
2605 if (pCurDq->pRefLayer != NULL) {
2606 pCurDq->bBaseLayerAvailableFlag = true;
2607 } else {
2608 pCurDq->bBaseLayerAvailableFlag = false;
2609 }
2610
2611 if (pCtx->pTaskManage) {
2612 pCtx->pTaskManage->InitFrame (kiCurDid);
2613 }
2614 }
2615
SetFastCodingFunc(SWelsFuncPtrList * pFuncList)2616 static inline void SetFastCodingFunc (SWelsFuncPtrList* pFuncList) {
2617 pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa;
2618 pFuncList->sSampleDealingFuncs.pfMdCost = pFuncList->sSampleDealingFuncs.pfSampleSad;
2619 pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 = pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad;
2620 pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad;
2621 }
SetNormalCodingFunc(SWelsFuncPtrList * pFuncList)2622 static inline void SetNormalCodingFunc (SWelsFuncPtrList* pFuncList) {
2623 pFuncList->pfIntraFineMd = WelsMdIntraFinePartition;
2624 pFuncList->sSampleDealingFuncs.pfMdCost = pFuncList->sSampleDealingFuncs.pfSampleSatd;
2625 pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3 =
2626 pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Satd;
2627 pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 =
2628 pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Satd;
2629 pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 =
2630 pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd;
2631 }
SetMeMethod(const uint8_t uiMethod,PSearchMethodFunc & pSearchMethodFunc)2632 bool SetMeMethod (const uint8_t uiMethod, PSearchMethodFunc& pSearchMethodFunc) {
2633 switch (uiMethod) {
2634 case ME_DIA:
2635 pSearchMethodFunc = WelsDiamondSearch;
2636 break;
2637 case ME_CROSS:
2638 pSearchMethodFunc = WelsMotionCrossSearch;
2639 break;
2640 case ME_DIA_CROSS:
2641 pSearchMethodFunc = WelsDiamondCrossSearch;
2642 break;
2643 case ME_DIA_CROSS_FME:
2644 pSearchMethodFunc = WelsDiamondCrossFeatureSearch;
2645 break;
2646 case ME_FULL:
2647 pSearchMethodFunc = WelsDiamondSearch;
2648 return false;
2649 default:
2650 pSearchMethodFunc = WelsDiamondSearch;
2651 return false;
2652 }
2653 return true;
2654 }
2655
2656
2657
PreprocessSliceCoding(sWelsEncCtx * pCtx)2658 void PreprocessSliceCoding (sWelsEncCtx* pCtx) {
2659 SDqLayer* pCurLayer = pCtx->pCurDqLayer;
2660 //const bool kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
2661 bool bFastMode = (pCtx->pSvcParam->iComplexityMode == LOW_COMPLEXITY);
2662 SWelsFuncPtrList* pFuncList = pCtx->pFuncList;
2663 SLogContext* pLogCtx = & (pCtx->sLogCtx);
2664 /* function pointers conditional assignment under sWelsEncCtx, layer_mb_enc_rec (in stack) is exclusive */
2665 if ((pCtx->pSvcParam->iUsageType == CAMERA_VIDEO_REAL_TIME && bFastMode) ||
2666 (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME && P_SLICE == pCtx->eSliceType
2667 && bFastMode) //TODO: here is for sync with the origin code, consider the design again with more tests
2668 ) {
2669 SetFastCodingFunc (pFuncList);
2670 } else {
2671 SetNormalCodingFunc (pFuncList);
2672 }
2673
2674 if (P_SLICE == pCtx->eSliceType) {
2675 for (int i = 0; i < BLOCK_STATIC_IDC_ALL; i++) {
2676 pFuncList->pfMotionSearch[i] = WelsMotionEstimateSearch;
2677 }
2678 pFuncList->pfSearchMethod[BLOCK_16x16] =
2679 pFuncList->pfSearchMethod[BLOCK_16x8] =
2680 pFuncList->pfSearchMethod[BLOCK_8x16] =
2681 pFuncList->pfSearchMethod[BLOCK_8x8] =
2682 pFuncList->pfSearchMethod[BLOCK_4x4] =
2683 pFuncList->pfSearchMethod[BLOCK_8x4] =
2684 pFuncList->pfSearchMethod[BLOCK_4x8] = WelsDiamondSearch;
2685 pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
2686 pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
2687 pFuncList->pfSetScrollingMv = SetScrollingMvToMdNull;
2688
2689 if (bFastMode) {
2690 pFuncList->pfCalculateSatd = NotCalculateSatdCost;
2691 pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa;
2692 } else {
2693 pFuncList->pfCalculateSatd = CalculateSatdCost;
2694 pFuncList->pfInterFineMd = WelsMdInterFinePartition;
2695 }
2696 } else {
2697 pFuncList->sSampleDealingFuncs.pfMeCost = NULL;
2698 }
2699
2700 //to init at each frame will be needed when dealing with hybrid content (camera+screen)
2701 if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
2702 if (P_SLICE == pCtx->eSliceType) {
2703 //MD related func pointers
2704 pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen;
2705
2706 //ME related func pointers
2707 SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
2708 if (pVaaExt->sScrollDetectInfo.bScrollDetectFlag
2709 && (pVaaExt->sScrollDetectInfo.iScrollMvX | pVaaExt->sScrollDetectInfo.iScrollMvY)) {
2710 pFuncList->pfSetScrollingMv = SetScrollingMvToMd;
2711 } else {
2712 pFuncList->pfSetScrollingMv = SetScrollingMvToMdNull;
2713 }
2714
2715 pFuncList->pfMotionSearch[NO_STATIC] = WelsMotionEstimateSearch;
2716 pFuncList->pfMotionSearch[COLLOCATED_STATIC] = WelsMotionEstimateSearchStatic;
2717 pFuncList->pfMotionSearch[SCROLLED_STATIC] = WelsMotionEstimateSearchScrolled;
2718 //ME16x16
2719 if (!SetMeMethod (ME_DIA_CROSS, pFuncList->pfSearchMethod[BLOCK_16x16])) {
2720 WelsLog (pLogCtx, WELS_LOG_WARNING, "SetMeMethod(BLOCK_16x16) ME_DIA_CROSS unsuccessful, switched to default search");
2721 }
2722 //ME8x8
2723 SFeatureSearchPreparation* pFeatureSearchPreparation = pCurLayer->pFeatureSearchPreparation;
2724 if (pFeatureSearchPreparation) {
2725 pFeatureSearchPreparation->iHighFreMbCount = 0;
2726
2727 //calculate bFMESwitchFlag
2728 SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
2729 const int32_t kiMbSize = pCurLayer->iMbHeight * pCurLayer->iMbWidth;
2730 pFeatureSearchPreparation->bFMESwitchFlag = CalcFMESwitchFlag (pFeatureSearchPreparation->uiFMEGoodFrameCount,
2731 pFeatureSearchPreparation->iHighFreMbCount * 100 / kiMbSize, pCtx->pVaa->sVaaCalcInfo.iFrameSad / kiMbSize,
2732 pVaaExt->sScrollDetectInfo.bScrollDetectFlag);
2733
2734 //PerformFMEPreprocess
2735 SScreenBlockFeatureStorage* pScreenBlockFeatureStorage = pCurLayer->pRefPic->pScreenBlockFeatureStorage;
2736 pFeatureSearchPreparation->pRefBlockFeature = pScreenBlockFeatureStorage;
2737 if (pFeatureSearchPreparation->bFMESwitchFlag
2738 && !pScreenBlockFeatureStorage->bRefBlockFeatureCalculated) {
2739 SPicture* pRef = (pCtx->pSvcParam->bEnableLongTermReference ? pCurLayer->pRefOri[0] : pCurLayer->pRefPic);
2740 PerformFMEPreprocess (pFuncList, pRef, pFeatureSearchPreparation->pFeatureOfBlock,
2741 pScreenBlockFeatureStorage);
2742 }
2743
2744 //assign ME pointer
2745 if (pFeatureSearchPreparation->bFMESwitchFlag && pScreenBlockFeatureStorage->bRefBlockFeatureCalculated
2746 && (!pScreenBlockFeatureStorage->iIs16x16)) {
2747 if (!SetMeMethod (ME_DIA_CROSS_FME, pFuncList->pfSearchMethod[BLOCK_8x8])) {
2748 WelsLog (pLogCtx, WELS_LOG_WARNING,
2749 "SetMeMethod(BLOCK_8x8) ME_DIA_CROSS_FME unsuccessful, switched to default search");
2750 }
2751 }
2752
2753 //assign UpdateFMESwitch pointer
2754 if (pFeatureSearchPreparation->bFMESwitchFlag) {
2755 pFuncList->pfUpdateFMESwitch = UpdateFMESwitch;
2756 } else {
2757 pFuncList->pfUpdateFMESwitch = UpdateFMESwitchNull;
2758 }
2759 }//if (pFeatureSearchPreparation)
2760 } else {
2761 //reset some status when at I_SLICE
2762 pCurLayer->pFeatureSearchPreparation->bFMESwitchFlag = true;
2763 pCurLayer->pFeatureSearchPreparation->uiFMEGoodFrameCount = FMESWITCH_DEFAULT_GOODFRAME_NUM;
2764 }
2765 }
2766
2767 // update some layer dependent variable to save judgements in mb-level
2768 pCurLayer->bSatdInMdFlag = ((pFuncList->sSampleDealingFuncs.pfMeCost == pFuncList->sSampleDealingFuncs.pfSampleSatd)
2769 && (pFuncList->sSampleDealingFuncs.pfMdCost == pFuncList->sSampleDealingFuncs.pfSampleSatd));
2770
2771 const int32_t kiCurDid = pCtx->uiDependencyId;
2772 const int32_t kiCurTid = pCtx->uiTemporalId;
2773 if (pCurLayer->bDeblockingParallelFlag && (pCurLayer->iLoopFilterDisableIdc != 1)
2774 #if !defined(ENABLE_FRAME_DUMP)
2775 && (NRI_PRI_LOWEST != pCtx->eNalPriority)
2776 && (pCtx->pSvcParam->sDependencyLayers[kiCurDid].iHighestTemporalId == 0
2777 || kiCurTid < pCtx->pSvcParam->sDependencyLayers[kiCurDid].iHighestTemporalId)
2778 #endif// !ENABLE_FRAME_DUMP
2779 ) {
2780 pFuncList->pfDeblocking.pfDeblockingFilterSlice = DeblockingFilterSliceAvcbase;
2781 } else {
2782 pFuncList->pfDeblocking.pfDeblockingFilterSlice = DeblockingFilterSliceAvcbaseNull;
2783 }
2784 }
2785
2786 /*!
2787 * \brief swap pDq layers between current pDq layer and reference pDq layer
2788 */
2789
WelsSwapDqLayers(sWelsEncCtx * pCtx,const int32_t kiNextDqIdx)2790 static inline void WelsSwapDqLayers (sWelsEncCtx* pCtx, const int32_t kiNextDqIdx) {
2791 // swap and assign reference
2792 SDqLayer* pTmpLayer = pCtx->ppDqLayerList[kiNextDqIdx];
2793 SDqLayer* pRefLayer = pCtx->pCurDqLayer;
2794 pCtx->pCurDqLayer = pTmpLayer;
2795 pCtx->pCurDqLayer->pRefLayer = pRefLayer;
2796 }
2797
2798 /*!
2799 * \brief prefetch reference picture after WelsBuildRefList
2800 */
PrefetchReferencePicture(sWelsEncCtx * pCtx,const EVideoFrameType keFrameType)2801 static inline void PrefetchReferencePicture (sWelsEncCtx* pCtx, const EVideoFrameType keFrameType) {
2802 const int32_t kiSliceCount = pCtx->pCurDqLayer->iMaxSliceNum;
2803 int32_t iIdx = 0;
2804 uint8_t uiRefIdx = -1;
2805
2806 assert (kiSliceCount > 0);
2807 if (keFrameType != videoFrameTypeIDR) {
2808 assert (pCtx->iNumRef0 > 0);
2809 pCtx->pRefPic = pCtx->pRefList0[0]; // always get item 0 due to reordering done
2810 pCtx->pCurDqLayer->pRefPic = pCtx->pRefPic;
2811 uiRefIdx = 0; // reordered reference iIndex
2812 } else { // safe for IDR coding
2813 pCtx->pRefPic = NULL;
2814 pCtx->pCurDqLayer->pRefPic = NULL;
2815 }
2816
2817 iIdx = 0;
2818 while (iIdx < kiSliceCount) {
2819 pCtx->pCurDqLayer->ppSliceInLayer[iIdx]->sSliceHeaderExt.sSliceHeader.uiRefIndex = uiRefIdx;
2820 ++ iIdx;
2821 }
2822 }
2823
WelsWriteOneSPS(sWelsEncCtx * pCtx,const int32_t kiSpsIdx,int32_t & iNalSize)2824 int32_t WelsWriteOneSPS (sWelsEncCtx* pCtx, const int32_t kiSpsIdx, int32_t& iNalSize) {
2825 int iNal = pCtx->pOut->iNalIndex;
2826 WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
2827
2828 WelsWriteSpsNal (&pCtx->pSpsArray[kiSpsIdx], &pCtx->pOut->sBsWrite,
2829 pCtx->pFuncList->pParametersetStrategy->GetSpsIdOffsetList (PARA_SET_TYPE_AVCSPS));
2830 WelsUnloadNal (pCtx->pOut);
2831
2832 int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
2833 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
2834 pCtx->pFrameBs + pCtx->iPosBsBuffer,
2835 &iNalSize);
2836 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
2837
2838 pCtx->iPosBsBuffer += iNalSize;
2839 return ENC_RETURN_SUCCESS;
2840 }
2841
WelsWriteOnePPS(sWelsEncCtx * pCtx,const int32_t kiPpsIdx,int32_t & iNalSize)2842 int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNalSize) {
2843 //TODO
2844 int32_t iNal = pCtx->pOut->iNalIndex;
2845 /* generate picture parameter set */
2846 WelsLoadNal (pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST);
2847
2848 WelsWritePpsSyntax (&pCtx->pPPSArray[kiPpsIdx], &pCtx->pOut->sBsWrite,
2849 pCtx->pFuncList->pParametersetStrategy);
2850 WelsUnloadNal (pCtx->pOut);
2851
2852 int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
2853 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
2854 pCtx->pFrameBs + pCtx->iPosBsBuffer,
2855 &iNalSize);
2856 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
2857
2858 pCtx->iPosBsBuffer += iNalSize;
2859 return ENC_RETURN_SUCCESS;
2860 }
2861
2862
2863 /*!
2864 * \brief write all parameter sets introduced in SVC extension
2865 * \return writing results, success or error
2866 */
WelsWriteParameterSets(sWelsEncCtx * pCtx,int32_t * pNalLen,int32_t * pNumNal,int32_t * pTotalLength)2867 int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal, int32_t* pTotalLength) {
2868 int32_t iSize = 0;
2869 int32_t iNal = 0;
2870 int32_t iIdx = 0;
2871 int32_t iId = 0;
2872 int32_t iCountNal = 0;
2873 int32_t iNalLength = 0;
2874 int32_t iReturn = ENC_RETURN_SUCCESS;
2875
2876 if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal || NULL == pCtx->pFuncList->pParametersetStrategy)
2877 return ENC_RETURN_UNEXPECTED;
2878
2879 *pTotalLength = 0;
2880 /* write all SPS */
2881 iIdx = 0;
2882 while (iIdx < pCtx->iSpsNum) {
2883 pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
2884 /* generate sequence parameters set */
2885 iId = pCtx->pFuncList->pParametersetStrategy->GetSpsIdx (iIdx);
2886
2887 WelsWriteOneSPS (pCtx, iId, iNalLength);
2888
2889 pNalLen[iCountNal] = iNalLength;
2890 iSize += iNalLength;
2891
2892 ++ iIdx;
2893 ++ iCountNal;
2894 }
2895
2896 /* write all Subset SPS */
2897 iIdx = 0;
2898 while (iIdx < pCtx->iSubsetSpsNum) {
2899 iNal = pCtx->pOut->iNalIndex;
2900
2901 pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSubsetArray[iIdx].pSps.uiSpsId, PARA_SET_TYPE_SUBSETSPS);
2902
2903 iId = iIdx;
2904
2905 /* generate Subset SPS */
2906 WelsLoadNal (pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST);
2907
2908 WelsWriteSubsetSpsSyntax (&pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite,
2909 pCtx->pFuncList->pParametersetStrategy->GetSpsIdOffsetList (PARA_SET_TYPE_SUBSETSPS));
2910 WelsUnloadNal (pCtx->pOut);
2911
2912 iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
2913 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
2914 pCtx->pFrameBs + pCtx->iPosBsBuffer,
2915 &iNalLength);
2916 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
2917 pNalLen[iCountNal] = iNalLength;
2918
2919 pCtx->iPosBsBuffer += iNalLength;
2920 iSize += iNalLength;
2921
2922 ++ iIdx;
2923 ++ iCountNal;
2924 }
2925
2926 pCtx->pFuncList->pParametersetStrategy->UpdatePpsList (pCtx);
2927
2928 iIdx = 0;
2929 while (iIdx < pCtx->iPpsNum) {
2930 pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
2931
2932 WelsWriteOnePPS (pCtx, iIdx, iNalLength);
2933
2934 pNalLen[iCountNal] = iNalLength;
2935 iSize += iNalLength;
2936
2937 ++ iIdx;
2938 ++ iCountNal;
2939 }
2940
2941 *pNumNal = iCountNal;
2942 *pTotalLength = iSize;
2943
2944 return ENC_RETURN_SUCCESS;
2945 }
2946
AddPrefixNal(sWelsEncCtx * pCtx,SLayerBSInfo * pLayerBsInfo,int32_t * pNalLen,int32_t * pNalIdxInLayer,const EWelsNalUnitType keNalType,const EWelsNalRefIdc keNalRefIdc,int32_t & iPayloadSize)2947 static inline int32_t AddPrefixNal (sWelsEncCtx* pCtx,
2948 SLayerBSInfo* pLayerBsInfo,
2949 int32_t* pNalLen,
2950 int32_t* pNalIdxInLayer,
2951 const EWelsNalUnitType keNalType,
2952 const EWelsNalRefIdc keNalRefIdc,
2953 int32_t& iPayloadSize) {
2954 int32_t iReturn = ENC_RETURN_SUCCESS;
2955 iPayloadSize = 0;
2956
2957 if (keNalRefIdc != NRI_PRI_LOWEST) {
2958 WelsLoadNal (pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc);
2959
2960 WelsWriteSVCPrefixNal (&pCtx->pOut->sBsWrite, keNalRefIdc, (NAL_UNIT_CODED_SLICE_IDR == keNalType));
2961
2962 WelsUnloadNal (pCtx->pOut);
2963
2964 iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
2965 &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
2966 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
2967 pCtx->pFrameBs + pCtx->iPosBsBuffer,
2968 &pNalLen[*pNalIdxInLayer]);
2969 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
2970 iPayloadSize = pNalLen[*pNalIdxInLayer];
2971
2972 pCtx->iPosBsBuffer += iPayloadSize;
2973
2974 (*pNalIdxInLayer) ++;
2975 } else { // No Prefix NAL Unit RBSP syntax here, but need add NAL Unit Header extension
2976 WelsLoadNal (pCtx->pOut, NAL_UNIT_PREFIX, keNalRefIdc);
2977 // No need write any syntax of prefix NAL Unit RBSP here
2978 WelsUnloadNal (pCtx->pOut);
2979
2980 iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
2981 &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
2982 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
2983 pCtx->pFrameBs + pCtx->iPosBsBuffer,
2984 &pNalLen[*pNalIdxInLayer]);
2985 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
2986 iPayloadSize = pNalLen[*pNalIdxInLayer];
2987
2988 pCtx->iPosBsBuffer += iPayloadSize;
2989
2990 (*pNalIdxInLayer) ++;
2991 }
2992
2993 return ENC_RETURN_SUCCESS;
2994 }
2995
WritePadding(sWelsEncCtx * pCtx,int32_t iLen,int32_t & iSize)2996 int32_t WritePadding (sWelsEncCtx* pCtx, int32_t iLen, int32_t& iSize) {
2997 int32_t i = 0;
2998 int32_t iNal = 0;
2999 SBitStringAux* pBs = NULL;
3000 int32_t iNalLen;
3001
3002 iSize = 0;
3003 iNal = pCtx->pOut->iNalIndex;
3004 pBs = &pCtx->pOut->sBsWrite; // SBitStringAux instance for non VCL NALs decoding
3005
3006 if ((pBs->pEndBuf - pBs->pCurBuf) < iLen || iNal >= pCtx->pOut->iCountNals) {
3007 #if GOM_TRACE_FLAG
3008 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
3009 "[RC] paddingcal pBuffer overflow, bufferlen=%lld, paddinglen=%d, iNalIdx= %d, iCountNals= %d",
3010 static_cast<long long int> (pBs->pEndBuf - pBs->pCurBuf), iLen, iNal, pCtx->pOut->iCountNals);
3011 #endif
3012 return ENC_RETURN_MEMOVERFLOWFOUND;
3013 }
3014
3015 WelsLoadNal (pCtx->pOut, NAL_UNIT_FILLER_DATA, NRI_PRI_LOWEST);
3016
3017 for (i = 0; i < iLen; i++) {
3018 BsWriteBits (pBs, 8, 0xff);
3019 }
3020
3021 BsRbspTrailingBits (pBs);
3022
3023 WelsUnloadNal (pCtx->pOut);
3024 int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
3025 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
3026 pCtx->pFrameBs + pCtx->iPosBsBuffer,
3027 &iNalLen);
3028 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3029
3030 pCtx->iPosBsBuffer += iNalLen;
3031 iSize += iNalLen;
3032
3033 return ENC_RETURN_SUCCESS;
3034 }
3035
3036 /*
3037 * Force coding IDR as follows
3038 */
ForceCodingIDR(sWelsEncCtx * pCtx,int32_t iLayerId)3039 int32_t ForceCodingIDR (sWelsEncCtx* pCtx, int32_t iLayerId) {
3040 if (NULL == pCtx)
3041 return 1;
3042 if ((iLayerId < 0) || (iLayerId >= MAX_SPATIAL_LAYER_NUM) || (!pCtx->pSvcParam->bSimulcastAVC)) {
3043 for (int32_t iDid = 0; iDid < pCtx->pSvcParam->iSpatialLayerNum; iDid++) {
3044 SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iDid];
3045 pParamInternal->iCodingIndex = 0;
3046 pParamInternal->iFrameIndex = 0;
3047 pParamInternal->iFrameNum = 0;
3048 pParamInternal->iPOC = 0;
3049 pParamInternal->bEncCurFrmAsIdrFlag = true;
3050 pCtx->sEncoderStatistics[0].uiIDRReqNum++;
3051 }
3052 WelsLog (&pCtx->sLogCtx, WELS_LOG_INFO, "ForceCodingIDR(iDid 0-%d)at InputFrameCount=%d\n",
3053 pCtx->pSvcParam->iSpatialLayerNum - 1, pCtx->sEncoderStatistics[0].uiInputFrameCount);
3054
3055
3056
3057 } else {
3058 SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iLayerId];
3059 pParamInternal->iCodingIndex = 0;
3060 pParamInternal->iFrameIndex = 0;
3061 pParamInternal->iFrameNum = 0;
3062 pParamInternal->iPOC = 0;
3063 pParamInternal->bEncCurFrmAsIdrFlag = true;
3064 pCtx->sEncoderStatistics[iLayerId].uiIDRReqNum++;
3065 WelsLog (&pCtx->sLogCtx, WELS_LOG_INFO, "ForceCodingIDR(iDid %d)at InputFrameCount=%d\n", iLayerId,
3066 pCtx->sEncoderStatistics[iLayerId].uiInputFrameCount);
3067 }
3068 pCtx->bCheckWindowStatusRefreshFlag = false;
3069
3070
3071 return 0;
3072 }
3073
WelsEncoderEncodeParameterSets(sWelsEncCtx * pCtx,void * pDst)3074 int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) {
3075 if (NULL == pCtx || NULL == pDst) {
3076 return ENC_RETURN_UNEXPECTED;
3077 }
3078
3079 SFrameBSInfo* pFbi = (SFrameBSInfo*)pDst;
3080 SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0];
3081 int32_t iCountNal = 0;
3082 int32_t iTotalLength = 0;
3083
3084 pLayerBsInfo->pBsBuf = pCtx->pFrameBs;
3085 pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen;
3086 InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize);
3087
3088 pCtx->iPosBsBuffer = 0;
3089 int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iTotalLength);
3090 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3091
3092 pLayerBsInfo->uiSpatialId = 0;
3093 pLayerBsInfo->uiTemporalId = 0;
3094 pLayerBsInfo->uiQualityId = 0;
3095 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3096 pLayerBsInfo->iNalCount = iCountNal;
3097 pLayerBsInfo->eFrameType = videoFrameTypeInvalid;
3098 pLayerBsInfo->iSubSeqId = 0;
3099 //pCtx->eLastNalPriority = NRI_PRI_HIGHEST;
3100 pFbi->iLayerNum = 1;
3101 pFbi->eFrameType = videoFrameTypeInvalid;
3102 WelsEmms();
3103
3104 return ENC_RETURN_SUCCESS;
3105 }
3106
GetSubSequenceId(sWelsEncCtx * pCtx,EVideoFrameType eFrameType)3107 int32_t GetSubSequenceId (sWelsEncCtx* pCtx, EVideoFrameType eFrameType) {
3108 int32_t iSubSeqId = 0;
3109 if (eFrameType == videoFrameTypeIDR)
3110 iSubSeqId = 0;
3111 else if (eFrameType == videoFrameTypeI)
3112 iSubSeqId = 1;
3113 else if (eFrameType == videoFrameTypeP) {
3114 if (pCtx->bCurFrameMarkedAsSceneLtr)
3115 iSubSeqId = 2;
3116 else
3117 iSubSeqId = 3 + pCtx->uiTemporalId; //T0:3 T1:4 T2:5 T3:6
3118 } else
3119 iSubSeqId = 3 + MAX_TEMPORAL_LAYER_NUM;
3120 return iSubSeqId;
3121 }
3122
3123 // writing parasets for (simulcast) svc
WriteSsvcParaset(sWelsEncCtx * pCtx,const int32_t kiSpatialNum,SLayerBSInfo * & pLayerBsInfo,int32_t & iLayerNum,int32_t & iFrameSize)3124 int32_t WriteSsvcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
3125 SLayerBSInfo*& pLayerBsInfo, int32_t& iLayerNum, int32_t& iFrameSize) {
3126 int32_t iNonVclSize = 0, iCountNal = 0, iReturn = ENC_RETURN_SUCCESS;
3127 iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iNonVclSize);
3128 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3129 for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
3130 SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iSpatialId];
3131 if (pParamInternal->uiIdrPicId < 65535) {
3132 ++ pParamInternal->uiIdrPicId;
3133 } else {
3134 pParamInternal->uiIdrPicId = 0;
3135 }
3136 }
3137 pLayerBsInfo->uiSpatialId = 0;
3138 pLayerBsInfo->uiTemporalId = 0;
3139 pLayerBsInfo->uiQualityId = 0;
3140 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3141 pLayerBsInfo->iNalCount = iCountNal;
3142 pLayerBsInfo->eFrameType = videoFrameTypeIDR;
3143 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, videoFrameTypeIDR);
3144 //point to next pLayerBsInfo
3145 ++ pLayerBsInfo;
3146 ++ pCtx->pOut->iLayerBsIndex;
3147 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3148 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
3149
3150 //update for external countings
3151 ++ iLayerNum;
3152 iFrameSize += iNonVclSize;
3153 return iReturn;
3154 }
3155
3156 // writing parasets for simulcast avc
WriteSavcParaset(sWelsEncCtx * pCtx,const int32_t iIdx,SLayerBSInfo * & pLayerBsInfo,int32_t & iLayerNum,int32_t & iFrameSize)3157 int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t iIdx,
3158 SLayerBSInfo*& pLayerBsInfo, int32_t& iLayerNum, int32_t& iFrameSize) {
3159 int32_t iNonVclSize = 0, iCountNal = 0, iReturn = ENC_RETURN_SUCCESS;
3160
3161 // write SPS
3162 iNonVclSize = 0;
3163
3164 //writing one NAL
3165 int32_t iNalSize = 0;
3166 iCountNal = 0;
3167
3168
3169 if (pCtx->pFuncList->pParametersetStrategy) {
3170 pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
3171 }
3172
3173 iReturn = WelsWriteOneSPS (pCtx, iIdx, iNalSize);
3174 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3175
3176 pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
3177 iNonVclSize += iNalSize;
3178 iCountNal = 1;
3179
3180 //finish writing one NAL
3181
3182 pLayerBsInfo->uiSpatialId = iIdx;
3183 pLayerBsInfo->uiTemporalId = 0;
3184 pLayerBsInfo->uiQualityId = 0;
3185 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3186 pLayerBsInfo->iNalCount = iCountNal;
3187 pLayerBsInfo->eFrameType = videoFrameTypeIDR;
3188 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, videoFrameTypeIDR);
3189 //point to next pLayerBsInfo
3190 ++ pLayerBsInfo;
3191 ++ pCtx->pOut->iLayerBsIndex;
3192 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3193 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
3194 //update for external countings
3195 ++ iLayerNum;
3196
3197 // write PPS
3198
3199 //TODO: under new strategy, will PPS be correctly updated?
3200
3201 //writing one NAL
3202 iNalSize = 0;
3203 iCountNal = 0;
3204
3205 if (pCtx->pFuncList->pParametersetStrategy) {
3206 pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
3207 }
3208
3209 iReturn = WelsWriteOnePPS (pCtx, iIdx, iNalSize);
3210 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3211
3212 pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
3213 iNonVclSize += iNalSize;
3214 iCountNal = 1;
3215 //finish writing one NAL
3216
3217 pLayerBsInfo->uiSpatialId = iIdx;
3218 pLayerBsInfo->uiTemporalId = 0;
3219 pLayerBsInfo->uiQualityId = 0;
3220 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3221 pLayerBsInfo->iNalCount = iCountNal;
3222 pLayerBsInfo->eFrameType = videoFrameTypeIDR;
3223 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, videoFrameTypeIDR);
3224 //point to next pLayerBsInfo
3225 ++ pLayerBsInfo;
3226 ++ pCtx->pOut->iLayerBsIndex;
3227 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3228 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
3229 //update for external countings
3230 ++ iLayerNum;
3231
3232 // to check number of layers / nals / slices dependencies
3233 if (iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
3234 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WriteSavcParaset(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
3235 iLayerNum, MAX_LAYER_NUM_OF_FRAME);
3236 return 1;
3237 }
3238
3239 iFrameSize += iNonVclSize;
3240 return iReturn;
3241 }
3242
3243 //cover the logic of simulcast avc + sps_pps_listing
WriteSavcParaset_Listing(sWelsEncCtx * pCtx,const int32_t kiSpatialNum,SLayerBSInfo * & pLayerBsInfo,int32_t & iLayerNum,int32_t & iFrameSize)3244 int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
3245 SLayerBSInfo*& pLayerBsInfo, int32_t& iLayerNum, int32_t& iFrameSize) {
3246 int32_t iNonVclSize = 0, iCountNal = 0, iReturn = ENC_RETURN_SUCCESS;
3247
3248 // write SPS
3249 iNonVclSize = 0;
3250
3251 for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
3252 SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iSpatialId];
3253 if (pParamInternal->uiIdrPicId < 65535) {
3254 ++ pParamInternal->uiIdrPicId;
3255 } else {
3256 pParamInternal->uiIdrPicId = 0;
3257 }
3258
3259 iCountNal = 0;
3260
3261 for (int32_t iIdx = 0; iIdx < pCtx->iSpsNum; iIdx++) {
3262 //writing one NAL
3263 int32_t iNalSize = 0;
3264 iReturn = WelsWriteOneSPS (pCtx, iIdx, iNalSize);
3265 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3266
3267 pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
3268 iNonVclSize += iNalSize;
3269 iCountNal ++;
3270 //finish writing one NAL
3271 }
3272
3273 pLayerBsInfo->uiSpatialId = iSpatialId;
3274 pLayerBsInfo->uiTemporalId = 0;
3275 pLayerBsInfo->uiQualityId = 0;
3276 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3277 pLayerBsInfo->iNalCount = iCountNal;
3278 pLayerBsInfo->eFrameType = videoFrameTypeIDR;
3279 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, videoFrameTypeIDR);
3280 //point to next pLayerBsInfo
3281 ++ pLayerBsInfo;
3282 ++ pCtx->pOut->iLayerBsIndex;
3283 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3284 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
3285 //update for external countings
3286 ++ iLayerNum;
3287 }
3288
3289 // write PPS
3290 pCtx->pFuncList->pParametersetStrategy->UpdatePpsList (pCtx);
3291
3292 //TODO: under new strategy, will PPS be correctly updated?
3293 for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
3294 iCountNal = 0;
3295 for (int32_t iIdx = 0; iIdx < pCtx->iPpsNum; iIdx++) {
3296 //writing one NAL
3297 int32_t iNalSize = 0;
3298 iReturn = WelsWriteOnePPS (pCtx, iIdx, iNalSize);
3299 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3300
3301 pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
3302 iNonVclSize += iNalSize;
3303 iCountNal ++;
3304 //finish writing one NAL
3305 }
3306
3307 pLayerBsInfo->uiSpatialId = iSpatialId;
3308 pLayerBsInfo->uiTemporalId = 0;
3309 pLayerBsInfo->uiQualityId = 0;
3310 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
3311 pLayerBsInfo->iNalCount = iCountNal;
3312 pLayerBsInfo->eFrameType = videoFrameTypeIDR;
3313 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, videoFrameTypeIDR);
3314 //point to next pLayerBsInfo
3315 ++ pLayerBsInfo;
3316 ++ pCtx->pOut->iLayerBsIndex;
3317 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3318 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
3319 //update for external countings
3320 ++ iLayerNum;
3321 }
3322
3323 // to check number of layers / nals / slices dependencies
3324 if (iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
3325 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WriteSavcParaset(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
3326 iLayerNum, MAX_LAYER_NUM_OF_FRAME);
3327 return ENC_RETURN_UNEXPECTED;
3328 }
3329
3330 iFrameSize += iNonVclSize;
3331 return iReturn;
3332 }
3333
StackBackEncoderStatus(sWelsEncCtx * pEncCtx,EVideoFrameType keFrameType)3334 void StackBackEncoderStatus (sWelsEncCtx* pEncCtx,
3335 EVideoFrameType keFrameType) {
3336 SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
3337 // for bitstream writing
3338 pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position
3339 pEncCtx->pOut->iNalIndex = 0; // reset NAL index
3340 pEncCtx->pOut->iLayerBsIndex = 0; // reset index of Layer Bs
3341
3342 InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize);
3343 if ((keFrameType == videoFrameTypeP) || (keFrameType == videoFrameTypeI)) {
3344 pParamInternal->iFrameIndex --;
3345 if (pParamInternal->iPOC != 0) {
3346 pParamInternal->iPOC -= 2;
3347 } else {
3348 pParamInternal->iPOC = (1 << pEncCtx->pSps->iLog2MaxPocLsb) - 2;
3349 }
3350
3351 LoadBackFrameNum (pEncCtx, pEncCtx->uiDependencyId);
3352
3353 pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
3354 pEncCtx->eSliceType = P_SLICE;
3355 //pEncCtx->eNalPriority = pEncCtx->eLastNalPriority; //not need this since eNalPriority will be updated at the beginning of coding a frame
3356 } else if (keFrameType == videoFrameTypeIDR) {
3357 pParamInternal->uiIdrPicId --;
3358
3359 //set the next frame to be IDR
3360 ForceCodingIDR (pEncCtx, pEncCtx->uiDependencyId);
3361 } else { // B pictures are not supported now, any else?
3362 assert (0);
3363 }
3364
3365 // no need to stack back RC info since the info is still useful for later RQ model calculation
3366 // no need to stack back MB slicing info for dynamic balancing, since the info is still refer-able
3367 }
3368
ClearFrameBsInfo(sWelsEncCtx * pCtx,SFrameBSInfo * pFbi)3369 void ClearFrameBsInfo (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi) {
3370 pFbi->sLayerInfo[0].pBsBuf = pCtx->pFrameBs;
3371 pFbi->sLayerInfo[0].pNalLengthInByte = pCtx->pOut->pNalLen;
3372
3373 for (int i = 0; i < pFbi->iLayerNum; i++) {
3374 pFbi->sLayerInfo[i].iNalCount = 0;
3375 pFbi->sLayerInfo[i].eFrameType = videoFrameTypeSkip;
3376 }
3377 pFbi->iLayerNum = 0;
3378 pFbi->iFrameSizeInBytes = 0;
3379 }
PrepareEncodeFrame(sWelsEncCtx * pCtx,SLayerBSInfo * & pLayerBsInfo,int32_t iSpatialNum,int8_t & iCurDid,int32_t & iCurTid,int32_t & iLayerNum,int32_t & iFrameSize,long long uiTimeStamp)3380 EVideoFrameType PrepareEncodeFrame (sWelsEncCtx* pCtx, SLayerBSInfo*& pLayerBsInfo, int32_t iSpatialNum,
3381 int8_t& iCurDid, int32_t& iCurTid,
3382 int32_t& iLayerNum, int32_t& iFrameSize, long long uiTimeStamp) {
3383 SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
3384 SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
3385
3386 bool bSkipFrameFlag = WelsRcCheckFrameStatus (pCtx, uiTimeStamp, iSpatialNum, iCurDid);
3387 EVideoFrameType eFrameType = DecideFrameType (pCtx, iSpatialNum, iCurDid, bSkipFrameFlag);
3388 if (eFrameType == videoFrameTypeSkip) {
3389 if (pSvcParam->bSimulcastAVC) {
3390 if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip)
3391 pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iCurDid);
3392 WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
3393 "[Rc] Frame timestamp = %lld, iDid = %d,skip one frame due to target_br, continual skipped %d frames",
3394 uiTimeStamp, iCurDid, pCtx->pWelsSvcRc[iCurDid].iContinualSkipFrames);
3395 }
3396
3397 else {
3398 if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) {
3399 for (int32_t i = 0; i < iSpatialNum; i++) {
3400 pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, (pSpatialIndexMap + i)->iDid);
3401 }
3402 }
3403 WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
3404 "[Rc] Frame timestamp = %lld, iDid = %d,skip one frame due to target_br, continual skipped %d frames",
3405 uiTimeStamp, iCurDid, pCtx->pWelsSvcRc[iCurDid].iContinualSkipFrames);
3406 }
3407
3408 } else {
3409 SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iCurDid];
3410
3411 iCurTid = GetTemporalLevel (pParamInternal, pParamInternal->iCodingIndex,
3412 pSvcParam->uiGopSize);
3413 pCtx->uiTemporalId = iCurTid;
3414 if (eFrameType == videoFrameTypeIDR) {
3415 // write parameter sets bitstream or SEI/SSEI (if any) here
3416 // TODO: use function pointer instead
3417 if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
3418 if (pSvcParam->bSimulcastAVC) {
3419 pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
3420 ++ pParamInternal->uiIdrPicId;
3421 } else {
3422 pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
3423 }
3424 } else {
3425 pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
3426
3427
3428 }
3429 }
3430 }
3431 return eFrameType;
3432 }
3433 /*!
3434 * \brief core svc encoding process
3435 *
3436 * \pParam pCtx sWelsEncCtx*, encoder context
3437 * \pParam pFbi FrameBSInfo*
3438 * \pParam pSrcPic Source Picture
3439 * \return EFrameType (videoFrameTypeIDR/videoFrameTypeI/videoFrameTypeP)
3440 */
WelsEncoderEncodeExt(sWelsEncCtx * pCtx,SFrameBSInfo * pFbi,const SSourcePicture * pSrcPic)3441 int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSourcePicture* pSrcPic) {
3442 if (pCtx == NULL) {
3443 return ENC_RETURN_MEMALLOCERR;
3444 }
3445 SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0];
3446 SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
3447 SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
3448 #if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
3449 SPicture* fsnr = NULL;
3450 #endif//ENABLE_FRAME_DUMP || ENABLE_PSNR_CALC
3451 SPicture* pEncPic = NULL; // to be decided later
3452 #if defined(MT_DEBUG)
3453 int32_t iDidList[MAX_DEPENDENCY_LAYER] = {0};
3454 #endif
3455 int32_t iLayerNum = 0;
3456 int32_t iLayerSize = 0;
3457 int32_t iSpatialNum =
3458 0; // available count number of spatial layers due to frame size changed in this given frame
3459 int32_t iSpatialIdx = 0; // iIndex of spatial layers due to frame size changed in this given frame
3460 int32_t iFrameSize = 0;
3461 int32_t iNalIdxInLayer = 0;
3462 int32_t iCountNal = 0;
3463 EVideoFrameType eFrameType = videoFrameTypeInvalid;
3464 int32_t iCurWidth = 0;
3465 int32_t iCurHeight = 0;
3466 EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0;
3467 EWelsNalRefIdc eNalRefIdc = NRI_PRI_LOWEST;
3468 int8_t iCurDid = 0;
3469 int32_t iCurTid = 0;
3470 bool bAvcBased = false;
3471 SLogContext* pLogCtx = & (pCtx->sLogCtx);
3472 #if defined(ENABLE_PSNR_CALC)
3473 float fSnrY = .0f, fSnrU = .0f, fSnrV = .0f;
3474 #endif//ENABLE_PSNR_CALC
3475
3476 #if defined(_DEBUG)
3477 int32_t i = 0, j = 0, k = 0;
3478 #endif//_DEBUG
3479 pCtx->iEncoderError = ENC_RETURN_SUCCESS;
3480 pCtx->bCurFrameMarkedAsSceneLtr = false;
3481 pFbi->eFrameType = videoFrameTypeSkip;
3482 pFbi->iLayerNum = 0; // for initialization
3483 pFbi->uiTimeStamp = GetTimestampForRc (pSrcPic->uiTimeStamp, pCtx->uiLastTimestamp,
3484 pCtx->pSvcParam->sSpatialLayers[pCtx->pSvcParam->iSpatialLayerNum - 1].fFrameRate);
3485 for (int32_t iNalIdx = 0; iNalIdx < MAX_LAYER_NUM_OF_FRAME; iNalIdx++) {
3486 pFbi->sLayerInfo[iNalIdx].eFrameType = videoFrameTypeSkip;
3487 pFbi->sLayerInfo[iNalIdx].iNalCount = 0;
3488 }
3489 // perform csc/denoise/downsample/padding, generate spatial layers
3490 iSpatialNum = pCtx->pVpp->BuildSpatialPicList (pCtx, pSrcPic);
3491 if (iSpatialNum == -1) {
3492 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "Failed in allocating memory in BuildSpatialPicList");
3493 return ENC_RETURN_MEMALLOCERR;
3494 }
3495
3496 if (pCtx->pFuncList->pfRc.pfWelsUpdateMaxBrWindowStatus) {
3497 pCtx->pFuncList->pfRc.pfWelsUpdateMaxBrWindowStatus (pCtx, iSpatialNum, pFbi->uiTimeStamp);
3498 }
3499
3500 if (iSpatialNum < 1) {
3501 for (int32_t iDidIdx = 0; iDidIdx < pSvcParam->iSpatialLayerNum; iDidIdx++) {
3502 SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iDidIdx];
3503 pParamInternal->iCodingIndex ++;
3504 }
3505 pFbi->eFrameType = videoFrameTypeSkip;
3506 pLayerBsInfo->eFrameType = videoFrameTypeSkip;
3507 WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
3508 "[Rc] Frame timestamp = %lld, skip one frame due to preprocessing return (temporal layer settings or else)",
3509 pSrcPic->uiTimeStamp);
3510 return ENC_RETURN_SUCCESS;
3511 }
3512
3513 InitBitStream (pCtx);
3514 pLayerBsInfo->pBsBuf = pCtx->pFrameBs ;
3515 pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen;
3516 iCurDid = pSpatialIndexMap->iDid;
3517 pCtx->pCurDqLayer = pCtx->ppDqLayerList[iCurDid];
3518 pCtx->pCurDqLayer->pRefLayer = NULL;
3519 if (!pSvcParam->bSimulcastAVC) {
3520 eFrameType = PrepareEncodeFrame (pCtx, pLayerBsInfo, iSpatialNum, iCurDid, iCurTid, iLayerNum, iFrameSize,
3521 pFbi->uiTimeStamp);
3522 if (eFrameType == videoFrameTypeSkip) {
3523 pFbi->eFrameType = videoFrameTypeSkip;
3524 pLayerBsInfo->eFrameType = videoFrameTypeSkip;
3525 return ENC_RETURN_SUCCESS;
3526 }
3527 } else {
3528 for (int32_t iDidIdx = 0; iDidIdx < pSvcParam->iSpatialLayerNum; iDidIdx++) {
3529 SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iDidIdx];
3530 int32_t iTemporalId = GetTemporalLevel (pParamInternal, pParamInternal->iCodingIndex,
3531 pSvcParam->uiGopSize);
3532 if (iTemporalId == INVALID_TEMPORAL_ID)
3533 pParamInternal->iCodingIndex ++;
3534 }
3535 }
3536
3537 while (iSpatialIdx < iSpatialNum) {
3538 iCurDid = (pSpatialIndexMap + iSpatialIdx)->iDid;
3539 SSpatialLayerConfig* pParam = &pSvcParam->sSpatialLayers[iCurDid];
3540 SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iCurDid];
3541 int32_t iDecompositionStages = pSvcParam->sDependencyLayers[iCurDid].iDecompositionStages;
3542 pCtx->pCurDqLayer = pCtx->ppDqLayerList[iCurDid];
3543 pCtx->uiDependencyId = iCurDid;
3544
3545 if (pSvcParam->bSimulcastAVC) {
3546 eFrameType = PrepareEncodeFrame (pCtx, pLayerBsInfo, iSpatialNum, iCurDid, iCurTid, iLayerNum, iFrameSize,
3547 pFbi->uiTimeStamp);
3548 if (eFrameType == videoFrameTypeSkip) {
3549 pLayerBsInfo->eFrameType = videoFrameTypeSkip;
3550 ++iSpatialIdx;
3551 continue;
3552 }
3553 }
3554 InitFrameCoding (pCtx, eFrameType, iCurDid);
3555 pCtx->pVpp->AnalyzeSpatialPic (pCtx, iCurDid);
3556
3557 pCtx->pEncPic = pEncPic = (pSpatialIndexMap + iSpatialIdx)->pSrc;
3558 pCtx->pEncPic->iPictureType = pCtx->eSliceType;
3559 pCtx->pEncPic->iFramePoc = pParamInternal->iPOC;
3560
3561 iCurWidth = pParam->iVideoWidth;
3562 iCurHeight = pParam->iVideoHeight;
3563 #if defined(MT_DEBUG)
3564 iDidList[iSpatialIdx] = iCurDid;
3565 #endif
3566 // Encoding this picture might mulitiple sQualityStat layers potentially be encoded as followed
3567 switch (pParam->sSliceArgument.uiSliceMode) {
3568 case SM_FIXEDSLCNUM_SLICE: {
3569 if ((pSvcParam->iMultipleThreadIdc > 1) &&
3570 (pSvcParam->bUseLoadBalancing
3571 && pSvcParam->iMultipleThreadIdc >= pSvcParam->sSpatialLayers[iCurDid].sSliceArgument.uiSliceNum)
3572 ) {
3573 if (iCurDid > 0)
3574 AdjustEnhanceLayer (pCtx, iCurDid);
3575 else
3576 AdjustBaseLayer (pCtx);
3577 }
3578
3579 break;
3580 }
3581 case SM_SIZELIMITED_SLICE: {
3582 int32_t iPicIPartitionNum = PicPartitionNumDecision (pCtx);
3583 // MT compatibility
3584 pCtx->iActiveThreadsNum =
3585 iPicIPartitionNum; // we try to active number of threads, equal to number of picture partitions
3586 WelsInitCurrentDlayerMltslc (pCtx, iPicIPartitionNum);
3587 break;
3588 }
3589 default: {
3590 break;
3591 }
3592 }
3593
3594 /* coding each spatial layer, only one sQualityStat layer within spatial support */
3595 int32_t iSliceCount = 1;
3596 if (iLayerNum >= MAX_LAYER_NUM_OF_FRAME) { // check available layer_bs_info writing as follows
3597 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d)!", iLayerNum,
3598 MAX_LAYER_NUM_OF_FRAME);
3599 return ENC_RETURN_UNSUPPORTED_PARA;
3600 }
3601
3602 iNalIdxInLayer = 0;
3603 bAvcBased = ((pSvcParam->bSimulcastAVC) || (iCurDid == BASE_DEPENDENCY_ID));
3604 pCtx->bNeedPrefixNalFlag = ((!pSvcParam->bSimulcastAVC) && (bAvcBased &&
3605 (pSvcParam->bPrefixNalAddingCtrl ||
3606 (pSvcParam->iSpatialLayerNum > 1))));
3607
3608 if (eFrameType == videoFrameTypeP) {
3609 eNalType = bAvcBased ? NAL_UNIT_CODED_SLICE : NAL_UNIT_CODED_SLICE_EXT;
3610 } else if (eFrameType == videoFrameTypeIDR) {
3611 eNalType = bAvcBased ? NAL_UNIT_CODED_SLICE_IDR : NAL_UNIT_CODED_SLICE_EXT;
3612 }
3613 if (iCurTid == 0 || pCtx->eSliceType == I_SLICE)
3614 eNalRefIdc = NRI_PRI_HIGHEST;
3615 else if (iCurTid == iDecompositionStages)
3616 eNalRefIdc = NRI_PRI_LOWEST;
3617 else if (1 + iCurTid == iDecompositionStages)
3618 eNalRefIdc = NRI_PRI_LOW;
3619 else if (2 + iCurTid == iDecompositionStages)
3620 eNalRefIdc = NRI_PRI_HIGH;
3621 else // more details for other temporal layers?
3622 eNalRefIdc = NRI_PRI_HIGHEST;
3623 pCtx->eNalType = eNalType;
3624 pCtx->eNalPriority = eNalRefIdc;
3625
3626 pCtx->pDecPic = pCtx->ppRefPicListExt[iCurDid]->pNextBuffer;
3627 #if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
3628 fsnr = pCtx->pDecPic;
3629 #endif//#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
3630 pCtx->pDecPic->iPictureType = pCtx->eSliceType;
3631 pCtx->pDecPic->iFramePoc = pParamInternal->iPOC;
3632
3633 WelsInitCurrentLayer (pCtx, iCurWidth, iCurHeight);
3634
3635 pCtx->pReferenceStrategy->MarkPic();
3636 if (!pCtx->pReferenceStrategy->BuildRefList (pParamInternal->iPOC, 0)) {
3637 WelsLog (pLogCtx, WELS_LOG_WARNING,
3638 "WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d. ForceCodingIDR!",
3639 pCtx->iNumRef0);
3640 eFrameType = videoFrameTypeIDR;
3641 pCtx->iEncoderError = ENC_RETURN_CORRECTED;
3642 break;
3643 }
3644 if (pCtx->eSliceType != I_SLICE) {
3645 pCtx->pReferenceStrategy->AfterBuildRefList();
3646 }
3647 #ifdef LONG_TERM_REF_DUMP
3648 DumpRef (pCtx);
3649 #endif
3650 if (pSvcParam->iRCMode != RC_OFF_MODE)
3651 pCtx->pVpp->AnalyzePictureComplexity (pCtx, pCtx->pEncPic, ((pCtx->eSliceType == P_SLICE)
3652 && (pCtx->iNumRef0 > 0)) ? pCtx->pRefList0[0] : NULL,
3653 iCurDid, (pCtx->eSliceType == P_SLICE) && pSvcParam->bEnableBackgroundDetection);
3654 WelsUpdateRefSyntax (pCtx, pParamInternal->iPOC,
3655 eFrameType); //get reordering syntax used for writing slice header and transmit to encoder.
3656 PrefetchReferencePicture (pCtx, eFrameType); // update reference picture for current pDq layer
3657 pCtx->pFuncList->pfRc.pfWelsRcPictureInit (pCtx, pFbi->uiTimeStamp);
3658 PreprocessSliceCoding (pCtx); // MUST be called after pfWelsRcPictureInit() and WelsInitCurrentLayer()
3659
3660 //TODO Complexity Calculation here for screen content
3661 iLayerSize = 0;
3662 if (SM_SINGLE_SLICE == pParam->sSliceArgument.uiSliceMode) { // only one slice within a sQualityStat layer
3663 int32_t iSliceSize = 0;
3664 int32_t iPayloadSize = 0;
3665 SSlice* pCurSlice = &pCtx->pCurDqLayer->sSliceBufferInfo[0].pSliceBuffer[0];
3666
3667 if (pCtx->bNeedPrefixNalFlag) {
3668 pCtx->iEncoderError = AddPrefixNal (pCtx, pLayerBsInfo, &pLayerBsInfo->pNalLengthInByte[0], &iNalIdxInLayer, eNalType,
3669 eNalRefIdc,
3670 iPayloadSize);
3671 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3672 iLayerSize += iPayloadSize;
3673 }
3674
3675 WelsLoadNal (pCtx->pOut, eNalType, eNalRefIdc);
3676 assert (0 == (int) pCurSlice->iSliceIdx);
3677 pCtx->iEncoderError = SetSliceBoundaryInfo (pCtx->pCurDqLayer, pCurSlice, 0);
3678 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3679
3680 pCtx->iEncoderError = WelsCodeOneSlice (pCtx, pCurSlice, eNalType);
3681 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3682
3683 WelsUnloadNal (pCtx->pOut);
3684
3685 pCtx->iEncoderError = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
3686 &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
3687 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
3688 pCtx->pFrameBs + pCtx->iPosBsBuffer,
3689 &pLayerBsInfo->pNalLengthInByte[iNalIdxInLayer]);
3690 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3691 iSliceSize = pLayerBsInfo->pNalLengthInByte[iNalIdxInLayer];
3692
3693 iLayerSize += iSliceSize;
3694 pCtx->iPosBsBuffer += iSliceSize;
3695 pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
3696 pLayerBsInfo->uiSpatialId = iCurDid;
3697 pLayerBsInfo->uiTemporalId = iCurTid;
3698 pLayerBsInfo->uiQualityId = 0;
3699 pLayerBsInfo->iNalCount = ++ iNalIdxInLayer;
3700 pLayerBsInfo->eFrameType = eFrameType;
3701 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
3702 }
3703 // for dynamic slicing single threading..
3704 else if ((SM_SIZELIMITED_SLICE == pParam->sSliceArgument.uiSliceMode) && (pSvcParam->iMultipleThreadIdc <= 1)) {
3705 const int32_t kiLastMbInFrame = pCtx->pCurDqLayer->sSliceEncCtx.iMbNumInFrame;
3706 pCtx->iEncoderError = WelsCodeOnePicPartition (pCtx, pFbi, pLayerBsInfo, &iNalIdxInLayer, &iLayerSize, 0,
3707 kiLastMbInFrame - 1, 0);
3708 pLayerBsInfo->eFrameType = eFrameType;
3709 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
3710 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3711 } else {
3712 //other multi-slice uiSliceMode
3713 // THREAD_FULLY_FIRE_MODE/THREAD_PICK_UP_MODE for any mode of non-SM_SIZELIMITED_SLICE
3714 if ((SM_SIZELIMITED_SLICE != pParam->sSliceArgument.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1)) {
3715 iSliceCount = GetCurrentSliceNum (pCtx->pCurDqLayer);
3716 if (iLayerNum + 1 >= MAX_LAYER_NUM_OF_FRAME) { // check available layer_bs_info for further writing as followed
3717 WelsLog (pLogCtx, WELS_LOG_ERROR,
3718 "WelsEncoderEncodeExt(), iLayerNum(%d) overflow(max:%d) at iDid= %d uiSliceMode= %d, iSliceCount= %d!",
3719 iLayerNum, MAX_LAYER_NUM_OF_FRAME, iCurDid, pParam->sSliceArgument.uiSliceMode, iSliceCount);
3720 return ENC_RETURN_UNSUPPORTED_PARA;
3721 }
3722 if (iSliceCount <= 1) {
3723 WelsLog (pLogCtx, WELS_LOG_ERROR,
3724 "WelsEncoderEncodeExt(), iSliceCount(%d) from GetCurrentSliceNum() is untrusted due stack/heap crupted!",
3725 iSliceCount);
3726 return ENC_RETURN_UNEXPECTED;
3727 }
3728 //note: the old codes are removed at commit: 3e0ee69
3729 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3730 pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
3731 pLayerBsInfo->uiSpatialId = pCtx->uiDependencyId;
3732 pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId;
3733 pLayerBsInfo->uiQualityId = 0;
3734 pLayerBsInfo->iNalCount = 0;
3735 pLayerBsInfo->eFrameType = eFrameType;
3736 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
3737
3738 pCtx->pTaskManage->ExecuteTasks();
3739 if (pCtx->iEncoderError) {
3740 WelsLog (pLogCtx, WELS_LOG_ERROR,
3741 "WelsEncoderEncodeExt(), multi-slice (mode %d) encoding error!",
3742 pParam->sSliceArgument.uiSliceMode);
3743 return pCtx->iEncoderError;
3744 }
3745
3746 iLayerSize = AppendSliceToFrameBs (pCtx, pLayerBsInfo, iSliceCount);
3747 }
3748 // THREAD_FULLY_FIRE_MODE && SM_SIZELIMITED_SLICE
3749 else if ((SM_SIZELIMITED_SLICE == pParam->sSliceArgument.uiSliceMode) && (pSvcParam->iMultipleThreadIdc > 1)) {
3750 const int32_t kiPartitionCnt = pCtx->iActiveThreadsNum;
3751
3752 //TODO: use a function to remove duplicate code here and ln3994
3753 int32_t iLayerBsIdx = pCtx->pOut->iLayerBsIndex;
3754 SLayerBSInfo* pLbi = &pFbi->sLayerInfo[iLayerBsIdx];
3755 pLbi->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
3756 pLbi->uiLayerType = VIDEO_CODING_LAYER;
3757 pLbi->uiSpatialId = pCtx->uiDependencyId;
3758 pLbi->uiTemporalId = pCtx->uiTemporalId;
3759 pLbi->uiQualityId = 0;
3760 pLbi->iNalCount = 0;
3761 pLbi->eFrameType = eFrameType;
3762 pLbi->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
3763 int32_t iIdx = 0;
3764 while (iIdx < kiPartitionCnt) {
3765 pCtx->pSliceThreading->pThreadPEncCtx[iIdx].pFrameBsInfo = pFbi;
3766 pCtx->pSliceThreading->pThreadPEncCtx[iIdx].iSliceIndex = iIdx;
3767 ++ iIdx;
3768 }
3769
3770 int32_t iRet = InitAllSlicesInThread (pCtx);
3771 if (iRet) {
3772 WelsLog (pLogCtx, WELS_LOG_ERROR,
3773 "WelsEncoderEncodeExt(), multi-slice (mode %d) InitAllSlicesInThread() error!",
3774 pParam->sSliceArgument.uiSliceMode);
3775 return ENC_RETURN_UNEXPECTED;
3776 }
3777 pCtx->pTaskManage->ExecuteTasks();
3778
3779 if (pCtx->iEncoderError) {
3780 WelsLog (pLogCtx, WELS_LOG_ERROR,
3781 "WelsEncoderEncodeExt(), multi-slice (mode %d) encoding error = %d!",
3782 pParam->sSliceArgument.uiSliceMode, pCtx->iEncoderError);
3783 return pCtx->iEncoderError;
3784 }
3785
3786 iRet = SliceLayerInfoUpdate (pCtx, pFbi, pLayerBsInfo, pParam->sSliceArgument.uiSliceMode);
3787 if (iRet) {
3788 WelsLog (pLogCtx, WELS_LOG_ERROR,
3789 "WelsEncoderEncodeExt(), multi-slice (mode %d) InitAllSlicesInThread() error!",
3790 pParam->sSliceArgument.uiSliceMode);
3791 return ENC_RETURN_UNEXPECTED;
3792 }
3793
3794 iSliceCount = GetCurrentSliceNum (pCtx->pCurDqLayer);
3795 iLayerSize = AppendSliceToFrameBs (pCtx, pLayerBsInfo, iSliceCount);
3796 } else { // for non-dynamic-slicing mode single threading branch..
3797 const bool bNeedPrefix = pCtx->bNeedPrefixNalFlag;
3798 int32_t iSliceIdx = 0;
3799 SSlice* pCurSlice = NULL;
3800
3801 iSliceCount = GetCurrentSliceNum (pCtx->pCurDqLayer);
3802 while (iSliceIdx < iSliceCount) {
3803 int32_t iSliceSize = 0;
3804 int32_t iPayloadSize = 0;
3805
3806 if (bNeedPrefix) {
3807 pCtx->iEncoderError = AddPrefixNal (pCtx, pLayerBsInfo, &pLayerBsInfo->pNalLengthInByte[0], &iNalIdxInLayer, eNalType,
3808 eNalRefIdc,
3809 iPayloadSize);
3810 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3811 iLayerSize += iPayloadSize;
3812 }
3813
3814 WelsLoadNal (pCtx->pOut, eNalType, eNalRefIdc);
3815
3816 pCurSlice = &pCtx->pCurDqLayer->sSliceBufferInfo[0].pSliceBuffer[iSliceIdx];
3817 assert (iSliceIdx == pCurSlice->iSliceIdx);
3818 pCtx->iEncoderError = SetSliceBoundaryInfo (pCtx->pCurDqLayer, pCurSlice, iSliceIdx);
3819
3820 pCtx->iEncoderError = WelsCodeOneSlice (pCtx, pCurSlice, eNalType);
3821 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3822
3823 WelsUnloadNal (pCtx->pOut);
3824
3825 pCtx->iEncoderError = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
3826 &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
3827 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
3828 pCtx->pFrameBs + pCtx->iPosBsBuffer, &pLayerBsInfo->pNalLengthInByte[iNalIdxInLayer]);
3829 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
3830 iSliceSize = pLayerBsInfo->pNalLengthInByte[iNalIdxInLayer];
3831
3832 pCtx->iPosBsBuffer += iSliceSize;
3833 iLayerSize += iSliceSize;
3834
3835 #if defined(SLICE_INFO_OUTPUT)
3836 fprintf (stderr,
3837 "@slice=%-6d sliceType:%c idc:%d size:%-6d\n",
3838 iSliceIdx,
3839 (pCtx->eSliceType == P_SLICE ? 'P' : 'I'),
3840 eNalRefIdc,
3841 iSliceSize);
3842 #endif//SLICE_INFO_OUTPUT
3843 ++ iNalIdxInLayer;
3844 ++ iSliceIdx;
3845 }
3846
3847 pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
3848 pLayerBsInfo->uiSpatialId = iCurDid;
3849 pLayerBsInfo->uiTemporalId = iCurTid;
3850 pLayerBsInfo->uiQualityId = 0;
3851 pLayerBsInfo->iNalCount = iNalIdxInLayer;
3852 pLayerBsInfo->eFrameType = eFrameType;
3853 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
3854 }
3855 }
3856
3857 if (NULL != pCtx->pFuncList->pfRc.pfWelsRcPostFrameSkipping
3858 && pCtx->pFuncList->pfRc.pfWelsRcPostFrameSkipping (pCtx, iCurDid, pFbi->uiTimeStamp)) {
3859
3860 StackBackEncoderStatus (pCtx, eFrameType);
3861 ClearFrameBsInfo (pCtx, pFbi);
3862
3863 iFrameSize = 0;
3864 iLayerSize = 0;
3865 iLayerNum = 0;
3866
3867 if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) {
3868 pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iSpatialNum);
3869 }
3870
3871 WelsRcPostFrameSkippedUpdate (pCtx, iCurDid);
3872 pCtx->iEncoderError = ENC_RETURN_SUCCESS;
3873 return ENC_RETURN_SUCCESS;
3874 }
3875
3876 // deblocking filter
3877 if (
3878 (!pCtx->pCurDqLayer->bDeblockingParallelFlag) &&
3879 #if !defined(ENABLE_FRAME_DUMP)
3880 ((eNalRefIdc != NRI_PRI_LOWEST) && (pSvcParam->sDependencyLayers[iCurDid].iHighestTemporalId == 0
3881 || iCurTid < pSvcParam->sDependencyLayers[iCurDid].iHighestTemporalId)) &&
3882 #endif//!ENABLE_FRAME_DUMP
3883 true
3884 ) {
3885 PerformDeblockingFilter (pCtx);
3886 }
3887
3888 pCtx->pFuncList->pfRc.pfWelsRcPictureInfoUpdate (pCtx, iLayerSize);
3889 iFrameSize += iLayerSize;
3890 RcTraceFrameBits (pCtx, pFbi->uiTimeStamp, iFrameSize);
3891 pCtx->pDecPic->iFrameAverageQp = pCtx->pWelsSvcRc[iCurDid].iAverageFrameQp;
3892
3893 //update scc related
3894 pCtx->pFuncList->pfUpdateFMESwitch (pCtx->pCurDqLayer);
3895
3896 // reference picture list update
3897 if (eNalRefIdc != NRI_PRI_LOWEST) {
3898 if (!pCtx->pReferenceStrategy->UpdateRefList()) {
3899 WelsLog (pLogCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), WelsUpdateRefList failed. ForceCodingIDR!");
3900 //the above is to set the next frame to be IDR
3901 pCtx->iEncoderError = ENC_RETURN_CORRECTED;
3902 break;
3903 }
3904 }
3905
3906
3907 //check MinCr
3908 {
3909 int32_t iMinCrFrameSize = (pParam->iVideoWidth * pParam->iVideoHeight * 3) >> 2; //MinCr = 2;
3910 if (pParam->uiLevelIdc == LEVEL_3_1 || pParam->uiLevelIdc == LEVEL_3_2 || pParam->uiLevelIdc == LEVEL_4_0)
3911 iMinCrFrameSize >>= 1; //MinCr = 4
3912 if (iFrameSize > iMinCrFrameSize)
3913 WelsLog (pLogCtx, WELS_LOG_WARNING,
3914 "WelsEncoderEncodeExt()MinCr Checking,codec bitstream size is larger than Level limitation");
3915 }
3916 #ifdef ENABLE_FRAME_DUMP
3917 {
3918 DumpDependencyRec (fsnr, &pSvcParam->sDependencyLayers[iCurDid].sRecFileName[0], iCurDid,
3919 pCtx->bDependencyRecFlag[iCurDid], pCtx->pCurDqLayer, pSvcParam->bSimulcastAVC);
3920 pCtx->bDependencyRecFlag[iCurDid] = true;
3921 }
3922 #endif//ENABLE_FRAME_DUMP
3923
3924 #if defined(ENABLE_PSNR_CALC)
3925 fSnrY = WelsCalcPsnr (fsnr->pData[0],
3926 fsnr->iLineSize[0],
3927 pEncPic->pData[0],
3928 pEncPic->iLineSize[0],
3929 iCurWidth,
3930 iCurHeight);
3931 fSnrU = WelsCalcPsnr (fsnr->pData[1],
3932 fsnr->iLineSize[1],
3933 pEncPic->pData[1],
3934 pEncPic->iLineSize[1],
3935 (iCurWidth >> 1),
3936 (iCurHeight >> 1));
3937 fSnrV = WelsCalcPsnr (fsnr->pData[2],
3938 fsnr->iLineSize[2],
3939 pEncPic->pData[2],
3940 pEncPic->iLineSize[2],
3941 (iCurWidth >> 1),
3942 (iCurHeight >> 1));
3943 #endif//ENABLE_PSNR_CALC
3944
3945 #if defined(LAYER_INFO_OUTPUT)
3946 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",
3947 (iSpatialIdx == 0) ? "#AU" : " ",
3948 pParamInternal->iPOC,
3949 pParamInternal->iFrameNum,
3950 (eFrameType == videoFrameTypeI || eFrameType == videoFrameTypeIDR) ? "I" : "P",
3951 iCurTid,
3952 iCurDid,
3953 0,
3954 pCtx->pWelsSvcRc[pCtx->uiDependencyId].iAverageFrameQp,
3955 fSnrY,
3956 fSnrU,
3957 fSnrV,
3958 (iLayerSize << 3));
3959 #endif//LAYER_INFO_OUTPUT
3960
3961 #if defined(STAT_OUTPUT)
3962
3963 #if defined(ENABLE_PSNR_CALC)
3964 {
3965 pCtx->sStatData[iCurDid][0].sQualityStat.rYPsnr[pCtx->eSliceType] += fSnrY;
3966 pCtx->sStatData[iCurDid][0].sQualityStat.rUPsnr[pCtx->eSliceType] += fSnrU;
3967 pCtx->sStatData[iCurDid][0].sQualityStat.rVPsnr[pCtx->eSliceType] += fSnrV;
3968 }
3969 #endif//ENABLE_PSNR_CALC
3970
3971 #if defined(MB_TYPES_CHECK) //091025, frame output
3972 if (pCtx->eSliceType == P_SLICE) {
3973 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Intra4x4] += pCtx->sPerInfo.iMbCount[P_SLICE][Intra4x4];
3974 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Intra16x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Intra16x16];
3975 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter16x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter16x16];
3976 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter16x8] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter16x8];
3977 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter8x16] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter8x16];
3978 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][Inter8x8] += pCtx->sPerInfo.iMbCount[P_SLICE][Inter8x8];
3979 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][PSkip] += pCtx->sPerInfo.iMbCount[P_SLICE][PSkip];
3980 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][8] += pCtx->sPerInfo.iMbCount[P_SLICE][8];
3981 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][9] += pCtx->sPerInfo.iMbCount[P_SLICE][9];
3982 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][10] += pCtx->sPerInfo.iMbCount[P_SLICE][10];
3983 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[P_SLICE][11] += pCtx->sPerInfo.iMbCount[P_SLICE][11];
3984 } else if (pCtx->eSliceType == I_SLICE) {
3985 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][Intra4x4] += pCtx->sPerInfo.iMbCount[I_SLICE][Intra4x4];
3986 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][Intra16x16] += pCtx->sPerInfo.iMbCount[I_SLICE][Intra16x16];
3987 pCtx->sStatData[iCurDid][0].sSliceData.iMbCount[I_SLICE][7] += pCtx->sPerInfo.iMbCount[I_SLICE][7];
3988 }
3989
3990 memset (pCtx->sPerInfo.iMbCount[P_SLICE], 0, 18 * sizeof (int32_t));
3991 memset (pCtx->sPerInfo.iMbCount[I_SLICE], 0, 18 * sizeof (int32_t));
3992
3993 #endif//MB_TYPES_CHECK
3994 {
3995 ++ pCtx->sStatData[iCurDid][0].sSliceData.iSliceCount[pCtx->eSliceType]; // for multiple slices coding
3996 pCtx->sStatData[iCurDid][0].sSliceData.iSliceSize[pCtx->eSliceType] += (iLayerSize << 3); // bits
3997 }
3998 #endif//STAT_OUTPUT
3999
4000 iCountNal = pLayerBsInfo->iNalCount;
4001 ++ iLayerNum;
4002 ++ pLayerBsInfo;
4003 ++ pCtx->pOut->iLayerBsIndex;
4004 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
4005 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
4006
4007 if (pSvcParam->iPaddingFlag && pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize > 0) {
4008 int32_t iPaddingNalSize = 0;
4009 pCtx->iEncoderError = WritePadding (pCtx, pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize, iPaddingNalSize);
4010 WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
4011
4012 #if GOM_TRACE_FLAG
4013 WelsLog (pLogCtx, WELS_LOG_INFO, "[RC] dependency ID = %d,encoding_qp = %d Padding: %d", pCtx->uiDependencyId,
4014 pCtx->iGlobalQp,
4015 pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize);
4016 #endif
4017 if (iPaddingNalSize <= 0)
4018 return ENC_RETURN_UNEXPECTED;
4019
4020 pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingBitrateStat += pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize;
4021
4022 pCtx->pWelsSvcRc[pCtx->uiDependencyId].iPaddingSize = 0;
4023
4024 pLayerBsInfo->uiSpatialId = 0;
4025 pLayerBsInfo->uiTemporalId = 0;
4026 pLayerBsInfo->uiQualityId = 0;
4027 pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
4028 pLayerBsInfo->iNalCount = 1;
4029 pLayerBsInfo->pNalLengthInByte[0] = iPaddingNalSize;
4030 pLayerBsInfo->eFrameType = eFrameType;
4031 pLayerBsInfo->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
4032 ++ pLayerBsInfo;
4033 ++ pCtx->pOut->iLayerBsIndex;
4034 pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
4035 pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + 1;
4036 ++ iLayerNum;
4037
4038 iFrameSize += iPaddingNalSize;
4039 }
4040
4041 if ((pParam->sSliceArgument.uiSliceMode == SM_FIXEDSLCNUM_SLICE)
4042 && pSvcParam->bUseLoadBalancing
4043 && pSvcParam->iMultipleThreadIdc > 1 &&
4044 pSvcParam->iMultipleThreadIdc >= pParam->sSliceArgument.uiSliceNum) {
4045 CalcSliceComplexRatio (pCtx->pCurDqLayer);
4046 #if defined(MT_DEBUG)
4047 TrackSliceComplexities (pCtx, iCurDid);
4048 #endif//#if defined(MT_DEBUG)
4049 }
4050
4051 pCtx->eLastNalPriority[iCurDid] = eNalRefIdc;
4052 ++ iSpatialIdx;
4053
4054 if (iCurDid + 1 < pSvcParam->iSpatialLayerNum) {
4055 //for next layer, note that iSpatialIdx has been ++ so it is pointer to next layer
4056 WelsSwapDqLayers (pCtx, (pSpatialIndexMap + iSpatialIdx)->iDid);
4057 }
4058
4059 if (pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, iCurDid) != 0) {
4060 ForceCodingIDR (pCtx, iCurDid);
4061 WelsLog (pLogCtx, WELS_LOG_WARNING,
4062 "WelsEncoderEncodeExt(), Logic Error Found in Preprocess updating. ForceCodingIDR!");
4063 //the above is to set the next frame IDR
4064 pFbi->eFrameType = eFrameType;
4065 pLayerBsInfo->eFrameType = eFrameType;
4066 return ENC_RETURN_CORRECTED;
4067 }
4068
4069 if (pSvcParam->bEnableLongTermReference && ((pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag
4070 && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == videoFrameTypeIDR)) {
4071 pCtx->bRefOfCurTidIsLtr[iCurDid][iCurTid] = true;
4072 }
4073 if (pSvcParam->bSimulcastAVC)
4074 ++ pParamInternal->iCodingIndex;
4075 }//end of (iSpatialIdx/iSpatialNum)
4076
4077 if (!pSvcParam->bSimulcastAVC) {
4078 for (int32_t i = 0; i < pSvcParam->iSpatialLayerNum; i++) {
4079 SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[i];
4080 pParamInternal->iCodingIndex ++;
4081 }
4082 }
4083
4084 if (ENC_RETURN_CORRECTED == pCtx->iEncoderError) {
4085 pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, (pSpatialIndexMap + iSpatialIdx)->iDid);
4086 ForceCodingIDR (pCtx, (pSpatialIndexMap + iSpatialIdx)->iDid);
4087 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), Logic Error Found in temporal level. ForceCodingIDR!");
4088 //the above is to set the next frame IDR
4089 pFbi->eFrameType = eFrameType;
4090 pLayerBsInfo->eFrameType = eFrameType;
4091 return ENC_RETURN_CORRECTED;
4092 }
4093
4094 #if defined(MT_DEBUG)
4095 TrackSliceConsumeTime (pCtx, iDidList, iSpatialNum);
4096 #endif//MT_DEBUG
4097
4098 // to check number of layers / nals / slices dependencies
4099 if (iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
4100 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
4101 iLayerNum, MAX_LAYER_NUM_OF_FRAME);
4102 return 1;
4103 }
4104
4105
4106 pFbi->iLayerNum = iLayerNum;
4107
4108 WelsLog (pLogCtx, WELS_LOG_DEBUG, "WelsEncoderEncodeExt() OutputInfo iLayerNum = %d,iFrameSize = %d",
4109 iLayerNum, iFrameSize);
4110 for (int32_t i = 0; i < iLayerNum; i++)
4111 WelsLog (pLogCtx, WELS_LOG_DEBUG,
4112 "WelsEncoderEncodeExt() OutputInfo iLayerId = %d,iNalType = %d,iNalCount = %d, first Nal Length=%d,uiSpatialId = %d,uiTemporalId = %d,iSubSeqId = %d",
4113 i,
4114 pFbi->sLayerInfo[i].uiLayerType, pFbi->sLayerInfo[i].iNalCount, pFbi->sLayerInfo[i].pNalLengthInByte[0],
4115 pFbi->sLayerInfo[i].uiSpatialId, pFbi->sLayerInfo[i].uiTemporalId, pFbi->sLayerInfo[i].iSubSeqId);
4116 WelsEmms();
4117
4118 pLayerBsInfo->eFrameType = eFrameType;
4119 pFbi->iFrameSizeInBytes = iFrameSize;
4120 pFbi->eFrameType = eFrameType;
4121 for (int32_t k = 0; k < pFbi->iLayerNum; k++) {
4122 if (pFbi->eFrameType != pFbi->sLayerInfo[k].eFrameType) {
4123 pFbi->eFrameType = videoFrameTypeIPMixed;
4124 }
4125 }
4126 #ifdef _DEBUG
4127 if (pFbi->iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
4128 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
4129 pFbi->iLayerNum, MAX_LAYER_NUM_OF_FRAME);
4130 return ENC_RETURN_UNEXPECTED;
4131 }
4132
4133 int32_t iTotalNal = 0;
4134 for (int32_t k = 0; k < pFbi->iLayerNum; k++) {
4135 iTotalNal += pFbi->sLayerInfo[k].iNalCount;
4136
4137 if ((pCtx->iActiveThreadsNum > 1) && (MAX_NAL_UNITS_IN_LAYER < pFbi->sLayerInfo[k].iNalCount)) {
4138 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR,
4139 "WelsEncoderEncodeExt(), iCountNumNals(%d) > MAX_NAL_UNITS_IN_LAYER(%d) under multi-thread(%d) NOT supported!",
4140 pFbi->sLayerInfo[k].iNalCount, MAX_NAL_UNITS_IN_LAYER, pCtx->iActiveThreadsNum);
4141 return ENC_RETURN_UNEXPECTED;
4142 }
4143 }
4144
4145 if (iTotalNal > pCtx->pOut->iCountNals) {
4146 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iTotalNal(%d) > iCountNals(%d)!",
4147 iTotalNal, pCtx->pOut->iCountNals);
4148 return ENC_RETURN_UNEXPECTED;
4149 }
4150 #endif
4151 return ENC_RETURN_SUCCESS;
4152 }
4153
4154 /*!
4155 * \brief Wels SVC encoder parameters adjustment
4156 * SVC adjustment results in new requirement in memory blocks adjustment
4157 */
WelsEncoderParamAdjust(sWelsEncCtx ** ppCtx,SWelsSvcCodingParam * pNewParam)4158 int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewParam) {
4159 SWelsSvcCodingParam* pOldParam = NULL;
4160 int32_t iReturn = ENC_RETURN_SUCCESS;
4161 int8_t iIndexD = 0;
4162 bool bNeedReset = false;
4163 int16_t iSliceNum = 1; // number of slices used
4164 int32_t iCacheLineSize = 16; // on chip cache line size in byte
4165 uint32_t uiCpuFeatureFlags = 0;
4166
4167 if (NULL == ppCtx || NULL == *ppCtx || NULL == pNewParam) return 1;
4168
4169 /* Check validation in new parameters */
4170 iReturn = ParamValidationExt (& (*ppCtx)->sLogCtx, pNewParam);
4171 if (iReturn != ENC_RETURN_SUCCESS) return iReturn;
4172
4173 iReturn = GetMultipleThreadIdc (& (*ppCtx)->sLogCtx, pNewParam, iSliceNum, iCacheLineSize, uiCpuFeatureFlags);
4174 if (iReturn != ENC_RETURN_SUCCESS) {
4175 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR, "WelsEncoderParamAdjust(), GetMultipleThreadIdc failed return %d.",
4176 iReturn);
4177 return iReturn;
4178 }
4179
4180 pOldParam = (*ppCtx)->pSvcParam;
4181
4182 if (pOldParam->iUsageType != pNewParam->iUsageType) {
4183 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
4184 "WelsEncoderParamAdjust(), does not expect in-middle change of iUsgaeType from %d to %d", pOldParam->iUsageType,
4185 pNewParam->iUsageType);
4186 return ENC_RETURN_UNSUPPORTED_PARA;
4187 }
4188
4189 /* Decide whether need reset for IDR frame based on adjusting prarameters changed */
4190 /* Temporal levels, spatial settings and/ or quality settings changed need update parameter sets related. */
4191 bNeedReset = (pOldParam == NULL) ||
4192 (pOldParam->bSimulcastAVC != pNewParam->bSimulcastAVC) ||
4193 (pOldParam->iSpatialLayerNum != pNewParam->iSpatialLayerNum) ||
4194 (pOldParam->iPicWidth != pNewParam->iPicWidth
4195 || pOldParam->iPicHeight != pNewParam->iPicHeight) ||
4196 (pOldParam->SUsedPicRect.iWidth != pNewParam->SUsedPicRect.iWidth
4197 || pOldParam->SUsedPicRect.iHeight != pNewParam->SUsedPicRect.iHeight) ||
4198 (pOldParam->bEnableLongTermReference != pNewParam->bEnableLongTermReference) ||
4199 (pOldParam->iLTRRefNum != pNewParam->iLTRRefNum) ||
4200 (pOldParam->iMultipleThreadIdc != pNewParam->iMultipleThreadIdc) ||
4201 (pOldParam->bEnableBackgroundDetection != pNewParam->bEnableBackgroundDetection) ||
4202 (pOldParam->bEnableAdaptiveQuant != pNewParam->bEnableAdaptiveQuant) ||
4203 (pOldParam->eSpsPpsIdStrategy != pNewParam->eSpsPpsIdStrategy);
4204 if ((pNewParam->iMaxNumRefFrame > pOldParam->iMaxNumRefFrame) ||
4205 ((pOldParam->iMaxNumRefFrame == 1) && (pOldParam->iTemporalLayerNum == 1) && (pNewParam->iTemporalLayerNum == 2))) {
4206 bNeedReset = true;
4207 }
4208 if (bNeedReset) {
4209 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4210 "WelsEncoderParamAdjust(),bSimulcastAVC(%d,%d),iSpatialLayerNum(%d,%d),iPicWidth(%d,%d),iPicHeight(%d,%d),Rect.iWidth(%d,%d),Rect.iHeight(%d,%d)",
4211 pOldParam->bSimulcastAVC, pNewParam->bSimulcastAVC,
4212 pOldParam->iSpatialLayerNum, pNewParam->iSpatialLayerNum,
4213 pOldParam->iPicWidth, pNewParam->iPicWidth,
4214 pOldParam->iPicHeight, pNewParam->iPicHeight,
4215 pOldParam->SUsedPicRect.iWidth, pNewParam->SUsedPicRect.iWidth,
4216 pOldParam->SUsedPicRect.iHeight, pNewParam->SUsedPicRect.iHeight);
4217
4218 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4219 "WelsEncoderParamAdjust(),bEnableLongTermReference(%d,%d),iLTRRefNum(%d,%d),iMultipleThreadIdc(%d,%d),bEnableBackgroundDetection(%d,%d),bEnableAdaptiveQuant(%d,%d),eSpsPpsIdStrategy(%d,%d),iMaxNumRefFrame(%d,%d),iTemporalLayerNum(%d,%d)",
4220 pOldParam->bEnableLongTermReference, pNewParam->bEnableLongTermReference,
4221 pOldParam->iLTRRefNum, pNewParam->iLTRRefNum,
4222 pOldParam->iMultipleThreadIdc, pNewParam->iMultipleThreadIdc,
4223 pOldParam->bEnableBackgroundDetection, pNewParam->bEnableBackgroundDetection,
4224 pOldParam->bEnableAdaptiveQuant, pNewParam->bEnableAdaptiveQuant,
4225 pOldParam->eSpsPpsIdStrategy, pNewParam->eSpsPpsIdStrategy,
4226 pOldParam->iMaxNumRefFrame, pNewParam->iMaxNumRefFrame,
4227 pOldParam->iTemporalLayerNum, pNewParam->iTemporalLayerNum);
4228 }
4229 if (!bNeedReset) { // Check its picture resolutions/quality settings respectively in each dependency layer
4230 iIndexD = 0;
4231 assert (pOldParam->iSpatialLayerNum == pNewParam->iSpatialLayerNum);
4232 do {
4233 const SSpatialLayerInternal* kpOldDlp = &pOldParam->sDependencyLayers[iIndexD];
4234 const SSpatialLayerInternal* kpNewDlp = &pNewParam->sDependencyLayers[iIndexD];
4235 float fT1 = .0f;
4236 float fT2 = .0f;
4237
4238 // check frame size settings
4239 if (pOldParam->sSpatialLayers[iIndexD].iVideoWidth != pNewParam->sSpatialLayers[iIndexD].iVideoWidth ||
4240 pOldParam->sSpatialLayers[iIndexD].iVideoHeight != pNewParam->sSpatialLayers[iIndexD].iVideoHeight ||
4241 kpOldDlp->iActualWidth != kpNewDlp->iActualWidth ||
4242 kpOldDlp->iActualHeight != kpNewDlp->iActualHeight) {
4243 bNeedReset = true;
4244 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4245 "WelsEncoderParamAdjust(),iIndexD = %d,sSpatialLayers.wxh_old(%d,%d),sSpatialLayers.wxh_new(%d,%d),iActualwxh_old(%d,%d),iActualwxh_new(%d,%d)",
4246 iIndexD, pOldParam->sSpatialLayers[iIndexD].iVideoWidth, pOldParam->sSpatialLayers[iIndexD].iVideoHeight,
4247 pNewParam->sSpatialLayers[iIndexD].iVideoWidth, pNewParam->sSpatialLayers[iIndexD].iVideoHeight,
4248 kpOldDlp->iActualWidth, kpOldDlp->iActualHeight,
4249 kpNewDlp->iActualWidth, kpNewDlp->iActualHeight);
4250 break;
4251 }
4252
4253 if (pOldParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceMode !=
4254 pNewParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceMode
4255 ||
4256 pOldParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceNum !=
4257 pNewParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceNum) {
4258
4259 bNeedReset = true;
4260 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4261 "WelsEncoderParamAdjust(),iIndexD = %d,uiSliceMode (%d,%d),uiSliceNum(%d,%d)", iIndexD,
4262 pOldParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceMode,
4263 pNewParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceMode,
4264 pOldParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceNum,
4265 pNewParam->sSpatialLayers[iIndexD].sSliceArgument.uiSliceNum);
4266
4267 break;
4268 }
4269
4270 // check frame rate
4271 // we can not check whether corresponding fFrameRate is equal or not,
4272 // only need to check d_max/d_min and max_fr/d_max whether it is equal or not
4273 if (kpNewDlp->fInputFrameRate > EPSN && kpOldDlp->fInputFrameRate > EPSN)
4274 fT1 = kpNewDlp->fOutputFrameRate / kpNewDlp->fInputFrameRate - kpOldDlp->fOutputFrameRate / kpOldDlp->fInputFrameRate;
4275 if (kpNewDlp->fOutputFrameRate > EPSN && kpOldDlp->fOutputFrameRate > EPSN)
4276 fT2 = pNewParam->fMaxFrameRate / kpNewDlp->fOutputFrameRate - pOldParam->fMaxFrameRate / kpOldDlp->fOutputFrameRate;
4277 if (fT1 > EPSN || fT1 < -EPSN || fT2 > EPSN || fT2 < -EPSN) {
4278 bNeedReset = true;
4279 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4280 "WelsEncoderParamAdjust() iIndexD = %d,fInputFrameRate(%f,%f),fOutputFrameRate(%f,%f),fMaxFrameRate(%f,%f)", iIndexD,
4281 kpOldDlp->fInputFrameRate, kpNewDlp->fInputFrameRate,
4282 kpOldDlp->fOutputFrameRate, kpNewDlp->fOutputFrameRate,
4283 pOldParam->fMaxFrameRate, pNewParam->fMaxFrameRate);
4284 break;
4285 }
4286 if (pOldParam->sSpatialLayers[iIndexD].uiProfileIdc != pNewParam->sSpatialLayers[iIndexD].uiProfileIdc) {
4287 bNeedReset = true;
4288 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4289 "WelsEncoderParamAdjust(),iIndexD = %d,uiProfileIdc(%d,%d)", iIndexD,
4290 pOldParam->sSpatialLayers[iIndexD].uiProfileIdc, pNewParam->sSpatialLayers[iIndexD].uiProfileIdc);
4291 break;
4292 }
4293 //check level change,if new level is smaller than old level,don't reset encoder. still use old level.
4294
4295 if (pNewParam->sSpatialLayers[iIndexD].uiLevelIdc > pOldParam->sSpatialLayers[iIndexD].uiLevelIdc) {
4296 bNeedReset = true;
4297 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO,
4298 "WelsEncoderParamAdjust(),iIndexD = %d,uiLevelIdc(%d,%d)", iIndexD,
4299 pOldParam->sSpatialLayers[iIndexD].uiLevelIdc, pNewParam->sSpatialLayers[iIndexD].uiLevelIdc);
4300 break;
4301 }
4302 ++ iIndexD;
4303 } while (iIndexD < pOldParam->iSpatialLayerNum);
4304 }
4305
4306 if (bNeedReset) {
4307 SLogContext sLogCtx = (*ppCtx)->sLogCtx;
4308
4309 int32_t iOldSpsPpsIdStrategy = pOldParam->eSpsPpsIdStrategy;
4310 SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
4311 int32_t iTmpPpsIdList[MAX_DQ_LAYER_NUM * MAX_PPS_COUNT];
4312 //for LTR or SPS,PPS ID update
4313 uint16_t uiMaxIdrPicId = 0;
4314 for (iIndexD = 0; iIndexD < pOldParam->iSpatialLayerNum; iIndexD++) {
4315 if (pOldParam->sDependencyLayers[iIndexD].uiIdrPicId > uiMaxIdrPicId)
4316 uiMaxIdrPicId = pOldParam->sDependencyLayers[iIndexD].uiIdrPicId;
4317 }
4318
4319 //for sEncoderStatistics
4320 SEncoderStatistics sTempEncoderStatistics[MAX_DEPENDENCY_LAYER];
4321 memcpy (sTempEncoderStatistics, (*ppCtx)->sEncoderStatistics, sizeof (sTempEncoderStatistics));
4322 int64_t uiStartTimestamp = (*ppCtx)->uiStartTimestamp;
4323 int32_t iStatisticsLogInterval = (*ppCtx)->iStatisticsLogInterval;
4324 int64_t iLastStatisticsLogTs = (*ppCtx)->iLastStatisticsLogTs;
4325 //for sEncoderStatistics
4326
4327 SExistingParasetList sExistingParasetList;
4328 SExistingParasetList* pExistingParasetList = NULL;
4329
4330 if (((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy))) {
4331 (*ppCtx)->pFuncList->pParametersetStrategy->OutputCurrentStructure (sTmpPsoVariable, iTmpPpsIdList, (*ppCtx),
4332 &sExistingParasetList);
4333
4334 if ((SPS_LISTING & iOldSpsPpsIdStrategy)
4335 && (SPS_LISTING & pNewParam->eSpsPpsIdStrategy)) {
4336 pExistingParasetList = &sExistingParasetList;
4337 }
4338 }
4339
4340 WelsUninitEncoderExt (ppCtx);
4341
4342 /* Update new parameters */
4343 if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx, pExistingParasetList))
4344 return 1;
4345 //if WelsInitEncoderExt succeed
4346 //for LTR or SPS,PPS ID update
4347 for (iIndexD = 0; iIndexD < pNewParam->iSpatialLayerNum; iIndexD++) {
4348 (*ppCtx)->pSvcParam->sDependencyLayers[iIndexD].uiIdrPicId = uiMaxIdrPicId;
4349 }
4350
4351 //for sEncoderStatistics
4352 memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics));
4353 (*ppCtx)->uiStartTimestamp = uiStartTimestamp;
4354 (*ppCtx)->iStatisticsLogInterval = iStatisticsLogInterval;
4355 (*ppCtx)->iLastStatisticsLogTs = iLastStatisticsLogTs;
4356 //for sEncoderStatistics
4357
4358 //load back the needed structure for eSpsPpsIdStrategy
4359 if (((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy))
4360 || ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
4361 && (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy))) {
4362 (*ppCtx)->pFuncList->pParametersetStrategy->LoadPreviousStructure (sTmpPsoVariable, iTmpPpsIdList);
4363 }
4364 } else {
4365 /* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */
4366 pNewParam->iNumRefFrame = WELS_CLIP3 (pNewParam->iNumRefFrame, MIN_REF_PIC_COUNT,
4367 (pNewParam->iUsageType == CAMERA_VIDEO_REAL_TIME ? MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA :
4368 MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN));
4369 pNewParam->iLoopFilterDisableIdc = WELS_CLIP3 (pNewParam->iLoopFilterDisableIdc, 0, 6);
4370 pNewParam->iLoopFilterAlphaC0Offset = WELS_CLIP3 (pNewParam->iLoopFilterAlphaC0Offset, -6, 6);
4371 pNewParam->iLoopFilterBetaOffset = WELS_CLIP3 (pNewParam->iLoopFilterBetaOffset, -6, 6);
4372 pNewParam->fMaxFrameRate = WELS_CLIP3 (pNewParam->fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
4373
4374 // we can not use direct struct based memcpy due some fields need keep unchanged as before
4375 pOldParam->fMaxFrameRate = pNewParam->fMaxFrameRate; // maximal frame rate [Hz / fps]
4376 pOldParam->iComplexityMode = pNewParam->iComplexityMode; // color space of input sequence
4377 pOldParam->uiIntraPeriod = pNewParam->uiIntraPeriod; // intra period (multiple of GOP size as desired)
4378 pOldParam->eSpsPpsIdStrategy = pNewParam->eSpsPpsIdStrategy;
4379 pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl;
4380 pOldParam->iNumRefFrame = pNewParam->iNumRefFrame; // number of reference frame used
4381 pOldParam->uiGopSize = pNewParam->uiGopSize;
4382 if (pOldParam->iTemporalLayerNum != pNewParam->iTemporalLayerNum) {
4383 pOldParam->iTemporalLayerNum = pNewParam->iTemporalLayerNum;
4384 for (int32_t iIndexD = 0; iIndexD < MAX_DEPENDENCY_LAYER; iIndexD++)
4385 pOldParam->sDependencyLayers[iIndexD].iCodingIndex = 0;
4386 }
4387 pOldParam->iDecompStages = pNewParam->iDecompStages;
4388 /* denoise control */
4389 pOldParam->bEnableDenoise = pNewParam->bEnableDenoise;
4390
4391 /* background detection control */
4392 pOldParam->bEnableBackgroundDetection = pNewParam->bEnableBackgroundDetection;
4393
4394 /* adaptive quantization control */
4395 pOldParam->bEnableAdaptiveQuant = pNewParam->bEnableAdaptiveQuant;
4396
4397 /* int32_t term reference control */
4398 pOldParam->bEnableLongTermReference = pNewParam->bEnableLongTermReference;
4399 pOldParam->iLtrMarkPeriod = pNewParam->iLtrMarkPeriod;
4400
4401 // keep below values unchanged as before
4402 pOldParam->bEnableSSEI = pNewParam->bEnableSSEI;
4403 pOldParam->bSimulcastAVC = pNewParam->bSimulcastAVC;
4404 pOldParam->bEnableFrameCroppingFlag = pNewParam->bEnableFrameCroppingFlag; // enable frame cropping flag
4405
4406 /* Motion search */
4407
4408 /* Deblocking loop filter */
4409 pOldParam->iLoopFilterDisableIdc =
4410 pNewParam->iLoopFilterDisableIdc; // 0: on, 1: off, 2: on except for slice boundaries
4411 pOldParam->iLoopFilterAlphaC0Offset = pNewParam->iLoopFilterAlphaC0Offset;// AlphaOffset: valid range [-6, 6], default 0
4412 pOldParam->iLoopFilterBetaOffset =
4413 pNewParam->iLoopFilterBetaOffset; // BetaOffset: valid range [-6, 6], default 0
4414
4415 /* Rate Control */
4416 pOldParam->iRCMode = pNewParam->iRCMode;
4417 pOldParam->iTargetBitrate =
4418 pNewParam->iTargetBitrate; // overall target bitrate introduced in RC module
4419 pOldParam->iPaddingFlag = pNewParam->iPaddingFlag;
4420
4421 /* Layer definition */
4422 pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl;
4423
4424 // d
4425 iIndexD = 0;
4426 do {
4427 SSpatialLayerInternal* pOldDlpInternal = &pOldParam->sDependencyLayers[iIndexD];
4428 SSpatialLayerInternal* pNewDlpInternal = &pNewParam->sDependencyLayers[iIndexD];
4429
4430 SSpatialLayerConfig* pOldDlp = &pOldParam->sSpatialLayers[iIndexD];
4431 SSpatialLayerConfig* pNewDlp = &pNewParam->sSpatialLayers[iIndexD];
4432
4433 pOldDlpInternal->fInputFrameRate = pNewDlpInternal->fInputFrameRate; // input frame rate
4434 pOldDlpInternal->fOutputFrameRate = pNewDlpInternal->fOutputFrameRate; // output frame rate
4435 pOldDlp->iSpatialBitrate = pNewDlp->iSpatialBitrate;
4436 pOldDlp->iMaxSpatialBitrate = pNewDlp->iMaxSpatialBitrate;
4437 pOldDlp->uiProfileIdc =
4438 pNewDlp->uiProfileIdc; // value of profile IDC (0 for auto-detection)
4439 pOldDlp->iDLayerQp = pNewDlp->iDLayerQp;
4440
4441 /* Derived variants below */
4442 pOldDlpInternal->iTemporalResolution = pNewDlpInternal->iTemporalResolution;
4443 pOldDlpInternal->iDecompositionStages = pNewDlpInternal->iDecompositionStages;
4444 memcpy (pOldDlpInternal->uiCodingIdx2TemporalId, pNewDlpInternal->uiCodingIdx2TemporalId,
4445 sizeof (pOldDlpInternal->uiCodingIdx2TemporalId)); // confirmed_safe_unsafe_usage
4446 ++ iIndexD;
4447 } while (iIndexD < pOldParam->iSpatialLayerNum);
4448 }
4449
4450 /* Any else initialization/reset for rate control here? */
4451
4452 return 0;
4453 }
4454
WelsEncoderApplyLTR(SLogContext * pLogCtx,sWelsEncCtx ** ppCtx,SLTRConfig * pLTRValue)4455 int32_t WelsEncoderApplyLTR (SLogContext* pLogCtx, sWelsEncCtx** ppCtx, SLTRConfig* pLTRValue) {
4456 SWelsSvcCodingParam sConfig;
4457 int32_t iNumRefFrame = 1;
4458 int32_t iRet = 0;
4459 memcpy (&sConfig, (*ppCtx)->pSvcParam, sizeof (SWelsSvcCodingParam));
4460 sConfig.bEnableLongTermReference = pLTRValue->bEnableLongTermReference;
4461 sConfig.iLTRRefNum = pLTRValue->iLTRRefNum;
4462 int32_t uiGopSize = 1 << (sConfig.iTemporalLayerNum - 1);
4463 if (sConfig.iUsageType == SCREEN_CONTENT_REAL_TIME) {
4464 if (sConfig.bEnableLongTermReference) {
4465 sConfig.iLTRRefNum = LONG_TERM_REF_NUM_SCREEN;//WELS_CLIP3 (sConfig.iLTRRefNum, 1, LONG_TERM_REF_NUM_SCREEN);
4466 iNumRefFrame = WELS_MAX (1, WELS_LOG2 (uiGopSize)) + sConfig.iLTRRefNum;
4467 } else {
4468 sConfig.iLTRRefNum = 0;
4469 iNumRefFrame = WELS_MAX (1, uiGopSize >> 1);
4470 }
4471 } else {
4472 if (sConfig.bEnableLongTermReference) {
4473 sConfig.iLTRRefNum = LONG_TERM_REF_NUM;//WELS_CLIP3 (sConfig.iLTRRefNum, 1, LONG_TERM_REF_NUM);
4474 } else {
4475 sConfig.iLTRRefNum = 0;
4476 }
4477 iNumRefFrame = ((uiGopSize >> 1) > 1) ? ((uiGopSize >> 1) + sConfig.iLTRRefNum) : (MIN_REF_PIC_COUNT +
4478 sConfig.iLTRRefNum);
4479 iNumRefFrame = WELS_CLIP3 (iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA);
4480
4481 }
4482 if (iNumRefFrame > sConfig.iMaxNumRefFrame) {
4483 WelsLog (pLogCtx, WELS_LOG_WARNING,
4484 " CWelsH264SVCEncoder::SetOption LTR flag = %d and number = %d: Required number of reference increased to %d and iMaxNumRefFrame is adjusted (from %d)",
4485 sConfig.bEnableLongTermReference, sConfig.iLTRRefNum, iNumRefFrame, sConfig.iMaxNumRefFrame);
4486 sConfig.iMaxNumRefFrame = iNumRefFrame;
4487 }
4488
4489 if (sConfig.iNumRefFrame < iNumRefFrame) {
4490 WelsLog (pLogCtx, WELS_LOG_WARNING,
4491 " CWelsH264SVCEncoder::SetOption LTR flag = %d and number = %d, Required number of reference increased from Old = %d to New = %d because of LTR setting",
4492 sConfig.bEnableLongTermReference, sConfig.iLTRRefNum, sConfig.iNumRefFrame, iNumRefFrame);
4493 sConfig.iNumRefFrame = iNumRefFrame;
4494 }
4495 WelsLog (pLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption enable LTR = %d,ltrnum = %d",
4496 sConfig.bEnableLongTermReference, sConfig.iLTRRefNum);
4497 iRet = WelsEncoderParamAdjust (ppCtx, &sConfig);
4498 return iRet;
4499 }
4500
DynSliceRealloc(sWelsEncCtx * pCtx,SFrameBSInfo * pFrameBsInfo,SLayerBSInfo * pLayerBsInfo)4501 int32_t DynSliceRealloc (sWelsEncCtx* pCtx,
4502 SFrameBSInfo* pFrameBsInfo,
4503 SLayerBSInfo* pLayerBsInfo) {
4504 int32_t iRet = 0;
4505
4506 iRet = FrameBsRealloc (pCtx, pFrameBsInfo, pLayerBsInfo, pCtx->pCurDqLayer->iMaxSliceNum);
4507 if (ENC_RETURN_SUCCESS != iRet) {
4508 return iRet;
4509 }
4510
4511 iRet = ReallocSliceBuffer (pCtx);
4512 if (ENC_RETURN_SUCCESS != iRet) {
4513 return iRet;
4514 }
4515
4516 return iRet;
4517 }
4518
WelsCodeOnePicPartition(sWelsEncCtx * pCtx,SFrameBSInfo * pFrameBSInfo,SLayerBSInfo * pLayerBsInfo,int32_t * pNalIdxInLayer,int32_t * pLayerSize,int32_t iFirstMbIdxInPartition,int32_t iEndMbIdxInPartition,int32_t iStartSliceIdx)4519 int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
4520 SFrameBSInfo* pFrameBSInfo,
4521 SLayerBSInfo* pLayerBsInfo,
4522 int32_t* pNalIdxInLayer,
4523 int32_t* pLayerSize,
4524 int32_t iFirstMbIdxInPartition,
4525 int32_t iEndMbIdxInPartition,
4526 int32_t iStartSliceIdx
4527 ) {
4528
4529 SDqLayer* pCurLayer = pCtx->pCurDqLayer;
4530 uint32_t uSlcBuffIdx = 0;
4531 SSlice* pStartSlice = &pCurLayer->sSliceBufferInfo[uSlcBuffIdx].pSliceBuffer[iStartSliceIdx];
4532 int32_t iNalIdxInLayer = *pNalIdxInLayer;
4533 int32_t iSliceIdx = iStartSliceIdx;
4534 const int32_t kiSliceStep = pCtx->iActiveThreadsNum;
4535 const int32_t kiPartitionId = iStartSliceIdx % kiSliceStep;
4536 int32_t iPartitionBsSize = 0;
4537 int32_t iAnyMbLeftInPartition = iEndMbIdxInPartition - iFirstMbIdxInPartition + 1;
4538 const EWelsNalUnitType keNalType = pCtx->eNalType;
4539 const EWelsNalRefIdc keNalRefIdc = pCtx->eNalPriority;
4540 const bool kbNeedPrefix = pCtx->bNeedPrefixNalFlag;
4541 const int32_t kiSliceIdxStep = pCtx->iActiveThreadsNum;
4542 int32_t iReturn = ENC_RETURN_SUCCESS;
4543
4544 pStartSlice->sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = iFirstMbIdxInPartition;
4545
4546 while (iAnyMbLeftInPartition > 0) {
4547 int32_t iSliceSize = 0;
4548 int32_t iPayloadSize = 0;
4549 SSlice* pCurSlice = NULL;
4550
4551 if (iSliceIdx >= (pCurLayer->sSliceBufferInfo[uSlcBuffIdx].iMaxSliceNum -
4552 kiSliceIdxStep)) { // insufficient memory in pSliceInLayer[]
4553 if (pCtx->iActiveThreadsNum == 1) {
4554 //only single thread support re-alloc now
4555 if (DynSliceRealloc (pCtx, pFrameBSInfo, pLayerBsInfo)) {
4556 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
4557 "CWelsH264SVCEncoder::WelsCodeOnePicPartition: DynSliceRealloc not successful");
4558 return ENC_RETURN_MEMALLOCERR;
4559 }
4560 } else if (iSliceIdx >= pCurLayer->iMaxSliceNum) {
4561 WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
4562 "CWelsH264SVCEncoder::WelsCodeOnePicPartition: iSliceIdx(%d) over iMaxSliceNum(%d)", iSliceIdx,
4563 pCurLayer->iMaxSliceNum);
4564 return ENC_RETURN_MEMALLOCERR;
4565 }
4566 }
4567
4568 if (kbNeedPrefix) {
4569 iReturn = AddPrefixNal (pCtx, pLayerBsInfo, &pLayerBsInfo->pNalLengthInByte[0], &iNalIdxInLayer, keNalType, keNalRefIdc,
4570 iPayloadSize);
4571 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
4572 iPartitionBsSize += iPayloadSize;
4573 }
4574
4575 WelsLoadNal (pCtx->pOut, keNalType, keNalRefIdc);
4576 pCurSlice = &pCtx->pCurDqLayer->sSliceBufferInfo[uSlcBuffIdx].pSliceBuffer[iSliceIdx];
4577 pCurSlice->iSliceIdx = iSliceIdx;
4578
4579 iReturn = WelsCodeOneSlice (pCtx, pCurSlice, keNalType);
4580 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
4581 WelsUnloadNal (pCtx->pOut);
4582
4583 iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[pCtx->pOut->iNalIndex - 1],
4584 &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt,
4585 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,
4586 pCtx->pFrameBs + pCtx->iPosBsBuffer,
4587 &pLayerBsInfo->pNalLengthInByte[iNalIdxInLayer]);
4588 WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
4589 iSliceSize = pLayerBsInfo->pNalLengthInByte[iNalIdxInLayer];
4590
4591 pCtx->iPosBsBuffer += iSliceSize;
4592 iPartitionBsSize += iSliceSize;
4593
4594 #if defined(SLICE_INFO_OUTPUT)
4595 fprintf (stderr,
4596 "@slice=%-6d sliceType:%c idc:%d size:%-6d\n",
4597 iSliceIdx,
4598 (pCtx->eSliceType == P_SLICE ? 'P' : 'I'),
4599 keNalRefIdc,
4600 iSliceSize);
4601 #endif//SLICE_INFO_OUTPUT
4602
4603 ++ iNalIdxInLayer;
4604 iSliceIdx += kiSliceStep; //if iSliceIdx is not continuous
4605 iAnyMbLeftInPartition = iEndMbIdxInPartition - pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId];
4606 }
4607
4608 *pLayerSize = iPartitionBsSize;
4609 *pNalIdxInLayer = iNalIdxInLayer;
4610
4611 // slice based packing???
4612 pLayerBsInfo->uiLayerType = VIDEO_CODING_LAYER;
4613 pLayerBsInfo->uiSpatialId = pCtx->uiDependencyId;
4614 pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId;
4615 pLayerBsInfo->uiQualityId = 0;
4616 pLayerBsInfo->iNalCount = iNalIdxInLayer;
4617 return ENC_RETURN_SUCCESS;
4618 }
4619 } // namespace WelsEnc
4620