(Auto)update libjingle 72320533-> 72380285

git-svn-id: http://webrtc.googlecode.com/svn/trunk/talk@6808 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/media/webrtc/webrtcvideoengine.cc b/media/webrtc/webrtcvideoengine.cc
index 1491a9f..7afe5de 100644
--- a/media/webrtc/webrtcvideoengine.cc
+++ b/media/webrtc/webrtcvideoengine.cc
@@ -3786,6 +3786,7 @@
        it != receive_codecs_.end(); ++it) {
     pt_to_codec[it->plType] = &(*it);
   }
+  bool rtx_registered = false;
   for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
        it != receive_codecs_.end(); ++it) {
     if (it->codecType == webrtc::kVideoCodecRED) {
@@ -3796,16 +3797,18 @@
     // If this is an RTX codec we have to verify that it is associated with
     // a valid video codec which we have RTX support for.
     if (_stricmp(it->plName, kRtxCodecName) == 0) {
+      // WebRTC only supports one RTX codec at a time.
+      if (rtx_registered) {
+        LOG(LS_ERROR) << "Only one RTX codec at a time is supported.";
+        return false;
+      }
       std::map<int, int>::iterator apt_it = associated_payload_types_.find(
           it->plType);
       bool valid_apt = false;
       if (apt_it != associated_payload_types_.end()) {
         std::map<int, webrtc::VideoCodec*>::iterator codec_it =
             pt_to_codec.find(apt_it->second);
-        // We currently only support RTX associated with VP8 due to limitations
-        // in webrtc where only one RTX payload type can be registered.
-        valid_apt = codec_it != pt_to_codec.end() &&
-            _stricmp(codec_it->second->plName, kVp8CodecName) == 0;
+        valid_apt = codec_it != pt_to_codec.end();
       }
       if (!valid_apt) {
         LOG(LS_ERROR) << "The RTX codec isn't associated with a known and "
@@ -3817,6 +3820,7 @@
         LOG_RTCERR2(SetRtxReceivePayloadType, channel_id, it->plType);
         return false;
       }
+      rtx_registered = true;
       continue;
     }
     if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) {
@@ -3926,10 +3930,13 @@
       options_.screencast_min_bitrate.GetWithDefaultIfUnset(0);
   bool leaky_bucket = options_.video_leaky_bucket.GetWithDefaultIfUnset(true);
   bool reset_send_codec =
-      target_width != cur_width || target_height != cur_height ||
+    target_width != cur_width || target_height != cur_height;
+  if (vie_codec.codecType == webrtc::kVideoCodecVP8) {
+    reset_send_codec = reset_send_codec ||
       automatic_resize != vie_codec.codecSpecific.VP8.automaticResizeOn ||
       enable_denoising != vie_codec.codecSpecific.VP8.denoisingOn ||
       vp8_frame_dropping != vie_codec.codecSpecific.VP8.frameDroppingOn;
+  }
 
   if (reset_send_codec) {
     // Set the new codec on vie.
@@ -3940,9 +3947,11 @@
     vie_codec.minBitrate = target_codec.minBitrate;
     vie_codec.maxBitrate = target_codec.maxBitrate;
     vie_codec.targetBitrate = 0;
-    vie_codec.codecSpecific.VP8.automaticResizeOn = automatic_resize;
-    vie_codec.codecSpecific.VP8.denoisingOn = enable_denoising;
-    vie_codec.codecSpecific.VP8.frameDroppingOn = vp8_frame_dropping;
+    if (vie_codec.codecType == webrtc::kVideoCodecVP8) {
+      vie_codec.codecSpecific.VP8.automaticResizeOn = automatic_resize;
+      vie_codec.codecSpecific.VP8.denoisingOn = enable_denoising;
+      vie_codec.codecSpecific.VP8.frameDroppingOn = vp8_frame_dropping;
+    }
     MaybeChangeBitrates(channel_id, &vie_codec);
 
     if (engine()->vie()->codec()->SetSendCodec(channel_id, vie_codec) != 0) {
diff --git a/media/webrtc/webrtcvideoengine_unittest.cc b/media/webrtc/webrtcvideoengine_unittest.cc
index 9993a9e..18d90f8 100644
--- a/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/media/webrtc/webrtcvideoengine_unittest.cc
@@ -59,6 +59,7 @@
 static const cricket::VideoCodec kVP8Codec180p(100, "VP8", 320, 180, 30, 0);
 
 static const cricket::VideoCodec kVP8Codec(100, "VP8", 640, 400, 30, 0);
+static const cricket::VideoCodec kH264Codec(127, "H264", 640, 400, 30, 0);
 static const cricket::VideoCodec kRedCodec(101, "red", 0, 0, 0, 0);
 static const cricket::VideoCodec kUlpFecCodec(102, "ulpfec", 0, 0, 0, 0);
 static const cricket::VideoCodec* const kVideoCodecs[] = {
@@ -2114,6 +2115,142 @@
   EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
 }
 
+TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithExternalH264) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kH264Codec);
+  cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0);
+  rtx_codec.SetParam("apt", kH264Codec.id);
+  codecs.push_back(rtx_codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  EXPECT_EQ(96, vie_.GetRtxSendPayloadType(channel_num));
+
+  cricket::StreamParams params =
+    cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
+  params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
+  EXPECT_TRUE(channel_->AddSendStream(params));
+
+  EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num));
+  EXPECT_EQ(1, vie_.GetNumRtxSsrcs(channel_num));
+  EXPECT_EQ(static_cast<int>(kRtxSsrcs1[0]), vie_.GetRtxSsrc(channel_num, 0));
+
+  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 127));
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+  EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs1[0]));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, SetSendCodecsWithVP8AndExternalH264) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kH264Codec);
+  cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0);
+  rtx_codec.SetParam("apt", kH264Codec.id);
+  codecs.push_back(rtx_codec);
+  codecs.push_back(kVP8Codec);
+  cricket::VideoCodec rtx_codec2(97, "rtx", 0, 0, 0, 0);
+  rtx_codec2.SetParam("apt", kVP8Codec.id);
+  codecs.push_back(rtx_codec2);
+
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  // The first matched codec should be set, i.e., H.264.
+
+  EXPECT_EQ(96, vie_.GetRtxSendPayloadType(channel_num));
+
+  cricket::StreamParams params =
+    cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
+  params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
+  EXPECT_TRUE(channel_->AddSendStream(params));
+
+  EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num));
+  EXPECT_EQ(1, vie_.GetNumRtxSsrcs(channel_num));
+  EXPECT_EQ(static_cast<int>(kRtxSsrcs1[0]), vie_.GetRtxSsrc(channel_num, 0));
+
+  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 127));
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+  EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs1[0]));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecsWithExternalH264) {
+  // WebRtcVideoEngine assumes that if we have encode support for a codec, we
+  // also have decode support. It doesn't support decode only support. Therefore
+  // we here have to register both an encoder and a decoder factory with H264
+  // support, to be able to test the decoder factory.
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
+  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264);
+  EXPECT_TRUE(SetupEngine());
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  engine_.SetExternalDecoderFactory(&decoder_factory_);
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kH264Codec);
+  cricket::VideoCodec rtx_codec(96, "rtx", 0, 0, 0, 0);
+  rtx_codec.SetParam("apt", kH264Codec.id);
+  codecs.push_back(rtx_codec);
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+
+  EXPECT_EQ(96, vie_.GetRtxRecvPayloadType(channel_num));
+
+  cricket::StreamParams params =
+    cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
+    params.AddFidSsrc(kSsrcs1[0], kRtxSsrcs1[0]);
+  EXPECT_TRUE(channel_->AddRecvStream(params));
+
+  EXPECT_EQ(1, vie_.GetNumSsrcs(channel_num));
+  EXPECT_EQ(static_cast<int>(kRtxSsrcs1[0]),
+            vie_.GetRemoteRtxSsrc(channel_num));
+
+  EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 127));
+  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
+  EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders());
+
+  EXPECT_TRUE(channel_->RemoveRecvStream(kSsrcs1[0]));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, SetRecvCodecsWithVP8AndExternalH264) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
+  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecH264);
+  EXPECT_TRUE(SetupEngine());
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  engine_.SetExternalDecoderFactory(&decoder_factory_);
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  cricket::VideoCodec rtx_codec(97, "rtx", 0, 0, 0, 0);
+  rtx_codec.SetParam("apt", kH264Codec.id);
+  codecs.push_back(kH264Codec);
+  codecs.push_back(rtx_codec);
+
+  cricket::VideoCodec rtx_codec2(96, "rtx", 0, 0, 0, 0);
+  rtx_codec2.SetParam("apt", kVP8Codec.id);
+  codecs.push_back(kVP8Codec);
+  codecs.push_back(rtx_codec);
+  // Should fail since WebRTC only supports one RTX codec at a time.
+  EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
+
+  codecs.pop_back();
+
+  // One RTX codec should be fine.
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+
+  // The RTX payload type should have been set.
+  EXPECT_EQ(rtx_codec.id, vie_.GetRtxRecvPayloadType(channel_num));
+}
+
 // Tests that OnReadyToSend will be propagated into ViE.
 TEST_F(WebRtcVideoEngineTestFake, OnReadyToSend) {
   EXPECT_TRUE(SetupEngine());