summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Chromium Automerger <chromium-automerger@android>2014-08-22 20:51:43 +0000
committerAndroid Chromium Automerger <chromium-automerger@android>2014-08-22 20:51:43 +0000
commit53e892fb0348c6a70a9062c90679bfc66d9ae7c0 (patch)
treef5a65e878b7700cfec06f4757ffedaa5d2e331a9
parent430518e6143a3019568ded58407cb72f805f532c (diff)
parentf854f30d7981795f687f9b4379100c037934535d (diff)
downloadwebrtc-53e892fb0348c6a70a9062c90679bfc66d9ae7c0.tar.gz
Merge third_party/webrtc from https://chromium.googlesource.com/external/webrtc/trunk/webrtc.git at f854f30d7981795f687f9b4379100c037934535d
This commit was generated by merge_from_chromium.py. Change-Id: Ic25930ad2a0758a4b68350bbc1368924011f37d1
-rw-r--r--base/latebindingsymboltable.cc2
-rw-r--r--modules/audio_coding/main/acm2/acm_send_test.cc139
-rw-r--r--modules/audio_coding/main/acm2/acm_send_test.h85
-rw-r--r--modules/audio_coding/main/acm2/audio_coding_module.gypi13
-rw-r--r--modules/audio_coding/main/acm2/audio_coding_module_unittest.cc213
-rw-r--r--modules/modules.gyp1
6 files changed, 440 insertions, 13 deletions
diff --git a/base/latebindingsymboltable.cc b/base/latebindingsymboltable.cc
index 1896bd0f..030f7208 100644
--- a/base/latebindingsymboltable.cc
+++ b/base/latebindingsymboltable.cc
@@ -100,7 +100,7 @@ bool LateBindingSymbolTable::LoadFromPath(const char *dll_path) {
// is necessary for same-named symbols in different ABI
// versions of the same library to not explode.
RTLD_NOW|RTLD_LOCAL
-#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
+#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && defined(RTLD_DEEPBIND)
// RTLD_DEEPBIND makes symbol dependencies in the
// newly-loaded tree prefer to resolve to definitions within
// that tree (the default on OS X). This is necessary for
diff --git a/modules/audio_coding/main/acm2/acm_send_test.cc b/modules/audio_coding/main/acm2/acm_send_test.cc
new file mode 100644
index 00000000..67cc9b2b
--- /dev/null
+++ b/modules/audio_coding/main/acm2/acm_send_test.cc
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014 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_coding/main/acm2/acm_send_test.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/checks.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
+#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
+#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
+
+namespace webrtc {
+namespace test {
+
+AcmSendTest::AcmSendTest(InputAudioFile* audio_source,
+ int source_rate_hz,
+ int test_duration_ms)
+ : clock_(0),
+ acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
+ audio_source_(audio_source),
+ source_rate_hz_(source_rate_hz),
+ input_block_size_samples_(source_rate_hz_ * kBlockSizeMs / 1000),
+ codec_registered_(false),
+ test_duration_ms_(test_duration_ms),
+ frame_type_(kAudioFrameSpeech),
+ payload_type_(0),
+ timestamp_(0),
+ sequence_number_(0) {
+ input_frame_.sample_rate_hz_ = source_rate_hz_;
+ input_frame_.num_channels_ = 1;
+ input_frame_.samples_per_channel_ = input_block_size_samples_;
+ assert(input_block_size_samples_ * input_frame_.num_channels_ <=
+ AudioFrame::kMaxDataSizeSamples);
+ acm_->RegisterTransportCallback(this);
+}
+
+bool AcmSendTest::RegisterCodec(const char* payload_name,
+ int sampling_freq_hz,
+ int channels,
+ int payload_type,
+ int frame_size_samples) {
+ FATAL_ERROR_IF(AudioCodingModule::Codec(
+ payload_name, &codec_, sampling_freq_hz, channels) != 0);
+ codec_.pltype = payload_type;
+ codec_.pacsize = frame_size_samples;
+ codec_registered_ = (acm_->RegisterSendCodec(codec_) == 0);
+ assert(channels == 1); // TODO(henrik.lundin) Add multi-channel support.
+ input_frame_.num_channels_ = channels;
+ assert(input_block_size_samples_ * input_frame_.num_channels_ <=
+ AudioFrame::kMaxDataSizeSamples);
+ return codec_registered_;
+}
+
+Packet* AcmSendTest::NextPacket() {
+ assert(codec_registered_);
+ if (filter_.test(payload_type_)) {
+ // This payload type should be filtered out. Since the payload type is the
+ // same throughout the whole test run, no packet at all will be delivered.
+ // We can just as well signal that the test is over by returning NULL.
+ return NULL;
+ }
+ // Insert audio and process until one packet is produced.
+ while (clock_.TimeInMilliseconds() < test_duration_ms_) {
+ clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
+ FATAL_ERROR_IF(
+ !audio_source_->Read(input_block_size_samples_, input_frame_.data_));
+ FATAL_ERROR_IF(acm_->Add10MsData(input_frame_) != 0);
+ input_frame_.timestamp_ += input_block_size_samples_;
+ int32_t encoded_bytes = acm_->Process();
+ if (encoded_bytes > 0) {
+ // Encoded packet received.
+ return CreatePacket();
+ }
+ }
+ // Test ended.
+ return NULL;
+}
+
+// This method receives the callback from ACM when a new packet is produced.
+int32_t AcmSendTest::SendData(FrameType frame_type,
+ uint8_t payload_type,
+ uint32_t timestamp,
+ const uint8_t* payload_data,
+ uint16_t payload_len_bytes,
+ const RTPFragmentationHeader* fragmentation) {
+ // Store the packet locally.
+ frame_type_ = frame_type;
+ payload_type_ = payload_type;
+ timestamp_ = timestamp;
+ last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
+ assert(last_payload_vec_.size() == payload_len_bytes);
+ return 0;
+}
+
+Packet* AcmSendTest::CreatePacket() {
+ const size_t kRtpHeaderSize = 12;
+ size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
+ uint8_t* packet_memory = new uint8_t[allocated_bytes];
+ // Populate the header bytes.
+ packet_memory[0] = 0x80;
+ packet_memory[1] = payload_type_;
+ packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
+ packet_memory[3] = (sequence_number_) & 0xFF;
+ packet_memory[4] = (timestamp_ >> 24) & 0xFF;
+ packet_memory[5] = (timestamp_ >> 16) & 0xFF;
+ packet_memory[6] = (timestamp_ >> 8) & 0xFF;
+ packet_memory[7] = timestamp_ & 0xFF;
+ // Set SSRC to 0x12345678.
+ packet_memory[8] = 0x12;
+ packet_memory[9] = 0x34;
+ packet_memory[10] = 0x56;
+ packet_memory[11] = 0x78;
+
+ ++sequence_number_;
+
+ // Copy the payload data.
+ memcpy(packet_memory + kRtpHeaderSize,
+ &last_payload_vec_[0],
+ last_payload_vec_.size());
+ Packet* packet =
+ new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds());
+ assert(packet);
+ assert(packet->valid_header());
+ return packet;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/modules/audio_coding/main/acm2/acm_send_test.h b/modules/audio_coding/main/acm2/acm_send_test.h
new file mode 100644
index 00000000..5e9bd977
--- /dev/null
+++ b/modules/audio_coding/main/acm2/acm_send_test.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 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_CODING_MAIN_ACM2_ACM_SEND_TEST_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_SEND_TEST_H_
+
+#include <vector>
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
+#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h"
+#include "webrtc/system_wrappers/interface/clock.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+namespace test {
+class InputAudioFile;
+class Packet;
+
+class AcmSendTest : public AudioPacketizationCallback, public PacketSource {
+ public:
+ AcmSendTest(InputAudioFile* audio_source,
+ int source_rate_hz,
+ int test_duration_ms);
+ virtual ~AcmSendTest() {}
+
+ // Registers the send codec. Returns true on success, false otherwise.
+ bool RegisterCodec(const char* payload_name,
+ int sampling_freq_hz,
+ int channels,
+ int payload_type,
+ int frame_size_samples);
+
+ // Returns the next encoded packet. Returns NULL if the test duration was
+ // exceeded. Ownership of the packet is handed over to the caller.
+ // Inherited from PacketSource.
+ Packet* NextPacket();
+
+ // Inherited from AudioPacketizationCallback.
+ virtual int32_t SendData(
+ FrameType frame_type,
+ uint8_t payload_type,
+ uint32_t timestamp,
+ const uint8_t* payload_data,
+ uint16_t payload_len_bytes,
+ const RTPFragmentationHeader* fragmentation) OVERRIDE;
+
+ private:
+ static const int kBlockSizeMs = 10;
+
+ // Creates a Packet object from the last packet produced by ACM (and received
+ // through the SendData method as a callback). Ownership of the new Packet
+ // object is transferred to the caller.
+ Packet* CreatePacket();
+
+ SimulatedClock clock_;
+ scoped_ptr<AudioCodingModule> acm_;
+ InputAudioFile* audio_source_;
+ int source_rate_hz_;
+ const int input_block_size_samples_;
+ AudioFrame input_frame_;
+ CodecInst codec_;
+ bool codec_registered_;
+ int test_duration_ms_;
+ // The following member variables are set whenever SendData() is called.
+ FrameType frame_type_;
+ int payload_type_;
+ uint32_t timestamp_;
+ uint16_t sequence_number_;
+ std::vector<uint8_t> last_payload_vec_;
+
+ DISALLOW_COPY_AND_ASSIGN(AcmSendTest);
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_SEND_TEST_H_
diff --git a/modules/audio_coding/main/acm2/audio_coding_module.gypi b/modules/audio_coding/main/acm2/audio_coding_module.gypi
index dccfe682..f88dbd37 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module.gypi
+++ b/modules/audio_coding/main/acm2/audio_coding_module.gypi
@@ -130,6 +130,19 @@
],
}, # acm_receive_test
{
+ 'target_name': 'acm_send_test',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'audio_coding_module',
+ 'neteq_unittest_tools',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'acm_send_test.cc',
+ 'acm_send_test.h',
+ ],
+ }, # acm_send_test
+ {
'target_name': 'delay_test',
'type': 'executable',
'dependencies': [
diff --git a/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc
index 7e2ede50..9c21fece 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/main/acm2/audio_coding_module_unittest.cc
@@ -12,12 +12,16 @@
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/md5digest.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_receive_test.h"
+#include "webrtc/modules/audio_coding/main/acm2/acm_send_test.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
#include "webrtc/modules/audio_coding/neteq/tools/audio_checksum.h"
#include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
+#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
#include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h"
+#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
#include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/clock.h"
@@ -516,6 +520,19 @@ TEST_F(AcmIsacMtTest, DoTest) {
}
class AcmReceiverBitExactness : public ::testing::Test {
+ public:
+ static std::string PlatformChecksum(std::string win64,
+ std::string android,
+ std::string others) {
+#if defined(_WIN32) && defined(WEBRTC_ARCH_64_BITS)
+ return win64;
+#elif defined(WEBRTC_ANDROID)
+ return android;
+#else
+ return others;
+#endif
+ }
+
protected:
void Run(int output_freq_hz, const std::string& checksum_ref) {
const std::string input_file_name =
@@ -546,18 +563,6 @@ class AcmReceiverBitExactness : public ::testing::Test {
std::string checksum_string = checksum.Finish();
EXPECT_EQ(checksum_ref, checksum_string);
}
-
- static std::string PlatformChecksum(std::string win64,
- std::string android,
- std::string others) {
-#if defined(_WIN32) && defined(WEBRTC_ARCH_64_BITS)
- return win64;
-#elif defined(WEBRTC_ANDROID)
- return android;
-#else
- return others;
-#endif
- }
};
TEST_F(AcmReceiverBitExactness, 8kHzOutput) {
@@ -587,4 +592,188 @@ TEST_F(AcmReceiverBitExactness, 48kHzOutput) {
"76b9e99e0a3998aa28355e7a2bd836f7",
"89b4b19bdb4de40f1d88302ef8cb9f9b"));
}
+
+// This test verifies bit exactness for the send-side of ACM. The test setup is
+// a chain of three different test classes:
+//
+// test::AcmSendTest -> AcmSenderBitExactness -> test::AcmReceiveTest
+//
+// The receiver side is driving the test by requesting new packets from
+// AcmSenderBitExactness::NextPacket(). This method, in turn, asks for the
+// packet from test::AcmSendTest::NextPacket, which inserts audio from the
+// input file until one packet is produced. (The input file loops indefinitely.)
+// Before passing the packet to the receiver, this test class verifies the
+// packet header and updates a payload checksum with the new payload. The
+// decoded output from the receiver is also verified with a (separate) checksum.
+class AcmSenderBitExactness : public ::testing::Test,
+ public test::PacketSource {
+ protected:
+ static const int kTestDurationMs = 1000;
+
+ AcmSenderBitExactness()
+ : frame_size_rtp_timestamps_(0),
+ packet_count_(0),
+ payload_type_(0),
+ last_sequence_number_(0),
+ last_timestamp_(0) {}
+
+ // Sets up the test::AcmSendTest object. Returns true on success, otherwise
+ // false.
+ bool SetUpSender() {
+ const std::string input_file_name =
+ webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+ // Note that |audio_source_| will loop forever. The test duration is set
+ // explicitly by |kTestDurationMs|.
+ audio_source_.reset(new test::InputAudioFile(input_file_name));
+ static const int kSourceRateHz = 32000;
+ send_test_.reset(new test::AcmSendTest(
+ audio_source_.get(), kSourceRateHz, kTestDurationMs));
+ return send_test_.get() != NULL;
+ }
+
+ // Registers a send codec in the test::AcmSendTest object. Returns true on
+ // success, false on failure.
+ bool RegisterSendCodec(const char* payload_name,
+ int sampling_freq_hz,
+ int channels,
+ int payload_type,
+ int frame_size_samples,
+ int frame_size_rtp_timestamps) {
+ payload_type_ = payload_type;
+ frame_size_rtp_timestamps_ = frame_size_rtp_timestamps;
+ return send_test_->RegisterCodec(payload_name,
+ sampling_freq_hz,
+ channels,
+ payload_type,
+ frame_size_samples);
+ }
+
+ // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
+ // before calling this method.
+ void Run(const std::string& audio_checksum_ref,
+ const std::string& payload_checksum_ref,
+ int expected_packets) {
+ // Set up the receiver used to decode the packets and verify the decoded
+ // output.
+ test::AudioChecksum audio_checksum;
+ const std::string output_file_name =
+ webrtc::test::OutputPath() +
+ ::testing::UnitTest::GetInstance()
+ ->current_test_info()
+ ->test_case_name() +
+ "_" +
+ ::testing::UnitTest::GetInstance()->current_test_info()->name() +
+ "_output.pcm";
+ test::OutputAudioFile output_file(output_file_name);
+ // Have the output audio sent both to file and to the checksum calculator.
+ test::AudioSinkFork output(&audio_checksum, &output_file);
+ const int kOutputFreqHz = 8000;
+ test::AcmReceiveTest receive_test(this, &output, kOutputFreqHz);
+ ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
+
+ // This is where the actual test is executed.
+ receive_test.Run();
+
+ // Extract and verify the audio checksum.
+ std::string checksum_string = audio_checksum.Finish();
+ EXPECT_EQ(audio_checksum_ref, checksum_string);
+
+ // Extract and verify the payload checksum.
+ char checksum_result[rtc::Md5Digest::kSize];
+ payload_checksum_.Finish(checksum_result, rtc::Md5Digest::kSize);
+ checksum_string = rtc::hex_encode(checksum_result, rtc::Md5Digest::kSize);
+ EXPECT_EQ(payload_checksum_ref, checksum_string);
+
+ // Verify number of packets produced.
+ EXPECT_EQ(expected_packets, packet_count_);
+ }
+
+ // Returns a pointer to the next packet. Returns NULL if the source is
+ // depleted (i.e., the test duration is exceeded), or if an error occurred.
+ // Inherited from test::PacketSource.
+ test::Packet* NextPacket() OVERRIDE {
+ // Get the next packet from AcmSendTest. Ownership of |packet| is
+ // transferred to this method.
+ test::Packet* packet = send_test_->NextPacket();
+ if (!packet)
+ return NULL;
+
+ VerifyPacket(packet);
+ // TODO(henrik.lundin) Save the packet to file as well.
+
+ // Pass it on to the caller. The caller becomes the owner of |packet|.
+ return packet;
+ }
+
+ // Verifies the packet.
+ void VerifyPacket(const test::Packet* packet) {
+ EXPECT_TRUE(packet->valid_header());
+ // (We can check the header fields even if valid_header() is false.)
+ EXPECT_EQ(payload_type_, packet->header().payloadType);
+ if (packet_count_ > 0) {
+ // This is not the first packet.
+ uint16_t sequence_number_diff =
+ packet->header().sequenceNumber - last_sequence_number_;
+ EXPECT_EQ(1, sequence_number_diff);
+ uint32_t timestamp_diff = packet->header().timestamp - last_timestamp_;
+ EXPECT_EQ(frame_size_rtp_timestamps_, timestamp_diff);
+ }
+ ++packet_count_;
+ last_sequence_number_ = packet->header().sequenceNumber;
+ last_timestamp_ = packet->header().timestamp;
+ // Update the checksum.
+ payload_checksum_.Update(packet->payload(), packet->payload_length_bytes());
+ }
+
+ void SetUpTest(const char* codec_name,
+ int codec_sample_rate_hz,
+ int channels,
+ int payload_type,
+ int codec_frame_size_samples,
+ int codec_frame_size_rtp_timestamps) {
+ ASSERT_TRUE(SetUpSender());
+ ASSERT_TRUE(RegisterSendCodec(codec_name,
+ codec_sample_rate_hz,
+ channels,
+ payload_type,
+ codec_frame_size_samples,
+ codec_frame_size_rtp_timestamps));
+ }
+
+ scoped_ptr<test::AcmSendTest> send_test_;
+ scoped_ptr<test::InputAudioFile> audio_source_;
+ uint32_t frame_size_rtp_timestamps_;
+ int packet_count_;
+ uint8_t payload_type_;
+ uint16_t last_sequence_number_;
+ uint32_t last_timestamp_;
+ rtc::Md5Digest payload_checksum_;
+};
+
+TEST_F(AcmSenderBitExactness, IsacWb30ms) {
+ ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 480, 480));
+ Run(AcmReceiverBitExactness::PlatformChecksum(
+ "c7e5bdadfa2871df95639fcc297cf23d",
+ "0499ca260390769b3172136faad925b9",
+ "0b58f9eeee43d5891f5f6c75e77984a3"),
+ AcmReceiverBitExactness::PlatformChecksum(
+ "d42cb5195463da26c8129bbfe73a22e6",
+ "83de248aea9c3c2bd680b6952401b4ca",
+ "3c79f16f34218271f3dca4e2b1dfe1bb"),
+ 33);
+}
+
+TEST_F(AcmSenderBitExactness, IsacWb60ms) {
+ ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
+ Run(AcmReceiverBitExactness::PlatformChecksum(
+ "14d63c5f08127d280e722e3191b73bdd",
+ "8da003e16c5371af2dc2be79a50f9076",
+ "1ad29139a04782a33daad8c2b9b35875"),
+ AcmReceiverBitExactness::PlatformChecksum(
+ "ebe04a819d3a9d83a83a17f271e1139a",
+ "97aeef98553b5a4b5a68f8b716e8eaf0",
+ "9e0a0ab743ad987b55b8e14802769c56"),
+ 16);
+}
+
} // namespace webrtc
diff --git a/modules/modules.gyp b/modules/modules.gyp
index e6919f1a..f68ea7cb 100644
--- a/modules/modules.gyp
+++ b/modules/modules.gyp
@@ -69,6 +69,7 @@
],
'dependencies': [
'acm_receive_test',
+ 'acm_send_test',
'audio_coding_module',
'audio_processing',
'bitrate_controller',