📄 mp4_parser_stbl.c
字号:
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
pCurTrack->uDecodeTimeDelta_SampleNo++;
uSampleNo = pCurTrack->uDecodeTimeDelta_SampleNo;
if (uSampleNo < pCurTrack->uDecodeTimeDelta_CurSampleCount) {
*puDecodeTimeDelta = pCurTrack->uDecodeTimeDelta_ThisSampleDelta;
return MP4_PARSER_OK;
}
pCurTrack->uDecodeTimeDelta_TableIndex++;
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
uDecodeTimeToSampleTableSize = pCurTrack->uTimeToSampleTableEntryCount;
if (pCurTrack->uDecodeTimeDelta_TableIndex >= uDecodeTimeToSampleTableSize)
return MP4_PARSER_READ_EOF;
if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, pCurTrack->uDecodeTimeDelta_TableIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
return ret;
*puDecodeTimeDelta = uThisSampleDelta;
pCurTrack->uDecodeTimeDelta_CurSampleCount += uThisSampleCount;
pCurTrack->uDecodeTimeDelta_ThisSampleDelta = uThisSampleDelta;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the decode time delta of certain number of consecutive samples in the
specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetDecodeTimeDelta_Array(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo,
kal_uint64 *puDecodeTimeDeltaArray, kal_uint32 *pArraySize,
MP4_Track_Type eTrackType)
{
kal_uint32 uIndex;
MP4_Parser_Status ret;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puDecodeTimeDeltaArray!=NULL);
MP4_PARSER_CHECK_ARG(pArraySize!=0);
if ((ret=MP4_GetDecodeTimeDelta(pstMp4Parser, uSampleNo, &(puDecodeTimeDeltaArray[0]) , eTrackType))!=MP4_PARSER_OK)
return ret;
for (uIndex=1; uIndex<*pArraySize; uIndex++) {
if ((ret=MP4_GetDecodeTimeDelta_Next(pstMp4Parser, &(puDecodeTimeDeltaArray[uIndex]) , eTrackType))!=MP4_PARSER_OK)
{
*pArraySize = uIndex;
return ret;
}
}
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the sample number with respect to the specified decoding time in the
specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetSampleNumber(STMp4Parser *pstMp4Parser, kal_uint32 *puSampleNo,
kal_uint64 uDecodeTime, MP4_Track_Type eTrackType)
{
kal_uint64 uCurDecodeTime = 0;
kal_uint32 uDecodeTimeToSampleTableSize;
kal_uint32 uThisSampleCount;
kal_uint32 uThisSampleDelta;
kal_uint32 uCurSampleCount = 0;
kal_uint32 uIndex = 0;
kal_uint8 bTrackNo;
MP4_Parser_Status ret;
STMp4Track *pCurTrack;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puSampleNo!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
if (pCurTrack->uSTTSCacheTableEntryCount > 0) {
/// STTS cache is enabled. Perform bunary search.
kal_uint16 start_index, end_index;
STTS_Cache_Entry *stts_cache_table;
stts_cache_table = pCurTrack->pSTTSCacheTable;
do { /// Initial Cache
MP4_STTS_ProcCacheTableByTrack(pstMp4Parser, eTrackType, 64 );
}
while (pCurTrack->uSTTSCacheIndex != pCurTrack->uSTTSCacheTableEntryCount &&
uDecodeTime > stts_cache_table[pCurTrack->uSTTSCacheIndex-1].accumulated_decode_time);
start_index = 0;
end_index = pCurTrack->uSTTSCacheIndex-1;
while ((end_index-start_index)>1) {
kal_uint16 middle_index = (start_index+end_index)>>1;
if (uDecodeTime > stts_cache_table[middle_index].accumulated_decode_time)
start_index = middle_index;
else
end_index = middle_index;
}
if (start_index) {
uIndex = end_index * pCurTrack->uSTTSCacheTableStepSize;
uCurSampleCount = stts_cache_table[start_index].accumulated_sample_count;
uCurDecodeTime = stts_cache_table[start_index].accumulated_decode_time;
}
}
uDecodeTimeToSampleTableSize = pCurTrack->uTimeToSampleTableEntryCount;
for (; uIndex<uDecodeTimeToSampleTableSize; uIndex++) {
if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, uIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
return ret;
uCurDecodeTime += (kal_uint64)uThisSampleCount * (kal_uint64)uThisSampleDelta;
uCurSampleCount += uThisSampleCount;
if (uCurDecodeTime >= uDecodeTime) {
*puSampleNo = uCurSampleCount - (uCurDecodeTime-uDecodeTime+uThisSampleDelta-1)/uThisSampleDelta;
return MP4_PARSER_OK;
}
}
return MP4_PARSER_NO_SUCH_SAMPLE;
}
/*******************************************************************************
Get the decode time with respect to the specified sample number in the
specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetDecodeTime(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo,
kal_uint64 *puDecodeTime, MP4_Track_Type eTrackType )
{
kal_uint32 uDecodeTimeToSampleTableSize;
kal_uint32 uThisSampleCount;
kal_uint32 uThisSampleDelta = 0;
kal_uint32 uCurSampleCount = 0;
kal_uint32 uIndex = 0;
kal_uint8 bTrackNo;
MP4_Parser_Status ret;
STMp4Track *pCurTrack;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puDecodeTime!=NULL);
*puDecodeTime = 0;
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
if (pCurTrack->uSTTSCacheTableEntryCount > 0) {
/// STTS cache is enabled. Perform binary search.
kal_uint16 start_index, end_index;
STTS_Cache_Entry *stts_cache_table;
stts_cache_table = pCurTrack->pSTTSCacheTable;
do { /// Initial Cache
MP4_STTS_ProcCacheTableByTrack(pstMp4Parser, eTrackType, 32 );
}
while (pCurTrack->uSTTSCacheIndex != pCurTrack->uSTTSCacheTableEntryCount &&
uSampleNo > stts_cache_table[pCurTrack->uSTTSCacheIndex-1].accumulated_sample_count);
start_index = 0;
end_index = pCurTrack->uSTTSCacheIndex-1;
while ((end_index-start_index)>1) {
kal_uint16 middle_index = (start_index+end_index)>>1;
if (uSampleNo > stts_cache_table[middle_index].accumulated_sample_count)
start_index = middle_index;
else
end_index = middle_index;
}
if (start_index) {
uIndex = end_index * pCurTrack->uSTTSCacheTableStepSize;
uCurSampleCount = stts_cache_table[start_index].accumulated_sample_count;
*puDecodeTime = stts_cache_table[start_index].accumulated_decode_time;
}
}
uDecodeTimeToSampleTableSize = pCurTrack->uTimeToSampleTableEntryCount;
for (; uIndex<uDecodeTimeToSampleTableSize; uIndex++) {
if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, uIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
return ret;
uCurSampleCount += uThisSampleCount;
if (uCurSampleCount > uSampleNo) {
*puDecodeTime += (kal_uint64)uThisSampleDelta * (kal_uint64)(uSampleNo - uCurSampleCount + uThisSampleCount );
break;
} else {
*puDecodeTime += (kal_uint64)uThisSampleDelta * (kal_uint64)uThisSampleCount;
}
}
/// if the decode time of the specified sample is 0, it is an error case.
if (uSampleNo != 0 && *puDecodeTime == pCurTrack->uDecodeTime_PrevDecodeTime
&& uSampleNo != pCurTrack->uDecodeTime_SampleNo)
return MP4_PARSER_PARSE_ERROR;
pCurTrack->uDecodeTime_SampleNo = uSampleNo;
pCurTrack->uDecodeTime_TableIndex = uIndex;
pCurTrack->uDecodeTime_PrevDecodeTime = *puDecodeTime;
pCurTrack->uDecodeTime_ThisSampleDelta = uThisSampleDelta;
pCurTrack->uDecodeTime_CurSampleCount = uCurSampleCount;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the decode time of the "NEXT" sample in the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetDecodeTime_Next(STMp4Parser *pstMp4Parser, kal_uint64 *puDecodeTime,
MP4_Track_Type eTrackType)
{
MP4_Parser_Status ret;
kal_uint32 uSampleNo;
kal_uint32 uDecodeTimeToSampleTableSize;
kal_uint32 uThisSampleCount;
kal_uint32 uThisSampleDelta;
kal_uint8 bTrackNo;
STMp4Track *pCurTrack;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puDecodeTime!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
uSampleNo = pCurTrack->uDecodeTime_SampleNo;
pCurTrack->uDecodeTime_SampleNo++;
if (uSampleNo < pCurTrack->uDecodeTime_CurSampleCount) {
pCurTrack->uDecodeTime_PrevDecodeTime += pCurTrack->uDecodeTime_ThisSampleDelta;
*puDecodeTime = pCurTrack->uDecodeTime_PrevDecodeTime;
return MP4_PARSER_OK;
}
pCurTrack->uDecodeTime_TableIndex++;
uDecodeTimeToSampleTableSize = pCurTrack->uTimeToSampleTableEntryCount;
if (pCurTrack->uDecodeTime_TableIndex >= uDecodeTimeToSampleTableSize)
return MP4_PARSER_READ_EOF;
if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, pCurTrack->uDecodeTime_TableIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
return ret;
pCurTrack->uDecodeTime_PrevDecodeTime += uThisSampleDelta;
pCurTrack->uDecodeTime_CurSampleCount += uThisSampleCount;
pCurTrack->uDecodeTime_ThisSampleDelta = uThisSampleDelta;
*puDecodeTime = pCurTrack->uDecodeTime_PrevDecodeTime;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the decode time of certain number of consecutive samples in the
specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetDecodeTime_Array(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo,
kal_uint64 *puDecodeTimeArray, kal_uint32 *pArraySize,
MP4_Track_Type eTrackType)
{
kal_uint32 uIndex;
MP4_Parser_Status ret;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puDecodeTimeArray!=NULL);
MP4_PARSER_CHECK_ARG(pArraySize!=0);
if ((ret=MP4_GetDecodeTime(pstMp4Parser, uSampleNo, &(puDecodeTimeArray[0]) , eTrackType))!=MP4_PARSER_OK)
return ret;
for (uIndex=1; uIndex<*pArraySize; uIndex++) {
if ((ret=MP4_GetDecodeTime_Next(pstMp4Parser, &(puDecodeTimeArray[uIndex]) , eTrackType))!=MP4_PARSER_OK)
{
*pArraySize = uIndex;
return ret;
}
}
return MP4_PARSER_OK;
}
/* --------------------- Sync Sample Box related functions --------------------- */
/*******************************************************************************
Get the sync sample number with respect to the given index in the sync
sample table of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetSyncSampleNo(STMp4Parser *pstMp4Parser, kal_uint32 uIndex,
kal_uint32 *puSyncSampleNo, MP4_Track_Type type)
{
MP4_Parser_Status ret;
kal_uint32 uOffset;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puSyncSampleNo!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
return ret;
MP4_PARSER_ASSERT(uIndex < pstMp4Parser->stMp4Track[bTrackNo].uSyncCount);
uOffset = pstMp4Parser->stMp4Track[bTrackNo].uOffsetSyncSampleTable;
uOffset += (uIndex * 4);
if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstMp4Parser->pstFSAL, uOffset))!=FSAL_OK)
return MP4_PARSER_FILE_SEEK_ERROR;
if ((pstMp4Parser->eFSALErr=FSAL_Read_UINT(pstMp4Parser->pstFSAL, puSyncSampleNo))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
/// Change starting number of index from 1 to 0.
*puSyncSampleNo -= 1;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the sample number of the previous sync sample of the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetPrevSyncSampleNo(STMp4Parser *pstMp4Parser, kal_uint32 uCurSampleNo,
kal_uint32 *puPrevSyncSampleNo, MP4_Track_Type eTrackType)
{
kal_uint32 uSyncSampleNo = 0;
kal_uint32 uStartIndex, uEndIndex;
kal_uint8 bTrackNo;
MP4_Parser_Status ret;
STMp4Track *pCurTrack;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puPrevSyncSampleNo!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -