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