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 #include <stdio.h>
29
30 #include <string>
31 #include <vector>
32
33 #include "talk/media/base/testutils.h"
34 #include "talk/media/devices/filevideocapturer.h"
35 #include "webrtc/base/gunit.h"
36 #include "webrtc/base/logging.h"
37 #include "webrtc/base/thread.h"
38
39 namespace {
40
41 class FileVideoCapturerTest : public testing::Test {
42 public:
SetUp()43 virtual void SetUp() {
44 capturer_.reset(new cricket::FileVideoCapturer);
45 }
46
OpenFile(const std::string & filename)47 bool OpenFile(const std::string& filename) {
48 return capturer_->Init(cricket::GetTestFilePath(filename));
49 }
50
51 protected:
52 class VideoCapturerListener : public sigslot::has_slots<> {
53 public:
VideoCapturerListener()54 VideoCapturerListener()
55 : frame_count_(0),
56 frame_width_(0),
57 frame_height_(0),
58 resolution_changed_(false) {
59 }
60
OnFrameCaptured(cricket::VideoCapturer * capturer,const cricket::CapturedFrame * frame)61 void OnFrameCaptured(cricket::VideoCapturer* capturer,
62 const cricket::CapturedFrame* frame) {
63 ++frame_count_;
64 if (1 == frame_count_) {
65 frame_width_ = frame->width;
66 frame_height_ = frame->height;
67 } else if (frame_width_ != frame->width ||
68 frame_height_ != frame->height) {
69 resolution_changed_ = true;
70 }
71 }
72
frame_count() const73 int frame_count() const { return frame_count_; }
frame_width() const74 int frame_width() const { return frame_width_; }
frame_height() const75 int frame_height() const { return frame_height_; }
resolution_changed() const76 bool resolution_changed() const { return resolution_changed_; }
77
78 private:
79 int frame_count_;
80 int frame_width_;
81 int frame_height_;
82 bool resolution_changed_;
83 };
84
85 rtc::scoped_ptr<cricket::FileVideoCapturer> capturer_;
86 cricket::VideoFormat capture_format_;
87 };
88
TEST_F(FileVideoCapturerTest,TestNotOpened)89 TEST_F(FileVideoCapturerTest, TestNotOpened) {
90 EXPECT_EQ("", capturer_->GetId());
91 EXPECT_TRUE(capturer_->GetSupportedFormats()->empty());
92 EXPECT_EQ(NULL, capturer_->GetCaptureFormat());
93 EXPECT_FALSE(capturer_->IsRunning());
94 }
95
TEST_F(FileVideoCapturerTest,TestInvalidOpen)96 TEST_F(FileVideoCapturerTest, TestInvalidOpen) {
97 EXPECT_FALSE(OpenFile("NotmeNotme"));
98 }
99
TEST_F(FileVideoCapturerTest,TestOpen)100 TEST_F(FileVideoCapturerTest, TestOpen) {
101 EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames"));
102 EXPECT_NE("", capturer_->GetId());
103 EXPECT_TRUE(NULL != capturer_->GetSupportedFormats());
104 EXPECT_EQ(1U, capturer_->GetSupportedFormats()->size());
105 EXPECT_EQ(NULL, capturer_->GetCaptureFormat()); // not started yet
106 EXPECT_FALSE(capturer_->IsRunning());
107 }
108
TEST_F(FileVideoCapturerTest,TestLargeSmallDesiredFormat)109 TEST_F(FileVideoCapturerTest, TestLargeSmallDesiredFormat) {
110 EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames"));
111 // desired format with large resolution.
112 cricket::VideoFormat desired(
113 3200, 2400, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY);
114 EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_));
115 EXPECT_EQ(320, capture_format_.width);
116 EXPECT_EQ(240, capture_format_.height);
117
118 // Desired format with small resolution.
119 desired.width = 0;
120 desired.height = 0;
121 EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_));
122 EXPECT_EQ(320, capture_format_.width);
123 EXPECT_EQ(240, capture_format_.height);
124 }
125
TEST_F(FileVideoCapturerTest,TestSupportedAsDesiredFormat)126 TEST_F(FileVideoCapturerTest, TestSupportedAsDesiredFormat) {
127 EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames"));
128 // desired format same as the capture format supported by the file
129 cricket::VideoFormat desired = capturer_->GetSupportedFormats()->at(0);
130 EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_));
131 EXPECT_TRUE(desired == capture_format_);
132
133 // desired format same as the supported capture format except the fourcc
134 desired.fourcc = cricket::FOURCC_ANY;
135 EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_));
136 EXPECT_NE(capture_format_.fourcc, desired.fourcc);
137
138 // desired format with minimum interval
139 desired.interval = cricket::VideoFormat::kMinimumInterval;
140 EXPECT_TRUE(capturer_->GetBestCaptureFormat(desired, &capture_format_));
141 }
142
TEST_F(FileVideoCapturerTest,TestNoRepeat)143 TEST_F(FileVideoCapturerTest, TestNoRepeat) {
144 EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames"));
145 VideoCapturerListener listener;
146 capturer_->SignalFrameCaptured.connect(
147 &listener, &VideoCapturerListener::OnFrameCaptured);
148 capturer_->set_repeat(0);
149 capture_format_ = capturer_->GetSupportedFormats()->at(0);
150 EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(capture_format_));
151 EXPECT_TRUE_WAIT(!capturer_->IsRunning(), 20000);
152 EXPECT_EQ(48, listener.frame_count());
153 }
154
TEST_F(FileVideoCapturerTest,TestRepeatForever)155 TEST_F(FileVideoCapturerTest, TestRepeatForever) {
156 // Start the capturer_ with 50 fps and read no less than 150 frames.
157 EXPECT_TRUE(OpenFile("captured-320x240-2s-48.frames"));
158 VideoCapturerListener listener;
159 capturer_->SignalFrameCaptured.connect(
160 &listener, &VideoCapturerListener::OnFrameCaptured);
161 capturer_->set_repeat(cricket::FileVideoCapturer::kForever);
162 capture_format_ = capturer_->GetSupportedFormats()->at(0);
163 capture_format_.interval = cricket::VideoFormat::FpsToInterval(50);
164 EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(capture_format_));
165 EXPECT_TRUE(NULL != capturer_->GetCaptureFormat());
166 EXPECT_TRUE(capture_format_ == *capturer_->GetCaptureFormat());
167 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
168 listener.frame_count() >= 150, 20000);
169 capturer_->Stop();
170 EXPECT_FALSE(capturer_->IsRunning());
171 EXPECT_GE(listener.frame_count(), 150);
172 EXPECT_FALSE(listener.resolution_changed());
173 EXPECT_EQ(listener.frame_width(), capture_format_.width);
174 EXPECT_EQ(listener.frame_height(), capture_format_.height);
175 }
176
177 // See: https://code.google.com/p/webrtc/issues/detail?id=2409
TEST_F(FileVideoCapturerTest,DISABLED_TestPartialFrameHeader)178 TEST_F(FileVideoCapturerTest, DISABLED_TestPartialFrameHeader) {
179 EXPECT_TRUE(OpenFile("1.frame_plus_1.byte"));
180 VideoCapturerListener listener;
181 capturer_->SignalFrameCaptured.connect(
182 &listener, &VideoCapturerListener::OnFrameCaptured);
183 capturer_->set_repeat(0);
184 capture_format_ = capturer_->GetSupportedFormats()->at(0);
185 EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(capture_format_));
186 EXPECT_TRUE_WAIT(!capturer_->IsRunning(), 1000);
187 EXPECT_EQ(1, listener.frame_count());
188 }
189
TEST_F(FileVideoCapturerTest,TestFileDevices)190 TEST_F(FileVideoCapturerTest, TestFileDevices) {
191 cricket::Device not_a_file("I'm a camera", "with an id");
192 EXPECT_FALSE(
193 cricket::FileVideoCapturer::IsFileVideoCapturerDevice(not_a_file));
194 const std::string test_file =
195 cricket::GetTestFilePath("captured-320x240-2s-48.frames");
196 cricket::Device file_device =
197 cricket::FileVideoCapturer::CreateFileVideoCapturerDevice(test_file);
198 EXPECT_TRUE(
199 cricket::FileVideoCapturer::IsFileVideoCapturerDevice(file_device));
200 EXPECT_TRUE(capturer_->Init(file_device));
201 EXPECT_EQ(file_device.id, capturer_->GetId());
202 }
203
204 } // unnamed namespace
205