| 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/callback_helpers.h" |
| 15 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "media/base/android/audio_decoder_job.h" | 18 #include "media/base/android/audio_decoder_job.h" |
| 19 #include "media/base/android/media_drm_bridge.h" | 19 #include "media/base/android/media_drm_bridge.h" |
| 20 #include "media/base/android/media_player_manager.h" | 20 #include "media/base/android/media_player_manager.h" |
| 21 #include "media/base/android/video_decoder_job.h" | 21 #include "media/base/android/video_decoder_job.h" |
| 22 #include "media/base/buffers.h" | 22 |
| 23 | 23 |
| 24 namespace media { | 24 namespace media { |
| 25 | 25 |
| 26 MediaSourcePlayer::MediaSourcePlayer( | 26 MediaSourcePlayer::MediaSourcePlayer( |
| 27 int player_id, | 27 int player_id, |
| 28 MediaPlayerManager* manager, | 28 MediaPlayerManager* manager, |
| 29 const RequestMediaResourcesCB& request_media_resources_cb, | 29 const RequestMediaResourcesCB& request_media_resources_cb, |
| 30 const ReleaseMediaResourcesCB& release_media_resources_cb, | 30 const ReleaseMediaResourcesCB& release_media_resources_cb, |
| 31 scoped_ptr<DemuxerAndroid> demuxer) | 31 scoped_ptr<DemuxerAndroid> demuxer) |
| 32 : MediaPlayerAndroid(player_id, | 32 : MediaPlayerAndroid(player_id, |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 return; | 290 return; |
| 291 } | 291 } |
| 292 | 292 |
| 293 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 293 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
| 294 ProcessPendingEvents(); | 294 ProcessPendingEvents(); |
| 295 } | 295 } |
| 296 | 296 |
| 297 void MediaSourcePlayer::OnDemuxerConfigsAvailable( | 297 void MediaSourcePlayer::OnDemuxerConfigsAvailable( |
| 298 const DemuxerConfigs& configs) { | 298 const DemuxerConfigs& configs) { |
| 299 DVLOG(1) << __FUNCTION__; | 299 DVLOG(1) << __FUNCTION__; |
| 300 DCHECK(!HasAudio() && !HasVideo()); |
| 300 duration_ = configs.duration; | 301 duration_ = configs.duration; |
| 301 clock_.SetDuration(duration_); | 302 clock_.SetDuration(duration_); |
| 302 | 303 |
| 303 audio_codec_ = configs.audio_codec; | 304 SetDemuxerConfigs(configs, true); |
| 304 num_channels_ = configs.audio_channels; | 305 SetDemuxerConfigs(configs, false); |
| 305 sampling_rate_ = configs.audio_sampling_rate; | |
| 306 is_audio_encrypted_ = configs.is_audio_encrypted; | |
| 307 audio_extra_data_ = configs.audio_extra_data; | |
| 308 video_codec_ = configs.video_codec; | |
| 309 width_ = configs.video_size.width(); | |
| 310 height_ = configs.video_size.height(); | |
| 311 is_video_encrypted_ = configs.is_video_encrypted; | |
| 312 | 306 |
| 313 manager()->OnMediaMetadataChanged( | 307 manager()->OnMediaMetadataChanged( |
| 314 player_id(), duration_, width_, height_, true); | 308 player_id(), duration_, width_, height_, true); |
| 315 | |
| 316 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | |
| 317 if (reconfig_audio_decoder_) | |
| 318 ConfigureAudioDecoderJob(); | |
| 319 | |
| 320 if (reconfig_video_decoder_) | |
| 321 ConfigureVideoDecoderJob(); | |
| 322 | |
| 323 ClearPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | |
| 324 | |
| 325 // Resume decoding after the config change if we are still playing. | |
| 326 if (playing_) | |
| 327 StartInternal(); | |
| 328 } | |
| 329 } | 309 } |
| 330 | 310 |
| 331 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { | 311 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { |
| 332 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; | 312 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; |
| 333 DCHECK_LT(0u, data.access_units.size()); | 313 DCHECK_LT(0u, data.access_units.size()); |
| 314 CHECK_GE(1u, data.demuxer_configs.size()); |
| 334 | 315 |
| 335 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { | 316 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { |
| 336 has_pending_audio_data_request_ = false; | 317 has_pending_audio_data_request_ = false; |
| 337 ProcessPendingEvents(); | 318 ProcessPendingEvents(); |
| 338 return; | 319 return; |
| 339 } | 320 } |
| 340 | 321 |
| 341 if (has_pending_video_data_request_ && data.type == DemuxerStream::VIDEO) { | 322 if (has_pending_video_data_request_ && data.type == DemuxerStream::VIDEO) { |
| 342 next_video_data_is_iframe_ = false; | 323 next_video_data_is_iframe_ = false; |
| 343 has_pending_video_data_request_ = false; | 324 has_pending_video_data_request_ = false; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 if (audio_decoder_job_) | 470 if (audio_decoder_job_) |
| 490 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime()); | 471 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime()); |
| 491 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); | 472 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); |
| 492 return; | 473 return; |
| 493 } | 474 } |
| 494 | 475 |
| 495 start_time_ticks_ = base::TimeTicks(); | 476 start_time_ticks_ = base::TimeTicks(); |
| 496 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 477 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
| 497 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; | 478 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; |
| 498 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); | 479 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); |
| 499 demuxer_->RequestDemuxerConfigs(); | 480 manager()->OnMediaMetadataChanged( |
| 500 return; | 481 player_id(), duration_, width_, height_, true); |
| 482 |
| 483 if (reconfig_audio_decoder_) |
| 484 ConfigureAudioDecoderJob(); |
| 485 |
| 486 if (reconfig_video_decoder_) |
| 487 ConfigureVideoDecoderJob(); |
| 488 |
| 489 ClearPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
| 501 } | 490 } |
| 502 | 491 |
| 503 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { | 492 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { |
| 504 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; | 493 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; |
| 505 // Setting a new surface will require a new MediaCodec to be created. | 494 // Setting a new surface will require a new MediaCodec to be created. |
| 506 ResetVideoDecoderJob(); | 495 ResetVideoDecoderJob(); |
| 507 ConfigureVideoDecoderJob(); | 496 ConfigureVideoDecoderJob(); |
| 508 | 497 |
| 509 // Return early if we can't successfully configure a new video decoder job | 498 // Return early if we can't successfully configure a new video decoder job |
| 510 // yet. | 499 // yet. |
| 511 if (HasVideo() && !video_decoder_job_) | 500 if (HasVideo() && !video_decoder_job_) |
| 512 return; | 501 return; |
| 513 } | 502 } |
| 514 | 503 |
| 515 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { | 504 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
| 516 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; | 505 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; |
| 517 // If one of the decoder is not initialized, cancel this event as it will be | 506 // If one of the decoder is not initialized, cancel this event as it will be |
| 518 // called later when Start() is called again. | 507 // called later when Start() is called again. |
| 519 if ((HasVideo() && !video_decoder_job_) || | 508 if ((HasVideo() && !video_decoder_job_) || |
| 520 (HasAudio() && !audio_decoder_job_)) { | 509 (HasAudio() && !audio_decoder_job_)) { |
| 521 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 510 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
| 522 return; | 511 return; |
| 523 } | 512 } |
| 524 | 513 |
| 525 DCHECK(audio_decoder_job_ || AudioFinished()); | 514 DCHECK(audio_decoder_job_ || AudioFinished()); |
| 526 DCHECK(video_decoder_job_ || VideoFinished()); | 515 DCHECK(video_decoder_job_ || VideoFinished()); |
| 527 | |
| 528 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); | 516 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); |
| 529 | 517 |
| 530 // It is possible that all streams have finished decode, yet starvation | 518 // It is possible that all streams have finished decode, yet starvation |
| 531 // occurred during the last stream's EOS decode. In this case, prefetch is a | 519 // occurred during the last stream's EOS decode. In this case, prefetch is a |
| 532 // no-op. | 520 // no-op. |
| 533 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 521 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
| 534 if (count == 0) | 522 if (count == 0) |
| 535 return; | 523 return; |
| 536 | 524 |
| 537 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); | 525 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 // If we have a valid timestamp, start the starvation callback. Otherwise, | 630 // If we have a valid timestamp, start the starvation callback. Otherwise, |
| 643 // reset the |start_time_ticks_| so that the next frame will not suffer | 631 // reset the |start_time_ticks_| so that the next frame will not suffer |
| 644 // from the decoding delay caused by the current frame. | 632 // from the decoding delay caused by the current frame. |
| 645 if (current_presentation_timestamp != kNoTimestamp()) | 633 if (current_presentation_timestamp != kNoTimestamp()) |
| 646 StartStarvationCallback(current_presentation_timestamp, | 634 StartStarvationCallback(current_presentation_timestamp, |
| 647 max_presentation_timestamp); | 635 max_presentation_timestamp); |
| 648 else | 636 else |
| 649 start_time_ticks_ = base::TimeTicks::Now(); | 637 start_time_ticks_ = base::TimeTicks::Now(); |
| 650 } | 638 } |
| 651 | 639 |
| 652 if (is_audio) { | 640 if (is_audio) |
| 653 DecodeMoreAudio(); | 641 DecodeMoreAudio(); |
| 654 return; | 642 else |
| 655 } | 643 DecodeMoreVideo(); |
| 656 | 644 |
| 657 DecodeMoreVideo(); | 645 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) |
| 646 ProcessPendingEvents(); |
| 658 } | 647 } |
| 659 | 648 |
| 660 void MediaSourcePlayer::DecodeMoreAudio() { | 649 void MediaSourcePlayer::DecodeMoreAudio() { |
| 661 DVLOG(1) << __FUNCTION__; | 650 DVLOG(1) << __FUNCTION__; |
| 662 DCHECK(!audio_decoder_job_->is_decoding()); | 651 DCHECK(!audio_decoder_job_->is_decoding()); |
| 663 DCHECK(!AudioFinished()); | 652 DCHECK(!AudioFinished()); |
| 664 | 653 |
| 665 if (audio_decoder_job_->Decode( | 654 scoped_ptr<DemuxerConfigs> configs(audio_decoder_job_->Decode( |
| 666 start_time_ticks_, | 655 start_time_ticks_, |
| 667 start_presentation_timestamp_, | 656 start_presentation_timestamp_, |
| 668 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 657 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, |
| 669 weak_factory_.GetWeakPtr(), | 658 weak_factory_.GetWeakPtr(), |
| 670 true))) { | 659 true))); |
| 660 if (!configs) { |
| 671 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", | 661 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", |
| 672 audio_decoder_job_.get()); | 662 audio_decoder_job_.get()); |
| 673 return; | 663 return; |
| 674 } | 664 } |
| 675 | 665 |
| 676 // Failed to start the next decode. | 666 // Failed to start the next decode. |
| 677 // Wait for demuxer ready message. | |
| 678 DCHECK(!reconfig_audio_decoder_); | 667 DCHECK(!reconfig_audio_decoder_); |
| 679 reconfig_audio_decoder_ = true; | 668 reconfig_audio_decoder_ = true; |
| 669 SetDemuxerConfigs(*configs, true); |
| 680 | 670 |
| 681 // Config change may have just been detected on the other stream. If so, | 671 // Config change may have just been detected on the other stream. If so, |
| 682 // don't send a duplicate demuxer config request. | 672 // don't send a duplicate demuxer config request. |
| 683 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 673 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
| 684 DCHECK(reconfig_video_decoder_); | 674 DCHECK(reconfig_video_decoder_); |
| 685 return; | 675 return; |
| 686 } | 676 } |
| 687 | 677 |
| 688 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 678 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
| 689 ProcessPendingEvents(); | |
| 690 } | 679 } |
| 691 | 680 |
| 692 void MediaSourcePlayer::DecodeMoreVideo() { | 681 void MediaSourcePlayer::DecodeMoreVideo() { |
| 693 DVLOG(1) << __FUNCTION__; | 682 DVLOG(1) << __FUNCTION__; |
| 694 DCHECK(!video_decoder_job_->is_decoding()); | 683 DCHECK(!video_decoder_job_->is_decoding()); |
| 695 DCHECK(!VideoFinished()); | 684 DCHECK(!VideoFinished()); |
| 696 | 685 |
| 697 if (video_decoder_job_->Decode( | 686 scoped_ptr<DemuxerConfigs> configs(video_decoder_job_->Decode( |
| 698 start_time_ticks_, | 687 start_time_ticks_, |
| 699 start_presentation_timestamp_, | 688 start_presentation_timestamp_, |
| 700 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 689 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, |
| 701 weak_factory_.GetWeakPtr(), | 690 weak_factory_.GetWeakPtr(), |
| 702 false))) { | 691 false))); |
| 692 if (!configs) { |
| 703 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", | 693 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", |
| 704 video_decoder_job_.get()); | 694 video_decoder_job_.get()); |
| 705 return; | 695 return; |
| 706 } | 696 } |
| 707 | 697 |
| 708 // Failed to start the next decode. | 698 // Failed to start the next decode. |
| 709 // Wait for demuxer ready message. | |
| 710 | |
| 711 // After this detection of video config change, next video data received | 699 // After this detection of video config change, next video data received |
| 712 // will begin with I-frame. | 700 // will begin with I-frame. |
| 713 next_video_data_is_iframe_ = true; | 701 next_video_data_is_iframe_ = true; |
| 714 | 702 |
| 715 DCHECK(!reconfig_video_decoder_); | 703 DCHECK(!reconfig_video_decoder_); |
| 716 reconfig_video_decoder_ = true; | 704 reconfig_video_decoder_ = true; |
| 705 SetDemuxerConfigs(*configs, false); |
| 717 | 706 |
| 718 // Config change may have just been detected on the other stream. If so, | 707 // Config change may have just been detected on the other stream. If so, |
| 719 // don't send a duplicate demuxer config request. | 708 // don't send a duplicate demuxer config request. |
| 720 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 709 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
| 721 DCHECK(reconfig_audio_decoder_); | 710 DCHECK(reconfig_audio_decoder_); |
| 722 return; | 711 return; |
| 723 } | 712 } |
| 724 | 713 |
| 725 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 714 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
| 726 ProcessPendingEvents(); | |
| 727 } | 715 } |
| 728 | 716 |
| 729 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { | 717 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { |
| 730 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; | 718 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; |
| 731 if (is_audio) | 719 if (is_audio) |
| 732 reached_audio_eos_ = true; | 720 reached_audio_eos_ = true; |
| 733 else | 721 else |
| 734 reached_video_eos_ = true; | 722 reached_video_eos_ = true; |
| 735 | 723 |
| 736 if (AudioFinished() && VideoFinished()) { | 724 if (AudioFinished() && VideoFinished()) { |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 start_time_ticks_ = base::TimeTicks::Now(); | 955 start_time_ticks_ = base::TimeTicks::Now(); |
| 968 start_presentation_timestamp_ = GetCurrentTime(); | 956 start_presentation_timestamp_ = GetCurrentTime(); |
| 969 if (!clock_.IsPlaying()) | 957 if (!clock_.IsPlaying()) |
| 970 clock_.Play(); | 958 clock_.Play(); |
| 971 | 959 |
| 972 if (!AudioFinished()) | 960 if (!AudioFinished()) |
| 973 DecodeMoreAudio(); | 961 DecodeMoreAudio(); |
| 974 | 962 |
| 975 if (!VideoFinished()) | 963 if (!VideoFinished()) |
| 976 DecodeMoreVideo(); | 964 DecodeMoreVideo(); |
| 965 |
| 966 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) |
| 967 ProcessPendingEvents(); |
| 977 } | 968 } |
| 978 | 969 |
| 979 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { | 970 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { |
| 980 static const char* kPendingEventNames[] = { | 971 static const char* kPendingEventNames[] = { |
| 981 "SEEK", | 972 "SEEK", |
| 982 "SURFACE_CHANGE", | 973 "SURFACE_CHANGE", |
| 983 "CONFIG_CHANGE", | 974 "CONFIG_CHANGE", |
| 984 "PREFETCH_REQUEST", | 975 "PREFETCH_REQUEST", |
| 985 "PREFETCH_DONE", | 976 "PREFETCH_DONE", |
| 986 }; | 977 }; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1007 } | 998 } |
| 1008 | 999 |
| 1009 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 1000 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
| 1010 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 1001 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
| 1011 DCHECK_NE(event, NO_EVENT_PENDING); | 1002 DCHECK_NE(event, NO_EVENT_PENDING); |
| 1012 DCHECK(IsEventPending(event)) << GetEventName(event); | 1003 DCHECK(IsEventPending(event)) << GetEventName(event); |
| 1013 | 1004 |
| 1014 pending_event_ &= ~event; | 1005 pending_event_ &= ~event; |
| 1015 } | 1006 } |
| 1016 | 1007 |
| 1008 void MediaSourcePlayer::SetDemuxerConfigs(const DemuxerConfigs& configs, |
| 1009 bool is_audio) { |
| 1010 if (is_audio) { |
| 1011 audio_codec_ = configs.audio_codec; |
| 1012 num_channels_ = configs.audio_channels; |
| 1013 sampling_rate_ = configs.audio_sampling_rate; |
| 1014 is_audio_encrypted_ = configs.is_audio_encrypted; |
| 1015 audio_extra_data_ = configs.audio_extra_data; |
| 1016 } else { |
| 1017 video_codec_ = configs.video_codec; |
| 1018 width_ = configs.video_size.width(); |
| 1019 height_ = configs.video_size.height(); |
| 1020 is_video_encrypted_ = configs.is_video_encrypted; |
| 1021 } |
| 1022 } |
| 1023 |
| 1017 } // namespace media | 1024 } // namespace media |
| OLD | NEW |