Removing FEC functionality from the default RTP module.

This CL removes the last default module methods used from ViEEncoder and
the default module itself will be removed in a separate CL.

BUG=769
R=stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/35309004

Cr-Commit-Position: refs/heads/master@{#8505}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8505 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
index d895880..1a2f25a 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc
@@ -94,10 +94,10 @@
   configuration.clock = system_clock_;
   configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get();
   dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
-  rtcp_sender_ =
-      new RTCPSender(0, false, system_clock_, receive_statistics_.get(), NULL);
-  rtcp_receiver_ =
-      new RTCPReceiver(0, system_clock_, NULL, dummy_rtp_rtcp_impl_);
+  rtcp_sender_ = new RTCPSender(0, false, system_clock_,
+                                receive_statistics_.get(), NULL);
+  rtcp_receiver_ = new RTCPReceiver(0, system_clock_, NULL, NULL, NULL,
+                                    dummy_rtp_rtcp_impl_);
   test_transport_ = new TestTransport(rtcp_receiver_);
 
   EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_));
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
index b1b46df..02f1fa3 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -32,6 +32,8 @@
     int32_t id,
     Clock* clock,
     RtcpPacketTypeCounterObserver* packet_type_counter_observer,
+    RtcpBandwidthObserver* rtcp_bandwidth_observer,
+    RtcpIntraFrameObserver* rtcp_intra_frame_observer,
     ModuleRtpRtcpImpl* owner)
     : TMMBRHelp(),
       _clock(clock),
@@ -40,8 +42,8 @@
       _rtpRtcp(*owner),
       _criticalSectionFeedbacks(
           CriticalSectionWrapper::CreateCriticalSection()),
-      _cbRtcpBandwidthObserver(NULL),
-      _cbRtcpIntraFrameObserver(NULL),
+      _cbRtcpBandwidthObserver(rtcp_bandwidth_observer),
+      _cbRtcpIntraFrameObserver(rtcp_intra_frame_observer),
       _criticalSectionRTCPReceiver(
           CriticalSectionWrapper::CreateCriticalSection()),
       main_ssrc_(0),
@@ -131,14 +133,6 @@
   return _remoteSSRC;
 }
 
-void RTCPReceiver::RegisterRtcpObservers(
-    RtcpIntraFrameObserver* intra_frame_callback,
-    RtcpBandwidthObserver* bandwidth_callback) {
-  CriticalSectionScoped lock(_criticalSectionFeedbacks);
-  _cbRtcpIntraFrameObserver = intra_frame_callback;
-  _cbRtcpBandwidthObserver = bandwidth_callback;
-}
-
 void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
                             const std::set<uint32_t>& registered_ssrcs) {
   uint32_t old_ssrc = 0;
@@ -149,7 +143,6 @@
     registered_ssrcs_ = registered_ssrcs;
   }
   {
-    CriticalSectionScoped lock(_criticalSectionFeedbacks);
     if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
       _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
     }
