📄 mp4_parser_audio.c
字号:
MP4_PARSER_ASSERT(pstMp4Parser->uADIFFrameHeaderLen ==
(63 + pstMp4Parser->uAudioPCEBitLength + 7) / 8 + 1);
return MP4_PARSER_OK;
}
/*
* Prepare for every audio sample of the whole stream.
*/
void prepareADTSFrameHeader(STMp4Parser *pstMp4Parser, kal_uint8* pbFrameHeader, kal_uint32 uSampleSize)
{
kal_uint32 uBitCnt;
MP4_PARSER_ASSERT_NO_RET_VAL(pstMp4Parser!=NULL);
MP4_PARSER_ASSERT_NO_RET_VAL(pbFrameHeader!=NULL);
/* adts_fixed_header */
uBitCnt = 0;
putbits(pbFrameHeader, &uBitCnt, 0xFFF, 12); // syncword
putbits(pbFrameHeader, &uBitCnt, 0, 1); // ID
putbits(pbFrameHeader, &uBitCnt, 0, 2); // Layer
putbits(pbFrameHeader, &uBitCnt, 1, 1); // Protection absent
putbits(pbFrameHeader, &uBitCnt, 1, 2); // Profile
putbits(pbFrameHeader, &uBitCnt, MP4_Audio_GetFreqIndex(pstMp4Parser), 4); // sample_frequency_index
putbits(pbFrameHeader, &uBitCnt, 0, 1); // private_bit
putbits(pbFrameHeader, &uBitCnt, pstMp4Parser->bAudioChannelConfig, 3); // Channel_configuration
putbits(pbFrameHeader, &uBitCnt, 1, 1); // original_copy
putbits(pbFrameHeader, &uBitCnt, 0, 1); // Home
/* adts_variable_header */
putbits(pbFrameHeader, &uBitCnt, 0, 1); // copy_identification_bit
putbits(pbFrameHeader, &uBitCnt, 0, 1); // copy_identification_byte
putbits(pbFrameHeader, &uBitCnt, uSampleSize + ADTS_HEADER_SIZE, 13); // length
putbits(pbFrameHeader, &uBitCnt, 0x7FF, 11); // buffer_fullness
putbits(pbFrameHeader, &uBitCnt, 0, 2); // no_raw_data_blocks_in_frame
MP4_PARSER_ASSERT_NO_RET_VAL(uBitCnt==56);
}
MP4_Parser_Status prepareAACFrameHeader(STMp4Parser *pstMp4Parser)
{
MP4_Parser_Status ret;
MP4_Audio_Type eAudioType;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
eAudioType = MP4_GetAudioType(pstMp4Parser);
if (eAudioType != MP4_AUDIO_AAC)
return MP4_PARSER_OK;
if (pstMp4Parser->bAudioChannelConfig==0) {
/* Generate ADIF stream */
pstMp4Parser->bAddADIFFrameHeader = KAL_TRUE;
if ((ret=prepareADIFFrameHeader(pstMp4Parser))!=MP4_PARSER_OK)
return ret;
} else {
/* Generate ADTS stream */
pstMp4Parser->bAddADTSFrameHeader = KAL_TRUE;
}
return MP4_PARSER_OK;
}
kal_uint8 MP4_Audio_GetFreqIndex(STMp4Parser *pstMp4Parser)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
return pstMp4Parser->bAudioSamplingFreqIndex;
}
MP4_Parser_Status MP4_Audio_SetFSAL(STMp4Parser *pstMp4Parser, STFSAL *pstFSALAudio)
{
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(pstFSALAudio!=NULL);
pstMp4Parser->pstFSALAudio = pstFSALAudio;
return MP4_PARSER_OK;
}
MP4_Parser_Status MP4_Audio_Seek_To_Video(STMp4Parser *pstMp4Parser, kal_uint64 uVideoDecodeTime, kal_uint32 *puAudioSampleNo)
{
MP4_Parser_Status ret;
kal_uint64 uAudioDecodeTime;
kal_uint32 uVideoTimeScale;
kal_uint32 uAudioTimeScale;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puAudioSampleNo!=NULL);
if ((ret=MP4_GetMediaTimeScale(pstMp4Parser, &uVideoTimeScale, MP4_TRACK_VIDEO))!=MP4_PARSER_OK)
return ret;
if ((ret=MP4_GetMediaTimeScale(pstMp4Parser, &uAudioTimeScale, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
uAudioDecodeTime = uVideoDecodeTime * uAudioTimeScale / uVideoTimeScale;
if ((ret=MP4_GetSampleNumber(pstMp4Parser, puAudioSampleNo, uAudioDecodeTime, MP4_TRACK_AUDIO ))!=MP4_PARSER_OK)
return ret;
return MP4_PARSER_OK;
}
MP4_Parser_Status MP4_Audio_Seek(STMp4Parser *pstMp4Parser, kal_uint32 uAudioSampleNo)
{
MP4_Parser_Status ret;
kal_uint32 uAudioSampleCount;
kal_uint32 uAudioTimeScale;
kal_uint64 uAudioDecodeTime;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
pstMp4Parser->uAudioReadSampleNo = uAudioSampleNo;
pstMp4Parser->uAudioReadSampleOffset = 0;
pstMp4Parser->uADTSHeaderReadOffset = 0;
if ((ret=MP4_GetMediaTimeScale(pstMp4Parser, &uAudioTimeScale, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
if ((ret=MP4_GetSampleCount(pstMp4Parser, MP4_TRACK_AUDIO, &uAudioSampleCount))!=MP4_PARSER_OK)
return ret;
if ((ret=MP4_GetDecodeTime(pstMp4Parser, uAudioSampleNo, &uAudioDecodeTime, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
pstMp4Parser->uAudioSeekPointTime = uAudioDecodeTime * 1000 / uAudioTimeScale;
if (uAudioSampleNo < uAudioSampleCount) {
if ((ret=MP4_GetSampleOffset(pstMp4Parser, uAudioSampleNo, &(pstMp4Parser->uAudioReadSampleFileOffset), MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
}
return MP4_PARSER_OK;
}
/*
* Invoke MP4_GetSampleOffset_Next for optimization
*/
MP4_Parser_Status MP4_Audio_Seek_Internal(STMp4Parser *pstMp4Parser, kal_uint32 uAudioSampleNo)
{
MP4_Parser_Status ret;
kal_uint32 uAudioSampleCount;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
pstMp4Parser->uAudioReadSampleNo = uAudioSampleNo;
pstMp4Parser->uAudioReadSampleOffset = 0;
pstMp4Parser->uADTSHeaderReadOffset = 0;
if ((ret=MP4_GetSampleCount(pstMp4Parser, MP4_TRACK_AUDIO, &uAudioSampleCount))!=MP4_PARSER_OK)
return ret;
if (uAudioSampleNo<uAudioSampleCount) {
if ((ret=MP4_GetSampleOffset_Next(pstMp4Parser, &(pstMp4Parser->uAudioReadSampleFileOffset), MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
}
return MP4_PARSER_OK;
}
/* Update some variables after reading some data */
#define MP4_AUDIO_READ_UPDATE(uLen) \
*uReadSize += (uLen); \
pBuf += (uLen); \
uSizeLeft -= (uLen)
/**
* Read audio samples as a contiguous stream.
* Note that fsal_direct_seek must be done immediately before fsal_direct_read,
* to avoid the situation
* that when accessing sample tables, file position has been changed.
*/
MP4_Parser_Status MP4_Audio_Read(STMp4Parser *pstMp4Parser, kal_uint8* pBuf, kal_uint32 uSize, kal_uint32 *uReadSize)
{
MP4_Parser_Status ret;
kal_uint32 uSizeLeft = uSize;
kal_uint32 uCurSampleSize;
kal_uint32 uCurSampleOffset;
kal_uint32 uSampleCount;
kal_uint32 uFileOffset;
kal_uint8 *pbADTSFrameHeader;
kal_uint8 *pbADIFFrameHeader;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(pstMp4Parser->pstFSALAudio!=NULL);
MP4_PARSER_CHECK_ARG(pBuf!=NULL);
MP4_PARSER_CHECK_ARG(uReadSize!=NULL);
/* Initialize some local variables */
*uReadSize = 0;
pbADTSFrameHeader = pstMp4Parser->pbADTSFrameHeader;
pbADIFFrameHeader = pstMp4Parser->pbADIFFrameHeader;
/* consider when there is no audio track or audio sample number is 0 */
if ((ret=MP4_GetSampleCount(pstMp4Parser, MP4_TRACK_AUDIO, &uSampleCount))!=MP4_PARSER_OK)
return ret;
if (pstMp4Parser->uAudioReadSampleNo >= uSampleCount)
return MP4_PARSER_READ_EOF;
if ((ret=MP4_GetSampleSize(pstMp4Parser, pstMp4Parser->uAudioReadSampleNo, &uCurSampleSize, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
uCurSampleOffset = pstMp4Parser->uAudioReadSampleOffset;
uFileOffset = pstMp4Parser->uAudioReadSampleFileOffset;
if (KAL_TRUE == pstMp4Parser->bAddADIFFrameHeader) {
/* handle the case if the ADTS frame header has not been read out completely */
if (pstMp4Parser->uADIFHeaderReadOffset < pstMp4Parser->uADIFFrameHeaderLen) {
kal_uint32 uADIFFrameSizeLeft = pstMp4Parser->uADIFFrameHeaderLen - pstMp4Parser->uADIFHeaderReadOffset;
if (uADIFFrameSizeLeft >= uSizeLeft) {
kal_mem_cpy(pBuf, pbADIFFrameHeader + pstMp4Parser->uADIFHeaderReadOffset, uSizeLeft);
pstMp4Parser->uADIFHeaderReadOffset += uSizeLeft;
MP4_AUDIO_READ_UPDATE(uSizeLeft);
return MP4_PARSER_OK;
} else {
kal_mem_cpy(pBuf, pbADIFFrameHeader + pstMp4Parser->uADIFHeaderReadOffset, uADIFFrameSizeLeft);
pstMp4Parser->uADIFHeaderReadOffset = pstMp4Parser->uADIFFrameHeaderLen;
MP4_AUDIO_READ_UPDATE(uADIFFrameSizeLeft);
}
}
}
if (KAL_TRUE == pstMp4Parser->bAddADTSFrameHeader) {
/* handle the case if the ADTS frame header has been read partially */
if (pstMp4Parser->uADTSHeaderReadOffset < ADTS_HEADER_SIZE) {
kal_uint32 uADTSFrameSizeLeft = ADTS_HEADER_SIZE - pstMp4Parser->uADTSHeaderReadOffset;
prepareADTSFrameHeader(pstMp4Parser, pbADTSFrameHeader, uCurSampleSize);
if (uADTSFrameSizeLeft >= uSizeLeft) {
kal_mem_cpy(pBuf, pbADTSFrameHeader + pstMp4Parser->uADTSHeaderReadOffset, uSizeLeft);
pstMp4Parser->uADTSHeaderReadOffset += uSizeLeft;
MP4_AUDIO_READ_UPDATE(uSizeLeft);
return MP4_PARSER_OK;
} else {
kal_mem_cpy(pBuf, pbADTSFrameHeader + pstMp4Parser->uADTSHeaderReadOffset, uADTSFrameSizeLeft);
pstMp4Parser->uADTSHeaderReadOffset = ADTS_HEADER_SIZE;
MP4_AUDIO_READ_UPDATE(uADTSFrameSizeLeft);
}
}
}
/* handle the case if the current sample has been read partially */
if (pstMp4Parser->uAudioReadSampleOffset!=0) {
kal_uint32 uCurSampleSizeLeft = uCurSampleSize - uCurSampleOffset;
uFileOffset += pstMp4Parser->uAudioReadSampleOffset;
if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstMp4Parser->pstFSALAudio, uFileOffset))!=FSAL_OK)
return MP4_PARSER_FILE_SEEK_ERROR;
if (uCurSampleSizeLeft > uSizeLeft) {
if ((pstMp4Parser->eFSALErr=FSAL_Read(pstMp4Parser->pstFSALAudio, pBuf, uSizeLeft))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
pstMp4Parser->uAudioReadSampleOffset += uSizeLeft;
MP4_AUDIO_READ_UPDATE(uSizeLeft);
return MP4_PARSER_OK;
} else {
if ((pstMp4Parser->eFSALErr=FSAL_Read(pstMp4Parser->pstFSALAudio, pBuf, uCurSampleSizeLeft))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
MP4_AUDIO_READ_UPDATE(uCurSampleSizeLeft);
/* read out the current sample, seek to next sample */
if ((ret=MP4_Audio_Seek_Internal(pstMp4Parser, pstMp4Parser->uAudioReadSampleNo+1))!=MP4_PARSER_OK)
return ret;
}
}
while(uSizeLeft > 0 && pstMp4Parser->uAudioReadSampleNo < uSampleCount) {
if ((ret=MP4_GetSampleSize(pstMp4Parser, pstMp4Parser->uAudioReadSampleNo, &uCurSampleSize, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
uFileOffset = pstMp4Parser->uAudioReadSampleFileOffset;
if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstMp4Parser->pstFSALAudio, uFileOffset))!=FSAL_OK)
return MP4_PARSER_FILE_SEEK_ERROR;
if (KAL_TRUE == pstMp4Parser->bAddADTSFrameHeader) {
if (pstMp4Parser->uADTSHeaderReadOffset < ADTS_HEADER_SIZE) {
kal_uint32 uADTSFrameSizeLeft = ADTS_HEADER_SIZE - pstMp4Parser->uADTSHeaderReadOffset;
prepareADTSFrameHeader(pstMp4Parser, pbADTSFrameHeader, uCurSampleSize);
if (uADTSFrameSizeLeft >= uSizeLeft) {
kal_mem_cpy(pBuf, pbADTSFrameHeader + pstMp4Parser->uADTSHeaderReadOffset, uSizeLeft);
pstMp4Parser->uADTSHeaderReadOffset += uSizeLeft;
MP4_AUDIO_READ_UPDATE(uSizeLeft);
break;
} else {
kal_mem_cpy(pBuf, pbADTSFrameHeader + pstMp4Parser->uADTSHeaderReadOffset, uADTSFrameSizeLeft);
pstMp4Parser->uADTSHeaderReadOffset = ADTS_HEADER_SIZE;
MP4_AUDIO_READ_UPDATE(uADTSFrameSizeLeft);
}
}
}
if (uCurSampleSize > uSizeLeft) {
if((pstMp4Parser->eFSALErr=FSAL_Read(pstMp4Parser->pstFSALAudio, pBuf, uSizeLeft))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
pstMp4Parser->uAudioReadSampleOffset = uSizeLeft;
MP4_AUDIO_READ_UPDATE(uSizeLeft);
break;
} else {
if ((pstMp4Parser->eFSALErr=FSAL_Read(pstMp4Parser->pstFSALAudio, pBuf, uCurSampleSize))!=FSAL_OK)
return MP4_PARSER_FILE_READ_ERROR;
MP4_AUDIO_READ_UPDATE(uCurSampleSize);
if ((ret=MP4_Audio_Seek_Internal(pstMp4Parser, pstMp4Parser->uAudioReadSampleNo+1))!=MP4_PARSER_OK)
return ret;
}
}
if (pstMp4Parser->uAudioReadSampleNo >= uSampleCount)
return MP4_PARSER_READ_EOF;
else
return MP4_PARSER_OK;
}
MP4_Parser_Status MP4_Audio_TimeToSampleNo(STMp4Parser *pstMp4Parser, kal_uint64 uMiliSecond, kal_uint32 *puAudioSampleNo )
{
MP4_Parser_Status ret;
kal_uint64 uAudioDecodeTime;
kal_uint32 uAudioTimeScale;
MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
MP4_PARSER_CHECK_ARG(puAudioSampleNo!=NULL);
if ((ret=MP4_GetMediaTimeScale(pstMp4Parser, &uAudioTimeScale, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
uAudioDecodeTime = uMiliSecond * uAudioTimeScale / 1000;
if ((ret=MP4_GetSampleNumber(pstMp4Parser, puAudioSampleNo, uAudioDecodeTime, MP4_TRACK_AUDIO))!=MP4_PARSER_OK)
return ret;
return MP4_PARSER_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -