| 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" |
| 11 #include "base/barrier_closure.h" | 11 #include "base/barrier_closure.h" |
| 12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/callback_helpers.h" |
| 14 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 17 #include "media/base/android/audio_decoder_job.h" | 18 #include "media/base/android/audio_decoder_job.h" |
| 18 #include "media/base/android/media_drm_bridge.h" | 19 #include "media/base/android/media_drm_bridge.h" |
| 19 #include "media/base/android/media_player_manager.h" | 20 #include "media/base/android/media_player_manager.h" |
| 20 #include "media/base/android/video_decoder_job.h" | 21 #include "media/base/android/video_decoder_job.h" |
| 21 #include "media/base/audio_timestamp_helper.h" | 22 #include "media/base/audio_timestamp_helper.h" |
| 22 #include "media/base/buffers.h" | 23 #include "media/base/buffers.h" |
| 23 | 24 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { | 224 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { |
| 224 return clock_.Elapsed(); | 225 return clock_.Elapsed(); |
| 225 } | 226 } |
| 226 | 227 |
| 227 base::TimeDelta MediaSourcePlayer::GetDuration() { | 228 base::TimeDelta MediaSourcePlayer::GetDuration() { |
| 228 return duration_; | 229 return duration_; |
| 229 } | 230 } |
| 230 | 231 |
| 231 void MediaSourcePlayer::Release() { | 232 void MediaSourcePlayer::Release() { |
| 232 DVLOG(1) << __FUNCTION__; | 233 DVLOG(1) << __FUNCTION__; |
| 234 |
| 235 // Allow pending seeks and config changes to survive this Release(). |
| 236 // If previously pending a prefetch done event, or a job was still decoding, |
| 237 // then at end of Release() we need to ProcessPendingEvents() to process any |
| 238 // seek or config change that was blocked by the prefetch or decode. |
| 239 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data |
| 240 // or drop data received across Release()+Start(). See http://crbug.com/306314 |
| 241 // and http://crbug.com/304234. |
| 242 bool process_pending_events = false; |
| 243 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) || |
| 244 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) || |
| 245 (video_decoder_job_ && video_decoder_job_->is_decoding()); |
| 246 |
| 247 // Clear all the pending events except seeks and config changes. |
| 248 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING); |
| 249 |
| 233 audio_decoder_job_.reset(); | 250 audio_decoder_job_.reset(); |
| 234 video_decoder_job_.reset(); | 251 video_decoder_job_.reset(); |
| 252 |
| 253 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable() |
| 235 reconfig_audio_decoder_ = false; | 254 reconfig_audio_decoder_ = false; |
| 236 reconfig_video_decoder_ = false; | 255 reconfig_video_decoder_ = false; |
| 256 |
| 257 // Prevent player restart, including job re-creation attempts. |
| 237 playing_ = false; | 258 playing_ = false; |
| 238 pending_event_ = NO_EVENT_PENDING; | 259 |
| 239 decoder_starvation_callback_.Cancel(); | 260 decoder_starvation_callback_.Cancel(); |
| 240 surface_ = gfx::ScopedJavaSurface(); | 261 surface_ = gfx::ScopedJavaSurface(); |
| 241 manager()->ReleaseMediaResources(player_id()); | 262 manager()->ReleaseMediaResources(player_id()); |
| 263 if (process_pending_events) { |
| 264 DVLOG(1) << __FUNCTION__ << " : Resuming seek or config change processing"; |
| 265 ProcessPendingEvents(); |
| 266 } |
| 242 } | 267 } |
| 243 | 268 |
| 244 void MediaSourcePlayer::SetVolume(double volume) { | 269 void MediaSourcePlayer::SetVolume(double volume) { |
| 245 volume_ = volume; | 270 volume_ = volume; |
| 246 SetVolumeInternal(); | 271 SetVolumeInternal(); |
| 247 } | 272 } |
| 248 | 273 |
| 249 void MediaSourcePlayer::OnKeyAdded() { | 274 void MediaSourcePlayer::OnKeyAdded() { |
| 250 DVLOG(1) << __FUNCTION__; | 275 DVLOG(1) << __FUNCTION__; |
| 251 if (!is_waiting_for_key_) | 276 if (!is_waiting_for_key_) |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 "MediaCodecStatus", | 567 "MediaCodecStatus", |
| 543 base::IntToString(status)); | 568 base::IntToString(status)); |
| 544 } else { | 569 } else { |
| 545 TRACE_EVENT_ASYNC_END1("media", | 570 TRACE_EVENT_ASYNC_END1("media", |
| 546 "MediaSourcePlayer::DecodeMoreVideo", | 571 "MediaSourcePlayer::DecodeMoreVideo", |
| 547 video_decoder_job_.get(), | 572 video_decoder_job_.get(), |
| 548 "MediaCodecStatus", | 573 "MediaCodecStatus", |
| 549 base::IntToString(status)); | 574 base::IntToString(status)); |
| 550 } | 575 } |
| 551 | 576 |
| 577 // Let tests hook the completion of this decode cycle. |
| 578 if (!decode_callback_for_testing_.is_null()) |
| 579 base::ResetAndReturn(&decode_callback_for_testing_).Run(); |
| 580 |
| 552 bool is_clock_manager = is_audio || !HasAudio(); | 581 bool is_clock_manager = is_audio || !HasAudio(); |
| 553 | 582 |
| 554 if (is_clock_manager) | 583 if (is_clock_manager) |
| 555 decoder_starvation_callback_.Cancel(); | 584 decoder_starvation_callback_.Cancel(); |
| 556 | 585 |
| 557 if (status == MEDIA_CODEC_ERROR) { | 586 if (status == MEDIA_CODEC_ERROR) { |
| 587 DVLOG(1) << __FUNCTION__ << " : decode error"; |
| 558 Release(); | 588 Release(); |
| 559 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); | 589 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); |
| 560 return; | 590 return; |
| 561 } | 591 } |
| 562 | 592 |
| 563 if (pending_event_ != NO_EVENT_PENDING) { | 593 if (pending_event_ != NO_EVENT_PENDING) { |
| 564 ProcessPendingEvents(); | 594 ProcessPendingEvents(); |
| 565 return; | 595 return; |
| 566 } | 596 } |
| 567 | 597 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 | 858 |
| 829 bool MediaSourcePlayer::IsProtectedSurfaceRequired() { | 859 bool MediaSourcePlayer::IsProtectedSurfaceRequired() { |
| 830 return is_video_encrypted_ && | 860 return is_video_encrypted_ && |
| 831 drm_bridge_ && drm_bridge_->IsProtectedSurfaceRequired(); | 861 drm_bridge_ && drm_bridge_->IsProtectedSurfaceRequired(); |
| 832 } | 862 } |
| 833 | 863 |
| 834 void MediaSourcePlayer::OnPrefetchDone() { | 864 void MediaSourcePlayer::OnPrefetchDone() { |
| 835 DVLOG(1) << __FUNCTION__; | 865 DVLOG(1) << __FUNCTION__; |
| 836 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); | 866 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); |
| 837 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); | 867 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); |
| 838 DCHECK(IsEventPending(PREFETCH_DONE_EVENT_PENDING)); | 868 |
| 869 // A previously posted OnPrefetchDone() could race against a Release(). If |
| 870 // Release() won the race, we should no longer have decoder jobs. |
| 871 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data |
| 872 // or drop data received across Release()+Start(). See http://crbug.com/306314 |
| 873 // and http://crbug.com/304234. |
| 874 if (!IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { |
| 875 DVLOG(1) << __FUNCTION__ << " : aborting"; |
| 876 DCHECK(!audio_decoder_job_ && !video_decoder_job_); |
| 877 return; |
| 878 } |
| 839 | 879 |
| 840 ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING); | 880 ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING); |
| 841 | 881 |
| 842 if (pending_event_ != NO_EVENT_PENDING) { | 882 if (pending_event_ != NO_EVENT_PENDING) { |
| 843 ProcessPendingEvents(); | 883 ProcessPendingEvents(); |
| 844 return; | 884 return; |
| 845 } | 885 } |
| 846 | 886 |
| 847 start_time_ticks_ = base::TimeTicks::Now(); | 887 start_time_ticks_ = base::TimeTicks::Now(); |
| 848 start_presentation_timestamp_ = GetCurrentTime(); | 888 start_presentation_timestamp_ = GetCurrentTime(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 | 927 |
| 888 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 928 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
| 889 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 929 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
| 890 DCHECK_NE(event, NO_EVENT_PENDING); | 930 DCHECK_NE(event, NO_EVENT_PENDING); |
| 891 DCHECK(IsEventPending(event)) << GetEventName(event); | 931 DCHECK(IsEventPending(event)) << GetEventName(event); |
| 892 | 932 |
| 893 pending_event_ &= ~event; | 933 pending_event_ &= ~event; |
| 894 } | 934 } |
| 895 | 935 |
| 896 } // namespace media | 936 } // namespace media |
| OLD | NEW |