liveMedia/MPEG4LATMAudioRTPSource.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-2012 Live Networks, Inc.  All rights reserved.
00018 // MPEG-4 audio, using LATM multiplexing
00019 // Implementation
00020 
00021 #include "MPEG4LATMAudioRTPSource.hh"
00022 
00024 
00025 class LATMBufferedPacket: public BufferedPacket {
00026 public:
00027   LATMBufferedPacket(Boolean includeLATMDataLengthField);
00028   virtual ~LATMBufferedPacket();
00029 
00030 private: // redefined virtual functions
00031   virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00032                                  unsigned dataSize);
00033 
00034 private:
00035   Boolean fIncludeLATMDataLengthField;
00036 };
00037 
00038 class LATMBufferedPacketFactory: public BufferedPacketFactory {
00039 private: // redefined virtual functions
00040   virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00041 };
00042 
00044 
00045 MPEG4LATMAudioRTPSource*
00046 MPEG4LATMAudioRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00047                                    unsigned char rtpPayloadFormat,
00048                                    unsigned rtpTimestampFrequency) {
00049   return new MPEG4LATMAudioRTPSource(env, RTPgs, rtpPayloadFormat,
00050                                      rtpTimestampFrequency);
00051 }
00052 
00053 MPEG4LATMAudioRTPSource
00054 ::MPEG4LATMAudioRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00055                           unsigned char rtpPayloadFormat,
00056                           unsigned rtpTimestampFrequency)
00057   : MultiFramedRTPSource(env, RTPgs,
00058                          rtpPayloadFormat, rtpTimestampFrequency,
00059                          new LATMBufferedPacketFactory),
00060     fIncludeLATMDataLengthField(True) {
00061 }
00062 
00063 MPEG4LATMAudioRTPSource::~MPEG4LATMAudioRTPSource() {
00064 }
00065 
00066 void MPEG4LATMAudioRTPSource::omitLATMDataLengthField() {
00067   fIncludeLATMDataLengthField = False;
00068 }
00069 
00070 Boolean MPEG4LATMAudioRTPSource
00071 ::processSpecialHeader(BufferedPacket* packet,
00072                        unsigned& resultSpecialHeaderSize) {
00073   fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame;
00074           // whether the *previous* packet ended a frame
00075 
00076   // The RTP "M" (marker) bit indicates the last fragment of a frame:
00077   fCurrentPacketCompletesFrame = packet->rtpMarkerBit();
00078 
00079   // There is no special header
00080   resultSpecialHeaderSize = 0;
00081   return True;
00082 }
00083 
00084 char const* MPEG4LATMAudioRTPSource::MIMEtype() const {
00085   return "audio/MP4A-LATM";
00086 }
00087 
00088 
00090 
00091 LATMBufferedPacket::LATMBufferedPacket(Boolean includeLATMDataLengthField)
00092   : fIncludeLATMDataLengthField(includeLATMDataLengthField) {
00093 }
00094 
00095 LATMBufferedPacket::~LATMBufferedPacket() {
00096 }
00097 
00098 unsigned LATMBufferedPacket
00099 ::nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {
00100   // Look at the LATM data length byte(s), to determine the size
00101   // of the LATM payload.
00102   unsigned resultFrameSize = 0;
00103   unsigned i;
00104   for (i = 0; i < dataSize; ++i) {
00105     resultFrameSize += framePtr[i];
00106     if (framePtr[i] != 0xFF) break;
00107   }
00108   ++i;
00109   if (fIncludeLATMDataLengthField) {
00110     resultFrameSize += i;
00111   } else {
00112     framePtr += i;
00113     dataSize -= i;
00114   }
00115 
00116   return (resultFrameSize <= dataSize) ? resultFrameSize : dataSize;
00117 }
00118 
00119 BufferedPacket* LATMBufferedPacketFactory
00120 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00121   MPEG4LATMAudioRTPSource* source = (MPEG4LATMAudioRTPSource*)ourSource;
00122   return new LATMBufferedPacket(source->returnedFrameIncludesLATMDataLengthField());
00123 }
00124 
00125 
00127 
00128 static Boolean getNibble(char const*& configStr,
00129                          unsigned char& resultNibble) {
00130   char c = configStr[0];
00131   if (c == '\0') return False; // we've reached the end
00132 
00133   if (c >= '0' && c <= '9') {
00134     resultNibble = c - '0';
00135   } else if (c >= 'A' && c <= 'F') {
00136     resultNibble = 10 + c - 'A';
00137   } else if (c >= 'a' && c <= 'f') {
00138     resultNibble = 10 + c - 'a';
00139   } else {
00140     return False;
00141   }
00142 
00143   ++configStr; // move to the next nibble
00144   return True;
00145 }
00146 
00147 static Boolean getByte(char const*& configStr, unsigned char& resultByte) {
00148   resultByte = 0; // by default, in case parsing fails
00149 
00150   unsigned char firstNibble;
00151   if (!getNibble(configStr, firstNibble)) return False;
00152   resultByte = firstNibble<<4;
00153 
00154   unsigned char secondNibble = 0;
00155   if (!getNibble(configStr, secondNibble) && configStr[0] != '\0') {
00156     // There's a second nibble, but it's malformed
00157     return False;
00158   }
00159   resultByte |= secondNibble;
00160 
00161   return True;
00162 }
00163 
00164 Boolean
00165 parseStreamMuxConfigStr(char const* configStr,
00166                         // result parameters:
00167                         Boolean& audioMuxVersion,
00168                         Boolean& allStreamsSameTimeFraming,
00169                         unsigned char& numSubFrames,
00170                         unsigned char& numProgram,
00171                         unsigned char& numLayer,
00172                         unsigned char*& audioSpecificConfig,
00173                         unsigned& audioSpecificConfigSize) {
00174   // Set default versions of the result parameters:
00175   audioMuxVersion = 0;
00176   allStreamsSameTimeFraming = 1;
00177   numSubFrames = numProgram = numLayer = 0;
00178   audioSpecificConfig = NULL;
00179   audioSpecificConfigSize = 0;
00180 
00181   do {
00182     if (configStr == NULL) break;
00183 
00184     unsigned char nextByte;
00185 
00186     if (!getByte(configStr, nextByte)) break;
00187     audioMuxVersion = (nextByte&0x80)>>7;
00188     if (audioMuxVersion != 0) break;
00189 
00190     allStreamsSameTimeFraming = (nextByte&0x40)>>6;
00191     numSubFrames = (nextByte&0x3F);
00192 
00193     if (!getByte(configStr, nextByte)) break;
00194     numProgram = (nextByte&0xF0)>>4;
00195 
00196     numLayer = (nextByte&0x0E)>>1;
00197 
00198     // The one remaining bit, and the rest of the string,
00199     // are used for "audioSpecificConfig":
00200     unsigned char remainingBit = nextByte&1;
00201 
00202     unsigned ascSize = (strlen(configStr)+1)/2 + 1;
00203     audioSpecificConfig = new unsigned char[ascSize];
00204 
00205     Boolean parseSuccess;
00206     unsigned i = 0;
00207     do {
00208       nextByte = 0;
00209       parseSuccess = getByte(configStr, nextByte);
00210       audioSpecificConfig[i++] = (remainingBit<<7)|((nextByte&0xFE)>>1);
00211       remainingBit = nextByte&1;
00212     } while (parseSuccess);
00213     if (i != ascSize) break; // part of the remaining string was bad
00214 
00215     audioSpecificConfigSize = ascSize;
00216     return True; // parsing succeeded
00217   } while (0);
00218 
00219   delete[] audioSpecificConfig;
00220   return False; // parsing failed
00221 }
00222 
00223 unsigned char* parseStreamMuxConfigStr(char const* configStr,
00224                                        // result parameter:
00225                                        unsigned& audioSpecificConfigSize) {
00226   Boolean audioMuxVersion, allStreamsSameTimeFraming;
00227   unsigned char numSubFrames, numProgram, numLayer;
00228   unsigned char* audioSpecificConfig;
00229 
00230   if (!parseStreamMuxConfigStr(configStr,
00231                                audioMuxVersion, allStreamsSameTimeFraming,
00232                                numSubFrames, numProgram, numLayer,
00233                                audioSpecificConfig, audioSpecificConfigSize)) {
00234     audioSpecificConfigSize = 0;
00235     return NULL;
00236   }
00237 
00238   return audioSpecificConfig;
00239 }
00240 
00241 unsigned char* parseGeneralConfigStr(char const* configStr,
00242                                      // result parameter:
00243                                      unsigned& configSize) {
00244   unsigned char* config = NULL;
00245   do {
00246     if (configStr == NULL) break;
00247     configSize = (strlen(configStr)+1)/2;
00248 
00249     config = new unsigned char[configSize];
00250     if (config == NULL) break;
00251 
00252     unsigned i;
00253     for (i = 0; i < configSize; ++i) {
00254       if (!getByte(configStr, config[i])) break;
00255     }
00256     if (i != configSize) break; // part of the string was bad
00257 
00258     return config;
00259   } while (0);
00260 
00261   configSize = 0;
00262   delete[] config;
00263   return NULL;
00264 }

Generated on Thu May 17 07:11:47 2012 for live by  doxygen 1.5.2