📄 mp4file.cpp
字号:
#ifdef O_LARGEFILE // UGH! fopen doesn't open a file in 64-bit mode, period. // So we need to use open() and then fdopen() int fd; int flags = O_LARGEFILE; if (strchr(fmode, '+')) { flags |= O_CREAT | O_RDWR; if (fmode[0] == 'w') { flags |= O_TRUNC; } } else { if (fmode[0] == 'w') { flags |= O_CREAT | O_TRUNC | O_WRONLY; } else { flags |= O_RDONLY; } } fd = open(m_fileName, flags, 0666); if (fd >= 0) { m_pFile = fdopen(fd, fmode); }#else m_pFile = fopen(m_fileName, fmode);#endif if (m_pFile == NULL) {#ifdef SIMON_CHANGED printf("\n[%s] %s", "MP4Open", "failed"); RaiseException(1, 0, 0, NULL);#else throw new MP4Error(errno, "failed", "MP4Open");#endif } if (m_mode == 'r') {#ifdef SIMON_CHANGED // Simon Chun fseek(m_pFile, 0L, SEEK_END); m_orgFileSize = m_fileSize = ftell(m_pFile); fseek(m_pFile, 0L, SEEK_SET);#else struct stat s; if (fstat(fileno(m_pFile), &s) < 0) { throw new MP4Error(errno, "stat failed", "MP4Open"); } m_orgFileSize = m_fileSize = s.st_size;#endif } else { m_orgFileSize = m_fileSize = 0; }}#ifdef _WIN32void MP4File::Open(const wchar_t* fmode){ ASSERT(m_pFile == NULL);#ifdef O_LARGEFILE // UGH! fopen doesn't open a file in 64-bit mode, period. // So we need to use open() and then fdopen() int fd; int flags = O_LARGEFILE; if (strchr(fmode, '+')) { flags |= O_CREAT | O_RDWR; if (fmode[0] == 'w') { flags |= O_TRUNC; } } else { if (fmode[0] == 'w') { flags |= O_CREAT | O_TRUNC | O_WRONLY; } else { flags |= O_RDONLY; } } fd = _wopen(m_fileName_w, flags, 0666); if (fd >= 0) { m_pFile = _wfdopen(fd, fmode); }#else m_pFile = _wfopen(m_fileName_w, fmode);#endif if (m_pFile == NULL) {#ifdef SIMON_CHANGED printf("\n[%s] %s", "MP4Open", "failed"); RaiseException(1, 0, 0, NULL);#else throw new MP4Error(errno, "failed", "MP4Open");#endif } if (m_mode == 'r') {#ifdef SIMON_CHANGED // Simon Chun fseek(m_pFile, 0L, SEEK_END); m_orgFileSize = m_fileSize = ftell(m_pFile); fseek(m_pFile, 0L, SEEK_SET);#else struct stat s; if (fstat(fileno(m_pFile), &s) < 0) { throw new MP4Error(errno, "stat failed", "MP4Open"); } m_orgFileSize = m_fileSize = s.st_size;#endif } 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; pTrakAtom->FindProperty( "trak.tkhd.trackId", (MP4Property**)&pTrackIdProperty); // find track type property MP4StringProperty* pTypeProperty = NULL; 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); } __except (EXCEPTION_EXECUTE_HANDLER) {// 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; }}MP4Duration MP4File::UpdateDuration(MP4Duration duration){ MP4Duration currentDuration = GetDuration(); if (duration > currentDuration) { SetDuration(duration); return duration; } return currentDuration;}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(); } fclose(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#ifdef SIMON_CHANGED wchar_t tmpfile_wchar[256]; GetTempFileName(L".", // dir. for temp. files L"mp4", // temp. filename prefix 0, // create unique name tmpfile_wchar); // buffer for name wchar_t2char(tmpfile_wchar, m_tempFileName);#else#ifndef _WIN32 u_int32_t i; for (i = getpid(); i < 0xFFFFFFFF; i++) { sprintf(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 GetTempFileName(".", // dir. for temp. files "mp4", // temp. filename prefix 0, // create unique name m_tempFileName); // buffer for name #endif#endif /* SIMON_CHANGED */ return m_tempFileName;}void MP4File::Rename(const char* oldFileName, const char* newFileName){ int rc;#ifdef SIMON_CHANGED wchar_t old_wchar[256], new_wchar[256]; char2wchar_t(newFileName, new_wchar); char2wchar_t(oldFileName, old_wchar); DeleteFile(new_wchar); if (MoveFile(old_wchar, new_wchar)) rc = 0; else rc = 1;#else#ifdef _WIN32 rc = remove(newFileName); if (rc == 0) { rc = rename(oldFileName, newFileName); }#else rc = rename(oldFileName, newFileName);#endif#endif /* SIMON_CHANGED */ if (rc != 0) {// throw new MP4Error(errno, "can't overwrite existing file", "Rename"); RaiseException(1, 0, 0, NULL); }}void MP4File::ProtectWriteOperation(char* where){ if (m_mode == 'r') {// throw new MP4Error("operation not permitted in read mode", where); RaiseException(1, 0, 0, NULL); }}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)) {#ifdef SIMON_CHANGED printf("\n[%s] %s - %s", "MP4File::FindIntegerProperty", "no such property", name); RaiseException(1, 0, 0, NULL);#else throw new MP4Error("no such property - %s", "MP4File::FindIntegerProperty", name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -