Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: media/base/android/media_source_player.cc

Issue 215783002: Fix an issue that audio and video may run out of sync (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: adding TODO for pointer comparison Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/android/media_source_player.h ('k') | media/base/android/media_source_player_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698