blob: 9e2d174f61b6508dcea0d0b1ce051a3c327f6956 [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"
26#include "webrtc/media/base/videoframe.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)
213 : last_capture_state_(CS_STARTING),
214 frame_count_(0),
215 frame_fourcc_(0),
216 frame_width_(0),
217 frame_height_(0),
218 frame_size_(0),
219 resolution_changed_(false) {
220 capturer->SignalStateChange.connect(this,
221 &VideoCapturerListener::OnStateChange);
222 capturer->SignalFrameCaptured.connect(this,
223 &VideoCapturerListener::OnFrameCaptured);
224}
225
226void VideoCapturerListener::OnStateChange(VideoCapturer* capturer,
227 CaptureState result) {
228 last_capture_state_ = result;
229}
230
231void VideoCapturerListener::OnFrameCaptured(VideoCapturer* capturer,
232 const CapturedFrame* frame) {
233 ++frame_count_;
234 if (1 == frame_count_) {
235 frame_fourcc_ = frame->fourcc;
236 frame_width_ = frame->width;
237 frame_height_ = frame->height;
238 frame_size_ = frame->data_size;
239 } else if (frame_width_ != frame->width || frame_height_ != frame->height) {
240 resolution_changed_ = true;
241 }
242}
243
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000244cricket::StreamParams CreateSimStreamParams(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200245 const std::string& cname,
246 const std::vector<uint32_t>& ssrcs) {
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000247 cricket::StreamParams sp;
248 cricket::SsrcGroup sg(cricket::kSimSsrcGroupSemantics, ssrcs);
249 sp.ssrcs = ssrcs;
250 sp.ssrc_groups.push_back(sg);
251 sp.cname = cname;
252 return sp;
253}
254
255// There should be an rtx_ssrc per ssrc.
256cricket::StreamParams CreateSimWithRtxStreamParams(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200257 const std::string& cname,
258 const std::vector<uint32_t>& ssrcs,
259 const std::vector<uint32_t>& rtx_ssrcs) {
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000260 cricket::StreamParams sp = CreateSimStreamParams(cname, ssrcs);
261 for (size_t i = 0; i < ssrcs.size(); ++i) {
262 sp.ssrcs.push_back(rtx_ssrcs[i]);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200263 std::vector<uint32_t> fid_ssrcs;
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000264 fid_ssrcs.push_back(ssrcs[i]);
265 fid_ssrcs.push_back(rtx_ssrcs[i]);
266 cricket::SsrcGroup fid_group(cricket::kFidSsrcGroupSemantics, fid_ssrcs);
267 sp.ssrc_groups.push_back(fid_group);
268 }
269 return sp;
270}
271
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000272} // namespace cricket