(Auto)update libjingle 69260070-> 69276003

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6439 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/media/webrtc/fakewebrtcvoiceengine.h b/talk/media/webrtc/fakewebrtcvoiceengine.h
index 7285908..ff2079b 100644
--- a/talk/media/webrtc/fakewebrtcvoiceengine.h
+++ b/talk/media/webrtc/fakewebrtcvoiceengine.h
@@ -97,7 +97,8 @@
           volume_pan_right(1.0),
           file(false),
           vad(false),
-          fec(false),
+          codec_fec(false),
+          red(false),
           nack(false),
           media_processor_registered(false),
           rx_agc_enabled(false),
@@ -105,7 +106,7 @@
           cn8_type(13),
           cn16_type(105),
           dtmf_type(106),
-          fec_type(117),
+          red_type(117),
           nack_max_packets(0),
           vie_network(NULL),
           video_channel(-1),
@@ -125,7 +126,8 @@
     float volume_pan_right;
     bool file;
     bool vad;
-    bool fec;
+    bool codec_fec;
+    bool red;
     bool nack;
     bool media_processor_registered;
     bool rx_agc_enabled;
@@ -134,7 +136,7 @@
     int cn8_type;
     int cn16_type;
     int dtmf_type;
-    int fec_type;
+    int red_type;
     int nack_max_packets;
     webrtc::ViENetwork* vie_network;
     int video_channel;
@@ -215,8 +217,11 @@
   bool GetVAD(int channel) {
     return channels_[channel]->vad;
   }
