blob: 93d1bc0b3df13186bdf74f477c1f069c362a1150 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kjellandera96e2d72016-02-04 23:52:28 -080011#include "webrtc/media/base/testutils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
13#include <math.h>
andresp@webrtc.orgff689be2015-02-12 11:54:26 +000014#include <algorithm>
kwiberg686a8ef2016-02-26 03:00:35 -080015#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000016
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000017#include "webrtc/base/bytebuffer.h"
18#include "webrtc/base/fileutils.h"
19#include "webrtc/base/gunit.h"
20#include "webrtc/base/pathutils.h"
21#include "webrtc/base/stream.h"
22#include "webrtc/base/stringutils.h"
23#include "webrtc/base/testutils.h"
kjellandera96e2d72016-02-04 23:52:28 -080024#include "webrtc/media/base/rtpdump.h"
25#include "webrtc/media/base/videocapturer.h"
nisseacd935b2016-11-11 03:55:13 -080026#include "webrtc/video_frame.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
28namespace cricket {
29
30/////////////////////////////////////////////////////////////////////////
31// Implementation of RawRtpPacket
32/////////////////////////////////////////////////////////////////////////
Peter Boström0c4e06b2015-10-07 12:23:21 +020033void RawRtpPacket::WriteToByteBuffer(uint32_t in_ssrc,
jbauchf1f87202016-03-30 06:43:37 -070034 rtc::ByteBufferWriter* buf) const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035 if (!buf) return;
36
37 buf->WriteUInt8(ver_to_cc);
38 buf->WriteUInt8(m_to_pt);
39 buf->WriteUInt16(sequence_number);
40 buf->WriteUInt32(timestamp);
41 buf->WriteUInt32(in_ssrc);
42 buf->WriteBytes(payload, sizeof(payload));
43}
44
jbauchf1f87202016-03-30 06:43:37 -070045bool RawRtpPacket::ReadFromByteBuffer(rtc::ByteBufferReader* buf) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046 if (!buf) return false;
47
48 bool ret = true;
49 ret &= buf->ReadUInt8(&ver_to_cc);
50 ret &= buf->ReadUInt8(&m_to_pt);
51 ret &= buf->ReadUInt16(&sequence_number);
52 ret &= buf->ReadUInt32(&timestamp);
53 ret &= buf->ReadUInt32(&ssrc);
54 ret &= buf->ReadBytes(payload, sizeof(payload));
55 return ret;
56}
57
Peter Boström0c4e06b2015-10-07 12:23:21 +020058bool RawRtpPacket::SameExceptSeqNumTimestampSsrc(const RawRtpPacket& packet,
59 uint16_t seq,
60 uint32_t ts,
61 uint32_t ssc) const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062 return sequence_number == seq &&
63 timestamp == ts &&
64 ver_to_cc == packet.ver_to_cc &&
65 m_to_pt == packet.m_to_pt &&
66 ssrc == ssc &&
67 0 == memcmp(payload, packet.payload, sizeof(payload));
68}
69
70/////////////////////////////////////////////////////////////////////////
71// Implementation of RawRtcpPacket
72/////////////////////////////////////////////////////////////////////////
jbauchf1f87202016-03-30 06:43:37 -070073void RawRtcpPacket::WriteToByteBuffer(rtc::ByteBufferWriter *buf) const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074 if (!buf) return;
75
76 buf->WriteUInt8(ver_to_count);
77 buf->WriteUInt8(type);
78 buf->WriteUInt16(length);
79 buf->WriteBytes(payload, sizeof(payload));
80}
81
jbauchf1f87202016-03-30 06:43:37 -070082bool RawRtcpPacket::ReadFromByteBuffer(rtc::ByteBufferReader* buf) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083 if (!buf) return false;
84
85 bool ret = true;
86 ret &= buf->ReadUInt8(&ver_to_count);
87 ret &= buf->ReadUInt8(&type);
88 ret &= buf->ReadUInt16(&length);
89 ret &= buf->ReadBytes(payload, sizeof(payload));
90 return ret;
91}
92
93bool RawRtcpPacket::EqualsTo(const RawRtcpPacket& packet) const {
94 return ver_to_count == packet.ver_to_count &&
95 type == packet.type &&
96 length == packet.length &&
97 0 == memcmp(payload, packet.payload, sizeof(payload));
98}
99
100/////////////////////////////////////////////////////////////////////////
101// Implementation of class RtpTestUtility
102/////////////////////////////////////////////////////////////////////////
103const RawRtpPacket RtpTestUtility::kTestRawRtpPackets[] = {
104 {0x80, 0, 0, 0, RtpTestUtility::kDefaultSsrc, "RTP frame 0"},
105 {0x80, 0, 1, 30, RtpTestUtility::kDefaultSsrc, "RTP frame 1"},
106 {0x80, 0, 2, 30, RtpTestUtility::kDefaultSsrc, "RTP frame 1"},
107 {0x80, 0, 3, 60, RtpTestUtility::kDefaultSsrc, "RTP frame 2"}
108};
109const RawRtcpPacket RtpTestUtility::kTestRawRtcpPackets[] = {
110 // The Version is 2, the Length is 2, and the payload has 8 bytes.
111 {0x80, 0, 2, "RTCP0000"},
112 {0x80, 0, 2, "RTCP0001"},
113 {0x80, 0, 2, "RTCP0002"},
114 {0x80, 0, 2, "RTCP0003"},
115};
116
117size_t RtpTestUtility::GetTestPacketCount() {
tfarina5237aaf2015-11-10 23:44:30 -0800118 return std::min(arraysize(kTestRawRtpPackets),
119 arraysize(kTestRawRtcpPackets));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000120}
121
Peter Boström0c4e06b2015-10-07 12:23:21 +0200122bool RtpTestUtility::WriteTestPackets(size_t count,
123 bool rtcp,
124 uint32_t rtp_ssrc,
125 RtpDumpWriter* writer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000126 if (!writer || count > GetTestPacketCount()) return false;
127
128 bool result = true;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200129 uint32_t elapsed_time_ms = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130 for (size_t i = 0; i < count && result; ++i) {
jbauchf1f87202016-03-30 06:43:37 -0700131 rtc::ByteBufferWriter buf;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000132 if (rtcp) {
133 kTestRawRtcpPackets[i].WriteToByteBuffer(&buf);
134 } else {
135 kTestRawRtpPackets[i].WriteToByteBuffer(rtp_ssrc, &buf);
136 }
137
138 RtpDumpPacket dump_packet(buf.Data(), buf.Length(), elapsed_time_ms, rtcp);
139 elapsed_time_ms += kElapsedTimeInterval;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000140 result &= (rtc::SR_SUCCESS == writer->WritePacket(dump_packet));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000141 }
142 return result;
143}
144
Peter Boström0c4e06b2015-10-07 12:23:21 +0200145bool RtpTestUtility::VerifyTestPacketsFromStream(size_t count,
146 rtc::StreamInterface* stream,
147 uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 if (!stream) return false;
149
Peter Boström0c4e06b2015-10-07 12:23:21 +0200150 uint32_t prev_elapsed_time = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000151 bool result = true;
152 stream->Rewind();
153 RtpDumpLoopReader reader(stream);
154 for (size_t i = 0; i < count && result; ++i) {
155 // Which loop and which index in the loop are we reading now.
156 size_t loop = i / GetTestPacketCount();
157 size_t index = i % GetTestPacketCount();
158
159 RtpDumpPacket packet;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000160 result &= (rtc::SR_SUCCESS == reader.ReadPacket(&packet));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161 // Check the elapsed time of the dump packet.
162 result &= (packet.elapsed_time >= prev_elapsed_time);
163 prev_elapsed_time = packet.elapsed_time;
164
165 // Check the RTP or RTCP packet.
jbauchf1f87202016-03-30 06:43:37 -0700166 rtc::ByteBufferReader buf(reinterpret_cast<const char*>(&packet.data[0]),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 packet.data.size());
168 if (packet.is_rtcp()) {
169 // RTCP packet.
170 RawRtcpPacket rtcp_packet;
171 result &= rtcp_packet.ReadFromByteBuffer(&buf);
172 result &= rtcp_packet.EqualsTo(kTestRawRtcpPackets[index]);
173 } else {
174 // RTP packet.
175 RawRtpPacket rtp_packet;
176 result &= rtp_packet.ReadFromByteBuffer(&buf);
177 result &= rtp_packet.SameExceptSeqNumTimestampSsrc(
178 kTestRawRtpPackets[index],
Peter Boström0c4e06b2015-10-07 12:23:21 +0200179 static_cast<uint16_t>(kTestRawRtpPackets[index].sequence_number +
180 loop * GetTestPacketCount()),
181 static_cast<uint32_t>(kTestRawRtpPackets[index].timestamp +
182 loop * kRtpTimestampIncrease),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000183 ssrc);
184 }
185 }
186
187 stream->Rewind();
188 return result;
189}
190
191bool RtpTestUtility::VerifyPacket(const RtpDumpPacket* dump,
192 const RawRtpPacket* raw,
193 bool header_only) {
194 if (!dump || !raw) return false;
195
jbauchf1f87202016-03-30 06:43:37 -0700196 rtc::ByteBufferWriter buf;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000197 raw->WriteToByteBuffer(RtpTestUtility::kDefaultSsrc, &buf);
198
199 if (header_only) {
200 size_t header_len = 0;
201 dump->GetRtpHeaderLen(&header_len);
202 return header_len == dump->data.size() &&
203 buf.Length() > dump->data.size() &&
204 0 == memcmp(buf.Data(), &dump->data[0], dump->data.size());
205 } else {
206 return buf.Length() == dump->data.size() &&
207 0 == memcmp(buf.Data(), &dump->data[0], dump->data.size());
208 }
209}
210
211// Implementation of VideoCaptureListener.
212VideoCapturerListener::VideoCapturerListener(VideoCapturer* capturer)
nisse79246972016-08-23 05:50:09 -0700213 : capturer_(capturer),
214 last_capture_state_(CS_STARTING),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 frame_count_(0),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000216 frame_width_(0),
217 frame_height_(0),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000218 resolution_changed_(false) {
219 capturer->SignalStateChange.connect(this,
220 &VideoCapturerListener::OnStateChange);
nisse79246972016-08-23 05:50:09 -0700221 capturer->AddOrUpdateSink(this, rtc::VideoSinkWants());
222}
223
224VideoCapturerListener::~VideoCapturerListener() {
225 capturer_->RemoveSink(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226}
227
228void VideoCapturerListener::OnStateChange(VideoCapturer* capturer,
229 CaptureState result) {
230 last_capture_state_ = result;
231}
232
nisseacd935b2016-11-11 03:55:13 -0800233void VideoCapturerListener::OnFrame(const webrtc::VideoFrame& frame) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234 ++frame_count_;
235 if (1 == frame_count_) {
nisse79246972016-08-23 05:50:09 -0700236 frame_width_ = frame.width();
237 frame_height_ = frame.height();
238 } else if (frame_width_ != frame.width() || frame_height_ != frame.height()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000239 resolution_changed_ = true;
240 }
241}
242
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000243cricket::StreamParams CreateSimStreamParams(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200244 const std::string& cname,
245 const std::vector<uint32_t>& ssrcs) {
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000246 cricket::StreamParams sp;
247 cricket::SsrcGroup sg(cricket::kSimSsrcGroupSemantics, ssrcs);
248 sp.ssrcs = ssrcs;
249 sp.ssrc_groups.push_back(sg);
250 sp.cname = cname;
251 return sp;
252}
253
254// There should be an rtx_ssrc per ssrc.
255cricket::StreamParams CreateSimWithRtxStreamParams(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200256 const std::string& cname,
257 const std::vector<uint32_t>& ssrcs,
258 const std::vector<uint32_t>& rtx_ssrcs) {
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000259 cricket::StreamParams sp = CreateSimStreamParams(cname, ssrcs);
260 for (size_t i = 0; i < ssrcs.size(); ++i) {
261 sp.ssrcs.push_back(rtx_ssrcs[i]);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200262 std::vector<uint32_t> fid_ssrcs;
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000263 fid_ssrcs.push_back(ssrcs[i]);
264 fid_ssrcs.push_back(rtx_ssrcs[i]);
265 cricket::SsrcGroup fid_group(cricket::kFidSsrcGroupSemantics, fid_ssrcs);
266 sp.ssrc_groups.push_back(fid_group);
267 }
268 return sp;
269}
270
brandtr9688e382016-11-22 00:59:48 -0800271cricket::StreamParams CreatePrimaryWithFecFrStreamParams(
272 const std::string& cname,
273 uint32_t primary_ssrc,
274 uint32_t flexfec_ssrc) {
275 cricket::StreamParams sp;
276 cricket::SsrcGroup sg(cricket::kFecFrSsrcGroupSemantics,
277 {primary_ssrc, flexfec_ssrc});
278 sp.ssrcs = {primary_ssrc};
279 sp.ssrc_groups.push_back(sg);
280 sp.cname = cname;
281 return sp;
282}
283
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284} // namespace cricket