| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/filters/audio_clock.h" | 5 #include "media/filters/audio_clock.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 // First write: initialize buffer with silence. | 36 // First write: initialize buffer with silence. |
| 37 if (start_timestamp_ == front_timestamp_ && buffered_.empty()) | 37 if (start_timestamp_ == front_timestamp_ && buffered_.empty()) |
| 38 PushBufferedAudioData(delay_frames, 0.0); | 38 PushBufferedAudioData(delay_frames, 0.0); |
| 39 | 39 |
| 40 // Move frames from |buffered_| into the computed timestamp based on | 40 // Move frames from |buffered_| into the computed timestamp based on |
| 41 // |delay_frames|. | 41 // |delay_frames|. |
| 42 // | 42 // |
| 43 // The ordering of compute -> push -> pop eliminates unnecessary memory | 43 // The ordering of compute -> push -> pop eliminates unnecessary memory |
| 44 // reallocations in cases where |buffered_| gets emptied. | 44 // reallocations in cases where |buffered_| gets emptied. |
| 45 const int64_t original_buffered_frames = total_buffered_frames_; | |
| 46 int64_t frames_played = | 45 int64_t frames_played = |
| 47 std::max(INT64_C(0), total_buffered_frames_ - delay_frames); | 46 std::max(INT64_C(0), total_buffered_frames_ - delay_frames); |
| 48 front_timestamp_ += ComputeBufferedMediaTime(frames_played); | |
| 49 PushBufferedAudioData(frames_written, playback_rate); | 47 PushBufferedAudioData(frames_written, playback_rate); |
| 50 PushBufferedAudioData(frames_requested - frames_written, 0.0); | 48 PushBufferedAudioData(frames_requested - frames_written, 0.0); |
| 51 PopBufferedAudioData(frames_played); | 49 PopBufferedAudioData(frames_played); |
| 52 | 50 |
| 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. |
| 53 back_timestamp_ += base::TimeDelta::FromMicroseconds( | 54 back_timestamp_ += base::TimeDelta::FromMicroseconds( |
| 54 frames_written * playback_rate * microseconds_per_frame_); | 55 frames_written * playback_rate * microseconds_per_frame_); |
| 55 | 56 front_timestamp_ = back_timestamp_ - ComputeBufferedMediaDuration(); |
| 56 // Ensure something crazy hasn't happened to desync the front and back values. | 57 DCHECK_LE(front_timestamp_, back_timestamp_); |
| 57 DCHECK_LE(front_timestamp_.InMicroseconds(), back_timestamp_.InMicroseconds()) | |
| 58 << "frames_written=" << frames_written | |
| 59 << ", frames_requested=" << frames_requested | |
| 60 << ", delay_frames=" << delay_frames | |
| 61 << ", playback_rate=" << playback_rate | |
| 62 << ", frames_played=" << frames_played | |
| 63 << ", original_buffered_frames=" << original_buffered_frames | |
| 64 << ", total_buffered_frames_=" << total_buffered_frames_; | |
| 65 | |
| 66 // Update cached values. | |
| 67 double scaled_frames = 0; | |
| 68 double scaled_frames_at_same_rate = 0; | |
| 69 bool found_silence = false; | |
| 70 for (size_t i = 0; i < buffered_.size(); ++i) { | |
| 71 if (buffered_[i].playback_rate == 0) { | |
| 72 found_silence = true; | |
| 73 continue; | |
| 74 } | |
| 75 | |
| 76 // Any buffered silence breaks our contiguous stretch of audio data. | |
| 77 if (found_silence) | |
| 78 break; | |
| 79 | |
| 80 scaled_frames += (buffered_[i].frames * buffered_[i].playback_rate); | |
| 81 | |
| 82 if (i == 0) | |
| 83 scaled_frames_at_same_rate = scaled_frames; | |
| 84 } | |
| 85 | |
| 86 contiguous_audio_data_buffered_ = base::TimeDelta::FromMicroseconds( | |
| 87 scaled_frames * microseconds_per_frame_); | |
| 88 contiguous_audio_data_buffered_at_same_rate_ = | |
| 89 base::TimeDelta::FromMicroseconds(scaled_frames_at_same_rate * | |
| 90 microseconds_per_frame_); | |
| 91 } | 58 } |
| 92 | 59 |
| 93 void AudioClock::CompensateForSuspendedWrites(base::TimeDelta elapsed, | 60 void AudioClock::CompensateForSuspendedWrites(base::TimeDelta elapsed, |
| 94 int delay_frames) { | 61 int delay_frames) { |
| 95 const int64_t frames_elapsed = | 62 const int64_t frames_elapsed = |
| 96 elapsed.InMicroseconds() / microseconds_per_frame_ + 0.5; | 63 elapsed.InMicroseconds() / microseconds_per_frame_ + 0.5; |
| 97 | 64 |
| 98 // No need to do anything if we're within the limits of our played out audio | 65 // No need to do anything if we're within the limits of our played out audio |
| 99 // or there are no delay frames, the next WroteAudio() call will expire | 66 // or there are no delay frames, the next WroteAudio() call will expire |
| 100 // everything correctly. | 67 // everything correctly. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 } | 104 } |
| 138 | 105 |
| 139 media_time_us = max_media_time_us; | 106 media_time_us = max_media_time_us; |
| 140 frames_until_timestamp += buffered_[i].frames; | 107 frames_until_timestamp += buffered_[i].frames; |
| 141 } | 108 } |
| 142 | 109 |
| 143 return base::TimeDelta::FromMicroseconds(frames_until_timestamp * | 110 return base::TimeDelta::FromMicroseconds(frames_until_timestamp * |
| 144 microseconds_per_frame_); | 111 microseconds_per_frame_); |
| 145 } | 112 } |
| 146 | 113 |
| 114 void AudioClock::ContiguousAudioDataBufferedForTesting( |
| 115 base::TimeDelta* total, |
| 116 base::TimeDelta* same_rate_total) const { |
| 117 double scaled_frames = 0; |
| 118 double scaled_frames_at_same_rate = 0; |
| 119 bool found_silence = false; |
| 120 for (size_t i = 0; i < buffered_.size(); ++i) { |
| 121 if (buffered_[i].playback_rate == 0) { |
| 122 found_silence = true; |
| 123 continue; |
| 124 } |
| 125 |
| 126 // Any buffered silence breaks our contiguous stretch of audio data. |
| 127 if (found_silence) |
| 128 break; |
| 129 |
| 130 scaled_frames += (buffered_[i].frames * buffered_[i].playback_rate); |
| 131 |
| 132 if (i == 0) |
| 133 scaled_frames_at_same_rate = scaled_frames; |
| 134 } |
| 135 |
| 136 *total = base::TimeDelta::FromMicroseconds(scaled_frames * |
| 137 microseconds_per_frame_); |
| 138 *same_rate_total = base::TimeDelta::FromMicroseconds( |
| 139 scaled_frames_at_same_rate * microseconds_per_frame_); |
| 140 } |
| 141 |
| 147 AudioClock::AudioData::AudioData(int64_t frames, double playback_rate) | 142 AudioClock::AudioData::AudioData(int64_t frames, double playback_rate) |
| 148 : frames(frames), playback_rate(playback_rate) { | 143 : frames(frames), playback_rate(playback_rate) { |
| 149 } | 144 } |
| 150 | 145 |
| 151 void AudioClock::PushBufferedAudioData(int64_t frames, double playback_rate) { | 146 void AudioClock::PushBufferedAudioData(int64_t frames, double playback_rate) { |
| 152 if (frames == 0) | 147 if (frames == 0) |
| 153 return; | 148 return; |
| 154 | 149 |
| 155 total_buffered_frames_ += frames; | 150 total_buffered_frames_ += frames; |
| 156 | 151 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 171 while (frames > 0) { | 166 while (frames > 0) { |
| 172 int64_t frames_to_pop = std::min(buffered_.front().frames, frames); | 167 int64_t frames_to_pop = std::min(buffered_.front().frames, frames); |
| 173 buffered_.front().frames -= frames_to_pop; | 168 buffered_.front().frames -= frames_to_pop; |
| 174 if (buffered_.front().frames == 0) | 169 if (buffered_.front().frames == 0) |
| 175 buffered_.pop_front(); | 170 buffered_.pop_front(); |
| 176 | 171 |
| 177 frames -= frames_to_pop; | 172 frames -= frames_to_pop; |
| 178 } | 173 } |
| 179 } | 174 } |
| 180 | 175 |
| 181 base::TimeDelta AudioClock::ComputeBufferedMediaTime(int64_t frames) const { | 176 base::TimeDelta AudioClock::ComputeBufferedMediaDuration() const { |
| 182 DCHECK_LE(frames, total_buffered_frames_); | |
| 183 | |
| 184 double scaled_frames = 0; | 177 double scaled_frames = 0; |
| 185 for (size_t i = 0; i < buffered_.size() && frames > 0; ++i) { | 178 for (const auto& buffer : buffered_) |
| 186 int64_t min_frames = std::min(buffered_[i].frames, frames); | 179 scaled_frames += buffer.frames * buffer.playback_rate; |
| 187 scaled_frames += min_frames * buffered_[i].playback_rate; | |
| 188 frames -= min_frames; | |
| 189 } | |
| 190 | |
| 191 return base::TimeDelta::FromMicroseconds(scaled_frames * | 180 return base::TimeDelta::FromMicroseconds(scaled_frames * |
| 192 microseconds_per_frame_); | 181 microseconds_per_frame_); |
| 193 } | 182 } |
| 194 | 183 |
| 195 } // namespace media | 184 } // namespace media |
| OLD | NEW |