⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4file.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2001 - 2005.  All Rights Reserved. *  * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, * and was contributed by Ximpo Group Ltd. * * Portions created by Ximpo Group Ltd. are * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved. * * Contributor(s):  *		Dave Mackie		  dmackie@cisco.com *              Alix Marchandise-Franquet alix@cisco.com *              Ximpo Group Ltd.          mp4v2@ximpo.com *              Bill May                  wmay@cisco.com */#include "mp4common.h"MP4File::MP4File(u_int32_t verbosity){	m_fileName = NULL;	#ifdef _WIN32	m_fileName_w = NULL;	#endif	m_pFile = NULL;	m_virtual_IO = NULL;	m_orgFileSize = 0;	m_fileSize = 0;	m_pRootAtom = NULL;	m_odTrackId = MP4_INVALID_TRACK_ID;	m_verbosity = verbosity;	m_mode = 0;	m_createFlags = 0;	m_useIsma = false;	m_pModificationProperty = NULL;	m_pTimeScaleProperty = NULL;	m_pDurationProperty = NULL;	m_memoryBuffer = NULL;	m_memoryBufferSize = 0;	m_memoryBufferPosition = 0;	m_numReadBits = 0;	m_bufReadBits = 0;	m_numWriteBits = 0;	m_bufWriteBits = 0;	m_editName = NULL;#ifndef _WIN32	m_tempFileName[0] = '\0';#endif	m_trakName[0] = '\0';}MP4File::~MP4File(){	MP4Free(m_fileName);	#ifdef _WIN32	MP4Free(m_fileName_w);	#endif	if (m_pFile != NULL) {	  // not closed ?	  m_virtual_IO->Close(m_pFile);	  m_pFile = NULL;	}	delete m_pRootAtom;	for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {		delete m_pTracks[i];	}	MP4Free(m_memoryBuffer);	// just in case	CHECK_AND_FREE(m_editName);	}void MP4File::Read(const char* fileName){	m_fileName = MP4Stralloc(fileName);	m_mode = 'r';	Open("rb");	ReadFromFile();	CacheProperties();}#ifdef _WIN32void MP4File::Read(const wchar_t* fileName){	m_fileName_w = MP4Stralloc(fileName);	m_mode = 'r';	Open(L"rb");	ReadFromFile();	CacheProperties();}#endif// benski>void MP4File::ReadEx(const char *fileName, void *user, Virtual_IO *virtual_IO){	m_fileName = MP4Stralloc(fileName);	m_mode = 'r'; 	m_pFile = user;	m_virtual_IO = virtual_IO;	ASSERT(m_pFile);	ASSERT(m_virtual_IO)		m_orgFileSize = m_fileSize = m_virtual_IO->GetFileLength(m_pFile); 	ReadFromFile();	CacheProperties();}void MP4File::Create(const char* fileName, u_int32_t flags, 		     int add_ftyp, int add_iods, 		     char* majorBrand, u_int32_t minorVersion, 		     char** supportedBrands, u_int32_t supportedBrandsCount){	m_fileName = MP4Stralloc(fileName);	m_mode = 'w';	m_createFlags = flags;	Open("wb+");	// generate a skeletal atom tree	m_pRootAtom = MP4Atom::CreateAtom(NULL);	m_pRootAtom->SetFile(this);	m_pRootAtom->Generate();	if (add_ftyp != 0) {	  MakeFtypAtom(majorBrand, minorVersion, 		       supportedBrands, supportedBrandsCount);	}	CacheProperties();	// create mdat, and insert it after ftyp, and before moov	(void)InsertChildAtom(m_pRootAtom, "mdat", 			      add_ftyp != 0 ? 1 : 0);	// start writing	m_pRootAtom->BeginWrite();	if (add_iods != 0) {	  (void)AddChildAtom("moov", "iods");	}}bool MP4File::Use64Bits (const char *atomName){  uint32_t atomid = ATOMID(atomName);  if (atomid == ATOMID("mdat") || atomid == ATOMID("stbl")) {    return (m_createFlags & MP4_CREATE_64BIT_DATA) == MP4_CREATE_64BIT_DATA;  }   if (atomid == ATOMID("mvhd") ||      atomid == ATOMID("tkhd") ||      atomid == ATOMID("mdhd")) {    return (m_createFlags & MP4_CREATE_64BIT_TIME) == MP4_CREATE_64BIT_TIME;  }  return false;}void MP4File::Check64BitStatus (const char *atomName){  uint32_t atomid = ATOMID(atomName);  if (atomid == ATOMID("mdat") || atomid == ATOMID("stbl")) {    m_createFlags |= MP4_CREATE_64BIT_DATA;  } else if (atomid == ATOMID("mvhd") ||	     atomid == ATOMID("tkhd") ||	     atomid == ATOMID("mdhd")) {    m_createFlags |= MP4_CREATE_64BIT_TIME;  }}    bool MP4File::Modify(const char* fileName){	m_fileName = MP4Stralloc(fileName);	m_mode = 'r';	Open("rb+");	ReadFromFile();	m_mode = 'w';	// find the moov atom	MP4Atom* pMoovAtom = m_pRootAtom->FindAtom("moov");	u_int32_t numAtoms;	if (pMoovAtom == NULL) {		// there isn't one, odd but we can still proceed	  return false;	  //pMoovAtom = AddChildAtom(m_pRootAtom, "moov");	} else {		numAtoms = m_pRootAtom->GetNumberOfChildAtoms();		// work backwards thru the top level atoms		int32_t i;		bool lastAtomIsMoov = true;		MP4Atom* pLastAtom = NULL;		for (i = numAtoms - 1; i >= 0; i--) {			MP4Atom* pAtom = m_pRootAtom->GetChildAtom(i);			const char* type = pAtom->GetType();						// get rid of any trailing free or skips			if (!strcmp(type, "free") || !strcmp(type, "skip")) {				m_pRootAtom->DeleteChildAtom(pAtom);				continue;			}			if (strcmp(type, "moov")) {				if (pLastAtom == NULL) {					pLastAtom = pAtom;					lastAtomIsMoov = false;				}				continue;			}			// now at moov atom			// multiple moov atoms?!?			if (pAtom != pMoovAtom) {				throw new MP4Error(					"Badly formed mp4 file, multiple moov atoms", 					"MP4Modify");			}			if (lastAtomIsMoov) {				// position to start of moov atom,				// effectively truncating file 				// prior to adding new mdat				SetPosition(pMoovAtom->GetStart());			} else { // last atom isn't moov				// need to place a free atom 				MP4Atom* pFreeAtom = MP4Atom::CreateAtom("free");				// in existing position of the moov atom				m_pRootAtom->InsertChildAtom(pFreeAtom, i);				m_pRootAtom->DeleteChildAtom(pMoovAtom);				m_pRootAtom->AddChildAtom(pMoovAtom);				// write free atom to disk				SetPosition(pMoovAtom->GetStart());				pFreeAtom->SetSize(pMoovAtom->GetSize());				pFreeAtom->Write();				// finally set our file position to the end of the last atom				SetPosition(pLastAtom->GetEnd());			}			break;		}		ASSERT(i != -1);	}	CacheProperties();	// of moov atom	numAtoms = m_pRootAtom->GetNumberOfChildAtoms();	// insert another mdat prior to moov atom (the last atom)	MP4Atom* pMdatAtom = InsertChildAtom(m_pRootAtom, "mdat", numAtoms - 1);	// start writing new mdat	pMdatAtom->BeginWrite(Use64Bits("mdat"));	return true;}void MP4File::Optimize(const char* orgFileName, const char* newFileName){	m_fileName = MP4Stralloc(orgFileName);	m_mode = 'r';	// first load meta-info into memory	Open("rb");	ReadFromFile();	CacheProperties();	// of moov atom	// now switch over to writing the new file	MP4Free(m_fileName);	#ifdef _WIN32	MP4Free(m_fileName_w);	#endif	// create a temporary file if necessary	if (newFileName == NULL) {		m_fileName = MP4Stralloc(TempFileName());	} else {		m_fileName = MP4Stralloc(newFileName);	}	void* pReadFile = m_pFile;	Virtual_IO *pReadIO = m_virtual_IO;	m_pFile = NULL;	m_mode = 'w';	Open("wb");	SetIntegerProperty("moov.mvhd.modificationTime", 		MP4GetAbsTimestamp());	// writing meta info in the optimal order	((MP4RootAtom*)m_pRootAtom)->BeginOptimalWrite();	// write data in optimal order	RewriteMdat(pReadFile, m_pFile, pReadIO, m_virtual_IO);	// finish writing	((MP4RootAtom*)m_pRootAtom)->FinishOptimalWrite();	// cleanup	m_virtual_IO->Close(m_pFile);	m_pFile = NULL;	pReadIO->Close(pReadFile);	// move temporary file into place	if (newFileName == NULL) {		Rename(m_fileName, orgFileName);	}}void MP4File::RewriteMdat(void* pReadFile, void* pWriteFile,			  Virtual_IO *readIO, Virtual_IO *writeIO){	u_int32_t numTracks = m_pTracks.Size();	MP4ChunkId* chunkIds = new MP4ChunkId[numTracks];	MP4ChunkId* maxChunkIds = new MP4ChunkId[numTracks];	MP4Timestamp* nextChunkTimes = new MP4Timestamp[numTracks];	for (u_int32_t i = 0; i < numTracks; i++) {		chunkIds[i] = 1;		maxChunkIds[i] = m_pTracks[i]->GetNumberOfChunks();		nextChunkTimes[i] = MP4_INVALID_TIMESTAMP;	}	while (true) {		u_int32_t nextTrackIndex = (u_int32_t)-1;		MP4Timestamp nextTime = MP4_INVALID_TIMESTAMP;		for (u_int32_t i = 0; i < numTracks; i++) {			if (chunkIds[i] > maxChunkIds[i]) {				continue;			}			if (nextChunkTimes[i] == MP4_INVALID_TIMESTAMP) {				MP4Timestamp chunkTime =					m_pTracks[i]->GetChunkTime(chunkIds[i]);				nextChunkTimes[i] = MP4ConvertTime(chunkTime,					m_pTracks[i]->GetTimeScale(), GetTimeScale());			}			// time is not earliest so far			if (nextChunkTimes[i] > nextTime) {				continue;			}			// prefer hint tracks to media tracks if times are equal			if (nextChunkTimes[i] == nextTime 			  && strcmp(m_pTracks[i]->GetType(), MP4_HINT_TRACK_TYPE)) {				continue;			}			// this is our current choice of tracks			nextTime = nextChunkTimes[i];			nextTrackIndex = i;		}		if (nextTrackIndex == (u_int32_t)-1) {			break;		}		// point into original mp4 file for read chunk call		m_pFile = pReadFile;		m_virtual_IO = readIO;		m_mode = 'r';		u_int8_t* pChunk;		u_int32_t chunkSize;		m_pTracks[nextTrackIndex]->			ReadChunk(chunkIds[nextTrackIndex], &pChunk, &chunkSize);		// point back at the new mp4 file for write chunk		m_pFile = pWriteFile;		m_virtual_IO = writeIO;		m_mode = 'w';		m_pTracks[nextTrackIndex]->			RewriteChunk(chunkIds[nextTrackIndex], pChunk, chunkSize);		MP4Free(pChunk);		chunkIds[nextTrackIndex]++;		nextChunkTimes[nextTrackIndex] = MP4_INVALID_TIMESTAMP;	}	delete [] chunkIds;	delete [] maxChunkIds;	delete [] nextChunkTimes;}void MP4File::Open(const char* fmode){	ASSERT(m_pFile == NULL);	FILE *openFile = 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 = open(m_fileName, flags, 0666); 	if (fd >= 0) {		openFile = fdopen(fd, fmode);	}#else	openFile = fopen(m_fileName, fmode);#endif	m_pFile = openFile;	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;	}}#ifdef _WIN32void MP4File::Open(const wchar_t* fmode){	ASSERT(m_pFile == NULL);	FILE *openFile = 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) {		openFile = _wfdopen(fd, fmode);	}#else	openFile = _wfopen(m_fileName_w, fmode);#endif	m_pFile = openFile;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -