AecDump implementation.

This CL implements webrtc::AecDump, which is an interface defined in
https://codereview.webrtc.org/2778783002.

This AudioProcessing submodule writes audio and APM state to a
file. The file writing is done by posting IO tasks
(write_to_file_task.h) on an rtc::TaskQueue. There is an existing
implementation for this through AudioProcessing::StartDebugRecording()
and AudioProcessing::StopDebugRecording(). This implementation still
works, and is used as the default until this dependent CL:
https://codereview.webrtc.org/2896813002/.

To be able to build webrtc without protobuf support, the interface is
isolated from protobuf types. Audio data from AudioProcessing is
passed to AecDumpImpl through the AecDump interface. There it is
stored in protobuf objects, which are posted on the task queue.

This functionality is verified correct by the CL
https://codereview.webrtc.org/2864373002, which enables this recording
submodule in APM tests.

BUG=webrtc:7404

Review-Url: https://codereview.webrtc.org/2865113002
Cr-Commit-Position: refs/heads/master@{#18241}
This commit is contained in:
aleloi 2017-05-23 08:52:05 -07:00 committed by Commit bot
parent f27c5b8d6e
commit 06013e99ac
11 changed files with 775 additions and 0 deletions

View File

@ -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",
]

View File

@ -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",
]
}

View 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/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<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_

View 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/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<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

View 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/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<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_

View 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/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<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()));
}

View 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

View 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/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<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_

View 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

View 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/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

View 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/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_