| /* |
| * libjingle |
| * Copyright 2004 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 <stdio.h> |
| |
| #include <string> |
| #include <vector> |
| |
| #include "talk/media/base/testutils.h" |
| #include "talk/media/devices/filevideocapturer.h" |
| #include "webrtc/base/gunit.h" |
| #include "webrtc/base/logging.h" |
| #include "webrtc/base/thread.h" |
| |
| namespace { |
| |
| class FileVideoCapturerTest : public testing::Test { |
| public: |
| virtual void SetUp() { |
| capturer_.reset(new cricket::FileVideoCapturer); |
| } |
| |
| bool OpenFile(const std::string& filename) { |
| return capturer_->Init(cricket::GetTestFilePath(filename)); |
| } |
| |
| protected: |
| class VideoCapturerListener : public sigslot::has_slots<> { |
| public: |
| VideoCapturerListener() |
| : frame_count_(0), |
| frame_width_(0), |
| frame_height_(0), |
| resolution_changed_(false) { |
| } |
| |
| void OnFrameCaptured(cricket::VideoCapturer* capturer, |
| const cricket::CapturedFrame* frame) { |
| ++frame_count_; |
| if (1 == frame_count_) { |
| frame_width_ = frame->width; |
| frame_height_ = frame->height; |
| } else if (frame_width_ != frame->width || |
| frame_height_ != frame->height) { |
| resolution_changed_ = true; |
| } |
| } |
| |
| int frame_count() const { return frame_count_; } |
| int frame_width() const { return frame_width_; } |
| int frame_height() const { return frame_height_; } |
| bool resolution_changed() const { return resolution_changed_; } |
| |
| private: |
| int frame_count_; |
| int frame_width_; |
| int frame_height_; |
| bool resolution_changed_; |
| }; |
| |
| rtc::scoped_ptr<cricket::FileVideoCapturer> capturer_; |
| cricket::VideoFormat capture_format_; |
| }; |
| |
| TEST_F(FileVideoCapturerTest, TestNotOpened) { |
| EXPECT_EQ("", capturer_->GetId()); |
| EXPECT_TRUE(capturer_->GetSupportedFormats()->empty()); |
| EXPECT_EQ(NULL, capturer_->GetCaptureFormat()); |
| EXPECT_FALSE(capturer_->IsRunning()); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestInvalidOpen) { |
| EXPECT_FALSE(OpenFile("NotmeNotme")); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestOpen) { |
| EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames")); |
| EXPECT_NE("", capturer_->GetId()); |
| EXPECT_TRUE(NULL != capturer_->GetSupportedFormats()); |
| EXPECT_EQ(1U, capturer_->GetSupportedFormats()->size()); |
| EXPECT_EQ(NULL, capturer_->GetCaptureFormat()); // not started yet |
| EXPECT_FALSE(capturer_->IsRunning()); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestLargeSmallDesiredFormat) { |
| EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames")); |
| // desired format with large resolution. |
| cricket::VideoFormat desired( |
| 3200, 2400, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY); |
| EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_)); |
| EXPECT_EQ(320, capture_format_.width); |
| EXPECT_EQ(240, capture_format_.height); |
| |
| // Desired format with small resolution. |
| desired.width = 0; |
| desired.height = 0; |
| EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_)); |
| EXPECT_EQ(320, capture_format_.width); |
| EXPECT_EQ(240, capture_format_.height); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestSupportedAsDesiredFormat) { |
| EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames")); |
| // desired format same as the capture format supported by the file |
| cricket::VideoFormat desired = capturer_->GetSupportedFormats()->at(0); |
| EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_)); |
| EXPECT_TRUE(desired == capture_format_); |
| |
| // desired format same as the supported capture format except the fourcc |
| desired.fourcc = cricket::FOURCC_ANY; |
| EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_)); |
| EXPECT_NE(capture_format_.fourcc, desired.fourcc); |
| |
| // desired format with minimum interval |
| desired.interval = cricket::VideoFormat::kMinimumInterval; |
| EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_)); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestNoRepeat) { |
| EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames")); |
| VideoCapturerListener listener; |
| capturer_->SignalFrameCaptured.connect( |
| &listener, &VideoCapturerListener::OnFrameCaptured); |
| capturer_->set_repeat(0); |
| capture_format_ = capturer_->GetSupportedFormats()->at(0); |
| EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(capture_format_)); |
| EXPECT_TRUE_WAIT(!capturer_->IsRunning(), 20000); |
| EXPECT_EQ(48, listener.frame_count()); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestRepeatForever) { |
| // Start the capturer_ with 50 fps and read no less than 150 frames. |
| EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames")); |
| VideoCapturerListener listener; |
| capturer_->SignalFrameCaptured.connect( |
| &listener, &VideoCapturerListener::OnFrameCaptured); |
| capturer_->set_repeat(cricket::FileVideoCapturer::kForever); |
| capture_format_ = capturer_->GetSupportedFormats()->at(0); |
| capture_format_.interval = cricket::VideoFormat::FpsToInterval(50); |
| EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(capture_format_)); |
| EXPECT_TRUE(NULL != capturer_->GetCaptureFormat()); |
| EXPECT_TRUE(capture_format_ == *capturer_->GetCaptureFormat()); |
| EXPECT_TRUE_WAIT(!capturer_->IsRunning() || |
| listener.frame_count() >= 150, 20000); |
| capturer_->Stop(); |
| EXPECT_FALSE(capturer_->IsRunning()); |
| EXPECT_GE(listener.frame_count(), 150); |
| EXPECT_FALSE(listener.resolution_changed()); |
| EXPECT_EQ(listener.frame_width(), capture_format_.width); |
| EXPECT_EQ(listener.frame_height(), capture_format_.height); |
| } |
| |
| // See: https://code.google.com/p/webrtc/issues/detail?id=2409 |
| TEST_F(FileVideoCapturerTest, DISABLED_TestPartialFrameHeader) { |
| EXPECT_TRUE(OpenFile("1.frame_plus_1.byte")); |
| VideoCapturerListener listener; |
| capturer_->SignalFrameCaptured.connect( |
| &listener, &VideoCapturerListener::OnFrameCaptured); |
| capturer_->set_repeat(0); |
| capture_format_ = capturer_->GetSupportedFormats()->at(0); |
| EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(capture_format_)); |
| EXPECT_TRUE_WAIT(!capturer_->IsRunning(), 1000); |
| EXPECT_EQ(1, listener.frame_count()); |
| } |
| |
| TEST_F(FileVideoCapturerTest, TestFileDevices) { |
| cricket::Device not_a_file("I'm a camera", "with an id"); |
| EXPECT_FALSE( |
| cricket::FileVideoCapturer::IsFileVideoCapturerDevice(not_a_file)); |
| const std::string test_file = |
| cricket::GetTestFilePath("captured-320x240-2s-48.frames"); |
| cricket::Device file_device = |
| cricket::FileVideoCapturer::CreateFileVideoCapturerDevice(test_file); |
| EXPECT_TRUE( |
| cricket::FileVideoCapturer::IsFileVideoCapturerDevice(file_device)); |
| EXPECT_TRUE(capturer_->Init(file_device)); |
| EXPECT_EQ(file_device.id, capturer_->GetId()); |
| } |
| |
| } // unnamed namespace |