Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / app / webrtc / videosource_unittest.cc
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 <string>
29 #include <vector>
30
31 #include "talk/app/webrtc/remotevideocapturer.h"
32 #include "talk/app/webrtc/test/fakeconstraints.h"
33 #include "talk/app/webrtc/videosource.h"
34 #include "talk/media/base/fakemediaengine.h"
35 #include "talk/media/base/fakevideorenderer.h"
36 #include "talk/media/devices/fakedevicemanager.h"
37 #include "talk/media/webrtc/webrtcvideoframe.h"
38 #include "talk/session/media/channelmanager.h"
39 #include "webrtc/base/gunit.h"
40
41 using webrtc::FakeConstraints;
42 using webrtc::VideoSource;
43 using webrtc::MediaConstraintsInterface;
44 using webrtc::MediaSourceInterface;
45 using webrtc::ObserverInterface;
46 using webrtc::VideoSourceInterface;
47
48 namespace {
49
50 // Max wait time for a test.
51 const int kMaxWaitMs = 100;
52
53 }  // anonymous namespace
54
55
56 // TestVideoCapturer extends cricket::FakeVideoCapturer so it can be used for
57 // testing without known camera formats.
58 // It keeps its own lists of cricket::VideoFormats for the unit tests in this
59 // file.
60 class TestVideoCapturer : public cricket::FakeVideoCapturer {
61  public:
62   TestVideoCapturer() : test_without_formats_(false) {
63     std::vector<cricket::VideoFormat> formats;
64     formats.push_back(cricket::VideoFormat(1280, 720,
65         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
66     formats.push_back(cricket::VideoFormat(640, 480,
67         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
68     formats.push_back(cricket::VideoFormat(640, 400,
69             cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
70     formats.push_back(cricket::VideoFormat(320, 240,
71         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
72     formats.push_back(cricket::VideoFormat(352, 288,
73             cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
74     ResetSupportedFormats(formats);
75   }
76
77   // This function is used for resetting the supported capture formats and
78   // simulating a cricket::VideoCapturer implementation that don't support
79   // capture format enumeration. This is used to simulate the current
80   // Chrome implementation.
81   void TestWithoutCameraFormats() {
82     test_without_formats_ = true;
83     std::vector<cricket::VideoFormat> formats;
84     ResetSupportedFormats(formats);
85   }
86
87   virtual cricket::CaptureState Start(
88       const cricket::VideoFormat& capture_format) {
89     if (test_without_formats_) {
90       std::vector<cricket::VideoFormat> formats;
91       formats.push_back(capture_format);
92       ResetSupportedFormats(formats);
93     }
94     return FakeVideoCapturer::Start(capture_format);
95   }
96
97   virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired,
98                                     cricket::VideoFormat* best_format) {
99     if (test_without_formats_) {
100       *best_format = desired;
101       return true;
102     }
103     return FakeVideoCapturer::GetBestCaptureFormat(desired,
104                                                    best_format);
105   }
106
107  private:
108   bool test_without_formats_;
109 };
110
111 class StateObserver : public ObserverInterface {
112  public:
113   explicit StateObserver(VideoSourceInterface* source)
114      : state_(source->state()),
115        source_(source) {
116   }
117   virtual void OnChanged() {
118     state_ = source_->state();
119   }
120   MediaSourceInterface::SourceState state() const { return state_; }
121
122  private:
123   MediaSourceInterface::SourceState state_;
124   rtc::scoped_refptr<VideoSourceInterface> source_;
125 };
126
127 class VideoSourceTest : public testing::Test {
128  protected:
129   VideoSourceTest()
130       : capturer_cleanup_(new TestVideoCapturer()),
131         capturer_(capturer_cleanup_.get()),
132         channel_manager_(new cricket::ChannelManager(
133           new cricket::FakeMediaEngine(),
134           new cricket::FakeDeviceManager(), rtc::Thread::Current())) {
135   }
136
137   void SetUp() {
138     ASSERT_TRUE(channel_manager_->Init());
139   }
140
141   void CreateVideoSource() {
142     CreateVideoSource(NULL);
143   }
144
145   void CreateVideoSource(
146       const webrtc::MediaConstraintsInterface* constraints) {
147     // VideoSource take ownership of |capturer_|
148     source_ = VideoSource::Create(channel_manager_.get(),
149                                   capturer_cleanup_.release(),
150                                   constraints);
151
152     ASSERT_TRUE(source_.get() != NULL);
153     EXPECT_EQ(capturer_, source_->GetVideoCapturer());
154
155     state_observer_.reset(new StateObserver(source_));
156     source_->RegisterObserver(state_observer_.get());
157     source_->AddSink(&renderer_);
158   }
159
160   rtc::scoped_ptr<TestVideoCapturer> capturer_cleanup_;
161   TestVideoCapturer* capturer_;
162   cricket::FakeVideoRenderer renderer_;
163   rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
164   rtc::scoped_ptr<StateObserver> state_observer_;
165   rtc::scoped_refptr<VideoSource> source_;
166 };
167
168
169 // Test that a VideoSource transition to kLive state when the capture
170 // device have started and kEnded if it is stopped.
171 // It also test that an output can receive video frames.
172 TEST_F(VideoSourceTest, StartStop) {
173   // Initialize without constraints.
174   CreateVideoSource();
175   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
176                  kMaxWaitMs);
177
178   ASSERT_TRUE(capturer_->CaptureFrame());
179   EXPECT_EQ(1, renderer_.num_rendered_frames());
180
181   capturer_->Stop();
182   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
183                  kMaxWaitMs);
184 }
185
186 // Test start stop with a remote VideoSource - the video source that has a
187 // RemoteVideoCapturer and takes video frames from FrameInput.
188 TEST_F(VideoSourceTest, StartStopRemote) {
189   source_ = VideoSource::Create(channel_manager_.get(),
190                                 new webrtc::RemoteVideoCapturer(),
191                                 NULL);
192
193   ASSERT_TRUE(source_.get() != NULL);
194   EXPECT_TRUE(NULL != source_->GetVideoCapturer());
195
196   state_observer_.reset(new StateObserver(source_));
197   source_->RegisterObserver(state_observer_.get());
198   source_->AddSink(&renderer_);
199
200   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
201                  kMaxWaitMs);
202
203   cricket::VideoRenderer* frameinput = source_->FrameInput();
204   cricket::WebRtcVideoFrame test_frame;
205   frameinput->SetSize(1280, 720, 0);
206   frameinput->RenderFrame(&test_frame);
207   EXPECT_EQ(1, renderer_.num_rendered_frames());
208
209   source_->GetVideoCapturer()->Stop();
210   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
211                  kMaxWaitMs);
212 }
213
214 // Test that a VideoSource transition to kEnded if the capture device
215 // fails.
216 TEST_F(VideoSourceTest, CameraFailed) {
217   CreateVideoSource();
218   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
219                  kMaxWaitMs);
220
221   capturer_->SignalStateChange(capturer_, cricket::CS_FAILED);
222   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
223                  kMaxWaitMs);
224 }
225
226 // Test that the capture output is CIF if we set max constraints to CIF.
227 // and the capture device support CIF.
228 TEST_F(VideoSourceTest, MandatoryConstraintCif5Fps) {
229   FakeConstraints constraints;
230   constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 352);
231   constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 288);
232   constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 5);
233
234   CreateVideoSource(&constraints);
235   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
236                  kMaxWaitMs);
237   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
238   ASSERT_TRUE(format != NULL);
239   EXPECT_EQ(352, format->width);
240   EXPECT_EQ(288, format->height);
241   EXPECT_EQ(30, format->framerate());
242 }
243
244 // Test that the capture output is 720P if the camera support it and the
245 // optional constraint is set to 720P.
246 TEST_F(VideoSourceTest, MandatoryMinVgaOptional720P) {
247   FakeConstraints constraints;
248   constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640);
249   constraints.AddMandatory(MediaConstraintsInterface::kMinHeight, 480);
250   constraints.AddOptional(MediaConstraintsInterface::kMinWidth, 1280);
251   constraints.AddOptional(MediaConstraintsInterface::kMinAspectRatio,
252                           1280.0 / 720);
253
254   CreateVideoSource(&constraints);
255   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
256                  kMaxWaitMs);
257   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
258   ASSERT_TRUE(format != NULL);
259   EXPECT_EQ(1280, format->width);
260   EXPECT_EQ(720, format->height);
261   EXPECT_EQ(30, format->framerate());
262 }
263
264 // Test that the capture output have aspect ratio 4:3 if a mandatory constraint
265 // require it even if an optional constraint request a higher resolution
266 // that don't have this aspect ratio.
267 TEST_F(VideoSourceTest, MandatoryAspectRatio4To3) {
268   FakeConstraints constraints;
269   constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640);
270   constraints.AddMandatory(MediaConstraintsInterface::kMinHeight, 480);
271   constraints.AddMandatory(MediaConstraintsInterface::kMaxAspectRatio,
272                            640.0 / 480);
273   constraints.AddOptional(MediaConstraintsInterface::kMinWidth, 1280);
274
275   CreateVideoSource(&constraints);
276   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
277                  kMaxWaitMs);
278   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
279   ASSERT_TRUE(format != NULL);
280   EXPECT_EQ(640, format->width);
281   EXPECT_EQ(480, format->height);
282   EXPECT_EQ(30, format->framerate());
283 }
284
285
286 // Test that the source state transition to kEnded if the mandatory aspect ratio
287 // is set higher than supported.
288 TEST_F(VideoSourceTest, MandatoryAspectRatioTooHigh) {
289   FakeConstraints constraints;
290   constraints.AddMandatory(MediaConstraintsInterface::kMinAspectRatio, 2);
291   CreateVideoSource(&constraints);
292   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
293                  kMaxWaitMs);
294 }
295
296 // Test that the source ignores an optional aspect ratio that is higher than
297 // supported.
298 TEST_F(VideoSourceTest, OptionalAspectRatioTooHigh) {
299   FakeConstraints constraints;
300   constraints.AddOptional(MediaConstraintsInterface::kMinAspectRatio, 2);
301   CreateVideoSource(&constraints);
302   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
303                  kMaxWaitMs);
304   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
305   ASSERT_TRUE(format != NULL);
306   double aspect_ratio = static_cast<double>(format->width) / format->height;
307   EXPECT_LT(aspect_ratio, 2);
308 }
309
310 // Test that the source starts video with the default resolution if the
311 // camera doesn't support capability enumeration and there are no constraints.
312 TEST_F(VideoSourceTest, NoCameraCapability) {
313   capturer_->TestWithoutCameraFormats();
314
315   CreateVideoSource();
316   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
317                  kMaxWaitMs);
318   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
319   ASSERT_TRUE(format != NULL);
320   EXPECT_EQ(640, format->width);
321   EXPECT_EQ(480, format->height);
322   EXPECT_EQ(30, format->framerate());
323 }
324
325 // Test that the source can start the video and get the requested aspect ratio
326 // if the camera doesn't support capability enumeration and the aspect ratio is
327 // set.
328 TEST_F(VideoSourceTest, NoCameraCapability16To9Ratio) {
329   capturer_->TestWithoutCameraFormats();
330
331   FakeConstraints constraints;
332   double requested_aspect_ratio = 640.0 / 360;
333   constraints.AddMandatory(MediaConstraintsInterface::kMinWidth, 640);
334   constraints.AddMandatory(MediaConstraintsInterface::kMinAspectRatio,
335                            requested_aspect_ratio);
336
337   CreateVideoSource(&constraints);
338   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
339                  kMaxWaitMs);
340   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
341   double aspect_ratio = static_cast<double>(format->width) / format->height;
342   EXPECT_LE(requested_aspect_ratio, aspect_ratio);
343 }
344
345 // Test that the source state transitions to kEnded if an unknown mandatory
346 // constraint is found.
347 TEST_F(VideoSourceTest, InvalidMandatoryConstraint) {
348   FakeConstraints constraints;
349   constraints.AddMandatory("weird key", 640);
350
351   CreateVideoSource(&constraints);
352   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
353                  kMaxWaitMs);
354 }
355
356 // Test that the source ignores an unknown optional constraint.
357 TEST_F(VideoSourceTest, InvalidOptionalConstraint) {
358   FakeConstraints constraints;
359   constraints.AddOptional("weird key", 640);
360
361   CreateVideoSource(&constraints);
362   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
363                  kMaxWaitMs);
364 }
365
366 TEST_F(VideoSourceTest, SetValidOptionValues) {
367   FakeConstraints constraints;
368   constraints.AddMandatory(MediaConstraintsInterface::kNoiseReduction, "false");
369
370   CreateVideoSource(&constraints);
371
372   bool value = true;
373   EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
374   EXPECT_FALSE(value);
375 }
376
377 TEST_F(VideoSourceTest, OptionNotSet) {
378   FakeConstraints constraints;
379   CreateVideoSource(&constraints);
380   bool value;
381   EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
382 }
383
384 TEST_F(VideoSourceTest, MandatoryOptionOverridesOptional) {
385   FakeConstraints constraints;
386   constraints.AddMandatory(
387       MediaConstraintsInterface::kNoiseReduction, true);
388   constraints.AddOptional(
389       MediaConstraintsInterface::kNoiseReduction, false);
390
391   CreateVideoSource(&constraints);
392
393   bool value = false;
394   EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
395   EXPECT_TRUE(value);
396 }
397
398 TEST_F(VideoSourceTest, InvalidOptionKeyOptional) {
399   FakeConstraints constraints;
400   constraints.AddOptional(
401       MediaConstraintsInterface::kNoiseReduction, false);
402   constraints.AddOptional("invalidKey", false);
403
404   CreateVideoSource(&constraints);
405
406   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
407       kMaxWaitMs);
408   bool value = true;
409   EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
410   EXPECT_FALSE(value);
411 }
412
413 TEST_F(VideoSourceTest, InvalidOptionKeyMandatory) {
414   FakeConstraints constraints;
415   constraints.AddMandatory(
416       MediaConstraintsInterface::kNoiseReduction, false);
417   constraints.AddMandatory("invalidKey", false);
418
419   CreateVideoSource(&constraints);
420
421   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
422       kMaxWaitMs);
423   bool value;
424   EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
425 }
426
427 TEST_F(VideoSourceTest, InvalidOptionValueOptional) {
428   FakeConstraints constraints;
429   constraints.AddOptional(
430       MediaConstraintsInterface::kNoiseReduction, "not a boolean");
431
432   CreateVideoSource(&constraints);
433
434   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
435       kMaxWaitMs);
436   bool value = false;
437   EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
438 }
439
440 TEST_F(VideoSourceTest, InvalidOptionValueMandatory) {
441   FakeConstraints constraints;
442   // Optional constraints should be ignored if the mandatory constraints fail.
443   constraints.AddOptional(
444       MediaConstraintsInterface::kNoiseReduction, "false");
445   // Values are case-sensitive and must be all lower-case.
446   constraints.AddMandatory(
447       MediaConstraintsInterface::kNoiseReduction, "True");
448
449   CreateVideoSource(&constraints);
450
451   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
452       kMaxWaitMs);
453   bool value;
454   EXPECT_FALSE(source_->options()->video_noise_reduction.Get(&value));
455 }
456
457 TEST_F(VideoSourceTest, MixedOptionsAndConstraints) {
458   FakeConstraints constraints;
459   constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 352);
460   constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 288);
461   constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 5);
462
463   constraints.AddMandatory(
464       MediaConstraintsInterface::kNoiseReduction, false);
465   constraints.AddOptional(
466       MediaConstraintsInterface::kNoiseReduction, true);
467
468   CreateVideoSource(&constraints);
469   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
470                  kMaxWaitMs);
471   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
472   ASSERT_TRUE(format != NULL);
473   EXPECT_EQ(352, format->width);
474   EXPECT_EQ(288, format->height);
475   EXPECT_EQ(30, format->framerate());
476
477   bool value = true;
478   EXPECT_TRUE(source_->options()->video_noise_reduction.Get(&value));
479   EXPECT_FALSE(value);
480 }
481
482 // Tests that the source starts video with the default resolution for
483 // screencast if no constraint is set.
484 TEST_F(VideoSourceTest, ScreencastResolutionNoConstraint) {
485   capturer_->TestWithoutCameraFormats();
486   capturer_->SetScreencast(true);
487
488   CreateVideoSource();
489   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
490                  kMaxWaitMs);
491   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
492   ASSERT_TRUE(format != NULL);
493   EXPECT_EQ(640, format->width);
494   EXPECT_EQ(480, format->height);
495   EXPECT_EQ(30, format->framerate());
496 }
497
498 // Tests that the source starts video with the max width and height set by
499 // constraints for screencast.
500 TEST_F(VideoSourceTest, ScreencastResolutionWithConstraint) {
501   FakeConstraints constraints;
502   constraints.AddMandatory(MediaConstraintsInterface::kMaxWidth, 480);
503   constraints.AddMandatory(MediaConstraintsInterface::kMaxHeight, 270);
504
505   capturer_->TestWithoutCameraFormats();
506   capturer_->SetScreencast(true);
507
508   CreateVideoSource(&constraints);
509   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
510                  kMaxWaitMs);
511   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
512   ASSERT_TRUE(format != NULL);
513   EXPECT_EQ(480, format->width);
514   EXPECT_EQ(270, format->height);
515   EXPECT_EQ(30, format->framerate());
516 }
517
518 TEST_F(VideoSourceTest, MandatorySubOneFpsConstraints) {
519   FakeConstraints constraints;
520   constraints.AddMandatory(MediaConstraintsInterface::kMaxFrameRate, 0.5);
521
522   CreateVideoSource(&constraints);
523   EXPECT_EQ_WAIT(MediaSourceInterface::kEnded, state_observer_->state(),
524                  kMaxWaitMs);
525   ASSERT_TRUE(capturer_->GetCaptureFormat() == NULL);
526 }
527
528 TEST_F(VideoSourceTest, OptionalSubOneFpsConstraints) {
529   FakeConstraints constraints;
530   constraints.AddOptional(MediaConstraintsInterface::kMaxFrameRate, 0.5);
531
532   CreateVideoSource(&constraints);
533   EXPECT_EQ_WAIT(MediaSourceInterface::kLive, state_observer_->state(),
534                  kMaxWaitMs);
535   const cricket::VideoFormat* format = capturer_->GetCaptureFormat();
536   ASSERT_TRUE(format != NULL);
537   EXPECT_EQ(30, format->framerate());
538 }
539