• 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    decoder.c
33  *
34  * \brief   Interfaces implementation introduced in decoder system architecture
35  *
36  * \date    03/10/2009 Created
37  *
38  *************************************************************************************
39  */
40 #include "codec_def.h"
41 #include "decoder.h"
42 #include "cpu.h"
43 #include "au_parser.h"
44 #include "get_intra_predictor.h"
45 #include "rec_mb.h"
46 #include "mc.h"
47 #include "decode_mb_aux.h"
48 #include "manage_dec_ref.h"
49 #include "decoder_core.h"
50 #include "deblocking.h"
51 #include "expand_pic.h"
52 #include "decode_slice.h"
53 #include "error_concealment.h"
54 #include "memory_align.h"
55 #include "wels_decoder_thread.h"
56 
57 namespace WelsDec {
58 
59 extern PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const int32_t kiPicHeight);
60 
61 extern void FreePicture (PPicture pPic, CMemoryAlign* pMa);
62 
CreatePicBuff(PWelsDecoderContext pCtx,PPicBuff * ppPicBuf,const int32_t kiSize,const int32_t kiPicWidth,const int32_t kiPicHeight)63 static int32_t CreatePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiSize,
64                               const int32_t kiPicWidth, const int32_t kiPicHeight) {
65 
66   PPicBuff pPicBuf = NULL;
67   int32_t iPicIdx = 0;
68   if (kiSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
69     return ERR_INFO_INVALID_PARAM;
70   }
71 
72   CMemoryAlign* pMa = pCtx->pMemAlign;
73 
74   pPicBuf = (PPicBuff)pMa->WelsMallocz (sizeof (SPicBuff), "PPicBuff");
75 
76   if (NULL == pPicBuf) {
77     return ERR_INFO_OUT_OF_MEMORY;
78   }
79 
80   pPicBuf->ppPic = (PPicture*)pMa->WelsMallocz (kiSize * sizeof (PPicture), "PPicture*");
81 
82   if (NULL == pPicBuf->ppPic) {
83     pPicBuf->iCapacity = 0;
84     DestroyPicBuff (pCtx, &pPicBuf, pMa);
85     return ERR_INFO_OUT_OF_MEMORY;
86   }
87 
88   for (iPicIdx = 0; iPicIdx < kiSize; ++ iPicIdx) {
89     PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
90     if (NULL == pPic) {
91       // init capacity first for free memory
92       pPicBuf->iCapacity = iPicIdx;
93       DestroyPicBuff (pCtx, &pPicBuf, pMa);
94       return ERR_INFO_OUT_OF_MEMORY;
95     }
96     pPicBuf->ppPic[iPicIdx] = pPic;
97   }
98 
99 // initialize context in queue
100   pPicBuf->iCapacity   = kiSize;
101   pPicBuf->iCurrentIdx = 0;
102   * ppPicBuf           = pPicBuf;
103 
104   return ERR_NONE;
105 }
106 
IncreasePicBuff(PWelsDecoderContext pCtx,PPicBuff * ppPicBuf,const int32_t kiOldSize,const int32_t kiPicWidth,const int32_t kiPicHeight,const int32_t kiNewSize)107 static int32_t IncreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
108                                 const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
109   PPicBuff pPicOldBuf = *ppPicBuf;
110   PPicBuff pPicNewBuf = NULL;
111   int32_t iPicIdx = 0;
112   if (kiOldSize <= 0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
113     return ERR_INFO_INVALID_PARAM;
114   }
115 
116   CMemoryAlign* pMa = pCtx->pMemAlign;
117   pPicNewBuf = (PPicBuff)pMa->WelsMallocz (sizeof (SPicBuff), "PPicBuff");
118 
119   if (NULL == pPicNewBuf) {
120     return ERR_INFO_OUT_OF_MEMORY;
121   }
122 
123   pPicNewBuf->ppPic = (PPicture*)pMa->WelsMallocz (kiNewSize * sizeof (PPicture), "PPicture*");
124 
125   if (NULL == pPicNewBuf->ppPic) {
126     pPicNewBuf->iCapacity = 0;
127     DestroyPicBuff (pCtx, &pPicNewBuf, pMa);
128     return ERR_INFO_OUT_OF_MEMORY;
129   }
130 
131   // increase new PicBuf
132   for (iPicIdx = kiOldSize; iPicIdx < kiNewSize; ++ iPicIdx) {
133     PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
134     if (NULL == pPic) {
135       // Set maximum capacity as the new malloc memory at the tail
136       pPicNewBuf->iCapacity = iPicIdx;
137       DestroyPicBuff (pCtx, &pPicNewBuf, pMa);
138       return ERR_INFO_OUT_OF_MEMORY;
139     }
140     pPicNewBuf->ppPic[iPicIdx] = pPic;
141   }
142 
143   // copy old PicBuf to new PicBuf
144   memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiOldSize * sizeof (PPicture));
145 
146 // initialize context in queue
147   pPicNewBuf->iCapacity   = kiNewSize;
148   pPicNewBuf->iCurrentIdx = pPicOldBuf->iCurrentIdx;
149   * ppPicBuf              = pPicNewBuf;
150 
151   for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
152     pPicNewBuf->ppPic[i]->bUsedAsRef = false;
153     pPicNewBuf->ppPic[i]->bIsLongRef = false;
154     pPicNewBuf->ppPic[i]->iRefCount = 0;
155     pPicNewBuf->ppPic[i]->bIsComplete = false;
156   }
157 // remove old PicBuf
158   if (pPicOldBuf->ppPic != NULL) {
159     pMa->WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
160     pPicOldBuf->ppPic = NULL;
161   }
162   pPicOldBuf->iCapacity = 0;
163   pPicOldBuf->iCurrentIdx = 0;
164   pMa->WelsFree (pPicOldBuf, "pPicOldBuf");
165   pPicOldBuf = NULL;
166   return ERR_NONE;
167 }
168 
DecreasePicBuff(PWelsDecoderContext pCtx,PPicBuff * ppPicBuf,const int32_t kiOldSize,const int32_t kiPicWidth,const int32_t kiPicHeight,const int32_t kiNewSize)169 static int32_t DecreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
170                                 const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
171   PPicBuff pPicOldBuf = *ppPicBuf;
172   PPicBuff pPicNewBuf = NULL;
173   int32_t iPicIdx = 0;
174   if (kiOldSize <= 0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
175     return ERR_INFO_INVALID_PARAM;
176   }
177 
178   CMemoryAlign* pMa = pCtx->pMemAlign;
179 
180   pPicNewBuf = (PPicBuff)pMa->WelsMallocz (sizeof (SPicBuff), "PPicBuff");
181 
182   if (NULL == pPicNewBuf) {
183     return ERR_INFO_OUT_OF_MEMORY;
184   }
185 
186   pPicNewBuf->ppPic = (PPicture*)pMa->WelsMallocz (kiNewSize * sizeof (PPicture), "PPicture*");
187 
188   if (NULL == pPicNewBuf->ppPic) {
189     pPicNewBuf->iCapacity = 0;
190     DestroyPicBuff (pCtx, &pPicNewBuf, pMa);
191     return ERR_INFO_OUT_OF_MEMORY;
192   }
193 
194   ResetReorderingPictureBuffers (pCtx->pPictReoderingStatus, pCtx->pPictInfoList, false);
195 
196   int32_t iPrevPicIdx = -1;
197   for (iPrevPicIdx = 0; iPrevPicIdx < kiOldSize; ++iPrevPicIdx) {
198     if (pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb == pPicOldBuf->ppPic[iPrevPicIdx]) {
199       break;
200     }
201   }
202   int32_t iDelIdx;
203   if (iPrevPicIdx < kiOldSize && iPrevPicIdx >= kiNewSize) {
204     // found pPreviousDecodedPictureInDpb,
205     pPicNewBuf->ppPic[0] = pPicOldBuf->ppPic[iPrevPicIdx];
206     pPicNewBuf->iCurrentIdx = 0;
207     memcpy (pPicNewBuf->ppPic + 1, pPicOldBuf->ppPic, (kiNewSize - 1) * sizeof (PPicture));
208     iDelIdx = kiNewSize - 1;
209   } else {
210     memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiNewSize * sizeof (PPicture));
211     pPicNewBuf->iCurrentIdx = iPrevPicIdx < kiNewSize ? iPrevPicIdx : 0;
212     iDelIdx = kiNewSize;
213   }
214 
215   //update references due to allocation changes
216   //all references' references have to be reset oss-buzz 14423
217   for (int32_t i = 0; i < kiNewSize; i++) {
218     for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) {
219       int32_t j = -1;
220       while (++j < MAX_DPB_COUNT && pPicNewBuf->ppPic[i]->pRefPic[listIdx][j] != NULL) {
221         pPicNewBuf->ppPic[i]->pRefPic[listIdx][j] = NULL;
222       }
223     }
224   }
225 
226   for (iPicIdx = iDelIdx; iPicIdx < kiOldSize; iPicIdx++) {
227     if (iPrevPicIdx != iPicIdx) {
228       if (pPicOldBuf->ppPic[iPicIdx] != NULL) {
229         FreePicture (pPicOldBuf->ppPic[iPicIdx], pMa);
230         pPicOldBuf->ppPic[iPicIdx] = NULL;
231       }
232     }
233   }
234 
235   // initialize context in queue
236   pPicNewBuf->iCapacity = kiNewSize;
237   * ppPicBuf             = pPicNewBuf;
238 
239   for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
240     pPicNewBuf->ppPic[i]->bUsedAsRef = false;
241     pPicNewBuf->ppPic[i]->bIsLongRef = false;
242     pPicNewBuf->ppPic[i]->iRefCount = 0;
243     pPicNewBuf->ppPic[i]->bIsComplete = false;
244   }
245   // remove old PicBuf
246   if (pPicOldBuf->ppPic != NULL) {
247     pMa->WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
248     pPicOldBuf->ppPic = NULL;
249   }
250   pPicOldBuf->iCapacity = 0;
251   pPicOldBuf->iCurrentIdx = 0;
252   pMa->WelsFree (pPicOldBuf, "pPicOldBuf");
253   pPicOldBuf = NULL;
254 
255   return ERR_NONE;
256 }
257 
DestroyPicBuff(PWelsDecoderContext pCtx,PPicBuff * ppPicBuf,CMemoryAlign * pMa)258 void DestroyPicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, CMemoryAlign* pMa) {
259   PPicBuff pPicBuf = NULL;
260 
261   ResetReorderingPictureBuffers (pCtx->pPictReoderingStatus, pCtx->pPictInfoList, false);
262 
263   if (NULL == ppPicBuf || NULL == *ppPicBuf)
264     return;
265 
266   pPicBuf = *ppPicBuf;
267   while (pPicBuf->ppPic != NULL) {
268     int32_t iPicIdx = 0;
269     while (iPicIdx < pPicBuf->iCapacity) {
270       PPicture pPic = pPicBuf->ppPic[iPicIdx];
271       if (pPic != NULL) {
272         FreePicture (pPic, pMa);
273       }
274       pPic = NULL;
275       ++ iPicIdx;
276     }
277 
278     pMa->WelsFree (pPicBuf->ppPic, "pPicBuf->queue");
279 
280     pPicBuf->ppPic = NULL;
281   }
282   pPicBuf->iCapacity = 0;
283   pPicBuf->iCurrentIdx = 0;
284 
285   pMa->WelsFree (pPicBuf, "pPicBuf");
286 
287   pPicBuf = NULL;
288   *ppPicBuf = NULL;
289 }
290 
291 //reset picture reodering buffer list
ResetReorderingPictureBuffers(PPictReoderingStatus pPictReoderingStatus,PPictInfo pPictInfo,const bool & fullReset)292 void ResetReorderingPictureBuffers (PPictReoderingStatus pPictReoderingStatus, PPictInfo pPictInfo,
293                                     const bool& fullReset) {
294   if (pPictReoderingStatus != NULL && pPictInfo != NULL) {
295     int32_t pictInfoListCount = fullReset ? 16 : (pPictReoderingStatus->iLargestBufferedPicIndex + 1);
296     pPictReoderingStatus->iPictInfoIndex = 0;
297     pPictReoderingStatus->iMinPOC = IMinInt32;
298     pPictReoderingStatus->iNumOfPicts = 0;
299     pPictReoderingStatus->iLastGOPRemainPicts = 0;
300     pPictReoderingStatus->iLastWrittenPOC = IMinInt32;
301     pPictReoderingStatus->iLargestBufferedPicIndex = 0;
302     for (int32_t i = 0; i < pictInfoListCount; ++i) {
303       pPictInfo[i].bLastGOP = false;
304       pPictInfo[i].iPOC = IMinInt32;
305     }
306     pPictInfo->sBufferInfo.iBufferStatus = 0;
307 		pPictReoderingStatus->bHasBSlice = false;
308   }
309 }
310 
311 /*
312  * fill data fields in default for decoder context
313  */
WelsDecoderDefaults(PWelsDecoderContext pCtx,SLogContext * pLogCtx)314 void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
315   int32_t iCpuCores               = 1;
316   pCtx->sLogCtx = *pLogCtx;
317 
318   pCtx->pArgDec                   = NULL;
319 
320   pCtx->bHaveGotMemory            = false;              // not ever request memory blocks for decoder context related
321   pCtx->uiCpuFlag                 = 0;
322 
323   pCtx->bAuReadyFlag              = 0;                  // au data is not ready
324   pCtx->bCabacInited = false;
325 
326   pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
327 
328   pCtx->iImgWidthInPixel          = 0;
329   pCtx->iImgHeightInPixel         = 0;                  // alloc picture data when picture size is available
330   pCtx->iLastImgWidthInPixel      = 0;
331   pCtx->iLastImgHeightInPixel     = 0;
332   pCtx->bFreezeOutput = true;
333 
334   pCtx->iFrameNum                 = -1;
335   pCtx->pLastDecPicInfo->iPrevFrameNum             = -1;
336   pCtx->iErrorCode                = ERR_NONE;
337 
338   pCtx->pDec                      = NULL;
339 
340   pCtx->pTempDec                  = NULL;
341 
342   WelsResetRefPic (pCtx);
343 
344   pCtx->iActiveFmoNum             = 0;
345 
346   pCtx->pPicBuff          = NULL;
347 
348   //pCtx->sSpsPpsCtx.bAvcBasedFlag             = true;
349   pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = NULL;
350   pCtx->pDecoderStatistics->iAvgLumaQp = -1;
351   pCtx->pDecoderStatistics->iStatisticsLogInterval = 1000;
352   pCtx->bUseScalingList = false;
353   /*pCtx->sSpsPpsCtx.iSpsErrorIgnored = 0;
354   pCtx->sSpsPpsCtx.iSubSpsErrorIgnored = 0;
355   pCtx->sSpsPpsCtx.iPpsErrorIgnored = 0;
356   pCtx->sSpsPpsCtx.iPPSInvalidNum = 0;
357   pCtx->sSpsPpsCtx.iPPSLastInvalidId = -1;
358   pCtx->sSpsPpsCtx.iSPSInvalidNum = 0;
359   pCtx->sSpsPpsCtx.iSPSLastInvalidId = -1;
360   pCtx->sSpsPpsCtx.iSubSPSInvalidNum = 0;
361   pCtx->sSpsPpsCtx.iSubSPSLastInvalidId = -1;
362   */
363   pCtx->iFeedbackNalRefIdc = -1; //initialize
364   pCtx->pLastDecPicInfo->iPrevPicOrderCntMsb = 0;
365   pCtx->pLastDecPicInfo->iPrevPicOrderCntLsb = 0;
366 
367 }
368 
369 /*
370 * fill data fields in SPS and PPS default for decoder context
371 */
WelsDecoderSpsPpsDefaults(SWelsDecoderSpsPpsCTX & sSpsPpsCtx)372 void WelsDecoderSpsPpsDefaults (SWelsDecoderSpsPpsCTX& sSpsPpsCtx) {
373   sSpsPpsCtx.bSpsExistAheadFlag = false;
374   sSpsPpsCtx.bSubspsExistAheadFlag = false;
375   sSpsPpsCtx.bPpsExistAheadFlag = false;
376   sSpsPpsCtx.bAvcBasedFlag = true;
377   sSpsPpsCtx.iSpsErrorIgnored = 0;
378   sSpsPpsCtx.iSubSpsErrorIgnored = 0;
379   sSpsPpsCtx.iPpsErrorIgnored = 0;
380   sSpsPpsCtx.iPPSInvalidNum = 0;
381   sSpsPpsCtx.iPPSLastInvalidId = -1;
382   sSpsPpsCtx.iSPSInvalidNum = 0;
383   sSpsPpsCtx.iSPSLastInvalidId = -1;
384   sSpsPpsCtx.iSubSPSInvalidNum = 0;
385   sSpsPpsCtx.iSubSPSLastInvalidId = -1;
386   sSpsPpsCtx.iSeqId = -1;
387 }
388 
389 /*
390 * fill last decoded picture info
391 */
WelsDecoderLastDecPicInfoDefaults(SWelsLastDecPicInfo & sLastDecPicInfo)392 void WelsDecoderLastDecPicInfoDefaults (SWelsLastDecPicInfo& sLastDecPicInfo) {
393   sLastDecPicInfo.iPrevPicOrderCntMsb = 0;
394   sLastDecPicInfo.iPrevPicOrderCntLsb = 0;
395   sLastDecPicInfo.pPreviousDecodedPictureInDpb = NULL;
396   sLastDecPicInfo.iPrevFrameNum = -1;
397   sLastDecPicInfo.bLastHasMmco5 = false;
398   sLastDecPicInfo.uiDecodingTimeStamp = 0;
399 }
400 
401 /*!
402 * \brief   copy SpsPps from one Ctx to another ctx for threaded code
403 */
CopySpsPps(PWelsDecoderContext pFromCtx,PWelsDecoderContext pToCtx)404 void CopySpsPps (PWelsDecoderContext pFromCtx, PWelsDecoderContext pToCtx) {
405   pToCtx->sSpsPpsCtx = pFromCtx->sSpsPpsCtx;
406   PAccessUnit pFromCurAu = pFromCtx->pAccessUnitList;
407   PSps pTmpLayerSps[MAX_LAYER_NUM];
408   for (int i = 0; i < MAX_LAYER_NUM; i++) {
409     pTmpLayerSps[i] = NULL;
410   }
411   // track the layer sps for the current au
412   for (unsigned int i = pFromCurAu->uiStartPos; i <= pFromCurAu->uiEndPos; i++) {
413     uint32_t uiDid = pFromCurAu->pNalUnitsList[i]->sNalHeaderExt.uiDependencyId;
414     pTmpLayerSps[uiDid] = pFromCurAu->pNalUnitsList[i]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
415     for (unsigned int j = 0; j < MAX_SPS_COUNT + 1; ++j) {
416       if (&pFromCtx->sSpsPpsCtx.sSpsBuffer[j] == pTmpLayerSps[uiDid]) {
417         pTmpLayerSps[uiDid] = &pToCtx->sSpsPpsCtx.sSpsBuffer[j];
418         break;
419       }
420     }
421   }
422   for (int i = 0; i < MAX_LAYER_NUM; i++) {
423     if (pTmpLayerSps[i] != NULL) {
424       pToCtx->sSpsPpsCtx.pActiveLayerSps[i] = pTmpLayerSps[i];
425     }
426   }
427 }
428 
429 /*
430  *  destory_mb_blocks
431  */
432 
433 /*
434  *  get size of reference picture list in target layer incoming, = (iNumRefFrames
435  */
GetTargetRefListSize(PWelsDecoderContext pCtx)436 static inline int32_t GetTargetRefListSize (PWelsDecoderContext pCtx) {
437   int32_t iNumRefFrames = 0;
438   // +2 for EC MV Copy buffer exchange
439   if ((pCtx == NULL) || (pCtx->pSps == NULL)) {
440     iNumRefFrames = MAX_REF_PIC_COUNT + 2;
441   } else {
442     iNumRefFrames = pCtx->pSps->iNumRefFrames + 2;
443     int32_t  iThreadCount = GetThreadCount (pCtx);
444     if (iThreadCount > 1) {
445       //due to thread and reordering buffering, it needs more dpb space
446       iNumRefFrames = MAX_DPB_COUNT + iThreadCount;
447     }
448   }
449 
450 #ifdef LONG_TERM_REF
451   //pic_queue size minimum set 2
452   if (iNumRefFrames < 2) {
453     iNumRefFrames = 2;
454   }
455 #endif
456 
457   return iNumRefFrames;
458 }
459 
460 /*
461  *  request memory blocks for decoder avc part
462  */
WelsRequestMem(PWelsDecoderContext pCtx,const int32_t kiMbWidth,const int32_t kiMbHeight,bool & bReallocFlag)463 int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight,
464                         bool& bReallocFlag) {
465   const int32_t kiPicWidth      = kiMbWidth << 4;
466   const int32_t kiPicHeight     = kiMbHeight << 4;
467   int32_t iErr = ERR_NONE;
468 
469   int32_t iPicQueueSize         = 0;    // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
470   bReallocFlag                  = false;
471   bool  bNeedChangePicQueue     = true;
472   CMemoryAlign* pMa = pCtx->pMemAlign;
473 
474   WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiPicWidth <= 0 || kiPicHeight <= 0))
475 
476   // Fixed the issue about different gop size over last, 5/17/2010
477   // get picture queue size currently
478   iPicQueueSize = GetTargetRefListSize (pCtx);  // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
479   pCtx->iPicQueueNumber = iPicQueueSize;
480   if (pCtx->pPicBuff != NULL
481       && pCtx->pPicBuff->iCapacity ==
482       iPicQueueSize) // comparing current picture queue size requested and previous allocation picture queue
483     bNeedChangePicQueue = false;
484   // HD based pic buffer need consider memory size consumed when switch from 720p to other lower size
485   WELS_VERIFY_RETURN_IF (ERR_NONE, pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel
486                          && kiPicHeight == pCtx->iImgHeightInPixel) && (!bNeedChangePicQueue)) // have same scaled buffer
487 
488   // sync update pRefList
489   if (GetThreadCount (pCtx) <= 1) {
490     WelsResetRefPic (pCtx); // added to sync update ref list due to pictures are free
491   }
492 
493   if (pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel && kiPicHeight == pCtx->iImgHeightInPixel)
494       && pCtx->pPicBuff != NULL && pCtx->pPicBuff->iCapacity != iPicQueueSize) {
495     // currently only active for LIST_0 due to have no B frames
496     // Actually just need one memory allocation for the PicBuff. While it needs two pointer list (LIST_0 and LIST_1).
497     WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
498              "WelsRequestMem(): memory re-alloc for no resolution change (size = %d * %d), ref list size change from %d to %d",
499              kiPicWidth, kiPicHeight, pCtx->pPicBuff->iCapacity, iPicQueueSize);
500     if (pCtx->pPicBuff->iCapacity < iPicQueueSize) {
501       iErr = IncreasePicBuff (pCtx, &pCtx->pPicBuff, pCtx->pPicBuff->iCapacity, kiPicWidth, kiPicHeight,
502                               iPicQueueSize);
503     } else {
504       iErr = DecreasePicBuff (pCtx, &pCtx->pPicBuff, pCtx->pPicBuff->iCapacity, kiPicWidth, kiPicHeight,
505                               iPicQueueSize);
506     }
507   } else {
508     if (pCtx->bHaveGotMemory)
509       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
510                "WelsRequestMem(): memory re-alloc for resolution change, size change from %d * %d to %d * %d, ref list size change from %d to %d",
511                pCtx->iImgWidthInPixel, pCtx->iImgHeightInPixel, kiPicWidth, kiPicHeight, pCtx->pPicBuff->iCapacity,
512                iPicQueueSize);
513     else
514       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "WelsRequestMem(): memory alloc size = %d * %d, ref list size = %d",
515                kiPicWidth, kiPicHeight, iPicQueueSize);
516     // for Recycled_Pic_Queue
517     PPicBuff* ppPic = &pCtx->pPicBuff;
518     if (NULL != ppPic && NULL != *ppPic) {
519       DestroyPicBuff (pCtx, ppPic, pMa);
520     }
521 
522 
523     pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = NULL;
524 
525     // currently only active for LIST_0 due to have no B frames
526     iErr = CreatePicBuff (pCtx, &pCtx->pPicBuff, iPicQueueSize, kiPicWidth, kiPicHeight);
527   }
528 
529   if (iErr != ERR_NONE)
530     return iErr;
531 
532 
533   pCtx->iImgWidthInPixel    = kiPicWidth;   // target width of image to be reconstruted while decoding
534   pCtx->iImgHeightInPixel   = kiPicHeight;  // target height of image to be reconstruted while decoding
535 
536   pCtx->bHaveGotMemory      = true;         // global memory for decoder context related is requested
537   pCtx->pDec                = NULL;         // need prefetch a new pic due to spatial size changed
538 
539   if (pCtx->pCabacDecEngine == NULL)
540     pCtx->pCabacDecEngine = (SWelsCabacDecEngine*) pMa->WelsMallocz (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");
541   WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, (NULL == pCtx->pCabacDecEngine))
542 
543   bReallocFlag              = true;         // memory re-allocation successfully finished
544   return ERR_NONE;
545 }
546 
547 /*
548  *  free memory dynamically allocated during decoder
549  */
WelsFreeDynamicMemory(PWelsDecoderContext pCtx)550 void WelsFreeDynamicMemory (PWelsDecoderContext pCtx) {
551 
552   CMemoryAlign* pMa = pCtx->pMemAlign;
553 
554   //free dq layer memory
555   UninitialDqLayersContext (pCtx);
556 
557   //free FMO memory
558   ResetFmoList (pCtx);
559 
560   //free ref-pic list & picture memory
561   WelsResetRefPic (pCtx);
562 
563   PPicBuff* pPicBuff = &pCtx->pPicBuff;
564   if (NULL != pPicBuff && NULL != *pPicBuff) {
565     DestroyPicBuff (pCtx, pPicBuff, pMa);
566   }
567   if (GetThreadCount (pCtx) > 1) {
568     //prevent from double destruction of PPicBuff
569     PWelsDecoderThreadCTX pThreadCtx = (PWelsDecoderThreadCTX) (pCtx->pThreadCtx);
570     int32_t threadCount = pThreadCtx->sThreadInfo.uiThrMaxNum;
571     int32_t  id = pThreadCtx->sThreadInfo.uiThrNum;
572     for (int32_t i = 0; i < threadCount; ++i) {
573       if (pThreadCtx[i - id].pCtx != NULL) {
574         pThreadCtx[i - id].pCtx->pPicBuff = NULL;
575       }
576     }
577   }
578 
579   if (pCtx->pTempDec) {
580     FreePicture (pCtx->pTempDec, pCtx->pMemAlign);
581     pCtx->pTempDec = NULL;
582   }
583 
584   // added for safe memory
585   pCtx->iImgWidthInPixel  = 0;
586   pCtx->iImgHeightInPixel = 0;
587   pCtx->iLastImgWidthInPixel  = 0;
588   pCtx->iLastImgHeightInPixel = 0;
589   pCtx->bFreezeOutput = true;
590   pCtx->bHaveGotMemory = false;
591 
592   //free CABAC memory
593   pMa->WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
594 }
595 
596 /*!
597  * \brief   Open decoder
598  */
WelsOpenDecoder(PWelsDecoderContext pCtx,SLogContext * pLogCtx)599 int32_t WelsOpenDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
600   int iRet = ERR_NONE;
601   // function pointers
602   InitDecFuncs (pCtx, pCtx->uiCpuFlag);
603 
604   // vlc tables
605   InitVlcTable (pCtx->pVlcTable);
606 
607   // static memory
608   iRet = WelsInitStaticMemory (pCtx);
609   if (ERR_NONE != iRet) {
610     pCtx->iErrorCode |= dsOutOfMemory;
611     WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitStaticMemory() failed in WelsOpenDecoder().");
612     return iRet;
613   }
614 
615 #ifdef LONG_TERM_REF
616   pCtx->bParamSetsLostFlag = true;
617 #else
618   pCtx->bReferenceLostAtT0Flag = true; // should be true to waiting IDR at incoming AU bits following, 6/4/2010
619 #endif //LONG_TERM_REF
620   pCtx->bNewSeqBegin = true;
621   pCtx->bPrintFrameErrorTraceFlag = true;
622   pCtx->iIgnoredErrorInfoPacketCount = 0;
623   pCtx->bFrameFinish = true;
624   return iRet;
625 }
626 
627 /*!
628  * \brief   Close decoder
629  */
WelsCloseDecoder(PWelsDecoderContext pCtx)630 void WelsCloseDecoder (PWelsDecoderContext pCtx) {
631   WelsFreeDynamicMemory (pCtx);
632 
633   WelsFreeStaticMemory (pCtx);
634 
635 #ifdef LONG_TERM_REF
636   pCtx->bParamSetsLostFlag       = false;
637 #else
638   pCtx->bReferenceLostAtT0Flag = false;
639 #endif
640   pCtx->bNewSeqBegin = false;
641   pCtx->bPrintFrameErrorTraceFlag = false;
642 }
643 
644 /*!
645  * \brief   configure decoder parameters
646  */
DecoderConfigParam(PWelsDecoderContext pCtx,const SDecodingParam * kpParam)647 int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpParam) {
648   if (NULL == pCtx || NULL == kpParam)
649     return ERR_INFO_INVALID_PARAM;
650 
651   memcpy (pCtx->pParam, kpParam, sizeof (SDecodingParam));
652   if ((pCtx->pParam->eEcActiveIdc > ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
653       || (pCtx->pParam->eEcActiveIdc < ERROR_CON_DISABLE)) {
654     WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
655              "eErrorConMethod (%d) not in range: (%d - %d). Set as default value: (%d).", pCtx->pParam->eEcActiveIdc,
656              ERROR_CON_DISABLE, ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE,
657              ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
658     pCtx->pParam->eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
659   }
660 
661   if (pCtx->pParam->bParseOnly) //parse only, disable EC method
662     pCtx->pParam->eEcActiveIdc = ERROR_CON_DISABLE;
663   InitErrorCon (pCtx);
664 
665   if (VIDEO_BITSTREAM_SVC == pCtx->pParam->sVideoProperty.eVideoBsType ||
666       VIDEO_BITSTREAM_AVC == pCtx->pParam->sVideoProperty.eVideoBsType) {
667     pCtx->eVideoType = pCtx->pParam->sVideoProperty.eVideoBsType;
668   } else {
669     pCtx->eVideoType = VIDEO_BITSTREAM_DEFAULT;
670   }
671 
672   WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "eVideoType: %d", pCtx->eVideoType);
673 
674   return ERR_NONE;
675 }
676 
677 /*!
678  *************************************************************************************
679  * \brief   Initialize Wels decoder parameters and memory
680  *
681  * \param   pCtx input context to be initialized at first stage
682  *
683  * \return  0 - successed
684  * \return  1 - failed
685  *
686  * \note    N/A
687  *************************************************************************************
688  */
WelsInitDecoder(PWelsDecoderContext pCtx,SLogContext * pLogCtx)689 int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
690   if (pCtx == NULL) {
691     return ERR_INFO_INVALID_PTR;
692   }
693 
694   // open decoder
695   return WelsOpenDecoder (pCtx, pLogCtx);
696 }
697 
698 /*!
699  *************************************************************************************
700  * \brief   Uninitialize Wels decoder parameters and memory
701  *
702  * \param   pCtx input context to be uninitialized at release stage
703  *
704  * \return  NONE
705  *
706  * \note    N/A
707  *************************************************************************************
708  */
WelsEndDecoder(PWelsDecoderContext pCtx)709 void WelsEndDecoder (PWelsDecoderContext pCtx) {
710   // close decoder
711   WelsCloseDecoder (pCtx);
712 }
713 
GetVclNalTemporalId(PWelsDecoderContext pCtx)714 void GetVclNalTemporalId (PWelsDecoderContext pCtx) {
715   PAccessUnit pAccessUnit = pCtx->pAccessUnitList;
716   int32_t idx = pAccessUnit->uiStartPos;
717 
718   pCtx->iFeedbackVclNalInAu = FEEDBACK_VCL_NAL;
719   pCtx->iFeedbackTidInAu    = pAccessUnit->pNalUnitsList[idx]->sNalHeaderExt.uiTemporalId;
720   pCtx->iFeedbackNalRefIdc  = pAccessUnit->pNalUnitsList[idx]->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc;
721 }
722 
723 /*!
724  *************************************************************************************
725  * \brief   First entrance to decoding core interface.
726  *
727  * \param   pCtx            decoder context
728  * \param   pBufBs          bit streaming buffer
729  * \param   kBsLen          size in bytes length of bit streaming buffer input
730  * \param   ppDst           picture payload data to be output
731  * \param   pDstBufInfo     buf information of ouput data
732  *
733  * \return  0 - successed
734  * \return  1 - failed
735  *
736  * \note    N/A
737  *************************************************************************************
738  */
WelsDecodeBs(PWelsDecoderContext pCtx,const uint8_t * kpBsBuf,const int32_t kiBsLen,uint8_t ** ppDst,SBufferInfo * pDstBufInfo,SParserBsInfo * pDstBsInfo)739 int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,
740                       uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo) {
741   if (!pCtx->bEndOfStreamFlag) {
742     SDataBuffer* pRawData   = &pCtx->sRawData;
743     SDataBuffer* pSavedData = NULL;
744 
745     int32_t iSrcIdx        = 0; //the index of source bit-stream till now after parsing one or more NALs
746     int32_t iSrcConsumed   = 0; // consumed bit count of source bs
747     int32_t iDstIdx        = 0; //the size of current NAL after 0x03 removal and 00 00 01 removal
748     int32_t iSrcLength     = 0; //the total size of current AU or NAL
749     int32_t iRet = 0;
750     int32_t iConsumedBytes = 0;
751     int32_t iOffset        = 0;
752 
753     uint8_t* pSrcNal       = NULL;
754     uint8_t* pDstNal       = NULL;
755     uint8_t* pNalPayload   = NULL;
756 
757 
758     if (NULL == DetectStartCodePrefix (kpBsBuf, &iOffset,
759                                        kiBsLen)) {  //CAN'T find the 00 00 01 start prefix from the source buffer
760       pCtx->iErrorCode |= dsBitstreamError;
761       return dsBitstreamError;
762     }
763 
764     pSrcNal    = const_cast<uint8_t*> (kpBsBuf) + iOffset;
765     iSrcLength = kiBsLen - iOffset;
766 
767     if ((kiBsLen + 4) > (pRawData->pEnd - pRawData->pCurPos)) {
768       pRawData->pCurPos = pRawData->pHead;
769     }
770 
771     if (pCtx->pParam->bParseOnly) {
772       pSavedData = &pCtx->sSavedData;
773       if ((kiBsLen + 4) > (pSavedData->pEnd - pSavedData->pCurPos)) {
774         pSavedData->pCurPos = pSavedData->pHead;
775       }
776     }
777     //copy raw data from source buffer (application) to raw data buffer (codec inside)
778     //0x03 removal and extract all of NAL Unit from current raw data
779     pDstNal = pRawData->pCurPos;
780 
781     bool bNalStartBytes = false;
782 
783     while (iSrcConsumed < iSrcLength) {
784       if ((2 + iSrcConsumed < iSrcLength) && (0 == LD16 (pSrcNal + iSrcIdx)) && (pSrcNal[2 + iSrcIdx] <= 0x03)) {
785         if (bNalStartBytes && (pSrcNal[2 + iSrcIdx] != 0x00 && pSrcNal[2 + iSrcIdx] != 0x01)) {
786           pCtx->iErrorCode |= dsBitstreamError;
787           return pCtx->iErrorCode;
788         }
789 
790         if (pSrcNal[2 + iSrcIdx] == 0x02) {
791           pCtx->iErrorCode |= dsBitstreamError;
792           return pCtx->iErrorCode;
793         } else if (pSrcNal[2 + iSrcIdx] == 0x00) {
794           pDstNal[iDstIdx++] = pSrcNal[iSrcIdx++];
795           iSrcConsumed++;
796           bNalStartBytes = true;
797         } else if (pSrcNal[2 + iSrcIdx] == 0x03) {
798           if ((3 + iSrcConsumed < iSrcLength) && pSrcNal[3 + iSrcIdx] > 0x03) {
799             pCtx->iErrorCode |= dsBitstreamError;
800             return pCtx->iErrorCode;
801           } else {
802             ST16 (pDstNal + iDstIdx, 0);
803             iDstIdx      += 2;
804             iSrcIdx      += 3;
805             iSrcConsumed += 3;
806           }
807         } else { // 0x01
808           bNalStartBytes = false;
809 
810           iConsumedBytes = 0;
811           pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
812                                0; // set 4 reserved bytes to zero
813           pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
814           if (pNalPayload) { //parse correct
815             if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) {
816               iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
817             }
818             CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
819             if (pCtx->bAuReadyFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) {
820               if (GetThreadCount (pCtx) <= 1) {
821                 ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
822               } else {
823                 pCtx->pAccessUnitList->uiAvailUnitsNum = 1;
824               }
825             }
826           }
827           DecodeFinishUpdate (pCtx);
828 
829           if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
830 #ifdef LONG_TERM_REF
831             pCtx->bParamSetsLostFlag = true;
832 #else
833             pCtx->bReferenceLostAtT0Flag = true;
834 #endif
835             if (dsOutOfMemory & pCtx->iErrorCode) {
836               return pCtx->iErrorCode;
837             }
838           }
839           if (iRet) {
840             iRet = 0;
841             if (dsNoParamSets & pCtx->iErrorCode) {
842 #ifdef LONG_TERM_REF
843               pCtx->bParamSetsLostFlag = true;
844 #else
845               pCtx->bReferenceLostAtT0Flag = true;
846 #endif
847             }
848             return pCtx->iErrorCode;
849           }
850 
851           pDstNal += (iDstIdx + 4); //init, increase 4 reserved zero bytes, used to store the next NAL
852           if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) {
853             pDstNal = pRawData->pCurPos = pRawData->pHead;
854           } else {
855             pRawData->pCurPos = pDstNal;
856           }
857 
858           pSrcNal += iSrcIdx + 3;
859           iSrcConsumed += 3;
860           iSrcIdx = 0;
861           iDstIdx  = 0; //reset 0, used to statistic the length of next NAL
862         }
863         continue;
864       }
865       pDstNal[iDstIdx++] = pSrcNal[iSrcIdx++];
866       iSrcConsumed++;
867     }
868 
869     //last NAL decoding
870 
871     iConsumedBytes = 0;
872     pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
873                          0; // set 4 reserved bytes to zero
874     pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL
875     pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
876     if (pNalPayload) { //parse correct
877       if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) {
878         iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
879       }
880       if (GetThreadCount (pCtx) <= 1) {
881         CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
882       }
883       if (pCtx->bAuReadyFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) {
884         if (GetThreadCount (pCtx) <= 1) {
885           ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
886         } else {
887           pCtx->pAccessUnitList->uiAvailUnitsNum = 1;
888         }
889       }
890     }
891     DecodeFinishUpdate (pCtx);
892 
893     if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
894 #ifdef LONG_TERM_REF
895       pCtx->bParamSetsLostFlag = true;
896 #else
897       pCtx->bReferenceLostAtT0Flag = true;
898 #endif
899       return pCtx->iErrorCode;
900     }
901     if (iRet) {
902       iRet = 0;
903       if (dsNoParamSets & pCtx->iErrorCode) {
904 #ifdef LONG_TERM_REF
905         pCtx->bParamSetsLostFlag = true;
906 #else
907         pCtx->bReferenceLostAtT0Flag = true;
908 #endif
909       }
910       return pCtx->iErrorCode;
911     }
912   } else { /* no supplementary picture payload input, but stored a picture */
913     PAccessUnit pCurAu =
914       pCtx->pAccessUnitList; // current access unit, it will never point to NULL after decode's successful initialization
915 
916     if (pCurAu->uiAvailUnitsNum == 0) {
917       return pCtx->iErrorCode;
918     } else {
919       pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
920 
921       ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
922     }
923     DecodeFinishUpdate (pCtx);
924 
925     if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
926 #ifdef LONG_TERM_REF
927       pCtx->bParamSetsLostFlag = true;
928 #else
929       pCtx->bReferenceLostAtT0Flag = true;
930 #endif
931       return pCtx->iErrorCode;
932     }
933   }
934 
935   return pCtx->iErrorCode;
936 }
937 
938 /*!
939  * \brief   make sure synchonozization picture resolution (get from slice header) among different parts (i.e, memory related and so on)
940  *          over decoder internal
941  * ( MB coordinate and parts of data within decoder context structure )
942  * \param   pCtx        Wels decoder context
943  * \param   iMbWidth    MB width
944  * \pram    iMbHeight   MB height
945  * \return  0 - successful; none 0 - something wrong
946  */
SyncPictureResolutionExt(PWelsDecoderContext pCtx,const int32_t kiMbWidth,const int32_t kiMbHeight)947 int32_t SyncPictureResolutionExt (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight) {
948   int32_t iErr = ERR_NONE;
949   const int32_t kiPicWidth    = kiMbWidth << 4;
950   const int32_t kiPicHeight   = kiMbHeight << 4;
951   //fix Bugzilla Bug1479656 reallocate temp dec picture
952   if (pCtx->pTempDec != NULL && (pCtx->pTempDec->iWidthInPixel != kiPicWidth
953                                  || pCtx->pTempDec->iHeightInPixel != kiPicHeight)) {
954     FreePicture (pCtx->pTempDec, pCtx->pMemAlign);
955     pCtx->pTempDec = AllocPicture (pCtx, pCtx->pSps->iMbWidth << 4, pCtx->pSps->iMbHeight << 4);
956   }
957   bool bReallocFlag = false;
958   iErr = WelsRequestMem (pCtx, kiMbWidth, kiMbHeight, bReallocFlag); // common memory used
959   if (ERR_NONE != iErr) {
960     WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
961              "SyncPictureResolutionExt()::WelsRequestMem--buffer allocated failure.");
962     pCtx->iErrorCode |= dsOutOfMemory;
963     return iErr;
964   }
965 
966   iErr = InitialDqLayersContext (pCtx, kiPicWidth, kiPicHeight);
967   if (ERR_NONE != iErr) {
968     WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
969              "SyncPictureResolutionExt()::InitialDqLayersContext--buffer allocated failure.");
970     pCtx->iErrorCode |= dsOutOfMemory;
971   }
972 #if defined(MEMORY_MONITOR)
973   if (bReallocFlag) {
974     WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "SyncPictureResolutionExt(), overall memory usage: %llu bytes",
975              static_cast<unsigned long long> (sizeof (SWelsDecoderContext) + pCtx->pMemAlign->WelsGetMemoryUsage()));
976   }
977 #endif//MEMORY_MONITOR
978   return iErr;
979 }
980 
InitDecFuncs(PWelsDecoderContext pCtx,uint32_t uiCpuFlag)981 void InitDecFuncs (PWelsDecoderContext pCtx, uint32_t uiCpuFlag) {
982   WelsBlockFuncInit (&pCtx->sBlockFunc, uiCpuFlag);
983   InitPredFunc (pCtx, uiCpuFlag);
984   InitMcFunc (& (pCtx->sMcFunc), uiCpuFlag);
985   InitExpandPictureFunc (& (pCtx->sExpandPicFunc), uiCpuFlag);
986   DeblockingInit (&pCtx->sDeblockingFunc, uiCpuFlag);
987 }
988 
989 namespace {
990 
991 template<void pfIdctResAddPred (uint8_t* pPred, int32_t iStride, int16_t* pRs)>
IdctFourResAddPred_(uint8_t * pPred,int32_t iStride,int16_t * pRs,const int8_t * pNzc)992 void IdctFourResAddPred_ (uint8_t* pPred, int32_t iStride, int16_t* pRs, const int8_t* pNzc) {
993   if (pNzc[0] || pRs[0 * 16])
994     pfIdctResAddPred (pPred + 0 * iStride + 0, iStride, pRs + 0 * 16);
995   if (pNzc[1] || pRs[1 * 16])
996     pfIdctResAddPred (pPred + 0 * iStride + 4, iStride, pRs + 1 * 16);
997   if (pNzc[4] || pRs[2 * 16])
998     pfIdctResAddPred (pPred + 4 * iStride + 0, iStride, pRs + 2 * 16);
999   if (pNzc[5] || pRs[3 * 16])
1000     pfIdctResAddPred (pPred + 4 * iStride + 4, iStride, pRs + 3 * 16);
1001 }
1002 
1003 } // anon ns
1004 
InitPredFunc(PWelsDecoderContext pCtx,uint32_t uiCpuFlag)1005 void InitPredFunc (PWelsDecoderContext pCtx, uint32_t uiCpuFlag) {
1006   pCtx->pGetI16x16LumaPredFunc[I16_PRED_V     ] = WelsI16x16LumaPredV_c;
1007   pCtx->pGetI16x16LumaPredFunc[I16_PRED_H     ] = WelsI16x16LumaPredH_c;
1008   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC    ] = WelsI16x16LumaPredDc_c;
1009   pCtx->pGetI16x16LumaPredFunc[I16_PRED_P     ] = WelsI16x16LumaPredPlane_c;
1010   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_L  ] = WelsI16x16LumaPredDcLeft_c;
1011   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T  ] = WelsI16x16LumaPredDcTop_c;
1012   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_128] = WelsI16x16LumaPredDcNA_c;
1013 
1014   pCtx->pGetI4x4LumaPredFunc[I4_PRED_V     ] = WelsI4x4LumaPredV_c;
1015   pCtx->pGetI4x4LumaPredFunc[I4_PRED_H     ] = WelsI4x4LumaPredH_c;
1016   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC    ] = WelsI4x4LumaPredDc_c;
1017   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_L  ] = WelsI4x4LumaPredDcLeft_c;
1018   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_T  ] = WelsI4x4LumaPredDcTop_c;
1019   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_128] = WelsI4x4LumaPredDcNA_c;
1020   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL    ] = WelsI4x4LumaPredDDL_c;
1021   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL_TOP] = WelsI4x4LumaPredDDLTop_c;
1022   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDR    ] = WelsI4x4LumaPredDDR_c;
1023   pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL    ] = WelsI4x4LumaPredVL_c;
1024   pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL_TOP] = WelsI4x4LumaPredVLTop_c;
1025   pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR    ] = WelsI4x4LumaPredVR_c;
1026   pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU    ] = WelsI4x4LumaPredHU_c;
1027   pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD    ] = WelsI4x4LumaPredHD_c;
1028 
1029   pCtx->pGetI8x8LumaPredFunc[I4_PRED_V     ] = WelsI8x8LumaPredV_c;
1030   pCtx->pGetI8x8LumaPredFunc[I4_PRED_H     ] = WelsI8x8LumaPredH_c;
1031   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC    ] = WelsI8x8LumaPredDc_c;
1032   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC_L  ] = WelsI8x8LumaPredDcLeft_c;
1033   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC_T  ] = WelsI8x8LumaPredDcTop_c;
1034   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC_128] = WelsI8x8LumaPredDcNA_c;
1035   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DDL    ] = WelsI8x8LumaPredDDL_c;
1036   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DDL_TOP] = WelsI8x8LumaPredDDLTop_c;
1037   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DDR    ] = WelsI8x8LumaPredDDR_c;
1038   pCtx->pGetI8x8LumaPredFunc[I4_PRED_VL    ] = WelsI8x8LumaPredVL_c;
1039   pCtx->pGetI8x8LumaPredFunc[I4_PRED_VL_TOP] = WelsI8x8LumaPredVLTop_c;
1040   pCtx->pGetI8x8LumaPredFunc[I4_PRED_VR    ] = WelsI8x8LumaPredVR_c;
1041   pCtx->pGetI8x8LumaPredFunc[I4_PRED_HU    ] = WelsI8x8LumaPredHU_c;
1042   pCtx->pGetI8x8LumaPredFunc[I4_PRED_HD    ] = WelsI8x8LumaPredHD_c;
1043 
1044   pCtx->pGetIChromaPredFunc[C_PRED_DC    ] = WelsIChromaPredDc_c;
1045   pCtx->pGetIChromaPredFunc[C_PRED_H     ] = WelsIChromaPredH_c;
1046   pCtx->pGetIChromaPredFunc[C_PRED_V     ] = WelsIChromaPredV_c;
1047   pCtx->pGetIChromaPredFunc[C_PRED_P     ] = WelsIChromaPredPlane_c;
1048   pCtx->pGetIChromaPredFunc[C_PRED_DC_L  ] = WelsIChromaPredDcLeft_c;
1049   pCtx->pGetIChromaPredFunc[C_PRED_DC_T  ] = WelsIChromaPredDcTop_c;
1050   pCtx->pGetIChromaPredFunc[C_PRED_DC_128] = WelsIChromaPredDcNA_c;
1051 
1052   pCtx->pIdctResAddPredFunc     = IdctResAddPred_c;
1053   pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_c>;
1054 
1055   pCtx->pIdctResAddPredFunc8x8  = IdctResAddPred8x8_c;
1056 
1057 #if defined(HAVE_NEON)
1058   if (uiCpuFlag & WELS_CPU_NEON) {
1059     pCtx->pIdctResAddPredFunc   = IdctResAddPred_neon;
1060     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_neon>;
1061 
1062     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_neon;
1063     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_neon;
1064     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_neon;
1065     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_neon;
1066 
1067     pCtx->pGetI4x4LumaPredFunc[I4_PRED_V    ] = WelsDecoderI4x4LumaPredV_neon;
1068     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H    ] = WelsDecoderI4x4LumaPredH_neon;
1069     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL  ] = WelsDecoderI4x4LumaPredDDL_neon;
1070     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDR  ] = WelsDecoderI4x4LumaPredDDR_neon;
1071     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL   ] = WelsDecoderI4x4LumaPredVL_neon;
1072     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR   ] = WelsDecoderI4x4LumaPredVR_neon;
1073     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU   ] = WelsDecoderI4x4LumaPredHU_neon;
1074     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD   ] = WelsDecoderI4x4LumaPredHD_neon;
1075 
1076     pCtx->pGetIChromaPredFunc[C_PRED_H]       = WelsDecoderIChromaPredH_neon;
1077     pCtx->pGetIChromaPredFunc[C_PRED_V]       = WelsDecoderIChromaPredV_neon;
1078     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_neon;
1079     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_neon;
1080   }
1081 #endif//HAVE_NEON
1082 
1083 #if defined(HAVE_NEON_AARCH64)
1084   if (uiCpuFlag & WELS_CPU_NEON) {
1085     pCtx->pIdctResAddPredFunc   = IdctResAddPred_AArch64_neon;
1086     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_AArch64_neon>;
1087 
1088     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_AArch64_neon;
1089     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_AArch64_neon;
1090     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_AArch64_neon;
1091     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_AArch64_neon;
1092     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_L]  = WelsDecoderI16x16LumaPredDcLeft_AArch64_neon;
1093     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T]  = WelsDecoderI16x16LumaPredDcTop_AArch64_neon;
1094 
1095     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H    ] = WelsDecoderI4x4LumaPredH_AArch64_neon;
1096     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL  ] = WelsDecoderI4x4LumaPredDDL_AArch64_neon;
1097     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL_TOP] = WelsDecoderI4x4LumaPredDDLTop_AArch64_neon;
1098     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL   ] = WelsDecoderI4x4LumaPredVL_AArch64_neon;
1099     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL_TOP ] = WelsDecoderI4x4LumaPredVLTop_AArch64_neon;
1100     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR   ] = WelsDecoderI4x4LumaPredVR_AArch64_neon;
1101     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU   ] = WelsDecoderI4x4LumaPredHU_AArch64_neon;
1102     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD   ] = WelsDecoderI4x4LumaPredHD_AArch64_neon;
1103     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC   ] = WelsDecoderI4x4LumaPredDc_AArch64_neon;
1104     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_T   ] = WelsDecoderI4x4LumaPredDcTop_AArch64_neon;
1105 
1106     pCtx->pGetIChromaPredFunc[C_PRED_H]       = WelsDecoderIChromaPredH_AArch64_neon;
1107     pCtx->pGetIChromaPredFunc[C_PRED_V]       = WelsDecoderIChromaPredV_AArch64_neon;
1108     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_AArch64_neon;
1109     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_AArch64_neon;
1110     pCtx->pGetIChromaPredFunc[C_PRED_DC_T]      = WelsDecoderIChromaPredDcTop_AArch64_neon;
1111   }
1112 #endif//HAVE_NEON_AARCH64
1113 
1114 #if defined(X86_ASM)
1115   if (uiCpuFlag & WELS_CPU_MMXEXT) {
1116     pCtx->pIdctResAddPredFunc   = IdctResAddPred_mmx;
1117     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_mmx>;
1118 
1119     ///////mmx code opt---
1120     pCtx->pGetIChromaPredFunc[C_PRED_H]      = WelsDecoderIChromaPredH_mmx;
1121     pCtx->pGetIChromaPredFunc[C_PRED_V]      = WelsDecoderIChromaPredV_mmx;
1122     pCtx->pGetIChromaPredFunc[C_PRED_DC_L  ] = WelsDecoderIChromaPredDcLeft_mmx;
1123     pCtx->pGetIChromaPredFunc[C_PRED_DC_128] = WelsDecoderIChromaPredDcNA_mmx;
1124     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDR]  = WelsDecoderI4x4LumaPredDDR_mmx;
1125     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD ]  = WelsDecoderI4x4LumaPredHD_mmx;
1126     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU ]  = WelsDecoderI4x4LumaPredHU_mmx;
1127     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR ]  = WelsDecoderI4x4LumaPredVR_mmx;
1128     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL]  = WelsDecoderI4x4LumaPredDDL_mmx;
1129     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL ]  = WelsDecoderI4x4LumaPredVL_mmx;
1130   }
1131   if (uiCpuFlag & WELS_CPU_SSE2) {
1132     pCtx->pIdctResAddPredFunc     = IdctResAddPred_sse2;
1133     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_sse2>;
1134 
1135     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_sse2;
1136     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_sse2;
1137     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_sse2;
1138     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_sse2;
1139     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T  ] = WelsDecoderI16x16LumaPredDcTop_sse2;
1140     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_128] = WelsDecoderI16x16LumaPredDcNA_sse2;
1141     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_sse2;
1142     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_sse2;
1143     pCtx->pGetIChromaPredFunc[C_PRED_DC_T]    = WelsDecoderIChromaPredDcTop_sse2;
1144     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H]     = WelsDecoderI4x4LumaPredH_sse2;
1145   }
1146 #if defined(HAVE_AVX2)
1147   if (uiCpuFlag & WELS_CPU_AVX2) {
1148     pCtx->pIdctResAddPredFunc     = IdctResAddPred_avx2;
1149     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_avx2;
1150   }
1151 #endif
1152 
1153 #endif
1154 
1155 #if defined(HAVE_MMI)
1156   if (uiCpuFlag & WELS_CPU_MMI) {
1157     pCtx->pIdctResAddPredFunc   = IdctResAddPred_mmi;
1158     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_mmi>;
1159 
1160     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_mmi;
1161     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_mmi;
1162     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_mmi;
1163     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_mmi;
1164     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T  ] = WelsDecoderI16x16LumaPredDcTop_mmi;
1165     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_128] = WelsDecoderI16x16LumaPredDcNA_mmi;
1166     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_mmi;
1167     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_mmi;
1168     pCtx->pGetIChromaPredFunc[C_PRED_DC_T]    = WelsDecoderIChromaPredDcTop_mmi;
1169     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H]     = WelsDecoderI4x4LumaPredH_mmi;
1170   }
1171 #endif//HAVE_MMI
1172 
1173 #if defined(HAVE_LSX)
1174   if (uiCpuFlag & WELS_CPU_LSX) {
1175     pCtx->pIdctResAddPredFunc   = IdctResAddPred_lsx;
1176     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_lsx>;
1177     pCtx->pIdctResAddPredFunc8x8  = IdctResAddPred8x8_lsx;
1178   }
1179 #endif
1180 }
1181 
1182 //reset decoder number related statistics info
ResetDecStatNums(SDecoderStatistics * pDecStat)1183 void ResetDecStatNums (SDecoderStatistics* pDecStat) {
1184   uint32_t uiWidth = pDecStat->uiWidth;
1185   uint32_t uiHeight = pDecStat->uiHeight;
1186   int32_t iAvgLumaQp = pDecStat->iAvgLumaQp;
1187   uint32_t iLogInterval = pDecStat->iStatisticsLogInterval;
1188   uint32_t uiProfile = pDecStat->uiProfile;
1189   uint32_t uiLevel = pDecStat->uiLevel;
1190   memset (pDecStat, 0, sizeof (SDecoderStatistics));
1191   pDecStat->uiWidth = uiWidth;
1192   pDecStat->uiHeight = uiHeight;
1193   pDecStat->iAvgLumaQp = iAvgLumaQp;
1194   pDecStat->iStatisticsLogInterval = iLogInterval;
1195   pDecStat->uiProfile = uiProfile;
1196   pDecStat->uiLevel = uiLevel;
1197 }
1198 
1199 //update information when freezing occurs, including IDR/non-IDR number
UpdateDecStatFreezingInfo(const bool kbIdrFlag,SDecoderStatistics * pDecStat)1200 void UpdateDecStatFreezingInfo (const bool kbIdrFlag, SDecoderStatistics* pDecStat) {
1201   if (kbIdrFlag)
1202     pDecStat->uiFreezingIDRNum++;
1203   else
1204     pDecStat->uiFreezingNonIDRNum++;
1205 }
1206 
1207 //update information when no freezing occurs, including QP, correct IDR number, ECed IDR number
UpdateDecStatNoFreezingInfo(PWelsDecoderContext pCtx)1208 void UpdateDecStatNoFreezingInfo (PWelsDecoderContext pCtx) {
1209   PDqLayer pCurDq = pCtx->pCurDqLayer;
1210   PPicture pPic = pCtx->pDec;
1211   SDecoderStatistics* pDecStat = pCtx->pDecoderStatistics;
1212 
1213   if (pDecStat->iAvgLumaQp == -1) //first correct frame received
1214     pDecStat->iAvgLumaQp = 0;
1215 
1216   //update QP info
1217   int32_t iTotalQp = 0;
1218   const int32_t kiMbNum = pCurDq->iMbWidth * pCurDq->iMbHeight;
1219   if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { //all correct
1220     for (int32_t iMb = 0; iMb < kiMbNum; ++iMb) {
1221       iTotalQp += pCurDq->pLumaQp[iMb];
1222     }
1223     iTotalQp /= kiMbNum;
1224   } else {
1225     int32_t iCorrectMbNum = 0;
1226     for (int32_t iMb = 0; iMb < kiMbNum; ++iMb) {
1227       iCorrectMbNum += (int32_t) pCurDq->pMbCorrectlyDecodedFlag[iMb];
1228       iTotalQp += pCurDq->pLumaQp[iMb] * pCurDq->pMbCorrectlyDecodedFlag[iMb];
1229     }
1230     if (iCorrectMbNum == 0) //non MB is correct, should remain QP statistic info
1231       iTotalQp = pDecStat->iAvgLumaQp;
1232     else
1233       iTotalQp /= iCorrectMbNum;
1234   }
1235   if (pDecStat->uiDecodedFrameCount + 1 == 0) { //maximum uint32_t reached
1236     ResetDecStatNums (pDecStat);
1237     pDecStat->iAvgLumaQp = iTotalQp;
1238   } else
1239     pDecStat->iAvgLumaQp = (int) ((uint64_t) (pDecStat->iAvgLumaQp * pDecStat->uiDecodedFrameCount + iTotalQp) /
1240                                   (pDecStat->uiDecodedFrameCount + 1));
1241 
1242   //update IDR number
1243   if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag) {
1244     pDecStat->uiIDRCorrectNum += (pPic->bIsComplete);
1245     if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE)
1246       pDecStat->uiEcIDRNum += (!pPic->bIsComplete);
1247   }
1248 }
1249 
1250 //update decoder statistics information
UpdateDecStat(PWelsDecoderContext pCtx,const bool kbOutput)1251 void UpdateDecStat (PWelsDecoderContext pCtx, const bool kbOutput) {
1252   if (pCtx->bFreezeOutput)
1253     UpdateDecStatFreezingInfo (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag, pCtx->pDecoderStatistics);
1254   else if (kbOutput)
1255     UpdateDecStatNoFreezingInfo (pCtx);
1256 }
1257 
1258 
1259 } // namespace WelsDec
1260