parse only add and UT
This commit is contained in:
parent
53c14dccf0
commit
b231e3f000
@ -457,6 +457,7 @@ typedef struct TagSVCDecodingParam {
|
||||
unsigned char uiTargetDqLayer; ///< setting target dq layer id
|
||||
|
||||
ERROR_CON_IDC eEcActiveIdc; ///< whether active error concealment feature in decoder
|
||||
bool bParseOnly; ///< decoder for parse only, no reconstruction
|
||||
|
||||
SVideoProperty sVideoProperty; ///< video stream property
|
||||
} SDecodingParam, *PDecodingParam;
|
||||
@ -574,7 +575,7 @@ typedef struct TagParserBsInfo {
|
||||
unsigned char* pDstBuff; ///< outputted dst buffer for parsed bitstream
|
||||
int iSpsWidthInPixel; ///< required SPS width info
|
||||
int iSpsHeightInPixel; ///< required SPS height info
|
||||
} SParserBsInfo, PParserBsInfo;
|
||||
} SParserBsInfo, *PParserBsInfo;
|
||||
|
||||
/**
|
||||
* @brief Structure for encoder statistics
|
||||
|
@ -86,7 +86,7 @@ uint8_t* DetectStartCodePrefix (const uint8_t* kpBuf, int32_t* pOffset, int32_t
|
||||
uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeader, uint8_t* pSrcRbsp,
|
||||
int32_t iSrcRbspLen, uint8_t* pSrcNal, int32_t iSrcNalLen, int32_t* pConsumedBytes);
|
||||
|
||||
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen);
|
||||
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen, uint8_t* pSrcNal, const int32_t kSrcNalLen);
|
||||
|
||||
int32_t ParseRefBasePicMarking (PBitStringAux pBs, PRefBasePicMarking pRefBasePicMarking);
|
||||
|
||||
@ -113,7 +113,7 @@ bool CheckNextAuNewSeq (PWelsDecoderContext pCtx, const PNalUnit kpCurNal, const
|
||||
* \note Call it in case eNalUnitType is SPS.
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight);
|
||||
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight, uint8_t* pSrcNal, const int32_t kSrcNalLen);
|
||||
|
||||
/*!
|
||||
*************************************************************************************
|
||||
@ -129,7 +129,7 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
|
||||
* \note Call it in case eNalUnitType is PPS.
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux);
|
||||
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux, uint8_t* pSrcNal, const int32_t kSrcNalLen);
|
||||
|
||||
/*!
|
||||
*************************************************************************************
|
||||
|
@ -65,7 +65,15 @@ int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t
|
||||
|
||||
int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset);
|
||||
|
||||
|
||||
//The following for writing bs in decoder for Parse Only purpose
|
||||
void DecInitBitsForEncoding (PBitStringAux pBitString, uint8_t* kpBuf, const int32_t kiSize);
|
||||
int32_t DecBsWriteBits (PBitStringAux pBitString, int32_t iLen, const uint32_t kuiValue);
|
||||
int32_t DecBsWriteOneBit (PBitStringAux pBitString, const uint32_t kuiValue);
|
||||
int32_t DecBsFlush (PBitStringAux pBitString);
|
||||
int32_t DecBsWriteUe (PBitStringAux pBitString, const uint32_t kuiValue);
|
||||
int32_t DecBsWriteSe (PBitStringAux pBitString, const int32_t kiValue);
|
||||
int32_t DecBsRbspTrailingBits (PBitStringAux pBitString);
|
||||
void RBSP2EBSP (uint8_t* pDstBuf, uint8_t* pSrcBuf, const int32_t kiSize);
|
||||
|
||||
} // namespace WelsDec
|
||||
|
||||
|
@ -68,7 +68,7 @@ int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpPa
|
||||
* \note N/A
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx);
|
||||
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, const bool bParseOnly, SLogContext* pLogCtx);
|
||||
|
||||
/*!
|
||||
*************************************************************************************
|
||||
@ -101,7 +101,7 @@ void WelsEndDecoder (PWelsDecoderContext pCtx);
|
||||
*/
|
||||
|
||||
int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,
|
||||
uint8_t** ppDst, SBufferInfo* pDstBufInfo);
|
||||
uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo);
|
||||
|
||||
/*
|
||||
* request memory blocks for decoder avc part
|
||||
|
@ -102,6 +102,19 @@ uint8_t* pStartPos;
|
||||
uint8_t* pCurPos;
|
||||
} SDataBuffer;
|
||||
|
||||
//limit size for SPS PPS total permitted size for parse_only
|
||||
#define SPS_PPS_BS_SIZE 128
|
||||
typedef struct TagSpsBsInfo {
|
||||
uint8_t pSpsBsBuf [SPS_PPS_BS_SIZE];
|
||||
int32_t iSpsId;
|
||||
uint16_t uiSpsBsLen;
|
||||
} SSpsBsInfo;
|
||||
|
||||
typedef struct TagPpsBsInfo {
|
||||
uint8_t pPpsBsBuf [SPS_PPS_BS_SIZE];
|
||||
int32_t iPpsId;
|
||||
uint16_t uiPpsBsLen;
|
||||
} SPpsBsInfo;
|
||||
//#ifdef __cplusplus
|
||||
//extern "C" {
|
||||
//#endif//__cplusplus
|
||||
@ -210,6 +223,7 @@ SLogContext sLogCtx;
|
||||
void* pArgDec; // structured arguments for decoder, reserved here for extension in the future
|
||||
|
||||
SDataBuffer sRawData;
|
||||
SDataBuffer sSavedData; //for parse only purpose
|
||||
|
||||
// Configuration
|
||||
SDecodingParam* pParam;
|
||||
@ -334,6 +348,14 @@ bool bNewSeqBegin;
|
||||
bool bNextNewSeqBegin;
|
||||
int iOverwriteFlags;
|
||||
ERROR_CON_IDC eErrorConMethod; //
|
||||
|
||||
//for Parse only
|
||||
bool bParseOnly;
|
||||
SSpsBsInfo sSpsBsInfo [MAX_SPS_COUNT];
|
||||
SSpsBsInfo sSubsetSpsBsInfo [MAX_PPS_COUNT];
|
||||
SPpsBsInfo sPpsBsInfo [MAX_PPS_COUNT];
|
||||
SParserBsInfo* pParserBsInfo;
|
||||
|
||||
PPicture pPreviousDecodedPictureInDpb; //pointer to previously decoded picture in DPB for error concealment
|
||||
PGetIntraPredFunc pGetI16x16LumaPredFunc[7]; //h264_predict_copy_16x16;
|
||||
PGetIntraPredFunc pGetI4x4LumaPredFunc[14]; // h264_predict_4x4_t
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "error_code.h"
|
||||
#include "memmgr_nal_unit.h"
|
||||
#include "decoder_core.h"
|
||||
#include "bit_stream.h"
|
||||
#include "mem_align.h"
|
||||
|
||||
namespace WelsDec {
|
||||
/*!
|
||||
@ -110,6 +112,7 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
|
||||
bool bExtensionFlag = false;
|
||||
int32_t iErr = ERR_NONE;
|
||||
int32_t iBitSize = 0;
|
||||
SDataBuffer* pSavedData = &pCtx->sSavedData;
|
||||
SLogContext* pLogCtx = & (pCtx->sLogCtx);
|
||||
pNalUnitHeader->eNalUnitType = NAL_UNIT_UNSPEC_0;//SHOULD init it. because pCtx->sCurNalHead is common variable.
|
||||
|
||||
@ -296,9 +299,28 @@ uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeade
|
||||
iNalSize -= NAL_UNIT_HEADER_EXT_SIZE;
|
||||
*pConsumedBytes += NAL_UNIT_HEADER_EXT_SIZE;
|
||||
|
||||
if (pCtx->bParseOnly) {
|
||||
pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
|
||||
pCurNal->sNalData.sVclNal.iNalLength = iSrcNalLen - NAL_UNIT_HEADER_EXT_SIZE;
|
||||
if (pCurNal->sNalHeaderExt.bIdrFlag) {
|
||||
* (pSrcNal + 3) &= 0xE0;
|
||||
* (pSrcNal + 3) |= 0x05;
|
||||
} else {
|
||||
* (pSrcNal + 3) &= 0xE0;
|
||||
* (pSrcNal + 3) |= 0x01;
|
||||
}
|
||||
memcpy (pSavedData->pCurPos, pSrcNal, 4);
|
||||
pSavedData->pCurPos += 4;
|
||||
memcpy (pSavedData->pCurPos, pSrcNal + 7, iSrcNalLen - 7);
|
||||
pSavedData->pCurPos += iSrcNalLen - 7;
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
if (pCtx->bParseOnly) {
|
||||
pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
|
||||
pCurNal->sNalData.sVclNal.iNalLength = iSrcNalLen;
|
||||
memcpy (pSavedData->pCurPos, pSrcNal, iSrcNalLen);
|
||||
pSavedData->pCurPos += iSrcNalLen;
|
||||
}
|
||||
if (NAL_UNIT_PREFIX == pCtx->sPrefixNal.sNalHeaderExt.sNalUnitHeader.eNalUnitType) {
|
||||
if (pCtx->sPrefixNal.sNalData.sPrefixNal.bPrefixNalCorrectFlag) {
|
||||
PrefetchNalHeaderExtSyntax (pCtx, pCurNal, &pCtx->sPrefixNal);
|
||||
@ -501,7 +523,8 @@ bool CheckNextAuNewSeq (PWelsDecoderContext pCtx, const PNalUnit kpCurNal, const
|
||||
*
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen) {
|
||||
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen, uint8_t* pSrcNal,
|
||||
const int32_t kSrcNalLen) {
|
||||
PBitStringAux pBs = NULL;
|
||||
EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; // make initial value as unspecified
|
||||
int32_t iPicWidth = 0;
|
||||
@ -528,7 +551,7 @@ int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t
|
||||
return iErr;
|
||||
}
|
||||
}
|
||||
iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight);
|
||||
iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight, pSrcNal, kSrcNalLen);
|
||||
if (ERR_NONE != iErr) { // modified for pSps/pSubsetSps invalid, 12/1/2009
|
||||
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
|
||||
pCtx->iErrorCode |= dsNoParamSets;
|
||||
@ -550,7 +573,7 @@ int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t
|
||||
return iErr;
|
||||
}
|
||||
}
|
||||
iErr = ParsePps (pCtx, &pCtx->sPpsBuffer[0], pBs);
|
||||
iErr = ParsePps (pCtx, &pCtx->sPpsBuffer[0], pBs, pSrcNal, kSrcNalLen);
|
||||
if (ERR_NONE != iErr) { // modified for pps invalid, 12/1/2009
|
||||
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE)
|
||||
pCtx->iErrorCode |= dsNoParamSets;
|
||||
@ -795,7 +818,8 @@ bool CheckSpsActive (PWelsDecoderContext pCtx, PSps pSps) {
|
||||
*************************************************************************************
|
||||
*/
|
||||
|
||||
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight) {
|
||||
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight,
|
||||
uint8_t* pSrcNal, const int32_t kSrcNalLen) {
|
||||
PBitStringAux pBs = pBsAux;
|
||||
SSubsetSps sTempSubsetSps;
|
||||
PSps pSps = NULL;
|
||||
@ -995,6 +1019,79 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
|
||||
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); //vui_parameters_present_flag
|
||||
pSps->bVuiParamPresentFlag = !!uiCode;
|
||||
|
||||
if (pCtx->bParseOnly) {
|
||||
if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //sps bs exceeds!
|
||||
pCtx->iErrorCode |= dsOutOfMemory;
|
||||
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
|
||||
}
|
||||
if (!kbUseSubsetFlag) { //SPS
|
||||
SSpsBsInfo* pSpsBs = &pCtx->sSpsBsInfo [iSpsId];
|
||||
pSpsBs->iSpsId = iSpsId;
|
||||
memcpy (pSpsBs->pSpsBsBuf, pSrcNal, kSrcNalLen);
|
||||
pSpsBs->uiSpsBsLen = (uint32_t) kSrcNalLen;
|
||||
} else { //subset SPS
|
||||
SSpsBsInfo* pSpsBs = &pCtx->sSubsetSpsBsInfo [iSpsId];
|
||||
pSpsBs->iSpsId = iSpsId;
|
||||
pSpsBs->pSpsBsBuf [0] = pSpsBs->pSpsBsBuf [1] = pSpsBs->pSpsBsBuf [2] = 0x00;
|
||||
pSpsBs->pSpsBsBuf [3] = 0x01;
|
||||
pSpsBs->pSpsBsBuf [4] = 0x67;
|
||||
|
||||
//re-write subset SPS to SPS
|
||||
SBitStringAux sSubsetSpsBs;
|
||||
uint8_t* pBsBuf = static_cast<uint8_t*> (WelsMalloc (SPS_PPS_BS_SIZE + 4,
|
||||
"Temp buffer for parse only usage.")); //to reserve 4 bytes for UVLC writing buffer
|
||||
if (NULL == pBsBuf) {
|
||||
pCtx->iErrorCode |= dsOutOfMemory;
|
||||
return pCtx->iErrorCode;
|
||||
}
|
||||
DecInitBitsForEncoding (&sSubsetSpsBs, pBsBuf, pBs->pEndBuf - pBs->pStartBuf);
|
||||
DecBsWriteBits (&sSubsetSpsBs, 8, 77); //profile_idc, forced to Main profile
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet0Flag); // constraint_set0_flag
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet1Flag); // constraint_set1_flag
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet2Flag); // constraint_set2_flag
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet3Flag); // constraint_set3_flag
|
||||
DecBsWriteBits (&sSubsetSpsBs, 4, 0); //constraint_set4_flag, constraint_set5_flag, reserved_zero_2bits
|
||||
DecBsWriteBits (&sSubsetSpsBs, 8, pSps->uiLevelIdc); //level_idc
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->iSpsId); //sps_id
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->uiLog2MaxFrameNum - 4); //log2_max_frame_num_minus4
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->uiPocType); //pic_order_cnt_type
|
||||
if (pSps->uiPocType == 0) {
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->iLog2MaxPocLsb - 4); //log2_max_pic_order_cnt_lsb_minus4
|
||||
} else if (pSps->uiPocType == 1) {
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bDeltaPicOrderAlwaysZeroFlag); //delta_pic_order_always_zero_flag
|
||||
DecBsWriteSe (&sSubsetSpsBs, pSps->iOffsetForNonRefPic); //offset_for_no_ref_pic
|
||||
DecBsWriteSe (&sSubsetSpsBs, pSps->iOffsetForTopToBottomField); //offset_for_top_to_bottom_field
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->iNumRefFramesInPocCycle); //num_ref_frames_in_pic_order_cnt_cycle
|
||||
for (int32_t i = 0; i < pSps->iNumRefFramesInPocCycle; ++i) {
|
||||
DecBsWriteSe (&sSubsetSpsBs, pSps->iOffsetForRefFrame[i]); //offset_for_ref_frame[i]
|
||||
}
|
||||
}
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->iNumRefFrames); //max_num_ref_frames
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bGapsInFrameNumValueAllowedFlag); //gaps_in_frame_num_value_allowed_flag
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->iMbWidth - 1); //pic_width_in_mbs_minus1
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->iMbHeight - 1); //pic_height_in_map_units_minus1
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bFrameMbsOnlyFlag); //frame_mbs_only_flag
|
||||
if (!pSps->bFrameMbsOnlyFlag) {
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bMbaffFlag); //mb_adaptive_frame_field_flag
|
||||
}
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bDirect8x8InferenceFlag); //direct_8x8_inference_flag
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, pSps->bFrameCroppingFlag); //frame_cropping_flag
|
||||
if (pSps->bFrameCroppingFlag) {
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iLeftOffset); //frame_crop_left_offset
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iRightOffset); //frame_crop_right_offset
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iTopOffset); //frame_crop_top_offset
|
||||
DecBsWriteUe (&sSubsetSpsBs, pSps->sFrameCrop.iBottomOffset); //frame_crop_bottom_offset
|
||||
}
|
||||
DecBsWriteOneBit (&sSubsetSpsBs, 0); //vui_parameters_present_flag
|
||||
DecBsRbspTrailingBits (&sSubsetSpsBs); //finished, rbsp trailing bit
|
||||
int32_t iRbspSize = sSubsetSpsBs.pCurBuf - sSubsetSpsBs.pStartBuf;
|
||||
RBSP2EBSP (pSpsBs->pSpsBsBuf + 5, sSubsetSpsBs.pStartBuf, iRbspSize);
|
||||
pSpsBs->uiSpsBsLen = sSubsetSpsBs.pCurBuf - sSubsetSpsBs.pStartBuf + 5;
|
||||
if (pBsBuf) {
|
||||
WelsFree (pBsBuf, "pBsBuf for parse only usage");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if SPS SVC extension applicated
|
||||
if (kbUseSubsetFlag && (PRO_SCALABLE_BASELINE == uiProfileIdc || PRO_SCALABLE_HIGH == uiProfileIdc)) {
|
||||
if (DecodeSpsSvcExt (pCtx, pSubsetSps, pBs) != ERR_NONE) {
|
||||
@ -1080,7 +1177,8 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
|
||||
* \note Call it in case eNalUnitType is PPS.
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux) {
|
||||
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux, uint8_t* pSrcNal,
|
||||
const int32_t kSrcNalLen) {
|
||||
|
||||
PPps pPps = NULL;
|
||||
SPps sTempPps;
|
||||
@ -1194,6 +1292,16 @@ int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux)
|
||||
memcpy (&pCtx->sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
|
||||
pCtx->bPpsAvailFlags[uiPpsId] = true;
|
||||
}
|
||||
if (pCtx->bParseOnly) {
|
||||
if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { //pps bs exceeds
|
||||
pCtx->iErrorCode |= dsOutOfMemory;
|
||||
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
|
||||
}
|
||||
SPpsBsInfo* pPpsBs = &pCtx->sPpsBsInfo [uiPpsId];
|
||||
pPpsBs->iPpsId = (int32_t) uiPpsId;
|
||||
memcpy (pPpsBs->pPpsBsBuf, pSrcNal, kSrcNalLen);
|
||||
pPpsBs->uiPpsBsLen = kSrcNalLen;
|
||||
}
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ inline uint32_t GetValue4Bytes (uint8_t* pDstNal) {
|
||||
}
|
||||
|
||||
int32_t InitReadBits (PBitStringAux pBitString, intX_t iEndOffset) {
|
||||
if(pBitString->pCurBuf>=(pBitString->pEndBuf - iEndOffset)) {
|
||||
if (pBitString->pCurBuf >= (pBitString->pEndBuf - iEndOffset)) {
|
||||
return ERR_INFO_INVALID_ACCESS;
|
||||
}
|
||||
pBitString->uiCurBits = GetValue4Bytes (pBitString->pCurBuf);
|
||||
@ -79,11 +79,141 @@ int32_t InitBits (PBitStringAux pBitString, const uint8_t* kpBuf, const int32_t
|
||||
pBitString->iBits = kiSize; // count bits of overall bitstreaming inputindex;
|
||||
pBitString->pCurBuf = pBitString->pStartBuf;
|
||||
int32_t iErr = InitReadBits (pBitString, 0);
|
||||
if(iErr) {
|
||||
if (iErr) {
|
||||
return iErr;
|
||||
}
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
//Following for write bs in decoder
|
||||
void DecInitBitsForEncoding (PBitStringAux pBitString, uint8_t* pBuf, const int32_t kiSize) {
|
||||
uint8_t* pPtr = pBuf;
|
||||
pBitString->pStartBuf = pPtr;
|
||||
pBitString->pCurBuf = pPtr;
|
||||
pBitString->pEndBuf = pPtr + kiSize;
|
||||
pBitString->iLeftBits = 32;
|
||||
pBitString->uiCurBits = 0;
|
||||
}
|
||||
|
||||
#define WRITE_BE_32(ptr, val) do { \
|
||||
(ptr)[0] = (val) >> 24; \
|
||||
(ptr)[1] = (val) >> 16; \
|
||||
(ptr)[2] = (val) >> 8; \
|
||||
(ptr)[3] = (val) >> 0; \
|
||||
} while (0);
|
||||
|
||||
int32_t DecBsWriteBits (PBitStringAux pBitString, int32_t iLen, const uint32_t kuiValue) {
|
||||
if (iLen < pBitString->iLeftBits) {
|
||||
pBitString->uiCurBits = (pBitString->uiCurBits << iLen) | kuiValue;
|
||||
pBitString->iLeftBits -= iLen;
|
||||
} else {
|
||||
iLen -= pBitString->iLeftBits;
|
||||
pBitString->uiCurBits = (pBitString->uiCurBits << pBitString->iLeftBits) | (kuiValue >> iLen);
|
||||
WRITE_BE_32 (pBitString->pCurBuf, pBitString->uiCurBits);
|
||||
pBitString->pCurBuf += 4;
|
||||
pBitString->uiCurBits = kuiValue & ((1 << iLen) - 1);
|
||||
pBitString->iLeftBits = 32 - iLen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t DecBsWriteOneBit (PBitStringAux pBitString, const uint32_t kuiValue) {
|
||||
DecBsWriteBits (pBitString, 1, kuiValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t DecBsFlush (PBitStringAux pBitString) {
|
||||
WRITE_BE_32 (pBitString->pCurBuf, pBitString->uiCurBits << pBitString->iLeftBits);
|
||||
pBitString->pCurBuf += 4 - pBitString->iLeftBits / 8;
|
||||
pBitString->iLeftBits = 32;
|
||||
pBitString->uiCurBits = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t g_kuiDecGolombUELength[256] = {
|
||||
1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, //14
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, //30
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,//46
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,//62
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,//
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
17
|
||||
};
|
||||
|
||||
int32_t DecBsWriteUe (PBitStringAux pBitString, const uint32_t kuiValue) {
|
||||
uint32_t iTmpValue = kuiValue + 1;
|
||||
if (256 > kuiValue) {
|
||||
DecBsWriteBits (pBitString, g_kuiDecGolombUELength[kuiValue], kuiValue + 1);
|
||||
} else {
|
||||
uint32_t n = 0;
|
||||
if (iTmpValue & 0xffff0000) {
|
||||
iTmpValue >>= 16;
|
||||
n += 16;
|
||||
}
|
||||
if (iTmpValue & 0xff) {
|
||||
iTmpValue >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
|
||||
//n += (g_kuiDecGolombUELength[iTmpValue] >> 1);
|
||||
|
||||
n += (g_kuiDecGolombUELength[iTmpValue - 1] >> 1);
|
||||
DecBsWriteBits (pBitString, (n << 1) + 1, kuiValue + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t DecBsWriteSe (PBitStringAux pBitString, const int32_t kiValue) {
|
||||
uint32_t iTmpValue;
|
||||
if (0 == kiValue) {
|
||||
DecBsWriteOneBit (pBitString, 1);
|
||||
} else if (0 < kiValue) {
|
||||
iTmpValue = (kiValue << 1) - 1;
|
||||
DecBsWriteUe (pBitString, iTmpValue);
|
||||
} else {
|
||||
iTmpValue = ((-kiValue) << 1);
|
||||
DecBsWriteUe (pBitString, iTmpValue);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t DecBsRbspTrailingBits (PBitStringAux pBitString) {
|
||||
DecBsWriteOneBit (pBitString, 1);
|
||||
DecBsFlush (pBitString);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RBSP2EBSP (uint8_t* pDstBuf, uint8_t* pSrcBuf, const int32_t kiSize) {
|
||||
uint8_t* pSrcPointer = pSrcBuf;
|
||||
uint8_t* pDstPointer = pDstBuf;
|
||||
uint8_t* pSrcEnd = pSrcBuf + kiSize;
|
||||
int32_t iZeroCount = 0;
|
||||
|
||||
while (pSrcPointer < pSrcEnd) {
|
||||
if (iZeroCount == 2 && *pSrcPointer <= 3) {
|
||||
//add the code 0x03
|
||||
*pDstPointer++ = 3;
|
||||
iZeroCount = 0;
|
||||
}
|
||||
if (*pSrcPointer == 0) {
|
||||
++ iZeroCount;
|
||||
} else {
|
||||
iZeroCount = 0;
|
||||
}
|
||||
*pDstPointer++ = *pSrcPointer++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace WelsDec
|
||||
|
||||
|
@ -350,6 +350,9 @@ int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpPa
|
||||
return iRet;
|
||||
pCtx->eErrorConMethod = pCtx->pParam->eEcActiveIdc;
|
||||
|
||||
if (pCtx->bParseOnly) //parse only, disable EC method
|
||||
pCtx->eErrorConMethod = ERROR_CON_DISABLE;
|
||||
|
||||
if (VIDEO_BITSTREAM_SVC == pCtx->pParam->sVideoProperty.eVideoBsType ||
|
||||
VIDEO_BITSTREAM_AVC == pCtx->pParam->sVideoProperty.eVideoBsType) {
|
||||
pCtx->eVideoType = pCtx->pParam->sVideoProperty.eVideoBsType;
|
||||
@ -374,7 +377,7 @@ int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpPa
|
||||
* \note N/A
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
|
||||
int32_t WelsInitDecoder (PWelsDecoderContext pCtx, const bool bParseOnly, SLogContext* pLogCtx) {
|
||||
if (pCtx == NULL) {
|
||||
return ERR_INFO_INVALID_PTR;
|
||||
}
|
||||
@ -382,6 +385,7 @@ int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
|
||||
// default
|
||||
WelsDecoderDefaults (pCtx, pLogCtx);
|
||||
|
||||
pCtx->bParseOnly = bParseOnly;
|
||||
// open decoder
|
||||
return WelsOpenDecoder (pCtx);
|
||||
}
|
||||
@ -427,9 +431,10 @@ void GetVclNalTemporalId (PWelsDecoderContext pCtx) {
|
||||
*************************************************************************************
|
||||
*/
|
||||
int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,
|
||||
uint8_t** ppDst, SBufferInfo* pDstBufInfo) {
|
||||
uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo) {
|
||||
if (!pCtx->bEndOfStreamFlag) {
|
||||
SDataBuffer* pRawData = &pCtx->sRawData;
|
||||
SDataBuffer* pSavedData = NULL;
|
||||
|
||||
int32_t iSrcIdx = 0; //the index of source bit-stream till now after parsing one or more NALs
|
||||
int32_t iSrcConsumed = 0; // consumed bit count of source bs
|
||||
@ -457,7 +462,12 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
|
||||
pRawData->pCurPos = pRawData->pHead;
|
||||
}
|
||||
|
||||
|
||||
if (pCtx->bParseOnly) {
|
||||
pSavedData = &pCtx->sSavedData;
|
||||
if ((kiBsLen + 4) > (pSavedData->pEnd - pSavedData->pCurPos)) {
|
||||
pSavedData->pCurPos = pSavedData->pHead;
|
||||
}
|
||||
}
|
||||
//copy raw data from source buffer (application) to raw data buffer (codec inside)
|
||||
//0x03 removal and extract all of NAL Unit from current raw data
|
||||
pDstNal = pRawData->pCurPos;
|
||||
@ -481,7 +491,7 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
|
||||
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
|
||||
}
|
||||
if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) && pNalPayload) {
|
||||
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes);
|
||||
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
|
||||
}
|
||||
if (pCtx->bAuReadyFlag) {
|
||||
ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
|
||||
@ -542,7 +552,7 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
|
||||
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
|
||||
}
|
||||
if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) && pNalPayload) {
|
||||
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes);
|
||||
iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3);
|
||||
}
|
||||
if (pCtx->bAuReadyFlag) {
|
||||
ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);
|
||||
|
@ -88,21 +88,23 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
|
||||
|
||||
pCtx->iTotalNumMbRec = 0;
|
||||
|
||||
//////output:::normal path
|
||||
ppDst[0] = pPic->pData[0];
|
||||
ppDst[1] = pPic->pData[1];
|
||||
ppDst[2] = pPic->pData[2];
|
||||
if (!pCtx->bParseOnly) {
|
||||
//////output:::normal path
|
||||
ppDst[0] = pPic->pData[0];
|
||||
ppDst[1] = pPic->pData[1];
|
||||
ppDst[2] = pPic->pData[2];
|
||||
|
||||
pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;
|
||||
pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;
|
||||
|
||||
pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
|
||||
pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;
|
||||
pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
|
||||
pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
|
||||
ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
|
||||
ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
|
||||
ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
|
||||
pDstInfo->iBufferStatus = 1;
|
||||
pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
|
||||
pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;
|
||||
pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
|
||||
pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
|
||||
ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
|
||||
ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
|
||||
ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
|
||||
pDstInfo->iBufferStatus = 1;
|
||||
}
|
||||
|
||||
bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth)
|
||||
|| (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight);
|
||||
@ -114,7 +116,6 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
|
||||
else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE && pCtx->iErrorCode && bOutResChange)
|
||||
pCtx->bFreezeOutput = true;
|
||||
|
||||
|
||||
if ((pDstInfo->iBufferStatus == 1) && (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag)) {
|
||||
if (pPic->bIsComplete)
|
||||
pCtx->sDecoderStatistics.uiIDRRecvNum++;
|
||||
@ -331,6 +332,14 @@ int32_t InitBsBuffer (PWelsDecoderContext pCtx) {
|
||||
}
|
||||
pCtx->sRawData.pStartPos = pCtx->sRawData.pCurPos = pCtx->sRawData.pHead;
|
||||
pCtx->sRawData.pEnd = pCtx->sRawData.pHead + pCtx->iMaxBsBufferSizeInByte;
|
||||
if (pCtx->bParseOnly) {
|
||||
if ((pCtx->sSavedData.pHead = static_cast<uint8_t*> (WelsMalloc (pCtx->iMaxBsBufferSizeInByte,
|
||||
"pCtx->sSavedData.pHead"))) == NULL) {
|
||||
return ERR_INFO_OUT_OF_MEMORY;
|
||||
}
|
||||
pCtx->sSavedData.pStartPos = pCtx->sSavedData.pCurPos = pCtx->sSavedData.pHead;
|
||||
pCtx->sSavedData.pEnd = pCtx->sSavedData.pHead + pCtx->iMaxBsBufferSizeInByte;
|
||||
}
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
@ -434,6 +443,13 @@ void WelsFreeMemory (PWelsDecoderContext pCtx) {
|
||||
pCtx->sRawData.pEnd = NULL;
|
||||
pCtx->sRawData.pStartPos = NULL;
|
||||
pCtx->sRawData.pCurPos = NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1692,7 +1708,8 @@ int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferI
|
||||
|
||||
if (ERR_NONE != iErr) {
|
||||
ForceResetCurrentAccessUnit (pCtx->pAccessUnitList);
|
||||
pDstInfo->iBufferStatus = 0;
|
||||
if (!pCtx->bParseOnly)
|
||||
pDstInfo->iBufferStatus = 0;
|
||||
return iErr;
|
||||
}
|
||||
|
||||
@ -1713,6 +1730,53 @@ int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferI
|
||||
|
||||
iErr = DecodeCurrentAccessUnit (pCtx, ppDst, pDstInfo);
|
||||
|
||||
if (pCtx->bParseOnly) {
|
||||
if (dsErrorFree == pCtx->iErrorCode) {
|
||||
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->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->iNalNum = 0;
|
||||
pCtx->pParserBsInfo->iSpsWidthInPixel = 0;
|
||||
pCtx->pParserBsInfo->iSpsHeightInPixel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
WelsDecodeAccessUnitEnd (pCtx);
|
||||
|
||||
pCtx->bNewSeqBegin = false;
|
||||
@ -1985,10 +2049,13 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
if (bReconstructSlice) {
|
||||
if (WelsDecodeConstructSlice (pCtx, pNalCur)) {
|
||||
pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false
|
||||
return -1;
|
||||
|
||||
if (!pCtx->bParseOnly) {
|
||||
if (bReconstructSlice) {
|
||||
if (WelsDecodeConstructSlice (pCtx, pNalCur)) {
|
||||
pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bAllRefComplete && (pCtx->sRefPic.uiRefCount[LIST_0] > 0 || pCtx->eSliceType != I_SLICE)) {
|
||||
@ -2031,20 +2098,21 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
|
||||
#endif//#if !CODEC_FOR_TESTBED
|
||||
|
||||
if (dq_cur->uiLayerDqId == kuiTargetLayerDqId) {
|
||||
if (!pCtx->bInstantDecFlag) {
|
||||
//Do error concealment here
|
||||
if ((NeedErrorCon (pCtx)) && (pCtx->eErrorConMethod != ERROR_CON_DISABLE)) {
|
||||
ImplementErrorCon (pCtx);
|
||||
pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
|
||||
pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
|
||||
pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
|
||||
if (!pCtx->bParseOnly) {
|
||||
if (!pCtx->bInstantDecFlag) {
|
||||
//Do error concealment here
|
||||
if ((NeedErrorCon (pCtx)) && (pCtx->eErrorConMethod != ERROR_CON_DISABLE)) {
|
||||
ImplementErrorCon (pCtx);
|
||||
pCtx->iTotalNumMbRec = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
|
||||
pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
|
||||
pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;
|
||||
}
|
||||
}
|
||||
|
||||
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
|
||||
return ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo)) {
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
if (uiNalRefIdc > 0) {
|
||||
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for EC
|
||||
iRet = WelsMarkAsRef (pCtx);
|
||||
|
@ -256,6 +256,8 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
|
||||
|
||||
pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
|
||||
pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
|
||||
pCtx->pDec->iSpsId = pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSpsId;
|
||||
pCtx->pDec->iPpsId = pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iPpsId;
|
||||
|
||||
for (j = pCurAU->uiStartPos; j <= pCurAU->uiEndPos; j++) {
|
||||
if (pCurAU->pNalUnitsList[j]->sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR
|
||||
|
@ -104,7 +104,7 @@ virtual long EXTAPI GetOption (DECODER_OPTION eOptID, void* pOption);
|
||||
PWelsDecoderContext m_pDecContext;
|
||||
welsCodecTrace* m_pWelsTrace;
|
||||
|
||||
int32_t InitDecoder (void);
|
||||
int32_t InitDecoder (const bool);
|
||||
void UninitDecoder (void);
|
||||
|
||||
#ifdef OUTPUT_BIT_STREAM
|
||||
|
@ -197,7 +197,7 @@ long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
|
||||
}
|
||||
|
||||
// H.264 decoder initialization,including memory allocation,then open it ready to decode
|
||||
iRet = InitDecoder();
|
||||
iRet = InitDecoder (pParam->bParseOnly);
|
||||
if (iRet)
|
||||
return iRet;
|
||||
|
||||
@ -232,16 +232,18 @@ void CWelsDecoder::UninitDecoder (void) {
|
||||
}
|
||||
|
||||
// the return value of this function is not suitable, it need report failure info to upper layer.
|
||||
int32_t CWelsDecoder::InitDecoder (void) {
|
||||
int32_t CWelsDecoder::InitDecoder (const bool bParseOnly) {
|
||||
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::init_decoder(), openh264 codec version = %s",
|
||||
VERSION_NUMBER);
|
||||
|
||||
if (m_pDecContext) //free
|
||||
UninitDecoder();
|
||||
m_pDecContext = (PWelsDecoderContext)WelsMalloc (sizeof (SWelsDecoderContext), "m_pDecContext");
|
||||
if (NULL == m_pDecContext)
|
||||
return cmMallocMemeError;
|
||||
|
||||
return WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
|
||||
return WelsInitDecoder (m_pDecContext, bParseOnly, &m_pWelsTrace->m_sLogCtx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -422,7 +424,7 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
|
||||
m_pDecContext->iFeedbackTidInAu = -1; //initialize
|
||||
|
||||
WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst,
|
||||
pDstInfo); //iErrorCode has been modified in this function
|
||||
pDstInfo, NULL); //iErrorCode has been modified in this function
|
||||
m_pDecContext->bInstantDecFlag = false; //reset no-delay flag
|
||||
if (m_pDecContext->iErrorCode) {
|
||||
EWelsNalUnitType eNalType =
|
||||
@ -500,7 +502,30 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
|
||||
DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc,
|
||||
const int kiSrcLen,
|
||||
SParserBsInfo* pDstInfo) {
|
||||
//TODO, add function here
|
||||
if (CheckBsBuffer (m_pDecContext, kiSrcLen)) {
|
||||
return dsOutOfMemory;
|
||||
}
|
||||
if (kiSrcLen > 0 && kpSrc != NULL) {
|
||||
#ifdef OUTPUT_BITSTREAM
|
||||
if (m_pFBS) {
|
||||
WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS);
|
||||
WelsFflush (m_pFBS);
|
||||
}
|
||||
#endif//OUTPUT_BIT_STREAM
|
||||
m_pDecContext->bEndOfStreamFlag = false;
|
||||
} else {
|
||||
//For application MODE, the error detection should be added for safe.
|
||||
//But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL.
|
||||
m_pDecContext->bEndOfStreamFlag = true;
|
||||
m_pDecContext->bInstantDecFlag = true;
|
||||
}
|
||||
|
||||
m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding.
|
||||
m_pDecContext->pParserBsInfo = pDstInfo;
|
||||
pDstInfo->iNalNum = 0;
|
||||
pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
|
||||
WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo);
|
||||
|
||||
return (DECODING_STATE) m_pDecContext->iErrorCode;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "BaseDecoderTest.h"
|
||||
#include "BaseEncoderTest.h"
|
||||
#include "wels_common_defs.h"
|
||||
#include "utils/HashFunctions.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace WelsCommon;
|
||||
@ -68,6 +69,8 @@ static void TestOutPutTrace (void* ctx, int level, const char* string) {
|
||||
|
||||
class EncodeDecodeTestBase : public ::testing::TestWithParam<EncodeDecodeFileParamBase>,
|
||||
public BaseEncoderTest, public BaseDecoderTest {
|
||||
public:
|
||||
uint8_t iRandValue;
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
BaseEncoderTest::SetUp();
|
||||
@ -103,6 +106,26 @@ class EncodeDecodeTestBase : public ::testing::TestWithParam<EncodeDecodeFilePar
|
||||
|
||||
|
||||
}
|
||||
virtual void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) {
|
||||
//for encoder
|
||||
//I420: 1(Y) + 1/4(U) + 1/4(V)
|
||||
int frameSize = EncDecFileParam.width * EncDecFileParam.height * 3 / 2;
|
||||
buf_.SetLength (frameSize);
|
||||
ASSERT_TRUE (buf_.Length() == (size_t)frameSize);
|
||||
memset (&EncPic, 0, sizeof (SSourcePicture));
|
||||
EncPic.iPicWidth = EncDecFileParam.width;
|
||||
EncPic.iPicHeight = EncDecFileParam.height;
|
||||
EncPic.iColorFormat = videoFormatI420;
|
||||
EncPic.iStride[0] = EncPic.iPicWidth;
|
||||
EncPic.iStride[1] = EncPic.iStride[2] = EncPic.iPicWidth >> 1;
|
||||
EncPic.pData[0] = buf_.data();
|
||||
EncPic.pData[1] = EncPic.pData[0] + EncDecFileParam.width * EncDecFileParam.height;
|
||||
EncPic.pData[2] = EncPic.pData[1] + (EncDecFileParam.width * EncDecFileParam.height >> 2);
|
||||
//for decoder
|
||||
memset (&info, 0, sizeof (SFrameBSInfo));
|
||||
//set a fixed random value
|
||||
iRandValue = rand() % 256;
|
||||
}
|
||||
|
||||
virtual void encToDecData (const SFrameBSInfo& info, int& len) {
|
||||
len = 0;
|
||||
@ -1983,7 +2006,6 @@ TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_P) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F (EncodeDecodeTestAPI, SetOptionEncParamExt) {
|
||||
int iWidth = (((rand() % MAX_WIDTH) >> 1) + 16) << 1;
|
||||
int iHeight = (((rand() % MAX_HEIGHT) >> 1) + 16) << 1;
|
||||
@ -2237,3 +2259,154 @@ TEST_F (DecodeCrashTestAPI, DecoderCrashTest) {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
const uint32_t kiTotalLayer = 3; //DO NOT CHANGE!
|
||||
const uint32_t kiSliceNum = 2; //DO NOT CHANGE!
|
||||
const uint32_t kiWidth = 160; //DO NOT CHANGE!
|
||||
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!
|
||||
"c58322f886a3ba958c6f60b46b98f67b5d860866",
|
||||
"f2799e1e5f6e33c6274f4e1f6273c721475492d0",
|
||||
"8f0fafeaa2746e04d42fb17104efb61c9dbd1a6f"
|
||||
};
|
||||
|
||||
class DecodeParseAPI : public EncodeDecodeTestBase {
|
||||
public:
|
||||
void SetUp() {
|
||||
SHA1Reset (&ctx_);
|
||||
EncodeDecodeTestBase::SetUp();
|
||||
|
||||
if (decoder_)
|
||||
decoder_->Uninitialize();
|
||||
SDecodingParam decParam;
|
||||
memset (&decParam, 0, sizeof (SDecodingParam));
|
||||
decParam.eOutputColorFormat = videoFormatI420;
|
||||
decParam.uiTargetDqLayer = UCHAR_MAX;
|
||||
decParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
|
||||
decParam.bParseOnly = true;
|
||||
decParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
|
||||
|
||||
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;
|
||||
iHeight_ = kiHeight;
|
||||
}
|
||||
void TearDown() {
|
||||
EncodeDecodeTestBase::TearDown();
|
||||
if (BsInfo_.pDstBuff) {
|
||||
delete[] BsInfo_.pDstBuff;
|
||||
BsInfo_.pDstBuff = NULL;
|
||||
}
|
||||
fclose (fYuv_);
|
||||
}
|
||||
|
||||
void prepareEncDecParam (const EncodeDecodeFileParamBase p) {
|
||||
EncodeDecodeTestBase::prepareEncDecParam (p);
|
||||
unsigned char* pTmpPtr = BsInfo_.pDstBuff; //store for restore
|
||||
memset (&BsInfo_, 0, sizeof (SParserBsInfo));
|
||||
BsInfo_.pDstBuff = pTmpPtr;
|
||||
}
|
||||
|
||||
void EncodeOneFrame (int iIdx) {
|
||||
int iFrameSize = iWidth_ * iHeight_ * 3 / 2;
|
||||
int iSize = fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
|
||||
if (feof (fYuv_) || iSize != iFrameSize) {
|
||||
rewind (fYuv_);
|
||||
iSize = fread (buf_.data(), sizeof (char), iFrameSize, fYuv_);
|
||||
ASSERT_TRUE (iSize == iFrameSize);
|
||||
}
|
||||
int rv = encoder_->EncodeFrame (&EncPic, &info);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
|
||||
}
|
||||
|
||||
protected:
|
||||
SParserBsInfo BsInfo_;
|
||||
FILE* fYuv_;
|
||||
int iWidth_;
|
||||
int iHeight_;
|
||||
SHA1Context ctx_;
|
||||
};
|
||||
|
||||
//#define DEBUG_FILE_SAVE
|
||||
TEST_F (DecodeParseAPI, ParseOnly_General) {
|
||||
EncodeDecodeFileParamBase p;
|
||||
p.width = iWidth_;
|
||||
p.height = iHeight_;
|
||||
p.frameRate = kiFrameRate;
|
||||
p.numframes = kiFrameNum;
|
||||
prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate);
|
||||
param_.iSpatialLayerNum = kiTotalLayer;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == 0);
|
||||
int32_t iTraceLevel = WELS_LOG_QUIET;
|
||||
encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
|
||||
decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
|
||||
uint32_t uiTargetLayerId = rand() % kiTotalLayer; //run only once
|
||||
#ifdef DEBUG_FILE_SAVE
|
||||
FILE* fDec = fopen ("output.264", "wb");
|
||||
FILE* fEnc = fopen ("enc.264", "wb");
|
||||
FILE* fExtract = fopen ("extract.264", "wb");
|
||||
#endif
|
||||
if (uiTargetLayerId < kiTotalLayer) { //should always be true
|
||||
//Start for enc
|
||||
int iLen = 0;
|
||||
prepareEncDecParam (p);
|
||||
int iFrame = 0;
|
||||
|
||||
while (iFrame < p.numframes) {
|
||||
//encode
|
||||
EncodeOneFrame (iFrame);
|
||||
//extract target layer data
|
||||
encToDecData (info, iLen);
|
||||
#ifdef DEBUG_FILE_SAVE
|
||||
fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fEnc);
|
||||
#endif
|
||||
ExtractDidNal (&info, iLen, &m_SLostSim, uiTargetLayerId);
|
||||
#ifdef DEBUG_FILE_SAVE
|
||||
fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, fExtract);
|
||||
#endif
|
||||
//parseonly
|
||||
//BsInfo_.pDstBuff = new unsigned char [1000000];
|
||||
rv = decoder_->DecodeParser (info.sLayerInfo[0].pBsBuf, iLen, &BsInfo_);
|
||||
EXPECT_TRUE (rv == 0);
|
||||
EXPECT_TRUE (BsInfo_.iNalNum == 0);
|
||||
rv = decoder_->DecodeParser (NULL, 0, &BsInfo_);
|
||||
EXPECT_TRUE (rv == 0);
|
||||
EXPECT_TRUE (BsInfo_.iNalNum != 0);
|
||||
//get final output bs
|
||||
iLen = 0;
|
||||
int i = 0;
|
||||
while (i < BsInfo_.iNalNum) {
|
||||
iLen += BsInfo_.iNalLenInByte[i];
|
||||
i++;
|
||||
}
|
||||
#ifdef DEBUG_FILE_SAVE
|
||||
fwrite (BsInfo_.pDstBuff, iLen, 1, fDec);
|
||||
#endif
|
||||
SHA1Input (&ctx_, BsInfo_.pDstBuff, iLen);
|
||||
iFrame++;
|
||||
}
|
||||
//calculate final SHA1 value
|
||||
unsigned char digest[SHA_DIGEST_LENGTH];
|
||||
SHA1Result (&ctx_, digest);
|
||||
if (!HasFatalFailure()) {
|
||||
CompareHash (digest, pHashStr[uiTargetLayerId]);
|
||||
}
|
||||
} //while
|
||||
#ifdef DEBUG_FILE_SAVE
|
||||
fclose (fEnc);
|
||||
fclose (fExtract);
|
||||
fclose (fDec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user