1835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org/*
2835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *
4835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *  Use of this source code is governed by a BSD-style license
5835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *  that can be found in the LICENSE file in the root of the source
6835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *  tree. An additional intellectual property rights grant can be found
7835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *  in the file PATENTS.  All contributing project authors may
8835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org */
10835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
11835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
12e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h"
13835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org#include "webrtc/test/testsupport/fileutils.h"
14835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
15835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgusing google::RegisterFlagValidator;
16835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgusing google::ParseCommandLineFlags;
17835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgusing std::string;
18835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgusing testing::InitGoogleTest;
19835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
20835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgnamespace webrtc {
21835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgnamespace test {
22835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
23835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const int kOpusBlockDurationMs = 20;
24254879d7e969771c28d0882582e02b1a0b0eeb14minyue@webrtc.orgstatic const int kOpusSamplingKhz = 48;
25835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
26b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org// Define switch for input file name.
27835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic bool ValidateInFilename(const char* flagname, const string& value) {
28835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  FILE* fid = fopen(value.c_str(), "rb");
29835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (fid != NULL) {
30835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    fclose(fid);
31835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    return true;
32835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  }
33835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  printf("Invalid input filename.");
34835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return false;
35835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
36b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
37835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_string(in_filename,
38835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org              ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm"),
39835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org              "Filename for input audio (should be 48 kHz sampled raw data).");
40b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
41835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const bool in_filename_dummy =
42835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename);
43835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
44b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org// Define switch for output file name.
45835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic bool ValidateOutFilename(const char* flagname, const string& value) {
46835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  FILE* fid = fopen(value.c_str(), "wb");
47835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (fid != NULL) {
48835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    fclose(fid);
49835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    return true;
50835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  }
51835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  printf("Invalid output filename.");
52835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return false;
53835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
54b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
55835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_string(out_filename, OutputPath() + "neteq4_opus_fec_quality_test.pcm",
56835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org              "Name of output audio file.");
57b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
58835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const bool out_filename_dummy =
59835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    RegisterFlagValidator(&FLAGS_out_filename, &ValidateOutFilename);
60835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
61b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org// Define switch for channels.
62835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic bool ValidateChannels(const char* flagname, int32_t value) {
63835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (value == 1 || value == 2)
64835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    return true;
65835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  printf("Invalid number of channels, should be either 1 or 2.");
66835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return false;
67835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
68b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
69835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_int32(channels, 1, "Number of channels in input audio.");
70b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
71835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const bool channels_dummy =
72835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    RegisterFlagValidator(&FLAGS_channels, &ValidateChannels);
73835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
74b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org// Define switch for bit rate.
75835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic bool ValidateBitRate(const char* flagname, int32_t value) {
76835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (value >= 6 && value <= 510)
77835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    return true;
78835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  printf("Invalid bit rate, should be between 6 and 510 kbps.");
79835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return false;
80835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
81b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
82835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_int32(bit_rate_kbps, 32, "Target bit rate (kbps).");
83b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
84835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const bool bit_rate_dummy =
85835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    RegisterFlagValidator(&FLAGS_bit_rate_kbps, &ValidateBitRate);
86835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
87b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org// Define switch for reported packet loss rate.
88835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic bool ValidatePacketLossRate(const char* flagname, int32_t value) {
89835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (value >= 0 && value <= 100)
90835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    return true;
91835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  printf("Invalid packet loss percentile, should be between 0 and 100.");
92835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return false;
93835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
94b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
95835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_int32(reported_loss_rate, 10, "Reported percentile of packet loss.");
96b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
97835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const bool reported_loss_rate_dummy =
98835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    RegisterFlagValidator(&FLAGS_reported_loss_rate, &ValidatePacketLossRate);
99835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
100b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org// Define switch for runtime.
101835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic bool ValidateRuntime(const char* flagname, int32_t value) {
102835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (value > 0)
103835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    return true;
104835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  printf("Invalid runtime, should be greater than 0.");
105835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return false;
106835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
107b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org
108835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_int32(runtime_ms, 10000, "Simulated runtime (milliseconds).");
109835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgstatic const bool runtime_dummy =
110835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    RegisterFlagValidator(&FLAGS_runtime_ms, &ValidateRuntime);
111835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
112835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgDEFINE_bool(fec, true, "Whether to enable FEC for encoding.");
113835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
114835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgclass NetEqOpusFecQualityTest : public NetEqQualityTest {
115835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org protected:
116835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  NetEqOpusFecQualityTest();
117835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  virtual void SetUp() OVERRIDE;
118835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  virtual void TearDown() OVERRIDE;
119835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  virtual int EncodeBlock(int16_t* in_data, int block_size_samples,
120835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                          uint8_t* payload, int max_bytes);
121835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org private:
122835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  WebRtcOpusEncInst* opus_encoder_;
123835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  int channels_;
124835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  int bit_rate_kbps_;
125835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  bool fec_;
126835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  int target_loss_rate_;
127835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org};
128835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
129835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgNetEqOpusFecQualityTest::NetEqOpusFecQualityTest()
130254879d7e969771c28d0882582e02b1a0b0eeb14minyue@webrtc.org    : NetEqQualityTest(kOpusBlockDurationMs, kOpusSamplingKhz,
131254879d7e969771c28d0882582e02b1a0b0eeb14minyue@webrtc.org                       kOpusSamplingKhz,
132835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                       (FLAGS_channels == 1) ? kDecoderOpus : kDecoderOpus_2ch,
133b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org                       FLAGS_channels,
134b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org                       FLAGS_in_filename,
135835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                       FLAGS_out_filename),
136835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org      opus_encoder_(NULL),
137835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org      channels_(FLAGS_channels),
138835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org      bit_rate_kbps_(FLAGS_bit_rate_kbps),
139835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org      fec_(FLAGS_fec),
140b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org      target_loss_rate_(FLAGS_reported_loss_rate) {
141835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
142835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
143835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgvoid NetEqOpusFecQualityTest::SetUp() {
144835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  // Create encoder memory.
145835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  WebRtcOpus_EncoderCreate(&opus_encoder_, channels_);
146835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  ASSERT_TRUE(opus_encoder_ != NULL);
147835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  // Set bitrate.
148835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_kbps_ * 1000));
149835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  if (fec_) {
150835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org    EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
151835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  }
152b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org  EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_,
153b5272dfc7e7599580263bcde04b0484a6379f2b9minyue@webrtc.org                                            target_loss_rate_));
154835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  NetEqQualityTest::SetUp();
155835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
156835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
157835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgvoid NetEqOpusFecQualityTest::TearDown() {
158835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  // Free memory.
159835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
160835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  NetEqQualityTest::TearDown();
161835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
162835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
163835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgint NetEqOpusFecQualityTest::EncodeBlock(int16_t* in_data,
164835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                                         int block_size_samples,
165835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                                         uint8_t* payload, int max_bytes) {
166835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  int value = WebRtcOpus_Encode(opus_encoder_, in_data,
167835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                                block_size_samples, max_bytes,
168835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org                                payload);
169835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  EXPECT_GT(value, 0);
170835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  return value;
171835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
172835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
173835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.orgTEST_F(NetEqOpusFecQualityTest, Test) {
174835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org  Simulate(FLAGS_runtime_ms);
175835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}
176835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org
177835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}  // namespace test
178835b016d936aeb6c48b42c211ef257d6d3057c4fminyue@webrtc.org}  // namespace webrtc
179