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