1/*
2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "testing/gtest/include/gtest/gtest.h"
12#include "webrtc/base/scoped_ptr.h"
13#include "webrtc/common_types.h"
14#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h"
15#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
16#include "webrtc/modules/audio_coding/test/utility.h"
17#include "webrtc/modules/include/module_common_types.h"
18#include "webrtc/system_wrappers/include/sleep.h"
19#include "webrtc/test/testsupport/fileutils.h"
20
21namespace webrtc {
22
23class TargetDelayTest : public ::testing::Test {
24 protected:
25  TargetDelayTest() : acm_(AudioCodingModule::Create(0)) {}
26
27  ~TargetDelayTest() {}
28
29  void SetUp() {
30    EXPECT_TRUE(acm_.get() != NULL);
31
32    CodecInst codec;
33    ASSERT_EQ(0, AudioCodingModule::Codec("L16", &codec, kSampleRateHz, 1));
34    ASSERT_EQ(0, acm_->InitializeReceiver());
35    ASSERT_EQ(0, acm_->RegisterReceiveCodec(codec));
36
37    rtp_info_.header.payloadType = codec.pltype;
38    rtp_info_.header.timestamp = 0;
39    rtp_info_.header.ssrc = 0x12345678;
40    rtp_info_.header.markerBit = false;
41    rtp_info_.header.sequenceNumber = 0;
42    rtp_info_.type.Audio.channel = 1;
43    rtp_info_.type.Audio.isCNG = false;
44    rtp_info_.frameType = kAudioFrameSpeech;
45
46    int16_t audio[kFrameSizeSamples];
47    const int kRange = 0x7FF;  // 2047, easy for masking.
48    for (size_t n = 0; n < kFrameSizeSamples; ++n)
49      audio[n] = (rand() & kRange) - kRange / 2;
50    WebRtcPcm16b_Encode(audio, kFrameSizeSamples, payload_);
51  }
52
53  void OutOfRangeInput() {
54    EXPECT_EQ(-1, SetMinimumDelay(-1));
55    EXPECT_EQ(-1, SetMinimumDelay(10001));
56  }
57
58  void NoTargetDelayBufferSizeChanges() {
59    for (int n = 0; n < 30; ++n)  // Run enough iterations.
60      Run(true);
61    int clean_optimal_delay = GetCurrentOptimalDelayMs();
62    Run(false);  // Run with jitter.
63    int jittery_optimal_delay = GetCurrentOptimalDelayMs();
64    EXPECT_GT(jittery_optimal_delay, clean_optimal_delay);
65    int required_delay = RequiredDelay();
66    EXPECT_GT(required_delay, 0);
67    EXPECT_NEAR(required_delay, jittery_optimal_delay, 1);
68  }
69
70  void WithTargetDelayBufferNotChanging() {
71    // A target delay that is one packet larger than jitter.
72    const int kTargetDelayMs = (kInterarrivalJitterPacket + 1) *
73        kNum10msPerFrame * 10;
74    ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
75    for (int n = 0; n < 30; ++n)  // Run enough iterations to fill the buffer.
76      Run(true);
77    int clean_optimal_delay = GetCurrentOptimalDelayMs();
78    EXPECT_EQ(kTargetDelayMs, clean_optimal_delay);
79    Run(false);  // Run with jitter.
80    int jittery_optimal_delay = GetCurrentOptimalDelayMs();
81    EXPECT_EQ(jittery_optimal_delay, clean_optimal_delay);
82  }
83
84  void RequiredDelayAtCorrectRange() {
85    for (int n = 0; n < 30; ++n)  // Run clean and store delay.
86      Run(true);
87    int clean_optimal_delay = GetCurrentOptimalDelayMs();
88
89    // A relatively large delay.
90    const int kTargetDelayMs = (kInterarrivalJitterPacket + 10) *
91        kNum10msPerFrame * 10;
92    ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
93    for (int n = 0; n < 300; ++n)  // Run enough iterations to fill the buffer.
94      Run(true);
95    Run(false);  // Run with jitter.
96
97    int jittery_optimal_delay = GetCurrentOptimalDelayMs();
98    EXPECT_EQ(kTargetDelayMs, jittery_optimal_delay);
99
100    int required_delay = RequiredDelay();
101
102    // Checking |required_delay| is in correct range.
103    EXPECT_GT(required_delay, 0);
104    EXPECT_GT(jittery_optimal_delay, required_delay);
105    EXPECT_GT(required_delay, clean_optimal_delay);
106
107    // A tighter check for the value of |required_delay|.
108    // The jitter forces a delay of
109    // |kInterarrivalJitterPacket * kNum10msPerFrame * 10| milliseconds. So we
110    // expect |required_delay| be close to that.
111    EXPECT_NEAR(kInterarrivalJitterPacket * kNum10msPerFrame * 10,
112                required_delay, 1);
113  }
114
115  void TargetDelayBufferMinMax() {
116    const int kTargetMinDelayMs = kNum10msPerFrame * 10;
117    ASSERT_EQ(0, SetMinimumDelay(kTargetMinDelayMs));
118    for (int m = 0; m < 30; ++m)  // Run enough iterations to fill the buffer.
119      Run(true);
120    int clean_optimal_delay = GetCurrentOptimalDelayMs();
121    EXPECT_EQ(kTargetMinDelayMs, clean_optimal_delay);
122
123    const int kTargetMaxDelayMs = 2 * (kNum10msPerFrame * 10);
124    ASSERT_EQ(0, SetMaximumDelay(kTargetMaxDelayMs));
125    for (int n = 0; n < 30; ++n)  // Run enough iterations to fill the buffer.
126      Run(false);
127
128    int capped_optimal_delay = GetCurrentOptimalDelayMs();
129    EXPECT_EQ(kTargetMaxDelayMs, capped_optimal_delay);
130  }
131
132 private:
133  static const int kSampleRateHz = 16000;
134  static const int kNum10msPerFrame = 2;
135  static const size_t kFrameSizeSamples = 320;  // 20 ms @ 16 kHz.
136  // payload-len = frame-samples * 2 bytes/sample.
137  static const int kPayloadLenBytes = 320 * 2;
138  // Inter-arrival time in number of packets in a jittery channel. One is no
139  // jitter.
140  static const int kInterarrivalJitterPacket = 2;
141
142  void Push() {
143    rtp_info_.header.timestamp += kFrameSizeSamples;
144    rtp_info_.header.sequenceNumber++;
145    ASSERT_EQ(0, acm_->IncomingPacket(payload_, kFrameSizeSamples * 2,
146                                      rtp_info_));
147  }
148
149  // Pull audio equivalent to the amount of audio in one RTP packet.
150  void Pull() {
151    AudioFrame frame;
152    for (int k = 0; k < kNum10msPerFrame; ++k) {  // Pull one frame.
153      ASSERT_EQ(0, acm_->PlayoutData10Ms(-1, &frame));
154      // Had to use ASSERT_TRUE, ASSERT_EQ generated error.
155      ASSERT_TRUE(kSampleRateHz == frame.sample_rate_hz_);
156      ASSERT_EQ(1u, frame.num_channels_);
157      ASSERT_TRUE(kSampleRateHz / 100 == frame.samples_per_channel_);
158    }
159  }
160
161  void Run(bool clean) {
162    for (int n = 0; n < 10; ++n) {
163      for (int m = 0; m < 5; ++m) {
164        Push();
165        Pull();
166      }
167
168      if (!clean) {
169        for (int m = 0; m < 10; ++m) {  // Long enough to trigger delay change.
170          Push();
171          for (int n = 0; n < kInterarrivalJitterPacket; ++n)
172            Pull();
173        }
174      }
175    }
176  }
177
178  int SetMinimumDelay(int delay_ms) {
179    return acm_->SetMinimumPlayoutDelay(delay_ms);
180  }
181
182  int SetMaximumDelay(int delay_ms) {
183    return acm_->SetMaximumPlayoutDelay(delay_ms);
184  }
185
186  int GetCurrentOptimalDelayMs() {
187    NetworkStatistics stats;
188    acm_->GetNetworkStatistics(&stats);
189    return stats.preferredBufferSize;
190  }
191
192  int RequiredDelay() {
193    return acm_->LeastRequiredDelayMs();
194  }
195
196  rtc::scoped_ptr<AudioCodingModule> acm_;
197  WebRtcRTPHeader rtp_info_;
198  uint8_t payload_[kPayloadLenBytes];
199};
200
201#if defined(WEBRTC_ANDROID)
202#define MAYBE_OutOfRangeInput DISABLED_OutOfRangeInput
203#else
204#define MAYBE_OutOfRangeInput OutOfRangeInput
205#endif
206TEST_F(TargetDelayTest, MAYBE_OutOfRangeInput) {
207  OutOfRangeInput();
208}
209
210#if defined(WEBRTC_ANDROID)
211#define MAYBE_NoTargetDelayBufferSizeChanges \
212  DISABLED_NoTargetDelayBufferSizeChanges
213#else
214#define MAYBE_NoTargetDelayBufferSizeChanges NoTargetDelayBufferSizeChanges
215#endif
216TEST_F(TargetDelayTest, MAYBE_NoTargetDelayBufferSizeChanges) {
217  NoTargetDelayBufferSizeChanges();
218}
219
220#if defined(WEBRTC_ANDROID)
221#define MAYBE_WithTargetDelayBufferNotChanging \
222  DISABLED_WithTargetDelayBufferNotChanging
223#else
224#define MAYBE_WithTargetDelayBufferNotChanging WithTargetDelayBufferNotChanging
225#endif
226TEST_F(TargetDelayTest, MAYBE_WithTargetDelayBufferNotChanging) {
227  WithTargetDelayBufferNotChanging();
228}
229
230#if defined(WEBRTC_ANDROID)
231#define MAYBE_RequiredDelayAtCorrectRange DISABLED_RequiredDelayAtCorrectRange
232#else
233#define MAYBE_RequiredDelayAtCorrectRange RequiredDelayAtCorrectRange
234#endif
235TEST_F(TargetDelayTest, MAYBE_RequiredDelayAtCorrectRange) {
236  RequiredDelayAtCorrectRange();
237}
238
239#if defined(WEBRTC_ANDROID)
240#define MAYBE_TargetDelayBufferMinMax DISABLED_TargetDelayBufferMinMax
241#else
242#define MAYBE_TargetDelayBufferMinMax TargetDelayBufferMinMax
243#endif
244TEST_F(TargetDelayTest, MAYBE_TargetDelayBufferMinMax) {
245  TargetDelayBufferMinMax();
246}
247
248}  // namespace webrtc
249
250