int MP4DemuxParseAtom(MP4DEMUXCONTEXT *pMP4DemuxContext)
{
unsigned int uiSize = 0;
unsigned int uiBytesLeft = 0;
char pcTag[5] = {0};
unsigned char ucVersion;
unsigned int uiFlags;
unsigned int uiEntryCount;
unsigned int i;
int iRet = MP4DEMUX_EC_OK;
pMP4DemuxContext->iVideoStreamCodec = TP_AVCODEC_UNDET;
pMP4DemuxContext->iVideoStreamCodec2 = TP_AVCODEC_UNDET;
// 清空所有 track 的 codec 缓存
for (int i = 0; i < MP4DEMUX_MAX_TRACK; i++)
{
pMP4DemuxContext->tempCodecType[i] = TP_AVCODEC_UNDET;
}
do
{
if (pMP4DemuxContext->iDataSource == MP4DEMUX_DATASOURCE_FROM_FILE && pMP4DemuxContext->uiInfoBufferOffset + 8 >= pMP4DemuxContext->uiInfoBufferSize)
{
STM_DEBUG("Buffer size (%d) is smaller than 8, need copy",
pMP4DemuxContext->uiInfoBufferSize - pMP4DemuxContext->uiInfoBufferOffset);
pMP4DemuxContext->uiInfoBufferOffsetInFile += pMP4DemuxContext->uiInfoBufferOffset;
return MP4DEMUX_EC_NEED_COPY;
}
CHECK_ERROR(MP4DemuxGetBE32(&uiSize, pMP4DemuxContext)); // Get box size
iRet = MP4DemuxCheckSize(uiSize, pMP4DemuxContext);
if (iRet != MP4DEMUX_EC_OK)
{
if (iRet == MP4DEMUX_EC_NEED_COPY)
{
STM_DEBUG("Buffer is too small to be parsed (%d, %u), need copy",
pMP4DemuxContext->uiInfoBufferSize - pMP4DemuxContext->uiInfoBufferOffset, uiSize);
}
else
{
STM_ERROR("MP4DEMUX_STATUS_MOOV_PARSING failure: box size (%u) is error", uiSize);
}
return iRet;
}
CHECK_ERROR(MP4DemuxGetTag(pcTag, pMP4DemuxContext)); // Get box tag
STM_DEBUG("Box size: %u, name: %s", uiSize, pcTag);
#ifndef KjbSDK_SUPPORT
if (MP4DemuxIsEqualFCC(pcTag, "moov") ||
#else
if (MP4DemuxIsEqualFCC(pcTag, "tpmb") ||
#endif
MP4DemuxIsEqualFCC(pcTag, "trak") ||
MP4DemuxIsEqualFCC(pcTag, "avc1") ||
MP4DemuxIsEqualFCC(pcTag, "minf") ||
MP4DemuxIsEqualFCC(pcTag, "stbl") ||
MP4DemuxIsEqualFCC(pcTag, "stsd") ||
MP4DemuxIsEqualFCC(pcTag, "mdia") ||
MP4DemuxIsEqualFCC(pcTag, "edts") ||
MP4DemuxIsEqualFCC(pcTag, "mp4a") ||
MP4DemuxIsEqualFCC(pcTag, "hev1"))
{
pMP4DemuxContext->uiMoovReadSize += 8;
if (MP4DemuxIsEqualFCC(pcTag, "trak"))
{
if (pMP4DemuxContext->iCurTrack == MP4DEMUX_MAX_TRACK - 1)
{
STM_INFO("Warning!!Exceeding the max track:%d, sd card may be used by other models", MP4DEMUX_MAX_TRACK);
return MP4DEMUX_EC_OK;
}
pMP4DemuxContext->iCurTrack++;
}
if (MP4DemuxIsEqualFCC(pcTag, "stsd"))
{
CHECK_ERROR(MP4DemuxAdvance(8, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += 8;
}
if (MP4DemuxIsEqualFCC(pcTag, "avc1"))
{
CHECK_ERROR(MP4DemuxAdvance(78, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += 78;
}
if (MP4DemuxIsEqualFCC(pcTag, "hev1"))
{
CHECK_ERROR(MP4DemuxAdvance(78, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += 78;
}
if (MP4DemuxIsEqualFCC(pcTag, "mp4a"))
{
CHECK_ERROR(MP4DemuxAdvance(28, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += 28;
}
}
else if (MP4DemuxIsEqualFCC(pcTag, "mvhd")) // mvhd
{
/* check data valid */
if (uiSize < 108)
{
STM_ERROR("Invalid mvhd");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
ucVersion = uiFlags & 0xff000000;
uiFlags = uiFlags & 0x00ffffff;
if (ucVersion == 0)
{
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiCreationTime), pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiModificationTime), pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiTimeScale), pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiDuration), pMP4DemuxContext));
}
#if 0
else if (ucVersion == 1) // version 1 is not supported for now
{
// see 14496-12 8.2.2.2
CHECK_ERROR(MP4DemuxAdvance(28, pMP4DemuxContext));
}
#endif
CHECK_ERROR(MP4DemuxAdvance(4, pMP4DemuxContext)); // TODO: rate
CHECK_ERROR(MP4DemuxAdvance(2, pMP4DemuxContext)); // TODO: volume
CHECK_ERROR(MP4DemuxAdvance(70, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiNextTrackID), pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "tkhd"))
{
unsigned int uiCreationTime;
unsigned int uiModificationTime;
unsigned int uiDuration;
unsigned int uiTrackId;
/* check data valid */
if (uiSize < 92)
{
STM_ERROR("Invalid tkhd");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
ucVersion = uiFlags & 0xff000000;
uiFlags = uiFlags & 0x00ffffff;
if (ucVersion == 0)
{
CHECK_ERROR(MP4DemuxGetBE32(&uiCreationTime, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiModificationTime, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiTrackId, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxAdvance(4, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiDuration, pMP4DemuxContext));
}
#if 0
else if (ucVersion == 1) // version 1 is not supported for now
{
// see 14496-12 8.3.2.2
CHECK_ERROR(MP4DemuxAdvance(32, pMP4DemuxContext));
}
#endif
CHECK_ERROR(MP4DemuxAdvance(12, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxAdvance(2, pMP4DemuxContext)); // volume
CHECK_ERROR(MP4DemuxAdvance(2, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxAdvance(36, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE16(&(pMP4DemuxContext->pusImageWidth[pMP4DemuxContext->iCurTrack]), pMP4DemuxContext));
CHECK_ERROR(MP4DemuxAdvance(2, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE16(&(pMP4DemuxContext->pusImageHeight[pMP4DemuxContext->iCurTrack]), pMP4DemuxContext));
CHECK_ERROR(MP4DemuxAdvance(2, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "hdlr"))
{
/* check data valid */
if (uiSize < 20)
{
STM_ERROR("Invalid hdlr");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxAdvance(8, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetTag(pcTag, pMP4DemuxContext));
if (MP4DemuxIsEqualFCC(pcTag, "vide")) // soun/text
{
pMP4DemuxContext->usImageWidth = pMP4DemuxContext->pusImageWidth[pMP4DemuxContext->iCurTrack];
pMP4DemuxContext->usImageHeight = pMP4DemuxContext->pusImageHeight[pMP4DemuxContext->iCurTrack];
}
CHECK_ERROR(MP4DemuxAdvance(uiSize - 20, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "avcC"))
{
unsigned char ucConfigurationVersion = 0;
unsigned char ucAVCProfileIndication = 0;
unsigned char ucProfileCompatibility = 0;
unsigned char ucAVCLevelIndication = 0;
unsigned char ucLengthSizeMinusOne = 0;
unsigned char ucNumOfSequenceParameterSets = 0;
unsigned char ucNumOfPictureParameterSets = 0;
unsigned short usSequenceParameterSetLength = 0;
unsigned short usPictureParameterSetLength = 0;
/* check data valid */
if (uiSize < 19)
{
STM_ERROR("Invalid avcC");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
// pMP4DemuxContext->iVideoStreamCodec2 = TP_AVCODEC_H264;
// 标记当前 track 是 H.264
pMP4DemuxContext->tempCodecType[pMP4DemuxContext->iCurTrack] = TP_AVCODEC_H264;
STM_INFO("Track %d marked as H.264", pMP4DemuxContext->iCurTrack);
CHECK_ERROR(MP4DemuxGetByte(&ucConfigurationVersion, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetByte(&ucAVCProfileIndication, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetByte(&ucProfileCompatibility, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetByte(&ucAVCLevelIndication, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetByte(&ucLengthSizeMinusOne, pMP4DemuxContext));
ucLengthSizeMinusOne &= 0x3;
CHECK_ERROR(MP4DemuxGetByte(&ucNumOfSequenceParameterSets, pMP4DemuxContext));
ucNumOfSequenceParameterSets &= 0x1f;
uiBytesLeft -= 6;
for (i = 0; i < ucNumOfSequenceParameterSets; i++)
{
/* check data valid */
if (uiBytesLeft < 2)
{
STM_ERROR("Invalid avcC");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxGetBE16(&usSequenceParameterSetLength, pMP4DemuxContext));
uiBytesLeft -= 2;
/* check data valid */
if (usSequenceParameterSetLength > uiBytesLeft - 1)
{
STM_ERROR("Invalid avcC");
return MP4DEMUX_EC_FAILURE;
}
#if 0
pMP4DemuxContext->iAVCSPSLength = usSequenceParameterSetLength;
CHECK_ERROR(MP4DemuxGetBytes(pMP4DemuxContext->pucAVCSPS, usSequenceParameterSetLength, pMP4DemuxContext));
#endif
CHECK_ERROR(MP4DemuxAdvance(usSequenceParameterSetLength, pMP4DemuxContext));
uiBytesLeft -= usSequenceParameterSetLength;
}
CHECK_ERROR(MP4DemuxGetByte(&ucNumOfPictureParameterSets, pMP4DemuxContext));
uiBytesLeft -= 1;
for (i = 0; i < ucNumOfPictureParameterSets; i++)
{
/* check data valid */
if (uiBytesLeft < 2)
{
STM_ERROR("Invalid avcC");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxGetBE16(&usPictureParameterSetLength, pMP4DemuxContext));
uiBytesLeft -= 2;
/* check data valid */
if (usPictureParameterSetLength > uiBytesLeft)
{
STM_ERROR("Invalid avcC");
return MP4DEMUX_EC_FAILURE;
}
#if 0
pMP4DemuxContext->piAVCPPSLength[i] = usPictureParameterSetLength;
CHECK_ERROR(MP4DemuxGetBytes(pMP4DemuxContext->pucAVCPPS[i], usPictureParameterSetLength, pMP4DemuxContext));
#endif
CHECK_ERROR(MP4DemuxAdvance(usPictureParameterSetLength, pMP4DemuxContext));
uiBytesLeft -= usPictureParameterSetLength;
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "hvcC"))
{
uiBytesLeft = uiSize - 8;
// pMP4DemuxContext->iVideoStreamCodec = TP_AVCODEC_H265;
// pMP4DemuxContext->iVideoStreamCodec2 = TP_AVCODEC_H265;
// 标记当前 track 是 H.265
pMP4DemuxContext->tempCodecType[pMP4DemuxContext->iCurTrack] = TP_AVCODEC_H265;
STM_INFO("Track %d marked as H.265", pMP4DemuxContext->iCurTrack);
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "stco"))
{
unsigned int uiFirstSampleOffset;
/* check data valid */
if (uiSize < 16)
{
STM_ERROR("Invalid stco");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
uiBytesLeft -= 8;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
pMP4DemuxContext->puiSTCOEntryCount[pMP4DemuxContext->iCurTrack] = uiEntryCount;
pMP4DemuxContext->puiStartPos4STCO[pMP4DemuxContext->iCurTrack] = pMP4DemuxContext->uiInfoBufferOffsetInFile + pMP4DemuxContext->uiInfoBufferOffset;
MP4DemuxResetBufferChunkOffset(pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
// Fill data
MP4DemuxAppendBufferChunkOffset(0, pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
pMP4DemuxContext->puiNextSampleOffset[pMP4DemuxContext->iCurTrack] = uiFirstSampleOffset = pMP4DemuxContext->puiSTCOBuffer[pMP4DemuxContext->iCurTrack][0];
if (pMP4DemuxContext->iVideoTrack == pMP4DemuxContext->iCurTrack)
{
pMP4DemuxContext->uiFirstIDROffset = uiFirstSampleOffset;
}
/* We have got the offset of first sample already.
* In case of making error in MP4DemuxGetChunkIndexBySampleIndex(),
* pre-set puiChunkIndexOfLastSampleInSYSBfSTSC to 1.
*/
pMP4DemuxContext->puiChunkIndexOfLastSampleInSYSBfSTSC[pMP4DemuxContext->iCurTrack] = 1;
}
else
{
// only get the chunk offset of the first video chunk
if (pMP4DemuxContext->iVideoTrack == pMP4DemuxContext->iCurTrack)
{
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiFirstIDROffset), pMP4DemuxContext));
uiBytesLeft -= 4;
pMP4DemuxContext->bFinishParseHeaders |= 2;
}
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "stsz")) // dref, stsd, mp4s, stts, ctts, stsc, stco, stss
{
unsigned int uiSampleSize = 0;
/* check data valid */
if (uiSize < 20)
{
STM_ERROR("Invalid stsz");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiSampleSize, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
uiBytesLeft -= 12;
pMP4DemuxContext->puiSTSZEntryCount[pMP4DemuxContext->iCurTrack] = uiEntryCount;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
// record start pos of STSZ in pucInfoBuffer, this start means where the entry start
pMP4DemuxContext->puiStartPos4STSZ[pMP4DemuxContext->iCurTrack] = pMP4DemuxContext->uiInfoBufferOffsetInFile + pMP4DemuxContext->uiInfoBufferOffset;
MP4DemuxResetBufferSampleSize(pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
// Fill data
MP4DemuxAppendBufferSampleSize(0, pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
if (pMP4DemuxContext->iVideoTrack == pMP4DemuxContext->iCurTrack)
{
pMP4DemuxContext->uiFirstIDRSampleSize = pMP4DemuxContext->puiSTSZBuffer[pMP4DemuxContext->iCurTrack][0];
}
}
else
{
// only get the sample size of the first picture
if (pMP4DemuxContext->iVideoTrack == pMP4DemuxContext->iCurTrack)
{
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->uiFirstIDRSampleSize), pMP4DemuxContext));
uiBytesLeft -= 4;
pMP4DemuxContext->bFinishParseHeaders |= 1;
}
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "stts"))
{
/* check data valid */
if (uiSize < 16)
{
STM_ERROR("Invalid stts");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
uiBytesLeft -= 8;
pMP4DemuxContext->puiSTTSEntryCount[pMP4DemuxContext->iCurTrack] = uiEntryCount;
pMP4DemuxContext->puiStartPos4STTS[pMP4DemuxContext->iCurTrack] = pMP4DemuxContext->uiInfoBufferOffsetInFile + pMP4DemuxContext->uiInfoBufferOffset;
MP4DemuxResetBufferSampleDuration(pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
// Fill data
if (MP4DemuxAppendBufferSampleDuration(pMP4DemuxContext->iCurTrack, pMP4DemuxContext) != MP4DEMUX_EC_OK)
{
return MP4DEMUX_EC_FAILURE;
}
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "stss"))
{
/* check data valid */
if (uiSize < 16)
{
STM_ERROR("Invalid stss");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
uiBytesLeft -= 8;
pMP4DemuxContext->uiSTSSEntryCount[pMP4DemuxContext->iCurTrack] = uiEntryCount;
pMP4DemuxContext->uiStartPos4STSS[pMP4DemuxContext->iCurTrack] = pMP4DemuxContext->uiInfoBufferOffsetInFile + pMP4DemuxContext->uiInfoBufferOffset;
if (MP4DemuxResetBufferSyncSampleIndex(pMP4DemuxContext, pMP4DemuxContext->iCurTrack) == MP4DEMUX_EC_FAILURE)
{
return MP4DEMUX_EC_FAILURE;
}
// Fill data
MP4DemuxAppendBufferSyncSampleIndex(pMP4DemuxContext, pMP4DemuxContext->iCurTrack);
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "stsc"))
{
/* check data valid */
if (uiSize < 16)
{
STM_ERROR("Invalid stsc");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
uiBytesLeft -= 8;
pMP4DemuxContext->puiSTSCEntryCount[pMP4DemuxContext->iCurTrack] = uiEntryCount;
pMP4DemuxContext->puiStartPos4STSC[pMP4DemuxContext->iCurTrack] = pMP4DemuxContext->uiInfoBufferOffsetInFile + pMP4DemuxContext->uiInfoBufferOffset;
MP4DemuxResetBufferSampleChunk(pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
// Fill data
if (MP4DemuxAppendBufferSampleChunk(pMP4DemuxContext->iCurTrack, pMP4DemuxContext) != MP4DEMUX_EC_OK)
{
return MP4DEMUX_EC_FAILURE;
}
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "ctts")) // ctts
{
/* check data valid */
if (uiSize < 16)
{
STM_ERROR("Invalid ctts");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
uiBytesLeft -= 8;
pMP4DemuxContext->puiCTTSEntryCount[pMP4DemuxContext->iCurTrack] = uiEntryCount;
pMP4DemuxContext->puiStartPos4CTTS[pMP4DemuxContext->iCurTrack] = pMP4DemuxContext->uiInfoBufferOffsetInFile + pMP4DemuxContext->uiInfoBufferOffset;
MP4DemuxResetBufferCTTS(pMP4DemuxContext->iCurTrack, pMP4DemuxContext);
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "mdhd")) // mdhd
{
unsigned int uiTime;
/* check data valid */
if (uiSize < 32)
{
STM_ERROR("Invalid mdhd");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiTime, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiTime, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->puiTimeScale[pMP4DemuxContext->iCurTrack]),
pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&(pMP4DemuxContext->puiDuration[pMP4DemuxContext->iCurTrack]),
pMP4DemuxContext));
uiBytesLeft -= 20;
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "vmhd"))
{
/* check data valid */
if (uiSize < 20)
{
STM_ERROR("Invalid vmhd");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
if (pMP4DemuxContext->iVideoTrack == -1)
{
pMP4DemuxContext->iVideoTrack = pMP4DemuxContext->iCurTrack;
}
#ifdef DUAL_CAM
else
{
pMP4DemuxContext->iVideo2Track = pMP4DemuxContext->iCurTrack;
}
STM_INFO("video track:%d,%d", pMP4DemuxContext->iVideoTrack, pMP4DemuxContext->iVideo2Track);
#endif
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "smhd"))
{
/* check data valid */
if (uiSize < 16)
{
STM_ERROR("Invalid smhd");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
pMP4DemuxContext->iAudioTrack = pMP4DemuxContext->iCurTrack;
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "elst"))
{
/* check data valid */
if (uiSize < 28)
{
STM_ERROR("Invalid elst");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiEntryCount, pMP4DemuxContext));
/* check data valid */
if (uiEntryCount > 1 && uiSize < 40)
{
STM_ERROR("Invalid elst");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft -= 8;
for (i = 1; i < uiEntryCount; i++)
{
unsigned int uiTrackDuration;
int iMediaTime;
unsigned int uiMediaRate;
CHECK_ERROR(MP4DemuxGetBE32(&uiTrackDuration, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetSignedBE32(&iMediaTime, pMP4DemuxContext));
CHECK_ERROR(MP4DemuxGetBE32(&uiMediaRate, pMP4DemuxContext));
uiBytesLeft -= 12;
if (iMediaTime == -1)
{
// modify
pMP4DemuxContext->pllStartTime[pMP4DemuxContext->iCurTrack] += uiTrackDuration;
}
}
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "esds"))
{
/* check data valid */
if (uiSize < 51)
{
STM_ERROR("Invalid esds");
return MP4DEMUX_EC_FAILURE;
}
uiBytesLeft = uiSize - 8;
CHECK_ERROR(MP4DemuxGetBE32(&uiFlags, pMP4DemuxContext));
uiBytesLeft -= 4;
if (pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES)
{
iRet = MP4DemuxParseESDSTag(pMP4DemuxContext);
if (iRet < 0)
{
STM_ERROR("Invalid esds");
return iRet;
}
uiBytesLeft -= iRet;
}
CHECK_ERROR(MP4DemuxAdvance(uiBytesLeft, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "ulaw"))
{
pMP4DemuxContext->iAudioStreamCodec = TP_AVCODEC_PCM_MULAW;
/* check data valid */
if (uiSize < 8)
{
STM_ERROR("Invalid ulaw");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxAdvance(uiSize - 8, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
else if (MP4DemuxIsEqualFCC(pcTag, "alaw"))
{
pMP4DemuxContext->iAudioStreamCodec = TP_AVCODEC_PCM_ALAW;
/* check data valid */
if (uiSize < 8)
{
STM_ERROR("Invalid alaw");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxAdvance(uiSize - 8, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
/* if (MP4DemuxIsEqualFCC(pcTag, "iods" or esds, mp4a, mp4v, tref, nmhd, dinf, url, samr, hdlr,
* uuid, ctts, edts, udta, meta, mdat, ftyp, free, mdia)
*/
else
{
/* check data valid */
if (uiSize < 8)
{
STM_ERROR("Invalid other box");
return MP4DEMUX_EC_FAILURE;
}
CHECK_ERROR(MP4DemuxAdvance(uiSize - 8, pMP4DemuxContext));
pMP4DemuxContext->uiMoovReadSize += uiSize;
}
if (pMP4DemuxContext->uiMoovReadSize == pMP4DemuxContext->uiMoovSize)
{
return MP4DEMUX_EC_OK;
}
else if (pMP4DemuxContext->uiMoovReadSize > pMP4DemuxContext->uiMoovSize)
{
STM_ERROR("There is invalid box");
return MP4DEMUX_EC_FAILURE;
}
/* Only parse information of the first frame */
if ((pMP4DemuxContext->iOptions & MP4DEMUX_OPTION_PARSE_ALL_SAMPLES) == 0 && pMP4DemuxContext->bFinishParseHeaders == 3)
{
return (MP4DEMUX_EC_OK);
}
if (pMP4DemuxContext->iVideoTrack != -1)
{
pMP4DemuxContext->iVideoStreamCodec =
pMP4DemuxContext->tempCodecType[pMP4DemuxContext->iVideoTrack];
}
if (pMP4DemuxContext->iVideo2Track != -1)
{
pMP4DemuxContext->iVideoStreamCodec2 =
pMP4DemuxContext->tempCodecType[pMP4DemuxContext->iVideo2Track];
}
STM_INFO("iVideoTrack=%d, iVideoStreamCodec=%d, iVideo2Track=%d, iVideoStreamCodec2=%d",
pMP4DemuxContext->iVideoTrack,
pMP4DemuxContext->iVideoStreamCodec,
pMP4DemuxContext->iVideo2Track,
pMP4DemuxContext->iVideoStreamCodec2);
} while (1);
}这里好像没有解析完成,log看("iVideoTrack=%d, iVideoStreamCodec=%d, iVideo2Track=%d, iVideoStreamCodec2=%d",这里出现很多-1-1