Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h"
     12 
     13 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
     14 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
     15 
     16 namespace webrtc {
     17 
     18 FrameGenerator::FrameGenerator()
     19     : num_packets_(0), seq_num_(0), timestamp_(0) {}
     20 
     21 void FrameGenerator::NewFrame(int num_packets) {
     22   num_packets_ = num_packets;
     23   timestamp_ += 3000;
     24 }
     25 
     26 uint16_t FrameGenerator::NextSeqNum() { return ++seq_num_; }
     27 
     28 RtpPacket* FrameGenerator::NextPacket(int offset, size_t length) {
     29   RtpPacket* rtp_packet = new RtpPacket;
     30   for (size_t i = 0; i < length; ++i)
     31     rtp_packet->data[i + kRtpHeaderSize] = offset + i;
     32   rtp_packet->length = length + kRtpHeaderSize;
     33   memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader));
     34   rtp_packet->header.frameType = kVideoFrameDelta;
     35   rtp_packet->header.header.headerLength = kRtpHeaderSize;
     36   rtp_packet->header.header.markerBit = (num_packets_ == 1);
     37   rtp_packet->header.header.sequenceNumber = seq_num_;
     38   rtp_packet->header.header.timestamp = timestamp_;
     39   rtp_packet->header.header.payloadType = kVp8PayloadType;
     40   BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header);
     41   ++seq_num_;
     42   --num_packets_;
     43   return rtp_packet;
     44 }
     45 
     46 // Creates a new RtpPacket with the RED header added to the packet.
     47 RtpPacket* FrameGenerator::BuildMediaRedPacket(const RtpPacket* packet) {
     48   const size_t kHeaderLength = packet->header.header.headerLength;
     49   RtpPacket* red_packet = new RtpPacket;
     50   red_packet->header = packet->header;
     51   red_packet->length = packet->length + 1;  // 1 byte RED header.
     52   memset(red_packet->data, 0, red_packet->length);
     53   // Copy RTP header.
     54   memcpy(red_packet->data, packet->data, kHeaderLength);
     55   SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength);
     56   memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength,
     57          packet->length - kHeaderLength);
     58   return red_packet;
     59 }
     60 
     61 // Creates a new RtpPacket with FEC payload and red header. Does this by
     62 // creating a new fake media RtpPacket, clears the marker bit and adds a RED
     63 // header. Finally replaces the payload with the content of |packet->data|.
     64 RtpPacket* FrameGenerator::BuildFecRedPacket(const Packet* packet) {
     65   // Create a fake media packet to get a correct header. 1 byte RED header.
     66   ++num_packets_;
     67   RtpPacket* red_packet = NextPacket(0, packet->length + 1);
     68   red_packet->data[1] &= ~0x80;  // Clear marker bit.
     69   const size_t kHeaderLength = red_packet->header.header.headerLength;
     70   SetRedHeader(red_packet, kFecPayloadType, kHeaderLength);
     71   memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length);
     72   red_packet->length = kHeaderLength + 1 + packet->length;
     73   return red_packet;
     74 }
     75 
     76 void FrameGenerator::SetRedHeader(Packet* red_packet, uint8_t payload_type,
     77                                   size_t header_length) const {
     78   // Replace pltype.
     79   red_packet->data[1] &= 0x80;             // Reset.
     80   red_packet->data[1] += kRedPayloadType;  // Replace.
     81 
     82   // Add RED header, f-bit always 0.
     83   red_packet->data[header_length] = payload_type;
     84 }
     85 
     86 void FrameGenerator::BuildRtpHeader(uint8_t* data, const RTPHeader* header) {
     87   data[0] = 0x80;  // Version 2.
     88   data[1] = header->payloadType;
     89   data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0);
     90   ByteWriter<uint16_t>::WriteBigEndian(data + 2, header->sequenceNumber);
     91   ByteWriter<uint32_t>::WriteBigEndian(data + 4, header->timestamp);
     92   ByteWriter<uint32_t>::WriteBigEndian(data + 8, header->ssrc);
     93 }
     94 
     95 }  // namespace webrtc
     96