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