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 if (m_sReoderingStatus.iLastGOPRemainPicts == 0 && pDecContext->pSliceHeader->eSliceType == B_SLICE &&
1202 pDecContext->pSliceHeader->iPicOrderCntLsb <= m_sReoderingStatus.iLastWrittenPOC + 2) {
1203 //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
1204 ppDst[0] = pDstInfo->pDst[0];
1205 ppDst[1] = pDstInfo->pDst[1];
1206 ppDst[2] = pDstInfo->pDst[2];
1207 #if defined (_DEBUG)
1208 #ifdef _MOTION_VECTOR_DUMP_
1209 fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", pDecContext->pSliceHeader->iPicOrderCntLsb,
1210 pDecContext->uiDecodingTimeStamp);
1211 #endif
1212 #endif
1213 return iRet;
1214 }
1215 BufferingReadyPicture(pDecContext, ppDst, pDstInfo);
1216 if (!m_sReoderingStatus.bHasBSlice && m_sReoderingStatus.iNumOfPicts > 1) {
1217 ReleaseBufferedReadyPictureNoReorder (pDecContext, ppDst, pDstInfo);
1218 }
1219 else {
1220 ReleaseBufferedReadyPictureReorder (pDecContext, ppDst, pDstInfo);
1221 }
1222 }
1223 }
1224 }
1225 return iRet;
1226 }
1227
DecodeParser(const unsigned char * kpSrc,const int kiSrcLen,SParserBsInfo * pDstInfo)1228 DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) {
1229 PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx;
1230
1231 if (pDecContext == NULL || pDecContext->pParam == NULL) {
1232 if (m_pWelsTrace != NULL) {
1233 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n");
1234 }
1235 return dsInitialOptExpected;
1236 }
1237
1238 if (!pDecContext->pParam->bParseOnly) {
1239 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n");
1240 pDecContext->iErrorCode |= dsInvalidArgument;
1241 return dsInvalidArgument;
1242 }
1243 int64_t iEnd, iStart = WelsTime();
1244 if (CheckBsBuffer (pDecContext, kiSrcLen)) {
1245 if (ResetDecoder (pDecContext))
1246 return dsOutOfMemory;
1247
1248 return dsErrorFree;
1249 }
1250 if (kiSrcLen > 0 && kpSrc != NULL) {
1251 #ifdef OUTPUT_BITSTREAM
1252 if (m_pFBS) {
1253 WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
1254 WelsFflush (m_pFBS);
1255 }
1256 #endif//OUTPUT_BIT_STREAM
1257 pDecContext->bEndOfStreamFlag = false;
1258 } else {
1259 //For application MODE, the error detection should be added for safe.
1260 //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
1261 pDecContext->bEndOfStreamFlag = true;
1262 pDecContext->bInstantDecFlag = true;
1263 }
1264
1265 pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
1266 pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here.
1267 pDecContext->iFeedbackNalRefIdc = -1; //initialize
1268 if (!pDecContext->bFramePending) { //frame complete
1269 pDecContext->pParserBsInfo->iNalNum = 0;
1270 memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
1271 }
1272 pDstInfo->iNalNum = 0;
1273 pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
1274 if (pDstInfo) {
1275 pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
1276 pDstInfo->uiOutBsTimeStamp = 0;
1277 } else {
1278 pDecContext->uiTimeStamp = 0;
1279 }
1280 WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
1281 if (pDecContext->iErrorCode & dsOutOfMemory) {
1282 if (ResetDecoder (pDecContext))
1283 return dsOutOfMemory;
1284 return dsErrorFree;
1285 }
1286
1287 if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) {
1288 memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
1289
1290 if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count
1291 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1292 if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t
1293 ResetDecStatNums (pDecContext->pDecoderStatistics);
1294 pDecContext->pDecoderStatistics->uiDecodedFrameCount++;
1295 }
1296 }
1297 }
1298
1299 pDecContext->bInstantDecFlag = false; //reset no-delay flag
1300
1301 if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) {
1302 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode);
1303 pDecContext->bPrintFrameErrorTraceFlag = false;
1304 }
1305 iEnd = WelsTime();
1306 pDecContext->dDecTime += (iEnd - iStart) / 1e3;
1307 return (DECODING_STATE)pDecContext->iErrorCode;
1308 }
1309
DecodeFrame(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,int * pStride,int & iWidth,int & iHeight)1310 DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
1311 const int kiSrcLen,
1312 unsigned char** ppDst,
1313 int* pStride,
1314 int& iWidth,
1315 int& iHeight) {
1316 DECODING_STATE eDecState = dsErrorFree;
1317 SBufferInfo DstInfo;
1318
1319 memset (&DstInfo, 0, sizeof (SBufferInfo));
1320 DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0];
1321 DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1];
1322 DstInfo.UsrData.sSystemBuffer.iWidth = iWidth;
1323 DstInfo.UsrData.sSystemBuffer.iHeight = iHeight;
1324
1325 eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo);
1326 if (eDecState == dsErrorFree) {
1327 pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0];
1328 pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1];
1329 iWidth = DstInfo.UsrData.sSystemBuffer.iWidth;
1330 iHeight = DstInfo.UsrData.sSystemBuffer.iHeight;
1331 }
1332
1333 return eDecState;
1334 }
1335
DecodeFrameEx(const unsigned char * kpSrc,const int kiSrcLen,unsigned char * pDst,int iDstStride,int & iDstLen,int & iWidth,int & iHeight,int & iColorFormat)1336 DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc,
1337 const int kiSrcLen,
1338 unsigned char* pDst,
1339 int iDstStride,
1340 int& iDstLen,
1341 int& iWidth,
1342 int& iHeight,
1343 int& iColorFormat) {
1344 DECODING_STATE state = dsErrorFree;
1345
1346 return state;
1347 }
1348
ParseAccessUnit(SWelsDecoderThreadCTX & sThreadCtx)1349 DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) {
1350 sThreadCtx.pCtx->bHasNewSps = false;
1351 sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag;
1352 sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput;
1353 sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp;
1354 bool bPicBuffChanged = false;
1355 if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) {
1356 CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx);
1357 sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber;
1358 if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) {
1359 bPicBuffChanged = true;
1360 sThreadCtx.pCtx->pPicBuff = m_pPicBuff;
1361 sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL;
1362 sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel;
1363 sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel;
1364 }
1365 }
1366
1367 //if threadCount > 1, then each thread must contain exact one complete frame.
1368 if (GetThreadCount (sThreadCtx.pCtx) > 1) {
1369 sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0;
1370 sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0;
1371 }
1372
1373 int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst,
1374 &sThreadCtx.sDstInfo);
1375
1376 int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo);
1377 if (ERR_NONE != iErr) {
1378 return (DECODING_STATE) (iRet | iErr);
1379 }
1380 if (sThreadCtx.pCtx->bNewSeqBegin) {
1381 m_pPicBuff = sThreadCtx.pCtx->pPicBuff;
1382 } else if (bPicBuffChanged) {
1383 InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4);
1384 }
1385 if (!sThreadCtx.pCtx->bNewSeqBegin && m_pLastDecThrCtx != NULL) {
1386 sThreadCtx.pCtx->sFrameCrop = m_pLastDecThrCtx->pCtx->pSps->sFrameCrop;
1387 }
1388 m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag;
1389 m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput;
1390 return (DECODING_STATE)iErr;
1391 }
1392 /*
1393 * Run decoding picture in separate thread.
1394 */
1395
ThreadDecodeFrameInternal(const unsigned char * kpSrc,const int kiSrcLen,unsigned char ** ppDst,SBufferInfo * pDstInfo)1396 int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst,
1397 SBufferInfo* pDstInfo) {
1398 int state = dsErrorFree;
1399 int32_t i, j;
1400 int32_t signal = 0;
1401
1402 //serial using of threads
1403 if (m_DecCtxActiveCount < m_iThreadCount) {
1404 signal = m_DecCtxActiveCount;
1405 } else {
1406 signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum;
1407 }
1408
1409 WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1410
1411 for (i = 0; i < m_DecCtxActiveCount; ++i) {
1412 if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) {
1413 m_pDecThrCtxActive[i] = NULL;
1414 for (j = i; j < m_DecCtxActiveCount - 1; j++) {
1415 m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1];
1416 m_pDecThrCtxActive[j + 1] = NULL;
1417 }
1418 --m_DecCtxActiveCount;
1419 break;
1420 }
1421 }
1422
1423 m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal];
1424 if (m_pLastDecThrCtx != NULL) {
1425 m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx;
1426 }
1427 m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc);
1428 m_pDecThrCtx[signal].kiSrcLen = kiSrcLen;
1429 m_pDecThrCtx[signal].ppDst = ppDst;
1430 memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo));
1431
1432 ParseAccessUnit (m_pDecThrCtx[signal]);
1433 if (m_iThreadCount > 1) {
1434 m_pLastDecThrCtx = &m_pDecThrCtx[signal];
1435 }
1436 m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN;
1437 RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated);
1438
1439 // wait early picture
1440 if (m_DecCtxActiveCount >= m_iThreadCount) {
1441 WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE);
1442 RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle);
1443 }
1444 return state;
1445 }
1446
1447 } // namespace WelsDec
1448
1449
1450 using namespace WelsDec;
1451 /*
1452 * WelsGetDecoderCapability
1453 * @return: DecCapability information
1454 */
WelsGetDecoderCapability(SDecoderCapability * pDecCapability)1455 int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) {
1456 memset (pDecCapability, 0, sizeof (SDecoderCapability));
1457 pDecCapability->iProfileIdc = 66; //Baseline
1458 pDecCapability->iProfileIop = 0xE0; //11100000b
1459 pDecCapability->iLevelIdc = 32; //level_idc = 3.2
1460 pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2
1461 pDecCapability->iMaxFs = 5120; //from level_idc = 3.2
1462 pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2
1463 pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2
1464 pDecCapability->iMaxBr = 20000; //from level_idc = 3.2
1465 pDecCapability->bRedPicCap = 0; //not support redundant pic
1466
1467 return ERR_NONE;
1468 }
1469 /* WINAPI is indeed in prefix due to sync to application layer callings!! */
1470
1471 /*
1472 * WelsCreateDecoder
1473 * @return: success in return 0, otherwise failed.
1474 */
WelsCreateDecoder(ISVCDecoder ** ppDecoder)1475 long WelsCreateDecoder (ISVCDecoder** ppDecoder) {
1476
1477 if (NULL == ppDecoder) {
1478 return ERR_INVALID_PARAMETERS;
1479 }
1480
1481 *ppDecoder = new CWelsDecoder();
1482
1483 if (NULL == *ppDecoder) {
1484 return ERR_MALLOC_FAILED;
1485 }
1486
1487 return ERR_NONE;
1488 }
1489
1490 /*
1491 * WelsDestroyDecoder
1492 */
WelsDestroyDecoder(ISVCDecoder * pDecoder)1493 void WelsDestroyDecoder (ISVCDecoder* pDecoder) {
1494 if (NULL != pDecoder) {
1495 delete (CWelsDecoder*)pDecoder;
1496 }
1497 }
1498