| 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/audio_timestamp_helper.h" | |
| 23 #include "media/base/buffers.h" | 22 #include "media/base/buffers.h" |
| 24 | 23 |
| 25 namespace { | |
| 26 | |
| 27 // Use 16bit PCM for audio output. Keep this value in sync with the output | |
| 28 // format we passed to AudioTrack in MediaCodecBridge. | |
| 29 const int kBytesPerAudioOutputSample = 2; | |
| 30 } | |
| 31 | |
| 32 namespace media { | 24 namespace media { |
| 33 | 25 |
| 34 MediaSourcePlayer::MediaSourcePlayer( | 26 MediaSourcePlayer::MediaSourcePlayer( |
| 35 int player_id, | 27 int player_id, |
| 36 MediaPlayerManager* manager, | 28 MediaPlayerManager* manager, |
| 37 const RequestMediaResourcesCB& request_media_resources_cb, | 29 const RequestMediaResourcesCB& request_media_resources_cb, |
| 38 const ReleaseMediaResourcesCB& release_media_resources_cb, | 30 const ReleaseMediaResourcesCB& release_media_resources_cb, |
| 39 scoped_ptr<DemuxerAndroid> demuxer) | 31 scoped_ptr<DemuxerAndroid> demuxer) |
| 40 : MediaPlayerAndroid(player_id, | 32 : MediaPlayerAndroid(player_id, |
| 41 manager, | 33 manager, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 } | 102 } |
| 111 | 103 |
| 112 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( | 104 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( |
| 113 base::TimeDelta seek_time) { | 105 base::TimeDelta seek_time) { |
| 114 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; | 106 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; |
| 115 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); | 107 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); |
| 116 | 108 |
| 117 pending_seek_ = false; | 109 pending_seek_ = false; |
| 118 | 110 |
| 119 clock_.SetTime(seek_time, seek_time); | 111 clock_.SetTime(seek_time, seek_time); |
| 120 if (audio_timestamp_helper_) | |
| 121 audio_timestamp_helper_->SetBaseTimestamp(seek_time); | |
| 122 | 112 |
| 123 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) | 113 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) |
| 124 audio_decoder_job_->StopDecode(); | 114 audio_decoder_job_->StopDecode(); |
| 125 if (video_decoder_job_ && video_decoder_job_->is_decoding()) | 115 if (video_decoder_job_ && video_decoder_job_->is_decoding()) |
| 126 video_decoder_job_->StopDecode(); | 116 video_decoder_job_->StopDecode(); |
| 127 | 117 |
| 128 SetPendingEvent(SEEK_EVENT_PENDING); | 118 SetPendingEvent(SEEK_EVENT_PENDING); |
| 129 ProcessPendingEvents(); | 119 ProcessPendingEvents(); |
| 130 } | 120 } |
| 131 | 121 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 const DemuxerConfigs& configs) { | 298 const DemuxerConfigs& configs) { |
| 309 DVLOG(1) << __FUNCTION__; | 299 DVLOG(1) << __FUNCTION__; |
| 310 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); | 300 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); |
| 311 clock_.SetDuration(duration_); | 301 clock_.SetDuration(duration_); |
| 312 | 302 |
| 313 audio_codec_ = configs.audio_codec; | 303 audio_codec_ = configs.audio_codec; |
| 314 num_channels_ = configs.audio_channels; | 304 num_channels_ = configs.audio_channels; |
| 315 sampling_rate_ = configs.audio_sampling_rate; | 305 sampling_rate_ = configs.audio_sampling_rate; |
| 316 is_audio_encrypted_ = configs.is_audio_encrypted; | 306 is_audio_encrypted_ = configs.is_audio_encrypted; |
| 317 audio_extra_data_ = configs.audio_extra_data; | 307 audio_extra_data_ = configs.audio_extra_data; |
| 318 if (HasAudio()) { | |
| 319 DCHECK_GT(num_channels_, 0); | |
| 320 audio_timestamp_helper_.reset(new AudioTimestampHelper(sampling_rate_)); | |
| 321 audio_timestamp_helper_->SetBaseTimestamp(GetCurrentTime()); | |
| 322 } else { | |
| 323 audio_timestamp_helper_.reset(); | |
| 324 } | |
| 325 | |
| 326 video_codec_ = configs.video_codec; | 308 video_codec_ = configs.video_codec; |
| 327 width_ = configs.video_size.width(); | 309 width_ = configs.video_size.width(); |
| 328 height_ = configs.video_size.height(); | 310 height_ = configs.video_size.height(); |
| 329 is_video_encrypted_ = configs.is_video_encrypted; | 311 is_video_encrypted_ = configs.is_video_encrypted; |
| 330 | 312 |
| 331 manager()->OnMediaMetadataChanged( | 313 manager()->OnMediaMetadataChanged( |
| 332 player_id(), duration_, width_, height_, true); | 314 player_id(), duration_, width_, height_, true); |
| 333 | 315 |
| 334 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 316 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
| 335 if (reconfig_audio_decoder_) | 317 if (reconfig_audio_decoder_) |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 // player clock to the actual seek target. | 419 // player clock to the actual seek target. |
| 438 if (doing_browser_seek_) { | 420 if (doing_browser_seek_) { |
| 439 DCHECK(actual_browser_seek_time != kNoTimestamp()); | 421 DCHECK(actual_browser_seek_time != kNoTimestamp()); |
| 440 base::TimeDelta seek_time = actual_browser_seek_time; | 422 base::TimeDelta seek_time = actual_browser_seek_time; |
| 441 // A browser seek must not jump into the past. Ideally, it seeks to the | 423 // A browser seek must not jump into the past. Ideally, it seeks to the |
| 442 // requested time, but it might jump into the future. | 424 // requested time, but it might jump into the future. |
| 443 DCHECK(seek_time >= GetCurrentTime()); | 425 DCHECK(seek_time >= GetCurrentTime()); |
| 444 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " | 426 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " |
| 445 << seek_time.InSecondsF(); | 427 << seek_time.InSecondsF(); |
| 446 clock_.SetTime(seek_time, seek_time); | 428 clock_.SetTime(seek_time, seek_time); |
| 447 if (audio_timestamp_helper_) | 429 if (audio_decoder_job_) |
| 448 audio_timestamp_helper_->SetBaseTimestamp(seek_time); | 430 audio_decoder_job_->SetBaseTimestamp(seek_time); |
| 449 } else { | 431 } else { |
| 450 DCHECK(actual_browser_seek_time == kNoTimestamp()); | 432 DCHECK(actual_browser_seek_time == kNoTimestamp()); |
| 451 } | 433 } |
| 452 | 434 |
| 453 reached_audio_eos_ = false; | 435 reached_audio_eos_ = false; |
| 454 reached_video_eos_ = false; | 436 reached_video_eos_ = false; |
| 455 | 437 |
| 456 base::TimeDelta current_time = GetCurrentTime(); | 438 base::TimeDelta current_time = GetCurrentTime(); |
| 457 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| | 439 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| |
| 458 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| | 440 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| |
| 459 // is calculated from decoder output, while preroll relies on the access | 441 // is calculated from decoder output, while preroll relies on the access |
| 460 // unit's timestamp. There are some differences between the two. | 442 // unit's timestamp. There are some differences between the two. |
| 461 preroll_timestamp_ = current_time; | 443 preroll_timestamp_ = current_time; |
| 462 if (audio_decoder_job_) | 444 if (audio_decoder_job_) |
| 463 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 445 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 464 if (video_decoder_job_) | 446 if (video_decoder_job_) |
| 465 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 447 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 466 | 448 |
| 467 if (!doing_browser_seek_) | 449 if (!doing_browser_seek_) |
| 468 manager()->OnSeekComplete(player_id(), current_time); | 450 manager()->OnSeekComplete(player_id(), current_time); |
| 469 | 451 |
| 470 ProcessPendingEvents(); | 452 ProcessPendingEvents(); |
| 471 } | 453 } |
| 472 | 454 |
| 473 void MediaSourcePlayer::UpdateTimestamps( | 455 void MediaSourcePlayer::UpdateTimestamps( |
| 474 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { | 456 base::TimeDelta current_presentation_timestamp, |
| 475 base::TimeDelta new_max_time = presentation_timestamp; | 457 base::TimeDelta max_presentation_timestamp) { |
| 458 clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp); |
| 476 | 459 |
| 477 if (audio_output_bytes > 0) { | |
| 478 audio_timestamp_helper_->AddFrames( | |
| 479 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); | |
| 480 new_max_time = audio_timestamp_helper_->GetTimestamp(); | |
| 481 } | |
| 482 | |
| 483 clock_.SetMaxTime(new_max_time); | |
| 484 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); | 460 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); |
| 485 } | 461 } |
| 486 | 462 |
| 487 void MediaSourcePlayer::ProcessPendingEvents() { | 463 void MediaSourcePlayer::ProcessPendingEvents() { |
| 488 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; | 464 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; |
| 489 // Wait for all the decoding jobs to finish before processing pending tasks. | 465 // Wait for all the decoding jobs to finish before processing pending tasks. |
| 490 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { | 466 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { |
| 491 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; | 467 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; |
| 492 return; | 468 return; |
| 493 } | 469 } |
| 494 | 470 |
| 495 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) { | 471 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) { |
| 496 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding."; | 472 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding."; |
| 497 return; | 473 return; |
| 498 } | 474 } |
| 499 | 475 |
| 500 if (has_pending_audio_data_request_ || has_pending_video_data_request_) { | 476 if (has_pending_audio_data_request_ || has_pending_video_data_request_) { |
| 501 DVLOG(1) << __FUNCTION__ << " : has pending data request."; | 477 DVLOG(1) << __FUNCTION__ << " : has pending data request."; |
| 502 return; | 478 return; |
| 503 } | 479 } |
| 504 | 480 |
| 505 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { | 481 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { |
| 506 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; | 482 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; |
| 507 return; | 483 return; |
| 508 } | 484 } |
| 509 | 485 |
| 510 if (IsEventPending(SEEK_EVENT_PENDING)) { | 486 if (IsEventPending(SEEK_EVENT_PENDING)) { |
| 511 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT"; | 487 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT"; |
| 512 ClearDecodingData(); | 488 ClearDecodingData(); |
| 489 if (audio_decoder_job_) |
| 490 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime()); |
| 513 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); | 491 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); |
| 514 return; | 492 return; |
| 515 } | 493 } |
| 516 | 494 |
| 517 start_time_ticks_ = base::TimeTicks(); | 495 start_time_ticks_ = base::TimeTicks(); |
| 518 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 496 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
| 519 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; | 497 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; |
| 520 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); | 498 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_); |
| 521 demuxer_->RequestDemuxerConfigs(); | 499 demuxer_->RequestDemuxerConfigs(); |
| 522 return; | 500 return; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); | 552 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); |
| 575 | 553 |
| 576 // Now that all pending events have been handled, resume decoding if we are | 554 // Now that all pending events have been handled, resume decoding if we are |
| 577 // still playing. | 555 // still playing. |
| 578 if (playing_) | 556 if (playing_) |
| 579 StartInternal(); | 557 StartInternal(); |
| 580 } | 558 } |
| 581 | 559 |
| 582 void MediaSourcePlayer::MediaDecoderCallback( | 560 void MediaSourcePlayer::MediaDecoderCallback( |
| 583 bool is_audio, MediaCodecStatus status, | 561 bool is_audio, MediaCodecStatus status, |
| 584 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { | 562 base::TimeDelta current_presentation_timestamp, |
| 563 base::TimeDelta max_presentation_timestamp) { |
| 585 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; | 564 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; |
| 586 | 565 |
| 587 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. | 566 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. |
| 588 if (is_audio) { | 567 if (is_audio) { |
| 589 TRACE_EVENT_ASYNC_END1("media", | 568 TRACE_EVENT_ASYNC_END1("media", |
| 590 "MediaSourcePlayer::DecodeMoreAudio", | 569 "MediaSourcePlayer::DecodeMoreAudio", |
| 591 audio_decoder_job_.get(), | 570 audio_decoder_job_.get(), |
| 592 "MediaCodecStatus", | 571 "MediaCodecStatus", |
| 593 base::IntToString(status)); | 572 base::IntToString(status)); |
| 594 } else { | 573 } else { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 618 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); | 597 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); |
| 619 | 598 |
| 620 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of | 599 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of |
| 621 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process | 600 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process |
| 622 // any other pending events only after handling EOS detection. | 601 // any other pending events only after handling EOS detection. |
| 623 if (IsEventPending(SEEK_EVENT_PENDING)) { | 602 if (IsEventPending(SEEK_EVENT_PENDING)) { |
| 624 ProcessPendingEvents(); | 603 ProcessPendingEvents(); |
| 625 return; | 604 return; |
| 626 } | 605 } |
| 627 | 606 |
| 607 if (status == MEDIA_CODEC_OK && is_clock_manager && |
| 608 current_presentation_timestamp != kNoTimestamp()) { |
| 609 UpdateTimestamps( |
| 610 current_presentation_timestamp, max_presentation_timestamp); |
| 611 } |
| 612 |
| 628 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 613 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
| 629 PlaybackCompleted(is_audio); | 614 PlaybackCompleted(is_audio); |
| 630 | 615 |
| 631 if (pending_event_ != NO_EVENT_PENDING) { | 616 if (pending_event_ != NO_EVENT_PENDING) { |
| 632 ProcessPendingEvents(); | 617 ProcessPendingEvents(); |
| 633 return; | 618 return; |
| 634 } | 619 } |
| 635 | 620 |
| 636 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 621 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
| 637 return; | 622 return; |
| 638 | 623 |
| 639 if (status == MEDIA_CODEC_OK && is_clock_manager && | |
| 640 presentation_timestamp != kNoTimestamp()) { | |
| 641 UpdateTimestamps(presentation_timestamp, audio_output_bytes); | |
| 642 } | |
| 643 | |
| 644 if (!playing_) { | 624 if (!playing_) { |
| 645 if (is_clock_manager) | 625 if (is_clock_manager) |
| 646 clock_.Pause(); | 626 clock_.Pause(); |
| 647 return; | 627 return; |
| 648 } | 628 } |
| 649 | 629 |
| 650 if (status == MEDIA_CODEC_NO_KEY) { | 630 if (status == MEDIA_CODEC_NO_KEY) { |
| 651 is_waiting_for_key_ = true; | 631 is_waiting_for_key_ = true; |
| 652 return; | 632 return; |
| 653 } | 633 } |
| 654 | 634 |
| 655 // If the status is MEDIA_CODEC_STOPPED, stop decoding new data. The player is | 635 // If the status is MEDIA_CODEC_STOPPED, stop decoding new data. The player is |
| 656 // in the middle of a seek or stop event and needs to wait for the IPCs to | 636 // in the middle of a seek or stop event and needs to wait for the IPCs to |
| 657 // come. | 637 // come. |
| 658 if (status == MEDIA_CODEC_STOPPED) | 638 if (status == MEDIA_CODEC_STOPPED) |
| 659 return; | 639 return; |
| 660 | 640 |
| 661 if (is_clock_manager) { | 641 if (is_clock_manager) { |
| 662 // If we have a valid timestamp, start the starvation callback. Otherwise, | 642 // If we have a valid timestamp, start the starvation callback. Otherwise, |
| 663 // reset the |start_time_ticks_| so that the next frame will not suffer | 643 // reset the |start_time_ticks_| so that the next frame will not suffer |
| 664 // from the decoding delay caused by the current frame. | 644 // from the decoding delay caused by the current frame. |
| 665 if (presentation_timestamp != kNoTimestamp()) | 645 if (current_presentation_timestamp != kNoTimestamp()) |
| 666 StartStarvationCallback(presentation_timestamp); | 646 StartStarvationCallback(current_presentation_timestamp, |
| 647 max_presentation_timestamp); |
| 667 else | 648 else |
| 668 start_time_ticks_ = base::TimeTicks::Now(); | 649 start_time_ticks_ = base::TimeTicks::Now(); |
| 669 } | 650 } |
| 670 | 651 |
| 671 if (is_audio) { | 652 if (is_audio) { |
| 672 DecodeMoreAudio(); | 653 DecodeMoreAudio(); |
| 673 return; | 654 return; |
| 674 } | 655 } |
| 675 | 656 |
| 676 DecodeMoreVideo(); | 657 DecodeMoreVideo(); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 ResetAudioDecoderJob(); | 785 ResetAudioDecoderJob(); |
| 805 DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job"; | 786 DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job"; |
| 806 audio_decoder_job_.reset(AudioDecoderJob::Create( | 787 audio_decoder_job_.reset(AudioDecoderJob::Create( |
| 807 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0], | 788 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0], |
| 808 audio_extra_data_.size(), media_crypto.obj(), | 789 audio_extra_data_.size(), media_crypto.obj(), |
| 809 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 790 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
| 810 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); | 791 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO))); |
| 811 | 792 |
| 812 if (audio_decoder_job_) { | 793 if (audio_decoder_job_) { |
| 813 SetVolumeInternal(); | 794 SetVolumeInternal(); |
| 795 // Need to reset the base timestamp in |audio_decoder_job_|. |
| 796 // TODO(qinmin): When reconfiguring the |audio_decoder_job_|, there might |
| 797 // still be some audio frames in the decoder or in AudioTrack. Therefore, |
| 798 // we are losing some time here. http://crbug.com/357726. |
| 799 base::TimeDelta current_time = GetCurrentTime(); |
| 800 audio_decoder_job_->SetBaseTimestamp(current_time); |
| 801 clock_.SetTime(current_time, current_time); |
| 814 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 802 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 815 reconfig_audio_decoder_ = false; | 803 reconfig_audio_decoder_ = false; |
| 816 } | 804 } |
| 817 } | 805 } |
| 818 | 806 |
| 819 void MediaSourcePlayer::ResetVideoDecoderJob() { | 807 void MediaSourcePlayer::ResetVideoDecoderJob() { |
| 820 if (video_decoder_job_) { | 808 if (video_decoder_job_) { |
| 821 has_pending_video_data_request_ = | 809 has_pending_video_data_request_ = |
| 822 video_decoder_job_->is_requesting_demuxer_data(); | 810 video_decoder_job_->is_requesting_demuxer_data(); |
| 823 } | 811 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 player_id(), duration_, width_, height_, true); | 893 player_id(), duration_, width_, height_, true); |
| 906 } | 894 } |
| 907 | 895 |
| 908 void MediaSourcePlayer::OnDecoderStarved() { | 896 void MediaSourcePlayer::OnDecoderStarved() { |
| 909 DVLOG(1) << __FUNCTION__; | 897 DVLOG(1) << __FUNCTION__; |
| 910 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 898 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
| 911 ProcessPendingEvents(); | 899 ProcessPendingEvents(); |
| 912 } | 900 } |
| 913 | 901 |
| 914 void MediaSourcePlayer::StartStarvationCallback( | 902 void MediaSourcePlayer::StartStarvationCallback( |
| 915 base::TimeDelta presentation_timestamp) { | 903 base::TimeDelta current_presentation_timestamp, |
| 904 base::TimeDelta max_presentation_timestamp) { |
| 916 // 20ms was chosen because it is the typical size of a compressed audio frame. | 905 // 20ms was chosen because it is the typical size of a compressed audio frame. |
| 917 // Anything smaller than this would likely cause unnecessary cycling in and | 906 // Anything smaller than this would likely cause unnecessary cycling in and |
| 918 // out of the prefetch state. | 907 // out of the prefetch state. |
| 919 const base::TimeDelta kMinStarvationTimeout = | 908 const base::TimeDelta kMinStarvationTimeout = |
| 920 base::TimeDelta::FromMilliseconds(20); | 909 base::TimeDelta::FromMilliseconds(20); |
| 921 | 910 |
| 922 base::TimeDelta current_timestamp = GetCurrentTime(); | 911 base::TimeDelta current_timestamp = GetCurrentTime(); |
| 923 base::TimeDelta timeout; | 912 base::TimeDelta timeout; |
| 924 if (HasAudio()) { | 913 if (HasAudio()) { |
| 925 timeout = audio_timestamp_helper_->GetTimestamp() - current_timestamp; | 914 timeout = max_presentation_timestamp - current_timestamp; |
| 926 } else { | 915 } else { |
| 927 DCHECK(current_timestamp <= presentation_timestamp); | 916 DCHECK(current_timestamp <= current_presentation_timestamp); |
| 928 | 917 |
| 929 // For video only streams, fps can be estimated from the difference | 918 // For video only streams, fps can be estimated from the difference |
| 930 // between the previous and current presentation timestamps. The | 919 // between the previous and current presentation timestamps. The |
| 931 // previous presentation timestamp is equal to current_timestamp. | 920 // previous presentation timestamp is equal to current_timestamp. |
| 932 // TODO(qinmin): determine whether 2 is a good coefficient for estimating | 921 // TODO(qinmin): determine whether 2 is a good coefficient for estimating |
| 933 // video frame timeout. | 922 // video frame timeout. |
| 934 timeout = 2 * (presentation_timestamp - current_timestamp); | 923 timeout = 2 * (current_presentation_timestamp - current_timestamp); |
| 935 } | 924 } |
| 936 | 925 |
| 937 timeout = std::max(timeout, kMinStarvationTimeout); | 926 timeout = std::max(timeout, kMinStarvationTimeout); |
| 938 | 927 |
| 939 decoder_starvation_callback_.Reset(base::Bind( | 928 decoder_starvation_callback_.Reset(base::Bind( |
| 940 &MediaSourcePlayer::OnDecoderStarved, weak_factory_.GetWeakPtr())); | 929 &MediaSourcePlayer::OnDecoderStarved, weak_factory_.GetWeakPtr())); |
| 941 base::MessageLoop::current()->PostDelayedTask( | 930 base::MessageLoop::current()->PostDelayedTask( |
| 942 FROM_HERE, decoder_starvation_callback_.callback(), timeout); | 931 FROM_HERE, decoder_starvation_callback_.callback(), timeout); |
| 943 } | 932 } |
| 944 | 933 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1019 | 1008 |
| 1020 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 1009 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
| 1021 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 1010 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
| 1022 DCHECK_NE(event, NO_EVENT_PENDING); | 1011 DCHECK_NE(event, NO_EVENT_PENDING); |
| 1023 DCHECK(IsEventPending(event)) << GetEventName(event); | 1012 DCHECK(IsEventPending(event)) << GetEventName(event); |
| 1024 | 1013 |
| 1025 pending_event_ &= ~event; | 1014 pending_event_ &= ~event; |
| 1026 } | 1015 } |
| 1027 | 1016 |
| 1028 } // namespace media | 1017 } // namespace media |
| OLD | NEW |