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"
9 #include "base/logging.h"
10 #include "media/base/buffers.h"
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
) /
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
,
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);
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
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) {
66 // Any buffered silence breaks our contiguous stretch of audio data.
70 scaled_frames
+= (buffered_
[i
].frames
* buffered_
[i
].playback_rate
);
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::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
);
92 base::TimeDelta
AudioClock::TimeUntilPlayback(base::TimeDelta timestamp
) const {
93 DCHECK(timestamp
>= front_timestamp_
);
94 DCHECK(timestamp
<= back_timestamp_
);
96 int64_t frames_until_timestamp
= 0;
97 double timestamp_us
= timestamp
.InMicroseconds();
98 double media_time_us
= front_timestamp_
.InMicroseconds();
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
;
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
;
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
;
121 media_time_us
= max_media_time_us
;
122 frames_until_timestamp
+= buffered_
[i
].frames
;
125 return base::TimeDelta::FromMicroseconds(frames_until_timestamp
*
126 microseconds_per_frame_
);
129 AudioClock::AudioData::AudioData(int64_t frames
, float playback_rate
)
130 : frames(frames
), playback_rate(playback_rate
) {
133 void AudioClock::PushBufferedAudioData(int64_t frames
, float playback_rate
) {
137 total_buffered_frames_
+= frames
;
139 // Avoid creating extra elements where possible.
140 if (!buffered_
.empty() && buffered_
.back().playback_rate
== playback_rate
) {
141 buffered_
.back().frames
+= frames
;
145 buffered_
.push_back(AudioData(frames
, playback_rate
));
148 void AudioClock::PopBufferedAudioData(int64_t frames
) {
149 DCHECK_LE(frames
, total_buffered_frames_
);
151 total_buffered_frames_
-= frames
;
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();
159 frames
-= frames_to_pop
;
163 base::TimeDelta
AudioClock::ComputeBufferedMediaTime(int64_t frames
) const {
164 DCHECK_LE(frames
, total_buffered_frames_
);
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
;
173 return base::TimeDelta::FromMicroseconds(scaled_frames
*
174 microseconds_per_frame_
);