diff --git a/webrtc/modules/audio_coding/neteq/neteq.gypi b/webrtc/modules/audio_coding/neteq/neteq.gypi index 27e5c37aab..a8acfb3df2 100644 --- a/webrtc/modules/audio_coding/neteq/neteq.gypi +++ b/webrtc/modules/audio_coding/neteq/neteq.gypi @@ -167,6 +167,7 @@ 'PCM16B', 'neteq_unittest_tools', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', + '<(webrtc_root)/test/test.gyp:test_support_main', ], 'sources': [ 'test/neteq_speed_test.cc', diff --git a/webrtc/modules/audio_coding/neteq4/neteq.gypi b/webrtc/modules/audio_coding/neteq4/neteq.gypi index 41fdb31ea6..46601099d6 100644 --- a/webrtc/modules/audio_coding/neteq4/neteq.gypi +++ b/webrtc/modules/audio_coding/neteq4/neteq.gypi @@ -162,7 +162,7 @@ 'dependencies': [ '<(DEPTH)/testing/gmock.gyp:gmock', '<(DEPTH)/testing/gtest.gyp:gtest', - '<(webrtc_root)/test/test.gyp:test_support_main', + 'PCM16B', # Needed by neteq_performance_test. ], 'direct_dependent_settings': { 'include_dirs': [ @@ -177,6 +177,8 @@ 'tools/audio_loop.h', 'tools/input_audio_file.cc', 'tools/input_audio_file.h', + 'tools/neteq_performance_test.cc', + 'tools/neteq_performance_test.h', 'tools/rtp_generator.cc', 'tools/rtp_generator.h', ], diff --git a/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi b/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi index a2b9265613..c74466d6f0 100644 --- a/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi +++ b/webrtc/modules/audio_coding/neteq4/neteq_tests.gypi @@ -146,6 +146,7 @@ 'neteq_unittest_tools', 'PCM16B', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', + '<(webrtc_root)/test/test.gyp:test_support_main', ], 'sources': [ 'test/neteq_speed_test.cc', diff --git a/webrtc/modules/audio_coding/neteq4/test/neteq_performance_unittest.cc b/webrtc/modules/audio_coding/neteq4/test/neteq_performance_unittest.cc new file mode 100644 index 0000000000..aa33649ec7 --- /dev/null +++ b/webrtc/modules/audio_coding/neteq4/test/neteq_performance_unittest.cc @@ -0,0 +1,25 @@ +/* + * 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 "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h" +#include "webrtc/test/testsupport/perf_test.h" +#include "webrtc/typedefs.h" + +TEST(NetEqPerformanceTest, Run) { + const int kSimulationTimeMs = 1000000; + const int kLossPeriod = 10; // Drop every 10th packet. + const double kDriftFactor = 0.1; + int64_t runtime = webrtc::test::NetEqPerformanceTest::Run( + kSimulationTimeMs, kLossPeriod, kDriftFactor); + ASSERT_GT(runtime, 0); + webrtc::test::PrintResult( + "neteq4-runtime", "", "", runtime, "ms", true); +} diff --git a/webrtc/modules/audio_coding/neteq4/test/neteq_speed_test.cc b/webrtc/modules/audio_coding/neteq4/test/neteq_speed_test.cc index 34f0de44e3..cecd48b701 100644 --- a/webrtc/modules/audio_coding/neteq4/test/neteq_speed_test.cc +++ b/webrtc/modules/audio_coding/neteq4/test/neteq_speed_test.cc @@ -13,18 +13,9 @@ #include #include "gflags/gflags.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" -#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h" -#include "webrtc/modules/audio_coding/neteq4/tools/audio_loop.h" -#include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h" -#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h" #include "webrtc/typedefs.h" -using webrtc::NetEq; -using webrtc::test::AudioLoop; -using webrtc::test::RtpGenerator; -using webrtc::WebRtcRTPHeader; - // Flag validators. static bool ValidateRuntime(const char* flagname, int value) { if (value > 0) // Value is ok. @@ -59,15 +50,6 @@ static const bool drift_dummy = google::RegisterFlagValidator(&FLAGS_drift, &ValidateDriftfactor); int main(int argc, char* argv[]) { - static const int kMaxChannels = 1; - static const int kMaxSamplesPerMs = 48000 / 1000; - static const int kOutputBlockSizeMs = 10; - const std::string kInputFileName = - webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); - const int kSampRateHz = 32000; - const webrtc::NetEqDecoder kDecoderType = webrtc::kDecoderPCM16Bswb32kHz; - const int kPayloadType = 95; - std::string program_name = argv[0]; std::string usage = "Tool for measuring the speed of NetEq.\n" "Usage: " + program_name + " [options]\n\n" @@ -84,101 +66,15 @@ int main(int argc, char* argv[]) { return 0; } - // Initialize NetEq instance. - NetEq* neteq = NetEq::Create(kSampRateHz); - // Register decoder in |neteq|. - int error; - error = neteq->RegisterPayloadType(kDecoderType, kPayloadType); - if (error) { - std::cerr << "Cannot register decoder." << std::endl; - exit(1); - } - - // Set up AudioLoop object. - AudioLoop audio_loop; - const size_t kMaxLoopLengthSamples = kSampRateHz * 10; // 10 second loop. - const size_t kInputBlockSizeSamples = 60 * kSampRateHz / 1000; // 60 ms. - if (!audio_loop.Init(kInputFileName, kMaxLoopLengthSamples, - kInputBlockSizeSamples)) { - std::cerr << "Cannot initialize AudioLoop object." << std::endl; - exit(1); - } - - int32_t time_now_ms = 0; - - // Get first input packet. - WebRtcRTPHeader rtp_header; - RtpGenerator rtp_gen(kSampRateHz / 1000); - // Start with positive drift first half of simulation. - double drift_factor = 0.1; - rtp_gen.set_drift_factor(drift_factor); - bool drift_flipped = false; - int32_t packet_input_time_ms = - rtp_gen.GetRtpHeader(kPayloadType, kInputBlockSizeSamples, &rtp_header); - const int16_t* input_samples = audio_loop.GetNextBlock(); - if (!input_samples) exit(1); - uint8_t input_payload[kInputBlockSizeSamples * sizeof(int16_t)]; - int payload_len = WebRtcPcm16b_Encode(const_cast(input_samples), - kInputBlockSizeSamples, - input_payload); - assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t)); - - // Main loop. - while (time_now_ms < FLAGS_runtime_ms) { - while (packet_input_time_ms <= time_now_ms) { - // Drop every N packets, where N = FLAGS_lossrate. - bool lost = false; - if (FLAGS_lossrate > 0) { - lost = ((rtp_header.header.sequenceNumber - 1) % FLAGS_lossrate) == 0; - } - if (!lost) { - // Insert packet. - int error = neteq->InsertPacket( - rtp_header, input_payload, payload_len, - packet_input_time_ms * kSampRateHz / 1000); - if (error != NetEq::kOK) { - std::cerr << "InsertPacket returned error code " << - neteq->LastError() << std::endl; - exit(1); - } - } - - // Get next packet. - packet_input_time_ms = rtp_gen.GetRtpHeader(kPayloadType, - kInputBlockSizeSamples, - &rtp_header); - input_samples = audio_loop.GetNextBlock(); - if (!input_samples) exit(1); - payload_len = WebRtcPcm16b_Encode(const_cast(input_samples), - kInputBlockSizeSamples, - input_payload); - assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t)); - } - - // Get output audio, but don't do anything with it. - static const int kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs * - kMaxChannels; - int16_t out_data[kOutDataLen]; - int num_channels; - int samples_per_channel; - int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, - &num_channels, NULL); - if (error != NetEq::kOK) { - std::cerr << "GetAudio returned error code " << - neteq->LastError() << std::endl; - exit(1); - } - assert(samples_per_channel == kSampRateHz * 10 / 1000); - - time_now_ms += kOutputBlockSizeMs; - if (time_now_ms >= FLAGS_runtime_ms / 2 && !drift_flipped) { - // Apply negative drift second half of simulation. - rtp_gen.set_drift_factor(-drift_factor); - drift_flipped = true; - } + int64_t result = + webrtc::test::NetEqPerformanceTest::Run(FLAGS_runtime_ms, FLAGS_lossrate, + FLAGS_drift); + if (result <= 0) { + std::cout << "There was an error" << std::endl; + return -1; } std::cout << "Simulation done" << std::endl; - delete neteq; + std::cout << "Runtime = " << result << " ms" << std::endl; return 0; } diff --git a/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.cc b/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.cc new file mode 100644 index 0000000000..203ea040cc --- /dev/null +++ b/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.cc @@ -0,0 +1,130 @@ +/* + * 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/neteq4/tools/neteq_performance_test.h" + +#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h" +#include "webrtc/modules/audio_coding/neteq4/tools/audio_loop.h" +#include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h" +#include "webrtc/system_wrappers/interface/clock.h" +#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/typedefs.h" + +using webrtc::NetEq; +using webrtc::test::AudioLoop; +using webrtc::test::RtpGenerator; +using webrtc::WebRtcRTPHeader; + +namespace webrtc { +namespace test { + +int64_t NetEqPerformanceTest::Run(int runtime_ms, + int lossrate, + double drift_factor) { + const std::string kInputFileName = + webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"); + const int kSampRateHz = 32000; + const webrtc::NetEqDecoder kDecoderType = webrtc::kDecoderPCM16Bswb32kHz; + const int kPayloadType = 95; + + // Initialize NetEq instance. + NetEq* neteq = NetEq::Create(kSampRateHz); + // Register decoder in |neteq|. + if (neteq->RegisterPayloadType(kDecoderType, kPayloadType) != 0) + return -1; + + // Set up AudioLoop object. + AudioLoop audio_loop; + const size_t kMaxLoopLengthSamples = kSampRateHz * 10; // 10 second loop. + const size_t kInputBlockSizeSamples = 60 * kSampRateHz / 1000; // 60 ms. + if (!audio_loop.Init(kInputFileName, kMaxLoopLengthSamples, + kInputBlockSizeSamples)) + return -1; + + int32_t time_now_ms = 0; + + // Get first input packet. + WebRtcRTPHeader rtp_header; + RtpGenerator rtp_gen(kSampRateHz / 1000); + // Start with positive drift first half of simulation. + rtp_gen.set_drift_factor(drift_factor); + bool drift_flipped = false; + int32_t packet_input_time_ms = + rtp_gen.GetRtpHeader(kPayloadType, kInputBlockSizeSamples, &rtp_header); + const int16_t* input_samples = audio_loop.GetNextBlock(); + if (!input_samples) exit(1); + uint8_t input_payload[kInputBlockSizeSamples * sizeof(int16_t)]; + int payload_len = WebRtcPcm16b_Encode(const_cast(input_samples), + kInputBlockSizeSamples, + input_payload); + assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t)); + + // Main loop. + webrtc::Clock* clock = webrtc::Clock::GetRealTimeClock(); + int64_t start_time_ms = clock->TimeInMilliseconds(); + while (time_now_ms < runtime_ms) { + while (packet_input_time_ms <= time_now_ms) { + // Drop every N packets, where N = FLAGS_lossrate. + bool lost = false; + if (lossrate > 0) { + lost = ((rtp_header.header.sequenceNumber - 1) % lossrate) == 0; + } + if (!lost) { + // Insert packet. + int error = neteq->InsertPacket( + rtp_header, input_payload, payload_len, + packet_input_time_ms * kSampRateHz / 1000); + if (error != NetEq::kOK) + return -1; + } + + // Get next packet. + packet_input_time_ms = rtp_gen.GetRtpHeader(kPayloadType, + kInputBlockSizeSamples, + &rtp_header); + input_samples = audio_loop.GetNextBlock(); + if (!input_samples) return -1; + payload_len = WebRtcPcm16b_Encode(const_cast(input_samples), + kInputBlockSizeSamples, + input_payload); + assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t)); + } + + // Get output audio, but don't do anything with it. + static const int kMaxChannels = 1; + static const int kMaxSamplesPerMs = 48000 / 1000; + static const int kOutputBlockSizeMs = 10; + static const int kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs * + kMaxChannels; + int16_t out_data[kOutDataLen]; + int num_channels; + int samples_per_channel; + int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, + &num_channels, NULL); + if (error != NetEq::kOK) + return -1; + + assert(samples_per_channel == kSampRateHz * 10 / 1000); + + time_now_ms += kOutputBlockSizeMs; + if (time_now_ms >= runtime_ms / 2 && !drift_flipped) { + // Apply negative drift second half of simulation. + rtp_gen.set_drift_factor(-drift_factor); + drift_flipped = true; + } + } + int64_t end_time_ms = clock->TimeInMilliseconds(); + delete neteq; + return end_time_ms - start_time_ms; +} + +} // namespace test +} // namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h b/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h new file mode 100644 index 0000000000..1b205c03c1 --- /dev/null +++ b/webrtc/modules/audio_coding/neteq4/tools/neteq_performance_test.h @@ -0,0 +1,32 @@ +/* + * 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_NETEQ4_TOOLS_NETEQ_PERFORMANCE_TEST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ4_TOOLS_NETEQ_PERFORMANCE_TEST_H_ + +#include "webrtc/typedefs.h" + +namespace webrtc { +namespace test { + +class NetEqPerformanceTest { + public: + // Runs a performance test with parameters as follows: + // |runtime_ms|: the simulation time, i.e., the duration of the audio data. + // |lossrate|: drop one out of |lossrate| packets, e.g., one out of 10. + // |drift_factor|: clock drift in [0, 1]. + // Returns the runtime in ms. + static int64_t Run(int runtime_ms, int lossrate, double drift_factor); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ4_TOOLS_NETEQ_PERFORMANCE_TEST_H_ diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi index b60660ac39..57fd907350 100644 --- a/webrtc/webrtc_tests.gypi +++ b/webrtc/webrtc_tests.gypi @@ -54,6 +54,7 @@ 'target_name': 'webrtc_perf_tests', 'type': '<(gtest_target_type)', 'sources': [ + 'modules/audio_coding/neteq4/test/neteq_performance_unittest.cc', 'test/test_main.cc', 'video/call_perf_tests.cc', 'video/full_stack.cc', @@ -62,6 +63,7 @@ 'dependencies': [ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', + 'modules/modules.gyp:neteq_unittest_tools', # Needed by neteq_performance_unittest. 'modules/modules.gyp:rtp_rtcp', 'test/webrtc_test_common.gyp:webrtc_test_common', 'webrtc',