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

📄 mp4file.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
📖 第 1 页 / 共 4 页
字号:
}

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)
{
	MP4DescriptorProperty* pDescriptorProperty = NULL;
	m_pRootAtom->FindProperty("moov.iods.esIds",
		(MP4Property**)&pDescriptorProperty);
	ASSERT(pDescriptorProperty);

	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)
{
	char propName[1024];

	snprintf(propName, sizeof(propName), "%s.%s", trefName, "entryCount");
	m_pRootAtom->FindProperty(propName, ppCountProperty);
	ASSERT(*ppCountProperty);

	snprintf(propName, sizeof(propName), "%s.%s", trefName, "entries.trackId");
	m_pRootAtom->FindProperty(propName, ppTrackIdProperty);
	ASSERT(*ppTrackIdProperty);
}

void MP4File::AddTrackReference(const char* trefName, MP4TrackId refTrackId)
{
	MP4Integer32Property* pCountProperty = NULL;
	MP4Integer32Property* pTrackIdProperty = NULL;

	GetTrackReferenceProperties(trefName,
		(MP4Property**)&pCountProperty, 
		(MP4Property**)&pTrackIdProperty);

	pTrackIdProperty->AddValue(refTrackId);
	pCountProperty->IncrementValue();
}

u_int32_t MP4File::FindTrackReference(const char* trefName, 
	MP4TrackId refTrackId)
{
	MP4Integer32Property* pCountProperty = NULL;
	MP4Integer32Property* pTrackIdProperty = NULL;

	GetTrackReferenceProperties(trefName, 
		(MP4Property**)&pCountProperty, 
		(MP4Property**)&pTrackIdProperty);

	for (u_int32_t i = 0; i < pCountProperty->GetValue(); i++) {
		if (refTrackId == pTrackIdProperty->GetValue(i)) {
			return i + 1;	// N.B. 1 not 0 based index
		}
	}
	return 0;
}

void MP4File::RemoveTrackReference(const char* trefName, MP4TrackId refTrackId)
{
	MP4Integer32Property* pCountProperty = NULL;
	MP4Integer32Property* pTrackIdProperty = NULL;

	GetTrackReferenceProperties(trefName,
		(MP4Property**)&pCountProperty, 
		(MP4Property**)&pTrackIdProperty);

	for (u_int32_t i = 0; i < pCountProperty->GetValue(); i++) {
		if (refTrackId == pTrackIdProperty->GetValue(i)) {
			pTrackIdProperty->DeleteValue(i);
			pCountProperty->IncrementValue(-1);
		}
	}
}

void MP4File::AddDataReference(MP4TrackId trackId, const char* url)
{
	MP4Atom* pDrefAtom = 
		FindAtom(MakeTrackName(trackId, "mdia.minf.dinf.dref"));
	ASSERT(pDrefAtom);

	MP4Integer32Property* pCountProperty = NULL;
	pDrefAtom->FindProperty("dref.entryCount", 
		(MP4Property**)&pCountProperty);
	ASSERT(pCountProperty);
	pCountProperty->IncrementValue();

	MP4Atom* pUrlAtom = AddChildAtom(pDrefAtom, "url ");

	if (url && url[0] != '\0') {
		pUrlAtom->SetFlags(pUrlAtom->GetFlags() & 0xFFFFFE);

		MP4StringProperty* pUrlProperty = NULL;
		pUrlAtom->FindProperty("url .location",
			(MP4Property**)&pUrlProperty);
		ASSERT(pUrlProperty);
		pUrlProperty->SetValue(url);
	} else {
		pUrlAtom->SetFlags(pUrlAtom->GetFlags() | 1);
	}
}

MP4TrackId MP4File::AddSystemsTrack(const char* type)
{
	const char* normType = MP4Track::NormalizeTrackType(type); 

	// TBD if user type, fix name to four chars, and warn

	MP4TrackId trackId = AddTrack(type, MP4_MSECS_TIME_SCALE);

	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0);

	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4s");

	// 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 mp4s atom
	MP4Integer32Property* pStsdCountProperty;
	FindIntegerProperty(
		MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
		(MP4Property**)&pStsdCountProperty);
	pStsdCountProperty->IncrementValue();

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4s.esds.ESID", trackId);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId", 
		MP4SystemsV1ObjectType);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.streamType", 
		ConvertTrackTypeToStreamType(normType));

	return trackId;
}

MP4TrackId MP4File::AddODTrack()
{
	// until a demonstrated need emerges
	// we limit ourselves to one object description track
	if (m_odTrackId != MP4_INVALID_TRACK_ID) {
		throw new MP4Error("object description track already exists",
			"AddObjectDescriptionTrack");
	}

	m_odTrackId = AddSystemsTrack(MP4_OD_TRACK_TYPE);

	AddTrackToIod(m_odTrackId);

	AddDescendantAtoms(MakeTrackName(m_odTrackId, NULL), "tref.mpod");

	return m_odTrackId;
}

MP4TrackId MP4File::AddSceneTrack()
{
	MP4TrackId trackId = AddSystemsTrack(MP4_SCENE_TRACK_TYPE);

	AddTrackToIod(trackId);
	AddTrackToOd(trackId);

	return trackId;
}

MP4TrackId MP4File::AddAudioTrack(
	u_int32_t timeScale, 
	MP4Duration sampleDuration, 
	u_int8_t audioType)
{
	MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale);

	AddTrackToOd(trackId);

	SetTrackFloatProperty(trackId, "tkhd.volume", 1.0);

	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);

	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4a");

	// 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 mp4a atom
	MP4Integer32Property* pStsdCountProperty;
	FindIntegerProperty(
		MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
		(MP4Property**)&pStsdCountProperty);
	pStsdCountProperty->IncrementValue();

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4a.timeScale", timeScale);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4a.esds.ESID", trackId);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId", 
		audioType);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.streamType", 
		MP4AudioStreamType);

	m_pTracks[FindTrackIndex(trackId)]->
		SetFixedSampleDuration(sampleDuration);

	return trackId;
}

⌨️ 快捷键说明

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