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.
4 
5 #include "media/base/audio_buffer_converter.h"
6 
7 #include <algorithm>
8 #include <cmath>
9 
10 #include "base/check_op.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/sinc_resampler.h"
15 #include "media/base/timestamp_constants.h"
16 #include "media/base/vector_math.h"
17 
18 namespace media {
19 
20 // Is the config presented by |buffer| a config change from |params|?
IsConfigChange(const AudioParameters & params,const AudioBuffer & buffer)21 static bool IsConfigChange(const AudioParameters& params,
22                            const AudioBuffer& buffer) {
23   return buffer.sample_rate() != params.sample_rate() ||
24          buffer.channel_count() != params.channels() ||
25          buffer.channel_layout() != params.channel_layout();
26 }
27 
AudioBufferConverter(const AudioParameters & output_params)28 AudioBufferConverter::AudioBufferConverter(const AudioParameters& output_params)
29     : output_params_(output_params),
30       input_params_(output_params),
31       last_input_buffer_offset_(0),
32       input_frames_(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),
37       pool_(new AudioBufferMemoryPool()) {}
38 
39 AudioBufferConverter::~AudioBufferConverter() = default;
40 
AddInput(scoped_refptr<AudioBuffer> buffer)41 void AudioBufferConverter::AddInput(scoped_refptr<AudioBuffer> buffer) {
42   // On EOS flush any remaining buffered data.
43   if (buffer->end_of_stream()) {
44     Flush();
45     queued_outputs_.push_back(std::move(buffer));
46     return;
47   }
48 
49   // We'll need a new |audio_converter_| if there was a config change.
50   if (IsConfigChange(input_params_, *buffer))
51     ResetConverter(*buffer);
52 
53   // Pass straight through if there's no work to be done.
54   if (!audio_converter_) {
55     queued_outputs_.push_back(std::move(buffer));
56     return;
57   }
58 
59   if (timestamp_helper_.base_timestamp() == kNoTimestamp)
60     timestamp_helper_.SetBaseTimestamp(buffer->timestamp());
61 
62   input_frames_ += buffer->frame_count();
63   queued_inputs_.push_back(std::move(buffer));
64 
65   ConvertIfPossible();
66 }
67 
HasNextBuffer()68 bool AudioBufferConverter::HasNextBuffer() { return !queued_outputs_.empty(); }
69 
GetNextBuffer()70 scoped_refptr<AudioBuffer> AudioBufferConverter::GetNextBuffer() {
71   DCHECK(!queued_outputs_.empty());
72   auto out = std::move(queued_outputs_.front());
73   queued_outputs_.pop_front();
74   return out;
75 }
76 
Reset()77 void AudioBufferConverter::Reset() {
78   audio_converter_.reset();
79   queued_inputs_.clear();
80   queued_outputs_.clear();
81   timestamp_helper_.SetBaseTimestamp(kNoTimestamp);
82   input_params_ = output_params_;
83   input_frames_ = 0;
84   buffered_input_frames_ = 0.0;
85   last_input_buffer_offset_ = 0;
86 }
87 
ResetTimestampState()88 void AudioBufferConverter::ResetTimestampState() {
89   Flush();
90   timestamp_helper_.SetBaseTimestamp(kNoTimestamp);
91 }
92 
ProvideInput(AudioBus * audio_bus,uint32_t frames_delayed)93 double AudioBufferConverter::ProvideInput(AudioBus* audio_bus,
94                                           uint32_t frames_delayed) {
95   DCHECK(is_flushing_ || input_frames_ >= audio_bus->frames());
96 
97   int requested_frames_left = audio_bus->frames();
98   int dest_index = 0;
99 
100   while (requested_frames_left > 0 && !queued_inputs_.empty()) {
101     const auto& input_buffer = queued_inputs_.front();
102 
103     int frames_to_read =
104         std::min(requested_frames_left,
105                  input_buffer->frame_count() - last_input_buffer_offset_);
106     input_buffer->ReadFrames(frames_to_read, last_input_buffer_offset_,
107                              dest_index, audio_bus);
108     last_input_buffer_offset_ += frames_to_read;
109 
110     if (last_input_buffer_offset_ == input_buffer->frame_count()) {
111       // We've consumed all the frames in |input_buffer|.
112       queued_inputs_.pop_front();
113       last_input_buffer_offset_ = 0;
114     }
115 
116     requested_frames_left -= frames_to_read;
117     dest_index += frames_to_read;
118   }
119 
120   // If we're flushing, zero any extra space, otherwise we should always have
121   // enough data to completely fulfill the request.
122   if (is_flushing_ && requested_frames_left > 0) {
123     audio_bus->ZeroFramesPartial(audio_bus->frames() - requested_frames_left,
124                                  requested_frames_left);
125   } else {
126     DCHECK_EQ(requested_frames_left, 0);
127   }
128 
129   input_frames_ -= audio_bus->frames() - requested_frames_left;
130   DCHECK_GE(input_frames_, 0);
131 
132   buffered_input_frames_ += audio_bus->frames() - requested_frames_left;
133 
134   // Full volume.
135   return 1.0;
136 }
137 
ResetConverter(const AudioBuffer & buffer)138 void AudioBufferConverter::ResetConverter(const AudioBuffer& buffer) {
139   Flush();
140   audio_converter_.reset();
141   input_params_.Reset(
142       input_params_.format(), buffer.channel_layout(), buffer.sample_rate(),
143       // If resampling is needed and the FIFO disabled, the AudioConverter will
144       // always request SincResampler::kDefaultRequestSize frames.  Otherwise it
145       // will use the output frame size.
146       buffer.sample_rate() == output_params_.sample_rate()
147           ? output_params_.frames_per_buffer()
148           : SincResampler::kDefaultRequestSize);
149   input_params_.set_channels_for_discrete(buffer.channel_count());
150 
151   io_sample_rate_ratio_ = static_cast<double>(input_params_.sample_rate()) /
152                           output_params_.sample_rate();
153 
154   // If |buffer| matches |output_params_| we don't need an AudioConverter at
155   // all, and can early-out here.
156   if (!IsConfigChange(output_params_, buffer))
157     return;
158 
159   // Note: The FIFO is disabled to avoid extraneous memcpy().
160   audio_converter_.reset(
161       new AudioConverter(input_params_, output_params_, true));
162   audio_converter_->AddInput(this);
163 }
164 
ConvertIfPossible()165 void AudioBufferConverter::ConvertIfPossible() {
166   DCHECK(audio_converter_);
167 
168   int request_frames = 0;
169 
170   if (is_flushing_) {
171     // If we're flushing we want to convert *everything* even if this means
172     // we'll have to pad some silence in ProvideInput().
173     request_frames =
174         ceil((buffered_input_frames_ + input_frames_) / io_sample_rate_ratio_);
175   } else {
176     // How many calls to ProvideInput() we can satisfy completely.
177     int chunks = input_frames_ / input_params_.frames_per_buffer();
178 
179     // How many output frames that corresponds to:
180     request_frames = chunks * audio_converter_->ChunkSize();
181   }
182 
183   if (!request_frames)
184     return;
185 
186   auto output_buffer = AudioBuffer::CreateBuffer(
187       kSampleFormatPlanarF32, output_params_.channel_layout(),
188       output_params_.channels(), output_params_.sample_rate(), request_frames,
189       pool_);
190   std::unique_ptr<AudioBus> output_bus =
191       AudioBus::CreateWrapper(output_buffer->channel_count());
192 
193   int frames_remaining = request_frames;
194 
195   // The AudioConverter wants requests of a fixed size, so we'll slide an
196   // AudioBus of that size across the |output_buffer|.
197   while (frames_remaining != 0) {
198     // It's important that this is a multiple of AudioBus::kChannelAlignment in
199     // all requests except for the last, otherwise downstream SIMD optimizations
200     // will crash on unaligned data.
201     const int frames_this_iteration = std::min(
202         static_cast<int>(SincResampler::kDefaultRequestSize), frames_remaining);
203     const int offset_into_buffer =
204         output_buffer->frame_count() - frames_remaining;
205 
206     // Wrap the portion of the AudioBuffer in an AudioBus so the AudioConverter
207     // can fill it.
208     output_bus->set_frames(frames_this_iteration);
209     for (int ch = 0; ch < output_buffer->channel_count(); ++ch) {
210       output_bus->SetChannelData(
211           ch,
212           reinterpret_cast<float*>(output_buffer->channel_data()[ch]) +
213               offset_into_buffer);
214     }
215 
216     // Do the actual conversion.
217     audio_converter_->Convert(output_bus.get());
218     frames_remaining -= frames_this_iteration;
219     buffered_input_frames_ -= frames_this_iteration * io_sample_rate_ratio_;
220   }
221 
222   // Compute the timestamp.
223   output_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
224   timestamp_helper_.AddFrames(request_frames);
225 
226   queued_outputs_.push_back(std::move(output_buffer));
227 }
228 
Flush()229 void AudioBufferConverter::Flush() {
230   if (!audio_converter_)
231     return;
232   is_flushing_ = true;
233   ConvertIfPossible();
234   is_flushing_ = false;
235   audio_converter_->Reset();
236   DCHECK_EQ(input_frames_, 0);
237   DCHECK_EQ(last_input_buffer_offset_, 0);
238   DCHECK_LT(buffered_input_frames_, 1.0);
239   DCHECK(queued_inputs_.empty());
240   buffered_input_frames_ = 0.0;
241 }
242 
243 }  // namespace media
244