Upstream version 9.37.195.0
[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 const uint8 kBlackValue = 0x00;
22 const uint8 kColorValue = 0xAB;
23
24 ACTION_P(RunClosure, closure) {
25   closure.Run();
26 }
27
28 class MediaStreamVideoTrackTest : public ::testing::Test {
29  public:
30   MediaStreamVideoTrackTest()
31       : child_process_(new ChildProcess()),
32         mock_source_(new MockMediaStreamVideoSource(false)),
33         source_started_(false) {
34     blink_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
35                               blink::WebMediaStreamSource::TypeVideo,
36                               base::UTF8ToUTF16("dummy_source_name"));
37     blink_source_.setExtraData(mock_source_);
38   }
39
40   virtual ~MediaStreamVideoTrackTest() {
41   }
42
43   void DeliverVideoFrameAndWaitForRenderer(MockMediaStreamVideoSink* sink) {
44     base::RunLoop run_loop;
45     base::Closure quit_closure = run_loop.QuitClosure();
46     EXPECT_CALL(*sink, OnVideoFrame()).WillOnce(
47         RunClosure(quit_closure));
48     scoped_refptr<media::VideoFrame> frame =
49         media::VideoFrame::CreateColorFrame(
50             gfx::Size(MediaStreamVideoSource::kDefaultWidth,
51                       MediaStreamVideoSource::kDefaultHeight),
52             kColorValue, kColorValue, kColorValue, base::TimeDelta());
53     mock_source()->DeliverVideoFrame(frame);
54     run_loop.Run();
55   }
56
57  protected:
58   base::MessageLoop* io_message_loop() const {
59     return child_process_->io_message_loop();
60   }
61
62   // Create a track that's associated with |mock_source_|.
63   blink::WebMediaStreamTrack CreateTrack() {
64     blink::WebMediaConstraints constraints;
65     constraints.initialize();
66     bool enabled = true;
67     blink::WebMediaStreamTrack track =
68         MediaStreamVideoTrack::CreateVideoTrack(
69             mock_source_, constraints,
70             MediaStreamSource::ConstraintsCallback(), enabled);
71     if (!source_started_) {
72       mock_source_->StartMockedSource();
73       source_started_ = true;
74     }
75     return track;
76   }
77
78   MockMediaStreamVideoSource* mock_source() { return mock_source_; }
79   const blink::WebMediaStreamSource& blink_source() const {
80     return blink_source_;
81   }
82
83  private:
84   base::MessageLoopForUI message_loop_;
85   scoped_ptr<ChildProcess> child_process_;
86   blink::WebMediaStreamSource blink_source_;
87   // |mock_source_| is owned by |webkit_source_|.
88   MockMediaStreamVideoSource* mock_source_;
89   bool source_started_;
90 };
91
92 TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
93   MockMediaStreamVideoSink sink;
94   blink::WebMediaStreamTrack track = CreateTrack();
95   MediaStreamVideoSink::AddToVideoTrack(
96       &sink, sink.GetDeliverFrameCB(), track);
97
98   DeliverVideoFrameAndWaitForRenderer(&sink);
99   EXPECT_EQ(1, sink.number_of_frames());
100
101   DeliverVideoFrameAndWaitForRenderer(&sink);
102
103   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
104
105   scoped_refptr<media::VideoFrame> frame =
106       media::VideoFrame::CreateBlackFrame(
107           gfx::Size(MediaStreamVideoSource::kDefaultWidth,
108                     MediaStreamVideoSource::kDefaultHeight));
109   mock_source()->DeliverVideoFrame(frame);
110   // Wait for the IO thread to complete delivering frames.
111   io_message_loop()->RunUntilIdle();
112   EXPECT_EQ(2, sink.number_of_frames());
113 }
114
115 class CheckThreadHelper {
116  public:
117   CheckThreadHelper(base::Closure callback, bool* correct)
118       : callback_(callback),
119         correct_(correct) {
120   }
121
122   ~CheckThreadHelper() {
123     *correct_ = thread_checker_.CalledOnValidThread();
124     callback_.Run();
125   }
126
127  private:
128   base::Closure callback_;
129   bool* correct_;
130   base::ThreadCheckerImpl thread_checker_;
131 };
132
133 void CheckThreadVideoFrameReceiver(
134     CheckThreadHelper* helper,
135     const scoped_refptr<media::VideoFrame>& frame,
136     const media::VideoCaptureFormat& format,
137     const base::TimeTicks& estimated_capture_time) {
138   // Do nothing.
139 }
140
141 // Checks that the callback given to the track is reset on the right thread.
142 TEST_F(MediaStreamVideoTrackTest, ResetCallbackOnThread) {
143   MockMediaStreamVideoSink sink;
144   blink::WebMediaStreamTrack track = CreateTrack();
145
146   base::RunLoop run_loop;
147   bool correct = false;
148   MediaStreamVideoSink::AddToVideoTrack(
149       &sink,
150       base::Bind(
151           &CheckThreadVideoFrameReceiver,
152           base::Owned(new CheckThreadHelper(run_loop.QuitClosure(), &correct))),
153       track);
154   MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
155   run_loop.Run();
156   EXPECT_TRUE(correct) << "Not called on correct thread.";
157 }
158
159 TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
160   MockMediaStreamVideoSink sink;
161   blink::WebMediaStreamTrack track = CreateTrack();
162   MediaStreamVideoSink::AddToVideoTrack(
163       &sink, sink.GetDeliverFrameCB(), track);
164
165   MediaStreamVideoTrack* video_track =
166       MediaStreamVideoTrack::GetVideoTrack(track);
167
168   DeliverVideoFrameAndWaitForRenderer(&sink);
169   EXPECT_EQ(1, sink.number_of_frames());
170   EXPECT_EQ(kColorValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
171
172   video_track->SetEnabled(false);
173   EXPECT_FALSE(sink.enabled());
174
175   DeliverVideoFrameAndWaitForRenderer(&sink);
176   EXPECT_EQ(2, sink.number_of_frames());
177   EXPECT_EQ(kBlackValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
178
179   video_track->SetEnabled(true);
180   EXPECT_TRUE(sink.enabled());
181   DeliverVideoFrameAndWaitForRenderer(&sink);
182   EXPECT_EQ(3, sink.number_of_frames());
183   EXPECT_EQ(kColorValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
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