Add SetRetransmissionMode() to FecController, this will be used to control RTX settings in FecController.
Currently FecController knows about network conditions, these information can be used to control RTX settings in-call. Change-Id: I8f84164aeac48ea13b7f1cf82fd7424431f98ada Bug: webrtc:15167 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/304800 Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Reviewed-by: Per Kjellander <perkj@webrtc.org> Commit-Queue: Ying Wang <yinwa@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40192}
This commit is contained in:
parent
3d6e88e6ac
commit
2d598535aa
@ -31,6 +31,9 @@ class VCMProtectionCallback {
|
||||
uint32_t* sent_nack_rate_bps,
|
||||
uint32_t* sent_fec_rate_bps) = 0;
|
||||
|
||||
// 'retransmission_mode' is either a value of enum RetransmissionMode, or
|
||||
// computed with bitwise operators on values of enum RetransmissionMode.
|
||||
virtual void SetRetransmissionMode(int retransmission_mode) = 0;
|
||||
protected:
|
||||
virtual ~VCMProtectionCallback() {}
|
||||
};
|
||||
|
||||
@ -935,6 +935,13 @@ int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RtpVideoSender::SetRetransmissionMode(int retransmission_mode) {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const RtpStreamSender& stream : rtp_streams_) {
|
||||
stream.sender_video->SetRetransmissionSetting(retransmission_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void RtpVideoSender::SetFecAllowed(bool fec_allowed) {
|
||||
MutexLock lock(&mutex_);
|
||||
fec_allowed_ = fec_allowed;
|
||||
|
||||
@ -120,6 +120,11 @@ class RtpVideoSender : public RtpVideoSenderInterface,
|
||||
uint32_t* sent_fec_rate_bps)
|
||||
RTC_LOCKS_EXCLUDED(mutex_) override;
|
||||
|
||||
// 'retransmission_mode' is either a value of enum RetransmissionMode, or
|
||||
// computed with bitwise operators on values of enum RetransmissionMode.
|
||||
void SetRetransmissionMode(int retransmission_mode)
|
||||
RTC_LOCKS_EXCLUDED(mutex_) override;
|
||||
|
||||
// Implements FecControllerOverride.
|
||||
void SetFecAllowed(bool fec_allowed) RTC_LOCKS_EXCLUDED(mutex_) override;
|
||||
|
||||
|
||||
@ -1160,4 +1160,82 @@ TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
|
||||
EXPECT_NE(sent_packets[0].Timestamp(), first_frame_timestamp);
|
||||
}
|
||||
|
||||
// Integration test verifying that when retransmission mode is set to
|
||||
// kRetransmitBaseLayer,only base layer is retransmitted.
|
||||
TEST(RtpVideoSenderTest, RetransmitsBaseLayerOnly) {
|
||||
RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
|
||||
kPayloadType, {});
|
||||
test.SetActiveModules({true, true});
|
||||
|
||||
test.router()->SetRetransmissionMode(kRetransmitBaseLayer);
|
||||
constexpr uint8_t kPayload = 'a';
|
||||
EncodedImage encoded_image;
|
||||
encoded_image.SetTimestamp(1);
|
||||
encoded_image.capture_time_ms_ = 2;
|
||||
encoded_image._frameType = VideoFrameType::kVideoFrameKey;
|
||||
encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
|
||||
|
||||
// Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
|
||||
std::vector<uint16_t> rtp_sequence_numbers;
|
||||
std::vector<uint16_t> transport_sequence_numbers;
|
||||
std::vector<uint16_t> base_sequence_numbers;
|
||||
EXPECT_CALL(test.transport(), SendRtp)
|
||||
.Times(2)
|
||||
.WillRepeatedly([&rtp_sequence_numbers, &transport_sequence_numbers](
|
||||
const uint8_t* packet, size_t length,
|
||||
const PacketOptions& options) {
|
||||
RtpPacket rtp_packet;
|
||||
EXPECT_TRUE(rtp_packet.Parse(packet, length));
|
||||
rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
|
||||
transport_sequence_numbers.push_back(options.packet_id);
|
||||
return true;
|
||||
});
|
||||
CodecSpecificInfo key_codec_info;
|
||||
key_codec_info.codecType = kVideoCodecVP8;
|
||||
key_codec_info.codecSpecific.VP8.temporalIdx = 0;
|
||||
EXPECT_EQ(EncodedImageCallback::Result::OK,
|
||||
test.router()->OnEncodedImage(
|
||||
encoded_image, &key_codec_info).error);
|
||||
encoded_image.SetTimestamp(2);
|
||||
encoded_image.capture_time_ms_ = 3;
|
||||
encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
|
||||
CodecSpecificInfo delta_codec_info;
|
||||
delta_codec_info.codecType = kVideoCodecVP8;
|
||||
delta_codec_info.codecSpecific.VP8.temporalIdx = 1;
|
||||
EXPECT_EQ(EncodedImageCallback::Result::OK,
|
||||
test.router()->OnEncodedImage(
|
||||
encoded_image, &delta_codec_info).error);
|
||||
|
||||
test.AdvanceTime(TimeDelta::Millis(33));
|
||||
|
||||
// Construct a NACK message for requesting retransmission of both packet.
|
||||
rtcp::Nack nack;
|
||||
nack.SetMediaSsrc(kSsrc1);
|
||||
nack.SetPacketIds(rtp_sequence_numbers);
|
||||
rtc::Buffer nack_buffer = nack.Build();
|
||||
|
||||
std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
|
||||
EXPECT_CALL(test.transport(), SendRtp)
|
||||
.Times(1)
|
||||
.WillRepeatedly([&retransmitted_rtp_sequence_numbers](
|
||||
const uint8_t* packet, size_t length,
|
||||
const PacketOptions& options) {
|
||||
RtpPacket rtp_packet;
|
||||
EXPECT_TRUE(rtp_packet.Parse(packet, length));
|
||||
EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
|
||||
// Capture the retransmitted sequence number from the RTX header.
|
||||
rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
|
||||
retransmitted_rtp_sequence_numbers.push_back(
|
||||
ByteReader<uint16_t>::ReadBigEndian(payload.data()));
|
||||
return true;
|
||||
});
|
||||
test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
|
||||
test.AdvanceTime(TimeDelta::Millis(33));
|
||||
|
||||
// Verify that only base layer packet was retransmitted.
|
||||
std::vector<uint16_t> base_rtp_sequence_numbers(rtp_sequence_numbers.begin(),
|
||||
rtp_sequence_numbers.begin() + 1);
|
||||
EXPECT_EQ(retransmitted_rtp_sequence_numbers, base_rtp_sequence_numbers);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -223,6 +223,11 @@ size_t RTPSenderVideo::FecPacketOverhead() const {
|
||||
return overhead;
|
||||
}
|
||||
|
||||
void RTPSenderVideo::SetRetransmissionSetting(int32_t retransmission_settings) {
|
||||
RTC_DCHECK_RUNS_SERIALIZED(&send_checker_);
|
||||
retransmission_settings_ = retransmission_settings;
|
||||
}
|
||||
|
||||
void RTPSenderVideo::SetVideoStructure(
|
||||
const FrameDependencyStructure* video_structure) {
|
||||
if (frame_transformer_delegate_) {
|
||||
|
||||
@ -149,6 +149,10 @@ class RTPSenderVideo : public RTPVideoFrameSenderInterface {
|
||||
// place as the other rate stats.
|
||||
DataRate PostEncodeOverhead() const;
|
||||
|
||||
// 'retransmission_mode' is either a value of enum RetransmissionMode, or
|
||||
// computed with bitwise operators on values of enum RetransmissionMode.
|
||||
void SetRetransmissionSetting(int32_t retransmission_settings);
|
||||
|
||||
protected:
|
||||
static uint8_t GetTemporalId(const RTPVideoHeader& header);
|
||||
bool AllowRetransmission(uint8_t temporal_id,
|
||||
@ -201,11 +205,10 @@ class RTPSenderVideo : public RTPVideoFrameSenderInterface {
|
||||
RTPSender* const rtp_sender_;
|
||||
Clock* const clock_;
|
||||
|
||||
const int32_t retransmission_settings_;
|
||||
|
||||
// These members should only be accessed from within SendVideo() to avoid
|
||||
// potential race conditions.
|
||||
rtc::RaceChecker send_checker_;
|
||||
int32_t retransmission_settings_ RTC_GUARDED_BY(send_checker_);
|
||||
VideoRotation last_rotation_ RTC_GUARDED_BY(send_checker_);
|
||||
absl::optional<ColorSpace> last_color_space_ RTC_GUARDED_BY(send_checker_);
|
||||
bool transmit_color_space_next_frame_ RTC_GUARDED_BY(send_checker_);
|
||||
|
||||
@ -41,6 +41,7 @@ class ProtectionBitrateCalculatorTest : public ::testing::Test {
|
||||
*sent_fec_rate_bps = fec_rate_bps_;
|
||||
return 0;
|
||||
}
|
||||
void SetRetransmissionMode(int retransmission_mode) {}
|
||||
|
||||
uint32_t fec_rate_bps_ = 0;
|
||||
uint32_t nack_rate_bps_ = 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user