Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(567)

Side by Side Diff: media/filters/video_renderer_base_unittest.cc

Issue 11316293: Replace WaitableEvents and ConditionalVariables in VideoRendererBase tests with MessageLoop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix bustage Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/file_data_source_unittest.cc ('k') | media/media.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
OLDNEW
« no previous file with comments | « media/filters/file_data_source_unittest.cc ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698