blob: 4d037b7ba38239db179991bbc3a114620aa822e0 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef TALK_MEDIA_BASE_TESTUTILS_H_
29#define TALK_MEDIA_BASE_TESTUTILS_H_
30
wu@webrtc.orgcadf9042013-08-30 21:24:16 +000031#ifdef LINUX
32#include <X11/Xlib.h>
33// X defines a few macros that stomp on types that gunit.h uses.
34#undef None
35#undef Bool
36#endif
37
henrike@webrtc.org28e20752013-07-10 00:45:36 +000038#include <string>
39#include <vector>
wu@webrtc.orgcadf9042013-08-30 21:24:16 +000040
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041#if !defined(DISABLE_YUV)
42#include "libyuv/compare.h"
43#endif
44#include "talk/base/basictypes.h"
45#include "talk/base/sigslot.h"
46#include "talk/base/window.h"
47#include "talk/media/base/mediachannel.h"
48#include "talk/media/base/videocapturer.h"
49#include "talk/media/base/videocommon.h"
50
51namespace talk_base {
52class ByteBuffer;
53class StreamInterface;
54}
55
56namespace cricket {
57
58// Returns size of 420 image with rounding on chroma for odd sizes.
59#define I420_SIZE(w, h) (w * h + (((w + 1) / 2) * ((h + 1) / 2)) * 2)
60// Returns size of ARGB image.
61#define ARGB_SIZE(w, h) (w * h * 4)
62
63template <class T> inline std::vector<T> MakeVector(const T a[], size_t s) {
64 return std::vector<T>(a, a + s);
65}
66#define MAKE_VECTOR(a) cricket::MakeVector(a, ARRAY_SIZE(a))
67
68struct RtpDumpPacket;
69class RtpDumpWriter;
70class VideoFrame;
71
72struct RawRtpPacket {
73 void WriteToByteBuffer(uint32 in_ssrc, talk_base::ByteBuffer* buf) const;
74 bool ReadFromByteBuffer(talk_base::ByteBuffer* buf);
75 // Check if this packet is the same as the specified packet except the
76 // sequence number and timestamp, which should be the same as the specified
77 // parameters.
78 bool SameExceptSeqNumTimestampSsrc(
79 const RawRtpPacket& packet, uint16 seq, uint32 ts, uint32 ssc) const;
80 int size() const { return 28; }
81
82 uint8 ver_to_cc;
83 uint8 m_to_pt;
84 uint16 sequence_number;
85 uint32 timestamp;
86 uint32 ssrc;
87 char payload[16];
88};
89
90struct RawRtcpPacket {
91 void WriteToByteBuffer(talk_base::ByteBuffer* buf) const;
92 bool ReadFromByteBuffer(talk_base::ByteBuffer* buf);
93 bool EqualsTo(const RawRtcpPacket& packet) const;
94
95 uint8 ver_to_count;
96 uint8 type;
97 uint16 length;
98 char payload[16];
99};
100
101class RtpTestUtility {
102 public:
103 static size_t GetTestPacketCount();
104
105 // Write the first count number of kTestRawRtcpPackets or kTestRawRtpPackets,
106 // depending on the flag rtcp. If it is RTP, use the specified SSRC. Return
107 // true if successful.
108 static bool WriteTestPackets(
109 size_t count, bool rtcp, uint32 rtp_ssrc, RtpDumpWriter* writer);
110
111 // Loop read the first count number of packets from the specified stream.
112 // Verify the elapsed time of the dump packets increase monotonically. If the
113 // stream is a RTP stream, verify the RTP sequence number, timestamp, and
114 // payload. If the stream is a RTCP stream, verify the RTCP header and
115 // payload.
116 static bool VerifyTestPacketsFromStream(
117 size_t count, talk_base::StreamInterface* stream, uint32 ssrc);
118
119 // Verify the dump packet is the same as the raw RTP packet.
120 static bool VerifyPacket(const RtpDumpPacket* dump,
121 const RawRtpPacket* raw,
122 bool header_only);
123
124 static const uint32 kDefaultSsrc = 1;
125 static const uint32 kRtpTimestampIncrease = 90;
126 static const uint32 kDefaultTimeIncrease = 30;
127 static const uint32 kElapsedTimeInterval = 10;
128 static const RawRtpPacket kTestRawRtpPackets[];
129 static const RawRtcpPacket kTestRawRtcpPackets[];
130
131 private:
132 RtpTestUtility() {}
133};
134
135// Test helper for testing VideoCapturer implementations.
136class VideoCapturerListener : public sigslot::has_slots<> {
137 public:
138 explicit VideoCapturerListener(VideoCapturer* cap);
139
140 CaptureState last_capture_state() const { return last_capture_state_; }
141 int frame_count() const { return frame_count_; }
142 uint32 frame_fourcc() const { return frame_fourcc_; }
143 int frame_width() const { return frame_width_; }
144 int frame_height() const { return frame_height_; }
145 uint32 frame_size() const { return frame_size_; }
146 bool resolution_changed() const { return resolution_changed_; }
147
148 void OnStateChange(VideoCapturer* capturer, CaptureState state);
149 void OnFrameCaptured(VideoCapturer* capturer, const CapturedFrame* frame);
150
151 private:
152 CaptureState last_capture_state_;
153 int frame_count_;
154 uint32 frame_fourcc_;
155 int frame_width_;
156 int frame_height_;
157 uint32 frame_size_;
158 bool resolution_changed_;
159};
160
161class ScreencastEventCatcher : public sigslot::has_slots<> {
162 public:
163 ScreencastEventCatcher() : ssrc_(0), ev_(talk_base::WE_RESIZE) { }
164 uint32 ssrc() const { return ssrc_; }
165 talk_base::WindowEvent event() const { return ev_; }
166 void OnEvent(uint32 ssrc, talk_base::WindowEvent ev) {
167 ssrc_ = ssrc;
168 ev_ = ev;
169 }
170 private:
171 uint32 ssrc_;
172 talk_base::WindowEvent ev_;
173};
174
175class VideoMediaErrorCatcher : public sigslot::has_slots<> {
176 public:
177 VideoMediaErrorCatcher() : ssrc_(0), error_(VideoMediaChannel::ERROR_NONE) { }
178 uint32 ssrc() const { return ssrc_; }
179 VideoMediaChannel::Error error() const { return error_; }
180 void OnError(uint32 ssrc, VideoMediaChannel::Error error) {
181 ssrc_ = ssrc;
182 error_ = error;
183 }
184 private:
185 uint32 ssrc_;
186 VideoMediaChannel::Error error_;
187};
188
189// Returns the absolute path to a file in the testdata/ directory.
190std::string GetTestFilePath(const std::string& filename);
191
192// PSNR formula: psnr = 10 * log10 (Peak Signal^2 / mse)
193// sse is set to a small number for identical frames or sse == 0
194static inline double ComputePSNR(double sse, double count) {
195#if !defined(DISABLE_YUV)
196 return libyuv::SumSquareErrorToPsnr(static_cast<uint64>(sse),
197 static_cast<uint64>(count));
198#else
199 if (sse <= 0.)
200 sse = 65025.0 * count / pow(10., 128./10.); // produces max PSNR of 128
201 return 10.0 * log10(65025.0 * count / sse);
202#endif
203}
204
205static inline double ComputeSumSquareError(const uint8 *org, const uint8 *rec,
206 int size) {
207#if !defined(DISABLE_YUV)
208 return static_cast<double>(libyuv::ComputeSumSquareError(org, rec, size));
209#else
210 double sse = 0.;
211 for (int j = 0; j < size; ++j) {
212 const int diff = static_cast<int>(org[j]) - static_cast<int>(rec[j]);
213 sse += static_cast<double>(diff * diff);
214 }
215 return sse;
216#endif
217}
218
219// Loads the image with the specified prefix and size into |out|.
220bool LoadPlanarYuvTestImage(const std::string& prefix,
221 int width, int height, uint8* out);
222
223// Dumps the YUV image out to a file, for visual inspection.
224// PYUV tool can be used to view dump files.
225void DumpPlanarYuvTestImage(const std::string& prefix, const uint8* img,
226 int w, int h);
227
228// Dumps the ARGB image out to a file, for visual inspection.
229// ffplay tool can be used to view dump files.
230void DumpPlanarArgbTestImage(const std::string& prefix, const uint8* img,
231 int w, int h);
232
233// Compare two I420 frames.
234bool VideoFrameEqual(const VideoFrame* frame0, const VideoFrame* frame1);
235
236// Checks whether |codecs| contains |codec|; checks using Codec::Matches().
237template <class C>
238bool ContainsMatchingCodec(const std::vector<C>& codecs, const C& codec) {
239 typename std::vector<C>::const_iterator it;
240 for (it = codecs.begin(); it != codecs.end(); ++it) {
241 if (it->Matches(codec)) {
242 return true;
243 }
244 }
245 return false;
246}
247
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000248#define MAYBE_SKIP_SCREENCAST_TEST() \
249 if (!cricket::IsScreencastingAvailable()) { \
250 LOG(LS_WARNING) << "Skipping test, since it doesn't have the requisite " \
251 << "X environment for screen capture."; \
252 return; \
253 } \
254
255#ifdef LINUX
256struct XDisplay {
257 XDisplay() : display_(XOpenDisplay(NULL)) { }
258 ~XDisplay() { if (display_) XCloseDisplay(display_); }
259 bool IsValid() const { return display_ != NULL; }
260 operator Display*() { return display_; }
261 private:
262 Display* display_;
263};
264#endif
265
266// Returns true if screencasting is available. When false, anything that uses
267// screencasting features may fail.
268inline bool IsScreencastingAvailable() {
269#ifdef LINUX
270 XDisplay display;
271 if (!display.IsValid()) {
272 LOG(LS_WARNING) << "No X Display available.";
273 return false;
274 }
275#endif
276 return true;
277}
278
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279} // namespace cricket
280
281#endif // TALK_MEDIA_BASE_TESTUTILS_H_