tor-browser

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

aec_dump_impl.cc (11695B)


      1 /*
      2 *  Copyright (c) 2017 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_processing/aec_dump/aec_dump_impl.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstdio>
     16 #include <memory>
     17 #include <string>
     18 #include <utility>
     19 
     20 #include "absl/base/nullability.h"
     21 #include "absl/strings/string_view.h"
     22 #include "api/audio/audio_processing.h"
     23 #include "api/audio/audio_view.h"
     24 #include "api/task_queue/task_queue_base.h"
     25 #include "modules/audio_processing/aec_dump/aec_dump_factory.h"
     26 #include "modules/audio_processing/include/aec_dump.h"
     27 #include "modules/audio_processing/include/audio_frame_view.h"
     28 #include "rtc_base/checks.h"
     29 #include "rtc_base/event.h"
     30 #include "rtc_base/race_checker.h"
     31 #include "rtc_base/system/file_wrapper.h"
     32 
     33 // Generated at build-time by the protobuf compiler.
     34 #include "modules/audio_processing/debug.pb.h"
     35 
     36 namespace webrtc {
     37 
     38 namespace {
     39 void CopyFromConfigToEvent(const InternalAPMConfig& config,
     40                           audioproc::Config* pb_cfg) {
     41  pb_cfg->set_aec_enabled(config.aec_enabled);
     42  pb_cfg->set_aec_delay_agnostic_enabled(config.aec_delay_agnostic_enabled);
     43  pb_cfg->set_aec_drift_compensation_enabled(
     44      config.aec_drift_compensation_enabled);
     45  pb_cfg->set_aec_extended_filter_enabled(config.aec_extended_filter_enabled);
     46  pb_cfg->set_aec_suppression_level(config.aec_suppression_level);
     47 
     48  pb_cfg->set_aecm_enabled(config.aecm_enabled);
     49  pb_cfg->set_aecm_comfort_noise_enabled(config.aecm_comfort_noise_enabled);
     50  pb_cfg->set_aecm_routing_mode(config.aecm_routing_mode);
     51 
     52  pb_cfg->set_agc_enabled(config.agc_enabled);
     53  pb_cfg->set_agc_mode(config.agc_mode);
     54  pb_cfg->set_agc_limiter_enabled(config.agc_limiter_enabled);
     55  pb_cfg->set_noise_robust_agc_enabled(config.noise_robust_agc_enabled);
     56 
     57  pb_cfg->set_hpf_enabled(config.hpf_enabled);
     58 
     59  pb_cfg->set_ns_enabled(config.ns_enabled);
     60  pb_cfg->set_ns_level(config.ns_level);
     61 
     62  pb_cfg->set_transient_suppression_enabled(
     63      config.transient_suppression_enabled);
     64 
     65  pb_cfg->set_pre_amplifier_enabled(config.pre_amplifier_enabled);
     66  pb_cfg->set_pre_amplifier_fixed_gain_factor(
     67      config.pre_amplifier_fixed_gain_factor);
     68 
     69  pb_cfg->set_experiments_description(config.experiments_description);
     70 }
     71 
     72 }  // namespace
     73 
     74 AecDumpImpl::AecDumpImpl(FileWrapper debug_file,
     75                         int64_t max_log_size_bytes,
     76                         TaskQueueBase* absl_nonnull worker_queue)
     77    : debug_file_(std::move(debug_file)),
     78      num_bytes_left_for_log_(max_log_size_bytes),
     79      worker_queue_(worker_queue) {}
     80 
     81 AecDumpImpl::~AecDumpImpl() {
     82  // Block until all tasks have finished running.
     83  Event thread_sync_event;
     84  worker_queue_->PostTask([&thread_sync_event] { thread_sync_event.Set(); });
     85  // Wait until the event has been signaled with .Set(). By then all
     86  // pending tasks will have finished.
     87  thread_sync_event.Wait(Event::kForever);
     88 }
     89 
     90 void AecDumpImpl::WriteInitMessage(const ProcessingConfig& api_format,
     91                                   int64_t time_now_ms) {
     92  auto event = std::make_unique<audioproc::Event>();
     93  event->set_type(audioproc::Event::INIT);
     94  audioproc::Init* msg = event->mutable_init();
     95 
     96  msg->set_sample_rate(api_format.input_stream().sample_rate_hz());
     97  msg->set_output_sample_rate(api_format.output_stream().sample_rate_hz());
     98  msg->set_reverse_sample_rate(
     99      api_format.reverse_input_stream().sample_rate_hz());
    100  msg->set_reverse_output_sample_rate(
    101      api_format.reverse_output_stream().sample_rate_hz());
    102 
    103  msg->set_num_input_channels(
    104      static_cast<int32_t>(api_format.input_stream().num_channels()));
    105  msg->set_num_output_channels(
    106      static_cast<int32_t>(api_format.output_stream().num_channels()));
    107  msg->set_num_reverse_channels(
    108      static_cast<int32_t>(api_format.reverse_input_stream().num_channels()));
    109  msg->set_num_reverse_output_channels(
    110      api_format.reverse_output_stream().num_channels());
    111  msg->set_timestamp_ms(time_now_ms);
    112 
    113  PostWriteToFileTask(std::move(event));
    114 }
    115 
    116 void AecDumpImpl::AddCaptureStreamInput(
    117    const AudioFrameView<const float>& src) {
    118  capture_stream_info_.AddInput(src);
    119 }
    120 
    121 void AecDumpImpl::AddCaptureStreamInput(MonoView<const float> channel) {
    122  capture_stream_info_.AddInputChannel(channel);
    123 }
    124 
    125 void AecDumpImpl::AddCaptureStreamOutput(
    126    const AudioFrameView<const float>& src) {
    127  capture_stream_info_.AddOutput(src);
    128 }
    129 
    130 void AecDumpImpl::AddCaptureStreamOutput(MonoView<const float> channel) {
    131  capture_stream_info_.AddOutputChannel(channel);
    132 }
    133 
    134 void AecDumpImpl::AddCaptureStreamInput(const int16_t* const data,
    135                                        int num_channels,
    136                                        int samples_per_channel) {
    137  capture_stream_info_.AddInput(data, num_channels, samples_per_channel);
    138 }
    139 
    140 void AecDumpImpl::AddCaptureStreamOutput(const int16_t* const data,
    141                                         int num_channels,
    142                                         int samples_per_channel) {
    143  capture_stream_info_.AddOutput(data, num_channels, samples_per_channel);
    144 }
    145 
    146 void AecDumpImpl::AddAudioProcessingState(const AudioProcessingState& state) {
    147  capture_stream_info_.AddAudioProcessingState(state);
    148 }
    149 
    150 void AecDumpImpl::WriteCaptureStreamMessage() {
    151  PostWriteToFileTask(capture_stream_info_.FetchEvent());
    152 }
    153 
    154 void AecDumpImpl::WriteRenderStreamMessage(const int16_t* const data,
    155                                           int num_channels,
    156                                           int samples_per_channel) {
    157  auto event = std::make_unique<audioproc::Event>();
    158  event->set_type(audioproc::Event::REVERSE_STREAM);
    159  audioproc::ReverseStream* msg = event->mutable_reverse_stream();
    160  const size_t data_size = sizeof(int16_t) * samples_per_channel * num_channels;
    161  msg->set_data(data, data_size);
    162 
    163  PostWriteToFileTask(std::move(event));
    164 }
    165 
    166 void AecDumpImpl::WriteRenderStreamMessage(
    167    const AudioFrameView<const float>& src) {
    168  auto event = std::make_unique<audioproc::Event>();
    169  event->set_type(audioproc::Event::REVERSE_STREAM);
    170 
    171  audioproc::ReverseStream* msg = event->mutable_reverse_stream();
    172 
    173  for (int i = 0; i < src.num_channels(); ++i) {
    174    const auto& channel_view = src.channel(i);
    175    msg->add_channel(channel_view.begin(), sizeof(float) * channel_view.size());
    176  }
    177 
    178  PostWriteToFileTask(std::move(event));
    179 }
    180 
    181 void AecDumpImpl::WriteRenderStreamMessage(const float* const* data,
    182                                           int num_channels,
    183                                           int samples_per_channel) {
    184  auto event = std::make_unique<audioproc::Event>();
    185  event->set_type(audioproc::Event::REVERSE_STREAM);
    186 
    187  audioproc::ReverseStream* msg = event->mutable_reverse_stream();
    188 
    189  for (int i = 0; i < num_channels; ++i) {
    190    MonoView<const float> channel_view(data[i], samples_per_channel);
    191    msg->add_channel(channel_view.begin(), sizeof(float) * channel_view.size());
    192  }
    193 
    194  PostWriteToFileTask(std::move(event));
    195 }
    196 
    197 void AecDumpImpl::WriteConfig(const InternalAPMConfig& config) {
    198  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
    199  auto event = std::make_unique<audioproc::Event>();
    200  event->set_type(audioproc::Event::CONFIG);
    201  CopyFromConfigToEvent(config, event->mutable_config());
    202  PostWriteToFileTask(std::move(event));
    203 }
    204 
    205 void AecDumpImpl::WriteRuntimeSetting(
    206    const AudioProcessing::RuntimeSetting& runtime_setting) {
    207  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
    208  auto event = std::make_unique<audioproc::Event>();
    209  event->set_type(audioproc::Event::RUNTIME_SETTING);
    210  audioproc::RuntimeSetting* setting = event->mutable_runtime_setting();
    211  switch (runtime_setting.type()) {
    212    case AudioProcessing::RuntimeSetting::Type::kCapturePreGain: {
    213      float x;
    214      runtime_setting.GetFloat(&x);
    215      setting->set_capture_pre_gain(x);
    216      break;
    217    }
    218    case AudioProcessing::RuntimeSetting::Type::kCapturePostGain: {
    219      float x;
    220      runtime_setting.GetFloat(&x);
    221      setting->set_capture_post_gain(x);
    222      break;
    223    }
    224    case AudioProcessing::RuntimeSetting::Type::
    225        kCustomRenderProcessingRuntimeSetting: {
    226      float x;
    227      runtime_setting.GetFloat(&x);
    228      setting->set_custom_render_processing_setting(x);
    229      break;
    230    }
    231    case AudioProcessing::RuntimeSetting::Type::kCaptureCompressionGain:
    232      // Runtime AGC1 compression gain is ignored.
    233      // TODO(http://bugs.webrtc.org/10432): Store compression gain in aecdumps.
    234      break;
    235    case AudioProcessing::RuntimeSetting::Type::kCaptureFixedPostGain: {
    236      float x;
    237      runtime_setting.GetFloat(&x);
    238      setting->set_capture_fixed_post_gain(x);
    239      break;
    240    }
    241    case AudioProcessing::RuntimeSetting::Type::kCaptureOutputUsed: {
    242      bool x;
    243      runtime_setting.GetBool(&x);
    244      setting->set_capture_output_used(x);
    245      break;
    246    }
    247    case AudioProcessing::RuntimeSetting::Type::kPlayoutVolumeChange: {
    248      int x;
    249      runtime_setting.GetInt(&x);
    250      setting->set_playout_volume_change(x);
    251      break;
    252    }
    253    case AudioProcessing::RuntimeSetting::Type::kPlayoutAudioDeviceChange: {
    254      AudioProcessing::RuntimeSetting::PlayoutAudioDeviceInfo src;
    255      runtime_setting.GetPlayoutAudioDeviceInfo(&src);
    256      auto* dst = setting->mutable_playout_audio_device_change();
    257      dst->set_id(src.id);
    258      dst->set_max_volume(src.max_volume);
    259      break;
    260    }
    261    case AudioProcessing::RuntimeSetting::Type::kNotSpecified:
    262      RTC_DCHECK_NOTREACHED();
    263      break;
    264  }
    265  PostWriteToFileTask(std::move(event));
    266 }
    267 
    268 void AecDumpImpl::PostWriteToFileTask(std::unique_ptr<audioproc::Event> event) {
    269  RTC_DCHECK(event);
    270  worker_queue_->PostTask([event = std::move(event), this] {
    271    std::string event_string = event->SerializeAsString();
    272    const size_t event_byte_size = event_string.size();
    273 
    274    if (num_bytes_left_for_log_ >= 0) {
    275      const int64_t next_message_size = sizeof(int32_t) + event_byte_size;
    276      if (num_bytes_left_for_log_ < next_message_size) {
    277        // Ensure that no further events are written, even if they're smaller
    278        // than the current event.
    279        num_bytes_left_for_log_ = 0;
    280        return;
    281      }
    282      num_bytes_left_for_log_ -= next_message_size;
    283    }
    284 
    285    // Write message preceded by its size.
    286    if (!debug_file_.Write(&event_byte_size, sizeof(int32_t))) {
    287      RTC_DCHECK_NOTREACHED();
    288    }
    289    if (!debug_file_.Write(event_string.data(), event_string.size())) {
    290      RTC_DCHECK_NOTREACHED();
    291    }
    292  });
    293 }
    294 
    295 absl_nullable std::unique_ptr<AecDump> AecDumpFactory::Create(
    296    FileWrapper file,
    297    int64_t max_log_size_bytes,
    298    TaskQueueBase* absl_nonnull worker_queue) {
    299  RTC_DCHECK(worker_queue);
    300  if (!file.is_open())
    301    return nullptr;
    302 
    303  return std::make_unique<AecDumpImpl>(std::move(file), max_log_size_bytes,
    304                                       worker_queue);
    305 }
    306 
    307 absl_nullable std::unique_ptr<AecDump> AecDumpFactory::Create(
    308    absl::string_view file_name,
    309    int64_t max_log_size_bytes,
    310    TaskQueueBase* absl_nonnull worker_queue) {
    311  return Create(FileWrapper::OpenWriteOnly(file_name), max_log_size_bytes,
    312                worker_queue);
    313 }
    314 
    315 absl_nullable std::unique_ptr<AecDump> AecDumpFactory::Create(
    316    FILE* absl_nonnull handle,
    317    int64_t max_log_size_bytes,
    318    TaskQueueBase* absl_nonnull worker_queue) {
    319  return Create(FileWrapper(handle), max_log_size_bytes, worker_queue);
    320 }
    321 
    322 }  // namespace webrtc