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
FrameGenerator()18 FrameGenerator::FrameGenerator()
19 : num_packets_(0), seq_num_(0), timestamp_(0) {}
20
NewFrame(int num_packets)21 void FrameGenerator::NewFrame(int num_packets) {
22 num_packets_ = num_packets;
23 timestamp_ += 3000;
24 }
25
NextSeqNum()26 uint16_t FrameGenerator::NextSeqNum() { return ++seq_num_; }
27
NextPacket(int offset,size_t length)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.
BuildMediaRedPacket(const RtpPacket * 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|.
BuildFecRedPacket(const Packet * packet)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
SetRedHeader(Packet * red_packet,uint8_t payload_type,size_t header_length) const76 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
BuildRtpHeader(uint8_t * data,const RTPHeader * header)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