-  bool GetFEC(int channel) {
-    return channels_[channel]->fec;
+  bool GetRED(int channel) {
+    return channels_[channel]->red;
+  }
+  bool GetCodecFEC(int channel) {
+    return channels_[channel]->codec_fec;
   }
   bool GetNACK(int channel) {
     return channels_[channel]->nack;
@@ -244,8 +249,8 @@
   int GetSendTelephoneEventPayloadType(int channel) {
     return channels_[channel]->dtmf_type;
   }
-  int GetSendFECPayloadType(int channel) {
-    return channels_[channel]->fec_type;
+  int GetSendREDPayloadType(int channel) {
+    return channels_[channel]->red_type;
   }
   bool CheckPacket(int channel, const void* data, size_t len) {
     bool result = !CheckNoPacket(channel);
@@ -531,6 +536,16 @@
   }
   WEBRTC_STUB(GetVADStatus, (int channel, bool& enabled,
                              webrtc::VadModes& mode, bool& disabledDTX));
+  WEBRTC_FUNC(SetFECStatus, (int channel, bool enable)) {
+    WEBRTC_CHECK_CHANNEL(channel);
+    channels_[channel]->codec_fec = enable;
+    return 0;
+  }
+  WEBRTC_FUNC(GetFECStatus, (int channel, bool& enable)) {
+    WEBRTC_CHECK_CHANNEL(channel);
+    enable = channels_[channel]->codec_fec;
+    return 0;
+  }
 
   // webrtc::VoEDtmf
   WEBRTC_FUNC(SendTelephoneEvent, (int channel, int event_code,
@@ -843,16 +858,24 @@
     stats.packetsReceived = kIntStatValue;
     return 0;
   }
+#ifdef USE_WEBRTC_DEV_BRANCH
+  WEBRTC_FUNC(SetREDStatus, (int channel, bool enable, int redPayloadtype)) {
+#else
   WEBRTC_FUNC(SetFECStatus, (int channel, bool enable, int redPayloadtype)) {
+#endif  // USE_WEBRTC_DEV_BRANCH
     WEBRTC_CHECK_CHANNEL(channel);
-    channels_[channel]->fec = enable;
-    channels_[channel]->fec_type = redPayloadtype;
+    channels_[channel]->red = enable;
+    channels_[channel]->red_type = redPayloadtype;
     return 0;
   }
+#ifdef USE_WEBRTC_DEV_BRANCH
+  WEBRTC_FUNC(GetREDStatus, (int channel, bool& enable, int& redPayloadtype)) {
+#else
   WEBRTC_FUNC(GetFECStatus, (int channel, bool& enable, int& redPayloadtype)) {
+#endif  // USE_WEBRTC_DEV_BRANCH
     WEBRTC_CHECK_CHANNEL(channel);
-    enable = channels_[channel]->fec;
-    redPayloadtype = channels_[channel]->fec_type;
+    enable = channels_[channel]->red;
+    redPayloadtype = channels_[channel]->red_type;
     return 0;
   }
   WEBRTC_FUNC(SetNACKStatus, (int channel, bool enable, int maxNoPackets)) {
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index d7b3c4c..785cdf1 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -426,6 +426,16 @@
   return bitrate;
 }
 
+// True if params["useinbandfec"] == "1"
+static bool IsOpusFecEnabled(const AudioCodec& codec) {
+  CodecParameterMap::const_iterator param =
+      codec.params.find(kCodecParamUseInbandFec);
+  if (param == codec.params.end())
+    return false;
+
+  return param->second == kParamValueTrue;
+}
+
 void WebRtcVoiceEngine::ConstructCodecs() {
   LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
   int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
@@ -1943,10 +1953,16 @@
 
 bool WebRtcVoiceMediaChannel::SetSendCodecs(
     int channel, const std::vector<AudioCodec>& codecs) {
-  // Disable VAD, and FEC unless we know the other side wants them.
+  // Disable VAD, FEC, and RED unless we know the other side wants them.
   engine()->voe()->codec()->SetVADStatus(channel, false);
   engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
+#ifdef USE_WEBRTC_DEV_BRANCH
+  engine()->voe()->rtp()->SetREDStatus(channel, false);
+  engine()->voe()->codec()->SetFECStatus(channel, false);
+#else
+  // TODO(minyue): Remove code under #else case after new WebRTC roll.
   engine()->voe()->rtp()->SetFECStatus(channel, false);
+#endif  // USE_WEBRTC_DEV_BRANCH
 
   // Scan through the list to figure out the codec to use for sending, along
   // with the proper configuration for VAD and DTMF.
@@ -2005,11 +2021,24 @@
       if (bitrate_from_params != 0) {
         voe_codec.rate = bitrate_from_params;
       }
+
+      // If FEC is enabled.
+      if (IsOpusFecEnabled(*it)) {
+        LOG(LS_INFO) << "Enabling Opus FEC on channel " << channel;
+#ifdef USE_WEBRTC_DEV_BRANCH
+        if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
+          // Enable in-band FEC of the Opus codec. Treat any failure as a fatal
+          // internal error.
+          LOG_RTCERR2(SetFECStatus, channel, true);
+          return false;
+        }
+#endif  // USE_WEBRTC_DEV_BRANCH
+      }
     }
 
     // We'll use the first codec in the list to actually send audio data.
     // Be sure to use the payload type requested by the remote side.
-    // "red", for FEC audio, is a special case where the actual codec to be
+    // "red", for RED audio, is a special case where the actual codec to be
     // used is specified in params.
     if (IsRedCodec(it->name)) {
       // Parse out the RED parameters. If we fail, just ignore RED;
@@ -2020,9 +2049,16 @@
 
       // Enable redundant encoding of the specified codec. Treat any
       // failure as a fatal internal error.
+#ifdef USE_WEBRTC_DEV_BRANCH
+      LOG(LS_INFO) << "Enabling RED on channel " << channel;
+      if (engine()->voe()->rtp()->SetREDStatus(channel, true, it->id) == -1) {
+        LOG_RTCERR3(SetREDStatus, channel, true, it->id);
+#else
+      // TODO(minyue): Remove code under #else case after new WebRTC roll.
       LOG(LS_INFO) << "Enabling FEC";
       if (engine()->voe()->rtp()->SetFECStatus(channel, true, it->id) == -1) {
         LOG_RTCERR3(SetFECStatus, channel, true, it->id);
+#endif  // USE_WEBRTC_DEV_BRANCH
         return false;
       }
     } else {
diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index 5dab4ff..80a50c5 100644
--- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -745,7 +745,7 @@
   EXPECT_EQ(48000, gcodec.rate);
   EXPECT_STREQ("ISAC", gcodec.plname);
   EXPECT_FALSE(voe_.GetVAD(channel_num));
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
   EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
   EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true));
   EXPECT_EQ(106, voe_.GetSendTelephoneEventPayloadType(channel_num));
@@ -1144,6 +1144,81 @@
   EXPECT_TRUE(voe_.GetNACK(channel_num));
 }
 
+#ifdef USE_WEBRTC_DEV_BRANCH
+// Test that without useinbandfec, Opus FEC is off.
+TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecNoOpusFEC) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = voe_.GetLastChannel();
+  std::vector<cricket::AudioCodec> codecs;
+  codecs.push_back(kOpusCodec);
+  codecs[0].bitrate = 0;
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_FALSE(voe_.GetCodecFEC(channel_num));
+}
+
+// Test that with useinbandfec=0, Opus FEC is off.
+TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusDisableFEC) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = voe_.GetLastChannel();
+  std::vector<cricket::AudioCodec> codecs;
+  codecs.push_back(kOpusCodec);
+  codecs[0].bitrate = 0;
+  codecs[0].params["useinbandfec"] = "0";
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_FALSE(voe_.GetCodecFEC(channel_num));
+  webrtc::CodecInst gcodec;
+  EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
+  EXPECT_STREQ("opus", gcodec.plname);
+  EXPECT_EQ(1, gcodec.channels);
+  EXPECT_EQ(32000, gcodec.rate);
+}
+
+// Test that with useinbandfec=1, Opus FEC is on.
+TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusEnableFEC) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = voe_.GetLastChannel();
+  std::vector<cricket::AudioCodec> codecs;
+  codecs.push_back(kOpusCodec);
+  codecs[0].bitrate = 0;
+  codecs[0].params["useinbandfec"] = "1";
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_TRUE(voe_.GetCodecFEC(channel_num));
+  webrtc::CodecInst gcodec;
+  EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
+  EXPECT_STREQ("opus", gcodec.plname);
+  EXPECT_EQ(1, gcodec.channels);
+  EXPECT_EQ(32000, gcodec.rate);
+}
+
+// Test that with useinbandfec=1, stereo=1, Opus FEC is on.
+TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusEnableFECStereo) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = voe_.GetLastChannel();
+  std::vector<cricket::AudioCodec> codecs;
+  codecs.push_back(kOpusCodec);
+  codecs[0].bitrate = 0;
+  codecs[0].params["stereo"] = "1";
+  codecs[0].params["useinbandfec"] = "1";
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_TRUE(voe_.GetCodecFEC(channel_num));
+  webrtc::CodecInst gcodec;
+  EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
+  EXPECT_STREQ("opus", gcodec.plname);
+  EXPECT_EQ(2, gcodec.channels);
+  EXPECT_EQ(64000, gcodec.rate);
+}
+
+// Test that with non-Opus, codec FEC is off.
+TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecIsacNoFEC) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = voe_.GetLastChannel();
+  std::vector<cricket::AudioCodec> codecs;
+  codecs.push_back(kIsacCodec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_FALSE(voe_.GetCodecFEC(channel_num));
+}
+#endif  // USE_WEBRTC_DEV_BRANCH
+
 // Test that we can apply CELT with stereo mode but fail with mono mode.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCelt) {
   EXPECT_TRUE(SetupEngine());
