| 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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 // and http://crbug.com/304234. | 241 // and http://crbug.com/304234. |
| 242 bool process_pending_events = false; | 242 bool process_pending_events = false; |
| 243 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) || | 243 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) || |
| 244 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) || | 244 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) || |
| 245 (video_decoder_job_ && video_decoder_job_->is_decoding()); | 245 (video_decoder_job_ && video_decoder_job_->is_decoding()); |
| 246 | 246 |
| 247 // Clear all the pending events except seeks and config changes. | 247 // Clear all the pending events except seeks and config changes. |
| 248 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING); | 248 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING); |
| 249 | 249 |
| 250 audio_decoder_job_.reset(); | 250 audio_decoder_job_.reset(); |
| 251 video_decoder_job_.reset(); | 251 ResetVideoDecoderJob(); |
| 252 | 252 |
| 253 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable() | 253 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable() |
| 254 reconfig_audio_decoder_ = false; | 254 reconfig_audio_decoder_ = false; |
| 255 reconfig_video_decoder_ = false; | 255 reconfig_video_decoder_ = false; |
| 256 | 256 |
| 257 // Prevent player restart, including job re-creation attempts. | 257 // Prevent player restart, including job re-creation attempts. |
| 258 playing_ = false; | 258 playing_ = false; |
| 259 | 259 |
| 260 decoder_starvation_callback_.Cancel(); | 260 decoder_starvation_callback_.Cancel(); |
| 261 surface_ = gfx::ScopedJavaSurface(); | 261 surface_ = gfx::ScopedJavaSurface(); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 511 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
| 512 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; | 512 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; |
| 513 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); | 513 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); |
| 514 demuxer_->RequestDemuxerConfigs(); | 514 demuxer_->RequestDemuxerConfigs(); |
| 515 return; | 515 return; |
| 516 } | 516 } |
| 517 | 517 |
| 518 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { | 518 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { |
| 519 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; | 519 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; |
| 520 // Setting a new surface will require a new MediaCodec to be created. | 520 // Setting a new surface will require a new MediaCodec to be created. |
| 521 video_decoder_job_.reset(); | 521 ResetVideoDecoderJob(); |
| 522 ConfigureVideoDecoderJob(); | 522 ConfigureVideoDecoderJob(); |
| 523 | 523 |
| 524 // Return early if we can't successfully configure a new video decoder job | 524 // Return early if we can't successfully configure a new video decoder job |
| 525 // yet, except continue processing other pending events if |surface_| is | 525 // yet, except continue processing other pending events if |surface_| is |
| 526 // empty. | 526 // empty. |
| 527 if (!video_decoder_job_ && !surface_.IsEmpty()) | 527 if (!video_decoder_job_ && !surface_.IsEmpty()) |
| 528 return; | 528 return; |
| 529 } | 529 } |
| 530 | 530 |
| 531 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { | 531 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 741 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
| 742 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); | 742 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); |
| 743 | 743 |
| 744 if (audio_decoder_job_) { | 744 if (audio_decoder_job_) { |
| 745 SetVolumeInternal(); | 745 SetVolumeInternal(); |
| 746 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 746 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 747 reconfig_audio_decoder_ = false; | 747 reconfig_audio_decoder_ = false; |
| 748 } | 748 } |
| 749 } | 749 } |
| 750 | 750 |
| 751 void MediaSourcePlayer::ResetVideoDecoderJob() { |
| 752 video_decoder_job_.reset(); |
| 753 |
| 754 // Any eventual video decoder job re-creation will use the current |surface_|. |
| 755 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) |
| 756 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); |
| 757 } |
| 758 |
| 751 void MediaSourcePlayer::ConfigureVideoDecoderJob() { | 759 void MediaSourcePlayer::ConfigureVideoDecoderJob() { |
| 752 if (!HasVideo() || surface_.IsEmpty()) { | 760 if (!HasVideo() || surface_.IsEmpty()) { |
| 753 video_decoder_job_.reset(); | 761 ResetVideoDecoderJob(); |
| 754 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) | |
| 755 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); | |
| 756 return; | 762 return; |
| 757 } | 763 } |
| 758 | 764 |
| 759 // Create video decoder job only if config changes or we don't have a job. | 765 // Create video decoder job only if config changes or we don't have a job. |
| 760 if (video_decoder_job_ && !reconfig_video_decoder_) | 766 if (video_decoder_job_ && !reconfig_video_decoder_) { |
| 767 DCHECK(!IsEventPending(SURFACE_CHANGE_EVENT_PENDING)); |
| 761 return; | 768 return; |
| 769 } |
| 770 |
| 771 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); |
| 762 | 772 |
| 763 if (reconfig_video_decoder_) { | 773 if (reconfig_video_decoder_) { |
| 764 // No hack browser seek should be required. I-Frame must be next. | 774 // No hack browser seek should be required. I-Frame must be next. |
| 765 DCHECK(next_video_data_is_iframe_) << "Received video data between " | 775 DCHECK(next_video_data_is_iframe_) << "Received video data between " |
| 766 << "detecting video config change and reconfiguring video decoder"; | 776 << "detecting video config change and reconfiguring video decoder"; |
| 767 } | 777 } |
| 768 | 778 |
| 769 // If uncertain that video I-frame data is next and there is no seek already | 779 // If uncertain that video I-frame data is next and there is no seek already |
| 770 // in process, request browser demuxer seek so the new decoder will decode | 780 // in process, request browser demuxer seek so the new decoder will decode |
| 771 // an I-frame first. Otherwise, the new MediaCodec might crash. See b/8950387. | 781 // an I-frame first. Otherwise, the new MediaCodec might crash. See b/8950387. |
| 782 // Eventual OnDemuxerSeekDone() will trigger ProcessPendingEvents() and |
| 783 // continue from here. |
| 772 // TODO(wolenetz): Instead of doing hack browser seek, replay cached data | 784 // TODO(wolenetz): Instead of doing hack browser seek, replay cached data |
| 773 // since last keyframe. See http://crbug.com/304234. | 785 // since last keyframe. See http://crbug.com/304234. |
| 774 if (!next_video_data_is_iframe_ && !IsEventPending(SEEK_EVENT_PENDING)) { | 786 if (!next_video_data_is_iframe_ && !IsEventPending(SEEK_EVENT_PENDING)) { |
| 775 BrowserSeekToCurrentTime(); | 787 BrowserSeekToCurrentTime(); |
| 776 return; | 788 return; |
| 777 } | 789 } |
| 778 | 790 |
| 791 // Release the old VideoDecoderJob first so the surface can get released. |
| 792 // Android does not allow 2 MediaCodec instances use the same surface. |
| 793 ResetVideoDecoderJob(); |
| 794 |
| 779 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); | 795 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); |
| 780 if (is_video_encrypted_ && media_crypto.is_null()) | 796 if (is_video_encrypted_ && media_crypto.is_null()) |
| 781 return; | 797 return; |
| 782 | 798 |
| 783 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); | |
| 784 | |
| 785 DVLOG(1) << __FUNCTION__ << " : creating new video decoder job"; | 799 DVLOG(1) << __FUNCTION__ << " : creating new video decoder job"; |
| 786 | 800 |
| 787 // Release the old VideoDecoderJob first so the surface can get released. | |
| 788 // Android does not allow 2 MediaCodec instances use the same surface. | |
| 789 video_decoder_job_.reset(); | |
| 790 // Create the new VideoDecoderJob. | 801 // Create the new VideoDecoderJob. |
| 791 bool is_secure = IsProtectedSurfaceRequired(); | 802 bool is_secure = IsProtectedSurfaceRequired(); |
| 792 video_decoder_job_.reset( | 803 video_decoder_job_.reset( |
| 793 VideoDecoderJob::Create(video_codec_, | 804 VideoDecoderJob::Create(video_codec_, |
| 794 is_secure, | 805 is_secure, |
| 795 gfx::Size(width_, height_), | 806 gfx::Size(width_, height_), |
| 796 surface_.j_surface().obj(), | 807 surface_.j_surface().obj(), |
| 797 media_crypto.obj(), | 808 media_crypto.obj(), |
| 798 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 809 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
| 799 base::Unretained(demuxer_.get()), | 810 base::Unretained(demuxer_.get()), |
| 800 DemuxerStream::VIDEO))); | 811 DemuxerStream::VIDEO))); |
| 801 if (video_decoder_job_) { | 812 if (!video_decoder_job_) |
| 802 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 813 return; |
| 803 reconfig_video_decoder_ = false; | |
| 804 } | |
| 805 | 814 |
| 806 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) | 815 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 807 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); | 816 reconfig_video_decoder_ = false; |
| 808 | 817 |
| 809 // Inform the fullscreen view the player is ready. | 818 // Inform the fullscreen view the player is ready. |
| 810 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way | 819 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way |
| 811 // to inform ContentVideoView. | 820 // to inform ContentVideoView. |
| 812 manager()->OnMediaMetadataChanged( | 821 manager()->OnMediaMetadataChanged( |
| 813 player_id(), duration_, width_, height_, true); | 822 player_id(), duration_, width_, height_, true); |
| 814 } | 823 } |
| 815 | 824 |
| 816 void MediaSourcePlayer::OnDecoderStarved() { | 825 void MediaSourcePlayer::OnDecoderStarved() { |
| 817 DVLOG(1) << __FUNCTION__; | 826 DVLOG(1) << __FUNCTION__; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 | 936 |
| 928 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 937 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
| 929 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 938 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
| 930 DCHECK_NE(event, NO_EVENT_PENDING); | 939 DCHECK_NE(event, NO_EVENT_PENDING); |
| 931 DCHECK(IsEventPending(event)) << GetEventName(event); | 940 DCHECK(IsEventPending(event)) << GetEventName(event); |
| 932 | 941 |
| 933 pending_event_ &= ~event; | 942 pending_event_ &= ~event; |
| 934 } | 943 } |
| 935 | 944 |
| 936 } // namespace media | 945 } // namespace media |
| OLD | NEW |