blob: 594bf85cd9d85b09fa5586f4cb36b7d6127f19cb [file] [log] [blame]
aleloi06013e92017-05-23 08:52:05 -07001/*
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 <utility>
12
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/audio_processing/aec_dump/aec_dump_impl.h"
aleloi06013e92017-05-23 08:52:05 -070014
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "modules/audio_processing/aec_dump/aec_dump_factory.h"
16#include "rtc_base/checks.h"
17#include "rtc_base/event.h"
18#include "rtc_base/ptr_util.h"
aleloi06013e92017-05-23 08:52:05 -070019
20namespace webrtc {
21
22namespace {
23void CopyFromConfigToEvent(const webrtc::InternalAPMConfig& config,
24 webrtc::audioproc::Config* pb_cfg) {
25 pb_cfg->set_aec_enabled(config.aec_enabled);
26 pb_cfg->set_aec_delay_agnostic_enabled(config.aec_delay_agnostic_enabled);
27 pb_cfg->set_aec_drift_compensation_enabled(
28 config.aec_drift_compensation_enabled);
29 pb_cfg->set_aec_extended_filter_enabled(config.aec_extended_filter_enabled);
30 pb_cfg->set_aec_suppression_level(config.aec_suppression_level);
31
32 pb_cfg->set_aecm_enabled(config.aecm_enabled);
33 pb_cfg->set_aecm_comfort_noise_enabled(config.aecm_comfort_noise_enabled);
34 pb_cfg->set_aecm_routing_mode(config.aecm_routing_mode);
35
36 pb_cfg->set_agc_enabled(config.agc_enabled);
37 pb_cfg->set_agc_mode(config.agc_mode);
38 pb_cfg->set_agc_limiter_enabled(config.agc_limiter_enabled);
39 pb_cfg->set_noise_robust_agc_enabled(config.noise_robust_agc_enabled);
40
41 pb_cfg->set_hpf_enabled(config.hpf_enabled);
42
43 pb_cfg->set_ns_enabled(config.ns_enabled);
44 pb_cfg->set_ns_level(config.ns_level);
45
46 pb_cfg->set_transient_suppression_enabled(
47 config.transient_suppression_enabled);
48 pb_cfg->set_intelligibility_enhancer_enabled(
49 config.intelligibility_enhancer_enabled);
50
51 pb_cfg->set_experiments_description(config.experiments_description);
52}
53
54} // namespace
55
56AecDumpImpl::AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
57 int64_t max_log_size_bytes,
58 rtc::TaskQueue* worker_queue)
59 : debug_file_(std::move(debug_file)),
60 num_bytes_left_for_log_(max_log_size_bytes),
61 worker_queue_(worker_queue),
62 capture_stream_info_(CreateWriteToFileTask()) {}
63
64AecDumpImpl::~AecDumpImpl() {
65 // Block until all tasks have finished running.
66 rtc::Event thread_sync_event(false /* manual_reset */, false);
67 worker_queue_->PostTask([&thread_sync_event] { thread_sync_event.Set(); });
68 // Wait until the event has been signaled with .Set(). By then all
69 // pending tasks will have finished.
70 thread_sync_event.Wait(rtc::Event::kForever);
71}
72
73void AecDumpImpl::WriteInitMessage(
74 const InternalAPMStreamsConfig& streams_config) {
75 auto task = CreateWriteToFileTask();
76 auto* event = task->GetEvent();
77 event->set_type(audioproc::Event::INIT);
78 audioproc::Init* msg = event->mutable_init();
79
80 msg->set_sample_rate(streams_config.input_sample_rate);
81 msg->set_output_sample_rate(streams_config.output_sample_rate);
82 msg->set_reverse_sample_rate(streams_config.render_input_sample_rate);
83 msg->set_reverse_output_sample_rate(streams_config.render_output_sample_rate);
84
85 msg->set_num_input_channels(
86 static_cast<int32_t>(streams_config.input_num_channels));
87 msg->set_num_output_channels(
88 static_cast<int32_t>(streams_config.output_num_channels));
89 msg->set_num_reverse_channels(
90 static_cast<int32_t>(streams_config.render_input_num_channels));
91 msg->set_num_reverse_output_channels(
92 streams_config.render_output_num_channels);
93
94 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
95}
96
97void AecDumpImpl::AddCaptureStreamInput(const FloatAudioFrame& src) {
98 capture_stream_info_.AddInput(src);
99}
100
101void AecDumpImpl::AddCaptureStreamOutput(const FloatAudioFrame& src) {
102 capture_stream_info_.AddOutput(src);
103}
104
105void AecDumpImpl::AddCaptureStreamInput(const AudioFrame& frame) {
106 capture_stream_info_.AddInput(frame);
107}
108
109void AecDumpImpl::AddCaptureStreamOutput(const AudioFrame& frame) {
110 capture_stream_info_.AddOutput(frame);
111}
112
113void AecDumpImpl::AddAudioProcessingState(const AudioProcessingState& state) {
114 capture_stream_info_.AddAudioProcessingState(state);
115}
116
117void AecDumpImpl::WriteCaptureStreamMessage() {
118 auto task = capture_stream_info_.GetTask();
119 RTC_DCHECK(task);
aleloi06013e92017-05-23 08:52:05 -0700120 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
121 capture_stream_info_.SetTask(CreateWriteToFileTask());
122}
123
124void AecDumpImpl::WriteRenderStreamMessage(const AudioFrame& frame) {
125 auto task = CreateWriteToFileTask();
126 auto* event = task->GetEvent();
127
128 event->set_type(audioproc::Event::REVERSE_STREAM);
129 audioproc::ReverseStream* msg = event->mutable_reverse_stream();
130 const size_t data_size =
131 sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_;
yujo36b1a5f2017-06-12 12:45:32 -0700132 msg->set_data(frame.data(), data_size);
aleloi06013e92017-05-23 08:52:05 -0700133
134 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
135}
136
137void AecDumpImpl::WriteRenderStreamMessage(const FloatAudioFrame& src) {
138 auto task = CreateWriteToFileTask();
139 auto* event = task->GetEvent();
140
141 event->set_type(audioproc::Event::REVERSE_STREAM);
142
143 audioproc::ReverseStream* msg = event->mutable_reverse_stream();
144
145 for (size_t i = 0; i < src.num_channels(); ++i) {
146 const auto& channel_view = src.channel(i);
147 msg->add_channel(channel_view.begin(), sizeof(float) * channel_view.size());
148 }
149
150 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
151}
152
153void AecDumpImpl::WriteConfig(const InternalAPMConfig& config) {
154 RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
155 auto task = CreateWriteToFileTask();
156 auto* event = task->GetEvent();
157 event->set_type(audioproc::Event::CONFIG);
158 CopyFromConfigToEvent(config, event->mutable_config());
159 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
160}
161
162std::unique_ptr<WriteToFileTask> AecDumpImpl::CreateWriteToFileTask() {
163 return rtc::MakeUnique<WriteToFileTask>(debug_file_.get(),
164 &num_bytes_left_for_log_);
165}
166
167std::unique_ptr<AecDump> AecDumpFactory::Create(rtc::PlatformFile file,
168 int64_t max_log_size_bytes,
169 rtc::TaskQueue* worker_queue) {
170 RTC_DCHECK(worker_queue);
171 std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
172 FILE* handle = rtc::FdopenPlatformFileForWriting(file);
173 if (!handle) {
174 return nullptr;
175 }
176 if (!debug_file->OpenFromFileHandle(handle)) {
177 return nullptr;
178 }
179 return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
180 worker_queue);
181}
182
183std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name,
184 int64_t max_log_size_bytes,
185 rtc::TaskQueue* worker_queue) {
186 RTC_DCHECK(worker_queue);
187 std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
188 if (!debug_file->OpenFile(file_name.c_str(), false)) {
189 return nullptr;
190 }
191 return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
192 worker_queue);
193}
194
195std::unique_ptr<AecDump> AecDumpFactory::Create(FILE* handle,
196 int64_t max_log_size_bytes,
197 rtc::TaskQueue* worker_queue) {
198 RTC_DCHECK(worker_queue);
199 RTC_DCHECK(handle);
200 std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
201 if (!debug_file->OpenFromFileHandle(handle)) {
202 return nullptr;
203 }
204 return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
205 worker_queue);
206}
207} // namespace webrtc