📄 multiframedrtpsink.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA**********/// "liveMedia"// Copyright (c) 1996-2010 Live Networks, Inc. All rights reserved.// RTP sink for a common kind of payload format: Those which pack multiple,// complete codec frames (as many as possible) into each RTP packet.// Implementation#include "MultiFramedRTPSink.hh"#include "GroupsockHelper.hh"////////// MultiFramedRTPSink //////////void MultiFramedRTPSink::setPacketSizes(unsigned preferredPacketSize, unsigned maxPacketSize) { if (preferredPacketSize > maxPacketSize || preferredPacketSize == 0) return; // sanity check delete fOutBuf; fOutBuf = new OutPacketBuffer(preferredPacketSize, maxPacketSize); fOurMaxPacketSize = maxPacketSize; // save value, in case subclasses need it}MultiFramedRTPSink::MultiFramedRTPSink(UsageEnvironment& env, Groupsock* rtpGS, unsigned char rtpPayloadType, unsigned rtpTimestampFrequency, char const* rtpPayloadFormatName, unsigned numChannels) : RTPSink(env, rtpGS, rtpPayloadType, rtpTimestampFrequency, rtpPayloadFormatName, numChannels), fOutBuf(NULL), fCurFragmentationOffset(0), fPreviousFrameEndedFragmentation(False) { setPacketSizes(1000, 1448); // Default max packet size (1500, minus allowance for IP, UDP, UMTP headers) // (Also, make it a multiple of 4 bytes, just in case that matters.)}MultiFramedRTPSink::~MultiFramedRTPSink() { delete fOutBuf;}void MultiFramedRTPSink::doSpecialFrameHandling(unsigned /*fragmentationOffset*/, unsigned char* /*frameStart*/, unsigned /*numBytesInFrame*/, struct timeval frameTimestamp, unsigned /*numRemainingBytes*/) { // default implementation: If this is the first frame in the packet, // use its timestamp for the RTP timestamp: if (isFirstFrameInPacket()) { setTimestamp(frameTimestamp); }}Boolean MultiFramedRTPSink::allowFragmentationAfterStart() const { return False; // by default}Boolean MultiFramedRTPSink::allowOtherFramesAfterLastFragment() const { return False; // by default}Boolean MultiFramedRTPSink::frameCanAppearAfterPacketStart(unsigned char const* /*frameStart*/, unsigned /*numBytesInFrame*/) const { return True; // by default}unsigned MultiFramedRTPSink::specialHeaderSize() const { // default implementation: Assume no special header: return 0;}unsigned MultiFramedRTPSink::frameSpecificHeaderSize() const { // default implementation: Assume no frame-specific header: return 0;}unsigned MultiFramedRTPSink::computeOverflowForNewFrame(unsigned newFrameSize) const { // default implementation: Just call numOverflowBytes() return fOutBuf->numOverflowBytes(newFrameSize);}void MultiFramedRTPSink::setMarkerBit() { unsigned rtpHdr = fOutBuf->extractWord(0); rtpHdr |= 0x00800000; fOutBuf->insertWord(rtpHdr, 0);}void MultiFramedRTPSink::setTimestamp(struct timeval timestamp) { // First, convert the timestamp to a 32-bit RTP timestamp: fCurrentTimestamp = convertToRTPTimestamp(timestamp); // Then, insert it into the RTP packet: fOutBuf->insertWord(fCurrentTimestamp, fTimestampPosition);}void MultiFramedRTPSink::setSpecialHeaderWord(unsigned word, unsigned wordPosition) { fOutBuf->insertWord(word, fSpecialHeaderPosition + 4*wordPosition);}void MultiFramedRTPSink::setSpecialHeaderBytes(unsigned char const* bytes, unsigned numBytes, unsigned bytePosition) { fOutBuf->insert(bytes, numBytes, fSpecialHeaderPosition + bytePosition);}void MultiFramedRTPSink::setFrameSpecificHeaderWord(unsigned word, unsigned wordPosition) { fOutBuf->insertWord(word, fCurFrameSpecificHeaderPosition + 4*wordPosition);}void MultiFramedRTPSink::setFrameSpecificHeaderBytes(unsigned char const* bytes, unsigned numBytes, unsigned bytePosition) { fOutBuf->insert(bytes, numBytes, fCurFrameSpecificHeaderPosition + bytePosition);}void MultiFramedRTPSink::setFramePadding(unsigned numPaddingBytes) { if (numPaddingBytes > 0) { // Add the padding bytes (with the last one being the padding size): unsigned char paddingBuffer[255]; //max padding memset(paddingBuffer, 0, numPaddingBytes); paddingBuffer[numPaddingBytes-1] = numPaddingBytes; fOutBuf->enqueue(paddingBuffer, numPaddingBytes); // Set the RTP padding bit: unsigned rtpHdr = fOutBuf->extractWord(0); rtpHdr |= 0x20000000; fOutBuf->insertWord(rtpHdr, 0); }}Boolean MultiFramedRTPSink::continuePlaying() { // Send the first packet. // (This will also schedule any future sends.) buildAndSendPacket(True); return True;}void MultiFramedRTPSink::stopPlaying() { fOutBuf->resetPacketStart(); fOutBuf->resetOffset(); fOutBuf->resetOverflowData(); // Then call the default "stopPlaying()" function: MediaSink::stopPlaying();}void MultiFramedRTPSink::buildAndSendPacket(Boolean isFirstPacket) { fIsFirstPacket = isFirstPacket; // Set up the RTP header: unsigned rtpHdr = 0x80000000; // RTP version 2 rtpHdr |= (fRTPPayloadType<<16); rtpHdr |= fSeqNo; // sequence number fOutBuf->enqueueWord(rtpHdr); // Note where the RTP timestamp will go. // (We can't fill this in until we start packing payload frames.) fTimestampPosition = fOutBuf->curPacketSize(); fOutBuf->skipBytes(4); // leave a hole for the timestamp fOutBuf->enqueueWord(SSRC()); // Allow for a special, payload-format-specific header following the // RTP header: fSpecialHeaderPosition = fOutBuf->curPacketSize(); fSpecialHeaderSize = specialHeaderSize(); fOutBuf->skipBytes(fSpecialHeaderSize); // Begin packing as many (complete) frames into the packet as we can: fTotalFrameSpecificHeaderSizes = 0; fNoFramesLeft = False; fNumFramesUsedSoFar = 0; packFrame();}void MultiFramedRTPSink::packFrame() { // Get the next frame. // First, see if we have an overflow frame that was too big for the last pkt if (fOutBuf->haveOverflowData()) { // Use this frame before reading a new one from the source unsigned frameSize = fOutBuf->overflowDataSize(); struct timeval presentationTime = fOutBuf->overflowPresentationTime(); unsigned durationInMicroseconds = fOutBuf->overflowDurationInMicroseconds(); fOutBuf->useOverflowData(); afterGettingFrame1(frameSize, 0, presentationTime, durationInMicroseconds); } else { // Normal case: we need to read a new frame from the source if (fSource == NULL) return; fCurFrameSpecificHeaderPosition = fOutBuf->curPacketSize(); fCurFrameSpecificHeaderSize = frameSpecificHeaderSize();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -