Add tests for verifying transport feedback for audio and video.
BUG=webrtc:5263 R=mflodman@webrtc.org Review URL: https://codereview.webrtc.org/1589523002 . Cr-Commit-Position: refs/heads/master@{#11255}
This commit is contained in:
parent
fcfc804e43
commit
04cb763955
@ -31,7 +31,7 @@ CallTest::CallTest()
|
|||||||
audio_send_config_(nullptr),
|
audio_send_config_(nullptr),
|
||||||
audio_send_stream_(nullptr),
|
audio_send_stream_(nullptr),
|
||||||
fake_encoder_(clock_),
|
fake_encoder_(clock_),
|
||||||
num_video_streams_(0),
|
num_video_streams_(1),
|
||||||
num_audio_streams_(0),
|
num_audio_streams_(0),
|
||||||
fake_send_audio_device_(nullptr),
|
fake_send_audio_device_(nullptr),
|
||||||
fake_recv_audio_device_(nullptr) {}
|
fake_recv_audio_device_(nullptr) {}
|
||||||
@ -60,9 +60,9 @@ void CallTest::RunBaseTest(BaseTest* test) {
|
|||||||
}
|
}
|
||||||
CreateReceiverCall(recv_config);
|
CreateReceiverCall(recv_config);
|
||||||
}
|
}
|
||||||
|
test->OnCallsCreated(sender_call_.get(), receiver_call_.get());
|
||||||
send_transport_.reset(test->CreateSendTransport(sender_call_.get()));
|
send_transport_.reset(test->CreateSendTransport(sender_call_.get()));
|
||||||
receive_transport_.reset(test->CreateReceiveTransport());
|
receive_transport_.reset(test->CreateReceiveTransport());
|
||||||
test->OnCallsCreated(sender_call_.get(), receiver_call_.get());
|
|
||||||
|
|
||||||
if (test->ShouldCreateReceivers()) {
|
if (test->ShouldCreateReceivers()) {
|
||||||
send_transport_->SetReceiver(receiver_call_->Receiver());
|
send_transport_->SetReceiver(receiver_call_->Receiver());
|
||||||
@ -97,8 +97,10 @@ void CallTest::RunBaseTest(BaseTest* test) {
|
|||||||
test->OnAudioStreamsCreated(audio_send_stream_, audio_receive_streams_);
|
test->OnAudioStreamsCreated(audio_send_stream_, audio_receive_streams_);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateFrameGeneratorCapturer();
|
if (num_video_streams_ > 0) {
|
||||||
test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
|
CreateFrameGeneratorCapturer();
|
||||||
|
test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
|
||||||
|
}
|
||||||
|
|
||||||
Start();
|
Start();
|
||||||
test->PerformTest();
|
test->PerformTest();
|
||||||
@ -179,17 +181,20 @@ void CallTest::CreateSendConfig(size_t num_video_streams,
|
|||||||
RTC_DCHECK(num_video_streams <= kNumSsrcs);
|
RTC_DCHECK(num_video_streams <= kNumSsrcs);
|
||||||
RTC_DCHECK_LE(num_audio_streams, 1u);
|
RTC_DCHECK_LE(num_audio_streams, 1u);
|
||||||
RTC_DCHECK(num_audio_streams == 0 || voe_send_.channel_id >= 0);
|
RTC_DCHECK(num_audio_streams == 0 || voe_send_.channel_id >= 0);
|
||||||
video_send_config_ = VideoSendStream::Config(send_transport);
|
if (num_video_streams > 0) {
|
||||||
video_send_config_.encoder_settings.encoder = &fake_encoder_;
|
video_send_config_ = VideoSendStream::Config(send_transport);
|
||||||
video_send_config_.encoder_settings.payload_name = "FAKE";
|
video_send_config_.encoder_settings.encoder = &fake_encoder_;
|
||||||
video_send_config_.encoder_settings.payload_type = kFakeVideoSendPayloadType;
|
video_send_config_.encoder_settings.payload_name = "FAKE";
|
||||||
video_send_config_.rtp.extensions.push_back(
|
video_send_config_.encoder_settings.payload_type =
|
||||||
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
|
kFakeVideoSendPayloadType;
|
||||||
video_encoder_config_.streams = test::CreateVideoStreams(num_video_streams);
|
video_send_config_.rtp.extensions.push_back(
|
||||||
for (size_t i = 0; i < num_video_streams; ++i)
|
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
|
||||||
video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[i]);
|
video_encoder_config_.streams = test::CreateVideoStreams(num_video_streams);
|
||||||
video_send_config_.rtp.extensions.push_back(
|
for (size_t i = 0; i < num_video_streams; ++i)
|
||||||
RtpExtension(RtpExtension::kVideoRotation, kVideoRotationRtpExtensionId));
|
video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[i]);
|
||||||
|
video_send_config_.rtp.extensions.push_back(RtpExtension(
|
||||||
|
RtpExtension::kVideoRotation, kVideoRotationRtpExtensionId));
|
||||||
|
}
|
||||||
|
|
||||||
if (num_audio_streams > 0) {
|
if (num_audio_streams > 0) {
|
||||||
audio_send_config_ = AudioSendStream::Config(send_transport);
|
audio_send_config_ = AudioSendStream::Config(send_transport);
|
||||||
@ -199,27 +204,29 @@ void CallTest::CreateSendConfig(size_t num_video_streams,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CallTest::CreateMatchingReceiveConfigs(Transport* rtcp_send_transport) {
|
void CallTest::CreateMatchingReceiveConfigs(Transport* rtcp_send_transport) {
|
||||||
RTC_DCHECK(!video_send_config_.rtp.ssrcs.empty());
|
|
||||||
RTC_DCHECK(video_receive_configs_.empty());
|
RTC_DCHECK(video_receive_configs_.empty());
|
||||||
RTC_DCHECK(allocated_decoders_.empty());
|
RTC_DCHECK(allocated_decoders_.empty());
|
||||||
RTC_DCHECK(num_audio_streams_ == 0 || voe_send_.channel_id >= 0);
|
if (num_video_streams_ > 0) {
|
||||||
VideoReceiveStream::Config video_config(rtcp_send_transport);
|
RTC_DCHECK(!video_send_config_.rtp.ssrcs.empty());
|
||||||
video_config.rtp.remb = true;
|
VideoReceiveStream::Config video_config(rtcp_send_transport);
|
||||||
video_config.rtp.local_ssrc = kReceiverLocalVideoSsrc;
|
video_config.rtp.remb = true;
|
||||||
for (const RtpExtension& extension : video_send_config_.rtp.extensions)
|
video_config.rtp.local_ssrc = kReceiverLocalVideoSsrc;
|
||||||
video_config.rtp.extensions.push_back(extension);
|
for (const RtpExtension& extension : video_send_config_.rtp.extensions)
|
||||||
for (size_t i = 0; i < video_send_config_.rtp.ssrcs.size(); ++i) {
|
video_config.rtp.extensions.push_back(extension);
|
||||||
VideoReceiveStream::Decoder decoder =
|
for (size_t i = 0; i < video_send_config_.rtp.ssrcs.size(); ++i) {
|
||||||
test::CreateMatchingDecoder(video_send_config_.encoder_settings);
|
VideoReceiveStream::Decoder decoder =
|
||||||
allocated_decoders_.push_back(decoder.decoder);
|
test::CreateMatchingDecoder(video_send_config_.encoder_settings);
|
||||||
video_config.decoders.clear();
|
allocated_decoders_.push_back(decoder.decoder);
|
||||||
video_config.decoders.push_back(decoder);
|
video_config.decoders.clear();
|
||||||
video_config.rtp.remote_ssrc = video_send_config_.rtp.ssrcs[i];
|
video_config.decoders.push_back(decoder);
|
||||||
video_receive_configs_.push_back(video_config);
|
video_config.rtp.remote_ssrc = video_send_config_.rtp.ssrcs[i];
|
||||||
|
video_receive_configs_.push_back(video_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RTC_DCHECK(num_audio_streams_ <= 1);
|
RTC_DCHECK(num_audio_streams_ <= 1);
|
||||||
if (num_audio_streams_ == 1) {
|
if (num_audio_streams_ == 1) {
|
||||||
|
RTC_DCHECK(voe_send_.channel_id >= 0);
|
||||||
AudioReceiveStream::Config audio_config;
|
AudioReceiveStream::Config audio_config;
|
||||||
audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
|
audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
|
||||||
audio_config.rtcp_send_transport = rtcp_send_transport;
|
audio_config.rtcp_send_transport = rtcp_send_transport;
|
||||||
|
|||||||
@ -1542,82 +1542,115 @@ TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
|
|||||||
tester.RunTest();
|
tester.RunTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransportFeedbackTest(bool feedback_enabled) {
|
class TransportFeedbackTester : public test::EndToEndTest {
|
||||||
|
public:
|
||||||
|
explicit TransportFeedbackTester(bool feedback_enabled,
|
||||||
|
size_t num_video_streams,
|
||||||
|
size_t num_audio_streams)
|
||||||
|
: EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
|
||||||
|
feedback_enabled_(feedback_enabled),
|
||||||
|
num_video_streams_(num_video_streams),
|
||||||
|
num_audio_streams_(num_audio_streams) {
|
||||||
|
// Only one stream of each supported for now.
|
||||||
|
EXPECT_LE(num_video_streams, 1u);
|
||||||
|
EXPECT_LE(num_audio_streams, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Action OnSendRtcp(const uint8_t* data, size_t length) override {
|
||||||
|
EXPECT_FALSE(HasTransportFeedback(data, length));
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
|
||||||
|
if (HasTransportFeedback(data, length))
|
||||||
|
observation_complete_.Set();
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasTransportFeedback(const uint8_t* data, size_t length) const {
|
||||||
|
RTCPUtility::RTCPParserV2 parser(data, length, true);
|
||||||
|
EXPECT_TRUE(parser.IsValid());
|
||||||
|
|
||||||
|
RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
|
||||||
|
while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
|
||||||
|
if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback)
|
||||||
|
return true;
|
||||||
|
packet_type = parser.Iterate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerformTest() override {
|
||||||
|
const int64_t kDisabledFeedbackTimeoutMs = 5000;
|
||||||
|
EXPECT_EQ(feedback_enabled_,
|
||||||
|
observation_complete_.Wait(feedback_enabled_
|
||||||
|
? test::CallTest::kDefaultTimeoutMs
|
||||||
|
: kDisabledFeedbackTimeoutMs));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
|
||||||
|
receiver_call_ = receiver_call;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetNumVideoStreams() const override { return num_video_streams_; }
|
||||||
|
size_t GetNumAudioStreams() const override { return num_audio_streams_; }
|
||||||
|
|
||||||
|
void ModifyVideoConfigs(
|
||||||
|
VideoSendStream::Config* send_config,
|
||||||
|
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||||
|
VideoEncoderConfig* encoder_config) override {
|
||||||
|
send_config->rtp.extensions.clear();
|
||||||
|
send_config->rtp.extensions.push_back(
|
||||||
|
RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
|
||||||
|
(*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
|
||||||
|
(*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModifyAudioConfigs(
|
||||||
|
AudioSendStream::Config* send_config,
|
||||||
|
std::vector<AudioReceiveStream::Config>* receive_configs) override {
|
||||||
|
send_config->rtp.extensions.clear();
|
||||||
|
send_config->rtp.extensions.push_back(
|
||||||
|
RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
|
||||||
|
(*receive_configs)[0].rtp.extensions.clear();
|
||||||
|
(*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
|
||||||
|
(*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
|
||||||
|
(*receive_configs)[0].combined_audio_video_bwe = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
static const int kExtensionId = 5;
|
static const int kExtensionId = 5;
|
||||||
class TransportFeedbackObserver : public test::DirectTransport {
|
const bool feedback_enabled_;
|
||||||
public:
|
const size_t num_video_streams_;
|
||||||
TransportFeedbackObserver(Call* receiver_call, rtc::Event* done_event)
|
const size_t num_audio_streams_;
|
||||||
: DirectTransport(receiver_call), done_(done_event) {}
|
Call* receiver_call_;
|
||||||
virtual ~TransportFeedbackObserver() {}
|
};
|
||||||
|
|
||||||
bool SendRtcp(const uint8_t* data, size_t length) override {
|
TEST_F(EndToEndTest, VideoReceivesTransportFeedback) {
|
||||||
RTCPUtility::RTCPParserV2 parser(data, length, true);
|
TransportFeedbackTester test(true, 1, 0);
|
||||||
EXPECT_TRUE(parser.IsValid());
|
RunBaseTest(&test);
|
||||||
|
|
||||||
RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
|
|
||||||
while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
|
|
||||||
if (packet_type == RTCPUtility::RTCPPacketTypes::kTransportFeedback) {
|
|
||||||
done_->Set();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
packet_type = parser.Iterate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return test::DirectTransport::SendRtcp(data, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Event* done_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TransportFeedbackTester : public MultiStreamTest {
|
|
||||||
public:
|
|
||||||
explicit TransportFeedbackTester(bool feedback_enabled)
|
|
||||||
: feedback_enabled_(feedback_enabled), done_(false, false) {}
|
|
||||||
virtual ~TransportFeedbackTester() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void Wait() override {
|
|
||||||
const int64_t kDisabledFeedbackTimeoutMs = 5000;
|
|
||||||
EXPECT_EQ(feedback_enabled_, done_.Wait(feedback_enabled_
|
|
||||||
? test::CallTest::kDefaultTimeoutMs
|
|
||||||
: kDisabledFeedbackTimeoutMs));
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateSendConfig(
|
|
||||||
size_t stream_index,
|
|
||||||
VideoSendStream::Config* send_config,
|
|
||||||
VideoEncoderConfig* encoder_config,
|
|
||||||
test::FrameGeneratorCapturer** frame_generator) override {
|
|
||||||
send_config->rtp.extensions.push_back(
|
|
||||||
RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateReceiveConfig(
|
|
||||||
size_t stream_index,
|
|
||||||
VideoReceiveStream::Config* receive_config) override {
|
|
||||||
receive_config->rtp.extensions.push_back(
|
|
||||||
RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
|
|
||||||
receive_config->rtp.transport_cc = feedback_enabled_;
|
|
||||||
}
|
|
||||||
|
|
||||||
test::DirectTransport* CreateReceiveTransport(
|
|
||||||
Call* receiver_call) override {
|
|
||||||
return new TransportFeedbackObserver(receiver_call, &done_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const bool feedback_enabled_;
|
|
||||||
rtc::Event done_;
|
|
||||||
} tester(feedback_enabled);
|
|
||||||
tester.RunTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EndToEndTest, ReceivesTransportFeedback) {
|
TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) {
|
||||||
TransportFeedbackTest(true);
|
TransportFeedbackTester test(false, 1, 0);
|
||||||
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EndToEndTest, TransportFeedbackNotConfigured) {
|
TEST_F(EndToEndTest, AudioReceivesTransportFeedback) {
|
||||||
TransportFeedbackTest(false);
|
TransportFeedbackTester test(true, 0, 1);
|
||||||
|
RunBaseTest(&test);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) {
|
||||||
|
TransportFeedbackTester test(false, 0, 1);
|
||||||
|
RunBaseTest(&test);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) {
|
||||||
|
TransportFeedbackTester test(true, 1, 1);
|
||||||
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EndToEndTest, ObserversEncodedFrames) {
|
TEST_F(EndToEndTest, ObserversEncodedFrames) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user