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/renderers/video_renderer_impl.h" | 5 #include "media/renderers/video_renderer_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 | 361 |
362 // Can happen when demuxers are preparing for a new Seek(). | 362 // Can happen when demuxers are preparing for a new Seek(). |
363 if (!frame) { | 363 if (!frame) { |
364 DCHECK_EQ(status, VideoFrameStream::DEMUXER_READ_ABORTED); | 364 DCHECK_EQ(status, VideoFrameStream::DEMUXER_READ_ABORTED); |
365 return; | 365 return; |
366 } | 366 } |
367 | 367 |
368 if (frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)) { | 368 if (frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)) { |
369 DCHECK(!received_end_of_stream_); | 369 DCHECK(!received_end_of_stream_); |
370 received_end_of_stream_ = true; | 370 received_end_of_stream_ = true; |
371 | |
372 // See if we can fire EOS immediately instead of waiting for Render(). | |
373 MaybeFireEndedCallback_Locked(time_progressing_); | |
374 } else if ((low_delay_ || !video_frame_stream_->CanReadWithoutStalling()) && | 371 } else if ((low_delay_ || !video_frame_stream_->CanReadWithoutStalling()) && |
375 IsBeforeStartTime(frame->timestamp())) { | 372 IsBeforeStartTime(frame->timestamp())) { |
376 // Don't accumulate frames that are earlier than the start time if we | 373 // Don't accumulate frames that are earlier than the start time if we |
377 // won't have a chance for a better frame, otherwise we could declare | 374 // won't have a chance for a better frame, otherwise we could declare |
378 // HAVE_ENOUGH_DATA and start playback prematurely. | 375 // HAVE_ENOUGH_DATA and start playback prematurely. |
379 AttemptRead_Locked(); | 376 AttemptRead_Locked(); |
380 return; | 377 return; |
381 } else { | 378 } else { |
382 // If the sink hasn't been started, we still have time to release less | 379 // If the sink hasn't been started, we still have time to release less |
383 // than ideal frames prior to startup. We don't use IsBeforeStartTime() | 380 // than ideal frames prior to startup. We don't use IsBeforeStartTime() |
384 // here since it's based on a duration estimate and we can be exact here. | 381 // here since it's based on a duration estimate and we can be exact here. |
385 if (!sink_started_ && frame->timestamp() <= start_timestamp_) | 382 if (!sink_started_ && frame->timestamp() <= start_timestamp_) |
386 algorithm_->Reset(); | 383 algorithm_->Reset(); |
387 | 384 |
388 AddReadyFrame_Locked(frame); | 385 AddReadyFrame_Locked(frame); |
389 } | 386 } |
390 | 387 |
391 // Attempt to purge bad frames in case of underflow or backgrounding. | 388 // Attempt to purge bad frames in case of underflow or backgrounding. |
392 RemoveFramesForUnderflowOrBackgroundRendering(); | 389 RemoveFramesForUnderflowOrBackgroundRendering(); |
393 | 390 |
394 // Signal buffering state if we've met our conditions. | 391 // We may have removed all frames above and have reached end of stream. |
395 if (buffering_state_ == BUFFERING_HAVE_NOTHING && HaveEnoughData_Locked()) { | 392 MaybeFireEndedCallback_Locked(time_progressing_); |
396 TransitionToHaveEnough_Locked(); | |
397 | 393 |
398 // Paint the first frame if necessary. | 394 // Paint the first frame if possible and necessary. PaintSingleFrame() will |
399 if (!rendered_end_of_stream_ && !sink_started_) { | 395 // ignore repeated calls for the same frame. Paint ahead of HAVE_ENOUGH_DATA |
400 DCHECK(algorithm_->frames_queued()); | 396 // to ensure the user sees the frame as early as possible. |
| 397 if (!sink_started_ && algorithm_->frames_queued()) { |
| 398 // We want to paint the first frame under two conditions: Either (1) we have |
| 399 // enough frames to know it's definitely the first frame or (2) there may be |
| 400 // no more frames coming (sometimes unless we paint one of them). |
| 401 if (algorithm_->frames_queued() > 1 || received_end_of_stream_ || |
| 402 low_delay_ || !video_frame_stream_->CanReadWithoutStalling()) { |
401 scoped_refptr<VideoFrame> frame = algorithm_->first_frame(); | 403 scoped_refptr<VideoFrame> frame = algorithm_->first_frame(); |
402 CheckForMetadataChanges(frame->format(), frame->natural_size()); | 404 CheckForMetadataChanges(frame->format(), frame->natural_size()); |
403 sink_->PaintSingleFrame(frame); | 405 sink_->PaintSingleFrame(frame); |
404 } | 406 } |
405 } | 407 } |
406 | 408 |
| 409 // Signal buffering state if we've met our conditions. |
| 410 if (buffering_state_ == BUFFERING_HAVE_NOTHING && HaveEnoughData_Locked()) |
| 411 TransitionToHaveEnough_Locked(); |
| 412 |
407 // Always request more decoded video if we have capacity. This serves two | 413 // Always request more decoded video if we have capacity. This serves two |
408 // purposes: | 414 // purposes: |
409 // 1) Prerolling while paused | 415 // 1) Prerolling while paused |
410 // 2) Keeps decoding going if video rendering thread starts falling behind | 416 // 2) Keeps decoding going if video rendering thread starts falling behind |
411 AttemptRead_Locked(); | 417 AttemptRead_Locked(); |
412 } | 418 } |
413 | 419 |
414 bool VideoRendererImpl::HaveEnoughData_Locked() { | 420 bool VideoRendererImpl::HaveEnoughData_Locked() { |
415 DCHECK_EQ(state_, kPlaying); | 421 DCHECK_EQ(state_, kPlaying); |
416 lock_.AssertAcquired(); | 422 lock_.AssertAcquired(); |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 | 682 |
677 void VideoRendererImpl::AttemptReadAndCheckForMetadataChanges( | 683 void VideoRendererImpl::AttemptReadAndCheckForMetadataChanges( |
678 VideoPixelFormat pixel_format, | 684 VideoPixelFormat pixel_format, |
679 const gfx::Size& natural_size) { | 685 const gfx::Size& natural_size) { |
680 base::AutoLock auto_lock(lock_); | 686 base::AutoLock auto_lock(lock_); |
681 CheckForMetadataChanges(pixel_format, natural_size); | 687 CheckForMetadataChanges(pixel_format, natural_size); |
682 AttemptRead_Locked(); | 688 AttemptRead_Locked(); |
683 } | 689 } |
684 | 690 |
685 } // namespace media | 691 } // namespace media |
OLD | NEW |