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

📄 mp4file.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
📖 第 1 页 / 共 4 页
字号:
MP4TrackId MP4File::AddVideoTrack(
	u_int32_t timeScale, 
	MP4Duration sampleDuration, 
	u_int16_t width, 
	u_int16_t height, 
	u_int8_t videoType)
{
	MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);

	AddTrackToOd(trackId);

	SetTrackFloatProperty(trackId, "tkhd.width", width);
	SetTrackFloatProperty(trackId, "tkhd.height", height);

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

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

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

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4v.width", width);
	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4v.height", height);

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

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId", 
		videoType);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.streamType", 
		MP4VisualStreamType);

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsz.sampleSize", sampleDuration);

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

	return trackId;
}

MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId)
{
	// validate reference track id
	FindTrackIndex(refTrackId);

	MP4TrackId trackId = 
		AddTrack(MP4_HINT_TRACK_TYPE, GetTrackTimeScale(refTrackId));

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

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

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

	SetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.rtp .tims.timeScale", 
		GetTrackTimeScale(trackId));

	AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint");

	AddTrackReference(MakeTrackName(trackId, "tref.hint"), refTrackId);

	AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp ");

	AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf");

	return trackId;
}

void MP4File::DeleteTrack(MP4TrackId trackId)
{
	ProtectWriteOperation("MP4DeleteTrack");

	u_int32_t trakIndex = FindTrakAtomIndex(trackId);
	u_int16_t trackIndex = FindTrackIndex(trackId);
	MP4Track* pTrack = m_pTracks[trackIndex];

	MP4Atom* pTrakAtom = pTrack->GetTrakAtom();
	ASSERT(pTrakAtom);

	MP4Atom* pMoovAtom = FindAtom("moov");
	ASSERT(pMoovAtom);

	RemoveTrackFromIod(trackId);
	RemoveTrackFromOd(trackId);

	if (trackId == m_odTrackId) {
		m_odTrackId = 0;
	}

	pMoovAtom->DeleteChildAtom(pTrakAtom);

	m_trakIds.Delete(trakIndex);

	m_pTracks.Delete(trackIndex);

	delete pTrack;
	delete pTrakAtom;
}

u_int32_t MP4File::GetNumberOfTracks(const char* type, u_int8_t subType)
{
	if (type == NULL) {
		return m_pTracks.Size();
	} 

	u_int16_t typeSeen = 0;
	const char* normType = MP4Track::NormalizeTrackType(type);

	for (u_int16_t i = 0; i < m_pTracks.Size(); i++) {
		if (!strcmp(normType, m_pTracks[i]->GetType())) {
			if (subType) {
				if (normType == MP4_AUDIO_TRACK_TYPE) {
					if (subType != GetTrackAudioType(m_pTracks[i]->GetId())) {
						continue;
					}
				} else if (normType == MP4_VIDEO_TRACK_TYPE) {
					if (subType != GetTrackVideoType(m_pTracks[i]->GetId())) {
						continue;
					}
				} 
				// else unknown subtype, ignore it
			}
			typeSeen++;
		}
	}
	return typeSeen;
}

MP4TrackId MP4File::AllocTrackId()
{
	MP4TrackId trackId = 
		GetIntegerProperty("moov.mvhd.nextTrackId");

	if (trackId <= 0xFFFF) {
		// check that nextTrackid is correct
		try {
			FindTrackIndex(trackId);
			// ERROR, this trackId is in use
		}
		catch (MP4Error* e) {
			// OK, this trackId is not in use, proceed
			delete e;
			SetIntegerProperty("moov.mvhd.nextTrackId", trackId + 1);
			return trackId;
		}
	}

	// we need to search for a track id
	for (trackId = 1; trackId <= 0xFFFF; trackId++) {
		try {
			FindTrackIndex(trackId);
			// KEEP LOOKING, this trackId is in use
		}
		catch (MP4Error* e) {
			// OK, this trackId is not in use, proceed
			delete e;
			return trackId;
		}
	}

	// extreme case where mp4 file has 2^16 tracks in it
	throw new MP4Error("too many exising tracks", "AddTrack");
	return MP4_INVALID_TRACK_ID;		// to keep MSVC happy
}

