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