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()); |
334 | 314 |
335 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { | 315 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { |
336 has_pending_audio_data_request_ = false; | 316 has_pending_audio_data_request_ = false; |
337 ProcessPendingEvents(); | 317 ProcessPendingEvents(); |
338 return; | 318 return; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 if (audio_decoder_job_) | 469 if (audio_decoder_job_) |
490 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime()); | 470 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime()); |
491 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); | 471 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); |
492 return; | 472 return; |
493 } | 473 } |
494 | 474 |
495 start_time_ticks_ = base::TimeTicks(); | 475 start_time_ticks_ = base::TimeTicks(); |
496 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 476 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
497 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; | 477 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; |
498 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); | 478 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); |
499 demuxer_->RequestDemuxerConfigs(); | 479 manager()->OnMediaMetadataChanged( |
500 return; | 480 player_id(), duration_, width_, height_, true); |
481 | |
482 if (reconfig_audio_decoder_) | |
483 ConfigureAudioDecoderJob(); | |
484 | |
485 if (reconfig_video_decoder_) | |
486 ConfigureVideoDecoderJob(); | |
487 | |
488 ClearPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | |
501 } | 489 } |
502 | 490 |
503 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { | 491 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) { |
504 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; | 492 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT."; |
505 // Setting a new surface will require a new MediaCodec to be created. | 493 // Setting a new surface will require a new MediaCodec to be created. |
506 ResetVideoDecoderJob(); | 494 ResetVideoDecoderJob(); |
507 ConfigureVideoDecoderJob(); | 495 ConfigureVideoDecoderJob(); |
508 | 496 |
509 // Return early if we can't successfully configure a new video decoder job | 497 // Return early if we can't successfully configure a new video decoder job |
510 // yet. | 498 // yet. |
511 if (HasVideo() && !video_decoder_job_) | 499 if (HasVideo() && !video_decoder_job_) |
512 return; | 500 return; |
513 } | 501 } |
514 | 502 |
515 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { | 503 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
516 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; | 504 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; |
517 // If one of the decoder is not initialized, cancel this event as it will be | 505 // If one of the decoder is not initialized, cancel this event as it will be |
518 // called later when Start() is called again. | 506 // called later when Start() is called again. |
519 if ((HasVideo() && !video_decoder_job_) || | 507 if ((HasVideo() && !video_decoder_job_) || |
520 (HasAudio() && !audio_decoder_job_)) { | 508 (HasAudio() && !audio_decoder_job_)) { |
521 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 509 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
522 return; | 510 return; |
523 } | 511 } |
524 | 512 |
525 DCHECK(audio_decoder_job_ || AudioFinished()); | 513 DCHECK(audio_decoder_job_ || AudioFinished()); |
526 DCHECK(video_decoder_job_ || VideoFinished()); | 514 DCHECK(video_decoder_job_ || VideoFinished()); |
527 | |
528 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); | 515 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); |
529 | 516 |
530 // It is possible that all streams have finished decode, yet starvation | 517 // 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 | 518 // occurred during the last stream's EOS decode. In this case, prefetch is a |
532 // no-op. | 519 // no-op. |
533 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 520 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
534 if (count == 0) | 521 if (count == 0) |
535 return; | 522 return; |
536 | 523 |
537 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); | 524 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, | 629 // 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 | 630 // reset the |start_time_ticks_| so that the next frame will not suffer |
644 // from the decoding delay caused by the current frame. | 631 // from the decoding delay caused by the current frame. |
645 if (current_presentation_timestamp != kNoTimestamp()) | 632 if (current_presentation_timestamp != kNoTimestamp()) |
646 StartStarvationCallback(current_presentation_timestamp, | 633 StartStarvationCallback(current_presentation_timestamp, |
647 max_presentation_timestamp); | 634 max_presentation_timestamp); |
648 else | 635 else |
649 start_time_ticks_ = base::TimeTicks::Now(); | 636 start_time_ticks_ = base::TimeTicks::Now(); |
650 } | 637 } |
651 | 638 |
652 if (is_audio) { | 639 if (is_audio) |
653 DecodeMoreAudio(); | 640 DecodeMoreAudio(); |
654 return; | 641 else |
655 } | 642 DecodeMoreVideo(); |
656 | 643 |
657 DecodeMoreVideo(); | 644 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) |
645 ProcessPendingEvents(); | |
658 } | 646 } |
659 | 647 |
660 void MediaSourcePlayer::DecodeMoreAudio() { | 648 void MediaSourcePlayer::DecodeMoreAudio() { |
661 DVLOG(1) << __FUNCTION__; | 649 DVLOG(1) << __FUNCTION__; |
662 DCHECK(!audio_decoder_job_->is_decoding()); | 650 DCHECK(!audio_decoder_job_->is_decoding()); |
663 DCHECK(!AudioFinished()); | 651 DCHECK(!AudioFinished()); |
664 | 652 |
665 if (audio_decoder_job_->Decode( | 653 scoped_ptr<DemuxerConfigs> configs(audio_decoder_job_->Decode( |
666 start_time_ticks_, | 654 start_time_ticks_, |
667 start_presentation_timestamp_, | 655 start_presentation_timestamp_, |
668 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 656 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, |
669 weak_factory_.GetWeakPtr(), | 657 weak_factory_.GetWeakPtr(), |
670 true))) { | 658 true)).Pass()); |
wolenetz
2014/05/06 19:58:49
nit: I'm not sure .Pass() is needed here.
Looking
qinmin
2014/05/06 20:56:20
Done.
On 2014/05/06 19:58:49, wolenetz wrote:
| |
659 if (!configs) { | |
671 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", | 660 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", |
672 audio_decoder_job_.get()); | 661 audio_decoder_job_.get()); |
673 return; | 662 return; |
674 } | 663 } |
675 | 664 |
676 // Failed to start the next decode. | 665 // Failed to start the next decode. |
677 // Wait for demuxer ready message. | |
678 DCHECK(!reconfig_audio_decoder_); | 666 DCHECK(!reconfig_audio_decoder_); |
679 reconfig_audio_decoder_ = true; | 667 reconfig_audio_decoder_ = true; |
668 SetDemuxerConfigs(*configs, true); | |
680 | 669 |
681 // Config change may have just been detected on the other stream. If so, | 670 // Config change may have just been detected on the other stream. If so, |
682 // don't send a duplicate demuxer config request. | 671 // don't send a duplicate demuxer config request. |
683 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 672 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
684 DCHECK(reconfig_video_decoder_); | 673 DCHECK(reconfig_video_decoder_); |
685 return; | 674 return; |
686 } | 675 } |
687 | 676 |
688 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 677 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
689 ProcessPendingEvents(); | |
690 } | 678 } |
691 | 679 |
692 void MediaSourcePlayer::DecodeMoreVideo() { | 680 void MediaSourcePlayer::DecodeMoreVideo() { |
693 DVLOG(1) << __FUNCTION__; | 681 DVLOG(1) << __FUNCTION__; |
694 DCHECK(!video_decoder_job_->is_decoding()); | 682 DCHECK(!video_decoder_job_->is_decoding()); |
695 DCHECK(!VideoFinished()); | 683 DCHECK(!VideoFinished()); |
696 | 684 |
697 if (video_decoder_job_->Decode( | 685 scoped_ptr<DemuxerConfigs> configs(video_decoder_job_->Decode( |
698 start_time_ticks_, | 686 start_time_ticks_, |
699 start_presentation_timestamp_, | 687 start_presentation_timestamp_, |
700 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 688 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, |
701 weak_factory_.GetWeakPtr(), | 689 weak_factory_.GetWeakPtr(), |
702 false))) { | 690 false)).Pass()); |
wolenetz
2014/05/06 19:58:49
nit: ditto
qinmin
2014/05/06 20:56:20
Done.
| |
691 if (!configs) { | |
703 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", | 692 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", |
704 video_decoder_job_.get()); | 693 video_decoder_job_.get()); |
705 return; | 694 return; |
706 } | 695 } |
707 | 696 |
708 // Failed to start the next decode. | 697 // 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 | 698 // After this detection of video config change, next video data received |
712 // will begin with I-frame. | 699 // will begin with I-frame. |
713 next_video_data_is_iframe_ = true; | 700 next_video_data_is_iframe_ = true; |
714 | 701 |
715 DCHECK(!reconfig_video_decoder_); | 702 DCHECK(!reconfig_video_decoder_); |
716 reconfig_video_decoder_ = true; | 703 reconfig_video_decoder_ = true; |
704 SetDemuxerConfigs(*configs, false); | |
717 | 705 |
718 // Config change may have just been detected on the other stream. If so, | 706 // Config change may have just been detected on the other stream. If so, |
719 // don't send a duplicate demuxer config request. | 707 // don't send a duplicate demuxer config request. |
720 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 708 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
721 DCHECK(reconfig_audio_decoder_); | 709 DCHECK(reconfig_audio_decoder_); |
722 return; | 710 return; |
723 } | 711 } |
724 | 712 |
725 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 713 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
726 ProcessPendingEvents(); | |
727 } | 714 } |
728 | 715 |
729 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { | 716 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { |
730 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; | 717 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; |
731 if (is_audio) | 718 if (is_audio) |
732 reached_audio_eos_ = true; | 719 reached_audio_eos_ = true; |
733 else | 720 else |
734 reached_video_eos_ = true; | 721 reached_video_eos_ = true; |
735 | 722 |
736 if (AudioFinished() && VideoFinished()) { | 723 if (AudioFinished() && VideoFinished()) { |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
967 start_time_ticks_ = base::TimeTicks::Now(); | 954 start_time_ticks_ = base::TimeTicks::Now(); |
968 start_presentation_timestamp_ = GetCurrentTime(); | 955 start_presentation_timestamp_ = GetCurrentTime(); |
969 if (!clock_.IsPlaying()) | 956 if (!clock_.IsPlaying()) |
970 clock_.Play(); | 957 clock_.Play(); |
971 | 958 |
972 if (!AudioFinished()) | 959 if (!AudioFinished()) |
973 DecodeMoreAudio(); | 960 DecodeMoreAudio(); |
974 | 961 |
975 if (!VideoFinished()) | 962 if (!VideoFinished()) |
976 DecodeMoreVideo(); | 963 DecodeMoreVideo(); |
964 | |
965 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) | |
966 ProcessPendingEvents(); | |
977 } | 967 } |
978 | 968 |
979 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { | 969 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { |
980 static const char* kPendingEventNames[] = { | 970 static const char* kPendingEventNames[] = { |
981 "SEEK", | 971 "SEEK", |
982 "SURFACE_CHANGE", | 972 "SURFACE_CHANGE", |
983 "CONFIG_CHANGE", | 973 "CONFIG_CHANGE", |
984 "PREFETCH_REQUEST", | 974 "PREFETCH_REQUEST", |
985 "PREFETCH_DONE", | 975 "PREFETCH_DONE", |
986 }; | 976 }; |
(...skipping 20 matching lines...) Expand all Loading... | |
1007 } | 997 } |
1008 | 998 |
1009 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 999 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
1010 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 1000 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
1011 DCHECK_NE(event, NO_EVENT_PENDING); | 1001 DCHECK_NE(event, NO_EVENT_PENDING); |
1012 DCHECK(IsEventPending(event)) << GetEventName(event); | 1002 DCHECK(IsEventPending(event)) << GetEventName(event); |
1013 | 1003 |
1014 pending_event_ &= ~event; | 1004 pending_event_ &= ~event; |
1015 } | 1005 } |
1016 | 1006 |
1007 void MediaSourcePlayer::SetDemuxerConfigs(const DemuxerConfigs& configs, | |
1008 bool is_audio) { | |
1009 if (is_audio) { | |
1010 audio_codec_ = configs.audio_codec; | |
1011 num_channels_ = configs.audio_channels; | |
1012 sampling_rate_ = configs.audio_sampling_rate; | |
1013 is_audio_encrypted_ = configs.is_audio_encrypted; | |
1014 audio_extra_data_ = configs.audio_extra_data; | |
1015 } else { | |
1016 video_codec_ = configs.video_codec; | |
1017 width_ = configs.video_size.width(); | |
1018 height_ = configs.video_size.height(); | |
1019 is_video_encrypted_ = configs.is_video_encrypted; | |
1020 } | |
1021 } | |
1022 | |
1017 } // namespace media | 1023 } // namespace media |
OLD | NEW |