diff --git a/codec/decoder/plus/src/welsDecoderExt.cpp b/codec/decoder/plus/src/welsDecoderExt.cpp index 06d112176b..151d275c96 100644 --- a/codec/decoder/plus/src/welsDecoderExt.cpp +++ b/codec/decoder/plus/src/welsDecoderExt.cpp @@ -1325,12 +1325,48 @@ DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst, &sThreadCtx.sDstInfo); - int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo); + int32_t iErr = WelsDecodeInitAccessUnitStart (sThreadCtx.pCtx, &sThreadCtx.sDstInfo); if (ERR_NONE != iErr) { return (DECODING_STATE) (iRet | iErr); } + if (sThreadCtx.pCtx->bNewSeqBegin) { + if (GetThreadCount (sThreadCtx.pCtx) > 1) { + // A new sequence can reallocate the shared DPB. Make sure older + // worker threads have stopped using pictures from the previous DPB + // before AllocPicBuffOnNewSeqBegin() destroys it. + for (int32_t i = 0; i < m_DecCtxActiveCount; ++i) { + if (m_pDecThrCtxActive[i] != NULL && m_pDecThrCtxActive[i] != &sThreadCtx) { + WAIT_SEMAPHORE (&m_pDecThrCtxActive[i]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); + RELEASE_SEMAPHORE (&m_pDecThrCtxActive[i]->sThreadInfo.sIsIdle); + } + } + sThreadCtx.pCtx->pLastThreadCtx = NULL; + } + iErr = AllocPicBuffOnNewSeqBegin (sThreadCtx.pCtx); + if (ERR_NONE != iErr) { + return (DECODING_STATE) (iRet | iErr); + } + } if (sThreadCtx.pCtx->bNewSeqBegin) { m_pPicBuff = sThreadCtx.pCtx->pPicBuff; + // Keep all thread contexts from carrying stale pointers to the DPB that + // was just replaced. + for (int32_t i = 0; i < m_iCtxCount; ++i) { + if (&m_pDecThrCtx[i] != &sThreadCtx && m_pDecThrCtx[i].pCtx != NULL) { + m_pDecThrCtx[i].pCtx->pPicBuff = m_pPicBuff; + m_pDecThrCtx[i].pCtx->bHaveGotMemory = sThreadCtx.pCtx->bHaveGotMemory; + m_pDecThrCtx[i].pCtx->iPicQueueNumber = sThreadCtx.pCtx->iPicQueueNumber; + m_pDecThrCtx[i].pCtx->iImgWidthInPixel = sThreadCtx.pCtx->iImgWidthInPixel; + m_pDecThrCtx[i].pCtx->iImgHeightInPixel = sThreadCtx.pCtx->iImgHeightInPixel; + m_pDecThrCtx[i].pCtx->pDec = NULL; + m_pDecThrCtx[i].pCtx->pLastThreadCtx = NULL; + iErr = InitialDqLayersContext (m_pDecThrCtx[i].pCtx, sThreadCtx.pCtx->iImgWidthInPixel, + sThreadCtx.pCtx->iImgHeightInPixel); + if (ERR_NONE != iErr) { + return (DECODING_STATE) (iRet | iErr); + } + } + } } else if (bPicBuffChanged) { InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4); } @@ -1382,6 +1418,9 @@ int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const i memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo)); ParseAccessUnit (m_pDecThrCtx[signal]); + if (m_pDecThrCtx[signal].pCtx->bNewSeqBegin) { + m_pDecThrCtx[signal].pCtx->pLastThreadCtx = NULL; + } if (m_iThreadCount > 1) { m_pLastDecThrCtx = &m_pDecThrCtx[signal]; }