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 "media/filters/video_renderer_base.h" | 5 #include "media/filters/video_renderer_base.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
11 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
12 #include "media/base/buffers.h" | 12 #include "media/base/buffers.h" |
13 #include "media/base/limits.h" | 13 #include "media/base/limits.h" |
14 #include "media/base/pipeline.h" | 14 #include "media/base/pipeline.h" |
15 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
16 #include "media/filters/decrypting_demuxer_stream.h" | 16 #include "media/filters/decrypting_demuxer_stream.h" |
17 #include "media/filters/video_decoder_selector.h" | |
18 | 17 |
19 namespace media { | 18 namespace media { |
20 | 19 |
21 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { | 20 base::TimeDelta VideoRendererBase::kMaxLastFrameDuration() { |
22 return base::TimeDelta::FromMilliseconds(250); | 21 return base::TimeDelta::FromMilliseconds(250); |
23 } | 22 } |
24 | 23 |
25 VideoRendererBase::VideoRendererBase( | 24 VideoRendererBase::VideoRendererBase( |
26 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 25 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
27 const SetDecryptorReadyCB& set_decryptor_ready_cb, | 26 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
28 const PaintCB& paint_cb, | 27 const PaintCB& paint_cb, |
29 const SetOpaqueCB& set_opaque_cb, | 28 const SetOpaqueCB& set_opaque_cb, |
30 bool drop_frames) | 29 bool drop_frames) |
31 : message_loop_(message_loop), | 30 : message_loop_(message_loop), |
32 weak_factory_(this), | 31 weak_factory_(this), |
33 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 32 video_frame_stream_(message_loop, set_decryptor_ready_cb), |
34 received_end_of_stream_(false), | 33 received_end_of_stream_(false), |
35 frame_available_(&lock_), | 34 frame_available_(&lock_), |
36 state_(kUninitialized), | 35 state_(kUninitialized), |
37 thread_(base::kNullThreadHandle), | 36 thread_(base::kNullThreadHandle), |
38 pending_read_(false), | 37 pending_read_(false), |
39 drop_frames_(drop_frames), | 38 drop_frames_(drop_frames), |
40 playback_rate_(0), | 39 playback_rate_(0), |
41 paint_cb_(paint_cb), | 40 paint_cb_(paint_cb), |
42 set_opaque_cb_(set_opaque_cb), | 41 set_opaque_cb_(set_opaque_cb), |
43 last_timestamp_(kNoTimestamp()) { | 42 last_timestamp_(kNoTimestamp()) { |
(...skipping 22 matching lines...) Expand all Loading... |
66 callback.Run(); | 65 callback.Run(); |
67 } | 66 } |
68 | 67 |
69 void VideoRendererBase::Flush(const base::Closure& callback) { | 68 void VideoRendererBase::Flush(const base::Closure& callback) { |
70 DCHECK(message_loop_->BelongsToCurrentThread()); | 69 DCHECK(message_loop_->BelongsToCurrentThread()); |
71 base::AutoLock auto_lock(lock_); | 70 base::AutoLock auto_lock(lock_); |
72 DCHECK_EQ(state_, kPaused); | 71 DCHECK_EQ(state_, kPaused); |
73 flush_cb_ = callback; | 72 flush_cb_ = callback; |
74 state_ = kFlushingDecoder; | 73 state_ = kFlushingDecoder; |
75 | 74 |
76 if (decrypting_demuxer_stream_) { | 75 video_frame_stream_.Reset(base::Bind( |
77 decrypting_demuxer_stream_->Reset(base::Bind( | 76 &VideoRendererBase::OnVideoFrameStreamResetDone, weak_this_)); |
78 &VideoRendererBase::ResetDecoder, weak_this_)); | |
79 return; | |
80 } | |
81 | |
82 decoder_->Reset(base::Bind( | |
83 &VideoRendererBase::OnDecoderResetDone, weak_this_)); | |
84 } | |
85 | |
86 void VideoRendererBase::ResetDecoder() { | |
87 DCHECK(message_loop_->BelongsToCurrentThread()); | |
88 base::AutoLock auto_lock(lock_); | |
89 decoder_->Reset(base::Bind( | |
90 &VideoRendererBase::OnDecoderResetDone, weak_this_)); | |
91 } | 77 } |
92 | 78 |
93 void VideoRendererBase::Stop(const base::Closure& callback) { | 79 void VideoRendererBase::Stop(const base::Closure& callback) { |
94 DCHECK(message_loop_->BelongsToCurrentThread()); | 80 DCHECK(message_loop_->BelongsToCurrentThread()); |
95 base::AutoLock auto_lock(lock_); | 81 base::AutoLock auto_lock(lock_); |
96 if (state_ == kUninitialized || state_ == kStopped) { | 82 if (state_ == kUninitialized || state_ == kStopped) { |
97 callback.Run(); | 83 callback.Run(); |
98 return; | 84 return; |
99 } | 85 } |
100 | 86 |
(...skipping 13 matching lines...) Expand all Loading... |
114 // thread waiting for a read to complete. | 100 // thread waiting for a read to complete. |
115 frame_available_.Signal(); | 101 frame_available_.Signal(); |
116 std::swap(thread_, thread_to_join); | 102 std::swap(thread_, thread_to_join); |
117 } | 103 } |
118 | 104 |
119 if (thread_to_join != base::kNullThreadHandle) { | 105 if (thread_to_join != base::kNullThreadHandle) { |
120 base::AutoUnlock auto_unlock(lock_); | 106 base::AutoUnlock auto_unlock(lock_); |
121 base::PlatformThread::Join(thread_to_join); | 107 base::PlatformThread::Join(thread_to_join); |
122 } | 108 } |
123 | 109 |
124 if (decrypting_demuxer_stream_) { | 110 video_frame_stream_.Stop(callback); |
125 decrypting_demuxer_stream_->Reset(base::Bind( | |
126 &VideoRendererBase::StopDecoder, weak_this_, callback)); | |
127 return; | |
128 } | |
129 | |
130 if (decoder_) { | |
131 decoder_->Stop(callback); | |
132 return; | |
133 } | |
134 | |
135 callback.Run(); | |
136 } | |
137 | |
138 void VideoRendererBase::StopDecoder(const base::Closure& callback) { | |
139 DCHECK(message_loop_->BelongsToCurrentThread()); | |
140 base::AutoLock auto_lock(lock_); | |
141 decoder_->Stop(callback); | |
142 } | 111 } |
143 | 112 |
144 void VideoRendererBase::SetPlaybackRate(float playback_rate) { | 113 void VideoRendererBase::SetPlaybackRate(float playback_rate) { |
145 DCHECK(message_loop_->BelongsToCurrentThread()); | 114 DCHECK(message_loop_->BelongsToCurrentThread()); |
146 base::AutoLock auto_lock(lock_); | 115 base::AutoLock auto_lock(lock_); |
147 playback_rate_ = playback_rate; | 116 playback_rate_ = playback_rate; |
148 } | 117 } |
149 | 118 |
150 void VideoRendererBase::Preroll(base::TimeDelta time, | 119 void VideoRendererBase::Preroll(base::TimeDelta time, |
151 const PipelineStatusCB& cb) { | 120 const PipelineStatusCB& cb) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 init_cb_ = init_cb; | 158 init_cb_ = init_cb; |
190 statistics_cb_ = statistics_cb; | 159 statistics_cb_ = statistics_cb; |
191 max_time_cb_ = max_time_cb; | 160 max_time_cb_ = max_time_cb; |
192 size_changed_cb_ = size_changed_cb; | 161 size_changed_cb_ = size_changed_cb; |
193 ended_cb_ = ended_cb; | 162 ended_cb_ = ended_cb; |
194 error_cb_ = error_cb; | 163 error_cb_ = error_cb; |
195 get_time_cb_ = get_time_cb; | 164 get_time_cb_ = get_time_cb; |
196 get_duration_cb_ = get_duration_cb; | 165 get_duration_cb_ = get_duration_cb; |
197 state_ = kInitializing; | 166 state_ = kInitializing; |
198 | 167 |
199 scoped_ptr<VideoDecoderSelector> decoder_selector( | 168 video_frame_stream_.Initialize( |
200 new VideoDecoderSelector(base::MessageLoopProxy::current(), | |
201 decoders, | |
202 set_decryptor_ready_cb_)); | |
203 | |
204 // To avoid calling |decoder_selector| methods and passing ownership of | |
205 // |decoder_selector| in the same line. | |
206 VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get(); | |
207 | |
208 decoder_selector_ptr->SelectVideoDecoder( | |
209 stream, | 169 stream, |
| 170 decoders, |
210 statistics_cb, | 171 statistics_cb, |
211 base::Bind(&VideoRendererBase::OnDecoderSelected, weak_this_, | 172 base::Bind(&VideoRendererBase::OnVideoFrameStreamInitialized, |
212 base::Passed(&decoder_selector))); | 173 weak_this_)); |
213 } | 174 } |
214 | 175 |
215 void VideoRendererBase::OnDecoderSelected( | 176 void VideoRendererBase::OnVideoFrameStreamInitialized(bool success, |
216 scoped_ptr<VideoDecoderSelector> decoder_selector, | 177 bool has_alpha) { |
217 const scoped_refptr<VideoDecoder>& selected_decoder, | |
218 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { | |
219 DCHECK(message_loop_->BelongsToCurrentThread()); | 178 DCHECK(message_loop_->BelongsToCurrentThread()); |
220 base::AutoLock auto_lock(lock_); | 179 base::AutoLock auto_lock(lock_); |
221 | 180 |
222 if (state_ == kStopped) | 181 if (state_ == kStopped) |
223 return; | 182 return; |
224 | 183 |
225 DCHECK_EQ(state_, kInitializing); | 184 DCHECK_EQ(state_, kInitializing); |
226 | 185 |
227 if (!selected_decoder) { | 186 if (!success) { |
228 state_ = kUninitialized; | 187 state_ = kUninitialized; |
229 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 188 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
230 return; | 189 return; |
231 } | 190 } |
232 | 191 |
233 decoder_ = selected_decoder; | |
234 decrypting_demuxer_stream_ = decrypting_demuxer_stream; | |
235 | |
236 // We're all good! Consider ourselves flushed. (ThreadMain() should never | 192 // We're all good! Consider ourselves flushed. (ThreadMain() should never |
237 // see us in the kUninitialized state). | 193 // see us in the kUninitialized state). |
238 // Since we had an initial Preroll(), we consider ourself flushed, because we | 194 // Since we had an initial Preroll(), we consider ourself flushed, because we |
239 // have not populated any buffers yet. | 195 // have not populated any buffers yet. |
240 state_ = kFlushed; | 196 state_ = kFlushed; |
241 | 197 |
242 set_opaque_cb_.Run(!decoder_->HasAlpha()); | 198 set_opaque_cb_.Run(!has_alpha); |
243 set_opaque_cb_.Reset(); | 199 set_opaque_cb_.Reset(); |
244 | 200 |
245 // Create our video thread. | 201 // Create our video thread. |
246 if (!base::PlatformThread::Create(0, this, &thread_)) { | 202 if (!base::PlatformThread::Create(0, this, &thread_)) { |
247 NOTREACHED() << "Video thread creation failed"; | 203 NOTREACHED() << "Video thread creation failed"; |
248 state_ = kError; | 204 state_ = kError; |
249 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 205 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
250 return; | 206 return; |
251 } | 207 } |
252 | 208 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 | 386 |
431 // Maintain the latest frame decoded so the correct frame is displayed after | 387 // Maintain the latest frame decoded so the correct frame is displayed after |
432 // prerolling has completed. | 388 // prerolling has completed. |
433 if (state_ == kPrerolling && frame->GetTimestamp() <= preroll_timestamp_) { | 389 if (state_ == kPrerolling && frame->GetTimestamp() <= preroll_timestamp_) { |
434 ready_frames_.clear(); | 390 ready_frames_.clear(); |
435 } | 391 } |
436 | 392 |
437 AddReadyFrame_Locked(frame); | 393 AddReadyFrame_Locked(frame); |
438 | 394 |
439 if (state_ == kPrerolling) { | 395 if (state_ == kPrerolling) { |
440 if (!decoder_->HasOutputFrameAvailable() || | 396 if (!video_frame_stream_.HasOutputFrameAvailable() || |
441 ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames)) { | 397 ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames)) { |
442 TransitionToPrerolled_Locked(); | 398 TransitionToPrerolled_Locked(); |
443 } | 399 } |
444 } else { | 400 } else { |
445 // We only count frames decoded during normal playback. | 401 // We only count frames decoded during normal playback. |
446 PipelineStatistics statistics; | 402 PipelineStatistics statistics; |
447 statistics.video_frames_decoded = 1; | 403 statistics.video_frames_decoded = 1; |
448 statistics_cb_.Run(statistics); | 404 statistics_cb_.Run(statistics); |
449 } | 405 } |
450 | 406 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { | 450 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { |
495 return; | 451 return; |
496 } | 452 } |
497 | 453 |
498 switch (state_) { | 454 switch (state_) { |
499 case kPaused: | 455 case kPaused: |
500 case kFlushing: | 456 case kFlushing: |
501 case kPrerolling: | 457 case kPrerolling: |
502 case kPlaying: | 458 case kPlaying: |
503 pending_read_ = true; | 459 pending_read_ = true; |
504 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, weak_this_)); | 460 video_frame_stream_.ReadFrame(base::Bind(&VideoRendererBase::FrameReady, |
| 461 weak_this_)); |
505 return; | 462 return; |
506 | 463 |
507 case kUninitialized: | 464 case kUninitialized: |
508 case kInitializing: | 465 case kInitializing: |
509 case kPrerolled: | 466 case kPrerolled: |
510 case kFlushingDecoder: | 467 case kFlushingDecoder: |
511 case kFlushed: | 468 case kFlushed: |
512 case kEnded: | 469 case kEnded: |
513 case kStopped: | 470 case kStopped: |
514 case kError: | 471 case kError: |
515 return; | 472 return; |
516 } | 473 } |
517 } | 474 } |
518 | 475 |
519 void VideoRendererBase::OnDecoderResetDone() { | 476 void VideoRendererBase::OnVideoFrameStreamResetDone() { |
520 base::AutoLock auto_lock(lock_); | 477 base::AutoLock auto_lock(lock_); |
521 if (state_ == kStopped) | 478 if (state_ == kStopped) |
522 return; | 479 return; |
523 | 480 |
524 DCHECK_EQ(kFlushingDecoder, state_); | 481 DCHECK_EQ(kFlushingDecoder, state_); |
525 DCHECK(!pending_read_); | 482 DCHECK(!pending_read_); |
526 | 483 |
527 state_ = kFlushing; | 484 state_ = kFlushing; |
528 AttemptFlush_Locked(); | 485 AttemptFlush_Locked(); |
529 } | 486 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 // Because we might remain in the prerolled state for an undetermined amount | 528 // Because we might remain in the prerolled state for an undetermined amount |
572 // of time (e.g., we seeked while paused), we'll paint the first prerolled | 529 // of time (e.g., we seeked while paused), we'll paint the first prerolled |
573 // frame. | 530 // frame. |
574 if (!ready_frames_.empty()) | 531 if (!ready_frames_.empty()) |
575 PaintNextReadyFrame_Locked(); | 532 PaintNextReadyFrame_Locked(); |
576 | 533 |
577 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); | 534 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); |
578 } | 535 } |
579 | 536 |
580 } // namespace media | 537 } // namespace media |
OLD | NEW |