📄 rtphint.cpp
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. * * Contributor(s): * Dave Mackie dmackie@cisco.com */#include "mp4common.h"/* rtp hint track operations */MP4RtpHintTrack::MP4RtpHintTrack(MP4File* pFile, MP4Atom* pTrakAtom) : MP4Track(pFile, pTrakAtom){ m_pRefTrack = NULL; m_pRtpMapProperty = NULL; m_pPayloadNumberProperty = NULL; m_pMaxPacketSizeProperty = NULL; m_pSnroProperty = NULL; m_pTsroProperty = NULL; m_pReadHint = NULL; m_pReadHintSample = NULL; m_readHintSampleSize = 0; m_pWriteHint = NULL; m_writeHintId = MP4_INVALID_SAMPLE_ID; m_writePacketId = 0; m_pTrpy = NULL; m_pNump = NULL; m_pTpyl = NULL; m_pMaxr = NULL; m_pDmed = NULL; m_pDimm = NULL; m_pPmax = NULL; m_pDmax = NULL; m_pMaxPdu = NULL; m_pAvgPdu = NULL; m_pMaxBitRate = NULL; m_pAvgBitRate = NULL; m_thisSec = 0; m_bytesThisSec = 0; m_bytesThisHint = 0; m_bytesThisPacket = 0;}MP4RtpHintTrack::~MP4RtpHintTrack(){ delete m_pReadHint; delete m_pReadHintSample; delete m_pWriteHint;}void MP4RtpHintTrack::InitRefTrack(){ if (m_pRefTrack == NULL) { MP4Integer32Property* pRefTrackIdProperty = NULL; m_pTrakAtom->FindProperty( "trak.tref.hint.entries[0].trackId", (MP4Property**)&pRefTrackIdProperty); ASSERT(pRefTrackIdProperty); m_pRefTrack = m_pFile->GetTrack(pRefTrackIdProperty->GetValue()); }}void MP4RtpHintTrack::InitRtpStart() {#ifdef SIMON_CHANGED srand(GetTickCount()); ASSERT(m_pTrakAtom); m_pTrakAtom->FindProperty( "trak.udta.hnti.rtp .snro.offset", (MP4Property**)&m_pSnroProperty); if (m_pSnroProperty) { m_rtpSequenceStart = m_pSnroProperty->GetValue(); } else { m_rtpSequenceStart = rand(); } m_pTrakAtom->FindProperty( "trak.udta.hnti.rtp .tsro.offset", (MP4Property**)&m_pTsroProperty); if (m_pTsroProperty) { m_rtpTimestampStart = m_pTsroProperty->GetValue(); } else { m_rtpTimestampStart = rand(); }#else struct timeval tv; gettimeofday(&tv, NULL); srandom((tv.tv_usec << 12) | (tv.tv_sec & 0xFFF)); ASSERT(m_pTrakAtom); m_pTrakAtom->FindProperty( "trak.udta.hnti.rtp .snro.offset", (MP4Property**)&m_pSnroProperty); if (m_pSnroProperty) { m_rtpSequenceStart = m_pSnroProperty->GetValue(); } else { m_rtpSequenceStart = random(); } m_pTrakAtom->FindProperty( "trak.udta.hnti.rtp .tsro.offset", (MP4Property**)&m_pTsroProperty); if (m_pTsroProperty) { m_rtpTimestampStart = m_pTsroProperty->GetValue(); } else { m_rtpTimestampStart = random(); }#endif}void MP4RtpHintTrack::ReadHint( MP4SampleId hintSampleId, u_int16_t* pNumPackets){ if (m_pRefTrack == NULL) { InitRefTrack(); InitRtpStart(); } // dispose of any old hint delete m_pReadHint; m_pReadHint = NULL; delete m_pReadHintSample; m_pReadHintSample = NULL; m_readHintSampleSize = 0; // read the desired hint sample into memory ReadSample( hintSampleId, &m_pReadHintSample, &m_readHintSampleSize, &m_readHintTimestamp); m_pFile->EnableMemoryBuffer(m_pReadHintSample, m_readHintSampleSize); m_pReadHint = new MP4RtpHint(this); m_pReadHint->Read(m_pFile); m_pFile->DisableMemoryBuffer(); if (pNumPackets) { *pNumPackets = GetHintNumberOfPackets(); }}u_int16_t MP4RtpHintTrack::GetHintNumberOfPackets(){ if (m_pReadHint == NULL) { throw new MP4Error("no hint has been read", "MP4GetRtpHintNumberOfPackets"); } return m_pReadHint->GetNumberOfPackets();}bool MP4RtpHintTrack::GetPacketBFrame(u_int16_t packetIndex){ if (m_pReadHint == NULL) { throw new MP4Error("no hint has been read", "MP4GetRtpPacketBFrame"); } MP4RtpPacket* pPacket = m_pReadHint->GetPacket(packetIndex); return pPacket->IsBFrame();}u_int16_t MP4RtpHintTrack::GetPacketTransmitOffset(u_int16_t packetIndex){ if (m_pReadHint == NULL) { throw new MP4Error("no hint has been read", "MP4GetRtpPacketTransmitOffset"); } MP4RtpPacket* pPacket = m_pReadHint->GetPacket(packetIndex); return pPacket->GetTransmitOffset();}void MP4RtpHintTrack::ReadPacket( u_int16_t packetIndex, u_int8_t** ppBytes, u_int32_t* pNumBytes, u_int32_t ssrc, bool addHeader, bool addPayload){ if (m_pReadHint == NULL) { throw new MP4Error("no hint has been read", "MP4ReadRtpPacket"); } if (!addHeader && !addPayload) { throw new MP4Error("no data requested", "MP4ReadRtpPacket"); } MP4RtpPacket* pPacket = m_pReadHint->GetPacket(packetIndex); *pNumBytes = 0; if (addHeader) { *pNumBytes += 12; } if (addPayload) { *pNumBytes += pPacket->GetDataSize(); } // if needed, allocate the packet memory bool buffer_malloc = false; if (*ppBytes == NULL) { *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes); buffer_malloc = true; } try { u_int8_t* pDest = *ppBytes; if (addHeader) { *pDest++ = 0x80 | (pPacket->GetPBit() << 5) | (pPacket->GetXBit() << 4); *pDest++ = (pPacket->GetMBit() << 7) | pPacket->GetPayload(); *((u_int16_t*)pDest) = htons(m_rtpSequenceStart + pPacket->GetSequenceNumber()); pDest += 2; *((u_int32_t*)pDest) = htonl(m_rtpTimestampStart + (u_int32_t)m_readHintTimestamp); pDest += 4; *((u_int32_t*)pDest) = htonl(ssrc); pDest += 4; } if (addPayload) { pPacket->GetData(pDest); } } catch (MP4Error* e) { if (buffer_malloc) { MP4Free(*ppBytes); *ppBytes = NULL; } throw e; } VERBOSE_READ_HINT(m_pFile->GetVerbosity(), printf("ReadPacket: %u ", packetIndex); MP4HexDump(*ppBytes, *pNumBytes););}MP4Timestamp MP4RtpHintTrack::GetRtpTimestampStart(){ if (m_pRefTrack == NULL) { InitRefTrack(); InitRtpStart(); } return m_rtpTimestampStart;}void MP4RtpHintTrack::SetRtpTimestampStart(MP4Timestamp start){ if (!m_pTsroProperty) { MP4Atom* pTsroAtom = m_pFile->AddDescendantAtoms(m_pTrakAtom, "udta.hnti.rtp .tsro"); ASSERT(pTsroAtom); pTsroAtom->FindProperty("offset", (MP4Property**)&m_pTsroProperty); ASSERT(m_pTsroProperty); } m_pTsroProperty->SetValue(start); m_rtpTimestampStart = start;}void MP4RtpHintTrack::InitPayload(){ ASSERT(m_pTrakAtom); if (m_pRtpMapProperty == NULL) { m_pTrakAtom->FindProperty( "trak.udta.hinf.payt.rtpMap", (MP4Property**)&m_pRtpMapProperty); } if (m_pPayloadNumberProperty == NULL) { m_pTrakAtom->FindProperty( "trak.udta.hinf.payt.payloadNumber", (MP4Property**)&m_pPayloadNumberProperty); } if (m_pMaxPacketSizeProperty == NULL) { m_pTrakAtom->FindProperty( "trak.mdia.minf.stbl.stsd.rtp .maxPacketSize", (MP4Property**)&m_pMaxPacketSizeProperty); }}void MP4RtpHintTrack::GetPayload( char** ppPayloadName, u_int8_t* pPayloadNumber, u_int16_t* pMaxPayloadSize, char **ppEncodingParams){ const char* pRtpMap; char* pSlash; u_int32_t length; InitPayload(); if (ppPayloadName || ppEncodingParams) { if (ppPayloadName) *ppPayloadName = NULL; if (ppEncodingParams) *ppEncodingParams = NULL; if (m_pRtpMapProperty) { pRtpMap = m_pRtpMapProperty->GetValue();#if SIMON_CHANGED pSlash = (char *) strchr(pRtpMap, '/');#else pSlash = strchr(pRtpMap, '/');#endif if (pSlash) { length = pSlash - pRtpMap; } else { length = strlen(pRtpMap); } if (ppPayloadName) { *ppPayloadName = (char*)MP4Calloc(length + 1); strncpy(*ppPayloadName, pRtpMap, length); } if (pSlash && ppEncodingParams) { pSlash++; pSlash = strchr(pSlash, '/'); if (pSlash != NULL) { pSlash++; if (pSlash != '\0') { length = strlen(pRtpMap) - (pSlash - pRtpMap); *ppEncodingParams = (char *)MP4Calloc(length + 1); strncpy(*ppEncodingParams, pSlash, length); } } } } } if (pPayloadNumber) { if (m_pPayloadNumberProperty) { *pPayloadNumber = m_pPayloadNumberProperty->GetValue(); } else { *pPayloadNumber = 0; } } if (pMaxPayloadSize) { if (m_pMaxPacketSizeProperty) { *pMaxPayloadSize = m_pMaxPacketSizeProperty->GetValue(); } else { *pMaxPayloadSize = 0; } }}void MP4RtpHintTrack::SetPayload( const char* payloadName, u_int8_t payloadNumber, u_int16_t maxPayloadSize, const char *encoding_parms, bool include_rtp_map, bool include_mpeg4_esid){ InitRefTrack(); InitPayload(); ASSERT(m_pRtpMapProperty); ASSERT(m_pPayloadNumberProperty); ASSERT(m_pMaxPacketSizeProperty); size_t len = strlen(payloadName) + 16; if (encoding_parms != NULL) { size_t temp = strlen(encoding_parms); if (temp == 0) { encoding_parms = NULL; } else { len += temp; } } char* rtpMapBuf = (char*)MP4Malloc(len); sprintf(rtpMapBuf, "%s/%u%c%s", payloadName, GetTimeScale(), encoding_parms != NULL ? '/' : '\0', encoding_parms == NULL ? "" : encoding_parms); m_pRtpMapProperty->SetValue(rtpMapBuf); m_pPayloadNumberProperty->SetValue(payloadNumber); if (maxPayloadSize == 0) { maxPayloadSize = 1460; } m_pMaxPacketSizeProperty->SetValue(maxPayloadSize); // set sdp media type const char* sdpMediaType; if (!strcmp(m_pRefTrack->GetType(), MP4_AUDIO_TRACK_TYPE)) { sdpMediaType = "audio"; } else if (!strcmp(m_pRefTrack->GetType(), MP4_VIDEO_TRACK_TYPE)) { sdpMediaType = "video"; } else if (!strcmp(m_pRefTrack->GetType(), MP4_CNTL_TRACK_TYPE)) { sdpMediaType = "control"; } else { sdpMediaType = "application"; } char* sdpBuf = (char*)MP4Malloc( strlen(sdpMediaType) + strlen(rtpMapBuf) + 256); uint32_t buflen; buflen = sprintf(sdpBuf, "m=%s 0 RTP/AVP %u\015\012" "a=control:trackID=%u\015\012", sdpMediaType, payloadNumber, m_trackId); if (include_rtp_map) { buflen += sprintf(sdpBuf + buflen, "a=rtpmap:%u %s\015\012", payloadNumber, rtpMapBuf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -