liveMedia/MultiFramedRTPSink.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2014 Live Networks, Inc.  All rights reserved.
00018 // RTP sink for a common kind of payload format: Those which pack multiple,
00019 // complete codec frames (as many as possible) into each RTP packet.
00020 // Implementation
00021 
00022 #include "MultiFramedRTPSink.hh"
00023 #include "GroupsockHelper.hh"
00024 
00026 
00027 void MultiFramedRTPSink::setPacketSizes(unsigned preferredPacketSize,
00028                                         unsigned maxPacketSize) {
00029   if (preferredPacketSize > maxPacketSize || preferredPacketSize == 0) return;
00030       // sanity check
00031 
00032   delete fOutBuf;
00033   fOutBuf = new OutPacketBuffer(preferredPacketSize, maxPacketSize);
00034   fOurMaxPacketSize = maxPacketSize; // save value, in case subclasses need it
00035 }
00036 
00037 MultiFramedRTPSink::MultiFramedRTPSink(UsageEnvironment& env,
00038                                        Groupsock* rtpGS,
00039                                        unsigned char rtpPayloadType,
00040                                        unsigned rtpTimestampFrequency,
00041                                        char const* rtpPayloadFormatName,
00042                                        unsigned numChannels)
00043   : RTPSink(env, rtpGS, rtpPayloadType, rtpTimestampFrequency,
00044             rtpPayloadFormatName, numChannels),
00045     fOutBuf(NULL), fCurFragmentationOffset(0), fPreviousFrameEndedFragmentation(False),
00046     fOnSendErrorFunc(NULL), fOnSendErrorData(NULL) {
00047   setPacketSizes(1000, 1448);
00048       // Default max packet size (1500, minus allowance for IP, UDP, UMTP headers)
00049       // (Also, make it a multiple of 4 bytes, just in case that matters.)
00050 }
00051 
00052 MultiFramedRTPSink::~MultiFramedRTPSink() {
00053   delete fOutBuf;
00054 }
00055 
00056 void MultiFramedRTPSink
00057 ::doSpecialFrameHandling(unsigned /*fragmentationOffset*/,
00058                          unsigned char* /*frameStart*/,
00059                          unsigned /*numBytesInFrame*/,
00060                          struct timeval framePresentationTime,
00061                          unsigned /*numRemainingBytes*/) {
00062   // default implementation: If this is the first frame in the packet,
00063   // use its presentationTime for the RTP timestamp:
00064   if (isFirstFrameInPacket()) {
00065     setTimestamp(framePresentationTime);
00066   }
00067 }
00068 
00069 Boolean MultiFramedRTPSink::allowFragmentationAfterStart() const {
00070   return False; // by default
00071 }
00072 
00073 Boolean MultiFramedRTPSink::allowOtherFramesAfterLastFragment() const {
00074   return False; // by default
00075 }
00076 
00077 Boolean MultiFramedRTPSink
00078 ::frameCanAppearAfterPacketStart(unsigned char const* /*frameStart*/,
00079                                  unsigned /*numBytesInFrame*/) const {
00080   return True; // by default
00081 }
00082 
00083 unsigned MultiFramedRTPSink::specialHeaderSize() const {
00084   // default implementation: Assume no special header:
00085   return 0;
00086 }
00087 
00088 unsigned MultiFramedRTPSink::frameSpecificHeaderSize() const {
00089   // default implementation: Assume no frame-specific header:
00090   return 0;
00091 }
00092 
00093 unsigned MultiFramedRTPSink::computeOverflowForNewFrame(unsigned newFrameSize) const {
00094   // default implementation: Just call numOverflowBytes()
00095   return fOutBuf->numOverflowBytes(newFrameSize);
00096 }
00097 
00098 void MultiFramedRTPSink::setMarkerBit() {
00099   unsigned rtpHdr = fOutBuf->extractWord(0);
00100   rtpHdr |= 0x00800000;
00101   fOutBuf->insertWord(rtpHdr, 0);
00102 }
00103 
00104 void MultiFramedRTPSink::setTimestamp(struct timeval framePresentationTime) {
00105   // First, convert the presentation time to a 32-bit RTP timestamp:
00106   fCurrentTimestamp = convertToRTPTimestamp(framePresentationTime);
00107 
00108   // Then, insert it into the RTP packet:
00109   fOutBuf->insertWord(fCurrentTimestamp, fTimestampPosition);
00110 }
00111 
00112 void MultiFramedRTPSink::setSpecialHeaderWord(unsigned word,
00113                                               unsigned wordPosition) {
00114   fOutBuf->insertWord(word, fSpecialHeaderPosition + 4*wordPosition);
00115 }
00116 
00117 void MultiFramedRTPSink::setSpecialHeaderBytes(unsigned char const* bytes,
00118                                                unsigned numBytes,
00119                                                unsigned bytePosition) {
00120   fOutBuf->insert(bytes, numBytes, fSpecialHeaderPosition + bytePosition);
00121 }
00122 
00123 void MultiFramedRTPSink::setFrameSpecificHeaderWord(unsigned word,
00124                                                     unsigned wordPosition) {
00125   fOutBuf->insertWord(word, fCurFrameSpecificHeaderPosition + 4*wordPosition);
00126 }
00127 
00128 void MultiFramedRTPSink::setFrameSpecificHeaderBytes(unsigned char const* bytes,
00129                                                      unsigned numBytes,
00130                                                      unsigned bytePosition) {
00131   fOutBuf->insert(bytes, numBytes, fCurFrameSpecificHeaderPosition + bytePosition);
00132 }
00133 
00134 void MultiFramedRTPSink::setFramePadding(unsigned numPaddingBytes) {
00135   if (numPaddingBytes > 0) {
00136     // Add the padding bytes (with the last one being the padding size):
00137     unsigned char paddingBuffer[255]; //max padding
00138     memset(paddingBuffer, 0, numPaddingBytes);
00139     paddingBuffer[numPaddingBytes-1] = numPaddingBytes;
00140     fOutBuf->enqueue(paddingBuffer, numPaddingBytes);
00141 
00142     // Set the RTP padding bit:
00143     unsigned rtpHdr = fOutBuf->extractWord(0);
00144     rtpHdr |= 0x20000000;
00145     fOutBuf->insertWord(rtpHdr, 0);
00146   }
00147 }
00148 
00149 Boolean MultiFramedRTPSink::continuePlaying() {
00150   // Send the first packet.
00151   // (This will also schedule any future sends.)
00152   buildAndSendPacket(True);
00153   return True;
00154 }
00155 
00156 void MultiFramedRTPSink::stopPlaying() {
00157   fOutBuf->resetPacketStart();
00158   fOutBuf->resetOffset();
00159   fOutBuf->resetOverflowData();
00160 
00161   // Then call the default "stopPlaying()" function:
00162   MediaSink::stopPlaying();
00163 }
00164 
00165 void MultiFramedRTPSink::buildAndSendPacket(Boolean isFirstPacket) {
00166   fIsFirstPacket = isFirstPacket;
00167 
00168   // Set up the RTP header:
00169   unsigned rtpHdr = 0x80000000; // RTP version 2; marker ('M') bit not set (by default; it can be set later)
00170   rtpHdr |= (fRTPPayloadType<<16);
00171   rtpHdr |= fSeqNo; // sequence number
00172   fOutBuf->enqueueWord(rtpHdr);
00173 
00174   // Note where the RTP timestamp will go.
00175   // (We can't fill this in until we start packing payload frames.)
00176   fTimestampPosition = fOutBuf->curPacketSize();
00177   fOutBuf->skipBytes(4); // leave a hole for the timestamp
00178 
00179   fOutBuf->enqueueWord(SSRC());
00180 
00181   // Allow for a special, payload-format-specific header following the
00182   // RTP header:
00183   fSpecialHeaderPosition = fOutBuf->curPacketSize();
00184   fSpecialHeaderSize = specialHeaderSize();
00185   fOutBuf->skipBytes(fSpecialHeaderSize);
00186 
00187   // Begin packing as many (complete) frames into the packet as we can:
00188   fTotalFrameSpecificHeaderSizes = 0;
00189   fNoFramesLeft = False;
00190   fNumFramesUsedSoFar = 0;
00191   packFrame();
00192 }
00193 
00194 void MultiFramedRTPSink::packFrame() {
00195   // Get the next frame.
00196 
00197   // First, see if we have an overflow frame that was too big for the last pkt
00198   if (fOutBuf->haveOverflowData()) {
00199     // Use this frame before reading a new one from the source
00200     unsigned frameSize = fOutBuf->overflowDataSize();
00201     struct timeval presentationTime = fOutBuf->overflowPresentationTime();
00202     unsigned durationInMicroseconds = fOutBuf->overflowDurationInMicroseconds();
00203     fOutBuf->useOverflowData();
00204 
00205     afterGettingFrame1(frameSize, 0, presentationTime, durationInMicroseconds);
00206   } else {
00207     // Normal case: we need to read a new frame from the source
00208     if (fSource == NULL) return;
00209 
00210     fCurFrameSpecificHeaderPosition = fOutBuf->curPacketSize();
00211     fCurFrameSpecificHeaderSize = frameSpecificHeaderSize();
00212     fOutBuf->skipBytes(fCurFrameSpecificHeaderSize);
00213     fTotalFrameSpecificHeaderSizes += fCurFrameSpecificHeaderSize;
00214 
00215     fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(),
00216                           afterGettingFrame, this, ourHandleClosure, this);
00217   }
00218 }
00219 
00220 void MultiFramedRTPSink
00221 ::afterGettingFrame(void* clientData, unsigned numBytesRead,
00222                     unsigned numTruncatedBytes,
00223                     struct timeval presentationTime,
00224                     unsigned durationInMicroseconds) {
00225   MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;
00226   sink->afterGettingFrame1(numBytesRead, numTruncatedBytes,
00227                            presentationTime, durationInMicroseconds);
00228 }
00229 
00230 void MultiFramedRTPSink
00231 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00232                      struct timeval presentationTime,
00233                      unsigned durationInMicroseconds) {
00234   if (fIsFirstPacket) {
00235     // Record the fact that we're starting to play now:
00236     gettimeofday(&fNextSendTime, NULL);
00237   }
00238 
00239   fMostRecentPresentationTime = presentationTime;
00240   if (fInitialPresentationTime.tv_sec == 0 && fInitialPresentationTime.tv_usec == 0) {
00241     fInitialPresentationTime = presentationTime;
00242   }    
00243 
00244   if (numTruncatedBytes > 0) {
00245     unsigned const bufferSize = fOutBuf->totalBytesAvailable();
00246     envir() << "MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size ("
00247             << bufferSize << ").  "
00248             << numTruncatedBytes << " bytes of trailing data was dropped!  Correct this by increasing \"OutPacketBuffer::maxSize\" to at least "
00249             << OutPacketBuffer::maxSize + numTruncatedBytes << ", *before* creating this 'RTPSink'.  (Current value is "
00250             << OutPacketBuffer::maxSize << ".)\n";
00251   }
00252   unsigned curFragmentationOffset = fCurFragmentationOffset;
00253   unsigned numFrameBytesToUse = frameSize;
00254   unsigned overflowBytes = 0;
00255 
00256   // If we have already packed one or more frames into this packet,
00257   // check whether this new frame is eligible to be packed after them.
00258   // (This is independent of whether the packet has enough room for this
00259   // new frame; that check comes later.)
00260   if (fNumFramesUsedSoFar > 0) {
00261     if ((fPreviousFrameEndedFragmentation
00262          && !allowOtherFramesAfterLastFragment())
00263         || !frameCanAppearAfterPacketStart(fOutBuf->curPtr(), frameSize)) {
00264       // Save away this frame for next time:
00265       numFrameBytesToUse = 0;
00266       fOutBuf->setOverflowData(fOutBuf->curPacketSize(), frameSize,
00267                                presentationTime, durationInMicroseconds);
00268     }
00269   }
00270   fPreviousFrameEndedFragmentation = False;
00271 
00272   if (numFrameBytesToUse > 0) {
00273     // Check whether this frame overflows the packet
00274     if (fOutBuf->wouldOverflow(frameSize)) {
00275       // Don't use this frame now; instead, save it as overflow data, and
00276       // send it in the next packet instead.  However, if the frame is too
00277       // big to fit in a packet by itself, then we need to fragment it (and
00278       // use some of it in this packet, if the payload format permits this.)
00279       if (isTooBigForAPacket(frameSize)
00280           && (fNumFramesUsedSoFar == 0 || allowFragmentationAfterStart())) {
00281         // We need to fragment this frame, and use some of it now:
00282         overflowBytes = computeOverflowForNewFrame(frameSize);
00283         numFrameBytesToUse -= overflowBytes;
00284         fCurFragmentationOffset += numFrameBytesToUse;
00285       } else {
00286         // We don't use any of this frame now:
00287         overflowBytes = frameSize;
00288         numFrameBytesToUse = 0;
00289       }
00290       fOutBuf->setOverflowData(fOutBuf->curPacketSize() + numFrameBytesToUse,
00291                                overflowBytes, presentationTime, durationInMicroseconds);
00292     } else if (fCurFragmentationOffset > 0) {
00293       // This is the last fragment of a frame that was fragmented over
00294       // more than one packet.  Do any special handling for this case:
00295       fCurFragmentationOffset = 0;
00296       fPreviousFrameEndedFragmentation = True;
00297     }
00298   }
00299 
00300   if (numFrameBytesToUse == 0 && frameSize > 0) {
00301     // Send our packet now, because we have filled it up:
00302     sendPacketIfNecessary();
00303   } else {
00304     // Use this frame in our outgoing packet:
00305     unsigned char* frameStart = fOutBuf->curPtr();
00306     fOutBuf->increment(numFrameBytesToUse);
00307         // do this now, in case "doSpecialFrameHandling()" calls "setFramePadding()" to append padding bytes
00308 
00309     // Here's where any payload format specific processing gets done:
00310     doSpecialFrameHandling(curFragmentationOffset, frameStart,
00311                            numFrameBytesToUse, presentationTime,
00312                            overflowBytes);
00313 
00314     ++fNumFramesUsedSoFar;
00315 
00316     // Update the time at which the next packet should be sent, based
00317     // on the duration of the frame that we just packed into it.
00318     // However, if this frame has overflow data remaining, then don't
00319     // count its duration yet.
00320     if (overflowBytes == 0) {
00321       fNextSendTime.tv_usec += durationInMicroseconds;
00322       fNextSendTime.tv_sec += fNextSendTime.tv_usec/1000000;
00323       fNextSendTime.tv_usec %= 1000000;
00324     }
00325 
00326     // Send our packet now if (i) it's already at our preferred size, or
00327     // (ii) (heuristic) another frame of the same size as the one we just
00328     //      read would overflow the packet, or
00329     // (iii) it contains the last fragment of a fragmented frame, and we
00330     //      don't allow anything else to follow this or
00331     // (iv) one frame per packet is allowed:
00332     if (fOutBuf->isPreferredSize()
00333         || fOutBuf->wouldOverflow(numFrameBytesToUse)
00334         || (fPreviousFrameEndedFragmentation &&
00335             !allowOtherFramesAfterLastFragment())
00336         || !frameCanAppearAfterPacketStart(fOutBuf->curPtr() - frameSize,
00337                                            frameSize) ) {
00338       // The packet is ready to be sent now
00339       sendPacketIfNecessary();
00340     } else {
00341       // There's room for more frames; try getting another:
00342       packFrame();
00343     }
00344   }
00345 }
00346 
00347 static unsigned const rtpHeaderSize = 12;
00348 
00349 Boolean MultiFramedRTPSink::isTooBigForAPacket(unsigned numBytes) const {
00350   // Check whether a 'numBytes'-byte frame - together with a RTP header and
00351   // (possible) special headers - would be too big for an output packet:
00352   // (Later allow for RTP extension header!) #####
00353   numBytes += rtpHeaderSize + specialHeaderSize() + frameSpecificHeaderSize();
00354   return fOutBuf->isTooBigForAPacket(numBytes);
00355 }
00356 
00357 void MultiFramedRTPSink::sendPacketIfNecessary() {
00358   if (fNumFramesUsedSoFar > 0) {
00359     // Send the packet:
00360 #ifdef TEST_LOSS
00361     if ((our_random()%10) != 0) // simulate 10% packet loss #####
00362 #endif
00363       if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) {
00364         // if failure handler has been specified, call it
00365         if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData);
00366       }
00367     ++fPacketCount;
00368     fTotalOctetCount += fOutBuf->curPacketSize();
00369     fOctetCount += fOutBuf->curPacketSize()
00370       - rtpHeaderSize - fSpecialHeaderSize - fTotalFrameSpecificHeaderSizes;
00371 
00372     ++fSeqNo; // for next time
00373   }
00374 
00375   if (fOutBuf->haveOverflowData()
00376       && fOutBuf->totalBytesAvailable() > fOutBuf->totalBufferSize()/2) {
00377     // Efficiency hack: Reset the packet start pointer to just in front of
00378     // the overflow data (allowing for the RTP header and special headers),
00379     // so that we probably don't have to "memmove()" the overflow data
00380     // into place when building the next packet:
00381     unsigned newPacketStart = fOutBuf->curPacketSize()
00382       - (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize());
00383     fOutBuf->adjustPacketStart(newPacketStart);
00384   } else {
00385     // Normal case: Reset the packet start pointer back to the start:
00386     fOutBuf->resetPacketStart();
00387   }
00388   fOutBuf->resetOffset();
00389   fNumFramesUsedSoFar = 0;
00390 
00391   if (fNoFramesLeft) {
00392     // We're done:
00393     onSourceClosure();
00394   } else {
00395     // We have more frames left to send.  Figure out when the next frame
00396     // is due to start playing, then make sure that we wait this long before
00397     // sending the next packet.
00398     struct timeval timeNow;
00399     gettimeofday(&timeNow, NULL);
00400     int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
00401     int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
00402     if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:
00403       uSecondsToGo = 0;
00404     }
00405 
00406     // Delay this amount of time:
00407     nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this);
00408   }
00409 }
00410 
00411 // The following is called after each delay between packet sends:
00412 void MultiFramedRTPSink::sendNext(void* firstArg) {
00413   MultiFramedRTPSink* sink = (MultiFramedRTPSink*)firstArg;
00414   sink->buildAndSendPacket(False);
00415 }
00416 
00417 void MultiFramedRTPSink::ourHandleClosure(void* clientData) {
00418   MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;
00419   // There are no frames left, but we may have a partially built packet
00420   //  to send
00421   sink->fNoFramesLeft = True;
00422   sink->sendPacketIfNecessary();
00423 }

Generated on Tue Mar 25 14:35:35 2014 for live by  doxygen 1.5.2