liveMedia/H264VideoRTPSource.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 // H.264 Video RTP Sources
00019 // Implementation
00020 
00021 #include "H264VideoRTPSource.hh"
00022 #include "Base64.hh"
00023 
00025 
00026 class H264BufferedPacket: public BufferedPacket {
00027 public:
00028   H264BufferedPacket(H264VideoRTPSource& ourSource);
00029   virtual ~H264BufferedPacket();
00030 
00031 private: // redefined virtual functions
00032   virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00033                                          unsigned dataSize);
00034 private:
00035   H264VideoRTPSource& fOurSource;
00036 };
00037 
00038 class H264BufferedPacketFactory: public BufferedPacketFactory {
00039 private: // redefined virtual functions
00040   virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00041 };
00042 
00043 
00045 
00046 H264VideoRTPSource*
00047 H264VideoRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00048                               unsigned char rtpPayloadFormat,
00049                               unsigned rtpTimestampFrequency) {
00050   return new H264VideoRTPSource(env, RTPgs, rtpPayloadFormat,
00051                                 rtpTimestampFrequency);
00052 }
00053 
00054 H264VideoRTPSource
00055 ::H264VideoRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00056                      unsigned char rtpPayloadFormat,
00057                      unsigned rtpTimestampFrequency)
00058   : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency,
00059                          new H264BufferedPacketFactory) {
00060 }
00061 
00062 H264VideoRTPSource::~H264VideoRTPSource() {
00063 }
00064 
00065 Boolean H264VideoRTPSource
00066 ::processSpecialHeader(BufferedPacket* packet,
00067                        unsigned& resultSpecialHeaderSize) {
00068   unsigned char* headerStart = packet->data();
00069   unsigned packetSize = packet->dataSize();
00070 
00071   // The header has a minimum size of 0, since the NAL header is used
00072   // as a payload header
00073   unsigned expectedHeaderSize = 0;
00074 
00075   // Check if the type field is 28 (FU-A) or 29 (FU-B)
00076   fCurPacketNALUnitType = (headerStart[0]&0x1F);
00077   switch (fCurPacketNALUnitType) {
00078   case 24: { // STAP-A
00079     expectedHeaderSize = 1; // discard the type byte
00080     break;
00081   }
00082   case 25: case 26: case 27: { // STAP-B, MTAP16, or MTAP24
00083     expectedHeaderSize = 3; // discard the type byte, and the initial DON
00084     break;
00085   }
00086   case 28: case 29: { // // FU-A or FU-B
00087     // For these NALUs, the first two bytes are the FU indicator and the FU header.
00088     // If the start bit is set, we reconstruct the original NAL header:
00089     unsigned char startBit = headerStart[1]&0x80;
00090     unsigned char endBit = headerStart[1]&0x40;
00091     if (startBit) {
00092       expectedHeaderSize = 1;
00093       if (packetSize < expectedHeaderSize) return False;
00094 
00095       headerStart[1] = (headerStart[0]&0xE0)+(headerStart[1]&0x1F);
00096       fCurrentPacketBeginsFrame = True;
00097     } else {
00098       // If the startbit is not set, both the FU indicator and header
00099       // can be discarded
00100       expectedHeaderSize = 2;
00101       if (packetSize < expectedHeaderSize) return False;
00102       fCurrentPacketBeginsFrame = False;
00103     }
00104     fCurrentPacketCompletesFrame = (endBit != 0);
00105     break;
00106   }
00107   default: {
00108     // This packet contains one or more complete, decodable NAL units
00109     fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame = True;
00110     break;
00111   }
00112   }
00113 
00114   resultSpecialHeaderSize = expectedHeaderSize;
00115   return True;
00116 }
00117 
00118 char const* H264VideoRTPSource::MIMEtype() const {
00119   return "video/H264";
00120 }
00121 
00122 SPropRecord* parseSPropParameterSets(char const* sPropParameterSetsStr,
00123                                      // result parameter:
00124                                      unsigned& numSPropRecords) {
00125   // Make a copy of the input string, so we can replace the commas with '\0's:
00126   char* inStr = strDup(sPropParameterSetsStr);
00127   if (inStr == NULL) {
00128     numSPropRecords = 0;
00129     return NULL;
00130   }
00131 
00132   // Count the number of commas (and thus the number of parameter sets):
00133   numSPropRecords = 1;
00134   char* s;
00135   for (s = inStr; *s != '\0'; ++s) {
00136     if (*s == ',') {
00137       ++numSPropRecords;
00138       *s = '\0';
00139     }
00140   }
00141 
00142   // Allocate and fill in the result array:
00143   SPropRecord* resultArray = new SPropRecord[numSPropRecords];
00144   s = inStr;
00145   for (unsigned i = 0; i < numSPropRecords; ++i) {
00146     resultArray[i].sPropBytes = base64Decode(s, resultArray[i].sPropLength);
00147     s += strlen(s) + 1;
00148   }
00149 
00150   delete[] inStr;
00151   return resultArray;
00152 }
00153 
00154 
00156 
00157 H264BufferedPacket::H264BufferedPacket(H264VideoRTPSource& ourSource)
00158   : fOurSource(ourSource) {
00159 }
00160 
00161 H264BufferedPacket::~H264BufferedPacket() {
00162 }
00163 
00164 unsigned H264BufferedPacket
00165 ::nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {
00166   unsigned resultNALUSize = 0; // if an error occurs
00167 
00168   switch (fOurSource.fCurPacketNALUnitType) {
00169   case 24: case 25: { // STAP-A or STAP-B
00170     // The first two bytes are NALU size:
00171     if (dataSize < 2) break;
00172     resultNALUSize = (framePtr[0]<<8)|framePtr[1];
00173     framePtr += 2;
00174     break;
00175   }
00176   case 26: { // MTAP16
00177     // The first two bytes are NALU size.  The next three are the DOND and TS offset:
00178     if (dataSize < 5) break;
00179     resultNALUSize = (framePtr[0]<<8)|framePtr[1];
00180     framePtr += 5;
00181     break;
00182   }
00183   case 27: { // MTAP24
00184     // The first two bytes are NALU size.  The next four are the DOND and TS offset:
00185     if (dataSize < 6) break;
00186     resultNALUSize = (framePtr[0]<<8)|framePtr[1];
00187     framePtr += 6;
00188     break;
00189   }
00190   default: {
00191     // Common case: We use the entire packet data:
00192     return dataSize;
00193   }
00194   }
00195 
00196   return (resultNALUSize <= dataSize) ? resultNALUSize : dataSize;
00197 }
00198 
00199 BufferedPacket* H264BufferedPacketFactory
00200 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00201   return new H264BufferedPacket((H264VideoRTPSource&)(*ourSource));
00202 }

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