| 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();
|
| }
|
|
|
|
|