Merge pull request #1721 from huili2/DecodeFrameNodelay
add new API as DecodeFrameNoDelay for immediate decoding
This commit is contained in:
@@ -114,6 +114,8 @@ typedef unsigned char bool;
|
|||||||
* this can be done in a loop until data ends
|
* this can be done in a loop until data ends
|
||||||
* @code
|
* @code
|
||||||
* //for Decoding only
|
* //for Decoding only
|
||||||
|
* iRet = DecodeFrameNoDelay(pBuf, iSize, pData, &sDstBufInfo);
|
||||||
|
* //or
|
||||||
* iRet = DecodeFrame2(pBuf, iSize, pData, &sDstBufInfo);
|
* iRet = DecodeFrame2(pBuf, iSize, pData, &sDstBufInfo);
|
||||||
* //for Parsing only
|
* //for Parsing only
|
||||||
* iRet = DecodeParser(pBuf, iSize, &sDstParseInfo);
|
* iRet = DecodeParser(pBuf, iSize, &sDstParseInfo);
|
||||||
@@ -126,10 +128,11 @@ typedef unsigned char bool;
|
|||||||
* output pData[0], pData[1], pData[2];
|
* output pData[0], pData[1], pData[2];
|
||||||
* }
|
* }
|
||||||
* //for Parsing only, sDstParseInfo can be used for, e.g., HW decoding
|
* //for Parsing only, sDstParseInfo can be used for, e.g., HW decoding
|
||||||
* if (sDstBufInfo.iBufferStatus==1){
|
* if (sDstBufInfo.iNalNum > 0){
|
||||||
* Hardware decoding sDstParseInfo;
|
* Hardware decoding sDstParseInfo;
|
||||||
* }
|
* }
|
||||||
* //no-delay decoding can be realized by directly calling decoder again with NULL input, as in the following. In this case, decoder would immediately reconstruct the input data. This can also be used similarly for Parsing only. Consequent decoding error and output indication should also be considered as above.
|
* //no-delay decoding can be realized by directly calling DecodeFrameNoDelay(), which is the recommended usage.
|
||||||
|
* //no-delay decoding can also be realized by directly calling DecodeFrame2() again with NULL input, as in the following. In this case, decoder would immediately reconstruct the input data. This can also be used similarly for Parsing only. Consequent decoding error and output indication should also be considered as above.
|
||||||
* iRet = DecodeFrame2(NULL, 0, pData, &sDstBufInfo);
|
* iRet = DecodeFrame2(NULL, 0, pData, &sDstBufInfo);
|
||||||
* judge iRet, sDstBufInfo.iBufferStatus ...
|
* judge iRet, sDstBufInfo.iBufferStatus ...
|
||||||
* @endcode
|
* @endcode
|
||||||
@@ -369,6 +372,23 @@ class ISVCDecoder {
|
|||||||
int& iWidth,
|
int& iWidth,
|
||||||
int& iHeight) = 0;
|
int& iHeight) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief For slice level DecodeFrameNoDelay() (4 parameters input),
|
||||||
|
* whatever the function return value is, the output data
|
||||||
|
* of I420 format will only be available when pDstInfo->iBufferStatus == 1,.
|
||||||
|
* This function will parse and reconstruct the input frame immediately if it is complete
|
||||||
|
* It is recommended as the main decoding function for H.264/AVC format input
|
||||||
|
* @param pSrc the h264 stream to be decoded
|
||||||
|
* @param iSrcLen the length of h264 stream
|
||||||
|
* @param ppDst buffer pointer of decoded data (YUV)
|
||||||
|
* @param pDstInfo information provided to API(width, height, etc.)
|
||||||
|
* @return 0 - success; otherwise -failed;
|
||||||
|
*/
|
||||||
|
virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
|
||||||
|
const int iSrcLen,
|
||||||
|
unsigned char** ppDst,
|
||||||
|
SBufferInfo* pDstInfo) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief For slice level DecodeFrame2() (4 parameters input),
|
* @brief For slice level DecodeFrame2() (4 parameters input),
|
||||||
* whatever the function return value is, the output data
|
* whatever the function return value is, the output data
|
||||||
@@ -472,6 +492,11 @@ DECODING_STATE (*DecodeFrame) (ISVCDecoder*, const unsigned char* pSrc,
|
|||||||
int* iWidth,
|
int* iWidth,
|
||||||
int* iHeight);
|
int* iHeight);
|
||||||
|
|
||||||
|
DECODING_STATE (*DecodeFrameNoDelay) (ISVCDecoder*, const unsigned char* pSrc,
|
||||||
|
const int iSrcLen,
|
||||||
|
unsigned char** ppDst,
|
||||||
|
SBufferInfo* pDstInfo);
|
||||||
|
|
||||||
DECODING_STATE (*DecodeFrame2) (ISVCDecoder*, const unsigned char* pSrc,
|
DECODING_STATE (*DecodeFrame2) (ISVCDecoder*, const unsigned char* pSrc,
|
||||||
const int iSrcLen,
|
const int iSrcLen,
|
||||||
unsigned char** ppDst,
|
unsigned char** ppDst,
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
|
|||||||
#if defined ( STICK_STREAM_SIZE )
|
#if defined ( STICK_STREAM_SIZE )
|
||||||
if (fpTrack) {
|
if (fpTrack) {
|
||||||
fread (pInfo, 4, sizeof (unsigned long), fpTrack);
|
fread (pInfo, 4, sizeof (unsigned long), fpTrack);
|
||||||
iSliceSize = static_cast<int32_t>(pInfo[2]);
|
iSliceSize = static_cast<int32_t> (pInfo[2]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < iFileSize; i++) {
|
for (i = 0; i < iFileSize; i++) {
|
||||||
@@ -183,6 +183,11 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
|
|||||||
iSliceSize = i;
|
iSliceSize = i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (iSliceSize < 4) { //too small size, no effective data, ignore
|
||||||
|
iBufPos += iSliceSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//for coverage test purpose
|
//for coverage test purpose
|
||||||
int32_t iOutputColorFormat;
|
int32_t iOutputColorFormat;
|
||||||
pDecoder->GetOption (DECODER_OPTION_DATAFORMAT, &iOutputColorFormat);
|
pDecoder->GetOption (DECODER_OPTION_DATAFORMAT, &iOutputColorFormat);
|
||||||
@@ -211,7 +216,11 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
|
|||||||
uiTimeStamp ++;
|
uiTimeStamp ++;
|
||||||
memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
|
memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
|
||||||
sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
|
sDstBufInfo.uiInBsTimeStamp = uiTimeStamp;
|
||||||
|
#ifndef NO_DELAY_DECODING
|
||||||
|
pDecoder->DecodeFrameNoDelay (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
|
||||||
|
#else
|
||||||
pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
|
pDecoder->DecodeFrame2 (pBuf + iBufPos, iSliceSize, pData, &sDstBufInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sDstBufInfo.iBufferStatus == 1) {
|
if (sDstBufInfo.iBufferStatus == 1) {
|
||||||
pDst[0] = pData[0];
|
pDst[0] = pData[0];
|
||||||
@@ -273,36 +282,6 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
|
|||||||
++ iSliceIndex;
|
++ iSliceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get pending last frame
|
|
||||||
pData[0] = NULL;
|
|
||||||
pData[1] = NULL;
|
|
||||||
pData[2] = NULL;
|
|
||||||
memset (&sDstBufInfo, 0, sizeof (SBufferInfo));
|
|
||||||
|
|
||||||
pDecoder->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
|
|
||||||
if (sDstBufInfo.iBufferStatus == 1) {
|
|
||||||
pDst[0] = pData[0];
|
|
||||||
pDst[1] = pData[1];
|
|
||||||
pDst[2] = pData[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sDstBufInfo.iBufferStatus == 1) {
|
|
||||||
cOutputModule.Process ((void**)pDst, &sDstBufInfo, pYuvFile);
|
|
||||||
iWidth = sDstBufInfo.UsrData.sSystemBuffer.iWidth;
|
|
||||||
iHeight = sDstBufInfo.UsrData.sSystemBuffer.iHeight;
|
|
||||||
|
|
||||||
if (pOptionFile != NULL) {
|
|
||||||
/* Anyway, we need write in case of final frame decoding */
|
|
||||||
fwrite (&iFrameCount, sizeof (iFrameCount), 1, pOptionFile);
|
|
||||||
fwrite (&iWidth , sizeof (iWidth) , 1, pOptionFile);
|
|
||||||
fwrite (&iHeight, sizeof (iHeight), 1, pOptionFile);
|
|
||||||
iLastWidth = iWidth;
|
|
||||||
iLastHeight = iHeight;
|
|
||||||
}
|
|
||||||
++ iFrameCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined ( STICK_STREAM_SIZE )
|
#if defined ( STICK_STREAM_SIZE )
|
||||||
if (fpTrack) {
|
if (fpTrack) {
|
||||||
fclose (fpTrack);
|
fclose (fpTrack);
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ virtual DECODING_STATE EXTAPI DecodeFrame (const unsigned char* kpSrc,
|
|||||||
int& iWidth,
|
int& iWidth,
|
||||||
int& iHeight);
|
int& iHeight);
|
||||||
|
|
||||||
|
virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* kpSrc,
|
||||||
|
const int kiSrcLen,
|
||||||
|
unsigned char** ppDst,
|
||||||
|
SBufferInfo* pDstInfo);
|
||||||
|
|
||||||
virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* kpSrc,
|
virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* kpSrc,
|
||||||
const int kiSrcLen,
|
const int kiSrcLen,
|
||||||
unsigned char** ppDst,
|
unsigned char** ppDst,
|
||||||
|
|||||||
@@ -394,6 +394,22 @@ long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
|
|||||||
return cmInitParaError;
|
return cmInitParaError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODING_STATE CWelsDecoder::DecodeFrameNoDelay (const unsigned char* kpSrc,
|
||||||
|
const int kiSrcLen,
|
||||||
|
unsigned char** ppDst,
|
||||||
|
SBufferInfo* pDstInfo) {
|
||||||
|
int iRet;
|
||||||
|
SBufferInfo sTmpBufferInfo;
|
||||||
|
iRet = (int) DecodeFrame2 (kpSrc, kiSrcLen, ppDst, pDstInfo);
|
||||||
|
memcpy (&sTmpBufferInfo, pDstInfo, sizeof (SBufferInfo));
|
||||||
|
iRet |= DecodeFrame2 (NULL, 0, ppDst, pDstInfo);
|
||||||
|
if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) {
|
||||||
|
memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (DECODING_STATE) iRet;
|
||||||
|
}
|
||||||
|
|
||||||
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
|
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
|
||||||
const int kiSrcLen,
|
const int kiSrcLen,
|
||||||
unsigned char** ppDst,
|
unsigned char** ppDst,
|
||||||
|
|||||||
@@ -2,34 +2,35 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
// Cast to this function type to ignore other parameters.
|
// Cast to this function type to ignore other parameters.
|
||||||
typedef int (*Func)(const void*);
|
typedef int (*Func) (const void*);
|
||||||
#define CALL(p, m) (((Func)((*p)->m))(p))
|
#define CALL(p, m) (((Func)((*p)->m))(p))
|
||||||
// Check if the function return an expected number.
|
// Check if the function return an expected number.
|
||||||
#define CHECK(n, p, m) check(n, CALL(p, m), #m)
|
#define CHECK(n, p, m) check(n, CALL(p, m), #m)
|
||||||
|
|
||||||
typedef void(*CheckFunc)(int, int, const char*);
|
typedef void (*CheckFunc) (int, int, const char*);
|
||||||
|
|
||||||
void CheckEncoderInterface(ISVCEncoder* p, CheckFunc check) {
|
void CheckEncoderInterface (ISVCEncoder* p, CheckFunc check) {
|
||||||
CHECK(1, p, Initialize);
|
CHECK (1, p, Initialize);
|
||||||
CHECK(2, p, InitializeExt);
|
CHECK (2, p, InitializeExt);
|
||||||
CHECK(3, p, GetDefaultParams);
|
CHECK (3, p, GetDefaultParams);
|
||||||
CHECK(4, p, Uninitialize);
|
CHECK (4, p, Uninitialize);
|
||||||
CHECK(5, p, EncodeFrame);
|
CHECK (5, p, EncodeFrame);
|
||||||
CHECK(6, p, EncodeParameterSets);
|
CHECK (6, p, EncodeParameterSets);
|
||||||
CHECK(7, p, ForceIntraFrame);
|
CHECK (7, p, ForceIntraFrame);
|
||||||
CHECK(8, p, SetOption);
|
CHECK (8, p, SetOption);
|
||||||
CHECK(9, p, GetOption);
|
CHECK (9, p, GetOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckDecoderInterface(ISVCDecoder* p, CheckFunc check) {
|
void CheckDecoderInterface (ISVCDecoder* p, CheckFunc check) {
|
||||||
CHECK(1, p, Initialize);
|
CHECK (1, p, Initialize);
|
||||||
CHECK(2, p, Uninitialize);
|
CHECK (2, p, Uninitialize);
|
||||||
CHECK(3, p, DecodeFrame);
|
CHECK (3, p, DecodeFrame);
|
||||||
CHECK(4, p, DecodeFrame2);
|
CHECK (4, p, DecodeFrameNoDelay);
|
||||||
CHECK(5, p, DecodeFrameEx);
|
CHECK (5, p, DecodeFrame2);
|
||||||
CHECK(6, p, DecodeParser);
|
CHECK (6, p, DecodeFrameEx);
|
||||||
CHECK(7, p, SetOption);
|
CHECK (7, p, DecodeParser);
|
||||||
CHECK(8, p, GetOption);
|
CHECK (8, p, SetOption);
|
||||||
|
CHECK (9, p, GetOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bool_test_struct {
|
struct bool_test_struct {
|
||||||
@@ -37,14 +38,14 @@ struct bool_test_struct {
|
|||||||
bool b;
|
bool b;
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t GetBoolSize(void) {
|
size_t GetBoolSize (void) {
|
||||||
return sizeof(bool);
|
return sizeof (bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetBoolOffset(void) {
|
size_t GetBoolOffset (void) {
|
||||||
return offsetof(struct bool_test_struct, b);
|
return offsetof (struct bool_test_struct, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetBoolStructSize(void) {
|
size_t GetBoolStructSize (void) {
|
||||||
return sizeof(struct bool_test_struct);
|
return sizeof (struct bool_test_struct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,29 +77,34 @@ struct SVCDecoderImpl : public ISVCDecoder {
|
|||||||
EXPECT_TRUE (gThis == this);
|
EXPECT_TRUE (gThis == this);
|
||||||
return static_cast<DECODING_STATE> (3);
|
return static_cast<DECODING_STATE> (3);
|
||||||
}
|
}
|
||||||
virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
|
virtual DECODING_STATE EXTAPI DecodeFrameNoDelay (const unsigned char* pSrc,
|
||||||
const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
|
const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
|
||||||
EXPECT_TRUE (gThis == this);
|
EXPECT_TRUE (gThis == this);
|
||||||
return static_cast<DECODING_STATE> (4);
|
return static_cast<DECODING_STATE> (4);
|
||||||
}
|
}
|
||||||
|
virtual DECODING_STATE EXTAPI DecodeFrame2 (const unsigned char* pSrc,
|
||||||
|
const int iSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) {
|
||||||
|
EXPECT_TRUE (gThis == this);
|
||||||
|
return static_cast<DECODING_STATE> (5);
|
||||||
|
}
|
||||||
virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
|
virtual DECODING_STATE EXTAPI DecodeFrameEx (const unsigned char* pSrc,
|
||||||
const int iSrcLen, unsigned char* pDst, int iDstStride,
|
const int iSrcLen, unsigned char* pDst, int iDstStride,
|
||||||
int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) {
|
int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) {
|
||||||
EXPECT_TRUE (gThis == this);
|
EXPECT_TRUE (gThis == this);
|
||||||
return static_cast<DECODING_STATE> (5);
|
return static_cast<DECODING_STATE> (6);
|
||||||
}
|
}
|
||||||
virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
|
virtual DECODING_STATE EXTAPI DecodeParser (const unsigned char* pSrc,
|
||||||
const int iSrcLen, SParserBsInfo* pDstInfo) {
|
const int iSrcLen, SParserBsInfo* pDstInfo) {
|
||||||
EXPECT_TRUE (gThis == this);
|
EXPECT_TRUE (gThis == this);
|
||||||
return static_cast<DECODING_STATE> (6);
|
return static_cast<DECODING_STATE> (7);
|
||||||
}
|
}
|
||||||
virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) {
|
virtual long EXTAPI SetOption (DECODER_OPTION eOptionId, void* pOption) {
|
||||||
EXPECT_TRUE (gThis == this);
|
EXPECT_TRUE (gThis == this);
|
||||||
return 7;
|
return static_cast<DECODING_STATE> (8);
|
||||||
}
|
}
|
||||||
virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) {
|
virtual long EXTAPI GetOption (DECODER_OPTION eOptionId, void* pOption) {
|
||||||
EXPECT_TRUE (gThis == this);
|
EXPECT_TRUE (gThis == this);
|
||||||
return 8;
|
return static_cast<DECODING_STATE> (9);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user