Allow ulpfec payload type reconfig without recreating receive streams.
Bug: none Change-Id: I1c5dad7811dd93552c185145e5a1488a8e9bb863 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271000 Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37771}
This commit is contained in:
@ -303,6 +303,8 @@ class VideoReceiveStreamInterface : public MediaReceiveStreamInterface {
|
||||
// Must be called on the packet delivery thread.
|
||||
virtual void SetNackHistory(TimeDelta history) = 0;
|
||||
|
||||
virtual void SetUlpfecPayloadType(int ulpfec_payload_type) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VideoReceiveStreamInterface() {}
|
||||
};
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
@ -297,6 +298,10 @@ class FakeVideoReceiveStream final
|
||||
config_.rtp.nack.rtp_history_ms = history.ms();
|
||||
}
|
||||
|
||||
void SetUlpfecPayloadType(int ulpfec_payload_type) override {
|
||||
config_.rtp.ulpfec_payload_type = ulpfec_payload_type;
|
||||
}
|
||||
|
||||
void Start() override;
|
||||
void Stop() override;
|
||||
|
||||
|
@ -2972,14 +2972,14 @@ bool WebRtcVideoChannel::WebRtcVideoReceiveStream::ReconfigureCodecs(
|
||||
ExtractCodecInformation(recv_codecs, rtx_associated_payload_types,
|
||||
raw_payload_types, decoders);
|
||||
|
||||
bool recreate_needed = false;
|
||||
|
||||
const auto& codec = recv_codecs.front();
|
||||
if (config_.rtp.ulpfec_payload_type != codec.ulpfec.ulpfec_payload_type) {
|
||||
config_.rtp.ulpfec_payload_type = codec.ulpfec.ulpfec_payload_type;
|
||||
recreate_needed = true;
|
||||
stream_->SetUlpfecPayloadType(config_.rtp.ulpfec_payload_type);
|
||||
}
|
||||
|
||||
bool recreate_needed = false;
|
||||
|
||||
if (config_.rtp.red_payload_type != codec.ulpfec.red_payload_type) {
|
||||
config_.rtp.red_payload_type = codec.ulpfec.red_payload_type;
|
||||
recreate_needed = true;
|
||||
|
@ -124,22 +124,25 @@ std::unique_ptr<NackRequester> MaybeConstructNackModule(
|
||||
}
|
||||
|
||||
std::unique_ptr<UlpfecReceiver> MaybeConstructUlpfecReceiver(
|
||||
const VideoReceiveStreamInterface::Config::Rtp& rtp,
|
||||
uint32_t remote_ssrc,
|
||||
int red_payload_type,
|
||||
int ulpfec_payload_type,
|
||||
rtc::ArrayView<const RtpExtension> extensions,
|
||||
RecoveredPacketReceiver* callback,
|
||||
Clock* clock) {
|
||||
RTC_DCHECK_GE(rtp.ulpfec_payload_type, -1);
|
||||
if (rtp.red_payload_type == -1)
|
||||
RTC_DCHECK_GE(red_payload_type, -1);
|
||||
RTC_DCHECK_GE(ulpfec_payload_type, -1);
|
||||
if (red_payload_type == -1)
|
||||
return nullptr;
|
||||
|
||||
// TODO(tommi, brandtr): Consider including this check too once
|
||||
// `UlpfecReceiver` has been updated to not consider both red and ulpfec
|
||||
// payload ids.
|
||||
// if (rtp.ulpfec_payload_type == -1)
|
||||
// if (ulpfec_payload_type == -1)
|
||||
// return nullptr;
|
||||
|
||||
return std::make_unique<UlpfecReceiver>(rtp.remote_ssrc,
|
||||
rtp.ulpfec_payload_type, callback,
|
||||
rtp.extensions, clock);
|
||||
return std::make_unique<UlpfecReceiver>(remote_ssrc, ulpfec_payload_type,
|
||||
callback, extensions, clock);
|
||||
}
|
||||
|
||||
static const int kPacketLogIntervalMs = 10000;
|
||||
@ -256,7 +259,13 @@ RtpVideoStreamReceiver2::RtpVideoStreamReceiver2(
|
||||
forced_playout_delay_max_ms_("max_ms", absl::nullopt),
|
||||
forced_playout_delay_min_ms_("min_ms", absl::nullopt),
|
||||
rtp_receive_statistics_(rtp_receive_statistics),
|
||||
ulpfec_receiver_(MaybeConstructUlpfecReceiver(config->rtp, this, clock)),
|
||||
ulpfec_receiver_(
|
||||
MaybeConstructUlpfecReceiver(config->rtp.remote_ssrc,
|
||||
config->rtp.red_payload_type,
|
||||
config->rtp.ulpfec_payload_type,
|
||||
config->rtp.extensions,
|
||||
this,
|
||||
clock_)),
|
||||
packet_sink_(config->rtp.packet_sink_),
|
||||
receiving_(false),
|
||||
last_packet_log_ms_(-1),
|
||||
@ -983,6 +992,18 @@ void RtpVideoStreamReceiver2::SetNackHistory(TimeDelta history) {
|
||||
history.ms() > 0 ? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold);
|
||||
}
|
||||
|
||||
int RtpVideoStreamReceiver2::ulpfec_payload_type() const {
|
||||
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
|
||||
return ulpfec_receiver_ ? ulpfec_receiver_->ulpfec_payload_type() : -1;
|
||||
}
|
||||
|
||||
void RtpVideoStreamReceiver2::set_ulpfec_payload_type(int payload_type) {
|
||||
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
|
||||
ulpfec_receiver_ = MaybeConstructUlpfecReceiver(
|
||||
config_.rtp.remote_ssrc, config_.rtp.red_payload_type, payload_type,
|
||||
config_.rtp.extensions, this, clock_);
|
||||
}
|
||||
|
||||
absl::optional<int64_t> RtpVideoStreamReceiver2::LastReceivedPacketMs() const {
|
||||
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
|
||||
if (last_received_rtp_system_time_) {
|
||||
@ -1040,16 +1061,18 @@ void RtpVideoStreamReceiver2::ReceivePacket(const RtpPacketReceived& packet) {
|
||||
void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader(
|
||||
const RtpPacketReceived& packet) {
|
||||
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
|
||||
if (packet.PayloadType() == config_.rtp.red_payload_type &&
|
||||
packet.payload_size() > 0) {
|
||||
if (packet.payload()[0] == config_.rtp.ulpfec_payload_type) {
|
||||
// Notify video_receiver about received FEC packets to avoid NACKing these
|
||||
// packets.
|
||||
NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
|
||||
}
|
||||
if (ulpfec_receiver_ && ulpfec_receiver_->AddReceivedRedPacket(packet)) {
|
||||
ulpfec_receiver_->ProcessReceivedFec();
|
||||
}
|
||||
RTC_DCHECK_EQ(packet.PayloadType(), config_.rtp.red_payload_type);
|
||||
|
||||
if (!ulpfec_receiver_ || packet.payload_size() == 0U)
|
||||
return;
|
||||
|
||||
if (packet.payload()[0] == ulpfec_receiver_->ulpfec_payload_type()) {
|
||||
// Notify video_receiver about received FEC packets to avoid NACKing these
|
||||
// packets.
|
||||
NotifyReceiverOfEmptyPacket(packet.SequenceNumber());
|
||||
}
|
||||
if (ulpfec_receiver_->AddReceivedRedPacket(packet)) {
|
||||
ulpfec_receiver_->ProcessReceivedFec();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,6 +198,9 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender,
|
||||
|
||||
void SetNackHistory(TimeDelta history);
|
||||
|
||||
int ulpfec_payload_type() const;
|
||||
void set_ulpfec_payload_type(int payload_type);
|
||||
|
||||
absl::optional<int64_t> LastReceivedPacketMs() const;
|
||||
absl::optional<int64_t> LastReceivedKeyframePacketMs() const;
|
||||
|
||||
@ -320,7 +323,8 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender,
|
||||
FieldTrialOptional<int> forced_playout_delay_max_ms_;
|
||||
FieldTrialOptional<int> forced_playout_delay_min_ms_;
|
||||
ReceiveStatistics* const rtp_receive_statistics_;
|
||||
std::unique_ptr<UlpfecReceiver> ulpfec_receiver_;
|
||||
std::unique_ptr<UlpfecReceiver> ulpfec_receiver_
|
||||
RTC_GUARDED_BY(packet_sequence_checker_);
|
||||
|
||||
RTC_NO_UNIQUE_ADDRESS SequenceChecker worker_task_checker_;
|
||||
// TODO(bugs.webrtc.org/11993): This checker conceptually represents
|
||||
|
@ -349,7 +349,8 @@ void VideoReceiveStream2::Start() {
|
||||
}
|
||||
|
||||
const bool protected_by_fec =
|
||||
config_.rtp.protected_by_flexfec || config_.rtp.ulpfec_payload_type != -1;
|
||||
config_.rtp.protected_by_flexfec ||
|
||||
rtp_video_stream_receiver_.ulpfec_payload_type() != -1;
|
||||
|
||||
if (config_.rtp.nack.rtp_history_ms > 0 && protected_by_fec) {
|
||||
frame_buffer_->SetProtectionMode(kProtectionNackFEC);
|
||||
@ -530,7 +531,8 @@ void VideoReceiveStream2::SetNackHistory(TimeDelta history) {
|
||||
const_cast<int&>(config_.rtp.nack.rtp_history_ms) = history.ms();
|
||||
|
||||
const bool protected_by_fec =
|
||||
config_.rtp.protected_by_flexfec || config_.rtp.ulpfec_payload_type != -1;
|
||||
config_.rtp.protected_by_flexfec ||
|
||||
rtp_video_stream_receiver_.ulpfec_payload_type() != -1;
|
||||
|
||||
frame_buffer_->SetProtectionMode(history.ms() > 0 && protected_by_fec
|
||||
? kProtectionNackFEC
|
||||
@ -549,6 +551,11 @@ void VideoReceiveStream2::SetNackHistory(TimeDelta history) {
|
||||
frame_buffer_->SetMaxWaits(max_wait_for_keyframe, max_wait_for_frame);
|
||||
}
|
||||
|
||||
void VideoReceiveStream2::SetUlpfecPayloadType(int payload_type) {
|
||||
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
|
||||
rtp_video_stream_receiver_.set_ulpfec_payload_type(payload_type);
|
||||
}
|
||||
|
||||
void VideoReceiveStream2::CreateAndRegisterExternalDecoder(
|
||||
const Decoder& decoder) {
|
||||
TRACE_EVENT0("webrtc",
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef VIDEO_VIDEO_RECEIVE_STREAM2_H_
|
||||
#define VIDEO_VIDEO_RECEIVE_STREAM2_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -150,6 +151,7 @@ class VideoReceiveStream2
|
||||
void SetFlexFecProtection(RtpPacketSinkInterface* flexfec_sink) override;
|
||||
void SetLossNotificationEnabled(bool enabled) override;
|
||||
void SetNackHistory(TimeDelta history) override;
|
||||
void SetUlpfecPayloadType(int payload_type) override;
|
||||
|
||||
webrtc::VideoReceiveStreamInterface::Stats GetStats() const override;
|
||||
|
||||
|
Reference in New Issue
Block a user