Moving src/webrtc into src/.
In order to eliminate the WebRTC Subtree mirror in Chromium, WebRTC is moving the content of the src/webrtc directory up to the src/ directory. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true TBR=tommi@webrtc.org Bug: chromium:611808 Change-Id: Iac59c5b51b950f174119565bac87955a7994bc38 Reviewed-on: https://webrtc-review.googlesource.com/1560 Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Henrik Kjellander <kjellander@webrtc.org> Cr-Commit-Position: refs/heads/master@{#19845}
This commit is contained in:
committed by
Commit Bot
parent
6674846b4a
commit
bb547203bf
114
modules/audio_processing/aec_dump/BUILD.gn
Normal file
114
modules/audio_processing/aec_dump/BUILD.gn
Normal file
@ -0,0 +1,114 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni") # This contains def of 'rtc_enable_protobuf'
|
||||
|
||||
rtc_source_set("aec_dump") {
|
||||
sources = [
|
||||
"aec_dump_factory.h",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
"..:aec_dump_interface",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("mock_aec_dump") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"mock_aec_dump.cc",
|
||||
"mock_aec_dump.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"..:aec_dump_interface",
|
||||
]
|
||||
public_deps = [
|
||||
"../..:module_api",
|
||||
"../../../test:test_support",
|
||||
"//testing/gmock",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("mock_aec_dump_unittests") {
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"aec_dump_integration_test.cc",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":mock_aec_dump",
|
||||
"..:audio_processing",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"//testing/gtest",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
rtc_source_set("aec_dump_impl") {
|
||||
sources = [
|
||||
"aec_dump_impl.cc",
|
||||
"aec_dump_impl.h",
|
||||
"capture_stream_info.cc",
|
||||
"capture_stream_info.h",
|
||||
"write_to_file_task.cc",
|
||||
"write_to_file_task.h",
|
||||
]
|
||||
|
||||
public = []
|
||||
|
||||
public_deps = [
|
||||
":aec_dump",
|
||||
"..:aec_dump_interface",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../../../modules:module_api",
|
||||
"../../../rtc_base:protobuf_utils",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:rtc_task_queue",
|
||||
"../../../system_wrappers",
|
||||
]
|
||||
|
||||
deps += [ "../:audioproc_debug_proto" ]
|
||||
}
|
||||
|
||||
rtc_source_set("aec_dump_unittests") {
|
||||
testonly = true
|
||||
defines = []
|
||||
deps = [
|
||||
":aec_dump_impl",
|
||||
"..:aec_dump_interface",
|
||||
"..:audioproc_debug_proto",
|
||||
"../../../modules:module_api",
|
||||
"../../../rtc_base:rtc_task_queue",
|
||||
"../../../test:test_support",
|
||||
"//testing/gtest",
|
||||
]
|
||||
sources = [
|
||||
"aec_dump_unittest.cc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("null_aec_dump_factory") {
|
||||
assert_no_deps = [ ":aec_dump_impl" ]
|
||||
sources = [
|
||||
"null_aec_dump_factory.cc",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":aec_dump",
|
||||
"..:aec_dump_interface",
|
||||
]
|
||||
}
|
||||
47
modules/audio_processing/aec_dump/aec_dump_factory.h
Normal file
47
modules/audio_processing/aec_dump/aec_dump_factory.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_AEC_DUMP_FACTORY_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_AEC_DUMP_FACTORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/modules/audio_processing/include/aec_dump.h"
|
||||
#include "webrtc/rtc_base/platform_file.h"
|
||||
|
||||
namespace rtc {
|
||||
class TaskQueue;
|
||||
} // namespace rtc
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AecDumpFactory {
|
||||
public:
|
||||
// The |worker_queue| may not be null and must outlive the created
|
||||
// AecDump instance. |max_log_size_bytes == -1| means the log size
|
||||
// will be unlimited. |handle| may not be null. The AecDump takes
|
||||
// responsibility for |handle| and closes it in the destructor. A
|
||||
// non-null return value indicates that the file has been
|
||||
// sucessfully opened.
|
||||
static std::unique_ptr<AecDump> Create(rtc::PlatformFile file,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue);
|
||||
static std::unique_ptr<AecDump> Create(std::string file_name,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue);
|
||||
static std::unique_ptr<AecDump> Create(FILE* handle,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_AEC_DUMP_FACTORY_H_
|
||||
208
modules/audio_processing/aec_dump/aec_dump_impl.cc
Normal file
208
modules/audio_processing/aec_dump/aec_dump_impl.cc
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h"
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
|
||||
#include "webrtc/rtc_base/checks.h"
|
||||
#include "webrtc/rtc_base/event.h"
|
||||
#include "webrtc/rtc_base/ptr_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
void CopyFromConfigToEvent(const webrtc::InternalAPMConfig& config,
|
||||
webrtc::audioproc::Config* pb_cfg) {
|
||||
pb_cfg->set_aec_enabled(config.aec_enabled);
|
||||
pb_cfg->set_aec_delay_agnostic_enabled(config.aec_delay_agnostic_enabled);
|
||||
pb_cfg->set_aec_drift_compensation_enabled(
|
||||
config.aec_drift_compensation_enabled);
|
||||
pb_cfg->set_aec_extended_filter_enabled(config.aec_extended_filter_enabled);
|
||||
pb_cfg->set_aec_suppression_level(config.aec_suppression_level);
|
||||
|
||||
pb_cfg->set_aecm_enabled(config.aecm_enabled);
|
||||
pb_cfg->set_aecm_comfort_noise_enabled(config.aecm_comfort_noise_enabled);
|
||||
pb_cfg->set_aecm_routing_mode(config.aecm_routing_mode);
|
||||
|
||||
pb_cfg->set_agc_enabled(config.agc_enabled);
|
||||
pb_cfg->set_agc_mode(config.agc_mode);
|
||||
pb_cfg->set_agc_limiter_enabled(config.agc_limiter_enabled);
|
||||
pb_cfg->set_noise_robust_agc_enabled(config.noise_robust_agc_enabled);
|
||||
|
||||
pb_cfg->set_hpf_enabled(config.hpf_enabled);
|
||||
|
||||
pb_cfg->set_ns_enabled(config.ns_enabled);
|
||||
pb_cfg->set_ns_level(config.ns_level);
|
||||
|
||||
pb_cfg->set_transient_suppression_enabled(
|
||||
config.transient_suppression_enabled);
|
||||
pb_cfg->set_intelligibility_enhancer_enabled(
|
||||
config.intelligibility_enhancer_enabled);
|
||||
|
||||
pb_cfg->set_experiments_description(config.experiments_description);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AecDumpImpl::AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue)
|
||||
: debug_file_(std::move(debug_file)),
|
||||
num_bytes_left_for_log_(max_log_size_bytes),
|
||||
worker_queue_(worker_queue),
|
||||
capture_stream_info_(CreateWriteToFileTask()) {}
|
||||
|
||||
AecDumpImpl::~AecDumpImpl() {
|
||||
// Block until all tasks have finished running.
|
||||
rtc::Event thread_sync_event(false /* manual_reset */, false);
|
||||
worker_queue_->PostTask([&thread_sync_event] { thread_sync_event.Set(); });
|
||||
// Wait until the event has been signaled with .Set(). By then all
|
||||
// pending tasks will have finished.
|
||||
thread_sync_event.Wait(rtc::Event::kForever);
|
||||
}
|
||||
|
||||
void AecDumpImpl::WriteInitMessage(
|
||||
const InternalAPMStreamsConfig& streams_config) {
|
||||
auto task = CreateWriteToFileTask();
|
||||
auto* event = task->GetEvent();
|
||||
event->set_type(audioproc::Event::INIT);
|
||||
audioproc::Init* msg = event->mutable_init();
|
||||
|
||||
msg->set_sample_rate(streams_config.input_sample_rate);
|
||||
msg->set_output_sample_rate(streams_config.output_sample_rate);
|
||||
msg->set_reverse_sample_rate(streams_config.render_input_sample_rate);
|
||||
msg->set_reverse_output_sample_rate(streams_config.render_output_sample_rate);
|
||||
|
||||
msg->set_num_input_channels(
|
||||
static_cast<int32_t>(streams_config.input_num_channels));
|
||||
msg->set_num_output_channels(
|
||||
static_cast<int32_t>(streams_config.output_num_channels));
|
||||
msg->set_num_reverse_channels(
|
||||
static_cast<int32_t>(streams_config.render_input_num_channels));
|
||||
msg->set_num_reverse_output_channels(
|
||||
streams_config.render_output_num_channels);
|
||||
|
||||
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
|
||||
}
|
||||
|
||||
void AecDumpImpl::AddCaptureStreamInput(const FloatAudioFrame& src) {
|
||||
capture_stream_info_.AddInput(src);
|
||||
}
|
||||
|
||||
void AecDumpImpl::AddCaptureStreamOutput(const FloatAudioFrame& src) {
|
||||
capture_stream_info_.AddOutput(src);
|
||||
}
|
||||
|
||||
void AecDumpImpl::AddCaptureStreamInput(const AudioFrame& frame) {
|
||||
capture_stream_info_.AddInput(frame);
|
||||
}
|
||||
|
||||
void AecDumpImpl::AddCaptureStreamOutput(const AudioFrame& frame) {
|
||||
capture_stream_info_.AddOutput(frame);
|
||||
}
|
||||
|
||||
void AecDumpImpl::AddAudioProcessingState(const AudioProcessingState& state) {
|
||||
capture_stream_info_.AddAudioProcessingState(state);
|
||||
}
|
||||
|
||||
void AecDumpImpl::WriteCaptureStreamMessage() {
|
||||
auto task = capture_stream_info_.GetTask();
|
||||
RTC_DCHECK(task);
|
||||
std::move(task);
|
||||
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
|
||||
capture_stream_info_.SetTask(CreateWriteToFileTask());
|
||||
}
|
||||
|
||||
void AecDumpImpl::WriteRenderStreamMessage(const AudioFrame& frame) {
|
||||
auto task = CreateWriteToFileTask();
|
||||
auto* event = task->GetEvent();
|
||||
|
||||
event->set_type(audioproc::Event::REVERSE_STREAM);
|
||||
audioproc::ReverseStream* msg = event->mutable_reverse_stream();
|
||||
const size_t data_size =
|
||||
sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_;
|
||||
msg->set_data(frame.data(), data_size);
|
||||
|
||||
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
|
||||
}
|
||||
|
||||
void AecDumpImpl::WriteRenderStreamMessage(const FloatAudioFrame& src) {
|
||||
auto task = CreateWriteToFileTask();
|
||||
auto* event = task->GetEvent();
|
||||
|
||||
event->set_type(audioproc::Event::REVERSE_STREAM);
|
||||
|
||||
audioproc::ReverseStream* msg = event->mutable_reverse_stream();
|
||||
|
||||
for (size_t i = 0; i < src.num_channels(); ++i) {
|
||||
const auto& channel_view = src.channel(i);
|
||||
msg->add_channel(channel_view.begin(), sizeof(float) * channel_view.size());
|
||||
}
|
||||
|
||||
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
|
||||
}
|
||||
|
||||
void AecDumpImpl::WriteConfig(const InternalAPMConfig& config) {
|
||||
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
|
||||
auto task = CreateWriteToFileTask();
|
||||
auto* event = task->GetEvent();
|
||||
event->set_type(audioproc::Event::CONFIG);
|
||||
CopyFromConfigToEvent(config, event->mutable_config());
|
||||
worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
|
||||
}
|
||||
|
||||
std::unique_ptr<WriteToFileTask> AecDumpImpl::CreateWriteToFileTask() {
|
||||
return rtc::MakeUnique<WriteToFileTask>(debug_file_.get(),
|
||||
&num_bytes_left_for_log_);
|
||||
}
|
||||
|
||||
std::unique_ptr<AecDump> AecDumpFactory::Create(rtc::PlatformFile file,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue) {
|
||||
RTC_DCHECK(worker_queue);
|
||||
std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
|
||||
FILE* handle = rtc::FdopenPlatformFileForWriting(file);
|
||||
if (!handle) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!debug_file->OpenFromFileHandle(handle)) {
|
||||
return nullptr;
|
||||
}
|
||||
return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
|
||||
worker_queue);
|
||||
}
|
||||
|
||||
std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue) {
|
||||
RTC_DCHECK(worker_queue);
|
||||
std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
|
||||
if (!debug_file->OpenFile(file_name.c_str(), false)) {
|
||||
return nullptr;
|
||||
}
|
||||
return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
|
||||
worker_queue);
|
||||
}
|
||||
|
||||
std::unique_ptr<AecDump> AecDumpFactory::Create(FILE* handle,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue) {
|
||||
RTC_DCHECK(worker_queue);
|
||||
RTC_DCHECK(handle);
|
||||
std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
|
||||
if (!debug_file->OpenFromFileHandle(handle)) {
|
||||
return nullptr;
|
||||
}
|
||||
return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
|
||||
worker_queue);
|
||||
}
|
||||
} // namespace webrtc
|
||||
80
modules/audio_processing/aec_dump/aec_dump_impl.h
Normal file
80
modules/audio_processing/aec_dump/aec_dump_impl.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_AEC_DUMP_IMPL_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_AEC_DUMP_IMPL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/capture_stream_info.h"
|
||||
#include "webrtc/modules/audio_processing/aec_dump/write_to_file_task.h"
|
||||
#include "webrtc/modules/audio_processing/include/aec_dump.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/rtc_base/ignore_wundef.h"
|
||||
#include "webrtc/rtc_base/platform_file.h"
|
||||
#include "webrtc/rtc_base/race_checker.h"
|
||||
#include "webrtc/rtc_base/task_queue.h"
|
||||
#include "webrtc/rtc_base/thread_annotations.h"
|
||||
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
||||
|
||||
// Files generated at build-time by the protobuf compiler.
|
||||
RTC_PUSH_IGNORING_WUNDEF()
|
||||
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
|
||||
#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
|
||||
#else
|
||||
#include "webrtc/modules/audio_processing/debug.pb.h"
|
||||
#endif
|
||||
RTC_POP_IGNORING_WUNDEF()
|
||||
|
||||
namespace rtc {
|
||||
class TaskQueue;
|
||||
} // namespace rtc
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Task-queue based implementation of AecDump. It is thread safe by
|
||||
// relying on locks in TaskQueue.
|
||||
class AecDumpImpl : public AecDump {
|
||||
public:
|
||||
// Does member variables initialization shared across all c-tors.
|
||||
AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue);
|
||||
|
||||
~AecDumpImpl() override;
|
||||
|
||||
void WriteInitMessage(const InternalAPMStreamsConfig& api_format) override;
|
||||
|
||||
void AddCaptureStreamInput(const FloatAudioFrame& src) override;
|
||||
void AddCaptureStreamOutput(const FloatAudioFrame& src) override;
|
||||
void AddCaptureStreamInput(const AudioFrame& frame) override;
|
||||
void AddCaptureStreamOutput(const AudioFrame& frame) override;
|
||||
void AddAudioProcessingState(const AudioProcessingState& state) override;
|
||||
void WriteCaptureStreamMessage() override;
|
||||
|
||||
void WriteRenderStreamMessage(const AudioFrame& frame) override;
|
||||
void WriteRenderStreamMessage(const FloatAudioFrame& src) override;
|
||||
|
||||
void WriteConfig(const InternalAPMConfig& config) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<WriteToFileTask> CreateWriteToFileTask();
|
||||
|
||||
std::unique_ptr<FileWrapper> debug_file_;
|
||||
int64_t num_bytes_left_for_log_ = 0;
|
||||
rtc::RaceChecker race_checker_;
|
||||
rtc::TaskQueue* worker_queue_;
|
||||
CaptureStreamInfo capture_stream_info_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_AEC_DUMP_IMPL_H_
|
||||
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/mock_aec_dump.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/rtc_base/ptr_util.h"
|
||||
|
||||
using testing::_;
|
||||
using testing::AtLeast;
|
||||
using testing::Exactly;
|
||||
using testing::Matcher;
|
||||
using testing::StrictMock;
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<webrtc::AudioProcessing> CreateAudioProcessing() {
|
||||
webrtc::Config config;
|
||||
std::unique_ptr<webrtc::AudioProcessing> apm(
|
||||
webrtc::AudioProcessing::Create(config));
|
||||
RTC_DCHECK(apm);
|
||||
return apm;
|
||||
}
|
||||
|
||||
std::unique_ptr<webrtc::test::MockAecDump> CreateMockAecDump() {
|
||||
auto mock_aec_dump =
|
||||
rtc::MakeUnique<testing::StrictMock<webrtc::test::MockAecDump>>();
|
||||
EXPECT_CALL(*mock_aec_dump.get(), WriteConfig(_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mock_aec_dump.get(), WriteInitMessage(_)).Times(AtLeast(1));
|
||||
return std::unique_ptr<webrtc::test::MockAecDump>(std::move(mock_aec_dump));
|
||||
}
|
||||
|
||||
std::unique_ptr<webrtc::AudioFrame> CreateFakeFrame() {
|
||||
auto fake_frame = rtc::MakeUnique<webrtc::AudioFrame>();
|
||||
fake_frame->num_channels_ = 1;
|
||||
fake_frame->sample_rate_hz_ = 48000;
|
||||
fake_frame->samples_per_channel_ = 480;
|
||||
return fake_frame;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(AecDumpIntegration, ConfigurationAndInitShouldBeLogged) {
|
||||
auto apm = CreateAudioProcessing();
|
||||
|
||||
apm->AttachAecDump(CreateMockAecDump());
|
||||
}
|
||||
|
||||
TEST(AecDumpIntegration,
|
||||
RenderStreamShouldBeLoggedOnceEveryProcessReverseStream) {
|
||||
auto apm = CreateAudioProcessing();
|
||||
auto mock_aec_dump = CreateMockAecDump();
|
||||
auto fake_frame = CreateFakeFrame();
|
||||
|
||||
EXPECT_CALL(*mock_aec_dump.get(),
|
||||
WriteRenderStreamMessage(Matcher<const webrtc::AudioFrame&>(_)))
|
||||
.Times(Exactly(1));
|
||||
|
||||
apm->AttachAecDump(std::move(mock_aec_dump));
|
||||
apm->ProcessReverseStream(fake_frame.get());
|
||||
}
|
||||
|
||||
TEST(AecDumpIntegration, CaptureStreamShouldBeLoggedOnceEveryProcessStream) {
|
||||
auto apm = CreateAudioProcessing();
|
||||
auto mock_aec_dump = CreateMockAecDump();
|
||||
auto fake_frame = CreateFakeFrame();
|
||||
|
||||
EXPECT_CALL(*mock_aec_dump.get(),
|
||||
AddCaptureStreamInput(Matcher<const webrtc::AudioFrame&>(_)))
|
||||
.Times(AtLeast(1));
|
||||
|
||||
EXPECT_CALL(*mock_aec_dump.get(),
|
||||
AddCaptureStreamOutput(Matcher<const webrtc::AudioFrame&>(_)))
|
||||
.Times(Exactly(1));
|
||||
|
||||
EXPECT_CALL(*mock_aec_dump.get(), AddAudioProcessingState(_))
|
||||
.Times(Exactly(1));
|
||||
|
||||
EXPECT_CALL(*mock_aec_dump.get(), WriteCaptureStreamMessage())
|
||||
.Times(Exactly(1));
|
||||
|
||||
apm->AttachAecDump(std::move(mock_aec_dump));
|
||||
apm->ProcessStream(fake_frame.get());
|
||||
}
|
||||
71
modules/audio_processing/aec_dump/aec_dump_unittest.cc
Normal file
71
modules/audio_processing/aec_dump/aec_dump_unittest.cc
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
|
||||
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/rtc_base/task_queue.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
TEST(AecDumper, APICallsDoNotCrash) {
|
||||
// Note order of initialization: Task queue has to be initialized
|
||||
// before AecDump.
|
||||
rtc::TaskQueue file_writer_queue("file_writer_queue");
|
||||
|
||||
const std::string filename =
|
||||
webrtc::test::TempFilename(webrtc::test::OutputPath(), "aec_dump");
|
||||
|
||||
{
|
||||
std::unique_ptr<webrtc::AecDump> aec_dump =
|
||||
webrtc::AecDumpFactory::Create(filename, -1, &file_writer_queue);
|
||||
|
||||
const webrtc::AudioFrame frame;
|
||||
aec_dump->WriteRenderStreamMessage(frame);
|
||||
|
||||
aec_dump->AddCaptureStreamInput(frame);
|
||||
aec_dump->AddCaptureStreamOutput(frame);
|
||||
|
||||
aec_dump->WriteCaptureStreamMessage();
|
||||
|
||||
webrtc::InternalAPMConfig apm_config;
|
||||
aec_dump->WriteConfig(apm_config);
|
||||
|
||||
webrtc::InternalAPMStreamsConfig streams_config;
|
||||
aec_dump->WriteInitMessage(streams_config);
|
||||
}
|
||||
// Remove file after the AecDump d-tor has finished.
|
||||
ASSERT_EQ(0, remove(filename.c_str()));
|
||||
}
|
||||
|
||||
TEST(AecDumper, WriteToFile) {
|
||||
rtc::TaskQueue file_writer_queue("file_writer_queue");
|
||||
|
||||
const std::string filename =
|
||||
webrtc::test::TempFilename(webrtc::test::OutputPath(), "aec_dump");
|
||||
|
||||
{
|
||||
std::unique_ptr<webrtc::AecDump> aec_dump =
|
||||
webrtc::AecDumpFactory::Create(filename, -1, &file_writer_queue);
|
||||
const webrtc::AudioFrame frame;
|
||||
aec_dump->WriteRenderStreamMessage(frame);
|
||||
}
|
||||
|
||||
// Verify the file has been written after the AecDump d-tor has
|
||||
// finished.
|
||||
FILE* fid = fopen(filename.c_str(), "r");
|
||||
ASSERT_TRUE(fid != NULL);
|
||||
|
||||
// Clean it up.
|
||||
ASSERT_EQ(0, fclose(fid));
|
||||
ASSERT_EQ(0, remove(filename.c_str()));
|
||||
}
|
||||
69
modules/audio_processing/aec_dump/capture_stream_info.cc
Normal file
69
modules/audio_processing/aec_dump/capture_stream_info.cc
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/capture_stream_info.h"
|
||||
|
||||
namespace webrtc {
|
||||
CaptureStreamInfo::CaptureStreamInfo(std::unique_ptr<WriteToFileTask> task)
|
||||
: task_(std::move(task)) {
|
||||
RTC_DCHECK(task_);
|
||||
task_->GetEvent()->set_type(audioproc::Event::STREAM);
|
||||
}
|
||||
|
||||
CaptureStreamInfo::~CaptureStreamInfo() = default;
|
||||
|
||||
void CaptureStreamInfo::AddInput(const FloatAudioFrame& src) {
|
||||
RTC_DCHECK(task_);
|
||||
auto* stream = task_->GetEvent()->mutable_stream();
|
||||
|
||||
for (size_t i = 0; i < src.num_channels(); ++i) {
|
||||
const auto& channel_view = src.channel(i);
|
||||
stream->add_input_channel(channel_view.begin(),
|
||||
sizeof(float) * channel_view.size());
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureStreamInfo::AddOutput(const FloatAudioFrame& src) {
|
||||
RTC_DCHECK(task_);
|
||||
auto* stream = task_->GetEvent()->mutable_stream();
|
||||
|
||||
for (size_t i = 0; i < src.num_channels(); ++i) {
|
||||
const auto& channel_view = src.channel(i);
|
||||
stream->add_output_channel(channel_view.begin(),
|
||||
sizeof(float) * channel_view.size());
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureStreamInfo::AddInput(const AudioFrame& frame) {
|
||||
RTC_DCHECK(task_);
|
||||
auto* stream = task_->GetEvent()->mutable_stream();
|
||||
const size_t data_size =
|
||||
sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_;
|
||||
stream->set_input_data(frame.data(), data_size);
|
||||
}
|
||||
|
||||
void CaptureStreamInfo::AddOutput(const AudioFrame& frame) {
|
||||
RTC_DCHECK(task_);
|
||||
auto* stream = task_->GetEvent()->mutable_stream();
|
||||
const size_t data_size =
|
||||
sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_;
|
||||
stream->set_output_data(frame.data(), data_size);
|
||||
}
|
||||
|
||||
void CaptureStreamInfo::AddAudioProcessingState(
|
||||
const AecDump::AudioProcessingState& state) {
|
||||
RTC_DCHECK(task_);
|
||||
auto* stream = task_->GetEvent()->mutable_stream();
|
||||
stream->set_delay(state.delay);
|
||||
stream->set_drift(state.drift);
|
||||
stream->set_level(state.level);
|
||||
stream->set_keypress(state.keypress);
|
||||
}
|
||||
} // namespace webrtc
|
||||
66
modules/audio_processing/aec_dump/capture_stream_info.h
Normal file
66
modules/audio_processing/aec_dump/capture_stream_info.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_CAPTURE_STREAM_INFO_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_CAPTURE_STREAM_INFO_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/write_to_file_task.h"
|
||||
#include "webrtc/modules/audio_processing/include/aec_dump.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/rtc_base/checks.h"
|
||||
#include "webrtc/rtc_base/ignore_wundef.h"
|
||||
#include "webrtc/rtc_base/logging.h"
|
||||
|
||||
// Files generated at build-time by the protobuf compiler.
|
||||
RTC_PUSH_IGNORING_WUNDEF()
|
||||
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
|
||||
#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
|
||||
#else
|
||||
#include "webrtc/modules/audio_processing/debug.pb.h"
|
||||
#endif
|
||||
RTC_POP_IGNORING_WUNDEF()
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CaptureStreamInfo {
|
||||
public:
|
||||
explicit CaptureStreamInfo(std::unique_ptr<WriteToFileTask> task);
|
||||
~CaptureStreamInfo();
|
||||
void AddInput(const FloatAudioFrame& src);
|
||||
void AddOutput(const FloatAudioFrame& src);
|
||||
|
||||
void AddInput(const AudioFrame& frame);
|
||||
void AddOutput(const AudioFrame& frame);
|
||||
|
||||
void AddAudioProcessingState(const AecDump::AudioProcessingState& state);
|
||||
|
||||
std::unique_ptr<WriteToFileTask> GetTask() {
|
||||
RTC_DCHECK(task_);
|
||||
return std::move(task_);
|
||||
}
|
||||
|
||||
void SetTask(std::unique_ptr<WriteToFileTask> task) {
|
||||
RTC_DCHECK(!task_);
|
||||
RTC_DCHECK(task);
|
||||
task_ = std::move(task);
|
||||
task_->GetEvent()->set_type(audioproc::Event::STREAM);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<WriteToFileTask> task_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_CAPTURE_STREAM_INFO_H_
|
||||
19
modules/audio_processing/aec_dump/mock_aec_dump.cc
Normal file
19
modules/audio_processing/aec_dump/mock_aec_dump.cc
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "webrtc/modules/audio_processing/aec_dump/mock_aec_dump.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
|
||||
MockAecDump::MockAecDump() = default;
|
||||
MockAecDump::~MockAecDump() = default;
|
||||
}
|
||||
}
|
||||
50
modules/audio_processing/aec_dump/mock_aec_dump.h
Normal file
50
modules/audio_processing/aec_dump/mock_aec_dump.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_MOCK_AEC_DUMP_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_MOCK_AEC_DUMP_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/modules/audio_processing/include/aec_dump.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace test {
|
||||
|
||||
class MockAecDump : public AecDump {
|
||||
public:
|
||||
MockAecDump();
|
||||
virtual ~MockAecDump();
|
||||
|
||||
MOCK_METHOD1(WriteInitMessage,
|
||||
void(const InternalAPMStreamsConfig& streams_config));
|
||||
|
||||
MOCK_METHOD1(AddCaptureStreamInput, void(const FloatAudioFrame& src));
|
||||
MOCK_METHOD1(AddCaptureStreamOutput, void(const FloatAudioFrame& src));
|
||||
MOCK_METHOD1(AddCaptureStreamInput, void(const AudioFrame& frame));
|
||||
MOCK_METHOD1(AddCaptureStreamOutput, void(const AudioFrame& frame));
|
||||
MOCK_METHOD1(AddAudioProcessingState,
|
||||
void(const AudioProcessingState& state));
|
||||
MOCK_METHOD0(WriteCaptureStreamMessage, void());
|
||||
|
||||
MOCK_METHOD1(WriteRenderStreamMessage, void(const AudioFrame& frame));
|
||||
MOCK_METHOD1(WriteRenderStreamMessage, void(const FloatAudioFrame& src));
|
||||
|
||||
MOCK_METHOD1(WriteConfig, void(const InternalAPMConfig& config));
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_MOCK_AEC_DUMP_H_
|
||||
33
modules/audio_processing/aec_dump/null_aec_dump_factory.cc
Normal file
33
modules/audio_processing/aec_dump/null_aec_dump_factory.cc
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
|
||||
#include "webrtc/modules/audio_processing/include/aec_dump.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
std::unique_ptr<AecDump> AecDumpFactory::Create(rtc::PlatformFile file,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AecDump> AecDumpFactory::Create(FILE* handle,
|
||||
int64_t max_log_size_bytes,
|
||||
rtc::TaskQueue* worker_queue) {
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace webrtc
|
||||
68
modules/audio_processing/aec_dump/write_to_file_task.cc
Normal file
68
modules/audio_processing/aec_dump/write_to_file_task.cc
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_processing/aec_dump/write_to_file_task.h"
|
||||
|
||||
#include "webrtc/rtc_base/protobuf_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
WriteToFileTask::WriteToFileTask(webrtc::FileWrapper* debug_file,
|
||||
int64_t* num_bytes_left_for_log)
|
||||
: debug_file_(debug_file),
|
||||
num_bytes_left_for_log_(num_bytes_left_for_log) {}
|
||||
|
||||
WriteToFileTask::~WriteToFileTask() = default;
|
||||
|
||||
audioproc::Event* WriteToFileTask::GetEvent() {
|
||||
return &event_;
|
||||
}
|
||||
|
||||
bool WriteToFileTask::IsRoomForNextEvent(size_t event_byte_size) const {
|
||||
int64_t next_message_size = event_byte_size + sizeof(int32_t);
|
||||
return (*num_bytes_left_for_log_ < 0) ||
|
||||
(*num_bytes_left_for_log_ >= next_message_size);
|
||||
}
|
||||
|
||||
void WriteToFileTask::UpdateBytesLeft(size_t event_byte_size) {
|
||||
RTC_DCHECK(IsRoomForNextEvent(event_byte_size));
|
||||
if (*num_bytes_left_for_log_ >= 0) {
|
||||
*num_bytes_left_for_log_ -= (sizeof(int32_t) + event_byte_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool WriteToFileTask::Run() {
|
||||
if (!debug_file_->is_open()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ProtoString event_string;
|
||||
event_.SerializeToString(&event_string);
|
||||
|
||||
const size_t event_byte_size = event_.ByteSize();
|
||||
|
||||
if (!IsRoomForNextEvent(event_byte_size)) {
|
||||
debug_file_->CloseFile();
|
||||
return true;
|
||||
}
|
||||
|
||||
UpdateBytesLeft(event_byte_size);
|
||||
|
||||
// Write message preceded by its size.
|
||||
if (!debug_file_->Write(&event_byte_size, sizeof(int32_t))) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
if (!debug_file_->Write(event_string.data(), event_string.length())) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
return true; // Delete task from queue at once.
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
58
modules/audio_processing/aec_dump/write_to_file_task.h
Normal file
58
modules/audio_processing/aec_dump/write_to_file_task.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_WRITE_TO_FILE_TASK_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_WRITE_TO_FILE_TASK_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/rtc_base/checks.h"
|
||||
#include "webrtc/rtc_base/event.h"
|
||||
#include "webrtc/rtc_base/ignore_wundef.h"
|
||||
#include "webrtc/rtc_base/platform_file.h"
|
||||
#include "webrtc/rtc_base/task_queue.h"
|
||||
#include "webrtc/system_wrappers/include/file_wrapper.h"
|
||||
|
||||
// Files generated at build-time by the protobuf compiler.
|
||||
RTC_PUSH_IGNORING_WUNDEF()
|
||||
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
|
||||
#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
|
||||
#else
|
||||
#include "webrtc/modules/audio_processing/debug.pb.h"
|
||||
#endif
|
||||
RTC_POP_IGNORING_WUNDEF()
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class WriteToFileTask : public rtc::QueuedTask {
|
||||
public:
|
||||
WriteToFileTask(webrtc::FileWrapper* debug_file,
|
||||
int64_t* num_bytes_left_for_log);
|
||||
~WriteToFileTask() override;
|
||||
|
||||
audioproc::Event* GetEvent();
|
||||
|
||||
private:
|
||||
bool IsRoomForNextEvent(size_t event_byte_size) const;
|
||||
|
||||
void UpdateBytesLeft(size_t event_byte_size);
|
||||
|
||||
bool Run() override;
|
||||
|
||||
webrtc::FileWrapper* debug_file_;
|
||||
audioproc::Event event_;
|
||||
int64_t* num_bytes_left_for_log_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_WRITE_TO_FILE_TASK_H_
|
||||
Reference in New Issue
Block a user