OLD | NEW |
---|---|
(Empty) | |
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 <utility> | |
12 | |
13 #include "webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h" | |
14 | |
15 #include "webrtc/base/checks.h" | |
16 #include "webrtc/base/event.h" | |
17 #include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h" | |
18 | |
19 namespace webrtc { | |
20 | |
21 class WriteToFileTask : public rtc::QueuedTask { | |
22 public: | |
23 WriteToFileTask(webrtc::FileWrapper* debug_file, | |
24 std::unique_ptr<audioproc::Event> event, | |
25 int64_t* num_bytes_left_for_log) | |
26 : debug_file_(debug_file), | |
27 event_(std::move(event)), | |
28 num_bytes_left_for_log_(num_bytes_left_for_log) {} | |
29 | |
30 private: | |
31 bool IsRoomForNextEvent(size_t event_byte_size) const { | |
32 int64_t next_message_size = event_byte_size + sizeof(int32_t); | |
33 return (*num_bytes_left_for_log_ < 0) || | |
34 (*num_bytes_left_for_log_ >= next_message_size); | |
35 } | |
36 | |
37 void UpdateBytesLeft(size_t event_byte_size) { | |
38 RTC_DCHECK(IsRoomForNextEvent(event_byte_size)); | |
39 if (*num_bytes_left_for_log_ >= 0) { | |
40 *num_bytes_left_for_log_ -= (sizeof(int32_t) + event_byte_size); | |
41 } | |
42 } | |
43 | |
44 bool Run() override { | |
45 if (!debug_file_->is_open()) { | |
46 return true; | |
47 } | |
48 | |
49 std::string event_string; | |
50 event_->SerializeToString(&event_string); | |
51 | |
52 const size_t event_byte_size = event_->ByteSize(); | |
53 | |
54 if (!IsRoomForNextEvent(event_byte_size)) { | |
55 debug_file_->CloseFile(); | |
56 return true; | |
57 } | |
58 | |
59 UpdateBytesLeft(event_byte_size); | |
60 | |
61 // Write message preceded by its size. | |
62 if (!debug_file_->Write(&event_byte_size, sizeof(int32_t))) { | |
63 RTC_NOTREACHED(); | |
64 } | |
65 if (!debug_file_->Write(event_string.data(), event_string.length())) { | |
66 RTC_NOTREACHED(); | |
67 } | |
68 return true; // Delete task from queue at once. TODO(aleloi): | |
69 // instead consider a 'mega-task' that returns | |
70 // 'false', checks if there is something in a | |
71 // swap-queue and reposts itself periodically. | |
72 } | |
73 | |
74 webrtc::FileWrapper* debug_file_; | |
75 std::unique_ptr<audioproc::Event> event_; | |
76 int64_t* num_bytes_left_for_log_; | |
77 }; | |
78 | |
79 AecDumpImpl::AecDumpImpl(int64_t max_log_size_bytes, | |
80 rtc::TaskQueue* worker_queue) | |
81 : debug_file_(FileWrapper::Create()), | |
82 num_bytes_left_for_log_(max_log_size_bytes), | |
83 worker_queue_(worker_queue) {} | |
84 | |
85 AecDumpImpl::AecDumpImpl(rtc::PlatformFile file, | |
86 int64_t max_log_size_bytes, | |
87 rtc::TaskQueue* worker_queue) | |
88 : AecDumpImpl(max_log_size_bytes, worker_queue) { | |
89 FILE* handle = rtc::FdopenPlatformFileForWriting(file); | |
90 RTC_DCHECK(handle); | |
91 debug_file_->OpenFromFileHandle(handle); | |
92 } | |
93 | |
94 AecDumpImpl::AecDumpImpl(std::string file_name, | |
95 int64_t max_log_size_bytes, | |
96 rtc::TaskQueue* worker_queue) | |
97 : AecDumpImpl(max_log_size_bytes, worker_queue) { | |
98 RTC_DCHECK(debug_file_); | |
99 debug_file_->OpenFile(file_name.c_str(), false); | |
100 } | |
101 | |
102 AecDumpImpl::AecDumpImpl(FILE* handle, | |
103 int64_t max_log_size_bytes, | |
104 rtc::TaskQueue* worker_queue) | |
105 : AecDumpImpl(max_log_size_bytes, worker_queue) { | |
106 RTC_DCHECK(debug_file_); | |
107 debug_file_->OpenFromFileHandle(handle); | |
108 } | |
109 | |
110 AecDumpImpl::~AecDumpImpl() { | |
111 // Block until all tasks have finished running. | |
112 rtc::Event thread_sync_event(false /* manual_reset */, false); | |
113 worker_queue_->PostTask([&thread_sync_event] { thread_sync_event.Set(); }); | |
114 thread_sync_event.Wait(rtc::Event::kForever); | |
115 } | |
116 | |
117 std::unique_ptr<AecDump::CaptureStreamInfo> AecDumpImpl::GetCaptureStreamInfo() | |
118 const { | |
119 return std::unique_ptr<CaptureStreamInfoImpl>(new CaptureStreamInfoImpl( | |
120 std::unique_ptr<audioproc::Event>(new audioproc::Event()))); | |
121 } | |
122 | |
123 void AecDumpImpl::WriteInitMessage( | |
124 const InternalAPMStreamsConfig& streams_config) { | |
125 auto event = std::unique_ptr<audioproc::Event>(new audioproc::Event()); | |
126 event->set_type(audioproc::Event::INIT); | |
127 audioproc::Init* msg = event->mutable_init(); | |
128 | |
129 msg->set_sample_rate(streams_config.input_sample_rate); | |
130 msg->set_output_sample_rate(streams_config.output_sample_rate); | |
131 msg->set_reverse_sample_rate(streams_config.render_input_sample_rate); | |
132 msg->set_reverse_output_sample_rate(streams_config.render_output_sample_rate); | |
133 | |
134 msg->set_num_input_channels( | |
135 static_cast<int32_t>(streams_config.input_num_channels)); | |
136 msg->set_num_output_channels( | |
137 static_cast<int32_t>(streams_config.output_num_channels)); | |
138 msg->set_num_reverse_channels( | |
139 static_cast<int32_t>(streams_config.render_input_num_channels)); | |
140 msg->set_num_reverse_output_channels( | |
141 streams_config.render_output_num_channels); | |
142 | |
143 PostTask(std::move(event)); | |
144 } | |
145 | |
146 void AecDumpImpl::WriteRenderStreamMessage(const AudioFrame& frame) { | |
147 auto event = std::unique_ptr<audioproc::Event>(new audioproc::Event()); | |
148 | |
149 event->set_type(audioproc::Event::REVERSE_STREAM); | |
150 audioproc::ReverseStream* msg = event->mutable_reverse_stream(); | |
151 const size_t data_size = | |
152 sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_; | |
153 msg->set_data(frame.data_, data_size); | |
154 | |
155 PostTask(std::move(event)); | |
156 } | |
157 | |
158 void AecDumpImpl::WriteRenderStreamMessage(FloatAudioFrame src) { | |
159 auto event = std::unique_ptr<audioproc::Event>(new audioproc::Event()); | |
160 event->set_type(audioproc::Event::REVERSE_STREAM); | |
161 | |
162 audioproc::ReverseStream* msg = event->mutable_reverse_stream(); | |
163 | |
164 for (size_t i = 0; i < src.num_channels(); ++i) { | |
165 const auto& channel_view = src.channel(i); | |
166 msg->add_channel(channel_view.begin(), sizeof(float) * channel_view.size()); | |
167 } | |
168 | |
169 PostTask(std::move(event)); | |
170 } | |
171 | |
172 void AecDumpImpl::WriteCaptureStreamMessage( | |
173 std::unique_ptr<CaptureStreamInfo> capture_stream_info) { | |
174 // Really ugly, how is it done better? | |
175 auto event_ptr = | |
176 static_cast<CaptureStreamInfoImpl*>(capture_stream_info.get()) | |
177 ->GetEventMsg(); | |
178 if (event_ptr) { | |
179 PostTask(std::move(event_ptr)); | |
180 } | |
181 } | |
182 | |
183 void CopyFromConfigToEvent(const webrtc::InternalAPMConfig& config, | |
184 webrtc::audioproc::Config* pb_cfg) { | |
185 pb_cfg->set_aec_enabled(config.aec_enabled); | |
186 pb_cfg->set_aec_delay_agnostic_enabled(config.aec_delay_agnostic_enabled); | |
187 pb_cfg->set_aec_drift_compensation_enabled( | |
188 config.aec_drift_compensation_enabled); | |
189 pb_cfg->set_aec_extended_filter_enabled(config.aec_extended_filter_enabled); | |
190 pb_cfg->set_aec_suppression_level(config.aec_suppression_level); | |
191 | |
192 pb_cfg->set_aecm_enabled(config.aecm_enabled); | |
193 pb_cfg->set_aecm_comfort_noise_enabled(config.aecm_comfort_noise_enabled); | |
194 pb_cfg->set_aecm_routing_mode(config.aecm_routing_mode); | |
195 | |
196 pb_cfg->set_agc_enabled(config.agc_enabled); | |
197 pb_cfg->set_agc_mode(config.agc_mode); | |
198 pb_cfg->set_agc_limiter_enabled(config.agc_limiter_enabled); | |
199 pb_cfg->set_noise_robust_agc_enabled(config.noise_robust_agc_enabled); | |
200 | |
201 pb_cfg->set_hpf_enabled(config.hpf_enabled); | |
202 | |
203 pb_cfg->set_ns_enabled(config.ns_enabled); | |
204 pb_cfg->set_ns_level(config.ns_level); | |
205 | |
206 pb_cfg->set_transient_suppression_enabled( | |
207 config.transient_suppression_enabled); | |
208 pb_cfg->set_intelligibility_enhancer_enabled( | |
209 config.intelligibility_enhancer_enabled); | |
210 | |
211 pb_cfg->set_experiments_description(config.experiments_description); | |
212 } | |
213 | |
214 void AecDumpImpl::WriteConfig(const InternalAPMConfig& config, bool forced) { | |
215 auto event = std::unique_ptr<audioproc::Event>(new audioproc::Event()); | |
peah-webrtc
2017/05/04 14:40:32
Is it possible to have event being a part of Write
| |
216 event->set_type(audioproc::Event::CONFIG); | |
217 CopyFromConfigToEvent(config, event->mutable_config()); | |
218 | |
219 ProtoString serialized_config = event->mutable_config()->SerializeAsString(); | |
220 { | |
221 rtc::CritScope cs(&config_string_lock_); | |
222 if (!forced && serialized_config == last_serialized_capture_config_) { | |
223 return; | |
224 } | |
225 last_serialized_capture_config_ = serialized_config; | |
226 } | |
227 | |
228 PostTask(std::move(event)); | |
229 } | |
230 | |
231 void AecDumpImpl::PostTask(std::unique_ptr<audioproc::Event> event) { | |
232 RTC_DCHECK(event); | |
233 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new WriteToFileTask( | |
peah-webrtc
2017/05/04 14:40:32
Is it needed to create a new task here? Can't we r
| |
234 debug_file_.get(), std::move(event), &num_bytes_left_for_log_))); | |
235 } | |
236 | |
237 std::unique_ptr<AecDump> AecDumpFactory::Create(rtc::PlatformFile file, | |
238 int64_t max_log_size_bytes, | |
239 rtc::TaskQueue* worker_queue) { | |
240 return std::unique_ptr<AecDumpImpl>( | |
241 new AecDumpImpl(file, max_log_size_bytes, worker_queue)); | |
242 } | |
243 | |
244 std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name, | |
245 int64_t max_log_size_bytes, | |
246 rtc::TaskQueue* worker_queue) { | |
247 return std::unique_ptr<AecDumpImpl>( | |
248 new AecDumpImpl(file_name, max_log_size_bytes, worker_queue)); | |
249 } | |
250 | |
251 std::unique_ptr<AecDump> AecDumpFactory::Create(FILE* handle, | |
252 int64_t max_log_size_bytes, | |
253 rtc::TaskQueue* worker_queue) { | |
254 return std::unique_ptr<AecDumpImpl>( | |
255 new AecDumpImpl(handle, max_log_size_bytes, worker_queue)); | |
256 } | |
257 } // namespace webrtc | |
OLD | NEW |