📄 umc_mp4_spl.cpp
字号:
nBaseOffset += 8;
}
}
if (pTraf->tfhd.flags & DURATION_IS_EMPTY) {
// duration is empty, no track run
// TO DO: add one fragment containing only one sample, sample size and
// position are both zero. sample time stamp is set to default sample duration.
}
Ipp64u nLastBaseOffset = nBaseOffset;
for (Ipp32u k = 0; k < pTraf->entry_count; k++) {
// zero or more Trak Run Boxes
T_trun* pTrun = pTraf->trun[k];
if ((pTrun == NULL) || (pTrun->sample_count == 0))
continue;
/*** where to connect current track fragment ***/
Ipp32u nTrack;
umcRes = MapTrafIDToTrackID(pTraf->tfhd.track_ID, nTrack);
if (umcRes != UMC_OK)
continue;
if (pTrun->flags & DATA_OFFSET_PRESENT) {
// data-offset-present
if (nBaseOffset + pTrun->data_offset > nLastBaseOffset)
nLastBaseOffset = nBaseOffset + pTrun->data_offset;
}
umcRes = AddMoofRunToIndex(nTrack, pTrex, pTraf, pTrun, nLastBaseOffset);
UMC_CHECK_STATUS(umcRes)
}
nBaseOffset = nLastBaseOffset;
}
}
return UMC_OK;
}
AudioStreamType AudioObjectTypeID(Ipp32u value)
{
switch(value)
{
case 0x6b:
return UMC::MPEG1_AUDIO;
case 0x69:
return UMC::MPEG2_AUDIO;
case 0x66:
case 0x67:
case 0x68:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x06:
return UMC::AAC_MPEG4_STREAM;
default:
return UMC::UNDEF_AUDIO;
}
}
VideoStreamType GetVideoStreamType(Ipp8u value)
{
switch (value) {
case 0x14:
case 0x20:
return MPEG4_VIDEO;
case 0x60: // 13818-2
case 0x61: // 13818-2
case 0x62: // 13818-2
case 0x63: // 13818-2
case 0x64: // 13818-2
case 0x65: // 13818-2
return MPEG2_VIDEO;
case 0x6A:
return MPEG1_VIDEO;
case 0x6C: // 10918-1
return MJPEG_VIDEO;
case 0xf1:
return H264_VIDEO;
case 0xf2:
return H263_VIDEO;
case 0xf3:
return H261_VIDEO;
default:
return UNDEF_VIDEO;
}
}
AudioStreamType GetAudioStreamType(Ipp8u value)
{
switch (value) {
case 0x40: // 14496-3
case 0x66: // 13818-7
case 0x67: // 13818-7
case 0x68: // 13818-7
return AAC_MPEG4_STREAM;
case 0x69: // 13818-3
return MPEG2_AUDIO;
case 0x6B: // 11172-3
return MPEG1_AUDIO;
default:
return UNDEF_AUDIO;
}
}
Ipp32u GetChannelMask(Ipp32s channels)
{
switch(channels) {
case 1:
return CHANNEL_FRONT_CENTER;
case 2:
return CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT;
case 3:
return CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER;
case 4:
return CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
CHANNEL_TOP_CENTER;
case 5:
return CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT;
case 6:
return CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | CHANNEL_LOW_FREQUENCY;
case 7:
return CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | CHANNEL_LOW_FREQUENCY |
CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER;
default:
return 0;
}
}
Status MP4Splitter::FillAudioInfo(T_trak_data *pTrak, Ipp32u nTrack)
{
AudioStreamInfo *pAudioInfo = (AudioStreamInfo *)(m_pInfo->m_ppTrackInfo[nTrack]->m_pStreamInfo);
T_stsd_table_data *table = pTrak->mdia.minf.stbl.stsd.table;
Ipp8u *ptr = NULL;
Ipp32s len = 0;
/*** AMR audio ***/
if (table->damr.decoderConfigLen) {
len = table->damr.decoderConfigLen;
ptr = table->damr.decoderConfig;
} else
/*** AAC audio ***/
if (table->esds.decoderConfigLen) {
len = table->esds.decoderConfigLen;
ptr = table->esds.decoderConfig;
}
if (len) {
MediaData *pDecSpecInfo = new MediaData(len);
UMC_CHECK_PTR(pDecSpecInfo)
memcpy(pDecSpecInfo->GetDataPointer(), ptr, len);
pDecSpecInfo->SetDataSize(len);
pDecSpecInfo->SetTime(0, 0);
m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo = pDecSpecInfo;
}
if (table->damr.decoderConfigLen == 0) {
pAudioInfo->bitPerSample = 16;
pAudioInfo->bitrate = table->esds.avgBitrate;
pAudioInfo->channels = table->channels;
pAudioInfo->sample_frequency = table->sample_rate;
pAudioInfo->channel_mask = GetChannelMask(table->channels);
#if defined(_WIN32_WCE) /* conversion from unsigned __int64 to double not implemented */
Ipp64s s64_dur = (Ipp64s)(pTrak->mdia.mdhd.duration / 2);
pAudioInfo->duration = (Ipp64f)s64_dur / pTrak->mdia.mdhd.time_scale;
pAudioInfo->duration *= 2;
#else
pAudioInfo->duration = (Ipp64f)pTrak->mdia.mdhd.duration / pTrak->mdia.mdhd.time_scale;
#endif
pAudioInfo->is_protected = (table->is_protected) ? true : false;
pAudioInfo->stream_type = GetAudioStreamType(table->esds.objectTypeID);
pAudioInfo->stream_subtype = UNDEF_AUDIO_SUBTYPE;
switch (pAudioInfo->stream_type) {
case AAC_MPEG4_STREAM:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_AAC;
/*** update audio_info from DecSpecInfo ***/
if (m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo) {
sAudio_specific_config audio_config_data;
sBitsreamBuffer bs;
// T_mdia_data m_Mdia = m_headerMPEG4.moov.trak[nTrack]->mdia;
INIT_BITSTREAM(&bs, m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo->GetDataPointer())
bs.nDataLen = m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo->GetDataSize();
if (!dec_audio_specific_config(&audio_config_data,&bs)) {
//dec_audio_specific_config returns 0, if everything is OK.
pAudioInfo->stream_type = AudioObjectTypeID(audio_config_data.audioObjectType);
pAudioInfo->sample_frequency = get_sampling_frequency(&audio_config_data, 0);
if (1 == audio_config_data.sbrPresentFlag) {
pAudioInfo->sample_frequency = get_sampling_frequency(&audio_config_data, 1);
}
pAudioInfo->channels = get_channels_number(&audio_config_data);
}
}
break;
case MPEG2_AUDIO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEGA;
break;
case MPEG1_AUDIO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEGA;
break;
default:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_UNKNOWN;
}
} else { /*** AMR audio ***/
pAudioInfo->sample_frequency = 8000;
pAudioInfo->channels = 1;
pAudioInfo->stream_type = AMR_NB_AUDIO;
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_AMR;
}
pAudioInfo->streamPID = pTrak->tkhd.track_id;
return UMC_OK;
}
Status MP4Splitter::FillVideoInfo(T_trak_data *pTrak, Ipp32u nTrack)
{
VideoStreamInfo *pVideoInfo = (VideoStreamInfo *)(m_pInfo->m_ppTrackInfo[nTrack]->m_pStreamInfo);
T_stsd_table_data *table = pTrak->mdia.minf.stbl.stsd.table;
Ipp8u *ptr = NULL;
Ipp32s len = 0;
Status umcRes = UMC_OK;
pVideoInfo->clip_info.width = table->width;
pVideoInfo->clip_info.height = table->height;
pVideoInfo->aspect_ratio_width = 1;
pVideoInfo->aspect_ratio_height = 1;
pVideoInfo->color_format = YV12;
/*** update clip_info and interlace_type ***/
if (table->esds.decoderConfigLen) {
len = table->esds.decoderConfigLen;
ptr = table->esds.decoderConfig;
//get bitrate
pVideoInfo->bitrate = table->esds.avgBitrate;
//get info about stream from ESDS info
umcRes = ParseESDSHeader(pTrak, nTrack);
} else if (table->avcC.decoderConfigLen) {
len = table->avcC.decoderConfigLen;
ptr = table->avcC.decoderConfig;
//get info about stream from avcC info
umcRes = ParseAVCCHeader(pTrak, nTrack);
}
UMC_CHECK_STATUS(umcRes)
if (len) {
MediaData *pDecSpecInfo = new MediaData(len);
UMC_CHECK_PTR(pDecSpecInfo)
memcpy(pDecSpecInfo->GetDataPointer(), ptr, len);
pDecSpecInfo->SetDataSize(len);
pDecSpecInfo->SetTime(0, 0);
m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo = pDecSpecInfo;
}
pVideoInfo->streamPID = pTrak->tkhd.track_id;
//get duration
#if defined(_WIN32_WCE) /* conversion from unsigned __int64 to double not implemented */
Ipp64s s64_dur = (Ipp64s)(pTrak->mdia.mdhd.duration / 2);
pVideoInfo->duration = (Ipp64f)s64_dur / pTrak->mdia.mdhd.time_scale;
pVideoInfo->duration *= 2;
#else
pVideoInfo->duration = (Ipp64f)pTrak->mdia.mdhd.duration / pTrak->mdia.mdhd.time_scale;
#endif
//get framerate
if (pVideoInfo->duration)
pVideoInfo->framerate = (Ipp64f)pTrak->mdia.minf.stbl.stsz.total_entries / pVideoInfo->duration;
/*
if (pVideoInfo->duration > 0 && !m_headerMPEG4.moov.mvex.total_tracks) {
pInfo->m_video_info.framerate = (m_Mdia.minf.stbl.stsz.total_entries) /
pInfo->m_video_info.duration;
} else {
if (m_headerMPEG4.moov.mvex.total_tracks && m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration) {
pInfo->m_video_info.framerate = m_Mdia.mdhd.time_scale/
m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration;
} else {
if (m_headerMPEG4.moov.mvex.trex[uiPin] &&
m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration) {
pInfo->m_video_info.framerate = m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration;
}
//if duration was changed, after parsing of the all stream fragments
else if (m_pFirstSegmentDuration && m_pFirstSegmentDuration[uiPin] > 0) {
pInfo->m_video_info.framerate = (Ipp64f)(m_Mdia.minf.stbl.stsz.total_entries) /
m_pFirstSegmentDuration[uiPin];
pInfo->m_video_info.framerate *= m_Mdia.mdhd.time_scale;
} else {
pInfo->m_video_info.framerate = 0;
}
}
}
*/
//get stream type
pVideoInfo->stream_type = GetVideoStreamType(table->esds.objectTypeID);
pVideoInfo->stream_subtype = UNDEF_VIDEO_SUBTYPE;
if (pVideoInfo->stream_type == MPEG4_VIDEO) {
pVideoInfo->stream_subtype = MPEG4_VIDEO_QTIME;
} else if (pVideoInfo->stream_type == H264_VIDEO) {
pVideoInfo->stream_subtype = AVC1_VIDEO;
}
switch (pVideoInfo->stream_type) {
case MPEG4_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEG4V;
break;
case MPEG2_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEG2V;
break;
case MPEG1_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEG1V;
break;
case MJPEG_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MJPEG;
break;
case H264_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_H264;
break;
case H263_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_H263;
break;
case H261_VIDEO:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_H261;
break;
default:
m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_UNKNOWN;
}
return UMC_OK;
}
Status MP4Splitter::Init(SplitterParams& init)
{
Ipp32u iES, nAudio = 0, nVideo = 0;
IndexEntry entry;
Status umcRes;
int i_a = 0, i_v = 0;
if (init.m_pDataReader == NULL)
return UMC_ERR_NOT_ENOUGH_DATA;
m_bFlagStop = true;
/* init LockableDataReader */
umcRes = SplitterBase::Init(init);
UMC_CHECK_STATUS(umcRes)
m_pInfo = new SplitterInfo;
UMC_CHECK_PTR(m_pInfo)
m_pInfo->m_splitter_flags = init.m_lFlags;
m_pInfo->m_SystemType = MP4_ATOM_STREAM;
memset(&m_headerMPEG4, 0, sizeof(info_atoms));
/* read moov atom */
umcRes = ParseMP4Header();
UMC_CHECK_STATUS(umcRes)
m_pInfo->m_nOfTracks = m_headerMPEG4.moov.total_tracks;
#if defined(_WIN32_WCE) /* conversion from unsigned __int64 to double not implemented */
Ipp64s s64_dur = (Ipp64s)(m_headerMPEG4.moov.mvhd.duration / 2);
m_pInfo->m_dDuration = (Ipp64f)s64_dur / m_headerMPEG4.moov.mvhd.time_scale;
m_pInfo->m_dDuration *= 2;
#else
m_pInfo->m_dDuration = (Ipp64f)m_headerMPEG4.moov.mvhd.duration / m_headerMPEG4.moov.mvhd.time_scale;
#endif
m_pTrackIndex = new TrackIndex[m_pInfo->m_nOfTracks];
if (NULL == m_pTrackIndex)
return UMC_ERR_ALLOC;
UMC_ALLOC_ZERO_ARR(m_pInfo->m_ppTrackInfo, TrackInfo*, m_pInfo->m_nOfTracks)
UMC_ALLOC_ZERO_ARR(m_ppMediaBuffer, MediaBuffer*, m_pInfo->m_nOfTracks)
UMC_ALLOC_ZERO_ARR(m_ppLockedFrame, MediaData*, m_pInfo->m_nOfTracks)
UMC_NEW_ARR(m_pReadESThread, vm_thread, m_pInfo->m_nOfTracks)
UMC_ALLOC_ZERO_ARR(m_pLastPTS, Ipp64f, m_pInfo->m_nOfTracks)
for (iES = 0; iES < m_pInfo->m_nOfTracks; iES++) {
T_trak_data *pTrak = m_headerMPEG4.moov.trak[iES];
MediaBufferParams mParams;
int nBufferSize = 0;
umcRes = AddMoovToIndex(iES);
UMC_CHECK_STATUS(umcRes)
m_pTrackIndex[iES].First(entry);
m_pInfo->m_ppTrackInfo[iES] = new TrackInfo;
m_pInfo->m_ppTrackInfo[iES]->m_PID = pTrak->tkhd.track_id;
vm_thread_set_invalid(&m_pReadESThread[iES]);
if (pTrak->mdia.minf.is_audio) {
pAudioTrTbl[i_a++] = (Ipp8u)iES;
nAudio++;
m_pInfo->m_ppTrackInfo[iES]->m_pStreamInfo = new AudioStreamInfo;
umcRes = FillAudioInfo(pTrak, iES);
UMC_CHECK_STATUS(umcRes)
if ((m_pInfo->m_dRate == 1) && (m_pInfo->m_splitter_flags & AUDIO_SPLITTER)) {
m_pInfo->m_ppTrackInfo[iES]->m_isSelected = 1;
}
} else if (pTrak->mdia.minf.is_video) {
pVideoTrTbl[i_v++] = (Ipp8u)iES;
nVideo++;
m_pInfo->m_ppTrackInfo[iES]->m_pStreamInfo = new VideoStreamInfo;
umcRes = FillVideoInfo(pTrak, iES);
UMC_CHECK_STATUS(umcRes)
if (m_pInfo->m_splitter_flags & VIDEO_SPLITTER) {
m_pInfo->m_ppTrackInfo[iES]->m_isSelected = 1;
}
} else {
continue; // skip unsupported stream
}
// m_pInfo->m_ppTrackInfo[iES]->m_isSelected = 1;
UMC_NEW(m_ppMediaBuffer[iES], SampleBuffer);
UMC_NEW(m_ppLockedFrame[iES], MediaData);
mParams.m_numberOfFrames = NUMBEROFFRAMES;
nBufferSize = pTrak->mdia.minf.stbl.stsz.max_sample_size;
if (pTrak->mdia.minf.is_audio) {
if (nBufferSize < MINAUDIOBUFFERSIZE)
nBufferSize = MINAUDIOBUFFERSIZE;
} else if (pTrak->mdia.minf.is_video) {
if (nBufferSize < MINVIDEOBUFFERSIZE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -