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

Generated on Fri Sep 3 02:35:41 2010 for live by  doxygen 1.5.2