MP4TrackId MP4File::FindTrackId(
	u_int16_t trackIndex, const char* type, u_int8_t subType)
{
	if (type == NULL) {
		return m_pTracks[trackIndex]->GetId();
	} 

	u_int16_t typeSeen = 0;
	const char* normType = MP4Track::NormalizeTrackType(type);

	for (u_int16_t i = 0; i < m_pTracks.Size(); i++) {
		if (!strcmp(normType, m_pTracks[i]->GetType())) {
			if (subType) {
				if (normType == MP4_AUDIO_TRACK_TYPE) {
					if (subType != GetTrackAudioType(m_pTracks[i]->GetId())) {
						continue;
					}
				} else if (normType == MP4_VIDEO_TRACK_TYPE) {
					if (subType != GetTrackVideoType(m_pTracks[i]->GetId())) {
						continue;
					}
				} 
				// else unknown subtype, ignore it
			}

			if (trackIndex == typeSeen) {
				return m_pTracks[i]->GetId();
			}

			typeSeen++;
		}
	}

	throw new MP4Error("Track index doesn't exist - track %d type %s", 
			   "FindTrackId", 
			   trackIndex, type); 
	return MP4_INVALID_TRACK_ID; // satisfy MS compiler
}

u_int16_t MP4File::FindTrackIndex(MP4TrackId trackId)
{
	for (u_int16_t i = 0; i < m_pTracks.Size(); i++) {
		if (m_pTracks[i]->GetId() == trackId) {
			return i;
		}
	}
	
	throw new MP4Error("Track id %d doesn't exist", "FindTrackIndex", trackId); 
	return (u_int16_t)-1; // satisfy MS compiler
}

u_int16_t MP4File::FindTrakAtomIndex(MP4TrackId trackId)
{
	if (trackId) {
		for (u_int32_t i = 0; i < m_trakIds.Size(); i++) {
			if (m_trakIds[i] == trackId) {
				return i;
			}
		}
	}

	throw new MP4Error("Track id %d doesn't exist", "FindTrakAtomIndex",
			   trackId); 
	return (u_int16_t)-1; // satisfy MS compiler
}

u_int32_t MP4File::GetSampleSize(MP4TrackId trackId, MP4SampleId sampleId)
{
	return m_pTracks[FindTrackIndex(trackId)]->GetSampleSize(sampleId);
}

u_int32_t MP4File::GetTrackMaxSampleSize(MP4TrackId trackId)
{
	return m_pTracks[FindTrackIndex(trackId)]->GetMaxSampleSize();
}

MP4SampleId MP4File::GetSampleIdFromTime(MP4TrackId trackId, 
	MP4Timestamp when, bool wantSyncSample)
{
	return m_pTracks[FindTrackIndex(trackId)]->
		GetSampleIdFromTime(when, wantSyncSample);
}

MP4Timestamp MP4File::GetSampleTime(
	MP4TrackId trackId, MP4SampleId sampleId)
{
	MP4Timestamp timestamp;
	m_pTracks[FindTrackIndex(trackId)]->
		GetSampleTimes(sampleId, &timestamp, NULL);
	return timestamp;
}

MP4Duration MP4File::GetSampleDuration(
	MP4TrackId trackId, MP4SampleId sampleId)
{
	MP4Duration duration;
	m_pTracks[FindTrackIndex(trackId)]->
		GetSampleTimes(sampleId, NULL, &duration);
	return duration; 
}

MP4Duration MP4File::GetSampleRenderingOffset(
	MP4TrackId trackId, MP4SampleId sampleId)
{
	return m_pTracks[FindTrackIndex(trackId)]->
		GetSampleRenderingOffset(sampleId);
}

bool MP4File::GetSampleSync(MP4TrackId trackId, MP4SampleId sampleId)
{
	return m_pTracks[FindTrackIndex(trackId)]->IsSyncSample(sampleId);
}

void MP4File::ReadSample(MP4TrackId trackId, MP4SampleId sampleId,
		u_int8_t** ppBytes, u_int32_t* pNumBytes, 
		MP4Timestamp* pStartTime, MP4Duration* pDuration,
		MP4Duration* pRenderingOffset, bool* pIsSyncSample)
{
	m_pTracks[FindTrackIndex(trackId)]->
		ReadSample(sampleId, ppBytes, pNumBytes, 
			pStartTime, pDuration, pRenderingOffset, pIsSyncSample);
}

