Chromium Code Reviews| Index: webrtc/media/engine/webrtcvideoengine2.cc |
| diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc |
| index c43dff80d3d140f87334f482df5ae266026c4832..d18f6fc84ad2410c4289ff2af010212c80a7069a 100644 |
| --- a/webrtc/media/engine/webrtcvideoengine2.cc |
| +++ b/webrtc/media/engine/webrtcvideoengine2.cc |
| @@ -39,6 +39,18 @@ |
| namespace cricket { |
| namespace { |
| +// Three things happen when the FlexFEC field trial is enabled: |
| +// 1) FlexFEC is exposed in the default codec list, eventually showing up |
| +// in the default SDP. |
| +// 2) FlexFEC send parameters are set in the VideoSendStream config. |
| +// 3) FlexFEC receive parameters are set in the FlexfecReceiveStream config, |
| +// and the corresponding object is instantiated. |
| +const char kFlexfecFieldTrialName[] = "WebRTC-FlexFEC-03"; |
| + |
| +bool IsFlexfecEnabled() { |
| + return webrtc::field_trial::FindFullName(kFlexfecFieldTrialName) == "Enabled"; |
| +} |
| + |
| // Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. |
| class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { |
| public: |
| @@ -440,22 +452,29 @@ std::vector<VideoCodec> DefaultVideoCodecList() { |
| } |
| if (webrtc::H264Encoder::IsSupported() && |
| webrtc::H264Decoder::IsSupported()) { |
| - VideoCodec codec = MakeVideoCodecWithDefaultFeedbackParams( |
| + VideoCodec h264_codec = MakeVideoCodecWithDefaultFeedbackParams( |
| kDefaultH264PlType, kH264CodecName); |
| // TODO(hta): Move all parameter generation for SDP into the codec |
| // implementation, for all codecs and parameters. |
| // TODO(hta): Move selection of profile-level-id to H.264 codec |
| // implementation. |
| // TODO(hta): Set FMTP parameters for all codecs of type H264. |
| - codec.SetParam(kH264FmtpProfileLevelId, |
| - kH264ProfileLevelConstrainedBaseline); |
| - codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); |
| - codec.SetParam(kH264FmtpPacketizationMode, "1"); |
| - AddCodecAndMaybeRtxCodec(codec, &codecs); |
| + h264_codec.SetParam(kH264FmtpProfileLevelId, |
| + kH264ProfileLevelConstrainedBaseline); |
| + h264_codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); |
| + h264_codec.SetParam(kH264FmtpPacketizationMode, "1"); |
| + AddCodecAndMaybeRtxCodec(h264_codec, &codecs); |
| } |
| AddCodecAndMaybeRtxCodec(VideoCodec(kDefaultRedPlType, kRedCodecName), |
| &codecs); |
| codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); |
| + |
| + if (IsFlexfecEnabled()) { |
| + VideoCodec flexfec_codec(kDefaultFlexfecPlType, kFlexfecCodecName); |
| + flexfec_codec.SetParam(kFlexfecFmtpRepairWindow, "10000000"); |
|
stefan-webrtc
2016/11/17 12:48:59
Comment on how this window size was chosen.
brandtr
2016/11/17 13:23:36
Done.
|
| + codecs.push_back(flexfec_codec); |
| + } |
| + |
| return codecs; |
| } |
| @@ -1234,7 +1253,8 @@ bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp, |
| receive_ssrcs_.insert(used_ssrc); |
| webrtc::VideoReceiveStream::Config config(this); |
| - ConfigureReceiverRtp(&config, sp); |
| + webrtc::FlexfecConfig flexfec_config; |
| + ConfigureReceiverRtp(&config, &flexfec_config, sp); |
| // Set up A/V sync group based on sync label. |
| config.sync_group = sp.sync_label; |
| @@ -1247,13 +1267,14 @@ bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp, |
| receive_streams_[ssrc] = new WebRtcVideoReceiveStream( |
| call_, sp, std::move(config), external_decoder_factory_, default_stream, |
| - recv_codecs_); |
| + recv_codecs_, flexfec_config); |
| return true; |
| } |
| void WebRtcVideoChannel2::ConfigureReceiverRtp( |
| webrtc::VideoReceiveStream::Config* config, |
| + webrtc::FlexfecConfig* flexfec_config, |
| const StreamParams& sp) const { |
| uint32_t ssrc = sp.first_ssrc(); |
| @@ -1292,6 +1313,14 @@ void WebRtcVideoChannel2::ConfigureReceiverRtp( |
| rtx.payload_type = recv_codecs_[i].rtx_payload_type; |
| } |
| } |
| + |
| + // TODO(brandtr): This code needs to be generalized when we add support for |
| + // multistream protection. |
| + uint32_t flexfec_ssrc; |
| + if (sp.GetFecFrSsrc(ssrc, &flexfec_ssrc)) { |
| + flexfec_config->flexfec_ssrc = flexfec_ssrc; |
| + flexfec_config->protected_media_ssrcs = {ssrc}; |
| + } |
| } |
| bool WebRtcVideoChannel2::RemoveRecvStream(uint32_t ssrc) { |
| @@ -1449,14 +1478,15 @@ void WebRtcVideoChannel2::OnPacketReceived( |
| } |
| // See if this payload_type is registered as one that usually gets its own |
| - // SSRC (RTX) or at least is safe to drop either way (ULPFEC). If it is, and |
| + // SSRC (RTX) or at least is safe to drop either way (FEC). If it is, and |
| // it wasn't handled above by DeliverPacket, that means we don't know what |
| // stream it associates with, and we shouldn't ever create an implicit channel |
| // for these. |
| for (auto& codec : recv_codecs_) { |
| if (payload_type == codec.rtx_payload_type || |
| payload_type == codec.ulpfec.red_rtx_payload_type || |
| - payload_type == codec.ulpfec.ulpfec_payload_type) { |
| + payload_type == codec.ulpfec.ulpfec_payload_type || |
| + payload_type == codec.flexfec.flexfec_payload_type) { |
| return; |
| } |
| } |
| @@ -1599,8 +1629,35 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( |
| parameters_.conference_mode = send_params.conference_mode; |
| sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
| + |
| + // RTX. |
| sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |
| ¶meters_.config.rtp.rtx.ssrcs); |
| + |
| + // FlexFEC. |
| + // TODO(brandtr): This code needs to be generalized when we add support for |
| + // multistream protection. |
| + if (IsFlexfecEnabled()) { |
| + uint32_t flexfec_ssrc; |
| + bool flexfec_enabled = false; |
| + for (uint32_t primary_ssrc : parameters_.config.rtp.ssrcs) { |
| + if (sp.GetFecFrSsrc(primary_ssrc, &flexfec_ssrc)) { |
| + if (flexfec_enabled) { |
| + LOG(LS_INFO) << "Multiple FlexFEC streams proposed by remote, but " |
| + "our implementation only supports a single FlexFEC " |
| + "stream. Will not enable FlexFEC for proposed " |
| + "stream with SSRC: " |
| + << flexfec_ssrc << "."; |
| + continue; |
| + } |
| + |
| + flexfec_enabled = true; |
| + parameters_.config.rtp.flexfec.flexfec_ssrc = flexfec_ssrc; |
| + parameters_.config.rtp.flexfec.protected_media_ssrcs = {primary_ssrc}; |
| + } |
| + } |
| + } |
| + |
| parameters_.config.rtp.c_name = sp.cname; |
| if (rtp_extensions) { |
| parameters_.config.rtp.extensions = *rtp_extensions; |
| @@ -1785,6 +1842,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( |
| external_encoder_factory_->EncoderTypeHasInternalSource(type); |
| } |
| parameters_.config.rtp.ulpfec = codec_settings.ulpfec; |
| + parameters_.config.rtp.flexfec.flexfec_payload_type = |
| + codec_settings.flexfec.flexfec_payload_type; |
| // Set RTX payload type if RTX is enabled. |
| if (!parameters_.config.rtp.rtx.ssrcs.empty()) { |
| @@ -2160,12 +2219,15 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
| webrtc::VideoReceiveStream::Config config, |
| WebRtcVideoDecoderFactory* external_decoder_factory, |
| bool default_stream, |
| - const std::vector<VideoCodecSettings>& recv_codecs) |
| + const std::vector<VideoCodecSettings>& recv_codecs, |
| + webrtc::FlexfecConfig flexfec_config) |
|
magjed_webrtc
2016/11/17 13:37:19
Make this const-ref instead of by-value.
brandtr
2016/11/17 17:28:58
Done.
|
| : call_(call), |
| stream_params_(sp), |
| stream_(NULL), |
| default_stream_(default_stream), |
| config_(std::move(config)), |
| + flexfec_config_(flexfec_config), |
| + flexfec_stream_(nullptr), |
| external_decoder_factory_(external_decoder_factory), |
| sink_(NULL), |
| first_frame_timestamp_(-1), |
| @@ -2294,6 +2356,8 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ConfigureCodecs( |
| // TODO(pbos): Reconfigure RTX based on incoming recv_codecs. |
| config_.rtp.ulpfec = recv_codecs.front().ulpfec; |
| + flexfec_config_.flexfec_payload_type = |
| + recv_codecs.front().flexfec.flexfec_payload_type; |
| config_.rtp.nack.rtp_history_ms = |
| HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; |
| } |
| @@ -2365,11 +2429,19 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvParameters( |
| } |
| void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() { |
| - if (stream_ != NULL) { |
| + if (flexfec_stream_) { |
| + call_->DestroyFlexfecReceiveStream(flexfec_stream_); |
| + flexfec_stream_ = nullptr; |
| + } |
| + if (stream_) { |
| call_->DestroyVideoReceiveStream(stream_); |
| } |
| stream_ = call_->CreateVideoReceiveStream(config_.Copy()); |
| stream_->Start(); |
| + if (IsFlexfecEnabled() && flexfec_config_.IsValid()) { |
| + flexfec_stream_ = call_->CreateFlexfecReceiveStream(flexfec_config_); |
| + flexfec_stream_->Start(); |
| + } |
| } |
| void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders( |
| @@ -2488,6 +2560,9 @@ bool WebRtcVideoChannel2::VideoCodecSettings::operator==( |
| ulpfec.ulpfec_payload_type == other.ulpfec.ulpfec_payload_type && |
| ulpfec.red_payload_type == other.ulpfec.red_payload_type && |
| ulpfec.red_rtx_payload_type == other.ulpfec.red_rtx_payload_type && |
| + flexfec.flexfec_payload_type == other.flexfec.flexfec_payload_type && |
|
magjed_webrtc
2016/11/17 13:37:19
Maybe you should implement operator== for FlexfecC
brandtr
2016/11/17 17:28:58
Done. Also implemented it for UlpfecConfig, to fur
|
| + flexfec.flexfec_ssrc == other.flexfec.flexfec_ssrc && |
| + flexfec.protected_media_ssrcs == other.flexfec.protected_media_ssrcs && |
| rtx_payload_type == other.rtx_payload_type; |
| } |
| @@ -2507,6 +2582,7 @@ WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { |
| std::map<int, int> rtx_mapping; |
| webrtc::UlpfecConfig ulpfec_config; |
| + int flexfec_payload_type = -1; |
| for (size_t i = 0; i < codecs.size(); ++i) { |
| const VideoCodec& in_codec = codecs[i]; |
| @@ -2536,7 +2612,9 @@ WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { |
| } |
| case VideoCodec::CODEC_FLEXFEC: { |
| - // TODO(brandtr): To be implemented. |
| + // FlexFEC payload type, should not have duplicates. |
| + RTC_DCHECK(flexfec_payload_type == -1); |
|
magjed_webrtc
2016/11/17 13:37:19
Use RTC_DCHECK_EQ(-1, flexfec_payload_type) instea
brandtr
2016/11/17 17:28:58
Done.
|
| + flexfec_payload_type = in_codec.id; |
| continue; |
| } |
| @@ -2586,6 +2664,7 @@ WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { |
| for (size_t i = 0; i < video_codecs.size(); ++i) { |
| video_codecs[i].ulpfec = ulpfec_config; |
| + video_codecs[i].flexfec.flexfec_payload_type = flexfec_payload_type; |
| if (rtx_mapping[video_codecs[i].codec.id] != 0 && |
| rtx_mapping[video_codecs[i].codec.id] != |
| ulpfec_config.red_payload_type) { |