📄 rtphint.cpp
字号:
AddExtraProperties();
int32_t extraLength = (int32_t)pFile->ReadUInt32();
if (extraLength < 4) {
throw new MP4Error("bad packet extra info length",
"MP4RtpPacket::ReadExtra");
}
extraLength -= 4;
while (extraLength > 0) {
u_int32_t entryLength = pFile->ReadUInt32();
u_int32_t entryTag = pFile->ReadUInt32();
if (entryLength < 8) {
throw new MP4Error("bad packet extra info entry length",
"MP4RtpPacket::ReadExtra");
}
if (entryTag == STRTOINT32("rtpo") && entryLength == 12) {
// read the rtp timestamp offset
m_pProperties[16]->Read(pFile);
} else {
// ignore it, LATER carry it along
pFile->SetPosition(pFile->GetPosition() + entryLength - 8);
}
extraLength -= entryLength;
}
if (extraLength < 0) {
throw new MP4Error("invalid packet extra info length",
"MP4RtpPacket::ReadExtra");
}
}
void MP4RtpPacket::Set(u_int8_t payloadNumber,
u_int32_t packetId, bool setMbit)
{
((MP4BitfieldProperty*)m_pProperties[5])->SetValue(setMbit);
((MP4BitfieldProperty*)m_pProperties[6])->SetValue(payloadNumber);
((MP4Integer16Property*)m_pProperties[7])->SetValue(packetId);
}
int32_t MP4RtpPacket::GetTransmitOffset()
{
return ((MP4Integer32Property*)m_pProperties[0])->GetValue();
}
void MP4RtpPacket::SetTransmitOffset(int32_t transmitOffset)
{
((MP4Integer32Property*)m_pProperties[0])->SetValue(transmitOffset);
}
bool MP4RtpPacket::GetPBit()
{
return ((MP4BitfieldProperty*)m_pProperties[2])->GetValue();
}
bool MP4RtpPacket::GetXBit()
{
return ((MP4BitfieldProperty*)m_pProperties[3])->GetValue();
}
bool MP4RtpPacket::GetMBit()
{
return ((MP4BitfieldProperty*)m_pProperties[5])->GetValue();
}
u_int8_t MP4RtpPacket::GetPayload()
{
return ((MP4BitfieldProperty*)m_pProperties[6])->GetValue();
}
u_int16_t MP4RtpPacket::GetSequenceNumber()
{
return ((MP4Integer16Property*)m_pProperties[7])->GetValue();
}
bool MP4RtpPacket::IsBFrame()
{
return ((MP4BitfieldProperty*)m_pProperties[10])->GetValue();
}
void MP4RtpPacket::SetBFrame(bool isBFrame)
{
((MP4BitfieldProperty*)m_pProperties[10])->SetValue(isBFrame);
}
void MP4RtpPacket::SetTimestampOffset(u_int32_t timestampOffset)
{
if (timestampOffset == 0) {
return;
}
ASSERT(((MP4BitfieldProperty*)m_pProperties[9])->GetValue() == 0);
// set X bit
((MP4BitfieldProperty*)m_pProperties[9])->SetValue(1);
AddExtraProperties();
((MP4Integer32Property*)m_pProperties[16])->SetValue(timestampOffset);
}
void MP4RtpPacket::AddData(MP4RtpData* pData)
{
m_rtpData.Add(pData);
// increment entry count property
((MP4Integer16Property*)m_pProperties[12])->IncrementValue();
}
u_int32_t MP4RtpPacket::GetDataSize()
{
u_int32_t totalDataSize = 0;
for (u_int32_t i = 0; i < m_rtpData.Size(); i++) {
totalDataSize += m_rtpData[i]->GetDataSize();
}
return totalDataSize;
}
void MP4RtpPacket::GetData(u_int8_t* pDest)
{
for (u_int32_t i = 0; i < m_rtpData.Size(); i++) {
m_rtpData[i]->GetData(pDest);
pDest += m_rtpData[i]->GetDataSize();
}
}
void MP4RtpPacket::Write(MP4File* pFile)
{
MP4Container::Write(pFile);
for (u_int32_t i = 0; i < m_rtpData.Size(); i++) {
m_rtpData[i]->Write(pFile);
}
}
void MP4RtpPacket::WriteEmbeddedData(MP4File* pFile, u_int64_t startPos)
{
for (u_int32_t i = 0; i < m_rtpData.Size(); i++) {
m_rtpData[i]->WriteEmbeddedData(pFile, startPos);
}
}
void MP4RtpPacket::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits)
{
MP4Container::Dump(pFile, indent, dumpImplicits);
for (u_int32_t i = 0; i < m_rtpData.Size(); i++) {
Indent(pFile, indent);
fprintf(pFile, "RtpData: %u\n", i);
m_rtpData[i]->Dump(pFile, indent + 1, dumpImplicits);
}
}
MP4RtpData::MP4RtpData(MP4RtpPacket* pPacket)
{
m_pPacket = pPacket;
AddProperty( /* 0 */
new MP4Integer8Property("type"));
}
MP4Track* MP4RtpData::FindTrackFromRefIndex(u_int8_t refIndex)
{
MP4Track* pTrack;
if (refIndex == (u_int8_t)-1) {
// ourselves
pTrack = GetPacket()->GetHint()->GetTrack();
} else if (refIndex == 0) {
// our reference track
pTrack = GetPacket()->GetHint()->GetTrack()->GetRefTrack();
} else {
// some other track
MP4RtpHintTrack* pHintTrack =
GetPacket()->GetHint()->GetTrack();
MP4Atom* pTrakAtom = pHintTrack->GetTrakAtom();
ASSERT(pTrakAtom);
MP4Integer32Property* pTrackIdProperty = NULL;
pTrakAtom->FindProperty(
"trak.tref.hint.entries",
(MP4Property**)&pTrackIdProperty);
ASSERT(pTrackIdProperty);
u_int32_t refTrackId =
pTrackIdProperty->GetValue(refIndex - 1);
pTrack = pHintTrack->GetFile()->GetTrack(refTrackId);
}
return pTrack;
}
MP4RtpNullData::MP4RtpNullData(MP4RtpPacket* pPacket)
: MP4RtpData(pPacket)
{
((MP4Integer8Property*)m_pProperties[0])->SetValue(0);
AddProperty( /* 1 */
new MP4BytesProperty("pad", 15));
((MP4BytesProperty*)m_pProperties[1])->SetFixedSize(15);
}
MP4RtpImmediateData::MP4RtpImmediateData(MP4RtpPacket* pPacket)
: MP4RtpData(pPacket)
{
((MP4Integer8Property*)m_pProperties[0])->SetValue(1);
AddProperty( /* 1 */
new MP4Integer8Property("count"));
AddProperty( /* 2 */
new MP4BytesProperty("data", 14));
((MP4BytesProperty*)m_pProperties[2])->SetFixedSize(14);
}
void MP4RtpImmediateData::Set(const u_int8_t* pBytes, u_int8_t numBytes)
{
((MP4Integer8Property*)m_pProperties[1])->SetValue(numBytes);
((MP4BytesProperty*)m_pProperties[2])->SetValue(pBytes, numBytes);
}
u_int16_t MP4RtpImmediateData::GetDataSize()
{
return ((MP4Integer8Property*)m_pProperties[1])->GetValue();
}
void MP4RtpImmediateData::GetData(u_int8_t* pDest)
{
u_int8_t* pValue;
u_int32_t valueSize;
((MP4BytesProperty*)m_pProperties[2])->GetValue(&pValue, &valueSize);
memcpy(pDest, pValue, GetDataSize());
MP4Free(pValue);
}
MP4RtpSampleData::MP4RtpSampleData(MP4RtpPacket* pPacket)
: MP4RtpData(pPacket)
{
((MP4Integer8Property*)m_pProperties[0])->SetValue(2);
AddProperty( /* 1 */
new MP4Integer8Property("trackRefIndex"));
AddProperty( /* 2 */
new MP4Integer16Property("length"));
AddProperty( /* 3 */
new MP4Integer32Property("sampleNumber"));
AddProperty( /* 4 */
new MP4Integer32Property("sampleOffset"));
AddProperty( /* 5 */
new MP4Integer16Property("bytesPerBlock"));
AddProperty( /* 6 */
new MP4Integer16Property("samplesPerBlock"));
((MP4Integer16Property*)m_pProperties[5])->SetValue(1);
((MP4Integer16Property*)m_pProperties[6])->SetValue(1);
m_pRefData = NULL;
m_pRefTrack = NULL;
m_refSampleId = MP4_INVALID_SAMPLE_ID;
m_refSampleOffset = 0;
}
void MP4RtpSampleData::SetEmbeddedImmediate(MP4SampleId sampleId,
u_int8_t* pData, u_int16_t dataLength)
{
((MP4Integer8Property*)m_pProperties[1])->SetValue((u_int8_t)-1);
((MP4Integer16Property*)m_pProperties[2])->SetValue(dataLength);
((MP4Integer32Property*)m_pProperties[3])->SetValue(sampleId);
((MP4Integer32Property*)m_pProperties[4])->SetValue(0);
m_pRefData = pData;
}
void MP4RtpSampleData::SetReferenceSample(
MP4SampleId refSampleId, u_int32_t refSampleOffset,
u_int16_t sampleLength)
{
((MP4Integer8Property*)m_pProperties[1])->SetValue(0);
((MP4Integer16Property*)m_pProperties[2])->SetValue(sampleLength);
((MP4Integer32Property*)m_pProperties[3])->SetValue(refSampleId);
((MP4Integer32Property*)m_pProperties[4])->SetValue(refSampleOffset);
}
void MP4RtpSampleData::SetEmbeddedSample(
MP4SampleId sampleId, MP4Track* pRefTrack,
MP4SampleId refSampleId, u_int32_t refSampleOffset,
u_int16_t sampleLength)
{
((MP4Integer8Property*)m_pProperties[1])->SetValue((u_int8_t)-1);
((MP4Integer16Property*)m_pProperties[2])->SetValue(sampleLength);
((MP4Integer32Property*)m_pProperties[3])->SetValue(sampleId);
((MP4Integer32Property*)m_pProperties[4])->SetValue(0);
m_pRefTrack = pRefTrack;
m_refSampleId = refSampleId;
m_refSampleOffset = refSampleOffset;
}
u_int16_t MP4RtpSampleData::GetDataSize()
{
return ((MP4Integer16Property*)m_pProperties[2])->GetValue();
}
void MP4RtpSampleData::GetData(u_int8_t* pDest)
{
u_int8_t trackRefIndex =
((MP4Integer8Property*)m_pProperties[1])->GetValue();
MP4Track* pSampleTrack =
FindTrackFromRefIndex(trackRefIndex);
pSampleTrack->ReadSampleFragment(
((MP4Integer32Property*)m_pProperties[3])->GetValue(), // sampleId
((MP4Integer32Property*)m_pProperties[4])->GetValue(), // sampleOffset
((MP4Integer16Property*)m_pProperties[2])->GetValue(), // sampleLength
pDest);
}
void MP4RtpSampleData::WriteEmbeddedData(MP4File* pFile, u_int64_t startPos)
{
// if not using embedded data, nothing to do
if (((MP4Integer8Property*)m_pProperties[1])->GetValue() != (u_int8_t)-1) {
return;
}
// figure out the offset within this hint sample for this embedded data
u_int64_t offset = pFile->GetPosition() - startPos;
ASSERT(offset <= 0xFFFFFFFF);
((MP4Integer32Property*)m_pProperties[4])->SetValue((u_int32_t)offset);
u_int16_t length = ((MP4Integer16Property*)m_pProperties[2])->GetValue();
if (m_pRefData) {
pFile->WriteBytes(m_pRefData, length);
return;
}
if (m_refSampleId != MP4_INVALID_SAMPLE_ID) {
u_int8_t* pSample = NULL;
u_int32_t sampleSize = 0;
ASSERT(m_pRefTrack);
m_pRefTrack->ReadSample(m_refSampleId, &pSample, &sampleSize);
ASSERT(m_refSampleOffset + length <= sampleSize);
pFile->WriteBytes(&pSample[m_refSampleOffset], length);
MP4Free(pSample);
return;
}
}
MP4RtpSampleDescriptionData::MP4RtpSampleDescriptionData(MP4RtpPacket* pPacket)
: MP4RtpData(pPacket)
{
((MP4Integer8Property*)m_pProperties[0])->SetValue(3);
AddProperty( /* 1 */
new MP4Integer8Property("trackRefIndex"));
AddProperty( /* 2 */
new MP4Integer16Property("length"));
AddProperty( /* 3 */
new MP4Integer32Property("sampleDescriptionIndex"));
AddProperty( /* 4 */
new MP4Integer32Property("sampleDescriptionOffset"));
AddProperty( /* 5 */
new MP4Integer32Property("reserved"));
}
void MP4RtpSampleDescriptionData::Set(u_int32_t sampleDescrIndex,
u_int32_t offset, u_int16_t length)
{
((MP4Integer16Property*)m_pProperties[2])->SetValue(length);
((MP4Integer32Property*)m_pProperties[3])->SetValue(sampleDescrIndex);
((MP4Integer32Property*)m_pProperties[4])->SetValue(offset);
}
u_int16_t MP4RtpSampleDescriptionData::GetDataSize()
{
return ((MP4Integer16Property*)m_pProperties[2])->GetValue();
}
void MP4RtpSampleDescriptionData::GetData(u_int8_t* pDest)
{
// we start with the index into our track references
u_int8_t trackRefIndex =
((MP4Integer8Property*)m_pProperties[1])->GetValue();
// from which we can find the track structure
MP4Track* pSampleTrack =
FindTrackFromRefIndex(trackRefIndex);
// next find the desired atom in the track's sample description table
u_int32_t sampleDescrIndex =
((MP4Integer32Property*)m_pProperties[3])->GetValue();
MP4Atom* pTrakAtom =
pSampleTrack->GetTrakAtom();
char sdName[64];
sprintf(sdName, "trak.mdia.minf.stbl.stsd.*[%u]", sampleDescrIndex);
MP4Atom* pSdAtom =
pTrakAtom->FindAtom(sdName);
// bad reference
if (pSdAtom == NULL) {
throw new MP4Error("invalid sample description index",
"MP4RtpSampleDescriptionData::GetData");
}
// check validity of the upcoming copy
u_int16_t length =
((MP4Integer16Property*)m_pProperties[2])->GetValue();
u_int32_t offset =
((MP4Integer32Property*)m_pProperties[4])->GetValue();
if (offset + length > pSdAtom->GetSize()) {
throw new MP4Error("offset and/or length are too large",
"MP4RtpSampleDescriptionData::GetData");
}
// now we use the raw file to get the desired bytes
MP4File* pFile = GetPacket()->GetHint()->GetTrack()->GetFile();
u_int64_t orgPos = pFile->GetPosition();
// It's not entirely clear from the spec whether the offset is from
// the start of the sample descirption atom, or the start of the atom's
// data. I believe it is the former, but the commented out code will
// realize the latter interpretation if I turn out to be wrong.
u_int64_t dataPos = pSdAtom->GetStart();
//u_int64_t dataPos = pSdAtom->GetEnd() - pSdAtom->GetSize();
pFile->SetPosition(dataPos + offset);
pFile->ReadBytes(pDest, length);
pFile->SetPosition(orgPos);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -