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.c
33 *
34 * \brief core encoder
35 *
36 * \date 5/14/2009 Created
37 *
38 *************************************************************************************
39 */
40 #include "encoder.h"
41 #include "cpu_core.h"
42
43 #include "decode_mb_aux.h"
44 #include "get_intra_predictor.h"
45
46 #include "deblocking.h"
47 #include "ref_list_mgr_svc.h"
48 #include "mc.h"
49 #include "paraset_strategy.h"
50 #include "sample.h"
51
52 #include "svc_enc_golomb.h"
53 #include "svc_base_layer_md.h"
54 #include "svc_mode_decision.h"
55 #include "set_mb_syn_cavlc.h"
56 #include "crt_util_safe_x.h" // Safe CRT routines like utils for cross_platforms
57 #include "slice_multi_threading.h"
58
59 // global function pointers definition
60 namespace WelsEnc {
61 /* Motion compensation */
62
63
64 /*!
65 * \brief initialize source picture body
66 * \param pSrc SSourcePicture*
67 * \param csp internal csp format
68 * \param iWidth widht of picture in pixels
69 * \param iHeight iHeight of picture in pixels
70 * \return successful - 0; otherwise none 0 for failed
71 */
InitPic(const void * kpSrc,const int32_t kiColorspace,const int32_t kiWidth,const int32_t kiHeight)72 int32_t InitPic (const void* kpSrc, const int32_t kiColorspace, const int32_t kiWidth, const int32_t kiHeight) {
73 SSourcePicture* pSrcPic = (SSourcePicture*)kpSrc;
74
75 if (NULL == pSrcPic || kiWidth == 0 || kiHeight == 0)
76 return 1;
77
78 pSrcPic->iColorFormat = kiColorspace;
79 pSrcPic->iPicWidth = kiWidth;
80 pSrcPic->iPicHeight = kiHeight;
81
82 //currently encoder only supports videoFormatI420.
83 if ((kiColorspace & (~videoFormatVFlip)) != videoFormatI420)
84 return 2;
85 switch (kiColorspace & (~videoFormatVFlip)) {
86 case videoFormatI420:
87 case videoFormatYV12:
88 pSrcPic->pData[0] = NULL;
89 pSrcPic->pData[1] = NULL;
90 pSrcPic->pData[2] = NULL;
91 pSrcPic->pData[3] = NULL;
92 pSrcPic->iStride[0] = kiWidth;
93 pSrcPic->iStride[2] = pSrcPic->iStride[1] = kiWidth >> 1;
94 pSrcPic->iStride[3] = 0;
95 break;
96 case videoFormatYUY2:
97 case videoFormatYVYU:
98 case videoFormatUYVY:
99 pSrcPic->pData[0] = NULL;
100 pSrcPic->pData[1] = NULL;
101 pSrcPic->pData[2] = NULL;
102 pSrcPic->pData[3] = NULL;
103 pSrcPic->iStride[0] = CALC_BI_STRIDE (kiWidth, 16);
104 pSrcPic->iStride[3] = pSrcPic->iStride[2] = pSrcPic->iStride[1] = 0;
105 break;
106 case videoFormatRGB:
107 case videoFormatBGR:
108 pSrcPic->pData[0] = NULL;
109 pSrcPic->pData[1] = NULL;
110 pSrcPic->pData[2] = NULL;
111 pSrcPic->pData[3] = NULL;
112 pSrcPic->iStride[0] = CALC_BI_STRIDE (kiWidth, 24);
113 pSrcPic->iStride[3] = pSrcPic->iStride[2] = pSrcPic->iStride[1] = 0;
114 if (kiColorspace & videoFormatVFlip)
115 pSrcPic->iColorFormat = kiColorspace & (~videoFormatVFlip);
116 else
117 pSrcPic->iColorFormat = kiColorspace | videoFormatVFlip;
118 break;
119 case videoFormatBGRA:
120 case videoFormatRGBA:
121 case videoFormatARGB:
122 case videoFormatABGR:
123 pSrcPic->pData[0] = NULL;
124 pSrcPic->pData[1] = NULL;
125 pSrcPic->pData[2] = NULL;
126 pSrcPic->pData[3] = NULL;
127 pSrcPic->iStride[0] = kiWidth << 2;
128 pSrcPic->iStride[3] = pSrcPic->iStride[2] = pSrcPic->iStride[1] = 0;
129 if (kiColorspace & videoFormatVFlip)
130 pSrcPic->iColorFormat = kiColorspace & (~videoFormatVFlip);
131 else
132 pSrcPic->iColorFormat = kiColorspace | videoFormatVFlip;
133 break;
134 default:
135 return 2; // any else?
136 }
137
138 return 0;
139 }
140
141
WelsInitBGDFunc(SWelsFuncPtrList * pFuncList,const bool kbEnableBackgroundDetection)142 void WelsInitBGDFunc (SWelsFuncPtrList* pFuncList, const bool kbEnableBackgroundDetection) {
143 if (kbEnableBackgroundDetection) {
144 pFuncList->pfInterMdBackgroundDecision = WelsMdInterJudgeBGDPskip;
145 pFuncList->pfMdBackgroundInfoUpdate = WelsMdUpdateBGDInfo;
146 } else {
147 pFuncList->pfInterMdBackgroundDecision = WelsMdInterJudgeBGDPskipFalse;
148 pFuncList->pfMdBackgroundInfoUpdate = WelsMdUpdateBGDInfoNULL;
149 }
150 }
151
152 /*!
153 * \brief initialize function pointers that potentially used in Wels encoding
154 * \param pEncCtx sWelsEncCtx*
155 * \return successful - 0; otherwise none 0 for failed
156 */
InitFunctionPointers(sWelsEncCtx * pEncCtx,SWelsSvcCodingParam * pParam,uint32_t uiCpuFlag)157 int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam, uint32_t uiCpuFlag) {
158 int32_t iReturn = ENC_RETURN_SUCCESS;
159 SWelsFuncPtrList* pFuncList = pEncCtx->pFuncList;
160 bool bScreenContent = (SCREEN_CONTENT_REAL_TIME == pParam->iUsageType);
161
162 /* Functionality utilization of CPU instructions dependency */
163 pFuncList->pfSetMemZeroSize8 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage
164 pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage
165 pFuncList->pfSetMemZeroSize64 = WelsSetMemZero_c; // confirmed_safe_unsafe_usage
166 #if defined(X86_ASM)
167 if (uiCpuFlag & WELS_CPU_MMXEXT) {
168 pFuncList->pfSetMemZeroSize8 = WelsSetMemZeroSize8_mmx; // confirmed_safe_unsafe_usage
169 pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZeroSize64_mmx; // confirmed_safe_unsafe_usage
170 pFuncList->pfSetMemZeroSize64 = WelsSetMemZeroSize64_mmx; // confirmed_safe_unsafe_usage
171 }
172 if (uiCpuFlag & WELS_CPU_SSE2) {
173 pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZeroAligned64_sse2; // confirmed_safe_unsafe_usage
174 }
175 #endif//X86_ASM
176
177 #if defined(HAVE_NEON)
178 if (uiCpuFlag & WELS_CPU_NEON) {
179 pFuncList->pfSetMemZeroSize8 = WelsSetMemZero_neon;
180 pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZero_neon;
181 pFuncList->pfSetMemZeroSize64 = WelsSetMemZero_neon;
182 }
183 #endif
184
185 #if defined(HAVE_NEON_AARCH64)
186 if (uiCpuFlag & WELS_CPU_NEON) {
187 pFuncList->pfSetMemZeroSize8 = WelsSetMemZero_AArch64_neon;
188 pFuncList->pfSetMemZeroSize64Aligned16 = WelsSetMemZero_AArch64_neon;
189 pFuncList->pfSetMemZeroSize64 = WelsSetMemZero_AArch64_neon;
190 }
191 #endif
192
193 InitExpandPictureFunc (& (pFuncList->sExpandPicFunc), uiCpuFlag);
194
195 /* Intra_Prediction_fn*/
196 WelsInitIntraPredFuncs (pFuncList, uiCpuFlag);
197
198 /* ME func */
199 WelsInitMeFunc (pFuncList, uiCpuFlag, bScreenContent);
200
201 /* sad, satd, average */
202 WelsInitSampleSadFunc (pFuncList, uiCpuFlag);
203
204 //
205 WelsInitBGDFunc (pFuncList, pParam->bEnableBackgroundDetection);
206 WelsInitSCDPskipFunc (pFuncList, bScreenContent && (pParam->bEnableSceneChangeDetect));
207
208 // for pfGetVarianceFromIntraVaa function ptr adaptive by CPU features, 6/7/2010
209 InitIntraAnalysisVaaInfo (pFuncList, uiCpuFlag);
210
211 /* Motion compensation */
212 /*init pixel average function*/
213 /*get one column or row pixel when refinement*/
214 InitMcFunc (&pFuncList->sMcFuncs, uiCpuFlag);
215 InitCoeffFunc (pFuncList, uiCpuFlag, pParam->iEntropyCodingModeFlag);
216
217 WelsInitEncodingFuncs (pFuncList, uiCpuFlag);
218 WelsInitReconstructionFuncs (pFuncList, uiCpuFlag);
219
220 DeblockingInit (&pFuncList->pfDeblocking, uiCpuFlag);
221 WelsBlockFuncInit (&pFuncList->pfSetNZCZero, uiCpuFlag);
222
223 InitFillNeighborCacheInterFunc (pFuncList, pParam->bEnableBackgroundDetection);
224
225 pFuncList->pParametersetStrategy = IWelsParametersetStrategy::CreateParametersetStrategy (pParam->eSpsPpsIdStrategy,
226 pParam->bSimulcastAVC, pParam->iSpatialLayerNum);
227 WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pFuncList->pParametersetStrategy))
228
229 return iReturn;
230 }
231
UpdateFrameNum(sWelsEncCtx * pEncCtx,const int32_t kiDidx)232 void UpdateFrameNum (sWelsEncCtx* pEncCtx, const int32_t kiDidx) {
233 SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
234 bool bNeedFrameNumIncreasing = false;
235
236 if (NRI_PRI_LOWEST != pEncCtx->eLastNalPriority[kiDidx]) {
237 bNeedFrameNumIncreasing = true;
238 }
239
240 if (bNeedFrameNumIncreasing) {
241 if (pParamInternal->iFrameNum < (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1)
242 ++ pParamInternal->iFrameNum;
243 else
244 pParamInternal->iFrameNum = 0; // if iFrameNum overflow
245 }
246
247 pEncCtx->eLastNalPriority[kiDidx] = NRI_PRI_LOWEST;
248 }
249
250
LoadBackFrameNum(sWelsEncCtx * pEncCtx,const int32_t kiDidx)251 void LoadBackFrameNum (sWelsEncCtx* pEncCtx, const int32_t kiDidx) {
252 SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
253 bool bNeedFrameNumIncreasing = false;
254
255 if (NRI_PRI_LOWEST != pEncCtx->eLastNalPriority[kiDidx]) {
256 bNeedFrameNumIncreasing = true;
257 }
258
259 if (bNeedFrameNumIncreasing) {
260 if (pParamInternal->iFrameNum != 0) {
261 pParamInternal->iFrameNum --;
262 } else {
263 pParamInternal->iFrameNum = (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1;
264 }
265 }
266 }
267
InitBitStream(sWelsEncCtx * pEncCtx)268 void InitBitStream (sWelsEncCtx* pEncCtx) {
269 // for bitstream writing
270 pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position
271 pEncCtx->pOut->iNalIndex = 0; // reset NAL index
272 pEncCtx->pOut->iLayerBsIndex = 0; // reset index of Layer Bs
273
274 InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize);
275 }
276 /*!
277 * \brief initialize frame coding
278 */
InitFrameCoding(sWelsEncCtx * pEncCtx,const EVideoFrameType keFrameType,const int32_t kiDidx)279 void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType, const int32_t kiDidx) {
280 SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
281 if (keFrameType == videoFrameTypeP) {
282 ++pParamInternal->iFrameIndex;
283
284 if (pParamInternal->iPOC < (1 << pEncCtx->pSps->iLog2MaxPocLsb) -
285 2) // if iPOC type is no 0, this need be modification
286 pParamInternal->iPOC += 2; // for POC type 0
287 else
288 pParamInternal->iPOC = 0;
289
290 UpdateFrameNum (pEncCtx, kiDidx);
291
292 pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
293 pEncCtx->eSliceType = P_SLICE;
294 pEncCtx->eNalPriority = NRI_PRI_HIGH;
295 } else if (keFrameType == videoFrameTypeIDR) {
296 pParamInternal->iFrameNum = 0;
297 pParamInternal->iPOC = 0;
298 pParamInternal->bEncCurFrmAsIdrFlag = false;
299 pParamInternal->iFrameIndex = 0;
300
301 pEncCtx->eNalType = NAL_UNIT_CODED_SLICE_IDR;
302 pEncCtx->eSliceType = I_SLICE;
303 pEncCtx->eNalPriority = NRI_PRI_HIGHEST;
304
305 pParamInternal->iCodingIndex = 0;
306
307 // reset_ref_list
308
309 // rc_init_gop
310 } else if (keFrameType == videoFrameTypeI) {
311 if (pParamInternal->iPOC < (1 << pEncCtx->pSps->iLog2MaxPocLsb) -
312 2) // if iPOC type is no 0, this need be modification
313 pParamInternal->iPOC += 2; // for POC type 0
314 else
315 pParamInternal->iPOC = 0;
316
317 UpdateFrameNum (pEncCtx, kiDidx);
318
319 pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
320 pEncCtx->eSliceType = I_SLICE;
321 pEncCtx->eNalPriority = NRI_PRI_HIGHEST;
322
323 // rc_init_gop
324 } else { // B pictures are not supported now, any else?
325 assert (0);
326 }
327
328 #if defined(STAT_OUTPUT)
329 memset (&pEncCtx->sPerInfo, 0, sizeof (SStatSliceInfo));
330 #endif//FRAME_INFO_OUTPUT
331 }
332
DecideFrameType(sWelsEncCtx * pEncCtx,const int8_t kiSpatialNum,const int32_t kiDidx,bool bSkipFrameFlag)333 EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum, const int32_t kiDidx,
334 bool bSkipFrameFlag) {
335 SWelsSvcCodingParam* pSvcParam = pEncCtx->pSvcParam;
336 SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
337 EVideoFrameType iFrameType = videoFrameTypeInvalid;
338 bool bSceneChangeFlag = false;
339 if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
340 if ((!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag ||
341 (kiSpatialNum < pSvcParam->iSpatialLayerNum)) {
342 bSceneChangeFlag = false;
343 } else {
344 bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag;
345 }
346 if (pEncCtx->pVaa->bIdrPeriodFlag || pParamInternal->bEncCurFrmAsIdrFlag || (!pSvcParam->bEnableLongTermReference
347 && bSceneChangeFlag && !bSkipFrameFlag)) {
348 iFrameType = videoFrameTypeIDR;
349 } else if (pSvcParam->bEnableLongTermReference && (bSceneChangeFlag
350 || pEncCtx->pVaa->eSceneChangeIdc == LARGE_CHANGED_SCENE)) {
351 int iActualLtrcount = 0;
352 SPicture** pLongTermRefList = pEncCtx->ppRefPicListExt[0]->pLongRefList;
353 for (int i = 0; i < pSvcParam->iLTRRefNum; ++i) {
354 if (NULL != pLongTermRefList[i] && pLongTermRefList[i]->bUsedAsRef && pLongTermRefList[i]->bIsLongRef
355 && pLongTermRefList[i]->bIsSceneLTR) {
356 ++iActualLtrcount;
357 }
358 }
359 if (iActualLtrcount == pSvcParam->iLTRRefNum && bSceneChangeFlag) {
360 iFrameType = videoFrameTypeIDR;
361 } else {
362 iFrameType = videoFrameTypeP;
363 pEncCtx->bCurFrameMarkedAsSceneLtr = true;
364 }
365 } else {
366 iFrameType = videoFrameTypeP;
367 }
368 if (videoFrameTypeP == iFrameType && bSkipFrameFlag) {
369 iFrameType = videoFrameTypeSkip;
370 } else if (videoFrameTypeIDR == iFrameType) {
371 pParamInternal->iCodingIndex = 0;
372 pEncCtx->bCurFrameMarkedAsSceneLtr = true;
373 }
374
375 } else {
376 // perform scene change detection
377 if ((!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag ||
378 (kiSpatialNum < pSvcParam->iSpatialLayerNum)
379 || (pParamInternal->iFrameIndex < (VGOP_SIZE << 1))) { // avoid too frequent I frame coding, rc control
380 bSceneChangeFlag = false;
381 } else {
382 bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag;
383 }
384
385 //scene_changed_flag: RC enable && iSpatialNum == pSvcParam->iSpatialLayerNum
386 //bIdrPeriodFlag: RC disable || iSpatialNum != pSvcParam->iSpatialLayerNum
387 //pEncCtx->bEncCurFrmAsIdrFlag: 1. first frame should be IDR; 2. idr pause; 3. idr request
388 iFrameType = (pEncCtx->pVaa->bIdrPeriodFlag || bSceneChangeFlag
389 || pParamInternal->bEncCurFrmAsIdrFlag) ? videoFrameTypeIDR : videoFrameTypeP;
390 if ( videoFrameTypeIDR == iFrameType ) {
391 WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
392 "encoding videoFrameTypeIDR due to ( bIdrPeriodFlag %d, bSceneChangeFlag %d, bEncCurFrmAsIdrFlag %d )",
393 pEncCtx->pVaa->bIdrPeriodFlag,
394 bSceneChangeFlag,
395 pParamInternal->bEncCurFrmAsIdrFlag);
396 }
397
398 if (videoFrameTypeP == iFrameType && bSkipFrameFlag) { // for frame skip, 1/5/2010
399 iFrameType = videoFrameTypeSkip;
400 } else if (videoFrameTypeIDR == iFrameType) {
401 pParamInternal->iCodingIndex = 0;
402 }
403 }
404 return iFrameType;
405 }
406
407 /*!
408 * \brief Dump reconstruction for dependency layer
409 */
410
DumpDependencyRec(SPicture * pCurPicture,const char * kpFileName,const int8_t kiDid,bool bAppend,SDqLayer * pDqLayer,bool bSimulCastAVC)411 extern "C" void DumpDependencyRec (SPicture* pCurPicture, const char* kpFileName, const int8_t kiDid, bool bAppend,
412 SDqLayer* pDqLayer, bool bSimulCastAVC) {
413 WelsFileHandle* pDumpRecFile = NULL;
414 int32_t iWrittenSize = 0;
415 const char* openMode = bAppend ? "ab" : "wb";
416 SWelsSPS* pSpsTmp = NULL;
417 if (bSimulCastAVC || (kiDid == BASE_DEPENDENCY_ID)) {
418 pSpsTmp = pDqLayer->sLayerInfo.pSpsP;
419 } else {
420 pSpsTmp = & (pDqLayer->sLayerInfo.pSubsetSpsP->pSps);
421 }
422 bool bFrameCroppingFlag = pSpsTmp->bFrameCroppingFlag;
423 SCropOffset* pFrameCrop = &pSpsTmp->sFrameCrop;
424
425 if (NULL == pCurPicture || NULL == kpFileName || kiDid >= MAX_DEPENDENCY_LAYER)
426 return;
427 if (strlen (kpFileName) > 0) // confirmed_safe_unsafe_usage
428 pDumpRecFile = WelsFopen (kpFileName, openMode);
429 else {
430 char sDependencyRecFileName[16] = {0};
431 WelsSnprintf (sDependencyRecFileName, 16, "rec%d.yuv", kiDid); // confirmed_safe_unsafe_usage
432 pDumpRecFile = WelsFopen (sDependencyRecFileName, openMode);
433 }
434 if (NULL != pDumpRecFile && bAppend)
435 WelsFseek (pDumpRecFile, 0, SEEK_END);
436
437 if (NULL != pDumpRecFile) {
438 int32_t i = 0;
439 int32_t j = 0;
440 const int32_t kiStrideY = pCurPicture->iLineSize[0];
441 const int32_t kiLumaWidth = bFrameCroppingFlag ? (pCurPicture->iWidthInPixel - ((pFrameCrop->iCropLeft +
442 pFrameCrop->iCropRight) << 1)) : pCurPicture->iWidthInPixel;
443 const int32_t kiLumaHeight = bFrameCroppingFlag ? (pCurPicture->iHeightInPixel - ((pFrameCrop->iCropTop +
444 pFrameCrop->iCropBottom) << 1)) : pCurPicture->iHeightInPixel;
445 const int32_t kiChromaWidth = kiLumaWidth >> 1;
446 const int32_t kiChromaHeight = kiLumaHeight >> 1;
447 uint8_t* pSrc = NULL;
448 pSrc = bFrameCroppingFlag ? (pCurPicture->pData[0] + kiStrideY * (pFrameCrop->iCropTop << 1) +
449 (pFrameCrop->iCropLeft << 1)) : pCurPicture->pData[0];
450 for (j = 0; j < kiLumaHeight; ++ j) {
451 iWrittenSize = WelsFwrite (pSrc + j * kiStrideY, 1, kiLumaWidth, pDumpRecFile);
452 assert (iWrittenSize == kiLumaWidth);
453 if (iWrittenSize < kiLumaWidth) {
454 assert (0); // make no sense for us if writing failed
455 WelsFclose (pDumpRecFile);
456 return;
457 }
458 }
459 for (i = 1; i < I420_PLANES; ++ i) {
460 const int32_t kiStrideUV = pCurPicture->iLineSize[i];
461 pSrc = bFrameCroppingFlag ? (pCurPicture->pData[i] + kiStrideUV * pFrameCrop->iCropTop + pFrameCrop->iCropLeft) :
462 pCurPicture->pData[i];
463 for (j = 0; j < kiChromaHeight; ++ j) {
464 iWrittenSize = WelsFwrite (pSrc + j * kiStrideUV, 1, kiChromaWidth, pDumpRecFile);
465 assert (iWrittenSize == kiChromaWidth);
466 if (iWrittenSize < kiChromaWidth) {
467 assert (0); // make no sense for us if writing failed
468 WelsFclose (pDumpRecFile);
469 return;
470 }
471 }
472 }
473 WelsFclose (pDumpRecFile);
474 pDumpRecFile = NULL;
475 }
476 }
477
478 /*!
479 * \brief Dump the reconstruction pictures
480 */
481
DumpRecFrame(SPicture * pCurPicture,const char * kpFileName,const int8_t kiDid,bool bAppend,SDqLayer * pDqLayer)482 void DumpRecFrame (SPicture* pCurPicture, const char* kpFileName, const int8_t kiDid, bool bAppend,
483 SDqLayer* pDqLayer) {
484 WelsFileHandle* pDumpRecFile = NULL;
485 SWelsSPS* pSpsTmp = (kiDid > BASE_DEPENDENCY_ID) ? & (pDqLayer->sLayerInfo.pSubsetSpsP->pSps) :
486 pDqLayer->sLayerInfo.pSpsP;
487 bool bFrameCroppingFlag = pSpsTmp->bFrameCroppingFlag;
488 SCropOffset* pFrameCrop = &pSpsTmp->sFrameCrop;
489
490 int32_t iWrittenSize = 0;
491 const char* openMode = bAppend ? "ab" : "wb";
492
493 if (NULL == pCurPicture || NULL == kpFileName)
494 return;
495
496 if (strlen (kpFileName) > 0) { // confirmed_safe_unsafe_usage
497 pDumpRecFile = WelsFopen (kpFileName, openMode);
498 } else {
499 pDumpRecFile = WelsFopen ("rec.yuv", openMode);
500 }
501 if (NULL != pDumpRecFile && bAppend)
502 WelsFseek (pDumpRecFile, 0, SEEK_END);
503
504 if (NULL != pDumpRecFile) {
505 int32_t i = 0;
506 int32_t j = 0;
507 const int32_t kiStrideY = pCurPicture->iLineSize[0];
508 const int32_t kiLumaWidth = bFrameCroppingFlag ? (pCurPicture->iWidthInPixel - ((pFrameCrop->iCropLeft +
509 pFrameCrop->iCropRight) << 1)) : pCurPicture->iWidthInPixel;
510 const int32_t kiLumaHeight = bFrameCroppingFlag ? (pCurPicture->iHeightInPixel - ((pFrameCrop->iCropTop +
511 pFrameCrop->iCropBottom) << 1)) : pCurPicture->iHeightInPixel;
512 const int32_t kiChromaWidth = kiLumaWidth >> 1;
513 const int32_t kiChromaHeight = kiLumaHeight >> 1;
514 uint8_t* pSrc = NULL;
515 pSrc = bFrameCroppingFlag ? (pCurPicture->pData[0] + kiStrideY * (pFrameCrop->iCropTop << 1) +
516 (pFrameCrop->iCropLeft << 1)) : pCurPicture->pData[0];
517 for (j = 0; j < kiLumaHeight; ++ j) {
518 iWrittenSize = WelsFwrite (pSrc + j * kiStrideY, 1, kiLumaWidth, pDumpRecFile);
519 assert (iWrittenSize == kiLumaWidth);
520 if (iWrittenSize < kiLumaWidth) {
521 assert (0); // make no sense for us if writing failed
522 WelsFclose (pDumpRecFile);
523 return;
524 }
525 }
526 for (i = 1; i < I420_PLANES; ++ i) {
527 const int32_t kiStrideUV = pCurPicture->iLineSize[i];
528 pSrc = bFrameCroppingFlag ? (pCurPicture->pData[i] + kiStrideUV * pFrameCrop->iCropTop + pFrameCrop->iCropLeft) :
529 pCurPicture->pData[i];
530 for (j = 0; j < kiChromaHeight; ++ j) {
531 iWrittenSize = WelsFwrite (pSrc + j * kiStrideUV, 1, kiChromaWidth, pDumpRecFile);
532 assert (iWrittenSize == kiChromaWidth);
533 if (iWrittenSize < kiChromaWidth) {
534 assert (0); // make no sense for us if writing failed
535 WelsFclose (pDumpRecFile);
536 return;
537 }
538 }
539 }
540 WelsFclose (pDumpRecFile);
541 pDumpRecFile = NULL;
542 }
543 }
544
545
546
547 /***********************************************************************************/
WelsSetMemZero_c(void * pDst,int32_t iSize)548 void WelsSetMemZero_c (void* pDst, int32_t iSize) { // confirmed_safe_unsafe_usage
549 memset (pDst, 0, iSize);
550 }
551 }
552