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

📄 rtphint.cpp

📁 AAC编解码源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		InitStats();
	}

	if (m_pWriteHint) {
		throw new MP4Error("unwritten hint is still pending", "MP4AddRtpHint");
	}

	m_pWriteHint = new MP4RtpHint(this);
	m_pWriteHint->SetBFrame(isBFrame);
	m_pWriteHint->SetTimestampOffset(timestampOffset);

	m_bytesThisHint = 0;
	m_writeHintId++;
}

void MP4RtpHintTrack::AddPacket(bool setMbit, int32_t transmitOffset)
{
	if (m_pWriteHint == NULL) {
		throw new MP4Error("no hint pending", "MP4RtpAddPacket");
	}

	MP4RtpPacket* pPacket = m_pWriteHint->AddPacket();

	ASSERT(m_pPayloadNumberProperty);

	pPacket->Set(
		m_pPayloadNumberProperty->GetValue(), 
		m_writePacketId++, 
		setMbit);
	pPacket->SetTransmitOffset(transmitOffset);

	m_bytesThisHint += 12;
	if (m_bytesThisPacket > m_pPmax->GetValue()) {
		m_pPmax->SetValue(m_bytesThisPacket);
	}
	m_bytesThisPacket = 12;
	m_pNump->IncrementValue();
	m_pTrpy->IncrementValue(12); // RTP packet header size
}

void MP4RtpHintTrack::AddImmediateData(
	const u_int8_t* pBytes,
	u_int32_t numBytes)
{
	if (m_pWriteHint == NULL) {
		throw new MP4Error("no hint pending", "MP4RtpAddImmediateData");
	}

	MP4RtpPacket* pPacket = m_pWriteHint->GetCurrentPacket();
	if (pPacket == NULL) {
		throw new MP4Error("no packet pending", "MP4RtpAddImmediateData");
	}

	if (pBytes == NULL || numBytes == 0) {
		throw new MP4Error("no data",
			"AddImmediateData");
	}
	if (numBytes > 14) {
		throw new MP4Error("data size is larger than 14 bytes",
			"AddImmediateData");
	}

	MP4RtpImmediateData* pData = new MP4RtpImmediateData(pPacket);
	pData->Set(pBytes, numBytes);

	pPacket->AddData(pData);

	m_bytesThisHint += numBytes;
	m_bytesThisPacket += numBytes;
	m_pDimm->IncrementValue(numBytes);
	m_pTpyl->IncrementValue(numBytes);
	m_pTrpy->IncrementValue(numBytes);
}

void MP4RtpHintTrack::AddSampleData(
	MP4SampleId sampleId,
	u_int32_t dataOffset,
	u_int32_t dataLength)
{
	if (m_pWriteHint == NULL) {
		throw new MP4Error("no hint pending", "MP4RtpAddSampleData");
	}

	MP4RtpPacket* pPacket = m_pWriteHint->GetCurrentPacket();
	if (pPacket == NULL) {
		throw new MP4Error("no packet pending", "MP4RtpAddSampleData");
	}

	MP4RtpSampleData* pData = new MP4RtpSampleData(pPacket);

	pData->SetReferenceSample(sampleId, dataOffset, dataLength);

	pPacket->AddData(pData);

	m_bytesThisHint += dataLength;
	m_bytesThisPacket += dataLength;
	m_pDmed->IncrementValue(dataLength);
	m_pTpyl->IncrementValue(dataLength);
	m_pTrpy->IncrementValue(dataLength);
}

