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