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