📄 mp4file.cpp
字号:
}MP4TrackId MP4File::AddH263VideoTrack( u_int32_t timeScale, MP4Duration sampleDuration, u_int16_t width, u_int16_t height, u_int8_t h263Level, u_int8_t h263Profile, u_int32_t avgBitrate, u_int32_t maxBitrate){ MP4TrackId trackId = AddVideoTrackDefault(timeScale, sampleDuration, width, height, "s263"); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.s263.width", width); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.s263.height", height); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.s263.d263.h263Level", h263Level); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.s263.d263.h263Profile", h263Profile); // Add the bitr atom (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"), "bitr"); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.s263.d263.bitr.avgBitrate", avgBitrate); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.s263.d263.bitr.maxBitrate", maxBitrate); SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsz.sampleSize", sampleDuration); return trackId;}MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId){ // validate reference track id (void)FindTrackIndex(refTrackId); MP4TrackId trackId = AddTrack(MP4_HINT_TRACK_TYPE, GetTrackTimeScale(refTrackId)); (void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "hmhd", 0); (void)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)); (void)AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint"); AddTrackReference(MakeTrackName(trackId, "tref.hint"), refTrackId); (void)AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp "); (void)AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf"); return trackId;}MP4TrackId MP4File::AddTextTrack(MP4TrackId refTrackId){ // validate reference track id (void)FindTrackIndex(refTrackId); MP4TrackId trackId = AddTrack(MP4_TEXT_TRACK_TYPE, GetTrackTimeScale(refTrackId)); (void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "gmhd", 0); (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "text"); // 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 text atom MP4Integer32Property* pStsdCountProperty; FindIntegerProperty( MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), (MP4Property**)&pStsdCountProperty); pStsdCountProperty->IncrementValue(); return trackId;}MP4TrackId MP4File::AddChapterTextTrack(MP4TrackId refTrackId){ // validate reference track id (void)FindTrackIndex(refTrackId); MP4TrackId trackId = AddTrack(MP4_TEXT_TRACK_TYPE, GetTrackTimeScale(refTrackId)); (void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "gmhd", 0); (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "text"); // 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 text atom MP4Integer32Property* pStsdCountProperty; FindIntegerProperty( MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), (MP4Property**)&pStsdCountProperty); pStsdCountProperty->IncrementValue(); // add a "text" atom to the generic media header // this is different to the stsd "text" atom added above // truth be told, it's not clear what this second "text" atom does, // but all iTunes Store movies (with chapter markers) have it, // as do all movies with chapter tracks made by hand in QuickTime Pro (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.gmhd"), "text"); // disable the chapter text track // it won't display anyway, as it has zero display size, // but nonetheless it's good to disable it // the track still operates as a chapter track when disabled MP4Atom *pTkhdAtom = FindAtom(MakeTrackName(trackId, "tkhd")); if (pTkhdAtom) { pTkhdAtom->SetFlags(0xE); } // add a "chapter" track reference to our reference track, // pointing to this new chapter track (void)AddDescendantAtoms(MakeTrackName(refTrackId, NULL), "tref.chap"); AddTrackReference(MakeTrackName(refTrackId, "tref.chap"), trackId); 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, ShallHaveIods()); 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 = MP4NormalizeTrackType(type, m_verbosity); 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 != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) { continue; } } else if (normType == MP4_VIDEO_TRACK_TYPE) { if (subType != GetTrackEsdsObjectTypeId(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 { (void)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 { (void)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 = MP4NormalizeTrackType(type, m_verbosity); 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 != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) { continue; } } else if (normType == MP4_VIDEO_TRACK_TYPE) { if (subType != GetTrackEsdsObjectTypeId(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); if (name == NULL || name[0] == '\0') { snprintf(m_trakName, sizeof(m_trakName), "moov.trak[%u]", trakIndex); } else { snprintf(m_trakName, sizeof(m_trakName), "moov.trak[%u].%s", trakIndex, name); } return m_trakName;}MP4Atom *MP4File::FindTrackAtom (MP4TrackId trackId, const char *name){ return FindAtom(MakeTrackName(trackId, name));}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){ SetInte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -