target_delay_unittest.cc (5443B)
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 <cstddef> 12 #include <cstdint> 13 #include <cstdlib> 14 #include <map> 15 #include <memory> 16 17 #include "api/array_view.h" 18 #include "api/audio/audio_frame.h" 19 #include "api/audio_codecs/audio_format.h" 20 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 21 #include "api/environment/environment_factory.h" 22 #include "api/neteq/default_neteq_factory.h" 23 #include "api/neteq/neteq.h" 24 #include "api/rtp_headers.h" 25 #include "api/units/timestamp.h" 26 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h" 27 #include "modules/audio_coding/include/audio_coding_module.h" 28 #include "test/gtest.h" 29 30 namespace webrtc { 31 32 class TargetDelayTest : public ::testing::Test { 33 protected: 34 TargetDelayTest() 35 : neteq_( 36 DefaultNetEqFactory().Create(CreateEnvironment(), 37 NetEq::Config(), 38 CreateBuiltinAudioDecoderFactory())) {} 39 40 ~TargetDelayTest() override {} 41 42 void SetUp() override { 43 constexpr int pltype = 108; 44 std::map<int, SdpAudioFormat> receive_codecs = { 45 {pltype, {"L16", kSampleRateHz, 1}}}; 46 neteq_->SetCodecs(receive_codecs); 47 48 rtp_header_.payloadType = pltype; 49 rtp_header_.timestamp = 0; 50 rtp_header_.ssrc = 0x12345678; 51 rtp_header_.markerBit = false; 52 rtp_header_.sequenceNumber = 0; 53 54 int16_t audio[kFrameSizeSamples]; 55 const int kRange = 0x7FF; // 2047, easy for masking. 56 for (size_t n = 0; n < kFrameSizeSamples; ++n) 57 audio[n] = (rand() & kRange) - kRange / 2; 58 WebRtcPcm16b_Encode(audio, kFrameSizeSamples, payload_); 59 } 60 61 void OutOfRangeInput() { 62 EXPECT_FALSE(SetMinimumDelay(-1)); 63 EXPECT_FALSE(SetMinimumDelay(10001)); 64 } 65 66 void TargetDelayBufferMinMax() { 67 const int kTargetMinDelayMs = kNum10msPerFrame * 10; 68 ASSERT_TRUE(SetMinimumDelay(kTargetMinDelayMs)); 69 for (int m = 0; m < 30; ++m) // Run enough iterations to fill the buffer. 70 Run(true); 71 int clean_optimal_delay = GetCurrentOptimalDelayMs(); 72 EXPECT_EQ(kTargetMinDelayMs, clean_optimal_delay); 73 74 const int kTargetMaxDelayMs = 2 * (kNum10msPerFrame * 10); 75 ASSERT_TRUE(SetMaximumDelay(kTargetMaxDelayMs)); 76 for (int n = 0; n < 30; ++n) // Run enough iterations to fill the buffer. 77 Run(false); 78 79 int capped_optimal_delay = GetCurrentOptimalDelayMs(); 80 EXPECT_EQ(kTargetMaxDelayMs, capped_optimal_delay); 81 } 82 83 private: 84 static const int kSampleRateHz = 16000; 85 static const int kNum10msPerFrame = 2; 86 static const size_t kFrameSizeSamples = 320; // 20 ms @ 16 kHz. 87 // payload-len = frame-samples * 2 bytes/sample. 88 static const int kPayloadLenBytes = 320 * 2; 89 // Inter-arrival time in number of packets in a jittery channel. One is no 90 // jitter. 91 static const int kInterarrivalJitterPacket = 2; 92 93 void Push() { 94 rtp_header_.timestamp += kFrameSizeSamples; 95 rtp_header_.sequenceNumber++; 96 ASSERT_EQ(0, neteq_->InsertPacket( 97 rtp_header_, 98 ArrayView<const uint8_t>(payload_, kFrameSizeSamples * 2), 99 Timestamp::MinusInfinity())); 100 } 101 102 // Pull audio equivalent to the amount of audio in one RTP packet. 103 void Pull() { 104 AudioFrame frame; 105 bool muted; 106 for (int k = 0; k < kNum10msPerFrame; ++k) { // Pull one frame. 107 ASSERT_EQ(NetEq::kOK, neteq_->GetAudio(&frame, &muted)); 108 ASSERT_FALSE(muted); 109 // Had to use ASSERT_TRUE, ASSERT_EQ generated error. 110 ASSERT_TRUE(kSampleRateHz == frame.sample_rate_hz_); 111 ASSERT_EQ(1u, frame.num_channels_); 112 ASSERT_TRUE(kSampleRateHz / 100 == frame.samples_per_channel_); 113 } 114 } 115 116 void Run(bool clean) { 117 for (int n = 0; n < 10; ++n) { 118 for (int m = 0; m < 5; ++m) { 119 Push(); 120 Pull(); 121 } 122 123 if (!clean) { 124 for (int o = 0; o < 10; ++o) { // Long enough to trigger delay change. 125 Push(); 126 for (int p = 0; p < kInterarrivalJitterPacket; ++p) 127 Pull(); 128 } 129 } 130 } 131 } 132 133 int SetMinimumDelay(int delay_ms) { 134 return neteq_->SetMinimumDelay(delay_ms); 135 } 136 137 int SetMaximumDelay(int delay_ms) { 138 return neteq_->SetMaximumDelay(delay_ms); 139 } 140 141 int GetCurrentOptimalDelayMs() { 142 NetEqNetworkStatistics neteq_stats; 143 neteq_->NetworkStatistics(&neteq_stats); 144 return neteq_stats.preferred_buffer_size_ms; 145 } 146 147 std::unique_ptr<NetEq> neteq_; 148 RTPHeader rtp_header_; 149 uint8_t payload_[kPayloadLenBytes]; 150 }; 151 152 // Flaky on iOS: webrtc:7057. 153 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) 154 #define MAYBE_OutOfRangeInput DISABLED_OutOfRangeInput 155 #else 156 #define MAYBE_OutOfRangeInput OutOfRangeInput 157 #endif 158 TEST_F(TargetDelayTest, MAYBE_OutOfRangeInput) { 159 OutOfRangeInput(); 160 } 161 162 // Flaky on iOS: webrtc:7057. 163 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) 164 #define MAYBE_TargetDelayBufferMinMax DISABLED_TargetDelayBufferMinMax 165 #else 166 #define MAYBE_TargetDelayBufferMinMax TargetDelayBufferMinMax 167 #endif 168 TEST_F(TargetDelayTest, MAYBE_TargetDelayBufferMinMax) { 169 TargetDelayBufferMinMax(); 170 } 171 172 } // namespace webrtc