00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "QuickTimeGenericRTPSource.hh"
00023
00025
00026
00027
00028
00029 class QTGenericBufferedPacket: public BufferedPacket {
00030 public:
00031 QTGenericBufferedPacket(QuickTimeGenericRTPSource& ourSource);
00032 virtual ~QTGenericBufferedPacket();
00033
00034 private:
00035 virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00036 unsigned dataSize);
00037 private:
00038 QuickTimeGenericRTPSource& fOurSource;
00039 };
00040
00041 class QTGenericBufferedPacketFactory: public BufferedPacketFactory {
00042 private:
00043 virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00044 };
00045
00046
00048
00049 QuickTimeGenericRTPSource*
00050 QuickTimeGenericRTPSource::createNew(UsageEnvironment& env,
00051 Groupsock* RTPgs,
00052 unsigned char rtpPayloadFormat,
00053 unsigned rtpTimestampFrequency,
00054 char const* mimeTypeString) {
00055 return new QuickTimeGenericRTPSource(env, RTPgs, rtpPayloadFormat,
00056 rtpTimestampFrequency,
00057 mimeTypeString);
00058 }
00059
00060 QuickTimeGenericRTPSource
00061 ::QuickTimeGenericRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00062 unsigned char rtpPayloadFormat,
00063 unsigned rtpTimestampFrequency,
00064 char const* mimeTypeString)
00065 : MultiFramedRTPSource(env, RTPgs,
00066 rtpPayloadFormat, rtpTimestampFrequency,
00067 new QTGenericBufferedPacketFactory),
00068 fMIMEtypeString(strDup(mimeTypeString)) {
00069 qtState.PCK = 0;
00070 qtState.timescale = 0;
00071 qtState.sdAtom = NULL;
00072 qtState.sdAtomSize = qtState.width = qtState.height = 0;
00073 }
00074
00075 QuickTimeGenericRTPSource::~QuickTimeGenericRTPSource() {
00076 delete[] qtState.sdAtom;
00077 delete[] (char*)fMIMEtypeString;
00078 }
00079
00080 Boolean QuickTimeGenericRTPSource
00081 ::processSpecialHeader(BufferedPacket* packet,
00082 unsigned& resultSpecialHeaderSize) {
00083 unsigned char* headerStart = packet->data();
00084 unsigned packetSize = packet->dataSize();
00085
00086
00087
00088 unsigned expectedHeaderSize = 4;
00089 if (packetSize < expectedHeaderSize) return False;
00090
00091 unsigned char VER = (headerStart[0]&0xF0)>>4;
00092 if (VER > 1) return False;
00093 qtState.PCK = (headerStart[0]&0x0C)>>2;
00094 #ifdef DEBUG
00095 Boolean S = (headerStart[0]&0x02) != 0;
00096 #endif
00097 Boolean Q = (headerStart[0]&0x01) != 0;
00098
00099 Boolean L = (headerStart[1]&0x80) != 0;
00100
00101 #ifdef DEBUG
00102 Boolean D = (headerStart[2]&0x80) != 0;
00103 unsigned short payloadId = ((headerStart[2]&0x7F)<<8)|headerStart[3];
00104 #endif
00105 headerStart += 4;
00106
00107 #ifdef DEBUG
00108 fprintf(stderr, "PCK: %d, S: %d, Q: %d, L: %d, D: %d, payloadId: %d\n", qtState.PCK, S, Q, L, D, payloadId);
00109 #endif
00110
00111 if (Q) {
00112 expectedHeaderSize += 4;
00113 if (packetSize < expectedHeaderSize) return False;
00114
00115 #ifdef DEBUG
00116 Boolean K = (headerStart[0]&0x80) != 0;
00117 Boolean F = (headerStart[0]&0x40) != 0;
00118 Boolean A = (headerStart[0]&0x20) != 0;
00119 Boolean Z = (headerStart[0]&0x10) != 0;
00120 #endif
00121 unsigned payloadDescriptionLength = (headerStart[2]<<8)|headerStart[3];
00122 headerStart += 4;
00123
00124 #ifdef DEBUG
00125 fprintf(stderr, "\tK: %d, F: %d, A: %d, Z: %d, payloadDescriptionLength: %d\n", K, F, A, Z, payloadDescriptionLength);
00126 #endif
00127
00128 if (payloadDescriptionLength < 12) return False;
00129 expectedHeaderSize += (payloadDescriptionLength - 4);
00130 unsigned nonPaddedSize = expectedHeaderSize;
00131 expectedHeaderSize += 3;
00132 expectedHeaderSize -= expectedHeaderSize%4;
00133 if (packetSize < expectedHeaderSize) return False;
00134 unsigned char padding = expectedHeaderSize - nonPaddedSize;
00135
00136 #ifdef DEBUG
00137 unsigned mediaType = (headerStart[0]<<24)|(headerStart[1]<<16)
00138 |(headerStart[2]<<8)|headerStart[3];
00139 #endif
00140 qtState.timescale = (headerStart[4]<<24)|(headerStart[5]<<16)
00141 |(headerStart[6]<<8)|headerStart[7];
00142 headerStart += 8;
00143
00144 payloadDescriptionLength -= 12;
00145 #ifdef DEBUG
00146 fprintf(stderr, "\tmediaType: '%c%c%c%c', timescale: %d, %d bytes of TLVs left\n", mediaType>>24, (mediaType&0xFF0000)>>16, (mediaType&0xFF00)>>8, mediaType&0xFF, qtState.timescale, payloadDescriptionLength);
00147 #endif
00148
00149 while (payloadDescriptionLength > 3) {
00150 unsigned short tlvLength = (headerStart[0]<<8)|headerStart[1];
00151 unsigned short tlvType = (headerStart[2]<<8)|headerStart[3];
00152 payloadDescriptionLength -= 4;
00153 if (tlvLength > payloadDescriptionLength) return False;
00154 headerStart += 4;
00155 #ifdef DEBUG
00156 fprintf(stderr, "\t\tTLV '%c%c', length %d, leaving %d remaining bytes\n", tlvType>>8, tlvType&0xFF, tlvLength, payloadDescriptionLength - tlvLength);
00157 for (int i = 0; i < tlvLength; ++i) fprintf(stderr, "%02x:", headerStart[i]); fprintf(stderr, "\n");
00158 #endif
00159
00160
00161 switch (tlvType) {
00162 case ('s'<<8|'d'): {
00163
00164 unsigned atomLength = (headerStart[0]<<24)|(headerStart[1]<<16)
00165 |(headerStart[2]<<8)|(headerStart[3]);
00166 if (atomLength != (unsigned)tlvLength) break;
00167
00168 delete[] qtState.sdAtom; qtState.sdAtom = new char[tlvLength];
00169 memmove(qtState.sdAtom, headerStart, tlvLength);
00170 qtState.sdAtomSize = tlvLength;
00171 break;
00172 }
00173 case ('t'<<8|'w'): {
00174 qtState.width = (headerStart[0]<<8)|headerStart[1];
00175 break;
00176 }
00177 case ('t'<<8|'h'): {
00178 qtState.height = (headerStart[0]<<8)|headerStart[1];
00179 break;
00180 }
00181 }
00182
00183 payloadDescriptionLength -= tlvLength;
00184 headerStart += tlvLength;
00185 }
00186 if (payloadDescriptionLength > 0) return False;
00187 headerStart += padding;
00188 }
00189
00190 if (L) {
00191 expectedHeaderSize += 4;
00192 if (packetSize < expectedHeaderSize) return False;
00193
00194 unsigned ssInfoLength = (headerStart[2]<<8)|headerStart[3];
00195 headerStart += 4;
00196
00197 #ifdef DEBUG
00198 fprintf(stderr, "\tssInfoLength: %d\n", ssInfoLength);
00199 #endif
00200
00201 if (ssInfoLength < 4) return False;
00202 expectedHeaderSize += (ssInfoLength - 4);
00203 unsigned nonPaddedSize = expectedHeaderSize;
00204 expectedHeaderSize += 3;
00205 expectedHeaderSize -= expectedHeaderSize%4;
00206 if (packetSize < expectedHeaderSize) return False;
00207 unsigned char padding = expectedHeaderSize - nonPaddedSize;
00208
00209 ssInfoLength -= 4;
00210 while (ssInfoLength > 3) {
00211 unsigned short tlvLength = (headerStart[0]<<8)|headerStart[1];
00212 #ifdef DEBUG
00213 unsigned short tlvType = (headerStart[2]<<8)|headerStart[3];
00214 #endif
00215 ssInfoLength -= 4;
00216 if (tlvLength > ssInfoLength) return False;
00217 #ifdef DEBUG
00218 fprintf(stderr, "\t\tTLV '%c%c', length %d, leaving %d remaining bytes\n", tlvType>>8, tlvType&0xFF, tlvLength, ssInfoLength - tlvLength);
00219 for (int i = 0; i < tlvLength; ++i) fprintf(stderr, "%02x:", headerStart[4+i]); fprintf(stderr, "\n");
00220 #endif
00221 ssInfoLength -= tlvLength;
00222 headerStart += 4 + tlvLength;
00223 }
00224 if (ssInfoLength > 0) return False;
00225 headerStart += padding;
00226 }
00227
00228 fCurrentPacketBeginsFrame = fCurrentPacketCompletesFrame;
00229
00230 fCurrentPacketCompletesFrame = packet->rtpMarkerBit();
00231
00232 resultSpecialHeaderSize = expectedHeaderSize;
00233 #ifdef DEBUG
00234 fprintf(stderr, "Result special header size: %d\n", resultSpecialHeaderSize);
00235 #endif
00236 return True;
00237 }
00238
00239 char const* QuickTimeGenericRTPSource::MIMEtype() const {
00240 if (fMIMEtypeString == NULL) return MultiFramedRTPSource::MIMEtype();
00241
00242 return fMIMEtypeString;
00243 }
00244
00245
00247
00248 QTGenericBufferedPacket
00249 ::QTGenericBufferedPacket(QuickTimeGenericRTPSource& ourSource)
00250 : fOurSource(ourSource) {
00251 }
00252
00253 QTGenericBufferedPacket::~QTGenericBufferedPacket() {
00254 }
00255
00256 unsigned QTGenericBufferedPacket::
00257 nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {
00258
00259 if (fOurSource.qtState.PCK != 2) return dataSize;
00260
00261 if (dataSize < 8) return 0;
00262
00263 unsigned short sampleLength = (framePtr[2]<<8)|framePtr[3];
00264
00265 framePtr += 8;
00266 dataSize -= 8;
00267
00268 return sampleLength < dataSize ? sampleLength : dataSize;
00269 }
00270
00271 BufferedPacket* QTGenericBufferedPacketFactory
00272 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00273 return new QTGenericBufferedPacket((QuickTimeGenericRTPSource&)(*ourSource));
00274 }