diff options
Diffstat (limited to 'talk/media/base/capturemanager_unittest.cc')
-rw-r--r-- | talk/media/base/capturemanager_unittest.cc | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/talk/media/base/capturemanager_unittest.cc b/talk/media/base/capturemanager_unittest.cc new file mode 100644 index 0000000000..e9903425b8 --- /dev/null +++ b/talk/media/base/capturemanager_unittest.cc @@ -0,0 +1,228 @@ +/* + * libjingle + * Copyright 2012 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "talk/media/base/capturemanager.h" + +#include "talk/media/base/fakevideocapturer.h" +#include "talk/media/base/fakevideorenderer.h" +#include "webrtc/base/gunit.h" +#include "webrtc/base/sigslot.h" + +const int kMsCallbackWait = 50; + +const int kFps = 30; +const cricket::VideoFormatPod kCameraFormats[] = { + {640, 480, cricket::VideoFormat::FpsToInterval(kFps), cricket::FOURCC_I420}, + {320, 240, cricket::VideoFormat::FpsToInterval(kFps), cricket::FOURCC_I420} +}; + +class CaptureManagerTest : public ::testing::Test, public sigslot::has_slots<> { + public: + CaptureManagerTest() + : capture_manager_(), + callback_count_(0), + format_vga_(kCameraFormats[0]), + format_qvga_(kCameraFormats[1]) { + } + virtual void SetUp() { + PopulateSupportedFormats(); + capture_state_ = cricket::CS_STOPPED; + capture_manager_.SignalCapturerStateChange.connect( + this, + &CaptureManagerTest::OnCapturerStateChange); + } + void PopulateSupportedFormats() { + std::vector<cricket::VideoFormat> formats; + for (int i = 0; i < ARRAY_SIZE(kCameraFormats); ++i) { + formats.push_back(cricket::VideoFormat(kCameraFormats[i])); + } + video_capturer_.ResetSupportedFormats(formats); + } + int NumFramesRendered() { return video_renderer_.num_rendered_frames(); } + bool WasRenderedResolution(cricket::VideoFormat format) { + return format.width == video_renderer_.width() && + format.height == video_renderer_.height(); + } + cricket::CaptureState capture_state() { return capture_state_; } + int callback_count() { return callback_count_; } + void OnCapturerStateChange(cricket::VideoCapturer* capturer, + cricket::CaptureState capture_state) { + capture_state_ = capture_state; + ++callback_count_; + } + + protected: + cricket::FakeVideoCapturer video_capturer_; + cricket::FakeVideoRenderer video_renderer_; + + cricket::CaptureManager capture_manager_; + + cricket::CaptureState capture_state_; + int callback_count_; + cricket::VideoFormat format_vga_; + cricket::VideoFormat format_qvga_; +}; + +// Incorrect use cases. +TEST_F(CaptureManagerTest, InvalidCallOrder) { + // Capturer must be registered before any of these calls. + EXPECT_FALSE(capture_manager_.AddVideoRenderer(&video_capturer_, + &video_renderer_)); +} + +TEST_F(CaptureManagerTest, InvalidAddingRemoving) { + EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_, + cricket::VideoFormat())); + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_vga_)); + EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); + EXPECT_EQ(1, callback_count()); + EXPECT_FALSE(capture_manager_.AddVideoRenderer(&video_capturer_, NULL)); + EXPECT_FALSE(capture_manager_.RemoveVideoRenderer(&video_capturer_, + &video_renderer_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, format_vga_)); +} + +// Valid use cases +TEST_F(CaptureManagerTest, KeepFirstResolutionHigh) { + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_vga_)); + EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); + EXPECT_EQ(1, callback_count()); + EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_, + &video_renderer_)); + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(1, NumFramesRendered()); + // Renderer should be fed frames with the resolution of format_vga_. + EXPECT_TRUE(WasRenderedResolution(format_vga_)); + + // Start again with one more format. + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_qvga_)); + // Existing renderers should be fed frames with the resolution of format_vga_. + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_TRUE(WasRenderedResolution(format_vga_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, format_vga_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, + format_qvga_)); + EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_, + format_vga_)); + EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_, + format_qvga_)); +} + +// Should pick the lowest resolution as the highest resolution is not chosen +// until after capturing has started. This ensures that no particular resolution +// is favored over others. +TEST_F(CaptureManagerTest, KeepFirstResolutionLow) { + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_qvga_)); + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_vga_)); + EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_, + &video_renderer_)); + EXPECT_EQ_WAIT(1, callback_count(), kMsCallbackWait); + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(1, NumFramesRendered()); + EXPECT_TRUE(WasRenderedResolution(format_qvga_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, + format_qvga_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, + format_vga_)); +} + +// Ensure that the reference counting is working when multiple start and +// multiple stop calls are made. +TEST_F(CaptureManagerTest, MultipleStartStops) { + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_vga_)); + // Add video capturer but with different format. + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_qvga_)); + EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); + EXPECT_EQ(1, callback_count()); + EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_, + &video_renderer_)); + // Ensure that a frame can be captured when two start calls have been made. + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(1, NumFramesRendered()); + + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, format_vga_)); + // Video should still render since there has been two start calls but only + // one stop call. + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(2, NumFramesRendered()); + + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, + format_qvga_)); + EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait); + EXPECT_EQ(2, callback_count()); + // Last stop call should fail as it is one more than the number of start + // calls. + EXPECT_FALSE(capture_manager_.StopVideoCapture(&video_capturer_, + format_vga_)); +} + +TEST_F(CaptureManagerTest, TestForceRestart) { + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_qvga_)); + EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_, + &video_renderer_)); + EXPECT_EQ_WAIT(1, callback_count(), kMsCallbackWait); + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(1, NumFramesRendered()); + EXPECT_TRUE(WasRenderedResolution(format_qvga_)); + // Now restart with vga. + EXPECT_TRUE(capture_manager_.RestartVideoCapture( + &video_capturer_, format_qvga_, format_vga_, + cricket::CaptureManager::kForceRestart)); + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(2, NumFramesRendered()); + EXPECT_TRUE(WasRenderedResolution(format_vga_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, + format_vga_)); +} + +TEST_F(CaptureManagerTest, TestRequestRestart) { + EXPECT_TRUE(capture_manager_.StartVideoCapture(&video_capturer_, + format_vga_)); + EXPECT_TRUE(capture_manager_.AddVideoRenderer(&video_capturer_, + &video_renderer_)); + EXPECT_EQ_WAIT(1, callback_count(), kMsCallbackWait); + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(1, NumFramesRendered()); + EXPECT_TRUE(WasRenderedResolution(format_vga_)); + // Now request restart with qvga. + EXPECT_TRUE(capture_manager_.RestartVideoCapture( + &video_capturer_, format_vga_, format_qvga_, + cricket::CaptureManager::kRequestRestart)); + EXPECT_TRUE(video_capturer_.CaptureFrame()); + EXPECT_EQ(2, NumFramesRendered()); + EXPECT_TRUE(WasRenderedResolution(format_vga_)); + EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_, + format_qvga_)); +} |