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

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: Created 6 years, 9 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
477 if (audio_output_bytes > 0) { 478 if (audio_output_bytes > 0) {
478 audio_timestamp_helper_->AddFrames( 479 audio_timestamp_helper_->AddFrames(
479 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); 480 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_));
480 new_max_time = audio_timestamp_helper_->GetTimestamp(); 481 int64 frames_to_play =
482 audio_timestamp_helper_->frame_count() - audio_head_position;
483 DCHECK(frames_to_play >= 0);
wolenetz 2014/04/01 18:15:47 nit: lint: "Consider using DCHECK_GE instead of DC
qinmin 2014/04/01 20:42:34 Done.
484 base::TimeDelta new_max_time = audio_timestamp_helper_->GetTimestamp();
485 base::TimeDelta current_presentation_timestamp =
486 base::TimeTicks::Now() - audio_render_time + new_max_time -
487 audio_timestamp_helper_->GetFrameDuration(frames_to_play);
488 if (current_presentation_timestamp >= new_max_time)
489 current_presentation_timestamp = new_max_time;
490 clock_.SetTime(current_presentation_timestamp, new_max_time);
491 } else {
492 clock_.SetMaxTime(presentation_timestamp);
481 } 493 }
482 494
483 clock_.SetMaxTime(new_max_time);
484 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); 495 manager()->OnTimeUpdate(player_id(), GetCurrentTime());
485 } 496 }
486 497
487 void MediaSourcePlayer::ProcessPendingEvents() { 498 void MediaSourcePlayer::ProcessPendingEvents() {
488 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; 499 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_;
489 // Wait for all the decoding jobs to finish before processing pending tasks. 500 // Wait for all the decoding jobs to finish before processing pending tasks.
490 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { 501 if (video_decoder_job_ && video_decoder_job_->is_decoding()) {
491 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; 502 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding.";
492 return; 503 return;
493 } 504 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); 585 DCHECK_EQ(pending_event_, NO_EVENT_PENDING);
575 586
576 // Now that all pending events have been handled, resume decoding if we are 587 // Now that all pending events have been handled, resume decoding if we are
577 // still playing. 588 // still playing.
578 if (playing_) 589 if (playing_)
579 StartInternal(); 590 StartInternal();
580 } 591 }
581 592
582 void MediaSourcePlayer::MediaDecoderCallback( 593 void MediaSourcePlayer::MediaDecoderCallback(
583 bool is_audio, MediaCodecStatus status, 594 bool is_audio, MediaCodecStatus status,
584 base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { 595 base::TimeDelta presentation_timestamp, size_t audio_output_bytes,
596 int64 audio_head_position, base::TimeTicks audio_render_time) {
585 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; 597 DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status;
586 598
587 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. 599 // TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed.
588 if (is_audio) { 600 if (is_audio) {
589 TRACE_EVENT_ASYNC_END1("media", 601 TRACE_EVENT_ASYNC_END1("media",
590 "MediaSourcePlayer::DecodeMoreAudio", 602 "MediaSourcePlayer::DecodeMoreAudio",
591 audio_decoder_job_.get(), 603 audio_decoder_job_.get(),
592 "MediaCodecStatus", 604 "MediaCodecStatus",
593 base::IntToString(status)); 605 base::IntToString(status));
594 } else { 606 } else {
(...skipping 23 matching lines...) Expand all
618 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); 630 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING));
619 631
620 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of 632 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of
621 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process 633 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process
622 // any other pending events only after handling EOS detection. 634 // any other pending events only after handling EOS detection.
623 if (IsEventPending(SEEK_EVENT_PENDING)) { 635 if (IsEventPending(SEEK_EVENT_PENDING)) {
624 ProcessPendingEvents(); 636 ProcessPendingEvents();
625 return; 637 return;
626 } 638 }
627 639
640 if (status == MEDIA_CODEC_OK && is_clock_manager &&
641 presentation_timestamp != kNoTimestamp()) {
642 UpdateTimestamps(
643 presentation_timestamp, audio_output_bytes, audio_head_position,
644 audio_render_time);
645 }
646
628 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) 647 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM)
629 PlaybackCompleted(is_audio); 648 PlaybackCompleted(is_audio);
630 649
631 if (pending_event_ != NO_EVENT_PENDING) { 650 if (pending_event_ != NO_EVENT_PENDING) {
632 ProcessPendingEvents(); 651 ProcessPendingEvents();
633 return; 652 return;
634 } 653 }
635 654
636 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) 655 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM)
637 return; 656 return;
638 657
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_) { 658 if (!playing_) {
645 if (is_clock_manager) 659 if (is_clock_manager)
646 clock_.Pause(); 660 clock_.Pause();
647 return; 661 return;
648 } 662 }
649 663
650 if (status == MEDIA_CODEC_NO_KEY) { 664 if (status == MEDIA_CODEC_NO_KEY) {
651 is_waiting_for_key_ = true; 665 is_waiting_for_key_ = true;
652 return; 666 return;
653 } 667 }
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 1033
1020 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { 1034 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) {
1021 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; 1035 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")";
1022 DCHECK_NE(event, NO_EVENT_PENDING); 1036 DCHECK_NE(event, NO_EVENT_PENDING);
1023 DCHECK(IsEventPending(event)) << GetEventName(event); 1037 DCHECK(IsEventPending(event)) << GetEventName(event);
1024 1038
1025 pending_event_ &= ~event; 1039 pending_event_ &= ~event;
1026 } 1040 }
1027 1041
1028 } // namespace media 1042 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698