272 lines
8.1 KiB
C++
272 lines
8.1 KiB
C++
/*
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "modules/audio_coding/test/EncodeDecodeTest.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
|
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
|
#include "modules/audio_coding/include/audio_coding_module.h"
|
|
#include "rtc_base/strings/string_builder.h"
|
|
#include "test/gtest.h"
|
|
#include "test/testsupport/file_utils.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
// Buffer size for stereo 48 kHz audio.
|
|
constexpr size_t kWebRtc10MsPcmAudio = 960;
|
|
|
|
} // namespace
|
|
|
|
TestPacketization::TestPacketization(RTPStream* rtpStream, uint16_t frequency)
|
|
: _rtpStream(rtpStream), _frequency(frequency), _seqNo(0) {}
|
|
|
|
TestPacketization::~TestPacketization() {}
|
|
|
|
int32_t TestPacketization::SendData(const AudioFrameType /* frameType */,
|
|
const uint8_t payloadType,
|
|
const uint32_t timeStamp,
|
|
const uint8_t* payloadData,
|
|
const size_t payloadSize,
|
|
int64_t absolute_capture_timestamp_ms) {
|
|
_rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize,
|
|
_frequency);
|
|
return 1;
|
|
}
|
|
|
|
Sender::Sender()
|
|
: _acm(NULL), _pcmFile(), _audioFrame(), _packetization(NULL) {}
|
|
|
|
void Sender::Setup(AudioCodingModule* acm,
|
|
RTPStream* rtpStream,
|
|
std::string in_file_name,
|
|
int in_sample_rate,
|
|
int payload_type,
|
|
SdpAudioFormat format) {
|
|
// Open input file
|
|
const std::string file_name = webrtc::test::ResourcePath(in_file_name, "pcm");
|
|
_pcmFile.Open(file_name, in_sample_rate, "rb");
|
|
if (format.num_channels == 2) {
|
|
_pcmFile.ReadStereo(true);
|
|
}
|
|
// Set test length to 500 ms (50 blocks of 10 ms each).
|
|
_pcmFile.SetNum10MsBlocksToRead(50);
|
|
// Fast-forward 1 second (100 blocks) since the file starts with silence.
|
|
_pcmFile.FastForward(100);
|
|
|
|
acm->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
|
|
payload_type, format, absl::nullopt));
|
|
_packetization = new TestPacketization(rtpStream, format.clockrate_hz);
|
|
EXPECT_EQ(0, acm->RegisterTransportCallback(_packetization));
|
|
|
|
_acm = acm;
|
|
}
|
|
|
|
void Sender::Teardown() {
|
|
_pcmFile.Close();
|
|
delete _packetization;
|
|
}
|
|
|
|
bool Sender::Add10MsData() {
|
|
if (!_pcmFile.EndOfFile()) {
|
|
EXPECT_GT(_pcmFile.Read10MsData(_audioFrame), 0);
|
|
int32_t ok = _acm->Add10MsData(_audioFrame);
|
|
EXPECT_GE(ok, 0);
|
|
return ok >= 0 ? true : false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Sender::Run() {
|
|
while (true) {
|
|
if (!Add10MsData()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Receiver::Receiver()
|
|
: _playoutLengthSmpls(kWebRtc10MsPcmAudio),
|
|
_payloadSizeBytes(MAX_INCOMING_PAYLOAD) {}
|
|
|
|
void Receiver::Setup(AudioCodingModule* acm,
|
|
RTPStream* rtpStream,
|
|
std::string out_file_name,
|
|
size_t channels,
|
|
int file_num) {
|
|
EXPECT_EQ(0, acm->InitializeReceiver());
|
|
|
|
if (channels == 1) {
|
|
acm->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
|
|
{104, {"ISAC", 32000, 1}},
|
|
{107, {"L16", 8000, 1}},
|
|
{108, {"L16", 16000, 1}},
|
|
{109, {"L16", 32000, 1}},
|
|
{0, {"PCMU", 8000, 1}},
|
|
{8, {"PCMA", 8000, 1}},
|
|
{102, {"ILBC", 8000, 1}},
|
|
{9, {"G722", 8000, 1}},
|
|
{120, {"OPUS", 48000, 2}},
|
|
{13, {"CN", 8000, 1}},
|
|
{98, {"CN", 16000, 1}},
|
|
{99, {"CN", 32000, 1}}});
|
|
} else {
|
|
ASSERT_EQ(channels, 2u);
|
|
acm->SetReceiveCodecs({{111, {"L16", 8000, 2}},
|
|
{112, {"L16", 16000, 2}},
|
|
{113, {"L16", 32000, 2}},
|
|
{110, {"PCMU", 8000, 2}},
|
|
{118, {"PCMA", 8000, 2}},
|
|
{119, {"G722", 8000, 2}},
|
|
{120, {"OPUS", 48000, 2, {{"stereo", "1"}}}}});
|
|
}
|
|
|
|
int playSampFreq;
|
|
std::string file_name;
|
|
rtc::StringBuilder file_stream;
|
|
file_stream << webrtc::test::OutputPath() << out_file_name << file_num
|
|
<< ".pcm";
|
|
file_name = file_stream.str();
|
|
_rtpStream = rtpStream;
|
|
|
|
playSampFreq = 32000;
|
|
_pcmFile.Open(file_name, 32000, "wb+");
|
|
|
|
_realPayloadSizeBytes = 0;
|
|
_playoutBuffer = new int16_t[kWebRtc10MsPcmAudio];
|
|
_frequency = playSampFreq;
|
|
_acm = acm;
|
|
_firstTime = true;
|
|
}
|
|
|
|
void Receiver::Teardown() {
|
|
delete[] _playoutBuffer;
|
|
_pcmFile.Close();
|
|
}
|
|
|
|
bool Receiver::IncomingPacket() {
|
|
if (!_rtpStream->EndOfFile()) {
|
|
if (_firstTime) {
|
|
_firstTime = false;
|
|
_realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload,
|
|
_payloadSizeBytes, &_nextTime);
|
|
if (_realPayloadSizeBytes == 0) {
|
|
if (_rtpStream->EndOfFile()) {
|
|
_firstTime = true;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
EXPECT_EQ(0, _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes,
|
|
_rtpHeader));
|
|
_realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload,
|
|
_payloadSizeBytes, &_nextTime);
|
|
if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
|
|
_firstTime = true;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Receiver::PlayoutData() {
|
|
AudioFrame audioFrame;
|
|
bool muted;
|
|
int32_t ok = _acm->PlayoutData10Ms(_frequency, &audioFrame, &muted);
|
|
if (muted) {
|
|
ADD_FAILURE();
|
|
return false;
|
|
}
|
|
EXPECT_EQ(0, ok);
|
|
if (ok < 0) {
|
|
return false;
|
|
}
|
|
if (_playoutLengthSmpls == 0) {
|
|
return false;
|
|
}
|
|
_pcmFile.Write10MsData(audioFrame.data(), audioFrame.samples_per_channel_ *
|
|
audioFrame.num_channels_);
|
|
return true;
|
|
}
|
|
|
|
void Receiver::Run() {
|
|
uint8_t counter500Ms = 50;
|
|
uint32_t clock = 0;
|
|
|
|
while (counter500Ms > 0) {
|
|
if (clock == 0 || clock >= _nextTime) {
|
|
EXPECT_TRUE(IncomingPacket());
|
|
if (clock == 0) {
|
|
clock = _nextTime;
|
|
}
|
|
}
|
|
if ((clock % 10) == 0) {
|
|
if (!PlayoutData()) {
|
|
clock++;
|
|
continue;
|
|
}
|
|
}
|
|
if (_rtpStream->EndOfFile()) {
|
|
counter500Ms--;
|
|
}
|
|
clock++;
|
|
}
|
|
}
|
|
|
|
EncodeDecodeTest::EncodeDecodeTest() = default;
|
|
|
|
void EncodeDecodeTest::Perform() {
|
|
const std::map<int, SdpAudioFormat> send_codecs = {
|
|
{103, {"ISAC", 16000, 1}}, {104, {"ISAC", 32000, 1}},
|
|
{107, {"L16", 8000, 1}}, {108, {"L16", 16000, 1}},
|
|
{109, {"L16", 32000, 1}}, {0, {"PCMU", 8000, 1}},
|
|
{8, {"PCMA", 8000, 1}},
|
|
#ifdef WEBRTC_CODEC_ILBC
|
|
{102, {"ILBC", 8000, 1}},
|
|
#endif
|
|
{9, {"G722", 8000, 1}}};
|
|
int file_num = 0;
|
|
for (const auto& send_codec : send_codecs) {
|
|
RTPFile rtpFile;
|
|
std::unique_ptr<AudioCodingModule> acm(AudioCodingModule::Create(
|
|
AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory())));
|
|
|
|
std::string fileName = webrtc::test::TempFilename(
|
|
webrtc::test::OutputPath(), "encode_decode_rtp");
|
|
rtpFile.Open(fileName.c_str(), "wb+");
|
|
rtpFile.WriteHeader();
|
|
Sender sender;
|
|
sender.Setup(acm.get(), &rtpFile, "audio_coding/testfile32kHz", 32000,
|
|
send_codec.first, send_codec.second);
|
|
sender.Run();
|
|
sender.Teardown();
|
|
rtpFile.Close();
|
|
|
|
rtpFile.Open(fileName.c_str(), "rb");
|
|
rtpFile.ReadHeader();
|
|
Receiver receiver;
|
|
receiver.Setup(acm.get(), &rtpFile, "encodeDecode_out", 1, file_num);
|
|
receiver.Run();
|
|
receiver.Teardown();
|
|
rtpFile.Close();
|
|
|
|
file_num++;
|
|
}
|
|
}
|
|
|
|
} // namespace webrtc
|