ref: 06b8e1abb7b13367ef6ad6f385197b94dfe647f9
parent: 5b12578960b1a9cbb009a4ed2ffb41459345ec71
author: huili2 <huili2@cisco.com>
date: Tue Mar 3 18:51:19 EST 2015
allow slice-level data come in for parse only
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -366,6 +366,9 @@
//for Parse only
bool bParseOnly;
+ bool bFramePending;
+ int32_t iNalNum;
+ int32_t iNalLenInByte[MAX_NAL_UNITS_IN_LAYER];
SSpsBsInfo sSpsBsInfo [MAX_SPS_COUNT];
SSpsBsInfo sSubsetSpsBsInfo [MAX_PPS_COUNT];
SPpsBsInfo sPpsBsInfo [MAX_PPS_COUNT];
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -72,6 +72,79 @@
}
}
+ if (pCtx->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo
+ PAccessUnit pCurAu = pCtx->pAccessUnitList;
+ static bool bFirstIDR = true;
+ if (dsErrorFree == pCtx->iErrorCode) { //correct decoding, add to data buffer
+ SParserBsInfo* pParser = pCtx->pParserBsInfo;
+ SNalUnit* pCurNal = NULL;
+ int32_t iTotalNalLen = 0;
+ int32_t iNalLen = 0;
+ int32_t iNum = 0;
+ while (iNum < pParser->iNalNum) {
+ iTotalNalLen += pParser->iNalLenInByte[iNum++];
+ }
+ uint8_t* pDstBuf = pParser->pDstBuff + iTotalNalLen;
+ int32_t iIdx = pCurAu->uiStartPos;
+ int32_t iEndIdx = pCurAu->uiEndPos;
+ uint8_t* pNalBs = NULL;
+ pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0;
+ //pParser->iNalNum = 0;
+ pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4);
+ pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4);
+
+ if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR
+ if (bFirstIDR) { //add required sps/pps
+ bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType);
+ SSpsBsInfo* pSpsBs = NULL;
+ SPpsBsInfo* pPpsBs = NULL;
+ int32_t iSpsId = pCtx->pSps->iSpsId;
+ int32_t iPpsId = pCtx->pPps->iPpsId;
+ pCtx->bParamSetsLostFlag = false;
+ //find required sps, pps and write into dst buff
+ pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId];
+ memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen);
+ pParser->iNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen;
+ pCtx->iNalLenInByte[pCtx->iNalNum ++] = pSpsBs->uiSpsBsLen;
+ pDstBuf += pSpsBs->uiSpsBsLen;
+ pPpsBs = &pCtx->sPpsBsInfo [iPpsId];
+ memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen);
+ pParser->iNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen;
+ pDstBuf += pPpsBs->uiPpsBsLen;
+ bFirstIDR = false;
+ }
+ } else { //IDR required SPS, PPS
+ bFirstIDR = true;
+ }
+ //then VCL data re-write
+ while (iIdx <= iEndIdx) {
+ pCurNal = pCurAu->pNalUnitsList [iIdx ++];
+ iNalLen = pCurNal->sNalData.sVclNal.iNalLength;
+ pNalBs = pCurNal->sNalData.sVclNal.pNalPos;
+ pParser->iNalLenInByte [pParser->iNalNum ++] = iNalLen;
+ memcpy (pDstBuf, pNalBs, iNalLen);
+ pDstBuf += iNalLen;
+ }
+ if (pCtx->iTotalNumMbRec == kiTotalNumMbInCurLayer) { //frame complete
+ pCtx->iTotalNumMbRec = 0;
+ pCtx->bFramePending = false;
+ } else if (pCtx->iTotalNumMbRec != 0) { //frame incomplete
+ pCtx->bFramePending = true;
+ pCtx->pDec->bIsComplete = false;
+ pCtx->iErrorCode |= dsFramePending;
+ return -1;
+ //pCtx->pParserBsInfo->iNalNum = 0;
+ }
+ } else { //error
+ pCtx->pParserBsInfo->uiOutBsTimeStamp = 0;
+ pCtx->pParserBsInfo->iNalNum = 0;
+ pCtx->pParserBsInfo->iSpsWidthInPixel = 0;
+ pCtx->pParserBsInfo->iSpsHeightInPixel = 0;
+ return -1;
+ }
+ return 0;
+ }
+
if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"DecodeFrameConstruction(): iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d ",
@@ -87,15 +160,6 @@
pCtx->iTotalNumMbRec = 0;
- if (pCtx->bParseOnly) { //should exit for parse only to prevent access NULL pDstInfo
- if (bFrameCompleteFlag)
- return 0;
- else { //incomplete frame
- pCtx->pDec->bIsComplete = false;
- return -1;
- }
- }
-
//////output:::normal path
pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp;
ppDst[0] = pPic->pData[0];
@@ -401,6 +465,18 @@
pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead;
pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte;
if (pCtx->bParseOnly) {
+ pCtx->pParserBsInfo = static_cast<SParserBsInfo*> (WelsMallocz (sizeof (SParserBsInfo), "pCtx->pParserBsInfo"));
+ if (pCtx->pParserBsInfo == NULL) {
+ return ERR_INFO_OUT_OF_MEMORY;
+ }
+ memset (pCtx->pParserBsInfo, 0, sizeof (SParserBsInfo));
+ pCtx->pParserBsInfo->pDstBuff = static_cast<uint8_t*> (WelsMallocz (MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t),
+ "pCtx->pParserBsInfo->pDstBuff"));
+ if (pCtx->pParserBsInfo->pDstBuff == NULL) {
+ return ERR_INFO_OUT_OF_MEMORY;
+ }
+ memset (pCtx->pParserBsInfo->pDstBuff, 0, MAX_ACCESS_UNIT_CAPACITY * sizeof (uint8_t));
+
if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (WelsMallocz (pCtx->iMaxBsBufferSizeInByte,
"pCtx->sSavedData.pHead"))) == NULL) {
return ERR_INFO_OUT_OF_MEMORY;
@@ -506,15 +582,24 @@
pCtx->sRawData.pEnd = NULL;
pCtx->sRawData.pStartPos = NULL;
pCtx->sRawData.pCurPos = NULL;
- if (pCtx->sSavedData.pHead) {
- WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData->pHead");
+ if (pCtx->bParseOnly) {
+ if (pCtx->sSavedData.pHead) {
+ WelsFree (pCtx->sSavedData.pHead, "pCtx->sSavedData->pHead");
+ }
+ pCtx->sSavedData.pHead = NULL;
+ pCtx->sSavedData.pEnd = NULL;
+ pCtx->sSavedData.pStartPos = NULL;
+ pCtx->sSavedData.pCurPos = NULL;
+ if (pCtx->pParserBsInfo) {
+ if (pCtx->pParserBsInfo->pDstBuff) {
+ WelsFree (pCtx->pParserBsInfo->pDstBuff, "pCtx->pParserBsInfo->pDstBuff");
+ pCtx->pParserBsInfo->pDstBuff = NULL;
+ }
+ WelsFree (pCtx->pParserBsInfo, "pCtx->pParserBsInfo");
+ pCtx->pParserBsInfo = NULL;
+ }
}
- pCtx->sSavedData.pHead = NULL;
- pCtx->sSavedData.pEnd = NULL;
- pCtx->sSavedData.pStartPos = NULL;
- pCtx->sSavedData.pCurPos = NULL;
}
-
/*
* DecodeNalHeaderExt
* Trigger condition: NAL_UNIT_TYPE = NAL_UNIT_PREFIX or NAL_UNIT_CODED_SLICE_EXT
@@ -1864,57 +1949,6 @@
iErr = DecodeCurrentAccessUnit (pCtx, ppDst, pDstInfo);
- if (pCtx->bParseOnly) {
- if ((dsErrorFree == pCtx->iErrorCode) && (iErr == 0)) { //frame complete, output
- SParserBsInfo* pParser = pCtx->pParserBsInfo;
- uint8_t* pDstBuf = pParser->pDstBuff;
- SNalUnit* pCurNal = NULL;
- int32_t iNalLen = 0;
- int32_t iIdx = pCurAu->uiStartPos;
- int32_t iEndIdx = pCurAu->uiEndPos;
- uint8_t* pNalBs = NULL;
- pParser->uiOutBsTimeStamp = (pCurAu->pNalUnitsList [iIdx]) ? pCurAu->pNalUnitsList [iIdx]->uiTimeStamp : 0;
- pParser->iNalNum = 0;
- pParser->iSpsWidthInPixel = (pCtx->pSps->iMbWidth << 4);
- pParser->iSpsHeightInPixel = (pCtx->pSps->iMbHeight << 4);
-
- if (pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.bIdrFlag) { //IDR
- bool bSubSps = (NAL_UNIT_CODED_SLICE_EXT == pCurAu->pNalUnitsList [iIdx]->sNalHeaderExt.sNalUnitHeader.eNalUnitType);
- SSpsBsInfo* pSpsBs = NULL;
- SPpsBsInfo* pPpsBs = NULL;
- int32_t iSpsId = pCtx->pSps->iSpsId;
- int32_t iPpsId = pCtx->pPps->iPpsId;
- pCtx->bParamSetsLostFlag = false;
- //find required sps, pps and write into dst buff
- pSpsBs = bSubSps ? &pCtx->sSubsetSpsBsInfo [iSpsId] : &pCtx->sSpsBsInfo [iSpsId];
- memcpy (pDstBuf, pSpsBs->pSpsBsBuf, pSpsBs->uiSpsBsLen);
- pParser->iNalLenInByte [pParser->iNalNum ++] = pSpsBs->uiSpsBsLen;
- pDstBuf += pSpsBs->uiSpsBsLen;
- pPpsBs = &pCtx->sPpsBsInfo [iPpsId];
- memcpy (pDstBuf, pPpsBs->pPpsBsBuf, pPpsBs->uiPpsBsLen);
- pParser->iNalLenInByte [pParser->iNalNum ++] = pPpsBs->uiPpsBsLen;
- pDstBuf += pPpsBs->uiPpsBsLen;
- } //IDR required SPS, PPS
- //then VCL data re-write
- while (iIdx <= iEndIdx) {
- pCurNal = pCurAu->pNalUnitsList [iIdx ++];
- iNalLen = pCurNal->sNalData.sVclNal.iNalLength;
- pNalBs = pCurNal->sNalData.sVclNal.pNalPos;
- pParser->iNalLenInByte [pParser->iNalNum ++] = iNalLen;
- memcpy (pDstBuf, pNalBs, iNalLen);
- pDstBuf += iNalLen;
- }
- } else { //error
- pCtx->pParserBsInfo->uiOutBsTimeStamp = 0;
- pCtx->pParserBsInfo->iNalNum = 0;
- pCtx->pParserBsInfo->iSpsWidthInPixel = 0;
- pCtx->pParserBsInfo->iSpsHeightInPixel = 0;
- if (dsErrorFree == pCtx->iErrorCode) { //frame not complete
- pCtx->iErrorCode |= dsFramePending;
- }
- }
- }
-
WelsDecodeAccessUnitEnd (pCtx);
if (ERR_NONE != iErr) {
@@ -2056,6 +2090,8 @@
if (pCtx->pDec == NULL) {
pCtx->pDec = PrefetchPic (pCtx->pPicBuff[0]);
+ if (pCtx->iTotalNumMbRec != 0)
+ pCtx->iTotalNumMbRec = 0;
if (NULL == pCtx->pDec) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR,
@@ -2326,6 +2362,8 @@
if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
MarkECFrameAsRef (pCtx);
}
+ } else if (pCtx->bParseOnly) { //clear parse only internal data status
+ pCtx->pParserBsInfo->iNalNum = 0;
} else {
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
pCtx->pDec = NULL;
--- a/codec/decoder/core/src/pic_queue.cpp
+++ b/codec/decoder/core/src/pic_queue.cpp
@@ -82,19 +82,25 @@
iLumaSize = iPicWidth * iPicHeight;
iChromaSize = iPicChromaWidth * iPicChromaHeight;
- pPic->pBuffer[0] = static_cast<uint8_t*> (WelsMallocz (iLumaSize /* luma */
- + (iChromaSize << 1) /* Cb,Cr */, "_pic->buffer[0]"));
- memset (pPic->pBuffer[0], 128, (iLumaSize + (iChromaSize << 1)));
+ if (pCtx->bParseOnly) {
+ pPic->pBuffer[0] = pPic->pBuffer[1] = pPic->pBuffer[2] = NULL;
+ pPic->pData[0] = pPic->pData[1] = pPic->pData[2] = NULL;
+ pPic->iLinesize[0] = iPicWidth;
+ pPic->iLinesize[1] = pPic->iLinesize[2] = iPicChromaWidth;
+ } else {
+ pPic->pBuffer[0] = static_cast<uint8_t*> (WelsMallocz (iLumaSize /* luma */
+ + (iChromaSize << 1) /* Cb,Cr */, "_pic->buffer[0]"));
+ memset (pPic->pBuffer[0], 128, (iLumaSize + (iChromaSize << 1)));
- WELS_VERIFY_RETURN_PROC_IF (NULL, NULL == pPic->pBuffer[0], FreePicture (pPic));
- pPic->iLinesize[0] = iPicWidth;
- pPic->iLinesize[1] = pPic->iLinesize[2] = iPicChromaWidth;
- pPic->pBuffer[1] = pPic->pBuffer[0] + iLumaSize;
- pPic->pBuffer[2] = pPic->pBuffer[1] + iChromaSize;
- pPic->pData[0] = pPic->pBuffer[0] + (1 + pPic->iLinesize[0]) * PADDING_LENGTH;
- pPic->pData[1] = pPic->pBuffer[1] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[1]) * PADDING_LENGTH) >> 1);
- pPic->pData[2] = pPic->pBuffer[2] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[2]) * PADDING_LENGTH) >> 1);
-
+ WELS_VERIFY_RETURN_PROC_IF (NULL, NULL == pPic->pBuffer[0], FreePicture (pPic));
+ pPic->iLinesize[0] = iPicWidth;
+ pPic->iLinesize[1] = pPic->iLinesize[2] = iPicChromaWidth;
+ pPic->pBuffer[1] = pPic->pBuffer[0] + iLumaSize;
+ pPic->pBuffer[2] = pPic->pBuffer[1] + iChromaSize;
+ pPic->pData[0] = pPic->pBuffer[0] + (1 + pPic->iLinesize[0]) * PADDING_LENGTH;
+ pPic->pData[1] = pPic->pBuffer[1] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[1]) * PADDING_LENGTH) >> 1);
+ pPic->pData[2] = pPic->pBuffer[2] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[2]) * PADDING_LENGTH) >> 1);
+ }
pPic->iPlanes = 3; // yv12 in default
pPic->iWidthInPixel = kiPicWidth;
pPic->iHeightInPixel = kiPicHeight;
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -574,7 +574,10 @@
m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
m_pDecContext->eErrorConMethod = ERROR_CON_DISABLE; //add protection to disable EC here.
- m_pDecContext->pParserBsInfo = pDstInfo;
+ if (!m_pDecContext->bFramePending) { //frame complete
+ m_pDecContext->pParserBsInfo->iNalNum = 0;
+ memset (m_pDecContext->pParserBsInfo->iNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER);
+ }
pDstInfo->iNalNum = 0;
pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
if (pDstInfo) {
@@ -584,6 +587,10 @@
m_pDecContext->uiTimeStamp = 0;
}
WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
+ if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) {
+ memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo));
+ }
+
m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
return (DECODING_STATE) m_pDecContext->iErrorCode;
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -2461,7 +2461,6 @@
const uint32_t kiHeight = 96; //DO NOT CHANGE!
const uint32_t kiFrameRate = 12; //DO NOT CHANGE!
const uint32_t kiFrameNum = 100; //DO NOT CHANGE!
-const uint32_t kiMaxBsSize = 10000000; //DO NOT CHANGE!
const char* pHashStr[] = { //DO NOT CHANGE!
"d1c255a57aa2c5e1192a90680c00e6ee3e73fe59",
"f350001c333902029800bd291fbed915a4bdf19a",
@@ -2487,9 +2486,6 @@
int rv = decoder_->Initialize (&decParam);
ASSERT_EQ (0, rv);
memset (&BsInfo_, 0, sizeof (SParserBsInfo));
- BsInfo_.pDstBuff = NULL;
- BsInfo_.pDstBuff = new unsigned char [kiMaxBsSize];
- ASSERT_TRUE (BsInfo_.pDstBuff != NULL);
fYuv_ = fopen ("./res/CiscoVT2people_160x96_6fps.yuv", "rb");
ASSERT_TRUE (fYuv_ != NULL);
iWidth_ = kiWidth;
@@ -2497,10 +2493,6 @@
}
void TearDown() {
EncodeDecodeTestBase::TearDown();
- if (BsInfo_.pDstBuff) {
- delete[] BsInfo_.pDstBuff;
- BsInfo_.pDstBuff = NULL;
- }
fclose (fYuv_);
}
@@ -3449,7 +3441,7 @@
uint8_t* ptr = buf_.data();
uint8_t uiVal = rand() % 256;
for (int i = 0; i < frameSize; i++) {
- ptr[i] = bAllRandom? (rand() % 256) :uiVal;
+ ptr[i] = bAllRandom ? (rand() % 256) : uiVal;
}
int rv = encoder_->EncodeFrame (&EncPic, &info);
if (0 == iCheckTypeIndex)
@@ -3464,9 +3456,9 @@
TEST_P (EncodeTestAPI, SetEncOptionSize) {
EncodeOptionParam p = GetParam();
- FILE * pFile = NULL;
- if (p.sFileSave != NULL && strlen(p.sFileSave) > 0) {
- pFile = fopen(p.sFileSave, "wb");
+ FILE* pFile = NULL;
+ if (p.sFileSave != NULL && strlen (p.sFileSave) > 0) {
+ pFile = fopen (p.sFileSave, "wb");
}
memset (¶m_, 0, sizeof (SEncParamExt));
encoder_->GetDefaultParams (¶m_);
@@ -3502,16 +3494,16 @@
unsigned char* pData[3] = { NULL };
while (iIdx <= p.iNumframes) {
EncodeOneFrameRandom (0, p.bAllRandom);
- encToDecData(info, iLen);
- if( pFile ) {
+ encToDecData (info, iLen);
+ if (pFile) {
fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pFile);
fflush (pFile);
}
- memset(&dstBufInfo_, 0, sizeof(SBufferInfo));
- if(iLen && p.bTestDecoder) {
- rv = decoder_->DecodeFrameNoDelay(info.sLayerInfo[0].pBsBuf, iLen, pData, &dstBufInfo_);
- ASSERT_EQ(rv, 0);
- ASSERT_EQ(dstBufInfo_.iBufferStatus, 1);
+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
+ if (iLen && p.bTestDecoder) {
+ rv = decoder_->DecodeFrameNoDelay (info.sLayerInfo[0].pBsBuf, iLen, pData, &dstBufInfo_);
+ ASSERT_EQ (rv, 0);
+ ASSERT_EQ (dstBufInfo_.iBufferStatus, 1);
}
int iLayer = 0;
while (iLayer < info.iLayerNum) {
@@ -3529,7 +3521,7 @@
}
iIdx++;
}
- if( pFile ) {
+ if (pFile) {
fclose (pFile);
}
}