Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: media/filters/audio_clock.cc

Issue 1233963002: Fix accumulation error with front_timestamp, move test only code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698