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 <stdlib.h>
12
13 #include <algorithm>
14 #include <vector>
15
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/common_types.h"
18 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
19 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
20 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
22 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h"
23 #include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h"
24
25 namespace {
26
27 const unsigned char kPayloadType = 100;
28
29 };
30
31 namespace webrtc {
32
33 class RtpRtcpVideoTest : public ::testing::Test {
34 protected:
RtpRtcpVideoTest()35 RtpRtcpVideoTest()
36 : rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
37 test_ssrc_(3456),
38 test_timestamp_(4567),
39 test_sequence_number_(2345),
40 fake_clock(123456) {}
~RtpRtcpVideoTest()41 ~RtpRtcpVideoTest() {}
42
SetUp()43 virtual void SetUp() {
44 transport_ = new LoopBackTransport();
45 receiver_ = new TestRtpReceiver();
46 receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock));
47 RtpRtcp::Configuration configuration;
48 configuration.audio = false;
49 configuration.clock = &fake_clock;
50 configuration.outgoing_transport = transport_;
51
52 video_module_ = RtpRtcp::CreateRtpRtcp(configuration);
53 rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
54 &fake_clock, receiver_, NULL, &rtp_payload_registry_));
55
56 video_module_->SetRTCPStatus(RtcpMode::kCompound);
57 video_module_->SetSSRC(test_ssrc_);
58 rtp_receiver_->SetNACKStatus(kNackRtcp);
59 video_module_->SetStorePacketsStatus(true, 600);
60 EXPECT_EQ(0, video_module_->SetSendingStatus(true));
61
62 transport_->SetSendModule(video_module_, &rtp_payload_registry_,
63 rtp_receiver_.get(), receive_statistics_.get());
64
65 VideoCodec video_codec;
66 memset(&video_codec, 0, sizeof(video_codec));
67 video_codec.plType = 123;
68 memcpy(video_codec.plName, "I420", 5);
69
70 EXPECT_EQ(0, video_module_->RegisterSendPayload(video_codec));
71 EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(video_codec.plName,
72 video_codec.plType,
73 90000,
74 0,
75 video_codec.maxBitrate));
76
77 payload_data_length_ = sizeof(video_frame_);
78
79 for (size_t n = 0; n < payload_data_length_; n++) {
80 video_frame_[n] = n%10;
81 }
82 }
83
BuildRTPheader(uint8_t * dataBuffer,uint32_t timestamp,uint32_t sequence_number)84 size_t BuildRTPheader(uint8_t* dataBuffer,
85 uint32_t timestamp,
86 uint32_t sequence_number) {
87 dataBuffer[0] = static_cast<uint8_t>(0x80); // version 2
88 dataBuffer[1] = static_cast<uint8_t>(kPayloadType);
89 ByteWriter<uint16_t>::WriteBigEndian(dataBuffer + 2, sequence_number);
90 ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + 4, timestamp);
91 ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + 8, 0x1234); // SSRC.
92 size_t rtpHeaderLength = 12;
93 return rtpHeaderLength;
94 }
95
PaddingPacket(uint8_t * buffer,uint32_t timestamp,uint32_t sequence_number,size_t bytes)96 size_t PaddingPacket(uint8_t* buffer,
97 uint32_t timestamp,
98 uint32_t sequence_number,
99 size_t bytes) {
100 // Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP.
101 size_t max_length = 224;
102
103 size_t padding_bytes_in_packet = max_length;
104 if (bytes < max_length) {
105 padding_bytes_in_packet = (bytes + 16) & 0xffe0; // Keep our modulus 32.
106 }
107 // Correct seq num, timestamp and payload type.
108 size_t header_length = BuildRTPheader(buffer, timestamp, sequence_number);
109 buffer[0] |= 0x20; // Set padding bit.
110 int32_t* data =
111 reinterpret_cast<int32_t*>(&(buffer[header_length]));
112
113 // Fill data buffer with random data.
114 for (size_t j = 0; j < (padding_bytes_in_packet >> 2); j++) {
115 data[j] = rand(); // NOLINT
116 }
117 // Set number of padding bytes in the last byte of the packet.
118 buffer[header_length + padding_bytes_in_packet - 1] =
119 padding_bytes_in_packet;
120 return padding_bytes_in_packet + header_length;
121 }
122
TearDown()123 virtual void TearDown() {
124 delete video_module_;
125 delete transport_;
126 delete receiver_;
127 }
128
129 int test_id_;
130 rtc::scoped_ptr<ReceiveStatistics> receive_statistics_;
131 RTPPayloadRegistry rtp_payload_registry_;
132 rtc::scoped_ptr<RtpReceiver> rtp_receiver_;
133 RtpRtcp* video_module_;
134 LoopBackTransport* transport_;
135 TestRtpReceiver* receiver_;
136 uint32_t test_ssrc_;
137 uint32_t test_timestamp_;
138 uint16_t test_sequence_number_;
139 uint8_t video_frame_[65000];
140 size_t payload_data_length_;
141 SimulatedClock fake_clock;
142 };
143
TEST_F(RtpRtcpVideoTest,BasicVideo)144 TEST_F(RtpRtcpVideoTest, BasicVideo) {
145 uint32_t timestamp = 3000;
146 EXPECT_EQ(0, video_module_->SendOutgoingData(kVideoFrameDelta, 123,
147 timestamp,
148 timestamp / 90,
149 video_frame_,
150 payload_data_length_));
151 }
152
TEST_F(RtpRtcpVideoTest,PaddingOnlyFrames)153 TEST_F(RtpRtcpVideoTest, PaddingOnlyFrames) {
154 const size_t kPadSize = 255;
155 uint8_t padding_packet[kPadSize];
156 uint32_t seq_num = 0;
157 uint32_t timestamp = 3000;
158 VideoCodec codec;
159 codec.codecType = kVideoCodecVP8;
160 codec.plType = kPayloadType;
161 strncpy(codec.plName, "VP8", 4);
162 EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(codec.plName,
163 codec.plType,
164 90000,
165 0,
166 codec.maxBitrate));
167 for (int frame_idx = 0; frame_idx < 10; ++frame_idx) {
168 for (int packet_idx = 0; packet_idx < 5; ++packet_idx) {
169 size_t packet_size = PaddingPacket(padding_packet, timestamp, seq_num,
170 kPadSize);
171 ++seq_num;
172 RTPHeader header;
173 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
174 EXPECT_TRUE(parser->Parse(padding_packet, packet_size, &header));
175 PayloadUnion payload_specific;
176 EXPECT_TRUE(rtp_payload_registry_.GetPayloadSpecifics(header.payloadType,
177 &payload_specific));
178 const uint8_t* payload = padding_packet + header.headerLength;
179 const size_t payload_length = packet_size - header.headerLength;
180 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, payload,
181 payload_length,
182 payload_specific, true));
183 EXPECT_EQ(0u, receiver_->payload_size());
184 EXPECT_EQ(payload_length, receiver_->rtp_header().header.paddingLength);
185 }
186 timestamp += 3000;
187 fake_clock.AdvanceTimeMilliseconds(33);
188 }
189 }
190
191 } // namespace webrtc
192