void MP4File::WriteSample(MP4TrackId trackId,
		u_int8_t* pBytes, u_int32_t numBytes,
		MP4Duration duration, MP4Duration renderingOffset, bool isSyncSample)
{
	ProtectWriteOperation("MP4WriteSample");

	m_pTracks[FindTrackIndex(trackId)]->
		WriteSample(pBytes, numBytes, duration, renderingOffset, isSyncSample);

	m_pModificationProperty->SetValue(MP4GetAbsTimestamp());
}

void MP4File::SetSampleRenderingOffset(MP4TrackId trackId, 
	MP4SampleId sampleId, MP4Duration renderingOffset)
{
	ProtectWriteOperation("MP4SetSampleRenderingOffset");

	m_pTracks[FindTrackIndex(trackId)]->
		SetSampleRenderingOffset(sampleId, renderingOffset);

	m_pModificationProperty->SetValue(MP4GetAbsTimestamp());
}

char* MP4File::MakeTrackName(MP4TrackId trackId, const char* name)
{
	u_int16_t trakIndex = FindTrakAtomIndex(trackId);

	static char trakName[1024];
	if (name == NULL || name[0] == '\0') {
		snprintf(trakName, sizeof(trakName), 
			"moov.trak[%u]", trakIndex);
	} else {
		snprintf(trakName, sizeof(trakName), 
			"moov.trak[%u].%s", trakIndex, name);
	}
	return trakName;
}

u_int64_t MP4File::GetTrackIntegerProperty(MP4TrackId trackId, const char* name)
{
	return GetIntegerProperty(MakeTrackName(trackId, name));
}

void MP4File::SetTrackIntegerProperty(MP4TrackId trackId, const char* name, 
	int64_t value)
{
	SetIntegerProperty(MakeTrackName(trackId, name), value);
}

float MP4File::GetTrackFloatProperty(MP4TrackId trackId, const char* name)
{
	return GetFloatProperty(MakeTrackName(trackId, name));
}

void MP4File::SetTrackFloatProperty(MP4TrackId trackId, const char* name, 
	float value)
{
	SetFloatProperty(MakeTrackName(trackId, name), value);
}

const char* MP4File::GetTrackStringProperty(MP4TrackId trackId, const char* name)
{
	return GetStringProperty(MakeTrackName(trackId, name));
}

void MP4File::SetTrackStringProperty(MP4TrackId trackId, const char* name,
	const char* value)
{
	SetStringProperty(MakeTrackName(trackId, name), value);
}

void MP4File::GetTrackBytesProperty(MP4TrackId trackId, const char* name, 
	u_int8_t** ppValue, u_int32_t* pValueSize)
{
	GetBytesProperty(MakeTrackName(trackId, name), ppValue, pValueSize);
}

void MP4File::SetTrackBytesProperty(MP4TrackId trackId, const char* name, 
	const u_int8_t* pValue, u_int32_t valueSize)
{
	SetBytesProperty(MakeTrackName(trackId, name), pValue, valueSize);
}


// file level convenience functions

MP4Duration MP4File::GetDuration()
{
	return m_pDurationProperty->GetValue();
}

void MP4File::SetDuration(MP4Duration value)
{
	m_pDurationProperty->SetValue(value);
}

u_int32_t MP4File::GetTimeScale()
{
	return m_pTimeScaleProperty->GetValue();
}

void MP4File::SetTimeScale(u_int32_t value)
{
	if (value == 0) {
		throw new MP4Error("invalid value", "SetTimeScale");
	}
	m_pTimeScaleProperty->SetValue(value);
}

u_int8_t MP4File::GetODProfileLevel()
{
	return GetIntegerProperty("moov.iods.ODProfileLevelId");
}

void MP4File::SetODProfileLevel(u_int8_t value)
{
	SetIntegerProperty("moov.iods.ODProfileLevelId", value);
}
 
u_int8_t MP4File::GetSceneProfileLevel()
{
	return GetIntegerProperty("moov.iods.sceneProfileLevelId");
}

void MP4File::SetSceneProfileLevel(u_int8_t value)
{
	SetIntegerProperty("moov.iods.sceneProfileLevelId", value);
}
 
