Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / media / filters / audio_clock.cc
blobc561c27be0f2e8d71a4bcdcd341a0ac14f860313
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 sample_rate_(sample_rate),
17 microseconds_per_frame_(
18 static_cast<double>(base::Time::kMicrosecondsPerSecond) /
19 sample_rate),
20 total_buffered_frames_(0),
21 front_timestamp_(start_timestamp),
22 back_timestamp_(start_timestamp) {
25 AudioClock::~AudioClock() {
28 void AudioClock::WroteAudio(int frames_written,
29 int frames_requested,
30 int delay_frames,
31 double playback_rate) {
32 DCHECK_GE(frames_written, 0);
33 DCHECK_LE(frames_written, frames_requested);
34 DCHECK_GE(delay_frames, 0);
35 DCHECK_GE(playback_rate, 0);
37 // First write: initialize buffer with silence.
38 if (start_timestamp_ == front_timestamp_ && buffered_.empty())
39 PushBufferedAudioData(delay_frames, 0.0f);
41 // Move frames from |buffered_| into the computed timestamp based on
42 // |delay_frames|.
44 // The ordering of compute -> push -> pop eliminates unnecessary memory
45 // reallocations in cases where |buffered_| gets emptied.
46 int64_t frames_played =
47 std::max(INT64_C(0), total_buffered_frames_ - delay_frames);
48 front_timestamp_ += ComputeBufferedMediaTime(frames_played);
49 PushBufferedAudioData(frames_written, playback_rate);
50 PushBufferedAudioData(frames_requested - frames_written, 0.0f);
51 PopBufferedAudioData(frames_played);
53 back_timestamp_ += base::TimeDelta::FromMicroseconds(
54 frames_written * playback_rate * microseconds_per_frame_);
56 // Update cached values.
57 double scaled_frames = 0;
58 double scaled_frames_at_same_rate = 0;
59 bool found_silence = false;
60 for (size_t i = 0; i < buffered_.size(); ++i) {
61 if (buffered_[i].playback_rate == 0) {
62 found_silence = true;
63 continue;
66 // Any buffered silence breaks our contiguous stretch of audio data.
67 if (found_silence)
68 break;
70 scaled_frames += (buffered_[i].frames * buffered_[i].playback_rate);
72 if (i == 0)
73 scaled_frames_at_same_rate = scaled_frames;
76 contiguous_audio_data_buffered_ = base::TimeDelta::FromMicroseconds(
77 scaled_frames * microseconds_per_frame_);
78 contiguous_audio_data_buffered_at_same_rate_ =
79 base::TimeDelta::FromMicroseconds(scaled_frames_at_same_rate *
80 microseconds_per_frame_);
83 base::TimeDelta AudioClock::TimeUntilPlayback(base::TimeDelta timestamp) const {
84 DCHECK(timestamp >= front_timestamp_);
85 DCHECK(timestamp <= back_timestamp_);
87 int64_t frames_until_timestamp = 0;
88 double timestamp_us = timestamp.InMicroseconds();
89 double media_time_us = front_timestamp_.InMicroseconds();
91 for (size_t i = 0; i < buffered_.size(); ++i) {
92 // Leading silence is always accounted prior to anything else.
93 if (buffered_[i].playback_rate == 0) {
94 frames_until_timestamp += buffered_[i].frames;
95 continue;
98 // Calculate upper bound on media time for current block of buffered frames.
99 double delta_us = buffered_[i].frames * buffered_[i].playback_rate *
100 microseconds_per_frame_;
101 double max_media_time_us = media_time_us + delta_us;
103 // Determine amount of media time to convert to frames for current block. If
104 // target timestamp falls within current block, scale the amount of frames
105 // based on remaining amount of media time.
106 if (timestamp_us <= max_media_time_us) {
107 frames_until_timestamp +=
108 buffered_[i].frames * (timestamp_us - media_time_us) / delta_us;
109 break;
112 media_time_us = max_media_time_us;
113 frames_until_timestamp += buffered_[i].frames;
116 return base::TimeDelta::FromMicroseconds(frames_until_timestamp *
117 microseconds_per_frame_);
120 AudioClock::AudioData::AudioData(int64_t frames, double playback_rate)
121 : frames(frames), playback_rate(playback_rate) {
124 void AudioClock::PushBufferedAudioData(int64_t frames, double playback_rate) {
125 if (frames == 0)
126 return;
128 total_buffered_frames_ += frames;
130 // Avoid creating extra elements where possible.
131 if (!buffered_.empty() && buffered_.back().playback_rate == playback_rate) {
132 buffered_.back().frames += frames;
133 return;
136 buffered_.push_back(AudioData(frames, playback_rate));
139 void AudioClock::PopBufferedAudioData(int64_t frames) {
140 DCHECK_LE(frames, total_buffered_frames_);
142 total_buffered_frames_ -= frames;
144 while (frames > 0) {
145 int64_t frames_to_pop = std::min(buffered_.front().frames, frames);
146 buffered_.front().frames -= frames_to_pop;
147 if (buffered_.front().frames == 0)
148 buffered_.pop_front();
150 frames -= frames_to_pop;
154 base::TimeDelta AudioClock::ComputeBufferedMediaTime(int64_t frames) const {
155 DCHECK_LE(frames, total_buffered_frames_);
157 double scaled_frames = 0;
158 for (size_t i = 0; i < buffered_.size() && frames > 0; ++i) {
159 int64_t min_frames = std::min(buffered_[i].frames, frames);
160 scaled_frames += min_frames * buffered_[i].playback_rate;
161 frames -= min_frames;
164 return base::TimeDelta::FromMicroseconds(scaled_frames *
165 microseconds_per_frame_);
168 } // namespace media