tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

file_audio_device.cc (12788B)


      1 /*
      2 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3 *
      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 
     11 #include "modules/audio_device/dummy/file_audio_device.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstring>
     16 
     17 #include "absl/strings/string_view.h"
     18 #include "api/audio/audio_device.h"
     19 #include "api/audio/audio_device_defines.h"
     20 #include "modules/audio_device/audio_device_buffer.h"
     21 #include "modules/audio_device/audio_device_generic.h"
     22 #include "rtc_base/checks.h"
     23 #include "rtc_base/logging.h"
     24 #include "rtc_base/platform_thread.h"
     25 #include "rtc_base/synchronization/mutex.h"
     26 #include "rtc_base/system/file_wrapper.h"
     27 #include "rtc_base/thread.h"
     28 #include "rtc_base/time_utils.h"
     29 
     30 namespace webrtc {
     31 
     32 const int kRecordingFixedSampleRate = 48000;
     33 const size_t kRecordingNumChannels = 2;
     34 const int kPlayoutFixedSampleRate = 48000;
     35 const size_t kPlayoutNumChannels = 2;
     36 const size_t kPlayoutBufferSize =
     37    kPlayoutFixedSampleRate / 100 * kPlayoutNumChannels * 2;
     38 const size_t kRecordingBufferSize =
     39    kRecordingFixedSampleRate / 100 * kRecordingNumChannels * 2;
     40 
     41 FileAudioDevice::FileAudioDevice(absl::string_view inputFilename,
     42                                 absl::string_view outputFilename)
     43    : _ptrAudioBuffer(nullptr),
     44      _recordingBuffer(nullptr),
     45      _playoutBuffer(nullptr),
     46      _recordingFramesLeft(0),
     47      _playoutFramesLeft(0),
     48      _recordingBufferSizeIn10MS(0),
     49      _recordingFramesIn10MS(0),
     50      _playoutFramesIn10MS(0),
     51      _playing(false),
     52      _recording(false),
     53      _lastCallPlayoutMillis(0),
     54      _lastCallRecordMillis(0),
     55      _outputFilename(outputFilename),
     56      _inputFilename(inputFilename) {}
     57 
     58 FileAudioDevice::~FileAudioDevice() {}
     59 
     60 int32_t FileAudioDevice::ActiveAudioLayer(
     61    AudioDeviceModule::AudioLayer& /* audioLayer */) const {
     62  return -1;
     63 }
     64 
     65 AudioDeviceGeneric::InitStatus FileAudioDevice::Init() {
     66  return InitStatus::OK;
     67 }
     68 
     69 int32_t FileAudioDevice::Terminate() {
     70  return 0;
     71 }
     72 
     73 bool FileAudioDevice::Initialized() const {
     74  return true;
     75 }
     76 
     77 int16_t FileAudioDevice::PlayoutDevices() {
     78  return 1;
     79 }
     80 
     81 int16_t FileAudioDevice::RecordingDevices() {
     82  return 1;
     83 }
     84 
     85 int32_t FileAudioDevice::PlayoutDeviceName(uint16_t index,
     86                                           char name[kAdmMaxDeviceNameSize],
     87                                           char guid[kAdmMaxGuidSize]) {
     88  const char* kName = "dummy_device";
     89  const char* kGuid = "dummy_device_unique_id";
     90  if (index < 1) {
     91    memset(name, 0, kAdmMaxDeviceNameSize);
     92    memset(guid, 0, kAdmMaxGuidSize);
     93    memcpy(name, kName, strlen(kName));
     94    memcpy(guid, kGuid, strlen(guid));
     95    return 0;
     96  }
     97  return -1;
     98 }
     99 
    100 int32_t FileAudioDevice::RecordingDeviceName(uint16_t index,
    101                                             char name[kAdmMaxDeviceNameSize],
    102                                             char guid[kAdmMaxGuidSize]) {
    103  const char* kName = "dummy_device";
    104  const char* kGuid = "dummy_device_unique_id";
    105  if (index < 1) {
    106    memset(name, 0, kAdmMaxDeviceNameSize);
    107    memset(guid, 0, kAdmMaxGuidSize);
    108    memcpy(name, kName, strlen(kName));
    109    memcpy(guid, kGuid, strlen(guid));
    110    return 0;
    111  }
    112  return -1;
    113 }
    114 
    115 int32_t FileAudioDevice::SetPlayoutDevice(uint16_t index) {
    116  if (index == 0) {
    117    _playout_index = index;
    118    return 0;
    119  }
    120  return -1;
    121 }
    122 
    123 int32_t FileAudioDevice::SetPlayoutDevice(
    124    AudioDeviceModule::WindowsDeviceType /* device */) {
    125  return -1;
    126 }
    127 
    128 int32_t FileAudioDevice::SetRecordingDevice(uint16_t index) {
    129  if (index == 0) {
    130    _record_index = index;
    131    return _record_index;
    132  }
    133  return -1;
    134 }
    135 
    136 int32_t FileAudioDevice::SetRecordingDevice(
    137    AudioDeviceModule::WindowsDeviceType /* device */) {
    138  return -1;
    139 }
    140 
    141 int32_t FileAudioDevice::PlayoutIsAvailable(bool& available) {
    142  if (_playout_index == 0) {
    143    available = true;
    144    return _playout_index;
    145  }
    146  available = false;
    147  return -1;
    148 }
    149 
    150 int32_t FileAudioDevice::InitPlayout() {
    151  MutexLock lock(&mutex_);
    152 
    153  if (_playing) {
    154    return -1;
    155  }
    156 
    157  _playoutFramesIn10MS = static_cast<size_t>(kPlayoutFixedSampleRate / 100);
    158 
    159  if (_ptrAudioBuffer) {
    160    // Update webrtc audio buffer with the selected parameters
    161    _ptrAudioBuffer->SetPlayoutSampleRate(kPlayoutFixedSampleRate);
    162    _ptrAudioBuffer->SetPlayoutChannels(kPlayoutNumChannels);
    163  }
    164  return 0;
    165 }
    166 
    167 bool FileAudioDevice::PlayoutIsInitialized() const {
    168  return _playoutFramesIn10MS != 0;
    169 }
    170 
    171 int32_t FileAudioDevice::RecordingIsAvailable(bool& available) {
    172  if (_record_index == 0) {
    173    available = true;
    174    return _record_index;
    175  }
    176  available = false;
    177  return -1;
    178 }
    179 
    180 int32_t FileAudioDevice::InitRecording() {
    181  MutexLock lock(&mutex_);
    182 
    183  if (_recording) {
    184    return -1;
    185  }
    186 
    187  _recordingFramesIn10MS = static_cast<size_t>(kRecordingFixedSampleRate / 100);
    188 
    189  if (_ptrAudioBuffer) {
    190    _ptrAudioBuffer->SetRecordingSampleRate(kRecordingFixedSampleRate);
    191    _ptrAudioBuffer->SetRecordingChannels(kRecordingNumChannels);
    192  }
    193  return 0;
    194 }
    195 
    196 bool FileAudioDevice::RecordingIsInitialized() const {
    197  return _recordingFramesIn10MS != 0;
    198 }
    199 
    200 int32_t FileAudioDevice::StartPlayout() {
    201  if (_playing) {
    202    return 0;
    203  }
    204 
    205  _playing = true;
    206  _playoutFramesLeft = 0;
    207 
    208  if (!_playoutBuffer) {
    209    _playoutBuffer = new int8_t[kPlayoutBufferSize];
    210  }
    211  if (!_playoutBuffer) {
    212    _playing = false;
    213    return -1;
    214  }
    215 
    216  // PLAYOUT
    217  if (!_outputFilename.empty()) {
    218    _outputFile = FileWrapper::OpenWriteOnly(_outputFilename);
    219    if (!_outputFile.is_open()) {
    220      RTC_LOG(LS_ERROR) << "Failed to open playout file: " << _outputFilename;
    221      _playing = false;
    222      delete[] _playoutBuffer;
    223      _playoutBuffer = nullptr;
    224      return -1;
    225    }
    226  }
    227 
    228  _ptrThreadPlay = PlatformThread::SpawnJoinable(
    229      [this] {
    230        while (PlayThreadProcess()) {
    231        }
    232      },
    233      "webrtc_audio_module_play_thread",
    234      ThreadAttributes().SetPriority(ThreadPriority::kRealtime));
    235 
    236  RTC_LOG(LS_INFO) << "Started playout capture to output file: "
    237                   << _outputFilename;
    238  return 0;
    239 }
    240 
    241 int32_t FileAudioDevice::StopPlayout() {
    242  {
    243    MutexLock lock(&mutex_);
    244    _playing = false;
    245  }
    246 
    247  // stop playout thread first
    248  if (!_ptrThreadPlay.empty())
    249    _ptrThreadPlay.Finalize();
    250 
    251  MutexLock lock(&mutex_);
    252 
    253  _playoutFramesLeft = 0;
    254  delete[] _playoutBuffer;
    255  _playoutBuffer = nullptr;
    256  _outputFile.Close();
    257 
    258  RTC_LOG(LS_INFO) << "Stopped playout capture to output file: "
    259                   << _outputFilename;
    260  return 0;
    261 }
    262 
    263 bool FileAudioDevice::Playing() const {
    264  return _playing;
    265 }
    266 
    267 int32_t FileAudioDevice::StartRecording() {
    268  _recording = true;
    269 
    270  // Make sure we only create the buffer once.
    271  _recordingBufferSizeIn10MS =
    272      _recordingFramesIn10MS * kRecordingNumChannels * 2;
    273  if (!_recordingBuffer) {
    274    _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS];
    275  }
    276 
    277  if (!_inputFilename.empty()) {
    278    _inputFile = FileWrapper::OpenReadOnly(_inputFilename);
    279    if (!_inputFile.is_open()) {
    280      RTC_LOG(LS_ERROR) << "Failed to open audio input file: "
    281                        << _inputFilename;
    282      _recording = false;
    283      delete[] _recordingBuffer;
    284      _recordingBuffer = nullptr;
    285      return -1;
    286    }
    287  }
    288 
    289  _ptrThreadRec = PlatformThread::SpawnJoinable(
    290      [this] {
    291        while (RecThreadProcess()) {
    292        }
    293      },
    294      "webrtc_audio_module_capture_thread",
    295      ThreadAttributes().SetPriority(ThreadPriority::kRealtime));
    296 
    297  RTC_LOG(LS_INFO) << "Started recording from input file: " << _inputFilename;
    298 
    299  return 0;
    300 }
    301 
    302 int32_t FileAudioDevice::StopRecording() {
    303  {
    304    MutexLock lock(&mutex_);
    305    _recording = false;
    306  }
    307 
    308  if (!_ptrThreadRec.empty())
    309    _ptrThreadRec.Finalize();
    310 
    311  MutexLock lock(&mutex_);
    312  _recordingFramesLeft = 0;
    313  if (_recordingBuffer) {
    314    delete[] _recordingBuffer;
    315    _recordingBuffer = nullptr;
    316  }
    317  _inputFile.Close();
    318 
    319  RTC_LOG(LS_INFO) << "Stopped recording from input file: " << _inputFilename;
    320  return 0;
    321 }
    322 
    323 bool FileAudioDevice::Recording() const {
    324  return _recording;
    325 }
    326 
    327 int32_t FileAudioDevice::InitSpeaker() {
    328  return -1;
    329 }
    330 
    331 bool FileAudioDevice::SpeakerIsInitialized() const {
    332  return false;
    333 }
    334 
    335 int32_t FileAudioDevice::InitMicrophone() {
    336  return 0;
    337 }
    338 
    339 bool FileAudioDevice::MicrophoneIsInitialized() const {
    340  return true;
    341 }
    342 
    343 int32_t FileAudioDevice::SpeakerVolumeIsAvailable(bool& /* available */) {
    344  return -1;
    345 }
    346 
    347 int32_t FileAudioDevice::SetSpeakerVolume(uint32_t /* volume */) {
    348  return -1;
    349 }
    350 
    351 int32_t FileAudioDevice::SpeakerVolume(uint32_t& /* volume */) const {
    352  return -1;
    353 }
    354 
    355 int32_t FileAudioDevice::MaxSpeakerVolume(uint32_t& /* maxVolume */) const {
    356  return -1;
    357 }
    358 
    359 int32_t FileAudioDevice::MinSpeakerVolume(uint32_t& /* minVolume */) const {
    360  return -1;
    361 }
    362 
    363 int32_t FileAudioDevice::MicrophoneVolumeIsAvailable(bool& /* available */) {
    364  return -1;
    365 }
    366 
    367 int32_t FileAudioDevice::SetMicrophoneVolume(uint32_t /* volume */) {
    368  return -1;
    369 }
    370 
    371 int32_t FileAudioDevice::MicrophoneVolume(uint32_t& /* volume */) const {
    372  return -1;
    373 }
    374 
    375 int32_t FileAudioDevice::MaxMicrophoneVolume(uint32_t& /* maxVolume */) const {
    376  return -1;
    377 }
    378 
    379 int32_t FileAudioDevice::MinMicrophoneVolume(uint32_t& /* minVolume */) const {
    380  return -1;
    381 }
    382 
    383 int32_t FileAudioDevice::SpeakerMuteIsAvailable(bool& /* available */) {
    384  return -1;
    385 }
    386 
    387 int32_t FileAudioDevice::SetSpeakerMute(bool /* enable */) {
    388  return -1;
    389 }
    390 
    391 int32_t FileAudioDevice::SpeakerMute(bool& /* enabled */) const {
    392  return -1;
    393 }
    394 
    395 int32_t FileAudioDevice::MicrophoneMuteIsAvailable(bool& /* available */) {
    396  return -1;
    397 }
    398 
    399 int32_t FileAudioDevice::SetMicrophoneMute(bool /* enable */) {
    400  return -1;
    401 }
    402 
    403 int32_t FileAudioDevice::MicrophoneMute(bool& /* enabled */) const {
    404  return -1;
    405 }
    406 
    407 int32_t FileAudioDevice::StereoPlayoutIsAvailable(bool& available) {
    408  available = true;
    409  return 0;
    410 }
    411 int32_t FileAudioDevice::SetStereoPlayout(bool /* enable */) {
    412  return 0;
    413 }
    414 
    415 int32_t FileAudioDevice::StereoPlayout(bool& enabled) const {
    416  enabled = true;
    417  return 0;
    418 }
    419 
    420 int32_t FileAudioDevice::StereoRecordingIsAvailable(bool& available) {
    421  available = true;
    422  return 0;
    423 }
    424 
    425 int32_t FileAudioDevice::SetStereoRecording(bool /* enable */) {
    426  return 0;
    427 }
    428 
    429 int32_t FileAudioDevice::StereoRecording(bool& enabled) const {
    430  enabled = true;
    431  return 0;
    432 }
    433 
    434 int32_t FileAudioDevice::PlayoutDelay(uint16_t& /* delayMS */) const {
    435  return 0;
    436 }
    437 
    438 void FileAudioDevice::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
    439  MutexLock lock(&mutex_);
    440 
    441  _ptrAudioBuffer = audioBuffer;
    442 
    443  // Inform the AudioBuffer about default settings for this implementation.
    444  // Set all values to zero here since the actual settings will be done by
    445  // InitPlayout and InitRecording later.
    446  _ptrAudioBuffer->SetRecordingSampleRate(0);
    447  _ptrAudioBuffer->SetPlayoutSampleRate(0);
    448  _ptrAudioBuffer->SetRecordingChannels(0);
    449  _ptrAudioBuffer->SetPlayoutChannels(0);
    450 }
    451 
    452 bool FileAudioDevice::PlayThreadProcess() {
    453  if (!_playing) {
    454    return false;
    455  }
    456  int64_t currentTime = TimeMillis();
    457  mutex_.Lock();
    458 
    459  if (_lastCallPlayoutMillis == 0 ||
    460      currentTime - _lastCallPlayoutMillis >= 10) {
    461    mutex_.Unlock();
    462    _ptrAudioBuffer->RequestPlayoutData(_playoutFramesIn10MS);
    463    mutex_.Lock();
    464 
    465    _playoutFramesLeft = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer);
    466    RTC_DCHECK_EQ(_playoutFramesIn10MS, _playoutFramesLeft);
    467    if (_outputFile.is_open()) {
    468      _outputFile.Write(_playoutBuffer, kPlayoutBufferSize);
    469    }
    470    _lastCallPlayoutMillis = currentTime;
    471  }
    472  _playoutFramesLeft = 0;
    473  mutex_.Unlock();
    474 
    475  int64_t deltaTimeMillis = TimeMillis() - currentTime;
    476  if (deltaTimeMillis < 10) {
    477    Thread::SleepMs(10 - deltaTimeMillis);
    478  }
    479 
    480  return true;
    481 }
    482 
    483 bool FileAudioDevice::RecThreadProcess() {
    484  if (!_recording) {
    485    return false;
    486  }
    487 
    488  int64_t currentTime = TimeMillis();
    489  mutex_.Lock();
    490 
    491  if (_lastCallRecordMillis == 0 || currentTime - _lastCallRecordMillis >= 10) {
    492    if (_inputFile.is_open()) {
    493      if (_inputFile.Read(_recordingBuffer, kRecordingBufferSize) > 0) {
    494        _ptrAudioBuffer->SetRecordedBuffer(_recordingBuffer,
    495                                           _recordingFramesIn10MS);
    496      } else {
    497        _inputFile.Rewind();
    498      }
    499      _lastCallRecordMillis = currentTime;
    500      mutex_.Unlock();
    501      _ptrAudioBuffer->DeliverRecordedData();
    502      mutex_.Lock();
    503    }
    504  }
    505 
    506  mutex_.Unlock();
    507 
    508  int64_t deltaTimeMillis = TimeMillis() - currentTime;
    509  if (deltaTimeMillis < 10) {
    510    Thread::SleepMs(10 - deltaTimeMillis);
    511  }
    512 
    513  return true;
    514 }
    515 
    516 }  // namespace webrtc