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