liveMedia/MPEG4GenericRTPSource.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 // MPEG4-GENERIC ("audio", "video", or "application") RTP stream sources
00019 // Implementation
00020 
00021 #include "MPEG4GenericRTPSource.hh"
00022 #include "BitVector.hh"
00023 #include "MPEG4LATMAudioRTPSource.hh" // for parseGeneralConfigStr()
00024 
00026 
00027 class MPEG4GenericBufferedPacket: public BufferedPacket {
00028 public:
00029   MPEG4GenericBufferedPacket(MPEG4GenericRTPSource* ourSource);
00030   virtual ~MPEG4GenericBufferedPacket();
00031 
00032 private: // redefined virtual functions
00033   virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00034                                          unsigned dataSize);
00035 private:
00036   MPEG4GenericRTPSource* fOurSource;
00037 };
00038 
00039 class MPEG4GenericBufferedPacketFactory: public BufferedPacketFactory {
00040 private: // redefined virtual functions
00041   virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00042 };
00043 
00044 
00046 struct AUHeader {
00047   unsigned size;
00048   unsigned index; // indexDelta for the 2nd & subsequent headers
00049 };
00050 
00051 
00053 
00054 //##### NOTE: INCOMPLETE!!! Support more modes, and interleaving #####
00055 
00056 MPEG4GenericRTPSource*
00057 MPEG4GenericRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00058                                  unsigned char rtpPayloadFormat,
00059                                  unsigned rtpTimestampFrequency,
00060                                  char const* mediumName,
00061                                  char const* mode,
00062                                  unsigned sizeLength, unsigned indexLength,
00063                                  unsigned indexDeltaLength
00064                                  ) {
00065   return new MPEG4GenericRTPSource(env, RTPgs, rtpPayloadFormat,
00066                                    rtpTimestampFrequency, mediumName,
00067                                    mode, sizeLength, indexLength,
00068                                    indexDeltaLength
00069                                    );
00070 }
00071 
00072 MPEG4GenericRTPSource
00073 ::MPEG4GenericRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00074                         unsigned char rtpPayloadFormat,
00075                         unsigned rtpTimestampFrequency,
00076                         char const* mediumName,
00077                         char const* mode,
00078                         unsigned sizeLength, unsigned indexLength,
00079                         unsigned indexDeltaLength
00080                         )
00081   : MultiFramedRTPSource(env, RTPgs,
00082                          rtpPayloadFormat, rtpTimestampFrequency,
00083                          new MPEG4GenericBufferedPacketFactory),
00084   fSizeLength(sizeLength), fIndexLength(indexLength),
00085   fIndexDeltaLength(indexDeltaLength),
00086   fNumAUHeaders(0), fNextAUHeader(0), fAUHeaders(NULL) {
00087     unsigned mimeTypeLength =
00088       strlen(mediumName) + 14 /* strlen("/MPEG4-GENERIC") */ + 1;
00089     fMIMEType = new char[mimeTypeLength];
00090     if (fMIMEType != NULL) {
00091       sprintf(fMIMEType, "%s/MPEG4-GENERIC", mediumName);
00092     }
00093 
00094     fMode = strDup(mode);
00095     // Check for a "mode" that we don't yet support: //#####
00096     if (mode == NULL ||
00097         (strcmp(mode, "aac-hbr") != 0 && strcmp(mode, "generic") != 0)) {
00098       envir() << "MPEG4GenericRTPSource Warning: Unknown or unsupported \"mode\": "
00099               << mode << "\n";
00100     }
00101 }
00102 
00103 MPEG4GenericRTPSource::~MPEG4GenericRTPSource() {
00104   delete[] fAUHeaders;
00105   delete[] fMode;
00106   delete[] fMIMEType;
00107 }
00108 
00109 Boolean MPEG4GenericRTPSource
00110 ::processSpecialHeader(BufferedPacket* packet,
00111                        unsigned& resultSpecialHeaderSize) {
00112   unsigned char* headerStart = packet->data();
00113   unsigned packetSize = packet->dataSize();
00114 
00115   fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame;
00116           // whether the *previous* packet ended a frame
00117 
00118   // The RTP "M" (marker) bit indicates the last fragment of a frame:
00119   fCurrentPacketCompletesFrame = packet->rtpMarkerBit();
00120 
00121   // default values:
00122   resultSpecialHeaderSize = 0;
00123   fNumAUHeaders = 0;
00124   fNextAUHeader = 0;
00125   delete[] fAUHeaders; fAUHeaders = NULL;
00126 
00127   if (fSizeLength > 0) {
00128     // The packet begins with a "AU Header Section".  Parse it, to
00129     // determine the "AU-header"s for each frame present in this packet:
00130     resultSpecialHeaderSize += 2;
00131     if (packetSize < resultSpecialHeaderSize) return False;
00132 
00133     unsigned AU_headers_length = (headerStart[0]<<8)|headerStart[1];
00134     unsigned AU_headers_length_bytes = (AU_headers_length+7)/8;
00135     if (packetSize
00136         < resultSpecialHeaderSize + AU_headers_length_bytes) return False;
00137     resultSpecialHeaderSize += AU_headers_length_bytes;
00138 
00139     // Figure out how many AU-headers are present in the packet:
00140     int bitsAvail = AU_headers_length - (fSizeLength + fIndexLength);
00141     if (bitsAvail >= 0 && (fSizeLength + fIndexDeltaLength) > 0) {
00142       fNumAUHeaders = 1 + bitsAvail/(fSizeLength + fIndexDeltaLength);
00143     }
00144     if (fNumAUHeaders > 0) {
00145       fAUHeaders = new AUHeader[fNumAUHeaders];
00146       // Fill in each header:
00147       BitVector bv(&headerStart[2], 0, AU_headers_length);
00148       fAUHeaders[0].size = bv.getBits(fSizeLength);
00149       fAUHeaders[0].index = bv.getBits(fIndexLength);
00150 
00151       for (unsigned i = 1; i < fNumAUHeaders; ++i) {
00152         fAUHeaders[i].size = bv.getBits(fSizeLength);
00153         fAUHeaders[i].index = bv.getBits(fIndexDeltaLength);
00154       }
00155     }
00156 
00157   }
00158 
00159   return True;
00160 }
00161 
00162 char const* MPEG4GenericRTPSource::MIMEtype() const {
00163   return fMIMEType;
00164 }
00165 
00166 
00169 
00170 MPEG4GenericBufferedPacket
00171 ::MPEG4GenericBufferedPacket(MPEG4GenericRTPSource* ourSource)
00172   : fOurSource(ourSource) {
00173 }
00174 
00175 MPEG4GenericBufferedPacket::~MPEG4GenericBufferedPacket() {
00176 }
00177 
00178 unsigned MPEG4GenericBufferedPacket
00179 ::nextEnclosedFrameSize(unsigned char*& /*framePtr*/, unsigned dataSize) {
00180   // WE CURRENTLY DON'T IMPLEMENT INTERLEAVING.  FIX THIS! #####
00181   AUHeader* auHeader = fOurSource->fAUHeaders;
00182   if (auHeader == NULL) return dataSize;
00183   unsigned numAUHeaders = fOurSource->fNumAUHeaders;
00184 
00185   if (fOurSource->fNextAUHeader >= numAUHeaders) {
00186     fOurSource->envir() << "MPEG4GenericBufferedPacket::nextEnclosedFrameSize("
00187                         << dataSize << "): data error ("
00188                         << auHeader << "," << fOurSource->fNextAUHeader
00189                         << "," << numAUHeaders << ")!\n";
00190     return dataSize;
00191   }
00192 
00193   auHeader = &auHeader[fOurSource->fNextAUHeader++];
00194   return auHeader->size <= dataSize ? auHeader->size : dataSize;
00195 }
00196 
00197 BufferedPacket* MPEG4GenericBufferedPacketFactory
00198 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00199   return new MPEG4GenericBufferedPacket((MPEG4GenericRTPSource*)ourSource);
00200 }
00201 
00202 
00204 
00205 static unsigned const samplingFrequencyFromIndex[16] = {
00206   96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
00207   16000, 12000, 11025, 8000, 7350, 0, 0, 0
00208 };
00209 
00210 unsigned samplingFrequencyFromAudioSpecificConfig(char const* configStr) {
00211   unsigned char* config = NULL;
00212   unsigned result = 0; // if returned, indicates an error
00213 
00214   do {
00215     // Begin by parsing the config string:
00216     unsigned configSize;
00217     config = parseGeneralConfigStr(configStr, configSize);
00218     if (config == NULL) break;
00219 
00220     if (configSize < 2) break;
00221     unsigned char samplingFrequencyIndex = ((config[0]&0x07)<<1) | (config[1]>>7);
00222     if (samplingFrequencyIndex < 15) {
00223       result = samplingFrequencyFromIndex[samplingFrequencyIndex];
00224       break;
00225     }
00226 
00227     // Index == 15 means that the actual frequency is next (24 bits):
00228     if (configSize < 5) break;
00229     result = ((config[1]&0x7F)<<17) | (config[2]<<9) | (config[3]<<1) | (config[4]>>7);
00230   } while (0);
00231 
00232   delete[] config;
00233   return result;
00234 }

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