u_int8_t MP4File::GetVideoProfileLevel()
{
	return GetIntegerProperty("moov.iods.visualProfileLevelId");
}

void MP4File::SetVideoProfileLevel(u_int8_t value)
{
	SetIntegerProperty("moov.iods.visualProfileLevelId", value);
}
 
u_int8_t MP4File::GetAudioProfileLevel()
{
	return GetIntegerProperty("moov.iods.audioProfileLevelId");
}

void MP4File::SetAudioProfileLevel(u_int8_t value)
{
	SetIntegerProperty("moov.iods.audioProfileLevelId", value);
}
 
u_int8_t MP4File::GetGraphicsProfileLevel()
{
	return GetIntegerProperty("moov.iods.graphicsProfileLevelId");
}

void MP4File::SetGraphicsProfileLevel(u_int8_t value)
{
	SetIntegerProperty("moov.iods.graphicsProfileLevelId", value);
}
 
const char* MP4File::GetSessionSdp()
{
	return GetStringProperty("moov.udta.hnti.rtp .sdpText");
}

void MP4File::SetSessionSdp(const char* sdpString)
{
	AddDescendantAtoms("moov", "udta.hnti.rtp ");

	SetStringProperty("moov.udta.hnti.rtp .sdpText", sdpString);
}

void MP4File::AppendSessionSdp(const char* sdpFragment)
{
	const char* oldSdpString = NULL;
	try {
		oldSdpString = GetSessionSdp();
	}
	catch (MP4Error* e) {
		delete e;
		SetSessionSdp(sdpFragment);
		return;
	}

	char* newSdpString =
		(char*)MP4Malloc(strlen(oldSdpString) + strlen(sdpFragment) + 1);
	strcpy(newSdpString, oldSdpString);
	strcat(newSdpString, sdpFragment);
	SetSessionSdp(newSdpString);
	MP4Free(newSdpString);
}


// track level convenience functions

MP4SampleId MP4File::GetTrackNumberOfSamples(MP4TrackId trackId)
{
	return m_pTracks[FindTrackIndex(trackId)]->GetNumberOfSamples();
}

const char* MP4File::GetTrackType(MP4TrackId trackId)
{
	return m_pTracks[FindTrackIndex(trackId)]->GetType();
}

u_int32_t MP4File::GetTrackTimeScale(MP4TrackId trackId)
{
	return m_pTracks[FindTrackIndex(trackId)]->GetTimeScale();
}

void MP4File::SetTrackTimeScale(MP4TrackId trackId, u_int32_t value)
{
	if (value == 0) {
		throw new MP4Error("invalid value", "SetTrackTimeScale");
	}
	SetTrackIntegerProperty(trackId, "mdia.mdhd.timeScale", value);
}

MP4Duration MP4File::GetTrackDuration(MP4TrackId trackId)
{
	return GetTrackIntegerProperty(trackId, "mdia.mdhd.duration");
}

u_int8_t MP4File::GetTrackAudioType(MP4TrackId trackId)
{
	return GetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId");
}

u_int8_t MP4File::GetTrackAudioMpeg4Type(MP4TrackId trackId)
{
	// verify that track is an MPEG-4 audio track 
	if (GetTrackAudioType(trackId) != MP4_MPEG4_AUDIO_TYPE) {
		return MP4_MPEG4_INVALID_AUDIO_TYPE;
	}

	u_int8_t* pEsConfig = NULL;
	u_int32_t esConfigSize;

	// The Mpeg4 audio type (AAC, CELP, HXVC, ...)
	// is the first 5 bits of the ES configuration

	GetTrackESConfiguration(trackId, &pEsConfig, &esConfigSize);

	if (esConfigSize < 1) {
		return MP4_MPEG4_INVALID_AUDIO_TYPE;
	}

	u_int8_t mpeg4Type = (pEsConfig[0] >> 3);

	free(pEsConfig);

	return mpeg4Type;
}

u_int8_t MP4File::GetTrackVideoType(MP4TrackId trackId)
{
	return GetTrackIntegerProperty(trackId, 
		"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId");
}

MP4Duration MP4File::GetTrackFixedSampleDuration(MP4TrackId trackId)
{
	return m_pTracks[FindTrackIndex(trackId)]->GetFixedSampleDuration();
}

⌨️ 快捷键说明

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