📄 mp4file.cpp
字号:
MP4TrackId MP4File::AddVideoTrack( u_int32_t timeScale, MP4Duration sampleDuration, u_int16_t width, u_int16_t height, u_int8_t videoType){ MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale); AddTrackToOd(trackId); SetTrackFloatProperty(trackId, "tkhd.width", width); SetTrackFloatProperty(trackId, "tkhd.height", height); InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0); AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4v"); // stsd is a unique beast in that it has a count of the number // of child atoms that needs to be incremented after we add the mp4v atom MP4Integer32Property* pStsdCountProperty; FindIntegerProperty( MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), (MP4Property**)&pStsdCountProperty); pStsdCountProperty->IncrementValue(); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4v.width", width); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4v.height", height); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4v.esds.ESID", trackId); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId", videoType); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.streamType", MP4VisualStreamType); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsz.sampleSize", sampleDuration); m_pTracks[FindTrackIndex(trackId)]-> SetFixedSampleDuration(sampleDuration); return trackId;}MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId){ // validate reference track id FindTrackIndex(refTrackId); MP4TrackId trackId = AddTrack(MP4_HINT_TRACK_TYPE, GetTrackTimeScale(refTrackId)); InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "hmhd", 0); AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "rtp "); // stsd is a unique beast in that it has a count of the number // of child atoms that needs to be incremented after we add the rtp atom MP4Integer32Property* pStsdCountProperty; FindIntegerProperty( MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), (MP4Property**)&pStsdCountProperty); pStsdCountProperty->IncrementValue(); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.rtp .tims.timeScale", GetTrackTimeScale(trackId)); AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint"); AddTrackReference(MakeTrackName(trackId, "tref.hint"), refTrackId); AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp "); AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf"); return trackId;}void MP4File::DeleteTrack(MP4TrackId trackId){ ProtectWriteOperation("MP4DeleteTrack"); u_int32_t trakIndex = FindTrakAtomIndex(trackId); u_int16_t trackIndex = FindTrackIndex(trackId); MP4Track* pTrack = m_pTracks[trackIndex]; MP4Atom* pTrakAtom = pTrack->GetTrakAtom(); ASSERT(pTrakAtom); MP4Atom* pMoovAtom = FindAtom("moov"); ASSERT(pMoovAtom); RemoveTrackFromIod(trackId); RemoveTrackFromOd(trackId); if (trackId == m_odTrackId) { m_odTrackId = 0; } pMoovAtom->DeleteChildAtom(pTrakAtom); m_trakIds.Delete(trakIndex); m_pTracks.Delete(trackIndex); delete pTrack; delete pTrakAtom;}u_int32_t MP4File::GetNumberOfTracks(const char* type, u_int8_t subType){ if (type == NULL) { return m_pTracks.Size(); } u_int32_t typeSeen = 0; const char* normType = MP4Track::NormalizeTrackType(type); for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { if (!strcmp(normType, m_pTracks[i]->GetType())) { if (subType) { if (normType == MP4_AUDIO_TRACK_TYPE) { if (subType != GetTrackAudioType(m_pTracks[i]->GetId())) { continue; } } else if (normType == MP4_VIDEO_TRACK_TYPE) { if (subType != GetTrackVideoType(m_pTracks[i]->GetId())) { continue; } } // else unknown subtype, ignore it } typeSeen++; } } return typeSeen;}MP4TrackId MP4File::AllocTrackId(){ MP4TrackId trackId = GetIntegerProperty("moov.mvhd.nextTrackId"); if (trackId <= 0xFFFF) { // check that nextTrackid is correct try { FindTrackIndex(trackId); // ERROR, this trackId is in use } catch (MP4Error* e) { // OK, this trackId is not in use, proceed delete e; SetIntegerProperty("moov.mvhd.nextTrackId", trackId + 1); return trackId; } } // we need to search for a track id for (trackId = 1; trackId <= 0xFFFF; trackId++) { try { FindTrackIndex(trackId); // KEEP LOOKING, this trackId is in use } catch (MP4Error* e) { // OK, this trackId is not in use, proceed delete e; return trackId; } } // extreme case where mp4 file has 2^16 tracks in it throw new MP4Error("too many existing tracks", "AddTrack"); return MP4_INVALID_TRACK_ID; // to keep MSVC happy}MP4TrackId MP4File::FindTrackId( u_int16_t trackIndex, const char* type, u_int8_t subType){ if (type == NULL) { return m_pTracks[trackIndex]->GetId(); } u_int32_t typeSeen = 0; const char* normType = MP4Track::NormalizeTrackType(type); for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { if (!strcmp(normType, m_pTracks[i]->GetType())) { if (subType) { if (normType == MP4_AUDIO_TRACK_TYPE) { if (subType != GetTrackAudioType(m_pTracks[i]->GetId())) { continue; } } else if (normType == MP4_VIDEO_TRACK_TYPE) { if (subType != GetTrackVideoType(m_pTracks[i]->GetId())) { continue; } } // else unknown subtype, ignore it } if (trackIndex == typeSeen) { return m_pTracks[i]->GetId(); } typeSeen++; } } throw new MP4Error("Track index doesn't exist - track %d type %s", "FindTrackId", trackIndex, type); return MP4_INVALID_TRACK_ID; // satisfy MS compiler}u_int16_t MP4File::FindTrackIndex(MP4TrackId trackId){ for (u_int32_t i = 0; i < m_pTracks.Size() && i <= 0xFFFF; i++) { if (m_pTracks[i]->GetId() == trackId) { return (u_int16_t)i; } } throw new MP4Error("Track id %d doesn't exist", "FindTrackIndex", trackId); return (u_int16_t)-1; // satisfy MS compiler}u_int16_t MP4File::FindTrakAtomIndex(MP4TrackId trackId){ if (trackId) { for (u_int32_t i = 0; i < m_trakIds.Size(); i++) { if (m_trakIds[i] == trackId) { return i; } } } throw new MP4Error("Track id %d doesn't exist", "FindTrakAtomIndex", trackId); return (u_int16_t)-1; // satisfy MS compiler}u_int32_t MP4File::GetSampleSize(MP4TrackId trackId, MP4SampleId sampleId){ return m_pTracks[FindTrackIndex(trackId)]->GetSampleSize(sampleId);}u_int32_t MP4File::GetTrackMaxSampleSize(MP4TrackId trackId){ return m_pTracks[FindTrackIndex(trackId)]->GetMaxSampleSize();}MP4SampleId MP4File::GetSampleIdFromTime(MP4TrackId trackId, MP4Timestamp when, bool wantSyncSample){ return m_pTracks[FindTrackIndex(trackId)]-> GetSampleIdFromTime(when, wantSyncSample);}MP4Timestamp MP4File::GetSampleTime( MP4TrackId trackId, MP4SampleId sampleId){ MP4Timestamp timestamp; m_pTracks[FindTrackIndex(trackId)]-> GetSampleTimes(sampleId, ×tamp, NULL); return timestamp;}MP4Duration MP4File::GetSampleDuration( MP4TrackId trackId, MP4SampleId sampleId){ MP4Duration duration; m_pTracks[FindTrackIndex(trackId)]-> GetSampleTimes(sampleId, NULL, &duration); return duration; }MP4Duration MP4File::GetSampleRenderingOffset( MP4TrackId trackId, MP4SampleId sampleId){ return m_pTracks[FindTrackIndex(trackId)]-> GetSampleRenderingOffset(sampleId);}bool MP4File::GetSampleSync(MP4TrackId trackId, MP4SampleId sampleId){ return m_pTracks[FindTrackIndex(trackId)]->IsSyncSample(sampleId);}void MP4File::ReadSample(MP4TrackId trackId, MP4SampleId sampleId, u_int8_t** ppBytes, u_int32_t* pNumBytes, MP4Timestamp* pStartTime, MP4Duration* pDuration, MP4Duration* pRenderingOffset, bool* pIsSyncSample){ m_pTracks[FindTrackIndex(trackId)]-> ReadSample(sampleId, ppBytes, pNumBytes, pStartTime, pDuration, pRenderingOffset, pIsSyncSample);}void MP4File::WriteSample(MP4TrackId trackId, const u_int8_t* pBytes, u_int32_t numBytes, MP4Duration duration, MP4Duration renderingOffset, bool isSyncSample){ ProtectWriteOperation("MP4WriteSample"); m_pTracks[FindTrackIndex(trackId)]-> WriteSample(pBytes, numBytes, duration, renderingOffset, isSyncSample); m_pModificationProperty->SetValue(MP4GetAbsTimestamp());}void MP4File::SetSampleRenderingOffset(MP4TrackId trackId, MP4SampleId sampleId, MP4Duration renderingOffset){ ProtectWriteOperation("MP4SetSampleRenderingOffset"); m_pTracks[FindTrackIndex(trackId)]-> SetSampleRenderingOffset(sampleId, renderingOffset); m_pModificationProperty->SetValue(MP4GetAbsTimestamp());}char* MP4File::MakeTrackName(MP4TrackId trackId, const char* name){ u_int16_t trakIndex = FindTrakAtomIndex(trackId); static char trakName[1024]; if (name == NULL || name[0] == '\0') { snprintf(trakName, sizeof(trakName), "moov.trak[%u]", trakIndex); } else { snprintf(trakName, sizeof(trakName), "moov.trak[%u].%s", trakIndex, name); } return trakName;}u_int64_t MP4File::GetTrackIntegerProperty(MP4TrackId trackId, const char* name){ return GetIntegerProperty(MakeTrackName(trackId, name));}void MP4File::SetTrackIntegerProperty(MP4TrackId trackId, const char* name, int64_t value){ SetIntegerProperty(MakeTrackName(trackId, name), value);}float MP4File::GetTrackFloatProperty(MP4TrackId trackId, const char* name){ return GetFloatProperty(MakeTrackName(trackId, name));}void MP4File::SetTrackFloatProperty(MP4TrackId trackId, const char* name, float value){ SetFloatProperty(MakeTrackName(trackId, name), value);}const char* MP4File::GetTrackStringProperty(MP4TrackId trackId, const char* name){ return GetStringProperty(MakeTrackName(trackId, name));}void MP4File::SetTrackStringProperty(MP4TrackId trackId, const char* name, const char* value){ SetStringProperty(MakeTrackName(trackId, name), value);}void MP4File::GetTrackBytesProperty(MP4TrackId trackId, const char* name, u_int8_t** ppValue, u_int32_t* pValueSize){ GetBytesProperty(MakeTrackName(trackId, name), ppValue, pValueSize);}void MP4File::SetTrackBytesProperty(MP4TrackId trackId, const char* name, const u_int8_t* pValue, u_int32_t valueSize){ SetBytesProperty(MakeTrackName(trackId, name), pValue, valueSize);}// file level convenience functionsMP4Duration MP4File::GetDuration(){ return m_pDurationProperty->GetValue();}void MP4File::SetDuration(MP4Duration value){ m_pDurationProperty->SetValue(value);}u_int32_t MP4File::GetTimeScale(){ return m_pTimeScaleProperty->GetValue();}void MP4File::SetTimeScale(u_int32_t value){ if (value == 0) { throw new MP4Error("invalid value", "SetTimeScale"); } m_pTimeScaleProperty->SetValue(value);}u_int8_t MP4File::GetODProfileLevel(){ return GetIntegerProperty("moov.iods.ODProfileLevelId");}void MP4File::SetODProfileLevel(u_int8_t value){ SetIntegerProperty("moov.iods.ODProfileLevelId", value);} u_int8_t MP4File::GetSceneProfileLevel(){ return GetIntegerProperty("moov.iods.sceneProfileLevelId");}void MP4File::SetSceneProfileLevel(u_int8_t value){ SetIntegerProperty("moov.iods.sceneProfileLevelId", value);} u_int8_t MP4File::GetVideoProfileLevel(){ return GetIntegerProperty("moov.iods.visualProfileLevelId");}void MP4File::SetVideoProfileLevel(u_int8_t value){ SetIntegerProperty("moov.iods.visualProfileLevelId", value);} u_int8_t MP4File::GetAudioProfileLevel(){ return GetIntegerProperty("moov.iods.audioProfileLevelId");}void MP4File::SetAudioProfileLevel(u_int8_t value){ SetIntegerProperty("moov.iods.audioProfileLevelId", value);} u_int8_t MP4File::GetGraphicsProfileLevel(){ return GetIntegerProperty("moov.iods.graphicsProfileLevelId");}void MP4File::SetGraphicsProfileLevel(u_int8_t value){ SetIntegerProperty("moov.iods.graphicsProfileLevelId", value);} const char* MP4File::GetSessionSdp(){ return GetStringProperty("moov.udta.hnti.rtp .sdpText");}void MP4File::SetSessionSdp(const char* sdpString){ AddDescendantAtoms("moov", "udta.hnti.rtp "); SetStringProperty("moov.udta.hnti.rtp .sdpText", sdpString);}void MP4File::AppendSessionSdp(const char* sdpFragment){ const char* oldSdpString = NULL; try { oldSdpString = GetSessionSdp(); } catch (MP4Error* e) { delete e; SetSessionSdp(sdpFragment); return; } char* newSdpString = (char*)MP4Malloc(strlen(oldSdpString) + strlen(sdpFragment) + 1); strcpy(newSdpString, oldSdpString); strcat(newSdpString, sdpFragment); SetSessionSdp(newSdpString); MP4Free(newSdpString);}// track level convenience functionsMP4SampleId MP4File::GetTrackNumberOfSamples(MP4TrackId trackId){ return m_pTracks[FindTrackIndex(trackId)]->GetNumberOfSamples();}const char* MP4File::GetTrackType(MP4TrackId trackId){ return m_pTracks[FindTrackIndex(trackId)]->GetType();}u_int32_t MP4File::GetTrackTimeScale(MP4TrackId trackId){ return m_pTracks[FindTrackIndex(trackId)]->GetTimeScale();}void MP4File::SetTrackTimeScale(MP4TrackId trackId, u_int32_t value){ if (value == 0) { throw new MP4Error("invalid value", "SetTrackTimeScale"); } SetTrackIntegerProperty(trackId, "mdia.mdhd.timeScale", value);}MP4Duration MP4File::GetTrackDuration(MP4TrackId trackId){ return GetTrackIntegerProperty(trackId, "mdia.mdhd.duration");}u_int8_t MP4File::GetTrackAudioType(MP4TrackId trackId){ return GetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId");}u_int8_t MP4File::GetTrackAudioMpeg4Type(MP4TrackId trackId){ // verify that track is an MPEG-4 audio track if (GetTrackAudioType(trackId) != MP4_MPEG4_AUDIO_TYPE) { return MP4_MPEG4_INVALID_AUDIO_TYPE; } u_int8_t* pEsConfig = NULL; u_int32_t esConfigSize; // The Mpeg4 audio type (AAC, CELP, HXVC, ...) // is the first 5 bits of the ES configuration GetTrackESConfiguration(trackId, &pEsConfig, &esConfigSize); if (esConfigSize < 1) { return MP4_MPEG4_INVALID_AUDIO_TYPE; } u_int8_t mpeg4Type = (pEsConfig[0] >> 3); free(pEsConfig); return mpeg4Type;}u_int8_t MP4File::GetTrackVideoType(MP4TrackId trackId){ return GetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId");}MP4Duration MP4File::GetTrackFixedSampleDuration(MP4TrackId trackId){ return m_pTracks[FindTrackIndex(trackId)]->GetFixedSampleDuration();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -