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

Generated on Tue Jul 22 06:39:06 2008 for live by  doxygen 1.5.2