00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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:
00032 virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00033 unsigned dataSize);
00034 private:
00035 H264VideoRTPSource& fOurSource;
00036 };
00037
00038 class H264BufferedPacketFactory: public BufferedPacketFactory {
00039 private:
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
00072
00073 unsigned expectedHeaderSize = 0;
00074
00075
00076 fCurPacketNALUnitType = (headerStart[0]&0x1F);
00077 switch (fCurPacketNALUnitType) {
00078 case 24: {
00079 expectedHeaderSize = 1;
00080 break;
00081 }
00082 case 25: case 26: case 27: {
00083 expectedHeaderSize = 3;
00084 break;
00085 }
00086 case 28: case 29: {
00087
00088
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
00099
00100 expectedHeaderSize = 2;
00101 if (packetSize < expectedHeaderSize) return False;
00102 fCurrentPacketBeginsFrame = False;
00103 }
00104 fCurrentPacketCompletesFrame = (endBit != 0);
00105 break;
00106 }
00107 default: {
00108
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
00124 unsigned& numSPropRecords) {
00125
00126 char* inStr = strDup(sPropParameterSetsStr);
00127 if (inStr == NULL) {
00128 numSPropRecords = 0;
00129 return NULL;
00130 }
00131
00132
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
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;
00167
00168 switch (fOurSource.fCurPacketNALUnitType) {
00169 case 24: case 25: {
00170
00171 if (dataSize < 2) break;
00172 resultNALUSize = (framePtr[0]<<8)|framePtr[1];
00173 framePtr += 2;
00174 break;
00175 }
00176 case 26: {
00177
00178 if (dataSize < 5) break;
00179 resultNALUSize = (framePtr[0]<<8)|framePtr[1];
00180 framePtr += 5;
00181 break;
00182 }
00183 case 27: {
00184
00185 if (dataSize < 6) break;
00186 resultNALUSize = (framePtr[0]<<8)|framePtr[1];
00187 framePtr += 6;
00188 break;
00189 }
00190 default: {
00191
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 }