@@ -1315,7 +1390,7 @@
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
   EXPECT_TRUE(voe_.GetVAD(channel_num));
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
   EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
   EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
   EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
@@ -1348,7 +1423,7 @@
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
   EXPECT_TRUE(voe_.GetVAD(channel_num));
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
   EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
   EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
   EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
@@ -1412,13 +1487,13 @@
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
   EXPECT_TRUE(voe_.GetVAD(channel_num));
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
   EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false));
   EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true));
   EXPECT_EQ(98, voe_.GetSendTelephoneEventPayloadType(channel_num));
 }
 
-// Test that we set up FEC correctly as caller.
+// Test that we set up RED correctly as caller.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDAsCaller) {
   EXPECT_TRUE(SetupEngine());
   int channel_num = voe_.GetLastChannel();
@@ -1434,11 +1509,11 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_TRUE(voe_.GetFEC(channel_num));
-  EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
+  EXPECT_TRUE(voe_.GetRED(channel_num));
+  EXPECT_EQ(127, voe_.GetSendREDPayloadType(channel_num));
 }
 
-// Test that we set up FEC correctly as callee.
+// Test that we set up RED correctly as callee.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDAsCallee) {
   EXPECT_TRUE(engine_.Init(talk_base::Thread::Current()));
   channel_ = engine_.CreateChannel();
@@ -1459,11 +1534,11 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_TRUE(voe_.GetFEC(channel_num));
-  EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
+  EXPECT_TRUE(voe_.GetRED(channel_num));
+  EXPECT_EQ(127, voe_.GetSendREDPayloadType(channel_num));
 }
 
-// Test that we set up FEC correctly if params are omitted.
+// Test that we set up RED correctly if params are omitted.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsREDNoParams) {
   EXPECT_TRUE(SetupEngine());
   int channel_num = voe_.GetLastChannel();
@@ -1478,8 +1553,8 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_TRUE(voe_.GetFEC(channel_num));
-  EXPECT_EQ(127, voe_.GetSendFECPayloadType(channel_num));
+  EXPECT_TRUE(voe_.GetRED(channel_num));
+  EXPECT_EQ(127, voe_.GetSendREDPayloadType(channel_num));
 }
 
 // Test that we ignore RED if the parameters aren't named the way we expect.
@@ -1498,7 +1573,7 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
 }
 
 // Test that we ignore RED if it uses different primary/secondary encoding.
@@ -1517,7 +1592,7 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
 }
 
 // Test that we ignore RED if it uses more than 2 encodings.
@@ -1536,7 +1611,7 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
 }
 
 // Test that we ignore RED if it has bogus codec ids.
@@ -1555,7 +1630,7 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
 }
 
 // Test that we ignore RED if it refers to a codec that is not present.
@@ -1574,7 +1649,7 @@
   EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
   EXPECT_EQ(96, gcodec.pltype);
   EXPECT_STREQ("ISAC", gcodec.plname);
-  EXPECT_FALSE(voe_.GetFEC(channel_num));
+  EXPECT_FALSE(voe_.GetRED(channel_num));
 }
 
 // Test support for audio level header extension.