Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/threading/platform_thread.h" | 7 #include "base/threading/platform_thread.h" |
| 8 #include "media/base/buffers.h" | 8 #include "media/base/buffers.h" |
| 9 #include "media/base/callback.h" | 9 #include "media/base/callback.h" |
| 10 #include "media/base/filter_host.h" | 10 #include "media/base/filter_host.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 } | 51 } |
| 52 | 52 |
| 53 void VideoRendererBase::Pause(FilterCallback* callback) { | 53 void VideoRendererBase::Pause(FilterCallback* callback) { |
| 54 base::AutoLock auto_lock(lock_); | 54 base::AutoLock auto_lock(lock_); |
| 55 DCHECK(state_ != kUninitialized || state_ == kError); | 55 DCHECK(state_ != kUninitialized || state_ == kError); |
| 56 AutoCallbackRunner done_runner(callback); | 56 AutoCallbackRunner done_runner(callback); |
| 57 state_ = kPaused; | 57 state_ = kPaused; |
| 58 } | 58 } |
| 59 | 59 |
| 60 void VideoRendererBase::Flush(FilterCallback* callback) { | 60 void VideoRendererBase::Flush(FilterCallback* callback) { |
| 61 base::AutoLock auto_lock(lock_); | |
| 61 DCHECK_EQ(state_, kPaused); | 62 DCHECK_EQ(state_, kPaused); |
| 62 | |
| 63 base::AutoLock auto_lock(lock_); | |
| 64 flush_callback_.reset(callback); | 63 flush_callback_.reset(callback); |
| 65 state_ = kFlushing; | 64 state_ = kFlushing; |
| 66 | 65 |
| 67 if (pending_paint_ == false) | 66 if (!pending_paint_) |
| 68 FlushBuffers(); | 67 FlushBuffers_Locked(); |
| 69 } | 68 } |
| 70 | 69 |
| 71 void VideoRendererBase::Stop(FilterCallback* callback) { | 70 void VideoRendererBase::Stop(FilterCallback* callback) { |
| 72 base::PlatformThreadHandle old_thread_handle = base::kNullThreadHandle; | 71 base::PlatformThreadHandle old_thread_handle = base::kNullThreadHandle; |
| 73 { | 72 { |
| 74 base::AutoLock auto_lock(lock_); | 73 base::AutoLock auto_lock(lock_); |
| 75 state_ = kStopped; | 74 state_ = kStopped; |
| 76 | 75 |
| 77 if (!pending_paint_ && !pending_paint_with_last_available_) | 76 if (!pending_paint_ && !pending_paint_with_last_available_) |
| 78 DoStopOrErrorFlush_Locked(); | 77 DoStopOrErrorFlush_Locked(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 101 void VideoRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 100 void VideoRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 102 bool run_callback = false; | 101 bool run_callback = false; |
| 103 | 102 |
| 104 { | 103 { |
| 105 base::AutoLock auto_lock(lock_); | 104 base::AutoLock auto_lock(lock_); |
| 106 // There is a race condition between filters to receive SeekTask(). | 105 // There is a race condition between filters to receive SeekTask(). |
| 107 // It turns out we could receive buffer from decoder before seek() | 106 // It turns out we could receive buffer from decoder before seek() |
| 108 // is called on us. so we do the following: | 107 // is called on us. so we do the following: |
| 109 // kFlushed => ( Receive first buffer or Seek() ) => kSeeking and | 108 // kFlushed => ( Receive first buffer or Seek() ) => kSeeking and |
| 110 // kSeeking => ( Receive enough buffers) => kPrerolled. ) | 109 // kSeeking => ( Receive enough buffers) => kPrerolled. ) |
| 111 DCHECK(kPrerolled == state_ || kFlushed == state_ || kSeeking == state_); | 110 DCHECK(state_ == kPrerolled || state_ == kFlushed || state_ == kSeeking); |
| 112 DCHECK(!cb.is_null()); | 111 DCHECK(!cb.is_null()); |
| 113 DCHECK(seek_cb_.is_null()); | 112 DCHECK(seek_cb_.is_null()); |
| 114 | 113 |
| 115 if (state_ == kPrerolled) { | 114 if (state_ == kPrerolled) { |
| 116 // Already get enough buffers from decoder. | 115 // Already get enough buffers from decoder. |
| 117 run_callback = true; | 116 run_callback = true; |
| 118 | 117 |
| 119 } else { | 118 } else { |
| 120 // Otherwise we are either kFlushed or kSeeking, but without enough | 119 // Otherwise we are either kFlushed or kSeeking, but without enough |
| 121 // buffers we should save the callback function and call it later. | 120 // buffers we should save the callback function and call it later. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 254 continue; | 253 continue; |
| 255 | 254 |
| 256 scoped_refptr<VideoFrame> next_frame = frames_queue_ready_.front(); | 255 scoped_refptr<VideoFrame> next_frame = frames_queue_ready_.front(); |
| 257 if (next_frame->IsEndOfStream()) { | 256 if (next_frame->IsEndOfStream()) { |
| 258 state_ = kEnded; | 257 state_ = kEnded; |
| 259 DVLOG(1) << "Video render gets EOS"; | 258 DVLOG(1) << "Video render gets EOS"; |
| 260 host()->NotifyEnded(); | 259 host()->NotifyEnded(); |
| 261 continue; | 260 continue; |
| 262 } | 261 } |
| 263 | 262 |
| 264 if (next_frame->GetTimestamp() <= host()->GetTime() + kIdleTimeDelta || | 263 // Normally we're ready to loop again at this point, but there are |
| 265 current_frame_.get() == NULL || | 264 // exceptions that cause us to drop a frame and/or consider painting a |
| 266 current_frame_->GetTimestamp() > host()->GetDuration()) { | 265 // "next" frame. |
| 267 // 1. either next frame's time-stamp is already current. | 266 if (next_frame->GetTimestamp() > host()->GetTime() + kIdleTimeDelta && |
| 268 // 2. or we do not have any current frame yet anyway. | 267 current_frame_ && |
| 269 // 3. or a special case when the stream is badly formatted that | 268 current_frame_->GetTimestamp() <= host()->GetDuration()) { |
| 270 // we get video frame with time-stamp greater than the duration. | 269 continue; |
|
scherkus (not reviewing)
2011/08/24 20:46:37
I love continues
| |
| 271 // In this case we should proceed anyway and try to obtain the | 270 } |
| 272 // end-of-stream packet. | 271 |
| 273 scoped_refptr<VideoFrame> timeout_frame; | 272 // If we got here then: |
|
scherkus (not reviewing)
2011/08/24 20:46:37
nit: I'd put the "either" here and nix the "or"s i
| |
| 274 bool new_frame_available = false; | 273 // 1. either next frame's time-stamp is already current. |
|
scherkus (not reviewing)
2011/08/24 20:46:37
nit: s/time-stamp/timestamp/g
| |
| 275 if (!pending_paint_) { | 274 // 2. or we do not have any current frame yet anyway. |
| 276 // In this case, current frame could be recycled. | 275 // 3. or a special case when the stream is badly formatted that |
| 277 timeout_frame = current_frame_; | 276 // we get video frame with time-stamp greater than the duration. |
| 278 current_frame_ = frames_queue_ready_.front(); | 277 // In this case we should proceed anyway and try to obtain the |
| 278 // end-of-stream packet. | |
| 279 scoped_refptr<VideoFrame> timeout_frame; | |
| 280 bool new_frame_available = false; | |
| 281 if (!pending_paint_) { | |
| 282 // In this case, current frame could be recycled. | |
| 283 timeout_frame = current_frame_; | |
| 284 current_frame_ = frames_queue_ready_.front(); | |
| 285 frames_queue_ready_.pop_front(); | |
| 286 new_frame_available = true; | |
| 287 } else if (pending_paint_ && frames_queue_ready_.size() >= 2 && | |
| 288 !frames_queue_ready_[1]->IsEndOfStream()) { | |
| 289 // Painter could be really slow, therefore we had to skip frames if | |
| 290 // 1. We had not reached end of stream. | |
| 291 // 2. The next frame of current frame is also out-dated. | |
| 292 base::TimeDelta next_remaining_time = | |
| 293 frames_queue_ready_[1]->GetTimestamp() - host()->GetTime(); | |
| 294 if (next_remaining_time.InMicroseconds() <= 0) { | |
| 295 // Since the current frame is still hold by painter/compositor, and | |
| 296 // the next frame is already timed-out, we should skip the next frame | |
| 297 // which is the first frame in the queue. | |
| 298 timeout_frame = frames_queue_ready_.front(); | |
| 279 frames_queue_ready_.pop_front(); | 299 frames_queue_ready_.pop_front(); |
| 280 new_frame_available = true; | 300 ++frames_dropped; |
| 281 } else if (pending_paint_ && frames_queue_ready_.size() >= 2 && | |
| 282 !frames_queue_ready_[1]->IsEndOfStream()) { | |
| 283 // Painter could be really slow, therefore we had to skip frames if | |
| 284 // 1. We had not reached end of stream. | |
| 285 // 2. The next frame of current frame is also out-dated. | |
| 286 base::TimeDelta next_remaining_time = | |
| 287 frames_queue_ready_[1]->GetTimestamp() - host()->GetTime(); | |
| 288 if (next_remaining_time.InMicroseconds() <= 0) { | |
| 289 // Since the current frame is still hold by painter/compositor, and | |
| 290 // the next frame is already timed-out, we should skip the next frame | |
| 291 // which is the first frame in the queue. | |
| 292 timeout_frame = frames_queue_ready_.front(); | |
| 293 frames_queue_ready_.pop_front(); | |
| 294 ++frames_dropped; | |
| 295 } | |
| 296 } | 301 } |
| 297 if (timeout_frame.get()) { | 302 } |
| 298 frames_queue_done_.push_back(timeout_frame); | 303 if (timeout_frame.get()) { |
| 299 ScheduleRead_Locked(); | 304 frames_queue_done_.push_back(timeout_frame); |
| 300 } | 305 ScheduleRead_Locked(); |
| 301 if (new_frame_available) { | 306 } |
| 302 base::AutoUnlock auto_unlock(lock_); | 307 if (new_frame_available) { |
| 303 OnFrameAvailable(); | 308 base::AutoUnlock auto_unlock(lock_); |
| 304 } | 309 OnFrameAvailable(); |
| 305 } | 310 } |
| 306 } | 311 } |
| 307 } | 312 } |
| 308 | 313 |
| 309 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { | 314 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { |
| 310 base::AutoLock auto_lock(lock_); | 315 base::AutoLock auto_lock(lock_); |
| 311 DCHECK(!pending_paint_ && !pending_paint_with_last_available_); | 316 DCHECK(!pending_paint_ && !pending_paint_with_last_available_); |
| 312 | 317 |
| 313 if ((!current_frame_.get() || current_frame_->IsEndOfStream()) && | 318 if ((!current_frame_.get() || current_frame_->IsEndOfStream()) && |
| 314 (!last_available_frame_.get() || | 319 (!last_available_frame_.get() || |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 335 base::AutoLock auto_lock(lock_); | 340 base::AutoLock auto_lock(lock_); |
| 336 | 341 |
| 337 // Note that we do not claim |pending_paint_| when we return NULL frame, in | 342 // Note that we do not claim |pending_paint_| when we return NULL frame, in |
| 338 // that case, |current_frame_| could be changed before PutCurrentFrame. | 343 // that case, |current_frame_| could be changed before PutCurrentFrame. |
| 339 if (pending_paint_) { | 344 if (pending_paint_) { |
| 340 DCHECK(current_frame_.get() == frame.get()); | 345 DCHECK(current_frame_.get() == frame.get()); |
| 341 DCHECK(!pending_paint_with_last_available_); | 346 DCHECK(!pending_paint_with_last_available_); |
| 342 pending_paint_ = false; | 347 pending_paint_ = false; |
| 343 } else if (pending_paint_with_last_available_) { | 348 } else if (pending_paint_with_last_available_) { |
| 344 DCHECK(last_available_frame_.get() == frame.get()); | 349 DCHECK(last_available_frame_.get() == frame.get()); |
| 350 DCHECK(!pending_paint_); | |
| 345 pending_paint_with_last_available_ = false; | 351 pending_paint_with_last_available_ = false; |
| 346 } else { | 352 } else { |
| 347 DCHECK(frame.get() == NULL); | 353 DCHECK(frame.get() == NULL); |
| 348 } | 354 } |
| 349 | 355 |
| 350 // We had cleared the |pending_paint_| flag, there are chances that current | 356 // We had cleared the |pending_paint_| flag, there are chances that current |
| 351 // frame is timed-out. We will wake up our main thread to advance the current | 357 // frame is timed-out. We will wake up our main thread to advance the current |
| 352 // frame when this is true. | 358 // frame when this is true. |
| 353 frame_available_.Signal(); | 359 frame_available_.Signal(); |
| 354 if (state_ == kFlushing) { | 360 if (state_ == kFlushing) { |
| 355 FlushBuffers(); | 361 FlushBuffers_Locked(); |
| 356 } else if (state_ == kError || state_ == kStopped) { | 362 } else if (state_ == kError || state_ == kStopped) { |
| 357 DoStopOrErrorFlush_Locked(); | 363 DoStopOrErrorFlush_Locked(); |
| 358 } | 364 } |
| 359 } | 365 } |
| 360 | 366 |
| 361 void VideoRendererBase::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) { | 367 void VideoRendererBase::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) { |
| 362 if (frame) { | 368 if (frame) { |
| 363 PipelineStatistics statistics; | 369 PipelineStatistics statistics; |
| 364 statistics.video_frames_decoded = 1; | 370 statistics.video_frames_decoded = 1; |
| 365 statistics_callback_->Run(statistics); | 371 statistics_callback_->Run(statistics); |
| 366 } | 372 } |
| 367 | 373 |
| 368 base::AutoLock auto_lock(lock_); | 374 base::AutoLock auto_lock(lock_); |
| 369 | 375 |
| 370 if (!frame) { | 376 if (!frame) { |
| 371 EnterErrorState_Locked(PIPELINE_ERROR_DECODE); | 377 EnterErrorState_Locked(PIPELINE_ERROR_DECODE); |
| 372 return; | 378 return; |
| 373 } | 379 } |
| 374 | 380 |
| 375 // Decoder could reach seek state before our Seek() get called. | 381 // Decoder could reach seek state before our Seek() get called. |
| 376 // We will enter kSeeking | 382 // We will enter kSeeking |
| 377 if (kFlushed == state_) | 383 if (state_ == kFlushed) |
| 378 state_ = kSeeking; | 384 state_ = kSeeking; |
| 379 | 385 |
| 380 // Synchronous flush between filters should prevent this from happening. | 386 // Synchronous flush between filters should prevent this from happening. |
| 381 DCHECK_NE(state_, kStopped); | 387 DCHECK_NE(state_, kStopped); |
| 382 if (frame.get() && !frame->IsEndOfStream()) | 388 if (frame.get() && !frame->IsEndOfStream()) |
| 383 --pending_reads_; | 389 --pending_reads_; |
| 384 | 390 |
| 385 DCHECK(state_ != kUninitialized && state_ != kStopped && state_ != kError); | 391 DCHECK(state_ != kUninitialized && state_ != kStopped && state_ != kError); |
| 386 | 392 |
| 387 if (state_ == kPaused || state_ == kFlushing) { | 393 if (state_ == kPaused || state_ == kFlushing) { |
| 388 // Decoder are flushing rubbish video frame, we will not display them. | 394 // Decoder are flushing rubbish video frame, we will not display them. |
| 389 if (frame.get() && !frame->IsEndOfStream()) | 395 if (frame.get() && !frame->IsEndOfStream()) |
| 390 frames_queue_done_.push_back(frame); | 396 frames_queue_done_.push_back(frame); |
| 391 DCHECK_LE(frames_queue_done_.size(), | 397 DCHECK_LE(frames_queue_done_.size(), |
| 392 static_cast<size_t>(Limits::kMaxVideoFrames)); | 398 static_cast<size_t>(Limits::kMaxVideoFrames)); |
| 393 | 399 |
| 394 // Excluding kPause here, because in pause state, we will never | 400 // Excluding kPause here, because in pause state, we will never |
| 395 // transfer out-bounding buffer. We do not flush buffer when Compositor | 401 // transfer out-bounding buffer. We do not flush buffer when Compositor |
| 396 // hold reference to our video frame either. | 402 // hold reference to our video frame either. |
| 397 if (state_ == kFlushing && pending_paint_ == false) | 403 if (state_ == kFlushing && pending_paint_ == false) |
| 398 FlushBuffers(); | 404 FlushBuffers_Locked(); |
| 399 | 405 |
| 400 return; | 406 return; |
| 401 } | 407 } |
| 402 | 408 |
| 403 // Discard frames until we reach our desired seek timestamp. | 409 // Discard frames until we reach our desired seek timestamp. |
| 404 if (state_ == kSeeking && !frame->IsEndOfStream() && | 410 if (state_ == kSeeking && !frame->IsEndOfStream() && |
| 405 (frame->GetTimestamp() + frame->GetDuration()) <= seek_timestamp_) { | 411 (frame->GetTimestamp() + frame->GetDuration()) <= seek_timestamp_) { |
| 406 frames_queue_done_.push_back(frame); | 412 frames_queue_done_.push_back(frame); |
| 407 ScheduleRead_Locked(); | 413 ScheduleRead_Locked(); |
| 408 } else { | 414 } else { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 433 new_frame_available = true; | 439 new_frame_available = true; |
| 434 | 440 |
| 435 // If we reach prerolled state before Seek() is called by pipeline, | 441 // If we reach prerolled state before Seek() is called by pipeline, |
| 436 // |seek_callback_| is not set, we will return immediately during | 442 // |seek_callback_| is not set, we will return immediately during |
| 437 // when Seek() is eventually called. | 443 // when Seek() is eventually called. |
| 438 if (!seek_cb_.is_null()) { | 444 if (!seek_cb_.is_null()) { |
| 439 ResetAndRunCB(&seek_cb_, PIPELINE_OK); | 445 ResetAndRunCB(&seek_cb_, PIPELINE_OK); |
| 440 } | 446 } |
| 441 } | 447 } |
| 442 } else if (state_ == kFlushing && pending_reads_ == 0 && !pending_paint_) { | 448 } else if (state_ == kFlushing && pending_reads_ == 0 && !pending_paint_) { |
| 443 OnFlushDone(); | 449 OnFlushDone_Locked(); |
| 444 } | 450 } |
| 445 | 451 |
| 446 if (new_frame_available) { | 452 if (new_frame_available) { |
| 447 base::AutoUnlock auto_unlock(lock_); | 453 base::AutoUnlock auto_unlock(lock_); |
| 448 OnFrameAvailable(); | 454 OnFrameAvailable(); |
| 449 } | 455 } |
| 450 } | 456 } |
| 451 | 457 |
| 452 void VideoRendererBase::ReadInput(scoped_refptr<VideoFrame> frame) { | 458 void VideoRendererBase::ReadInput(scoped_refptr<VideoFrame> frame) { |
| 453 // We should never return empty frames or EOS frame. | 459 // We should never return empty frames or EOS frame. |
| 454 DCHECK(frame.get() && !frame->IsEndOfStream()); | 460 DCHECK(frame.get() && !frame->IsEndOfStream()); |
| 455 | 461 |
| 456 decoder_->ProduceVideoFrame(frame); | 462 decoder_->ProduceVideoFrame(frame); |
| 457 ++pending_reads_; | 463 ++pending_reads_; |
| 458 } | 464 } |
| 459 | 465 |
| 460 void VideoRendererBase::ScheduleRead_Locked() { | 466 void VideoRendererBase::ScheduleRead_Locked() { |
| 461 lock_.AssertAcquired(); | 467 lock_.AssertAcquired(); |
| 462 DCHECK_NE(kEnded, state_); | 468 DCHECK_NE(kEnded, state_); |
| 463 // TODO(jiesun): We use dummy buffer to feed decoder to let decoder to | 469 // TODO(jiesun): We use dummy buffer to feed decoder to let decoder to |
| 464 // provide buffer pools. In the future, we may want to implement real | 470 // provide buffer pools. In the future, we may want to implement real |
| 465 // buffer pool to recycle buffers. | 471 // buffer pool to recycle buffers. |
| 466 while (!frames_queue_done_.empty()) { | 472 while (!frames_queue_done_.empty()) { |
| 467 scoped_refptr<VideoFrame> video_frame = frames_queue_done_.front(); | 473 scoped_refptr<VideoFrame> video_frame = frames_queue_done_.front(); |
| 468 frames_queue_done_.pop_front(); | 474 frames_queue_done_.pop_front(); |
| 469 ReadInput(video_frame); | 475 ReadInput(video_frame); |
| 470 } | 476 } |
| 471 } | 477 } |
| 472 | 478 |
| 473 void VideoRendererBase::FlushBuffers() { | 479 void VideoRendererBase::FlushBuffers_Locked() { |
| 480 lock_.AssertAcquired(); | |
| 474 DCHECK(!pending_paint_); | 481 DCHECK(!pending_paint_); |
| 475 | 482 |
| 476 // We should never put EOF frame into "done queue". | 483 // We should never put EOF frame into "done queue". |
| 477 while (!frames_queue_ready_.empty()) { | 484 while (!frames_queue_ready_.empty()) { |
| 478 scoped_refptr<VideoFrame> video_frame = frames_queue_ready_.front(); | 485 scoped_refptr<VideoFrame> video_frame = frames_queue_ready_.front(); |
| 479 if (!video_frame->IsEndOfStream()) { | 486 if (!video_frame->IsEndOfStream()) { |
| 480 frames_queue_done_.push_back(video_frame); | 487 frames_queue_done_.push_back(video_frame); |
| 481 } | 488 } |
| 482 frames_queue_ready_.pop_front(); | 489 frames_queue_ready_.pop_front(); |
| 483 } | 490 } |
| 484 if (current_frame_.get() && !current_frame_->IsEndOfStream()) { | 491 if (current_frame_.get() && !current_frame_->IsEndOfStream()) { |
| 485 frames_queue_done_.push_back(current_frame_); | 492 frames_queue_done_.push_back(current_frame_); |
| 486 } | 493 } |
| 487 current_frame_ = NULL; | 494 current_frame_ = NULL; |
| 488 | 495 |
| 489 // Flush all buffers out to decoder. | 496 // Flush all buffers out to decoder. |
| 490 ScheduleRead_Locked(); | 497 ScheduleRead_Locked(); |
| 491 | 498 |
| 492 if (pending_reads_ == 0 && state_ == kFlushing) | 499 if (pending_reads_ == 0 && state_ == kFlushing) |
| 493 OnFlushDone(); | 500 OnFlushDone_Locked(); |
| 494 } | 501 } |
| 495 | 502 |
| 496 void VideoRendererBase::OnFlushDone() { | 503 void VideoRendererBase::OnFlushDone_Locked() { |
| 497 // Check all buffers are return to owners. | 504 lock_.AssertAcquired(); |
| 505 // Check all buffers are returned to owners. | |
| 498 DCHECK_EQ(frames_queue_done_.size(), 0u); | 506 DCHECK_EQ(frames_queue_done_.size(), 0u); |
| 499 DCHECK(!current_frame_.get()); | 507 DCHECK(!current_frame_.get()); |
| 500 DCHECK(frames_queue_ready_.empty()); | 508 DCHECK(frames_queue_ready_.empty()); |
| 501 | 509 |
| 502 if (flush_callback_.get()) { // This ensures callback is invoked once. | 510 if (flush_callback_.get()) { // This ensures callback is invoked once. |
| 503 flush_callback_->Run(); | 511 flush_callback_->Run(); |
| 504 flush_callback_.reset(); | 512 flush_callback_.reset(); |
| 505 } | 513 } |
| 506 state_ = kFlushed; | 514 state_ = kFlushed; |
| 507 } | 515 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 host()->SetError(status); | 586 host()->SetError(status); |
| 579 | 587 |
| 580 if (callback.get()) | 588 if (callback.get()) |
| 581 callback->Run(); | 589 callback->Run(); |
| 582 } | 590 } |
| 583 | 591 |
| 584 void VideoRendererBase::DoStopOrErrorFlush_Locked() { | 592 void VideoRendererBase::DoStopOrErrorFlush_Locked() { |
| 585 DCHECK(!pending_paint_); | 593 DCHECK(!pending_paint_); |
| 586 DCHECK(!pending_paint_with_last_available_); | 594 DCHECK(!pending_paint_with_last_available_); |
| 587 lock_.AssertAcquired(); | 595 lock_.AssertAcquired(); |
| 588 FlushBuffers(); | 596 FlushBuffers_Locked(); |
| 589 last_available_frame_ = NULL; | 597 last_available_frame_ = NULL; |
| 590 DCHECK_EQ(pending_reads_, 0); | 598 DCHECK_EQ(pending_reads_, 0); |
| 591 } | 599 } |
| 592 | 600 |
| 593 } // namespace media | 601 } // namespace media |
| OLD | NEW |