• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "host/frontend/webrtc/audio_handler.h"
18 
19 #include <algorithm>
20 #include <chrono>
21 
22 #include <android-base/logging.h>
23 #include <rtc_base/time_utils.h>
24 
25 namespace cuttlefish {
26 namespace {
27 
28 const virtio_snd_pcm_info STREAMS[] = {{
29     .hdr =
30         {
31             .hda_fn_nid = Le32(0),
32         },
33     .features = Le32(0),
34     // webrtc's api is quite primitive and doesn't allow for many different
35     // formats: It only takes the bits_per_sample as a parameter and assumes
36     // the underlying format to be one of the following:
37     .formats = Le64(
38         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U8) |
39         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U16) |
40         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24) |
41         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U32)),
42     .rates = Le64(
43         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_5512) |
44         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_8000) |
45         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_11025) |
46         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_16000) |
47         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_22050) |
48         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_32000) |
49         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_44100) |
50         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_48000) |
51         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_64000) |
52         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_88200) |
53         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_96000) |
54         (((uint64_t)1) << (uint8_t)
55              AudioStreamRate::VIRTIO_SND_PCM_RATE_176400) |
56         (((uint64_t)1) << (uint8_t)
57              AudioStreamRate::VIRTIO_SND_PCM_RATE_192000) |
58         (((uint64_t)1) << (uint8_t)
59              AudioStreamRate::VIRTIO_SND_PCM_RATE_384000)),
60     .direction = (uint8_t)AudioStreamDirection::VIRTIO_SND_D_OUTPUT,
61     .channels_min = 1,
62     .channels_max = 2,
63 }, {
64     .hdr =
65         {
66             .hda_fn_nid = Le32(0),
67         },
68     .features = Le32(0),
69     // webrtc's api is quite primitive and doesn't allow for many different
70     // formats: It only takes the bits_per_sample as a parameter and assumes
71     // the underlying format to be one of the following:
72     .formats = Le64(
73         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U8) |
74         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U16) |
75         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24) |
76         (((uint64_t)1) << (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U32)),
77     .rates = Le64(
78         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_5512) |
79         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_8000) |
80         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_11025) |
81         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_16000) |
82         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_22050) |
83         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_32000) |
84         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_44100) |
85         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_48000) |
86         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_64000) |
87         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_88200) |
88         (((uint64_t)1) << (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_96000) |
89         (((uint64_t)1) << (uint8_t)
90              AudioStreamRate::VIRTIO_SND_PCM_RATE_176400) |
91         (((uint64_t)1) << (uint8_t)
92              AudioStreamRate::VIRTIO_SND_PCM_RATE_192000) |
93         (((uint64_t)1) << (uint8_t)
94              AudioStreamRate::VIRTIO_SND_PCM_RATE_384000)),
95     .direction = (uint8_t)AudioStreamDirection::VIRTIO_SND_D_INPUT,
96     .channels_min = 1,
97     .channels_max = 2,
98 }};
99 constexpr uint32_t NUM_STREAMS = sizeof(STREAMS) / sizeof(STREAMS[0]);
100 
IsCapture(uint32_t stream_id)101 bool IsCapture(uint32_t stream_id) {
102   CHECK(stream_id < NUM_STREAMS) << "Invalid stream id: " << stream_id;
103   return STREAMS[stream_id].direction ==
104          (uint8_t)AudioStreamDirection::VIRTIO_SND_D_INPUT;
105 }
106 
107 class CvdAudioFrameBuffer : public webrtc_streaming::AudioFrameBuffer {
108  public:
CvdAudioFrameBuffer(const uint8_t * buffer,int bits_per_sample,int sample_rate,int channels,int frames)109   CvdAudioFrameBuffer(const uint8_t* buffer, int bits_per_sample,
110                       int sample_rate, int channels, int frames)
111       : buffer_(buffer),
112         bits_per_sample_(bits_per_sample),
113         sample_rate_(sample_rate),
114         channels_(channels),
115         frames_(frames) {}
116 
bits_per_sample() const117   int bits_per_sample() const override { return bits_per_sample_; }
118 
sample_rate() const119   int sample_rate() const override { return sample_rate_; }
120 
channels() const121   int channels() const override { return channels_; }
122 
frames() const123   int frames() const override { return frames_; }
124 
data() const125   const uint8_t* data() const override { return buffer_; }
126 
127  private:
128   const uint8_t* buffer_;
129   int bits_per_sample_;
130   int sample_rate_;
131   int channels_;
132   int frames_;
133 };
134 
BitsPerSample(uint8_t virtio_format)135 int BitsPerSample(uint8_t virtio_format) {
136   switch (virtio_format) {
137     /* analog formats (width / physical width) */
138     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_IMA_ADPCM:
139       /*  4 /  4 bits */
140       return 4;
141     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_MU_LAW:
142       /*  8 /  8 bits */
143       return 8;
144     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_A_LAW:
145       /*  8 /  8 bits */
146       return 8;
147     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S8:
148       /*  8 /  8 bits */
149       return 8;
150     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U8:
151       /*  8 /  8 bits */
152       return 8;
153     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S16:
154       /* 16 / 16 bits */
155       return 16;
156     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U16:
157       /* 16 / 16 bits */
158       return 16;
159     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S18_3:
160       /* 18 / 24 bits */
161       return 24;
162     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U18_3:
163       /* 18 / 24 bits */
164       return 24;
165     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S20_3:
166       /* 20 / 24 bits */
167       return 24;
168     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U20_3:
169       /* 20 / 24 bits */
170       return 24;
171     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S24_3:
172       /* 24 / 24 bits */
173       return 24;
174     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24_3:
175       /* 24 / 24 bits */
176       return 24;
177     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S20:
178       /* 20 / 32 bits */
179       return 32;
180     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U20:
181       /* 20 / 32 bits */
182       return 32;
183     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S24:
184       /* 24 / 32 bits */
185       return 32;
186     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U24:
187       /* 24 / 32 bits */
188       return 32;
189     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_S32:
190       /* 32 / 32 bits */
191       return 32;
192     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_U32:
193       /* 32 / 32 bits */
194       return 32;
195     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_FLOAT:
196       /* 32 / 32 bits */
197       return 32;
198     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_FLOAT64:
199       /* 64 / 64 bits */
200       return 64;
201     /* digital formats (width / physical width) */
202     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_DSD_U8:
203       /*  8 /  8 bits */
204       return 8;
205     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_DSD_U16:
206       /* 16 / 16 bits */
207       return 16;
208     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_DSD_U32:
209       /* 32 / 32 bits */
210       return 32;
211     case (uint8_t)AudioStreamFormat::VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME:
212       /* 32 / 32 bits */
213       return 32;
214     default:
215       LOG(ERROR) << "Unknown virtio-snd audio format: " << virtio_format;
216       return -1;
217   }
218 }
219 
SampleRate(uint8_t virtio_rate)220 int SampleRate(uint8_t virtio_rate) {
221   switch (virtio_rate) {
222     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_5512:
223       return 5512;
224     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_8000:
225       return 8000;
226     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_11025:
227       return 11025;
228     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_16000:
229       return 16000;
230     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_22050:
231       return 22050;
232     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_32000:
233       return 32000;
234     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_44100:
235       return 44100;
236     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_48000:
237       return 48000;
238     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_64000:
239       return 64000;
240     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_88200:
241       return 88200;
242     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_96000:
243       return 96000;
244     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_176400:
245       return 176400;
246     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_192000:
247       return 192000;
248     case (uint8_t)AudioStreamRate::VIRTIO_SND_PCM_RATE_384000:
249       return 384000;
250     default:
251       LOG(ERROR) << "Unknown virtio-snd sample rate: " << virtio_rate;
252       return -1;
253   }
254 }
255 
256 }  // namespace
257 
AudioHandler(std::unique_ptr<AudioServer> audio_server,std::shared_ptr<webrtc_streaming::AudioSink> audio_sink,std::shared_ptr<webrtc_streaming::AudioSource> audio_source)258 AudioHandler::AudioHandler(
259     std::unique_ptr<AudioServer> audio_server,
260     std::shared_ptr<webrtc_streaming::AudioSink> audio_sink,
261     std::shared_ptr<webrtc_streaming::AudioSource> audio_source)
262     : audio_sink_(audio_sink),
263       audio_server_(std::move(audio_server)),
264       stream_descs_(NUM_STREAMS),
265       audio_source_(audio_source) {}
266 
Start()267 void AudioHandler::Start() {
268   server_thread_ = std::thread([this]() { Loop(); });
269 }
270 
Loop()271 [[noreturn]] void AudioHandler::Loop() {
272   for (;;) {
273     auto audio_client = audio_server_->AcceptClient(
274         NUM_STREAMS, 0 /* num_jacks, */, 0 /* num_chmaps, */,
275         262144 /* tx_shm_len */, 262144 /* rx_shm_len */);
276     CHECK(audio_client) << "Failed to create audio client connection instance";
277 
278     std::thread playback_thread([this, &audio_client]() {
279       while (audio_client->ReceivePlayback(*this)) {
280       }
281     });
282     std::thread capture_thread([this, &audio_client]() {
283       while (audio_client->ReceiveCapture(*this)) {
284       }
285     });
286     // Wait for the client to do something
287     while (audio_client->ReceiveCommands(*this)) {
288     }
289     playback_thread.join();
290     capture_thread.join();
291   }
292 }
293 
StreamsInfo(StreamInfoCommand & cmd)294 void AudioHandler::StreamsInfo(StreamInfoCommand& cmd) {
295   if (cmd.start_id() >= NUM_STREAMS ||
296       cmd.start_id() + cmd.count() > NUM_STREAMS) {
297     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG, {});
298     return;
299   }
300   std::vector<virtio_snd_pcm_info> stream_info(
301       &STREAMS[cmd.start_id()], &STREAMS[0] + cmd.start_id() + cmd.count());
302   cmd.Reply(AudioStatus::VIRTIO_SND_S_OK, stream_info);
303 }
304 
SetStreamParameters(StreamSetParamsCommand & cmd)305 void AudioHandler::SetStreamParameters(StreamSetParamsCommand& cmd) {
306   if (cmd.stream_id() >= NUM_STREAMS) {
307     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
308     return;
309   }
310   const auto& stream_info = STREAMS[cmd.stream_id()];
311   auto bits_per_sample = BitsPerSample(cmd.format());
312   auto sample_rate = SampleRate(cmd.rate());
313   auto channels = cmd.channels();
314   if (bits_per_sample < 0 || sample_rate < 0 ||
315       channels < stream_info.channels_min ||
316       channels > stream_info.channels_max) {
317     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
318     return;
319   }
320   {
321     std::lock_guard<std::mutex> lock(stream_descs_[cmd.stream_id()].mtx);
322     stream_descs_[cmd.stream_id()].bits_per_sample = bits_per_sample;
323     stream_descs_[cmd.stream_id()].sample_rate = sample_rate;
324     stream_descs_[cmd.stream_id()].channels = channels;
325     auto len10ms = (channels * (sample_rate / 100) * bits_per_sample) / 8;
326     stream_descs_[cmd.stream_id()].buffer.Reset(len10ms);
327   }
328   cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
329 }
330 
PrepareStream(StreamControlCommand & cmd)331 void AudioHandler::PrepareStream(StreamControlCommand& cmd) {
332   if (cmd.stream_id() >= NUM_STREAMS) {
333     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
334     return;
335   }
336   cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
337 }
338 
ReleaseStream(StreamControlCommand & cmd)339 void AudioHandler::ReleaseStream(StreamControlCommand& cmd) {
340   if (cmd.stream_id() >= NUM_STREAMS) {
341     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
342     return;
343   }
344   cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
345 }
346 
StartStream(StreamControlCommand & cmd)347 void AudioHandler::StartStream(StreamControlCommand& cmd) {
348   if (cmd.stream_id() >= NUM_STREAMS) {
349     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
350     return;
351   }
352   stream_descs_[cmd.stream_id()].active = true;
353   cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
354 }
355 
StopStream(StreamControlCommand & cmd)356 void AudioHandler::StopStream(StreamControlCommand& cmd) {
357   if (cmd.stream_id() >= NUM_STREAMS) {
358     cmd.Reply(AudioStatus::VIRTIO_SND_S_BAD_MSG);
359     return;
360   }
361   stream_descs_[cmd.stream_id()].active = false;
362   cmd.Reply(AudioStatus::VIRTIO_SND_S_OK);
363 }
364 
OnPlaybackBuffer(TxBuffer buffer)365 void AudioHandler::OnPlaybackBuffer(TxBuffer buffer) {
366   auto stream_id = buffer.stream_id();
367   auto& stream_desc = stream_descs_[stream_id];
368   {
369     std::lock_guard<std::mutex> lock(stream_desc.mtx);
370     auto& holding_buffer = stream_descs_[stream_id].buffer;
371     // Invalid or capture streams shouldn't send tx buffers
372     if (stream_id >= NUM_STREAMS || IsCapture(stream_id)) {
373       buffer.SendStatus(AudioStatus::VIRTIO_SND_S_BAD_MSG, 0, 0);
374       return;
375     }
376     // A buffer may be received for an inactive stream if we were slow to
377     // process it and the other side stopped the stream. Quitely ignore it in
378     // that case
379     if (!stream_desc.active) {
380       buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
381       return;
382     }
383     // Webrtc will silently ignore any buffer with a length different than 10ms,
384     // so we must split any buffer bigger than that and temporarily store any
385     // remaining frames that are less than that size.
386     auto current_time = rtc::TimeMillis();
387     // The timestamp of the first 10ms chunk to be sent so that the last one
388     // will have the current time
389     auto base_time =
390         current_time - ((buffer.len() - 1) / holding_buffer.buffer.size()) * 10;
391     // number of frames in a 10 ms buffer
392     const int frames = stream_desc.sample_rate / 100;
393     size_t pos = 0;
394     while (pos < buffer.len()) {
395       if (holding_buffer.empty() &&
396           buffer.len() - pos >= holding_buffer.buffer.size()) {
397         // Avoid the extra copy into holding buffer
398         // This casts away volatility of the pointer, necessary because the
399         // webrtc api doesn't expect volatile memory. This should be safe though
400         // because webrtc will use the contents of the buffer before returning
401         // and only then we release it.
402         auto audio_frame_buffer = std::make_shared<CvdAudioFrameBuffer>(
403             const_cast<const uint8_t*>(&buffer.get()[pos]),
404             stream_desc.bits_per_sample, stream_desc.sample_rate,
405             stream_desc.channels, frames);
406         audio_sink_->OnFrame(audio_frame_buffer, base_time);
407         pos += holding_buffer.buffer.size();
408       } else {
409         pos += holding_buffer.Add(buffer.get() + pos, buffer.len() - pos);
410         if (holding_buffer.full()) {
411           auto buffer_ptr = const_cast<const uint8_t*>(holding_buffer.data());
412           auto audio_frame_buffer = std::make_shared<CvdAudioFrameBuffer>(
413               buffer_ptr, stream_desc.bits_per_sample,
414               stream_desc.sample_rate, stream_desc.channels, frames);
415           audio_sink_->OnFrame(audio_frame_buffer, base_time);
416           holding_buffer.count = 0;
417         }
418       }
419       base_time += 10;
420     }
421   }
422   buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
423 }
424 
OnCaptureBuffer(RxBuffer buffer)425 void AudioHandler::OnCaptureBuffer(RxBuffer buffer) {
426   auto stream_id = buffer.stream_id();
427   auto& stream_desc = stream_descs_[stream_id];
428   {
429     std::lock_guard<std::mutex> lock(stream_desc.mtx);
430     // Invalid or playback streams shouldn't send rx buffers
431     if (stream_id >= NUM_STREAMS || !IsCapture(stream_id)) {
432       LOG(ERROR) << "Received capture buffers on playback stream " << stream_id;
433       buffer.SendStatus(AudioStatus::VIRTIO_SND_S_BAD_MSG, 0, 0);
434       return;
435     }
436     // A buffer may be received for an inactive stream if we were slow to
437     // process it and the other side stopped the stream. Quitely ignore it in
438     // that case
439     if (!stream_desc.active) {
440       buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
441       return;
442     }
443     auto bytes_per_sample = stream_desc.bits_per_sample / 8;
444     auto samples_per_channel =
445         buffer.len() / stream_desc.channels / bytes_per_sample;
446     bool muted = false;
447     auto res = audio_source_->GetMoreAudioData(
448         const_cast<uint8_t*>(buffer.get()), bytes_per_sample,
449         samples_per_channel, stream_desc.channels, stream_desc.sample_rate,
450         muted);
451     if (res < 0) {
452       // This is likely a recoverable error, log the error but don't let the VMM
453       // know about it so that it doesn't crash.
454       LOG(ERROR) << "Failed to receive audio data from client";
455     }
456   }
457   buffer.SendStatus(AudioStatus::VIRTIO_SND_S_OK, 0, buffer.len());
458 }
459 
Reset(size_t size)460 void AudioHandler::HoldingBuffer::Reset(size_t size) {
461   buffer.resize(size);
462   count = 0;
463 }
464 
Add(const volatile uint8_t * data,size_t max_len)465 size_t AudioHandler::HoldingBuffer::Add(const volatile uint8_t* data,
466                                         size_t max_len) {
467   auto added_len = std::min(max_len, buffer.size() - count);
468   std::copy(data, data + added_len, &buffer[count]);
469   count += added_len;
470   return added_len;
471 }
472 
empty() const473 bool AudioHandler::HoldingBuffer::empty() const { return count == 0; }
474 
full() const475 bool AudioHandler::HoldingBuffer::full() const {
476   return count == buffer.size();
477 }
478 
data()479 uint8_t* AudioHandler::HoldingBuffer::data() { return buffer.data(); }
480 
481 }  // namespace cuttlefish
482