📄 mp4file.cpp
字号:
if (m_pFile == NULL) { throw new MP4Error(errno, "failed", "MP4Open"); } m_virtual_IO = &FILE_virtual_IO; if (m_mode == 'r') { m_orgFileSize = m_fileSize = m_virtual_IO->GetFileLength(m_pFile); // benski } else { m_orgFileSize = m_fileSize = 0; }}#endifvoid MP4File::ReadFromFile(){ // ensure we start at beginning of file SetPosition(0); // create a new root atom ASSERT(m_pRootAtom == NULL); m_pRootAtom = MP4Atom::CreateAtom(NULL); u_int64_t fileSize = GetSize(); m_pRootAtom->SetFile(this); m_pRootAtom->SetStart(0); m_pRootAtom->SetSize(fileSize); m_pRootAtom->SetEnd(fileSize); m_pRootAtom->Read(); // create MP4Track's for any tracks in the file GenerateTracks();}void MP4File::GenerateTracks(){ u_int32_t trackIndex = 0; while (true) { char trackName[32]; snprintf(trackName, sizeof(trackName), "moov.trak[%u]", trackIndex); // find next trak atom MP4Atom* pTrakAtom = m_pRootAtom->FindAtom(trackName); // done, no more trak atoms if (pTrakAtom == NULL) { break; } // find track id property MP4Integer32Property* pTrackIdProperty = NULL; (void)pTrakAtom->FindProperty( "trak.tkhd.trackId", (MP4Property**)&pTrackIdProperty); // find track type property MP4StringProperty* pTypeProperty = NULL; (void)pTrakAtom->FindProperty( "trak.mdia.hdlr.handlerType", (MP4Property**)&pTypeProperty); // ensure we have the basics properties if (pTrackIdProperty && pTypeProperty) { m_trakIds.Add(pTrackIdProperty->GetValue()); MP4Track* pTrack = NULL; try { if (!strcmp(pTypeProperty->GetValue(), MP4_HINT_TRACK_TYPE)) { pTrack = new MP4RtpHintTrack(this, pTrakAtom); } else { pTrack = new MP4Track(this, pTrakAtom); } m_pTracks.Add(pTrack); } catch (MP4Error* e) { VERBOSE_ERROR(m_verbosity, e->Print()); delete e; } // remember when we encounter the OD track if (pTrack && !strcmp(pTrack->GetType(), MP4_OD_TRACK_TYPE)) { if (m_odTrackId == MP4_INVALID_TRACK_ID) { m_odTrackId = pTrackIdProperty->GetValue(); } else { VERBOSE_READ(GetVerbosity(), printf("Warning: multiple OD tracks present\n")); } } } else { m_trakIds.Add(0); } trackIndex++; }}void MP4File::CacheProperties(){ FindIntegerProperty("moov.mvhd.modificationTime", (MP4Property**)&m_pModificationProperty); FindIntegerProperty("moov.mvhd.timeScale", (MP4Property**)&m_pTimeScaleProperty); FindIntegerProperty("moov.mvhd.duration", (MP4Property**)&m_pDurationProperty);}void MP4File::BeginWrite(){ m_pRootAtom->BeginWrite();}void MP4File::FinishWrite(){ // for all tracks, flush chunking buffers for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { ASSERT(m_pTracks[i]); m_pTracks[i]->FinishWrite(); } // ask root atom to write m_pRootAtom->FinishWrite(); // check if file shrunk, e.g. we deleted a track if (GetSize() < m_orgFileSize) { // just use a free atom to mark unused space // MP4Optimize() should be used to clean up this space MP4Atom* pFreeAtom = MP4Atom::CreateAtom("free"); ASSERT(pFreeAtom); pFreeAtom->SetFile(this); int64_t size = m_orgFileSize - (m_fileSize + 8); if (size < 0) size = 0; pFreeAtom->SetSize(size); pFreeAtom->Write(); delete pFreeAtom; }}void MP4File::UpdateDuration(MP4Duration duration){ MP4Duration currentDuration = GetDuration(); if (duration > currentDuration) { SetDuration(duration); }}void MP4File::Dump(FILE* pDumpFile, bool dumpImplicits){ if (pDumpFile == NULL) { pDumpFile = stdout; } fprintf(pDumpFile, "Dumping %s meta-information...\n", m_fileName); m_pRootAtom->Dump(pDumpFile, 0, dumpImplicits);}void MP4File::Close(){ if (m_mode == 'w') { SetIntegerProperty("moov.mvhd.modificationTime", MP4GetAbsTimestamp()); FinishWrite(); } m_virtual_IO->Close(m_pFile); m_pFile = NULL;}const char* MP4File::TempFileName(){ // there are so many attempts in libc to get this right // that for portablity reasons, it's best just to roll our own#ifndef _WIN32 u_int32_t i; for (i = getpid(); i < 0xFFFFFFFF; i++) { snprintf(m_tempFileName, sizeof(m_tempFileName), "./tmp%u.mp4", i); if (access(m_tempFileName, F_OK) != 0) { break; } } if (i == 0xFFFFFFFF) { throw new MP4Error("can't create temporary file", "TempFileName"); }#else GetTempFileNameA(".", // dir. for temp. files "mp4", // temp. filename prefix 0, // create unique name m_tempFileName); // buffer for name #endif return (char *)m_tempFileName;}void MP4File::Rename(const char* oldFileName, const char* newFileName){ int rc;#ifdef _WIN32 rc = remove(newFileName); if (rc == 0) { rc = rename(oldFileName, newFileName); }#else rc = rename(oldFileName, newFileName);#endif if (rc != 0) { throw new MP4Error(errno, "can't overwrite existing file", "Rename"); }}void MP4File::ProtectWriteOperation(char* where){ if (m_mode == 'r') { throw new MP4Error("operation not permitted in read mode", where); }}MP4Track* MP4File::GetTrack(MP4TrackId trackId){ return m_pTracks[FindTrackIndex(trackId)];}MP4Atom* MP4File::FindAtom(const char* name){ MP4Atom* pAtom = NULL; if (!name || !strcmp(name, "")) { pAtom = m_pRootAtom; } else { pAtom = m_pRootAtom->FindAtom(name); } return pAtom;}MP4Atom* MP4File::AddChildAtom( const char* parentName, const char* childName){ return AddChildAtom(FindAtom(parentName), childName);}MP4Atom* MP4File::AddChildAtom( MP4Atom* pParentAtom, const char* childName){ return InsertChildAtom(pParentAtom, childName, pParentAtom->GetNumberOfChildAtoms());}MP4Atom* MP4File::InsertChildAtom( const char* parentName, const char* childName, u_int32_t index){ return InsertChildAtom(FindAtom(parentName), childName, index); }MP4Atom* MP4File::InsertChildAtom( MP4Atom* pParentAtom, const char* childName, u_int32_t index){ MP4Atom* pChildAtom = MP4Atom::CreateAtom(childName); ASSERT(pParentAtom); pParentAtom->InsertChildAtom(pChildAtom, index); pChildAtom->Generate(); return pChildAtom;}MP4Atom* MP4File::AddDescendantAtoms( const char* ancestorName, const char* descendantNames){ return AddDescendantAtoms(FindAtom(ancestorName), descendantNames);}MP4Atom* MP4File::AddDescendantAtoms( MP4Atom* pAncestorAtom, const char* descendantNames){ ASSERT(pAncestorAtom); MP4Atom* pParentAtom = pAncestorAtom; MP4Atom* pChildAtom = NULL; while (true) { char* childName = MP4NameFirst(descendantNames); if (childName == NULL) { break; } descendantNames = MP4NameAfterFirst(descendantNames); pChildAtom = pParentAtom->FindChildAtom(childName); if (pChildAtom == NULL) { pChildAtom = AddChildAtom(pParentAtom, childName); } pParentAtom = pChildAtom; MP4Free(childName); } return pChildAtom;}bool MP4File::FindProperty(const char* name, MP4Property** ppProperty, u_int32_t* pIndex){ if (pIndex) { *pIndex = 0; // set the default answer for index } return m_pRootAtom->FindProperty(name, ppProperty, pIndex);}void MP4File::FindIntegerProperty(const char* name, MP4Property** ppProperty, u_int32_t* pIndex){ if (!FindProperty(name, ppProperty, pIndex)) { throw new MP4Error("no such property - %s", "MP4File::FindIntegerProperty", name); } switch ((*ppProperty)->GetType()) { case Integer8Property: case Integer16Property: case Integer24Property: case Integer32Property: case Integer64Property: break; default: throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindIntegerProperty", name, (*ppProperty)->GetType()); }}u_int64_t MP4File::GetIntegerProperty(const char* name){ MP4Property* pProperty; u_int32_t index; FindIntegerProperty(name, &pProperty, &index); return ((MP4IntegerProperty*)pProperty)->GetValue(index);}void MP4File::SetIntegerProperty(const char* name, u_int64_t value){ ProtectWriteOperation("SetIntegerProperty"); MP4Property* pProperty = NULL; u_int32_t index = 0; FindIntegerProperty(name, &pProperty, &index); ((MP4IntegerProperty*)pProperty)->SetValue(value, index);}void MP4File::FindFloatProperty(const char* name, MP4Property** ppProperty, u_int32_t* pIndex){ if (!FindProperty(name, ppProperty, pIndex)) { throw new MP4Error("no such property - %s", "MP4File::FindFloatProperty", name); } if ((*ppProperty)->GetType() != Float32Property) { throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindFloatProperty", name, (*ppProperty)->GetType()); }}float MP4File::GetFloatProperty(const char* name){ MP4Property* pProperty; u_int32_t index; FindFloatProperty(name, &pProperty, &index); return ((MP4Float32Property*)pProperty)->GetValue(index);}void MP4File::SetFloatProperty(const char* name, float value){ ProtectWriteOperation("SetFloatProperty"); MP4Property* pProperty; u_int32_t index; FindFloatProperty(name, &pProperty, &index); ((MP4Float32Property*)pProperty)->SetValue(value, index);}void MP4File::FindStringProperty(const char* name, MP4Property** ppProperty, u_int32_t* pIndex){ if (!FindProperty(name, ppProperty, pIndex)) { throw new MP4Error("no such property - %s", "MP4File::FindStringProperty", name); } if ((*ppProperty)->GetType() != StringProperty) { throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindStringProperty", name, (*ppProperty)->GetType()); }}const char* MP4File::GetStringProperty(const char* name){ MP4Property* pProperty; u_int32_t index; FindStringProperty(name, &pProperty, &index); return ((MP4StringProperty*)pProperty)->GetValue(index);}void MP4File::SetStringProperty(const char* name, const char* value){ ProtectWriteOperation("SetStringProperty"); MP4Property* pProperty; u_int32_t index; FindStringProperty(name, &pProperty, &index); ((MP4StringProperty*)pProperty)->SetValue(value, index);}void MP4File::FindBytesProperty(const char* name, MP4Property** ppProperty, u_int32_t* pIndex){ if (!FindProperty(name, ppProperty, pIndex)) { throw new MP4Error("no such property %s", "MP4File::FindBytesProperty", name); } if ((*ppProperty)->GetType() != BytesProperty) { throw new MP4Error("type mismatch - property %s - type %d", "MP4File::FindBytesProperty", name, (*ppProperty)->GetType()); }}void MP4File::GetBytesProperty(const char* name, u_int8_t** ppValue, u_int32_t* pValueSize){ MP4Property* pProperty; u_int32_t index; FindBytesProperty(name, &pProperty, &index); ((MP4BytesProperty*)pProperty)->GetValue(ppValue, pValueSize, index);}void MP4File::SetBytesProperty(const char* name, const u_int8_t* pValue, u_int32_t valueSize){ ProtectWriteOperation("SetBytesProperty"); MP4Property* pProperty; u_int32_t index; FindBytesProperty(name, &pProperty, &index); ((MP4BytesProperty*)pProperty)->SetValue(pValue, valueSize, index);}// track functionsMP4TrackId MP4File::AddTrack(const char* type, u_int32_t timeScale){ ProtectWriteOperation("AddTrack"); // create and add new trak atom MP4Atom* pTrakAtom = AddChildAtom("moov", "trak"); // allocate a new track id MP4TrackId trackId = AllocTrackId(); m_trakIds.Add(trackId); // set track id MP4Integer32Property* pInteger32Property = NULL; (void)pTrakAtom->FindProperty("trak.tkhd.trackId", (MP4Property**)&pInteger32Property); ASSERT(pInteger32Property); pInteger32Property->SetValue(trackId); // set track type const char* normType = MP4NormalizeTrackType(type, m_verbosity); // sanity check for user defined types if (strlen(normType) > 4) { VERBOSE_WARNING(m_verbosity, printf("AddTrack: type truncated to four characters\n")); // StringProperty::SetValue() will do the actual truncation } MP4StringProperty* pStringProperty = NULL; (void)pTrakAtom->FindProperty("trak.mdia.hdlr.handlerType", (MP4Property**)&pStringProperty);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -