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

Unified Diff: media/renderers/audio_renderer_impl.cc

Issue 1160853006: Improve audio/video sync during underflow, reduce underflow frequency. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments. Created 5 years, 6 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/renderers/audio_renderer_impl.h ('k') | media/renderers/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/renderers/audio_renderer_impl.cc
diff --git a/media/renderers/audio_renderer_impl.cc b/media/renderers/audio_renderer_impl.cc
index 59f05b321d02334bcbec796751eccc5987bf6184..7a2c0293f6623d4f8e7efa91fadceef98e3c9052 100644
--- a/media/renderers/audio_renderer_impl.cc
+++ b/media/renderers/audio_renderer_impl.cc
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/default_tick_clock.h"
#include "media/base/audio_buffer.h"
#include "media/base/audio_buffer_converter.h"
#include "media/base/audio_hardware_config.h"
@@ -52,6 +53,7 @@ AudioRendererImpl::AudioRendererImpl(
audio_buffer_stream_(
new AudioBufferStream(task_runner, decoders.Pass(), media_log)),
hardware_config_(hardware_config),
+ tick_clock_(new base::DefaultTickClock()),
playback_rate_(0.0),
state_(kUninitialized),
buffering_state_(BUFFERING_HAVE_NOTHING),
@@ -171,38 +173,59 @@ bool AudioRendererImpl::GetWallClockTimes(
const std::vector<base::TimeDelta>& media_timestamps,
std::vector<base::TimeTicks>* wall_clock_times) {
base::AutoLock auto_lock(lock_);
- if (last_render_time_.is_null() || !stop_rendering_time_.is_null() ||
- !playback_rate_ || buffering_state_ != BUFFERING_HAVE_ENOUGH ||
- !sink_playing_) {
- return false;
+ DCHECK(wall_clock_times->empty());
+
+ // When playback is paused (rate is zero), assume a rate of 1.0.
+ const double playback_rate = playback_rate_ ? playback_rate_ : 1.0;
+ const bool is_time_moving = sink_playing_ && playback_rate_ &&
+ !last_render_time_.is_null() &&
+ stop_rendering_time_.is_null();
+
+ // Pre-compute the time until playback of the audio buffer extents, since
+ // these values are frequently used below.
+ const base::TimeDelta time_until_front =
+ audio_clock_->TimeUntilPlayback(audio_clock_->front_timestamp());
+ const base::TimeDelta time_until_back =
+ audio_clock_->TimeUntilPlayback(audio_clock_->back_timestamp());
+
+ if (media_timestamps.empty()) {
+ // Return the current media time as a wall clock time while accounting for
+ // frames which may be in the process of play out.
+ wall_clock_times->push_back(std::min(
+ std::max(tick_clock_->NowTicks(), last_render_time_ + time_until_front),
+ last_render_time_ + time_until_back));
+ return is_time_moving;
}
- DCHECK(wall_clock_times->empty());
wall_clock_times->reserve(media_timestamps.size());
for (const auto& media_timestamp : media_timestamps) {
- base::TimeDelta base_time;
- if (media_timestamp < audio_clock_->front_timestamp()) {
- // See notes about |media_time| values less than |base_time| in TimeSource
- // header.
- base_time = audio_clock_->front_timestamp();
- } else if (media_timestamp > audio_clock_->back_timestamp()) {
- base_time = audio_clock_->back_timestamp();
- } else {
- // No need to estimate time, so return the actual wallclock time.
+ // When time was or is moving and the requested media timestamp is within
+ // range of played out audio, we can provide an exact conversion.
+ if (!last_render_time_.is_null() &&
+ media_timestamp >= audio_clock_->front_timestamp() &&
+ media_timestamp <= audio_clock_->back_timestamp()) {
wall_clock_times->push_back(
- last_render_time_ +
- audio_clock_->TimeUntilPlayback(media_timestamp));
+ last_render_time_ + audio_clock_->TimeUntilPlayback(media_timestamp));
continue;
}
+ base::TimeDelta base_timestamp, time_until_playback;
+ if (media_timestamp < audio_clock_->front_timestamp()) {
+ base_timestamp = audio_clock_->front_timestamp();
+ time_until_playback = time_until_front;
+ } else {
+ base_timestamp = audio_clock_->back_timestamp();
+ time_until_playback = time_until_back;
+ }
+
// In practice, most calls will be estimates given the relatively small
// window in which clients can get the actual time.
- wall_clock_times->push_back(
- last_render_time_ + audio_clock_->TimeUntilPlayback(base_time) +
- base::TimeDelta::FromMicroseconds(
- (media_timestamp - base_time).InMicroseconds() / playback_rate_));
+ wall_clock_times->push_back(last_render_time_ + time_until_playback +
+ (media_timestamp - base_timestamp) /
+ playback_rate);
}
- return true;
+
+ return is_time_moving;
}
TimeSource* AudioRendererImpl::GetTimeSource() {
@@ -596,10 +619,11 @@ int AudioRendererImpl::Render(AudioBus* audio_bus,
int frames_written = 0;
{
base::AutoLock auto_lock(lock_);
- last_render_time_ = base::TimeTicks::Now();
+ last_render_time_ = tick_clock_->NowTicks();
if (!stop_rendering_time_.is_null()) {
- // TODO(dalecurtis): Use |stop_rendering_time_| to advance the AudioClock.
+ audio_clock_->CompensateForSuspendedWrites(
+ last_render_time_ - stop_rendering_time_, delay_frames);
stop_rendering_time_ = base::TimeTicks();
}
« no previous file with comments | « media/renderers/audio_renderer_impl.h ('k') | media/renderers/audio_renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698