OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | |
6 | |
7 #include "base/bind.h" | 5 #include "base/bind.h" |
8 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/callback_helpers.h" |
| 8 #include "base/message_loop.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
11 #include "base/synchronization/condition_variable.h" | |
12 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
13 #include "base/synchronization/waitable_event.h" | 12 #include "base/timer.h" |
14 #include "base/test/test_timeouts.h" | |
15 #include "media/base/data_buffer.h" | 13 #include "media/base/data_buffer.h" |
16 #include "media/base/gmock_callback_support.h" | 14 #include "media/base/gmock_callback_support.h" |
17 #include "media/base/limits.h" | 15 #include "media/base/limits.h" |
18 #include "media/base/mock_callback.h" | |
19 #include "media/base/mock_filters.h" | 16 #include "media/base/mock_filters.h" |
| 17 #include "media/base/test_helpers.h" |
20 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
21 #include "media/filters/video_renderer_base.h" | 19 #include "media/filters/video_renderer_base.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
23 | 21 |
24 using ::testing::_; | 22 using ::testing::_; |
25 using ::testing::AnyNumber; | 23 using ::testing::AnyNumber; |
26 using ::testing::InSequence; | 24 using ::testing::InSequence; |
27 using ::testing::Invoke; | 25 using ::testing::Invoke; |
28 using ::testing::NotNull; | 26 using ::testing::NotNull; |
29 using ::testing::Return; | 27 using ::testing::Return; |
30 using ::testing::ReturnRef; | 28 using ::testing::ReturnRef; |
31 using ::testing::StrictMock; | 29 using ::testing::StrictMock; |
32 | 30 |
33 namespace media { | 31 namespace media { |
34 | 32 |
35 static const int kFrameDuration = 10; | 33 static const int kFrameDurationInMs = 10; |
36 static const int kVideoDuration = kFrameDuration * 100; | 34 static const int kVideoDurationInMs = kFrameDurationInMs * 100; |
37 static const int kEndOfStream = -1; | |
38 static const gfx::Size kNaturalSize(16u, 16u); | 35 static const gfx::Size kNaturalSize(16u, 16u); |
39 | 36 |
40 class VideoRendererBaseTest : public ::testing::Test { | 37 class VideoRendererBaseTest : public ::testing::Test { |
41 public: | 38 public: |
42 VideoRendererBaseTest() | 39 VideoRendererBaseTest() |
43 : decoder_(new MockVideoDecoder()), | 40 : decoder_(new MockVideoDecoder()), |
44 demuxer_stream_(new MockDemuxerStream()), | 41 demuxer_stream_(new MockDemuxerStream()) { |
45 cv_(&lock_), | |
46 event_(false, false), | |
47 timeout_(TestTimeouts::action_timeout()), | |
48 prerolling_(false), | |
49 next_frame_timestamp_(0), | |
50 paint_cv_(&lock_), | |
51 paint_was_called_(false), | |
52 should_queue_read_cb_(false) { | |
53 renderer_ = new VideoRendererBase( | 42 renderer_ = new VideoRendererBase( |
54 base::Bind(&VideoRendererBaseTest::Paint, base::Unretained(this)), | 43 base::Bind(&VideoRendererBaseTest::OnPaint, base::Unretained(this)), |
55 base::Bind(&VideoRendererBaseTest::OnSetOpaque, base::Unretained(this)), | 44 base::Bind(&VideoRendererBaseTest::OnSetOpaque, base::Unretained(this)), |
56 true); | 45 true); |
57 | 46 |
58 EXPECT_CALL(*demuxer_stream_, type()) | 47 EXPECT_CALL(*demuxer_stream_, type()) |
59 .WillRepeatedly(Return(DemuxerStream::VIDEO)); | 48 .WillRepeatedly(Return(DemuxerStream::VIDEO)); |
60 | 49 |
61 // We expect these to be called but we don't care how/when. | 50 // We expect these to be called but we don't care how/when. |
62 EXPECT_CALL(*decoder_, Stop(_)) | 51 EXPECT_CALL(*decoder_, Stop(_)) |
63 .WillRepeatedly(RunClosure<0>()); | 52 .WillRepeatedly(RunClosure<0>()); |
64 EXPECT_CALL(statistics_cb_object_, OnStatistics(_)) | 53 EXPECT_CALL(statistics_cb_object_, OnStatistics(_)) |
65 .Times(AnyNumber()); | 54 .Times(AnyNumber()); |
66 EXPECT_CALL(*this, OnTimeUpdate(_)) | 55 EXPECT_CALL(*this, OnTimeUpdate(_)) |
67 .Times(AnyNumber()); | 56 .Times(AnyNumber()); |
| 57 EXPECT_CALL(*this, OnPaint()) |
| 58 .Times(AnyNumber()); |
68 EXPECT_CALL(*this, OnSetOpaque(_)) | 59 EXPECT_CALL(*this, OnSetOpaque(_)) |
69 .Times(AnyNumber()); | 60 .Times(AnyNumber()); |
70 } | 61 } |
71 | 62 |
72 virtual ~VideoRendererBaseTest() { | 63 virtual ~VideoRendererBaseTest() {} |
73 read_queue_.clear(); | |
74 | |
75 if (renderer_) { | |
76 Stop(); | |
77 } | |
78 } | |
79 | 64 |
80 // Callbacks passed into VideoRendererBase(). | 65 // Callbacks passed into VideoRendererBase(). |
| 66 MOCK_CONST_METHOD0(OnPaint, void()); |
81 MOCK_CONST_METHOD1(OnSetOpaque, void(bool)); | 67 MOCK_CONST_METHOD1(OnSetOpaque, void(bool)); |
82 | 68 |
83 // Callbacks passed into Initialize(). | 69 // Callbacks passed into Initialize(). |
84 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); | 70 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); |
85 MOCK_METHOD1(OnNaturalSizeChanged, void(const gfx::Size&)); | 71 MOCK_METHOD1(OnNaturalSizeChanged, void(const gfx::Size&)); |
86 MOCK_METHOD0(OnEnded, void()); | |
87 MOCK_METHOD1(OnError, void(PipelineStatus)); | |
88 | 72 |
89 void Initialize() { | 73 void Initialize() { |
90 Initialize(kVideoDuration); | 74 InitializeWithDuration(kVideoDurationInMs); |
91 } | 75 } |
92 | 76 |
93 void Initialize(int duration) { | 77 void InitializeWithDuration(int duration_ms) { |
94 duration_ = duration; | 78 duration_ = base::TimeDelta::FromMilliseconds(duration_ms); |
95 | |
96 // TODO(scherkus): really, really, really need to inject a thread into | |
97 // VideoRendererBase... it makes mocking much harder. | |
98 | 79 |
99 // Monitor reads from the decoder. | 80 // Monitor reads from the decoder. |
100 EXPECT_CALL(*decoder_, Read(_)) | 81 EXPECT_CALL(*decoder_, Read(_)) |
101 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::FrameRequested)); | 82 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::FrameRequested)); |
102 | 83 |
103 EXPECT_CALL(*decoder_, Reset(_)) | 84 EXPECT_CALL(*decoder_, Reset(_)) |
104 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::FlushRequested)); | 85 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::FlushRequested)); |
105 | 86 |
106 InSequence s; | 87 InSequence s; |
107 | 88 |
108 EXPECT_CALL(*decoder_, Initialize(_, _, _)) | 89 EXPECT_CALL(*decoder_, Initialize(_, _, _)) |
109 .WillOnce(RunCallback<1>(PIPELINE_OK)); | 90 .WillOnce(RunCallback<1>(PIPELINE_OK)); |
110 | 91 |
111 // Set playback rate before anything else happens. | 92 // Set playback rate before anything else happens. |
112 renderer_->SetPlaybackRate(1.0f); | 93 renderer_->SetPlaybackRate(1.0f); |
113 | 94 |
114 // Initialize, we shouldn't have any reads. | 95 // Initialize, we shouldn't have any reads. |
115 InitializeRenderer(PIPELINE_OK); | 96 InitializeRenderer(PIPELINE_OK); |
116 | 97 |
117 // We expect the video size to be set. | 98 // We expect the video size to be set. |
118 EXPECT_CALL(*this, OnNaturalSizeChanged(kNaturalSize)); | 99 EXPECT_CALL(*this, OnNaturalSizeChanged(kNaturalSize)); |
119 | 100 |
120 // Start prerolling. | 101 // Start prerolling. |
121 Preroll(0); | 102 QueuePrerollFrames(0); |
| 103 Preroll(0, PIPELINE_OK); |
122 } | 104 } |
123 | 105 |
124 void InitializeRenderer(PipelineStatus expected_status) { | 106 void InitializeRenderer(PipelineStatus expected) { |
| 107 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected)); |
125 VideoRendererBase::VideoDecoderList decoders; | 108 VideoRendererBase::VideoDecoderList decoders; |
126 decoders.push_back(decoder_); | 109 decoders.push_back(decoder_); |
| 110 |
| 111 WaitableMessageLoopEvent event; |
127 renderer_->Initialize( | 112 renderer_->Initialize( |
128 demuxer_stream_, | 113 demuxer_stream_, |
129 decoders, | 114 decoders, |
130 NewExpectedStatusCB(expected_status), | 115 event.GetPipelineStatusCB(), |
131 base::Bind(&MockStatisticsCB::OnStatistics, | 116 base::Bind(&MockStatisticsCB::OnStatistics, |
132 base::Unretained(&statistics_cb_object_)), | 117 base::Unretained(&statistics_cb_object_)), |
133 base::Bind(&VideoRendererBaseTest::OnTimeUpdate, | 118 base::Bind(&VideoRendererBaseTest::OnTimeUpdate, |
134 base::Unretained(this)), | 119 base::Unretained(this)), |
135 base::Bind(&VideoRendererBaseTest::OnNaturalSizeChanged, | 120 base::Bind(&VideoRendererBaseTest::OnNaturalSizeChanged, |
136 base::Unretained(this)), | 121 base::Unretained(this)), |
137 base::Bind(&VideoRendererBaseTest::OnEnded, base::Unretained(this)), | 122 ended_event_.GetClosure(), |
138 base::Bind(&VideoRendererBaseTest::OnError, base::Unretained(this)), | 123 error_event_.GetPipelineStatusCB(), |
139 base::Bind(&VideoRendererBaseTest::GetTime, base::Unretained(this)), | 124 base::Bind(&VideoRendererBaseTest::GetTime, base::Unretained(this)), |
140 base::Bind(&VideoRendererBaseTest::GetDuration, | 125 base::Bind(&VideoRendererBaseTest::GetDuration, |
141 base::Unretained(this))); | 126 base::Unretained(this))); |
142 } | 127 event.RunAndWaitForStatus(expected); |
143 | |
144 // Instead of immediately satisfying a decoder Read request, queue it up. | |
145 void QueueReadCB() { | |
146 should_queue_read_cb_ = true; | |
147 } | |
148 | |
149 void SatisfyQueuedReadCB() { | |
150 base::AutoLock l(lock_); | |
151 CHECK(should_queue_read_cb_ && !queued_read_cb_.is_null()); | |
152 should_queue_read_cb_ = false; | |
153 VideoDecoder::ReadCB read_cb(queued_read_cb_); | |
154 queued_read_cb_.Reset(); | |
155 base::AutoUnlock u(lock_); | |
156 read_cb.Run(VideoDecoder::kOk, VideoFrame::CreateEmptyFrame()); | |
157 } | |
158 | |
159 void StartPrerolling(int timestamp, PipelineStatus expected_status) { | |
160 EXPECT_FALSE(prerolling_); | |
161 | |
162 next_frame_timestamp_ = 0; | |
163 prerolling_ = true; | |
164 renderer_->Preroll(base::TimeDelta::FromMilliseconds(timestamp), | |
165 base::Bind(&VideoRendererBaseTest::OnPrerollComplete, | |
166 base::Unretained(this), expected_status)); | |
167 } | 128 } |
168 | 129 |
169 void Play() { | 130 void Play() { |
170 SCOPED_TRACE("Play()"); | 131 SCOPED_TRACE("Play()"); |
171 renderer_->Play(NewWaitableClosure()); | 132 WaitableMessageLoopEvent event; |
172 WaitForClosure(); | 133 renderer_->Play(event.GetClosure()); |
| 134 event.RunAndWait(); |
173 } | 135 } |
174 | 136 |
175 // Preroll to the given timestamp. | 137 void Preroll(int timestamp_ms, PipelineStatus expected) { |
176 // | 138 SCOPED_TRACE(base::StringPrintf("Preroll(%d, %d)", timestamp_ms, expected)); |
177 // Use |kEndOfStream| to preroll end of stream frames. | 139 WaitableMessageLoopEvent event; |
178 void Preroll(int timestamp) { | 140 renderer_->Preroll( |
179 SCOPED_TRACE(base::StringPrintf("Preroll(%d)", timestamp)); | 141 base::TimeDelta::FromMilliseconds(timestamp_ms), |
180 bool end_of_stream = (timestamp == kEndOfStream); | 142 event.GetPipelineStatusCB()); |
181 int preroll_timestamp = end_of_stream ? 0 : timestamp; | 143 event.RunAndWaitForStatus(expected); |
182 StartPrerolling(preroll_timestamp, PIPELINE_OK); | |
183 FinishPrerolling(end_of_stream); | |
184 } | 144 } |
185 | 145 |
186 void Pause() { | 146 void Pause() { |
187 SCOPED_TRACE("Pause()"); | 147 SCOPED_TRACE("Pause()"); |
188 renderer_->Pause(NewWaitableClosure()); | 148 WaitableMessageLoopEvent event; |
189 WaitForClosure(); | 149 renderer_->Pause(event.GetClosure()); |
| 150 event.RunAndWait(); |
190 } | 151 } |
191 | 152 |
192 void Flush() { | 153 void Flush() { |
193 SCOPED_TRACE("Flush()"); | 154 SCOPED_TRACE("Flush()"); |
194 renderer_->Flush(NewWaitableClosure()); | 155 WaitableMessageLoopEvent event; |
195 WaitForClosure(); | 156 renderer_->Flush(event.GetClosure()); |
| 157 event.RunAndWait(); |
196 } | 158 } |
197 | 159 |
198 void Stop() { | 160 void Stop() { |
199 SCOPED_TRACE("Stop()"); | 161 SCOPED_TRACE("Stop()"); |
200 renderer_->Stop(NewWaitableClosure()); | 162 WaitableMessageLoopEvent event; |
201 WaitForClosure(); | 163 renderer_->Stop(event.GetClosure()); |
| 164 event.RunAndWait(); |
202 } | 165 } |
203 | 166 |
204 void Shutdown() { | 167 void Shutdown() { |
205 Pause(); | 168 Pause(); |
206 Flush(); | 169 Flush(); |
207 Stop(); | 170 Stop(); |
208 } | 171 } |
209 | 172 |
210 void DeliverNextFrame(bool end_of_stream) { | 173 // Queues a VideoFrame with |next_frame_timestamp_|. |
211 base::AutoLock l(lock_); | 174 void QueueNextFrame() { |
212 DeliverNextFrame_Locked(end_of_stream); | 175 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
| 176 DCHECK_LT(next_frame_timestamp_.InMicroseconds(), |
| 177 duration_.InMicroseconds()); |
| 178 |
| 179 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( |
| 180 VideoFrame::RGB32, kNaturalSize, gfx::Rect(kNaturalSize), kNaturalSize, |
| 181 next_frame_timestamp_); |
| 182 decode_results_.push_back(std::make_pair( |
| 183 VideoDecoder::kOk, frame)); |
| 184 next_frame_timestamp_ += |
| 185 base::TimeDelta::FromMilliseconds(kFrameDurationInMs); |
213 } | 186 } |
214 | 187 |
215 // Delivers the next frame to the video renderer. If |end_of_stream| | 188 void QueueEndOfStream() { |
216 // is true then an "end or stream" frame will be returned. Otherwise | 189 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
217 // A frame with |next_frame_timestamp_| will be returned. | 190 decode_results_.push_back(std::make_pair( |
218 void DeliverNextFrame_Locked(bool end_of_stream) { | 191 VideoDecoder::kOk, VideoFrame::CreateEmptyFrame())); |
219 lock_.AssertAcquired(); | 192 } |
220 | 193 |
221 VideoDecoder::ReadCB read_cb; | 194 void QueueDecodeError() { |
222 std::swap(read_cb, read_cb_); | 195 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
| 196 scoped_refptr<VideoFrame> null_frame; |
| 197 decode_results_.push_back(std::make_pair( |
| 198 VideoDecoder::kDecodeError, null_frame)); |
| 199 } |
223 | 200 |
224 DCHECK_LT(next_frame_timestamp_, duration_); | 201 void QueueAbortedRead() { |
225 int timestamp = next_frame_timestamp_; | 202 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
226 next_frame_timestamp_ += kFrameDuration; | 203 scoped_refptr<VideoFrame> null_frame; |
| 204 decode_results_.push_back(std::make_pair( |
| 205 VideoDecoder::kOk, null_frame)); |
| 206 } |
227 | 207 |
228 // Unlock to deliver the frame to avoid re-entrancy issues. | 208 void QueuePrerollFrames(int timestamp_ms) { |
229 base::AutoUnlock ul(lock_); | 209 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
230 if (end_of_stream) { | 210 next_frame_timestamp_ = base::TimeDelta(); |
231 read_cb.Run(VideoDecoder::kOk, VideoFrame::CreateEmptyFrame()); | 211 base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(timestamp_ms); |
232 } else { | 212 while (next_frame_timestamp_ < timestamp) { |
233 read_cb.Run(VideoDecoder::kOk, CreateFrame(timestamp)); | 213 QueueNextFrame(); |
| 214 } |
| 215 |
| 216 // Queue the frame at |timestamp| plus additional ones for prerolling. |
| 217 for (int i = 0; i < limits::kMaxVideoFrames; ++i) { |
| 218 QueueNextFrame(); |
234 } | 219 } |
235 } | 220 } |
236 | 221 |
237 void DecoderError() { | 222 scoped_refptr<VideoFrame> GetCurrentFrame() { |
238 // Lock+swap to avoid re-entrancy issues. | |
239 VideoDecoder::ReadCB read_cb; | |
240 { | |
241 base::AutoLock l(lock_); | |
242 std::swap(read_cb, read_cb_); | |
243 } | |
244 | |
245 read_cb.Run(VideoDecoder::kDecodeError, NULL); | |
246 } | |
247 | |
248 void AbortRead() { | |
249 // Lock+swap to avoid re-entrancy issues. | |
250 VideoDecoder::ReadCB read_cb; | |
251 { | |
252 base::AutoLock l(lock_); | |
253 std::swap(read_cb, read_cb_); | |
254 } | |
255 | |
256 read_cb.Run(VideoDecoder::kOk, NULL); | |
257 } | |
258 | |
259 void ExpectCurrentFrame(bool present) { | |
260 scoped_refptr<VideoFrame> frame; | 223 scoped_refptr<VideoFrame> frame; |
261 renderer_->GetCurrentFrame(&frame); | 224 renderer_->GetCurrentFrame(&frame); |
262 if (present) { | |
263 EXPECT_TRUE(frame); | |
264 } else { | |
265 EXPECT_FALSE(frame); | |
266 } | |
267 renderer_->PutCurrentFrame(frame); | 225 renderer_->PutCurrentFrame(frame); |
268 } | |
269 | |
270 void ExpectCurrentTimestamp(int timestamp) { | |
271 scoped_refptr<VideoFrame> frame; | |
272 renderer_->GetCurrentFrame(&frame); | |
273 EXPECT_EQ(timestamp, frame->GetTimestamp().InMilliseconds()); | |
274 renderer_->PutCurrentFrame(frame); | |
275 } | |
276 | |
277 base::Closure NewWaitableClosure() { | |
278 return base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)); | |
279 } | |
280 | |
281 void WaitForClosure() { | |
282 ASSERT_TRUE(event_.TimedWait(timeout_)); | |
283 event_.Reset(); | |
284 } | |
285 | |
286 // Creates a frame with given timestamp. | |
287 scoped_refptr<VideoFrame> CreateFrame(int timestamp) { | |
288 scoped_refptr<VideoFrame> frame = | |
289 VideoFrame::CreateFrame(VideoFrame::RGB32, kNaturalSize, | |
290 gfx::Rect(kNaturalSize), kNaturalSize, | |
291 base::TimeDelta::FromMilliseconds(timestamp)); | |
292 return frame; | 226 return frame; |
293 } | 227 } |
294 | 228 |
295 // Advances clock to |timestamp| and waits for the frame at |timestamp| to get | 229 int GetCurrentTimestampInMs() { |
296 // rendered using |read_cb_| as the signal that the frame has rendered. | 230 scoped_refptr<VideoFrame> frame = GetCurrentFrame(); |
297 void RenderFrame(int timestamp) { | 231 if (!frame) |
298 base::AutoLock l(lock_); | 232 return -1; |
299 time_ = base::TimeDelta::FromMilliseconds(timestamp); | 233 return frame->GetTimestamp().InMilliseconds(); |
300 paint_was_called_ = false; | |
301 if (read_cb_.is_null()) { | |
302 cv_.TimedWait(timeout_); | |
303 CHECK(!read_cb_.is_null()) << "Timed out waiting for read to occur."; | |
304 } | |
305 WaitForPaint_Locked(); | |
306 } | 234 } |
307 | 235 |
308 // Advances clock to |timestamp| (which should be the timestamp of the last | 236 void WaitForError(PipelineStatus expected) { |
309 // frame plus duration) and waits for the ended signal before returning. | 237 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); |
310 void RenderLastFrame(int timestamp) { | 238 error_event_.RunAndWaitForStatus(expected); |
311 EXPECT_CALL(*this, OnEnded()) | |
312 .WillOnce(Invoke(&event_, &base::WaitableEvent::Signal)); | |
313 { | |
314 base::AutoLock l(lock_); | |
315 time_ = base::TimeDelta::FromMilliseconds(timestamp); | |
316 } | |
317 CHECK(event_.TimedWait(timeout_)) << "Timed out waiting for ended signal."; | |
318 } | 239 } |
319 | 240 |
320 base::WaitableEvent* event() { return &event_; } | 241 void WaitForEnded() { |
321 const base::TimeDelta& timeout() { return timeout_; } | 242 SCOPED_TRACE("WaitForEnded()"); |
| 243 ended_event_.RunAndWait(); |
| 244 } |
322 | 245 |
323 void VerifyNotPrerolling() { | 246 void WaitForPendingRead() { |
| 247 SCOPED_TRACE("WaitForPendingRead()"); |
| 248 if (!read_cb_.is_null()) |
| 249 return; |
| 250 |
| 251 DCHECK(pending_read_cb_.is_null()); |
| 252 |
| 253 WaitableMessageLoopEvent event; |
| 254 pending_read_cb_ = event.GetClosure(); |
| 255 event.RunAndWait(); |
| 256 |
| 257 DCHECK(!read_cb_.is_null()); |
| 258 DCHECK(pending_read_cb_.is_null()); |
| 259 } |
| 260 |
| 261 void SatisfyPendingRead() { |
| 262 CHECK(!read_cb_.is_null()); |
| 263 CHECK(!decode_results_.empty()); |
| 264 |
| 265 base::Closure closure = base::Bind( |
| 266 read_cb_, decode_results_.front().first, |
| 267 decode_results_.front().second); |
| 268 |
| 269 read_cb_.Reset(); |
| 270 decode_results_.pop_front(); |
| 271 |
| 272 message_loop_.PostTask(FROM_HERE, closure); |
| 273 } |
| 274 |
| 275 void AdvanceTimeInMs(int time_ms) { |
| 276 DCHECK_EQ(&message_loop_, MessageLoop::current()); |
324 base::AutoLock l(lock_); | 277 base::AutoLock l(lock_); |
325 ASSERT_FALSE(prerolling_); | 278 time_ += base::TimeDelta::FromMilliseconds(time_ms); |
| 279 DCHECK_LE(time_.InMicroseconds(), duration_.InMicroseconds()); |
326 } | 280 } |
327 | 281 |
328 protected: | 282 protected: |
329 // Fixture members. | 283 // Fixture members. |
330 scoped_refptr<VideoRendererBase> renderer_; | 284 scoped_refptr<VideoRendererBase> renderer_; |
331 scoped_refptr<MockVideoDecoder> decoder_; | 285 scoped_refptr<MockVideoDecoder> decoder_; |
332 scoped_refptr<MockDemuxerStream> demuxer_stream_; | 286 scoped_refptr<MockDemuxerStream> demuxer_stream_; |
333 MockStatisticsCB statistics_cb_object_; | 287 MockStatisticsCB statistics_cb_object_; |
334 | 288 |
335 // Receives all the buffers that renderer had provided to |decoder_|. | |
336 std::deque<scoped_refptr<VideoFrame> > read_queue_; | |
337 | |
338 private: | 289 private: |
339 // Called by VideoRendererBase for accessing the current time. | |
340 base::TimeDelta GetTime() { | 290 base::TimeDelta GetTime() { |
341 base::AutoLock l(lock_); | 291 base::AutoLock l(lock_); |
342 return time_; | 292 return time_; |
343 } | 293 } |
344 | 294 |
345 base::TimeDelta GetDuration() { | 295 base::TimeDelta GetDuration() { |
346 return base::TimeDelta::FromMilliseconds(duration_); | 296 return duration_; |
347 } | 297 } |
348 | 298 |
349 // Called by VideoRendererBase when it wants a frame. | 299 void FrameRequested(const VideoDecoder::ReadCB& read_cb) { |
350 void FrameRequested(const VideoDecoder::ReadCB& callback) { | 300 // TODO(scherkus): Make VideoRendererBase call on right thread. |
351 base::AutoLock l(lock_); | 301 if (&message_loop_ != MessageLoop::current()) { |
352 if (should_queue_read_cb_) { | 302 message_loop_.PostTask(FROM_HERE, base::Bind( |
353 CHECK(queued_read_cb_.is_null()); | 303 &VideoRendererBaseTest::FrameRequested, base::Unretained(this), |
354 queued_read_cb_ = callback; | 304 read_cb)); |
355 return; | 305 return; |
356 } | 306 } |
| 307 |
357 CHECK(read_cb_.is_null()); | 308 CHECK(read_cb_.is_null()); |
358 read_cb_ = callback; | 309 read_cb_ = read_cb; |
359 cv_.Signal(); | 310 |
| 311 // Wake up WaitForPendingRead() if needed. |
| 312 if (!pending_read_cb_.is_null()) |
| 313 base::ResetAndReturn(&pending_read_cb_).Run(); |
| 314 |
| 315 if (decode_results_.empty()) |
| 316 return; |
| 317 |
| 318 SatisfyPendingRead(); |
360 } | 319 } |
361 | 320 |
362 void FlushRequested(const base::Closure& callback) { | 321 void FlushRequested(const base::Closure& callback) { |
363 // Lock+swap to avoid re-entrancy issues. | 322 // TODO(scherkus): Make VideoRendererBase call on right thread. |
364 VideoDecoder::ReadCB read_cb; | 323 if (&message_loop_ != MessageLoop::current()) { |
365 { | 324 message_loop_.PostTask(FROM_HERE, base::Bind( |
366 base::AutoLock l(lock_); | 325 &VideoRendererBaseTest::FlushRequested, base::Unretained(this), |
367 std::swap(read_cb, read_cb_); | 326 callback)); |
| 327 return; |
368 } | 328 } |
369 | 329 |
370 // Abort pending read. | 330 decode_results_.clear(); |
371 if (!read_cb.is_null()) | 331 if (!read_cb_.is_null()) { |
372 read_cb.Run(VideoDecoder::kOk, NULL); | 332 QueueAbortedRead(); |
| 333 SatisfyPendingRead(); |
| 334 } |
373 | 335 |
374 callback.Run(); | 336 message_loop_.PostTask(FROM_HERE, callback); |
375 } | 337 } |
376 | 338 |
377 void OnPrerollComplete(PipelineStatus expected_status, | 339 MessageLoop message_loop_; |
378 PipelineStatus status) { | |
379 base::AutoLock l(lock_); | |
380 EXPECT_EQ(status, expected_status); | |
381 EXPECT_TRUE(prerolling_); | |
382 prerolling_ = false; | |
383 cv_.Signal(); | |
384 } | |
385 | 340 |
386 void FinishPrerolling(bool end_of_stream) { | 341 // Used to protect |time_|. |
387 // Satisfy the read requests. The callback must be executed in order | |
388 // to exit the loop since VideoRendererBase can read a few extra frames | |
389 // after |timestamp| in order to preroll. | |
390 base::AutoLock l(lock_); | |
391 EXPECT_TRUE(prerolling_); | |
392 paint_was_called_ = false; | |
393 while (prerolling_) { | |
394 if (!read_cb_.is_null()) { | |
395 DeliverNextFrame_Locked(end_of_stream); | |
396 } else { | |
397 // We want to wait iff we're still prerolling but have no pending read. | |
398 cv_.TimedWait(timeout_); | |
399 CHECK(!prerolling_ || !read_cb_.is_null()) | |
400 << "Timed out waiting for preroll or read to occur."; | |
401 } | |
402 } | |
403 | |
404 EXPECT_TRUE(read_cb_.is_null()); | |
405 WaitForPaint_Locked(); | |
406 } | |
407 | |
408 void Paint() { | |
409 base::AutoLock l(lock_); | |
410 paint_was_called_ = true; | |
411 paint_cv_.Signal(); | |
412 } | |
413 | |
414 void WaitForPaint_Locked() { | |
415 lock_.AssertAcquired(); | |
416 if (paint_was_called_) | |
417 return; | |
418 paint_cv_.TimedWait(timeout_); | |
419 EXPECT_TRUE(paint_was_called_); | |
420 } | |
421 | |
422 base::Lock lock_; | 342 base::Lock lock_; |
423 base::ConditionVariable cv_; | |
424 base::WaitableEvent event_; | |
425 base::TimeDelta timeout_; | |
426 | |
427 // Used in conjunction with |lock_| and |cv_| for satisfying reads. | |
428 bool prerolling_; | |
429 VideoDecoder::ReadCB read_cb_; | |
430 int next_frame_timestamp_; | |
431 int duration_; | |
432 base::TimeDelta time_; | 343 base::TimeDelta time_; |
433 | 344 |
434 // Used in conjunction with |lock_| to wait for Paint() calls. | 345 // Used for satisfying reads. |
435 base::ConditionVariable paint_cv_; | 346 VideoDecoder::ReadCB read_cb_; |
436 bool paint_was_called_; | 347 base::TimeDelta next_frame_timestamp_; |
| 348 base::TimeDelta duration_; |
437 | 349 |
438 // Holding queue for Read callbacks for exercising delayed demux/decode. | 350 WaitableMessageLoopEvent error_event_; |
439 bool should_queue_read_cb_; | 351 WaitableMessageLoopEvent ended_event_; |
440 VideoDecoder::ReadCB queued_read_cb_; | 352 base::Closure pending_read_cb_; |
| 353 |
| 354 std::deque<std::pair< |
| 355 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_; |
441 | 356 |
442 DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest); | 357 DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest); |
443 }; | 358 }; |
444 | 359 |
445 TEST_F(VideoRendererBaseTest, Initialize) { | 360 TEST_F(VideoRendererBaseTest, Initialize) { |
446 Initialize(); | 361 Initialize(); |
447 ExpectCurrentTimestamp(0); | 362 EXPECT_EQ(0, GetCurrentTimestampInMs()); |
448 Shutdown(); | 363 Shutdown(); |
449 } | 364 } |
450 | 365 |
451 TEST_F(VideoRendererBaseTest, Play) { | 366 TEST_F(VideoRendererBaseTest, Play) { |
452 Initialize(); | 367 Initialize(); |
453 Play(); | 368 Play(); |
454 Shutdown(); | 369 Shutdown(); |
455 } | 370 } |
456 | 371 |
457 TEST_F(VideoRendererBaseTest, EndOfStream_DefaultFrameDuration) { | 372 TEST_F(VideoRendererBaseTest, EndOfStream_DefaultFrameDuration) { |
458 Initialize(); | 373 Initialize(); |
459 Play(); | 374 Play(); |
460 | 375 |
461 // Finish rendering up to the next-to-last frame. | |
462 int timestamp = kFrameDuration; | |
463 for (int i = 1; i < limits::kMaxVideoFrames; ++i) { | |
464 RenderFrame(timestamp); | |
465 timestamp += kFrameDuration; | |
466 } | |
467 | |
468 // Deliver the end of stream frame. | |
469 DeliverNextFrame(true); | |
470 | |
471 // Verify that the ended callback fires when the default last frame duration | 376 // Verify that the ended callback fires when the default last frame duration |
472 // has elapsed. | 377 // has elapsed. |
473 int end_timestamp = | 378 int end_timestamp = kFrameDurationInMs * limits::kMaxVideoFrames + |
474 timestamp + VideoRendererBase::kMaxLastFrameDuration().InMilliseconds(); | 379 VideoRendererBase::kMaxLastFrameDuration().InMilliseconds(); |
475 EXPECT_LT(end_timestamp, kVideoDuration); | 380 EXPECT_LT(end_timestamp, kVideoDurationInMs); |
476 RenderLastFrame(end_timestamp); | 381 |
| 382 QueueEndOfStream(); |
| 383 AdvanceTimeInMs(end_timestamp); |
| 384 WaitForEnded(); |
477 | 385 |
478 Shutdown(); | 386 Shutdown(); |
479 } | 387 } |
480 | 388 |
481 TEST_F(VideoRendererBaseTest, EndOfStream_ClipDuration) { | 389 TEST_F(VideoRendererBaseTest, EndOfStream_ClipDuration) { |
482 int duration = kVideoDuration + kFrameDuration / 2; | 390 int duration = kVideoDurationInMs + kFrameDurationInMs / 2; |
483 Initialize(duration); | 391 InitializeWithDuration(duration); |
484 Play(); | 392 Play(); |
485 | 393 |
486 // Render all frames except for the last |limits::kMaxVideoFrames| frames | 394 // Render all frames except for the last |limits::kMaxVideoFrames| frames |
487 // and deliver all the frames between the start and |duration|. The preroll | 395 // and deliver all the frames between the start and |duration|. The preroll |
488 // inside Initialize() makes this a little confusing, but |timestamp| is | 396 // inside Initialize() makes this a little confusing, but |timestamp| is |
489 // the current render time and DeliverNextFrame() delivers a frame with a | 397 // the current render time and QueueNextFrame() delivers a frame with a |
490 // timestamp that is |timestamp| + limits::kMaxVideoFrames * kFrameDuration. | 398 // timestamp that is |timestamp| + limits::kMaxVideoFrames * |
491 int timestamp = kFrameDuration; | 399 // kFrameDurationInMs. |
492 int end_timestamp = duration - limits::kMaxVideoFrames * kFrameDuration; | 400 int timestamp = kFrameDurationInMs; |
493 for (; timestamp < end_timestamp; timestamp += kFrameDuration) { | 401 int end_timestamp = duration - limits::kMaxVideoFrames * kFrameDurationInMs; |
494 RenderFrame(timestamp); | 402 for (; timestamp < end_timestamp; timestamp += kFrameDurationInMs) { |
495 DeliverNextFrame(false); | 403 QueueNextFrame(); |
496 } | 404 } |
497 | 405 |
498 // Render the next frame so that a Read() will get requested. | 406 // Queue the end of stream frame and wait for the last frame to be rendered. |
499 RenderFrame(timestamp); | 407 QueueEndOfStream(); |
500 | 408 AdvanceTimeInMs(duration); |
501 // Deliver the end of stream frame and wait for the last frame to be rendered. | 409 WaitForEnded(); |
502 DeliverNextFrame(true); | |
503 RenderLastFrame(duration); | |
504 | 410 |
505 Shutdown(); | 411 Shutdown(); |
506 } | 412 } |
507 | 413 |
508 TEST_F(VideoRendererBaseTest, DecoderError) { | 414 TEST_F(VideoRendererBaseTest, DecodeError_Playing) { |
509 Initialize(); | 415 Initialize(); |
510 Play(); | 416 Play(); |
511 RenderFrame(kFrameDuration); | 417 |
512 EXPECT_CALL(*this, OnError(PIPELINE_ERROR_DECODE)); | 418 QueueDecodeError(); |
513 DecoderError(); | 419 AdvanceTimeInMs(kVideoDurationInMs); |
| 420 WaitForError(PIPELINE_ERROR_DECODE); |
514 Shutdown(); | 421 Shutdown(); |
515 } | 422 } |
516 | 423 |
517 TEST_F(VideoRendererBaseTest, DecoderErrorDuringPreroll) { | 424 TEST_F(VideoRendererBaseTest, DecodeError_DuringPreroll) { |
518 Initialize(); | 425 Initialize(); |
519 Pause(); | 426 Pause(); |
520 Flush(); | 427 Flush(); |
521 StartPrerolling(kFrameDuration * 6, PIPELINE_ERROR_DECODE); | 428 |
522 DecoderError(); | 429 QueueDecodeError(); |
| 430 Preroll(kFrameDurationInMs * 6, PIPELINE_ERROR_DECODE); |
523 Shutdown(); | 431 Shutdown(); |
524 } | 432 } |
525 | 433 |
526 TEST_F(VideoRendererBaseTest, Preroll_Exact) { | 434 TEST_F(VideoRendererBaseTest, Preroll_Exact) { |
527 Initialize(); | 435 Initialize(); |
528 Pause(); | 436 Pause(); |
529 Flush(); | 437 Flush(); |
530 Preroll(kFrameDuration * 6); | 438 QueuePrerollFrames(kFrameDurationInMs * 6); |
531 ExpectCurrentTimestamp(kFrameDuration * 6); | 439 |
| 440 Preroll(kFrameDurationInMs * 6, PIPELINE_OK); |
| 441 EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); |
532 Shutdown(); | 442 Shutdown(); |
533 } | 443 } |
534 | 444 |
535 TEST_F(VideoRendererBaseTest, Preroll_RightBefore) { | 445 TEST_F(VideoRendererBaseTest, Preroll_RightBefore) { |
536 Initialize(); | 446 Initialize(); |
537 Pause(); | 447 Pause(); |
538 Flush(); | 448 Flush(); |
539 Preroll(kFrameDuration * 6 - 1); | 449 QueuePrerollFrames(kFrameDurationInMs * 6); |
540 ExpectCurrentTimestamp(kFrameDuration * 5); | 450 |
| 451 Preroll(kFrameDurationInMs * 6 - 1, PIPELINE_OK); |
| 452 EXPECT_EQ(kFrameDurationInMs * 5, GetCurrentTimestampInMs()); |
541 Shutdown(); | 453 Shutdown(); |
542 } | 454 } |
543 | 455 |
544 TEST_F(VideoRendererBaseTest, Preroll_RightAfter) { | 456 TEST_F(VideoRendererBaseTest, Preroll_RightAfter) { |
545 Initialize(); | 457 Initialize(); |
546 Pause(); | 458 Pause(); |
547 Flush(); | 459 Flush(); |
548 Preroll(kFrameDuration * 6 + 1); | 460 QueuePrerollFrames(kFrameDurationInMs * 6); |
549 ExpectCurrentTimestamp(kFrameDuration * 6); | 461 |
| 462 Preroll(kFrameDurationInMs * 6 + 1, PIPELINE_OK); |
| 463 EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); |
550 Shutdown(); | 464 Shutdown(); |
551 } | 465 } |
552 | 466 |
553 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Initialized) { | 467 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Initialized) { |
554 Initialize(); | 468 Initialize(); |
555 ExpectCurrentFrame(true); // Due to prerolling. | 469 EXPECT_TRUE(GetCurrentFrame()); // Due to prerolling. |
556 Shutdown(); | 470 Shutdown(); |
557 } | 471 } |
558 | 472 |
559 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Playing) { | 473 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Playing) { |
560 Initialize(); | 474 Initialize(); |
561 Play(); | 475 Play(); |
562 ExpectCurrentFrame(true); | 476 EXPECT_TRUE(GetCurrentFrame()); |
563 Shutdown(); | 477 Shutdown(); |
564 } | 478 } |
565 | 479 |
566 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Paused) { | 480 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Paused) { |
567 Initialize(); | 481 Initialize(); |
568 Play(); | 482 Play(); |
569 Pause(); | 483 Pause(); |
570 ExpectCurrentFrame(true); | 484 EXPECT_TRUE(GetCurrentFrame()); |
571 Shutdown(); | 485 Shutdown(); |
572 } | 486 } |
573 | 487 |
574 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Flushed) { | 488 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Flushed) { |
575 Initialize(); | 489 Initialize(); |
576 Play(); | 490 Play(); |
577 Pause(); | 491 Pause(); |
578 Flush(); | 492 Flush(); |
579 ExpectCurrentFrame(false); | 493 EXPECT_FALSE(GetCurrentFrame()); |
580 Shutdown(); | 494 Shutdown(); |
581 } | 495 } |
582 | 496 |
583 #if defined(OS_MACOSX) | 497 #if defined(OS_MACOSX) |
584 // http://crbug.com/109405 | 498 // http://crbug.com/109405 |
585 #define MAYBE_GetCurrentFrame_EndOfStream DISABLED_GetCurrentFrame_EndOfStream | 499 #define MAYBE_GetCurrentFrame_EndOfStream DISABLED_GetCurrentFrame_EndOfStream |
586 #else | 500 #else |
587 #define MAYBE_GetCurrentFrame_EndOfStream GetCurrentFrame_EndOfStream | 501 #define MAYBE_GetCurrentFrame_EndOfStream GetCurrentFrame_EndOfStream |
588 #endif | 502 #endif |
589 TEST_F(VideoRendererBaseTest, MAYBE_GetCurrentFrame_EndOfStream) { | 503 TEST_F(VideoRendererBaseTest, MAYBE_GetCurrentFrame_EndOfStream) { |
590 Initialize(); | 504 Initialize(); |
591 Play(); | 505 Play(); |
592 Pause(); | 506 Pause(); |
593 Flush(); | 507 Flush(); |
594 | 508 |
595 // Preroll only end of stream frames. | 509 // Preroll only end of stream frames. |
596 Preroll(kEndOfStream); | 510 QueueEndOfStream(); |
597 ExpectCurrentFrame(false); | 511 Preroll(0, PIPELINE_OK); |
| 512 EXPECT_FALSE(GetCurrentFrame()); |
598 | 513 |
599 // Start playing, we should immediately get notified of end of stream. | 514 // Start playing, we should immediately get notified of end of stream. |
600 EXPECT_CALL(*this, OnEnded()) | |
601 .WillOnce(Invoke(event(), &base::WaitableEvent::Signal)); | |
602 Play(); | 515 Play(); |
603 CHECK(event()->TimedWait(timeout())) << "Timed out waiting for ended signal."; | 516 WaitForEnded(); |
604 | 517 |
605 Shutdown(); | 518 Shutdown(); |
606 } | 519 } |
607 | 520 |
608 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Shutdown) { | 521 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Shutdown) { |
609 Initialize(); | 522 Initialize(); |
610 Shutdown(); | 523 Shutdown(); |
611 ExpectCurrentFrame(false); | 524 EXPECT_FALSE(GetCurrentFrame()); |
612 } | 525 } |
613 | 526 |
614 // Stop() is called immediately during an error. | 527 // Stop() is called immediately during an error. |
615 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Error) { | 528 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Error) { |
616 Initialize(); | 529 Initialize(); |
617 Stop(); | 530 Stop(); |
618 ExpectCurrentFrame(false); | 531 EXPECT_FALSE(GetCurrentFrame()); |
619 } | 532 } |
620 | 533 |
621 // Verify that shutdown can only proceed after we return the current frame. | 534 // Verify that shutdown can only proceed after we return the current frame. |
622 TEST_F(VideoRendererBaseTest, Shutdown_DuringPaint) { | 535 TEST_F(VideoRendererBaseTest, Shutdown_DuringPaint) { |
623 Initialize(); | 536 Initialize(); |
624 Play(); | 537 Play(); |
625 | 538 |
626 // Grab the frame. | 539 // Grab the frame. |
627 scoped_refptr<VideoFrame> frame; | 540 scoped_refptr<VideoFrame> frame; |
628 renderer_->GetCurrentFrame(&frame); | 541 renderer_->GetCurrentFrame(&frame); |
629 EXPECT_TRUE(frame); | 542 EXPECT_TRUE(frame); |
630 | 543 |
631 Pause(); | 544 Pause(); |
632 | 545 |
633 // Start flushing -- it won't complete until we return the frame. | 546 // Start flushing -- it won't complete until we return the frame. |
634 renderer_->Flush(NewWaitableClosure()); | 547 WaitableMessageLoopEvent event; |
| 548 renderer_->Flush(event.GetClosure()); |
635 | 549 |
636 // Return the frame and wait. | 550 // Return the frame and wait. |
637 renderer_->PutCurrentFrame(frame); | 551 renderer_->PutCurrentFrame(frame); |
638 WaitForClosure(); | 552 event.RunAndWait(); |
639 | 553 |
640 Stop(); | 554 Stop(); |
641 } | 555 } |
642 | 556 |
643 // Verify that a late decoder response doesn't break invariants in the renderer. | 557 // Verify that a late decoder response doesn't break invariants in the renderer. |
644 TEST_F(VideoRendererBaseTest, StopDuringOutstandingRead) { | 558 TEST_F(VideoRendererBaseTest, StopDuringOutstandingRead) { |
645 Initialize(); | 559 Initialize(); |
646 Pause(); | 560 Play(); |
647 Flush(); | 561 |
648 QueueReadCB(); | 562 // Advance time a bit to trigger a Read(). |
649 StartPrerolling(kFrameDuration * 6, PIPELINE_OK); // Force-decode some more. | 563 AdvanceTimeInMs(kFrameDurationInMs); |
650 renderer_->Stop(NewWaitableClosure()); | 564 WaitForPendingRead(); |
651 SatisfyQueuedReadCB(); | 565 |
652 WaitForClosure(); // Finish the Stop(). | 566 WaitableMessageLoopEvent event; |
| 567 renderer_->Stop(event.GetClosure()); |
| 568 |
| 569 QueueEndOfStream(); |
| 570 SatisfyPendingRead(); |
| 571 |
| 572 event.RunAndWait(); |
653 } | 573 } |
654 | 574 |
655 TEST_F(VideoRendererBaseTest, AbortPendingRead_Playing) { | 575 TEST_F(VideoRendererBaseTest, AbortPendingRead_Playing) { |
656 Initialize(); | 576 Initialize(); |
657 Play(); | 577 Play(); |
658 | 578 |
659 // Render a frame to trigger a Read(). | 579 // Advance time a bit to trigger a Read(). |
660 RenderFrame(kFrameDuration); | 580 AdvanceTimeInMs(kFrameDurationInMs); |
| 581 WaitForPendingRead(); |
661 | 582 |
662 AbortRead(); | 583 QueueAbortedRead(); |
| 584 SatisfyPendingRead(); |
663 | 585 |
664 Pause(); | 586 Pause(); |
665 Flush(); | 587 Flush(); |
666 Preroll(kFrameDuration * 6); | 588 QueuePrerollFrames(kFrameDurationInMs * 6); |
667 ExpectCurrentTimestamp(kFrameDuration * 6); | 589 Preroll(kFrameDurationInMs * 6, PIPELINE_OK); |
| 590 EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); |
668 Shutdown(); | 591 Shutdown(); |
669 } | 592 } |
670 | 593 |
671 TEST_F(VideoRendererBaseTest, AbortPendingRead_Flush) { | 594 TEST_F(VideoRendererBaseTest, AbortPendingRead_Flush) { |
672 Initialize(); | 595 Initialize(); |
673 Play(); | 596 Play(); |
674 | 597 |
675 // Render a frame to trigger a Read(). | 598 // Advance time a bit to trigger a Read(). |
676 RenderFrame(kFrameDuration); | 599 AdvanceTimeInMs(kFrameDurationInMs); |
| 600 WaitForPendingRead(); |
677 | 601 |
678 Pause(); | 602 Pause(); |
679 Flush(); | 603 Flush(); |
680 Shutdown(); | 604 Shutdown(); |
681 } | 605 } |
682 | 606 |
683 TEST_F(VideoRendererBaseTest, AbortPendingRead_Preroll) { | 607 TEST_F(VideoRendererBaseTest, AbortPendingRead_Preroll) { |
684 Initialize(); | 608 Initialize(); |
685 Pause(); | 609 Pause(); |
686 Flush(); | 610 Flush(); |
687 StartPrerolling(kFrameDuration * 6, PIPELINE_OK); | 611 |
688 AbortRead(); | 612 QueueAbortedRead(); |
689 VerifyNotPrerolling(); | 613 Preroll(kFrameDurationInMs * 6, PIPELINE_OK); |
690 Shutdown(); | 614 Shutdown(); |
691 } | 615 } |
692 | 616 |
693 TEST_F(VideoRendererBaseTest, VideoDecoder_InitFailure) { | 617 TEST_F(VideoRendererBaseTest, VideoDecoder_InitFailure) { |
694 InSequence s; | 618 InSequence s; |
695 | 619 |
696 EXPECT_CALL(*decoder_, Initialize(_, _, _)) | 620 EXPECT_CALL(*decoder_, Initialize(_, _, _)) |
697 .WillOnce(RunCallback<1>(PIPELINE_ERROR_DECODE)); | 621 .WillOnce(RunCallback<1>(PIPELINE_ERROR_DECODE)); |
698 InitializeRenderer(PIPELINE_ERROR_DECODE); | 622 InitializeRenderer(PIPELINE_ERROR_DECODE); |
| 623 |
| 624 Stop(); |
699 } | 625 } |
700 | 626 |
701 } // namespace media | 627 } // namespace media |
OLD | NEW |