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