Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(628)

Unified Diff: webrtc/media/engine/webrtcvideoengine2.cc

Issue 2511703002: Wire up FlexFEC in VideoEngine2. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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(&parameters_.config.rtp.ssrcs);
+
+ // RTX.
sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
&parameters_.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) {

Powered by Google App Engine
This is Rietveld 408576698