| 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { | 466 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { |
| 511 return; | 467 return; |
| 512 } | 468 } |
| 513 | 469 |
| 514 switch (state_) { | 470 switch (state_) { |
| 515 case kPaused: | 471 case kPaused: |
| 516 case kFlushing: | 472 case kFlushing: |
| 517 case kPrerolling: | 473 case kPrerolling: |
| 518 case kPlaying: | 474 case kPlaying: |
| 519 pending_read_ = true; | 475 pending_read_ = true; |
| 520 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, weak_this_)); | 476 video_frame_stream_.ReadFrame(base::Bind(&VideoRendererBase::FrameReady, |
| 477 weak_this_)); |
| 521 return; | 478 return; |
| 522 | 479 |
| 523 case kUninitialized: | 480 case kUninitialized: |
| 524 case kInitializing: | 481 case kInitializing: |
| 525 case kPrerolled: | 482 case kPrerolled: |
| 526 case kFlushingDecoder: | 483 case kFlushingDecoder: |
| 527 case kFlushed: | 484 case kFlushed: |
| 528 case kEnded: | 485 case kEnded: |
| 529 case kStopped: | 486 case kStopped: |
| 530 case kError: | 487 case kError: |
| 531 return; | 488 return; |
| 532 } | 489 } |
| 533 } | 490 } |
| 534 | 491 |
| 535 void VideoRendererBase::OnDecoderResetDone() { | 492 void VideoRendererBase::OnVideoFrameStreamResetDone() { |
| 536 base::AutoLock auto_lock(lock_); | 493 base::AutoLock auto_lock(lock_); |
| 537 if (state_ == kStopped) | 494 if (state_ == kStopped) |
| 538 return; | 495 return; |
| 539 | 496 |
| 540 DCHECK_EQ(kFlushingDecoder, state_); | 497 DCHECK_EQ(kFlushingDecoder, state_); |
| 541 DCHECK(!pending_read_); | 498 DCHECK(!pending_read_); |
| 542 | 499 |
| 543 state_ = kFlushing; | 500 state_ = kFlushing; |
| 544 AttemptFlush_Locked(); | 501 AttemptFlush_Locked(); |
| 545 } | 502 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 572 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); | 529 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); |
| 573 } | 530 } |
| 574 | 531 |
| 575 void VideoRendererBase::DoStopOrError_Locked() { | 532 void VideoRendererBase::DoStopOrError_Locked() { |
| 576 lock_.AssertAcquired(); | 533 lock_.AssertAcquired(); |
| 577 last_timestamp_ = kNoTimestamp(); | 534 last_timestamp_ = kNoTimestamp(); |
| 578 ready_frames_.clear(); | 535 ready_frames_.clear(); |
| 579 } | 536 } |
| 580 | 537 |
| 581 } // namespace media | 538 } // namespace media |
| OLD | NEW |