void AMRAudioRTPSink::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* frameStart, unsigned numBytesInFrame, struct timeval framePresentationTime, 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(); // Clear the "F" bit, because we're the last frame in this packet: ##### 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, framePresentationTime, numRemainingBytes); }
void MPEG4GenericRTPSink ::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* frameStart, unsigned numBytesInFrame, struct timeval frameTimestamp, unsigned numRemainingBytes) { // Set the "AU Header Section". This is 4 bytes: 2 bytes for the // initial "AU-headers-length" field, and 2 bytes for the first // (and only) "AU Header": unsigned fullFrameSize = fragmentationOffset + numBytesInFrame + numRemainingBytes; unsigned char headers[4]; headers[0] = 0; headers[1] = 16 /* bits */; // AU-headers-length headers[2] = fullFrameSize >> 5; headers[3] = (fullFrameSize&0x1F)<<3; setSpecialHeaderBytes(headers, sizeof headers); if (numRemainingBytes == 0) { // This packet contains the last (or only) fragment of the frame. // Set the RTP 'M' ('marker') bit: setMarkerBit(); } // Important: Also call our base class's doSpecialFrameHandling(), // to set the packet's timestamp: MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset, frameStart, numBytesInFrame, frameTimestamp, numRemainingBytes); }
void JPEGVideoRTPSink ::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* /*frameStart*/, unsigned /*numBytesInFrame*/, struct timeval frameTimestamp, unsigned numRemainingBytes) { // Our source is known to be a JPEGVideoSource JPEGVideoSource* source = (JPEGVideoSource*)fSource; if (source == NULL) return; // sanity check u_int8_t mainJPEGHeader[8]; // the special header mainJPEGHeader[0] = 0; // Type-specific mainJPEGHeader[1] = fragmentationOffset >> 16; mainJPEGHeader[2] = fragmentationOffset >> 8; mainJPEGHeader[3] = fragmentationOffset; mainJPEGHeader[4] = source->type(); mainJPEGHeader[5] = source->qFactor(); mainJPEGHeader[6] = source->width(); mainJPEGHeader[7] = source->height(); setSpecialHeaderBytes(mainJPEGHeader, sizeof mainJPEGHeader); if (fragmentationOffset == 0 && source->qFactor() >= 128) { // There is also a Quantization Header: u_int8_t precision; u_int16_t length; u_int8_t const* quantizationTables = source->quantizationTables(precision, length); unsigned const quantizationHeaderSize = 4 + length; u_int8_t* quantizationHeader = new u_int8_t[quantizationHeaderSize]; quantizationHeader[0] = 0; // MBZ quantizationHeader[1] = precision; quantizationHeader[2] = length >> 8; quantizationHeader[3] = length&0xFF; if (quantizationTables != NULL) { // sanity check for (u_int16_t i = 0; i < length; ++i) { quantizationHeader[4+i] = quantizationTables[i]; } } setSpecialHeaderBytes(quantizationHeader, quantizationHeaderSize, sizeof mainJPEGHeader /* start position */); delete[] quantizationHeader; }
void LiveAMRAudioRTPSink::doSpecialFrameHandling( unsigned fragmentationOffset, unsigned char* frameStart, unsigned numBytesInFrame, struct timeval frameTimestamp, unsigned numRemainingBytes ) { #define AUDIO_FRAMES_PER_RTP_FRAME 5 // 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: LiveAMRAudioDeviceSource* amrSource = (LiveAMRAudioDeviceSource*)fSource; if (amrSource == NULL) return; // sanity check u_int8_t toc = amrSource->lastFrameHeader(); if (numFramesUsedSoFar() < AUDIO_FRAMES_PER_RTP_FRAME - 1) { toc |= 0x80; } else { toc &=~ 0x80; } setSpecialHeaderBytes(&toc, 1, 1+numFramesUsedSoFar()); // Removing toc in custom AMR device source // update packet toc? // Important: Also call our base class's doSpecialFrameHandling(), // to set the packet's timestamp: MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset, frameStart, numBytesInFrame, frameTimestamp, numRemainingBytes); }
void JPEGVideoRTPSink ::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* /*frameStart*/, unsigned /*numBytesInFrame*/, struct timeval framePresentationTime, unsigned numRemainingBytes) { // Our source is known to be a JPEGVideoSource JPEGVideoSource* source = (JPEGVideoSource*)fSource; if (source == NULL) return; // sanity check u_int8_t mainJPEGHeader[8]; // the special header u_int8_t const type = source->type(); mainJPEGHeader[0] = 0; // Type-specific mainJPEGHeader[1] = fragmentationOffset >> 16; mainJPEGHeader[2] = fragmentationOffset >> 8; mainJPEGHeader[3] = fragmentationOffset; mainJPEGHeader[4] = type; mainJPEGHeader[5] = source->qFactor(); mainJPEGHeader[6] = source->width(); mainJPEGHeader[7] = source->height(); setSpecialHeaderBytes(mainJPEGHeader, sizeof mainJPEGHeader); unsigned restartMarkerHeaderSize = 0; // by default if (type >= 64 && type <= 127) { // There is also a Restart Marker Header: restartMarkerHeaderSize = 4; u_int16_t const restartInterval = source->restartInterval(); // should be non-zero u_int8_t restartMarkerHeader[4]; restartMarkerHeader[0] = restartInterval>>8; restartMarkerHeader[1] = restartInterval&0xFF; restartMarkerHeader[2] = restartMarkerHeader[3] = 0xFF; // F=L=1; Restart Count = 0x3FFF setSpecialHeaderBytes(restartMarkerHeader, restartMarkerHeaderSize, sizeof mainJPEGHeader/* start position */); }
void AC3AudioRTPSink ::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* frameStart, unsigned numBytesInFrame, struct timeval frameTimestamp, unsigned numRemainingBytes) { // Set the 2-byte "payload header", as defined in RFC 4184. unsigned char headers[2]; Boolean isFragment = numRemainingBytes > 0 || fragmentationOffset > 0; if (!isFragment) { headers[0] = 0; // One or more complete frames headers[1] = 1; // because we (for now) allow at most 1 frame per packet } else { if (fragmentationOffset > 0) { headers[0] = 3; // Fragment of frame other than initial fragment } else { // An initial fragment of the frame unsigned const totalFrameSize = fragmentationOffset + numBytesInFrame + numRemainingBytes; unsigned const fiveEighthsPoint = totalFrameSize/2 + totalFrameSize/8; headers[0] = numBytesInFrame >= fiveEighthsPoint ? 1 : 2; // Because this outgoing packet will be full (because it's an initial fragment), we can compute how many total // fragments (and thus packets) will make up the complete AC-3 frame: fTotNumFragmentsUsed = (totalFrameSize + (numBytesInFrame-1))/numBytesInFrame; } headers[1] = fTotNumFragmentsUsed; } setSpecialHeaderBytes(headers, sizeof headers); if (numRemainingBytes == 0) { // This packet contains the last (or only) fragment of the frame. // Set the RTP 'M' ('marker') bit: setMarkerBit(); } // Important: Also call our base class's doSpecialFrameHandling(), // to set the packet's timestamp: MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset, frameStart, numBytesInFrame, frameTimestamp, numRemainingBytes); }
void VP8VideoRTPSink ::doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* /*frameStart*/, unsigned /*numBytesInFrame*/, struct timeval framePresentationTime, unsigned numRemainingBytes) { // Set the "VP8 Payload Descriptor" (just the minimal required 1-byte version): u_int8_t vp8PayloadDescriptor = fragmentationOffset == 0 ? 0x10 : 0x00; // X = R = N = 0; PartID = 0; S = 1 iff this is the first (or only) fragment of the frame setSpecialHeaderBytes(&vp8PayloadDescriptor, 1); if (numRemainingBytes == 0) { // This packet contains the last (or only) fragment of the frame. // Set the RTP 'M' ('marker') bit: setMarkerBit(); } // Also set the RTP timestamp: setTimestamp(framePresentationTime); }