⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multiframedrtpsink.cpp

📁 H.264 RTSP 串流(live 555)視窗版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    fOutBuf->skipBytes(fCurFrameSpecificHeaderSize);    fTotalFrameSpecificHeaderSizes += fCurFrameSpecificHeaderSize;    fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(),			  afterGettingFrame, this, ourHandleClosure, this);  }}void MultiFramedRTPSink::afterGettingFrame(void* clientData, unsigned numBytesRead,		    unsigned numTruncatedBytes,		    struct timeval presentationTime,		    unsigned durationInMicroseconds) {  MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;  sink->afterGettingFrame1(numBytesRead, numTruncatedBytes,			   presentationTime, durationInMicroseconds);}void MultiFramedRTPSink::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,		     struct timeval presentationTime,		     unsigned durationInMicroseconds) {  if (fIsFirstPacket) {    // Record the fact that we're starting to play now:    gettimeofday(&fNextSendTime, NULL);  }  if (numTruncatedBytes > 0) {    unsigned const bufferSize = fOutBuf->totalBytesAvailable();    unsigned newMaxSize = frameSize + numTruncatedBytes;    envir() << "MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size ("	    << bufferSize << ").  "	    << numTruncatedBytes << " bytes of trailing data was dropped!  Correct this by increasing \"OutPacketBuffer::maxSize\" to at least "	    << newMaxSize << ", *before* creating this 'RTPSink'.  (Current value is "	    << OutPacketBuffer::maxSize << ".)\n";  }  unsigned curFragmentationOffset = fCurFragmentationOffset;  unsigned numFrameBytesToUse = frameSize;  unsigned overflowBytes = 0;  // If we have already packed one or more frames into this packet,  // check whether this new frame is eligible to be packed after them.  // (This is independent of whether the packet has enough room for this  // new frame; that check comes later.)  if (fNumFramesUsedSoFar > 0) {    if ((fPreviousFrameEndedFragmentation	 && !allowOtherFramesAfterLastFragment())	|| !frameCanAppearAfterPacketStart(fOutBuf->curPtr(), frameSize)) {      // Save away this frame for next time:      numFrameBytesToUse = 0;      fOutBuf->setOverflowData(fOutBuf->curPacketSize(), frameSize,			       presentationTime, durationInMicroseconds);    }  }  fPreviousFrameEndedFragmentation = False;  if (numFrameBytesToUse > 0) {    // Check whether this frame overflows the packet    if (fOutBuf->wouldOverflow(frameSize)) {      // Don't use this frame now; instead, save it as overflow data, and      // send it in the next packet instead.  However, if the frame is too      // big to fit in a packet by itself, then we need to fragment it (and      // use some of it in this packet, if the payload format permits this.)      if (isTooBigForAPacket(frameSize)          && (fNumFramesUsedSoFar == 0 || allowFragmentationAfterStart())) {        // We need to fragment this frame, and use some of it now:        overflowBytes = computeOverflowForNewFrame(frameSize);        numFrameBytesToUse -= overflowBytes;        fCurFragmentationOffset += numFrameBytesToUse;      } else {        // We don't use any of this frame now:        overflowBytes = frameSize;        numFrameBytesToUse = 0;      }      fOutBuf->setOverflowData(fOutBuf->curPacketSize() + numFrameBytesToUse,			       overflowBytes, presentationTime, durationInMicroseconds);    } else if (fCurFragmentationOffset > 0) {      // This is the last fragment of a frame that was fragmented over      // more than one packet.  Do any special handling for this case:      fCurFragmentationOffset = 0;      fPreviousFrameEndedFragmentation = True;    }  }  if (numFrameBytesToUse == 0) {    // Send our packet now, because we have filled it up:    sendPacketIfNecessary();  } else {    // Use this frame in our outgoing packet:    unsigned char* frameStart = fOutBuf->curPtr();    fOutBuf->increment(numFrameBytesToUse);        // do this now, in case "doSpecialFrameHandling()" calls "setFramePadding()" to append padding bytes    // Here's where any payload format specific processing gets done:    doSpecialFrameHandling(curFragmentationOffset, frameStart,			   numFrameBytesToUse, presentationTime,			   overflowBytes);    ++fNumFramesUsedSoFar;    // Update the time at which the next packet should be sent, based    // on the duration of the frame that we just packed into it.    // However, if this frame has overflow data remaining, then don't    // count its duration yet.    if (overflowBytes == 0) {      fNextSendTime.tv_usec += durationInMicroseconds;      fNextSendTime.tv_sec += fNextSendTime.tv_usec/1000000;      fNextSendTime.tv_usec %= 1000000;    }    // Send our packet now if (i) it's already at our preferred size, or    // (ii) (heuristic) another frame of the same size as the one we just    //      read would overflow the packet, or    // (iii) it contains the last fragment of a fragmented frame, and we    //      don't allow anything else to follow this or    // (iv) one frame per packet is allowed:    if (fOutBuf->isPreferredSize()        || fOutBuf->wouldOverflow(numFrameBytesToUse)        || (fPreviousFrameEndedFragmentation &&            !allowOtherFramesAfterLastFragment())        || !frameCanAppearAfterPacketStart(fOutBuf->curPtr() - frameSize,					   frameSize) ) {      // The packet is ready to be sent now      sendPacketIfNecessary();    } else {      // There's room for more frames; try getting another:      packFrame();    }  }}static unsigned const rtpHeaderSize = 12;Boolean MultiFramedRTPSink::isTooBigForAPacket(unsigned numBytes) const {  // Check whether a 'numBytes'-byte frame - together with a RTP header and  // (possible) special headers - would be too big for an output packet:  // (Later allow for RTP extension header!) #####  numBytes += rtpHeaderSize + specialHeaderSize() + frameSpecificHeaderSize();  return fOutBuf->isTooBigForAPacket(numBytes);}void MultiFramedRTPSink::sendPacketIfNecessary() {  if (fNumFramesUsedSoFar > 0) {    // Send the packet:#ifdef TEST_LOSS    if ((our_random()%10) != 0) // simulate 10% packet loss ######endif    fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize());    ++fPacketCount;    fTotalOctetCount += fOutBuf->curPacketSize();    fOctetCount += fOutBuf->curPacketSize()      - rtpHeaderSize - fSpecialHeaderSize - fTotalFrameSpecificHeaderSizes;    ++fSeqNo; // for next time  }  if (fOutBuf->haveOverflowData()      && fOutBuf->totalBytesAvailable() > fOutBuf->totalBufferSize()/2) {    // Efficiency hack: Reset the packet start pointer to just in front of    // the overflow data (allowing for the RTP header and special headers),    // so that we probably don't have to "memmove()" the overflow data    // into place when building the next packet:    unsigned newPacketStart = fOutBuf->curPacketSize()      - (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize());    fOutBuf->adjustPacketStart(newPacketStart);  } else {    // Normal case: Reset the packet start pointer back to the start:    fOutBuf->resetPacketStart();  }  fOutBuf->resetOffset();  fNumFramesUsedSoFar = 0;  if (fNoFramesLeft) {    // We're done:    onSourceClosure(this);  } else {    // We have more frames left to send.  Figure out when the next frame    // is due to start playing, then make sure that we wait this long before    // sending the next packet.    struct timeval timeNow;    gettimeofday(&timeNow, NULL);    int uSecondsToGo;    if (fNextSendTime.tv_sec < timeNow.tv_sec	|| (fNextSendTime.tv_sec == timeNow.tv_sec && fNextSendTime.tv_usec < timeNow.tv_usec)) {      uSecondsToGo = 0; // prevents integer underflow if too far behind    } else {      uSecondsToGo = (fNextSendTime.tv_sec - timeNow.tv_sec)*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);    }    // Delay this amount of time:    nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo,						(TaskFunc*)sendNext, this);  }}// The following is called after each delay between packet sends:void MultiFramedRTPSink::sendNext(void* firstArg) {  MultiFramedRTPSink* sink = (MultiFramedRTPSink*)firstArg;  sink->buildAndSendPacket(False);}void MultiFramedRTPSink::ourHandleClosure(void* clientData) {  MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;  // There are no frames left, but we may have a partially built packet  //  to send  sink->fNoFramesLeft = True;  sink->sendPacketIfNecessary();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -