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/base/audio_buffer_converter.h"
9 #include "base/logging.h"
10 #include "media/base/audio_buffer.h"
11 #include "media/base/audio_bus.h"
12 #include "media/base/audio_decoder_config.h"
13 #include "media/base/audio_timestamp_helper.h"
14 #include "media/base/buffers.h"
15 #include "media/base/sinc_resampler.h"
16 #include "media/base/vector_math.h"
20 // Is the config presented by |buffer| a config change from |params|?
21 static bool IsConfigChange(const AudioParameters
& params
,
22 const scoped_refptr
<AudioBuffer
>& buffer
) {
23 return buffer
->sample_rate() != params
.sample_rate() ||
24 buffer
->channel_count() != params
.channels() ||
25 buffer
->channel_layout() != params
.channel_layout();
28 AudioBufferConverter::AudioBufferConverter(const AudioParameters
& output_params
)
29 : output_params_(output_params
),
30 input_params_(output_params
),
31 last_input_buffer_offset_(0),
33 buffered_input_frames_(0.0),
34 io_sample_rate_ratio_(1.0),
35 timestamp_helper_(output_params_
.sample_rate()),
36 is_flushing_(false) {}
38 AudioBufferConverter::~AudioBufferConverter() {}
40 void AudioBufferConverter::AddInput(const scoped_refptr
<AudioBuffer
>& buffer
) {
41 // On EOS flush any remaining buffered data.
42 if (buffer
->end_of_stream()) {
44 queued_outputs_
.push_back(buffer
);
48 // We'll need a new |audio_converter_| if there was a config change.
49 if (IsConfigChange(input_params_
, buffer
))
50 ResetConverter(buffer
);
52 // Pass straight through if there's no work to be done.
53 if (!audio_converter_
) {
54 queued_outputs_
.push_back(buffer
);
58 if (timestamp_helper_
.base_timestamp() == kNoTimestamp())
59 timestamp_helper_
.SetBaseTimestamp(buffer
->timestamp());
61 queued_inputs_
.push_back(buffer
);
62 input_frames_
+= buffer
->frame_count();
67 bool AudioBufferConverter::HasNextBuffer() { return !queued_outputs_
.empty(); }
69 scoped_refptr
<AudioBuffer
> AudioBufferConverter::GetNextBuffer() {
70 DCHECK(!queued_outputs_
.empty());
71 scoped_refptr
<AudioBuffer
> out
= queued_outputs_
.front();
72 queued_outputs_
.pop_front();
76 void AudioBufferConverter::Reset() {
77 audio_converter_
.reset();
78 queued_inputs_
.clear();
79 queued_outputs_
.clear();
80 timestamp_helper_
.SetBaseTimestamp(kNoTimestamp());
81 input_params_
= output_params_
;
83 buffered_input_frames_
= 0.0;
84 last_input_buffer_offset_
= 0;
87 void AudioBufferConverter::ResetTimestampState() {
89 timestamp_helper_
.SetBaseTimestamp(kNoTimestamp());
92 double AudioBufferConverter::ProvideInput(AudioBus
* audio_bus
,
93 base::TimeDelta buffer_delay
) {
94 DCHECK(is_flushing_
|| input_frames_
>= audio_bus
->frames());
96 int requested_frames_left
= audio_bus
->frames();
99 while (requested_frames_left
> 0 && !queued_inputs_
.empty()) {
100 scoped_refptr
<AudioBuffer
> input_buffer
= queued_inputs_
.front();
103 std::min(requested_frames_left
,
104 input_buffer
->frame_count() - last_input_buffer_offset_
);
105 input_buffer
->ReadFrames(
106 frames_to_read
, last_input_buffer_offset_
, dest_index
, audio_bus
);
107 last_input_buffer_offset_
+= frames_to_read
;
109 if (last_input_buffer_offset_
== input_buffer
->frame_count()) {
110 // We've consumed all the frames in |input_buffer|.
111 queued_inputs_
.pop_front();
112 last_input_buffer_offset_
= 0;
115 requested_frames_left
-= frames_to_read
;
116 dest_index
+= frames_to_read
;
119 // If we're flushing, zero any extra space, otherwise we should always have
120 // enough data to completely fulfill the request.
121 if (is_flushing_
&& requested_frames_left
> 0) {
122 audio_bus
->ZeroFramesPartial(audio_bus
->frames() - requested_frames_left
,
123 requested_frames_left
);
125 DCHECK_EQ(requested_frames_left
, 0);
128 input_frames_
-= audio_bus
->frames() - requested_frames_left
;
129 DCHECK_GE(input_frames_
, 0);
131 buffered_input_frames_
+= audio_bus
->frames() - requested_frames_left
;
137 void AudioBufferConverter::ResetConverter(
138 const scoped_refptr
<AudioBuffer
>& buffer
) {
140 audio_converter_
.reset();
142 input_params_
.format(),
143 buffer
->channel_layout(),
144 buffer
->channel_count(),
145 buffer
->sample_rate(),
146 input_params_
.bits_per_sample(),
147 // If resampling is needed and the FIFO disabled, the AudioConverter will
148 // always request SincResampler::kDefaultRequestSize frames. Otherwise it
149 // will use the output frame size.
150 buffer
->sample_rate() == output_params_
.sample_rate()
151 ? output_params_
.frames_per_buffer()
152 : SincResampler::kDefaultRequestSize
);
154 io_sample_rate_ratio_
= static_cast<double>(input_params_
.sample_rate()) /
155 output_params_
.sample_rate();
157 // If |buffer| matches |output_params_| we don't need an AudioConverter at
158 // all, and can early-out here.
159 if (!IsConfigChange(output_params_
, buffer
))
162 // Note: The FIFO is disabled to avoid extraneous memcpy().
163 audio_converter_
.reset(
164 new AudioConverter(input_params_
, output_params_
, true));
165 audio_converter_
->AddInput(this);
168 void AudioBufferConverter::ConvertIfPossible() {
169 DCHECK(audio_converter_
);
171 int request_frames
= 0;
174 // If we're flushing we want to convert *everything* even if this means
175 // we'll have to pad some silence in ProvideInput().
177 ceil((buffered_input_frames_
+ input_frames_
) / io_sample_rate_ratio_
);
179 // How many calls to ProvideInput() we can satisfy completely.
180 int chunks
= input_frames_
/ input_params_
.frames_per_buffer();
182 // How many output frames that corresponds to:
183 request_frames
= chunks
* audio_converter_
->ChunkSize();
189 scoped_refptr
<AudioBuffer
> output_buffer
=
190 AudioBuffer::CreateBuffer(kSampleFormatPlanarF32
,
191 output_params_
.channel_layout(),
192 output_params_
.channels(),
193 output_params_
.sample_rate(),
195 scoped_ptr
<AudioBus
> output_bus
=
196 AudioBus::CreateWrapper(output_buffer
->channel_count());
198 int frames_remaining
= request_frames
;
200 // The AudioConverter wants requests of a fixed size, so we'll slide an
201 // AudioBus of that size across the |output_buffer|.
202 while (frames_remaining
!= 0) {
203 // It's important that this is a multiple of AudioBus::kChannelAlignment in
204 // all requests except for the last, otherwise downstream SIMD optimizations
205 // will crash on unaligned data.
206 const int frames_this_iteration
= std::min(
207 static_cast<int>(SincResampler::kDefaultRequestSize
), frames_remaining
);
208 const int offset_into_buffer
=
209 output_buffer
->frame_count() - frames_remaining
;
211 // Wrap the portion of the AudioBuffer in an AudioBus so the AudioConverter
213 output_bus
->set_frames(frames_this_iteration
);
214 for (int ch
= 0; ch
< output_buffer
->channel_count(); ++ch
) {
215 output_bus
->SetChannelData(
217 reinterpret_cast<float*>(output_buffer
->channel_data()[ch
]) +
221 // Do the actual conversion.
222 audio_converter_
->Convert(output_bus
.get());
223 frames_remaining
-= frames_this_iteration
;
224 buffered_input_frames_
-= frames_this_iteration
* io_sample_rate_ratio_
;
227 // Compute the timestamp.
228 output_buffer
->set_timestamp(timestamp_helper_
.GetTimestamp());
229 timestamp_helper_
.AddFrames(request_frames
);
231 queued_outputs_
.push_back(output_buffer
);
234 void AudioBufferConverter::Flush() {
235 if (!audio_converter_
)
239 is_flushing_
= false;
240 audio_converter_
->Reset();
241 DCHECK_EQ(input_frames_
, 0);
242 DCHECK_EQ(last_input_buffer_offset_
, 0);
243 DCHECK_LT(buffered_input_frames_
, 1.0);
244 DCHECK(queued_inputs_
.empty());
245 buffered_input_frames_
= 0.0;