📄 umc_mp4_mux.cpp
字号:
if (m_sTrack[ntrak].m_nSamplesCount + 1 >= m_sTrack[ntrak].m_nTrackSize)
{
m_sTrack[ntrak].m_pSamples = (sMuxSample*) realloc(m_sTrack[ntrak].m_pSamples, sizeof(sMuxSample) * (INITIAL_TRACK_SIZE + (size_t)m_sTrack[ntrak].m_nTrackSize));
m_sTrack[ntrak].m_nTrackSize += INITIAL_TRACK_SIZE;
}
return UMC_OK;
}
Status MP4Muxer::AdjustVideoData(MediaData* &lpData, Ipp32s nStreamNumber)
{
if (m_bDataFromEncoder && UMC::H264_VIDEO == m_pTrackParams[nStreamNumber].info.video->stream_type)
{
lpData = TransformH264Frame(lpData, nStreamNumber);
} else {
if (m_FirstFrame[nStreamNumber]) {
m_FirstFrame[nStreamNumber] = 0;
TM_esds_data *pEsds = &(m_headerMPEG4.trak[nStreamNumber]->mdia.minf.stbl.stsd.table[0].esds);
if (UMC::MPEG4_VIDEO == m_pTrackParams[nStreamNumber].info.video->stream_type) {
if (m_bDataFromEncoder) {
// mp4v from encoder: fill esds and PutData
int i, m_InfoLen = 0;
int mFrameLen = lpData->GetDataSize();
Ipp8u *pData = (Ipp8u *)lpData->GetDataPointer();
for (i = 0; i < mFrameLen - 3; i++) {
if (((pData[i]==0x00)&&(pData[i+1]==0x00)&&(pData[i+2]==0x01)&&(pData[i+3]==0xb6)) ||
((pData[i]==0x00)&&(pData[i+1]==0x00)&&(pData[i+2]==0x01)&&(pData[i+3]==0xb3))) {
m_InfoLen = i;
break;
}
}
// m_InfoLen can't be equal to zero
vm_trace_i(m_InfoLen);
if (m_InfoLen) {
pEsds->decoderConfigLen = m_InfoLen;
pEsds->decoderConfig = (Ipp8u *)malloc(m_InfoLen);
memcpy(pEsds->decoderConfig, pData, m_InfoLen);
lpData->MoveDataPointer(m_InfoLen); // cut off mp4v header
}
} else {
// mp4v from splitter: first frame is esds
pEsds->decoderConfigLen = lpData->GetDataSize();
pEsds->decoderConfig = (Ipp8u *)malloc(pEsds->decoderConfigLen);
memcpy(pEsds->decoderConfig, lpData->GetDataPointer(), lpData->GetDataSize());
lpData->SetDataSize(0);
}
}
}
}
return UMC_OK;
}
Status MP4Muxer::AdjustAudioData(MediaData* &lpData, Ipp32s nStreamNumber)
{
Ipp32s nbits, nbytes;
sBitsreamBuffer BS;
sAdts_fixed_header m_adts_fixed_header;
sAdts_variable_header m_adts_variable_header;
if (m_pTrackParams[nStreamNumber].info.audio->stream_type & AAC_AUDIO) {
if (m_bDataFromEncoder) {
GET_INIT_BITSTREAM(&BS, lpData->GetDataPointer());
if ((0 == dec_adts_fixed_header(&m_adts_fixed_header, &BS)) &&
(0 == dec_adts_variable_header(&m_adts_variable_header, &BS)))
{
Byte_alignment(&BS);
GET_BITS_COUNT(&BS, nbits);
nbytes = nbits >> 3;
if (m_adts_fixed_header.protection_absent == 0) {
nbytes += 2;
}
lpData->MoveDataPointer(nbytes); // cut off adts headers
}
}
if (m_FirstFrame[nStreamNumber]) {
m_FirstFrame[nStreamNumber] = 0;
if (m_bDataFromEncoder) {
sAudio_specific_config decSpecConfig;
MediaData p_SpecInfo(400);
/// AudioSpecificConfig;
decSpecConfig.sbrPresentFlag = 0;
decSpecConfig.audioObjectType = get_audio_object_type_by_adts_header(&m_adts_fixed_header);
decSpecConfig.samplingFrequencyIndex = m_adts_fixed_header.sampling_frequency_index;
decSpecConfig.samplingFrequency = 0;
decSpecConfig.channelConfiguration = m_adts_fixed_header.channel_configuration;
decSpecConfig.extensionAudioObjectType = 0; // for SBR
decSpecConfig.extensionSamplingFrequencyIndex = 0; // for SBR
decSpecConfig.extensionSamplingFrequency = 0; // for SBR
/// sGA_specific_config;
decSpecConfig.GASpecificConfig.frameLengthFlag = 1; //1024
decSpecConfig.GASpecificConfig.dependsOnCoreCoder = 0;
decSpecConfig.GASpecificConfig.coreCoderDelay = 0;
decSpecConfig.GASpecificConfig.extensionFlag = 0; // for SBR
// decSpecConfig.GASpecificConfig.pce;
INIT_BITSTREAM(&BS, p_SpecInfo.GetDataPointer());
enc_audio_specific_config(&decSpecConfig, &BS);
GET_BITS_COUNT(&BS, nbits);
nbytes = nbits >> 3;
p_SpecInfo.SetDataSize(nbytes);
TM_esds_data *pEsds = &(m_headerMPEG4.trak[nStreamNumber]->mdia.minf.stbl.stsd.table[0].esds);
pEsds->decoderConfigLen = nbytes;
pEsds->decoderConfig = (Ipp8u *)malloc(pEsds->decoderConfigLen);
memcpy(pEsds->decoderConfig, p_SpecInfo.GetDataPointer(), nbytes);
} else { // AAC from splitter case
TM_esds_data *pEsds = &(m_headerMPEG4.trak[nStreamNumber]->mdia.minf.stbl.stsd.table[0].esds);
pEsds->decoderConfigLen = lpData->GetDataSize();
pEsds->decoderConfig = (Ipp8u *)malloc(pEsds->decoderConfigLen);
memcpy(pEsds->decoderConfig, lpData->GetDataPointer(), lpData->GetDataSize());
lpData->SetDataSize(0);
}
} // m_bFirstAudioFrame
}
return UMC_OK;
}
Status MP4Muxer::UnlockBuffer(MediaData *lpData, Ipp32s iTrack)
{
Status umcRes;
UMC_CHECK(lpData, UMC_OK);
UMC_CHECK(lpData->GetDataSize(), UMC_OK);
umcRes = Muxer::UnlockBuffer(lpData, iTrack);
if (umcRes != UMC::UMC_OK) {
return umcRes;
}
return MuxData(false);
}
Status MP4Muxer::PutEndOfStream(Ipp32s iTrack)
{
Status umcRes;
umcRes = Muxer::PutEndOfStream(iTrack);
if ((umcRes != UMC::UMC_OK) && (umcRes != UMC::UMC_ERR_NULL_PTR)) {
return umcRes;
}
return MuxData(false);
} //Status Muxer::PutEndOfStream(Ipp32u iTrack)
Status MP4Muxer::Flush(void)
{
return MuxData(true);
} //Status MPEG2Muxer::Flush(void)
Status MP4Muxer::MuxData(bool bFlushMode)
{
AutomaticMutex guard(m_PutDataMutex);
Ipp32s nEndIndex;
MediaData cData, *pcData;
Status umcRes;
int nSize;
for (;;) {
//find shortest track, and add frame to it
nEndIndex = FindMinTrackEnd(m_sTrack, m_uiTotalNumStreams);
vm_debug_trace2(VM_DEBUG_PROGRESS, VM_STRING("nEndIndex = %i m_sTrack->m_nTrackEnd = %f\n"), nEndIndex, m_sTrack[nEndIndex].m_nTrackEnd);
if (nEndIndex == -1) break; // EOS in all tracks
umcRes = m_ppBuffers[nEndIndex]->LockOutputBuffer(&cData);
if (umcRes == UMC_OK) {
pcData = &cData;
if (IS_VIDEO(nEndIndex)) {
//maybe problem with video in one header, and audio in another
if (needNewFragment(pcData, nEndIndex))
DisposeDataToFile();
vm_debug_trace1(VM_DEBUG_PROGRESS, VM_STRING("m_nHeaderSize = %d\n"), m_nHeaderSize);
AdjustVideoData(pcData, nEndIndex);
} else {
vm_debug_trace(VM_DEBUG_PROGRESS, VM_STRING("audio buffer is chosen!!!\n"));
AdjustAudioData(pcData, nEndIndex);
}
if (pcData->GetDataSize() != 0) { // don't mux if decSpecInfo
vm_file *pFile = m_fTempOutput1;
if (IS_AUDIO(nEndIndex) && !m_bMoov)
pFile = m_fTempOutput2[nEndIndex];
nSize = _FWRITE_P(pcData, pFile);
vm_debug_trace2(VM_DEBUG_PROGRESS, VM_STRING("wrote from buffer %d to file %i bytes!!!\n"), nEndIndex, nSize);
m_nMdatSize += nSize;
SampleInfo(pcData, nEndIndex);
}
cData.SetDataSize(0);
m_ppBuffers[nEndIndex]->UnLockOutputBuffer(&cData);
} else if (umcRes == UMC_ERR_END_OF_STREAM) {
m_sTrack[nEndIndex].m_nTrackStatus = 1; // track is fully muxed
} else if (umcRes == UMC_ERR_NOT_ENOUGH_DATA) { // no data
if (bFlushMode == false) {
break; // break if not flush mode
} else {
m_sTrack[nEndIndex].m_nTrackStatus = 1;
}
} else {
break; // probably error
}
}
return UMC_OK;
}
Status MP4Muxer::WriteHeader()
{
vm_trace_s("WriteHeader");
//write the very head to file ("ftypisom-isom")
Write_head(m_pParams->m_lpDataWriter);
//update atoms in header (moov),
UpdateHeader();
//init atoms in header (moov)
InitAtoms();
//calculate sizes of all atoms in header (moov)
CalculateSizes();
//write main(single, if true == m_bMoov) "header" to file
if (Write_moov(m_pParams->m_lpDataWriter, &m_headerMPEG4) != UMC_OK )
return UMC_ERR_FAILED;
//if header has extensions, then file structure will has moof atoms
if (!m_bMoov)
{
if (Write_mvex(m_pParams->m_lpDataWriter, &m_headerMVEX) != UMC_OK)
return UMC_ERR_FAILED;
}
//write "mdat" atom size to first 4 bytes in file
WriteMdatSize();
//transfer data from temporary file to output resulting file
TransferDataFromTemporaryFile(m_fTempOutput1);
return UMC_OK;
}
Status MP4Muxer::WriteHeaderFragment()
{
vm_trace_s("WriteHeaderFragment");
InitMoof();
if (Write_moof(m_pParams->m_lpDataWriter, &m_headerMoof) != UMC_OK )
return UMC_ERR_FAILED;
WriteMdatSize();
TransferDataFromTemporaryFile(m_fTempOutput1);
for (Ipp32u i = 0; i < m_uiTotalNumStreams; i++)
{
if (IS_AUDIO(i)) {
_SEEK_FILE_START(m_fTempOutput2[i]);
TransferDataFromTemporaryFile(m_fTempOutput2[i]);
}
}
return UMC_OK;
}
Status MP4Muxer::DumpState()
{
Ipp32u i;
UMC_CHECK_PTR(m_ppBuffers);
for (i = 0; i < m_uiTotalNumStreams; i++) {
vm_trace_i(m_pTrackParams[i].type);
UMC_CHECK_PTR(m_ppBuffers[i]);
}
return UMC_OK;
}
} // namespace UMC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -