(Auto)update libjingle 68646004-> 68648993

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6348 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/media/webrtc/fakewebrtcvideoengine.h b/talk/media/webrtc/fakewebrtcvideoengine.h
index 3eba47b..440b6ca 100644
--- a/talk/media/webrtc/fakewebrtcvideoengine.h
+++ b/talk/media/webrtc/fakewebrtcvideoengine.h
@@ -285,6 +285,7 @@
           receiver_target_delay_(0),
           transmission_smoothing_(false),
           nack_(false),
+          fec_(false),
           hybrid_nack_fec_(false),
           send_video_bitrate_(0),
           send_fec_bitrate_(0),
@@ -325,6 +326,7 @@
     int receiver_target_delay_;
     bool transmission_smoothing_;
     bool nack_;
+    bool fec_;
     bool hybrid_nack_fec_;
     std::vector<webrtc::VideoCodec> recv_codecs;
     std::set<unsigned int> ext_decoder_pl_types_;
@@ -518,6 +520,10 @@
     WEBRTC_ASSERT_CHANNEL(channel);
     return channels_.find(channel)->second->receiver_target_delay_;
   }
+  bool GetFecStatus(int channel) const {
+    WEBRTC_ASSERT_CHANNEL(channel);
+    return channels_.find(channel)->second->fec_;
+  }
   bool GetNackStatus(int channel) const {
     WEBRTC_ASSERT_CHANNEL(channel);
     return channels_.find(channel)->second->nack_;
@@ -1037,16 +1043,28 @@
     channels_[channel]->hybrid_nack_fec_ = false;
     return 0;
   }
-  WEBRTC_STUB(SetFECStatus, (const int, const bool, const unsigned char,
-      const unsigned char));
+  WEBRTC_FUNC(SetFECStatus, (const int channel, const bool enable,
+      const unsigned char red_type, const unsigned char fec_type)) {
+    WEBRTC_CHECK_CHANNEL(channel);
+    if (enable && (red_type == fec_type ||
+        red_type == channels_[channel]->send_codec.plType ||
+        fec_type == channels_[channel]->send_codec.plType)) {
+      return -1;
+    }
+    channels_[channel]->fec_ = enable;
+    channels_[channel]->nack_ = false;
+    channels_[channel]->hybrid_nack_fec_ = false;
+    return 0;
+  }
   WEBRTC_FUNC(SetHybridNACKFECStatus, (const int channel, const bool enable,
       const unsigned char red_type, const unsigned char fec_type)) {
     WEBRTC_CHECK_CHANNEL(channel);
-    if (red_type == fec_type ||
+    if (enable && (red_type == fec_type ||
         red_type == channels_[channel]->send_codec.plType ||
-        fec_type == channels_[channel]->send_codec.plType) {
+        fec_type == channels_[channel]->send_codec.plType)) {
       return -1;
     }
+    channels_[channel]->fec_ = false;
     channels_[channel]->nack_ = false;
     channels_[channel]->hybrid_nack_fec_ = enable;
     return 0;
@@ -1111,7 +1129,7 @@
     channels_[channel]->transmission_smoothing_ = enable;
     return 0;
   }
-  WEBRTC_FUNC(SetReservedTransmitBitrate, (int channel, 
+  WEBRTC_FUNC(SetReservedTransmitBitrate, (int channel,
       unsigned int reserved_transmit_bitrate_bps)) {
     WEBRTC_CHECK_CHANNEL(channel);
     channels_[channel]->reserved_transmit_bitrate_bps_ =
diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc
index a029ec2..4717b43 100644
--- a/talk/media/webrtc/webrtcvideoengine.cc
+++ b/talk/media/webrtc/webrtcvideoengine.cc
@@ -3651,24 +3651,71 @@
                                          int red_payload_type,
                                          int fec_payload_type,
                                          bool nack_enabled) {
-  bool enable = (red_payload_type != -1 && fec_payload_type != -1 &&
+  bool fec_enabled = (red_payload_type != -1 && fec_payload_type != -1 &&
       !InConferenceMode());
-  if (enable) {
-    if (engine_->vie()->rtp()->SetHybridNACKFECStatus(
-        channel_id, nack_enabled, red_payload_type, fec_payload_type) != 0) {
-      LOG_RTCERR4(SetHybridNACKFECStatus,
-                  channel_id, nack_enabled, red_payload_type, fec_payload_type);
-      return false;
-    }
-    LOG(LS_INFO) << "Hybrid NACK/FEC enabled for channel " << channel_id;
-  } else {
-    if (engine_->vie()->rtp()->SetNACKStatus(channel_id, nack_enabled) != 0) {
-      LOG_RTCERR1(SetNACKStatus, channel_id);
-      return false;
-    }
-    std::string enabled = nack_enabled ? "enabled" : "disabled";
-    LOG(LS_INFO) << "NACK " << enabled << " for channel " << channel_id;
+  bool hybrid_enabled = (fec_enabled && nack_enabled);
+
+  if (!SetHybridNackFecStatus(channel_id, hybrid_enabled,
+                              red_payload_type, fec_payload_type)) {
+    return false;
   }
+  if (hybrid_enabled) {
+    return true;
+  }
+
+  if (!SetFecStatus(channel_id, fec_enabled,
+                    red_payload_type, fec_payload_type)) {
+    return false;
+  }
+  if (fec_enabled) {
+    return true;
+  }
+
+  if (!SetNackStatus(channel_id, nack_enabled)) {
+    return false;
+  }
+
+  return true;
+}
+
+bool WebRtcVideoMediaChannel::SetHybridNackFecStatus(int channel_id,
+                                                     bool enabled,
+                                                     int red_payload_type,
+                                                     int fec_payload_type) {
+  if (engine_->vie()->rtp()->SetHybridNACKFECStatus(
+      channel_id, enabled, red_payload_type, fec_payload_type) != 0) {
+    LOG_RTCERR4(SetHybridNACKFECStatus, channel_id, enabled,
+                red_payload_type, fec_payload_type);
+    return false;
+  }
+  std::string enabled_str = enabled ? "enabled" : "disabled";
+  LOG(LS_INFO) << "Hybrid NACK/FEC " << enabled_str
+               << " for channel " << channel_id;
+  return true;
+}
+
+bool WebRtcVideoMediaChannel::SetFecStatus(int channel_id,
+                                           bool enabled,
+                                           int red_payload_type,
+                                           int fec_payload_type) {
+  if (engine_->vie()->rtp()->SetFECStatus(
+      channel_id, enabled, red_payload_type, fec_payload_type) != 0) {
+    LOG_RTCERR4(SetFECStatus, channel_id, enabled,
+                red_payload_type, fec_payload_type);
+    return false;
+  }
+  std::string enabled_str = enabled ? "enabled" : "disabled";
+  LOG(LS_INFO) << "FEC " << enabled_str << " for channel " << channel_id;
+  return true;
+}
+
+bool WebRtcVideoMediaChannel::SetNackStatus(int channel_id, bool enabled) {
+  if (engine_->vie()->rtp()->SetNACKStatus(channel_id, enabled) != 0) {
+    LOG_RTCERR2(SetNACKStatus, channel_id, enabled);
+    return false;
+  }
+  std::string enabled_str = enabled ? "enabled" : "disabled";
+  LOG(LS_INFO) << "NACK " << enabled_str << " for channel " << channel_id;
   return true;
 }
 
diff --git a/talk/media/webrtc/webrtcvideoengine.h b/talk/media/webrtc/webrtcvideoengine.h
index 3928542..ea4b1bc 100644
--- a/talk/media/webrtc/webrtcvideoengine.h
+++ b/talk/media/webrtc/webrtcvideoengine.h
@@ -336,6 +336,11 @@
   bool ConfigureSending(int channel_id, uint32 local_ssrc_key);
   bool SetNackFec(int channel_id, int red_payload_type, int fec_payload_type,
                   bool nack_enabled);
+  bool SetHybridNackFecStatus(int channel_id, bool enabled,
+                              int red_payload_type, int fec_payload_type);
+  bool SetFecStatus(int channel_id, bool enabled,
+                    int red_payload_type, int fec_payload_type);
+  bool SetNackStatus(int channel_id, bool enabled);
   bool SetSendCodec(const webrtc::VideoCodec& codec);
   bool SetSendCodec(WebRtcVideoChannelSendInfo* send_channel,
                     const webrtc::VideoCodec& codec);
diff --git a/talk/media/webrtc/webrtcvideoengine_unittest.cc b/talk/media/webrtc/webrtcvideoengine_unittest.cc
index 804b70f..abc1a01 100644
--- a/talk/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine_unittest.cc
@@ -384,6 +384,7 @@
   VerifyVP8SendCodec(channel_num, kVP8Codec.width, kVP8Codec.height);
   EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num));
   EXPECT_FALSE(vie_.GetNackStatus(channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
   EXPECT_EQ(1, vie_.GetNumSetSendCodecs());
   // TODO(juberti): Check RTCP, PLI, TMMBR.
 }
@@ -1225,6 +1226,51 @@
   codecs.resize(1);  // toss out red and ulpfec
   EXPECT_TRUE(channel_->SetSendCodecs(codecs));
   EXPECT_TRUE(vie_.GetNackStatus(channel_num));
+  EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
+}
+
+// Test that FEC is enabled and NACK is disabled if we offer
+// RED/FEC and we disable nack.
+TEST_F(WebRtcVideoEngineTestFake, FecEnabled) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+  std::vector<cricket::VideoCodec> codecs = engine_.codecs();
+  // Clearing the codecs' FeedbackParams and setting send codecs should disable
+  // NACK.
+  for (std::vector<cricket::VideoCodec>::iterator iter = codecs.begin();
+       iter != codecs.end(); ++iter) {
+    // Intersecting with empty will clear the FeedbackParams.
+    cricket::FeedbackParams empty_params;
+    iter->feedback_params.Intersect(empty_params);
+    EXPECT_TRUE(iter->feedback_params.params().empty());
+  }
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_TRUE(vie_.GetFecStatus(channel_num));
+  EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num));
+  EXPECT_FALSE(vie_.GetNackStatus(channel_num));
+}
+
+// Test that FEC and NACK are disabled if we don't offer
+// RED/FEC and we disable nack.
+TEST_F(WebRtcVideoEngineTestFake, NackFecDisabled) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+  std::vector<cricket::VideoCodec> codecs = engine_.codecs();
+  codecs.resize(1);  // toss out red and ulpfec
+  // Clearing the codecs' FeedbackParams and setting send codecs should disable
+  // NACK.
+  for (std::vector<cricket::VideoCodec>::iterator iter = codecs.begin();
+       iter != codecs.end(); ++iter) {
+    // Intersecting with empty will clear the FeedbackParams.
+    cricket::FeedbackParams empty_params;
+    iter->feedback_params.Intersect(empty_params);
+    EXPECT_TRUE(iter->feedback_params.params().empty());
+  }
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
+  EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num));
+  EXPECT_FALSE(vie_.GetNackStatus(channel_num));
 }
 
 // Test that we enable hybrid NACK FEC mode.
@@ -1235,6 +1281,7 @@
   EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
   EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num));
   EXPECT_FALSE(vie_.GetNackStatus(channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
 }
 
 // Test that we enable hybrid NACK FEC mode when calling SetSendCodecs and
@@ -1246,6 +1293,7 @@
   EXPECT_TRUE(channel_->SetRecvCodecs(engine_.codecs()));
   EXPECT_TRUE(vie_.GetHybridNackFecStatus(channel_num));
   EXPECT_FALSE(vie_.GetNackStatus(channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
 }
 
 // Test NACK vs Hybrid NACK/FEC interop call setup, i.e. only use NACK even if
@@ -1261,6 +1309,7 @@
   EXPECT_TRUE(channel_->SetSendCodecs(send_codecs));
   EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num));
   EXPECT_TRUE(vie_.GetNackStatus(channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
 }
 
 // Test NACK vs Hybrid NACK/FEC interop call setup, i.e. only use NACK even if
@@ -1277,6 +1326,7 @@
   EXPECT_TRUE(channel_->SetRecvCodecs(recv_codecs));
   EXPECT_FALSE(vie_.GetHybridNackFecStatus(channel_num));
   EXPECT_TRUE(vie_.GetNackStatus(channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(channel_num));
 }
 
 // Test that NACK, not hybrid mode, is enabled in conference mode.
@@ -1291,11 +1341,13 @@
   EXPECT_TRUE(channel_->SetSendCodecs(engine_.codecs()));
   EXPECT_FALSE(vie_.GetHybridNackFecStatus(send_channel_num));
   EXPECT_TRUE(vie_.GetNackStatus(send_channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(send_channel_num));
   // Add a receive stream.
   EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
   int receive_channel_num = vie_.GetLastChannel();
   EXPECT_FALSE(vie_.GetHybridNackFecStatus(receive_channel_num));
   EXPECT_TRUE(vie_.GetNackStatus(receive_channel_num));
+  EXPECT_FALSE(vie_.GetFecStatus(receive_channel_num));
 }
 
 // Test that when AddRecvStream in conference mode, a new channel is created