• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  2009-2013, Cisco Systems
4  *     All rights reserved.
5  *
6  *     Redistribution and use in source and binary forms, with or without
7  *     modification, are permitted provided that the following conditions
8  *     are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *
13  *        * Redistributions in binary form must reproduce the above copyright
14  *          notice, this list of conditions and the following disclaimer in
15  *          the documentation and/or other materials provided with the
16  *          distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *     POSSIBILITY OF SUCH DAMAGE.
30  *
31  *
32  *  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       m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx;
1032       if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount;
1033       m_sPictInfoList[i].bLastGOP = false;
1034       m_iLastBufferedIdx = i;
1035       pDstInfo->iBufferStatus = 0;
1036       ++m_sReoderingStatus.iNumOfPicts;
1037       if (i > m_sReoderingStatus.iLargestBufferedPicIndex) {
1038         m_sReoderingStatus.iLargestBufferedPicIndex = i;
1039       }
1040       break;
1041     }
1042   }
1043 }
1044 
ReleaseBufferedReadyPictureReorder(PWelsDecoderContext pCtx,unsigned char ** ppDst,SBufferInfo * pDstInfo,bool isFlush)1045 void CWelsDecoder::ReleaseBufferedReadyPictureReorder (PWelsDecoderContext pCtx, unsigned char** ppDst,
1046     SBufferInfo* pDstInfo, bool isFlush) {
1047   PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1048   if (pCtx == NULL && m_iThreadCount <= 1) {
1049     pCtx = m_pDecThrCtx[0].pCtx;
1050   }
1051   if (m_sReoderingStatus.iLastGOPRemainPicts > 0) {
1052     m_sReoderingStatus.iMinPOC = IMinInt32;
1053     int32_t firstValidIdx = -1;
1054     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1055       if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) {
1056         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1057         m_sReoderingStatus.iPictInfoIndex = i;
1058         firstValidIdx = i;
1059         break;
1060       }
1061     }
1062     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1063       if (i == firstValidIdx) continue;
1064       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC
1065           && m_sPictInfoList[i].bLastGOP) {
1066         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1067         m_sReoderingStatus.iPictInfoIndex = i;
1068       }
1069     }
1070     m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1071 #if defined (_DEBUG)
1072 #ifdef _MOTION_VECTOR_DUMP_
1073     fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1074              m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1075 #endif
1076 #endif
1077     memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1078     ppDst[0] = pDstInfo->pDst[0];
1079     ppDst[1] = pDstInfo->pDst[1];
1080     ppDst[2] = pDstInfo->pDst[2];
1081     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1082     if (pPicBuff != NULL) {
1083       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1084       --pPic->iRefCount;
1085     }
1086     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1087     m_sReoderingStatus.iMinPOC = IMinInt32;
1088     --m_sReoderingStatus.iNumOfPicts;
1089     --m_sReoderingStatus.iLastGOPRemainPicts;
1090     if (m_sReoderingStatus.iLastGOPRemainPicts == 0) {
1091       m_sReoderingStatus.iLastWrittenPOC = IMinInt32;
1092     }
1093     return;
1094   }
1095   if (m_sReoderingStatus.iNumOfPicts > 0) {
1096     m_sReoderingStatus.iMinPOC = IMinInt32;
1097     int32_t firstValidIdx = -1;
1098     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1099       if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) {
1100         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1101         m_sReoderingStatus.iPictInfoIndex = i;
1102         firstValidIdx = i;
1103         break;
1104       }
1105     }
1106     for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1107       if (i == firstValidIdx) continue;
1108       if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) {
1109         m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC;
1110         m_sReoderingStatus.iPictInfoIndex = i;
1111       }
1112     }
1113   }
1114   if (m_sReoderingStatus.iMinPOC > IMinInt32) {
1115     bool isReady = true;
1116     if (!isFlush) {
1117       int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC;
1118       isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32
1119         && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1)
1120         || m_sReoderingStatus.iMinPOC < iLastPOC;
1121     }
1122     if (isReady) {
1123       m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;
1124 #if defined (_DEBUG)
1125 #ifdef _MOTION_VECTOR_DUMP_
1126       fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC,
1127                m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);
1128 #endif
1129 #endif
1130       memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo));
1131       ppDst[0] = pDstInfo->pDst[0];
1132       ppDst[1] = pDstInfo->pDst[1];
1133       ppDst[2] = pDstInfo->pDst[2];
1134       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1135       if (pPicBuff != NULL) {
1136         PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1137         --pPic->iRefCount;
1138       }
1139       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1140       m_sReoderingStatus.iMinPOC = IMinInt32;
1141       --m_sReoderingStatus.iNumOfPicts;
1142     }
1143   }
1144 }
1145 
1146 //if there is no b-frame, no ordering based on values of POCs is necessary.
1147 //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)1148 void CWelsDecoder::ReleaseBufferedReadyPictureNoReorder(PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo)
1149 {
1150   int32_t firstValidIdx = -1;
1151   uint32_t uiDecodingTimeStamp = 0;
1152   for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1153     if (m_sPictInfoList[i].iPOC != IMinInt32) {
1154       uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1155       m_sReoderingStatus.iPictInfoIndex = i;
1156       firstValidIdx = i;
1157       break;
1158     }
1159   }
1160   for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) {
1161     if (i == firstValidIdx) continue;
1162     if (m_sPictInfoList[i].iPOC != IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) {
1163       uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp;
1164       m_sReoderingStatus.iPictInfoIndex = i;
1165     }
1166   }
1167   if (uiDecodingTimeStamp > 0) {
1168 #if defined (_DEBUG)
1169 #ifdef _MOTION_VECTOR_DUMP_
1170     fprintf(stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC,
1171       uiDecodingTimeStamp);
1172 #endif
1173 #endif
1174     m_sReoderingStatus.iLastWrittenPOC = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC;
1175     memcpy(pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof(SBufferInfo));
1176     ppDst[0] = pDstInfo->pDst[0];
1177     ppDst[1] = pDstInfo->pDst[1];
1178     ppDst[2] = pDstInfo->pDst[2];
1179     m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32;
1180     if (pCtx || m_pPicBuff) {
1181       PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff;
1182       PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx];
1183       --pPic->iRefCount;
1184     }
1185     if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP) {
1186       --m_sReoderingStatus.iLastGOPRemainPicts;
1187       m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false;
1188     }
1189     --m_sReoderingStatus.iNumOfPicts;
1190   }
1191   return;
1192 }
1193 
ReorderPicturesInDisplay(PWelsDecoderContext pDecContext,unsigned char ** ppDst,SBufferInfo * pDstInfo)1194 DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay(PWelsDecoderContext pDecContext, unsigned char** ppDst,
1195   SBufferInfo* pDstInfo) {
1196   DECODING_STATE iRet = dsErrorFree;
1197   if (pDecContext->pSps != NULL) {
1198     m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83;
1199     if (!m_bIsBaseline) {
1200       if (pDstInfo->iBufferStatus == 1) {
1201         BufferingReadyPicture(pDecContext, ppDst, pDstInfo);
1202         if (!m_sReoderingStatus.bHasBSlice && m_sReoderingStatus.iNumOfPicts > 1) {
1203           ReleaseBufferedReadyPictureNoReorder (pDecContext, ppDst, pDstInfo);
1204         }
1205         else {
1206           ReleaseBufferedReadyPictureReorder (pDecContext, ppDst, pDstInfo);
1207         }
1208       }
1209     }
1210   }
1211   return iRet;
1212 }
1213 
DecodeParser(const unsigned char * kpSrc,const int kiSrcLen,SParserBsInfo * pDstInfo)1214 DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1215   PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1216 
1217   if (pDecContext == NULL || pDecContext->pParam == NULL) {
1218     if (m_pWelsTrace != NULL) {
1219       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1220     }
1221     return dsInitialOptExpected;
1222   }
1223 
1224   if (!pDecContext->pParam->bParseOnly) {
1225     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1226     pDecContext->iErrorCode |= dsInvalidArgument;
1227     return dsInvalidArgument;
1228   }
1229   int64_t iEnd, iStart = WelsTime();
1230   if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1231     if (ResetDecoder (pDecContext))
1232       return dsOutOfMemory;
1233 
1234     return dsErrorFree;
1235   }
1236   if (kiSrcLen > 0 && kpSrc != NULL) {
1237 #ifdef OUTPUT_BITSTREAM
1238     if (m_pFBS) {
1239       WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
1240       WelsFflush (m_pFBS);
1241     }
1242 #endif//OUTPUT_BIT_STREAM
1243     pDecContext->bEndOfStreamFlag = false;
1244   } else {
1245     //For application MODE, the error detection should be added for safe.
1246     //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
1247     pDecContext->bEndOfStreamFlag = true;
1248     pDecContext->bInstantDecFlag = true;
1249   }
1250 
1251   pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1252   pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1253   pDecContext->iFeedbackNalRefIdc = -1; //initialize
1254   if (!pDecContext->bFramePending) { //frame complete
1255     pDecContext->pParserBsInfo->iNalNum = 0;
1256     memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1257   }
1258   pDstInfo->iNalNum = 0;
1259   pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1260   if (pDstInfo) {
1261     pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1262     pDstInfo->uiOutBsTimeStamp = 0;
1263   } else {
1264     pDecContext->uiTimeStamp = 0;
1265   }
1266   WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1267   if (pDecContext->iErrorCode & dsOutOfMemory) {
1268     if (ResetDecoder (pDecContext))
1269       return dsOutOfMemory;
1270     return dsErrorFree;
1271   }
1272 
1273   if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1274     memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1275 
1276     if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1277       pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1278       if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1279         ResetDecStatNums (pDecContext->pDecoderStatistics);
1280         pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1281       }
1282     }
1283   }
1284 
1285   pDecContext->bInstantDecFlag = false; //reset no-delay flag
1286 
1287   if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1288     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1289     pDecContext->bPrintFrameErrorTraceFlag = false;
1290   }
1291   iEnd = WelsTime();
1292   pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1293   return (DECODING_STATE)pDecContext->iErrorCode;
1294 }
1295 
DecodeFrame(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,int * pStride,int & iWidth,int & iHeight)1296 DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1297     const int kiSrcLen,
1298     unsigned char** ppDst,
1299     int* pStride,
1300     int& iWidth,
1301     int& iHeight) {
1302   DECODING_STATE eDecState = dsErrorFree;
1303   SBufferInfo    DstInfo;
1304 
1305   memset (&DstInfo, 0, sizeof (SBufferInfo));
1306   DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1307   DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1308   DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1309   DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1310 
1311   eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1312   if (eDecState == dsErrorFree) {
1313     pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1314     pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1315     iWidth     = DstInfo.UsrData.sSystemBuffer.iWidth;
1316     iHeight    = DstInfo.UsrData.sSystemBuffer.iHeight;
1317   }
1318 
1319   return eDecState;
1320 }
1321 
DecodeFrameEx(const unsigned char * kpSrc,const int kiSrcLen,unsigned char * pDst,int iDstStride,int & iDstLen,int & iWidth,int & iHeight,int & iColorFormat)1322 DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
1323     const int kiSrcLen,
1324     unsigned char* pDst,
1325     int iDstStride,
1326     int& iDstLen,
1327     int& iWidth,
1328     int& iHeight,
1329     int& iColorFormat) {
1330   DECODING_STATE state = dsErrorFree;
1331 
1332   return state;
1333 }
1334 
ParseAccessUnit(SWelsDecoderThreadCTX & sThreadCtx)1335 DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1336   sThreadCtx.pCtx->bHasNewSps = false;
1337   sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1338   sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1339   sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1340   bool bPicBuffChanged = false;
1341   if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1342     CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1343     sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1344     if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1345       bPicBuffChanged = true;
1346       sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1347       sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1348       sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1349       sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1350     }
1351   }
1352 
1353   //if threadCount > 1, then each thread must contain exact one complete frame.
1354   if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1355     sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0;
1356     sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0;
1357   }
1358 
1359   int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1360                                       &sThreadCtx.sDstInfo);
1361 
1362   int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1363   if (ERR_NONE != iErr) {
1364     return (DECODING_STATE) (iRet | iErr);
1365   }
1366   if (sThreadCtx.pCtx->bNewSeqBegin) {
1367     m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1368   } else if (bPicBuffChanged) {
1369     InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1370   }
1371   if (!sThreadCtx.pCtx->bNewSeqBegin && m_pLastDecThrCtx != NULL) {
1372     sThreadCtx.pCtx->sFrameCrop = m_pLastDecThrCtx->pCtx->pSps->sFrameCrop;
1373   }
1374   m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1375   m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1376   return (DECODING_STATE)iErr;
1377 }
1378 /*
1379 * Run decoding picture in separate thread.
1380 */
1381 
ThreadDecodeFrameInternal(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)1382 int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1383     SBufferInfo* pDstInfo) {
1384   int state = dsErrorFree;
1385   int32_t i, j;
1386   int32_t signal = 0;
1387 
1388   //serial using of threads
1389   if (m_DecCtxActiveCount < m_iThreadCount) {
1390     signal = m_DecCtxActiveCount;
1391   } else {
1392     signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1393   }
1394 
1395   WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1396 
1397   for (i = 0; i < m_DecCtxActiveCount; ++i) {
1398     if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1399       m_pDecThrCtxActive[i] = NULL;
1400       for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1401         m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1402         m_pDecThrCtxActive[j + 1] = NULL;
1403       }
1404       --m_DecCtxActiveCount;
1405       break;
1406     }
1407   }
1408 
1409   m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1410   if (m_pLastDecThrCtx != NULL) {
1411     m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1412   }
1413   m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1414   m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1415   m_pDecThrCtx[signal].ppDst = ppDst;
1416   memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1417 
1418   ParseAccessUnit (m_pDecThrCtx[signal]);
1419   if (m_iThreadCount > 1) {
1420     m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1421   }
1422   m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1423   RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1424 
1425   // wait early picture
1426   if (m_DecCtxActiveCount >= m_iThreadCount) {
1427     WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1428     RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1429   }
1430   return state;
1431 }
1432 
1433 } // namespace WelsDec
1434 
1435 
1436 using namespace WelsDec;
1437 /*
1438 *       WelsGetDecoderCapability
1439 *       @return: DecCapability information
1440 */
WelsGetDecoderCapability(SDecoderCapability * pDecCapability)1441 int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1442   memset (pDecCapability, 0, sizeof (SDecoderCapability));
1443   pDecCapability->iProfileIdc = 66; //Baseline
1444   pDecCapability->iProfileIop = 0xE0; //11100000b
1445   pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1446   pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1447   pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1448   pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1449   pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1450   pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1451   pDecCapability->bRedPicCap = 0; //not support redundant pic
1452 
1453   return ERR_NONE;
1454 }
1455 /* WINAPI is indeed in prefix due to sync to application layer callings!! */
1456 
1457 /*
1458 *   WelsCreateDecoder
1459 *   @return:    success in return 0, otherwise failed.
1460 */
WelsCreateDecoder(ISVCDecoder ** ppDecoder)1461 long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1462 
1463   if (NULL == ppDecoder) {
1464     return ERR_INVALID_PARAMETERS;
1465   }
1466 
1467   *ppDecoder = new CWelsDecoder();
1468 
1469   if (NULL == *ppDecoder) {
1470     return ERR_MALLOC_FAILED;
1471   }
1472 
1473   return ERR_NONE;
1474 }
1475 
1476 /*
1477 *   WelsDestroyDecoder
1478 */
WelsDestroyDecoder(ISVCDecoder * pDecoder)1479 void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1480   if (NULL != pDecoder) {
1481     delete (CWelsDecoder*)pDecoder;
1482   }
1483 }
1484