00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MultiFramedRTPSink.hh"
00023 #include "GroupsockHelper.hh"
00024
00026
00027 void MultiFramedRTPSink::setPacketSizes(unsigned preferredPacketSize,
00028 unsigned maxPacketSize) {
00029 if (preferredPacketSize > maxPacketSize || preferredPacketSize == 0) return;
00030
00031
00032 delete fOutBuf;
00033 fOutBuf = new OutPacketBuffer(preferredPacketSize, maxPacketSize);
00034 fOurMaxPacketSize = maxPacketSize;
00035 }
00036
00037 MultiFramedRTPSink::MultiFramedRTPSink(UsageEnvironment& env,
00038 Groupsock* rtpGS,
00039 unsigned char rtpPayloadType,
00040 unsigned rtpTimestampFrequency,
00041 char const* rtpPayloadFormatName,
00042 unsigned numChannels)
00043 : RTPSink(env, rtpGS, rtpPayloadType, rtpTimestampFrequency,
00044 rtpPayloadFormatName, numChannels),
00045 fOutBuf(NULL), fCurFragmentationOffset(0), fPreviousFrameEndedFragmentation(False) {
00046 setPacketSizes(1000, 1448);
00047
00048
00049 }
00050
00051 MultiFramedRTPSink::~MultiFramedRTPSink() {
00052 delete fOutBuf;
00053 }
00054
00055 void MultiFramedRTPSink
00056 ::doSpecialFrameHandling(unsigned ,
00057 unsigned char* ,
00058 unsigned ,
00059 struct timeval frameTimestamp,
00060 unsigned ) {
00061
00062
00063 if (isFirstFrameInPacket()) {
00064 setTimestamp(frameTimestamp);
00065 }
00066 }
00067
00068 Boolean MultiFramedRTPSink::allowFragmentationAfterStart() const {
00069 return False;
00070 }
00071
00072 Boolean MultiFramedRTPSink::allowOtherFramesAfterLastFragment() const {
00073 return False;
00074 }
00075
00076 Boolean MultiFramedRTPSink
00077 ::frameCanAppearAfterPacketStart(unsigned char const* ,
00078 unsigned ) const {
00079 return True;
00080 }
00081
00082 unsigned MultiFramedRTPSink::specialHeaderSize() const {
00083
00084 return 0;
00085 }
00086
00087 unsigned MultiFramedRTPSink::frameSpecificHeaderSize() const {
00088
00089 return 0;
00090 }
00091
00092 void MultiFramedRTPSink::setMarkerBit() {
00093 unsigned rtpHdr = fOutBuf->extractWord(0);
00094 rtpHdr |= 0x00800000;
00095 fOutBuf->insertWord(rtpHdr, 0);
00096 }
00097
00098 void MultiFramedRTPSink::setTimestamp(struct timeval timestamp) {
00099
00100 fCurrentTimestamp = convertToRTPTimestamp(timestamp);
00101
00102
00103 fOutBuf->insertWord(fCurrentTimestamp, fTimestampPosition);
00104 }
00105
00106 void MultiFramedRTPSink::setSpecialHeaderWord(unsigned word,
00107 unsigned wordPosition) {
00108 fOutBuf->insertWord(word, fSpecialHeaderPosition + 4*wordPosition);
00109 }
00110
00111 void MultiFramedRTPSink::setSpecialHeaderBytes(unsigned char const* bytes,
00112 unsigned numBytes,
00113 unsigned bytePosition) {
00114 fOutBuf->insert(bytes, numBytes, fSpecialHeaderPosition + bytePosition);
00115 }
00116
00117 void MultiFramedRTPSink::setFrameSpecificHeaderWord(unsigned word,
00118 unsigned wordPosition) {
00119 fOutBuf->insertWord(word, fCurFrameSpecificHeaderPosition + 4*wordPosition);
00120 }
00121
00122 void MultiFramedRTPSink::setFrameSpecificHeaderBytes(unsigned char const* bytes,
00123 unsigned numBytes,
00124 unsigned bytePosition) {
00125 fOutBuf->insert(bytes, numBytes, fCurFrameSpecificHeaderPosition + bytePosition);
00126 }
00127
00128 void MultiFramedRTPSink::setFramePadding(unsigned numPaddingBytes) {
00129 if (numPaddingBytes > 0) {
00130
00131 unsigned char paddingBuffer[255];
00132 memset(paddingBuffer, 0, numPaddingBytes);
00133 paddingBuffer[numPaddingBytes-1] = numPaddingBytes;
00134 fOutBuf->enqueue(paddingBuffer, numPaddingBytes);
00135
00136
00137 unsigned rtpHdr = fOutBuf->extractWord(0);
00138 rtpHdr |= 0x20000000;
00139 fOutBuf->insertWord(rtpHdr, 0);
00140 }
00141 }
00142
00143 Boolean MultiFramedRTPSink::continuePlaying() {
00144
00145
00146 buildAndSendPacket(True);
00147 return True;
00148 }
00149
00150 void MultiFramedRTPSink::stopPlaying() {
00151 fOutBuf->resetPacketStart();
00152 fOutBuf->resetOffset();
00153 fOutBuf->resetOverflowData();
00154
00155
00156 MediaSink::stopPlaying();
00157 }
00158
00159 void MultiFramedRTPSink::buildAndSendPacket(Boolean isFirstPacket) {
00160 fIsFirstPacket = isFirstPacket;
00161
00162
00163 unsigned rtpHdr = 0x80000000;
00164 rtpHdr |= (fRTPPayloadType<<16);
00165 rtpHdr |= fSeqNo;
00166 fOutBuf->enqueueWord(rtpHdr);
00167
00168
00169
00170 fTimestampPosition = fOutBuf->curPacketSize();
00171 fOutBuf->skipBytes(4);
00172
00173 fOutBuf->enqueueWord(SSRC());
00174
00175
00176
00177 fSpecialHeaderPosition = fOutBuf->curPacketSize();
00178 fSpecialHeaderSize = specialHeaderSize();
00179 fOutBuf->skipBytes(fSpecialHeaderSize);
00180
00181
00182 fTotalFrameSpecificHeaderSizes = 0;
00183 fNoFramesLeft = False;
00184 fNumFramesUsedSoFar = 0;
00185 packFrame();
00186 }
00187
00188 void MultiFramedRTPSink::packFrame() {
00189
00190
00191
00192 if (fOutBuf->haveOverflowData()) {
00193
00194 unsigned frameSize = fOutBuf->overflowDataSize();
00195 struct timeval presentationTime = fOutBuf->overflowPresentationTime();
00196 unsigned durationInMicroseconds = fOutBuf->overflowDurationInMicroseconds();
00197 fOutBuf->useOverflowData();
00198
00199 afterGettingFrame1(frameSize, 0, presentationTime, durationInMicroseconds);
00200 } else {
00201
00202 if (fSource == NULL) return;
00203
00204 fCurFrameSpecificHeaderPosition = fOutBuf->curPacketSize();
00205 fCurFrameSpecificHeaderSize = frameSpecificHeaderSize();
00206 fOutBuf->skipBytes(fCurFrameSpecificHeaderSize);
00207 fTotalFrameSpecificHeaderSizes += fCurFrameSpecificHeaderSize;
00208
00209 fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(),
00210 afterGettingFrame, this, ourHandleClosure, this);
00211 }
00212 }
00213
00214 void MultiFramedRTPSink
00215 ::afterGettingFrame(void* clientData, unsigned numBytesRead,
00216 unsigned numTruncatedBytes,
00217 struct timeval presentationTime,
00218 unsigned durationInMicroseconds) {
00219 MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;
00220 sink->afterGettingFrame1(numBytesRead, numTruncatedBytes,
00221 presentationTime, durationInMicroseconds);
00222 }
00223
00224 void MultiFramedRTPSink
00225 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00226 struct timeval presentationTime,
00227 unsigned durationInMicroseconds) {
00228 if (fIsFirstPacket) {
00229
00230 gettimeofday(&fNextSendTime, NULL);
00231 }
00232
00233 if (numTruncatedBytes > 0) {
00234 unsigned const bufferSize = fOutBuf->totalBytesAvailable();
00235 unsigned newMaxSize = frameSize + numTruncatedBytes;
00236 envir() << "MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size ("
00237 << bufferSize << "). "
00238 << numTruncatedBytes << " bytes of trailing data was dropped! Correct this by increasing \"OutPacketBuffer::maxSize\" to at least "
00239 << newMaxSize << ", *before* creating this 'RTPSink'. (Current value is "
00240 << OutPacketBuffer::maxSize << ".)\n";
00241 }
00242 unsigned curFragmentationOffset = fCurFragmentationOffset;
00243 unsigned numFrameBytesToUse = frameSize;
00244 unsigned overflowBytes = 0;
00245
00246
00247
00248
00249
00250 if (fNumFramesUsedSoFar > 0) {
00251 if ((fPreviousFrameEndedFragmentation
00252 && !allowOtherFramesAfterLastFragment())
00253 || !frameCanAppearAfterPacketStart(fOutBuf->curPtr(), frameSize)) {
00254
00255 numFrameBytesToUse = 0;
00256 fOutBuf->setOverflowData(fOutBuf->curPacketSize(), frameSize,
00257 presentationTime, durationInMicroseconds);
00258 }
00259 }
00260 fPreviousFrameEndedFragmentation = False;
00261
00262 if (numFrameBytesToUse > 0) {
00263
00264 if (fOutBuf->wouldOverflow(frameSize)) {
00265
00266
00267
00268
00269 if (isTooBigForAPacket(frameSize)
00270 && (fNumFramesUsedSoFar == 0 || allowFragmentationAfterStart())) {
00271
00272 overflowBytes = fOutBuf->numOverflowBytes(frameSize);
00273 numFrameBytesToUse -= overflowBytes;
00274 fCurFragmentationOffset += numFrameBytesToUse;
00275 } else {
00276
00277 overflowBytes = frameSize;
00278 numFrameBytesToUse = 0;
00279 }
00280 fOutBuf->setOverflowData(fOutBuf->curPacketSize() + numFrameBytesToUse,
00281 overflowBytes, presentationTime,
00282 durationInMicroseconds);
00283 } else if (fCurFragmentationOffset > 0) {
00284
00285
00286 fCurFragmentationOffset = 0;
00287 fPreviousFrameEndedFragmentation = True;
00288 }
00289 }
00290
00291 if (numFrameBytesToUse == 0) {
00292
00293 sendPacketIfNecessary();
00294 } else {
00295
00296 unsigned char * frameStart = fOutBuf->curPtr();
00297 fOutBuf->increment(numFrameBytesToUse);
00298
00299
00300
00301 doSpecialFrameHandling(curFragmentationOffset, frameStart,
00302 numFrameBytesToUse, presentationTime,
00303 overflowBytes);
00304
00305 ++fNumFramesUsedSoFar;
00306
00307
00308
00309
00310
00311 if (overflowBytes == 0) {
00312 fNextSendTime.tv_usec += durationInMicroseconds;
00313 fNextSendTime.tv_sec += fNextSendTime.tv_usec/1000000;
00314 fNextSendTime.tv_usec %= 1000000;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323 if (fOutBuf->isPreferredSize()
00324 || fOutBuf->wouldOverflow(numFrameBytesToUse)
00325 || (fPreviousFrameEndedFragmentation &&
00326 !allowOtherFramesAfterLastFragment())
00327 || !frameCanAppearAfterPacketStart(fOutBuf->curPtr() - frameSize,
00328 frameSize) ) {
00329
00330 sendPacketIfNecessary();
00331 } else {
00332
00333 packFrame();
00334 }
00335 }
00336 }
00337
00338 static unsigned const rtpHeaderSize = 12;
00339
00340 Boolean MultiFramedRTPSink::isTooBigForAPacket(unsigned numBytes) const {
00341
00342
00343
00344 numBytes += rtpHeaderSize + specialHeaderSize() + frameSpecificHeaderSize();
00345 return fOutBuf->isTooBigForAPacket(numBytes);
00346 }
00347
00348 void MultiFramedRTPSink::sendPacketIfNecessary() {
00349 if (fNumFramesUsedSoFar > 0) {
00350
00351 #ifdef TEST_LOSS
00352 if ((our_random()%10) != 0)
00353 #endif
00354 fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize());
00355 ++fPacketCount;
00356 fTotalOctetCount += fOutBuf->curPacketSize();
00357 fOctetCount += fOutBuf->curPacketSize()
00358 - rtpHeaderSize - fSpecialHeaderSize - fTotalFrameSpecificHeaderSizes;
00359
00360 ++fSeqNo;
00361 }
00362
00363 if (fOutBuf->haveOverflowData()
00364 && fOutBuf->totalBytesAvailable() > fOutBuf->totalBufferSize()/2) {
00365
00366
00367
00368
00369 unsigned newPacketStart = fOutBuf->curPacketSize()
00370 - (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize());
00371 fOutBuf->adjustPacketStart(newPacketStart);
00372 } else {
00373
00374 fOutBuf->resetPacketStart();
00375 }
00376 fOutBuf->resetOffset();
00377 fNumFramesUsedSoFar = 0;
00378
00379 if (fNoFramesLeft) {
00380
00381 onSourceClosure(this);
00382 } else {
00383
00384
00385
00386 struct timeval timeNow;
00387 gettimeofday(&timeNow, NULL);
00388 int uSecondsToGo;
00389 if (fNextSendTime.tv_sec < timeNow.tv_sec) {
00390 uSecondsToGo = 0;
00391 } else {
00392 uSecondsToGo = (fNextSendTime.tv_sec - timeNow.tv_sec)*1000000
00393 + (fNextSendTime.tv_usec - timeNow.tv_usec);
00394 }
00395
00396
00397 nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo,
00398 (TaskFunc*)sendNext, this);
00399 }
00400 }
00401
00402
00403 void MultiFramedRTPSink::sendNext(void* firstArg) {
00404 MultiFramedRTPSink* sink = (MultiFramedRTPSink*)firstArg;
00405 sink->buildAndSendPacket(False);
00406 }
00407
00408 void MultiFramedRTPSink::ourHandleClosure(void* clientData) {
00409 MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;
00410
00411
00412 sink->fNoFramesLeft = True;
00413 sink->sendPacketIfNecessary();
00414 }