| 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 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 VideoRendererBase::VideoRendererBase( | 24 VideoRendererBase::VideoRendererBase( |
| 25 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 25 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| 26 ScopedVector<VideoDecoder> decoders, | 26 ScopedVector<VideoDecoder> decoders, |
| 27 const SetDecryptorReadyCB& set_decryptor_ready_cb, | 27 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
| 28 const PaintCB& paint_cb, | 28 const PaintCB& paint_cb, |
| 29 const SetOpaqueCB& set_opaque_cb, | 29 const SetOpaqueCB& set_opaque_cb, |
| 30 bool drop_frames) | 30 bool drop_frames) |
| 31 : message_loop_(message_loop), | 31 : message_loop_(message_loop), |
| 32 weak_factory_(this), | 32 weak_factory_(this), |
| 33 video_frame_stream_(new VideoFrameStream( | 33 video_frame_stream_( |
| 34 message_loop, decoders.Pass(), set_decryptor_ready_cb)), | 34 message_loop, decoders.Pass(), set_decryptor_ready_cb), |
| 35 received_end_of_stream_(false), | 35 received_end_of_stream_(false), |
| 36 frame_available_(&lock_), | 36 frame_available_(&lock_), |
| 37 state_(kUninitialized), | 37 state_(kUninitialized), |
| 38 thread_(base::kNullThreadHandle), | 38 thread_(base::kNullThreadHandle), |
| 39 pending_read_(false), | 39 pending_read_(false), |
| 40 drop_frames_(drop_frames), | 40 drop_frames_(drop_frames), |
| 41 playback_rate_(0), | 41 playback_rate_(0), |
| 42 paint_cb_(paint_cb), | 42 paint_cb_(paint_cb), |
| 43 set_opaque_cb_(set_opaque_cb), | 43 set_opaque_cb_(set_opaque_cb), |
| 44 last_timestamp_(kNoTimestamp()) { | 44 last_timestamp_(kNoTimestamp()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 71 DCHECK(message_loop_->BelongsToCurrentThread()); | 71 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 72 base::AutoLock auto_lock(lock_); | 72 base::AutoLock auto_lock(lock_); |
| 73 DCHECK_EQ(state_, kPaused); | 73 DCHECK_EQ(state_, kPaused); |
| 74 flush_cb_ = callback; | 74 flush_cb_ = callback; |
| 75 state_ = kFlushingDecoder; | 75 state_ = kFlushingDecoder; |
| 76 | 76 |
| 77 // This is necessary if the decoder has already seen an end of stream and | 77 // This is necessary if the decoder has already seen an end of stream and |
| 78 // needs to drain it before flushing it. | 78 // needs to drain it before flushing it. |
| 79 ready_frames_.clear(); | 79 ready_frames_.clear(); |
| 80 received_end_of_stream_ = false; | 80 received_end_of_stream_ = false; |
| 81 video_frame_stream_->Reset(base::Bind( | 81 video_frame_stream_.Reset(base::Bind( |
| 82 &VideoRendererBase::OnVideoFrameStreamResetDone, weak_this_)); | 82 &VideoRendererBase::OnVideoFrameStreamResetDone, weak_this_)); |
| 83 } | 83 } |
| 84 | 84 |
| 85 void VideoRendererBase::Stop(const base::Closure& callback) { | 85 void VideoRendererBase::Stop(const base::Closure& callback) { |
| 86 DCHECK(message_loop_->BelongsToCurrentThread()); | 86 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 87 base::AutoLock auto_lock(lock_); | 87 base::AutoLock auto_lock(lock_); |
| 88 if (state_ == kUninitialized || state_ == kStopped) { | 88 if (state_ == kUninitialized || state_ == kStopped) { |
| 89 callback.Run(); | 89 callback.Run(); |
| 90 return; | 90 return; |
| 91 } | 91 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 106 // thread waiting for a read to complete. | 106 // thread waiting for a read to complete. |
| 107 frame_available_.Signal(); | 107 frame_available_.Signal(); |
| 108 std::swap(thread_, thread_to_join); | 108 std::swap(thread_, thread_to_join); |
| 109 } | 109 } |
| 110 | 110 |
| 111 if (thread_to_join != base::kNullThreadHandle) { | 111 if (thread_to_join != base::kNullThreadHandle) { |
| 112 base::AutoUnlock auto_unlock(lock_); | 112 base::AutoUnlock auto_unlock(lock_); |
| 113 base::PlatformThread::Join(thread_to_join); | 113 base::PlatformThread::Join(thread_to_join); |
| 114 } | 114 } |
| 115 | 115 |
| 116 video_frame_stream_->Stop(callback); | 116 video_frame_stream_.Stop(callback); |
| 117 } | 117 } |
| 118 | 118 |
| 119 void VideoRendererBase::SetPlaybackRate(float playback_rate) { | 119 void VideoRendererBase::SetPlaybackRate(float playback_rate) { |
| 120 DCHECK(message_loop_->BelongsToCurrentThread()); | 120 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 121 base::AutoLock auto_lock(lock_); | 121 base::AutoLock auto_lock(lock_); |
| 122 playback_rate_ = playback_rate; | 122 playback_rate_ = playback_rate; |
| 123 } | 123 } |
| 124 | 124 |
| 125 void VideoRendererBase::Preroll(base::TimeDelta time, | 125 void VideoRendererBase::Preroll(base::TimeDelta time, |
| 126 const PipelineStatusCB& cb) { | 126 const PipelineStatusCB& cb) { |
| 127 DCHECK(message_loop_->BelongsToCurrentThread()); | 127 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 128 base::AutoLock auto_lock(lock_); | 128 base::AutoLock auto_lock(lock_); |
| 129 DCHECK_EQ(state_, kFlushed) << "Must flush prior to prerolling."; | 129 DCHECK_EQ(state_, kFlushed) << "Must flush prior to prerolling."; |
| 130 DCHECK(!cb.is_null()); | 130 DCHECK(!cb.is_null()); |
| 131 DCHECK(preroll_cb_.is_null()); | 131 DCHECK(preroll_cb_.is_null()); |
| 132 | 132 |
| 133 state_ = kPrerolling; | 133 state_ = kPrerolling; |
| 134 preroll_cb_ = cb; | 134 preroll_cb_ = cb; |
| 135 preroll_timestamp_ = time; | 135 preroll_timestamp_ = time; |
| 136 AttemptRead_Locked(); | 136 AttemptRead_Locked(); |
| 137 } | 137 } |
| 138 | 138 |
| 139 void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream, | 139 void VideoRendererBase::Initialize(DemuxerStream* stream, |
| 140 const PipelineStatusCB& init_cb, | 140 const PipelineStatusCB& init_cb, |
| 141 const StatisticsCB& statistics_cb, | 141 const StatisticsCB& statistics_cb, |
| 142 const TimeCB& max_time_cb, | 142 const TimeCB& max_time_cb, |
| 143 const NaturalSizeChangedCB& size_changed_cb, | 143 const NaturalSizeChangedCB& size_changed_cb, |
| 144 const base::Closure& ended_cb, | 144 const base::Closure& ended_cb, |
| 145 const PipelineStatusCB& error_cb, | 145 const PipelineStatusCB& error_cb, |
| 146 const TimeDeltaCB& get_time_cb, | 146 const TimeDeltaCB& get_time_cb, |
| 147 const TimeDeltaCB& get_duration_cb) { | 147 const TimeDeltaCB& get_duration_cb) { |
| 148 DCHECK(message_loop_->BelongsToCurrentThread()); | 148 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 149 base::AutoLock auto_lock(lock_); | 149 base::AutoLock auto_lock(lock_); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 162 init_cb_ = init_cb; | 162 init_cb_ = init_cb; |
| 163 statistics_cb_ = statistics_cb; | 163 statistics_cb_ = statistics_cb; |
| 164 max_time_cb_ = max_time_cb; | 164 max_time_cb_ = max_time_cb; |
| 165 size_changed_cb_ = size_changed_cb; | 165 size_changed_cb_ = size_changed_cb; |
| 166 ended_cb_ = ended_cb; | 166 ended_cb_ = ended_cb; |
| 167 error_cb_ = error_cb; | 167 error_cb_ = error_cb; |
| 168 get_time_cb_ = get_time_cb; | 168 get_time_cb_ = get_time_cb; |
| 169 get_duration_cb_ = get_duration_cb; | 169 get_duration_cb_ = get_duration_cb; |
| 170 state_ = kInitializing; | 170 state_ = kInitializing; |
| 171 | 171 |
| 172 video_frame_stream_->Initialize( | 172 video_frame_stream_.Initialize( |
| 173 stream, | 173 stream, |
| 174 statistics_cb, | 174 statistics_cb, |
| 175 base::Bind(&VideoRendererBase::OnVideoFrameStreamInitialized, | 175 base::Bind(&VideoRendererBase::OnVideoFrameStreamInitialized, |
| 176 weak_this_)); | 176 weak_this_)); |
| 177 } | 177 } |
| 178 | 178 |
| 179 void VideoRendererBase::OnVideoFrameStreamInitialized(bool success, | 179 void VideoRendererBase::OnVideoFrameStreamInitialized(bool success, |
| 180 bool has_alpha) { | 180 bool has_alpha) { |
| 181 DCHECK(message_loop_->BelongsToCurrentThread()); | 181 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 182 base::AutoLock auto_lock(lock_); | 182 base::AutoLock auto_lock(lock_); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 | 389 |
| 390 // Maintain the latest frame decoded so the correct frame is displayed after | 390 // Maintain the latest frame decoded so the correct frame is displayed after |
| 391 // prerolling has completed. | 391 // prerolling has completed. |
| 392 if (state_ == kPrerolling && frame->GetTimestamp() <= preroll_timestamp_) { | 392 if (state_ == kPrerolling && frame->GetTimestamp() <= preroll_timestamp_) { |
| 393 ready_frames_.clear(); | 393 ready_frames_.clear(); |
| 394 } | 394 } |
| 395 | 395 |
| 396 AddReadyFrame_Locked(frame); | 396 AddReadyFrame_Locked(frame); |
| 397 | 397 |
| 398 if (state_ == kPrerolling) { | 398 if (state_ == kPrerolling) { |
| 399 if (!video_frame_stream_->HasOutputFrameAvailable() || | 399 if (!video_frame_stream_.HasOutputFrameAvailable() || |
| 400 ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames)) { | 400 ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames)) { |
| 401 TransitionToPrerolled_Locked(); | 401 TransitionToPrerolled_Locked(); |
| 402 } | 402 } |
| 403 } else { | 403 } else { |
| 404 // We only count frames decoded during normal playback. | 404 // We only count frames decoded during normal playback. |
| 405 PipelineStatistics statistics; | 405 PipelineStatistics statistics; |
| 406 statistics.video_frames_decoded = 1; | 406 statistics.video_frames_decoded = 1; |
| 407 statistics_cb_.Run(statistics); | 407 statistics_cb_.Run(statistics); |
| 408 } | 408 } |
| 409 | 409 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { | 453 ready_frames_.size() == static_cast<size_t>(limits::kMaxVideoFrames)) { |
| 454 return; | 454 return; |
| 455 } | 455 } |
| 456 | 456 |
| 457 switch (state_) { | 457 switch (state_) { |
| 458 case kPaused: | 458 case kPaused: |
| 459 case kFlushing: | 459 case kFlushing: |
| 460 case kPrerolling: | 460 case kPrerolling: |
| 461 case kPlaying: | 461 case kPlaying: |
| 462 pending_read_ = true; | 462 pending_read_ = true; |
| 463 video_frame_stream_->ReadFrame(base::Bind(&VideoRendererBase::FrameReady, | 463 video_frame_stream_.ReadFrame(base::Bind(&VideoRendererBase::FrameReady, |
| 464 weak_this_)); | 464 weak_this_)); |
| 465 return; | 465 return; |
| 466 | 466 |
| 467 case kUninitialized: | 467 case kUninitialized: |
| 468 case kInitializing: | 468 case kInitializing: |
| 469 case kPrerolled: | 469 case kPrerolled: |
| 470 case kFlushingDecoder: | 470 case kFlushingDecoder: |
| 471 case kFlushed: | 471 case kFlushed: |
| 472 case kEnded: | 472 case kEnded: |
| 473 case kStopped: | 473 case kStopped: |
| 474 case kError: | 474 case kError: |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 // Because we might remain in the prerolled state for an undetermined amount | 530 // Because we might remain in the prerolled state for an undetermined amount |
| 531 // of time (e.g., we seeked while paused), we'll paint the first prerolled | 531 // of time (e.g., we seeked while paused), we'll paint the first prerolled |
| 532 // frame. | 532 // frame. |
| 533 if (!ready_frames_.empty()) | 533 if (!ready_frames_.empty()) |
| 534 PaintNextReadyFrame_Locked(); | 534 PaintNextReadyFrame_Locked(); |
| 535 | 535 |
| 536 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); | 536 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); |
| 537 } | 537 } |
| 538 | 538 |
| 539 } // namespace media | 539 } // namespace media |
| OLD | NEW |