• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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