void MP4RtpHintTrack::AddESConfigurationPacket()
{
	if (m_pWriteHint == NULL) {
		throw new MP4Error("no hint pending", 
			"MP4RtpAddESConfigurationPacket");
	}

	u_int8_t* pConfig = NULL;
	u_int32_t configSize = 0;

	m_pFile->GetTrackESConfiguration(m_pRefTrack->GetId(),
		&pConfig, &configSize);

	if (pConfig == NULL) {
		return;
	}

	ASSERT(m_pMaxPacketSizeProperty);

	if (configSize > m_pMaxPacketSizeProperty->GetValue()) {
		throw new MP4Error("ES configuration is too large for RTP payload",
			"MP4RtpAddESConfigurationPacket");
	}

	AddPacket(false);

	MP4RtpPacket* pPacket = m_pWriteHint->GetCurrentPacket();
	ASSERT(pPacket);
	
	// This is ugly!
	// To get the ES configuration data somewhere known
	// we create a sample data reference that points to 
	// this hint track (not the media track)
	// and this sample of the hint track 
	// the offset into this sample is filled in during the write process
	MP4RtpSampleData* pData = new MP4RtpSampleData(pPacket);

	pData->SetEmbeddedImmediate(m_writeSampleId, pConfig, configSize);

	pPacket->AddData(pData);

	m_bytesThisHint += configSize;
	m_bytesThisPacket += configSize;
	m_pTpyl->IncrementValue(configSize);
	m_pTrpy->IncrementValue(configSize);
}

void MP4RtpHintTrack::WriteHint(MP4Duration duration, bool isSyncSample)
{
	if (m_pWriteHint == NULL) {
		throw new MP4Error("no hint pending", "MP4WriteRtpHint");
	}

	u_int8_t* pBytes;
	u_int64_t numBytes;

	m_pFile->EnableMemoryBuffer();

	m_pWriteHint->Write(m_pFile);

	m_pFile->DisableMemoryBuffer(&pBytes, &numBytes);

	WriteSample(pBytes, numBytes, duration, 0, isSyncSample);

	MP4Free(pBytes);

	// update statistics
	if (m_bytesThisPacket > m_pPmax->GetValue()) {
		m_pPmax->SetValue(m_bytesThisPacket);
	}

	if (duration > m_pDmax->GetValue()) {
		m_pDmax->SetValue(duration);
	}

	MP4Timestamp startTime;

	GetSampleTimes(m_writeHintId, &startTime, NULL);

	if (startTime < m_thisSec + GetTimeScale()) {
		m_bytesThisSec += m_bytesThisHint;
	} else {
		if (m_bytesThisSec > m_pMaxr->GetValue()) {
			m_pMaxr->SetValue(m_bytesThisSec);
		}
		m_thisSec = startTime - (startTime % GetTimeScale());
		m_bytesThisSec = m_bytesThisHint;
	}

	// cleanup
	delete m_pWriteHint;
	m_pWriteHint = NULL;
}

void MP4RtpHintTrack::FinishWrite()
{
	if (m_writeHintId != MP4_INVALID_SAMPLE_ID) {
		m_pMaxPdu->SetValue(m_pPmax->GetValue());
		if (m_pNump->GetValue()) {
			m_pAvgPdu->SetValue(m_pTrpy->GetValue() / m_pNump->GetValue());
		}

		m_pMaxBitRate->SetValue(m_pMaxr->GetValue() * 8);
		if (GetDuration()) {
			m_pAvgBitRate->SetValue(
				m_pTrpy->GetValue() * 8 * GetTimeScale() / GetDuration());
		}
	}

	MP4Track::FinishWrite();
}

