diff --git a/webrtc/modules/audio_processing/BUILD.gn b/webrtc/modules/audio_processing/BUILD.gn index 86df81da5c..b5209ca458 100644 --- a/webrtc/modules/audio_processing/BUILD.gn +++ b/webrtc/modules/audio_processing/BUILD.gn @@ -494,6 +494,7 @@ if (rtc_include_tests) { ":audioproc_f", ":audioproc_unittest_proto", ":unpack_aecdump", + "aec_dump:aec_dump_unittests", "test/conversational_speech", "test/py_quality_assessment", ] diff --git a/webrtc/modules/audio_processing/aec_dump/BUILD.gn b/webrtc/modules/audio_processing/aec_dump/BUILD.gn new file mode 100644 index 0000000000..4a02299eaa --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/BUILD.gn @@ -0,0 +1,74 @@ +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 = [ + "../../../base:rtc_base_approved", + ] +} + +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 = [ + "../../../base:protobuf_utils", + "../../../base:rtc_base_approved", + "../../../base:rtc_task_queue", + "../../../modules:module_api", + "../../../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", + "../../../base:rtc_task_queue", + "../../../modules:module_api", + "../../../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", + ] +} diff --git a/webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h b/webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h new file mode 100644 index 0000000000..98596a4568 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h @@ -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 +#include + +#include "webrtc/base/platform_file.h" +#include "webrtc/modules/audio_processing/include/aec_dump.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 Create(rtc::PlatformFile file, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue); + static std::unique_ptr Create(std::string file_name, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue); + static std::unique_ptr 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_ diff --git a/webrtc/modules/audio_processing/aec_dump/aec_dump_impl.cc b/webrtc/modules/audio_processing/aec_dump/aec_dump_impl.cc new file mode 100644 index 0000000000..256c191539 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/aec_dump_impl.cc @@ -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 + +#include "webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/event.h" +#include "webrtc/base/ptr_util.h" +#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.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 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(streams_config.input_num_channels)); + msg->set_num_output_channels( + static_cast(streams_config.output_num_channels)); + msg->set_num_reverse_channels( + static_cast(streams_config.render_input_num_channels)); + msg->set_num_reverse_output_channels( + streams_config.render_output_num_channels); + + worker_queue_->PostTask(std::unique_ptr(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(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(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(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(std::move(task))); +} + +std::unique_ptr AecDumpImpl::CreateWriteToFileTask() { + return rtc::MakeUnique(debug_file_.get(), + &num_bytes_left_for_log_); +} + +std::unique_ptr AecDumpFactory::Create(rtc::PlatformFile file, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue) { + RTC_DCHECK(worker_queue); + std::unique_ptr debug_file(FileWrapper::Create()); + FILE* handle = rtc::FdopenPlatformFileForWriting(file); + if (!handle) { + return nullptr; + } + if (!debug_file->OpenFromFileHandle(handle)) { + return nullptr; + } + return rtc::MakeUnique(std::move(debug_file), max_log_size_bytes, + worker_queue); +} + +std::unique_ptr AecDumpFactory::Create(std::string file_name, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue) { + RTC_DCHECK(worker_queue); + std::unique_ptr debug_file(FileWrapper::Create()); + if (!debug_file->OpenFile(file_name.c_str(), false)) { + return nullptr; + } + return rtc::MakeUnique(std::move(debug_file), max_log_size_bytes, + worker_queue); +} + +std::unique_ptr AecDumpFactory::Create(FILE* handle, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue) { + RTC_DCHECK(worker_queue); + RTC_DCHECK(handle); + std::unique_ptr debug_file(FileWrapper::Create()); + if (!debug_file->OpenFromFileHandle(handle)) { + return nullptr; + } + return rtc::MakeUnique(std::move(debug_file), max_log_size_bytes, + worker_queue); +} +} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h b/webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h new file mode 100644 index 0000000000..d9da14b979 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h @@ -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 +#include +#include + +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/base/platform_file.h" +#include "webrtc/base/race_checker.h" +#include "webrtc/base/task_queue.h" +#include "webrtc/base/thread_annotations.h" +#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/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 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 CreateWriteToFileTask(); + + std::unique_ptr 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_ diff --git a/webrtc/modules/audio_processing/aec_dump/aec_dump_unittest.cc b/webrtc/modules/audio_processing/aec_dump/aec_dump_unittest.cc new file mode 100644 index 0000000000..3061c23246 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/aec_dump_unittest.cc @@ -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 + +#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h" + +#include "webrtc/base/task_queue.h" +#include "webrtc/modules/include/module_common_types.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 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 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())); +} diff --git a/webrtc/modules/audio_processing/aec_dump/capture_stream_info.cc b/webrtc/modules/audio_processing/aec_dump/capture_stream_info.cc new file mode 100644 index 0000000000..2d7affcf4d --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/capture_stream_info.cc @@ -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 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 diff --git a/webrtc/modules/audio_processing/aec_dump/capture_stream_info.h b/webrtc/modules/audio_processing/aec_dump/capture_stream_info.h new file mode 100644 index 0000000000..36b860cea4 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/capture_stream_info.h @@ -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 +#include +#include + +#include "webrtc/base/checks.h" +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/base/logging.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" + +// 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 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 GetTask() { + RTC_DCHECK(task_); + return std::move(task_); + } + + void SetTask(std::unique_ptr task) { + RTC_DCHECK(!task_); + RTC_DCHECK(task); + task_ = std::move(task); + task_->GetEvent()->set_type(audioproc::Event::STREAM); + } + + private: + std::unique_ptr task_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_DUMP_CAPTURE_STREAM_INFO_H_ diff --git a/webrtc/modules/audio_processing/aec_dump/null_aec_dump_factory.cc b/webrtc/modules/audio_processing/aec_dump/null_aec_dump_factory.cc new file mode 100644 index 0000000000..7da3d5a53b --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/null_aec_dump_factory.cc @@ -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 AecDumpFactory::Create(rtc::PlatformFile file, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue) { + return nullptr; +} + +std::unique_ptr AecDumpFactory::Create(std::string file_name, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue) { + return nullptr; +} + +std::unique_ptr AecDumpFactory::Create(FILE* handle, + int64_t max_log_size_bytes, + rtc::TaskQueue* worker_queue) { + return nullptr; +} +} // namespace webrtc diff --git a/webrtc/modules/audio_processing/aec_dump/write_to_file_task.cc b/webrtc/modules/audio_processing/aec_dump/write_to_file_task.cc new file mode 100644 index 0000000000..f9aa567a84 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/write_to_file_task.cc @@ -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/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 diff --git a/webrtc/modules/audio_processing/aec_dump/write_to_file_task.h b/webrtc/modules/audio_processing/aec_dump/write_to_file_task.h new file mode 100644 index 0000000000..717f645c23 --- /dev/null +++ b/webrtc/modules/audio_processing/aec_dump/write_to_file_task.h @@ -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 +#include +#include + +#include "webrtc/base/checks.h" +#include "webrtc/base/event.h" +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/base/platform_file.h" +#include "webrtc/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_