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

📄 mp4track.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	MP4SampleId firstSampleInChunk = 		sampleId - ((sampleId - firstSample) % samplesPerChunk);	// need cumulative samples sizes from firstSample to sampleId - 1	u_int32_t sampleOffset = 0;	for (MP4SampleId i = firstSampleInChunk; i < sampleId; i++) {		sampleOffset += GetSampleSize(i);	}	return chunkOffset + sampleOffset;}void MP4Track::UpdateSampleToChunk(MP4SampleId sampleId,	 MP4ChunkId chunkId, u_int32_t samplesPerChunk){	u_int32_t numStsc = m_pStscCountProperty->GetValue();	// if samplesPerChunk == samplesPerChunk of last entry	if (numStsc && samplesPerChunk == 	  m_pStscSamplesPerChunkProperty->GetValue(numStsc-1)) {		// nothing to do	} else {		// add stsc entry		m_pStscFirstChunkProperty->AddValue(chunkId);		m_pStscSamplesPerChunkProperty->AddValue(samplesPerChunk);		m_pStscSampleDescrIndexProperty->AddValue(1);		m_pStscFirstSampleProperty->AddValue(sampleId - samplesPerChunk + 1);		m_pStscCountProperty->IncrementValue();	}}void MP4Track::UpdateChunkOffsets(u_int64_t chunkOffset){	if (m_pChunkOffsetProperty->GetType() == Integer32Property) {		((MP4Integer32Property*)m_pChunkOffsetProperty)->AddValue(chunkOffset);	} else {		((MP4Integer64Property*)m_pChunkOffsetProperty)->AddValue(chunkOffset);	}	m_pChunkCountProperty->IncrementValue();}MP4Duration MP4Track::GetFixedSampleDuration(){	u_int32_t numStts = m_pSttsCountProperty->GetValue();	if (numStts == 0) {		return m_fixedSampleDuration;	}	if (numStts != 1) {		return MP4_INVALID_DURATION;	// sample duration is not fixed	}	return m_pSttsSampleDeltaProperty->GetValue(0);}void MP4Track::SetFixedSampleDuration(MP4Duration duration){	u_int32_t numStts = m_pSttsCountProperty->GetValue();	// setting this is only allowed before samples have been written	if (numStts != 0) {		return;	}	m_fixedSampleDuration = duration;	return;}void MP4Track::GetSampleTimes(MP4SampleId sampleId,	MP4Timestamp* pStartTime, MP4Duration* pDuration){	u_int32_t numStts = m_pSttsCountProperty->GetValue();	MP4SampleId sid;	MP4Duration elapsed;			if (m_cachedSttsSid != MP4_INVALID_SAMPLE_ID && sampleId >= m_cachedSttsSid) {		sid	  = m_cachedSttsSid;		elapsed	  = m_cachedSttsElapsed;	} else {		m_cachedSttsIndex = 0;		sid	  = 1;		elapsed	  = 0;	}	for (u_int32_t sttsIndex = m_cachedSttsIndex; sttsIndex < numStts; sttsIndex++) {		u_int32_t sampleCount = 			m_pSttsSampleCountProperty->GetValue(sttsIndex);		u_int32_t sampleDelta = 			m_pSttsSampleDeltaProperty->GetValue(sttsIndex);		if (sampleId <= sid + sampleCount - 1) {			if (pStartTime) {			  *pStartTime = (sampleId - sid);			  *pStartTime *= sampleDelta;			  *pStartTime += elapsed;			}			if (pDuration) {				*pDuration = sampleDelta;			}			m_cachedSttsIndex = sttsIndex;			m_cachedSttsSid = sid;			m_cachedSttsElapsed = elapsed;			return;		}		sid += sampleCount;		elapsed += sampleCount * sampleDelta;	}	throw new MP4Error("sample id out of range", 		"MP4Track::GetSampleTimes");}MP4SampleId MP4Track::GetSampleIdFromTime(	MP4Timestamp when, 	bool wantSyncSample) {	u_int32_t numStts = m_pSttsCountProperty->GetValue();	MP4SampleId sid = 1;	MP4Duration elapsed = 0;	for (u_int32_t sttsIndex = 0; sttsIndex < numStts; sttsIndex++) {		u_int32_t sampleCount = 			m_pSttsSampleCountProperty->GetValue(sttsIndex);		u_int32_t sampleDelta = 			m_pSttsSampleDeltaProperty->GetValue(sttsIndex);		if (sampleDelta == 0 && sttsIndex < numStts - 1) {			VERBOSE_READ(m_pFile->GetVerbosity(),				printf("Warning: Zero sample duration, stts entry %u\n",				sttsIndex));		}		MP4Duration d = when - elapsed;		if (d <= sampleCount * sampleDelta) {			MP4SampleId sampleId = sid;			if (sampleDelta) {				sampleId += (d / sampleDelta);			}			if (wantSyncSample) {				return GetNextSyncSample(sampleId);			}			return sampleId;		}		sid += sampleCount;		elapsed += sampleCount * sampleDelta;	}	throw new MP4Error("time out of range", 		"MP4Track::GetSampleIdFromTime");	return 0; // satisfy MS compiler}void MP4Track::UpdateSampleTimes(MP4Duration duration){	u_int32_t numStts = m_pSttsCountProperty->GetValue();	// if duration == duration of last entry	if (numStts 	  && duration == m_pSttsSampleDeltaProperty->GetValue(numStts-1)) {		// increment last entry sampleCount		m_pSttsSampleCountProperty->IncrementValue(1, numStts-1);	} else {		// add stts entry, sampleCount = 1, sampleDuration = duration		m_pSttsSampleCountProperty->AddValue(1);		m_pSttsSampleDeltaProperty->AddValue(duration);		m_pSttsCountProperty->IncrementValue();;	}}u_int32_t MP4Track::GetSampleCttsIndex(MP4SampleId sampleId, 	MP4SampleId* pFirstSampleId){	u_int32_t numCtts = m_pCttsCountProperty->GetValue();	MP4SampleId sid = 1;		for (u_int32_t cttsIndex = 0; cttsIndex < numCtts; cttsIndex++) {		u_int32_t sampleCount = 			m_pCttsSampleCountProperty->GetValue(cttsIndex);		if (sampleId <= sid + sampleCount - 1) {			if (pFirstSampleId) {				*pFirstSampleId = sid;			}			return cttsIndex;		}		sid += sampleCount;	}	throw new MP4Error("sample id out of range", 		"MP4Track::GetSampleCttsIndex");	return 0; // satisfy MS compiler}MP4Duration MP4Track::GetSampleRenderingOffset(MP4SampleId sampleId){	if (m_pCttsCountProperty == NULL) {		return 0;	}	if (m_pCttsCountProperty->GetValue() == 0) {		return 0;	}	u_int32_t cttsIndex = GetSampleCttsIndex(sampleId);	return m_pCttsSampleOffsetProperty->GetValue(cttsIndex);}void MP4Track::UpdateRenderingOffsets(MP4SampleId sampleId, 	MP4Duration renderingOffset){	// if ctts atom doesn't exist	if (m_pCttsCountProperty == NULL) {		// no rendering offset, so nothing to do		if (renderingOffset == 0) {			return;		}		// else create a ctts atom		MP4Atom* pCttsAtom = AddAtom("trak.mdia.minf.stbl", "ctts");		// and get handles on the properties		ASSERT(pCttsAtom->FindProperty(			"ctts.entryCount",			(MP4Property**)&m_pCttsCountProperty));		ASSERT(pCttsAtom->FindProperty(			"ctts.entries.sampleCount",			(MP4Property**)&m_pCttsSampleCountProperty));		ASSERT(pCttsAtom->FindProperty(			"ctts.entries.sampleOffset",			(MP4Property**)&m_pCttsSampleOffsetProperty));		// if this is not the first sample		if (sampleId > 1) {			// add a ctts entry for all previous samples			// with rendering offset equal to zero			m_pCttsSampleCountProperty->AddValue(sampleId - 1);			m_pCttsSampleOffsetProperty->AddValue(0);			m_pCttsCountProperty->IncrementValue();;		}	}	// ctts atom exists (now)	u_int32_t numCtts = m_pCttsCountProperty->GetValue();	// if renderingOffset == renderingOffset of last entry	if (numCtts && renderingOffset	   == m_pCttsSampleOffsetProperty->GetValue(numCtts-1)) {		// increment last entry sampleCount		m_pCttsSampleCountProperty->IncrementValue(1, numCtts-1);	} else {		// add ctts entry, sampleCount = 1, sampleOffset = renderingOffset		m_pCttsSampleCountProperty->AddValue(1);		m_pCttsSampleOffsetProperty->AddValue(renderingOffset);		m_pCttsCountProperty->IncrementValue();	}}void MP4Track::SetSampleRenderingOffset(MP4SampleId sampleId,	 MP4Duration renderingOffset){	// check if any ctts entries exist	if (m_pCttsCountProperty == NULL	  || m_pCttsCountProperty->GetValue() == 0) {		// if not then Update routine can be used 		// to create a ctts entry for samples before this one		// and a ctts entry for this sample 		UpdateRenderingOffsets(sampleId, renderingOffset);		// but we also need a ctts entry 		// for all samples after this one		u_int32_t afterSamples = GetNumberOfSamples() - sampleId;		if (afterSamples) {			m_pCttsSampleCountProperty->AddValue(afterSamples);			m_pCttsSampleOffsetProperty->AddValue(0);			m_pCttsCountProperty->IncrementValue();;		}		return;	}	MP4SampleId firstSampleId;	u_int32_t cttsIndex = GetSampleCttsIndex(sampleId, &firstSampleId);	// do nothing in the degenerate case	if (renderingOffset == 	  m_pCttsSampleOffsetProperty->GetValue(cttsIndex)) {		return;	}	u_int32_t sampleCount =		m_pCttsSampleCountProperty->GetValue(cttsIndex);	// if this sample has it's own ctts entry	if (sampleCount == 1) {		// then just set the value, 		// note we don't attempt to collapse entries		m_pCttsSampleOffsetProperty->SetValue(renderingOffset, cttsIndex);		return;	}	MP4SampleId lastSampleId = firstSampleId + sampleCount - 1;	// else we share this entry with other samples	// we need to insert our own entry	if (sampleId == firstSampleId) {		// our sample is the first one		m_pCttsSampleCountProperty->			InsertValue(1, cttsIndex);		m_pCttsSampleOffsetProperty->			InsertValue(renderingOffset, cttsIndex);		m_pCttsSampleCountProperty->			SetValue(sampleCount - 1, cttsIndex + 1);		m_pCttsCountProperty->IncrementValue();	} else if (sampleId == lastSampleId) {		// our sample is the last one		m_pCttsSampleCountProperty->			InsertValue(1, cttsIndex + 1);		m_pCttsSampleOffsetProperty->			InsertValue(renderingOffset, cttsIndex + 1);		m_pCttsSampleCountProperty->			SetValue(sampleCount - 1, cttsIndex);		m_pCttsCountProperty->IncrementValue();	} else {		// our sample is in the middle, UGH!		// insert our new entry		m_pCttsSampleCountProperty->			InsertValue(1, cttsIndex + 1);		m_pCttsSampleOffsetProperty->			InsertValue(renderingOffset, cttsIndex + 1);		// adjust count of previous entry		m_pCttsSampleCountProperty->			SetValue(sampleId - firstSampleId, cttsIndex);		// insert new entry for those samples beyond our sample		m_pCttsSampleCountProperty->			InsertValue(lastSampleId - sampleId, cttsIndex + 2);		u_int32_t oldRenderingOffset =			m_pCttsSampleOffsetProperty->GetValue(cttsIndex);		m_pCttsSampleOffsetProperty->			InsertValue(oldRenderingOffset, cttsIndex + 2);		m_pCttsCountProperty->IncrementValue(2);	}}bool MP4Track::IsSyncSample(MP4SampleId sampleId){	if (m_pStssCountProperty == NULL) {		return true;	}	u_int32_t numStss = m_pStssCountProperty->GetValue();	u_int32_t stssLIndex = 0;	u_int32_t stssRIndex = numStss - 1;		while (stssRIndex >= stssLIndex){		u_int32_t stssIndex = (stssRIndex + stssLIndex) >> 1;		MP4SampleId syncSampleId = 			m_pStssSampleProperty->GetValue(stssIndex);		if (sampleId == syncSampleId) {			return true;		} 		if (sampleId > syncSampleId) {			stssLIndex = stssIndex + 1;		} else {			stssRIndex = stssIndex - 1;		}	}	return false;}// N.B. "next" is inclusive of this sample idMP4SampleId MP4Track::GetNextSyncSample(MP4SampleId sampleId){	if (m_pStssCountProperty == NULL) {		return sampleId;	}	u_int32_t numStss = m_pStssCountProperty->GetValue();		for (u_int32_t stssIndex = 0; stssIndex < numStss; stssIndex++) {		MP4SampleId syncSampleId = 			m_pStssSampleProperty->GetValue(stssIndex);		if (sampleId > syncSampleId) {			continue;		}		return syncSampleId;	}	// LATER check stsh for alternate sample	return MP4_INVALID_SAMPLE_ID;}void MP4Track::UpdateSyncSamples(MP4SampleId sampleId, bool isSyncSample){  if (isSyncSample) {    // if stss atom exists, add entry    if (m_pStssCountProperty) {      m_pStssSampleProperty->AddValue(sampleId);      m_pStssCountProperty->IncrementValue();    } // else nothing to do (yet)  } else { // !isSyncSample    // if stss atom doesn't exist, create one    if (m_pStssCountProperty == NULL) {      MP4Atom* pStssAtom = AddAtom("trak.mdia.minf.stbl", "stss");      ASSERT(pStssAtom->FindProperty(			      "stss.entryCount",			      (MP4Property**)&m_pStssCountProperty));		        ASSERT(pStssAtom->FindProperty(			      "stss.entries.sampleNumber",			      (MP4Property**)&m_pStssSampleProperty));      // set values for all samples that came before this one      uint32_t samples = GetNumberOfSamples();      for (MP4SampleId sid = 1; sid < samples; sid++) {	m_pStssSampleProperty->AddValue(sid);	m_pStssCountProperty->IncrementValue();      }    } // else nothing to do

⌨️ 快捷键说明

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