1 /*
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_SESSION_PHONE_TESTUTILS_H_
29 #define TALK_SESSION_PHONE_TESTUTILS_H_
30 
31 #include <string>
32 #include <vector>
33 
34 #include "talk/base/basictypes.h"
35 #include "talk/base/sigslot.h"
36 #include "talk/base/window.h"
37 #include "talk/session/phone/mediachannel.h"
38 #include "talk/session/phone/videocommon.h"
39 #include "talk/session/phone/videocapturer.h"
40 
41 namespace talk_base {
42 class ByteBuffer;
43 class StreamInterface;
44 }
45 
46 namespace cricket {
47 
48 // Returns size of 420 image with rounding on chroma for odd sizes.
49 #define I420_SIZE(w, h) (w * h + (((w + 1) / 2) * ((h + 1) / 2)) * 2)
50 // Returns size of ARGB image.
51 #define ARGB_SIZE(w, h) (w * h * 4)
52 
MakeVector(const T a[],size_t s)53 template <class T> inline std::vector<T> MakeVector(const T a[], size_t s) {
54   return std::vector<T>(a, a + s);
55 }
56 #define MAKE_VECTOR(a) cricket::MakeVector(a, ARRAY_SIZE(a))
57 
58 struct RtpDumpPacket;
59 class RtpDumpWriter;
60 class VideoFrame;
61 
62 struct RawRtpPacket {
63   void WriteToByteBuffer(uint32 in_ssrc, talk_base::ByteBuffer* buf) const;
64   bool ReadFromByteBuffer(talk_base::ByteBuffer* buf);
65   // Check if this packet is the same as the specified packet except the
66   // sequence number and timestamp, which should be the same as the specified
67   // parameters.
68   bool SameExceptSeqNumTimestampSsrc(
69       const RawRtpPacket& packet, uint16 seq, uint32 ts, uint32 ssc) const;
sizeRawRtpPacket70   int size() const { return 28; }
71 
72   uint8 ver_to_cc;
73   uint8 m_to_pt;
74   uint16 sequence_number;
75   uint32 timestamp;
76   uint32 ssrc;
77   char payload[16];
78 };
79 
80 struct RawRtcpPacket {
81   void WriteToByteBuffer(talk_base::ByteBuffer* buf) const;
82   bool ReadFromByteBuffer(talk_base::ByteBuffer* buf);
83   bool EqualsTo(const RawRtcpPacket& packet) const;
84 
85   uint8 ver_to_count;
86   uint8 type;
87   uint16 length;
88   char payload[16];
89 };
90 
91 class RtpTestUtility {
92  public:
93   static size_t GetTestPacketCount();
94 
95   // Write the first count number of kTestRawRtcpPackets or kTestRawRtpPackets,
96   // depending on the flag rtcp. If it is RTP, use the specified SSRC. Return
97   // true if successful.
98   static bool WriteTestPackets(
99       size_t count, bool rtcp, uint32 rtp_ssrc, RtpDumpWriter* writer);
100 
101   // Loop read the first count number of packets from the specified stream.
102   // Verify the elapsed time of the dump packets increase monotonically. If the
103   // stream is a RTP stream, verify the RTP sequence number, timestamp, and
104   // payload. If the stream is a RTCP stream, verify the RTCP header and
105   // payload.
106   static bool VerifyTestPacketsFromStream(
107       size_t count, talk_base::StreamInterface* stream, uint32 ssrc);
108 
109   // Verify the dump packet is the same as the raw RTP packet.
110   static bool VerifyPacket(const RtpDumpPacket* dump,
111                            const RawRtpPacket* raw,
112                            bool header_only);
113 
114   static const uint32 kDefaultSsrc = 1;
115   static const uint32 kRtpTimestampIncrease = 90;
116   static const uint32 kDefaultTimeIncrease = 30;
117   static const uint32 kElapsedTimeInterval = 10;
118   static const RawRtpPacket kTestRawRtpPackets[];
119   static const RawRtcpPacket kTestRawRtcpPackets[];
120 
121  private:
RtpTestUtility()122   RtpTestUtility() {}
123 };
124 
125 // Test helper for testing VideoCapturer implementations.
126 class VideoCapturerListener : public sigslot::has_slots<> {
127  public:
128   explicit VideoCapturerListener(VideoCapturer* cap);
129 
start_result()130   CaptureResult start_result() const { return start_result_; }
frame_count()131   int frame_count() const { return frame_count_; }
frame_fourcc()132   uint32 frame_fourcc() const { return frame_fourcc_; }
frame_width()133   int frame_width() const { return frame_width_; }
frame_height()134   int frame_height() const { return frame_height_; }
frame_size()135   uint32 frame_size() const { return frame_size_; }
resolution_changed()136   bool resolution_changed() const { return resolution_changed_; }
137 
138   void OnStartResult(VideoCapturer* capturer, CaptureResult result);
139   void OnFrameCaptured(VideoCapturer* capturer, const CapturedFrame* frame);
140   void OnCaptureEvent(VideoCapturer* capturer, CaptureEvent ev);
141 
142  private:
143   CaptureResult start_result_;
144   int frame_count_;
145   uint32 frame_fourcc_;
146   int frame_width_;
147   int frame_height_;
148   uint32 frame_size_;
149   bool resolution_changed_;
150 };
151 
152 class ScreencastEventCatcher : public sigslot::has_slots<> {
153  public:
ScreencastEventCatcher()154   ScreencastEventCatcher() : ssrc_(0), ev_(talk_base::WE_RESIZE) { }
ssrc()155   uint32 ssrc() const { return ssrc_; }
event()156   talk_base::WindowEvent event() const { return ev_; }
OnEvent(uint32 ssrc,talk_base::WindowEvent ev)157   void OnEvent(uint32 ssrc, talk_base::WindowEvent ev) {
158     ssrc_ = ssrc;
159     ev_ = ev;
160   }
161  private:
162   uint32 ssrc_;
163   talk_base::WindowEvent ev_;
164 };
165 
166 class VideoMediaErrorCatcher : public sigslot::has_slots<> {
167  public:
VideoMediaErrorCatcher()168   VideoMediaErrorCatcher() : ssrc_(0), error_(VideoMediaChannel::ERROR_NONE) { }
ssrc()169   uint32 ssrc() const { return ssrc_; }
error()170   VideoMediaChannel::Error error() const { return error_; }
OnError(uint32 ssrc,VideoMediaChannel::Error error)171   void OnError(uint32 ssrc, VideoMediaChannel::Error error) {
172     ssrc_ = ssrc;
173     error_ = error;
174   }
175  private:
176   uint32 ssrc_;
177   VideoMediaChannel::Error error_;
178 };
179 
180 // Returns the absolute path to a file in the testdata/ directory.
181 std::string GetTestFilePath(const std::string& filename);
182 
183 // PSNR formula: psnr = 10 * log10 (Peak Signal^2 / mse)
184 // sse is set to a small number for identical frames or sse == 0
185 double ComputePSNR(double sse, double size);
186 
187 double ComputeSumSquareError(const uint8 *org, const uint8 *rec,
188                              int size);
189 
190 // Loads the image with the specified prefix and size into |out|.
191 bool LoadPlanarYuvTestImage(const std::string& prefix,
192                             int width, int height, uint8* out);
193 
194 // Dumps the YUV image out to a file, for visual inspection.
195 // PYUV tool can be used to view dump files.
196 void DumpPlanarYuvTestImage(const std::string& prefix, const uint8* img,
197                             int w, int h);
198 
199 // Dumps the ARGB image out to a file, for visual inspection.
200 // ffplay tool can be used to view dump files.
201 void DumpPlanarArgbTestImage(const std::string& prefix, const uint8* img,
202                              int w, int h);
203 
204 // Compare two I420 frames.
205 bool VideoFrameEqual(const VideoFrame* frame0, const VideoFrame* frame1);
206 
207 }  // namespace cricket
208 
209 #endif  // TALK_SESSION_PHONE_TESTUTILS_H_
210