EncodeDecodeTest.cc (8705B)
1 /* 2 * Copyright (c) 2012 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/EncodeDecodeTest.h" 12 13 #include <cstdint> 14 #include <cstdio> 15 #include <cstdlib> 16 #include <map> 17 #include <memory> 18 #include <string> 19 20 #include "absl/strings/string_view.h" 21 #include "api/array_view.h" 22 #include "api/audio_codecs/audio_format.h" 23 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 24 #include "api/audio_codecs/builtin_audio_encoder_factory.h" 25 #include "api/environment/environment.h" 26 #include "api/environment/environment_factory.h" 27 #include "api/neteq/default_neteq_factory.h" 28 #include "api/neteq/neteq.h" 29 #include "api/units/timestamp.h" 30 #include "modules/audio_coding/include/audio_coding_module.h" 31 #include "modules/audio_coding/include/audio_coding_module_typedefs.h" 32 #include "modules/audio_coding/test/RTPFile.h" 33 #include "rtc_base/strings/string_builder.h" 34 #include "test/gtest.h" 35 #include "test/testsupport/file_utils.h" 36 37 namespace webrtc { 38 39 namespace { 40 // Buffer size for stereo 48 kHz audio. 41 constexpr size_t kWebRtc10MsPcmAudio = 960; 42 43 } // namespace 44 45 TestPacketization::TestPacketization(RTPStream* rtpStream, uint16_t frequency) 46 : _rtpStream(rtpStream), _frequency(frequency), _seqNo(0) {} 47 48 TestPacketization::~TestPacketization() {} 49 50 int32_t TestPacketization::SendData( 51 const AudioFrameType /* frameType */, 52 const uint8_t payloadType, 53 const uint32_t timeStamp, 54 const uint8_t* payloadData, 55 const size_t payloadSize, 56 int64_t /* absolute_capture_timestamp_ms */) { 57 _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize, 58 _frequency); 59 return 1; 60 } 61 62 Sender::Sender() 63 : _acm(nullptr), _pcmFile(), _audioFrame(), _packetization(nullptr) {} 64 65 void Sender::Setup(const Environment& env, 66 AudioCodingModule* acm, 67 RTPStream* rtpStream, 68 absl::string_view in_file_name, 69 int in_sample_rate, 70 int payload_type, 71 SdpAudioFormat format) { 72 // Open input file 73 const std::string file_name = test::ResourcePath(in_file_name, "pcm"); 74 _pcmFile.Open(file_name, in_sample_rate, "rb"); 75 if (format.num_channels == 2) { 76 _pcmFile.ReadStereo(true); 77 } 78 // Set test length to 500 ms (50 blocks of 10 ms each). 79 _pcmFile.SetNum10MsBlocksToRead(50); 80 // Fast-forward 1 second (100 blocks) since the file starts with silence. 81 _pcmFile.FastForward(100); 82 83 acm->SetEncoder(CreateBuiltinAudioEncoderFactory()->Create( 84 env, format, {.payload_type = payload_type})); 85 _packetization = new TestPacketization(rtpStream, format.clockrate_hz); 86 EXPECT_EQ(0, acm->RegisterTransportCallback(_packetization)); 87 88 _acm = acm; 89 } 90 91 void Sender::Teardown() { 92 _pcmFile.Close(); 93 delete _packetization; 94 } 95 96 bool Sender::Add10MsData() { 97 if (!_pcmFile.EndOfFile()) { 98 EXPECT_GT(_pcmFile.Read10MsData(_audioFrame), 0); 99 int32_t ok = _acm->Add10MsData(_audioFrame); 100 EXPECT_GE(ok, 0); 101 return ok >= 0 ? true : false; 102 } 103 return false; 104 } 105 106 void Sender::Run() { 107 while (true) { 108 if (!Add10MsData()) { 109 break; 110 } 111 } 112 } 113 114 Receiver::Receiver() 115 : _playoutLengthSmpls(kWebRtc10MsPcmAudio), 116 _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {} 117 118 void Receiver::Setup(NetEq* neteq, 119 RTPStream* rtpStream, 120 absl::string_view out_file_name, 121 size_t channels, 122 int file_num) { 123 if (channels == 1) { 124 neteq->SetCodecs({{107, {"L16", 8000, 1}}, 125 {108, {"L16", 16000, 1}}, 126 {109, {"L16", 32000, 1}}, 127 {0, {"PCMU", 8000, 1}}, 128 {8, {"PCMA", 8000, 1}}, 129 {9, {"G722", 8000, 1}}, 130 {120, {"OPUS", 48000, 2}}, 131 {13, {"CN", 8000, 1}}, 132 {98, {"CN", 16000, 1}}, 133 {99, {"CN", 32000, 1}}}); 134 } else { 135 ASSERT_EQ(channels, 2u); 136 neteq->SetCodecs({{111, {"L16", 8000, 2}}, 137 {112, {"L16", 16000, 2}}, 138 {113, {"L16", 32000, 2}}, 139 {110, {"PCMU", 8000, 2}}, 140 {118, {"PCMA", 8000, 2}}, 141 {119, {"G722", 8000, 2}}, 142 {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}}}); 143 } 144 145 int playSampFreq; 146 std::string file_name; 147 StringBuilder file_stream; 148 file_stream << test::OutputPath() << out_file_name << file_num << ".pcm"; 149 file_name = file_stream.str(); 150 _rtpStream = rtpStream; 151 152 playSampFreq = 32000; 153 _pcmFile.Open(file_name, 32000, "wb+"); 154 155 _realPayloadSizeBytes = 0; 156 _playoutBuffer = new int16_t[kWebRtc10MsPcmAudio]; 157 _frequency = playSampFreq; 158 _neteq = neteq; 159 _firstTime = true; 160 } 161 162 void Receiver::Teardown() { 163 delete[] _playoutBuffer; 164 _pcmFile.Close(); 165 } 166 167 bool Receiver::IncomingPacket() { 168 if (!_rtpStream->EndOfFile()) { 169 if (_firstTime) { 170 _firstTime = false; 171 _realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload, 172 _payloadSizeBytes, &_nextTime); 173 if (_realPayloadSizeBytes == 0) { 174 if (_rtpStream->EndOfFile()) { 175 _firstTime = true; 176 return true; 177 } else { 178 return false; 179 } 180 } 181 } 182 183 EXPECT_GE( 184 0, _neteq->InsertPacket(_rtpHeader, 185 ArrayView<const uint8_t>(_incomingPayload, 186 _realPayloadSizeBytes), 187 /*receive_time=*/Timestamp::Millis(_nextTime))); 188 _realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload, 189 _payloadSizeBytes, &_nextTime); 190 if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) { 191 _firstTime = true; 192 } 193 } 194 return true; 195 } 196 197 bool Receiver::PlayoutData() { 198 AudioFrame audioFrame; 199 bool muted; 200 int ok = _neteq->GetAudio(&audioFrame, &muted); 201 if (muted) { 202 ADD_FAILURE(); 203 return false; 204 } 205 EXPECT_EQ(NetEq::kOK, ok); 206 if (ok < 0) { 207 return false; 208 } 209 if (_playoutLengthSmpls == 0) { 210 return false; 211 } 212 EXPECT_TRUE(_resampler_helper.MaybeResample(_frequency, &audioFrame)); 213 _pcmFile.Write10MsData(audioFrame.data(), audioFrame.samples_per_channel_ * 214 audioFrame.num_channels_); 215 return true; 216 } 217 218 void Receiver::Run() { 219 uint8_t counter500Ms = 50; 220 uint32_t clock = 0; 221 222 while (counter500Ms > 0) { 223 if (clock == 0 || clock >= _nextTime) { 224 EXPECT_TRUE(IncomingPacket()); 225 if (clock == 0) { 226 clock = _nextTime; 227 } 228 } 229 if ((clock % 10) == 0) { 230 if (!PlayoutData()) { 231 clock++; 232 continue; 233 } 234 } 235 if (_rtpStream->EndOfFile()) { 236 counter500Ms--; 237 } 238 clock++; 239 } 240 } 241 242 EncodeDecodeTest::EncodeDecodeTest() = default; 243 244 void EncodeDecodeTest::Perform() { 245 const std::map<int, SdpAudioFormat> send_codecs = { 246 {107, {"L16", 8000, 1}}, {108, {"L16", 16000, 1}}, 247 {109, {"L16", 32000, 1}}, {0, {"PCMU", 8000, 1}}, 248 {8, {"PCMA", 8000, 1}}, 249 // TODO(bugs.webrtc.org/345525069): Either fix/enable or remove G722. 250 #if defined(__has_feature) && !__has_feature(undefined_behavior_sanitizer) 251 {9, {"G722", 8000, 1}}, 252 #endif 253 }; 254 const Environment env = CreateEnvironment(); 255 int file_num = 0; 256 for (const auto& send_codec : send_codecs) { 257 RTPFile rtpFile; 258 std::unique_ptr<AudioCodingModule> acm(AudioCodingModule::Create()); 259 260 std::string fileName = 261 test::TempFilename(test::OutputPath(), "encode_decode_rtp"); 262 rtpFile.Open(fileName.c_str(), "wb+"); 263 rtpFile.WriteHeader(); 264 Sender sender; 265 sender.Setup(env, acm.get(), &rtpFile, "audio_coding/testfile32kHz", 32000, 266 send_codec.first, send_codec.second); 267 sender.Run(); 268 sender.Teardown(); 269 rtpFile.Close(); 270 271 rtpFile.Open(fileName.c_str(), "rb"); 272 rtpFile.ReadHeader(); 273 std::unique_ptr<NetEq> neteq = DefaultNetEqFactory().Create( 274 env, NetEq::Config(), CreateBuiltinAudioDecoderFactory()); 275 Receiver receiver; 276 receiver.Setup(neteq.get(), &rtpFile, "encodeDecode_out", 1, file_num); 277 receiver.Run(); 278 receiver.Teardown(); 279 rtpFile.Close(); 280 281 file_num++; 282 } 283 } 284 285 } // namespace webrtc