• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2012 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 #include "talk/media/base/capturemanager.h"
29 
30 #include "talk/media/base/fakevideocapturer.h"
31 #include "talk/media/base/fakevideorenderer.h"
32 #include "webrtc/base/arraysize.h"
33 #include "webrtc/base/gunit.h"
34 #include "webrtc/base/sigslot.h"
35 
36 const int kMsCallbackWait = 50;
37 
38 const int kFps = 30;
39 const cricket::VideoFormatPod kCameraFormats[] = {
40   {640, 480, cricket::VideoFormat::FpsToInterval(kFps), cricket::FOURCC_I420},
41   {320, 240, cricket::VideoFormat::FpsToInterval(kFps), cricket::FOURCC_I420}
42 };
43 
44 class CaptureManagerTest : public ::testing::Test, public sigslot::has_slots<> {
45  public:
CaptureManagerTest()46   CaptureManagerTest()
47       : capture_manager_(),
48         callback_count_(0),
49         format_vga_(kCameraFormats[0]),
50         format_qvga_(kCameraFormats[1]) {
51   }
SetUp()52   virtual void SetUp() {
53     PopulateSupportedFormats();
54     capture_state_ = cricket::CS_STOPPED;
55     capture_manager_.SignalCapturerStateChange.connect(
56         this,
57         &CaptureManagerTest::OnCapturerStateChange);
58   }
PopulateSupportedFormats()59   void PopulateSupportedFormats() {
60     std::vector<cricket::VideoFormat> formats;
61     for (int i = 0; i < arraysize(kCameraFormats); ++i) {
62       formats.push_back(cricket::VideoFormat(kCameraFormats[i]));
63     }
64     video_capturer_.ResetSupportedFormats(formats);
65   }
NumFramesRendered()66   int NumFramesRendered() { return video_renderer_.num_rendered_frames(); }
WasRenderedResolution(cricket::VideoFormat format)67   bool WasRenderedResolution(cricket::VideoFormat format) {
68     return format.width == video_renderer_.width() &&
69         format.height == video_renderer_.height();
70   }
capture_state()71   cricket::CaptureState capture_state() { return capture_state_; }
callback_count()72   int callback_count() { return callback_count_; }
OnCapturerStateChange(cricket::VideoCapturer * capturer,cricket::CaptureState capture_state)73   void OnCapturerStateChange(cricket::VideoCapturer* capturer,
74                              cricket::CaptureState capture_state) {
75     capture_state_ = capture_state;
76     ++callback_count_;
77   }
78 
79  protected:
80   cricket::FakeVideoCapturer video_capturer_;
81   cricket::FakeVideoRenderer video_renderer_;
82 
83   cricket::CaptureManager capture_manager_;
84 
85   cricket::CaptureState capture_state_;
86   int callback_count_;
87   cricket::VideoFormat format_vga_;
88   cricket::VideoFormat format_qvga_;
89 };
90 
91 // Incorrect use cases.
TEST_F(CaptureManagerTest,InvalidCallOrder)92 TEST_F(CaptureManagerTest, InvalidCallOrder) {
93   // Capturer must be registered before any of these calls.
94   EXPECT_FALSE(capture_manager_.AddVideoRenderer(&video_capturer_,
95                                                  &video_renderer_));
96 }
97 
TEST_F(CaptureManagerTest,InvalidAddingRemoving)98 TEST_F(CaptureManagerTest, InvalidAddingRemoving) {
99   EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_,
100                                                  cricket::VideoFormat()));
101   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
102                                                  format_vga_));
103   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
104   EXPECT_EQ(1, callback_count());
105   EXPECT_FALSE(capture_manager_.AddVideoRenderer(&video_capturer_, NULL));
106   EXPECT_FALSE(capture_manager_.RemoveVideoRenderer(&video_capturer_,
107                                                     &video_renderer_));
108   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, format_vga_));
109 }
110 
111 // Valid use cases
TEST_F(CaptureManagerTest,KeepFirstResolutionHigh)112 TEST_F(CaptureManagerTest, KeepFirstResolutionHigh) {
113   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
114                                                  format_vga_));
115   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
116   EXPECT_EQ(1, callback_count());
117   EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_,
118                                                 &video_renderer_));
119   EXPECT_TRUE(video_capturer_.CaptureFrame());
120   EXPECT_EQ(1, NumFramesRendered());
121   // Renderer should be fed frames with the resolution of format_vga_.
122   EXPECT_TRUE(WasRenderedResolution(format_vga_));
123 
124   // Start again with one more format.
125   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
126                                                  format_qvga_));
127   // Existing renderers should be fed frames with the resolution of format_vga_.
128   EXPECT_TRUE(video_capturer_.CaptureFrame());
129   EXPECT_TRUE(WasRenderedResolution(format_vga_));
130   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, format_vga_));
131   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
132                                                 format_qvga_));
133   EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_,
134                                                  format_vga_));
135   EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_,
136                                                  format_qvga_));
137 }
138 
139 // Should pick the lowest resolution as the highest resolution is not chosen
140 // until after capturing has started. This ensures that no particular resolution
141 // is favored over others.
TEST_F(CaptureManagerTest,KeepFirstResolutionLow)142 TEST_F(CaptureManagerTest, KeepFirstResolutionLow) {
143   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
144                                                  format_qvga_));
145   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
146                                                  format_vga_));
147   EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_,
148                                                 &video_renderer_));
149   EXPECT_EQ_WAIT(1, callback_count(), kMsCallbackWait);
150   EXPECT_TRUE(video_capturer_.CaptureFrame());
151   EXPECT_EQ(1, NumFramesRendered());
152   EXPECT_TRUE(WasRenderedResolution(format_qvga_));
153   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
154                                                 format_qvga_));
155   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
156                                                 format_vga_));
157 }
158 
159 // Ensure that the reference counting is working when multiple start and
160 // multiple stop calls are made.
TEST_F(CaptureManagerTest,MultipleStartStops)161 TEST_F(CaptureManagerTest, MultipleStartStops) {
162   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
163                                                  format_vga_));
164   // Add video capturer but with different format.
165   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
166                                                  format_qvga_));
167   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
168   EXPECT_EQ(1, callback_count());
169   EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_,
170                                                 &video_renderer_));
171   // Ensure that a frame can be captured when two start calls have been made.
172   EXPECT_TRUE(video_capturer_.CaptureFrame());
173   EXPECT_EQ(1, NumFramesRendered());
174 
175   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, format_vga_));
176   // Video should still render since there has been two start calls but only
177   // one stop call.
178   EXPECT_TRUE(video_capturer_.CaptureFrame());
179   EXPECT_EQ(2, NumFramesRendered());
180 
181   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
182                                                 format_qvga_));
183   EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
184   EXPECT_EQ(2, callback_count());
185   // Last stop call should fail as it is one more than the number of start
186   // calls.
187   EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_,
188                                                  format_vga_));
189 }
190 
TEST_F(CaptureManagerTest,TestForceRestart)191 TEST_F(CaptureManagerTest, TestForceRestart) {
192   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
193                                                  format_qvga_));
194   EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_,
195                                                 &video_renderer_));
196   EXPECT_EQ_WAIT(1, callback_count(), kMsCallbackWait);
197   EXPECT_TRUE(video_capturer_.CaptureFrame());
198   EXPECT_EQ(1, NumFramesRendered());
199   EXPECT_TRUE(WasRenderedResolution(format_qvga_));
200   // Now restart with vga.
201   EXPECT_TRUE(capture_manager_.RestartVideoCapture(
202       &video_capturer_, format_qvga_, format_vga_,
203       cricket::CaptureManager::kForceRestart));
204   EXPECT_TRUE(video_capturer_.CaptureFrame());
205   EXPECT_EQ(2, NumFramesRendered());
206   EXPECT_TRUE(WasRenderedResolution(format_vga_));
207   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
208                                                 format_vga_));
209 }
210 
TEST_F(CaptureManagerTest,TestRequestRestart)211 TEST_F(CaptureManagerTest, TestRequestRestart) {
212   EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_,
213                                                  format_vga_));
214   EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_,
215                                                 &video_renderer_));
216   EXPECT_EQ_WAIT(1, callback_count(), kMsCallbackWait);
217   EXPECT_TRUE(video_capturer_.CaptureFrame());
218   EXPECT_EQ(1, NumFramesRendered());
219   EXPECT_TRUE(WasRenderedResolution(format_vga_));
220   // Now request restart with qvga.
221   EXPECT_TRUE(capture_manager_.RestartVideoCapture(
222       &video_capturer_, format_vga_, format_qvga_,
223       cricket::CaptureManager::kRequestRestart));
224   EXPECT_TRUE(video_capturer_.CaptureFrame());
225   EXPECT_EQ(2, NumFramesRendered());
226   EXPECT_TRUE(WasRenderedResolution(format_vga_));
227   EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
228                                                 format_qvga_));
229 }
230