00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "VorbisAudioRTPSink.hh"
00022 #include "Base64.hh"
00023
00024 VorbisAudioRTPSink::VorbisAudioRTPSink(UsageEnvironment& env, Groupsock* RTPgs,
00025 u_int8_t rtpPayloadFormat,
00026 u_int32_t rtpTimestampFrequency,
00027 unsigned numChannels,
00028 u_int8_t* identificationHeader, unsigned identificationHeaderSize,
00029 u_int8_t* commentHeader, unsigned commentHeaderSize,
00030 u_int8_t* setupHeader, unsigned setupHeaderSize,
00031 u_int32_t identField)
00032 : AudioRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, "VORBIS", numChannels),
00033 fIdent(identField), fFmtpSDPLine(NULL) {
00034
00035
00036
00037 unsigned numHeaders = 0;
00038 unsigned sizeSize[2];
00039 sizeSize[0] = sizeSize[1] = 0;
00040 if (identificationHeaderSize > 0) {
00041 sizeSize[numHeaders++] = identificationHeaderSize < 128 ? 1 : identificationHeaderSize < 16384 ? 2 : 3;
00042 }
00043 if (commentHeaderSize > 0) {
00044 sizeSize[numHeaders++] = commentHeaderSize < 128 ? 1 : commentHeaderSize < 16384 ? 2 : 3;
00045 }
00046 if (setupHeaderSize > 0) {
00047 ++numHeaders;
00048 } else {
00049 sizeSize[1] = 0;
00050 }
00051 if (numHeaders == 0) return;
00052 if (numHeaders == 1) sizeSize[0] = 0;
00053
00054
00055 unsigned length = identificationHeaderSize + commentHeaderSize + setupHeaderSize;
00056 if (length > (unsigned)0xFFFF) return;
00057 unsigned packedHeadersSize
00058 = 4
00059 + 3
00060 + 2
00061 + 1
00062 + sizeSize[0] + sizeSize[1]
00063 + length;
00064 u_int8_t* packedHeaders = new u_int8_t[packedHeadersSize];
00065 if (packedHeaders == NULL) return;
00066
00067
00068 u_int8_t* p = packedHeaders;
00069 *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 1;
00070 *p++ = fIdent>>16; *p++ = fIdent>>8; *p++ = fIdent;
00071 *p++ = length>>8; *p++ = length;
00072 *p++ = numHeaders-1;
00073 if (numHeaders > 1) {
00074
00075 unsigned length1 = identificationHeaderSize > 0 ? identificationHeaderSize : commentHeaderSize;
00076 if (length1 >= 16384) {
00077 *p++ = 0x80;
00078 }
00079 if (length1 >= 128) {
00080 *p++ = 0x80|((length1&0x3F80)>>7);
00081 }
00082 *p++ = length1&0x7F;
00083
00084 if (numHeaders > 2) {
00085
00086 unsigned length2 = commentHeaderSize;
00087 if (length2 >= 16384) {
00088 *p++ = 0x80;
00089 }
00090 if (length2 >= 128) {
00091 *p++ = 0x80|((length2&0x3F80)>>7);
00092 }
00093 *p++ = length2&0x7F;
00094 }
00095 }
00096
00097 if (identificationHeader != NULL) memmove(p, identificationHeader, identificationHeaderSize); p += identificationHeaderSize;
00098 if (commentHeader != NULL) memmove(p, commentHeader, commentHeaderSize); p += commentHeaderSize;
00099 if (setupHeader != NULL) memmove(p, setupHeader, setupHeaderSize);
00100
00101
00102 char* base64PackedHeaders = base64Encode((char const*)packedHeaders, packedHeadersSize);
00103 delete[] packedHeaders;
00104
00105 unsigned fmtpSDPLineMaxSize = 50 + strlen(base64PackedHeaders);
00106 fFmtpSDPLine = new char[fmtpSDPLineMaxSize];
00107 sprintf(fFmtpSDPLine, "a=fmtp:%d configuration=%s\r\n", rtpPayloadType(), base64PackedHeaders);
00108 delete[] base64PackedHeaders;
00109 }
00110
00111 VorbisAudioRTPSink::~VorbisAudioRTPSink() {
00112 delete[] fFmtpSDPLine;
00113 }
00114
00115 VorbisAudioRTPSink*
00116 VorbisAudioRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00117 u_int8_t rtpPayloadFormat, u_int32_t rtpTimestampFrequency, unsigned numChannels,
00118 u_int8_t* identificationHeader, unsigned identificationHeaderSize,
00119 u_int8_t* commentHeader, unsigned commentHeaderSize,
00120 u_int8_t* setupHeader, unsigned setupHeaderSize) {
00121 return new VorbisAudioRTPSink(env, RTPgs,
00122 rtpPayloadFormat, rtpTimestampFrequency, numChannels,
00123 identificationHeader, identificationHeaderSize,
00124 commentHeader, commentHeaderSize,
00125 setupHeader, setupHeaderSize);
00126 }
00127
00128 #define ADVANCE(n) do { p += (n); rem -= (n); } while (0)
00129 #define GET_ENCODED_VAL(n) do { u_int8_t byte; n = 0; do { if (rem == 0) break; byte = *p; n = n*128 + byte&0x7F; ADVANCE(1); } while (byte&0x80); } while (0); if (rem == 0) break
00130
00131 VorbisAudioRTPSink*
00132 VorbisAudioRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00133 u_int8_t rtpPayloadFormat, u_int32_t rtpTimestampFrequency, unsigned numChannels,
00134 char const* configStr) {
00135 u_int8_t* identificationHeader = NULL; unsigned identificationHeaderSize = 0;
00136 u_int8_t* commentHeader = NULL; unsigned commentHeaderSize = 0;
00137 u_int8_t* setupHeader = NULL; unsigned setupHeaderSize = 0;
00138 VorbisAudioRTPSink* resultSink = NULL;
00139
00140
00141 unsigned configDataSize;
00142 u_int8_t* configData = base64Decode(configStr, configDataSize);
00143 u_int8_t* p = configData;
00144 unsigned rem = configDataSize;
00145
00146 do {
00147 if (rem < 4) break;
00148 u_int32_t numPackedHeaders = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; ADVANCE(4);
00149
00150 if (numPackedHeaders == 0) break;
00151
00152
00153 if (rem < 3) break;
00154 u_int32_t ident = (p[0]<<16)|(p[1]<<8)|p[2]; ADVANCE(3);
00155
00156 if (rem < 2) break;
00157 u_int16_t length = (p[0]<<8)|p[1]; ADVANCE(2);
00158
00159 unsigned numHeaders;
00160 GET_ENCODED_VAL(numHeaders);
00161
00162 Boolean success = False;
00163 for (unsigned i = 0; i < numHeaders+1 && i < 3; ++i) {
00164 success = False;
00165 unsigned headerSize;
00166 if (i < numHeaders) {
00167
00168 GET_ENCODED_VAL(headerSize);
00169 if (headerSize > length) break;
00170 length -= headerSize;
00171 } else {
00172
00173 headerSize = length;
00174 }
00175
00176
00177 if (i == 0) {
00178 identificationHeaderSize = headerSize;
00179 identificationHeader = new u_int8_t[identificationHeaderSize];
00180 } else if (i == 1) {
00181 commentHeaderSize = headerSize;
00182 commentHeader = new u_int8_t[commentHeaderSize];
00183 } else {
00184 setupHeaderSize = headerSize;
00185 setupHeader = new u_int8_t[setupHeaderSize];
00186 }
00187
00188 success = True;
00189 }
00190 if (!success) break;
00191
00192
00193 if (identificationHeader != NULL) {
00194 memmove(identificationHeader, p, identificationHeaderSize); ADVANCE(identificationHeaderSize);
00195 if (commentHeader != NULL) {
00196 memmove(commentHeader, p, commentHeaderSize); ADVANCE(commentHeaderSize);
00197 if (setupHeader != NULL) {
00198 memmove(setupHeader, p, setupHeaderSize); ADVANCE(setupHeaderSize);
00199 }
00200 }
00201 }
00202
00203 resultSink = new VorbisAudioRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, numChannels,
00204 identificationHeader, identificationHeaderSize,
00205 commentHeader, commentHeaderSize,
00206 setupHeader, setupHeaderSize,
00207 ident);
00208 } while (0);
00209
00210 delete[] configData;
00211 delete[] identificationHeader; delete[] commentHeader; delete[] setupHeader;
00212 return resultSink;
00213 }
00214
00215 char const* VorbisAudioRTPSink::auxSDPLine() {
00216 return fFmtpSDPLine;
00217 }
00218
00219 void VorbisAudioRTPSink
00220 ::doSpecialFrameHandling(unsigned fragmentationOffset,
00221 unsigned char* frameStart,
00222 unsigned numBytesInFrame,
00223 struct timeval framePresentationTime,
00224 unsigned numRemainingBytes) {
00225
00226 u_int8_t header[4];
00227
00228
00229 header[0] = fIdent>>16; header[1] = fIdent>>8; header[2] = fIdent;
00230
00231
00232 u_int8_t F;
00233 if (numRemainingBytes > 0) {
00234 if (fragmentationOffset > 0) {
00235 F = 2<<6;
00236 } else {
00237 F = 1<<6;
00238 }
00239 } else {
00240 if (fragmentationOffset > 0) {
00241 F = 3<<6;
00242 } else {
00243 F = 0<<6;
00244 }
00245 }
00246 u_int8_t const VDT = 0<<4;
00247 u_int8_t numPkts = F == 0 ? (numFramesUsedSoFar() + 1): 0;
00248 header[3] = F|VDT|numPkts;
00249
00250 setSpecialHeaderBytes(header, sizeof header);
00251
00252
00253 u_int8_t frameSpecificHeader[2];
00254 frameSpecificHeader[0] = numBytesInFrame>>8;
00255 frameSpecificHeader[1] = numBytesInFrame;
00256 setFrameSpecificHeaderBytes(frameSpecificHeader, 2);
00257
00258
00259
00260 MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset,
00261 frameStart, numBytesInFrame,
00262 framePresentationTime,
00263 numRemainingBytes);
00264 }
00265
00266 Boolean VorbisAudioRTPSink::frameCanAppearAfterPacketStart(unsigned char const* ,
00267 unsigned ) const {
00268
00269 return numFramesUsedSoFar() <= 15;
00270 }
00271
00272 unsigned VorbisAudioRTPSink::specialHeaderSize() const {
00273 return 4;
00274 }
00275
00276 unsigned VorbisAudioRTPSink::frameSpecificHeaderSize() const {
00277 return 2;
00278 }