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/rtp_utility.h"
     14 
     15 namespace webrtc {
     16 
     17 FrameGenerator::FrameGenerator()
     18     : num_packets_(0), seq_num_(0), timestamp_(0) {}
     19 
     20 void FrameGenerator::NewFrame(int num_packets) {
     21   num_packets_ = num_packets;
     22   timestamp_ += 3000;
     23 }
     24 
     25 uint16_t FrameGenerator::NextSeqNum() { return ++seq_num_; }
     26 
     27 RtpPacket* FrameGenerator::NextPacket(int offset, size_t length) {
     28   RtpPacket* rtp_packet = new RtpPacket;
     29   for (size_t i = 0; i < length; ++i)
     30     rtp_packet->data[i + kRtpHeaderSize] = offset + i;
     31   rtp_packet->length = length + kRtpHeaderSize;
     32   memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader));
     33   rtp_packet->header.frameType = kVideoFrameDelta;
     34   rtp_packet->header.header.headerLength = kRtpHeaderSize;
     35   rtp_packet->header.header.markerBit = (num_packets_ == 1);
     36   rtp_packet->header.header.sequenceNumber = seq_num_;
     37   rtp_packet->header.header.timestamp = timestamp_;
     38   rtp_packet->header.header.payloadType = kVp8PayloadType;
     39   BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header);
     40   ++seq_num_;
     41   --num_packets_;
     42   return rtp_packet;
     43 }
     44 
     45 // Creates a new RtpPacket with the RED header added to the packet.
     46 RtpPacket* FrameGenerator::BuildMediaRedPacket(const RtpPacket* packet) {
     47   const int kHeaderLength = packet->header.header.headerLength;
     48   RtpPacket* red_packet = new RtpPacket;
     49   red_packet->header = packet->header;
     50   red_packet->length = packet->length + 1;  // 1 byte RED header.
     51   memset(red_packet->data, 0, red_packet->length);
     52   // Copy RTP header.
     53   memcpy(red_packet->data, packet->data, kHeaderLength);
     54   SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength);
     55   memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength,
     56          packet->length - kHeaderLength);
     57   return red_packet;
     58 }
     59 
     60 // Creates a new RtpPacket with FEC payload and red header. Does this by
     61 // creating a new fake media RtpPacket, clears the marker bit and adds a RED
     62 // header. Finally replaces the payload with the content of |packet->data|.
     63 RtpPacket* FrameGenerator::BuildFecRedPacket(const Packet* packet) {
     64   // Create a fake media packet to get a correct header. 1 byte RED header.
     65   ++num_packets_;
     66   RtpPacket* red_packet = NextPacket(0, packet->length + 1);
     67   red_packet->data[1] &= ~0x80;  // Clear marker bit.
     68   const int kHeaderLength = red_packet->header.header.headerLength;
     69   SetRedHeader(red_packet, kFecPayloadType, kHeaderLength);
     70   memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length);
     71   red_packet->length = kHeaderLength + 1 + packet->length;
     72   return red_packet;
     73 }
     74 
     75 void FrameGenerator::SetRedHeader(Packet* red_packet, uint8_t payload_type,
     76                                   int header_length) const {
     77   // Replace pltype.
     78   red_packet->data[1] &= 0x80;             // Reset.
     79   red_packet->data[1] += kRedPayloadType;  // Replace.
     80 
     81   // Add RED header, f-bit always 0.
     82   red_packet->data[header_length] = payload_type;
     83 }
     84 
     85 void FrameGenerator::BuildRtpHeader(uint8_t* data, const RTPHeader* header) {
     86   data[0] = 0x80;  // Version 2.
     87   data[1] = header->payloadType;
     88   data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0);
     89   RtpUtility::AssignUWord16ToBuffer(data + 2, header->sequenceNumber);
     90   RtpUtility::AssignUWord32ToBuffer(data + 4, header->timestamp);
     91   RtpUtility::AssignUWord32ToBuffer(data + 8, header->ssrc);
     92 }
     93 
     94 }  // namespace webrtc
     95