@@ -1291,7 +1284,6 @@
   // Get net bitrate from bounding set depending on sent packet rate
   if (CalcMinBitRate(&bitrate)) {
     // we have a new bandwidth estimate on this channel
-    CriticalSectionScoped lock(_criticalSectionFeedbacks);
     if (_cbRtcpBandwidthObserver) {
         _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
     }
@@ -1336,8 +1328,6 @@
     }
   }
   {
-    CriticalSectionScoped lock(_criticalSectionFeedbacks);
-
     // We need feedback that we have received a report block(s) so that we
     // can generate a new packet in a conference relay scenario, one received
     // report can generate several RTCP packets, based on number relayed/mixed
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h
index 919e966..2086afc 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -32,6 +32,8 @@
  RTCPReceiver(int32_t id,
               Clock* clock,
               RtcpPacketTypeCounterObserver* packet_type_counter_observer,
+              RtcpBandwidthObserver* rtcp_bandwidth_observer,
+              RtcpIntraFrameObserver* rtcp_intra_frame_observer,
               ModuleRtpRtcpImpl* owner);
     virtual ~RTCPReceiver();
 
@@ -49,9 +51,6 @@
 
     uint32_t RelaySSRC() const;
 
-    void RegisterRtcpObservers(RtcpIntraFrameObserver* intra_frame_callback,
-                               RtcpBandwidthObserver* bandwidth_callback);
-
     int32_t IncomingRTCPPacket(
         RTCPHelp::RTCPPacketInformation& rtcpPacketInformation,
         RTCPUtility::RTCPParserV2 *rtcpParser);
@@ -238,8 +237,8 @@
   ModuleRtpRtcpImpl& _rtpRtcp;
 
   CriticalSectionWrapper* _criticalSectionFeedbacks;
-  RtcpBandwidthObserver* _cbRtcpBandwidthObserver;
-  RtcpIntraFrameObserver* _cbRtcpIntraFrameObserver;
+  RtcpBandwidthObserver* const _cbRtcpBandwidthObserver;
+  RtcpIntraFrameObserver* const _cbRtcpIntraFrameObserver;
 
   CriticalSectionWrapper* _criticalSectionRTCPReceiver;
   uint32_t main_ssrc_;
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index fc09542..fcd4df8 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -86,7 +86,8 @@
     configuration.outgoing_transport = test_transport_;
     configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get();
     rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
-    rtcp_receiver_ = new RTCPReceiver(0, &system_clock_, NULL, rtp_rtcp_impl_);
+    rtcp_receiver_ = new RTCPReceiver(0, &system_clock_, NULL, NULL, NULL,
+                                      rtp_rtcp_impl_);
     test_transport_->SetRTCPReceiver(rtcp_receiver_);
   }
   ~RtcpReceiverTest() {
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
index 4e532e6..d548e26 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
@@ -305,7 +305,8 @@
         0, &clock_, test_transport_, NULL, rtp_payload_registry_.get()));
     rtcp_sender_ =
         new RTCPSender(0, false, &clock_, receive_statistics_.get(), NULL);
-    rtcp_receiver_ = new RTCPReceiver(0, &clock_, NULL, rtp_rtcp_impl_);
+    rtcp_receiver_ = new RTCPReceiver(0, &clock_, NULL, NULL, NULL,
+                                      rtp_rtcp_impl_);
     test_transport_->SetRTCPReceiver(rtcp_receiver_);
     // Initialize
     EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_));
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 60e1a27..9acf5fe 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -76,6 +76,8 @@
       rtcp_receiver_(configuration.id,
                      configuration.clock,
                      configuration.rtcp_packet_type_counter_observer,
+                     configuration.bandwidth_callback,
+                     configuration.intra_frame_callback,
                      this),
       clock_(configuration.clock),
       id_(configuration.id),
@@ -108,8 +110,6 @@
     default_module_->RegisterChildModule(this);
   }
   // TODO(pwestin) move to constructors of each rtp/rtcp sender/receiver object.
-  rtcp_receiver_.RegisterRtcpObservers(configuration.intra_frame_callback,
-                                       configuration.bandwidth_callback);
   rtcp_sender_.RegisterSendTransport(configuration.outgoing_transport);
 
   // Make sure that RTCP objects are aware of our SSRC.
@@ -970,20 +970,7 @@
 int32_t ModuleRtpRtcpImpl::SetFecParameters(
     const FecProtectionParams* delta_params,
     const FecProtectionParams* key_params) {
-  if (IsDefaultModule())  {
-    // For default we need to update all child modules too.
-    CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-
-    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
-    while (it != child_modules_.end()) {
-      RtpRtcp* module = *it;
-      if (module) {
-        module->SetFecParameters(delta_params, key_params);
-      }
-      it++;
-    }
-    return 0;
-  }
+  DCHECK(!IsDefaultModule());
   return rtp_sender_.SetFecParameters(delta_params, key_params);
 }
 
