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