void MP4RtpHintTrack::InitStats()
{
	MP4Atom* pHinfAtom = m_pTrakAtom->FindAtom("trak.udta.hinf");

	ASSERT(pHinfAtom);

	pHinfAtom->FindProperty("hinf.trpy.bytes", (MP4Property**)&m_pTrpy); 
	pHinfAtom->FindProperty("hinf.nump.packets", (MP4Property**)&m_pNump); 
	pHinfAtom->FindProperty("hinf.tpyl.bytes", (MP4Property**)&m_pTpyl); 
	pHinfAtom->FindProperty("hinf.maxr.bytes", (MP4Property**)&m_pMaxr); 
	pHinfAtom->FindProperty("hinf.dmed.bytes", (MP4Property**)&m_pDmed); 
	pHinfAtom->FindProperty("hinf.dimm.bytes", (MP4Property**)&m_pDimm); 
	pHinfAtom->FindProperty("hinf.pmax.bytes", (MP4Property**)&m_pPmax); 
	pHinfAtom->FindProperty("hinf.dmax.milliSecs", (MP4Property**)&m_pDmax); 

	MP4Atom* pHmhdAtom = m_pTrakAtom->FindAtom("trak.mdia.minf.hmhd");

	ASSERT(pHmhdAtom);

	pHmhdAtom->FindProperty("hmhd.maxPduSize", (MP4Property**)&m_pMaxPdu); 
	pHmhdAtom->FindProperty("hmhd.avgPduSize", (MP4Property**)&m_pAvgPdu); 
	pHmhdAtom->FindProperty("hmhd.maxBitRate", (MP4Property**)&m_pMaxBitRate); 
	pHmhdAtom->FindProperty("hmhd.avgBitRate", (MP4Property**)&m_pAvgBitRate); 

	MP4Integer32Property* pMaxrPeriod = NULL;
	pHinfAtom->FindProperty("hinf.maxr.granularity",
		 (MP4Property**)&pMaxrPeriod); 
	if (pMaxrPeriod) {
		pMaxrPeriod->SetValue(1000);	// 1 second
	}
}


MP4RtpHint::MP4RtpHint(MP4RtpHintTrack* pTrack)
{
	m_pTrack = pTrack;

	AddProperty( /* 0 */
		new MP4Integer16Property("packetCount"));
	AddProperty( /* 1 */
		new MP4Integer16Property("reserved"));
}

MP4RtpHint::~MP4RtpHint()
{
	for (u_int32_t i = 0; i < m_rtpPackets.Size(); i++) {
		delete m_rtpPackets[i];
	}
}

MP4RtpPacket* MP4RtpHint::AddPacket() 
{
	MP4RtpPacket* pPacket = new MP4RtpPacket(this);
	m_rtpPackets.Add(pPacket);

	// packetCount property
	((MP4Integer16Property*)m_pProperties[0])->IncrementValue();

	pPacket->SetBFrame(m_isBFrame);
	pPacket->SetTimestampOffset(m_timestampOffset);

	return pPacket;
}

void MP4RtpHint::Read(MP4File* pFile)
{
	// call base class Read for required properties
	MP4Container::Read(pFile);

	u_int16_t numPackets =
		((MP4Integer16Property*)m_pProperties[0])->GetValue();

	for (u_int16_t i = 0; i < numPackets; i++) {
		MP4RtpPacket* pPacket = new MP4RtpPacket(this);

		m_rtpPackets.Add(pPacket);

		pPacket->Read(pFile);
	}

	VERBOSE_READ_HINT(pFile->GetVerbosity(),
		printf("ReadHint:\n"); Dump(stdout, 10, false););
}

void MP4RtpHint::Write(MP4File* pFile)
{
	u_int64_t hintStartPos = pFile->GetPosition();

	MP4Container::Write(pFile);

	u_int64_t packetStartPos = pFile->GetPosition();

	u_int32_t i;

	// first write out packet (and data) entries
	for (i = 0; i < m_rtpPackets.Size(); i++) {
		m_rtpPackets[i]->Write(pFile);
	}

	// now let packets write their extra data into the hint sample
	for (i = 0; i < m_rtpPackets.Size(); i++) {
		m_rtpPackets[i]->WriteEmbeddedData(pFile, hintStartPos);
	}

	u_int64_t endPos = pFile->GetPosition();

	pFile->SetPosition(packetStartPos);

	// finally rewrite the packet and data entries
	// which now contain the correct offsets for the embedded data
	for (i = 0; i < m_rtpPackets.Size(); i++) {
		m_rtpPackets[i]->Write(pFile);
	}

	pFile->SetPosition(endPos);

	VERBOSE_WRITE_HINT(pFile->GetVerbosity(),
		printf("WriteRtpHint:\n"); Dump(stdout, 14, false));
}