@@ -1015,52 +1002,11 @@
                                     uint32_t* video_rate,
                                     uint32_t* fec_rate,
                                     uint32_t* nack_rate) const {
-  if (IsDefaultModule()) {
-    // For default we need to update the send bitrate.
-    CriticalSectionScoped lock(critical_section_module_ptrs_feedback_.get());
-
-    if (total_rate != NULL)
-      *total_rate = 0;
-    if (video_rate != NULL)
-      *video_rate = 0;
-    if (fec_rate != NULL)
-      *fec_rate = 0;
-    if (nack_rate != NULL)
-      *nack_rate = 0;
-
-    std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
-    while (it != child_modules_.end()) {
-      RtpRtcp* module = *it;
-      if (module) {
-        uint32_t child_total_rate = 0;
-        uint32_t child_video_rate = 0;
-        uint32_t child_fec_rate = 0;
-        uint32_t child_nack_rate = 0;
-        module->BitrateSent(&child_total_rate,
-                            &child_video_rate,
-                            &child_fec_rate,
-                            &child_nack_rate);
-        if (total_rate != NULL && child_total_rate > *total_rate)
-          *total_rate = child_total_rate;
-        if (video_rate != NULL && child_video_rate > *video_rate)
-          *video_rate = child_video_rate;
-        if (fec_rate != NULL && child_fec_rate > *fec_rate)
-          *fec_rate = child_fec_rate;
-        if (nack_rate != NULL && child_nack_rate > *nack_rate)
-          *nack_rate = child_nack_rate;
-      }
-      it++;
-    }
-    return;
-  }
-  if (total_rate != NULL)
-    *total_rate = rtp_sender_.BitrateSent();
-  if (video_rate != NULL)
-    *video_rate = rtp_sender_.VideoBitrateSent();
-  if (fec_rate != NULL)
-    *fec_rate = rtp_sender_.FecOverheadRate();
-  if (nack_rate != NULL)
-    *nack_rate = rtp_sender_.NackOverheadRate();
+  DCHECK(!IsDefaultModule());
+  *total_rate = rtp_sender_.BitrateSent();
+  *video_rate = rtp_sender_.VideoBitrateSent();
+  *fec_rate = rtp_sender_.FecOverheadRate();
+  *nack_rate = rtp_sender_.NackOverheadRate();
 }
 
 void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 95cba40..50b8a49 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -58,6 +58,26 @@
   }
 
  private:
+  ViEChannel* const owner_;
+};
+
+class ViEChannelProtectionCallback : public VCMProtectionCallback {
+ public:
+  ViEChannelProtectionCallback(ViEChannel* owner) : owner_(owner) {}
+  ~ViEChannelProtectionCallback() {}
+
+
+  int ProtectionRequest(
+      const FecProtectionParams* delta_fec_params,
+      const FecProtectionParams* key_fec_params,
+      uint32_t* sent_video_rate_bps,
+      uint32_t* sent_nack_rate_bps,
+      uint32_t* sent_fec_rate_bps) override {
+    return owner_->ProtectionRequest(delta_fec_params, key_fec_params,
+                                     sent_video_rate_bps, sent_nack_rate_bps,
+                                     sent_fec_rate_bps);
+  }
+ private:
   ViEChannel* owner_;
 };
 
@@ -83,6 +103,7 @@
       rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()),
       default_rtp_rtcp_(default_rtp_rtcp),
       send_payload_router_(new PayloadRouter()),
+      vcm_protection_callback_(new ViEChannelProtectionCallback(this)),
       vcm_(VideoCodingModule::Create()),
       vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this),
       vie_sender_(channel_id),
@@ -699,6 +720,23 @@
   return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
 }
 
+bool ViEChannel::IsSendingFecEnabled() {
+  bool fec_enabled = false;
+  uint8_t pltype_red = 0;
+  uint8_t pltype_fec = 0;
+  rtp_rtcp_->GenericFECStatus(fec_enabled, pltype_red, pltype_fec);
+  if (fec_enabled)
+    return true;
+
+  CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+  for (auto* module : simulcast_rtp_rtcp_) {
+    module->GenericFECStatus(fec_enabled, pltype_red, pltype_fec);
+    if (fec_enabled)
+      return true;
+  }
+  return false;
+}
+
 int32_t ViEChannel::ProcessFECRequest(
     const bool enable,
     const unsigned char payload_typeRED,
@@ -1513,6 +1551,10 @@
   return send_payload_router_;
 }
 
+VCMProtectionCallback* ViEChannel::vcm_protection_callback() {
+  return vcm_protection_callback_.get();
+}
+
 CallStatsObserver* ViEChannel::GetStatsObserver() {
   return stats_observer_.get();
 }
@@ -1650,6 +1692,30 @@
   vcm_->SetReceiveChannelParameters(rtt);
 }
 
