mp4file.cpp

来自「faac-1.25.rar音频编解码器demo」· C++ 代码 · 共 2,476 行 · 第 1/5 页

CPP
2,476
字号
	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
#ifndef _WIN32
	static char tempFileName[64];
	u_int32_t i;
	for (i = getpid(); i < 0xFFFFFFFF; i++) {
		sprintf(tempFileName, "./tmp%u.mp4", i);
		if (access(tempFileName, F_OK) != 0) {
			break;
		}
	}
	if (i == 0xFFFFFFFF) {
		throw new MP4Error("can't create temporary file", "TempFileName");
	}
#else
	static char tempFileName[MAX_PATH + 3];
	GetTempFileName(".", // dir. for temp. files 
					"mp4",                // temp. filename prefix 
					0,                    // create unique name 
					tempFileName);        // buffer for name 
#endif

	return 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 functions

MP4TrackId 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;
	pTrakAtom->FindProperty(
		"trak.tkhd.trackId", (MP4Property**)&pInteger32Property);
	ASSERT(pInteger32Property);
	pInteger32Property->SetValue(trackId);

	// set track type
	const char* normType = MP4Track::NormalizeTrackType(type);

	// 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;
	pTrakAtom->FindProperty(
		"trak.mdia.hdlr.handlerType", (MP4Property**)&pStringProperty);
	ASSERT(pStringProperty);
	pStringProperty->SetValue(normType);

	// set track time scale
	pInteger32Property = NULL;
	pTrakAtom->FindProperty(
		"trak.mdia.mdhd.timeScale", (MP4Property**)&pInteger32Property);
	ASSERT(pInteger32Property);
	pInteger32Property->SetValue(timeScale ? timeScale : 1000);

	// now have enough to create MP4Track object
	MP4Track* pTrack = NULL;
	if (!strcmp(normType, MP4_HINT_TRACK_TYPE)) {
	  pTrack = new MP4RtpHintTrack(this, pTrakAtom);
	} else {
	  pTrack = new MP4Track(this, pTrakAtom);
	}
	m_pTracks.Add(pTrack);

	// mark non-hint tracks as enabled
	if (strcmp(normType, MP4_HINT_TRACK_TYPE)) {
	  SetTrackIntegerProperty(trackId, "tkhd.flags", 1);
	}

	// mark track as contained in this file
	// LATER will provide option for external data references
	AddDataReference(trackId, NULL);

	return trackId;
}

void MP4File::AddTrackToIod(MP4TrackId trackId)
{
	MP4DescriptorProperty* pDescriptorProperty = NULL;
	m_pRootAtom->FindProperty("moov.iods.esIds", 
		(MP4Property**)&pDescriptorProperty);
	ASSERT(pDescriptorProperty);

	MP4Descriptor* pDescriptor = 
		pDescriptorProperty->AddDescriptor(MP4ESIDIncDescrTag);
	ASSERT(pDescriptor);

	MP4Integer32Property* pIdProperty = NULL;
	pDescriptor->FindProperty("id", 
		(MP4Property**)&pIdProperty);
	ASSERT(pIdProperty);

	pIdProperty->SetValue(trackId);
}

 void MP4File::RemoveTrackFromIod(MP4TrackId trackId, bool shallHaveIods)
{
	MP4DescriptorProperty* pDescriptorProperty = NULL;
	m_pRootAtom->FindProperty("moov.iods.esIds",
		(MP4Property**)&pDescriptorProperty);

	if (shallHaveIods) {
		ASSERT(pDescriptorProperty);
	} else {
		if (!pDescriptorProperty) {
			return;
		}
	}

	for (u_int32_t i = 0; i < pDescriptorProperty->GetCount(); i++) {
		static char name[32];
		snprintf(name, sizeof(name), "esIds[%u].id", i);

		MP4Integer32Property* pIdProperty = NULL;
		pDescriptorProperty->FindProperty(name, 
			(MP4Property**)&pIdProperty);
		ASSERT(pIdProperty);

		if (pIdProperty->GetValue() == trackId) {
			pDescriptorProperty->DeleteDescriptor(i);
			break;
		}
	}
}

void MP4File::AddTrackToOd(MP4TrackId trackId)
{
	if (!m_odTrackId) {
		return;
	}

	AddTrackReference(MakeTrackName(m_odTrackId, "tref.mpod"), trackId);
}

void MP4File::RemoveTrackFromOd(MP4TrackId trackId)
{
	if (!m_odTrackId) {
		return;
	}

	RemoveTrackReference(MakeTrackName(m_odTrackId, "tref.mpod"), trackId);
}

void MP4File::GetTrackReferenceProperties(const char* trefName,
	MP4Property** ppCountProperty, MP4Property** ppTrackIdProperty)

⌨️ 快捷键说明

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