Exemple #1
0
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);
}
Exemple #5
0
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);
}