Add an unpacker tool for audioproc debug files.
- It only unpacks audio data at the moment. - Also switch to Chrome's protoc.gypi for protobuf targets. This reduces the complexity of our targets. Review URL: http://webrtc-codereview.appspot.com/241009 git-svn-id: http://webrtc.googlecode.com/svn/trunk@817 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
fc9bcef8c7
commit
cb18121990
97
src/build/protoc.gypi
Normal file
97
src/build/protoc.gypi
Normal file
@ -0,0 +1,97 @@
|
||||
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# It was necessary to copy this file to WebRTC, because the path to
|
||||
# build/common.gypi is different for the standalone and Chromium builds. Gyp
|
||||
# doesn't permit conditional inclusion or variable expansion in include paths.
|
||||
# http://code.google.com/p/gyp/wiki/InputFormatReference#Including_Other_Files
|
||||
|
||||
# This file is meant to be included into a target to provide a rule
|
||||
# to invoke protoc in a consistent manner.
|
||||
#
|
||||
# To use this, create a gyp target with the following form:
|
||||
# {
|
||||
# 'target_name': 'my_proto_lib',
|
||||
# 'type': 'static_library',
|
||||
# 'sources': [
|
||||
# 'foo.proto',
|
||||
# 'bar.proto',
|
||||
# ],
|
||||
# 'variables': {
|
||||
# # Optional, see below: 'proto_in_dir': '.'
|
||||
# 'proto_out_dir': 'dir/for/my_proto_lib'
|
||||
# },
|
||||
# 'includes': ['path/to/this/gypi/file'],
|
||||
# }
|
||||
# If necessary, you may add normal .cc files to the sources list or other gyp
|
||||
# dependencies. The proto headers are guaranteed to be generated before any
|
||||
# source files, even within this target, are compiled.
|
||||
#
|
||||
# The 'proto_in_dir' variable must be the relative path to the
|
||||
# directory containing the .proto files. If left out, it defaults to '.'.
|
||||
#
|
||||
# The 'proto_out_dir' variable specifies the path suffix that output
|
||||
# files are generated under. Targets that gyp-depend on my_proto_lib
|
||||
# will be able to include the resulting proto headers with an include
|
||||
# like:
|
||||
# #include "dir/for/my_proto_lib/foo.pb.h"
|
||||
#
|
||||
# Implementation notes:
|
||||
# A proto_out_dir of foo/bar produces
|
||||
# <(SHARED_INTERMEDIATE_DIR)/protoc_out/foo/bar/{file1,file2}.pb.{cc,h}
|
||||
# <(SHARED_INTERMEDIATE_DIR)/pyproto/foo/bar/{file1,file2}_pb2.py
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'protoc': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
|
||||
'cc_dir': '<(SHARED_INTERMEDIATE_DIR)/protoc_out/<(proto_out_dir)',
|
||||
'py_dir': '<(PRODUCT_DIR)/pyproto/<(proto_out_dir)',
|
||||
'proto_in_dir%': '.',
|
||||
},
|
||||
'rules': [
|
||||
{
|
||||
'rule_name': 'genproto',
|
||||
'extension': 'proto',
|
||||
'inputs': [
|
||||
'<(protoc)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(py_dir)/<(RULE_INPUT_ROOT)_pb2.py',
|
||||
'<(cc_dir)/<(RULE_INPUT_ROOT).pb.cc',
|
||||
'<(cc_dir)/<(RULE_INPUT_ROOT).pb.h',
|
||||
],
|
||||
'action': [
|
||||
'<(protoc)',
|
||||
'--proto_path=<(proto_in_dir)',
|
||||
# Naively you'd use <(RULE_INPUT_PATH) here, but protoc requires
|
||||
# --proto_path is a strict prefix of the path given as an argument.
|
||||
'<(proto_in_dir)/<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)',
|
||||
'--cpp_out=<(cc_dir)',
|
||||
'--python_out=<(py_dir)',
|
||||
],
|
||||
'message': 'Generating C++ and Python code from <(RULE_INPUT_PATH)',
|
||||
'process_outputs_as_sources': 1,
|
||||
},
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/third_party/protobuf/protobuf.gyp:protoc#host',
|
||||
'<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite',
|
||||
],
|
||||
'include_dirs': [
|
||||
'<(SHARED_INTERMEDIATE_DIR)/protoc_out',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'<(SHARED_INTERMEDIATE_DIR)/protoc_out',
|
||||
]
|
||||
},
|
||||
'export_dependent_settings': [
|
||||
# The generated headers reference headers within protobuf_lite,
|
||||
# so dependencies must be able to find those headers too.
|
||||
'<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite',
|
||||
],
|
||||
# This target exports a hard dependency because it generates header
|
||||
# files.
|
||||
'hard_dependency': 1,
|
||||
}
|
||||
@ -7,94 +7,59 @@
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'protoc_out_dir': '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
|
||||
'protoc_out_relpath': 'webrtc/audio_processing',
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'audioproc_unittest',
|
||||
'type': 'executable',
|
||||
'conditions': [
|
||||
['prefer_fixed_point==1', {
|
||||
'defines': ['WEBRTC_APM_UNIT_TEST_FIXED_PROFILE'],
|
||||
'defines': [ 'WEBRTC_APM_UNIT_TEST_FIXED_PROFILE' ],
|
||||
}, {
|
||||
'defines': ['WEBRTC_APM_UNIT_TEST_FLOAT_PROFILE'],
|
||||
'defines': [ 'WEBRTC_APM_UNIT_TEST_FLOAT_PROFILE' ],
|
||||
}],
|
||||
],
|
||||
'dependencies': [
|
||||
'audioproc_unittest_proto',
|
||||
'audio_processing',
|
||||
'audioproc_unittest_proto',
|
||||
'<(webrtc_root)/common_audio/common_audio.gyp:spl',
|
||||
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
|
||||
'<(webrtc_root)/../test/test.gyp:test_support',
|
||||
'<(webrtc_root)/../testing/gtest.gyp:gtest',
|
||||
'<(webrtc_root)/../third_party/protobuf/protobuf.gyp:protobuf_lite',
|
||||
],
|
||||
'include_dirs': [
|
||||
'<(webrtc_root)/../testing/gtest/include',
|
||||
'<(protoc_out_dir)',
|
||||
],
|
||||
'sources': [
|
||||
'test/unit_test.cc',
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/unittest.pb.cc',
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/unittest.pb.h',
|
||||
],
|
||||
'sources': [ 'test/unit_test.cc', ],
|
||||
},
|
||||
{
|
||||
# Protobuf compiler / generate rule for audioproc_unittest
|
||||
'target_name': 'audioproc_unittest_proto',
|
||||
'type': 'none',
|
||||
'type': 'static_library',
|
||||
'sources': [ 'test/unittest.proto', ],
|
||||
'variables': {
|
||||
'proto_relpath':
|
||||
'<(webrtc_root)/modules/audio_processing/test',
|
||||
'proto_in_dir': 'test',
|
||||
# Workaround to protect against gyp's pathname relativization when this
|
||||
# file is included by modules.gyp.
|
||||
'proto_out_protected': 'webrtc/audio_processing',
|
||||
'proto_out_dir': '<(proto_out_protected)',
|
||||
},
|
||||
'sources': [
|
||||
'<(proto_relpath)/unittest.proto',
|
||||
],
|
||||
'rules': [
|
||||
{
|
||||
'rule_name': 'genproto',
|
||||
'extension': 'proto',
|
||||
'inputs': [
|
||||
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/<(RULE_INPUT_ROOT).pb.cc',
|
||||
'<(protoc_out_dir)/<(RULE_INPUT_ROOT).pb.h',
|
||||
],
|
||||
'action': [
|
||||
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
|
||||
'--proto_path=<(proto_relpath)',
|
||||
'<(proto_relpath)/<(RULE_INPUT_NAME)',
|
||||
'--cpp_out=<(protoc_out_dir)/<(protoc_out_relpath)',
|
||||
],
|
||||
'message': 'Generating C++ code from <(RULE_INPUT_PATH)',
|
||||
},
|
||||
],
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/../third_party/protobuf/protobuf.gyp:protoc#host',
|
||||
],
|
||||
# This target exports a hard dependency because it generates header
|
||||
# files.
|
||||
'hard_dependency': 1,
|
||||
'includes': [ '../../../build/protoc.gypi', ],
|
||||
},
|
||||
{
|
||||
'target_name': 'audioproc_process_test',
|
||||
'target_name': 'audioproc',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'audio_processing',
|
||||
'audioproc_debug_proto',
|
||||
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
|
||||
'<(webrtc_root)/../testing/gtest.gyp:gtest',
|
||||
'<(webrtc_root)/../third_party/protobuf/protobuf.gyp:protobuf_lite',
|
||||
],
|
||||
'include_dirs': [
|
||||
'<(webrtc_root)/../testing/gtest/include',
|
||||
'<(protoc_out_dir)',
|
||||
],
|
||||
'sources': [
|
||||
'test/process_test.cc',
|
||||
'sources': [ 'test/process_test.cc', ],
|
||||
},
|
||||
{
|
||||
'target_name': 'unpack',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'audioproc_debug_proto',
|
||||
'<(webrtc_root)/../third_party/google-gflags/google-gflags.gyp:google-gflags',
|
||||
],
|
||||
'sources': [ 'test/unpack.cc', ],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@ -7,34 +7,21 @@
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'protoc_out_dir': '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
|
||||
'protoc_out_relpath': 'webrtc/audio_processing',
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'audio_processing',
|
||||
'type': '<(library)',
|
||||
'conditions': [
|
||||
['prefer_fixed_point==1', {
|
||||
'dependencies': ['ns_fix'],
|
||||
'defines': ['WEBRTC_NS_FIXED'],
|
||||
'dependencies': [ 'ns_fix' ],
|
||||
'defines': [ 'WEBRTC_NS_FIXED' ],
|
||||
}, {
|
||||
'dependencies': ['ns'],
|
||||
'defines': ['WEBRTC_NS_FLOAT'],
|
||||
}],
|
||||
['build_with_chromium==1', {
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/../protobuf/protobuf.gyp:protobuf_lite',
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/../third_party/protobuf/protobuf.gyp:protobuf_lite',
|
||||
],
|
||||
'dependencies': [ 'ns' ],
|
||||
'defines': [ 'WEBRTC_NS_FLOAT' ],
|
||||
}],
|
||||
],
|
||||
'dependencies': [
|
||||
'debug_proto',
|
||||
'audioproc_debug_proto',
|
||||
'aec',
|
||||
'aecm',
|
||||
'agc',
|
||||
@ -45,7 +32,6 @@
|
||||
'include_dirs': [
|
||||
'interface',
|
||||
'../interface',
|
||||
'<(protoc_out_dir)',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
@ -77,54 +63,20 @@
|
||||
'processing_component.h',
|
||||
'voice_detection_impl.cc',
|
||||
'voice_detection_impl.h',
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/debug.pb.cc',
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/debug.pb.h',
|
||||
],
|
||||
},
|
||||
{
|
||||
# Protobuf compiler / generate rule for audio_processing
|
||||
'target_name': 'debug_proto',
|
||||
'type': 'none',
|
||||
'target_name': 'audioproc_debug_proto',
|
||||
'type': 'static_library',
|
||||
'sources': [ 'debug.proto', ],
|
||||
'variables': {
|
||||
'proto_relpath': '<(webrtc_root)/modules/audio_processing',
|
||||
'proto_in_dir': '.',
|
||||
# Workaround to protect against gyp's pathname relativization when this
|
||||
# file is included by modules.gyp.
|
||||
'proto_out_protected': 'webrtc/audio_processing',
|
||||
'proto_out_dir': '<(proto_out_protected)',
|
||||
},
|
||||
'sources': [
|
||||
'<(proto_relpath)/debug.proto',
|
||||
],
|
||||
'rules': [
|
||||
{
|
||||
'rule_name': 'genproto',
|
||||
'extension': 'proto',
|
||||
'inputs': [
|
||||
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
|
||||
],
|
||||
'outputs': [
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/<(RULE_INPUT_ROOT).pb.cc',
|
||||
'<(protoc_out_dir)/<(protoc_out_relpath)/<(RULE_INPUT_ROOT).pb.h',
|
||||
],
|
||||
'action': [
|
||||
'<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
|
||||
'--proto_path=<(proto_relpath)',
|
||||
'<(proto_relpath)/<(RULE_INPUT_NAME)',
|
||||
'--cpp_out=<(protoc_out_dir)/<(protoc_out_relpath)',
|
||||
],
|
||||
'message': 'Generating C++ code from <(RULE_INPUT_PATH)',
|
||||
},
|
||||
],
|
||||
'conditions': [
|
||||
['build_with_chromium==1', {
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/../protobuf/protobuf.gyp:protoc#host',
|
||||
],
|
||||
}, {
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/../third_party/protobuf/protobuf.gyp:protoc#host',
|
||||
],
|
||||
}],
|
||||
],
|
||||
# This target exports a hard dependency because it generates header
|
||||
# files.
|
||||
'hard_dependency': 1,
|
||||
'includes': [ '../../../build/protoc.gypi', ],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ bool ReadMessageFromFile(FILE* file,
|
||||
::google::protobuf::MessageLite* msg) {
|
||||
// The "wire format" for the size is little-endian.
|
||||
// Assume process_test is running on a little-endian machine.
|
||||
int32_t size;
|
||||
int32_t size = 0;
|
||||
if (fread(&size, sizeof(int32_t), 1, file) != 1) {
|
||||
return false;
|
||||
}
|
||||
@ -116,11 +116,12 @@ void usage() {
|
||||
printf(" --vad_out_file FILE\n");
|
||||
printf("\n");
|
||||
printf("Modifiers:\n");
|
||||
printf(" --noasm Disable SSE optimization.\n");
|
||||
printf(" --perf Measure performance.\n");
|
||||
printf(" --quiet Suppress text output.\n");
|
||||
printf(" --no_progress Suppress progress.\n");
|
||||
printf(" --version Print version information and exit.\n");
|
||||
printf(" --noasm Disable SSE optimization.\n");
|
||||
printf(" --perf Measure performance.\n");
|
||||
printf(" --quiet Suppress text output.\n");
|
||||
printf(" --no_progress Suppress progress.\n");
|
||||
printf(" --debug_file FILE Dump a debug recording.\n");
|
||||
printf(" --version Print version information and exit.\n");
|
||||
}
|
||||
|
||||
// void function for gtest.
|
||||
@ -359,9 +360,9 @@ void void_main(int argc, char* argv[]) {
|
||||
printf("%s\n", version);
|
||||
return;
|
||||
|
||||
} else if (strcmp(argv[i], "--debug_recording") == 0) {
|
||||
} else if (strcmp(argv[i], "--debug_file") == 0) {
|
||||
i++;
|
||||
ASSERT_LT(i, argc) << "Specify filename after --debug_recording";
|
||||
ASSERT_LT(i, argc) << "Specify filename after --debug_file";
|
||||
ASSERT_EQ(apm->kNoError, apm->StartDebugRecording(argv[i]));
|
||||
} else {
|
||||
FAIL() << "Unrecognized argument " << argv[i];
|
||||
|
||||
118
src/modules/audio_processing/test/unpack.cc
Normal file
118
src/modules/audio_processing/test/unpack.cc
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2011 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.
|
||||
*/
|
||||
|
||||
// Commandline tool to unpack audioproc debug files.
|
||||
//
|
||||
// The debug files are dumped as protobuf blobs. For analysis, it's necessary
|
||||
// to unpack the file into its component parts: audio and other data.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "google/gflags.h"
|
||||
#include "webrtc/audio_processing/debug.pb.h"
|
||||
|
||||
using webrtc::audioproc::Event;
|
||||
using webrtc::audioproc::ReverseStream;
|
||||
using webrtc::audioproc::Stream;
|
||||
|
||||
// TODO(andrew): unpack more of the data.
|
||||
DEFINE_string(input_file, "input.pcm", "The name of the input stream file.");
|
||||
DEFINE_string(output_file, "output.pcm", "The name of the output stream file.");
|
||||
DEFINE_string(reverse_file, "reverse.pcm", "The name of the reverse input "
|
||||
"file.");
|
||||
|
||||
// TODO(andrew): move this to a helper class to share with process_test.cc?
|
||||
// Returns true on success, false on error or end-of-file.
|
||||
bool ReadMessageFromFile(FILE* file,
|
||||
::google::protobuf::MessageLite* msg) {
|
||||
// The "wire format" for the size is little-endian.
|
||||
// Assume process_test is running on a little-endian machine.
|
||||
int32_t size = 0;
|
||||
if (fread(&size, sizeof(int32_t), 1, file) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (size <= 0) {
|
||||
return false;
|
||||
}
|
||||
size_t usize = static_cast<size_t>(size);
|
||||
|
||||
char array[usize];
|
||||
if (fread(array, sizeof(char), usize, file) != usize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
msg->Clear();
|
||||
return msg->ParseFromArray(array, usize);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string program_name = argv[0];
|
||||
std::string usage = "Commandline tool to unpack audioproc debug files.\n"
|
||||
"Example usage:\n" + program_name + " debug_dump.pb\n";
|
||||
google::SetUsageMessage(usage);
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
if (argc < 2) {
|
||||
printf("%s", google::ProgramUsage());
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE* debug_file = fopen(argv[1], "rb");
|
||||
FILE* input_file = fopen(FLAGS_input_file.c_str(), "wb");
|
||||
FILE* output_file = fopen(FLAGS_output_file.c_str(), "wb");
|
||||
FILE* reverse_file = fopen(FLAGS_reverse_file.c_str(), "wb");
|
||||
Event event_msg;
|
||||
while (ReadMessageFromFile(debug_file, &event_msg)) {
|
||||
if (event_msg.type() == Event::REVERSE_STREAM) {
|
||||
if (!event_msg.has_reverse_stream()) {
|
||||
printf("Corrupted input file: ReverseStream missing.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const ReverseStream msg = event_msg.reverse_stream();
|
||||
if (!msg.has_data()) {
|
||||
printf("Corrupted input file: ReverseStream::data missing.\n");
|
||||
return 1;
|
||||
}
|
||||
if (fwrite(msg.data().data(), msg.data().size(), 1, reverse_file) != 1) {
|
||||
printf("Error when writing to %s\n", FLAGS_reverse_file.c_str());
|
||||
return 1;
|
||||
}
|
||||
} else if (event_msg.type() == Event::STREAM) {
|
||||
if (!event_msg.has_stream()) {
|
||||
printf("Corrupted input file: Stream missing.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Stream msg = event_msg.stream();
|
||||
if (!msg.has_input_data()) {
|
||||
printf("Corrupted input file: Stream::input_data missing.\n");
|
||||
return 1;
|
||||
}
|
||||
if (fwrite(msg.input_data().data(), msg.input_data().size(), 1,
|
||||
input_file) != 1) {
|
||||
printf("Error when writing to %s\n", FLAGS_input_file.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!msg.has_output_data()) {
|
||||
printf("Corrupted input file: Stream::output_data missing.\n");
|
||||
return 1;
|
||||
}
|
||||
if (fwrite(msg.output_data().data(), msg.output_data().size(), 1,
|
||||
output_file) != 1) {
|
||||
printf("Error when writing to %s\n", FLAGS_output_file.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user