Let FlexfecReceiveStreamImpl send RTCP RRs.
This CL adds an RTP module to FlexfecReceiveStreamImpl, and wires it up to send RTCP RRs. It further makes some methods take const refs instead of values, to make it more clear where packet copies are made. This change reduces the number of copies by one, for the case when media packets are added to the FlexFEC receiver. The end-to-end test is modified to check for RTCP RRs being sent. Part of this modification involves some indentation changes, and the diff thus looks bigger than it logically is. BUG=webrtc:5654 Review-Url: https://codereview.webrtc.org/2625633003 Cr-Commit-Position: refs/heads/master@{#16106}
This commit is contained in:
parent
9506e12eba
commit
fa5a368b3c
@ -702,8 +702,9 @@ FlexfecReceiveStream* Call::CreateFlexfecReceiveStream(
|
|||||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||||
|
|
||||||
RecoveredPacketReceiver* recovered_packet_receiver = this;
|
RecoveredPacketReceiver* recovered_packet_receiver = this;
|
||||||
FlexfecReceiveStreamImpl* receive_stream =
|
FlexfecReceiveStreamImpl* receive_stream = new FlexfecReceiveStreamImpl(
|
||||||
new FlexfecReceiveStreamImpl(config, recovered_packet_receiver);
|
config, recovered_packet_receiver, call_stats_->rtcp_rtt_stats(),
|
||||||
|
module_process_thread_.get());
|
||||||
|
|
||||||
{
|
{
|
||||||
WriteLockScoped write_lock(*receive_crit_);
|
WriteLockScoped write_lock(*receive_crit_);
|
||||||
@ -1165,10 +1166,9 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type,
|
|||||||
ParseRtpPacket(packet, length, packet_time);
|
ParseRtpPacket(packet, length, packet_time);
|
||||||
if (parsed_packet) {
|
if (parsed_packet) {
|
||||||
NotifyBweOfReceivedPacket(*parsed_packet);
|
NotifyBweOfReceivedPacket(*parsed_packet);
|
||||||
auto status =
|
auto status = it->second->AddAndProcessReceivedPacket(*parsed_packet)
|
||||||
it->second->AddAndProcessReceivedPacket(std::move(*parsed_packet))
|
? DELIVERY_OK
|
||||||
? DELIVERY_OK
|
: DELIVERY_PACKET_ERROR;
|
||||||
: DELIVERY_PACKET_ERROR;
|
|
||||||
if (status == DELIVERY_OK)
|
if (status == DELIVERY_OK)
|
||||||
event_log_->LogRtpHeader(kIncomingPacket, media_type, packet, length);
|
event_log_->LogRtpHeader(kIncomingPacket, media_type, packet, length);
|
||||||
return status;
|
return status;
|
||||||
|
|||||||
@ -10,10 +10,16 @@
|
|||||||
|
|
||||||
#include "webrtc/call/flexfec_receive_stream_impl.h"
|
#include "webrtc/call/flexfec_receive_stream_impl.h"
|
||||||
|
|
||||||
#include <utility>
|
#include <string>
|
||||||
|
|
||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||||
|
#include "webrtc/modules/utility/include/process_thread.h"
|
||||||
|
#include "webrtc/system_wrappers/include/clock.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -97,33 +103,77 @@ std::unique_ptr<FlexfecReceiver> MaybeCreateFlexfecReceiver(
|
|||||||
recovered_packet_receiver));
|
recovered_packet_receiver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<RtpRtcp> CreateRtpRtcpModule(
|
||||||
|
ReceiveStatistics* receive_statistics,
|
||||||
|
Transport* rtcp_send_transport,
|
||||||
|
RtcpRttStats* rtt_stats) {
|
||||||
|
RtpRtcp::Configuration configuration;
|
||||||
|
configuration.audio = false;
|
||||||
|
configuration.receiver_only = true;
|
||||||
|
configuration.clock = Clock::GetRealTimeClock();
|
||||||
|
configuration.receive_statistics = receive_statistics;
|
||||||
|
configuration.outgoing_transport = rtcp_send_transport;
|
||||||
|
configuration.rtt_stats = rtt_stats;
|
||||||
|
std::unique_ptr<RtpRtcp> rtp_rtcp(RtpRtcp::CreateRtpRtcp(configuration));
|
||||||
|
return rtp_rtcp;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FlexfecReceiveStreamImpl::FlexfecReceiveStreamImpl(
|
FlexfecReceiveStreamImpl::FlexfecReceiveStreamImpl(
|
||||||
const Config& config,
|
const Config& config,
|
||||||
RecoveredPacketReceiver* recovered_packet_receiver)
|
RecoveredPacketReceiver* recovered_packet_receiver,
|
||||||
: started_(false),
|
RtcpRttStats* rtt_stats,
|
||||||
config_(config),
|
ProcessThread* process_thread)
|
||||||
receiver_(
|
: config_(config),
|
||||||
MaybeCreateFlexfecReceiver(config_, recovered_packet_receiver)) {
|
started_(false),
|
||||||
|
receiver_(MaybeCreateFlexfecReceiver(config_, recovered_packet_receiver)),
|
||||||
|
rtp_receive_statistics_(
|
||||||
|
ReceiveStatistics::Create(Clock::GetRealTimeClock())),
|
||||||
|
rtp_rtcp_(CreateRtpRtcpModule(rtp_receive_statistics_.get(),
|
||||||
|
config_.rtcp_send_transport,
|
||||||
|
rtt_stats)),
|
||||||
|
process_thread_(process_thread) {
|
||||||
LOG(LS_INFO) << "FlexfecReceiveStreamImpl: " << config_.ToString();
|
LOG(LS_INFO) << "FlexfecReceiveStreamImpl: " << config_.ToString();
|
||||||
|
|
||||||
|
// RTCP reporting.
|
||||||
|
rtp_rtcp_->SetSendingMediaStatus(false);
|
||||||
|
rtp_rtcp_->SetRTCPStatus(config_.rtcp_mode);
|
||||||
|
rtp_rtcp_->SetSSRC(config_.local_ssrc);
|
||||||
|
process_thread_->RegisterModule(rtp_rtcp_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
FlexfecReceiveStreamImpl::~FlexfecReceiveStreamImpl() {
|
FlexfecReceiveStreamImpl::~FlexfecReceiveStreamImpl() {
|
||||||
LOG(LS_INFO) << "~FlexfecReceiveStreamImpl: " << config_.ToString();
|
LOG(LS_INFO) << "~FlexfecReceiveStreamImpl: " << config_.ToString();
|
||||||
Stop();
|
Stop();
|
||||||
|
process_thread_->DeRegisterModule(rtp_rtcp_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlexfecReceiveStreamImpl::AddAndProcessReceivedPacket(
|
bool FlexfecReceiveStreamImpl::AddAndProcessReceivedPacket(
|
||||||
RtpPacketReceived packet) {
|
const RtpPacketReceived& packet) {
|
||||||
{
|
{
|
||||||
rtc::CritScope cs(&crit_);
|
rtc::CritScope cs(&crit_);
|
||||||
if (!started_)
|
if (!started_)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!receiver_)
|
if (!receiver_)
|
||||||
return false;
|
return false;
|
||||||
return receiver_->AddAndProcessReceivedPacket(std::move(packet));
|
|
||||||
|
if (!receiver_->AddAndProcessReceivedPacket(packet))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Do not report media packets in the RTCP RRs generated by |rtp_rtcp_|.
|
||||||
|
if (packet.Ssrc() == config_.remote_ssrc) {
|
||||||
|
RTPHeader header;
|
||||||
|
packet.GetHeader(&header);
|
||||||
|
// FlexFEC packets are never retransmitted.
|
||||||
|
const bool kNotRetransmitted = false;
|
||||||
|
rtp_receive_statistics_->IncomingPacket(header, packet.size(),
|
||||||
|
kNotRetransmitted);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlexfecReceiveStreamImpl::Start() {
|
void FlexfecReceiveStreamImpl::Start() {
|
||||||
|
|||||||
@ -12,25 +12,31 @@
|
|||||||
#define WEBRTC_CALL_FLEXFEC_RECEIVE_STREAM_IMPL_H_
|
#define WEBRTC_CALL_FLEXFEC_RECEIVE_STREAM_IMPL_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "webrtc/base/basictypes.h"
|
|
||||||
#include "webrtc/base/criticalsection.h"
|
#include "webrtc/base/criticalsection.h"
|
||||||
#include "webrtc/call/flexfec_receive_stream.h"
|
#include "webrtc/call/flexfec_receive_stream.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
|
|
||||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class FlexfecReceiver;
|
||||||
|
class ProcessThread;
|
||||||
|
class ReceiveStatistics;
|
||||||
|
class RecoveredPacketReceiver;
|
||||||
|
class RtcpRttStats;
|
||||||
|
class RtpPacketReceived;
|
||||||
|
class RtpRtcp;
|
||||||
|
|
||||||
class FlexfecReceiveStreamImpl : public FlexfecReceiveStream {
|
class FlexfecReceiveStreamImpl : public FlexfecReceiveStream {
|
||||||
public:
|
public:
|
||||||
FlexfecReceiveStreamImpl(const Config& config,
|
FlexfecReceiveStreamImpl(const Config& config,
|
||||||
RecoveredPacketReceiver* recovered_packet_receiver);
|
RecoveredPacketReceiver* recovered_packet_receiver,
|
||||||
|
RtcpRttStats* rtt_stats,
|
||||||
|
ProcessThread* process_thread);
|
||||||
~FlexfecReceiveStreamImpl() override;
|
~FlexfecReceiveStreamImpl() override;
|
||||||
|
|
||||||
const Config& GetConfig() const { return config_; }
|
const Config& GetConfig() const { return config_; }
|
||||||
|
|
||||||
bool AddAndProcessReceivedPacket(RtpPacketReceived packet);
|
bool AddAndProcessReceivedPacket(const RtpPacketReceived& packet);
|
||||||
|
|
||||||
// Implements FlexfecReceiveStream.
|
// Implements FlexfecReceiveStream.
|
||||||
void Start() override;
|
void Start() override;
|
||||||
@ -38,11 +44,18 @@ class FlexfecReceiveStreamImpl : public FlexfecReceiveStream {
|
|||||||
Stats GetStats() const override;
|
Stats GetStats() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rtc::CriticalSection crit_;
|
// Config.
|
||||||
bool started_ GUARDED_BY(crit_);
|
|
||||||
|
|
||||||
const Config config_;
|
const Config config_;
|
||||||
|
bool started_ GUARDED_BY(crit_);
|
||||||
|
rtc::CriticalSection crit_;
|
||||||
|
|
||||||
|
// Erasure code interfacing.
|
||||||
const std::unique_ptr<FlexfecReceiver> receiver_;
|
const std::unique_ptr<FlexfecReceiver> receiver_;
|
||||||
|
|
||||||
|
// RTCP reporting.
|
||||||
|
const std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
|
||||||
|
const std::unique_ptr<RtpRtcp> rtp_rtcp_;
|
||||||
|
ProcessThread* process_thread_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -12,10 +12,13 @@
|
|||||||
|
|
||||||
#include "webrtc/base/array_view.h"
|
#include "webrtc/base/array_view.h"
|
||||||
#include "webrtc/call/flexfec_receive_stream_impl.h"
|
#include "webrtc/call/flexfec_receive_stream_impl.h"
|
||||||
|
#include "webrtc/modules/pacing/packet_router.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
|
#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
|
#include "webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
|
||||||
|
#include "webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
|
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
|
||||||
|
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
|
||||||
#include "webrtc/test/gmock.h"
|
#include "webrtc/test/gmock.h"
|
||||||
#include "webrtc/test/gtest.h"
|
#include "webrtc/test/gtest.h"
|
||||||
#include "webrtc/test/mock_transport.h"
|
#include "webrtc/test/mock_transport.h"
|
||||||
@ -74,11 +77,16 @@ class FlexfecReceiveStreamTest : public ::testing::Test {
|
|||||||
protected:
|
protected:
|
||||||
FlexfecReceiveStreamTest()
|
FlexfecReceiveStreamTest()
|
||||||
: config_(CreateDefaultConfig(&rtcp_send_transport_)),
|
: config_(CreateDefaultConfig(&rtcp_send_transport_)),
|
||||||
receive_stream_(config_, &recovered_packet_receiver_) {}
|
receive_stream_(config_,
|
||||||
|
&recovered_packet_receiver_,
|
||||||
|
&rtt_stats_,
|
||||||
|
&process_thread_) {}
|
||||||
|
|
||||||
|
MockTransport rtcp_send_transport_;
|
||||||
FlexfecReceiveStream::Config config_;
|
FlexfecReceiveStream::Config config_;
|
||||||
MockRecoveredPacketReceiver recovered_packet_receiver_;
|
MockRecoveredPacketReceiver recovered_packet_receiver_;
|
||||||
MockTransport rtcp_send_transport_;
|
MockRtcpRttStats rtt_stats_;
|
||||||
|
MockProcessThread process_thread_;
|
||||||
|
|
||||||
FlexfecReceiveStreamImpl receive_stream_;
|
FlexfecReceiveStreamImpl receive_stream_;
|
||||||
};
|
};
|
||||||
@ -126,7 +134,8 @@ TEST_F(FlexfecReceiveStreamTest, RecoversPacketWhenStarted) {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver;
|
testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver;
|
||||||
FlexfecReceiveStreamImpl receive_stream(config_, &recovered_packet_receiver);
|
FlexfecReceiveStreamImpl receive_stream(config_, &recovered_packet_receiver,
|
||||||
|
&rtt_stats_, &process_thread_);
|
||||||
|
|
||||||
// Do not call back before being started.
|
// Do not call back before being started.
|
||||||
receive_stream.AddAndProcessReceivedPacket(ParsePacket(kFlexfecPacket));
|
receive_stream.AddAndProcessReceivedPacket(ParsePacket(kFlexfecPacket));
|
||||||
|
|||||||
@ -2219,6 +2219,7 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
config_.rtp.local_ssrc = local_ssrc;
|
config_.rtp.local_ssrc = local_ssrc;
|
||||||
|
flexfec_config_.local_ssrc = local_ssrc;
|
||||||
LOG(LS_INFO)
|
LOG(LS_INFO)
|
||||||
<< "RecreateWebRtcStream (recv) because of SetLocalSsrc; local_ssrc="
|
<< "RecreateWebRtcStream (recv) because of SetLocalSsrc; local_ssrc="
|
||||||
<< local_ssrc;
|
<< local_ssrc;
|
||||||
@ -2246,6 +2247,7 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetFeedbackParameters(
|
|||||||
config_.rtp.nack.rtp_history_ms = nack_history_ms;
|
config_.rtp.nack.rtp_history_ms = nack_history_ms;
|
||||||
config_.rtp.transport_cc = transport_cc_enabled;
|
config_.rtp.transport_cc = transport_cc_enabled;
|
||||||
config_.rtp.rtcp_mode = rtcp_mode;
|
config_.rtp.rtcp_mode = rtcp_mode;
|
||||||
|
flexfec_config_.rtcp_mode = rtcp_mode;
|
||||||
LOG(LS_INFO)
|
LOG(LS_INFO)
|
||||||
<< "RecreateWebRtcStream (recv) because of SetFeedbackParameters; nack="
|
<< "RecreateWebRtcStream (recv) because of SetFeedbackParameters; nack="
|
||||||
<< nack_enabled << ", remb=" << remb_enabled
|
<< nack_enabled << ", remb=" << remb_enabled
|
||||||
|
|||||||
@ -43,13 +43,13 @@ class FlexfecReceiver {
|
|||||||
// Inserts a received packet (can be either media or FlexFEC) into the
|
// Inserts a received packet (can be either media or FlexFEC) into the
|
||||||
// internal buffer, and sends the received packets to the erasure code.
|
// internal buffer, and sends the received packets to the erasure code.
|
||||||
// All newly recovered packets are sent back through the callback.
|
// All newly recovered packets are sent back through the callback.
|
||||||
bool AddAndProcessReceivedPacket(RtpPacketReceived packet);
|
bool AddAndProcessReceivedPacket(const RtpPacketReceived& packet);
|
||||||
|
|
||||||
// Returns a counter describing the added and recovered packets.
|
// Returns a counter describing the added and recovered packets.
|
||||||
FecPacketCounter GetPacketCounter() const;
|
FecPacketCounter GetPacketCounter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool AddReceivedPacket(RtpPacketReceived packet);
|
bool AddReceivedPacket(const RtpPacketReceived& packet);
|
||||||
bool ProcessReceivedPackets();
|
bool ProcessReceivedPackets();
|
||||||
|
|
||||||
// Config.
|
// Config.
|
||||||
|
|||||||
@ -45,7 +45,8 @@ FlexfecReceiver::FlexfecReceiver(
|
|||||||
|
|
||||||
FlexfecReceiver::~FlexfecReceiver() = default;
|
FlexfecReceiver::~FlexfecReceiver() = default;
|
||||||
|
|
||||||
bool FlexfecReceiver::AddAndProcessReceivedPacket(RtpPacketReceived packet) {
|
bool FlexfecReceiver::AddAndProcessReceivedPacket(
|
||||||
|
const RtpPacketReceived& packet) {
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||||
if (!AddReceivedPacket(std::move(packet))) {
|
if (!AddReceivedPacket(std::move(packet))) {
|
||||||
return false;
|
return false;
|
||||||
@ -58,7 +59,7 @@ FecPacketCounter FlexfecReceiver::GetPacketCounter() const {
|
|||||||
return packet_counter_;
|
return packet_counter_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlexfecReceiver::AddReceivedPacket(RtpPacketReceived packet) {
|
bool FlexfecReceiver::AddReceivedPacket(const RtpPacketReceived& packet) {
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
||||||
|
|
||||||
// RTP packets with a full base header (12 bytes), but without payload,
|
// RTP packets with a full base header (12 bytes), but without payload,
|
||||||
|
|||||||
@ -279,6 +279,7 @@ void CallTest::CreateMatchingReceiveConfigs(Transport* rtcp_send_transport) {
|
|||||||
config.payload_type = kFlexfecPayloadType;
|
config.payload_type = kFlexfecPayloadType;
|
||||||
config.remote_ssrc = kFlexfecSendSsrc;
|
config.remote_ssrc = kFlexfecSendSsrc;
|
||||||
config.protected_media_ssrcs = {kVideoSendSsrcs[0]};
|
config.protected_media_ssrcs = {kVideoSendSsrcs[0]};
|
||||||
|
config.local_ssrc = kReceiverLocalVideoSsrc;
|
||||||
for (const RtpExtension& extension : video_send_config_.rtp.extensions)
|
for (const RtpExtension& extension : video_send_config_.rtp.extensions)
|
||||||
config.rtp_header_extensions.push_back(extension);
|
config.rtp_header_extensions.push_back(extension);
|
||||||
flexfec_receive_configs_.push_back(config);
|
flexfec_receive_configs_.push_back(config);
|
||||||
|
|||||||
@ -56,7 +56,6 @@ class CallTest : public ::testing::Test {
|
|||||||
static const uint32_t kFlexfecSendSsrc;
|
static const uint32_t kFlexfecSendSsrc;
|
||||||
static const uint32_t kReceiverLocalVideoSsrc;
|
static const uint32_t kReceiverLocalVideoSsrc;
|
||||||
static const uint32_t kReceiverLocalAudioSsrc;
|
static const uint32_t kReceiverLocalAudioSsrc;
|
||||||
static const uint32_t kReceiverLocalFlexfecSsrc;
|
|
||||||
static const int kNackRtpHistoryMs;
|
static const int kNackRtpHistoryMs;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -705,84 +705,126 @@ TEST_P(EndToEndTest, CanReceiveUlpfec) {
|
|||||||
RunBaseTest(&test);
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(EndToEndTest, CanReceiveFlexfec) {
|
class FlexfecRenderObserver : public test::EndToEndTest,
|
||||||
class FlexfecRenderObserver : public test::EndToEndTest,
|
public rtc::VideoSinkInterface<VideoFrame> {
|
||||||
public rtc::VideoSinkInterface<VideoFrame> {
|
public:
|
||||||
public:
|
static constexpr uint32_t kVideoLocalSsrc = 123;
|
||||||
FlexfecRenderObserver()
|
static constexpr uint32_t kFlexfecLocalSsrc = 456;
|
||||||
: EndToEndTest(kDefaultTimeoutMs), random_(0xcafef00d1) {}
|
|
||||||
|
|
||||||
size_t GetNumFlexfecStreams() const override { return 1; }
|
explicit FlexfecRenderObserver(bool expect_flexfec_rtcp)
|
||||||
|
: test::EndToEndTest(test::CallTest::kDefaultTimeoutMs),
|
||||||
|
expect_flexfec_rtcp_(expect_flexfec_rtcp),
|
||||||
|
received_flexfec_rtcp_(false),
|
||||||
|
random_(0xcafef00d1) {}
|
||||||
|
|
||||||
private:
|
size_t GetNumFlexfecStreams() const override { return 1; }
|
||||||
Action OnSendRtp(const uint8_t* packet, size_t length) override {
|
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
RTPHeader header;
|
|
||||||
EXPECT_TRUE(parser_->Parse(packet, length, &header));
|
|
||||||
|
|
||||||
uint8_t payload_type = header.payloadType;
|
private:
|
||||||
if (payload_type != kFakeVideoSendPayloadType) {
|
Action OnSendRtp(const uint8_t* packet, size_t length) override {
|
||||||
EXPECT_EQ(kFlexfecPayloadType, payload_type);
|
rtc::CritScope lock(&crit_);
|
||||||
}
|
RTPHeader header;
|
||||||
|
EXPECT_TRUE(parser_->Parse(packet, length, &header));
|
||||||
|
|
||||||
// Is this a retransmitted media packet? From the perspective of FEC, this
|
uint8_t payload_type = header.payloadType;
|
||||||
// packet is then no longer dropped, so remove it from the list of
|
if (payload_type != test::CallTest::kFakeVideoSendPayloadType) {
|
||||||
// dropped packets.
|
EXPECT_EQ(test::CallTest::kFlexfecPayloadType, payload_type);
|
||||||
if (payload_type == kFakeVideoSendPayloadType) {
|
|
||||||
auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
|
|
||||||
if (seq_num_it != dropped_sequence_numbers_.end()) {
|
|
||||||
dropped_sequence_numbers_.erase(seq_num_it);
|
|
||||||
auto ts_it = dropped_timestamps_.find(header.timestamp);
|
|
||||||
EXPECT_NE(ts_it, dropped_timestamps_.end());
|
|
||||||
dropped_timestamps_.erase(ts_it);
|
|
||||||
|
|
||||||
return SEND_PACKET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simulate 5% packet loss. Record what media packets, and corresponding
|
|
||||||
// timestamps, that were dropped.
|
|
||||||
if (random_.Rand(1, 100) <= 5) {
|
|
||||||
if (payload_type == kFakeVideoSendPayloadType) {
|
|
||||||
dropped_sequence_numbers_.insert(header.sequenceNumber);
|
|
||||||
dropped_timestamps_.insert(header.timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DROP_PACKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SEND_PACKET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnFrame(const VideoFrame& video_frame) override {
|
// Is this a retransmitted media packet? From the perspective of FEC, this
|
||||||
rtc::CritScope lock(&crit_);
|
// packet is then no longer dropped, so remove it from the list of
|
||||||
// Rendering frame with timestamp of packet that was dropped -> FEC
|
// dropped packets.
|
||||||
// protection worked.
|
if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
|
||||||
auto it = dropped_timestamps_.find(video_frame.timestamp());
|
auto seq_num_it = dropped_sequence_numbers_.find(header.sequenceNumber);
|
||||||
if (it != dropped_timestamps_.end())
|
if (seq_num_it != dropped_sequence_numbers_.end()) {
|
||||||
|
dropped_sequence_numbers_.erase(seq_num_it);
|
||||||
|
auto ts_it = dropped_timestamps_.find(header.timestamp);
|
||||||
|
EXPECT_NE(ts_it, dropped_timestamps_.end());
|
||||||
|
dropped_timestamps_.erase(ts_it);
|
||||||
|
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate 5% packet loss. Record what media packets, and corresponding
|
||||||
|
// timestamps, that were dropped.
|
||||||
|
if (random_.Rand(1, 100) <= 5) {
|
||||||
|
if (payload_type == test::CallTest::kFakeVideoSendPayloadType) {
|
||||||
|
dropped_sequence_numbers_.insert(header.sequenceNumber);
|
||||||
|
dropped_timestamps_.insert(header.timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DROP_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
|
||||||
|
test::RtcpPacketParser parser;
|
||||||
|
|
||||||
|
parser.Parse(data, length);
|
||||||
|
if (parser.sender_ssrc() == kFlexfecLocalSsrc) {
|
||||||
|
EXPECT_EQ(1, parser.receiver_report()->num_packets());
|
||||||
|
const std::vector<rtcp::ReportBlock>& report_blocks =
|
||||||
|
parser.receiver_report()->report_blocks();
|
||||||
|
if (!report_blocks.empty()) {
|
||||||
|
EXPECT_EQ(1U, report_blocks.size());
|
||||||
|
EXPECT_EQ(test::CallTest::kFlexfecSendSsrc,
|
||||||
|
report_blocks[0].source_ssrc());
|
||||||
|
received_flexfec_rtcp_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnFrame(const VideoFrame& video_frame) override {
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
// Rendering frame with timestamp of packet that was dropped -> FEC
|
||||||
|
// protection worked.
|
||||||
|
auto it = dropped_timestamps_.find(video_frame.timestamp());
|
||||||
|
if (it != dropped_timestamps_.end()) {
|
||||||
|
if (!expect_flexfec_rtcp_ || received_flexfec_rtcp_) {
|
||||||
observation_complete_.Set();
|
observation_complete_.Set();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ModifyVideoConfigs(
|
void ModifyVideoConfigs(
|
||||||
VideoSendStream::Config* send_config,
|
VideoSendStream::Config* send_config,
|
||||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||||
VideoEncoderConfig* encoder_config) override {
|
VideoEncoderConfig* encoder_config) override {
|
||||||
(*receive_configs)[0].renderer = this;
|
(*receive_configs)[0].rtp.local_ssrc = kVideoLocalSsrc;
|
||||||
}
|
(*receive_configs)[0].renderer = this;
|
||||||
|
}
|
||||||
|
|
||||||
void PerformTest() override {
|
void ModifyFlexfecConfigs(
|
||||||
EXPECT_TRUE(Wait())
|
std::vector<FlexfecReceiveStream::Config>* receive_configs) override {
|
||||||
<< "Timed out waiting for dropped frames to be rendered.";
|
(*receive_configs)[0].local_ssrc = kFlexfecLocalSsrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc::CriticalSection crit_;
|
void PerformTest() override {
|
||||||
std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
|
EXPECT_TRUE(Wait())
|
||||||
// Since several packets can have the same timestamp a multiset is used
|
<< "Timed out waiting for dropped frames to be rendered.";
|
||||||
// instead of a set.
|
}
|
||||||
std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
|
|
||||||
Random random_;
|
|
||||||
} test;
|
|
||||||
|
|
||||||
|
rtc::CriticalSection crit_;
|
||||||
|
std::set<uint32_t> dropped_sequence_numbers_ GUARDED_BY(crit_);
|
||||||
|
// Since several packets can have the same timestamp a multiset is used
|
||||||
|
// instead of a set.
|
||||||
|
std::multiset<uint32_t> dropped_timestamps_ GUARDED_BY(crit_);
|
||||||
|
bool expect_flexfec_rtcp_;
|
||||||
|
bool received_flexfec_rtcp_;
|
||||||
|
Random random_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(EndToEndTest, ReceivesFlexfec) {
|
||||||
|
FlexfecRenderObserver test(false);
|
||||||
|
RunBaseTest(&test);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(EndToEndTest, ReceivesFlexfecAndSendsCorrespondingRtcp) {
|
||||||
|
FlexfecRenderObserver test(true);
|
||||||
RunBaseTest(&test);
|
RunBaseTest(&test);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1121,6 +1121,7 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
|
|||||||
flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
|
flexfec_receive_config.remote_ssrc = video_send_config_.rtp.flexfec.ssrc;
|
||||||
flexfec_receive_config.protected_media_ssrcs =
|
flexfec_receive_config.protected_media_ssrcs =
|
||||||
video_send_config_.rtp.flexfec.protected_media_ssrcs;
|
video_send_config_.rtp.flexfec.protected_media_ssrcs;
|
||||||
|
flexfec_receive_config.local_ssrc = kReceiverLocalVideoSsrc;
|
||||||
flexfec_receive_config.transport_cc = params_.call.send_side_bwe;
|
flexfec_receive_config.transport_cc = params_.call.send_side_bwe;
|
||||||
if (params_.call.send_side_bwe) {
|
if (params_.call.send_side_bwe) {
|
||||||
flexfec_receive_config.rtp_header_extensions.push_back(
|
flexfec_receive_config.rtp_header_extensions.push_back(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user