📄 mp4_parser_stbl.c
字号:
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
uEndIndex = pCurTrack->uSyncCount;
/// If the Sync Sample Box is not present, every sample is a random access point.
if (uEndIndex==0) {
*puPrevSyncSampleNo = uCurSampleNo;
return MP4_PARSER_OK;
}
if (pCurTrack->uSTSSCacheTableEntryCount > 0) {
/// STSS cache is enabled. Perform binary search.
kal_uint16 start_index, end_index;
STSS_Cache_Entry *stss_cache_table;
stss_cache_table = pCurTrack->pSTSSCacheTable;
do { /// Initial Cache
MP4_STSS_ProcCacheTableByTrack(pstMp4Parser, eTrackType, 4 );
}
while (pCurTrack->uSTSSCacheIndex != pCurTrack->uSTSSCacheTableEntryCount &&
uCurSampleNo > stss_cache_table[pCurTrack->uSTSSCacheIndex-1].sample_number);
start_index = 0;
end_index = pCurTrack->uSTSSCacheIndex-1;
while ((end_index-start_index)>1) {
kal_uint16 middle_index = (start_index+end_index)>>1;
if (uCurSampleNo > stss_cache_table[middle_index].sample_number)
start_index = middle_index;
else
end_index = middle_index;
}
uStartIndex = start_index * pCurTrack->uSTSSCacheTableStepSize;
uEndIndex = end_index * pCurTrack->uSTSSCacheTableStepSize;
}
else {
uStartIndex = 0;
uEndIndex --;
}
/// Perform binary search
while ((uEndIndex-uStartIndex)>1) {
kal_uint32 uMiddleIndex = (uStartIndex+uEndIndex)>>1;
if ((ret=MP4_GetSyncSampleNo(pstMp4Parser, uMiddleIndex, &uSyncSampleNo, eTrackType))!=MP4_PARSER_OK)
return ret;
if (uCurSampleNo > uSyncSampleNo)
uStartIndex = uMiddleIndex;
else
uEndIndex = uMiddleIndex;
}
if ((ret=MP4_GetSyncSampleNo(pstMp4Parser, uStartIndex, puPrevSyncSampleNo, eTrackType))!=MP4_PARSER_OK)
return ret;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the audio type of the MP4 parser.
*******************************************************************************/
MP4_Audio_Type MP4_GetAudioType(STMp4Parser *pstMp4Parser)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
return pstMp4Parser->bAudioType;
}
/*******************************************************************************
Get the video type of the MP4 parser.
*******************************************************************************/
MP4_Video_Type MP4_GetVideoType(STMp4Parser *pstMp4Parser)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
return pstMp4Parser->bVideoType;
}
/*******************************************************************************
Get the offset of MOOV box.
*******************************************************************************/
kal_uint32 MP4_GetMovieHeaderOffset(STMp4Parser *pstMp4Parser)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
return pstMp4Parser->uMOOVOffset;
}
/*******************************************************************************
Get the offset of VOS.
*******************************************************************************/
kal_uint32 MP4_Video_GetVOSOffset(STMp4Parser *pstMp4Parser)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_ASSERT(MP4_VIDEO_MPEG4==MP4_GetVideoType(pstMp4Parser));
return pstMp4Parser->uVOSOffset;
}
/*******************************************************************************
Get the size of VOS.
*******************************************************************************/
kal_uint32 MP4_Video_GetVOSSize(STMp4Parser *pstMp4Parser)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_ASSERT(MP4_VIDEO_MPEG4==MP4_GetVideoType(pstMp4Parser));
return pstMp4Parser->uVOSSize;
}
/*******************************************************************************
Set the FSAL interface for STCO box.
*******************************************************************************/
MP4_Parser_Status MP4_SetFSAL_STCO(STMp4Parser *pstMp4Parser, MP4_Track_Type eTrackType, STFSAL *pstFSAL)
{
MP4_Parser_Status ret;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(pstFSAL!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pstMp4Parser->stMp4Track[bTrackNo].pstFSAL_STCO = pstFSAL;
return MP4_PARSER_OK;
}
/*******************************************************************************
Set the FSAL interface for STSZ box.
*******************************************************************************/
MP4_Parser_Status MP4_SetFSAL_STSZ(STMp4Parser *pstMp4Parser, MP4_Track_Type eTrackType, STFSAL *pstFSAL)
{
MP4_Parser_Status ret;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(pstFSAL!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pstMp4Parser->stMp4Track[bTrackNo].pstFSAL_STSZ = pstFSAL;
return MP4_PARSER_OK;
}
/*******************************************************************************
Update the sample count. Compare the sample count calculated from STSC and
stored in STSZ and make the smaller one to be the real sample count.
*******************************************************************************/
MP4_Parser_Status MP4_UpdateSampleCount(STMp4Parser *pstMp4Parser, MP4_Track_Type eTrackType)
{
kal_uint32 uSampleToChunkIndex;
kal_uint32 uFirstChunk, uLastChunk;
kal_uint32 uSampleToChunkEntryCount;
kal_uint32 uSampleSum = 0;
kal_uint32 uSamplePerChunk;
kal_uint8 bTrackNo;
STMp4Track *pCurTrack;
MP4_Parser_Status ret;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
if ((ret = MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
if (pCurTrack->bSampleCountUpdated)
return MP4_PARSER_OK;
if ((ret = MP4_GetSampleToChunkEntryCount(pstMp4Parser, eTrackType, &uSampleToChunkEntryCount))!=MP4_PARSER_OK)
return ret;
pCurTrack->uSampleToChunkEntryCount = uSampleToChunkEntryCount;
uSampleToChunkEntryCount--;
for (uSampleToChunkIndex=0; uSampleToChunkIndex<uSampleToChunkEntryCount; uSampleToChunkIndex++) {
if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
uSampleSum += (uLastChunk - uFirstChunk)*uSamplePerChunk;
}
// handle the last entry
if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
if ((ret = MP4_GetChunkCount(pstMp4Parser, eTrackType, &uLastChunk))!=MP4_PARSER_OK)
return ret;
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
uSampleSum += (uLastChunk - uFirstChunk)*uSamplePerChunk;
if( pCurTrack->uSampleCount > uSampleSum )
pCurTrack->uSampleCount = uSampleSum;
pCurTrack->bSampleCountUpdated = KAL_TRUE;
return MP4_PARSER_OK;
}
/*******************************************************************************
Initialize the STTS cache of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_STTS_InitCacheTableByTrack( STMp4Parser *pstMp4Parser, MP4_Track_Type eTrackType,
STTS_Cache_Entry *pSTTSCacheTable, kal_uint32 uSTTSCacheTableCount,
kal_uint32 *puSTTSCacheTblCntExist)
{
kal_uint32 uThisSampleCount;
kal_uint32 uThisSampleDelta;
kal_uint32 uIndex = 0;
kal_uint32 uSTTSEntryCount = 0;
kal_uint32 uCurSampleCount = 0;
kal_uint64 uCurDecodeTime = 0;
kal_uint16 uCacheIndex = 0;
kal_uint16 uStepSize = 0;
kal_uint16 uStepCounter = 0;
kal_uint8 bTrackNo;
MP4_Parser_Status ret;
*puSTTSCacheTblCntExist = 0;
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
uSTTSEntryCount = pstMp4Parser->stMp4Track[bTrackNo].uTimeToSampleTableEntryCount;
if ((0==uSTTSCacheTableCount) || (0==uSTTSEntryCount))
return MP4_PARSER_OK;
uStepSize = (uSTTSEntryCount+uSTTSCacheTableCount-1) / uSTTSCacheTableCount;
/* avoid divide-by-zero */
if (0 == uStepSize)
uStepSize = 1;
uSTTSCacheTableCount = uSTTSEntryCount / uStepSize;
/// In the initialization, process at most 2048 STTS entries to prevent the response time
/// from being too long.
if (uSTTSEntryCount > 4096)
uSTTSEntryCount = 4096;
for (uIndex=0; uIndex<uSTTSEntryCount; uIndex++) {
if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, uIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
return ret;
uCurSampleCount += uThisSampleCount;
uCurDecodeTime += (kal_uint64)uThisSampleDelta * (kal_uint64)uThisSampleCount;
uStepCounter++;
if (uStepCounter == uStepSize) {
uStepCounter = 0;
pSTTSCacheTable[uCacheIndex].accumulated_sample_count = uCurSampleCount;
pSTTSCacheTable[uCacheIndex++].accumulated_decode_time = uCurDecodeTime;
if( uCacheIndex == uSTTSCacheTableCount )
break;
}
}
pstMp4Parser->stMp4Track[bTrackNo].uSTTSStepCounter = uStepCounter;
pstMp4Parser->stMp4Track[bTrackNo].uSTTSCurSampleCount = uCurSampleCount;
pstMp4Parser->stMp4Track[bTrackNo].uSTTSCurDecodeTime = uCurDecodeTime;
pstMp4Parser->stMp4Track[bTrackNo].uSTTSCacheIndex = uCacheIndex;
pstMp4Parser->stMp4Track[bTrackNo].uSTTSIndex = uIndex;
pstMp4Parser->stMp4Track[bTrackNo].pSTTSCacheTable = pSTTSCacheTable;
pstMp4Parser->stMp4Track[bTrackNo].uSTTSCacheTableStepSize = uStepSize;
pstMp4Parser->stMp4Track[bTrackNo].uSTTSCacheTableEntryCount = uSTTSCacheTableCount;
*puSTTSCacheTblCntExist = uSTTSCacheTableCount;
return MP4_PARSER_OK;
}
/*******************************************************************************
Process certain number of STTS cache of the specified track.
uCount is the number of STTS entries to be processed.
*******************************************************************************/
static MP4_Parser_Status MP4_STTS_ProcCacheTableByTrack( STMp4Parser *pstMp4Parser, MP4_Track_Type eTrackType, kal_uint16 uCount )
{
kal_uint32 uIndex, local_counter;
kal_uint32 uSTTSEntryCount, uSTTSCacheTableCount;
kal_uint32 uThisSampleCount;
kal_uint32 uThisSampleDelta;
kal_uint32 uCurSampleCount;
kal_uint64 uCurDecodeTime;
kal_uint16 uCacheIndex;
kal_uint16 uStepSize;
kal_uint16 uStepCounter;
kal_uint8 bTrackNo;
MP4_Parser_Status ret;
STTS_Cache_Entry *pSTTSCacheTable;
STMp4Track *pCurTrack;
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
uCacheIndex = pCurTrack->uSTTSCacheIndex;
uSTTSCacheTableCount = pCurTrack->uSTTSCacheTableEntryCount;
if (uSTTSCacheTableCount==0 || uCacheIndex==uSTTSCacheTableCount)
return MP4_PARSER_OK;
uSTTSEntryCount = pCurTrack->uTimeToSampleTableEntryCount;
uStepCounter = pCurTrack->uSTTSStepCounter;
uCurSampleCount = pCurTrack->uSTTSCurSampleCount;
uCurDecodeTime = pCurTrack->uSTTSCurDecodeTime;
uIndex = pCurTrack->uSTTSIndex;
pSTTSCacheTable = pCurTrack->pSTTSCacheTable;
uStepSize = pCurTrack->uSTTSCacheTableStepSize;
for (local_counter=0; uIndex<uSTTSEntryCount && local_counter<uCount; uIndex++, local_counter++) {
if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, uIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
return ret;
uCurSampleCount += uThisSampleCount;
uCurDecodeTime += (kal_uint64)uThisSampleDelta * (kal_uint64)uThisSampleCount;
uStepCounter++;
if (uStepCounter == uStepSize) {
uStepCounter = 0;
pSTTSCacheTable[uCacheIndex].accumulated_sample_count = uCurSampleCount;
pSTTSCacheTable[uCacheIndex++].accumulated_decode_time = uCurDecodeTime;
if( uCacheIndex == uSTTSCacheTableCount )
break;
}
}
pCurTrack->uSTTSStepCounter = uStepCounter;
pCurTrack->uSTTSCurSampleCount = uCurSampleCount;
pCurTrack->uSTTSCurDecodeTime = uCurDecodeTime;
pCurTrack->uSTTSCacheIndex = uCacheIndex;
pCurTrack->uSTTSIndex = uIndex;
return MP4_PARSER_OK;
}
/*******************************************************************************
Initialize the STTS cache.
*******************************************************************************/
static MP4_Parser_Status MP4_STTS_InitCacheTable(STMp4Parser *pstMp4Parser, kal_uint32 *pSTTSCachePool, kal_uint32 uSTTSCachePoolSize, kal_uint32 *puSTTSCachePoolUsed)
{
MP4_Parser_Status ret;
kal_uint8 bTrackNo;
STMp4Track *pAudioTrack, *pVideoTrack;
const kal_uint16 entry_size = sizeof(STTS_Cache_Entry)/sizeof(kal_uint32);
*puSTTSCachePoolUsed = 0;
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, MP4_TRACK_AUDIO, &bTrackNo))!=MP4_PARSER_OK)
pAudioTrack = NULL;
else
pAudioTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -