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