Chromium Code Reviews| 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" |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 DVLOG(1) << __FUNCTION__; | 309 DVLOG(1) << __FUNCTION__; |
| 310 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); | 310 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); |
| 311 clock_.SetDuration(duration_); | 311 clock_.SetDuration(duration_); |
| 312 | 312 |
| 313 audio_codec_ = configs.audio_codec; | 313 audio_codec_ = configs.audio_codec; |
| 314 num_channels_ = configs.audio_channels; | 314 num_channels_ = configs.audio_channels; |
| 315 sampling_rate_ = configs.audio_sampling_rate; | 315 sampling_rate_ = configs.audio_sampling_rate; |
| 316 is_audio_encrypted_ = configs.is_audio_encrypted; | 316 is_audio_encrypted_ = configs.is_audio_encrypted; |
| 317 audio_extra_data_ = configs.audio_extra_data; | 317 audio_extra_data_ = configs.audio_extra_data; |
| 318 if (HasAudio()) { | 318 if (HasAudio()) { |
| 319 DCHECK_GT(num_channels_, 0); | 319 if (reconfig_audio_decoder_ || !audio_decoder_job_) { |
| 320 audio_timestamp_helper_.reset(new AudioTimestampHelper(sampling_rate_)); | 320 DCHECK_GT(num_channels_, 0); |
| 321 audio_timestamp_helper_->SetBaseTimestamp(GetCurrentTime()); | 321 audio_timestamp_helper_.reset(new AudioTimestampHelper(sampling_rate_)); |
| 322 audio_timestamp_helper_->SetBaseTimestamp(GetCurrentTime()); | |
| 323 } | |
| 322 } else { | 324 } else { |
| 323 audio_timestamp_helper_.reset(); | 325 audio_timestamp_helper_.reset(); |
| 324 } | 326 } |
| 325 | 327 |
| 326 video_codec_ = configs.video_codec; | 328 video_codec_ = configs.video_codec; |
| 327 width_ = configs.video_size.width(); | 329 width_ = configs.video_size.width(); |
| 328 height_ = configs.video_size.height(); | 330 height_ = configs.video_size.height(); |
| 329 is_video_encrypted_ = configs.is_video_encrypted; | 331 is_video_encrypted_ = configs.is_video_encrypted; |
| 330 | 332 |
| 331 manager()->OnMediaMetadataChanged( | 333 manager()->OnMediaMetadataChanged( |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 if (video_decoder_job_) | 466 if (video_decoder_job_) |
| 465 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 467 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
| 466 | 468 |
| 467 if (!doing_browser_seek_) | 469 if (!doing_browser_seek_) |
| 468 manager()->OnSeekComplete(player_id(), current_time); | 470 manager()->OnSeekComplete(player_id(), current_time); |
| 469 | 471 |
| 470 ProcessPendingEvents(); | 472 ProcessPendingEvents(); |
| 471 } | 473 } |
| 472 | 474 |
| 473 void MediaSourcePlayer::UpdateTimestamps( | 475 void MediaSourcePlayer::UpdateTimestamps( |
| 474 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { | 476 base::TimeDelta presentation_timestamp, size_t audio_output_bytes, |
| 475 base::TimeDelta new_max_time = presentation_timestamp; | 477 int64 audio_head_position, base::TimeTicks audio_render_time) { |
| 476 | 478 // If audio is present and there is no audio data passed to the AudioTrack, |
| 479 // just let the clock progress by itself. | |
| 477 if (audio_output_bytes > 0) { | 480 if (audio_output_bytes > 0) { |
| 478 audio_timestamp_helper_->AddFrames( | 481 audio_timestamp_helper_->AddFrames( |
| 479 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); | 482 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); |
| 480 new_max_time = audio_timestamp_helper_->GetTimestamp(); | 483 int64 frames_to_play = |
| 484 audio_timestamp_helper_->frame_count() - audio_head_position; | |
| 485 DCHECK_GE(frames_to_play, 0); | |
| 486 base::TimeDelta new_max_time = audio_timestamp_helper_->GetTimestamp(); | |
| 487 // Do a rough estimation of the current presentation time, assuming | |
| 488 // playback is smooth since the last time send the data to the AudioTrack. | |
| 489 base::TimeDelta current_presentation_timestamp = | |
| 490 base::TimeTicks::Now() - audio_render_time + new_max_time - | |
| 491 audio_timestamp_helper_->GetFrameDuration(frames_to_play); | |
| 492 if (current_presentation_timestamp >= new_max_time) | |
| 493 current_presentation_timestamp = new_max_time; | |
|
acolwell GONE FROM CHROMIUM
2014/04/04 19:25:58
It feels like the bulk of this logic should be in
qinmin
2014/04/04 19:42:51
ok, I will move the logic there.
However, the rec
| |
| 494 clock_.SetTime(current_presentation_timestamp, new_max_time); | |
| 495 } else if (!HasAudio()) { | |
| 496 clock_.SetMaxTime(presentation_timestamp); | |
| 481 } | 497 } |
| 482 | 498 |
| 483 clock_.SetMaxTime(new_max_time); | |
| 484 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); | 499 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); |
| 485 } | 500 } |
| 486 | 501 |
| 487 void MediaSourcePlayer::ProcessPendingEvents() { | 502 void MediaSourcePlayer::ProcessPendingEvents() { |
| 488 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; | 503 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; |
| 489 // Wait for all the decoding jobs to finish before processing pending tasks. | 504 // Wait for all the decoding jobs to finish before processing pending tasks. |
| 490 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { | 505 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { |
| 491 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; | 506 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; |
| 492 return; | 507 return; |
| 493 } | 508 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); | 589 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); |
| 575 | 590 |
| 576 // Now that all pending events have been handled, resume decoding if we are | 591 // Now that all pending events have been handled, resume decoding if we are |
| 577 // still playing. | 592 // still playing. |
| 578 if (playing_) | 593 if (playing_) |
| 579 StartInternal(); | 594 StartInternal(); |
| 580 } | 595 } |
| 581 | 596 |
| 582 void MediaSourcePlayer::MediaDecoderCallback( | 597 void MediaSourcePlayer::MediaDecoderCallback( |
| 583 bool is_audio, MediaCodecStatus status, | 598 bool is_audio, MediaCodecStatus status, |
| 584 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { | 599 base::TimeDelta presentation_timestamp, size_t audio_output_bytes, |
| 600 int64 audio_head_position, base::TimeTicks audio_render_time) { | |
| 585 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; | 601 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; |
| 602 DCHECK(is_audio || (audio_output_bytes == 0 && audio_head_position == 0 && | |
| 603 audio_render_time.is_null())); | |
| 586 | 604 |
| 587 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. | 605 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. |
| 588 if (is_audio) { | 606 if (is_audio) { |
| 589 TRACE_EVENT_ASYNC_END1("media", | 607 TRACE_EVENT_ASYNC_END1("media", |
| 590 "MediaSourcePlayer::DecodeMoreAudio", | 608 "MediaSourcePlayer::DecodeMoreAudio", |
| 591 audio_decoder_job_.get(), | 609 audio_decoder_job_.get(), |
| 592 "MediaCodecStatus", | 610 "MediaCodecStatus", |
| 593 base::IntToString(status)); | 611 base::IntToString(status)); |
| 594 } else { | 612 } else { |
| 595 TRACE_EVENT_ASYNC_END1("media", | 613 TRACE_EVENT_ASYNC_END1("media", |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 618 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); | 636 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); |
| 619 | 637 |
| 620 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of | 638 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of |
| 621 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process | 639 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process |
| 622 // any other pending events only after handling EOS detection. | 640 // any other pending events only after handling EOS detection. |
| 623 if (IsEventPending(SEEK_EVENT_PENDING)) { | 641 if (IsEventPending(SEEK_EVENT_PENDING)) { |
| 624 ProcessPendingEvents(); | 642 ProcessPendingEvents(); |
| 625 return; | 643 return; |
| 626 } | 644 } |
| 627 | 645 |
| 646 if (status == MEDIA_CODEC_OK && is_clock_manager && | |
| 647 presentation_timestamp != kNoTimestamp()) { | |
| 648 UpdateTimestamps( | |
| 649 presentation_timestamp, audio_output_bytes, audio_head_position, | |
| 650 audio_render_time); | |
| 651 } | |
| 652 | |
| 628 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 653 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
| 629 PlaybackCompleted(is_audio); | 654 PlaybackCompleted(is_audio); |
| 630 | 655 |
| 631 if (pending_event_ != NO_EVENT_PENDING) { | 656 if (pending_event_ != NO_EVENT_PENDING) { |
| 632 ProcessPendingEvents(); | 657 ProcessPendingEvents(); |
| 633 return; | 658 return; |
| 634 } | 659 } |
| 635 | 660 |
| 636 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 661 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
| 637 return; | 662 return; |
| 638 | 663 |
| 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_) { | 664 if (!playing_) { |
| 645 if (is_clock_manager) | 665 if (is_clock_manager) |
| 646 clock_.Pause(); | 666 clock_.Pause(); |
| 647 return; | 667 return; |
| 648 } | 668 } |
| 649 | 669 |
| 650 if (status == MEDIA_CODEC_NO_KEY) { | 670 if (status == MEDIA_CODEC_NO_KEY) { |
| 651 is_waiting_for_key_ = true; | 671 is_waiting_for_key_ = true; |
| 652 return; | 672 return; |
| 653 } | 673 } |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1019 | 1039 |
| 1020 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 1040 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
| 1021 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 1041 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
| 1022 DCHECK_NE(event, NO_EVENT_PENDING); | 1042 DCHECK_NE(event, NO_EVENT_PENDING); |
| 1023 DCHECK(IsEventPending(event)) << GetEventName(event); | 1043 DCHECK(IsEventPending(event)) << GetEventName(event); |
| 1024 | 1044 |
| 1025 pending_event_ &= ~event; | 1045 pending_event_ &= ~event; |
| 1026 } | 1046 } |
| 1027 | 1047 |
| 1028 } // namespace media | 1048 } // namespace media |
| OLD | NEW |