PacketLossTest.cc (6154B)
1 /* 2 * Copyright (c) 2014 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 "modules/audio_coding/test/PacketLossTest.h" 12 13 #include <cstdint> 14 #include <memory> 15 #include <string> 16 17 #include "absl/strings/string_view.h" 18 #include "api/array_view.h" 19 #include "api/audio_codecs/audio_encoder.h" 20 #include "api/audio_codecs/audio_format.h" 21 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 22 #include "api/environment/environment.h" 23 #include "api/environment/environment_factory.h" 24 #include "api/neteq/default_neteq_factory.h" 25 #include "api/neteq/neteq.h" 26 #include "api/units/timestamp.h" 27 #include "modules/audio_coding/include/audio_coding_module.h" 28 #include "modules/audio_coding/test/EncodeDecodeTest.h" 29 #include "modules/audio_coding/test/RTPFile.h" 30 #include "rtc_base/strings/string_builder.h" 31 #include "test/gtest.h" 32 #include "test/testsupport/file_utils.h" 33 34 namespace webrtc { 35 36 ReceiverWithPacketLoss::ReceiverWithPacketLoss() 37 : loss_rate_(0), 38 burst_length_(1), 39 packet_counter_(0), 40 lost_packet_counter_(0), 41 burst_lost_counter_(burst_length_) {} 42 43 void ReceiverWithPacketLoss::Setup(NetEq* neteq, 44 RTPStream* rtpStream, 45 absl::string_view out_file_name, 46 int channels, 47 int file_num, 48 int loss_rate, 49 int burst_length) { 50 loss_rate_ = loss_rate; 51 burst_length_ = burst_length; 52 burst_lost_counter_ = burst_length_; // To prevent first packet gets lost. 53 StringBuilder ss; 54 ss << out_file_name << "_" << loss_rate_ << "_" << burst_length_ << "_"; 55 Receiver::Setup(neteq, rtpStream, ss.str(), channels, file_num); 56 } 57 58 bool ReceiverWithPacketLoss::IncomingPacket() { 59 if (!_rtpStream->EndOfFile()) { 60 if (packet_counter_ == 0) { 61 _realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload, 62 _payloadSizeBytes, &_nextTime); 63 if (_realPayloadSizeBytes == 0) { 64 if (_rtpStream->EndOfFile()) { 65 packet_counter_ = 0; 66 return true; 67 } else { 68 return false; 69 } 70 } 71 } 72 73 if (!PacketLost()) { 74 _neteq->InsertPacket( 75 _rtpHeader, 76 ArrayView<const uint8_t>(_incomingPayload, _realPayloadSizeBytes), 77 Timestamp::Millis(_nextTime)); 78 } 79 packet_counter_++; 80 _realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload, 81 _payloadSizeBytes, &_nextTime); 82 if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) { 83 packet_counter_ = 0; 84 lost_packet_counter_ = 0; 85 } 86 } 87 return true; 88 } 89 90 bool ReceiverWithPacketLoss::PacketLost() { 91 if (burst_lost_counter_ < burst_length_) { 92 lost_packet_counter_++; 93 burst_lost_counter_++; 94 return true; 95 } 96 97 if (lost_packet_counter_ * 100 < loss_rate_ * packet_counter_) { 98 lost_packet_counter_++; 99 burst_lost_counter_ = 1; 100 return true; 101 } 102 return false; 103 } 104 105 SenderWithFEC::SenderWithFEC() : expected_loss_rate_(0) {} 106 107 void SenderWithFEC::Setup(const Environment& env, 108 AudioCodingModule* acm, 109 RTPStream* rtpStream, 110 absl::string_view in_file_name, 111 int payload_type, 112 SdpAudioFormat format, 113 int expected_loss_rate) { 114 Sender::Setup(env, acm, rtpStream, in_file_name, format.clockrate_hz, 115 payload_type, format); 116 EXPECT_TRUE(SetFEC(true)); 117 EXPECT_TRUE(SetPacketLossRate(expected_loss_rate)); 118 } 119 120 bool SenderWithFEC::SetFEC(bool enable_fec) { 121 bool success = false; 122 _acm->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* enc) { 123 if (*enc && (*enc)->SetFec(enable_fec)) { 124 success = true; 125 } 126 }); 127 return success; 128 } 129 130 bool SenderWithFEC::SetPacketLossRate(int expected_loss_rate) { 131 if (_acm->SetPacketLossRate(expected_loss_rate) == 0) { 132 expected_loss_rate_ = expected_loss_rate; 133 return true; 134 } 135 return false; 136 } 137 138 PacketLossTest::PacketLossTest(int channels, 139 int expected_loss_rate, 140 int actual_loss_rate, 141 int burst_length) 142 : channels_(channels), 143 in_file_name_(channels_ == 1 ? "audio_coding/testfile32kHz" 144 : "audio_coding/teststereo32kHz"), 145 sample_rate_hz_(32000), 146 expected_loss_rate_(expected_loss_rate), 147 actual_loss_rate_(actual_loss_rate), 148 burst_length_(burst_length) {} 149 150 void PacketLossTest::Perform() { 151 #ifndef WEBRTC_CODEC_OPUS 152 return; 153 #else 154 const Environment env = CreateEnvironment(); 155 RTPFile rtpFile; 156 std::unique_ptr<AudioCodingModule> acm(AudioCodingModule::Create()); 157 SdpAudioFormat send_format = SdpAudioFormat("opus", 48000, 2); 158 if (channels_ == 2) { 159 send_format.parameters = {{"stereo", "1"}}; 160 } 161 162 std::string fileName = 163 test::TempFilename(test::OutputPath(), "packet_loss_test"); 164 rtpFile.Open(fileName.c_str(), "wb+"); 165 rtpFile.WriteHeader(); 166 SenderWithFEC sender; 167 sender.Setup(env, acm.get(), &rtpFile, in_file_name_, 120, send_format, 168 expected_loss_rate_); 169 sender.Run(); 170 sender.Teardown(); 171 rtpFile.Close(); 172 173 rtpFile.Open(fileName.c_str(), "rb"); 174 rtpFile.ReadHeader(); 175 std::unique_ptr<NetEq> neteq = DefaultNetEqFactory().Create( 176 env, NetEq::Config(), CreateBuiltinAudioDecoderFactory()); 177 ReceiverWithPacketLoss receiver; 178 receiver.Setup(neteq.get(), &rtpFile, "packetLoss_out", channels_, 15, 179 actual_loss_rate_, burst_length_); 180 receiver.Run(); 181 receiver.Teardown(); 182 rtpFile.Close(); 183 #endif 184 } 185 186 } // namespace webrtc