void MP4RtpHint::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits)
{
	MP4Container::Dump(pFile, indent, dumpImplicits);

	for (u_int32_t i = 0; i < m_rtpPackets.Size(); i++) {
		Indent(pFile, indent);
		fprintf(pFile, "RtpPacket: %u\n", i);
		m_rtpPackets[i]->Dump(pFile, indent + 1, dumpImplicits);
	}
}

MP4RtpPacket::MP4RtpPacket(MP4RtpHint* pHint)
{
	m_pHint = pHint;

	AddProperty( /* 0 */
		new MP4Integer32Property("relativeXmitTime"));
	AddProperty( /* 1 */
		new MP4BitfieldProperty("reserved1", 2));
	AddProperty( /* 2 */
		new MP4BitfieldProperty("Pbit", 1));
	AddProperty( /* 3 */
		new MP4BitfieldProperty("Xbit", 1));
	AddProperty( /* 4 */
		new MP4BitfieldProperty("reserved2", 4));
	AddProperty( /* 5 */
		new MP4BitfieldProperty("Mbit", 1));
	AddProperty( /* 6 */
		new MP4BitfieldProperty("payloadType", 7));
	AddProperty( /* 7  */
		new MP4Integer16Property("sequenceNumber"));
	AddProperty( /* 8 */
		new MP4BitfieldProperty("reserved3", 13));
	AddProperty( /* 9 */
		new MP4BitfieldProperty("extraFlag", 1));
	AddProperty( /* 10 */
		new MP4BitfieldProperty("bFrameFlag", 1));
	AddProperty( /* 11 */
		new MP4BitfieldProperty("repeatFlag", 1));
	AddProperty( /* 12 */
		new MP4Integer16Property("entryCount"));
}
 
MP4RtpPacket::~MP4RtpPacket()
{
	for (u_int32_t i = 0; i < m_rtpData.Size(); i++) {
		delete m_rtpData[i];
	}
}

void MP4RtpPacket::AddExtraProperties()
{
	AddProperty( /* 13 */
		new MP4Integer32Property("extraInformationLength"));

	// This is a bit of a hack, since the tlv entries are really defined 
	// as atoms but there is only one type defined now, rtpo, and getting 
	// our atom code hooked up here would be a major pain with little gain

	AddProperty( /* 14 */
		new MP4Integer32Property("tlvLength"));
	AddProperty( /* 15 */
		new MP4StringProperty("tlvType"));
	AddProperty( /* 16 */
		new MP4Integer32Property("timestampOffset"));

	((MP4Integer32Property*)m_pProperties[13])->SetValue(16);
	((MP4Integer32Property*)m_pProperties[14])->SetValue(12);
	((MP4StringProperty*)m_pProperties[15])->SetFixedLength(4);
	((MP4StringProperty*)m_pProperties[15])->SetValue("rtpo");
}

void MP4RtpPacket::Read(MP4File* pFile)
{
	// call base class Read for required properties
	MP4Container::Read(pFile);

	// read extra info if present
	// we only support the rtpo field!
	if (((MP4BitfieldProperty*)m_pProperties[9])->GetValue() == 1) {
		ReadExtra(pFile);
	}

	u_int16_t numDataEntries =
		((MP4Integer16Property*)m_pProperties[12])->GetValue();

	// read data entries
	for (u_int16_t i = 0; i < numDataEntries; i++) {
		u_int8_t dataType;
		pFile->PeekBytes(&dataType, 1);

		MP4RtpData* pData;

		switch (dataType) {
		case 0:
			pData = new MP4RtpNullData(this);
			break;
		case 1:
			pData = new MP4RtpImmediateData(this);
			break;
		case 2:
			pData = new MP4RtpSampleData(this);
			break;
		case 3:
			pData = new MP4RtpSampleDescriptionData(this);
			break;
		default:
			throw new MP4Error("unknown packet data entry type",
				"MP4ReadHint");
		}

		m_rtpData.Add(pData);

		// read data entry's properties
		pData->Read(pFile);
	}
}

void MP4RtpPacket::ReadExtra(MP4File* pFile)
{

⌨️ 快捷键说明

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