OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 #include "webrtc/base/logging.h" | 10 #include "webrtc/base/logging.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 _recordingFramesLeft(0), | 32 _recordingFramesLeft(0), |
33 _playoutFramesLeft(0), | 33 _playoutFramesLeft(0), |
34 _critSect(*CriticalSectionWrapper::CreateCriticalSection()), | 34 _critSect(*CriticalSectionWrapper::CreateCriticalSection()), |
35 _recordingBufferSizeIn10MS(0), | 35 _recordingBufferSizeIn10MS(0), |
36 _recordingFramesIn10MS(0), | 36 _recordingFramesIn10MS(0), |
37 _playoutFramesIn10MS(0), | 37 _playoutFramesIn10MS(0), |
38 _playing(false), | 38 _playing(false), |
39 _recording(false), | 39 _recording(false), |
40 _lastCallPlayoutMillis(0), | 40 _lastCallPlayoutMillis(0), |
41 _lastCallRecordMillis(0), | 41 _lastCallRecordMillis(0), |
42 _outputFile(*FileWrapper::Create()), | |
43 _inputFile(*FileWrapper::Create()), | |
44 _outputFilename(outputFilename), | 42 _outputFilename(outputFilename), |
45 _inputFilename(inputFilename), | 43 _inputFilename(inputFilename), |
46 _clock(Clock::GetRealTimeClock()) { | 44 _clock(Clock::GetRealTimeClock()) { |
47 } | 45 } |
48 | 46 |
49 FileAudioDevice::~FileAudioDevice() { | |
50 delete &_outputFile; | |
51 delete &_inputFile; | |
52 } | |
53 | |
54 int32_t FileAudioDevice::ActiveAudioLayer( | 47 int32_t FileAudioDevice::ActiveAudioLayer( |
55 AudioDeviceModule::AudioLayer& audioLayer) const { | 48 AudioDeviceModule::AudioLayer& audioLayer) const { |
56 return -1; | 49 return -1; |
57 } | 50 } |
58 | 51 |
59 AudioDeviceGeneric::InitStatus FileAudioDevice::Init() { | 52 AudioDeviceGeneric::InitStatus FileAudioDevice::Init() { |
60 return InitStatus::OK; | 53 return InitStatus::OK; |
61 } | 54 } |
62 | 55 |
63 int32_t FileAudioDevice::Terminate() { return 0; } | 56 int32_t FileAudioDevice::Terminate() { return 0; } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 183 |
191 if (!_playoutBuffer) { | 184 if (!_playoutBuffer) { |
192 _playoutBuffer = new int8_t[kPlayoutBufferSize]; | 185 _playoutBuffer = new int8_t[kPlayoutBufferSize]; |
193 } | 186 } |
194 if (!_playoutBuffer) { | 187 if (!_playoutBuffer) { |
195 _playing = false; | 188 _playing = false; |
196 return -1; | 189 return -1; |
197 } | 190 } |
198 | 191 |
199 // PLAYOUT | 192 // PLAYOUT |
200 if (!_outputFilename.empty() && | 193 if (!_outputFilename.empty()) { |
201 !_outputFile.OpenFile(_outputFilename.c_str(), false)) { | 194 _outputFile = rtc::File::Open(_outputFilename); |
202 LOG(LS_ERROR) << "Failed to open playout file: " << _outputFilename; | 195 if (!_outputFile.IsOpen()) { |
203 _playing = false; | 196 LOG(LS_ERROR) << "Failed to open playout file: " << _outputFilename; |
204 delete [] _playoutBuffer; | 197 _playing = false; |
205 _playoutBuffer = NULL; | 198 delete[] _playoutBuffer; |
206 return -1; | 199 _playoutBuffer = NULL; |
| 200 return -1; |
| 201 } |
207 } | 202 } |
208 | 203 |
209 _ptrThreadPlay.reset(new rtc::PlatformThread( | 204 _ptrThreadPlay.reset(new rtc::PlatformThread( |
210 PlayThreadFunc, this, "webrtc_audio_module_play_thread")); | 205 PlayThreadFunc, this, "webrtc_audio_module_play_thread")); |
211 _ptrThreadPlay->Start(); | 206 _ptrThreadPlay->Start(); |
212 _ptrThreadPlay->SetPriority(rtc::kRealtimePriority); | 207 _ptrThreadPlay->SetPriority(rtc::kRealtimePriority); |
213 | 208 |
214 LOG(LS_INFO) << "Started playout capture to output file: " | 209 LOG(LS_INFO) << "Started playout capture to output file: " |
215 << _outputFilename; | 210 << _outputFilename; |
216 return 0; | 211 return 0; |
217 } | 212 } |
218 | 213 |
219 int32_t FileAudioDevice::StopPlayout() { | 214 int32_t FileAudioDevice::StopPlayout() { |
220 { | 215 { |
221 CriticalSectionScoped lock(&_critSect); | 216 CriticalSectionScoped lock(&_critSect); |
222 _playing = false; | 217 _playing = false; |
223 } | 218 } |
224 | 219 |
225 // stop playout thread first | 220 // stop playout thread first |
226 if (_ptrThreadPlay) { | 221 if (_ptrThreadPlay) { |
227 _ptrThreadPlay->Stop(); | 222 _ptrThreadPlay->Stop(); |
228 _ptrThreadPlay.reset(); | 223 _ptrThreadPlay.reset(); |
229 } | 224 } |
230 | 225 |
231 CriticalSectionScoped lock(&_critSect); | 226 CriticalSectionScoped lock(&_critSect); |
232 | 227 |
233 _playoutFramesLeft = 0; | 228 _playoutFramesLeft = 0; |
234 delete [] _playoutBuffer; | 229 delete [] _playoutBuffer; |
235 _playoutBuffer = NULL; | 230 _playoutBuffer = NULL; |
236 _outputFile.CloseFile(); | 231 _outputFile.Close(); |
237 | 232 |
238 LOG(LS_INFO) << "Stopped playout capture to output file: " | 233 LOG(LS_INFO) << "Stopped playout capture to output file: " |
239 << _outputFilename; | 234 << _outputFilename; |
240 return 0; | 235 return 0; |
241 } | 236 } |
242 | 237 |
243 bool FileAudioDevice::Playing() const { | 238 bool FileAudioDevice::Playing() const { |
244 return true; | 239 return true; |
245 } | 240 } |
246 | 241 |
247 int32_t FileAudioDevice::StartRecording() { | 242 int32_t FileAudioDevice::StartRecording() { |
248 _recording = true; | 243 _recording = true; |
249 | 244 |
250 // Make sure we only create the buffer once. | 245 // Make sure we only create the buffer once. |
251 _recordingBufferSizeIn10MS = _recordingFramesIn10MS * | 246 _recordingBufferSizeIn10MS = _recordingFramesIn10MS * |
252 kRecordingNumChannels * | 247 kRecordingNumChannels * |
253 2; | 248 2; |
254 if (!_recordingBuffer) { | 249 if (!_recordingBuffer) { |
255 _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS]; | 250 _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS]; |
256 } | 251 } |
257 | 252 |
258 if (!_inputFilename.empty() && | 253 if (!_inputFilename.empty()) { |
259 !_inputFile.OpenFile(_inputFilename.c_str(), true)) { | 254 _inputFile = rtc::File::Open(_inputFilename); |
260 LOG(LS_ERROR) << "Failed to open audio input file: " << _inputFilename; | 255 if (!_inputFile.IsOpen()) { |
261 _recording = false; | 256 LOG(LS_ERROR) << "Failed to open audio input file: " << _inputFilename; |
262 delete[] _recordingBuffer; | 257 _recording = false; |
263 _recordingBuffer = NULL; | 258 delete[] _recordingBuffer; |
264 return -1; | 259 _recordingBuffer = NULL; |
| 260 return -1; |
| 261 } |
265 } | 262 } |
266 | 263 |
267 _ptrThreadRec.reset(new rtc::PlatformThread( | 264 _ptrThreadRec.reset(new rtc::PlatformThread( |
268 RecThreadFunc, this, "webrtc_audio_module_capture_thread")); | 265 RecThreadFunc, this, "webrtc_audio_module_capture_thread")); |
269 | 266 |
270 _ptrThreadRec->Start(); | 267 _ptrThreadRec->Start(); |
271 _ptrThreadRec->SetPriority(rtc::kRealtimePriority); | 268 _ptrThreadRec->SetPriority(rtc::kRealtimePriority); |
272 | 269 |
273 LOG(LS_INFO) << "Started recording from input file: " | 270 LOG(LS_INFO) << "Started recording from input file: " |
274 << _inputFilename; | 271 << _inputFilename; |
(...skipping 12 matching lines...) Expand all Loading... |
287 _ptrThreadRec->Stop(); | 284 _ptrThreadRec->Stop(); |
288 _ptrThreadRec.reset(); | 285 _ptrThreadRec.reset(); |
289 } | 286 } |
290 | 287 |
291 CriticalSectionScoped lock(&_critSect); | 288 CriticalSectionScoped lock(&_critSect); |
292 _recordingFramesLeft = 0; | 289 _recordingFramesLeft = 0; |
293 if (_recordingBuffer) { | 290 if (_recordingBuffer) { |
294 delete [] _recordingBuffer; | 291 delete [] _recordingBuffer; |
295 _recordingBuffer = NULL; | 292 _recordingBuffer = NULL; |
296 } | 293 } |
297 _inputFile.CloseFile(); | 294 _inputFile.Close(); |
298 | 295 |
299 LOG(LS_INFO) << "Stopped recording from input file: " | 296 LOG(LS_INFO) << "Stopped recording from input file: " |
300 << _inputFilename; | 297 << _inputFilename; |
301 return 0; | 298 return 0; |
302 } | 299 } |
303 | 300 |
304 bool FileAudioDevice::Recording() const { | 301 bool FileAudioDevice::Recording() const { |
305 return _recording; | 302 return _recording; |
306 } | 303 } |
307 | 304 |
308 int32_t FileAudioDevice::SetAGC(bool enable) { return -1; } | 305 int32_t FileAudioDevice::SetAGC(bool enable) { return -1; } |
309 | 306 |
310 bool FileAudioDevice::AGC() const { return false; } | 307 bool FileAudioDevice::AGC() const { return false; } |
311 | 308 |
312 int32_t FileAudioDevice::SetWaveOutVolume(uint16_t volumeLeft, | 309 int32_t FileAudioDevice::SetWaveOutVolume(uint16_t volumeLeft, |
313 uint16_t volumeRight) { | 310 uint16_t volumeRight) { |
314 return -1; | 311 return -1; |
315 } | 312 } |
316 | 313 |
317 int32_t FileAudioDevice::WaveOutVolume(uint16_t& volumeLeft, | 314 int32_t FileAudioDevice::WaveOutVolume(uint16_t& volumeLeft, |
318 uint16_t& volumeRight) const { | 315 uint16_t& volumeRight) const { |
319 return -1; | 316 return -1; |
320 } | 317 } |
321 | 318 |
322 int32_t FileAudioDevice::InitSpeaker() { return -1; } | 319 int32_t FileAudioDevice::InitSpeaker() { return -1; } |
323 | 320 |
324 bool FileAudioDevice::SpeakerIsInitialized() const { return false; } | 321 bool FileAudioDevice::SpeakerIsInitialized() const { return false; } |
325 | 322 |
326 int32_t FileAudioDevice::InitMicrophone() { return 0; } | 323 int32_t FileAudioDevice::InitMicrophone() { return 0; } |
327 | 324 |
328 bool FileAudioDevice::MicrophoneIsInitialized() const { return true; } | 325 bool FileAudioDevice::MicrophoneIsInitialized() const { return true; } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 | 458 |
462 // Inform the AudioBuffer about default settings for this implementation. | 459 // Inform the AudioBuffer about default settings for this implementation. |
463 // Set all values to zero here since the actual settings will be done by | 460 // Set all values to zero here since the actual settings will be done by |
464 // InitPlayout and InitRecording later. | 461 // InitPlayout and InitRecording later. |
465 _ptrAudioBuffer->SetRecordingSampleRate(0); | 462 _ptrAudioBuffer->SetRecordingSampleRate(0); |
466 _ptrAudioBuffer->SetPlayoutSampleRate(0); | 463 _ptrAudioBuffer->SetPlayoutSampleRate(0); |
467 _ptrAudioBuffer->SetRecordingChannels(0); | 464 _ptrAudioBuffer->SetRecordingChannels(0); |
468 _ptrAudioBuffer->SetPlayoutChannels(0); | 465 _ptrAudioBuffer->SetPlayoutChannels(0); |
469 } | 466 } |
470 | 467 |
471 bool FileAudioDevice::PlayThreadFunc(void* pThis) | 468 bool FileAudioDevice::PlayThreadFunc(void* pThis) { |
472 { | 469 return (static_cast<FileAudioDevice*>(pThis)->PlayThreadProcess()); |
473 return (static_cast<FileAudioDevice*>(pThis)->PlayThreadProcess()); | |
474 } | 470 } |
475 | 471 |
476 bool FileAudioDevice::RecThreadFunc(void* pThis) | 472 bool FileAudioDevice::RecThreadFunc(void* pThis) { |
477 { | 473 return (static_cast<FileAudioDevice*>(pThis)->RecThreadProcess()); |
478 return (static_cast<FileAudioDevice*>(pThis)->RecThreadProcess()); | |
479 } | 474 } |
480 | 475 |
481 bool FileAudioDevice::PlayThreadProcess() | 476 bool FileAudioDevice::PlayThreadProcess() { |
482 { | 477 if (!_playing) { |
483 if(!_playing) { | 478 return false; |
484 return false; | 479 } |
485 } | 480 uint64_t currentTime = _clock->CurrentNtpInMilliseconds(); |
486 uint64_t currentTime = _clock->CurrentNtpInMilliseconds(); | 481 _critSect.Enter(); |
| 482 |
| 483 if (_lastCallPlayoutMillis == 0 || |
| 484 currentTime - _lastCallPlayoutMillis >= 10) { |
| 485 _critSect.Leave(); |
| 486 _ptrAudioBuffer->RequestPlayoutData(_playoutFramesIn10MS); |
487 _critSect.Enter(); | 487 _critSect.Enter(); |
488 | 488 |
489 if (_lastCallPlayoutMillis == 0 || | 489 _playoutFramesLeft = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer); |
490 currentTime - _lastCallPlayoutMillis >= 10) { | 490 assert(_playoutFramesLeft == _playoutFramesIn10MS); |
491 _critSect.Leave(); | 491 if (_outputFile.IsOpen()) { |
492 _ptrAudioBuffer->RequestPlayoutData(_playoutFramesIn10MS); | 492 _outputFile.Write(reinterpret_cast<uint8_t*>(_playoutBuffer), |
493 _critSect.Enter(); | 493 kPlayoutBufferSize); |
| 494 } |
| 495 _lastCallPlayoutMillis = currentTime; |
| 496 } |
| 497 _playoutFramesLeft = 0; |
| 498 _critSect.Leave(); |
494 | 499 |
495 _playoutFramesLeft = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer); | 500 uint64_t deltaTimeMillis = _clock->CurrentNtpInMilliseconds() - currentTime; |
496 assert(_playoutFramesLeft == _playoutFramesIn10MS); | 501 if (deltaTimeMillis < 10) { |
497 if (_outputFile.is_open()) { | 502 SleepMs(10 - deltaTimeMillis); |
498 _outputFile.Write(_playoutBuffer, kPlayoutBufferSize); | 503 } |
499 } | |
500 _lastCallPlayoutMillis = currentTime; | |
501 } | |
502 _playoutFramesLeft = 0; | |
503 _critSect.Leave(); | |
504 | 504 |
505 uint64_t deltaTimeMillis = _clock->CurrentNtpInMilliseconds() - currentTime; | 505 return true; |
506 if(deltaTimeMillis < 10) { | |
507 SleepMs(10 - deltaTimeMillis); | |
508 } | |
509 | |
510 return true; | |
511 } | 506 } |
512 | 507 |
513 bool FileAudioDevice::RecThreadProcess() | 508 bool FileAudioDevice::RecThreadProcess() { |
514 { | 509 if (!_recording) { |
515 if (!_recording) { | 510 return false; |
516 return false; | 511 } |
| 512 |
| 513 uint64_t currentTime = _clock->CurrentNtpInMilliseconds(); |
| 514 _critSect.Enter(); |
| 515 |
| 516 if (_lastCallRecordMillis == 0 || currentTime - _lastCallRecordMillis >= 10) { |
| 517 if (_inputFile.IsOpen()) { |
| 518 if (_inputFile.Read(reinterpret_cast<uint8_t*>(_recordingBuffer), |
| 519 kRecordingBufferSize) > 0) { |
| 520 _ptrAudioBuffer->SetRecordedBuffer(_recordingBuffer, |
| 521 _recordingFramesIn10MS); |
| 522 } else { |
| 523 _inputFile.Seek(0); |
| 524 } |
| 525 _lastCallRecordMillis = currentTime; |
| 526 _critSect.Leave(); |
| 527 _ptrAudioBuffer->DeliverRecordedData(); |
| 528 _critSect.Enter(); |
517 } | 529 } |
| 530 } |
518 | 531 |
519 uint64_t currentTime = _clock->CurrentNtpInMilliseconds(); | 532 _critSect.Leave(); |
520 _critSect.Enter(); | |
521 | 533 |
522 if (_lastCallRecordMillis == 0 || | 534 uint64_t deltaTimeMillis = _clock->CurrentNtpInMilliseconds() - currentTime; |
523 currentTime - _lastCallRecordMillis >= 10) { | 535 if (deltaTimeMillis < 10) { |
524 if (_inputFile.is_open()) { | 536 SleepMs(10 - deltaTimeMillis); |
525 if (_inputFile.Read(_recordingBuffer, kRecordingBufferSize) > 0) { | 537 } |
526 _ptrAudioBuffer->SetRecordedBuffer(_recordingBuffer, | |
527 _recordingFramesIn10MS); | |
528 } else { | |
529 _inputFile.Rewind(); | |
530 } | |
531 _lastCallRecordMillis = currentTime; | |
532 _critSect.Leave(); | |
533 _ptrAudioBuffer->DeliverRecordedData(); | |
534 _critSect.Enter(); | |
535 } | |
536 } | |
537 | 538 |
538 _critSect.Leave(); | 539 return true; |
539 | |
540 uint64_t deltaTimeMillis = _clock->CurrentNtpInMilliseconds() - currentTime; | |
541 if(deltaTimeMillis < 10) { | |
542 SleepMs(10 - deltaTimeMillis); | |
543 } | |
544 | |
545 return true; | |
546 } | 540 } |
547 | 541 |
548 } // namespace webrtc | 542 } // namespace webrtc |
OLD | NEW |