+int ViEChannel::ProtectionRequest(const FecProtectionParams* delta_fec_params,
+                                  const FecProtectionParams* key_fec_params,
+                                  uint32_t* video_rate_bps,
+                                  uint32_t* nack_rate_bps,
+                                  uint32_t* fec_rate_bps) {
+  uint32_t not_used = 0;
+  rtp_rtcp_->SetFecParameters(delta_fec_params, key_fec_params);
+  rtp_rtcp_->BitrateSent(&not_used, video_rate_bps, fec_rate_bps,
+                         nack_rate_bps);
+  CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+  for (auto* module : simulcast_rtp_rtcp_) {
+    uint32_t child_video_rate = 0;
+    uint32_t child_fec_rate = 0;
+    uint32_t child_nack_rate = 0;
+    module->SetFecParameters(delta_fec_params, key_fec_params);
+    module->BitrateSent(&not_used, &child_video_rate, &child_fec_rate,
+                        &child_nack_rate);
+    *video_rate_bps += child_video_rate;
+    *nack_rate_bps += child_nack_rate;
+    *fec_rate_bps += child_fec_rate;
+  }
+  return 0;
+}
+
 void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) {
   for (size_t total_modules =
            1 + simulcast_rtp_rtcp_.size() + removed_rtp_rtcp_.size();
diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h
index 59ec250..dbb07b1 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -45,6 +45,7 @@
 class ReportBlockStats;
 class RtcpRttStats;
 class ThreadWrapper;
+class ViEChannelProtectionCallback;
 class ViEDecoderObserver;
 class ViEEffectFilter;
 class ViERTPObserver;
@@ -63,6 +64,7 @@
       public ViEFrameProviderBase {
  public:
   friend class ChannelStatsObserver;
+  friend class ViEChannelProtectionCallback;
 
   ViEChannel(int32_t channel_id,
              int32_t engine_id,
@@ -120,6 +122,7 @@
   int32_t SetHybridNACKFECStatus(const bool enable,
                                  const unsigned char payload_typeRED,
                                  const unsigned char payload_typeFEC);
+  bool IsSendingFecEnabled();
   int SetSenderBufferingMode(int target_delay_ms);
   int SetReceiverBufferingMode(int target_delay_ms);
   int32_t SetKeyFrameRequestMethod(const KeyFrameRequestMethod method);
@@ -305,6 +308,8 @@
   // Gets the modules used by the channel.
   RtpRtcp* rtp_rtcp();
   scoped_refptr<PayloadRouter> send_payload_router();
+  VCMProtectionCallback* vcm_protection_callback();
+
 
   CallStatsObserver* GetStatsObserver();
 
@@ -372,6 +377,12 @@
 
   void OnRttUpdate(int64_t rtt);
 
+  int ProtectionRequest(const FecProtectionParams* delta_fec_params,
+                        const FecProtectionParams* key_fec_params,
+                        uint32_t* sent_video_rate_bps,
+                        uint32_t* sent_nack_rate_bps,
+                        uint32_t* sent_fec_rate_bps);
+
  private:
   void ReserveRtpRtcpModules(size_t total_modules)
       EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_);
@@ -497,6 +508,7 @@
   std::list<RtpRtcp*> simulcast_rtp_rtcp_;
   std::list<RtpRtcp*> removed_rtp_rtcp_;
   scoped_refptr<PayloadRouter> send_payload_router_;
+  scoped_ptr<ViEChannelProtectionCallback> vcm_protection_callback_;
 
   VideoCodingModule* const vcm_;
   ViEReceiver vie_receiver_;
diff --git a/webrtc/video_engine/vie_channel_manager.cc b/webrtc/video_engine/vie_channel_manager.cc
index d0fcaaf..9a70364 100644
--- a/webrtc/video_engine/vie_channel_manager.cc
+++ b/webrtc/video_engine/vie_channel_manager.cc
@@ -118,8 +118,9 @@
     return -1;
   }
   // Connect the encoder with the send packet router, to enable sending.
-  vie_encoder->StartThreadsAndSetSendPayloadRouter(
-      channel_map_[new_channel_id]->send_payload_router());
+  vie_encoder->StartThreadsAndSetSharedMembers(
+      channel_map_[new_channel_id]->send_payload_router(),
+      channel_map_[new_channel_id]->vcm_protection_callback());
 
   // Add ViEEncoder to EncoderFeedBackObserver.
   unsigned int ssrc = 0;
@@ -184,8 +185,9 @@
       vie_encoder = NULL;
     }
     // Connect the encoder with the send packet router, to enable sending.
-    vie_encoder->StartThreadsAndSetSendPayloadRouter(
-        channel_map_[new_channel_id]->send_payload_router());
+    vie_encoder->StartThreadsAndSetSharedMembers(
+        channel_map_[new_channel_id]->send_payload_router(),
+        channel_map_[new_channel_id]->vcm_protection_callback());
 
     // Register the ViEEncoder to get key frame requests for this channel.
     unsigned int ssrc = 0;
@@ -254,7 +256,7 @@
     // threads and processing. This must be done before deleting the channel.
     if (vie_encoder->channel_id() == channel_id) {
       group->GetEncoderStateFeedback()->RemoveEncoder(vie_encoder);
-      vie_encoder->StopThreadsAndRemovePayloadRouter();
+      vie_encoder->StopThreadsAndRemoveSharedMembers();
     }
 
     unsigned int remote_ssrc = 0;
diff --git a/webrtc/video_engine/vie_codec_impl.cc b/webrtc/video_engine/vie_codec_impl.cc
index c64a738..c442f59 100644
--- a/webrtc/video_engine/vie_codec_impl.cc
+++ b/webrtc/video_engine/vie_codec_impl.cc
@@ -243,7 +243,8 @@
   shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
 
   // Update the protection mode, we might be switching NACK/FEC.
-  vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled());
+  vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled(),
+                                      vie_channel->IsSendingFecEnabled());
 
   // Get new best format for frame provider.
   ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc
