This CL is to add Opus complexity knob and to test it.

As a by-product, a generic tool for testing and comparing the complexity of codecs is added, and new audio files are added to the resources.

Three complexity tests are included
1. Default Opus complexity
2. Opus complexity knob
3. Default iSAC complexity (to compare with Opus)

The complexity tests are only meant for development reasons
and not to be run at bots.

The .isolate file is only needed for the APK packaging and test execution on Android.

TEST=passes all trybots

BUG=
R=kjellander@webrtc.org, tina.legrand@webrtc.org, turaj@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/8969004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5655 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/resources/audio_coding/music_stereo_48kHz.pcm.sha1 b/resources/audio_coding/music_stereo_48kHz.pcm.sha1
new file mode 100644
index 0000000..991cb57
--- /dev/null
+++ b/resources/audio_coding/music_stereo_48kHz.pcm.sha1
@@ -0,0 +1 @@
+77b123a152911b538951cadbee45007f9d1a370c
\ No newline at end of file
diff --git a/resources/audio_coding/speech_mono_16kHz.pcm.sha1 b/resources/audio_coding/speech_mono_16kHz.pcm.sha1
new file mode 100644
index 0000000..3cd29ed
--- /dev/null
+++ b/resources/audio_coding/speech_mono_16kHz.pcm.sha1
@@ -0,0 +1 @@
+89f191b706f8028e52ffd64525de1921eacd772a
\ No newline at end of file
diff --git a/resources/audio_coding/speech_mono_32_48kHz.pcm.sha1 b/resources/audio_coding/speech_mono_32_48kHz.pcm.sha1
new file mode 100644
index 0000000..c3e3560
--- /dev/null
+++ b/resources/audio_coding/speech_mono_32_48kHz.pcm.sha1
@@ -0,0 +1 @@
+009a3ee778767c2402b1d2c920bc2449265f5a2c
\ No newline at end of file
diff --git a/webrtc/build/apk_tests.gyp b/webrtc/build/apk_tests.gyp
index 8464d70..1df0469 100644
--- a/webrtc/build/apk_tests.gyp
+++ b/webrtc/build/apk_tests.gyp
@@ -199,7 +199,21 @@
       'includes': [
         '../../../build/apk_test.gypi',
       ],
-     },
+    },
+    {
+      'target_name': 'audio_codec_speed_tests_apk',
+      'type': 'none',
+      'variables': {
+        'test_suite_name': 'audio_codec_speed_tests',
+        'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)audio_codec_speed_tests<(SHARED_LIB_SUFFIX)',
+      },
+      'dependencies': [
+        '<(webrtc_root)/modules/modules.gyp:audio_codec_speed_tests',
+      ],
+      'includes': [
+        '../../../build/apk_test.gypi',
+      ],
+    }
   ],
 }
 
diff --git a/webrtc/build/apk_tests_noop.gyp b/webrtc/build/apk_tests_noop.gyp
index daf86e3..ed64863 100644
--- a/webrtc/build/apk_tests_noop.gyp
+++ b/webrtc/build/apk_tests_noop.gyp
@@ -61,5 +61,9 @@
       'target_name': 'webrtc_perf_tests_apk',
       'type': 'none',
     },
+    {
+      'target_name': 'audio_codec_speed_tests_apk',
+      'type': 'none',
+    },
   ],
 }
diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc b/webrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc
new file mode 100644
index 0000000..348a0c1
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc
@@ -0,0 +1,109 @@
+/*
+ *  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/codecs/isac/fix/interface/isacfix.h"
+#include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
+
+using ::std::tr1::make_tuple;
+using ::testing::ValuesIn;
+
+namespace webrtc {
+
+static const int kIsacBlockDurationMs = 30;
+static const int kIsacInputSamplingKhz = 16;
+static const int kIsacOutputSamplingKhz = 16;
+
+class IsacSpeedTest : public AudioCodecSpeedTest {
+ protected:
+  IsacSpeedTest();
+  virtual void SetUp() OVERRIDE;
+  virtual void TearDown() OVERRIDE;
+  virtual float EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
+                             int max_bytes, int* encoded_bytes);
+  virtual float DecodeABlock(const uint8_t* bit_stream, int encoded_bytes,
+                             int16_t* out_data);
+  ISACFIX_MainStruct *ISACFIX_main_inst_;
+};
+
+IsacSpeedTest::IsacSpeedTest()
+    : AudioCodecSpeedTest(kIsacBlockDurationMs,
+                          kIsacInputSamplingKhz,
+                          kIsacOutputSamplingKhz),
+      ISACFIX_main_inst_(NULL) {
+}
+
+void IsacSpeedTest::SetUp() {
+  AudioCodecSpeedTest::SetUp();
+
+  // Check whether the allocated buffer for the bit stream is large enough.
+  EXPECT_GE(max_bytes_, STREAM_MAXW16_60MS);
+
+  // Create encoder memory.
+  EXPECT_EQ(0, WebRtcIsacfix_Create(&ISACFIX_main_inst_));
+  EXPECT_EQ(0, WebRtcIsacfix_EncoderInit(ISACFIX_main_inst_, 1));
+  EXPECT_EQ(0, WebRtcIsacfix_DecoderInit(ISACFIX_main_inst_));
+  // Set bitrate and block length.
+  EXPECT_EQ(0, WebRtcIsacfix_Control(ISACFIX_main_inst_, bit_rate_,
+                                     block_duration_ms_));
+}
+
+void IsacSpeedTest::TearDown() {
+  AudioCodecSpeedTest::TearDown();
+  // Free memory.
+  EXPECT_EQ(0, WebRtcIsacfix_Free(ISACFIX_main_inst_));
+}
+
+float IsacSpeedTest::EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
+                                  int max_bytes, int* encoded_bytes) {
+  // ISAC takes 10 ms everycall
+  const int subblocks = block_duration_ms_ / 10;
+  const int subblock_length = 10 * input_sampling_khz_;
+  int value;
+
+  clock_t clocks = clock();
+  size_t pointer = 0;
+  for (int idx = 0; idx < subblocks; idx++, pointer += subblock_length) {
+    value = WebRtcIsacfix_Encode(ISACFIX_main_inst_, &in_data[pointer],
+                                 reinterpret_cast<int16_t*>(bit_stream));
+  }
+  clocks = clock() - clocks;
+  EXPECT_GT(value, 0);
+  assert(value <= max_bytes);
+  *encoded_bytes = value;
+  return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+float IsacSpeedTest::DecodeABlock(const uint8_t* bit_stream, int encoded_bytes,
+                                  int16_t* out_data) {
+  int value;
+  int16_t audio_type;
+  clock_t clocks = clock();
+  value = WebRtcIsacfix_Decode(ISACFIX_main_inst_,
+                               reinterpret_cast<const uint16_t*>(bit_stream),
+                               encoded_bytes, out_data, &audio_type);
+  clocks = clock() - clocks;
+  EXPECT_EQ(output_length_sample_, value);
+  return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+TEST_P(IsacSpeedTest, IsacEncodeDecodeTest) {
+  size_t kDurationSec = 400;  // Test audio length in second.
+  EncodeDecode(kDurationSec);
+}
+
+const coding_param param_set[] =
+    {make_tuple(1, 32000, string("audio_coding/speech_mono_16kHz"),
+                string("pcm"), true)};
+
+INSTANTIATE_TEST_CASE_P(AllTest, IsacSpeedTest,
+                        ValuesIn(param_set));
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
index 1370aff..8226f45 100644
--- a/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
+++ b/webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h
@@ -11,7 +11,7 @@
 #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_OPUS_INTERFACE_H_
 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_OPUS_INTERFACE_H_
 
-#include "typedefs.h"
+#include "webrtc/typedefs.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -59,6 +59,21 @@
  */
 int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate);
 
+/****************************************************************************
+ * WebRtcOpus_SetComplexity(...)
+ *
+ * This function adjusts the computational complexity. The effect is the same as
+ * calling the complexity setting of Opus as an Opus encoder related CTL.
+ *
+ * Input:
+ *      - inst               : Encoder context
+ *      - complexity         : New target complexity (0-10, inclusive)
+ *
+ * Return value              :  0 - Success
+ *                             -1 - Error
+ */
+int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity);
+
 int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, int channels);
 int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst);
 
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
index 98b924f..c4380a3 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
@@ -103,7 +103,15 @@
 
 int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
   if (inst) {
-  return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
+    return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
+  } else {
+    return -1;
+  }
+}
+
+int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
+  if (inst) {
+    return opus_encoder_ctl(inst->encoder, OPUS_SET_COMPLEXITY(complexity));
   } else {
     return -1;
   }
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc b/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
new file mode 100644
index 0000000..401474e
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -0,0 +1,118 @@
+/*
+ *  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/codecs/opus/interface/opus_interface.h"
+#include "webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h"
+
+using ::std::tr1::make_tuple;
+using ::testing::ValuesIn;
+
+namespace webrtc {
+
+static const int kOpusBlockDurationMs = 20;
+static const int kOpusInputSamplingKhz = 48;
+static const int kOpustOutputSamplingKhz = 32;
+
+class OpusSpeedTest : public AudioCodecSpeedTest {
+ protected:
+  OpusSpeedTest();
+  virtual void SetUp() OVERRIDE;
+  virtual void TearDown() OVERRIDE;
+  virtual float EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
+                             int max_bytes, int* encoded_bytes);
+  virtual float DecodeABlock(const uint8_t* bit_stream, int encoded_bytes,
+                             int16_t* out_data);
+  WebRtcOpusEncInst* opus_encoder_;
+  WebRtcOpusDecInst* opus_decoder_;
+};
+
+OpusSpeedTest::OpusSpeedTest()
+    : AudioCodecSpeedTest(kOpusBlockDurationMs,
+                          kOpusInputSamplingKhz,
+                          kOpustOutputSamplingKhz),
+      opus_encoder_(NULL),
+      opus_decoder_(NULL) {
+}
+
+void OpusSpeedTest::SetUp() {
+  AudioCodecSpeedTest::SetUp();
+  /* Create encoder memory. */
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
+  /* Set bitrate. */
+  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
+}
+
+void OpusSpeedTest::TearDown() {
+  AudioCodecSpeedTest::TearDown();
+  /* Free memory. */
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
+}
+
+float OpusSpeedTest::EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
+                                  int max_bytes, int* encoded_bytes) {
+  clock_t clocks = clock();
+  int value = WebRtcOpus_Encode(opus_encoder_, in_data,
+                                input_length_sample_, max_bytes,
+                                bit_stream);
+  clocks = clock() - clocks;
+  EXPECT_GT(value, 0);
+  *encoded_bytes = value;
+  return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+float OpusSpeedTest::DecodeABlock(const uint8_t* bit_stream,
+                                  int encoded_bytes, int16_t* out_data) {
+  int value;
+  int16_t audio_type;
+  clock_t clocks = clock();
+  value = WebRtcOpus_DecodeNew(opus_decoder_, bit_stream, encoded_bytes,
+                               out_data, &audio_type);
+  clocks = clock() - clocks;
+  EXPECT_EQ(output_length_sample_, value);
+  return 1000.0 * clocks / CLOCKS_PER_SEC;
+}
+
+#define ADD_TEST(complexity) \
+TEST_P(OpusSpeedTest, OpusSetComplexityTest##complexity) { \
+  /* Test audio length in second. */ \
+  size_t kDurationSec = 400; \
+  /* Set complexity. */ \
+  printf("Setting complexity to %d ...\n", complexity); \
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, complexity)); \
+  EncodeDecode(kDurationSec); \
+}
+
+ADD_TEST(10);
+ADD_TEST(9);
+ADD_TEST(8);
+ADD_TEST(7);
+ADD_TEST(6);
+ADD_TEST(5);
+ADD_TEST(4);
+ADD_TEST(3);
+ADD_TEST(2);
+ADD_TEST(1);
+ADD_TEST(0);
+
+// List all test cases: (channel, bit rat, filename, extension).
+const coding_param param_set[] =
+    {make_tuple(1, 64000, string("audio_coding/speech_mono_32_48kHz"),
+                string("pcm"), true),
+     make_tuple(1, 32000, string("audio_coding/speech_mono_32_48kHz"),
+                string("pcm"), true),
+     make_tuple(2, 64000, string("audio_coding/music_stereo_48kHz"),
+                string("pcm"), true)};
+
+INSTANTIATE_TEST_CASE_P(AllTest, OpusSpeedTest,
+                        ValuesIn(param_set));
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
index b699cf9..5b29c23 100644
--- a/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -202,6 +202,27 @@
   EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
 }
 
+TEST_F(OpusTest, OpusSetComplexity) {
+  // Test without creating encoder memory.
+  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 9));
+  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 9));
+
+  // Create encoder memory, try with different complexities.
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_mono_encoder_, 1));
+  EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_stereo_encoder_, 2));
+
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 0));
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 0));
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_mono_encoder_, 10));
+  EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 10));
+  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_mono_encoder_, 11));
+  EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_stereo_encoder_, 11));
+
+  // Free memory.
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_mono_encoder_));
+  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_stereo_encoder_));
+}
+
 // Encode and decode one frame (stereo), initialize the decoder and
 // decode once more.
 TEST_F(OpusTest, OpusDecodeInit) {
diff --git a/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
new file mode 100644
index 0000000..2563c41
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
@@ -0,0 +1,124 @@
+/*
+ *  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/codecs/tools/audio_codec_speed_test.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/test/testsupport/fileutils.h"
+
+using ::std::tr1::get;
+
+namespace webrtc {
+
+AudioCodecSpeedTest::AudioCodecSpeedTest(int block_duration_ms,
+                                         int input_sampling_khz,
+                                         int output_sampling_khz)
+    : block_duration_ms_(block_duration_ms),
+      input_sampling_khz_(input_sampling_khz),
+      output_sampling_khz_(output_sampling_khz),
+      input_length_sample_(block_duration_ms_ * input_sampling_khz_),
+      output_length_sample_(block_duration_ms_ * output_sampling_khz_),
+      data_pointer_(0),
+      loop_length_samples_(0),
+      max_bytes_(0),
+      encoded_bytes_(0),
+      encoding_time_ms_(0.0),
+      decoding_time_ms_(0.0),
+      out_file_(NULL) {
+}
+
+void AudioCodecSpeedTest::SetUp() {
+  channels_ = get<0>(GetParam());
+  bit_rate_ = get<1>(GetParam());
+  in_filename_ = test::ResourcePath(get<2>(GetParam()), get<3>(GetParam()));
+  save_out_data_ = get<4>(GetParam());
+
+  FILE* fp = fopen(in_filename_.c_str(), "rb");
+  assert(fp != NULL);
+
+  // Obtain file size.
+  fseek(fp, 0, SEEK_END);
+  loop_length_samples_ = ftell(fp) / sizeof(int16_t);
+  rewind(fp);
+
+  // Allocate memory to contain the whole file.
+  in_data_.reset(new int16_t[loop_length_samples_ +
+      input_length_sample_ * channels_]);
+
+  data_pointer_ = 0;
+
+  // Copy the file into the buffer.
+  ASSERT_EQ(fread(&in_data_[0], sizeof(int16_t), loop_length_samples_, fp),
+            loop_length_samples_);
+  fclose(fp);
+
+  // Add an extra block length of samples to the end of the array, starting
+  // over again from the beginning of the array. This is done to simplify
+  // the reading process when reading over the end of the loop.
+  memcpy(&in_data_[loop_length_samples_], &in_data_[0],
+         input_length_sample_ * channels_ * sizeof(int16_t));
+
+  max_bytes_ = input_length_sample_ * channels_ * sizeof(int16_t);
+  out_data_.reset(new int16_t[output_length_sample_ * channels_]);
+  bit_stream_.reset(new uint8_t[max_bytes_]);
+
+  if (save_out_data_) {
+    std::string out_filename =
+        ::testing::UnitTest::GetInstance()->current_test_info()->name();
+
+    // Erase '/'
+    size_t found;
+    while ((found = out_filename.find('/')) != std::string::npos)
+      out_filename.replace(found, 1, "_");
+
+    out_filename = test::OutputPath() + out_filename + ".pcm";
+
+    out_file_ = fopen(out_filename.c_str(), "wb");
+    assert(out_file_ != NULL);
+
+    printf("Output to be saved in %s.\n", out_filename.c_str());
+  }
+}
+
+void AudioCodecSpeedTest::TearDown() {
+  if (save_out_data_) {
+    fclose(out_file_);
+  }
+}
+
+void AudioCodecSpeedTest::EncodeDecode(size_t audio_duration_sec) {
+  size_t time_now_ms = 0;
+  float time_ms;
+
+  printf("Coding %d kHz-sampled %d-channel audio at %d bps ...\n",
+         input_sampling_khz_, channels_, bit_rate_);
+
+  while (time_now_ms < audio_duration_sec * 1000) {
+    // Encode & decode.
+    time_ms = EncodeABlock(&in_data_[data_pointer_], &bit_stream_[0],
+                           max_bytes_, &encoded_bytes_);
+    encoding_time_ms_ += time_ms;
+    time_ms = DecodeABlock(&bit_stream_[0], encoded_bytes_, &out_data_[0]);
+    decoding_time_ms_ += time_ms;
+    if (save_out_data_) {
+      fwrite(&out_data_[0], sizeof(int16_t),
+             output_length_sample_ * channels_, out_file_);
+    }
+    data_pointer_ = (data_pointer_ + input_length_sample_ * channels_) %
+        loop_length_samples_;
+    time_now_ms += block_duration_ms_;
+  }
+
+  printf("Encoding: %.2f%% real time,\nDecoding: %.2f%% real time.\n",
+         encoding_time_ms_ / audio_duration_sec / 10.0,
+         decoding_time_ms_ / audio_duration_sec / 10.0);
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
new file mode 100644
index 0000000..b385aa2
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
@@ -0,0 +1,94 @@
+/*
+ *  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_CODECS_TOOLS_AUDIO_CODEC_SPEED_TEST_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_TOOLS_AUDIO_CODEC_SPEED_TEST_H_
+
+#include <string>
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/typedefs.h"
+
+using ::std::string;
+using ::std::tr1::tuple;
+using ::testing::TestWithParam;
+
+namespace webrtc {
+
+// Define coding parameter as
+// <channels, bit_rate, file_name, extension, if_save_output>.
+typedef tuple<int, int, string, string, bool> coding_param;
+
+class AudioCodecSpeedTest : public TestWithParam<coding_param> {
+ protected:
+  AudioCodecSpeedTest(int block_duration_ms,
+                      int input_sampling_khz,
+                      int output_sampling_khz);
+  virtual void SetUp();
+  virtual void TearDown();
+
+  // EncodeABlock(...) does the following:
+  // 1. encodes a block of audio, saved in |in_data|,
+  // 2. save the bit stream to |bit_stream| of |max_bytes| bytes in size,
+  // 3. assign |encoded_bytes| with the length of the bit stream (in bytes),
+  // 4. return the cost of time (in millisecond) spent on actual encoding.
+  virtual float EncodeABlock(int16_t* in_data, uint8_t* bit_stream,
+                             int max_bytes, int* encoded_bytes) = 0;
+
+  // DecodeABlock(...) does the following:
+  // 1. decodes the bit stream in |bit_stream| with a length of |encoded_bytes|
+  // (in bytes),
+  // 2. save the decoded audio in |out_data|,
+  // 3. return the cost of time (in millisecond) spent on actual decoding.
+  virtual float DecodeABlock(const uint8_t* bit_stream, int encoded_bytes,
+                             int16_t* out_data) = 0;
+
+  // Encoding and decode an audio of |audio_duration| (in seconds) and
+  // record the runtime for encoding and decoding separately.
+  void EncodeDecode(size_t audio_duration);
+
+  int block_duration_ms_;
+  int input_sampling_khz_;
+  int output_sampling_khz_;
+
+  // Number of samples-per-channel in a frame.
+  int input_length_sample_;
+
+  // Expected output number of samples-per-channel in a frame.
+  int output_length_sample_;
+
+  scoped_ptr<int16_t[]> in_data_;
+  scoped_ptr<int16_t[]> out_data_;
+  size_t data_pointer_;
+  size_t loop_length_samples_;
+  scoped_ptr<uint8_t[]> bit_stream_;
+
+  // Maximum number of bytes in output bitstream for a frame of audio.
+  int max_bytes_;
+
+  int encoded_bytes_;
+  float encoding_time_ms_;
+  float decoding_time_ms_;
+  FILE* out_file_;
+
+  int channels_;
+
+  // Bit rate is in bit-per-second.
+  int bit_rate_;
+
+  string in_filename_;
+
+  // Determines whether to save the output to file.
+  bool save_out_data_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_TOOLS_AUDIO_CODEC_SPEED_TEST_H_
diff --git a/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.gypi b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.gypi
new file mode 100644
index 0000000..4d746e0
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.gypi
@@ -0,0 +1,71 @@
+# 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.
+
+{
+  'targets': [
+  {
+    'target_name': 'audio_codec_speed_tests',
+    'type': '<(gtest_target_type)',
+    'dependencies': [
+      'audio_processing',
+      'iSACFix',
+      'webrtc_opus',
+      '<(DEPTH)/testing/gtest.gyp:gtest',
+      '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+      '<(webrtc_root)/test/test.gyp:test_support_main',
+    ],
+    'sources': [
+      'audio_codec_speed_test.h',
+      'audio_codec_speed_test.cc',
+      '<(webrtc_root)/modules/audio_coding/codecs/opus/opus_speed_test.cc',
+      '<(webrtc_root)/modules/audio_coding/codecs/isac/fix/test/isac_speed_test.cc',
+    ],
+    'conditions': [
+      # TODO(henrike): remove build_with_chromium==1 when the bots are
+      # using Chromium's buildbots.
+      ['build_with_chromium==1 and OS=="android" and gtest_target_type=="shared_library"', {
+        'dependencies': [
+          '<(DEPTH)/testing/android/native_test.gyp:native_test_native_code',
+        ],
+      }],
+    ],
+  }],
+  'conditions': [
+    # TODO(henrike): remove build_with_chromium==1 when the bots are using
+    # Chromium's buildbots.
+    ['build_with_chromium==1 and OS=="android" and gtest_target_type=="shared_library"', {
+      'targets': [
+        {
+          'target_name': 'audio_codec_speed_tests_apk_target',
+          'type': 'none',
+          'dependencies': [
+            '<(apk_tests_path):audio_codec_speed_tests_apk',
+          ],
+        },
+      ],
+    }],
+    ['test_isolation_mode != "noop"', {
+      'targets': [
+        {
+          'target_name': 'audio_codec_speed_tests_run',
+          'type': 'none',
+          'dependencies': [
+            'audio_codec_speed_tests',
+          ],
+          'includes': [
+            '../../../../build/isolate.gypi',
+            'audio_codec_speed_tests.isolate',
+          ],
+          'sources': [
+            'audio_codec_speed_tests.isolate',
+          ],
+        },
+      ],
+    }],
+  ],
+}
diff --git a/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.isolate b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.isolate
new file mode 100644
index 0000000..82aaac0
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_tests.isolate
@@ -0,0 +1,42 @@
+# 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.
+{
+  'conditions': [
+    ['OS=="android"', {
+      # When doing Android builds, the WebRTC code is put in third_party/webrtc
+      # of a Chromium checkout, this is one level above the standalone build.
+      'variables': {
+        'isolate_dependency_untracked': [
+          '../../../../../../resources/',
+          '../../../../../../data/',
+        ],
+      },
+    }],
+    ['OS=="linux" or OS=="mac" or OS=="win"', {
+      'variables': {
+        'command': [
+          '../../../../../testing/test_env.py',
+          '<(PRODUCT_DIR)/audio_codec_speed_tests<(EXECUTABLE_SUFFIX)',
+        ],
+        'isolate_dependency_touched': [
+          '../../../../../DEPS',
+        ],
+        'isolate_dependency_tracked': [
+          '../../../../../resources/audio_coding/music_stereo_48kHz.pcm',
+          '../../../../../resources/audio_coding/speech_mono_16kHz.pcm',
+          '../../../../../resources/audio_coding/speech_mono_32_48kHz.pcm',
+          '../../../../../testing/test_env.py',
+          '<(PRODUCT_DIR)/audio_codec_speed_tests<(EXECUTABLE_SUFFIX)',
+        ],
+        'isolate_dependency_untracked': [
+          '../../../../../tools/swarming_client/',
+        ],
+      },
+    }],
+  ],
+}
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index f18551c..10da58a 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -43,6 +43,7 @@
       'includes': [
         'audio_coding/codecs/isac/isac_test.gypi',
         'audio_coding/codecs/isac/isacfix_test.gypi',
+        'audio_coding/codecs/tools/audio_codec_speed_tests.gypi',
         'audio_processing/audio_processing_tests.gypi',
         'rtp_rtcp/test/testFec/test_fec.gypi',
         'video_coding/main/source/video_coding_test.gypi',