blob: d10a2bd464bc2c86c13ca02399f288cca1e45694 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org20aabbb2012-02-20 09:17:41 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.org811269d2013-07-11 13:24:38 +000011#include "webrtc/modules/audio_device/audio_device_buffer.h"
andrew@webrtc.org25534502013-09-13 00:02:13 +000012
13#include <assert.h>
14#include <string.h>
15
Peter Kastingdce40cf2015-08-24 14:52:23 -070016#include "webrtc/base/format_macros.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000017#include "webrtc/modules/audio_device/audio_device_config.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010018#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
19#include "webrtc/system_wrappers/include/logging.h"
20#include "webrtc/system_wrappers/include/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
niklase@google.com470e71d2011-07-07 08:21:25 +000022namespace webrtc {
23
andrew@webrtc.org8f940132013-09-11 22:35:00 +000024static const int kHighDelayThresholdMs = 300;
25static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
26
niklase@google.com470e71d2011-07-07 08:21:25 +000027// ----------------------------------------------------------------------------
28// ctor
29// ----------------------------------------------------------------------------
30
henrika0fd68012016-07-04 13:01:19 +020031AudioDeviceBuffer::AudioDeviceBuffer()
32 : _id(-1),
33 _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
34 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
35 _ptrCbAudioTransport(NULL),
36 _recSampleRate(0),
37 _playSampleRate(0),
38 _recChannels(0),
39 _playChannels(0),
40 _recChannel(AudioDeviceModule::kChannelBoth),
41 _recBytesPerSample(0),
42 _playBytesPerSample(0),
43 _recSamples(0),
44 _recSize(0),
45 _playSamples(0),
46 _playSize(0),
47 _recFile(*FileWrapper::Create()),
48 _playFile(*FileWrapper::Create()),
49 _currentMicLevel(0),
50 _newMicLevel(0),
51 _typingStatus(false),
52 _playDelayMS(0),
53 _recDelayMS(0),
54 _clockDrift(0),
55 // Set to the interval in order to log on the first occurrence.
56 high_delay_counter_(kLogHighDelayIntervalFrames) {
57 // valid ID will be set later by SetId, use -1 for now
58 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created",
59 __FUNCTION__);
60 memset(_recBuffer, 0, kMaxBufferSizeBytes);
61 memset(_playBuffer, 0, kMaxBufferSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +000062}
63
64// ----------------------------------------------------------------------------
65// dtor
66// ----------------------------------------------------------------------------
67
henrika0fd68012016-07-04 13:01:19 +020068AudioDeviceBuffer::~AudioDeviceBuffer() {
69 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed",
70 __FUNCTION__);
71 {
72 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000073
henrika0fd68012016-07-04 13:01:19 +020074 _recFile.Flush();
75 _recFile.CloseFile();
76 delete &_recFile;
niklase@google.com470e71d2011-07-07 08:21:25 +000077
henrika0fd68012016-07-04 13:01:19 +020078 _playFile.Flush();
79 _playFile.CloseFile();
80 delete &_playFile;
81 }
niklase@google.com470e71d2011-07-07 08:21:25 +000082
henrika0fd68012016-07-04 13:01:19 +020083 delete &_critSect;
84 delete &_critSectCb;
niklase@google.com470e71d2011-07-07 08:21:25 +000085}
86
87// ----------------------------------------------------------------------------
88// SetId
89// ----------------------------------------------------------------------------
90
henrika0fd68012016-07-04 13:01:19 +020091void AudioDeviceBuffer::SetId(uint32_t id) {
92 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id,
93 "AudioDeviceBuffer::SetId(id=%d)", id);
94 _id = id;
niklase@google.com470e71d2011-07-07 08:21:25 +000095}
96
97// ----------------------------------------------------------------------------
98// RegisterAudioCallback
99// ----------------------------------------------------------------------------
100
henrika0fd68012016-07-04 13:01:19 +0200101int32_t AudioDeviceBuffer::RegisterAudioCallback(
102 AudioTransport* audioCallback) {
103 CriticalSectionScoped lock(&_critSectCb);
104 _ptrCbAudioTransport = audioCallback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000105
henrika0fd68012016-07-04 13:01:19 +0200106 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107}
108
109// ----------------------------------------------------------------------------
110// InitPlayout
111// ----------------------------------------------------------------------------
112
henrika0fd68012016-07-04 13:01:19 +0200113int32_t AudioDeviceBuffer::InitPlayout() {
114 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
115 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000116}
117
118// ----------------------------------------------------------------------------
119// InitRecording
120// ----------------------------------------------------------------------------
121
henrika0fd68012016-07-04 13:01:19 +0200122int32_t AudioDeviceBuffer::InitRecording() {
123 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
124 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000125}
126
127// ----------------------------------------------------------------------------
128// SetRecordingSampleRate
129// ----------------------------------------------------------------------------
130
henrika0fd68012016-07-04 13:01:19 +0200131int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz) {
132 CriticalSectionScoped lock(&_critSect);
133 _recSampleRate = fsHz;
134 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000135}
136
137// ----------------------------------------------------------------------------
138// SetPlayoutSampleRate
139// ----------------------------------------------------------------------------
140
henrika0fd68012016-07-04 13:01:19 +0200141int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz) {
142 CriticalSectionScoped lock(&_critSect);
143 _playSampleRate = fsHz;
144 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000145}
146
147// ----------------------------------------------------------------------------
148// RecordingSampleRate
149// ----------------------------------------------------------------------------
150
henrika0fd68012016-07-04 13:01:19 +0200151int32_t AudioDeviceBuffer::RecordingSampleRate() const {
152 return _recSampleRate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
155// ----------------------------------------------------------------------------
156// PlayoutSampleRate
157// ----------------------------------------------------------------------------
158
henrika0fd68012016-07-04 13:01:19 +0200159int32_t AudioDeviceBuffer::PlayoutSampleRate() const {
160 return _playSampleRate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161}
162
163// ----------------------------------------------------------------------------
164// SetRecordingChannels
165// ----------------------------------------------------------------------------
166
henrika0fd68012016-07-04 13:01:19 +0200167int32_t AudioDeviceBuffer::SetRecordingChannels(size_t channels) {
168 CriticalSectionScoped lock(&_critSect);
169 _recChannels = channels;
170 _recBytesPerSample =
171 2 * channels; // 16 bits per sample in mono, 32 bits in stereo
172 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000173}
174
175// ----------------------------------------------------------------------------
176// SetPlayoutChannels
177// ----------------------------------------------------------------------------
178
henrika0fd68012016-07-04 13:01:19 +0200179int32_t AudioDeviceBuffer::SetPlayoutChannels(size_t channels) {
180 CriticalSectionScoped lock(&_critSect);
181 _playChannels = channels;
182 // 16 bits per sample in mono, 32 bits in stereo
183 _playBytesPerSample = 2 * channels;
184 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185}
186
187// ----------------------------------------------------------------------------
188// SetRecordingChannel
189//
190// Select which channel to use while recording.
191// This API requires that stereo is enabled.
192//
193// Note that, the nChannel parameter in RecordedDataIsAvailable will be
194// set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample
195// will be 2 instead of 4 four these cases.
196// ----------------------------------------------------------------------------
197
henrika0fd68012016-07-04 13:01:19 +0200198int32_t AudioDeviceBuffer::SetRecordingChannel(
199 const AudioDeviceModule::ChannelType channel) {
200 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000201
henrika0fd68012016-07-04 13:01:19 +0200202 if (_recChannels == 1) {
203 return -1;
204 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000205
henrika0fd68012016-07-04 13:01:19 +0200206 if (channel == AudioDeviceModule::kChannelBoth) {
207 // two bytes per channel
208 _recBytesPerSample = 4;
209 } else {
210 // only utilize one out of two possible channels (left or right)
211 _recBytesPerSample = 2;
212 }
213 _recChannel = channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214
henrika0fd68012016-07-04 13:01:19 +0200215 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
218// ----------------------------------------------------------------------------
219// RecordingChannel
220// ----------------------------------------------------------------------------
221
henrika0fd68012016-07-04 13:01:19 +0200222int32_t AudioDeviceBuffer::RecordingChannel(
223 AudioDeviceModule::ChannelType& channel) const {
224 channel = _recChannel;
225 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
228// ----------------------------------------------------------------------------
229// RecordingChannels
230// ----------------------------------------------------------------------------
231
henrika0fd68012016-07-04 13:01:19 +0200232size_t AudioDeviceBuffer::RecordingChannels() const {
233 return _recChannels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000234}
235
236// ----------------------------------------------------------------------------
237// PlayoutChannels
238// ----------------------------------------------------------------------------
239
henrika0fd68012016-07-04 13:01:19 +0200240size_t AudioDeviceBuffer::PlayoutChannels() const {
241 return _playChannels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000242}
243
244// ----------------------------------------------------------------------------
245// SetCurrentMicLevel
246// ----------------------------------------------------------------------------
247
henrika0fd68012016-07-04 13:01:19 +0200248int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level) {
249 _currentMicLevel = level;
250 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000251}
252
henrika0fd68012016-07-04 13:01:19 +0200253int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus) {
254 _typingStatus = typingStatus;
255 return 0;
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000256}
257
niklase@google.com470e71d2011-07-07 08:21:25 +0000258// ----------------------------------------------------------------------------
259// NewMicLevel
260// ----------------------------------------------------------------------------
261
henrika0fd68012016-07-04 13:01:19 +0200262uint32_t AudioDeviceBuffer::NewMicLevel() const {
263 return _newMicLevel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000264}
265
266// ----------------------------------------------------------------------------
267// SetVQEData
268// ----------------------------------------------------------------------------
269
henrika0fd68012016-07-04 13:01:19 +0200270void AudioDeviceBuffer::SetVQEData(int playDelayMs,
271 int recDelayMs,
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000272 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000273 if (high_delay_counter_ < kLogHighDelayIntervalFrames) {
274 ++high_delay_counter_;
275 } else {
276 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
277 high_delay_counter_ = 0;
278 LOG(LS_WARNING) << "High audio device delay reported (render="
279 << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000280 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000281 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000282
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000283 _playDelayMS = playDelayMs;
284 _recDelayMS = recDelayMs;
285 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000286}
287
288// ----------------------------------------------------------------------------
289// StartInputFileRecording
290// ----------------------------------------------------------------------------
291
pbos@webrtc.org25509882013-04-09 10:30:35 +0000292int32_t AudioDeviceBuffer::StartInputFileRecording(
henrika0fd68012016-07-04 13:01:19 +0200293 const char fileName[kAdmMaxFileNameSize]) {
294 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
henrika0fd68012016-07-04 13:01:19 +0200296 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000297
henrika0fd68012016-07-04 13:01:19 +0200298 _recFile.Flush();
299 _recFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000300
henrika0fd68012016-07-04 13:01:19 +0200301 return _recFile.OpenFile(fileName, false) ? 0 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000302}
303
304// ----------------------------------------------------------------------------
305// StopInputFileRecording
306// ----------------------------------------------------------------------------
307
henrika0fd68012016-07-04 13:01:19 +0200308int32_t AudioDeviceBuffer::StopInputFileRecording() {
309 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000310
henrika0fd68012016-07-04 13:01:19 +0200311 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000312
henrika0fd68012016-07-04 13:01:19 +0200313 _recFile.Flush();
314 _recFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000315
henrika0fd68012016-07-04 13:01:19 +0200316 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317}
318
319// ----------------------------------------------------------------------------
320// StartOutputFileRecording
321// ----------------------------------------------------------------------------
322
pbos@webrtc.org25509882013-04-09 10:30:35 +0000323int32_t AudioDeviceBuffer::StartOutputFileRecording(
henrika0fd68012016-07-04 13:01:19 +0200324 const char fileName[kAdmMaxFileNameSize]) {
325 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000326
henrika0fd68012016-07-04 13:01:19 +0200327 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000328
henrika0fd68012016-07-04 13:01:19 +0200329 _playFile.Flush();
330 _playFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000331
henrika0fd68012016-07-04 13:01:19 +0200332 return _playFile.OpenFile(fileName, false) ? 0 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000333}
334
335// ----------------------------------------------------------------------------
336// StopOutputFileRecording
337// ----------------------------------------------------------------------------
338
henrika0fd68012016-07-04 13:01:19 +0200339int32_t AudioDeviceBuffer::StopOutputFileRecording() {
340 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000341
henrika0fd68012016-07-04 13:01:19 +0200342 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000343
henrika0fd68012016-07-04 13:01:19 +0200344 _playFile.Flush();
345 _playFile.CloseFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000346
henrika0fd68012016-07-04 13:01:19 +0200347 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000348}
349
350// ----------------------------------------------------------------------------
351// SetRecordedBuffer
352//
353// Store recorded audio buffer in local memory ready for the actual
354// "delivery" using a callback.
355//
356// This method can also parse out left or right channel from a stereo
357// input signal, i.e., emulate mono.
358//
359// Examples:
360//
361// 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000362// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000363// ----------------------------------------------------------------------------
364
pbos@webrtc.org25509882013-04-09 10:30:35 +0000365int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
henrika0fd68012016-07-04 13:01:19 +0200366 size_t nSamples) {
367 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
henrika0fd68012016-07-04 13:01:19 +0200369 if (_recBytesPerSample == 0) {
370 assert(false);
371 return -1;
372 }
373
374 _recSamples = nSamples;
375 _recSize = _recBytesPerSample * nSamples; // {2,4}*nSamples
376 if (_recSize > kMaxBufferSizeBytes) {
377 assert(false);
378 return -1;
379 }
380
381 if (_recChannel == AudioDeviceModule::kChannelBoth) {
382 // (default) copy the complete input buffer to the local buffer
383 memcpy(&_recBuffer[0], audioBuffer, _recSize);
384 } else {
385 int16_t* ptr16In = (int16_t*)audioBuffer;
386 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
387
388 if (AudioDeviceModule::kChannelRight == _recChannel) {
389 ptr16In++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000390 }
391
henrika0fd68012016-07-04 13:01:19 +0200392 // exctract left or right channel from input buffer to the local buffer
393 for (size_t i = 0; i < _recSamples; i++) {
394 *ptr16Out = *ptr16In;
395 ptr16Out++;
396 ptr16In++;
397 ptr16In++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000398 }
henrika0fd68012016-07-04 13:01:19 +0200399 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
henrika0fd68012016-07-04 13:01:19 +0200401 if (_recFile.is_open()) {
402 // write to binary file in mono or stereo (interleaved)
403 _recFile.Write(&_recBuffer[0], _recSize);
404 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
henrika0fd68012016-07-04 13:01:19 +0200406 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407}
408
409// ----------------------------------------------------------------------------
410// DeliverRecordedData
411// ----------------------------------------------------------------------------
412
henrika0fd68012016-07-04 13:01:19 +0200413int32_t AudioDeviceBuffer::DeliverRecordedData() {
414 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
henrika0fd68012016-07-04 13:01:19 +0200416 // Ensure that user has initialized all essential members
417 if ((_recSampleRate == 0) || (_recSamples == 0) ||
418 (_recBytesPerSample == 0) || (_recChannels == 0)) {
419 assert(false);
420 return -1;
421 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
henrika0fd68012016-07-04 13:01:19 +0200423 if (_ptrCbAudioTransport == NULL) {
424 WEBRTC_TRACE(
425 kTraceWarning, kTraceAudioDevice, _id,
426 "failed to deliver recorded data (AudioTransport does not exist)");
niklase@google.com470e71d2011-07-07 08:21:25 +0000427 return 0;
henrika0fd68012016-07-04 13:01:19 +0200428 }
429
430 int32_t res(0);
431 uint32_t newMicLevel(0);
432 uint32_t totalDelayMS = _playDelayMS + _recDelayMS;
433
434 res = _ptrCbAudioTransport->RecordedDataIsAvailable(
435 &_recBuffer[0], _recSamples, _recBytesPerSample, _recChannels,
436 _recSampleRate, totalDelayMS, _clockDrift, _currentMicLevel,
437 _typingStatus, newMicLevel);
438 if (res != -1) {
439 _newMicLevel = newMicLevel;
440 }
441
442 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000443}
444
445// ----------------------------------------------------------------------------
446// RequestPlayoutData
447// ----------------------------------------------------------------------------
448
henrika0fd68012016-07-04 13:01:19 +0200449int32_t AudioDeviceBuffer::RequestPlayoutData(size_t nSamples) {
450 uint32_t playSampleRate = 0;
451 size_t playBytesPerSample = 0;
452 size_t playChannels = 0;
453 {
454 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
henrika0fd68012016-07-04 13:01:19 +0200456 // Store copies under lock and use copies hereafter to avoid race with
457 // setter methods.
458 playSampleRate = _playSampleRate;
459 playBytesPerSample = _playBytesPerSample;
460 playChannels = _playChannels;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000461
henrika0fd68012016-07-04 13:01:19 +0200462 // Ensure that user has initialized all essential members
463 if ((playBytesPerSample == 0) || (playChannels == 0) ||
464 (playSampleRate == 0)) {
465 assert(false);
466 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000467 }
468
henrika0fd68012016-07-04 13:01:19 +0200469 _playSamples = nSamples;
470 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
471 if (_playSize > kMaxBufferSizeBytes) {
472 assert(false);
473 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000474 }
475
henrika0fd68012016-07-04 13:01:19 +0200476 if (nSamples != _playSamples) {
477 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
478 "invalid number of samples to be played out (%d)", nSamples);
479 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000480 }
henrika0fd68012016-07-04 13:01:19 +0200481 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000482
henrika0fd68012016-07-04 13:01:19 +0200483 size_t nSamplesOut(0);
484
485 CriticalSectionScoped lock(&_critSectCb);
486
487 if (_ptrCbAudioTransport == NULL) {
488 WEBRTC_TRACE(
489 kTraceWarning, kTraceAudioDevice, _id,
490 "failed to feed data to playout (AudioTransport does not exist)");
491 return 0;
492 }
493
494 if (_ptrCbAudioTransport) {
495 uint32_t res(0);
496 int64_t elapsed_time_ms = -1;
497 int64_t ntp_time_ms = -1;
498 res = _ptrCbAudioTransport->NeedMorePlayData(
499 _playSamples, playBytesPerSample, playChannels, playSampleRate,
500 &_playBuffer[0], nSamplesOut, &elapsed_time_ms, &ntp_time_ms);
501 if (res != 0) {
502 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
503 "NeedMorePlayData() failed");
504 }
505 }
506
507 return static_cast<int32_t>(nSamplesOut);
niklase@google.com470e71d2011-07-07 08:21:25 +0000508}
509
510// ----------------------------------------------------------------------------
511// GetPlayoutData
512// ----------------------------------------------------------------------------
513
henrika0fd68012016-07-04 13:01:19 +0200514int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer) {
515 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000516
henrika0fd68012016-07-04 13:01:19 +0200517 if (_playSize > kMaxBufferSizeBytes) {
518 WEBRTC_TRACE(kTraceError, kTraceUtility, _id,
519 "_playSize %" PRIuS
520 " exceeds kMaxBufferSizeBytes in "
521 "AudioDeviceBuffer::GetPlayoutData",
522 _playSize);
523 assert(false);
524 return -1;
525 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000526
henrika0fd68012016-07-04 13:01:19 +0200527 memcpy(audioBuffer, &_playBuffer[0], _playSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000528
henrika0fd68012016-07-04 13:01:19 +0200529 if (_playFile.is_open()) {
530 // write to binary file in mono or stereo (interleaved)
531 _playFile.Write(&_playBuffer[0], _playSize);
532 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000533
henrika0fd68012016-07-04 13:01:19 +0200534 return static_cast<int32_t>(_playSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +0000535}
536
niklase@google.com470e71d2011-07-07 08:21:25 +0000537} // namespace webrtc