Chromium Code Reviews| 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..09b41e4c569d97b8fa5ee02621b4de10c893c0dd 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_ERROR) << "FlexFEC is enabled, but no FlexFEC SSRC given. " |
| + "Therefore disabling FlexFEC."; |
| + return nullptr; |
| + } |
| + if (config.rtp.flexfec.protected_media_ssrcs.empty()) { |
| + LOG(LS_ERROR) << "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 " |
|
terelius
2016/11/15 09:58:09
Should this be LS_ERROR?
brandtr
2016/11/15 10:28:20
Changed all to be WARNINGs, as per offline discuss
|
| + "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) |
|
terelius
2016/11/15 09:58:09
Should this be LS_ERROR?
|
| + << "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() { |