blob: 12b28b3ab3f7cafaa9ce9b568864d6f69430d66c [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
pbos@webrtc.org811269d2013-07-11 13:24:38 +000016#include "webrtc/modules/audio_device/audio_device_config.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000017#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andrew@webrtc.org8f940132013-09-11 22:35:00 +000018#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org811269d2013-07-11 13:24:38 +000019#include "webrtc/system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
niklase@google.com470e71d2011-07-07 08:21:25 +000021namespace webrtc {
22
andrew@webrtc.org8f940132013-09-11 22:35:00 +000023static const int kHighDelayThresholdMs = 300;
24static const int kLogHighDelayIntervalFrames = 500; // 5 seconds.
25
niklase@google.com470e71d2011-07-07 08:21:25 +000026// ----------------------------------------------------------------------------
27// ctor
28// ----------------------------------------------------------------------------
29
30AudioDeviceBuffer::AudioDeviceBuffer() :
31 _id(-1),
32 _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
33 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()),
34 _ptrCbAudioTransport(NULL),
35 _recSampleRate(0),
36 _playSampleRate(0),
37 _recChannels(0),
38 _playChannels(0),
39 _recChannel(AudioDeviceModule::kChannelBoth),
40 _recBytesPerSample(0),
41 _playBytesPerSample(0),
42 _recSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000043 _recSize(0),
xians@google.com88bd4402011-08-04 15:33:30 +000044 _playSamples(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000045 _playSize(0),
46 _recFile(*FileWrapper::Create()),
47 _playFile(*FileWrapper::Create()),
niklase@google.com470e71d2011-07-07 08:21:25 +000048 _currentMicLevel(0),
xians@google.com88bd4402011-08-04 15:33:30 +000049 _newMicLevel(0),
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +000050 _typingStatus(false),
niklase@google.com470e71d2011-07-07 08:21:25 +000051 _playDelayMS(0),
52 _recDelayMS(0),
andrew@webrtc.org8f940132013-09-11 22:35:00 +000053 _clockDrift(0),
54 // Set to the interval in order to log on the first occurrence.
55 high_delay_counter_(kLogHighDelayIntervalFrames) {
niklase@google.com470e71d2011-07-07 08:21:25 +000056 // valid ID will be set later by SetId, use -1 for now
57 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s created", __FUNCTION__);
xians@webrtc.orgeff3c892011-12-06 10:02:56 +000058 memset(_recBuffer, 0, kMaxBufferSizeBytes);
59 memset(_playBuffer, 0, kMaxBufferSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +000060}
61
62// ----------------------------------------------------------------------------
63// dtor
64// ----------------------------------------------------------------------------
65
66AudioDeviceBuffer::~AudioDeviceBuffer()
67{
68 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
69 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +000070 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000071
72 _recFile.Flush();
73 _recFile.CloseFile();
74 delete &_recFile;
75
76 _playFile.Flush();
77 _playFile.CloseFile();
78 delete &_playFile;
niklase@google.com470e71d2011-07-07 08:21:25 +000079 }
80
81 delete &_critSect;
82 delete &_critSectCb;
83}
84
85// ----------------------------------------------------------------------------
86// SetId
87// ----------------------------------------------------------------------------
88
pbos@webrtc.org25509882013-04-09 10:30:35 +000089void AudioDeviceBuffer::SetId(uint32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000090{
91 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "AudioDeviceBuffer::SetId(id=%d)", id);
92 _id = id;
93}
94
95// ----------------------------------------------------------------------------
96// RegisterAudioCallback
97// ----------------------------------------------------------------------------
98
pbos@webrtc.org25509882013-04-09 10:30:35 +000099int32_t AudioDeviceBuffer::RegisterAudioCallback(AudioTransport* audioCallback)
niklase@google.com470e71d2011-07-07 08:21:25 +0000100{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000101 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000102 _ptrCbAudioTransport = audioCallback;
103
104 return 0;
105}
106
107// ----------------------------------------------------------------------------
108// InitPlayout
109// ----------------------------------------------------------------------------
110
pbos@webrtc.org25509882013-04-09 10:30:35 +0000111int32_t AudioDeviceBuffer::InitPlayout()
niklase@google.com470e71d2011-07-07 08:21:25 +0000112{
113 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 return 0;
115}
116
117// ----------------------------------------------------------------------------
118// InitRecording
119// ----------------------------------------------------------------------------
120
pbos@webrtc.org25509882013-04-09 10:30:35 +0000121int32_t AudioDeviceBuffer::InitRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000122{
123 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000124 return 0;
125}
126
127// ----------------------------------------------------------------------------
128// SetRecordingSampleRate
129// ----------------------------------------------------------------------------
130
pbos@webrtc.org25509882013-04-09 10:30:35 +0000131int32_t AudioDeviceBuffer::SetRecordingSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000132{
133 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingSampleRate(fsHz=%u)", fsHz);
134
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000135 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 _recSampleRate = fsHz;
137 return 0;
138}
139
140// ----------------------------------------------------------------------------
141// SetPlayoutSampleRate
142// ----------------------------------------------------------------------------
143
pbos@webrtc.org25509882013-04-09 10:30:35 +0000144int32_t AudioDeviceBuffer::SetPlayoutSampleRate(uint32_t fsHz)
niklase@google.com470e71d2011-07-07 08:21:25 +0000145{
146 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutSampleRate(fsHz=%u)", fsHz);
147
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000148 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000149 _playSampleRate = fsHz;
150 return 0;
151}
152
153// ----------------------------------------------------------------------------
154// RecordingSampleRate
155// ----------------------------------------------------------------------------
156
pbos@webrtc.org25509882013-04-09 10:30:35 +0000157int32_t AudioDeviceBuffer::RecordingSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000158{
159 return _recSampleRate;
160}
161
162// ----------------------------------------------------------------------------
163// PlayoutSampleRate
164// ----------------------------------------------------------------------------
165
pbos@webrtc.org25509882013-04-09 10:30:35 +0000166int32_t AudioDeviceBuffer::PlayoutSampleRate() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000167{
168 return _playSampleRate;
169}
170
171// ----------------------------------------------------------------------------
172// SetRecordingChannels
173// ----------------------------------------------------------------------------
174
pbos@webrtc.org25509882013-04-09 10:30:35 +0000175int32_t AudioDeviceBuffer::SetRecordingChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000176{
177 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetRecordingChannels(channels=%u)", channels);
178
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000179 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 _recChannels = channels;
181 _recBytesPerSample = 2*channels; // 16 bits per sample in mono, 32 bits in stereo
182 return 0;
183}
184
185// ----------------------------------------------------------------------------
186// SetPlayoutChannels
187// ----------------------------------------------------------------------------
188
pbos@webrtc.org25509882013-04-09 10:30:35 +0000189int32_t AudioDeviceBuffer::SetPlayoutChannels(uint8_t channels)
niklase@google.com470e71d2011-07-07 08:21:25 +0000190{
191 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "AudioDeviceBuffer::SetPlayoutChannels(channels=%u)", channels);
192
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000193 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 _playChannels = channels;
195 // 16 bits per sample in mono, 32 bits in stereo
196 _playBytesPerSample = 2*channels;
197 return 0;
198}
199
200// ----------------------------------------------------------------------------
201// SetRecordingChannel
202//
203// Select which channel to use while recording.
204// This API requires that stereo is enabled.
205//
206// Note that, the nChannel parameter in RecordedDataIsAvailable will be
207// set to 2 even for kChannelLeft and kChannelRight. However, nBytesPerSample
208// will be 2 instead of 4 four these cases.
209// ----------------------------------------------------------------------------
210
pbos@webrtc.org25509882013-04-09 10:30:35 +0000211int32_t AudioDeviceBuffer::SetRecordingChannel(const AudioDeviceModule::ChannelType channel)
niklase@google.com470e71d2011-07-07 08:21:25 +0000212{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000213 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214
215 if (_recChannels == 1)
216 {
217 return -1;
218 }
219
220 if (channel == AudioDeviceModule::kChannelBoth)
221 {
222 // two bytes per channel
223 _recBytesPerSample = 4;
224 }
225 else
226 {
227 // only utilize one out of two possible channels (left or right)
228 _recBytesPerSample = 2;
229 }
230 _recChannel = channel;
231
232 return 0;
233}
234
235// ----------------------------------------------------------------------------
236// RecordingChannel
237// ----------------------------------------------------------------------------
238
pbos@webrtc.org25509882013-04-09 10:30:35 +0000239int32_t AudioDeviceBuffer::RecordingChannel(AudioDeviceModule::ChannelType& channel) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000240{
241 channel = _recChannel;
242 return 0;
243}
244
245// ----------------------------------------------------------------------------
246// RecordingChannels
247// ----------------------------------------------------------------------------
248
pbos@webrtc.org25509882013-04-09 10:30:35 +0000249uint8_t AudioDeviceBuffer::RecordingChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000250{
251 return _recChannels;
252}
253
254// ----------------------------------------------------------------------------
255// PlayoutChannels
256// ----------------------------------------------------------------------------
257
pbos@webrtc.org25509882013-04-09 10:30:35 +0000258uint8_t AudioDeviceBuffer::PlayoutChannels() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000259{
260 return _playChannels;
261}
262
263// ----------------------------------------------------------------------------
264// SetCurrentMicLevel
265// ----------------------------------------------------------------------------
266
pbos@webrtc.org25509882013-04-09 10:30:35 +0000267int32_t AudioDeviceBuffer::SetCurrentMicLevel(uint32_t level)
niklase@google.com470e71d2011-07-07 08:21:25 +0000268{
269 _currentMicLevel = level;
270 return 0;
271}
272
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000273int32_t AudioDeviceBuffer::SetTypingStatus(bool typingStatus)
274{
275 _typingStatus = typingStatus;
276 return 0;
277}
278
niklase@google.com470e71d2011-07-07 08:21:25 +0000279// ----------------------------------------------------------------------------
280// NewMicLevel
281// ----------------------------------------------------------------------------
282
pbos@webrtc.org25509882013-04-09 10:30:35 +0000283uint32_t AudioDeviceBuffer::NewMicLevel() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000284{
285 return _newMicLevel;
286}
287
288// ----------------------------------------------------------------------------
289// SetVQEData
290// ----------------------------------------------------------------------------
291
andrew@webrtc.org5eb997a2013-09-12 01:01:42 +0000292void AudioDeviceBuffer::SetVQEData(int playDelayMs, int recDelayMs,
293 int clockDrift) {
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000294 if (high_delay_counter_ < kLogHighDelayIntervalFrames) {
295 ++high_delay_counter_;
296 } else {
297 if (playDelayMs + recDelayMs > kHighDelayThresholdMs) {
298 high_delay_counter_ = 0;
299 LOG(LS_WARNING) << "High audio device delay reported (render="
300 << playDelayMs << " ms, capture=" << recDelayMs << " ms)";
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 }
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000302 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000303
andrew@webrtc.org8f940132013-09-11 22:35:00 +0000304 _playDelayMS = playDelayMs;
305 _recDelayMS = recDelayMs;
306 _clockDrift = clockDrift;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
309// ----------------------------------------------------------------------------
310// StartInputFileRecording
311// ----------------------------------------------------------------------------
312
pbos@webrtc.org25509882013-04-09 10:30:35 +0000313int32_t AudioDeviceBuffer::StartInputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000314 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000315{
316 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
317
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000318 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000319
320 _recFile.Flush();
321 _recFile.CloseFile();
322
323 return (_recFile.OpenFile(fileName, false, false, false));
324}
325
326// ----------------------------------------------------------------------------
327// StopInputFileRecording
328// ----------------------------------------------------------------------------
329
pbos@webrtc.org25509882013-04-09 10:30:35 +0000330int32_t AudioDeviceBuffer::StopInputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000331{
332 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
333
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000334 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000335
336 _recFile.Flush();
337 _recFile.CloseFile();
338
339 return 0;
340}
341
342// ----------------------------------------------------------------------------
343// StartOutputFileRecording
344// ----------------------------------------------------------------------------
345
pbos@webrtc.org25509882013-04-09 10:30:35 +0000346int32_t AudioDeviceBuffer::StartOutputFileRecording(
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000347 const char fileName[kAdmMaxFileNameSize])
niklase@google.com470e71d2011-07-07 08:21:25 +0000348{
349 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
350
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000351 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
353 _playFile.Flush();
354 _playFile.CloseFile();
355
356 return (_playFile.OpenFile(fileName, false, false, false));
357}
358
359// ----------------------------------------------------------------------------
360// StopOutputFileRecording
361// ----------------------------------------------------------------------------
362
pbos@webrtc.org25509882013-04-09 10:30:35 +0000363int32_t AudioDeviceBuffer::StopOutputFileRecording()
niklase@google.com470e71d2011-07-07 08:21:25 +0000364{
365 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
366
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000367 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
369 _playFile.Flush();
370 _playFile.CloseFile();
371
372 return 0;
373}
374
375// ----------------------------------------------------------------------------
376// SetRecordedBuffer
377//
378// Store recorded audio buffer in local memory ready for the actual
379// "delivery" using a callback.
380//
381// This method can also parse out left or right channel from a stereo
382// input signal, i.e., emulate mono.
383//
384// Examples:
385//
386// 16-bit,48kHz mono, 10ms => nSamples=480 => _recSize=2*480=960 bytes
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000387// 16-bit,48kHz stereo,10ms => nSamples=480 => _recSize=4*480=1920 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000388// ----------------------------------------------------------------------------
389
pbos@webrtc.org25509882013-04-09 10:30:35 +0000390int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audioBuffer,
391 uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000392{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000393 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
395 if (_recBytesPerSample == 0)
396 {
397 assert(false);
398 return -1;
399 }
400
401 _recSamples = nSamples;
402 _recSize = _recBytesPerSample*nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000403 if (_recSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000404 {
405 assert(false);
406 return -1;
407 }
408
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 if (_recChannel == AudioDeviceModule::kChannelBoth)
410 {
411 // (default) copy the complete input buffer to the local buffer
412 memcpy(&_recBuffer[0], audioBuffer, _recSize);
413 }
414 else
415 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000416 int16_t* ptr16In = (int16_t*)audioBuffer;
417 int16_t* ptr16Out = (int16_t*)&_recBuffer[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
419 if (AudioDeviceModule::kChannelRight == _recChannel)
420 {
421 ptr16In++;
422 }
423
424 // exctract left or right channel from input buffer to the local buffer
pbos@webrtc.org25509882013-04-09 10:30:35 +0000425 for (uint32_t i = 0; i < _recSamples; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000426 {
427 *ptr16Out = *ptr16In;
428 ptr16Out++;
429 ptr16In++;
430 ptr16In++;
431 }
432 }
433
434 if (_recFile.Open())
435 {
436 // write to binary file in mono or stereo (interleaved)
437 _recFile.Write(&_recBuffer[0], _recSize);
438 }
439
440 return 0;
441}
442
443// ----------------------------------------------------------------------------
444// DeliverRecordedData
445// ----------------------------------------------------------------------------
446
pbos@webrtc.org25509882013-04-09 10:30:35 +0000447int32_t AudioDeviceBuffer::DeliverRecordedData()
niklase@google.com470e71d2011-07-07 08:21:25 +0000448{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000449 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000450
451 // Ensure that user has initialized all essential members
452 if ((_recSampleRate == 0) ||
453 (_recSamples == 0) ||
454 (_recBytesPerSample == 0) ||
455 (_recChannels == 0))
456 {
457 assert(false);
458 return -1;
459 }
460
461 if (_ptrCbAudioTransport == NULL)
462 {
463 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to deliver recorded data (AudioTransport does not exist)");
464 return 0;
465 }
466
pbos@webrtc.org25509882013-04-09 10:30:35 +0000467 int32_t res(0);
468 uint32_t newMicLevel(0);
469 uint32_t totalDelayMS = _playDelayMS +_recDelayMS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
niklase@google.com470e71d2011-07-07 08:21:25 +0000471 res = _ptrCbAudioTransport->RecordedDataIsAvailable(&_recBuffer[0],
472 _recSamples,
473 _recBytesPerSample,
474 _recChannels,
475 _recSampleRate,
476 totalDelayMS,
477 _clockDrift,
478 _currentMicLevel,
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000479 _typingStatus,
niklase@google.com470e71d2011-07-07 08:21:25 +0000480 newMicLevel);
481 if (res != -1)
482 {
483 _newMicLevel = newMicLevel;
484 }
485
486 return 0;
487}
488
489// ----------------------------------------------------------------------------
490// RequestPlayoutData
491// ----------------------------------------------------------------------------
492
pbos@webrtc.org25509882013-04-09 10:30:35 +0000493int32_t AudioDeviceBuffer::RequestPlayoutData(uint32_t nSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +0000494{
pbos@webrtc.org25509882013-04-09 10:30:35 +0000495 uint32_t playSampleRate = 0;
496 uint8_t playBytesPerSample = 0;
497 uint8_t playChannels = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000498 {
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000499 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000501 // Store copies under lock and use copies hereafter to avoid race with
502 // setter methods.
503 playSampleRate = _playSampleRate;
504 playBytesPerSample = _playBytesPerSample;
505 playChannels = _playChannels;
506
niklase@google.com470e71d2011-07-07 08:21:25 +0000507 // Ensure that user has initialized all essential members
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000508 if ((playBytesPerSample == 0) ||
509 (playChannels == 0) ||
510 (playSampleRate == 0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000511 {
512 assert(false);
513 return -1;
514 }
515
516 _playSamples = nSamples;
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000517 _playSize = playBytesPerSample * nSamples; // {2,4}*nSamples
braveyao@webrtc.org0a185222011-11-25 02:45:39 +0000518 if (_playSize > kMaxBufferSizeBytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 {
520 assert(false);
521 return -1;
522 }
523
524 if (nSamples != _playSamples)
525 {
526 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "invalid number of samples to be played out (%d)", nSamples);
527 return -1;
528 }
529 }
530
pbos@webrtc.org25509882013-04-09 10:30:35 +0000531 uint32_t nSamplesOut(0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000533 CriticalSectionScoped lock(&_critSectCb);
niklase@google.com470e71d2011-07-07 08:21:25 +0000534
535 if (_ptrCbAudioTransport == NULL)
536 {
537 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to feed data to playout (AudioTransport does not exist)");
538 return 0;
539 }
540
541 if (_ptrCbAudioTransport)
542 {
pbos@webrtc.org25509882013-04-09 10:30:35 +0000543 uint32_t res(0);
wu@webrtc.org94454b72014-06-05 20:34:08 +0000544 int64_t elapsed_time_ms = -1;
545 int64_t ntp_time_ms = -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546 res = _ptrCbAudioTransport->NeedMorePlayData(_playSamples,
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000547 playBytesPerSample,
548 playChannels,
549 playSampleRate,
niklase@google.com470e71d2011-07-07 08:21:25 +0000550 &_playBuffer[0],
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000551 nSamplesOut,
wu@webrtc.org94454b72014-06-05 20:34:08 +0000552 &elapsed_time_ms,
wu@webrtc.orgcb711f72014-05-19 17:39:11 +0000553 &ntp_time_ms);
niklase@google.com470e71d2011-07-07 08:21:25 +0000554 if (res != 0)
555 {
556 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "NeedMorePlayData() failed");
557 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000558 }
559
Peter Kastingb7e50542015-06-11 12:55:50 -0700560 return static_cast<int32_t>(nSamplesOut);
niklase@google.com470e71d2011-07-07 08:21:25 +0000561}
562
563// ----------------------------------------------------------------------------
564// GetPlayoutData
565// ----------------------------------------------------------------------------
566
pbos@webrtc.org25509882013-04-09 10:30:35 +0000567int32_t AudioDeviceBuffer::GetPlayoutData(void* audioBuffer)
niklase@google.com470e71d2011-07-07 08:21:25 +0000568{
mflodman@webrtc.orga014ecc2012-04-12 12:15:51 +0000569 CriticalSectionScoped lock(&_critSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000571 if (_playSize > kMaxBufferSizeBytes)
572 {
Peter Kasting728d9032015-06-11 14:31:38 -0700573 WEBRTC_TRACE(kTraceError, kTraceUtility, _id,
574 "_playSize %i exceeds kMaxBufferSizeBytes in "
575 "AudioDeviceBuffer::GetPlayoutData", _playSize);
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000576 assert(false);
leozwang@webrtc.org28f39132012-03-01 18:01:48 +0000577 return -1;
578 }
punyabrata@webrtc.orgc9801462011-11-29 18:49:54 +0000579
niklase@google.com470e71d2011-07-07 08:21:25 +0000580 memcpy(audioBuffer, &_playBuffer[0], _playSize);
581
582 if (_playFile.Open())
583 {
584 // write to binary file in mono or stereo (interleaved)
585 _playFile.Write(&_playBuffer[0], _playSize);
586 }
587
Peter Kastingb7e50542015-06-11 12:55:50 -0700588 return static_cast<int32_t>(_playSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +0000589}
590
niklase@google.com470e71d2011-07-07 08:21:25 +0000591} // namespace webrtc