Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_impl.h" | 5 #include "media/filters/video_renderer_impl.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/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 received_end_of_stream_(false), | 32 received_end_of_stream_(false), |
| 33 rendered_end_of_stream_(false), | 33 rendered_end_of_stream_(false), |
| 34 frame_available_(&lock_), | 34 frame_available_(&lock_), |
| 35 state_(kUninitialized), | 35 state_(kUninitialized), |
| 36 thread_(), | 36 thread_(), |
| 37 pending_read_(false), | 37 pending_read_(false), |
| 38 drop_frames_(drop_frames), | 38 drop_frames_(drop_frames), |
| 39 buffering_state_(BUFFERING_HAVE_NOTHING), | 39 buffering_state_(BUFFERING_HAVE_NOTHING), |
| 40 paint_cb_(paint_cb), | 40 paint_cb_(paint_cb), |
| 41 last_timestamp_(kNoTimestamp()), | 41 last_timestamp_(kNoTimestamp()), |
| 42 last_painted_timestamp_(kNoTimestamp()), | |
| 42 frames_decoded_(0), | 43 frames_decoded_(0), |
| 43 frames_dropped_(0), | 44 frames_dropped_(0), |
| 44 is_shutting_down_(false), | 45 is_shutting_down_(false), |
| 45 weak_factory_(this) { | 46 weak_factory_(this) { |
| 46 DCHECK(!paint_cb_.is_null()); | 47 DCHECK(!paint_cb_.is_null()); |
| 47 } | 48 } |
| 48 | 49 |
| 49 VideoRendererImpl::~VideoRendererImpl() { | 50 VideoRendererImpl::~VideoRendererImpl() { |
| 50 DCHECK(task_runner_->BelongsToCurrentThread()); | 51 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 51 | 52 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 | 178 |
| 178 // The number of milliseconds to idle when we do not have anything to do. | 179 // The number of milliseconds to idle when we do not have anything to do. |
| 179 // Nothing special about the value, other than we're being more OS-friendly | 180 // Nothing special about the value, other than we're being more OS-friendly |
| 180 // than sleeping for 1 millisecond. | 181 // than sleeping for 1 millisecond. |
| 181 // | 182 // |
| 182 // TODO(scherkus): switch to pure event-driven frame timing instead of this | 183 // TODO(scherkus): switch to pure event-driven frame timing instead of this |
| 183 // kIdleTimeDelta business http://crbug.com/106874 | 184 // kIdleTimeDelta business http://crbug.com/106874 |
| 184 const base::TimeDelta kIdleTimeDelta = | 185 const base::TimeDelta kIdleTimeDelta = |
| 185 base::TimeDelta::FromMilliseconds(10); | 186 base::TimeDelta::FromMilliseconds(10); |
| 186 | 187 |
| 188 // If we have no frames and haven't painted any frame for certain amount of | |
| 189 // time, declare BUFFERING_HAVE_NOTHING. | |
| 190 const base::TimeDelta kTimeToDeclareHaveNothing = | |
| 191 base::TimeDelta::FromSeconds(3); | |
| 192 | |
| 187 for (;;) { | 193 for (;;) { |
| 188 base::AutoLock auto_lock(lock_); | 194 base::AutoLock auto_lock(lock_); |
| 189 | 195 |
| 190 // Thread exit condition. | 196 // Thread exit condition. |
| 191 if (is_shutting_down_) | 197 if (is_shutting_down_) |
| 192 return; | 198 return; |
| 193 | 199 |
| 194 // Remain idle as long as we're not playing. | 200 // Remain idle as long as we're not playing. |
| 195 if (state_ != kPlaying || buffering_state_ != BUFFERING_HAVE_ENOUGH) { | 201 if (state_ != kPlaying || buffering_state_ != BUFFERING_HAVE_ENOUGH) { |
| 196 UpdateStatsAndWait_Locked(kIdleTimeDelta); | 202 UpdateStatsAndWait_Locked(kIdleTimeDelta); |
| 197 continue; | 203 continue; |
| 198 } | 204 } |
| 199 | 205 |
| 206 base::TimeDelta now = get_time_cb_.Run(); | |
|
scherkus (not reviewing)
2014/08/22 01:40:59
did we mean to use *media* time instead of wall cl
| |
| 207 | |
| 200 // Remain idle until we have the next frame ready for rendering. | 208 // Remain idle until we have the next frame ready for rendering. |
| 201 if (ready_frames_.empty()) { | 209 if (ready_frames_.empty()) { |
| 202 if (received_end_of_stream_) { | 210 if (received_end_of_stream_) { |
| 203 if (!rendered_end_of_stream_) { | 211 if (!rendered_end_of_stream_) { |
| 204 rendered_end_of_stream_ = true; | 212 rendered_end_of_stream_ = true; |
| 205 task_runner_->PostTask(FROM_HERE, ended_cb_); | 213 task_runner_->PostTask(FROM_HERE, ended_cb_); |
| 206 } | 214 } |
| 207 } else { | 215 } else if (last_painted_timestamp_ != kNoTimestamp() && |
| 216 now - last_painted_timestamp_ >= kTimeToDeclareHaveNothing) { | |
| 208 buffering_state_ = BUFFERING_HAVE_NOTHING; | 217 buffering_state_ = BUFFERING_HAVE_NOTHING; |
| 209 task_runner_->PostTask( | 218 task_runner_->PostTask( |
| 210 FROM_HERE, base::Bind(buffering_state_cb_, BUFFERING_HAVE_NOTHING)); | 219 FROM_HERE, base::Bind(buffering_state_cb_, BUFFERING_HAVE_NOTHING)); |
| 211 } | 220 } |
| 212 | 221 |
| 213 UpdateStatsAndWait_Locked(kIdleTimeDelta); | 222 UpdateStatsAndWait_Locked(kIdleTimeDelta); |
| 214 continue; | 223 continue; |
| 215 } | 224 } |
| 216 | 225 |
| 217 base::TimeDelta now = get_time_cb_.Run(); | |
| 218 base::TimeDelta target_paint_timestamp = ready_frames_.front()->timestamp(); | 226 base::TimeDelta target_paint_timestamp = ready_frames_.front()->timestamp(); |
| 219 base::TimeDelta latest_paint_timestamp; | 227 base::TimeDelta latest_paint_timestamp; |
| 220 | 228 |
| 221 // Deadline is defined as the duration between this frame and the next | 229 // Deadline is defined as the duration between this frame and the next |
| 222 // frame, using the delta between this frame and the previous frame as the | 230 // frame, using the delta between this frame and the previous frame as the |
| 223 // assumption for frame duration. | 231 // assumption for frame duration. |
| 224 // | 232 // |
| 225 // TODO(scherkus): This can be vastly improved. Use a histogram to measure | 233 // TODO(scherkus): This can be vastly improved. Use a histogram to measure |
| 226 // the accuracy of our frame timing code. http://crbug.com/149829 | 234 // the accuracy of our frame timing code. http://crbug.com/149829 |
| 227 if (last_timestamp_ == kNoTimestamp()) { | 235 if (last_timestamp_ == kNoTimestamp()) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 251 } | 259 } |
| 252 | 260 |
| 253 void VideoRendererImpl::PaintNextReadyFrame_Locked() { | 261 void VideoRendererImpl::PaintNextReadyFrame_Locked() { |
| 254 lock_.AssertAcquired(); | 262 lock_.AssertAcquired(); |
| 255 | 263 |
| 256 scoped_refptr<VideoFrame> next_frame = ready_frames_.front(); | 264 scoped_refptr<VideoFrame> next_frame = ready_frames_.front(); |
| 257 ready_frames_.pop_front(); | 265 ready_frames_.pop_front(); |
| 258 frames_decoded_++; | 266 frames_decoded_++; |
| 259 | 267 |
| 260 last_timestamp_ = next_frame->timestamp(); | 268 last_timestamp_ = next_frame->timestamp(); |
| 269 last_painted_timestamp_ = next_frame->timestamp(); | |
| 261 | 270 |
| 262 paint_cb_.Run(next_frame); | 271 paint_cb_.Run(next_frame); |
| 263 | 272 |
| 264 task_runner_->PostTask( | 273 task_runner_->PostTask( |
| 265 FROM_HERE, | 274 FROM_HERE, |
| 266 base::Bind(&VideoRendererImpl::AttemptRead, weak_factory_.GetWeakPtr())); | 275 base::Bind(&VideoRendererImpl::AttemptRead, weak_factory_.GetWeakPtr())); |
| 267 } | 276 } |
| 268 | 277 |
| 269 void VideoRendererImpl::DropNextReadyFrame_Locked() { | 278 void VideoRendererImpl::DropNextReadyFrame_Locked() { |
| 270 TRACE_EVENT0("media", "VideoRendererImpl:frameDropped"); | 279 TRACE_EVENT0("media", "VideoRendererImpl:frameDropped"); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 base::AutoLock auto_lock(lock_); | 445 base::AutoLock auto_lock(lock_); |
| 437 DCHECK_EQ(kFlushing, state_); | 446 DCHECK_EQ(kFlushing, state_); |
| 438 DCHECK(!pending_read_); | 447 DCHECK(!pending_read_); |
| 439 DCHECK(ready_frames_.empty()); | 448 DCHECK(ready_frames_.empty()); |
| 440 DCHECK(!received_end_of_stream_); | 449 DCHECK(!received_end_of_stream_); |
| 441 DCHECK(!rendered_end_of_stream_); | 450 DCHECK(!rendered_end_of_stream_); |
| 442 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); | 451 DCHECK_EQ(buffering_state_, BUFFERING_HAVE_NOTHING); |
| 443 | 452 |
| 444 state_ = kFlushed; | 453 state_ = kFlushed; |
| 445 last_timestamp_ = kNoTimestamp(); | 454 last_timestamp_ = kNoTimestamp(); |
| 455 last_painted_timestamp_ = kNoTimestamp(); | |
| 446 base::ResetAndReturn(&flush_cb_).Run(); | 456 base::ResetAndReturn(&flush_cb_).Run(); |
| 447 } | 457 } |
| 448 | 458 |
| 449 void VideoRendererImpl::UpdateStatsAndWait_Locked( | 459 void VideoRendererImpl::UpdateStatsAndWait_Locked( |
| 450 base::TimeDelta wait_duration) { | 460 base::TimeDelta wait_duration) { |
| 451 lock_.AssertAcquired(); | 461 lock_.AssertAcquired(); |
| 452 DCHECK_GE(frames_decoded_, 0); | 462 DCHECK_GE(frames_decoded_, 0); |
| 453 DCHECK_LE(frames_dropped_, frames_decoded_); | 463 DCHECK_LE(frames_dropped_, frames_decoded_); |
| 454 | 464 |
| 455 if (frames_decoded_) { | 465 if (frames_decoded_) { |
| 456 PipelineStatistics statistics; | 466 PipelineStatistics statistics; |
| 457 statistics.video_frames_decoded = frames_decoded_; | 467 statistics.video_frames_decoded = frames_decoded_; |
| 458 statistics.video_frames_dropped = frames_dropped_; | 468 statistics.video_frames_dropped = frames_dropped_; |
| 459 task_runner_->PostTask(FROM_HERE, base::Bind(statistics_cb_, statistics)); | 469 task_runner_->PostTask(FROM_HERE, base::Bind(statistics_cb_, statistics)); |
| 460 | 470 |
| 461 frames_decoded_ = 0; | 471 frames_decoded_ = 0; |
| 462 frames_dropped_ = 0; | 472 frames_dropped_ = 0; |
| 463 } | 473 } |
| 464 | 474 |
| 465 frame_available_.TimedWait(wait_duration); | 475 frame_available_.TimedWait(wait_duration); |
| 466 } | 476 } |
| 467 | 477 |
| 468 } // namespace media | 478 } // namespace media |
| OLD | NEW |