📄 umc_mp4_mux_atoms.cpp
字号:
InitStss(nTrack);
TM_stbl_data& stbl = m_headerMPEG4.trak[nTrack]->mdia.minf.stbl;
for (i = 0; i < m_sTrack[nTrack].m_nSamplesCount; i++)
{
stbl.stsz.table[i].size = m_sTrack[nTrack].m_pSamples[i].m_nSize;
stbl.stco.table[i].offset = (Ipp32u)m_sTrack[nTrack].m_pSamples[i].m_nPosition + (m_nHeaderSize + 24) + m_headerMVEX.size_atom; // +offset = (moov size + file head (ftyp, isom ))
stbl.stsc.table[i].chunk = m_sTrack[nTrack].m_pSamples[i].m_nFirstChunk;
stbl.stsc.table[i].samples = m_sTrack[nTrack].m_pSamples[i].m_nSamplesPerChunk;
stbl.stsc.table[i].id = m_sTrack[nTrack].m_pSamples[i].m_nId;
if (I_PICTURE == m_sTrack[nTrack].m_pSamples[i].m_frameTMype)
{
stbl.stss.table[stbl.stss.total_entries].sample = i;
stbl.stss.total_entries++;
}
}
// filling stts
dur = m_sTrack[nTrack].m_pSamples[0].m_nDuration;
stbl.stts.table[0].sample_count = 1;
stbl.stts.table[0].sample_duration = dur;
for (i = 1, j = 0; i < m_sTrack[nTrack].m_nSamplesCount - 1; i++)
{
if (dur != m_sTrack[nTrack].m_pSamples[i].m_nDuration)
{
j++;
stbl.stts.table[j].sample_count = 1;
dur = m_sTrack[nTrack].m_pSamples[i].m_nDuration;
stbl.stts.table[j].sample_duration = dur;
} else
{
stbl.stts.table[j].sample_count++;
}
}
if (i > 1)
{
if ((m_sTrack[nTrack].m_pSamples[i].m_nDuration == 0) || // last sample
m_sTrack[nTrack].m_pSamples[i].m_nDuration == m_sTrack[nTrack].m_pSamples[i - 1].m_nDuration)
{
stbl.stts.table[j].sample_count++; // last sample
} else
{
stbl.stts.table[j + 1].sample_count = 1;
stbl.stts.table[j + 1].sample_duration = m_sTrack[nTrack].m_pSamples[i].m_nDuration;
}
}
// filling 駎ts if needed
if (m_sTrack[nTrack].m_nCttsEntries) {
Ipp32s mDTS, curoff, off;
sMuxSample *pSamples = m_sTrack[nTrack].m_pSamples;
Ipp32u nSamples = m_sTrack[nTrack].m_nSamplesCount;
stbl.ctts.table[0].sample_count = 1;
stbl.ctts.table[0].sample_offset = -m_sTrack[nTrack].m_ctts_delta;
mDTS = pSamples[0].m_nTimeStamp + pSamples[0].m_nDuration;
curoff = -m_sTrack[nTrack].m_ctts_delta;
for (i = 1, j = 0; i < nSamples; i++) {
off = pSamples[i].m_nTimeStamp - mDTS - m_sTrack[nTrack].m_ctts_delta;
if (curoff != off) {
j++;
stbl.ctts.table[j].sample_count = 1;
stbl.ctts.table[j].sample_offset = off;
curoff = off;
} else {
stbl.ctts.table[j].sample_count++;
}
mDTS += pSamples[i].m_nDuration;
}
}
}
return UMC_OK;
}
static Ipp32s FindStartCode(Ipp8u * (&pb), size_t& nSize)
{
// there is no data
if ((Ipp32s) nSize < 4)
return 0;
// find start code
while ((4 <= nSize) && ((0 != pb[0]) || (0 != pb[1]) || (1 != pb[2])))
{
pb += 1;
nSize -= 1;
}
if (4 <= nSize)
return ((pb[0] << 24) | (pb[1] << 16) | (pb[2] << 8) | (pb[3]));
return 0;
} // Ipp32s FindStartCode(Ipp8u * (&pb), size_t &nSize)
Status MP4Muxer::CheckStartCode(Ipp32s nNAL, Ipp8s* pData, Ipp32u nPos, MediaData* mH264Data, bool bLast)
{
Ipp32s length = 0;
if (bLast)
{
length = mH264Data->GetDataSize() - nPos;
}
else
{
length = (Ipp8s*)pData - (Ipp8s*)mH264Data->GetBufferPointer() - nPos;
}
if (NAL_UT_SPS == nNAL || NAL_UT_SPS_EX == nNAL)
{
m_pH264Header->m_pNal_ut_sps[m_pH264Header->m_nSps_num].m_pNal_ut_sps = _NEW_n(Ipp8s, length);
m_pH264Header->m_pNal_ut_sps[m_pH264Header->m_nSps_num].m_nLength = length;
memcpy(m_pH264Header->m_pNal_ut_sps[m_pH264Header->m_nSps_num].m_pNal_ut_sps,
(Ipp8s*)mH264Data->GetBufferPointer() + nPos, length);
m_pH264Header->m_nSps_num++;
return UMC_HEADER;
}
if (NAL_UT_PPS == nNAL)
{
m_pH264Header->m_pNal_ut_pps[m_pH264Header->m_nPps_num].m_pNal_ut_pps = _NEW_n(Ipp8s, length);
m_pH264Header->m_pNal_ut_pps[m_pH264Header->m_nPps_num].m_nLength = length;
memcpy(m_pH264Header->m_pNal_ut_pps[m_pH264Header->m_nPps_num].m_pNal_ut_pps,
(Ipp8s*)mH264Data->GetBufferPointer() + nPos, length);
m_pH264Header->m_nPps_num++;
return UMC_HEADER;
}
if (NAL_UT_SLICE == nNAL || NAL_UT_IDR_SLICE == nNAL || NAL_UT_AUXILIARY == nNAL)
{
Ipp32u s_length = BSWAP32(length);
memcpy(m_pH264Data + m_nH264DataOffset, (Ipp8s*)&s_length, 4);
m_nH264DataOffset +=4;
memcpy(m_pH264Data + m_nH264DataOffset, (Ipp8s*)mH264Data->GetBufferPointer() + nPos, length);
m_nH264DataOffset +=length;
return UMC_DATA;
}
return UMC_NO_SUCH_CODE;
};
MediaData* MP4Muxer::TransformH264Frame(MediaData* mH264Data, Ipp32u nTrack)
{
Ipp8u *pData = (Ipp8u *) mH264Data->GetBufferPointer();
size_t nLen = mH264Data->GetDataSize();
bool bStop = false;
Ipp32s pos = 0;
Ipp32s nNAL = 0;
bool bIsData = false;
Status umcRes = 0;
//FILE* f2;
//f2 = fopen("1.h264", "ab+");
//fwrite(mH264Data->GetDataPointer(), 1, mH264Data->GetDataSize(), f2);
//fclose(f2);
if( m_iH264DataCurSize < nLen+10000 ){
_SAFE_DELETE_ARRAY(m_pH264Data);
m_iH264DataCurSize = nLen+10000; //Added ~10K, because cut of NAL unit takes 3 bytes away, but muxer adds size of NAL unit that is 4 bytest ( 1 byte difference )
_SAFE_NEW_n(m_pH264Data, Ipp8s, m_iH264DataCurSize);
m_mH264DataOut->SetBufferPointer((Ipp8u*)m_pH264Data, m_iH264DataCurSize);
}
// memset(m_pH264Data, 0, m_iH264DataCurSize);
_SAFE_NEW_n(m_pH264Header->m_pNal_ut_sps, sNal_ut_sps, 32);
_SAFE_NEW_n(m_pH264Header->m_pNal_ut_pps, sNal_ut_pps, 256);
while ((Ipp8s*)pData < ((Ipp8s*)mH264Data->GetBufferPointer() + mH264Data->GetDataSize()))
{
Ipp32s iCode = FindStartCode(pData, nLen);
// check start codes
if (NAL_UT_SPS == (iCode & NAL_UNITTYPE_BITS) ||
NAL_UT_SPS_EX == (iCode & NAL_UNITTYPE_BITS) ||
NAL_UT_PPS == (iCode & NAL_UNITTYPE_BITS) ||
NAL_UT_SLICE == (iCode & NAL_UNITTYPE_BITS) ||
NAL_UT_IDR_SLICE == (iCode & NAL_UNITTYPE_BITS) ||
NAL_UT_AUXILIARY == (iCode & NAL_UNITTYPE_BITS))
{
if (bStop)
{
umcRes = CheckStartCode(nNAL, (Ipp8s*)pData, pos, mH264Data, 0);
}
bStop = true;
}
else
{
if (bStop)
{
umcRes = CheckStartCode(nNAL, (Ipp8s*)pData, pos, mH264Data, 1);
}
bStop = false;
}
nNAL = iCode & NAL_UNITTYPE_BITS;
pos = (Ipp8s*)pData - (Ipp8s*)mH264Data->GetBufferPointer() + 3;
pData +=3;
nLen -= 3;
if (UMC_DATA == umcRes)
{
bIsData = true;
}
}
if (bIsData)
{
m_mH264DataOut->SetDataSize(m_nH264DataOffset);
m_mH264DataOut->SetTime(mH264Data->GetTime());
m_mH264DataOut->SetFrameType(mH264Data->GetFrameType());
Ipp64f dPTS, dDTS;
mH264Data->GetTime(dPTS, dDTS);
m_mH264DataOut->SetTime(dPTS, dDTS);
} else
return NULL;
m_nH264DataOffset = 0;
return m_mH264DataOut;
}
Status MP4Muxer::InitEsds(MuxerParams* params)
{
for (Ipp32u i = 0; i < m_headerMPEG4.total_tracks; i++)
{
Ipp32s nIndex = m_headerMPEG4.trak[i]->mdia.minf.stbl.stsd.total_entries - 1; // now total_entries = 1, so nIndex = 0;
TM_esds_data& esds = m_headerMPEG4.trak[i]->mdia.minf.stbl.stsd.table[nIndex].esds;
if (UMC::H264_VIDEO == m_pTrackParams[i].info.video->stream_type) {
if (!m_mH264DataOut)
m_mH264DataOut = new MediaData;
if (!m_pH264Header) {
m_pH264Header = new sH246_Header;
memset(m_pH264Header, 0, sizeof(sH246_Header));
}
}
esds.objectTypeID = 0;
esds.streamType = 0;
esds.decoderConfigLen = 0;
esds.decoderConfig = NULL;
esds.version = 0;
esds.flags = 0;
}
return UMC_OK;
};
Status MP4Muxer::InitMoof()
{
Ipp32u nTrack = 0;
Ipp32u i = 0;
m_headerMoof.sequence_number++;
m_headerMoof.size_atom = m_nHeaderSize;
if (m_headerMoof.trun)
{
for (nTrack = 0; nTrack < m_headerMPEG4.total_tracks; nTrack++)
{
_SAFE_DELETE_ARRAY(m_headerMoof.trun[nTrack].trun);
}
}
else
{
m_headerMoof.trun = _NEW_n(TM_table_trun, m_headerMPEG4.total_tracks);
}
for ( nTrack = 0; nTrack < m_headerMPEG4.total_tracks; nTrack++)
{
TM_table_trun& trunTrack = m_headerMoof.trun[nTrack];
trunTrack.entry_count = m_sTrack[nTrack].m_nSamplesCount;
trunTrack.trun = _NEW_n(TM_trun_table_data, trunTrack.entry_count);
for (i = 0; i < m_sTrack[nTrack].m_nSamplesCount; i++)
{
if (i != m_sTrack[nTrack].m_nSamplesCount - 1) {
trunTrack.trun[i].sample_duration = m_sTrack[nTrack].m_pSamples[i+1].m_nTimeStamp - m_sTrack[nTrack].m_pSamples[i].m_nTimeStamp;
} else {
if (i != 0) {
trunTrack.trun[i].sample_duration = trunTrack.trun[i-1].sample_duration; //last sample
}
}
// trunTrack.trun[i].sample_duration = m_sTrack[nTrack].m_pSamples[i].m_nTimeStamp;
trunTrack.trun[i].sample_size = m_sTrack[nTrack].m_pSamples[i].m_nSize;
}
}
return UMC_OK;
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -