liveMedia/QCELPAudioRTPSource.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-2013 Live Networks, Inc.  All rights reserved.
00018 // Qualcomm "PureVoice" (aka. "QCELP") Audio RTP Sources
00019 // Implementation
00020 
00021 #include "QCELPAudioRTPSource.hh"
00022 #include "MultiFramedRTPSource.hh"
00023 #include "FramedFilter.hh"
00024 #include <string.h>
00025 #include <stdlib.h>
00026 
00027 // This source is implemented internally by two separate sources:
00028 // (i) a RTP source for the raw (interleaved) QCELP frames, and
00029 // (ii) a deinterleaving filter that reads from this.
00030 // Define these two new classes here:
00031 
00032 class RawQCELPRTPSource: public MultiFramedRTPSource {
00033 public:
00034   static RawQCELPRTPSource* createNew(UsageEnvironment& env,
00035                                       Groupsock* RTPgs,
00036                                       unsigned char rtpPayloadFormat,
00037                                       unsigned rtpTimestampFrequency);
00038 
00039   unsigned char interleaveL() const { return fInterleaveL; }
00040   unsigned char interleaveN() const { return fInterleaveN; }
00041   unsigned char& frameIndex() { return fFrameIndex; } // index within pkt
00042 
00043 private:
00044   RawQCELPRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00045                     unsigned char rtpPayloadFormat,
00046                     unsigned rtpTimestampFrequency);
00047       // called only by createNew()
00048 
00049   virtual ~RawQCELPRTPSource();
00050 
00051 private:
00052   // redefined virtual functions:
00053   virtual Boolean processSpecialHeader(BufferedPacket* packet,
00054                                        unsigned& resultSpecialHeaderSize);
00055   virtual char const* MIMEtype() const;
00056 
00057   virtual Boolean hasBeenSynchronizedUsingRTCP();
00058 
00059 private:
00060   unsigned char fInterleaveL, fInterleaveN, fFrameIndex;
00061   unsigned fNumSuccessiveSyncedPackets;
00062 };
00063 
00064 class QCELPDeinterleaver: public FramedFilter {
00065 public:
00066   static QCELPDeinterleaver* createNew(UsageEnvironment& env,
00067                                        RawQCELPRTPSource* inputSource);
00068 
00069 private:
00070   QCELPDeinterleaver(UsageEnvironment& env,
00071                      RawQCELPRTPSource* inputSource);
00072       // called only by "createNew()"
00073 
00074   virtual ~QCELPDeinterleaver();
00075 
00076   static void afterGettingFrame(void* clientData, unsigned frameSize,
00077                                 unsigned numTruncatedBytes,
00078                                 struct timeval presentationTime,
00079                                 unsigned durationInMicroseconds);
00080   void afterGettingFrame1(unsigned frameSize, struct timeval presentationTime);
00081 
00082 private:
00083   // Redefined virtual functions:
00084   void doGetNextFrame();
00085   virtual void doStopGettingFrames();
00086 
00087 private:
00088   class QCELPDeinterleavingBuffer* fDeinterleavingBuffer;
00089   Boolean fNeedAFrame;
00090 };
00091 
00092 
00094 
00095 FramedSource*
00096 QCELPAudioRTPSource::createNew(UsageEnvironment& env,
00097                                Groupsock* RTPgs,
00098                                RTPSource*& resultRTPSource,
00099                                unsigned char rtpPayloadFormat,
00100                                unsigned rtpTimestampFrequency) {
00101   RawQCELPRTPSource* rawRTPSource;
00102   resultRTPSource = rawRTPSource
00103     = RawQCELPRTPSource::createNew(env, RTPgs, rtpPayloadFormat,
00104                                    rtpTimestampFrequency);
00105   if (resultRTPSource == NULL) return NULL;
00106 
00107   QCELPDeinterleaver* deinterleaver
00108     = QCELPDeinterleaver::createNew(env, rawRTPSource);
00109   if (deinterleaver == NULL) {
00110     Medium::close(resultRTPSource);
00111     resultRTPSource = NULL;
00112   }
00113 
00114   return deinterleaver;
00115 }
00116 
00117 
00119 
00120 // A subclass of BufferedPacket, used to separate out QCELP frames.
00121 
00122 class QCELPBufferedPacket: public BufferedPacket {
00123 public:
00124   QCELPBufferedPacket(RawQCELPRTPSource& ourSource);
00125   virtual ~QCELPBufferedPacket();
00126 
00127 private: // redefined virtual functions
00128   virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00129                                          unsigned dataSize);
00130 private:
00131   RawQCELPRTPSource& fOurSource;
00132 };
00133 
00134 class QCELPBufferedPacketFactory: public BufferedPacketFactory {
00135 private: // redefined virtual functions
00136   virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00137 };
00138 
00139 
00141 
00142 RawQCELPRTPSource*
00143 RawQCELPRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00144                              unsigned char rtpPayloadFormat,
00145                              unsigned rtpTimestampFrequency) {
00146   return new RawQCELPRTPSource(env, RTPgs, rtpPayloadFormat,
00147                                rtpTimestampFrequency);
00148 }
00149 
00150 RawQCELPRTPSource::RawQCELPRTPSource(UsageEnvironment& env,
00151                                      Groupsock* RTPgs,
00152                                      unsigned char rtpPayloadFormat,
00153                                      unsigned rtpTimestampFrequency)
00154   : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat,
00155                          rtpTimestampFrequency,
00156                          new QCELPBufferedPacketFactory),
00157   fInterleaveL(0), fInterleaveN(0), fFrameIndex(0),
00158   fNumSuccessiveSyncedPackets(0) {
00159 }
00160 
00161 RawQCELPRTPSource::~RawQCELPRTPSource() {
00162 }
00163 
00164 Boolean RawQCELPRTPSource
00165 ::processSpecialHeader(BufferedPacket* packet,
00166                        unsigned& resultSpecialHeaderSize) {
00167   unsigned char* headerStart = packet->data();
00168   unsigned packetSize = packet->dataSize();
00169 
00170   // First, check whether this packet's RTP timestamp is synchronized:
00171   if (RTPSource::hasBeenSynchronizedUsingRTCP()) {
00172     ++fNumSuccessiveSyncedPackets;
00173   } else {
00174     fNumSuccessiveSyncedPackets = 0;
00175   }
00176 
00177   // There's a 1-byte header indicating the interleave parameters
00178   if (packetSize < 1) return False;
00179 
00180   // Get the interleaving parameters from the 1-byte header,
00181   // and check them for validity:
00182   unsigned char const firstByte = headerStart[0];
00183   unsigned char const interleaveL = (firstByte&0x38)>>3;
00184   unsigned char const interleaveN = firstByte&0x07;
00185 #ifdef DEBUG
00186   fprintf(stderr, "packetSize: %d, interleaveL: %d, interleaveN: %d\n", packetSize, interleaveL, interleaveN);
00187 #endif
00188   if (interleaveL > 5 || interleaveN > interleaveL) return False; //invalid
00189 
00190   fInterleaveL = interleaveL;
00191   fInterleaveN = interleaveN;
00192   fFrameIndex = 0; // initially
00193 
00194   resultSpecialHeaderSize = 1;
00195   return True;
00196 }
00197 
00198 char const* RawQCELPRTPSource::MIMEtype() const {
00199   return "audio/QCELP";
00200 }
00201 
00202 Boolean RawQCELPRTPSource::hasBeenSynchronizedUsingRTCP() {
00203   // Don't report ourselves as being synchronized until we've received
00204   // at least a complete interleave cycle of synchronized packets.
00205   // This ensures that the receiver is currently getting a frame from
00206   // a packet that was synchronized.
00207   if (fNumSuccessiveSyncedPackets > (unsigned)(fInterleaveL+1)) {
00208     fNumSuccessiveSyncedPackets = fInterleaveL+2; // prevents overflow
00209     return True;
00210   }
00211   return False;
00212 }
00213 
00214 
00216 
00217 QCELPBufferedPacket::QCELPBufferedPacket(RawQCELPRTPSource& ourSource)
00218   : fOurSource(ourSource) {
00219 }
00220 
00221 QCELPBufferedPacket::~QCELPBufferedPacket() {
00222 }
00223 
00224 unsigned QCELPBufferedPacket::
00225   nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {
00226   // The size of the QCELP frame is determined by the first byte:
00227   if (dataSize == 0) return 0; // sanity check
00228   unsigned char const firstByte = framePtr[0];
00229 
00230   unsigned frameSize;
00231   switch (firstByte) {
00232   case 0: { frameSize = 1; break; }
00233   case 1: { frameSize = 4; break; }
00234   case 2: { frameSize = 8; break; }
00235   case 3: { frameSize = 17; break; }
00236   case 4: { frameSize = 35; break; }
00237   default: { frameSize = 0; break; }
00238   }
00239 
00240 #ifdef DEBUG
00241   fprintf(stderr, "QCELPBufferedPacket::nextEnclosedFrameSize(): frameSize: %d, dataSize: %d\n", frameSize, dataSize);
00242 #endif
00243   if (dataSize < frameSize) return 0;
00244 
00245   ++fOurSource.frameIndex();
00246   return frameSize;
00247 }
00248 
00249 BufferedPacket* QCELPBufferedPacketFactory
00250 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00251   return new QCELPBufferedPacket((RawQCELPRTPSource&)(*ourSource));
00252 }
00253 
00255 // (used to implement QCELPDeinterleaver)
00256 
00257 #define QCELP_MAX_FRAME_SIZE 35
00258 #define QCELP_MAX_INTERLEAVE_L 5
00259 #define QCELP_MAX_FRAMES_PER_PACKET 10
00260 #define QCELP_MAX_INTERLEAVE_GROUP_SIZE \
00261     ((QCELP_MAX_INTERLEAVE_L+1)*QCELP_MAX_FRAMES_PER_PACKET)
00262 
00263 class QCELPDeinterleavingBuffer {
00264 public:
00265   QCELPDeinterleavingBuffer();
00266   virtual ~QCELPDeinterleavingBuffer();
00267 
00268   void deliverIncomingFrame(unsigned frameSize,
00269                             unsigned char interleaveL,
00270                             unsigned char interleaveN,
00271                             unsigned char frameIndex,
00272                             unsigned short packetSeqNum,
00273                             struct timeval presentationTime);
00274   Boolean retrieveFrame(unsigned char* to, unsigned maxSize,
00275                         unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes,
00276                         struct timeval& resultPresentationTime);
00277 
00278   unsigned char* inputBuffer() { return fInputBuffer; }
00279   unsigned inputBufferSize() const { return QCELP_MAX_FRAME_SIZE; }
00280 
00281 private:
00282   class FrameDescriptor {
00283   public:
00284     FrameDescriptor();
00285     virtual ~FrameDescriptor();
00286 
00287     unsigned frameSize;
00288     unsigned char* frameData;
00289     struct timeval presentationTime;
00290   };
00291 
00292   // Use two banks of descriptors - one for incoming, one for outgoing
00293   FrameDescriptor fFrames[QCELP_MAX_INTERLEAVE_GROUP_SIZE][2];
00294   unsigned char fIncomingBankId; // toggles between 0 and 1
00295   unsigned char fIncomingBinMax; // in the incoming bank
00296   unsigned char fOutgoingBinMax; // in the outgoing bank
00297   unsigned char fNextOutgoingBin;
00298   Boolean fHaveSeenPackets;
00299   u_int16_t fLastPacketSeqNumForGroup;
00300   unsigned char* fInputBuffer;
00301   struct timeval fLastRetrievedPresentationTime;
00302 };
00303 
00304 
00306 
00307 QCELPDeinterleaver*
00308 QCELPDeinterleaver::createNew(UsageEnvironment& env,
00309                               RawQCELPRTPSource* inputSource) {
00310   return new QCELPDeinterleaver(env, inputSource);
00311 }
00312 
00313 QCELPDeinterleaver::QCELPDeinterleaver(UsageEnvironment& env,
00314                                        RawQCELPRTPSource* inputSource)
00315   : FramedFilter(env, inputSource),
00316     fNeedAFrame(False) {
00317   fDeinterleavingBuffer = new QCELPDeinterleavingBuffer();
00318 }
00319 
00320 QCELPDeinterleaver::~QCELPDeinterleaver() {
00321   delete fDeinterleavingBuffer;
00322 }
00323 
00324 static unsigned const uSecsPerFrame = 20000; // 20 ms
00325 
00326 void QCELPDeinterleaver::doGetNextFrame() {
00327   // First, try getting a frame from the deinterleaving buffer:
00328   if (fDeinterleavingBuffer->retrieveFrame(fTo, fMaxSize,
00329                                            fFrameSize, fNumTruncatedBytes,
00330                                            fPresentationTime)) {
00331     // Success!
00332     fNeedAFrame = False;
00333 
00334     fDurationInMicroseconds = uSecsPerFrame;
00335 
00336     // Call our own 'after getting' function.  Because we're not a 'leaf'
00337     // source, we can call this directly, without risking
00338     // infinite recursion
00339     afterGetting(this);
00340     return;
00341   }
00342 
00343   // No luck, so ask our source for help:
00344   fNeedAFrame = True;
00345   if (!fInputSource->isCurrentlyAwaitingData()) {
00346     fInputSource->getNextFrame(fDeinterleavingBuffer->inputBuffer(),
00347                                fDeinterleavingBuffer->inputBufferSize(),
00348                                afterGettingFrame, this,
00349                                FramedSource::handleClosure, this);
00350   }
00351 }
00352 
00353 void QCELPDeinterleaver::doStopGettingFrames() {
00354   fNeedAFrame = False;
00355   fInputSource->stopGettingFrames();
00356 }
00357 
00358 void QCELPDeinterleaver
00359 ::afterGettingFrame(void* clientData, unsigned frameSize,
00360                     unsigned /*numTruncatedBytes*/,
00361                     struct timeval presentationTime,
00362                     unsigned /*durationInMicroseconds*/) {
00363   QCELPDeinterleaver* deinterleaver = (QCELPDeinterleaver*)clientData;
00364   deinterleaver->afterGettingFrame1(frameSize, presentationTime);
00365 }
00366 
00367 void QCELPDeinterleaver
00368 ::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) {
00369   RawQCELPRTPSource* source = (RawQCELPRTPSource*)fInputSource;
00370 
00371   // First, put the frame into our deinterleaving buffer:
00372   fDeinterleavingBuffer
00373     ->deliverIncomingFrame(frameSize, source->interleaveL(),
00374                            source->interleaveN(), source->frameIndex(),
00375                            source->curPacketRTPSeqNum(),
00376                            presentationTime);
00377 
00378   // Then, try delivering a frame to the client (if he wants one):
00379   if (fNeedAFrame) doGetNextFrame();
00380 }
00381 
00382 
00384 
00385 QCELPDeinterleavingBuffer::QCELPDeinterleavingBuffer()
00386   : fIncomingBankId(0), fIncomingBinMax(0),
00387     fOutgoingBinMax(0), fNextOutgoingBin(0),
00388     fHaveSeenPackets(False) {
00389   fInputBuffer = new unsigned char[QCELP_MAX_FRAME_SIZE];
00390 }
00391 
00392 QCELPDeinterleavingBuffer::~QCELPDeinterleavingBuffer() {
00393   delete[] fInputBuffer;
00394 }
00395 
00396 void QCELPDeinterleavingBuffer
00397 ::deliverIncomingFrame(unsigned frameSize,
00398                        unsigned char interleaveL,
00399                        unsigned char interleaveN,
00400                        unsigned char frameIndex,
00401                        unsigned short packetSeqNum,
00402                        struct timeval presentationTime) {
00403   // First perform a sanity check on the parameters:
00404   // (This is overkill, as the source should have already done this.)
00405   if (frameSize > QCELP_MAX_FRAME_SIZE
00406       || interleaveL > QCELP_MAX_INTERLEAVE_L || interleaveN > interleaveL
00407       || frameIndex == 0 || frameIndex > QCELP_MAX_FRAMES_PER_PACKET) {
00408 #ifdef DEBUG
00409     fprintf(stderr, "QCELPDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, interleaveL, interleaveN, frameIndex);
00410 #endif
00411     return;
00412   }
00413 
00414   // The input "presentationTime" was that of the first frame in this
00415   // packet.  Update it for the current frame:
00416   unsigned uSecIncrement = (frameIndex-1)*(interleaveL+1)*uSecsPerFrame;
00417   presentationTime.tv_usec += uSecIncrement;
00418   presentationTime.tv_sec += presentationTime.tv_usec/1000000;
00419   presentationTime.tv_usec = presentationTime.tv_usec%1000000;
00420 
00421   // Next, check whether this packet is part of a new interleave group
00422   if (!fHaveSeenPackets
00423       || seqNumLT(fLastPacketSeqNumForGroup, packetSeqNum)) {
00424     // We've moved to a new interleave group
00425     fHaveSeenPackets = True;
00426     fLastPacketSeqNumForGroup = packetSeqNum + interleaveL - interleaveN;
00427 
00428     // Switch the incoming and outgoing banks:
00429     fIncomingBankId ^= 1;
00430     unsigned char tmp = fIncomingBinMax;
00431     fIncomingBinMax = fOutgoingBinMax;
00432     fOutgoingBinMax = tmp;
00433     fNextOutgoingBin = 0;
00434   }
00435 
00436   // Now move the incoming frame into the appropriate bin:
00437   unsigned const binNumber
00438     = interleaveN + (frameIndex-1)*(interleaveL+1);
00439   FrameDescriptor& inBin = fFrames[binNumber][fIncomingBankId];
00440   unsigned char* curBuffer = inBin.frameData;
00441   inBin.frameData = fInputBuffer;
00442   inBin.frameSize = frameSize;
00443   inBin.presentationTime = presentationTime;
00444 
00445   if (curBuffer == NULL) curBuffer = new unsigned char[QCELP_MAX_FRAME_SIZE];
00446   fInputBuffer = curBuffer;
00447 
00448   if (binNumber >= fIncomingBinMax) {
00449     fIncomingBinMax = binNumber + 1;
00450   }
00451 }
00452 
00453 Boolean QCELPDeinterleavingBuffer
00454 ::retrieveFrame(unsigned char* to, unsigned maxSize,
00455                 unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes,
00456                 struct timeval& resultPresentationTime) {
00457   if (fNextOutgoingBin >= fOutgoingBinMax) return False; // none left
00458 
00459   FrameDescriptor& outBin = fFrames[fNextOutgoingBin][fIncomingBankId^1];
00460   unsigned char* fromPtr;
00461   unsigned char fromSize = outBin.frameSize;
00462   outBin.frameSize = 0; // for the next time this bin is used
00463 
00464   // Check whether this frame is missing; if so, return an 'erasure' frame:
00465   unsigned char erasure = 14;
00466   if (fromSize == 0) {
00467     fromPtr = &erasure;
00468     fromSize = 1;
00469 
00470     // Compute this erasure frame's presentation time via extrapolation:
00471     resultPresentationTime = fLastRetrievedPresentationTime;
00472     resultPresentationTime.tv_usec += uSecsPerFrame;
00473     if (resultPresentationTime.tv_usec >= 1000000) {
00474       ++resultPresentationTime.tv_sec;
00475       resultPresentationTime.tv_usec -= 1000000;
00476     }
00477   } else {
00478     // Normal case - a frame exists:
00479     fromPtr = outBin.frameData;
00480     resultPresentationTime = outBin.presentationTime;
00481   }
00482 
00483   fLastRetrievedPresentationTime = resultPresentationTime;
00484 
00485   if (fromSize > maxSize) {
00486     resultNumTruncatedBytes = fromSize - maxSize;
00487     resultFrameSize = maxSize;
00488   } else {
00489     resultNumTruncatedBytes = 0;
00490     resultFrameSize = fromSize;
00491   }
00492   memmove(to, fromPtr, resultFrameSize);
00493 
00494   ++fNextOutgoingBin;
00495   return True;
00496 }
00497 
00498 QCELPDeinterleavingBuffer::FrameDescriptor::FrameDescriptor()
00499   : frameSize(0), frameData(NULL) {
00500 }
00501 
00502 QCELPDeinterleavingBuffer::FrameDescriptor::~FrameDescriptor() {
00503   delete[] frameData;
00504 }

Generated on Mon Apr 29 13:28:03 2013 for live by  doxygen 1.5.2