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 |