void MultiFramedRTPSink::buildAndSendPacket(Boolean isFirstPacket) { fIsFirstPacket = isFirstPacket; // Set up the RTP header: unsigned rtpHdr = 0x80000000; // RTP version 2; marker ('M') bit not set (by default; it can be set later) rtpHdr |= (fRTPPayloadType<<16); rtpHdr |= fSeqNo; // sequence number fOutBuf->enqueueWord(rtpHdr); // Note where the RTP timestamp will go. // (We can't fill this in until we start packing payload frames.) fTimestampPosition = fOutBuf->curPacketSize(); fOutBuf->skipBytes(4); // leave a hole for the timestamp fOutBuf->enqueueWord(SSRC()); // Allow for a special, payload-format-specific header following the // RTP header: fSpecialHeaderPosition = fOutBuf->curPacketSize(); fSpecialHeaderSize = specialHeaderSize(); fOutBuf->skipBytes(fSpecialHeaderSize); // Begin packing as many (complete) frames into the packet as we can: fTotalFrameSpecificHeaderSizes = 0; fNoFramesLeft = False; fNumFramesUsedSoFar = 0; packFrame(); }
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 AMRAudioRTPSink::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* frameStart, unsigned numBytesInFrame, struct timeval frameTimestamp, unsigned numRemainingBytes) { // If this is the 1st frame in the 1st packet, set the RTP 'M' (marker) // bit (because this is considered the start of a talk spurt): if (isFirstPacket() && isFirstFrameInPacket()) { setMarkerBit(); } // If this is the first frame in the packet, set the 1-byte payload // header (using CMR 15) if (isFirstFrameInPacket()) { u_int8_t payloadHeader = 0xF0; setSpecialHeaderBytes(&payloadHeader, 1, 0); } // Set the TOC field for the current frame, based on the "FT" and "Q" // values from our source: AMRAudioSource* amrSource = (AMRAudioSource*)fSource; if (amrSource == NULL) return; // sanity check u_int8_t toc = amrSource->lastFrameHeader(); Debug(ckite_log_message, "Last frame toc is %d\n", toc); // Clear the "F" bit, because we're the last frame in this packet: ##### toc &=~ 0x80; if (numFramesUsedSoFar() != specialHeaderSize() - 2) toc |= 0x80; setSpecialHeaderBytes(&toc, 1, 1+numFramesUsedSoFar()); // Important: Also call our base class's doSpecialFrameHandling(), // to set the packet's timestamp: MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset, frameStart, numBytesInFrame, frameTimestamp, numRemainingBytes); }