📄 mp4_parser_stbl.c
字号:
kal_uint32 uOffset;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puChunkOffset!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
return ret;
MP4_PARSER_ASSERT(uChunkNo<pstMp4Parser->stMp4Track[bTrackNo].uChunkCount);
uOffset = pstMp4Parser->stMp4Track[bTrackNo].uOffsetChunkOffsetTable;
uOffset += (uChunkNo * 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, puChunkOffset))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
return MP4_PARSER_OK;
}
/* --------------------- Sample To Chunk Table related functions --------------------- */
/*******************************************************************************
Get the the number of entries in the STSC box of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetSampleToChunkEntryCount(STMp4Parser *pstMp4Parser, MP4_Track_Type type, kal_uint32 *puEntryCount)
{
MP4_Parser_Status ret;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puEntryCount!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
return ret;
*puEntryCount = pstMp4Parser->stMp4Track[bTrackNo].uSampleToChunkEntryCount;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the index of the first chunk of the specified run in the STSC box
of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetFirstChunkInRun(STMp4Parser *pstMp4Parser, kal_uint32 uRun,
kal_uint32 *puFirstChunkInRun, MP4_Track_Type type)
{
MP4_Parser_Status ret;
kal_uint32 uOffset;
kal_uint8 bTrackNo;
STFSAL *pstFSAL_STCO;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puFirstChunkInRun!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK) {
return ret;
}
MP4_PARSER_ASSERT(uRun<pstMp4Parser->stMp4Track[bTrackNo].uSampleToChunkEntryCount);
pstFSAL_STCO = pstMp4Parser->stMp4Track[bTrackNo].pstFSAL_STCO;
if (pstFSAL_STCO == NULL)
pstFSAL_STCO = pstMp4Parser->pstFSAL;
uOffset = pstMp4Parser->stMp4Track[bTrackNo].uOffsetSampleToChunkTable;
uOffset += (uRun * 12);
if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstFSAL_STCO, uOffset))!=FSAL_OK)
return MP4_PARSER_FILE_SEEK_ERROR;
if ((pstMp4Parser->eFSALErr=FSAL_Read_UINT(pstFSAL_STCO, puFirstChunkInRun))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
*puFirstChunkInRun -= 1; /// index from 0
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the number of samples per chunk of the specified run in the STSC box
of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetSamplePerChunkInRun(STMp4Parser *pstMp4Parser, kal_uint32 uRun,
kal_uint32 *puSamplePerChunk, MP4_Track_Type type)
{
MP4_Parser_Status ret;
kal_uint32 uOffset;
kal_uint8 bTrackNo;
STMp4Track *pCurTrack;
STFSAL *pstFSAL_STCO;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puSamplePerChunk!=NULL);
if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
MP4_PARSER_ASSERT(uRun < pCurTrack->uSampleToChunkEntryCount);
pstFSAL_STCO = pCurTrack->pstFSAL_STCO;
if (pstFSAL_STCO == NULL)
pstFSAL_STCO = pstMp4Parser->pstFSAL;
uOffset = pCurTrack->uOffsetSampleToChunkTable;
uOffset += (uRun * 12 + 4);
if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstFSAL_STCO, uOffset))!=FSAL_OK)
return MP4_PARSER_FILE_SEEK_ERROR;
if ((pstMp4Parser->eFSALErr=FSAL_Read_UINT(pstFSAL_STCO, puSamplePerChunk))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
return MP4_PARSER_OK;
}
/*******************************************************************************
Get the number of the chunk and the file offset of the chunk
where the specified sample resides in.
*******************************************************************************/
static MP4_Parser_Status MP4_GetChunkNoAndOffset(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo,
kal_uint32 *puSampleInChunk, kal_uint32 *puSampleOffsetChunk,
MP4_Track_Type eTrackType )
{
MP4_Parser_Status ret;
kal_uint32 uSamplePerChunk;
kal_uint32 uSampleToChunkIndex = 0;
kal_uint32 uFirstChunk, uLastChunk;
kal_uint32 uSampleToChunkEntryCount = 0;
kal_uint32 uSampleSumPrev = 0, uSampleSum = 0;
STMp4Track *pCurTrack;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puSampleInChunk!=NULL);
MP4_PARSER_CHECK_ARG(puSampleOffsetChunk!=NULL);
if ((ret = MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
if ((ret = MP4_GetSampleToChunkEntryCount(pstMp4Parser, eTrackType, &uSampleToChunkEntryCount))!=MP4_PARSER_OK)
return ret;
if (pCurTrack->uSTSCCacheTableEntryCount > 0)
{ /// STSC cache is enabled. Perform binary search in the cache.
kal_uint16 start_index, end_index;
STSC_Cache_Entry *stsc_cache_table;
stsc_cache_table = pCurTrack->pSTSCCacheTable;
start_index = 0;
end_index = pCurTrack->uSTSCCacheTableEntryCount-1;
while ((end_index-start_index)>1)
{
kal_uint16 middle_index = (start_index+end_index)>>1;
if( uSampleNo > stsc_cache_table[middle_index].accumulated_sample_count )
start_index = middle_index;
else
end_index = middle_index;
}
if (start_index)
{
uSampleToChunkIndex=end_index * pCurTrack->uSTSCCacheTableStepSize;
uSampleSum = stsc_cache_table[start_index].accumulated_sample_count;
uSampleSumPrev = uSampleSum;
}
}
for (; uSampleToChunkIndex<uSampleToChunkEntryCount; uSampleToChunkIndex++) {
if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
if (uSampleToChunkIndex == uSampleToChunkEntryCount-1) {
if ((ret = MP4_GetChunkCount(pstMp4Parser, eTrackType, &uLastChunk))!=MP4_PARSER_OK)
return ret;
uLastChunk--;
} else {
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
uLastChunk--;
}
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, eTrackType))!=MP4_PARSER_OK)
return ret;
uSampleSum += (uLastChunk - uFirstChunk + 1)*uSamplePerChunk;
if (uSampleNo<uSampleSum) {
*puSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
*puSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
pCurTrack->uSampleToChunkIndex = uSampleToChunkIndex;
pCurTrack->uSamplePerChunk = uSamplePerChunk;
pCurTrack->uFirstChunk = uFirstChunk;
pCurTrack->uSampleSum = uSampleSum;
pCurTrack->uSampleSumPrev = uSampleSumPrev;
return MP4_PARSER_OK;
}
uSampleSumPrev = uSampleSum;
}
return MP4_PARSER_INTERNAL_ERROR;
}
static MP4_Parser_Status MP4_GetChunkNoAndOffset_Next(STMp4Parser *pstMp4Parser, kal_uint32 *uSampleInChunk, kal_uint32 *uSampleOffsetChunk, MP4_Track_Type type)
{
kal_uint32 uSampleToChunkIndex, uSampleNo;
kal_uint32 uFirstChunk, uLastChunk;
kal_uint32 uSampleToChunkEntryCount;
kal_uint32 uSamplePerChunk;
kal_uint32 uSampleSum, uSampleSumPrev;
MP4_Parser_Status ret;
STMp4Track *pCurTrack;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(uSampleInChunk!=NULL);
MP4_PARSER_CHECK_ARG(uSampleOffsetChunk!=NULL);
if ((ret = MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
uSampleNo = pCurTrack->uCurSampleNo;
uSampleToChunkEntryCount = pCurTrack->uSampleToChunkEntryCount;
uSampleToChunkIndex = pCurTrack->uSampleToChunkIndex;
uSampleSum = pCurTrack->uSampleSum;
uSampleSumPrev = pCurTrack->uSampleSumPrev;
uSamplePerChunk = pCurTrack->uSamplePerChunk;
uFirstChunk = pCurTrack->uFirstChunk;
if (uSampleNo<uSampleSum) {
*uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
*uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
return MP4_PARSER_OK;
}
uSampleSumPrev = uSampleSum;
uSampleToChunkIndex++;
if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, type))!=MP4_PARSER_OK) {
return ret;
}
if (uSampleToChunkIndex == uSampleToChunkEntryCount-1) {
if ((ret = MP4_GetChunkCount(pstMp4Parser, type, &uLastChunk))!=MP4_PARSER_OK) {
return ret;
}
uLastChunk--;
} else {
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, type))!=MP4_PARSER_OK) {
return ret;
}
uLastChunk--;
}
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, type))!=MP4_PARSER_OK) {
return ret;
}
uSampleSum += (uLastChunk - uFirstChunk + 1)*uSamplePerChunk;
*uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
*uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
pCurTrack->uSampleToChunkIndex = uSampleToChunkIndex;
pCurTrack->uSamplePerChunk = uSamplePerChunk;
pCurTrack->uFirstChunk = uFirstChunk;
pCurTrack->uSampleSum = uSampleSum;
pCurTrack->uSampleSumPrev = uSampleSumPrev;
return MP4_PARSER_OK;
}
static MP4_Parser_Status MP4_GetChunkNoAndOffset_Previous(STMp4Parser *pstMp4Parser, kal_uint32 *uSampleInChunk, kal_uint32 *uSampleOffsetChunk, MP4_Track_Type type)
{
kal_uint32 uSampleToChunkIndex, uSampleNo;
kal_uint32 uFirstChunk, uLastChunk;
kal_uint32 uSampleToChunkEntryCount;
kal_uint32 uSamplePerChunk;
kal_uint32 uSampleSum, uSampleSumPrev;
MP4_Parser_Status ret;
STMp4Track *pCurTrack;
kal_uint8 bTrackNo;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(uSampleInChunk!=NULL);
MP4_PARSER_CHECK_ARG(uSampleOffsetChunk!=NULL);
if ((ret = MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
return ret;
pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);
uSampleNo = pCurTrack->uCurSampleNo;
uSampleToChunkEntryCount = pCurTrack->uSampleToChunkEntryCount;
uSampleToChunkIndex = pCurTrack->uSampleToChunkIndex;
uSampleSum = pCurTrack->uSampleSum;
uSampleSumPrev = pCurTrack->uSampleSumPrev;
uSamplePerChunk = pCurTrack->uSamplePerChunk;
uFirstChunk = pCurTrack->uFirstChunk;
if (uSampleNo > uSampleSumPrev) {
*uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
*uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
return MP4_PARSER_OK;
}
uSampleSum = uSampleSumPrev;
uSampleToChunkIndex--;
if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, type))!=MP4_PARSER_OK) {
return ret;
}
if (uSampleToChunkIndex == uSampleToChunkEntryCount-1) {
if ((ret = MP4_GetChunkCount(pstMp4Parser, type, &uLastChunk))!=MP4_PARSER_OK) {
return ret;
}
uLastChunk--;
} else {
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, type))!=MP4_PARSER_OK) {
return ret;
}
uLastChunk--;
}
if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, type))!=MP4_PARSER_OK) {
return ret;
}
uSampleSumPrev -= (uLastChunk - uFirstChunk + 1)*uSamplePerChunk;
*uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
*uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
pCurTrack->uSampleToChunkIndex = uSampleToChunkIndex;
pCurTrack->uSamplePerChunk = uSamplePerChunk;
pCurTrack->uFirstChunk = uFirstChunk;
pCurTrack->uSampleSum = uSampleSum;
pCurTrack->uSampleSumPrev = uSampleSumPrev;
return MP4_PARSER_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -