OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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/base/android/media_source_player.h" | 5 #include "media/base/android/media_source_player.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 doing_browser_seek_(false), | 39 doing_browser_seek_(false), |
40 pending_seek_(false), | 40 pending_seek_(false), |
41 drm_bridge_(NULL), | 41 drm_bridge_(NULL), |
42 cdm_registration_id_(0), | 42 cdm_registration_id_(0), |
43 is_waiting_for_key_(false), | 43 is_waiting_for_key_(false), |
44 key_added_while_decode_pending_(false), | 44 key_added_while_decode_pending_(false), |
45 is_waiting_for_audio_decoder_(false), | 45 is_waiting_for_audio_decoder_(false), |
46 is_waiting_for_video_decoder_(false), | 46 is_waiting_for_video_decoder_(false), |
47 prerolling_(true), | 47 prerolling_(true), |
48 weak_factory_(this) { | 48 weak_factory_(this) { |
| 49 media_stat_.reset(new MediaStatistics()); |
| 50 |
49 audio_decoder_job_.reset(new AudioDecoderJob( | 51 audio_decoder_job_.reset(new AudioDecoderJob( |
50 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 52 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
51 base::Unretained(demuxer_.get()), | 53 base::Unretained(demuxer_.get()), |
52 DemuxerStream::AUDIO), | 54 DemuxerStream::AUDIO), |
53 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 55 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
54 weak_factory_.GetWeakPtr()))); | 56 weak_factory_.GetWeakPtr()), |
| 57 &media_stat_->AudioFrames())); |
55 video_decoder_job_.reset(new VideoDecoderJob( | 58 video_decoder_job_.reset(new VideoDecoderJob( |
56 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 59 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
57 base::Unretained(demuxer_.get()), | 60 base::Unretained(demuxer_.get()), |
58 DemuxerStream::VIDEO), | 61 DemuxerStream::VIDEO), |
59 base::Bind(request_media_resources_cb_, player_id), | 62 base::Bind(request_media_resources_cb_, player_id), |
60 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 63 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
61 weak_factory_.GetWeakPtr()))); | 64 weak_factory_.GetWeakPtr()), |
| 65 &media_stat_->VideoFrames())); |
| 66 |
62 demuxer_->Initialize(this); | 67 demuxer_->Initialize(this); |
63 interpolator_.SetUpperBound(base::TimeDelta()); | 68 interpolator_.SetUpperBound(base::TimeDelta()); |
64 weak_this_ = weak_factory_.GetWeakPtr(); | 69 weak_this_ = weak_factory_.GetWeakPtr(); |
65 } | 70 } |
66 | 71 |
67 MediaSourcePlayer::~MediaSourcePlayer() { | 72 MediaSourcePlayer::~MediaSourcePlayer() { |
68 Release(); | 73 Release(); |
69 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_); | 74 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_); |
70 if (drm_bridge_) { | 75 if (drm_bridge_) { |
71 drm_bridge_->UnregisterPlayer(cdm_registration_id_); | 76 drm_bridge_->UnregisterPlayer(cdm_registration_id_); |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 | 464 |
460 bool is_clock_manager = is_audio || !HasAudio(); | 465 bool is_clock_manager = is_audio || !HasAudio(); |
461 | 466 |
462 if (is_clock_manager) | 467 if (is_clock_manager) |
463 decoder_starvation_callback_.Cancel(); | 468 decoder_starvation_callback_.Cancel(); |
464 | 469 |
465 if (status == MEDIA_CODEC_ERROR) { | 470 if (status == MEDIA_CODEC_ERROR) { |
466 DVLOG(1) << __FUNCTION__ << " : decode error"; | 471 DVLOG(1) << __FUNCTION__ << " : decode error"; |
467 Release(); | 472 Release(); |
468 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); | 473 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); |
| 474 media_stat_->StopAndReport(); |
469 return; | 475 return; |
470 } | 476 } |
471 | 477 |
472 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); | 478 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); |
473 | 479 |
474 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of | 480 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of |
475 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process | 481 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process |
476 // any other pending events only after handling EOS detection. | 482 // any other pending events only after handling EOS detection. |
477 if (IsEventPending(SEEK_EVENT_PENDING)) { | 483 if (IsEventPending(SEEK_EVENT_PENDING)) { |
478 ProcessPendingEvents(); | 484 ProcessPendingEvents(); |
| 485 media_stat_->StopAndReport(); |
479 return; | 486 return; |
480 } | 487 } |
481 | 488 |
482 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) && | 489 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) && |
483 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) { | 490 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) { |
484 UpdateTimestamps(current_presentation_timestamp, | 491 UpdateTimestamps(current_presentation_timestamp, |
485 max_presentation_timestamp); | 492 max_presentation_timestamp); |
486 } | 493 } |
487 | 494 |
488 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 495 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
489 PlaybackCompleted(is_audio); | 496 PlaybackCompleted(is_audio); |
490 if (is_clock_manager) | 497 if (is_clock_manager) |
491 interpolator_.StopInterpolating(); | 498 interpolator_.StopInterpolating(); |
492 } | 499 } |
493 | 500 |
494 if (pending_event_ != NO_EVENT_PENDING) { | 501 if (pending_event_ != NO_EVENT_PENDING) { |
495 ProcessPendingEvents(); | 502 ProcessPendingEvents(); |
| 503 media_stat_->StopAndReport(); |
496 return; | 504 return; |
497 } | 505 } |
498 | 506 |
499 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 507 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
| 508 media_stat_->StopAndReport(); |
500 return; | 509 return; |
| 510 } |
501 | 511 |
502 if (!playing_) { | 512 if (!playing_) { |
503 if (is_clock_manager) | 513 if (is_clock_manager) |
504 interpolator_.StopInterpolating(); | 514 interpolator_.StopInterpolating(); |
505 | 515 |
| 516 media_stat_->StopAndReport(); |
506 return; | 517 return; |
507 } | 518 } |
508 | 519 |
509 if (status == MEDIA_CODEC_NO_KEY) { | 520 if (status == MEDIA_CODEC_NO_KEY) { |
510 if (key_added_while_decode_pending_) { | 521 if (key_added_while_decode_pending_) { |
511 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; | 522 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; |
512 ResumePlaybackAfterKeyAdded(); | 523 ResumePlaybackAfterKeyAdded(); |
513 } else { | 524 } else { |
514 is_waiting_for_key_ = true; | 525 is_waiting_for_key_ = true; |
515 manager()->OnWaitingForDecryptionKey(player_id()); | 526 manager()->OnWaitingForDecryptionKey(player_id()); |
516 } | 527 } |
| 528 media_stat_->StopAndReport(); |
517 return; | 529 return; |
518 } | 530 } |
519 | 531 |
520 // If |key_added_while_decode_pending_| is true and both audio and video | 532 // If |key_added_while_decode_pending_| is true and both audio and video |
521 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. | 533 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. |
522 // But that would add more complexity into this function. If we don't clear it | 534 // But that would add more complexity into this function. If we don't clear it |
523 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when | 535 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when |
524 // we don't really have a new key. This should rarely happen and the | 536 // we don't really have a new key. This should rarely happen and the |
525 // performance impact should be pretty small. | 537 // performance impact should be pretty small. |
526 // TODO(qinmin/xhwang): This class is complicated because we handle both audio | 538 // TODO(qinmin/xhwang): This class is complicated because we handle both audio |
527 // and video in one file. If we separate them, we should be able to remove a | 539 // and video in one file. If we separate them, we should be able to remove a |
528 // lot of duplication. | 540 // lot of duplication. |
529 | 541 |
530 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is | 542 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is |
531 // in the middle of a seek or stop event and needs to wait for the IPCs to | 543 // in the middle of a seek or stop event and needs to wait for the IPCs to |
532 // come. | 544 // come. |
533 if (status == MEDIA_CODEC_ABORT) | 545 if (status == MEDIA_CODEC_ABORT) { |
| 546 media_stat_->StopAndReport(); |
534 return; | 547 return; |
| 548 } |
535 | 549 |
536 if (prerolling_ && IsPrerollFinished(is_audio)) { | 550 if (prerolling_ && IsPrerollFinished(is_audio)) { |
537 if (IsPrerollFinished(!is_audio)) { | 551 if (IsPrerollFinished(!is_audio)) { |
538 prerolling_ = false; | 552 prerolling_ = false; |
539 StartInternal(); | 553 StartInternal(); |
540 } | 554 } |
541 return; | 555 return; |
542 } | 556 } |
543 | 557 |
544 if (is_clock_manager) { | 558 if (is_clock_manager) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 return audio_decoder_job_->OutputEOSReached() || !HasAudio(); | 660 return audio_decoder_job_->OutputEOSReached() || !HasAudio(); |
647 } | 661 } |
648 | 662 |
649 bool MediaSourcePlayer::VideoFinished() { | 663 bool MediaSourcePlayer::VideoFinished() { |
650 return video_decoder_job_->OutputEOSReached() || !HasVideo(); | 664 return video_decoder_job_->OutputEOSReached() || !HasVideo(); |
651 } | 665 } |
652 | 666 |
653 void MediaSourcePlayer::OnDecoderStarved() { | 667 void MediaSourcePlayer::OnDecoderStarved() { |
654 DVLOG(1) << __FUNCTION__; | 668 DVLOG(1) << __FUNCTION__; |
655 | 669 |
| 670 media_stat_->AddStarvation(); |
| 671 |
656 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 672 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
657 ProcessPendingEvents(); | 673 ProcessPendingEvents(); |
658 } | 674 } |
659 | 675 |
660 void MediaSourcePlayer::StartStarvationCallback( | 676 void MediaSourcePlayer::StartStarvationCallback( |
661 base::TimeDelta current_presentation_timestamp, | 677 base::TimeDelta current_presentation_timestamp, |
662 base::TimeDelta max_presentation_timestamp) { | 678 base::TimeDelta max_presentation_timestamp) { |
663 // 20ms was chosen because it is the typical size of a compressed audio frame. | 679 // 20ms was chosen because it is the typical size of a compressed audio frame. |
664 // Anything smaller than this would likely cause unnecessary cycling in and | 680 // Anything smaller than this would likely cause unnecessary cycling in and |
665 // out of the prefetch state. | 681 // out of the prefetch state. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 } | 728 } |
713 | 729 |
714 if (!playing_) | 730 if (!playing_) |
715 return; | 731 return; |
716 | 732 |
717 start_time_ticks_ = base::TimeTicks::Now(); | 733 start_time_ticks_ = base::TimeTicks::Now(); |
718 start_presentation_timestamp_ = GetCurrentTime(); | 734 start_presentation_timestamp_ = GetCurrentTime(); |
719 if (!interpolator_.interpolating()) | 735 if (!interpolator_.interpolating()) |
720 interpolator_.StartInterpolating(); | 736 interpolator_.StartInterpolating(); |
721 | 737 |
| 738 media_stat_->Start(); |
| 739 |
722 if (!AudioFinished()) | 740 if (!AudioFinished()) |
723 DecodeMoreAudio(); | 741 DecodeMoreAudio(); |
724 | 742 |
725 if (!VideoFinished()) | 743 if (!VideoFinished()) |
726 DecodeMoreVideo(); | 744 DecodeMoreVideo(); |
727 } | 745 } |
728 | 746 |
729 void MediaSourcePlayer::OnDemuxerConfigsChanged() { | 747 void MediaSourcePlayer::OnDemuxerConfigsChanged() { |
730 manager()->OnMediaMetadataChanged( | 748 manager()->OnMediaMetadataChanged( |
731 player_id(), duration_, GetVideoWidth(), GetVideoHeight(), true); | 749 player_id(), duration_, GetVideoWidth(), GetVideoHeight(), true); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release | 834 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release |
817 // MediaDrm when the video is paused, or when the device goes to sleep (see | 835 // MediaDrm when the video is paused, or when the device goes to sleep (see |
818 // http://crbug.com/272421). | 836 // http://crbug.com/272421). |
819 audio_decoder_job_->SetDrmBridge(NULL); | 837 audio_decoder_job_->SetDrmBridge(NULL); |
820 video_decoder_job_->SetDrmBridge(NULL); | 838 video_decoder_job_->SetDrmBridge(NULL); |
821 cdm_registration_id_ = 0; | 839 cdm_registration_id_ = 0; |
822 drm_bridge_ = NULL; | 840 drm_bridge_ = NULL; |
823 } | 841 } |
824 | 842 |
825 } // namespace media | 843 } // namespace media |
OLD | NEW |