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

Unified 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: addressing acolwell's comments 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/android/media_source_player.cc
diff --git a/media/base/android/media_source_player.cc b/media/base/android/media_source_player.cc
index e52d0e49fc2e651e0d6352b391a96432fc8cb6bc..8b19de7f8932fca8807f95ef7218b684623588ab 100644
--- a/media/base/android/media_source_player.cc
+++ b/media/base/android/media_source_player.cc
@@ -19,16 +19,8 @@
#include "media/base/android/media_drm_bridge.h"
#include "media/base/android/media_player_manager.h"
#include "media/base/android/video_decoder_job.h"
-#include "media/base/audio_timestamp_helper.h"
#include "media/base/buffers.h"
-namespace {
-
-// Use 16bit PCM for audio output. Keep this value in sync with the output
-// format we passed to AudioTrack in MediaCodecBridge.
-const int kBytesPerAudioOutputSample = 2;
-}
-
namespace media {
MediaSourcePlayer::MediaSourcePlayer(
@@ -117,8 +109,6 @@ void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding(
pending_seek_ = false;
clock_.SetTime(seek_time, seek_time);
- if (audio_timestamp_helper_)
- audio_timestamp_helper_->SetBaseTimestamp(seek_time);
if (audio_decoder_job_ && audio_decoder_job_->is_decoding())
audio_decoder_job_->StopDecode();
@@ -315,14 +305,6 @@ void MediaSourcePlayer::OnDemuxerConfigsAvailable(
sampling_rate_ = configs.audio_sampling_rate;
is_audio_encrypted_ = configs.is_audio_encrypted;
audio_extra_data_ = configs.audio_extra_data;
- if (HasAudio()) {
- DCHECK_GT(num_channels_, 0);
- audio_timestamp_helper_.reset(new AudioTimestampHelper(sampling_rate_));
- audio_timestamp_helper_->SetBaseTimestamp(GetCurrentTime());
- } else {
- audio_timestamp_helper_.reset();
- }
-
video_codec_ = configs.video_codec;
width_ = configs.video_size.width();
height_ = configs.video_size.height();
@@ -444,8 +426,8 @@ void MediaSourcePlayer::OnDemuxerSeekDone(
DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: "
<< seek_time.InSecondsF();
clock_.SetTime(seek_time, seek_time);
- if (audio_timestamp_helper_)
- audio_timestamp_helper_->SetBaseTimestamp(seek_time);
+ if (audio_decoder_job_)
+ audio_decoder_job_->SetBaseTimestamp(seek_time);
} else {
DCHECK(actual_browser_seek_time == kNoTimestamp());
}
@@ -471,16 +453,10 @@ void MediaSourcePlayer::OnDemuxerSeekDone(
}
void MediaSourcePlayer::UpdateTimestamps(
- base::TimeDelta presentation_timestamp, size_t audio_output_bytes) {
- base::TimeDelta new_max_time = presentation_timestamp;
+ base::TimeDelta current_presentation_timestamp,
+ base::TimeDelta max_presentation_timestamp) {
+ clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp);
- if (audio_output_bytes > 0) {
- audio_timestamp_helper_->AddFrames(
- audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_));
- new_max_time = audio_timestamp_helper_->GetTimestamp();
- }
-
- clock_.SetMaxTime(new_max_time);
manager()->OnTimeUpdate(player_id(), GetCurrentTime());
}
@@ -510,6 +486,8 @@ void MediaSourcePlayer::ProcessPendingEvents() {
if (IsEventPending(SEEK_EVENT_PENDING)) {
DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT";
ClearDecodingData();
+ if (audio_decoder_job_)
+ audio_decoder_job_->SetBaseTimestamp(GetCurrentTime());
demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_);
return;
}
@@ -581,7 +559,8 @@ void MediaSourcePlayer::ProcessPendingEvents() {
void MediaSourcePlayer::MediaDecoderCallback(
bool is_audio, MediaCodecStatus status,
- base::TimeDelta presentation_timestamp, size_t audio_output_bytes) {
+ base::TimeDelta current_presentation_timestamp,
+ base::TimeDelta max_presentation_timestamp) {
DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status;
// TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed.
@@ -625,6 +604,12 @@ void MediaSourcePlayer::MediaDecoderCallback(
return;
}
+ if (status == MEDIA_CODEC_OK && is_clock_manager &&
+ current_presentation_timestamp != kNoTimestamp()) {
+ UpdateTimestamps(
+ current_presentation_timestamp, max_presentation_timestamp);
+ }
+
if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM)
PlaybackCompleted(is_audio);
@@ -636,11 +621,6 @@ void MediaSourcePlayer::MediaDecoderCallback(
if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM)
return;
- if (status == MEDIA_CODEC_OK && is_clock_manager &&
- presentation_timestamp != kNoTimestamp()) {
- UpdateTimestamps(presentation_timestamp, audio_output_bytes);
- }
-
if (!playing_) {
if (is_clock_manager)
clock_.Pause();
@@ -662,8 +642,9 @@ void MediaSourcePlayer::MediaDecoderCallback(
// If we have a valid timestamp, start the starvation callback. Otherwise,
// reset the |start_time_ticks_| so that the next frame will not suffer
// from the decoding delay caused by the current frame.
- if (presentation_timestamp != kNoTimestamp())
- StartStarvationCallback(presentation_timestamp);
+ if (current_presentation_timestamp != kNoTimestamp())
+ StartStarvationCallback(current_presentation_timestamp,
+ max_presentation_timestamp);
else
start_time_ticks_ = base::TimeTicks::Now();
}
@@ -811,6 +792,13 @@ void MediaSourcePlayer::ConfigureAudioDecoderJob() {
if (audio_decoder_job_) {
SetVolumeInternal();
+ // Need to reset the base timestamp in |audio_decoder_job_|.
+ // TODO(qinmin): When reconfiguring the |audio_decoder_job_|, there might
+ // still be some audio frames in the decoder or in AudioTrack. Therefore,
+ // we are losing some time here. http://crbug.com/357726.
+ base::TimeDelta current_time = GetCurrentTime();
+ audio_decoder_job_->SetBaseTimestamp(current_time);
+ clock_.SetTime(current_time, current_time);
audio_decoder_job_->BeginPrerolling(preroll_timestamp_);
reconfig_audio_decoder_ = false;
}
@@ -912,7 +900,8 @@ void MediaSourcePlayer::OnDecoderStarved() {
}
void MediaSourcePlayer::StartStarvationCallback(
- base::TimeDelta presentation_timestamp) {
+ base::TimeDelta current_presentation_timestamp,
+ base::TimeDelta max_presentation_timestamp) {
// 20ms was chosen because it is the typical size of a compressed audio frame.
// Anything smaller than this would likely cause unnecessary cycling in and
// out of the prefetch state.
@@ -922,16 +911,16 @@ void MediaSourcePlayer::StartStarvationCallback(
base::TimeDelta current_timestamp = GetCurrentTime();
base::TimeDelta timeout;
if (HasAudio()) {
- timeout = audio_timestamp_helper_->GetTimestamp() - current_timestamp;
+ timeout = max_presentation_timestamp - current_timestamp;
} else {
- DCHECK(current_timestamp <= presentation_timestamp);
+ DCHECK(current_timestamp <= current_presentation_timestamp);
// For video only streams, fps can be estimated from the difference
// between the previous and current presentation timestamps. The
// previous presentation timestamp is equal to current_timestamp.
// TODO(qinmin): determine whether 2 is a good coefficient for estimating
// video frame timeout.
- timeout = 2 * (presentation_timestamp - current_timestamp);
+ timeout = 2 * (current_presentation_timestamp - current_timestamp);
}
timeout = std::max(timeout, kMinStarvationTimeout);
« 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