index 8324154..48fa0f0 100644
--- a/webrtc/video_engine/vie_encoder.cc
+++ b/webrtc/video_engine/vie_encoder.cc
@@ -143,6 +143,7 @@
     vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id,
                                                             channel_id))),
     send_payload_router_(NULL),
+    vcm_protection_callback_(NULL),
     callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
     data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
     bitrate_controller_(bitrate_controller),
@@ -228,10 +229,14 @@
   return true;
 }
 
-void ViEEncoder::StartThreadsAndSetSendPayloadRouter(
-    scoped_refptr<PayloadRouter> send_payload_router) {
+void ViEEncoder::StartThreadsAndSetSharedMembers(
+    scoped_refptr<PayloadRouter> send_payload_router,
+    VCMProtectionCallback* vcm_protection_callback) {
   DCHECK(send_payload_router_ == NULL);
+  DCHECK(vcm_protection_callback_ == NULL);
+
   send_payload_router_ = send_payload_router;
+  vcm_protection_callback_ = vcm_protection_callback;
 
   module_process_thread_.RegisterModule(&vcm_);
   module_process_thread_.RegisterModule(default_rtp_rtcp_.get());
@@ -239,7 +244,9 @@
   pacer_thread_->Start();
 }
 
-void ViEEncoder::StopThreadsAndRemovePayloadRouter() {
+void ViEEncoder::StopThreadsAndRemoveSharedMembers() {
+  vcm_.RegisterProtectionCallback(NULL);
+  vcm_protection_callback_ = NULL;
   pacer_thread_->Stop();
   pacer_thread_->DeRegisterModule(paced_sender_.get());
   module_process_thread_.DeRegisterModule(&vcm_);
@@ -651,29 +658,19 @@
   return 0;
 }
 
-int32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) {
+int32_t ViEEncoder::UpdateProtectionMethod(bool nack, bool fec) {
   DCHECK(send_payload_router_ != NULL);
-  bool fec_enabled = false;
-  uint8_t dummy_ptype_red = 0;
-  uint8_t dummy_ptypeFEC = 0;
+  DCHECK(vcm_protection_callback_ != NULL);
 
-  // Updated protection method to VCM to get correct packetization sizes.
-  // FEC has larger overhead than NACK -> set FEC if used.
-  int32_t error = default_rtp_rtcp_->GenericFECStatus(fec_enabled,
-                                                      dummy_ptype_red,
-                                                      dummy_ptypeFEC);
-  if (error) {
-    return -1;
-  }
-  if (fec_enabled_ == fec_enabled && nack_enabled_ == enable_nack) {
+  if (fec_enabled_ == fec && nack_enabled_ == nack) {
     // No change needed, we're already in correct state.
     return 0;
   }
-  fec_enabled_ = fec_enabled;
-  nack_enabled_ = enable_nack;
+  fec_enabled_ = fec;
+  nack_enabled_ = nack;
 
   // Set Video Protection for VCM.
-  if (fec_enabled && nack_enabled_) {
+  if (fec_enabled_ && nack_enabled_) {
     vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true);
   } else {
     vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_);
@@ -682,7 +679,7 @@
   }
 
   if (fec_enabled_ || nack_enabled_) {
-    vcm_.RegisterProtectionCallback(this);
+    vcm_.RegisterProtectionCallback(vcm_protection_callback_);
     // The send codec must be registered to set correct MTU.
     webrtc::VideoCodec codec;
     if (vcm_.SendCodec(&codec) == 0) {
@@ -741,18 +738,6 @@
       rtp_video_hdr) ? 0 : -1;
 }
 
-int32_t ViEEncoder::ProtectionRequest(
-    const FecProtectionParams* delta_fec_params,
-    const FecProtectionParams* key_fec_params,
-    uint32_t* sent_video_rate_bps,
-    uint32_t* sent_nack_rate_bps,
-    uint32_t* sent_fec_rate_bps) {
-  default_rtp_rtcp_->SetFecParameters(delta_fec_params, key_fec_params);
-  default_rtp_rtcp_->BitrateSent(NULL, sent_video_rate_bps, sent_fec_rate_bps,
-                                sent_nack_rate_bps);
-  return 0;
-}
-
 int32_t ViEEncoder::SendStatistics(const uint32_t bit_rate,
                                    const uint32_t frame_rate) {
   bitrate_controller_->SetBitrateSent(bit_rate);
diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h
index 34120bc..a862af7 100644
--- a/webrtc/video_engine/vie_encoder.h
+++ b/webrtc/video_engine/vie_encoder.h
@@ -48,7 +48,6 @@
 class ViEEncoder
     : public RtcpIntraFrameObserver,
       public VCMPacketizationCallback,
-      public VCMProtectionCallback,
       public VCMSendStatisticsCallback,
       public ViEFrameCallback {
  public:
@@ -70,12 +69,13 @@
   // only once.
   // Ideally this would be done in Init, but the dependencies between ViEEncoder
   // and ViEChannel makes it really hard to do in a good way.
-  void StartThreadsAndSetSendPayloadRouter(
-      scoped_refptr<PayloadRouter> send_payload_router);
+  void StartThreadsAndSetSharedMembers(
+      scoped_refptr<PayloadRouter> send_payload_router,
+      VCMProtectionCallback* vcm_protection_callback);
 
   // This function must be called before the corresponding ViEChannel is
   // deleted.
-  void StopThreadsAndRemovePayloadRouter();
+  void StopThreadsAndRemoveSharedMembers();
 
   void SetNetworkTransmissionState(bool is_transmitting);
 
@@ -129,7 +129,7 @@
 
   int CodecTargetBitrate(uint32_t* bitrate) const;
   // Loss protection.
-  int32_t UpdateProtectionMethod(bool enable_nack);
+  int32_t UpdateProtectionMethod(bool nack, bool fec);
   bool nack_enabled() const { return nack_enabled_; }
 
   // Buffering mode.
@@ -141,14 +141,6 @@
                            const RTPFragmentationHeader& fragmentation_header,
                            const RTPVideoHeader* rtp_video_hdr) OVERRIDE;
 
-  // Implements VideoProtectionCallback.
-  virtual int ProtectionRequest(
-      const FecProtectionParams* delta_fec_params,
-      const FecProtectionParams* key_fec_params,
-      uint32_t* sent_video_rate_bps,
-      uint32_t* sent_nack_rate_bps,
-      uint32_t* sent_fec_rate_bps) OVERRIDE;
-
   // Implements VideoSendStatisticsCallback.
   virtual int32_t SendStatistics(const uint32_t bit_rate,
                                  const uint32_t frame_rate) OVERRIDE;
@@ -218,6 +210,8 @@
   VideoProcessingModule& vpm_;
   rtc::scoped_ptr<RtpRtcp> default_rtp_rtcp_;
   scoped_refptr<PayloadRouter> send_payload_router_;
+  VCMProtectionCallback* vcm_protection_callback_;
+
   rtc::scoped_ptr<CriticalSectionWrapper> callback_cs_;
   rtc::scoped_ptr<CriticalSectionWrapper> data_cs_;
   rtc::scoped_ptr<BitrateObserver> bitrate_observer_;
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
index bf27d8a..96307e1 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
@@ -382,7 +382,8 @@
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
-  vie_encoder->UpdateProtectionMethod(enable);
+  vie_encoder->UpdateProtectionMethod(enable,
+                                      vie_channel->IsSendingFecEnabled());
   return 0;
 }
 
@@ -410,7 +411,7 @@
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
-  vie_encoder->UpdateProtectionMethod(false);
+  vie_encoder->UpdateProtectionMethod(false, true);
   return 0;
 }
 
@@ -443,7 +444,7 @@
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
-  vie_encoder->UpdateProtectionMethod(enable);
+  vie_encoder->UpdateProtectionMethod(enable, enable);
   return 0;
 }