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 |