 Chromium Code Reviews
 Chromium Code Reviews Issue 12324005:
  Fix crash in VideoRendererBase::ThreadMain().  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@git-svn
    
  
    Issue 12324005:
  Fix crash in VideoRendererBase::ThreadMain().  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@git-svn| 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" | 
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 drop_frames_(drop_frames), | 38 drop_frames_(drop_frames), | 
| 39 playback_rate_(0), | 39 playback_rate_(0), | 
| 40 paint_cb_(paint_cb), | 40 paint_cb_(paint_cb), | 
| 41 set_opaque_cb_(set_opaque_cb), | 41 set_opaque_cb_(set_opaque_cb), | 
| 42 last_timestamp_(kNoTimestamp()) { | 42 last_timestamp_(kNoTimestamp()) { | 
| 43 DCHECK(!paint_cb_.is_null()); | 43 DCHECK(!paint_cb_.is_null()); | 
| 44 } | 44 } | 
| 45 | 45 | 
| 46 VideoRendererBase::~VideoRendererBase() { | 46 VideoRendererBase::~VideoRendererBase() { | 
| 47 base::AutoLock auto_lock(lock_); | 47 base::AutoLock auto_lock(lock_); | 
| 48 CHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 48 CHECK(state_ == kStopped || state_ == kUninitialized) << state_; | 
| 49 CHECK_EQ(thread_, base::kNullThreadHandle); | 49 CHECK_EQ(thread_, base::kNullThreadHandle); | 
| 50 } | 50 } | 
| 51 | 51 | 
| 52 void VideoRendererBase::Play(const base::Closure& callback) { | 52 void VideoRendererBase::Play(const base::Closure& callback) { | 
| 53 DCHECK(message_loop_->BelongsToCurrentThread()); | 53 DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 54 base::AutoLock auto_lock(lock_); | 54 base::AutoLock auto_lock(lock_); | 
| 55 DCHECK_EQ(kPrerolled, state_); | 55 DCHECK_EQ(kPrerolled, state_); | 
| 56 state_ = kPlaying; | 56 state_ = kPlaying; | 
| 57 callback.Run(); | 57 callback.Run(); | 
| 58 } | 58 } | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 85 void VideoRendererBase::ResetDecoder() { | 85 void VideoRendererBase::ResetDecoder() { | 
| 86 DCHECK(message_loop_->BelongsToCurrentThread()); | 86 DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 87 base::AutoLock auto_lock(lock_); | 87 base::AutoLock auto_lock(lock_); | 
| 88 decoder_->Reset(base::Bind( | 88 decoder_->Reset(base::Bind( | 
| 89 &VideoRendererBase::OnDecoderResetDone, weak_this_)); | 89 &VideoRendererBase::OnDecoderResetDone, weak_this_)); | 
| 90 } | 90 } | 
| 91 | 91 | 
| 92 void VideoRendererBase::Stop(const base::Closure& callback) { | 92 void VideoRendererBase::Stop(const base::Closure& callback) { | 
| 93 DCHECK(message_loop_->BelongsToCurrentThread()); | 93 DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 94 base::AutoLock auto_lock(lock_); | 94 base::AutoLock auto_lock(lock_); | 
| 95 if (state_ == kUninitialized || state_ == kStopped) { | 95 if (state_ == kStopped) { | 
| 
acolwell GONE FROM CHROMIUM
2013/02/21 21:07:16
Do we still want to fall through if called in kUni
 
scherkus (not reviewing)
2013/02/22 01:45:49
GAH I forgot to fix this
 | |
| 96 callback.Run(); | 96 callback.Run(); | 
| 97 return; | 97 return; | 
| 98 } | 98 } | 
| 99 | 99 | 
| 100 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | 100 // TODO(scherkus): Consider invalidating |weak_factory_| and replacing | 
| 101 // task-running guards that check |state_| with DCHECK(). | 101 // task-running guards that check |state_| with DCHECK(). | 
| 102 | 102 | 
| 103 state_ = kStopped; | 103 state_ = kStopped; | 
| 104 | 104 | 
| 105 statistics_cb_.Reset(); | 105 statistics_cb_.Reset(); | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 119 base::AutoUnlock auto_unlock(lock_); | 119 base::AutoUnlock auto_unlock(lock_); | 
| 120 base::PlatformThread::Join(thread_to_join); | 120 base::PlatformThread::Join(thread_to_join); | 
| 121 } | 121 } | 
| 122 | 122 | 
| 123 if (decrypting_demuxer_stream_) { | 123 if (decrypting_demuxer_stream_) { | 
| 124 decrypting_demuxer_stream_->Reset(base::Bind( | 124 decrypting_demuxer_stream_->Reset(base::Bind( | 
| 125 &VideoRendererBase::StopDecoder, weak_this_, callback)); | 125 &VideoRendererBase::StopDecoder, weak_this_, callback)); | 
| 126 return; | 126 return; | 
| 127 } | 127 } | 
| 128 | 128 | 
| 129 decoder_->Stop(callback); | 129 if (decoder_) { | 
| 130 decoder_->Stop(callback); | |
| 131 return; | |
| 132 } | |
| 133 | |
| 134 callback.Run(); | |
| 130 } | 135 } | 
| 131 | 136 | 
| 132 void VideoRendererBase::StopDecoder(const base::Closure& callback) { | 137 void VideoRendererBase::StopDecoder(const base::Closure& callback) { | 
| 133 DCHECK(message_loop_->BelongsToCurrentThread()); | 138 DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 134 base::AutoLock auto_lock(lock_); | 139 base::AutoLock auto_lock(lock_); | 
| 135 decoder_->Stop(callback); | 140 decoder_->Stop(callback); | 
| 136 } | 141 } | 
| 137 | 142 | 
| 138 void VideoRendererBase::SetPlaybackRate(float playback_rate) { | 143 void VideoRendererBase::SetPlaybackRate(float playback_rate) { | 
| 139 DCHECK(message_loop_->BelongsToCurrentThread()); | 144 DCHECK(message_loop_->BelongsToCurrentThread()); | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 182 | 187 | 
| 183 weak_this_ = weak_factory_.GetWeakPtr(); | 188 weak_this_ = weak_factory_.GetWeakPtr(); | 
| 184 init_cb_ = init_cb; | 189 init_cb_ = init_cb; | 
| 185 statistics_cb_ = statistics_cb; | 190 statistics_cb_ = statistics_cb; | 
| 186 max_time_cb_ = max_time_cb; | 191 max_time_cb_ = max_time_cb; | 
| 187 size_changed_cb_ = size_changed_cb; | 192 size_changed_cb_ = size_changed_cb; | 
| 188 ended_cb_ = ended_cb; | 193 ended_cb_ = ended_cb; | 
| 189 error_cb_ = error_cb; | 194 error_cb_ = error_cb; | 
| 190 get_time_cb_ = get_time_cb; | 195 get_time_cb_ = get_time_cb; | 
| 191 get_duration_cb_ = get_duration_cb; | 196 get_duration_cb_ = get_duration_cb; | 
| 197 state_ = kInitializing; | |
| 192 | 198 | 
| 193 scoped_ptr<VideoDecoderSelector> decoder_selector( | 199 scoped_ptr<VideoDecoderSelector> decoder_selector( | 
| 194 new VideoDecoderSelector(base::MessageLoopProxy::current(), | 200 new VideoDecoderSelector(base::MessageLoopProxy::current(), | 
| 195 decoders, | 201 decoders, | 
| 196 set_decryptor_ready_cb_)); | 202 set_decryptor_ready_cb_)); | 
| 197 | 203 | 
| 198 // To avoid calling |decoder_selector| methods and passing ownership of | 204 // To avoid calling |decoder_selector| methods and passing ownership of | 
| 199 // |decoder_selector| in the same line. | 205 // |decoder_selector| in the same line. | 
| 200 VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get(); | 206 VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get(); | 
| 201 | 207 | 
| 202 decoder_selector_ptr->SelectVideoDecoder( | 208 decoder_selector_ptr->SelectVideoDecoder( | 
| 203 stream, | 209 stream, | 
| 204 statistics_cb, | 210 statistics_cb, | 
| 205 base::Bind(&VideoRendererBase::OnDecoderSelected, weak_this_, | 211 base::Bind(&VideoRendererBase::OnDecoderSelected, weak_this_, | 
| 206 base::Passed(&decoder_selector))); | 212 base::Passed(&decoder_selector))); | 
| 207 } | 213 } | 
| 208 | 214 | 
| 209 void VideoRendererBase::OnDecoderSelected( | 215 void VideoRendererBase::OnDecoderSelected( | 
| 210 scoped_ptr<VideoDecoderSelector> decoder_selector, | 216 scoped_ptr<VideoDecoderSelector> decoder_selector, | 
| 211 const scoped_refptr<VideoDecoder>& selected_decoder, | 217 const scoped_refptr<VideoDecoder>& selected_decoder, | 
| 212 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { | 218 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) { | 
| 213 DCHECK(message_loop_->BelongsToCurrentThread()); | 219 DCHECK(message_loop_->BelongsToCurrentThread()); | 
| 214 base::AutoLock auto_lock(lock_); | 220 base::AutoLock auto_lock(lock_); | 
| 215 | 221 | 
| 216 if (state_ == kStopped) | 222 if (state_ == kStopped) | 
| 217 return; | 223 return; | 
| 218 | 224 | 
| 225 DCHECK_EQ(state_, kInitializing); | |
| 226 | |
| 219 if (!selected_decoder) { | 227 if (!selected_decoder) { | 
| 220 state_ = kUninitialized; | 228 state_ = kUninitialized; | 
| 221 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 229 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 
| 222 return; | 230 return; | 
| 223 } | 231 } | 
| 224 | 232 | 
| 225 decoder_ = selected_decoder; | 233 decoder_ = selected_decoder; | 
| 226 decrypting_demuxer_stream_ = decrypting_demuxer_stream; | 234 decrypting_demuxer_stream_ = decrypting_demuxer_stream; | 
| 227 | 235 | 
| 228 // We're all good! Consider ourselves flushed. (ThreadMain() should never | 236 // We're all good! Consider ourselves flushed. (ThreadMain() should never | 
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 switch (state_) { | 516 switch (state_) { | 
| 509 case kPaused: | 517 case kPaused: | 
| 510 case kFlushing: | 518 case kFlushing: | 
| 511 case kPrerolling: | 519 case kPrerolling: | 
| 512 case kPlaying: | 520 case kPlaying: | 
| 513 pending_read_ = true; | 521 pending_read_ = true; | 
| 514 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, weak_this_)); | 522 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, weak_this_)); | 
| 515 return; | 523 return; | 
| 516 | 524 | 
| 517 case kUninitialized: | 525 case kUninitialized: | 
| 526 case kInitializing: | |
| 518 case kPrerolled: | 527 case kPrerolled: | 
| 519 case kFlushingDecoder: | 528 case kFlushingDecoder: | 
| 520 case kFlushed: | 529 case kFlushed: | 
| 521 case kEnded: | 530 case kEnded: | 
| 522 case kStopped: | 531 case kStopped: | 
| 523 case kError: | 532 case kError: | 
| 524 return; | 533 return; | 
| 525 } | 534 } | 
| 526 } | 535 } | 
| 527 | 536 | 
| 528 void VideoRendererBase::OnDecoderResetDone() { | 537 void VideoRendererBase::OnDecoderResetDone() { | 
| 529 base::AutoLock auto_lock(lock_); | 538 base::AutoLock auto_lock(lock_); | 
| 539 if (state_ == kStopped) | |
| 540 return; | |
| 541 | |
| 530 DCHECK_EQ(kFlushingDecoder, state_); | 542 DCHECK_EQ(kFlushingDecoder, state_); | 
| 531 DCHECK(!pending_read_); | 543 DCHECK(!pending_read_); | 
| 532 | 544 | 
| 533 state_ = kFlushing; | 545 state_ = kFlushing; | 
| 534 AttemptFlush_Locked(); | 546 AttemptFlush_Locked(); | 
| 535 } | 547 } | 
| 536 | 548 | 
| 537 void VideoRendererBase::AttemptFlush_Locked() { | 549 void VideoRendererBase::AttemptFlush_Locked() { | 
| 538 lock_.AssertAcquired(); | 550 lock_.AssertAcquired(); | 
| 539 DCHECK_EQ(kFlushing, state_); | 551 DCHECK_EQ(kFlushing, state_); | 
| (...skipping 27 matching lines...) Expand all Loading... | |
| 567 last_timestamp_ = kNoTimestamp(); | 579 last_timestamp_ = kNoTimestamp(); | 
| 568 ready_frames_.clear(); | 580 ready_frames_.clear(); | 
| 569 } | 581 } | 
| 570 | 582 | 
| 571 int VideoRendererBase::NumFrames_Locked() const { | 583 int VideoRendererBase::NumFrames_Locked() const { | 
| 572 lock_.AssertAcquired(); | 584 lock_.AssertAcquired(); | 
| 573 return ready_frames_.size(); | 585 return ready_frames_.size(); | 
| 574 } | 586 } | 
| 575 | 587 | 
| 576 } // namespace media | 588 } // namespace media | 
| OLD | NEW |