9b281a67d1553d985a436e261299956e1a96c2cf
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_video_track_unittest.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/callback.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/thread_checker_impl.h"
12 #include "content/child/child_process.h"
13 #include "content/renderer/media/media_stream_video_track.h"
14 #include "content/renderer/media/mock_media_stream_video_sink.h"
15 #include "content/renderer/media/mock_media_stream_video_source.h"
16 #include "media/base/video_frame.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace content {
20
21 ACTION_P(RunClosure, closure) {
22   closure.Run();
23 }
24
25 class MediaStreamVideoTrackTest : public ::testing::Test {
26  public:
27   MediaStreamVideoTrackTest()
28       : child_process_(new ChildProcess()),
29         mock_source_(new MockMediaStreamVideoSource(false)),
30         source_started_(false) {
31     blink_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
32                               blink::WebMediaStreamSource::TypeVideo,
33                               base::UTF8ToUTF16("dummy_source_name"));
34     blink_source_.setExtraData(mock_source_);
35   }
36
37   virtual ~MediaStreamVideoTrackTest() {
38   }
39
40   void DeliverVideoFrameAndWaitForRenderer(MockMediaStreamVideoSink* sink) {
41     base::RunLoop run_loop;
42     base::Closure quit_closure = run_loop.QuitClosure();
43     EXPECT_CALL(*sink, OnVideoFrame()).WillOnce(
44         RunClosure(quit_closure));
45     scoped_refptr<media::VideoFrame> frame =
46         media::VideoFrame::CreateBlackFrame(
47             gfx::Size(MediaStreamVideoSource::kDefaultWidth,
48                       MediaStreamVideoSource::kDefaultHeight));
49     mock_source()->DeliverVideoFrame(frame);
50     run_loop.Run();
51   }
52
53  protected:
54   base::MessageLoop* io_message_loop() const {
55     return child_process_->io_message_loop();
56   }
57
58   // Create a track that's associated with |mock_source_|.
59   blink::WebMediaStreamTrack CreateTrack() {
60     blink::WebMediaConstraints constraints;
61     constraints.initialize();
62     bool enabled = true;
63     blink::WebMediaStreamTrack track =
64         MediaStreamVideoTrack::CreateVideoTrack(
65             mock_source_, constraints,
66             MediaStreamSource::ConstraintsCallback(), enabled);
67     if (!source_started_) {
68       mock_source_->StartMockedSource();
69       source_started_ = true;
70     }
71     return track;
72   }
73
74   MockMediaStreamVideoSource* mock_source() { return mock_source_; }
75   const blink::WebMediaStreamSource& blink_source() const {
76     return blink_source_;
77   }
78
79  private:
80   base::MessageLoopForUI message_loop_;
81   scoped_ptr<ChildProcess> child_process_;
82   blink::WebMediaStreamSource blink_source_;
83   // |mock_source_| is owned by |webkit_source_|.
84   MockMediaStreamVideoSource* mock_source_;
85   bool source_started_;
86 };
87
88 TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
89   MockMediaStreamVideoSink sink;
90   blink::WebMediaStreamTrack track = CreateTrack();
91   MediaStreamVideoSink::AddToVideoTrack(
92       &sink, sink.GetDeliverFrameCB(), track);
93
94   DeliverVideoFrameAndWaitForRenderer(&sink);
95   EXPECT_EQ(1, sink.number_of_frames());
96
97   DeliverVideoFrameAndWaitForRenderer(&sink);
98
99   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
100
101   scoped_refptr<media::VideoFrame> frame =
102       media::VideoFrame::CreateBlackFrame(
103           gfx::Size(MediaStreamVideoSource::kDefaultWidth,
104                     MediaStreamVideoSource::kDefaultHeight));
105   mock_source()->DeliverVideoFrame(frame);
106   // Wait for the IO thread to complete delivering frames.
107   io_message_loop()->RunUntilIdle();
108   EXPECT_EQ(2, sink.number_of_frames());
109 }
110
111 class CheckThreadHelper {
112  public:
113   CheckThreadHelper(base::Closure callback, bool* correct)
114       : callback_(callback),
115         correct_(correct) {
116   }
117
118   ~CheckThreadHelper() {
119     *correct_ = thread_checker_.CalledOnValidThread();
120     callback_.Run();
121   }
122
123  private:
124   base::Closure callback_;
125   bool* correct_;
126   base::ThreadCheckerImpl thread_checker_;
127 };
128
129 void CheckThreadVideoFrameReceiver(
130     CheckThreadHelper* helper,
131     const scoped_refptr<media::VideoFrame>& frame,
132     const media::VideoCaptureFormat& format,
133     const base::TimeTicks& estimated_capture_time) {
134   // Do nothing.
135 }
136
137 // Checks that the callback given to the track is reset on the right thread.
138 TEST_F(MediaStreamVideoTrackTest, ResetCallbackOnThread) {
139   MockMediaStreamVideoSink sink;
140   blink::WebMediaStreamTrack track = CreateTrack();
141
142   base::RunLoop run_loop;
143   bool correct = false;
144   MediaStreamVideoSink::AddToVideoTrack(
145       &sink,
146       base::Bind(
147           &CheckThreadVideoFrameReceiver,
148           base::Owned(new CheckThreadHelper(run_loop.QuitClosure(), &correct))),
149       track);
150   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
151   run_loop.Run();
152   EXPECT_TRUE(correct) << "Not called on correct thread.";
153 }
154
155 TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
156   MockMediaStreamVideoSink sink;
157   blink::WebMediaStreamTrack track = CreateTrack();
158   MediaStreamVideoSink::AddToVideoTrack(
159       &sink, sink.GetDeliverFrameCB(), track);
160
161   MediaStreamVideoTrack* video_track =
162       MediaStreamVideoTrack::GetVideoTrack(track);
163
164   DeliverVideoFrameAndWaitForRenderer(&sink);
165   EXPECT_EQ(1, sink.number_of_frames());
166
167   video_track->SetEnabled(false);
168   EXPECT_FALSE(sink.enabled());
169
170   scoped_refptr<media::VideoFrame> frame =
171       media::VideoFrame::CreateBlackFrame(
172           gfx::Size(MediaStreamVideoSource::kDefaultWidth,
173                     MediaStreamVideoSource::kDefaultHeight));
174   mock_source()->DeliverVideoFrame(frame);
175   // Wait for the IO thread to complete delivering frames.
176   io_message_loop()->RunUntilIdle();
177   EXPECT_EQ(1, sink.number_of_frames());
178
179   video_track->SetEnabled(true);
180   EXPECT_TRUE(sink.enabled());
181   mock_source()->DeliverVideoFrame(frame);
182   DeliverVideoFrameAndWaitForRenderer(&sink);
183   EXPECT_EQ(2, sink.number_of_frames());
184   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
185 }
186
187 TEST_F(MediaStreamVideoTrackTest, SourceStopped) {
188   MockMediaStreamVideoSink sink;
189   blink::WebMediaStreamTrack track = CreateTrack();
190   MediaStreamVideoSink::AddToVideoTrack(
191       &sink, sink.GetDeliverFrameCB(), track);
192   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
193
194   mock_source()->StopSource();
195   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink.state());
196   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
197 }
198
199 TEST_F(MediaStreamVideoTrackTest, StopLastTrack) {
200   MockMediaStreamVideoSink sink1;
201   blink::WebMediaStreamTrack track1 = CreateTrack();
202   MediaStreamVideoSink::AddToVideoTrack(
203       &sink1, sink1.GetDeliverFrameCB(), track1);
204   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink1.state());
205
206   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
207             blink_source().readyState());
208
209   MockMediaStreamVideoSink sink2;
210   blink::WebMediaStreamTrack track2 = CreateTrack();
211   MediaStreamVideoSink::AddToVideoTrack(
212       &sink2, sink2.GetDeliverFrameCB(), track2);
213   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink2.state());
214
215   MediaStreamVideoTrack* native_track1 =
216       MediaStreamVideoTrack::GetVideoTrack(track1);
217   native_track1->Stop();
218   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink1.state());
219   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
220               blink_source().readyState());
221   MediaStreamVideoSink::RemoveFromVideoTrack(&sink1, track1);
222
223   MediaStreamVideoTrack* native_track2 =
224         MediaStreamVideoTrack::GetVideoTrack(track2);
225   native_track2->Stop();
226   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink2.state());
227   EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
228             blink_source().readyState());
229   MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
230 }
231
232 }  // namespace content