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. 4 5 #include "media/filters/audio_clock.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 #include "media/base/buffers.h" 11 12 namespace media { 13 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) { 23 } 24 25 AudioClock::~AudioClock() { 26 } 27 28 void AudioClock::WroteAudio(int frames_written, 29 int frames_requested, 30 int delay_frames, 31 float 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); 36 37 // First write: initialize buffer with silence. 38 if (start_timestamp_ == front_timestamp_ && buffered_.empty()) 39 PushBufferedAudioData(delay_frames, 0.0f); 40 41 // Move frames from |buffered_| into the computed timestamp based on 42 // |delay_frames|. 43 // 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); 52 53 back_timestamp_ += base::TimeDelta::FromMicroseconds( 54 frames_written * playback_rate * microseconds_per_frame_); 55 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; 64 } 65 66 // Any buffered silence breaks our contiguous stretch of audio data. 67 if (found_silence) 68 break; 69 70 scaled_frames += (buffered_[i].frames * buffered_[i].playback_rate); 71 72 if (i == 0) 73 scaled_frames_at_same_rate = scaled_frames; 74 } 75 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_); 81 } 82 83 base::TimeDelta AudioClock::TimestampSinceWriting( 84 base::TimeDelta time_since_writing) const { 85 int64_t frames_played_since_writing = std::min( 86 total_buffered_frames_, 87 static_cast<int64_t>(time_since_writing.InSecondsF() * sample_rate_)); 88 return front_timestamp_ + 89 ComputeBufferedMediaTime(frames_played_since_writing); 90 } 91 92 base::TimeDelta AudioClock::TimeUntilPlayback(base::TimeDelta timestamp) const { 93 DCHECK(timestamp >= front_timestamp_); 94 DCHECK(timestamp <= back_timestamp_); 95 96 int64_t frames_until_timestamp = 0; 97 double timestamp_us = timestamp.InMicroseconds(); 98 double media_time_us = front_timestamp_.InMicroseconds(); 99 100 for (size_t i = 0; i < buffered_.size(); ++i) { 101 // Leading silence is always accounted prior to anything else. 102 if (buffered_[i].playback_rate == 0) { 103 frames_until_timestamp += buffered_[i].frames; 104 continue; 105 } 106 107 // Calculate upper bound on media time for current block of buffered frames. 108 double delta_us = buffered_[i].frames * buffered_[i].playback_rate * 109 microseconds_per_frame_; 110 double max_media_time_us = media_time_us + delta_us; 111 112 // Determine amount of media time to convert to frames for current block. If 113 // target timestamp falls within current block, scale the amount of frames 114 // based on remaining amount of media time. 115 if (timestamp_us <= max_media_time_us) { 116 frames_until_timestamp += 117 buffered_[i].frames * (timestamp_us - media_time_us) / delta_us; 118 break; 119 } 120 121 media_time_us = max_media_time_us; 122 frames_until_timestamp += buffered_[i].frames; 123 } 124 125 return base::TimeDelta::FromMicroseconds(frames_until_timestamp * 126 microseconds_per_frame_); 127 } 128 129 AudioClock::AudioData::AudioData(int64_t frames, float playback_rate) 130 : frames(frames), playback_rate(playback_rate) { 131 } 132 133 void AudioClock::PushBufferedAudioData(int64_t frames, float playback_rate) { 134 if (frames == 0) 135 return; 136 137 total_buffered_frames_ += frames; 138 139 // Avoid creating extra elements where possible. 140 if (!buffered_.empty() && buffered_.back().playback_rate == playback_rate) { 141 buffered_.back().frames += frames; 142 return; 143 } 144 145 buffered_.push_back(AudioData(frames, playback_rate)); 146 } 147 148 void AudioClock::PopBufferedAudioData(int64_t frames) { 149 DCHECK_LE(frames, total_buffered_frames_); 150 151 total_buffered_frames_ -= frames; 152 153 while (frames > 0) { 154 int64_t frames_to_pop = std::min(buffered_.front().frames, frames); 155 buffered_.front().frames -= frames_to_pop; 156 if (buffered_.front().frames == 0) 157 buffered_.pop_front(); 158 159 frames -= frames_to_pop; 160 } 161 } 162 163 base::TimeDelta AudioClock::ComputeBufferedMediaTime(int64_t frames) const { 164 DCHECK_LE(frames, total_buffered_frames_); 165 166 double scaled_frames = 0; 167 for (size_t i = 0; i < buffered_.size() && frames > 0; ++i) { 168 int64_t min_frames = std::min(buffered_[i].frames, frames); 169 scaled_frames += min_frames * buffered_[i].playback_rate; 170 frames -= min_frames; 171 } 172 173 return base::TimeDelta::FromMicroseconds(scaled_frames * 174 microseconds_per_frame_); 175 } 176 177 } // namespace media 178