Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / filters / audio_clock.cc
blobe138cd528b93aadc105d8f26682d62b5646c9754
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/audio_clock.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "media/base/buffers.h"
12 namespace media {
14 AudioClock::AudioClock(base::TimeDelta start_timestamp, int sample_rate)
15 : start_timestamp_(start_timestamp),
16 microseconds_per_frame_(
17 static_cast<double>(base::Time::kMicrosecondsPerSecond) /
18 sample_rate),
19 total_buffered_frames_(0),
20 front_timestamp_(start_timestamp),
21 back_timestamp_(start_timestamp) {
24 AudioClock::~AudioClock() {
27 void AudioClock::WroteAudio(int frames_written,
28 int frames_requested,
29 int delay_frames,
30 double playback_rate) {
31 DCHECK_GE(frames_written, 0);
32 DCHECK_LE(frames_written, frames_requested);
33 DCHECK_GE(delay_frames, 0);
34 DCHECK_GE(playback_rate, 0);
36 // First write: initialize buffer with silence.
37 if (start_timestamp_ == front_timestamp_ && buffered_.empty())
38 PushBufferedAudioData(delay_frames, 0.0);
40 // Move frames from |buffered_| into the computed timestamp based on
41 // |delay_frames|.
43 // The ordering of compute -> push -> pop eliminates unnecessary memory
44 // reallocations in cases where |buffered_| gets emptied.
45 int64_t frames_played =
46 std::max(INT64_C(0), total_buffered_frames_ - delay_frames);
47 PushBufferedAudioData(frames_written, playback_rate);
48 PushBufferedAudioData(frames_requested - frames_written, 0.0);
49 PopBufferedAudioData(frames_played);
51 // Update our front and back timestamps. The back timestamp is considered the
52 // authoritative source of truth, so base the front timestamp on range of data
53 // buffered. Doing so avoids accumulation errors on the front timestamp.
54 back_timestamp_ += base::TimeDelta::FromMicroseconds(
55 frames_written * playback_rate * microseconds_per_frame_);
56 // Don't let front timestamp move earlier in time, as could occur due to delay
57 // frames pushed in the first write, above.
58 front_timestamp_ = std::max(front_timestamp_,
59 back_timestamp_ - ComputeBufferedMediaDuration());
60 DCHECK_GE(front_timestamp_, start_timestamp_);
61 DCHECK_LE(front_timestamp_, back_timestamp_);
64 void AudioClock::CompensateForSuspendedWrites(base::TimeDelta elapsed,
65 int delay_frames) {
66 const int64_t frames_elapsed =
67 elapsed.InMicroseconds() / microseconds_per_frame_ + 0.5;
69 // No need to do anything if we're within the limits of our played out audio
70 // or there are no delay frames, the next WroteAudio() call will expire
71 // everything correctly.
72 if (frames_elapsed < total_buffered_frames_ || !delay_frames)
73 return;
75 // Otherwise, flush everything and prime with the delay frames.
76 WroteAudio(0, 0, 0, 0);
77 DCHECK(buffered_.empty());
78 PushBufferedAudioData(delay_frames, 0.0);
81 base::TimeDelta AudioClock::TimeUntilPlayback(base::TimeDelta timestamp) const {
82 DCHECK_GE(timestamp, front_timestamp_);
83 DCHECK_LE(timestamp, back_timestamp_);
85 int64_t frames_until_timestamp = 0;
86 double timestamp_us = timestamp.InMicroseconds();
87 double media_time_us = front_timestamp_.InMicroseconds();
89 for (size_t i = 0; i < buffered_.size(); ++i) {
90 // Leading silence is always accounted prior to anything else.
91 if (buffered_[i].playback_rate == 0) {
92 frames_until_timestamp += buffered_[i].frames;
93 continue;
96 // Calculate upper bound on media time for current block of buffered frames.
97 double delta_us = buffered_[i].frames * buffered_[i].playback_rate *
98 microseconds_per_frame_;
99 double max_media_time_us = media_time_us + delta_us;
101 // Determine amount of media time to convert to frames for current block. If
102 // target timestamp falls within current block, scale the amount of frames
103 // based on remaining amount of media time.
104 if (timestamp_us <= max_media_time_us) {
105 frames_until_timestamp +=
106 buffered_[i].frames * (timestamp_us - media_time_us) / delta_us;
107 break;
110 media_time_us = max_media_time_us;
111 frames_until_timestamp += buffered_[i].frames;
114 return base::TimeDelta::FromMicroseconds(frames_until_timestamp *
115 microseconds_per_frame_);
118 void AudioClock::ContiguousAudioDataBufferedForTesting(
119 base::TimeDelta* total,
120 base::TimeDelta* same_rate_total) const {
121 double scaled_frames = 0;
122 double scaled_frames_at_same_rate = 0;
123 bool found_silence = false;
124 for (size_t i = 0; i < buffered_.size(); ++i) {
125 if (buffered_[i].playback_rate == 0) {
126 found_silence = true;
127 continue;
130 // Any buffered silence breaks our contiguous stretch of audio data.
131 if (found_silence)
132 break;
134 scaled_frames += (buffered_[i].frames * buffered_[i].playback_rate);
136 if (i == 0)
137 scaled_frames_at_same_rate = scaled_frames;
140 *total = base::TimeDelta::FromMicroseconds(scaled_frames *
141 microseconds_per_frame_);
142 *same_rate_total = base::TimeDelta::FromMicroseconds(
143 scaled_frames_at_same_rate * microseconds_per_frame_);
146 AudioClock::AudioData::AudioData(int64_t frames, double playback_rate)
147 : frames(frames), playback_rate(playback_rate) {
150 void AudioClock::PushBufferedAudioData(int64_t frames, double playback_rate) {
151 if (frames == 0)
152 return;
154 total_buffered_frames_ += frames;
156 // Avoid creating extra elements where possible.
157 if (!buffered_.empty() && buffered_.back().playback_rate == playback_rate) {
158 buffered_.back().frames += frames;
159 return;
162 buffered_.push_back(AudioData(frames, playback_rate));
165 void AudioClock::PopBufferedAudioData(int64_t frames) {
166 DCHECK_LE(frames, total_buffered_frames_);
168 total_buffered_frames_ -= frames;
170 while (frames > 0) {
171 int64_t frames_to_pop = std::min(buffered_.front().frames, frames);
172 buffered_.front().frames -= frames_to_pop;
173 if (buffered_.front().frames == 0)
174 buffered_.pop_front();
176 frames -= frames_to_pop;
180 base::TimeDelta AudioClock::ComputeBufferedMediaDuration() const {
181 double scaled_frames = 0;
182 for (const auto& buffer : buffered_)
183 scaled_frames += buffer.frames * buffer.playback_rate;
184 return base::TimeDelta::FromMicroseconds(scaled_frames *
185 microseconds_per_frame_);
188 } // namespace media