Resurrected test_api_audio.cc
I'll be doing some changes to code it tests (rtp_receiver_audio, specifically) and want to make sure there are tests in place before I touch anything. Fixed test_api_audio not properly checking payload data. Required a fix to LoopBackTransport in test_api to as to act like the regular audio and video parts of WebRTC and separate payload from header data. Also added a test for CNG and cleaned up constants. BUG=webrtc:5805 Review-Url: https://codereview.webrtc.org/2378403004 Cr-Commit-Position: refs/heads/master@{#14529}
This commit is contained in:
@ -14,6 +14,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/base/rate_limiter.h"
|
#include "webrtc/base/rate_limiter.h"
|
||||||
#include "webrtc/test/null_transport.h"
|
#include "webrtc/test/null_transport.h"
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ bool LoopBackTransport::SendRtp(const uint8_t* data,
|
|||||||
}
|
}
|
||||||
RTPHeader header;
|
RTPHeader header;
|
||||||
std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
|
std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
|
||||||
if (!parser->Parse(static_cast<const uint8_t*>(data), len, &header)) {
|
if (!parser->Parse(data, len, &header)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PayloadUnion payload_specific;
|
PayloadUnion payload_specific;
|
||||||
@ -52,9 +53,11 @@ bool LoopBackTransport::SendRtp(const uint8_t* data,
|
|||||||
&payload_specific)) {
|
&payload_specific)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const uint8_t* payload = data + header.headerLength;
|
||||||
|
RTC_CHECK_GE(len, header.headerLength);
|
||||||
|
const size_t payload_length = len - header.headerLength;
|
||||||
receive_statistics_->IncomingPacket(header, len, false);
|
receive_statistics_->IncomingPacket(header, len, false);
|
||||||
if (!rtp_receiver_->IncomingRtpPacket(header,
|
if (!rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
|
||||||
static_cast<const uint8_t*>(data), len,
|
|
||||||
payload_specific, true)) {
|
payload_specific, true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,30 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
#define test_rate 64000u
|
|
||||||
|
const uint32_t kTestRate = 64000u;
|
||||||
|
const uint8_t kTestPayload[] = { 't', 'e', 's', 't' };
|
||||||
|
const uint8_t kPcmuPayloadType = 96;
|
||||||
|
const uint8_t kDtmfPayloadType = 97;
|
||||||
|
|
||||||
|
struct CngCodecSpec {
|
||||||
|
int payload_type;
|
||||||
|
int clockrate_hz;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CngCodecSpec kCngCodecs[] = {{13, 8000},
|
||||||
|
{103, 16000},
|
||||||
|
{104, 32000},
|
||||||
|
{105, 48000}};
|
||||||
|
|
||||||
|
bool IsComfortNoisePayload(uint8_t payload_type) {
|
||||||
|
for (const auto& c : kCngCodecs) {
|
||||||
|
if (c.payload_type == payload_type)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class VerifyingAudioReceiver : public NullRtpData {
|
class VerifyingAudioReceiver : public NullRtpData {
|
||||||
public:
|
public:
|
||||||
@ -30,31 +53,16 @@ class VerifyingAudioReceiver : public NullRtpData {
|
|||||||
const uint8_t* payloadData,
|
const uint8_t* payloadData,
|
||||||
size_t payloadSize,
|
size_t payloadSize,
|
||||||
const webrtc::WebRtcRTPHeader* rtpHeader) override {
|
const webrtc::WebRtcRTPHeader* rtpHeader) override {
|
||||||
if (rtpHeader->header.payloadType == 98 ||
|
const uint8_t payload_type = rtpHeader->header.payloadType;
|
||||||
rtpHeader->header.payloadType == 99) {
|
if (payload_type == kPcmuPayloadType || payload_type == kDtmfPayloadType) {
|
||||||
EXPECT_EQ(4u, payloadSize);
|
EXPECT_EQ(sizeof(kTestPayload), payloadSize);
|
||||||
char str[5];
|
// All our test vectors for PCMU and DTMF are equal to |kTestPayload|.
|
||||||
memcpy(str, payloadData, payloadSize);
|
const size_t min_size = std::min(sizeof(kTestPayload), payloadSize);
|
||||||
str[4] = 0;
|
EXPECT_EQ(0, memcmp(payloadData, kTestPayload, min_size));
|
||||||
// All our test vectors for payload type 96 and 97 even the stereo is on
|
} else if (IsComfortNoisePayload(payload_type)) {
|
||||||
// a per channel base equal to the 4 chars "test".
|
// CNG types should be recognized properly.
|
||||||
// Note there is no null termination so we add that to use the
|
EXPECT_EQ(kAudioFrameCN, rtpHeader->frameType);
|
||||||
// test EXPECT_STRCASEEQ.
|
EXPECT_TRUE(rtpHeader->type.Audio.isCNG);
|
||||||
EXPECT_STRCASEEQ("test", str);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (rtpHeader->header.payloadType == 100 ||
|
|
||||||
rtpHeader->header.payloadType == 101 ||
|
|
||||||
rtpHeader->header.payloadType == 102) {
|
|
||||||
if (rtpHeader->type.Audio.channel == 1) {
|
|
||||||
if (payloadData[0] == 0xff) {
|
|
||||||
// All our test vectors for payload type 100, 101 and 102 have the
|
|
||||||
// first channel data being equal to 0xff.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ADD_FAILURE() << "This code path should never happen.";
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -67,14 +75,16 @@ class RTPCallback : public NullRtpFeedback {
|
|||||||
const int frequency,
|
const int frequency,
|
||||||
const size_t channels,
|
const size_t channels,
|
||||||
const uint32_t rate) override {
|
const uint32_t rate) override {
|
||||||
if (payloadType == 96) {
|
if (payloadType == kPcmuPayloadType) {
|
||||||
EXPECT_EQ(test_rate, rate) <<
|
EXPECT_EQ(kTestRate, rate) <<
|
||||||
"The rate should be 64K for this payloadType";
|
"The rate should be 64K for this payloadType";
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class RtpRtcpAudioTest : public ::testing::Test {
|
class RtpRtcpAudioTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
RtpRtcpAudioTest()
|
RtpRtcpAudioTest()
|
||||||
@ -88,12 +98,6 @@ class RtpRtcpAudioTest : public ::testing::Test {
|
|||||||
~RtpRtcpAudioTest() {}
|
~RtpRtcpAudioTest() {}
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
data_receiver1 = new VerifyingAudioReceiver();
|
|
||||||
data_receiver2 = new VerifyingAudioReceiver();
|
|
||||||
rtp_callback = new RTPCallback();
|
|
||||||
transport1 = new LoopBackTransport();
|
|
||||||
transport2 = new LoopBackTransport();
|
|
||||||
|
|
||||||
receive_statistics1_.reset(ReceiveStatistics::Create(&fake_clock));
|
receive_statistics1_.reset(ReceiveStatistics::Create(&fake_clock));
|
||||||
receive_statistics2_.reset(ReceiveStatistics::Create(&fake_clock));
|
receive_statistics2_.reset(ReceiveStatistics::Create(&fake_clock));
|
||||||
|
|
||||||
@ -106,49 +110,58 @@ class RtpRtcpAudioTest : public ::testing::Test {
|
|||||||
configuration.audio = true;
|
configuration.audio = true;
|
||||||
configuration.clock = &fake_clock;
|
configuration.clock = &fake_clock;
|
||||||
configuration.receive_statistics = receive_statistics1_.get();
|
configuration.receive_statistics = receive_statistics1_.get();
|
||||||
configuration.outgoing_transport = transport1;
|
configuration.outgoing_transport = &transport1;
|
||||||
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
|
|
||||||
module1 = RtpRtcp::CreateRtpRtcp(configuration);
|
module1.reset(RtpRtcp::CreateRtpRtcp(configuration));
|
||||||
rtp_receiver1_.reset(RtpReceiver::CreateAudioReceiver(
|
rtp_receiver1_.reset(RtpReceiver::CreateAudioReceiver(
|
||||||
&fake_clock, data_receiver1, NULL, rtp_payload_registry1_.get()));
|
&fake_clock, &data_receiver1, &rtp_callback,
|
||||||
|
rtp_payload_registry1_.get()));
|
||||||
|
|
||||||
configuration.receive_statistics = receive_statistics2_.get();
|
configuration.receive_statistics = receive_statistics2_.get();
|
||||||
configuration.outgoing_transport = transport2;
|
configuration.outgoing_transport = &transport2;
|
||||||
|
|
||||||
module2 = RtpRtcp::CreateRtpRtcp(configuration);
|
module2.reset(RtpRtcp::CreateRtpRtcp(configuration));
|
||||||
rtp_receiver2_.reset(RtpReceiver::CreateAudioReceiver(
|
rtp_receiver2_.reset(RtpReceiver::CreateAudioReceiver(
|
||||||
&fake_clock, data_receiver2, NULL, rtp_payload_registry2_.get()));
|
&fake_clock, &data_receiver2, &rtp_callback,
|
||||||
|
rtp_payload_registry2_.get()));
|
||||||
|
|
||||||
transport1->SetSendModule(module2, rtp_payload_registry2_.get(),
|
transport1.SetSendModule(module2.get(), rtp_payload_registry2_.get(),
|
||||||
rtp_receiver2_.get(), receive_statistics2_.get());
|
rtp_receiver2_.get(), receive_statistics2_.get());
|
||||||
transport2->SetSendModule(module1, rtp_payload_registry1_.get(),
|
transport2.SetSendModule(module1.get(), rtp_payload_registry1_.get(),
|
||||||
rtp_receiver1_.get(), receive_statistics1_.get());
|
rtp_receiver1_.get(), receive_statistics1_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
void RegisterPayload(const CodecInst& codec) {
|
||||||
delete module1;
|
EXPECT_EQ(0, module1->RegisterSendPayload(codec));
|
||||||
delete module2;
|
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
|
||||||
delete transport1;
|
codec.plname,
|
||||||
delete transport2;
|
codec.pltype,
|
||||||
delete data_receiver1;
|
codec.plfreq,
|
||||||
delete data_receiver2;
|
codec.channels,
|
||||||
delete rtp_callback;
|
codec.rate));
|
||||||
|
EXPECT_EQ(0, module2->RegisterSendPayload(codec));
|
||||||
|
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
|
||||||
|
codec.plname,
|
||||||
|
codec.pltype,
|
||||||
|
codec.plfreq,
|
||||||
|
codec.channels,
|
||||||
|
codec.rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpRtcp* module1;
|
VerifyingAudioReceiver data_receiver1;
|
||||||
RtpRtcp* module2;
|
VerifyingAudioReceiver data_receiver2;
|
||||||
|
RTPCallback rtp_callback;
|
||||||
std::unique_ptr<ReceiveStatistics> receive_statistics1_;
|
std::unique_ptr<ReceiveStatistics> receive_statistics1_;
|
||||||
std::unique_ptr<ReceiveStatistics> receive_statistics2_;
|
std::unique_ptr<ReceiveStatistics> receive_statistics2_;
|
||||||
std::unique_ptr<RtpReceiver> rtp_receiver1_;
|
|
||||||
std::unique_ptr<RtpReceiver> rtp_receiver2_;
|
|
||||||
std::unique_ptr<RTPPayloadRegistry> rtp_payload_registry1_;
|
std::unique_ptr<RTPPayloadRegistry> rtp_payload_registry1_;
|
||||||
std::unique_ptr<RTPPayloadRegistry> rtp_payload_registry2_;
|
std::unique_ptr<RTPPayloadRegistry> rtp_payload_registry2_;
|
||||||
VerifyingAudioReceiver* data_receiver1;
|
std::unique_ptr<RtpReceiver> rtp_receiver1_;
|
||||||
VerifyingAudioReceiver* data_receiver2;
|
std::unique_ptr<RtpReceiver> rtp_receiver2_;
|
||||||
LoopBackTransport* transport1;
|
std::unique_ptr<RtpRtcp> module1;
|
||||||
LoopBackTransport* transport2;
|
std::unique_ptr<RtpRtcp> module2;
|
||||||
RTPCallback* rtp_callback;
|
LoopBackTransport transport1;
|
||||||
|
LoopBackTransport transport2;
|
||||||
uint32_t test_ssrc;
|
uint32_t test_ssrc;
|
||||||
uint32_t test_timestamp;
|
uint32_t test_timestamp;
|
||||||
uint16_t test_sequence_number;
|
uint16_t test_sequence_number;
|
||||||
@ -170,36 +183,20 @@ TEST_F(RtpRtcpAudioTest, Basic) {
|
|||||||
|
|
||||||
// Send an empty RTP packet.
|
// Send an empty RTP packet.
|
||||||
// Should fail since we have not registered the payload type.
|
// Should fail since we have not registered the payload type.
|
||||||
EXPECT_FALSE(module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96, 0, -1,
|
EXPECT_FALSE(module1->SendOutgoingData(webrtc::kAudioFrameSpeech,
|
||||||
nullptr, 0, nullptr, nullptr,
|
kPcmuPayloadType, 0, -1, nullptr, 0,
|
||||||
nullptr));
|
nullptr, nullptr, nullptr));
|
||||||
|
|
||||||
CodecInst voice_codec;
|
CodecInst voice_codec = {};
|
||||||
memset(&voice_codec, 0, sizeof(voice_codec));
|
voice_codec.pltype = kPcmuPayloadType;
|
||||||
voice_codec.pltype = 96;
|
|
||||||
voice_codec.plfreq = 8000;
|
voice_codec.plfreq = 8000;
|
||||||
|
voice_codec.rate = kTestRate;
|
||||||
memcpy(voice_codec.plname, "PCMU", 5);
|
memcpy(voice_codec.plname, "PCMU", 5);
|
||||||
|
RegisterPayload(voice_codec);
|
||||||
|
|
||||||
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
|
EXPECT_TRUE(module1->SendOutgoingData(webrtc::kAudioFrameSpeech,
|
||||||
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
|
kPcmuPayloadType, 0, -1, kTestPayload,
|
||||||
voice_codec.plname,
|
4, nullptr, nullptr, nullptr));
|
||||||
voice_codec.pltype,
|
|
||||||
voice_codec.plfreq,
|
|
||||||
voice_codec.channels,
|
|
||||||
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
|
|
||||||
EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
|
|
||||||
voice_codec.rate = test_rate;
|
|
||||||
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
|
|
||||||
voice_codec.plname,
|
|
||||||
voice_codec.pltype,
|
|
||||||
voice_codec.plfreq,
|
|
||||||
voice_codec.channels,
|
|
||||||
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
|
|
||||||
|
|
||||||
const uint8_t test[5] = "test";
|
|
||||||
EXPECT_EQ(true,
|
|
||||||
module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96, 0, -1,
|
|
||||||
test, 4, nullptr, nullptr, nullptr));
|
|
||||||
|
|
||||||
EXPECT_EQ(test_ssrc, rtp_receiver2_->SSRC());
|
EXPECT_EQ(test_ssrc, rtp_receiver2_->SSRC());
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
@ -208,34 +205,19 @@ TEST_F(RtpRtcpAudioTest, Basic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RtpRtcpAudioTest, DTMF) {
|
TEST_F(RtpRtcpAudioTest, DTMF) {
|
||||||
CodecInst voice_codec;
|
CodecInst voice_codec = {};
|
||||||
memset(&voice_codec, 0, sizeof(voice_codec));
|
voice_codec.pltype = kPcmuPayloadType;
|
||||||
voice_codec.pltype = 96;
|
|
||||||
voice_codec.plfreq = 8000;
|
voice_codec.plfreq = 8000;
|
||||||
|
voice_codec.rate = kTestRate;
|
||||||
memcpy(voice_codec.plname, "PCMU", 5);
|
memcpy(voice_codec.plname, "PCMU", 5);
|
||||||
|
RegisterPayload(voice_codec);
|
||||||
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
|
|
||||||
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
|
|
||||||
voice_codec.plname,
|
|
||||||
voice_codec.pltype,
|
|
||||||
voice_codec.plfreq,
|
|
||||||
voice_codec.channels,
|
|
||||||
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
|
|
||||||
EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
|
|
||||||
voice_codec.rate = test_rate;
|
|
||||||
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
|
|
||||||
voice_codec.plname,
|
|
||||||
voice_codec.pltype,
|
|
||||||
voice_codec.plfreq,
|
|
||||||
voice_codec.channels,
|
|
||||||
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
|
|
||||||
|
|
||||||
module1->SetSSRC(test_ssrc);
|
module1->SetSSRC(test_ssrc);
|
||||||
module1->SetStartTimestamp(test_timestamp);
|
module1->SetStartTimestamp(test_timestamp);
|
||||||
EXPECT_EQ(0, module1->SetSendingStatus(true));
|
EXPECT_EQ(0, module1->SetSendingStatus(true));
|
||||||
|
|
||||||
// Prepare for DTMF.
|
// Prepare for DTMF.
|
||||||
voice_codec.pltype = 97;
|
voice_codec.pltype = kDtmfPayloadType;
|
||||||
voice_codec.plfreq = 8000;
|
voice_codec.plfreq = 8000;
|
||||||
memcpy(voice_codec.plname, "telephone-event", 16);
|
memcpy(voice_codec.plname, "telephone-event", 16);
|
||||||
|
|
||||||
@ -245,7 +227,7 @@ TEST_F(RtpRtcpAudioTest, DTMF) {
|
|||||||
voice_codec.pltype,
|
voice_codec.pltype,
|
||||||
voice_codec.plfreq,
|
voice_codec.plfreq,
|
||||||
voice_codec.channels,
|
voice_codec.channels,
|
||||||
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
|
voice_codec.rate));
|
||||||
|
|
||||||
// Start DTMF test.
|
// Start DTMF test.
|
||||||
int timeStamp = 160;
|
int timeStamp = 160;
|
||||||
@ -256,27 +238,70 @@ TEST_F(RtpRtcpAudioTest, DTMF) {
|
|||||||
}
|
}
|
||||||
timeStamp += 160; // Prepare for next packet.
|
timeStamp += 160; // Prepare for next packet.
|
||||||
|
|
||||||
const uint8_t test[9] = "test";
|
|
||||||
|
|
||||||
// Send RTP packets for 16 tones a 160 ms 100ms
|
// Send RTP packets for 16 tones a 160 ms 100ms
|
||||||
// pause between = 2560ms + 1600ms = 4160ms
|
// pause between = 2560ms + 1600ms = 4160ms
|
||||||
for (; timeStamp <= 250 * 160; timeStamp += 160) {
|
for (; timeStamp <= 250 * 160; timeStamp += 160) {
|
||||||
EXPECT_TRUE(module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
|
EXPECT_TRUE(module1->SendOutgoingData(
|
||||||
timeStamp, -1, test, 4, nullptr,
|
webrtc::kAudioFrameSpeech, kPcmuPayloadType, timeStamp, -1,
|
||||||
nullptr, nullptr));
|
kTestPayload, 4, nullptr, nullptr, nullptr));
|
||||||
fake_clock.AdvanceTimeMilliseconds(20);
|
fake_clock.AdvanceTimeMilliseconds(20);
|
||||||
module1->Process();
|
module1->Process();
|
||||||
}
|
}
|
||||||
EXPECT_EQ(0, module1->SendTelephoneEventOutband(32, 9000, 10));
|
EXPECT_EQ(0, module1->SendTelephoneEventOutband(32, 9000, 10));
|
||||||
|
|
||||||
for (; timeStamp <= 740 * 160; timeStamp += 160) {
|
for (; timeStamp <= 740 * 160; timeStamp += 160) {
|
||||||
EXPECT_TRUE(module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96,
|
EXPECT_TRUE(module1->SendOutgoingData(
|
||||||
timeStamp, -1, test, 4, nullptr,
|
webrtc::kAudioFrameSpeech, kPcmuPayloadType, timeStamp, -1,
|
||||||
nullptr, nullptr));
|
kTestPayload, 4, nullptr, nullptr, nullptr));
|
||||||
fake_clock.AdvanceTimeMilliseconds(20);
|
fake_clock.AdvanceTimeMilliseconds(20);
|
||||||
module1->Process();
|
module1->Process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
TEST_F(RtpRtcpAudioTest, ComfortNoise) {
|
||||||
|
module1->SetSSRC(test_ssrc);
|
||||||
|
module1->SetStartTimestamp(test_timestamp);
|
||||||
|
|
||||||
|
EXPECT_EQ(0, module1->SetSendingStatus(true));
|
||||||
|
|
||||||
|
// Register PCMU and all four comfort noise codecs
|
||||||
|
CodecInst voice_codec = {};
|
||||||
|
voice_codec.pltype = kPcmuPayloadType;
|
||||||
|
voice_codec.plfreq = 8000;
|
||||||
|
voice_codec.rate = kTestRate;
|
||||||
|
memcpy(voice_codec.plname, "PCMU", 5);
|
||||||
|
RegisterPayload(voice_codec);
|
||||||
|
|
||||||
|
for (const auto& c : kCngCodecs) {
|
||||||
|
CodecInst cng_codec = {};
|
||||||
|
cng_codec.pltype = c.payload_type;
|
||||||
|
cng_codec.plfreq = c.clockrate_hz;
|
||||||
|
memcpy(cng_codec.plname, "CN", 3);
|
||||||
|
RegisterPayload(cng_codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transmit comfort noise packets interleaved by PCMU packets.
|
||||||
|
uint32_t in_timestamp = 0;
|
||||||
|
for (const auto& c : kCngCodecs) {
|
||||||
|
uint32_t timestamp;
|
||||||
|
EXPECT_TRUE(module1->SendOutgoingData(
|
||||||
|
webrtc::kAudioFrameSpeech, kPcmuPayloadType, in_timestamp, -1,
|
||||||
|
kTestPayload, 4, nullptr, nullptr, nullptr));
|
||||||
|
|
||||||
|
EXPECT_EQ(test_ssrc, rtp_receiver2_->SSRC());
|
||||||
|
EXPECT_TRUE(rtp_receiver2_->Timestamp(×tamp));
|
||||||
|
EXPECT_EQ(test_timestamp + in_timestamp, timestamp);
|
||||||
|
in_timestamp += 10;
|
||||||
|
|
||||||
|
EXPECT_TRUE(module1->SendOutgoingData(webrtc::kAudioFrameCN, c.payload_type,
|
||||||
|
in_timestamp, -1, kTestPayload, 1,
|
||||||
|
nullptr, nullptr, nullptr));
|
||||||
|
|
||||||
|
EXPECT_EQ(test_ssrc, rtp_receiver2_->SSRC());
|
||||||
|
EXPECT_TRUE(rtp_receiver2_->Timestamp(×tamp));
|
||||||
|
EXPECT_EQ(test_timestamp + in_timestamp, timestamp);
|
||||||
|
in_timestamp += 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
Reference in New Issue
Block a user