• 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       iNumRefFrames = MAX_REF_PIC_COUNT;
446     }
447   }
448 
449 #ifdef LONG_TERM_REF
450   //pic_queue size minimum set 2
451   if (iNumRefFrames < 2) {
452     iNumRefFrames = 2;
453   }
454 #endif
455 
456   return iNumRefFrames;
457 }
458 
459 /*
460  *  request memory blocks for decoder avc part
461  */
WelsRequestMem(PWelsDecoderContext pCtx,const int32_t kiMbWidth,const int32_t kiMbHeight,bool & bReallocFlag)462 int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight,
463                         bool& bReallocFlag) {
464   const int32_t kiPicWidth      = kiMbWidth << 4;
465   const int32_t kiPicHeight     = kiMbHeight << 4;
466   int32_t iErr = ERR_NONE;
467 
468   int32_t iPicQueueSize         = 0;    // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
469   bReallocFlag                  = false;
470   bool  bNeedChangePicQueue     = true;
471   CMemoryAlign* pMa = pCtx->pMemAlign;
472 
473   WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiPicWidth <= 0 || kiPicHeight <= 0))
474 
475   // Fixed the issue about different gop size over last, 5/17/2010
476   // get picture queue size currently
477   iPicQueueSize = GetTargetRefListSize (pCtx);  // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
478   pCtx->iPicQueueNumber = iPicQueueSize;
479   if (pCtx->pPicBuff != NULL
480       && pCtx->pPicBuff->iCapacity ==
481       iPicQueueSize) // comparing current picture queue size requested and previous allocation picture queue
482     bNeedChangePicQueue = false;
483   // HD based pic buffer need consider memory size consumed when switch from 720p to other lower size
484   WELS_VERIFY_RETURN_IF (ERR_NONE, pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel
485                          && kiPicHeight == pCtx->iImgHeightInPixel) && (!bNeedChangePicQueue)) // have same scaled buffer
486 
487   // sync update pRefList
488   if (GetThreadCount (pCtx) <= 1) {
489     WelsResetRefPic (pCtx); // added to sync update ref list due to pictures are free
490   }
491 
492   if (pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel && kiPicHeight == pCtx->iImgHeightInPixel)
493       && pCtx->pPicBuff != NULL && pCtx->pPicBuff->iCapacity != iPicQueueSize) {
494     // currently only active for LIST_0 due to have no B frames
495     // Actually just need one memory allocation for the PicBuff. While it needs two pointer list (LIST_0 and LIST_1).
496     WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
497              "WelsRequestMem(): memory re-alloc for no resolution change (size = %d * %d), ref list size change from %d to %d",
498              kiPicWidth, kiPicHeight, pCtx->pPicBuff->iCapacity, iPicQueueSize);
499     if (pCtx->pPicBuff->iCapacity < iPicQueueSize) {
500       iErr = IncreasePicBuff (pCtx, &pCtx->pPicBuff, pCtx->pPicBuff->iCapacity, kiPicWidth, kiPicHeight,
501                               iPicQueueSize);
502     } else {
503       iErr = DecreasePicBuff (pCtx, &pCtx->pPicBuff, pCtx->pPicBuff->iCapacity, kiPicWidth, kiPicHeight,
504                               iPicQueueSize);
505     }
506   } else {
507     if (pCtx->bHaveGotMemory)
508       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
509                "WelsRequestMem(): memory re-alloc for resolution change, size change from %d * %d to %d * %d, ref list size change from %d to %d",
510                pCtx->iImgWidthInPixel, pCtx->iImgHeightInPixel, kiPicWidth, kiPicHeight, pCtx->pPicBuff->iCapacity,
511                iPicQueueSize);
512     else
513       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "WelsRequestMem(): memory alloc size = %d * %d, ref list size = %d",
514                kiPicWidth, kiPicHeight, iPicQueueSize);
515     // for Recycled_Pic_Queue
516     PPicBuff* ppPic = &pCtx->pPicBuff;
517     if (NULL != ppPic && NULL != *ppPic) {
518       DestroyPicBuff (pCtx, ppPic, pMa);
519     }
520 
521 
522     pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb = NULL;
523 
524     // currently only active for LIST_0 due to have no B frames
525     iErr = CreatePicBuff (pCtx, &pCtx->pPicBuff, iPicQueueSize, kiPicWidth, kiPicHeight);
526   }
527 
528   if (iErr != ERR_NONE)
529     return iErr;
530 
531 
532   pCtx->iImgWidthInPixel    = kiPicWidth;   // target width of image to be reconstruted while decoding
533   pCtx->iImgHeightInPixel   = kiPicHeight;  // target height of image to be reconstruted while decoding
534 
535   pCtx->bHaveGotMemory      = true;         // global memory for decoder context related is requested
536   pCtx->pDec                = NULL;         // need prefetch a new pic due to spatial size changed
537 
538   if (pCtx->pCabacDecEngine == NULL)
539     pCtx->pCabacDecEngine = (SWelsCabacDecEngine*) pMa->WelsMallocz (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");
540   WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, (NULL == pCtx->pCabacDecEngine))
541 
542   bReallocFlag              = true;         // memory re-allocation successfully finished
543   return ERR_NONE;
544 }
545 
546 /*
547  *  free memory dynamically allocated during decoder
548  */
WelsFreeDynamicMemory(PWelsDecoderContext pCtx)549 void WelsFreeDynamicMemory (PWelsDecoderContext pCtx) {
550 
551   CMemoryAlign* pMa = pCtx->pMemAlign;
552 
553   //free dq layer memory
554   UninitialDqLayersContext (pCtx);
555 
556   //free FMO memory
557   ResetFmoList (pCtx);
558 
559   //free ref-pic list & picture memory
560   WelsResetRefPic (pCtx);
561 
562   PPicBuff* pPicBuff = &pCtx->pPicBuff;
563   if (NULL != pPicBuff && NULL != *pPicBuff) {
564     DestroyPicBuff (pCtx, pPicBuff, pMa);
565   }
566   if (GetThreadCount (pCtx) > 1) {
567     //prevent from double destruction of PPicBuff
568     PWelsDecoderThreadCTX pThreadCtx = (PWelsDecoderThreadCTX) (pCtx->pThreadCtx);
569     int32_t threadCount = pThreadCtx->sThreadInfo.uiThrMaxNum;
570     int32_t  id = pThreadCtx->sThreadInfo.uiThrNum;
571     for (int32_t i = 0; i < threadCount; ++i) {
572       if (pThreadCtx[i - id].pCtx != NULL) {
573         pThreadCtx[i - id].pCtx->pPicBuff = NULL;
574       }
575     }
576   }
577 
578   if (pCtx->pTempDec) {
579     FreePicture (pCtx->pTempDec, pCtx->pMemAlign);
580     pCtx->pTempDec = NULL;
581   }
582 
583   // added for safe memory
584   pCtx->iImgWidthInPixel  = 0;
585   pCtx->iImgHeightInPixel = 0;
586   pCtx->iLastImgWidthInPixel  = 0;
587   pCtx->iLastImgHeightInPixel = 0;
588   pCtx->bFreezeOutput = true;
589   pCtx->bHaveGotMemory = false;
590 
591   //free CABAC memory
592   pMa->WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
593 }
594 
595 /*!
596  * \brief   Open decoder
597  */
WelsOpenDecoder(PWelsDecoderContext pCtx,SLogContext * pLogCtx)598 int32_t WelsOpenDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
599   int iRet = ERR_NONE;
600   // function pointers
601   InitDecFuncs (pCtx, pCtx->uiCpuFlag);
602 
603   // vlc tables
604   InitVlcTable (pCtx->pVlcTable);
605 
606   // static memory
607   iRet = WelsInitStaticMemory (pCtx);
608   if (ERR_NONE != iRet) {
609     pCtx->iErrorCode |= dsOutOfMemory;
610     WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitStaticMemory() failed in WelsOpenDecoder().");
611     return iRet;
612   }
613 
614 #ifdef LONG_TERM_REF
615   pCtx->bParamSetsLostFlag = true;
616 #else
617   pCtx->bReferenceLostAtT0Flag = true; // should be true to waiting IDR at incoming AU bits following, 6/4/2010
618 #endif //LONG_TERM_REF
619   pCtx->bNewSeqBegin = true;
620   pCtx->bPrintFrameErrorTraceFlag = true;
621   pCtx->iIgnoredErrorInfoPacketCount = 0;
622   pCtx->bFrameFinish = true;
623   return iRet;
624 }
625 
626 /*!
627  * \brief   Close decoder
628  */
WelsCloseDecoder(PWelsDecoderContext pCtx)629 void WelsCloseDecoder (PWelsDecoderContext pCtx) {
630   WelsFreeDynamicMemory (pCtx);
631 
632   WelsFreeStaticMemory (pCtx);
633 
634 #ifdef LONG_TERM_REF
635   pCtx->bParamSetsLostFlag       = false;
636 #else
637   pCtx->bReferenceLostAtT0Flag = false;
638 #endif
639   pCtx->bNewSeqBegin = false;
640   pCtx->bPrintFrameErrorTraceFlag = false;
641 }
642 
643 /*!
644  * \brief   configure decoder parameters
645  */
DecoderConfigParam(PWelsDecoderContext pCtx,const SDecodingParam * kpParam)646 int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpParam) {
647   if (NULL == pCtx || NULL == kpParam)
648     return ERR_INFO_INVALID_PARAM;
649 
650   memcpy (pCtx->pParam, kpParam, sizeof (SDecodingParam));
651   if ((pCtx->pParam->eEcActiveIdc > ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
652       || (pCtx->pParam->eEcActiveIdc < ERROR_CON_DISABLE)) {
653     WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
654              "eErrorConMethod (%d) not in range: (%d - %d). Set as default value: (%d).", pCtx->pParam->eEcActiveIdc,
655              ERROR_CON_DISABLE, ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE,
656              ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
657     pCtx->pParam->eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
658   }
659 
660   if (pCtx->pParam->bParseOnly) //parse only, disable EC method
661     pCtx->pParam->eEcActiveIdc = ERROR_CON_DISABLE;
662   InitErrorCon (pCtx);
663 
664   if (VIDEO_BITSTREAM_SVC == pCtx->pParam->sVideoProperty.eVideoBsType ||
665       VIDEO_BITSTREAM_AVC == pCtx->pParam->sVideoProperty.eVideoBsType) {
666     pCtx->eVideoType = pCtx->pParam->sVideoProperty.eVideoBsType;
667   } else {
668     pCtx->eVideoType = VIDEO_BITSTREAM_DEFAULT;
669   }
670 
671   WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "eVideoType: %d", pCtx->eVideoType);
672 
673   return ERR_NONE;
674 }
675 
676 /*!
677  *************************************************************************************
678  * \brief   Initialize Wels decoder parameters and memory
679  *
680  * \param   pCtx input context to be initialized at first stage
681  *
682  * \return  0 - successed
683  * \return  1 - failed
684  *
685  * \note    N/A
686  *************************************************************************************
687  */
WelsInitDecoder(PWelsDecoderContext pCtx,SLogContext * pLogCtx)688 int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
689   if (pCtx == NULL) {
690     return ERR_INFO_INVALID_PTR;
691   }
692 
693   // open decoder
694   return WelsOpenDecoder (pCtx, pLogCtx);
695 }
696 
697 /*!
698  *************************************************************************************
699  * \brief   Uninitialize Wels decoder parameters and memory
700  *
701  * \param   pCtx input context to be uninitialized at release stage
702  *
703  * \return  NONE
704  *
705  * \note    N/A
706  *************************************************************************************
707  */
WelsEndDecoder(PWelsDecoderContext pCtx)708 void WelsEndDecoder (PWelsDecoderContext pCtx) {
709   // close decoder
710   WelsCloseDecoder (pCtx);
711 }
712 
GetVclNalTemporalId(PWelsDecoderContext pCtx)713 void GetVclNalTemporalId (PWelsDecoderContext pCtx) {
714   PAccessUnit pAccessUnit = pCtx->pAccessUnitList;
715   int32_t idx = pAccessUnit->uiStartPos;
716 
717   pCtx->iFeedbackVclNalInAu = FEEDBACK_VCL_NAL;
718   pCtx->iFeedbackTidInAu    = pAccessUnit->pNalUnitsList[idx]->sNalHeaderExt.uiTemporalId;
719   pCtx->iFeedbackNalRefIdc  = pAccessUnit->pNalUnitsList[idx]->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc;
720 }
721 
722 /*!
723  *************************************************************************************
724  * \brief   First entrance to decoding core interface.
725  *
726  * \param   pCtx            decoder context
727  * \param   pBufBs          bit streaming buffer
728  * \param   kBsLen          size in bytes length of bit streaming buffer input
729  * \param   ppDst           picture payload data to be output
730  * \param   pDstBufInfo     buf information of ouput data
731  *
732  * \return  0 - successed
733  * \return  1 - failed
734  *
735  * \note    N/A
736  *************************************************************************************
737  */
WelsDecodeBs(PWelsDecoderContext pCtx,const uint8_t * kpBsBuf,const int32_t kiBsLen,uint8_t ** ppDst,SBufferInfo * pDstBufInfo,SParserBsInfo * pDstBsInfo)738 int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,
739                       uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo) {
740   if (!pCtx->bEndOfStreamFlag) {
741     SDataBuffer* pRawData   = &pCtx->sRawData;
742     SDataBuffer* pSavedData = NULL;
743 
744     int32_t iSrcIdx        = 0; //the index of source bit-stream till now after parsing one or more NALs
745     int32_t iSrcConsumed   = 0; // consumed bit count of source bs
746     int32_t iDstIdx        = 0; //the size of current NAL after 0x03 removal and 00 00 01 removal
747     int32_t iSrcLength     = 0; //the total size of current AU or NAL
748     int32_t iRet = 0;
749     int32_t iConsumedBytes = 0;
750     int32_t iOffset        = 0;
751 
752     uint8_t* pSrcNal       = NULL;
753     uint8_t* pDstNal       = NULL;
754     uint8_t* pNalPayload   = NULL;
755 
756 
757     if (NULL == DetectStartCodePrefix (kpBsBuf, &iOffset,
758                                        kiBsLen)) {  //CAN'T find the 00 00 01 start prefix from the source buffer
759       pCtx->iErrorCode |= dsBitstreamError;
760       return dsBitstreamError;
761     }
762 
763     pSrcNal    = const_cast<uint8_t*> (kpBsBuf) + iOffset;
764     iSrcLength = kiBsLen - iOffset;
765 
766     if ((kiBsLen + 4) > (pRawData->pEnd - pRawData->pCurPos)) {
767       pRawData->pCurPos = pRawData->pHead;
768     }
769 
770     if (pCtx->pParam->bParseOnly) {
771       pSavedData = &pCtx->sSavedData;
772       if ((kiBsLen + 4) > (pSavedData->pEnd - pSavedData->pCurPos)) {
773         pSavedData->pCurPos = pSavedData->pHead;
774       }
775     }
776     //copy raw data from source buffer (application) to raw data buffer (codec inside)
777     //0x03 removal and extract all of NAL Unit from current raw data
778     pDstNal = pRawData->pCurPos;
779 
780     bool bNalStartBytes = false;
781 
782     while (iSrcConsumed < iSrcLength) {
783       if ((2 + iSrcConsumed < iSrcLength) && (0 == LD16 (pSrcNal + iSrcIdx)) && (pSrcNal[2 + iSrcIdx] <= 0x03)) {
784         if (bNalStartBytes && (pSrcNal[2 + iSrcIdx] != 0x00 && pSrcNal[2 + iSrcIdx] != 0x01)) {
785           pCtx->iErrorCode |= dsBitstreamError;
786           return pCtx->iErrorCode;
787         }
788 
789         if (pSrcNal[2 + iSrcIdx] == 0x02) {
790           pCtx->iErrorCode |= dsBitstreamError;
791           return pCtx->iErrorCode;
792         } else if (pSrcNal[2 + iSrcIdx] == 0x00) {
793           pDstNal[iDstIdx++] = pSrcNal[iSrcIdx++];
794           iSrcConsumed++;
795           bNalStartBytes = true;
796         } else if (pSrcNal[2 + iSrcIdx] == 0x03) {
797           if ((3 + iSrcConsumed < iSrcLength) && pSrcNal[3 + iSrcIdx] > 0x03) {
798             pCtx->iErrorCode |= dsBitstreamError;
799             return pCtx->iErrorCode;
800           } else {
801             ST16 (pDstNal + iDstIdx, 0);
802             iDstIdx      += 2;
803             iSrcIdx      += 3;
804             iSrcConsumed += 3;
805           }
806         } else { // 0x01
807           bNalStartBytes = false;
808 
809           iConsumedBytes = 0;
810           pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
811                                0; // set 4 reserved bytes to zero
812           pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
813           if (pNalPayload) { //parse correct
814             if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) {
815               iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
816             }
817             CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
818             if (pCtx->bAuReadyFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) {
819               if (GetThreadCount (pCtx) <= 1) {
820                 ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
821               } else {
822                 pCtx->pAccessUnitList->uiAvailUnitsNum = 1;
823               }
824             }
825           }
826           DecodeFinishUpdate (pCtx);
827 
828           if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
829 #ifdef LONG_TERM_REF
830             pCtx->bParamSetsLostFlag = true;
831 #else
832             pCtx->bReferenceLostAtT0Flag = true;
833 #endif
834             if (dsOutOfMemory & pCtx->iErrorCode) {
835               return pCtx->iErrorCode;
836             }
837           }
838           if (iRet) {
839             iRet = 0;
840             if (dsNoParamSets & pCtx->iErrorCode) {
841 #ifdef LONG_TERM_REF
842               pCtx->bParamSetsLostFlag = true;
843 #else
844               pCtx->bReferenceLostAtT0Flag = true;
845 #endif
846             }
847             return pCtx->iErrorCode;
848           }
849 
850           pDstNal += (iDstIdx + 4); //init, increase 4 reserved zero bytes, used to store the next NAL
851           if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) {
852             pDstNal = pRawData->pCurPos = pRawData->pHead;
853           } else {
854             pRawData->pCurPos = pDstNal;
855           }
856 
857           pSrcNal += iSrcIdx + 3;
858           iSrcConsumed += 3;
859           iSrcIdx = 0;
860           iDstIdx  = 0; //reset 0, used to statistic the length of next NAL
861         }
862         continue;
863       }
864       pDstNal[iDstIdx++] = pSrcNal[iSrcIdx++];
865       iSrcConsumed++;
866     }
867 
868     //last NAL decoding
869 
870     iConsumedBytes = 0;
871     pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
872                          0; // set 4 reserved bytes to zero
873     pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL
874     pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
875     if (pNalPayload) { //parse correct
876       if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) {
877         iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
878       }
879       if (GetThreadCount (pCtx) <= 1) {
880         CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
881       }
882       if (pCtx->bAuReadyFlag && pCtx->pAccessUnitList->uiAvailUnitsNum != 0) {
883         if (GetThreadCount (pCtx) <= 1) {
884           ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
885         } else {
886           pCtx->pAccessUnitList->uiAvailUnitsNum = 1;
887         }
888       }
889     }
890     DecodeFinishUpdate (pCtx);
891 
892     if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
893 #ifdef LONG_TERM_REF
894       pCtx->bParamSetsLostFlag = true;
895 #else
896       pCtx->bReferenceLostAtT0Flag = true;
897 #endif
898       return pCtx->iErrorCode;
899     }
900     if (iRet) {
901       iRet = 0;
902       if (dsNoParamSets & pCtx->iErrorCode) {
903 #ifdef LONG_TERM_REF
904         pCtx->bParamSetsLostFlag = true;
905 #else
906         pCtx->bReferenceLostAtT0Flag = true;
907 #endif
908       }
909       return pCtx->iErrorCode;
910     }
911   } else { /* no supplementary picture payload input, but stored a picture */
912     PAccessUnit pCurAu =
913       pCtx->pAccessUnitList; // current access unit, it will never point to NULL after decode's successful initialization
914 
915     if (pCurAu->uiAvailUnitsNum == 0) {
916       return pCtx->iErrorCode;
917     } else {
918       pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
919 
920       ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
921     }
922     DecodeFinishUpdate (pCtx);
923 
924     if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) {
925 #ifdef LONG_TERM_REF
926       pCtx->bParamSetsLostFlag = true;
927 #else
928       pCtx->bReferenceLostAtT0Flag = true;
929 #endif
930       return pCtx->iErrorCode;
931     }
932   }
933 
934   return pCtx->iErrorCode;
935 }
936 
937 /*!
938  * \brief   make sure synchonozization picture resolution (get from slice header) among different parts (i.e, memory related and so on)
939  *          over decoder internal
940  * ( MB coordinate and parts of data within decoder context structure )
941  * \param   pCtx        Wels decoder context
942  * \param   iMbWidth    MB width
943  * \pram    iMbHeight   MB height
944  * \return  0 - successful; none 0 - something wrong
945  */
SyncPictureResolutionExt(PWelsDecoderContext pCtx,const int32_t kiMbWidth,const int32_t kiMbHeight)946 int32_t SyncPictureResolutionExt (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight) {
947   int32_t iErr = ERR_NONE;
948   const int32_t kiPicWidth    = kiMbWidth << 4;
949   const int32_t kiPicHeight   = kiMbHeight << 4;
950   //fix Bugzilla Bug1479656 reallocate temp dec picture
951   if (pCtx->pTempDec != NULL && (pCtx->pTempDec->iWidthInPixel != kiPicWidth
952                                  || pCtx->pTempDec->iHeightInPixel != kiPicHeight)) {
953     FreePicture (pCtx->pTempDec, pCtx->pMemAlign);
954     pCtx->pTempDec = AllocPicture (pCtx, pCtx->pSps->iMbWidth << 4, pCtx->pSps->iMbHeight << 4);
955   }
956   bool bReallocFlag = false;
957   iErr = WelsRequestMem (pCtx, kiMbWidth, kiMbHeight, bReallocFlag); // common memory used
958   if (ERR_NONE != iErr) {
959     WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
960              "SyncPictureResolutionExt()::WelsRequestMem--buffer allocated failure.");
961     pCtx->iErrorCode |= dsOutOfMemory;
962     return iErr;
963   }
964 
965   iErr = InitialDqLayersContext (pCtx, kiPicWidth, kiPicHeight);
966   if (ERR_NONE != iErr) {
967     WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
968              "SyncPictureResolutionExt()::InitialDqLayersContext--buffer allocated failure.");
969     pCtx->iErrorCode |= dsOutOfMemory;
970   }
971 #if defined(MEMORY_MONITOR)
972   if (bReallocFlag) {
973     WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "SyncPictureResolutionExt(), overall memory usage: %llu bytes",
974              static_cast<unsigned long long> (sizeof (SWelsDecoderContext) + pCtx->pMemAlign->WelsGetMemoryUsage()));
975   }
976 #endif//MEMORY_MONITOR
977   return iErr;
978 }
979 
InitDecFuncs(PWelsDecoderContext pCtx,uint32_t uiCpuFlag)980 void InitDecFuncs (PWelsDecoderContext pCtx, uint32_t uiCpuFlag) {
981   WelsBlockFuncInit (&pCtx->sBlockFunc, uiCpuFlag);
982   InitPredFunc (pCtx, uiCpuFlag);
983   InitMcFunc (& (pCtx->sMcFunc), uiCpuFlag);
984   InitExpandPictureFunc (& (pCtx->sExpandPicFunc), uiCpuFlag);
985   DeblockingInit (&pCtx->sDeblockingFunc, uiCpuFlag);
986 }
987 
988 namespace {
989 
990 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)991 void IdctFourResAddPred_ (uint8_t* pPred, int32_t iStride, int16_t* pRs, const int8_t* pNzc) {
992   if (pNzc[0] || pRs[0 * 16])
993     pfIdctResAddPred (pPred + 0 * iStride + 0, iStride, pRs + 0 * 16);
994   if (pNzc[1] || pRs[1 * 16])
995     pfIdctResAddPred (pPred + 0 * iStride + 4, iStride, pRs + 1 * 16);
996   if (pNzc[4] || pRs[2 * 16])
997     pfIdctResAddPred (pPred + 4 * iStride + 0, iStride, pRs + 2 * 16);
998   if (pNzc[5] || pRs[3 * 16])
999     pfIdctResAddPred (pPred + 4 * iStride + 4, iStride, pRs + 3 * 16);
1000 }
1001 
1002 } // anon ns
1003 
InitPredFunc(PWelsDecoderContext pCtx,uint32_t uiCpuFlag)1004 void InitPredFunc (PWelsDecoderContext pCtx, uint32_t uiCpuFlag) {
1005   pCtx->pGetI16x16LumaPredFunc[I16_PRED_V     ] = WelsI16x16LumaPredV_c;
1006   pCtx->pGetI16x16LumaPredFunc[I16_PRED_H     ] = WelsI16x16LumaPredH_c;
1007   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC    ] = WelsI16x16LumaPredDc_c;
1008   pCtx->pGetI16x16LumaPredFunc[I16_PRED_P     ] = WelsI16x16LumaPredPlane_c;
1009   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_L  ] = WelsI16x16LumaPredDcLeft_c;
1010   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T  ] = WelsI16x16LumaPredDcTop_c;
1011   pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_128] = WelsI16x16LumaPredDcNA_c;
1012 
1013   pCtx->pGetI4x4LumaPredFunc[I4_PRED_V     ] = WelsI4x4LumaPredV_c;
1014   pCtx->pGetI4x4LumaPredFunc[I4_PRED_H     ] = WelsI4x4LumaPredH_c;
1015   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC    ] = WelsI4x4LumaPredDc_c;
1016   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_L  ] = WelsI4x4LumaPredDcLeft_c;
1017   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_T  ] = WelsI4x4LumaPredDcTop_c;
1018   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_128] = WelsI4x4LumaPredDcNA_c;
1019   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL    ] = WelsI4x4LumaPredDDL_c;
1020   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL_TOP] = WelsI4x4LumaPredDDLTop_c;
1021   pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDR    ] = WelsI4x4LumaPredDDR_c;
1022   pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL    ] = WelsI4x4LumaPredVL_c;
1023   pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL_TOP] = WelsI4x4LumaPredVLTop_c;
1024   pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR    ] = WelsI4x4LumaPredVR_c;
1025   pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU    ] = WelsI4x4LumaPredHU_c;
1026   pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD    ] = WelsI4x4LumaPredHD_c;
1027 
1028   pCtx->pGetI8x8LumaPredFunc[I4_PRED_V     ] = WelsI8x8LumaPredV_c;
1029   pCtx->pGetI8x8LumaPredFunc[I4_PRED_H     ] = WelsI8x8LumaPredH_c;
1030   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC    ] = WelsI8x8LumaPredDc_c;
1031   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC_L  ] = WelsI8x8LumaPredDcLeft_c;
1032   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC_T  ] = WelsI8x8LumaPredDcTop_c;
1033   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DC_128] = WelsI8x8LumaPredDcNA_c;
1034   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DDL    ] = WelsI8x8LumaPredDDL_c;
1035   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DDL_TOP] = WelsI8x8LumaPredDDLTop_c;
1036   pCtx->pGetI8x8LumaPredFunc[I4_PRED_DDR    ] = WelsI8x8LumaPredDDR_c;
1037   pCtx->pGetI8x8LumaPredFunc[I4_PRED_VL    ] = WelsI8x8LumaPredVL_c;
1038   pCtx->pGetI8x8LumaPredFunc[I4_PRED_VL_TOP] = WelsI8x8LumaPredVLTop_c;
1039   pCtx->pGetI8x8LumaPredFunc[I4_PRED_VR    ] = WelsI8x8LumaPredVR_c;
1040   pCtx->pGetI8x8LumaPredFunc[I4_PRED_HU    ] = WelsI8x8LumaPredHU_c;
1041   pCtx->pGetI8x8LumaPredFunc[I4_PRED_HD    ] = WelsI8x8LumaPredHD_c;
1042 
1043   pCtx->pGetIChromaPredFunc[C_PRED_DC    ] = WelsIChromaPredDc_c;
1044   pCtx->pGetIChromaPredFunc[C_PRED_H     ] = WelsIChromaPredH_c;
1045   pCtx->pGetIChromaPredFunc[C_PRED_V     ] = WelsIChromaPredV_c;
1046   pCtx->pGetIChromaPredFunc[C_PRED_P     ] = WelsIChromaPredPlane_c;
1047   pCtx->pGetIChromaPredFunc[C_PRED_DC_L  ] = WelsIChromaPredDcLeft_c;
1048   pCtx->pGetIChromaPredFunc[C_PRED_DC_T  ] = WelsIChromaPredDcTop_c;
1049   pCtx->pGetIChromaPredFunc[C_PRED_DC_128] = WelsIChromaPredDcNA_c;
1050 
1051   pCtx->pIdctResAddPredFunc     = IdctResAddPred_c;
1052   pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_c>;
1053 
1054   pCtx->pIdctResAddPredFunc8x8  = IdctResAddPred8x8_c;
1055 
1056 #if defined(HAVE_NEON)
1057   if (uiCpuFlag & WELS_CPU_NEON) {
1058     pCtx->pIdctResAddPredFunc   = IdctResAddPred_neon;
1059     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_neon>;
1060 
1061     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_neon;
1062     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_neon;
1063     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_neon;
1064     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_neon;
1065 
1066     pCtx->pGetI4x4LumaPredFunc[I4_PRED_V    ] = WelsDecoderI4x4LumaPredV_neon;
1067     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H    ] = WelsDecoderI4x4LumaPredH_neon;
1068     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL  ] = WelsDecoderI4x4LumaPredDDL_neon;
1069     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDR  ] = WelsDecoderI4x4LumaPredDDR_neon;
1070     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL   ] = WelsDecoderI4x4LumaPredVL_neon;
1071     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR   ] = WelsDecoderI4x4LumaPredVR_neon;
1072     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU   ] = WelsDecoderI4x4LumaPredHU_neon;
1073     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD   ] = WelsDecoderI4x4LumaPredHD_neon;
1074 
1075     pCtx->pGetIChromaPredFunc[C_PRED_H]       = WelsDecoderIChromaPredH_neon;
1076     pCtx->pGetIChromaPredFunc[C_PRED_V]       = WelsDecoderIChromaPredV_neon;
1077     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_neon;
1078     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_neon;
1079   }
1080 #endif//HAVE_NEON
1081 
1082 #if defined(HAVE_NEON_AARCH64)
1083   if (uiCpuFlag & WELS_CPU_NEON) {
1084     pCtx->pIdctResAddPredFunc   = IdctResAddPred_AArch64_neon;
1085     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_AArch64_neon>;
1086 
1087     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_AArch64_neon;
1088     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_AArch64_neon;
1089     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_AArch64_neon;
1090     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_AArch64_neon;
1091     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_L]  = WelsDecoderI16x16LumaPredDcLeft_AArch64_neon;
1092     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T]  = WelsDecoderI16x16LumaPredDcTop_AArch64_neon;
1093 
1094     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H    ] = WelsDecoderI4x4LumaPredH_AArch64_neon;
1095     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL  ] = WelsDecoderI4x4LumaPredDDL_AArch64_neon;
1096     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL_TOP] = WelsDecoderI4x4LumaPredDDLTop_AArch64_neon;
1097     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL   ] = WelsDecoderI4x4LumaPredVL_AArch64_neon;
1098     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL_TOP ] = WelsDecoderI4x4LumaPredVLTop_AArch64_neon;
1099     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR   ] = WelsDecoderI4x4LumaPredVR_AArch64_neon;
1100     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU   ] = WelsDecoderI4x4LumaPredHU_AArch64_neon;
1101     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD   ] = WelsDecoderI4x4LumaPredHD_AArch64_neon;
1102     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC   ] = WelsDecoderI4x4LumaPredDc_AArch64_neon;
1103     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DC_T   ] = WelsDecoderI4x4LumaPredDcTop_AArch64_neon;
1104 
1105     pCtx->pGetIChromaPredFunc[C_PRED_H]       = WelsDecoderIChromaPredH_AArch64_neon;
1106     pCtx->pGetIChromaPredFunc[C_PRED_V]       = WelsDecoderIChromaPredV_AArch64_neon;
1107     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_AArch64_neon;
1108     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_AArch64_neon;
1109     pCtx->pGetIChromaPredFunc[C_PRED_DC_T]      = WelsDecoderIChromaPredDcTop_AArch64_neon;
1110   }
1111 #endif//HAVE_NEON_AARCH64
1112 
1113 #if defined(X86_ASM)
1114   if (uiCpuFlag & WELS_CPU_MMXEXT) {
1115     pCtx->pIdctResAddPredFunc   = IdctResAddPred_mmx;
1116     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_mmx>;
1117 
1118     ///////mmx code opt---
1119     pCtx->pGetIChromaPredFunc[C_PRED_H]      = WelsDecoderIChromaPredH_mmx;
1120     pCtx->pGetIChromaPredFunc[C_PRED_V]      = WelsDecoderIChromaPredV_mmx;
1121     pCtx->pGetIChromaPredFunc[C_PRED_DC_L  ] = WelsDecoderIChromaPredDcLeft_mmx;
1122     pCtx->pGetIChromaPredFunc[C_PRED_DC_128] = WelsDecoderIChromaPredDcNA_mmx;
1123     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDR]  = WelsDecoderI4x4LumaPredDDR_mmx;
1124     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HD ]  = WelsDecoderI4x4LumaPredHD_mmx;
1125     pCtx->pGetI4x4LumaPredFunc[I4_PRED_HU ]  = WelsDecoderI4x4LumaPredHU_mmx;
1126     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VR ]  = WelsDecoderI4x4LumaPredVR_mmx;
1127     pCtx->pGetI4x4LumaPredFunc[I4_PRED_DDL]  = WelsDecoderI4x4LumaPredDDL_mmx;
1128     pCtx->pGetI4x4LumaPredFunc[I4_PRED_VL ]  = WelsDecoderI4x4LumaPredVL_mmx;
1129   }
1130   if (uiCpuFlag & WELS_CPU_SSE2) {
1131     pCtx->pIdctResAddPredFunc     = IdctResAddPred_sse2;
1132     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_sse2>;
1133 
1134     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_sse2;
1135     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_sse2;
1136     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_sse2;
1137     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_sse2;
1138     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T  ] = WelsDecoderI16x16LumaPredDcTop_sse2;
1139     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_128] = WelsDecoderI16x16LumaPredDcNA_sse2;
1140     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_sse2;
1141     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_sse2;
1142     pCtx->pGetIChromaPredFunc[C_PRED_DC_T]    = WelsDecoderIChromaPredDcTop_sse2;
1143     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H]     = WelsDecoderI4x4LumaPredH_sse2;
1144   }
1145 #if defined(HAVE_AVX2)
1146   if (uiCpuFlag & WELS_CPU_AVX2) {
1147     pCtx->pIdctResAddPredFunc     = IdctResAddPred_avx2;
1148     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_avx2;
1149   }
1150 #endif
1151 
1152 #endif
1153 
1154 #if defined(HAVE_MMI)
1155   if (uiCpuFlag & WELS_CPU_MMI) {
1156     pCtx->pIdctResAddPredFunc   = IdctResAddPred_mmi;
1157     pCtx->pIdctFourResAddPredFunc = IdctFourResAddPred_<IdctResAddPred_mmi>;
1158 
1159     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC] = WelsDecoderI16x16LumaPredDc_mmi;
1160     pCtx->pGetI16x16LumaPredFunc[I16_PRED_P]  = WelsDecoderI16x16LumaPredPlane_mmi;
1161     pCtx->pGetI16x16LumaPredFunc[I16_PRED_H]  = WelsDecoderI16x16LumaPredH_mmi;
1162     pCtx->pGetI16x16LumaPredFunc[I16_PRED_V]  = WelsDecoderI16x16LumaPredV_mmi;
1163     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_T  ] = WelsDecoderI16x16LumaPredDcTop_mmi;
1164     pCtx->pGetI16x16LumaPredFunc[I16_PRED_DC_128] = WelsDecoderI16x16LumaPredDcNA_mmi;
1165     pCtx->pGetIChromaPredFunc[C_PRED_P ]      = WelsDecoderIChromaPredPlane_mmi;
1166     pCtx->pGetIChromaPredFunc[C_PRED_DC]      = WelsDecoderIChromaPredDc_mmi;
1167     pCtx->pGetIChromaPredFunc[C_PRED_DC_T]    = WelsDecoderIChromaPredDcTop_mmi;
1168     pCtx->pGetI4x4LumaPredFunc[I4_PRED_H]     = WelsDecoderI4x4LumaPredH_mmi;
1169   }
1170 #endif//HAVE_MMI
1171 }
1172 
1173 //reset decoder number related statistics info
ResetDecStatNums(SDecoderStatistics * pDecStat)1174 void ResetDecStatNums (SDecoderStatistics* pDecStat) {
1175   uint32_t uiWidth = pDecStat->uiWidth;
1176   uint32_t uiHeight = pDecStat->uiHeight;
1177   int32_t iAvgLumaQp = pDecStat->iAvgLumaQp;
1178   uint32_t iLogInterval = pDecStat->iStatisticsLogInterval;
1179   uint32_t uiProfile = pDecStat->uiProfile;
1180   uint32_t uiLevel = pDecStat->uiLevel;
1181   memset (pDecStat, 0, sizeof (SDecoderStatistics));
1182   pDecStat->uiWidth = uiWidth;
1183   pDecStat->uiHeight = uiHeight;
1184   pDecStat->iAvgLumaQp = iAvgLumaQp;
1185   pDecStat->iStatisticsLogInterval = iLogInterval;
1186   pDecStat->uiProfile = uiProfile;
1187   pDecStat->uiLevel = uiLevel;
1188 }
1189 
1190 //update information when freezing occurs, including IDR/non-IDR number
UpdateDecStatFreezingInfo(const bool kbIdrFlag,SDecoderStatistics * pDecStat)1191 void UpdateDecStatFreezingInfo (const bool kbIdrFlag, SDecoderStatistics* pDecStat) {
1192   if (kbIdrFlag)
1193     pDecStat->uiFreezingIDRNum++;
1194   else
1195     pDecStat->uiFreezingNonIDRNum++;
1196 }
1197 
1198 //update information when no freezing occurs, including QP, correct IDR number, ECed IDR number
UpdateDecStatNoFreezingInfo(PWelsDecoderContext pCtx)1199 void UpdateDecStatNoFreezingInfo (PWelsDecoderContext pCtx) {
1200   PDqLayer pCurDq = pCtx->pCurDqLayer;
1201   PPicture pPic = pCtx->pDec;
1202   SDecoderStatistics* pDecStat = pCtx->pDecoderStatistics;
1203 
1204   if (pDecStat->iAvgLumaQp == -1) //first correct frame received
1205     pDecStat->iAvgLumaQp = 0;
1206 
1207   //update QP info
1208   int32_t iTotalQp = 0;
1209   const int32_t kiMbNum = pCurDq->iMbWidth * pCurDq->iMbHeight;
1210   if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { //all correct
1211     for (int32_t iMb = 0; iMb < kiMbNum; ++iMb) {
1212       iTotalQp += pCurDq->pLumaQp[iMb];
1213     }
1214     iTotalQp /= kiMbNum;
1215   } else {
1216     int32_t iCorrectMbNum = 0;
1217     for (int32_t iMb = 0; iMb < kiMbNum; ++iMb) {
1218       iCorrectMbNum += (int32_t) pCurDq->pMbCorrectlyDecodedFlag[iMb];
1219       iTotalQp += pCurDq->pLumaQp[iMb] * pCurDq->pMbCorrectlyDecodedFlag[iMb];
1220     }
1221     if (iCorrectMbNum == 0) //non MB is correct, should remain QP statistic info
1222       iTotalQp = pDecStat->iAvgLumaQp;
1223     else
1224       iTotalQp /= iCorrectMbNum;
1225   }
1226   if (pDecStat->uiDecodedFrameCount + 1 == 0) { //maximum uint32_t reached
1227     ResetDecStatNums (pDecStat);
1228     pDecStat->iAvgLumaQp = iTotalQp;
1229   } else
1230     pDecStat->iAvgLumaQp = (int) ((uint64_t) (pDecStat->iAvgLumaQp * pDecStat->uiDecodedFrameCount + iTotalQp) /
1231                                   (pDecStat->uiDecodedFrameCount + 1));
1232 
1233   //update IDR number
1234   if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag) {
1235     pDecStat->uiIDRCorrectNum += (pPic->bIsComplete);
1236     if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE)
1237       pDecStat->uiEcIDRNum += (!pPic->bIsComplete);
1238   }
1239 }
1240 
1241 //update decoder statistics information
UpdateDecStat(PWelsDecoderContext pCtx,const bool kbOutput)1242 void UpdateDecStat (PWelsDecoderContext pCtx, const bool kbOutput) {
1243   if (pCtx->bFreezeOutput)
1244     UpdateDecStatFreezingInfo (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag, pCtx->pDecoderStatistics);
1245   else if (kbOutput)
1246     UpdateDecStatNoFreezingInfo (pCtx);
1247 }
1248 
1249 
1250 } // namespace WelsDec
1251