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 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 return clock_.Elapsed(); | 224 return clock_.Elapsed(); |
225 } | 225 } |
226 | 226 |
227 base::TimeDelta MediaSourcePlayer::GetDuration() { | 227 base::TimeDelta MediaSourcePlayer::GetDuration() { |
228 return duration_; | 228 return duration_; |
229 } | 229 } |
230 | 230 |
231 void MediaSourcePlayer::Release() { | 231 void MediaSourcePlayer::Release() { |
232 DVLOG(1) << __FUNCTION__; | 232 DVLOG(1) << __FUNCTION__; |
233 audio_decoder_job_.reset(); | 233 audio_decoder_job_.reset(); |
234 video_decoder_job_.reset(); | 234 ResetVideoDecoderJob(); |
235 reconfig_audio_decoder_ = false; | 235 reconfig_audio_decoder_ = false; |
236 reconfig_video_decoder_ = false; | 236 reconfig_video_decoder_ = false; |
237 playing_ = false; | 237 playing_ = false; |
238 pending_event_ = NO_EVENT_PENDING; | 238 pending_event_ = NO_EVENT_PENDING; |
239 decoder_starvation_callback_.Cancel(); | 239 decoder_starvation_callback_.Cancel(); |
240 surface_ = gfx::ScopedJavaSurface(); | 240 surface_ = gfx::ScopedJavaSurface(); |
241 manager()->ReleaseMediaResources(player_id()); | 241 manager()->ReleaseMediaResources(player_id()); |
242 } | 242 } |
243 | 243 |
244 void MediaSourcePlayer::SetVolume(double volume) { | 244 void MediaSourcePlayer::SetVolume(double volume) { |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 486 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
487 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; | 487 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; |
488 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); | 488 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); |
489 demuxer_->RequestDemuxerConfigs(); | 489 demuxer_->RequestDemuxerConfigs(); |
490 return; | 490 return; |
491 } | 491 } |
492 | 492 |
493 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { | 493 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { |
494 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; | 494 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; |
495 // Setting a new surface will require a new MediaCodec to be created. | 495 // Setting a new surface will require a new MediaCodec to be created. |
496 video_decoder_job_.reset(); | 496 ResetVideoDecoderJob(); |
497 ConfigureVideoDecoderJob(); | 497 ConfigureVideoDecoderJob(); |
498 | 498 |
499 // Return early if we can't successfully configure a new video decoder job | 499 // Return early if we can't successfully configure a new video decoder job |
500 // yet, except continue processing other pending events if |surface_| is | 500 // yet, except continue processing other pending events if |surface_| is |
501 // empty. | 501 // empty. |
502 if (!video_decoder_job_ && !surface_.IsEmpty()) | 502 if (!video_decoder_job_ && !surface_.IsEmpty()) |
503 return; | 503 return; |
504 } | 504 } |
505 | 505 |
506 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { | 506 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
711 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 711 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
712 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); | 712 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); |
713 | 713 |
714 if (audio_decoder_job_) { | 714 if (audio_decoder_job_) { |
715 SetVolumeInternal(); | 715 SetVolumeInternal(); |
716 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 716 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
717 reconfig_audio_decoder_ = false; | 717 reconfig_audio_decoder_ = false; |
718 } | 718 } |
719 } | 719 } |
720 | 720 |
721 void MediaSourcePlayer::ResetVideoDecoderJob() { | |
722 video_decoder_job_.reset(); | |
723 | |
724 // Any eventual video decoder job re-creation will use the current |surface_|. | |
725 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) | |
726 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); | |
727 } | |
728 | |
721 void MediaSourcePlayer::ConfigureVideoDecoderJob() { | 729 void MediaSourcePlayer::ConfigureVideoDecoderJob() { |
722 if (!HasVideo() || surface_.IsEmpty()) { | 730 if (!HasVideo() || surface_.IsEmpty()) { |
723 video_decoder_job_.reset(); | 731 ResetVideoDecoderJob(); |
724 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) | |
725 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); | |
726 return; | 732 return; |
727 } | 733 } |
728 | 734 |
729 // Create video decoder job only if config changes or we don't have a job. | 735 // Create video decoder job only if config changes or we don't have a job. |
730 if (video_decoder_job_ && !reconfig_video_decoder_) | 736 if (video_decoder_job_ && !reconfig_video_decoder_) { |
737 DCHECK(!IsEventPending(SURFACE_CHANGE_EVENT_PENDING)); | |
731 return; | 738 return; |
739 } | |
732 | 740 |
733 if (reconfig_video_decoder_) { | 741 if (reconfig_video_decoder_) { |
734 // No hack browser seek should be required. I-Frame must be next. | 742 // No hack browser seek should be required. I-Frame must be next. |
735 DCHECK(next_video_data_is_iframe_) << "Received video data between " | 743 DCHECK(next_video_data_is_iframe_) << "Received video data between " |
736 << "detecting video config change and reconfiguring video decoder"; | 744 << "detecting video config change and reconfiguring video decoder"; |
737 } | 745 } |
738 | 746 |
747 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); | |
xhwang
2013/10/31 21:37:18
Do we ever call ConfigureVideoDecoderJob() when vi
wolenetz
2013/11/02 00:00:57
Good point. Thanks for chat that helped clarify EM
| |
748 | |
739 // If uncertain that video I-frame data is next and there is no seek already | 749 // If uncertain that video I-frame data is next and there is no seek already |
740 // in process, request browser demuxer seek so the new decoder will decode | 750 // in process, request browser demuxer seek so the new decoder will decode |
741 // an I-frame first. Otherwise, the new MediaCodec might crash. See b/8950387. | 751 // an I-frame first. Otherwise, the new MediaCodec might crash. See b/8950387. |
752 // Eventual OnDemuxerSeekDone() will trigger ProcessPendingEvents() and | |
753 // continue from here. | |
742 // TODO(wolenetz): Instead of doing hack browser seek, replay cached data | 754 // TODO(wolenetz): Instead of doing hack browser seek, replay cached data |
743 // since last keyframe. See http://crbug.com/304234. | 755 // since last keyframe. See http://crbug.com/304234. |
744 if (!next_video_data_is_iframe_ && !IsEventPending(SEEK_EVENT_PENDING)) { | 756 if (!next_video_data_is_iframe_ && !IsEventPending(SEEK_EVENT_PENDING)) { |
745 BrowserSeekToCurrentTime(); | 757 BrowserSeekToCurrentTime(); |
746 return; | 758 return; |
747 } | 759 } |
748 | 760 |
761 // Release the old VideoDecoderJob first so the surface can get released. | |
762 // Android does not allow 2 MediaCodec instances use the same surface. | |
763 ResetVideoDecoderJob(); | |
764 | |
749 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); | 765 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); |
750 if (is_video_encrypted_ && media_crypto.is_null()) | 766 if (is_video_encrypted_ && media_crypto.is_null()) |
751 return; | 767 return; |
752 | 768 |
753 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); | |
754 | |
755 DVLOG(1) << __FUNCTION__ << " : creating new video decoder job"; | 769 DVLOG(1) << __FUNCTION__ << " : creating new video decoder job"; |
756 | 770 |
757 // Release the old VideoDecoderJob first so the surface can get released. | |
758 // Android does not allow 2 MediaCodec instances use the same surface. | |
759 video_decoder_job_.reset(); | |
760 // Create the new VideoDecoderJob. | 771 // Create the new VideoDecoderJob. |
761 bool is_secure = IsProtectedSurfaceRequired(); | 772 bool is_secure = IsProtectedSurfaceRequired(); |
762 video_decoder_job_.reset( | 773 video_decoder_job_.reset( |
763 VideoDecoderJob::Create(video_codec_, | 774 VideoDecoderJob::Create(video_codec_, |
764 is_secure, | 775 is_secure, |
765 gfx::Size(width_, height_), | 776 gfx::Size(width_, height_), |
766 surface_.j_surface().obj(), | 777 surface_.j_surface().obj(), |
767 media_crypto.obj(), | 778 media_crypto.obj(), |
768 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 779 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
769 base::Unretained(demuxer_.get()), | 780 base::Unretained(demuxer_.get()), |
770 DemuxerStream::VIDEO))); | 781 DemuxerStream::VIDEO))); |
771 if (video_decoder_job_) { | 782 if (video_decoder_job_) { |
acolwell GONE FROM CHROMIUM
2013/10/31 21:45:08
nit: reverse condition and return early.
wolenetz
2013/11/02 00:00:57
Done. This is a pattern I'll start watching for mo
| |
772 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 783 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
773 reconfig_video_decoder_ = false; | 784 reconfig_video_decoder_ = false; |
785 | |
786 // Inform the fullscreen view the player is ready. | |
787 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way | |
788 // to inform ContentVideoView. | |
789 manager()->OnMediaMetadataChanged( | |
790 player_id(), duration_, width_, height_, true); | |
774 } | 791 } |
775 | |
776 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) | |
777 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); | |
778 | |
779 // Inform the fullscreen view the player is ready. | |
780 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way | |
781 // to inform ContentVideoView. | |
782 manager()->OnMediaMetadataChanged( | |
783 player_id(), duration_, width_, height_, true); | |
784 } | 792 } |
785 | 793 |
786 void MediaSourcePlayer::OnDecoderStarved() { | 794 void MediaSourcePlayer::OnDecoderStarved() { |
787 DVLOG(1) << __FUNCTION__; | 795 DVLOG(1) << __FUNCTION__; |
788 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 796 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
789 ProcessPendingEvents(); | 797 ProcessPendingEvents(); |
790 } | 798 } |
791 | 799 |
792 void MediaSourcePlayer::StartStarvationCallback( | 800 void MediaSourcePlayer::StartStarvationCallback( |
793 const base::TimeDelta& presentation_timestamp) { | 801 const base::TimeDelta& presentation_timestamp) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
887 | 895 |
888 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 896 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
889 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 897 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
890 DCHECK_NE(event, NO_EVENT_PENDING); | 898 DCHECK_NE(event, NO_EVENT_PENDING); |
891 DCHECK(IsEventPending(event)) << GetEventName(event); | 899 DCHECK(IsEventPending(event)) << GetEventName(event); |
892 | 900 |
893 pending_event_ &= ~event; | 901 pending_event_ &= ~event; |
894 } | 902 } |
895 | 903 |
896 } // namespace media | 904 } // namespace media |
OLD | NEW |