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 * welsDecoderExt.cpp
33 *
34 * Abstract
35 * Cisco OpenH264 decoder extension utilization
36 *
37 * History
38 * 3/12/2009 Created
39 *
40 *
41 ************************************************************************/
42 //#include <assert.h>
43 #include "welsDecoderExt.h"
44 #include "welsCodecTrace.h"
45 #include "codec_def.h"
46 #include "typedefs.h"
47 #include "memory_align.h"
48 #include "utils.h"
49 #include "version.h"
50
51 //#include "macros.h"
52 #include "decoder.h"
53 #include "decoder_core.h"
54 #include "manage_dec_ref.h"
55 #include "error_concealment.h"
56
57 #include "measure_time.h"
58 extern "C" {
59 #include "decoder_core.h"
60 #include "manage_dec_ref.h"
61 }
62 #include "error_code.h"
63 #include "crt_util_safe_x.h" // Safe CRT routines like util for cross platforms
64 #include <time.h>
65 #if defined(_WIN32) /*&& defined(_DEBUG)*/
66
67 #include <windows.h>
68 #include <stdio.h>
69 #include <stdarg.h>
70 #include <sys/types.h>
71 #include <malloc.h>
72 #else
73 #include <sys/time.h>
74 #endif
75
76 namespace WelsDec {
77
78 //////////////////////////////////////////////////////////////////////
79 // Construction/Destruction
80 //////////////////////////////////////////////////////////////////////
81
82 /***************************************************************************
83 * Description:
84 * class CWelsDecoder constructor function, do initialization and
85 * alloc memory required
86 *
87 * Input parameters: none
88 *
89 * return: none
90 ***************************************************************************/
DECLARE_PROCTHREAD(pThrProcInit,p)91 DECLARE_PROCTHREAD (pThrProcInit, p) {
92 SWelsDecThreadInfo* sThreadInfo = (SWelsDecThreadInfo*)p;
93 #if defined(WIN32)
94 _alloca (WELS_DEC_MAX_THREAD_STACK_SIZE * (sThreadInfo->uiThrNum + 1));
95 #endif
96 return sThreadInfo->pThrProcMain (p);
97 }
98
ConstructAccessUnit(CWelsDecoder * pWelsDecoder,PWelsDecoderThreadCTX pThrCtx)99 static DECODING_STATE ConstructAccessUnit (CWelsDecoder* pWelsDecoder, PWelsDecoderThreadCTX pThrCtx) {
100 int iRet = dsErrorFree;
101 //WelsMutexLock (&pWelsDecoder->m_csDecoder);
102 if (pThrCtx->pCtx->pLastThreadCtx != NULL) {
103 PWelsDecoderThreadCTX pLastThreadCtx = (PWelsDecoderThreadCTX) (pThrCtx->pCtx->pLastThreadCtx);
104 WAIT_EVENT (&pLastThreadCtx->sSliceDecodeStart, WELS_DEC_THREAD_WAIT_INFINITE);
105 RESET_EVENT (&pLastThreadCtx->sSliceDecodeStart);
106 }
107 pThrCtx->pDec = NULL;
108 if (GetThreadCount (pThrCtx->pCtx) > 1) {
109 RESET_EVENT (&pThrCtx->sSliceDecodeFinish);
110 }
111 iRet |= pWelsDecoder->DecodeFrame2WithCtx (pThrCtx->pCtx, NULL, 0, pThrCtx->ppDst, &pThrCtx->sDstInfo);
112
113 //WelsMutexUnlock (&pWelsDecoder->m_csDecoder);
114 return (DECODING_STATE)iRet;
115 }
116
DECLARE_PROCTHREAD(pThrProcFrame,p)117 DECLARE_PROCTHREAD (pThrProcFrame, p) {
118 SWelsDecoderThreadCTX* pThrCtx = (SWelsDecoderThreadCTX*)p;
119 while (1) {
120 RELEASE_SEMAPHORE (pThrCtx->sThreadInfo.sIsBusy);
121 RELEASE_SEMAPHORE (&pThrCtx->sThreadInfo.sIsIdle);
122 WAIT_SEMAPHORE (&pThrCtx->sThreadInfo.sIsActivated, WELS_DEC_THREAD_WAIT_INFINITE);
123 if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_RUN) {
124 CWelsDecoder* pWelsDecoder = (CWelsDecoder*)pThrCtx->threadCtxOwner;
125 ConstructAccessUnit (pWelsDecoder, pThrCtx);
126 } else if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_ABORT) {
127 break;
128 }
129 }
130 return 0;
131 }
132
CWelsDecoder(void)133 CWelsDecoder::CWelsDecoder (void)
134 : m_pWelsTrace (NULL),
135 m_uiDecodeTimeStamp (0),
136 m_bIsBaseline (false),
137 m_iCpuCount (1),
138 m_iThreadCount (0),
139 m_iCtxCount (1),
140 m_pPicBuff (NULL),
141 m_bParamSetsLostFlag (false),
142 m_bFreezeOutput (false),
143 m_DecCtxActiveCount (0),
144 m_pDecThrCtx (NULL),
145 m_pLastDecThrCtx (NULL),
146 m_iLastBufferedIdx (0) {
147 #ifdef OUTPUT_BIT_STREAM
148 char chFileName[1024] = { 0 }; //for .264
149 int iBufUsed = 0;
150 int iBufLeft = 1023;
151 int iCurUsed;
152
153 char chFileNameSize[1024] = { 0 }; //for .len
154 int iBufUsedSize = 0;
155 int iBufLeftSize = 1023;
156 int iCurUsedSize;
157 #endif//OUTPUT_BIT_STREAM
158
159
160 m_pWelsTrace = new welsCodecTrace();
161 if (m_pWelsTrace != NULL) {
162 m_pWelsTrace->SetCodecInstance (this);
163 m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
164
165 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
166 }
167
168 ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
169
170 m_iCpuCount = GetCPUCount();
171 if (m_iCpuCount > WELS_DEC_MAX_NUM_CPU) {
172 m_iCpuCount = WELS_DEC_MAX_NUM_CPU;
173 }
174
175 m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];
176 memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);
177 for (int32_t i = 0; i < WELS_DEC_MAX_NUM_CPU; ++i) {
178 m_pDecThrCtxActive[i] = NULL;
179 }
180 #ifdef OUTPUT_BIT_STREAM
181 SWelsTime sCurTime;
182
183 WelsGetTimeOfDay (&sCurTime);
184
185 iCurUsed = WelsSnprintf (chFileName, iBufLeft, "bs_0x%p_", (void*)this);
186 iCurUsedSize = WelsSnprintf (chFileNameSize, iBufLeftSize, "size_0x%p_", (void*)this);
187
188 iBufUsed += iCurUsed;
189 iBufLeft -= iCurUsed;
190 if (iBufLeft > 0) {
191 iCurUsed = WelsStrftime (&chFileName[iBufUsed], iBufLeft, "%y%m%d%H%M%S", &sCurTime);
192 iBufUsed += iCurUsed;
193 iBufLeft -= iCurUsed;
194 }
195
196 iBufUsedSize += iCurUsedSize;
197 iBufLeftSize -= iCurUsedSize;
198 if (iBufLeftSize > 0) {
199 iCurUsedSize = WelsStrftime (&chFileNameSize[iBufUsedSize], iBufLeftSize, "%y%m%d%H%M%S", &sCurTime);
200 iBufUsedSize += iCurUsedSize;
201 iBufLeftSize -= iCurUsedSize;
202 }
203
204 if (iBufLeft > 0) {
205 iCurUsed = WelsSnprintf (&chFileName[iBufUsed], iBufLeft, ".%03.3u.264", WelsGetMillisecond (&sCurTime));
206 iBufUsed += iCurUsed;
207 iBufLeft -= iCurUsed;
208 }
209
210 if (iBufLeftSize > 0) {
211 iCurUsedSize = WelsSnprintf (&chFileNameSize[iBufUsedSize], iBufLeftSize, ".%03.3u.len",
212 WelsGetMillisecond (&sCurTime));
213 iBufUsedSize += iCurUsedSize;
214 iBufLeftSize -= iCurUsedSize;
215 }
216
217
218 m_pFBS = WelsFopen (chFileName, "wb");
219 m_pFBSSize = WelsFopen (chFileNameSize, "wb");
220 #endif//OUTPUT_BIT_STREAM
221 }
222
223 /***************************************************************************
224 * Description:
225 * class CWelsDecoder destructor function, destroy allocced memory
226 *
227 * Input parameters: none
228 *
229 * return: none
230 ***************************************************************************/
~CWelsDecoder()231 CWelsDecoder::~CWelsDecoder() {
232 if (m_pWelsTrace != NULL) {
233 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
234 }
235 CloseDecoderThreads();
236 UninitDecoder();
237
238 #ifdef OUTPUT_BIT_STREAM
239 if (m_pFBS) {
240 WelsFclose (m_pFBS);
241 m_pFBS = NULL;
242 }
243 if (m_pFBSSize) {
244 WelsFclose (m_pFBSSize);
245 m_pFBSSize = NULL;
246 }
247 #endif//OUTPUT_BIT_STREAM
248
249 if (m_pWelsTrace != NULL) {
250 delete m_pWelsTrace;
251 m_pWelsTrace = NULL;
252 }
253 if (m_pDecThrCtx != NULL) {
254 delete[] m_pDecThrCtx;
255 m_pDecThrCtx = NULL;
256 }
257 }
258
Initialize(const SDecodingParam * pParam)259 long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
260 int iRet = ERR_NONE;
261 if (m_pWelsTrace == NULL) {
262 return cmMallocMemeError;
263 }
264
265 if (pParam == NULL) {
266 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsDecoder::Initialize(), invalid input argument.");
267 return cmInitParaError;
268 }
269
270 // H.264 decoder initialization,including memory allocation,then open it ready to decode
271 iRet = InitDecoder (pParam);
272 if (iRet)
273 return iRet;
274
275 return cmResultSuccess;
276 }
277
Uninitialize()278 long CWelsDecoder::Uninitialize() {
279 UninitDecoder();
280
281 return ERR_NONE;
282 }
283
UninitDecoder(void)284 void CWelsDecoder::UninitDecoder (void) {
285 for (int32_t i = 0; i < m_iCtxCount; ++i) {
286 if (m_pDecThrCtx[i].pCtx != NULL) {
287 if (i > 0) {
288 WelsResetRefPicWithoutUnRef (m_pDecThrCtx[i].pCtx);
289 }
290 UninitDecoderCtx (m_pDecThrCtx[i].pCtx);
291 }
292 }
293 }
294
OpenDecoderThreads()295 void CWelsDecoder::OpenDecoderThreads() {
296 if (m_iThreadCount >= 1) {
297 m_uiDecodeTimeStamp = 0;
298 CREATE_SEMAPHORE (&m_sIsBusy, m_iThreadCount, m_iThreadCount, NULL);
299 WelsMutexInit (&m_csDecoder);
300 CREATE_EVENT (&m_sBufferingEvent, 1, 0, NULL);
301 SET_EVENT (&m_sBufferingEvent);
302 CREATE_EVENT (&m_sReleaseBufferEvent, 1, 0, NULL);
303 SET_EVENT (&m_sReleaseBufferEvent);
304 for (int32_t i = 0; i < m_iThreadCount; ++i) {
305 m_pDecThrCtx[i].sThreadInfo.uiThrMaxNum = m_iThreadCount;
306 m_pDecThrCtx[i].sThreadInfo.uiThrNum = i;
307 m_pDecThrCtx[i].sThreadInfo.uiThrStackSize = WELS_DEC_MAX_THREAD_STACK_SIZE;
308 m_pDecThrCtx[i].sThreadInfo.pThrProcMain = pThrProcFrame;
309 m_pDecThrCtx[i].sThreadInfo.sIsBusy = &m_sIsBusy;
310 m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
311 m_pDecThrCtx[i].threadCtxOwner = this;
312 m_pDecThrCtx[i].kpSrc = NULL;
313 m_pDecThrCtx[i].kiSrcLen = 0;
314 m_pDecThrCtx[i].ppDst = NULL;
315 m_pDecThrCtx[i].pDec = NULL;
316 CREATE_EVENT (&m_pDecThrCtx[i].sImageReady, 1, 0, NULL);
317 CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart, 1, 0, NULL);
318 CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinish, 1, 0, NULL);
319 CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, 0, 1, NULL);
320 CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated, 0, 1, NULL);
321 CREATE_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle, pThrProcInit, (void*) (& (m_pDecThrCtx[i])));
322 }
323 }
324 }
CloseDecoderThreads()325 void CWelsDecoder::CloseDecoderThreads() {
326 if (m_iThreadCount >= 1) {
327 for (int32_t i = 0; i < m_iThreadCount; i++) { //waiting the completion begun slices
328 WAIT_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
329 m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_ABORT;
330 RELEASE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated);
331 WAIT_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle);
332 CLOSE_EVENT (&m_pDecThrCtx[i].sImageReady);
333 CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart);
334 CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinish);
335 CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle);
336 CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated);
337 }
338 WelsMutexDestroy (&m_csDecoder);
339 CLOSE_EVENT (&m_sBufferingEvent);
340 CLOSE_EVENT (&m_sReleaseBufferEvent);
341 CLOSE_SEMAPHORE (&m_sIsBusy);
342 }
343 }
344
UninitDecoderCtx(PWelsDecoderContext & pCtx)345 void CWelsDecoder::UninitDecoderCtx (PWelsDecoderContext& pCtx) {
346 if (pCtx != NULL) {
347
348 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoderCtx(), openh264 codec version = %s.",
349 VERSION_NUMBER);
350
351 WelsEndDecoder (pCtx);
352
353 if (pCtx->pMemAlign != NULL) {
354 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
355 "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..",
356 pCtx->pMemAlign->WelsGetMemoryUsage());
357 delete pCtx->pMemAlign;
358 pCtx->pMemAlign = NULL;
359 }
360
361 if (NULL != pCtx) {
362 WelsFree (pCtx, "m_pDecContext");
363
364 pCtx = NULL;
365 }
366 if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = NULL;
367 }
368 }
369
370 // the return value of this function is not suitable, it need report failure info to upper layer.
InitDecoder(const SDecodingParam * pParam)371 int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {
372
373 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
374 "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
375 VERSION_NUMBER, (int32_t)pParam->bParseOnly);
376 if (m_iThreadCount >= 1 && pParam->bParseOnly) {
377 m_iThreadCount = 0;
378 }
379 OpenDecoderThreads();
380 //reset decoder context
381 memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics));
382 memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo));
383 memset (&m_sVlcTable, 0, sizeof (SVlcTable));
384 UninitDecoder();
385 WelsDecoderLastDecPicInfoDefaults (m_sLastDecPicInfo);
386 for (int32_t i = 0; i < m_iCtxCount; ++i) {
387 InitDecoderCtx (m_pDecThrCtx[i].pCtx, pParam);
388 if (m_iThreadCount >= 1) {
389 m_pDecThrCtx[i].pCtx->pThreadCtx = &m_pDecThrCtx[i];
390 }
391 }
392 m_bParamSetsLostFlag = false;
393 m_bFreezeOutput = false;
394 return cmResultSuccess;
395 }
396
397 // the return value of this function is not suitable, it need report failure info to upper layer.
InitDecoderCtx(PWelsDecoderContext & pCtx,const SDecodingParam * pParam)398 int32_t CWelsDecoder::InitDecoderCtx (PWelsDecoderContext& pCtx, const SDecodingParam* pParam) {
399
400 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
401 "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
402 VERSION_NUMBER, (int32_t)pParam->bParseOnly);
403
404 //reset decoder context
405 UninitDecoderCtx (pCtx);
406 pCtx = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
407 if (NULL == pCtx)
408 return cmMallocMemeError;
409 int32_t iCacheLineSize = 16; // on chip cache line size in byte
410 pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);
411 WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pMemAlign), UninitDecoderCtx (pCtx))
412 if (m_iCtxCount <= 1) m_pDecThrCtx[0].pCtx = pCtx;
413 //fill in default value into context
414 pCtx->pLastDecPicInfo = &m_sLastDecPicInfo;
415 pCtx->pDecoderStatistics = &m_sDecoderStatistics;
416 pCtx->pVlcTable = &m_sVlcTable;
417 pCtx->pPictInfoList = m_sPictInfoList;
418 pCtx->pPictReoderingStatus = &m_sReoderingStatus;
419 pCtx->pCsDecoder = &m_csDecoder;
420 WelsDecoderDefaults (pCtx, &m_pWelsTrace->m_sLogCtx);
421 WelsDecoderSpsPpsDefaults (pCtx->sSpsPpsCtx);
422 //check param and update decoder context
423 pCtx->pParam = (SDecodingParam*)pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
424 "SDecodingParam");
425 WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoderCtx (pCtx));
426 int32_t iRet = DecoderConfigParam (pCtx, pParam);
427 WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);
428
429 //init decoder
430 WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (pCtx, &m_pWelsTrace->m_sLogCtx),
431 UninitDecoderCtx (pCtx))
432 pCtx->pPicBuff = NULL;
433 return cmResultSuccess;
434 }
435
ResetDecoder(PWelsDecoderContext & pCtx)436 int32_t CWelsDecoder::ResetDecoder (PWelsDecoderContext& pCtx) {
437 // TBC: need to be modified when context and trace point are null
438 if (m_iThreadCount >= 1) {
439 ThreadResetDecoder (pCtx);
440 } else {
441 if (pCtx != NULL && m_pWelsTrace != NULL) {
442 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d",
443 pCtx->iErrorCode);
444 SDecodingParam sPrevParam;
445 memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));
446
447 WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoderCtx (pCtx, &sPrevParam),
448 UninitDecoderCtx (pCtx));
449 } else if (m_pWelsTrace != NULL) {
450 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
451 }
452 ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, false);
453 }
454 return ERR_INFO_UNINIT;
455 }
456
ThreadResetDecoder(PWelsDecoderContext & pCtx)457 int32_t CWelsDecoder::ThreadResetDecoder (PWelsDecoderContext& pCtx) {
458 // TBC: need to be modified when context and trace point are null
459 SDecodingParam sPrevParam;
460 if (pCtx != NULL && m_pWelsTrace != NULL) {
461 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", pCtx->iErrorCode);
462 memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam));
463 ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true);
464 CloseDecoderThreads();
465 UninitDecoder();
466 InitDecoder (&sPrevParam);
467 } else if (m_pWelsTrace != NULL) {
468 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null");
469 }
470 return ERR_INFO_UNINIT;
471 }
472
473 /*
474 * Set Option
475 */
SetOption(DECODER_OPTION eOptID,void * pOption)476 long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
477 int iVal = 0;
478 if (eOptID == DECODER_OPTION_NUM_OF_THREADS) {
479 if (pOption != NULL) {
480 int32_t threadCount = * ((int32_t*)pOption);
481 if (threadCount < 0) threadCount = 0;
482 if (threadCount > m_iCpuCount) {
483 threadCount = m_iCpuCount;
484 }
485 if (threadCount > 3) {
486 threadCount = 3;
487 }
488 if (threadCount != m_iThreadCount) {
489 m_iThreadCount = threadCount;
490 if (m_pDecThrCtx != NULL) {
491 delete [] m_pDecThrCtx;
492 m_iCtxCount = m_iThreadCount == 0 ? 1 : m_iThreadCount;
493 m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iCtxCount];
494 memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iCtxCount);
495 }
496 }
497 }
498 return cmResultSuccess;
499 }
500 for (int32_t i = 0; i < m_iCtxCount; ++i) {
501 PWelsDecoderContext pDecContext = m_pDecThrCtx[i].pCtx;
502 if (pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
503 eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
504 return dsInitialOptExpected;
505 if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded
506 if (pOption == NULL)
507 return cmInitParaError;
508
509 iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag
510
511 if (pDecContext == NULL) return dsInitialOptExpected;
512
513 pDecContext->bEndOfStreamFlag = iVal ? true : false;
514
515 return cmResultSuccess;
516 } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status
517 if (pOption == NULL)
518 return cmInitParaError;
519
520 if (pDecContext == NULL) return dsInitialOptExpected;
521
522 iVal = * ((int*)pOption); // int value for error concealment idc
523 iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
524 if ((pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) {
525 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
526 "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal);
527 return cmInitParaError;
528 }
529
530 pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal;
531 InitErrorCon (pDecContext);
532 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
533 "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal);
534
535 return cmResultSuccess;
536 } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
537 if (m_pWelsTrace) {
538 uint32_t level = * ((uint32_t*)pOption);
539 m_pWelsTrace->SetTraceLevel (level);
540 }
541 return cmResultSuccess;
542 } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
543 if (m_pWelsTrace) {
544 WelsTraceCallback callback = * ((WelsTraceCallback*)pOption);
545 m_pWelsTrace->SetTraceCallback (callback);
546 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
547 "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.",
548 callback);
549 }
550 return cmResultSuccess;
551 } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
552 if (m_pWelsTrace) {
553 void* ctx = * ((void**)pOption);
554 m_pWelsTrace->SetTraceCallbackContext (ctx);
555 }
556 return cmResultSuccess;
557 } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
558 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
559 "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
560 return cmInitParaError;
561 } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
562 if (pOption) {
563 if (pDecContext == NULL) return dsInitialOptExpected;
564 pDecContext->pDecoderStatistics->iStatisticsLogInterval = (* ((unsigned int*)pOption));
565 return cmResultSuccess;
566 }
567 } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) {
568 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
569 "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!");
570 return cmInitParaError;
571 }
572 }
573 return cmInitParaError;
574 }
575
576 /*
577 * Get Option
578 */
GetOption(DECODER_OPTION eOptID,void * pOption)579 long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
580 int iVal = 0;
581 if (DECODER_OPTION_NUM_OF_THREADS == eOptID) {
582 * ((int*)pOption) = m_iThreadCount;
583 return cmResultSuccess;
584 }
585 PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
586 if (pDecContext == NULL)
587 return cmInitExpected;
588
589 if (pOption == NULL)
590 return cmInitParaError;
591
592 if (DECODER_OPTION_END_OF_STREAM == eOptID) {
593 iVal = pDecContext->bEndOfStreamFlag;
594 * ((int*)pOption) = iVal;
595 return cmResultSuccess;
596 }
597 #ifdef LONG_TERM_REF
598 else if (DECODER_OPTION_IDR_PIC_ID == eOptID) {
599 iVal = pDecContext->uiCurIdrPicId;
600 * ((int*)pOption) = iVal;
601 return cmResultSuccess;
602 } else if (DECODER_OPTION_FRAME_NUM == eOptID) {
603 iVal = pDecContext->iFrameNum;
604 * ((int*)pOption) = iVal;
605 return cmResultSuccess;
606 } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) {
607 iVal = pDecContext->bCurAuContainLtrMarkSeFlag;
608 * ((int*)pOption) = iVal;
609 return cmResultSuccess;
610 } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) {
611 iVal = pDecContext->iFrameNumOfAuMarkedLtr;
612 * ((int*)pOption) = iVal;
613 return cmResultSuccess;
614 }
615 #endif
616 else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU
617 iVal = pDecContext->iFeedbackVclNalInAu;
618 * ((int*)pOption) = iVal;
619 return cmResultSuccess;
620 } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID
621 iVal = pDecContext->iFeedbackTidInAu;
622 * ((int*)pOption) = iVal;
623 return cmResultSuccess;
624 } else if (DECODER_OPTION_IS_REF_PIC == eOptID) {
625 iVal = pDecContext->iFeedbackNalRefIdc;
626 if (iVal > 0)
627 iVal = 1;
628 * ((int*)pOption) = iVal;
629 return cmResultSuccess;
630 } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) {
631 iVal = (int)pDecContext->pParam->eEcActiveIdc;
632 * ((int*)pOption) = iVal;
633 return cmResultSuccess;
634 } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
635 SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
636
637 memcpy (pDecoderStatistics, pDecContext->pDecoderStatistics, sizeof (SDecoderStatistics));
638
639 if (pDecContext->pDecoderStatistics->uiDecodedFrameCount != 0) { //not original status
640 pDecoderStatistics->fAverageFrameSpeedInMs = (float) (pDecContext->dDecTime) /
641 (pDecContext->pDecoderStatistics->uiDecodedFrameCount);
642 pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (pDecContext->dDecTime) /
643 (pDecContext->pDecoderStatistics->uiDecodedFrameCount + pDecContext->pDecoderStatistics->uiFreezingIDRNum +
644 pDecContext->pDecoderStatistics->uiFreezingNonIDRNum);
645 }
646 return cmResultSuccess;
647 } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) {
648 if (pOption) {
649 iVal = pDecContext->pDecoderStatistics->iStatisticsLogInterval;
650 * ((unsigned int*)pOption) = iVal;
651 return cmResultSuccess;
652 }
653 } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI
654 PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption));
655 memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo));
656 if (!pDecContext->pSps) {
657 return cmInitExpected;
658 } else {
659 pVuiSarInfo->uiSarWidth = pDecContext->pSps->sVui.uiSarWidth;
660 pVuiSarInfo->uiSarHeight = pDecContext->pSps->sVui.uiSarHeight;
661 pVuiSarInfo->bOverscanAppropriateFlag = pDecContext->pSps->sVui.bOverscanAppropriateFlag;
662 return cmResultSuccess;
663 }
664 } else if (DECODER_OPTION_PROFILE == eOptID) {
665 if (!pDecContext->pSps) {
666 return cmInitExpected;
667 }
668 iVal = (int)pDecContext->pSps->uiProfileIdc;
669 * ((int*)pOption) = iVal;
670 return cmResultSuccess;
671 } else if (DECODER_OPTION_LEVEL == eOptID) {
672 if (!pDecContext->pSps) {
673 return cmInitExpected;
674 }
675 iVal = (int)pDecContext->pSps->uiLevelIdc;
676 * ((int*)pOption) = iVal;
677 return cmResultSuccess;
678 } else if (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER == eOptID) {
679 for (int32_t activeThread = 0; activeThread < m_DecCtxActiveCount; ++activeThread) {
680 WAIT_SEMAPHORE (&m_pDecThrCtxActive[activeThread]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
681 RELEASE_SEMAPHORE (&m_pDecThrCtxActive[activeThread]->sThreadInfo.sIsIdle);
682 }
683 * ((int*)pOption) = m_sReoderingStatus.iNumOfPicts;
684 return cmResultSuccess;
685 }
686
687 return cmInitParaError;
688 }
689
DecodeFrameNoDelay(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)690 DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
691 const int kiSrcLen,
692 unsigned char** ppDst,
693 SBufferInfo* pDstInfo) {
694 int iRet = dsErrorFree;
695 if (m_iThreadCount >= 1) {
696 iRet = ThreadDecodeFrameInternal (kpSrc, kiSrcLen, ppDst, pDstInfo);
697 if (m_sReoderingStatus.iNumOfPicts) {
698 WAIT_EVENT (&m_sBufferingEvent, WELS_DEC_THREAD_WAIT_INFINITE);
699 RESET_EVENT (&m_sReleaseBufferEvent);
700 if (!m_sReoderingStatus.bHasBSlice) {
701 if (m_sReoderingStatus.iNumOfPicts > 1) {
702 ReleaseBufferedReadyPictureNoReorder (NULL, ppDst, pDstInfo);
703 }
704 }
705 else {
706 ReleaseBufferedReadyPictureReorder (NULL, ppDst, pDstInfo);
707 }
708 SET_EVENT(&m_sReleaseBufferEvent);
709 }
710 return (DECODING_STATE)iRet;
711 }
712 //SBufferInfo sTmpBufferInfo;
713 //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL};
714 iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
715 //memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
716 //ppTmpDst[0] = ppDst[0];
717 //ppTmpDst[1] = ppDst[1];
718 //ppTmpDst[2] = ppDst[2];
719 iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
720 //if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
721 //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
722 //ppDst[0] = ppTmpDst[0];
723 //ppDst[1] = ppTmpDst[1];
724 //ppDst[2] = ppTmpDst[2];
725 //}
726 return (DECODING_STATE)iRet;
727 }
728
DecodeFrame2WithCtx(PWelsDecoderContext pDecContext,const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)729 DECODING_STATE CWelsDecoder::DecodeFrame2WithCtx (PWelsDecoderContext pDecContext, const unsigned char* kpSrc,
730 const int kiSrcLen,
731 unsigned char** ppDst,
732 SBufferInfo* pDstInfo) {
733 if (pDecContext == NULL || pDecContext->pParam == NULL) {
734 if (m_pWelsTrace != NULL) {
735 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n");
736 }
737 return dsInitialOptExpected;
738 }
739
740 if (pDecContext->pParam->bParseOnly) {
741 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n");
742 pDecContext->iErrorCode |= dsInvalidArgument;
743 return dsInvalidArgument;
744 }
745 if (CheckBsBuffer (pDecContext, kiSrcLen)) {
746 if (ResetDecoder(pDecContext)) {
747 if (pDstInfo) pDstInfo->iBufferStatus = 0;
748 return dsOutOfMemory;
749 }
750 return dsErrorFree;
751 }
752 if (kiSrcLen > 0 && kpSrc != NULL) {
753 #ifdef OUTPUT_BIT_STREAM
754 if (m_pFBS) {
755 WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
756 WelsFflush (m_pFBS);
757 }
758 if (m_pFBSSize) {
759 WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize);
760 WelsFflush (m_pFBSSize);
761 }
762 #endif//OUTPUT_BIT_STREAM
763 pDecContext->bEndOfStreamFlag = false;
764 if (GetThreadCount (pDecContext) <= 0) {
765 pDecContext->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
766 }
767 } else {
768 //For application MODE, the error detection should be added for safe.
769 //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
770 pDecContext->bEndOfStreamFlag = true;
771 pDecContext->bInstantDecFlag = true;
772 }
773
774 int64_t iStart, iEnd;
775 iStart = WelsTime();
776
777 if (GetThreadCount (pDecContext) <= 1) {
778 ppDst[0] = ppDst[1] = ppDst[2] = NULL;
779 }
780 pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
781 pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
782 unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp;
783 if (GetThreadCount (pDecContext) <= 1) {
784 memset (pDstInfo, 0, sizeof (SBufferInfo));
785 }
786 pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp;
787 #ifdef LONG_TERM_REF
788 pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR
789 pDecContext->bCurAuContainLtrMarkSeFlag = false;
790 pDecContext->iFrameNumOfAuMarkedLtr = 0;
791 pDecContext->iFrameNum = -1; //initialize
792 #endif
793
794 pDecContext->iFeedbackTidInAu = -1; //initialize
795 pDecContext->iFeedbackNalRefIdc = -1; //initialize
796 if (pDstInfo) {
797 pDstInfo->uiOutYuvTimeStamp = 0;
798 pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
799 } else {
800 pDecContext->uiTimeStamp = 0;
801 }
802 WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, ppDst,
803 pDstInfo, NULL); //iErrorCode has been modified in this function
804 pDecContext->bInstantDecFlag = false; //reset no-delay flag
805 if (pDecContext->iErrorCode) {
806 EWelsNalUnitType eNalType =
807 NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently
808
809 eNalType = pDecContext->sCurNalHead.eNalUnitType;
810 if (pDecContext->iErrorCode & dsOutOfMemory) {
811 if (ResetDecoder (pDecContext)) {
812 if (pDstInfo) pDstInfo->iBufferStatus = 0;
813 return dsOutOfMemory;
814 }
815 return dsErrorFree;
816 }
817 if (pDecContext->iErrorCode & dsRefListNullPtrs) {
818 if (ResetDecoder (pDecContext)) {
819 if (pDstInfo) pDstInfo->iBufferStatus = 0;
820 return dsRefListNullPtrs;
821 }
822 return dsErrorFree;
823 }
824 //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss.
825 if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) ||
826 (VIDEO_BITSTREAM_AVC == pDecContext->eVideoType)) {
827 if (pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
828 #ifdef LONG_TERM_REF
829 pDecContext->bParamSetsLostFlag = true;
830 #else
831 pDecContext->bReferenceLostAtT0Flag = true;
832 #endif
833 }
834 }
835
836 if (pDecContext->bPrintFrameErrorTraceFlag) {
837 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
838 pDecContext->iErrorCode);
839 pDecContext->bPrintFrameErrorTraceFlag = false;
840 } else {
841 pDecContext->iIgnoredErrorInfoPacketCount++;
842 if (pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) {
843 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0.");
844 pDecContext->iIgnoredErrorInfoPacketCount = 0;
845 }
846 }
847 if ((pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
848 //TODO after dec status updated
849 pDecContext->iErrorCode |= dsDataErrorConcealed;
850
851 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
852 if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
853 ResetDecStatNums (pDecContext->pDecoderStatistics);
854 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
855 }
856 int32_t iMbConcealedNum = pDecContext->iMbEcedNum + pDecContext->iMbEcedPropNum;
857 pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->iMbNum == 0 ?
858 (pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
859 pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
860 iMbConcealedNum * 100) / pDecContext->iMbNum));
861 pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->iMbNum == 0 ?
862 (pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : ((
863 pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + ((
864 pDecContext->iMbEcedPropNum * 100) / pDecContext->iMbNum));
865 pDecContext->pDecoderStatistics->uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1);
866 pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
867 pDecContext->pDecoderStatistics->uiAvgEcRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
868 pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 :
869 pDecContext->pDecoderStatistics->uiAvgEcPropRatio / pDecContext->pDecoderStatistics->uiEcFrameNum;
870 }
871 iEnd = WelsTime();
872 pDecContext->dDecTime += (iEnd - iStart) / 1e3;
873
874 OutputStatisticsLog (*pDecContext->pDecoderStatistics);
875 if (GetThreadCount (pDecContext) >= 1) {
876 WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE);
877 RESET_EVENT (&m_sBufferingEvent);
878 BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
879 SET_EVENT (&m_sBufferingEvent);
880 } else {
881 ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
882 }
883
884 return (DECODING_STATE)pDecContext->iErrorCode;
885 }
886 // else Error free, the current codec works well
887
888 if (pDstInfo->iBufferStatus == 1) {
889
890 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
891 if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
892 ResetDecStatNums (pDecContext->pDecoderStatistics);
893 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
894 }
895
896 OutputStatisticsLog (*pDecContext->pDecoderStatistics);
897 }
898 iEnd = WelsTime();
899 pDecContext->dDecTime += (iEnd - iStart) / 1e3;
900
901 if (GetThreadCount (pDecContext) >= 1) {
902 WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE);
903 RESET_EVENT (&m_sBufferingEvent);
904 BufferingReadyPicture (pDecContext, ppDst, pDstInfo);
905 SET_EVENT (&m_sBufferingEvent);
906 } else {
907 ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo);
908 }
909 return dsErrorFree;
910 }
911
DecodeFrame2(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)912 DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
913 const int kiSrcLen,
914 unsigned char** ppDst,
915 SBufferInfo* pDstInfo) {
916 PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
917 return DecodeFrame2WithCtx (pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo);
918 }
919
FlushFrame(unsigned char ** ppDst,SBufferInfo * pDstInfo)920 DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst,
921 SBufferInfo* pDstInfo) {
922 bool bEndOfStreamFlag = true;
923 if (m_iThreadCount <= 1) {
924 for (int32_t j = 0; j < m_iCtxCount; ++j) {
925 if (!m_pDecThrCtx[j].pCtx->bEndOfStreamFlag) {
926 bEndOfStreamFlag = false;
927 }
928 }
929 }
930 if (bEndOfStreamFlag && m_sReoderingStatus.iNumOfPicts > 0) {
931 if (!m_sReoderingStatus.bHasBSlice) {
932 ReleaseBufferedReadyPictureNoReorder (NULL, ppDst, pDstInfo);
933 }
934 else {
935 ReleaseBufferedReadyPictureReorder (NULL, ppDst, pDstInfo, true);
936 }
937 }
938 return dsErrorFree;
939 }
940
OutputStatisticsLog(SDecoderStatistics & sDecoderStatistics)941 void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) {
942 if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0)
943 && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) {
944 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
945 "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \
946 uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \
947 uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \
948 uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \
949 iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \
950 uiProfile=%d, uiLevel=%d, \
951 iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,",
952 sDecoderStatistics.uiWidth,
953 sDecoderStatistics.uiHeight,
954 sDecoderStatistics.fAverageFrameSpeedInMs,
955 sDecoderStatistics.fActualAverageFrameSpeedInMs,
956
957 sDecoderStatistics.uiDecodedFrameCount,
958 sDecoderStatistics.uiResolutionChangeTimes,
959 sDecoderStatistics.uiIDRCorrectNum,
960
961 sDecoderStatistics.uiAvgEcRatio,
962 sDecoderStatistics.uiAvgEcPropRatio,
963 sDecoderStatistics.uiEcIDRNum,
964 sDecoderStatistics.uiEcFrameNum,
965
966 sDecoderStatistics.uiIDRLostNum,
967 sDecoderStatistics.uiFreezingIDRNum,
968 sDecoderStatistics.uiFreezingNonIDRNum,
969 sDecoderStatistics.iAvgLumaQp,
970
971 sDecoderStatistics.iSpsReportErrorNum,
972 sDecoderStatistics.iSubSpsReportErrorNum,
973 sDecoderStatistics.iPpsReportErrorNum,
974 sDecoderStatistics.iSpsNoExistNalNum,
975 sDecoderStatistics.iSubSpsNoExistNalNum,
976 sDecoderStatistics.iPpsNoExistNalNum,
977
978 sDecoderStatistics.uiProfile,
979 sDecoderStatistics.uiLevel,
980
981 sDecoderStatistics.iCurrentActiveSpsId,
982 sDecoderStatistics.iCurrentActivePpsId);
983 }
984 }
985
BufferingReadyPicture(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo)986 void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst,
987 SBufferInfo* pDstInfo) {
988 if (pDstInfo->iBufferStatus == 0) {
989 return;
990 }
991 m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83;
992 if (!m_bIsBaseline) {
993 if (pCtx->pSliceHeader->eSliceType == B_SLICE) {
994 m_sReoderingStatus.bHasBSlice = true;
995 }
996 if (m_sReoderingStatus.iNumOfPicts && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb
997 && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) {
998 m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts;
999
1000 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1001 if (m_sPictInfoList[i].iPOC > IMinInt32) {
1002 m_sPictInfoList[i].bLastGOP = true;
1003 }
1004 }
1005 } else {
1006 if (m_sReoderingStatus.iNumOfPicts > 0) {
1007 //This can happen when decoder moves to next GOP without being able to decoder first picture PicOrderCntLsb = 0
1008 bool hasGOPChanged = false;
1009 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1010 if (m_sPictInfoList[i].iPOC == pCtx->pSliceHeader->iPicOrderCntLsb) {
1011 hasGOPChanged = true;
1012 break;
1013 }
1014 }
1015 if (hasGOPChanged) {
1016 m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts;
1017 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1018 if (m_sPictInfoList[i].iPOC > IMinInt32) {
1019 m_sPictInfoList[i].bLastGOP = true;
1020 }
1021 }
1022 }
1023 }
1024 }
1025 }
1026 for (int32_t i = 0; i < 16; ++i) {
1027 if (m_sPictInfoList[i].iPOC == IMinInt32) {
1028 memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo));
1029 m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb;
1030 m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp;
1031 if (pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb != NULL) {
1032 m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
1033 if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount;
1034 }
1035 m_sPictInfoList[i].bLastGOP = false;
1036 m_iLastBufferedIdx = i;
1037 pDstInfo->iBufferStatus = 0;
1038 ++m_sReoderingStatus.iNumOfPicts;
1039 if (i > m_sReoderingStatus.iLargestBufferedPicIndex) {
1040 m_sReoderingStatus.iLargestBufferedPicIndex = i;
1041 }
1042 break;
1043 }
1044 }
1045 }
1046
ReleaseBufferedReadyPictureReorder(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo,bool isFlush)1047 void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx, unsigned char** ppDst,
1048 SBufferInfo* pDstInfo, bool isFlush) {
1049 PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1050 if (pCtx == NULL && m_iThreadCount <= 1) {
1051 pCtx = m_pDecThrCtx[0].pCtx;
1052 }
1053 if (m_sReoderingStatus.iLastGOPRemainPicts > 0) {
1054 m_sReoderingStatus.iMinPOC = IMinInt32;
1055 int32_t firstValidIdx = -1;
1056 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1057 if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) {
1058 m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1059 m_sReoderingStatus.iPictInfoIndex = i;
1060 firstValidIdx = i;
1061 break;
1062 }
1063 }
1064 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1065 if (i == firstValidIdx) continue;
1066 if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC
1067 && m_sPictInfoList[i].bLastGOP) {
1068 m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1069 m_sReoderingStatus.iPictInfoIndex = i;
1070 }
1071 }
1072 m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1073 #if defined (_DEBUG)
1074 #ifdef _MOTION_VECTOR_DUMP_
1075 fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1076 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1077 #endif
1078 #endif
1079 memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1080 ppDst[0] = pDstInfo->pDst[0];
1081 ppDst[1] = pDstInfo->pDst[1];
1082 ppDst[2] = pDstInfo->pDst[2];
1083 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1084 if (pPicBuff != NULL) {
1085 PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1086 --pPic->iRefCount;
1087 }
1088 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1089 m_sReoderingStatus.iMinPOC = IMinInt32;
1090 --m_sReoderingStatus.iNumOfPicts;
1091 --m_sReoderingStatus.iLastGOPRemainPicts;
1092 if (m_sReoderingStatus.iLastGOPRemainPicts == 0) {
1093 m_sReoderingStatus.iLastWrittenPOC = IMinInt32;
1094 }
1095 return;
1096 }
1097 if (m_sReoderingStatus.iNumOfPicts > 0) {
1098 m_sReoderingStatus.iMinPOC = IMinInt32;
1099 int32_t firstValidIdx = -1;
1100 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1101 if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
1102 m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1103 m_sReoderingStatus.iPictInfoIndex = i;
1104 firstValidIdx = i;
1105 break;
1106 }
1107 }
1108 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1109 if (i == firstValidIdx) continue;
1110 if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) {
1111 m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1112 m_sReoderingStatus.iPictInfoIndex = i;
1113 }
1114 }
1115 }
1116 if (m_sReoderingStatus.iMinPOC > IMinInt32) {
1117 bool isReady = true;
1118 if (!isFlush) {
1119 int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
1120 isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
1121 && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
1122 || m_sReoderingStatus.iMinPOC < iLastPOC;
1123 }
1124 if (isReady) {
1125 m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1126 #if defined (_DEBUG)
1127 #ifdef _MOTION_VECTOR_DUMP_
1128 fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1129 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1130 #endif
1131 #endif
1132 memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1133 ppDst[0] = pDstInfo->pDst[0];
1134 ppDst[1] = pDstInfo->pDst[1];
1135 ppDst[2] = pDstInfo->pDst[2];
1136 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1137 int32_t iPicBuffIdx = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx;
1138 if (pPicBuff != NULL) {
1139 if (iPicBuffIdx > 0 && iPicBuffIdx < pPicBuff->iCapacity)
1140 {
1141 PPicture pPic = pPicBuff->ppPic[iPicBuffIdx];
1142 --pPic->iRefCount;
1143 }
1144 }
1145 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1146 m_sReoderingStatus.iMinPOC = IMinInt32;
1147 --m_sReoderingStatus.iNumOfPicts;
1148 }
1149 }
1150 }
1151
1152 //if there is no b-frame, no ordering based on values of POCs is necessary.
1153 //The function is added to force to avoid picture reordering because some h.264 streams do not follow H.264 POC specifications.
ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo)1154 void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo)
1155 {
1156 int32_t firstValidIdx = -1;
1157 uint32_t uiDecodingTimeStamp = 0;
1158 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1159 if (m_sPictInfoList[i].iPOC != IMinInt32) {
1160 uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1161 m_sReoderingStatus.iPictInfoIndex = i;
1162 firstValidIdx = i;
1163 break;
1164 }
1165 }
1166 for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1167 if (i == firstValidIdx) continue;
1168 if (m_sPictInfoList[i].iPOC != IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
1169 uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1170 m_sReoderingStatus.iPictInfoIndex = i;
1171 }
1172 }
1173 if (uiDecodingTimeStamp > 0) {
1174 #if defined (_DEBUG)
1175 #ifdef _MOTION_VECTOR_DUMP_
1176 fprintf(stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC,
1177 uiDecodingTimeStamp);
1178 #endif
1179 #endif
1180 m_sReoderingStatus.iLastWrittenPOC = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC;
1181 memcpy(pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof(SBufferInfo));
1182 ppDst[0] = pDstInfo->pDst[0];
1183 ppDst[1] = pDstInfo->pDst[1];
1184 ppDst[2] = pDstInfo->pDst[2];
1185 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1186 if (pCtx || m_pPicBuff) {
1187 PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1188 PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1189 --pPic->iRefCount;
1190 }
1191 if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP) {
1192 --m_sReoderingStatus.iLastGOPRemainPicts;
1193 m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1194 }
1195 --m_sReoderingStatus.iNumOfPicts;
1196 }
1197 return;
1198 }
1199
ReorderPicturesInDisplay(PWelsDecoderContext pDecContext,unsigned char ** ppDst,SBufferInfo * pDstInfo)1200 DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay(PWelsDecoderContext pDecContext, unsigned char** ppDst,
1201 SBufferInfo* pDstInfo) {
1202 DECODING_STATE iRet = dsErrorFree;
1203 if (pDecContext->pSps != NULL) {
1204 m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
1205 if (!m_bIsBaseline) {
1206 if (pDstInfo->iBufferStatus == 1) {
1207 if (m_sReoderingStatus.iLastGOPRemainPicts == 0 && pDecContext->pSliceHeader->eSliceType == B_SLICE &&
1208 pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) {
1209 //issue #3478, use b-slice type to determine correct picture order as the first priority as POC order is not as reliable as based on b-slice
1210 ppDst[0] = pDstInfo->pDst[0];
1211 ppDst[1] = pDstInfo->pDst[1];
1212 ppDst[2] = pDstInfo->pDst[2];
1213 #if defined (_DEBUG)
1214 #ifdef _MOTION_VECTOR_DUMP_
1215 fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", pDecContext->pSliceHeader->iPicOrderCntLsb,
1216 pDecContext->uiDecodingTimeStamp);
1217 #endif
1218 #endif
1219 return iRet;
1220 }
1221 BufferingReadyPicture(pDecContext, ppDst, pDstInfo);
1222 if (!m_sReoderingStatus.bHasBSlice && m_sReoderingStatus.iNumOfPicts > 1) {
1223 ReleaseBufferedReadyPictureNoReorder (pDecContext, ppDst, pDstInfo);
1224 }
1225 else {
1226 ReleaseBufferedReadyPictureReorder (pDecContext, ppDst, pDstInfo);
1227 }
1228 }
1229 }
1230 }
1231 return iRet;
1232 }
1233
DecodeParser(const unsigned char * kpSrc,const int kiSrcLen,SParserBsInfo * pDstInfo)1234 DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1235 PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1236
1237 if (pDecContext == NULL || pDecContext->pParam == NULL) {
1238 if (m_pWelsTrace != NULL) {
1239 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1240 }
1241 return dsInitialOptExpected;
1242 }
1243
1244 if (!pDecContext->pParam->bParseOnly) {
1245 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1246 pDecContext->iErrorCode |= dsInvalidArgument;
1247 return dsInvalidArgument;
1248 }
1249 int64_t iEnd, iStart = WelsTime();
1250 if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1251 if (ResetDecoder (pDecContext))
1252 return dsOutOfMemory;
1253
1254 return dsErrorFree;
1255 }
1256 if (kiSrcLen > 0 && kpSrc != NULL) {
1257 #ifdef OUTPUT_BITSTREAM
1258 if (m_pFBS) {
1259 WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
1260 WelsFflush (m_pFBS);
1261 }
1262 #endif//OUTPUT_BIT_STREAM
1263 pDecContext->bEndOfStreamFlag = false;
1264 } else {
1265 //For application MODE, the error detection should be added for safe.
1266 //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
1267 pDecContext->bEndOfStreamFlag = true;
1268 pDecContext->bInstantDecFlag = true;
1269 }
1270
1271 pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1272 pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1273 pDecContext->iFeedbackNalRefIdc = -1; //initialize
1274 if (!pDecContext->bFramePending) { //frame complete
1275 pDecContext->pParserBsInfo->iNalNum = 0;
1276 memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1277 }
1278 pDstInfo->iNalNum = 0;
1279 pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1280 if (pDstInfo) {
1281 pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1282 pDstInfo->uiOutBsTimeStamp = 0;
1283 } else {
1284 pDecContext->uiTimeStamp = 0;
1285 }
1286 WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1287 if (pDecContext->iErrorCode & dsOutOfMemory) {
1288 if (ResetDecoder (pDecContext))
1289 return dsOutOfMemory;
1290 return dsErrorFree;
1291 }
1292
1293 if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1294 memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1295
1296 if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1297 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1298 if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1299 ResetDecStatNums (pDecContext->pDecoderStatistics);
1300 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1301 }
1302 }
1303 }
1304
1305 pDecContext->bInstantDecFlag = false; //reset no-delay flag
1306
1307 if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1308 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1309 pDecContext->bPrintFrameErrorTraceFlag = false;
1310 }
1311 iEnd = WelsTime();
1312 pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1313 return (DECODING_STATE)pDecContext->iErrorCode;
1314 }
1315
DecodeFrame(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,int * pStride,int & iWidth,int & iHeight)1316 DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1317 const int kiSrcLen,
1318 unsigned char** ppDst,
1319 int* pStride,
1320 int& iWidth,
1321 int& iHeight) {
1322 DECODING_STATE eDecState = dsErrorFree;
1323 SBufferInfo DstInfo;
1324
1325 memset (&DstInfo, 0, sizeof (SBufferInfo));
1326 DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1327 DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1328 DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1329 DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1330
1331 eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1332 if (eDecState == dsErrorFree) {
1333 pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1334 pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1335 iWidth = DstInfo.UsrData.sSystemBuffer.iWidth;
1336 iHeight = DstInfo.UsrData.sSystemBuffer.iHeight;
1337 }
1338
1339 return eDecState;
1340 }
1341
DecodeFrameEx(const unsigned char * kpSrc,const int kiSrcLen,unsigned char * pDst,int iDstStride,int & iDstLen,int & iWidth,int & iHeight,int & iColorFormat)1342 DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
1343 const int kiSrcLen,
1344 unsigned char* pDst,
1345 int iDstStride,
1346 int& iDstLen,
1347 int& iWidth,
1348 int& iHeight,
1349 int& iColorFormat) {
1350 DECODING_STATE state = dsErrorFree;
1351
1352 return state;
1353 }
1354
ParseAccessUnit(SWelsDecoderThreadCTX & sThreadCtx)1355 DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1356 sThreadCtx.pCtx->bHasNewSps = false;
1357 sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1358 sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1359 sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1360 bool bPicBuffChanged = false;
1361 if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1362 CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1363 sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1364 if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1365 bPicBuffChanged = true;
1366 sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1367 sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1368 sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1369 sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1370 }
1371 }
1372
1373 //if threadCount > 1, then each thread must contain exact one complete frame.
1374 if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1375 sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0;
1376 sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0;
1377 }
1378
1379 int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1380 &sThreadCtx.sDstInfo);
1381
1382 int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1383 if (ERR_NONE != iErr) {
1384 return (DECODING_STATE) (iRet | iErr);
1385 }
1386 if (sThreadCtx.pCtx->bNewSeqBegin) {
1387 m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1388 } else if (bPicBuffChanged) {
1389 InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1390 }
1391 if (!sThreadCtx.pCtx->bNewSeqBegin && m_pLastDecThrCtx != NULL) {
1392 sThreadCtx.pCtx->sFrameCrop = m_pLastDecThrCtx->pCtx->pSps->sFrameCrop;
1393 }
1394 m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1395 m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1396 return (DECODING_STATE)iErr;
1397 }
1398 /*
1399 * Run decoding picture in separate thread.
1400 */
1401
ThreadDecodeFrameInternal(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)1402 int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1403 SBufferInfo* pDstInfo) {
1404 int state = dsErrorFree;
1405 int32_t i, j;
1406 int32_t signal = 0;
1407
1408 //serial using of threads
1409 if (m_DecCtxActiveCount < m_iThreadCount) {
1410 signal = m_DecCtxActiveCount;
1411 } else {
1412 signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1413 }
1414
1415 WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1416
1417 for (i = 0; i < m_DecCtxActiveCount; ++i) {
1418 if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1419 m_pDecThrCtxActive[i] = NULL;
1420 for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1421 m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1422 m_pDecThrCtxActive[j + 1] = NULL;
1423 }
1424 --m_DecCtxActiveCount;
1425 break;
1426 }
1427 }
1428
1429 m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1430 if (m_pLastDecThrCtx != NULL) {
1431 m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1432 }
1433 m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1434 m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1435 m_pDecThrCtx[signal].ppDst = ppDst;
1436 memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1437
1438 ParseAccessUnit (m_pDecThrCtx[signal]);
1439 if (m_iThreadCount > 1) {
1440 m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1441 }
1442 m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1443 RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1444
1445 // wait early picture
1446 if (m_DecCtxActiveCount >= m_iThreadCount) {
1447 WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1448 RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1449 }
1450 return state;
1451 }
1452
1453 } // namespace WelsDec
1454
1455
1456 using namespace WelsDec;
1457 /*
1458 * WelsGetDecoderCapability
1459 * @return: DecCapability information
1460 */
WelsGetDecoderCapability(SDecoderCapability * pDecCapability)1461 int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1462 memset (pDecCapability, 0, sizeof (SDecoderCapability));
1463 pDecCapability->iProfileIdc = 66; //Baseline
1464 pDecCapability->iProfileIop = 0xE0; //11100000b
1465 pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1466 pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1467 pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1468 pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1469 pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1470 pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1471 pDecCapability->bRedPicCap = 0; //not support redundant pic
1472
1473 return ERR_NONE;
1474 }
1475 /* WINAPI is indeed in prefix due to sync to application layer callings!! */
1476
1477 /*
1478 * WelsCreateDecoder
1479 * @return: success in return 0, otherwise failed.
1480 */
WelsCreateDecoder(ISVCDecoder ** ppDecoder)1481 long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1482
1483 if (NULL == ppDecoder) {
1484 return ERR_INVALID_PARAMETERS;
1485 }
1486
1487 *ppDecoder = new CWelsDecoder();
1488
1489 if (NULL == *ppDecoder) {
1490 return ERR_MALLOC_FAILED;
1491 }
1492
1493 return ERR_NONE;
1494 }
1495
1496 /*
1497 * WelsDestroyDecoder
1498 */
WelsDestroyDecoder(ISVCDecoder * pDecoder)1499 void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1500 if (NULL != pDecoder) {
1501 delete (CWelsDecoder*)pDecoder;
1502 }
1503 }
1504