Index: webrtc/video/video_send_stream.cc |
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc |
index aac73aba98ea8ac5902e09b48a06ac2c3b3c6a11..51c9dad13160a4cbbc454e6576db27fb4274b3aa 100644 |
--- a/webrtc/video/video_send_stream.cc |
+++ b/webrtc/video/video_send_stream.cc |
@@ -44,6 +44,7 @@ std::vector<RtpRtcp*> CreateRtpRtcpModules( |
RtcpRttStats* rtt_stats, |
RtpPacketSender* paced_sender, |
TransportSequenceNumberAllocator* transport_sequence_number_allocator, |
+ FlexfecSender* flexfec_sender, |
SendStatisticsProxy* stats_proxy, |
SendDelayStats* send_delay_stats, |
RtcEventLog* event_log, |
@@ -54,6 +55,7 @@ std::vector<RtpRtcp*> CreateRtpRtcpModules( |
ReceiveStatistics* null_receive_statistics = configuration.receive_statistics; |
configuration.audio = false; |
configuration.receiver_only = false; |
+ configuration.flexfec_sender = flexfec_sender; |
configuration.receive_statistics = null_receive_statistics; |
configuration.outgoing_transport = outgoing_transport; |
configuration.intra_frame_callback = intra_frame_callback; |
@@ -82,6 +84,48 @@ std::vector<RtpRtcp*> CreateRtpRtcpModules( |
return modules; |
} |
+// TODO(brandtr): Update this function when we support multistream protection. |
+std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender( |
+ const VideoSendStream::Config& config) { |
+ if (config.rtp.flexfec.flexfec_payload_type < 0) { |
+ return nullptr; |
+ } |
+ RTC_DCHECK_GE(config.rtp.flexfec.flexfec_payload_type, 0); |
+ RTC_DCHECK_LE(config.rtp.flexfec.flexfec_payload_type, 127); |
+ if (config.rtp.flexfec.flexfec_ssrc == 0) { |
+ LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. " |
+ "Therefore disabling FlexFEC."; |
+ return nullptr; |
+ } |
+ if (config.rtp.flexfec.protected_media_ssrcs.empty()) { |
+ LOG(LS_WARNING) << "FlexFEC is enabled, but no protected media SSRC given. " |
+ "Therefore disabling FlexFEC."; |
+ return nullptr; |
+ } |
+ |
+ if (config.rtp.ssrcs.size() > 1) { |
+ LOG(LS_WARNING) << "Both FlexFEC and simulcast are enabled. This " |
+ "combination is however not supported by our current " |
+ "FlexFEC implementation. Therefore disabling FlexFEC."; |
+ return nullptr; |
+ } |
+ |
+ if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) { |
+ LOG(LS_WARNING) |
+ << "The supplied FlexfecConfig contained multiple protected " |
+ "media streams, but our implementation currently only " |
+ "supports protecting a single media stream. " |
+ "To avoid confusion, disabling FlexFEC completely."; |
+ return nullptr; |
+ } |
+ |
+ RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size()); |
+ return std::unique_ptr<FlexfecSender>(new FlexfecSender( |
+ config.rtp.flexfec.flexfec_payload_type, config.rtp.flexfec.flexfec_ssrc, |
+ config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions, |
+ Clock::GetRealTimeClock())); |
+} |
+ |
} // namespace |
std::string |
@@ -133,6 +177,7 @@ std::string VideoSendStream::Config::Rtp::ToString() const { |
ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; |
ss << ", ulpfec: " << ulpfec.ToString(); |
+ ss << ", flexfec: " << flexfec.ToString(); |
ss << ", rtx: " << rtx.ToString(); |
ss << ", c_name: " << c_name; |
ss << '}'; |
@@ -325,6 +370,9 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver, |
BitrateAllocator* const bitrate_allocator_; |
VieRemb* const remb_; |
+ // TODO(brandtr): Consider moving this to a new FlexfecSendStream class. |
+ std::unique_ptr<FlexfecSender> flexfec_sender_; |
+ |
rtc::CriticalSection ivf_writers_crit_; |
std::unique_ptr<IvfFileWriter> file_writers_[kMaxSimulcastStreams] GUARDED_BY( |
ivf_writers_crit_); |
@@ -661,6 +709,7 @@ VideoSendStreamImpl::VideoSendStreamImpl( |
congestion_controller_(congestion_controller), |
bitrate_allocator_(bitrate_allocator), |
remb_(remb), |
+ flexfec_sender_(MaybeCreateFlexfecSender(*config_)), |
max_padding_bitrate_(0), |
encoder_min_bitrate_bps_(0), |
encoder_max_bitrate_bps_(initial_encoder_max_bitrate), |
@@ -680,6 +729,7 @@ VideoSendStreamImpl::VideoSendStreamImpl( |
call_stats_->rtcp_rtt_stats(), |
congestion_controller_->pacer(), |
congestion_controller_->packet_router(), |
+ flexfec_sender_.get(), |
stats_proxy_, |
send_delay_stats, |
event_log, |
@@ -943,15 +993,36 @@ EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage( |
void VideoSendStreamImpl::ConfigureProtection() { |
RTC_DCHECK_RUN_ON(worker_queue_); |
+ // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender. |
+ const bool flexfec_enabled = (flexfec_sender_ != nullptr); |
+ |
+ // Consistency of NACK and RED+ULPFEC parameters is checked in this function. |
const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0; |
int red_payload_type = config_->rtp.ulpfec.red_payload_type; |
int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type; |
// Shorthands. |
auto IsRedEnabled = [&]() { return red_payload_type >= 0; }; |
+ auto DisableRed = [&]() { red_payload_type = -1; }; |
auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; }; |
auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; }; |
+ // If enabled, FlexFEC takes priority over RED+ULPFEC. |
+ if (flexfec_enabled) { |
+ // We can safely disable RED here, because if the remote supports FlexFEC, |
+ // we know that it has a receiver without the RED/RTX workaround. |
+ // See http://crbug.com/webrtc/6650 for more information. |
+ if (IsRedEnabled()) { |
+ LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED."; |
+ DisableRed(); |
+ } |
+ if (IsUlpfecEnabled()) { |
+ LOG(LS_INFO) |
+ << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC."; |
+ DisableUlpfec(); |
+ } |
+ } |
+ |
// Payload types without picture ID cannot determine that a stream is complete |
// without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance) |
// is a waste of bandwidth since FEC packets still have to be transmitted. |
@@ -999,8 +1070,10 @@ void VideoSendStreamImpl::ConfigureProtection() { |
} |
} |
- protection_bitrate_calculator_.SetProtectionMethod(IsUlpfecEnabled(), |
- nack_enabled); |
+ // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic, |
+ // so enable that logic if either of those FEC schemes are enabled. |
+ protection_bitrate_calculator_.SetProtectionMethod( |
+ flexfec_enabled || IsUlpfecEnabled(), nack_enabled); |
} |
void VideoSendStreamImpl::ConfigureSsrcs() { |