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

Generated on Fri Dec 19 21:58:19 2008 for live by  doxygen 1.5.2