Add various internal thread functions. Create function ParseAccessUnit and thread function ConstructAccessUnit in the condition that each input bitstream segment must contain exact one access unit (i.e. one slice or one frame).
Showing the changes to codec/decoder/plus/src/welsDecoderExt.cpp (1 of 4 files). Show all
Unified · Split
| @@ -51,6 +51,7 @@ · 50 unmodified lines | ||
| 51 | 51 | //#include "macros.h" |
| 52 | 52 | #include "decoder.h" |
| 53 | 53 | #include "decoder_core.h" |
| 54 | +#include "manage_dec_ref.h" | |
| 54 | 55 | #include "error_concealment.h" |
| 55 | 56 | |
| 56 | 57 | #include "measure_time.h" |
| @@ -67,12 +68,11 @@ extern "C" { · 10 unmodified lines | ||
| 67 | 68 | #include <stdio.h> |
| 68 | 69 | #include <stdarg.h> |
| 69 | 70 | #include <sys/types.h> |
| 71 | +#include <malloc.h> | |
| 70 | 72 | #else |
| 71 | 73 | #include <sys/time.h> |
| 72 | 74 | #endif |
| 73 | 75 | |
| 74 | −#define _PICTURE_REORDERING_ 1 | |
| 75 | − | |
| 76 | 76 | namespace WelsDec { |
| 77 | 77 | |
| 78 | 78 | ////////////////////////////////////////////////////////////////////// |
| @@ -88,9 +88,58 @@ namespace WelsDec { · 9 unmodified lines | ||
| 88 | 88 | * |
| 89 | 89 | * return: none |
| 90 | 90 | ***************************************************************************/ |
| 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 | + | |
| 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 | + RESET_EVENT (&pThrCtx->sSliceDecodeFinsh); | |
| 109 | + iRet |= pWelsDecoder->DecodeFrame2WithCtx (pThrCtx->pCtx, NULL, 0, pThrCtx->ppDst, &pThrCtx->sDstInfo); | |
| 110 | + | |
| 111 | + //WelsMutexUnlock (&pWelsDecoder->m_csDecoder); | |
| 112 | + return (DECODING_STATE)iRet; | |
| 113 | +} | |
| 114 | + | |
| 115 | +DECLARE_PROCTHREAD (pThrProcFrame, p) { | |
| 116 | + SWelsDecoderThreadCTX* pThrCtx = (SWelsDecoderThreadCTX*)p; | |
| 117 | + while (1) { | |
| 118 | + RELEASE_SEMAPHORE (pThrCtx->sThreadInfo.sIsBusy); | |
| 119 | + RELEASE_SEMAPHORE (&pThrCtx->sThreadInfo.sIsIdle); | |
| 120 | + WAIT_SEMAPHORE (&pThrCtx->sThreadInfo.sIsActivated, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 121 | + if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_RUN) { | |
| 122 | + CWelsDecoder* pWelsDecoder = (CWelsDecoder*)pThrCtx->threadCtxOwner; | |
| 123 | + ConstructAccessUnit (pWelsDecoder, pThrCtx); | |
| 124 | + } else if (pThrCtx->sThreadInfo.uiCommand == WELS_DEC_THREAD_COMMAND_ABORT) { | |
| 125 | + break; | |
| 126 | + } | |
| 127 | + } | |
| 128 | + return 0; | |
| 129 | +} | |
| 130 | + | |
| 91 | 131 | CWelsDecoder::CWelsDecoder (void) |
| 92 | − : m_pDecContext (NULL), | |
| 93 | − m_pWelsTrace (NULL) { | |
| 132 | + : m_pWelsTrace (NULL), | |
| 133 | + m_uiDecodeTimeStamp (0), | |
| 134 | + m_bIsBaseline (false), | |
| 135 | + m_iCpuCount (1), | |
| 136 | + m_iThreadCount (1), | |
| 137 | + m_pPicBuff (NULL), | |
| 138 | + m_bParamSetsLostFlag (false), | |
| 139 | + m_bFreezeOutput (false), | |
| 140 | + m_DecCtxActiveCount (0), | |
| 141 | + m_pDecThrCtx (NULL), | |
| 142 | + m_pLastDecThrCtx (NULL) { | |
| 94 | 143 | #ifdef OUTPUT_BIT_STREAM |
| 95 | 144 | char chFileName[1024] = { 0 }; //for .264 |
| 96 | 145 | int iBufUsed = 0; |
| @@ -114,6 +163,15 @@ CWelsDecoder::CWelsDecoder (void) · 17 unmodified lines | ||
| 114 | 163 | |
| 115 | 164 | ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true); |
| 116 | 165 | |
| 166 | + m_iCpuCount = GetCPUCount(); | |
| 167 | + if (m_iCpuCount > WELS_DEC_MAX_NUM_CPU) { | |
| 168 | + m_iCpuCount = WELS_DEC_MAX_NUM_CPU; | |
| 169 | + } | |
| 170 | + m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iThreadCount]; | |
| 171 | + memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iThreadCount); | |
| 172 | + for (int32_t i = 0; i < WELS_DEC_MAX_NUM_CPU; ++i) { | |
| 173 | + m_pDecThrCtxActive[i] = NULL; | |
| 174 | + } | |
| 117 | 175 | #ifdef OUTPUT_BIT_STREAM |
| 118 | 176 | SWelsTime sCurTime; |
| 119 | 177 | |
| @@ -169,7 +227,7 @@ CWelsDecoder::~CWelsDecoder() { · 49 unmodified lines | ||
| 169 | 227 | if (m_pWelsTrace != NULL) { |
| 170 | 228 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()"); |
| 171 | 229 | } |
| 172 | − | |
| 230 | + CloseDecoderThreads(); | |
| 173 | 231 | UninitDecoder(); |
| 174 | 232 | |
| 175 | 233 | #ifdef OUTPUT_BIT_STREAM |
| @@ -187,6 +245,10 @@ CWelsDecoder::~CWelsDecoder() { · 11 unmodified lines | ||
| 187 | 245 | delete m_pWelsTrace; |
| 188 | 246 | m_pWelsTrace = NULL; |
| 189 | 247 | } |
| 248 | + if (m_pDecThrCtx != NULL) { | |
| 249 | + delete[] m_pDecThrCtx; | |
| 250 | + m_pDecThrCtx = NULL; | |
| 251 | + } | |
| 190 | 252 | } |
| 191 | 253 | |
| 192 | 254 | long CWelsDecoder::Initialize (const SDecodingParam* pParam) { |
| @@ -215,26 +277,87 @@ long CWelsDecoder::Uninitialize() { · 22 unmodified lines | ||
| 215 | 277 | } |
| 216 | 278 | |
| 217 | 279 | void CWelsDecoder::UninitDecoder (void) { |
| 218 | − if (NULL == m_pDecContext) | |
| 219 | − return; | |
| 280 | + for (int32_t i = 0; i < m_iThreadCount; ++i) { | |
| 281 | + if (m_pDecThrCtx[i].pCtx != NULL) { | |
| 282 | + if (i > 0) { | |
| 283 | + WelsResetRefPicWithoutUnRef (m_pDecThrCtx[i].pCtx); | |
| 284 | + } | |
| 285 | + UninitDecoderCtx (m_pDecThrCtx[i].pCtx); | |
| 286 | + } | |
| 287 | + } | |
| 288 | +} | |
| 220 | 289 | |
| 221 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoder(), openh264 codec version = %s.", | |
| 222 | − VERSION_NUMBER); | |
| 290 | +void CWelsDecoder::OpenDecoderThreads() { | |
| 291 | + if (m_iThreadCount > 1) { | |
| 292 | + m_uiDecodeTimeStamp = 0; | |
| 293 | + CREATE_SEMAPHORE (&m_sIsBusy, m_iThreadCount, m_iThreadCount, NULL); | |
| 294 | + WelsMutexInit (&m_csDecoder); | |
| 295 | + CREATE_EVENT (&m_sBufferingEvent, 1, 0, NULL); | |
| 296 | + SET_EVENT (&m_sBufferingEvent); | |
| 297 | + CREATE_EVENT (&m_sReleaseBufferEvent, 1, 0, NULL); | |
| 298 | + SET_EVENT (&m_sReleaseBufferEvent); | |
| 299 | + for (int32_t i = 0; i < m_iThreadCount; ++i) { | |
| 300 | + m_pDecThrCtx[i].sThreadInfo.uiThrMaxNum = m_iThreadCount; | |
| 301 | + m_pDecThrCtx[i].sThreadInfo.uiThrNum = i; | |
| 302 | + m_pDecThrCtx[i].sThreadInfo.uiThrStackSize = WELS_DEC_MAX_THREAD_STACK_SIZE; | |
| 303 | + m_pDecThrCtx[i].sThreadInfo.pThrProcMain = pThrProcFrame; | |
| 304 | + m_pDecThrCtx[i].sThreadInfo.sIsBusy = &m_sIsBusy; | |
| 305 | + m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN; | |
| 306 | + m_pDecThrCtx[i].threadCtxOwner = this; | |
| 307 | + m_pDecThrCtx[i].kpSrc = NULL; | |
| 308 | + m_pDecThrCtx[i].kiSrcLen = 0; | |
| 309 | + m_pDecThrCtx[i].ppDst = NULL; | |
| 310 | + m_pDecThrCtx[i].pDec = NULL; | |
| 311 | + CREATE_EVENT (&m_pDecThrCtx[i].sImageReady, 1, 0, NULL); | |
| 312 | + CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart, 1, 0, NULL); | |
| 313 | + CREATE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinsh, 1, 0, NULL); | |
| 314 | + CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, 0, 1, NULL); | |
| 315 | + CREATE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated, 0, 1, NULL); | |
| 316 | + CREATE_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle, pThrProcInit, (void*) (& (m_pDecThrCtx[i]))); | |
| 317 | + } | |
| 318 | + } | |
| 319 | +} | |
| 320 | +void CWelsDecoder::CloseDecoderThreads() { | |
| 321 | + if (m_iThreadCount > 1) { | |
| 322 | + for (int32_t i = 0; i < m_iThreadCount; i++) { //waiting the completion begun slices | |
| 323 | + WAIT_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 324 | + m_pDecThrCtx[i].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_ABORT; | |
| 325 | + RELEASE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated); | |
| 326 | + WAIT_THREAD (&m_pDecThrCtx[i].sThreadInfo.sThrHandle); | |
| 327 | + CLOSE_EVENT (&m_pDecThrCtx[i].sImageReady); | |
| 328 | + CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeStart); | |
| 329 | + CLOSE_EVENT (&m_pDecThrCtx[i].sSliceDecodeFinsh); | |
| 330 | + CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsIdle); | |
| 331 | + CLOSE_SEMAPHORE (&m_pDecThrCtx[i].sThreadInfo.sIsActivated); | |
| 332 | + } | |
| 333 | + WelsMutexDestroy (&m_csDecoder); | |
| 334 | + CLOSE_EVENT (&m_sBufferingEvent); | |
| 335 | + CLOSE_EVENT (&m_sReleaseBufferEvent); | |
| 336 | + CLOSE_SEMAPHORE (&m_sIsBusy); | |
| 337 | + } | |
| 338 | +} | |
| 223 | 339 | |
| 224 | − WelsEndDecoder (m_pDecContext); | |
| 340 | +void CWelsDecoder::UninitDecoderCtx (PWelsDecoderContext& pCtx) { | |
| 341 | + if (pCtx != NULL) { | |
| 225 | 342 | |
| 226 | − if (m_pDecContext->pMemAlign != NULL) { | |
| 227 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 228 | − "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..", | |
| 229 | − m_pDecContext->pMemAlign->WelsGetMemoryUsage()); | |
| 230 | − delete m_pDecContext->pMemAlign; | |
| 231 | − m_pDecContext->pMemAlign = NULL; | |
| 232 | − } | |
| 343 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::UninitDecoderCtx(), openh264 codec version = %s.", | |
| 344 | + VERSION_NUMBER); | |
| 233 | 345 | |
| 234 | − if (NULL != m_pDecContext) { | |
| 235 | − WelsFree (m_pDecContext, "m_pDecContext"); | |
| 346 | + WelsEndDecoder (pCtx); | |
| 236 | 347 | |
| 237 | − m_pDecContext = NULL; | |
| 348 | + if (pCtx->pMemAlign != NULL) { | |
| 349 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 350 | + "CWelsDecoder::UninitDecoder(), verify memory usage (%d bytes) after free..", | |
| 351 | + pCtx->pMemAlign->WelsGetMemoryUsage()); | |
| 352 | + delete pCtx->pMemAlign; | |
| 353 | + pCtx->pMemAlign = NULL; | |
| 354 | + } | |
| 355 | + | |
| 356 | + if (NULL != pCtx) { | |
| 357 | + WelsFree (pCtx, "m_pDecContext"); | |
| 358 | + | |
| 359 | + pCtx = NULL; | |
| 360 | + } | |
| 238 | 361 | } |
| 239 | 362 | } |
| 240 | 363 | |
| @@ -244,59 +367,100 @@ int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) { · 3 unmodified lines | ||
| 244 | 367 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, |
| 245 | 368 | "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d", |
| 246 | 369 | VERSION_NUMBER, (int32_t)pParam->bParseOnly); |
| 247 | − | |
| 370 | + if (m_iThreadCount > 1 && pParam->bParseOnly) { | |
| 371 | + m_iThreadCount = 1; | |
| 372 | + } | |
| 373 | + OpenDecoderThreads(); | |
| 248 | 374 | //reset decoder context |
| 249 | 375 | memset (&m_sDecoderStatistics, 0, sizeof (SDecoderStatistics)); |
| 250 | 376 | memset (&m_sLastDecPicInfo, 0, sizeof (SWelsLastDecPicInfo)); |
| 251 | 377 | memset (&m_sVlcTable, 0, sizeof (SVlcTable)); |
| 378 | + UninitDecoder(); | |
| 252 | 379 | WelsDecoderLastDecPicInfoDefaults (m_sLastDecPicInfo); |
| 253 | − if (m_pDecContext) //free | |
| 254 | − UninitDecoder(); | |
| 255 | − m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext"); | |
| 256 | − if (NULL == m_pDecContext) | |
| 380 | + for (int32_t i = 0; i < m_iThreadCount; ++i) { | |
| 381 | + InitDecoderCtx (m_pDecThrCtx[i].pCtx, pParam); | |
| 382 | + if (m_iThreadCount > 1) { | |
| 383 | + m_pDecThrCtx[i].pCtx->pThreadCtx = &m_pDecThrCtx[i]; | |
| 384 | + } | |
| 385 | + } | |
| 386 | + m_bParamSetsLostFlag = false; | |
| 387 | + m_bFreezeOutput = false; | |
| 388 | + return cmResultSuccess; | |
| 389 | +} | |
| 390 | + | |
| 391 | +// the return value of this function is not suitable, it need report failure info to upper layer. | |
| 392 | +int32_t CWelsDecoder::InitDecoderCtx (PWelsDecoderContext& pCtx, const SDecodingParam* pParam) { | |
| 393 | + | |
| 394 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 395 | + "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d", | |
| 396 | + VERSION_NUMBER, (int32_t)pParam->bParseOnly); | |
| 397 | + | |
| 398 | + //reset decoder context | |
| 399 | + UninitDecoderCtx (pCtx); | |
| 400 | + pCtx = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext"); | |
| 401 | + if (NULL == pCtx) | |
| 257 | 402 | return cmMallocMemeError; |
| 258 | 403 | int32_t iCacheLineSize = 16; // on chip cache line size in byte |
| 259 | − m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize); | |
| 260 | − WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pMemAlign), UninitDecoder()) | |
| 404 | + pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize); | |
| 405 | + WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pMemAlign), UninitDecoderCtx (pCtx)) | |
| 261 | 406 | |
| 262 | 407 | //fill in default value into context |
| 263 | − m_pDecContext->pLastDecPicInfo = &m_sLastDecPicInfo; | |
| 264 | − m_pDecContext->pDecoderStatistics = &m_sDecoderStatistics; | |
| 265 | − m_pDecContext->pVlcTable = &m_sVlcTable; | |
| 266 | − m_pDecContext->pPictInfoList = m_sPictInfoList; | |
| 267 | − m_pDecContext->pPictReoderingStatus = &m_sReoderingStatus; | |
| 268 | − WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx); | |
| 269 | − WelsDecoderSpsPpsDefaults (m_pDecContext->sSpsPpsCtx); | |
| 270 | − | |
| 408 | + pCtx->pLastDecPicInfo = &m_sLastDecPicInfo; | |
| 409 | + pCtx->pDecoderStatistics = &m_sDecoderStatistics; | |
| 410 | + pCtx->pVlcTable = &m_sVlcTable; | |
| 411 | + pCtx->pPictInfoList = m_sPictInfoList; | |
| 412 | + pCtx->pPictReoderingStatus = &m_sReoderingStatus; | |
| 413 | + pCtx->pCsDecoder = &m_csDecoder; | |
| 414 | + WelsDecoderDefaults (pCtx, &m_pWelsTrace->m_sLogCtx); | |
| 415 | + WelsDecoderSpsPpsDefaults (pCtx->sSpsPpsCtx); | |
| 271 | 416 | //check param and update decoder context |
| 272 | − m_pDecContext->pParam = (SDecodingParam*)m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam), | |
| 273 | − "SDecodingParam"); | |
| 274 | − WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder()); | |
| 275 | − int32_t iRet = DecoderConfigParam (m_pDecContext, pParam); | |
| 417 | + pCtx->pParam = (SDecodingParam*)pCtx->pMemAlign->WelsMallocz (sizeof (SDecodingParam), | |
| 418 | + "SDecodingParam"); | |
| 419 | + WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == pCtx->pParam), UninitDecoderCtx (pCtx)); | |
| 420 | + int32_t iRet = DecoderConfigParam (pCtx, pParam); | |
| 276 | 421 | WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess); |
| 277 | 422 | |
| 278 | 423 | //init decoder |
| 279 | − WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx), | |
| 280 | − UninitDecoder()) | |
| 281 | − | |
| 424 | + WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, WelsInitDecoder (pCtx, &m_pWelsTrace->m_sLogCtx), | |
| 425 | + UninitDecoderCtx (pCtx)) | |
| 426 | + pCtx->pPicBuff = NULL; | |
| 282 | 427 | return cmResultSuccess; |
| 283 | 428 | } |
| 284 | 429 | |
| 285 | −int32_t CWelsDecoder::ResetDecoder() { | |
| 430 | +int32_t CWelsDecoder::ResetDecoder (PWelsDecoderContext& pCtx) { | |
| 286 | 431 | // TBC: need to be modified when context and trace point are null |
| 287 | − if (m_pDecContext != NULL && m_pWelsTrace != NULL) { | |
| 288 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", | |
| 289 | − m_pDecContext->iErrorCode); | |
| 290 | − SDecodingParam sPrevParam; | |
| 291 | − memcpy (&sPrevParam, m_pDecContext->pParam, sizeof (SDecodingParam)); | |
| 432 | + if (m_iThreadCount > 1) { | |
| 433 | + ThreadResetDecoder (pCtx); | |
| 434 | + } else { | |
| 435 | + if (pCtx != NULL && m_pWelsTrace != NULL) { | |
| 436 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", | |
| 437 | + pCtx->iErrorCode); | |
| 438 | + SDecodingParam sPrevParam; | |
| 439 | + memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam)); | |
| 440 | + | |
| 441 | + WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoderCtx (pCtx, &sPrevParam), | |
| 442 | + UninitDecoderCtx (pCtx)); | |
| 443 | + } else if (m_pWelsTrace != NULL) { | |
| 444 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null"); | |
| 445 | + } | |
| 446 | + ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, false); | |
| 447 | + } | |
| 448 | + return ERR_INFO_UNINIT; | |
| 449 | +} | |
| 292 | 450 | |
| 293 | − WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, InitDecoder (&sPrevParam), UninitDecoder()); | |
| 451 | +int32_t CWelsDecoder::ThreadResetDecoder (PWelsDecoderContext& pCtx) { | |
| 452 | + // TBC: need to be modified when context and trace point are null | |
| 453 | + SDecodingParam sPrevParam; | |
| 454 | + if (pCtx != NULL && m_pWelsTrace != NULL) { | |
| 455 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "ResetDecoder(), context error code is %d", pCtx->iErrorCode); | |
| 456 | + memcpy (&sPrevParam, pCtx->pParam, sizeof (SDecodingParam)); | |
| 457 | + ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, true); | |
| 458 | + CloseDecoderThreads(); | |
| 459 | + UninitDecoder(); | |
| 460 | + InitDecoder (&sPrevParam); | |
| 294 | 461 | } else if (m_pWelsTrace != NULL) { |
| 295 | 462 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "ResetDecoder() failed as decoder context null"); |
| 296 | 463 | } |
| 297 | −#ifdef _PICTURE_REORDERING_ | |
| 298 | − ResetReorderingPictureBuffers (&m_sReoderingStatus, m_sPictInfoList, false); | |
| 299 | −#endif | |
| 300 | 464 | return ERR_INFO_UNINIT; |
| 301 | 465 | } |
| 302 | 466 | |
| @@ -305,71 +469,95 @@ int32_t CWelsDecoder::ResetDecoder() { · 2 unmodified lines | ||
| 305 | 469 | */ |
| 306 | 470 | long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) { |
| 307 | 471 | int iVal = 0; |
| 472 | + if (eOptID == DECODER_OPTION_NUM_OF_THREADS) { | |
| 473 | + if (pOption != NULL) { | |
| 474 | + int32_t threadCount = * ((int32_t*)pOption); | |
| 475 | + if (threadCount <= 0) { | |
| 476 | + threadCount = 1; | |
| 477 | + } else if (threadCount > m_iCpuCount) { | |
| 478 | + threadCount = m_iCpuCount; | |
| 479 | + } | |
| 480 | + if (threadCount > 3) { | |
| 481 | + threadCount = 3; | |
| 482 | + } | |
| 483 | + if (threadCount != m_iThreadCount) { | |
| 484 | + m_iThreadCount = threadCount; | |
| 485 | + if (m_pDecThrCtx != NULL) { | |
| 486 | + delete [] m_pDecThrCtx; | |
| 487 | + m_pDecThrCtx = new SWelsDecoderThreadCTX[m_iThreadCount]; | |
| 488 | + memset (m_pDecThrCtx, 0, sizeof (SWelsDecoderThreadCTX)*m_iThreadCount); | |
| 489 | + } | |
| 490 | + } | |
| 491 | + } | |
| 492 | + return cmResultSuccess; | |
| 493 | + } | |
| 494 | + for (int32_t i = 0; i < m_iThreadCount; ++i) { | |
| 495 | + PWelsDecoderContext pDecContext = m_pDecThrCtx[i].pCtx; | |
| 496 | + if (pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL && | |
| 497 | + eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT) | |
| 498 | + return dsInitialOptExpected; | |
| 499 | + if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded | |
| 500 | + if (pOption == NULL) | |
| 501 | + return cmInitParaError; | |
| 308 | 502 | |
| 309 | − if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL && | |
| 310 | − eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT) | |
| 311 | − return dsInitialOptExpected; | |
| 312 | − if (eOptID == DECODER_OPTION_END_OF_STREAM) { // Indicate bit-stream of the final frame to be decoded | |
| 313 | − if (pOption == NULL) | |
| 314 | − return cmInitParaError; | |
| 315 | − | |
| 316 | − iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag | |
| 503 | + iVal = * ((int*)pOption); // boolean value for whether enabled End Of Stream flag | |
| 317 | 504 | |
| 318 | − m_pDecContext->bEndOfStreamFlag = iVal ? true : false; | |
| 505 | + pDecContext->bEndOfStreamFlag = iVal ? true : false; | |
| 319 | 506 | |
| 320 | − return cmResultSuccess; | |
| 321 | − } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status | |
| 322 | − if (pOption == NULL) | |
| 323 | − return cmInitParaError; | |
| 507 | + return cmResultSuccess; | |
| 508 | + } else if (eOptID == DECODER_OPTION_ERROR_CON_IDC) { // Indicate error concealment status | |
| 509 | + if (pOption == NULL) | |
| 510 | + return cmInitParaError; | |
| 511 | + | |
| 512 | + iVal = * ((int*)pOption); // int value for error concealment idc | |
| 513 | + iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE); | |
| 514 | + if ((pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) { | |
| 515 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 516 | + "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal); | |
| 517 | + return cmInitParaError; | |
| 518 | + } | |
| 324 | 519 | |
| 325 | − iVal = * ((int*)pOption); // int value for error concealment idc | |
| 326 | − iVal = WELS_CLIP3 (iVal, (int32_t)ERROR_CON_DISABLE, (int32_t)ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE); | |
| 327 | − if ((m_pDecContext->pParam->bParseOnly) && (iVal != (int32_t)ERROR_CON_DISABLE)) { | |
| 520 | + pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal; | |
| 521 | + InitErrorCon (pDecContext); | |
| 328 | 522 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, |
| 329 | − "CWelsDecoder::SetOption for ERROR_CON_IDC = %d not allowd for parse only!.", iVal); | |
| 330 | − return cmInitParaError; | |
| 331 | − } | |
| 332 | − | |
| 333 | − m_pDecContext->pParam->eEcActiveIdc = (ERROR_CON_IDC)iVal; | |
| 334 | − InitErrorCon (m_pDecContext); | |
| 335 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 336 | − "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal); | |
| 523 | + "CWelsDecoder::SetOption for ERROR_CON_IDC = %d.", iVal); | |
| 337 | 524 | |
| 338 | − return cmResultSuccess; | |
| 339 | − } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) { | |
| 340 | − if (m_pWelsTrace) { | |
| 341 | − uint32_t level = * ((uint32_t*)pOption); | |
| 342 | − m_pWelsTrace->SetTraceLevel (level); | |
| 343 | − } | |
| 344 | − return cmResultSuccess; | |
| 345 | − } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) { | |
| 346 | − if (m_pWelsTrace) { | |
| 347 | − WelsTraceCallback callback = * ((WelsTraceCallback*)pOption); | |
| 348 | − m_pWelsTrace->SetTraceCallback (callback); | |
| 349 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 350 | − "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.", | |
| 351 | − callback); | |
| 352 | − } | |
| 353 | − return cmResultSuccess; | |
| 354 | − } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) { | |
| 355 | − if (m_pWelsTrace) { | |
| 356 | − void* ctx = * ((void**)pOption); | |
| 357 | − m_pWelsTrace->SetTraceCallbackContext (ctx); | |
| 358 | − } | |
| 359 | − return cmResultSuccess; | |
| 360 | − } else if (eOptID == DECODER_OPTION_GET_STATISTICS) { | |
| 361 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, | |
| 362 | − "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!"); | |
| 363 | − return cmInitParaError; | |
| 364 | − } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) { | |
| 365 | − if (pOption) { | |
| 366 | − m_pDecContext->pDecoderStatistics->iStatisticsLogInterval = (* ((unsigned int*)pOption)); | |
| 367 | 525 | return cmResultSuccess; |
| 526 | + } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) { | |
| 527 | + if (m_pWelsTrace) { | |
| 528 | + uint32_t level = * ((uint32_t*)pOption); | |
| 529 | + m_pWelsTrace->SetTraceLevel (level); | |
| 530 | + } | |
| 531 | + return cmResultSuccess; | |
| 532 | + } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) { | |
| 533 | + if (m_pWelsTrace) { | |
| 534 | + WelsTraceCallback callback = * ((WelsTraceCallback*)pOption); | |
| 535 | + m_pWelsTrace->SetTraceCallback (callback); | |
| 536 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | |
| 537 | + "CWelsDecoder::SetOption():DECODER_OPTION_TRACE_CALLBACK callback = %p.", | |
| 538 | + callback); | |
| 539 | + } | |
| 540 | + return cmResultSuccess; | |
| 541 | + } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) { | |
| 542 | + if (m_pWelsTrace) { | |
| 543 | + void* ctx = * ((void**)pOption); | |
| 544 | + m_pWelsTrace->SetTraceCallbackContext (ctx); | |
| 545 | + } | |
| 546 | + return cmResultSuccess; | |
| 547 | + } else if (eOptID == DECODER_OPTION_GET_STATISTICS) { | |
| 548 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, | |
| 549 | + "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!"); | |
| 550 | + return cmInitParaError; | |
| 551 | + } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) { | |
| 552 | + if (pOption) { | |
| 553 | + pDecContext->pDecoderStatistics->iStatisticsLogInterval = (* ((unsigned int*)pOption)); | |
| 554 | + return cmResultSuccess; | |
| 555 | + } | |
| 556 | + } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) { | |
| 557 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, | |
| 558 | + "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!"); | |
| 559 | + return cmInitParaError; | |
| 368 | 560 | } |
| 369 | − } else if (eOptID == DECODER_OPTION_GET_SAR_INFO) { | |
| 370 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, | |
| 371 | − "CWelsDecoder::SetOption():DECODER_OPTION_GET_SAR_INFO: this option is get-only!"); | |
| 372 | − return cmInitParaError; | |
| 373 | 561 | } |
| 374 | 562 | return cmInitParaError; |
| 375 | 563 | } |
| @@ -379,105 +567,109 @@ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) { · 3 unmodified lines | ||
| 379 | 567 | */ |
| 380 | 568 | long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) { |
| 381 | 569 | int iVal = 0; |
| 382 | − | |
| 383 | − if (m_pDecContext == NULL) | |
| 570 | + if (DECODER_OPTION_NUM_OF_THREADS == eOptID) { | |
| 571 | + * ((int*)pOption) = m_iThreadCount; | |
| 572 | + return cmResultSuccess; | |
| 573 | + } | |
| 574 | + PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx; | |
| 575 | + if (pDecContext == NULL) | |
| 384 | 576 | return cmInitExpected; |
| 385 | 577 | |
| 386 | 578 | if (pOption == NULL) |
| 387 | 579 | return cmInitParaError; |
| 388 | 580 | |
| 389 | 581 | if (DECODER_OPTION_END_OF_STREAM == eOptID) { |
| 390 | − iVal = m_pDecContext->bEndOfStreamFlag; | |
| 582 | + iVal = pDecContext->bEndOfStreamFlag; | |
| 391 | 583 | * ((int*)pOption) = iVal; |
| 392 | 584 | return cmResultSuccess; |
| 393 | 585 | } |
| 394 | 586 | #ifdef LONG_TERM_REF |
| 395 | 587 | else if (DECODER_OPTION_IDR_PIC_ID == eOptID) { |
| 396 | − iVal = m_pDecContext->uiCurIdrPicId; | |
| 588 | + iVal = pDecContext->uiCurIdrPicId; | |
| 397 | 589 | * ((int*)pOption) = iVal; |
| 398 | 590 | return cmResultSuccess; |
| 399 | 591 | } else if (DECODER_OPTION_FRAME_NUM == eOptID) { |
| 400 | − iVal = m_pDecContext->iFrameNum; | |
| 592 | + iVal = pDecContext->iFrameNum; | |
| 401 | 593 | * ((int*)pOption) = iVal; |
| 402 | 594 | return cmResultSuccess; |
| 403 | 595 | } else if (DECODER_OPTION_LTR_MARKING_FLAG == eOptID) { |
| 404 | − iVal = m_pDecContext->bCurAuContainLtrMarkSeFlag; | |
| 596 | + iVal = pDecContext->bCurAuContainLtrMarkSeFlag; | |
| 405 | 597 | * ((int*)pOption) = iVal; |
| 406 | 598 | return cmResultSuccess; |
| 407 | 599 | } else if (DECODER_OPTION_LTR_MARKED_FRAME_NUM == eOptID) { |
| 408 | − iVal = m_pDecContext->iFrameNumOfAuMarkedLtr; | |
| 600 | + iVal = pDecContext->iFrameNumOfAuMarkedLtr; | |
| 409 | 601 | * ((int*)pOption) = iVal; |
| 410 | 602 | return cmResultSuccess; |
| 411 | 603 | } |
| 412 | 604 | #endif |
| 413 | 605 | else if (DECODER_OPTION_VCL_NAL == eOptID) { //feedback whether or not have VCL NAL in current AU |
| 414 | − iVal = m_pDecContext->iFeedbackVclNalInAu; | |
| 606 | + iVal = pDecContext->iFeedbackVclNalInAu; | |
| 415 | 607 | * ((int*)pOption) = iVal; |
| 416 | 608 | return cmResultSuccess; |
| 417 | 609 | } else if (DECODER_OPTION_TEMPORAL_ID == eOptID) { //if have VCL NAL in current AU, then feedback the temporal ID |
| 418 | − iVal = m_pDecContext->iFeedbackTidInAu; | |
| 610 | + iVal = pDecContext->iFeedbackTidInAu; | |
| 419 | 611 | * ((int*)pOption) = iVal; |
| 420 | 612 | return cmResultSuccess; |
| 421 | 613 | } else if (DECODER_OPTION_IS_REF_PIC == eOptID) { |
| 422 | − iVal = m_pDecContext->iFeedbackNalRefIdc; | |
| 614 | + iVal = pDecContext->iFeedbackNalRefIdc; | |
| 423 | 615 | if (iVal > 0) |
| 424 | 616 | iVal = 1; |
| 425 | 617 | * ((int*)pOption) = iVal; |
| 426 | 618 | return cmResultSuccess; |
| 427 | 619 | } else if (DECODER_OPTION_ERROR_CON_IDC == eOptID) { |
| 428 | − iVal = (int)m_pDecContext->pParam->eEcActiveIdc; | |
| 620 | + iVal = (int)pDecContext->pParam->eEcActiveIdc; | |
| 429 | 621 | * ((int*)pOption) = iVal; |
| 430 | 622 | return cmResultSuccess; |
| 431 | 623 | } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging |
| 432 | 624 | SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption)); |
| 433 | 625 | |
| 434 | − memcpy (pDecoderStatistics, m_pDecContext->pDecoderStatistics, sizeof (SDecoderStatistics)); | |
| 626 | + memcpy (pDecoderStatistics, pDecContext->pDecoderStatistics, sizeof (SDecoderStatistics)); | |
| 435 | 627 | |
| 436 | − if (m_pDecContext->pDecoderStatistics->uiDecodedFrameCount != 0) { //not original status | |
| 437 | − pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) / | |
| 438 | − (m_pDecContext->pDecoderStatistics->uiDecodedFrameCount); | |
| 439 | − pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) / | |
| 440 | − (m_pDecContext->pDecoderStatistics->uiDecodedFrameCount + m_pDecContext->pDecoderStatistics->uiFreezingIDRNum + | |
| 441 | − m_pDecContext->pDecoderStatistics->uiFreezingNonIDRNum); | |
| 628 | + if (pDecContext->pDecoderStatistics->uiDecodedFrameCount != 0) { //not original status | |
| 629 | + pDecoderStatistics->fAverageFrameSpeedInMs = (float) (pDecContext->dDecTime) / | |
| 630 | + (pDecContext->pDecoderStatistics->uiDecodedFrameCount); | |
| 631 | + pDecoderStatistics->fActualAverageFrameSpeedInMs = (float) (pDecContext->dDecTime) / | |
| 632 | + (pDecContext->pDecoderStatistics->uiDecodedFrameCount + pDecContext->pDecoderStatistics->uiFreezingIDRNum + | |
| 633 | + pDecContext->pDecoderStatistics->uiFreezingNonIDRNum); | |
| 442 | 634 | } |
| 443 | 635 | return cmResultSuccess; |
| 444 | 636 | } else if (eOptID == DECODER_OPTION_STATISTICS_LOG_INTERVAL) { |
| 445 | 637 | if (pOption) { |
| 446 | − iVal = m_pDecContext->pDecoderStatistics->iStatisticsLogInterval; | |
| 638 | + iVal = pDecContext->pDecoderStatistics->iStatisticsLogInterval; | |
| 447 | 639 | * ((unsigned int*)pOption) = iVal; |
| 448 | 640 | return cmResultSuccess; |
| 449 | 641 | } |
| 450 | 642 | } else if (DECODER_OPTION_GET_SAR_INFO == eOptID) { //get decoder SAR info in VUI |
| 451 | 643 | PVuiSarInfo pVuiSarInfo = (static_cast<PVuiSarInfo> (pOption)); |
| 452 | 644 | memset (pVuiSarInfo, 0, sizeof (SVuiSarInfo)); |
| 453 | − if (!m_pDecContext->pSps) { | |
| 645 | + if (!pDecContext->pSps) { | |
| 454 | 646 | return cmInitExpected; |
| 455 | 647 | } else { |
| 456 | − pVuiSarInfo->uiSarWidth = m_pDecContext->pSps->sVui.uiSarWidth; | |
| 457 | − pVuiSarInfo->uiSarHeight = m_pDecContext->pSps->sVui.uiSarHeight; | |
| 458 | − pVuiSarInfo->bOverscanAppropriateFlag = m_pDecContext->pSps->sVui.bOverscanAppropriateFlag; | |
| 648 | + pVuiSarInfo->uiSarWidth = pDecContext->pSps->sVui.uiSarWidth; | |
| 649 | + pVuiSarInfo->uiSarHeight = pDecContext->pSps->sVui.uiSarHeight; | |
| 650 | + pVuiSarInfo->bOverscanAppropriateFlag = pDecContext->pSps->sVui.bOverscanAppropriateFlag; | |
| 459 | 651 | return cmResultSuccess; |
| 460 | 652 | } |
| 461 | 653 | } else if (DECODER_OPTION_PROFILE == eOptID) { |
| 462 | − if (!m_pDecContext->pSps) { | |
| 654 | + if (!pDecContext->pSps) { | |
| 463 | 655 | return cmInitExpected; |
| 464 | 656 | } |
| 465 | − iVal = (int)m_pDecContext->pSps->uiProfileIdc; | |
| 657 | + iVal = (int)pDecContext->pSps->uiProfileIdc; | |
| 466 | 658 | * ((int*)pOption) = iVal; |
| 467 | 659 | return cmResultSuccess; |
| 468 | 660 | } else if (DECODER_OPTION_LEVEL == eOptID) { |
| 469 | − if (!m_pDecContext->pSps) { | |
| 661 | + if (!pDecContext->pSps) { | |
| 470 | 662 | return cmInitExpected; |
| 471 | 663 | } |
| 472 | − iVal = (int)m_pDecContext->pSps->uiLevelIdc; | |
| 664 | + iVal = (int)pDecContext->pSps->uiLevelIdc; | |
| 473 | 665 | * ((int*)pOption) = iVal; |
| 474 | 666 | return cmResultSuccess; |
| 475 | 667 | } else if (DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER == eOptID) { |
| 476 | − if (m_pDecContext->pSps && m_pDecContext->pSps->uiProfileIdc != 66) { | |
| 477 | − * ((int*)pOption) = m_sReoderingStatus.iNumOfPicts > 0 ? m_sReoderingStatus.iNumOfPicts : 0; | |
| 478 | − } else { | |
| 479 | − * ((int*)pOption) = 0; | |
| 668 | + for (int32_t activeThread = 0; activeThread < m_DecCtxActiveCount; ++activeThread) { | |
| 669 | + WAIT_SEMAPHORE (&m_pDecThrCtxActive[activeThread]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 670 | + RELEASE_SEMAPHORE (&m_pDecThrCtxActive[activeThread]->sThreadInfo.sIsIdle); | |
| 480 | 671 | } |
| 672 | + * ((int*)pOption) = m_sReoderingStatus.iNumOfPicts; | |
| 481 | 673 | return cmResultSuccess; |
| 482 | 674 | } |
| 483 | 675 | |
| @@ -488,7 +680,17 @@ DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc, · 4 unmodified lines | ||
| 488 | 680 | const int kiSrcLen, |
| 489 | 681 | unsigned char** ppDst, |
| 490 | 682 | SBufferInfo* pDstInfo) { |
| 491 | − int iRet; | |
| 683 | + int iRet = dsErrorFree; | |
| 684 | + if (m_iThreadCount > 1) { | |
| 685 | + iRet = ThreadDecodeFrameInternal (kpSrc, kiSrcLen, ppDst, pDstInfo); | |
| 686 | + if (m_sReoderingStatus.iNumOfPicts) { | |
| 687 | + WAIT_EVENT (&m_sBufferingEvent, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 688 | + RESET_EVENT (&m_sReleaseBufferEvent); | |
| 689 | + ReleaseBufferedReadyPicture (NULL, ppDst, pDstInfo); | |
| 690 | + SET_EVENT (&m_sReleaseBufferEvent); | |
| 691 | + } | |
| 692 | + return (DECODING_STATE)iRet; | |
| 693 | + } | |
| 492 | 694 | //SBufferInfo sTmpBufferInfo; |
| 493 | 695 | //unsigned char* ppTmpDst[3] = {NULL, NULL, NULL}; |
| 494 | 696 | iRet = (int)DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo); |
| @@ -506,24 +708,24 @@ DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc, · 11 unmodified lines | ||
| 506 | 708 | return (DECODING_STATE)iRet; |
| 507 | 709 | } |
| 508 | 710 | |
| 509 | −DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, | |
| 711 | +DECODING_STATE CWelsDecoder::DecodeFrame2WithCtx (PWelsDecoderContext pDecContext, const unsigned char* kpSrc, | |
| 510 | 712 | const int kiSrcLen, |
| 511 | 713 | unsigned char** ppDst, |
| 512 | 714 | SBufferInfo* pDstInfo) { |
| 513 | − if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) { | |
| 715 | + if (pDecContext == NULL || pDecContext->pParam == NULL) { | |
| 514 | 716 | if (m_pWelsTrace != NULL) { |
| 515 | 717 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n"); |
| 516 | 718 | } |
| 517 | 719 | return dsInitialOptExpected; |
| 518 | 720 | } |
| 519 | 721 | |
| 520 | − if (m_pDecContext->pParam->bParseOnly) { | |
| 722 | + if (pDecContext->pParam->bParseOnly) { | |
| 521 | 723 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n"); |
| 522 | − m_pDecContext->iErrorCode |= dsInvalidArgument; | |
| 724 | + pDecContext->iErrorCode |= dsInvalidArgument; | |
| 523 | 725 | return dsInvalidArgument; |
| 524 | 726 | } |
| 525 | − if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { | |
| 526 | − if (ResetDecoder()) | |
| 727 | + if (CheckBsBuffer (pDecContext, kiSrcLen)) { | |
| 728 | + if (ResetDecoder (pDecContext)) | |
| 527 | 729 | return dsOutOfMemory; |
| 528 | 730 | |
| 529 | 731 | return dsErrorFree; |
| @@ -539,147 +741,175 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, · 9 unmodified lines | ||
| 539 | 741 | WelsFflush (m_pFBSSize); |
| 540 | 742 | } |
| 541 | 743 | #endif//OUTPUT_BIT_STREAM |
| 542 | − m_pDecContext->bEndOfStreamFlag = false; | |
| 744 | + pDecContext->bEndOfStreamFlag = false; | |
| 543 | 745 | } else { |
| 544 | 746 | //For application MODE, the error detection should be added for safe. |
| 545 | 747 | //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL. |
| 546 | − m_pDecContext->bEndOfStreamFlag = true; | |
| 547 | − m_pDecContext->bInstantDecFlag = true; | |
| 748 | + pDecContext->bEndOfStreamFlag = true; | |
| 749 | + pDecContext->bInstantDecFlag = true; | |
| 548 | 750 | } |
| 549 | 751 | |
| 550 | 752 | int64_t iStart, iEnd; |
| 551 | 753 | iStart = WelsTime(); |
| 552 | 754 | |
| 553 | − ppDst[0] = ppDst[1] = ppDst[2] = NULL; | |
| 554 | − m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. | |
| 555 | − m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize | |
| 755 | + if (pDecContext->pThreadCtx == NULL) { | |
| 756 | + ppDst[0] = ppDst[1] = ppDst[2] = NULL; | |
| 757 | + } | |
| 758 | + pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. | |
| 759 | + pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize | |
| 556 | 760 | unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp; |
| 557 | − memset (pDstInfo, 0, sizeof (SBufferInfo)); | |
| 761 | + if (pDecContext->pThreadCtx == NULL) { | |
| 762 | + memset (pDstInfo, 0, sizeof (SBufferInfo)); | |
| 763 | + } | |
| 558 | 764 | pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp; |
| 559 | 765 | #ifdef LONG_TERM_REF |
| 560 | − m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR | |
| 561 | − m_pDecContext->bCurAuContainLtrMarkSeFlag = false; | |
| 562 | − m_pDecContext->iFrameNumOfAuMarkedLtr = 0; | |
| 563 | − m_pDecContext->iFrameNum = -1; //initialize | |
| 766 | + pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR | |
| 767 | + pDecContext->bCurAuContainLtrMarkSeFlag = false; | |
| 768 | + pDecContext->iFrameNumOfAuMarkedLtr = 0; | |
| 769 | + pDecContext->iFrameNum = -1; //initialize | |
| 564 | 770 | #endif |
| 565 | 771 | |
| 566 | − m_pDecContext->iFeedbackTidInAu = -1; //initialize | |
| 567 | − m_pDecContext->iFeedbackNalRefIdc = -1; //initialize | |
| 772 | + pDecContext->iFeedbackTidInAu = -1; //initialize | |
| 773 | + pDecContext->iFeedbackNalRefIdc = -1; //initialize | |
| 568 | 774 | if (pDstInfo) { |
| 569 | 775 | pDstInfo->uiOutYuvTimeStamp = 0; |
| 570 | − m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; | |
| 776 | + pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; | |
| 571 | 777 | } else { |
| 572 | − m_pDecContext->uiTimeStamp = 0; | |
| 778 | + pDecContext->uiTimeStamp = 0; | |
| 573 | 779 | } |
| 574 | − WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst, | |
| 780 | + WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, ppDst, | |
| 575 | 781 | pDstInfo, NULL); //iErrorCode has been modified in this function |
| 576 | − m_pDecContext->bInstantDecFlag = false; //reset no-delay flag | |
| 577 | − if (m_pDecContext->iErrorCode) { | |
| 782 | + pDecContext->bInstantDecFlag = false; //reset no-delay flag | |
| 783 | + if (pDecContext->iErrorCode) { | |
| 578 | 784 | EWelsNalUnitType eNalType = |
| 579 | 785 | NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently |
| 580 | 786 | |
| 581 | − eNalType = m_pDecContext->sCurNalHead.eNalUnitType; | |
| 582 | − if (m_pDecContext->iErrorCode & dsOutOfMemory) { | |
| 583 | − if (ResetDecoder()) { | |
| 787 | + eNalType = pDecContext->sCurNalHead.eNalUnitType; | |
| 788 | + if (pDecContext->iErrorCode & dsOutOfMemory) { | |
| 789 | + if (ResetDecoder (pDecContext)) { | |
| 584 | 790 | return dsOutOfMemory; |
| 585 | 791 | } |
| 586 | 792 | return dsErrorFree; |
| 587 | 793 | } |
| 588 | − if (m_pDecContext->iErrorCode & dsRefListNullPtrs) { | |
| 589 | − if (ResetDecoder()) { | |
| 794 | + if (pDecContext->iErrorCode & dsRefListNullPtrs) { | |
| 795 | + if (ResetDecoder (pDecContext)) { | |
| 590 | 796 | return dsRefListNullPtrs; |
| 591 | 797 | } |
| 592 | 798 | return dsErrorFree; |
| 593 | 799 | } |
| 594 | − if ((m_pDecContext->iErrorCode & (dsBitstreamError | dsDataErrorConcealed)) && m_pDecContext->eSliceType == B_SLICE) { | |
| 595 | − if (ResetDecoder()) { | |
| 800 | + if ((pDecContext->iErrorCode & (dsBitstreamError | dsDataErrorConcealed)) && pDecContext->eSliceType == B_SLICE) { | |
| 801 | + if (ResetDecoder (pDecContext)) { | |
| 596 | 802 | pDstInfo->iBufferStatus = 0; |
| 597 | − return (DECODING_STATE)m_pDecContext->iErrorCode; | |
| 803 | + return (DECODING_STATE)pDecContext->iErrorCode; | |
| 598 | 804 | } |
| 599 | 805 | return dsErrorFree; |
| 600 | 806 | } |
| 601 | 807 | //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss. |
| 602 | 808 | if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) || |
| 603 | − (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) { | |
| 604 | − if (m_pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 809 | + (VIDEO_BITSTREAM_AVC == pDecContext->eVideoType)) { | |
| 810 | + if (pDecContext->pParam->eEcActiveIdc == ERROR_CON_DISABLE) { | |
| 605 | 811 | #ifdef LONG_TERM_REF |
| 606 | − m_pDecContext->bParamSetsLostFlag = true; | |
| 812 | + pDecContext->bParamSetsLostFlag = true; | |
| 607 | 813 | #else |
| 608 | − m_pDecContext->bReferenceLostAtT0Flag = true; | |
| 814 | + pDecContext->bReferenceLostAtT0Flag = true; | |
| 609 | 815 | #endif |
| 610 | 816 | } |
| 611 | 817 | } |
| 612 | 818 | |
| 613 | − if (m_pDecContext->bPrintFrameErrorTraceFlag) { | |
| 819 | + if (pDecContext->bPrintFrameErrorTraceFlag) { | |
| 614 | 820 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", |
| 615 | − m_pDecContext->iErrorCode); | |
| 616 | − m_pDecContext->bPrintFrameErrorTraceFlag = false; | |
| 821 | + pDecContext->iErrorCode); | |
| 822 | + pDecContext->bPrintFrameErrorTraceFlag = false; | |
| 617 | 823 | } else { |
| 618 | − m_pDecContext->iIgnoredErrorInfoPacketCount++; | |
| 619 | − if (m_pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) { | |
| 824 | + pDecContext->iIgnoredErrorInfoPacketCount++; | |
| 825 | + if (pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) { | |
| 620 | 826 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0."); |
| 621 | − m_pDecContext->iIgnoredErrorInfoPacketCount = 0; | |
| 827 | + pDecContext->iIgnoredErrorInfoPacketCount = 0; | |
| 622 | 828 | } |
| 623 | 829 | } |
| 624 | − if ((m_pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) { | |
| 830 | + if ((pDecContext->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) { | |
| 625 | 831 | //TODO after dec status updated |
| 626 | − m_pDecContext->iErrorCode |= dsDataErrorConcealed; | |
| 832 | + pDecContext->iErrorCode |= dsDataErrorConcealed; | |
| 627 | 833 | |
| 628 | − m_pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 629 | − if (m_pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t | |
| 630 | − ResetDecStatNums (m_pDecContext->pDecoderStatistics); | |
| 631 | − m_pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 834 | + pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 835 | + if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t | |
| 836 | + ResetDecStatNums (pDecContext->pDecoderStatistics); | |
| 837 | + pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 632 | 838 | } |
| 633 | − int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum; | |
| 634 | − m_pDecContext->pDecoderStatistics->uiAvgEcRatio = m_pDecContext->iMbNum == 0 ? | |
| 635 | − (m_pDecContext->pDecoderStatistics->uiAvgEcRatio * m_pDecContext->pDecoderStatistics->uiEcFrameNum) : (( | |
| 636 | − m_pDecContext->pDecoderStatistics->uiAvgEcRatio * m_pDecContext->pDecoderStatistics->uiEcFrameNum) + (( | |
| 637 | − iMbConcealedNum * 100) / m_pDecContext->iMbNum)); | |
| 638 | − m_pDecContext->pDecoderStatistics->uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ? | |
| 639 | − (m_pDecContext->pDecoderStatistics->uiAvgEcPropRatio * m_pDecContext->pDecoderStatistics->uiEcFrameNum) : (( | |
| 640 | − m_pDecContext->pDecoderStatistics->uiAvgEcPropRatio * m_pDecContext->pDecoderStatistics->uiEcFrameNum) + (( | |
| 641 | − m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum)); | |
| 642 | − m_pDecContext->pDecoderStatistics->uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1); | |
| 643 | − m_pDecContext->pDecoderStatistics->uiAvgEcRatio = m_pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 : | |
| 644 | − m_pDecContext->pDecoderStatistics->uiAvgEcRatio / m_pDecContext->pDecoderStatistics->uiEcFrameNum; | |
| 645 | − m_pDecContext->pDecoderStatistics->uiAvgEcPropRatio = m_pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 : | |
| 646 | − m_pDecContext->pDecoderStatistics->uiAvgEcPropRatio / m_pDecContext->pDecoderStatistics->uiEcFrameNum; | |
| 839 | + int32_t iMbConcealedNum = pDecContext->iMbEcedNum + pDecContext->iMbEcedPropNum; | |
| 840 | + pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->iMbNum == 0 ? | |
| 841 | + (pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : (( | |
| 842 | + pDecContext->pDecoderStatistics->uiAvgEcRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + (( | |
| 843 | + iMbConcealedNum * 100) / pDecContext->iMbNum)); | |
| 844 | + pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->iMbNum == 0 ? | |
| 845 | + (pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) : (( | |
| 846 | + pDecContext->pDecoderStatistics->uiAvgEcPropRatio * pDecContext->pDecoderStatistics->uiEcFrameNum) + (( | |
| 847 | + pDecContext->iMbEcedPropNum * 100) / pDecContext->iMbNum)); | |
| 848 | + pDecContext->pDecoderStatistics->uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1); | |
| 849 | + pDecContext->pDecoderStatistics->uiAvgEcRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 : | |
| 850 | + pDecContext->pDecoderStatistics->uiAvgEcRatio / pDecContext->pDecoderStatistics->uiEcFrameNum; | |
| 851 | + pDecContext->pDecoderStatistics->uiAvgEcPropRatio = pDecContext->pDecoderStatistics->uiEcFrameNum == 0 ? 0 : | |
| 852 | + pDecContext->pDecoderStatistics->uiAvgEcPropRatio / pDecContext->pDecoderStatistics->uiEcFrameNum; | |
| 647 | 853 | } |
| 648 | 854 | iEnd = WelsTime(); |
| 649 | − m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; | |
| 855 | + pDecContext->dDecTime += (iEnd - iStart) / 1e3; | |
| 650 | 856 | |
| 651 | − OutputStatisticsLog (*m_pDecContext->pDecoderStatistics); | |
| 857 | + OutputStatisticsLog (*pDecContext->pDecoderStatistics); | |
| 652 | 858 | |
| 653 | −#ifdef _PICTURE_REORDERING_ | |
| 654 | − ReorderPicturesInDisplay (ppDst, pDstInfo); | |
| 655 | −#endif | |
| 859 | + if (pDecContext->pThreadCtx != NULL) { | |
| 860 | + WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 861 | + RESET_EVENT (&m_sBufferingEvent); | |
| 862 | + BufferingReadyPicture (pDecContext, ppDst, pDstInfo); | |
| 863 | + SET_EVENT (&m_sBufferingEvent); | |
| 864 | + } else { | |
| 865 | + ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo); | |
| 866 | + } | |
| 656 | 867 | |
| 657 | − return (DECODING_STATE)m_pDecContext->iErrorCode; | |
| 868 | + return (DECODING_STATE)pDecContext->iErrorCode; | |
| 658 | 869 | } |
| 659 | 870 | // else Error free, the current codec works well |
| 660 | 871 | |
| 661 | 872 | if (pDstInfo->iBufferStatus == 1) { |
| 662 | 873 | |
| 663 | − m_pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 664 | − if (m_pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t | |
| 665 | − ResetDecStatNums (m_pDecContext->pDecoderStatistics); | |
| 666 | − m_pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 874 | + pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 875 | + if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t | |
| 876 | + ResetDecStatNums (pDecContext->pDecoderStatistics); | |
| 877 | + pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 667 | 878 | } |
| 668 | 879 | |
| 669 | − OutputStatisticsLog (*m_pDecContext->pDecoderStatistics); | |
| 880 | + OutputStatisticsLog (*pDecContext->pDecoderStatistics); | |
| 670 | 881 | } |
| 671 | 882 | iEnd = WelsTime(); |
| 672 | − m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; | |
| 883 | + pDecContext->dDecTime += (iEnd - iStart) / 1e3; | |
| 673 | 884 | |
| 674 | −#ifdef _PICTURE_REORDERING_ | |
| 675 | − ReorderPicturesInDisplay (ppDst, pDstInfo); | |
| 676 | −#endif | |
| 885 | + if (pDecContext->pThreadCtx != NULL) { | |
| 886 | + WAIT_EVENT (&m_sReleaseBufferEvent, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 887 | + RESET_EVENT (&m_sBufferingEvent); | |
| 888 | + BufferingReadyPicture (pDecContext, ppDst, pDstInfo); | |
| 889 | + SET_EVENT (&m_sBufferingEvent); | |
| 890 | + } else { | |
| 891 | + ReorderPicturesInDisplay (pDecContext, ppDst, pDstInfo); | |
| 892 | + } | |
| 677 | 893 | return dsErrorFree; |
| 678 | 894 | } |
| 679 | 895 | |
| 896 | +DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, | |
| 897 | + const int kiSrcLen, | |
| 898 | + unsigned char** ppDst, | |
| 899 | + SBufferInfo* pDstInfo) { | |
| 900 | + PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx; | |
| 901 | + return DecodeFrame2WithCtx (pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo); | |
| 902 | +} | |
| 903 | + | |
| 680 | 904 | DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst, |
| 681 | 905 | SBufferInfo* pDstInfo) { |
| 682 | − if (m_pDecContext->bEndOfStreamFlag && m_sReoderingStatus.iNumOfPicts > 0) { | |
| 906 | + bool bEndOfStreamFlag = true; | |
| 907 | + for (int32_t j = 0; j < m_iThreadCount; ++j) { | |
| 908 | + if (!m_pDecThrCtx[j].pCtx->bEndOfStreamFlag) { | |
| 909 | + bEndOfStreamFlag = false; | |
| 910 | + } | |
| 911 | + } | |
| 912 | + if (bEndOfStreamFlag && m_sReoderingStatus.iNumOfPicts > 0) { | |
| 683 | 913 | m_sReoderingStatus.iMinPOC = IMinInt32; |
| 684 | 914 | for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { |
| 685 | 915 | if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) { |
| @@ -704,12 +934,15 @@ DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst, · 18 unmodified lines | ||
| 704 | 934 | ppDst[1] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[1]; |
| 705 | 935 | ppDst[2] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[2]; |
| 706 | 936 | m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; |
| 707 | − if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) | |
| 708 | − m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 937 | + PPicBuff pPicBuff = m_iThreadCount == 1 ? m_pDecThrCtx[0].pCtx->pPicBuff : m_pPicBuff; | |
| 938 | + if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx < pPicBuff->iCapacity) { | |
| 939 | + pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 940 | + } | |
| 709 | 941 | m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; |
| 710 | 942 | m_sReoderingStatus.iMinPOC = IMinInt32; |
| 711 | 943 | --m_sReoderingStatus.iNumOfPicts; |
| 712 | 944 | } |
| 945 | + | |
| 713 | 946 | return dsErrorFree; |
| 714 | 947 | } |
| 715 | 948 | |
| @@ -758,24 +991,15 @@ void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) · 42 unmodified lines | ||
| 758 | 991 | } |
| 759 | 992 | } |
| 760 | 993 | |
| 761 | −DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo) { | |
| 762 | − DECODING_STATE iRet = dsErrorFree; | |
| 994 | +void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst, | |
| 995 | + SBufferInfo* pDstInfo) { | |
| 763 | 996 | if (pDstInfo->iBufferStatus == 0) { |
| 764 | − return iRet; | |
| 997 | + return; | |
| 765 | 998 | } |
| 766 | − ++m_pDecContext->uiDecodingTimeStamp; | |
| 767 | − if (m_pDecContext->pSps->uiProfileIdc != 66 && m_pDecContext->pSps->uiProfileIdc != 83) { | |
| 768 | − /*if (m_pDecContext->pSliceHeader->iPicOrderCntLsb == 0) { | |
| 769 | − m_sReoderingStatus.iLastWrittenPOC = 0; | |
| 770 | − return dsErrorFree; | |
| 771 | − } | |
| 772 | − if (m_sReoderingStatus.iNumOfPicts == 0 && m_pDecContext->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin | |
| 773 | − && m_pDecContext->eSliceType != I_SLICE) { | |
| 774 | − m_sReoderingStatus.iLastWrittenPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb; | |
| 775 | − return dsErrorFree; | |
| 776 | − }*/ | |
| 777 | − if (m_sReoderingStatus.iNumOfPicts && m_pDecContext->pLastDecPicInfo->pPreviousDecodedPictureInDpb | |
| 778 | − && m_pDecContext->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) { | |
| 999 | + m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83; | |
| 1000 | + if (!m_bIsBaseline) { | |
| 1001 | + if (m_sReoderingStatus.iNumOfPicts && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb | |
| 1002 | + && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) { | |
| 779 | 1003 | m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts; |
| 780 | 1004 | for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { |
| 781 | 1005 | if (m_sPictInfoList[i].iPOC > IMinInt32) { |
| @@ -787,7 +1011,7 @@ DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SB · 5 unmodified lines | ||
| 787 | 1011 | //This can happen when decoder moves to next GOP without being able to decoder first picture PicOrderCntLsb = 0 |
| 788 | 1012 | bool hasGOPChanged = false; |
| 789 | 1013 | for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { |
| 790 | − if (m_sPictInfoList[i].iPOC == m_pDecContext->pSliceHeader->iPicOrderCntLsb) { | |
| 1014 | + if (m_sPictInfoList[i].iPOC == pCtx->pSliceHeader->iPicOrderCntLsb) { | |
| 791 | 1015 | hasGOPChanged = true; |
| 792 | 1016 | break; |
| 793 | 1017 | } |
| @@ -802,119 +1026,167 @@ DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SB · 8 unmodified lines | ||
| 802 | 1026 | } |
| 803 | 1027 | } |
| 804 | 1028 | } |
| 805 | − for (int32_t i = 0; i < 16; ++i) { | |
| 806 | − if (m_sPictInfoList[i].iPOC == IMinInt32) { | |
| 807 | − memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo)); | |
| 808 | − m_sPictInfoList[i].pData[0] = ppDst[0]; | |
| 809 | − m_sPictInfoList[i].pData[1] = ppDst[1]; | |
| 810 | − m_sPictInfoList[i].pData[2] = ppDst[2]; | |
| 811 | − m_sPictInfoList[i].iPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb; | |
| 812 | − m_sPictInfoList[i].uiDecodingTimeStamp = m_pDecContext->uiDecodingTimeStamp; | |
| 813 | − m_sPictInfoList[i].iPicBuffIdx = m_pDecContext->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx; | |
| 814 | − m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[i].iPicBuffIdx]->bAvailableFlag = false; | |
| 815 | − m_sPictInfoList[i].bLastGOP = false; | |
| 816 | − pDstInfo->iBufferStatus = 0; | |
| 817 | − ++m_sReoderingStatus.iNumOfPicts; | |
| 818 | − if (i > m_sReoderingStatus.iLargestBufferedPicIndex) { | |
| 819 | − m_sReoderingStatus.iLargestBufferedPicIndex = i; | |
| 820 | − } | |
| 821 | − break; | |
| 1029 | + } | |
| 1030 | + for (int32_t i = 0; i < 16; ++i) { | |
| 1031 | + if (m_sPictInfoList[i].iPOC == IMinInt32) { | |
| 1032 | + memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo)); | |
| 1033 | + m_sPictInfoList[i].pData[0] = ppDst[0]; | |
| 1034 | + m_sPictInfoList[i].pData[1] = ppDst[1]; | |
| 1035 | + m_sPictInfoList[i].pData[2] = ppDst[2]; | |
| 1036 | + m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb; | |
| 1037 | + m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp; | |
| 1038 | + m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx; | |
| 1039 | + pCtx->pPicBuff->ppPic[m_sPictInfoList[i].iPicBuffIdx]->bAvailableFlag = false; | |
| 1040 | + m_sPictInfoList[i].bLastGOP = false; | |
| 1041 | + pDstInfo->iBufferStatus = 0; | |
| 1042 | + ++m_sReoderingStatus.iNumOfPicts; | |
| 1043 | + if (i > m_sReoderingStatus.iLargestBufferedPicIndex) { | |
| 1044 | + m_sReoderingStatus.iLargestBufferedPicIndex = i; | |
| 822 | 1045 | } |
| 1046 | + break; | |
| 823 | 1047 | } |
| 824 | − if (m_sReoderingStatus.iLastGOPRemainPicts > 0) { | |
| 825 | − m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 826 | − for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { | |
| 827 | − if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) { | |
| 828 | − m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 829 | − m_sReoderingStatus.iPictInfoIndex = i; | |
| 830 | − } | |
| 831 | − if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC | |
| 832 | − && m_sPictInfoList[i].bLastGOP) { | |
| 833 | − m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 834 | − m_sReoderingStatus.iPictInfoIndex = i; | |
| 835 | − } | |
| 1048 | + } | |
| 1049 | +} | |
| 1050 | + | |
| 1051 | +void CWelsDecoder::ReleaseBufferedReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst, | |
| 1052 | + SBufferInfo* pDstInfo) { | |
| 1053 | + PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff; | |
| 1054 | + if (!m_bIsBaseline && m_sReoderingStatus.iLastGOPRemainPicts > 0) { | |
| 1055 | + m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 1056 | + for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { | |
| 1057 | + if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) { | |
| 1058 | + m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 1059 | + m_sReoderingStatus.iPictInfoIndex = i; | |
| 836 | 1060 | } |
| 837 | − m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC; | |
| 1061 | + if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC | |
| 1062 | + && m_sPictInfoList[i].bLastGOP) { | |
| 1063 | + m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 1064 | + m_sReoderingStatus.iPictInfoIndex = i; | |
| 1065 | + } | |
| 1066 | + } | |
| 1067 | + m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC; | |
| 838 | 1068 | #if defined (_DEBUG) |
| 839 | 1069 | #ifdef _MOTION_VECTOR_DUMP_ |
| 840 | − fprintf (stderr, "Output POC: #%d\n", m_sReoderingStatus.iLastWrittenPOC); | |
| 1070 | + fprintf (stderr, "Output POC: #%d\n", m_sReoderingStatus.iLastWrittenPOC); | |
| 841 | 1071 | #endif |
| 842 | 1072 | #endif |
| 1073 | + memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); | |
| 1074 | + ppDst[0] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[0]; | |
| 1075 | + ppDst[1] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[1]; | |
| 1076 | + ppDst[2] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[2]; | |
| 1077 | + m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; | |
| 1078 | + pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 1079 | + m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; | |
| 1080 | + m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 1081 | + --m_sReoderingStatus.iNumOfPicts; | |
| 1082 | + --m_sReoderingStatus.iLastGOPRemainPicts; | |
| 1083 | + if (m_sReoderingStatus.iLastGOPRemainPicts == 0) { | |
| 1084 | + m_sReoderingStatus.iLastWrittenPOC = IMinInt32; | |
| 1085 | + } | |
| 1086 | + return; | |
| 1087 | + } | |
| 1088 | + if (m_sReoderingStatus.iNumOfPicts && m_bIsBaseline) { | |
| 1089 | + uint32_t uiDecodingTimeStamp = 0; | |
| 1090 | + for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { | |
| 1091 | + if (m_sPictInfoList[i].iPOC > IMinInt32) { | |
| 1092 | + uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp; | |
| 1093 | + m_sReoderingStatus.iPictInfoIndex = i; | |
| 1094 | + break; | |
| 1095 | + } | |
| 1096 | + } | |
| 1097 | + for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { | |
| 1098 | + if (m_sReoderingStatus.iPictInfoIndex != i && m_sPictInfoList[i].iPOC > IMinInt32 | |
| 1099 | + && m_sPictInfoList[i].sBufferInfo.uiInBsTimeStamp < uiDecodingTimeStamp) { | |
| 1100 | + uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp; | |
| 1101 | + m_sReoderingStatus.iPictInfoIndex = i; | |
| 1102 | + } | |
| 1103 | + } | |
| 1104 | + if (uiDecodingTimeStamp > 0) { | |
| 843 | 1105 | memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); |
| 844 | 1106 | ppDst[0] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[0]; |
| 845 | 1107 | ppDst[1] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[1]; |
| 846 | 1108 | ppDst[2] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[2]; |
| 847 | 1109 | m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; |
| 848 | − if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) | |
| 849 | − m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 850 | − m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; | |
| 851 | − m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 1110 | + pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 852 | 1111 | --m_sReoderingStatus.iNumOfPicts; |
| 853 | − --m_sReoderingStatus.iLastGOPRemainPicts; | |
| 854 | − if (m_sReoderingStatus.iLastGOPRemainPicts == 0) { | |
| 855 | − m_sReoderingStatus.iLastWrittenPOC = IMinInt32; | |
| 856 | − } | |
| 857 | − return iRet; | |
| 858 | 1112 | } |
| 859 | − if (m_sReoderingStatus.iNumOfPicts > 0) { | |
| 860 | − m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 861 | − for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { | |
| 862 | − if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) { | |
| 863 | − m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 864 | − m_sReoderingStatus.iPictInfoIndex = i; | |
| 865 | − } | |
| 866 | − if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) { | |
| 867 | − m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 868 | − m_sReoderingStatus.iPictInfoIndex = i; | |
| 869 | − } | |
| 1113 | + return; | |
| 1114 | + } | |
| 1115 | + if (m_sReoderingStatus.iNumOfPicts > 0) { | |
| 1116 | + m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 1117 | + for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { | |
| 1118 | + if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) { | |
| 1119 | + m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 1120 | + m_sReoderingStatus.iPictInfoIndex = i; | |
| 870 | 1121 | } |
| 1122 | + if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) { | |
| 1123 | + m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; | |
| 1124 | + m_sReoderingStatus.iPictInfoIndex = i; | |
| 1125 | + } | |
| 1126 | + } | |
| 1127 | + } | |
| 1128 | + if (m_sReoderingStatus.iMinPOC > IMinInt32) { | |
| 1129 | + bool isReady = false; | |
| 1130 | + if (pCtx != NULL) { | |
| 1131 | + isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32 | |
| 1132 | + && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1) | |
| 1133 | + || m_sReoderingStatus.iMinPOC < pCtx->pSliceHeader->iPicOrderCntLsb; | |
| 1134 | + } else { | |
| 1135 | + isReady = m_sReoderingStatus.iMinPOC == 0 || (m_sReoderingStatus.iLastWrittenPOC >= 0 | |
| 1136 | + && m_sReoderingStatus.iMinPOC <= m_sReoderingStatus.iLastWrittenPOC + 2) ; | |
| 871 | 1137 | } |
| 872 | − if (m_sReoderingStatus.iMinPOC > IMinInt32) { | |
| 873 | − if ((m_sReoderingStatus.iLastWrittenPOC > IMinInt32 | |
| 874 | − && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1) | |
| 875 | − || m_sReoderingStatus.iMinPOC < m_pDecContext->pSliceHeader->iPicOrderCntLsb) { | |
| 876 | − m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC; | |
| 1138 | + if (isReady) { | |
| 1139 | + m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC; | |
| 877 | 1140 | #if defined (_DEBUG) |
| 878 | 1141 | #ifdef _MOTION_VECTOR_DUMP_ |
| 879 | − fprintf (stderr, "Output POC: #%d\n", m_sReoderingStatus.iLastWrittenPOC); | |
| 1142 | + fprintf (stderr, "Output POC: #%d\n", m_sReoderingStatus.iLastWrittenPOC); | |
| 880 | 1143 | #endif |
| 881 | 1144 | #endif |
| 882 | − memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); | |
| 883 | − ppDst[0] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[0]; | |
| 884 | − ppDst[1] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[1]; | |
| 885 | − ppDst[2] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[2]; | |
| 886 | − m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; | |
| 887 | − if (m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) | |
| 888 | − m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 889 | − m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; | |
| 890 | − m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 891 | − --m_sReoderingStatus.iNumOfPicts; | |
| 892 | − return iRet; | |
| 893 | − } | |
| 1145 | + memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); | |
| 1146 | + ppDst[0] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[0]; | |
| 1147 | + ppDst[1] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[1]; | |
| 1148 | + ppDst[2] = m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].pData[2]; | |
| 1149 | + m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; | |
| 1150 | + pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; | |
| 1151 | + m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; | |
| 1152 | + m_sReoderingStatus.iMinPOC = IMinInt32; | |
| 1153 | + --m_sReoderingStatus.iNumOfPicts; | |
| 894 | 1154 | } |
| 895 | 1155 | } |
| 1156 | +} | |
| 896 | 1157 | |
| 1158 | +DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (PWelsDecoderContext pDecContext, unsigned char** ppDst, | |
| 1159 | + SBufferInfo* pDstInfo) { | |
| 1160 | + DECODING_STATE iRet = dsErrorFree; | |
| 1161 | + if (pDstInfo->iBufferStatus == 1) { | |
| 1162 | + ++pDecContext->uiDecodingTimeStamp; | |
| 1163 | + m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83; | |
| 1164 | + if (!m_bIsBaseline) { | |
| 1165 | + BufferingReadyPicture (pDecContext, ppDst, pDstInfo); | |
| 1166 | + ReleaseBufferedReadyPicture (pDecContext, ppDst, pDstInfo); | |
| 1167 | + } | |
| 1168 | + } | |
| 897 | 1169 | return iRet; |
| 898 | 1170 | } |
| 899 | 1171 | |
| 900 | −DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, | |
| 901 | − const int kiSrcLen, | |
| 902 | − SParserBsInfo* pDstInfo) { | |
| 903 | − if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) { | |
| 1172 | +DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) { | |
| 1173 | + PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx; | |
| 1174 | + | |
| 1175 | + if (pDecContext == NULL || pDecContext->pParam == NULL) { | |
| 904 | 1176 | if (m_pWelsTrace != NULL) { |
| 905 | 1177 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n"); |
| 906 | 1178 | } |
| 907 | 1179 | return dsInitialOptExpected; |
| 908 | 1180 | } |
| 909 | 1181 | |
| 910 | − if (!m_pDecContext->pParam->bParseOnly) { | |
| 1182 | + if (!pDecContext->pParam->bParseOnly) { | |
| 911 | 1183 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n"); |
| 912 | − m_pDecContext->iErrorCode |= dsInvalidArgument; | |
| 1184 | + pDecContext->iErrorCode |= dsInvalidArgument; | |
| 913 | 1185 | return dsInvalidArgument; |
| 914 | 1186 | } |
| 915 | 1187 | int64_t iEnd, iStart = WelsTime(); |
| 916 | − if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { | |
| 917 | − if (ResetDecoder()) | |
| 1188 | + if (CheckBsBuffer (pDecContext, kiSrcLen)) { | |
| 1189 | + if (ResetDecoder (pDecContext)) | |
| 918 | 1190 | return dsOutOfMemory; |
| 919 | 1191 | |
| 920 | 1192 | return dsErrorFree; |
| @@ -926,58 +1198,57 @@ DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, · 5 unmodified lines | ||
| 926 | 1198 | WelsFflush (m_pFBS); |
| 927 | 1199 | } |
| 928 | 1200 | #endif//OUTPUT_BIT_STREAM |
| 929 | − m_pDecContext->bEndOfStreamFlag = false; | |
| 1201 | + pDecContext->bEndOfStreamFlag = false; | |
| 930 | 1202 | } else { |
| 931 | 1203 | //For application MODE, the error detection should be added for safe. |
| 932 | 1204 | //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL. |
| 933 | − m_pDecContext->bEndOfStreamFlag = true; | |
| 934 | − m_pDecContext->bInstantDecFlag = true; | |
| 1205 | + pDecContext->bEndOfStreamFlag = true; | |
| 1206 | + pDecContext->bInstantDecFlag = true; | |
| 935 | 1207 | } |
| 936 | 1208 | |
| 937 | − m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. | |
| 938 | − m_pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here. | |
| 939 | − m_pDecContext->iFeedbackNalRefIdc = -1; //initialize | |
| 940 | − if (!m_pDecContext->bFramePending) { //frame complete | |
| 941 | − m_pDecContext->pParserBsInfo->iNalNum = 0; | |
| 942 | − memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER); | |
| 1209 | + pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. | |
| 1210 | + pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here. | |
| 1211 | + pDecContext->iFeedbackNalRefIdc = -1; //initialize | |
| 1212 | + if (!pDecContext->bFramePending) { //frame complete | |
| 1213 | + pDecContext->pParserBsInfo->iNalNum = 0; | |
| 1214 | + memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER); | |
| 943 | 1215 | } |
| 944 | 1216 | pDstInfo->iNalNum = 0; |
| 945 | 1217 | pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0; |
| 946 | 1218 | if (pDstInfo) { |
| 947 | − m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; | |
| 1219 | + pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; | |
| 948 | 1220 | pDstInfo->uiOutBsTimeStamp = 0; |
| 949 | 1221 | } else { |
| 950 | − m_pDecContext->uiTimeStamp = 0; | |
| 1222 | + pDecContext->uiTimeStamp = 0; | |
| 951 | 1223 | } |
| 952 | − WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo); | |
| 953 | − if (m_pDecContext->iErrorCode & dsOutOfMemory) { | |
| 954 | − if (ResetDecoder()) | |
| 1224 | + WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo); | |
| 1225 | + if (pDecContext->iErrorCode & dsOutOfMemory) { | |
| 1226 | + if (ResetDecoder (pDecContext)) | |
| 955 | 1227 | return dsOutOfMemory; |
| 956 | 1228 | return dsErrorFree; |
| 957 | 1229 | } |
| 958 | 1230 | |
| 959 | − if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) { | |
| 960 | − memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); | |
| 1231 | + if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) { | |
| 1232 | + memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); | |
| 961 | 1233 | |
| 962 | − if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count | |
| 963 | − m_pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 964 | − if (m_pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t | |
| 965 | − ResetDecStatNums (m_pDecContext->pDecoderStatistics); | |
| 966 | − m_pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 1234 | + if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count | |
| 1235 | + pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 1236 | + if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t | |
| 1237 | + ResetDecStatNums (pDecContext->pDecoderStatistics); | |
| 1238 | + pDecContext->pDecoderStatistics->uiDecodedFrameCount++; | |
| 967 | 1239 | } |
| 968 | 1240 | } |
| 969 | 1241 | } |
| 970 | 1242 | |
| 971 | − m_pDecContext->bInstantDecFlag = false; //reset no-delay flag | |
| 1243 | + pDecContext->bInstantDecFlag = false; //reset no-delay flag | |
| 972 | 1244 | |
| 973 | − if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) { | |
| 974 | − WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode); | |
| 975 | − m_pDecContext->bPrintFrameErrorTraceFlag = false; | |
| 1245 | + if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) { | |
| 1246 | + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode); | |
| 1247 | + pDecContext->bPrintFrameErrorTraceFlag = false; | |
| 976 | 1248 | } |
| 977 | 1249 | iEnd = WelsTime(); |
| 978 | − m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; | |
| 979 | − | |
| 980 | − return (DECODING_STATE) m_pDecContext->iErrorCode; | |
| 1250 | + pDecContext->dDecTime += (iEnd - iStart) / 1e3; | |
| 1251 | + return (DECODING_STATE)pDecContext->iErrorCode; | |
| 981 | 1252 | } |
| 982 | 1253 | |
| 983 | 1254 | DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc, |
| @@ -1019,6 +1290,92 @@ DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc, · 35 unmodified lines | ||
| 1019 | 1290 | return state; |
| 1020 | 1291 | } |
| 1021 | 1292 | |
| 1293 | +DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) { | |
| 1294 | + sThreadCtx.pCtx->bHasNewSps = false; | |
| 1295 | + sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag; | |
| 1296 | + sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput; | |
| 1297 | + sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp; | |
| 1298 | + bool bPicBuffChanged = false; | |
| 1299 | + if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) { | |
| 1300 | + CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx); | |
| 1301 | + sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber; | |
| 1302 | + if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) { | |
| 1303 | + bPicBuffChanged = true; | |
| 1304 | + sThreadCtx.pCtx->pPicBuff = m_pPicBuff; | |
| 1305 | + sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL; | |
| 1306 | + sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel; | |
| 1307 | + sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel; | |
| 1308 | + } | |
| 1309 | + } | |
| 1310 | + int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst, | |
| 1311 | + &sThreadCtx.sDstInfo); | |
| 1312 | + | |
| 1313 | + int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo); | |
| 1314 | + if (ERR_NONE != iErr) { | |
| 1315 | + return (DECODING_STATE) (iRet | iErr); | |
| 1316 | + } | |
| 1317 | + if (sThreadCtx.pCtx->bNewSeqBegin) { | |
| 1318 | + m_pPicBuff = sThreadCtx.pCtx->pPicBuff; | |
| 1319 | + } else if (bPicBuffChanged) { | |
| 1320 | + InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4); | |
| 1321 | + } | |
| 1322 | + m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag; | |
| 1323 | + m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput; | |
| 1324 | + return (DECODING_STATE)iErr; | |
| 1325 | +} | |
| 1326 | +/* | |
| 1327 | +* Run decoding picture in separate thread. | |
| 1328 | +*/ | |
| 1329 | + | |
| 1330 | +int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, | |
| 1331 | + SBufferInfo* pDstInfo) { | |
| 1332 | + int state = dsErrorFree; | |
| 1333 | + int32_t i, j; | |
| 1334 | + int32_t signal = 0; | |
| 1335 | + | |
| 1336 | + //serial using of threads | |
| 1337 | + if (m_DecCtxActiveCount < m_iThreadCount) { | |
| 1338 | + signal = m_DecCtxActiveCount; | |
| 1339 | + } else { | |
| 1340 | + signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum; | |
| 1341 | + } | |
| 1342 | + | |
| 1343 | + WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 1344 | + | |
| 1345 | + for (i = 0; i < m_DecCtxActiveCount; ++i) { | |
| 1346 | + if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) { | |
| 1347 | + m_pDecThrCtxActive[i] = NULL; | |
| 1348 | + for (j = i; j < m_DecCtxActiveCount - 1; j++) { | |
| 1349 | + m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1]; | |
| 1350 | + m_pDecThrCtxActive[j + 1] = NULL; | |
| 1351 | + } | |
| 1352 | + --m_DecCtxActiveCount; | |
| 1353 | + break; | |
| 1354 | + } | |
| 1355 | + } | |
| 1356 | + | |
| 1357 | + m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal]; | |
| 1358 | + if (m_pLastDecThrCtx != NULL) { | |
| 1359 | + m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx; | |
| 1360 | + } | |
| 1361 | + m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc); | |
| 1362 | + m_pDecThrCtx[signal].kiSrcLen = kiSrcLen; | |
| 1363 | + m_pDecThrCtx[signal].ppDst = ppDst; | |
| 1364 | + memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo)); | |
| 1365 | + | |
| 1366 | + ParseAccessUnit (m_pDecThrCtx[signal]); | |
| 1367 | + m_pLastDecThrCtx = &m_pDecThrCtx[signal]; | |
| 1368 | + m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN; | |
| 1369 | + RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated); | |
| 1370 | + | |
| 1371 | + // wait early picture | |
| 1372 | + if (m_DecCtxActiveCount >= m_iThreadCount) { | |
| 1373 | + WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); | |
| 1374 | + RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle); | |
| 1375 | + } | |
| 1376 | + return state; | |
| 1377 | +} | |
| 1378 | + | |
| 1022 | 1379 | } // namespace WelsDec |
| 1023 | 1380 | |
| 1024 | 1381 | |