Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video_engine / vie_channel.cc
index 34a0950..bbcb602 100644 (file)
@@ -41,6 +41,50 @@ const int kInvalidRtpExtensionId = 0;
 static const int kMaxTargetDelayMs = 10000;
 static const float kMaxIncompleteTimeMultiplier = 3.5f;
 
+namespace {
+
+RTCPReportBlock AggregateReportBlocks(
+    const std::vector<RTCPReportBlock>& report_blocks,
+    std::map<uint32_t, RTCPReportBlock>* prev_report_blocks) {
+  int fraction_lost_sum = 0;
+  int fl_seq_num_sum = 0;
+  int jitter_sum = 0;
+  int number_of_report_blocks = 0;
+  RTCPReportBlock aggregate;
+  std::vector<RTCPReportBlock>::const_iterator report_block =
+      report_blocks.begin();
+  for (; report_block != report_blocks.end(); ++report_block) {
+    aggregate.cumulativeLost += report_block->cumulativeLost;
+    std::map<uint32_t, RTCPReportBlock>::iterator prev_report_block =
+        prev_report_blocks->find(report_block->sourceSSRC);
+    if (prev_report_block != prev_report_blocks->end()) {
+      // Skip the first report block since we won't be able to get a correct
+      // weight for it.
+      int seq_num_diff = report_block->extendedHighSeqNum -
+                         prev_report_block->second.extendedHighSeqNum;
+      if (seq_num_diff > 0) {
+        fraction_lost_sum += report_block->fractionLost * seq_num_diff;
+        fl_seq_num_sum += seq_num_diff;
+      }
+    }
+    jitter_sum += report_block->jitter;
+    ++number_of_report_blocks;
+    (*prev_report_blocks)[report_block->sourceSSRC] = *report_block;
+  }
+  if (fl_seq_num_sum > 0) {
+    aggregate.fractionLost =
+        (fraction_lost_sum + fl_seq_num_sum / 2) / fl_seq_num_sum;
+  }
+  if (number_of_report_blocks > 0) {
+    aggregate.jitter =
+        (jitter_sum + number_of_report_blocks / 2) / number_of_report_blocks;
+  }
+  // Not well defined for aggregated report blocks.
+  aggregate.extendedHighSeqNum = 0;
+  return aggregate;
+}
+}  // namespace
+
 // Helper class receiving statistics callbacks.
 class ChannelStatsObserver : public CallStatsObserver {
  public:
@@ -76,10 +120,10 @@ ViEChannel::ViEChannel(int32_t channel_id,
       callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
       rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()),
       default_rtp_rtcp_(default_rtp_rtcp),
-      vcm_(*VideoCodingModule::Create()),
-      vie_receiver_(channel_id, &vcm_, remote_bitrate_estimator, this),
+      vcm_(VideoCodingModule::Create()),
+      vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this),
       vie_sender_(channel_id),
-      vie_sync_(&vcm_, this),
+      vie_sync_(vcm_, this),
       stats_observer_(new ChannelStatsObserver(this)),
       module_process_thread_(module_process_thread),
       codec_observer_(NULL),
@@ -89,6 +133,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
       intra_frame_observer_(intra_frame_observer),
       rtt_stats_(rtt_stats),
       paced_sender_(paced_sender),
+      pad_with_redundant_payloads_(false),
       bandwidth_observer_(bandwidth_observer),
       send_timestamp_extension_id_(kInvalidRtpExtensionId),
       absolute_send_time_extension_id_(kInvalidRtpExtensionId),
@@ -102,8 +147,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
       sender_(sender),
       nack_history_size_sender_(kSendSidePacketHistorySize),
       max_nack_reordering_threshold_(kMaxPacketAgeToNack),
-      pre_render_callback_(NULL),
-      config_(config) {
+      pre_render_callback_(NULL) {
   RtpRtcp::Configuration configuration;
   configuration.id = ViEModuleId(engine_id, channel_id);
   configuration.audio = false;
@@ -116,10 +160,13 @@ ViEChannel::ViEChannel(int32_t channel_id,
   configuration.remote_bitrate_estimator = remote_bitrate_estimator;
   configuration.paced_sender = paced_sender;
   configuration.receive_statistics = vie_receiver_.GetReceiveStatistics();
+  configuration.send_bitrate_observer = &send_bitrate_observer_;
+  configuration.send_frame_count_observer = &send_frame_count_observer_;
+  configuration.send_side_delay_observer = &send_side_delay_observer_;
 
   rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
   vie_receiver_.SetRtpRtcpModule(rtp_rtcp_.get());
-  vcm_.SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
+  vcm_->SetNackSettings(kMaxNackListSize, max_nack_reordering_threshold_, 0);
 }
 
 int32_t ViEChannel::Init() {
@@ -139,32 +186,32 @@ int32_t ViEChannel::Init() {
   if (paced_sender_) {
     rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
   }
-  if (vcm_.InitializeReceiver() != 0) {
+  if (vcm_->InitializeReceiver() != 0) {
     return -1;
   }
-  if (vcm_.SetVideoProtection(kProtectionKeyOnLoss, true)) {
+  if (vcm_->SetVideoProtection(kProtectionKeyOnLoss, true)) {
     return -1;
   }
-  if (vcm_.RegisterReceiveCallback(this) != 0) {
+  if (vcm_->RegisterReceiveCallback(this) != 0) {
     return -1;
   }
-  vcm_.RegisterFrameTypeCallback(this);
-  vcm_.RegisterReceiveStatisticsCallback(this);
-  vcm_.RegisterDecoderTimingCallback(this);
-  vcm_.SetRenderDelay(kViEDefaultRenderDelayMs);
-  if (module_process_thread_.RegisterModule(&vcm_) != 0) {
+  vcm_->RegisterFrameTypeCallback(this);
+  vcm_->RegisterReceiveStatisticsCallback(this);
+  vcm_->RegisterDecoderTimingCallback(this);
+  vcm_->SetRenderDelay(kViEDefaultRenderDelayMs);
+  if (module_process_thread_.RegisterModule(vcm_) != 0) {
     return -1;
   }
 #ifdef VIDEOCODEC_VP8
   VideoCodec video_codec;
-  if (vcm_.Codec(kVideoCodecVP8, &video_codec) == VCM_OK) {
+  if (vcm_->Codec(kVideoCodecVP8, &video_codec) == VCM_OK) {
     rtp_rtcp_->RegisterSendPayload(video_codec);
     // TODO(holmer): Can we call SetReceiveCodec() here instead?
     if (!vie_receiver_.RegisterPayload(video_codec)) {
       return -1;
     }
-    vcm_.RegisterReceiveCodec(&video_codec, number_of_cores_);
-    vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
+    vcm_->RegisterReceiveCodec(&video_codec, number_of_cores_);
+    vcm_->RegisterSendCodec(&video_codec, number_of_cores_,
                            rtp_rtcp_->MaxDataPayloadLength());
   } else {
     assert(false);
@@ -178,7 +225,7 @@ ViEChannel::~ViEChannel() {
   // Make sure we don't get more callbacks from the RTP module.
   module_process_thread_.DeRegisterModule(vie_receiver_.GetReceiveStatistics());
   module_process_thread_.DeRegisterModule(rtp_rtcp_.get());
-  module_process_thread_.DeRegisterModule(&vcm_);
+  module_process_thread_.DeRegisterModule(vcm_);
   module_process_thread_.DeRegisterModule(&vie_sync_);
   while (simulcast_rtp_rtcp_.size() > 0) {
     std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
@@ -196,7 +243,7 @@ ViEChannel::~ViEChannel() {
     StopDecodeThread();
   }
   // Release modules.
-  VideoCodingModule::Destroy(&vcm_);
+  VideoCodingModule::Destroy(vcm_);
 }
 
 int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
@@ -244,31 +291,25 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
       num_modules_to_add = 0;
     }
 
-    while (removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0) {
-      RtpRtcp* rtp_rtcp = removed_rtp_rtcp_.front();
+    // Add back removed rtp modules. Order is important (allocate from front of
+    // removed modules) to preserve RTP settings such as SSRCs for simulcast
+    // streams.
+    std::list<RtpRtcp*> new_rtp_modules;
+    for (; removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0;
+         --num_modules_to_add) {
+      new_rtp_modules.push_back(removed_rtp_rtcp_.front());
       removed_rtp_rtcp_.pop_front();
-      simulcast_rtp_rtcp_.push_back(rtp_rtcp);
-      rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
-      rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
-      module_process_thread_.RegisterModule(rtp_rtcp);
-      --num_modules_to_add;
     }
 
-    for (int i = 0; i < num_modules_to_add; ++i) {
-      RtpRtcp::Configuration configuration;
-      configuration.id = ViEModuleId(engine_id_, channel_id_);
-      configuration.audio = false;  // Video.
-      configuration.default_module = default_rtp_rtcp_;
-      configuration.outgoing_transport = &vie_sender_;
-      configuration.intra_frame_callback = intra_frame_observer_;
-      configuration.bandwidth_callback = bandwidth_observer_.get();
-      configuration.rtt_stats = rtt_stats_;
-      configuration.paced_sender = paced_sender_;
+    for (int i = 0; i < num_modules_to_add; ++i)
+      new_rtp_modules.push_back(CreateRtpRtcpModule());
 
-      RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
+    // Initialize newly added modules.
+    for (std::list<RtpRtcp*>::iterator it = new_rtp_modules.begin();
+         it != new_rtp_modules.end();
+         ++it) {
+      RtpRtcp* rtp_rtcp = *it;
 
-      // Silently ignore error.
-      module_process_thread_.RegisterModule(rtp_rtcp);
       rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP());
 
       if (rtp_rtcp_->StorePackets()) {
@@ -278,13 +319,23 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
       }
 
       if (fec_enabled) {
-        rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red,
-            payload_type_fec);
+        rtp_rtcp->SetGenericFECStatus(
+            fec_enabled, payload_type_red, payload_type_fec);
       }
       rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
       rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
+
+      int mode;
+      uint32_t ssrc;
+      int payload_type;
+      rtp_rtcp_->RTXSendStatus(&mode, &ssrc, &payload_type);
+      rtp_rtcp->SetRTXSendStatus(mode);
       simulcast_rtp_rtcp_.push_back(rtp_rtcp);
+
+      // Silently ignore error.
+      module_process_thread_.RegisterModule(rtp_rtcp);
     }
+
     // Remove last in list if we have too many.
     for (int j = simulcast_rtp_rtcp_.size();
          j > (video_codec.numberOfSimulcastStreams - 1);
@@ -293,10 +344,8 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
       module_process_thread_.DeRegisterModule(rtp_rtcp);
       rtp_rtcp->SetSendingStatus(false);
       rtp_rtcp->SetSendingMediaStatus(false);
-      rtp_rtcp->RegisterSendFrameCountObserver(NULL);
       rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
       rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
-      rtp_rtcp->RegisterVideoBitrateObserver(NULL);
       simulcast_rtp_rtcp_.pop_back();
       removed_rtp_rtcp_.push_front(rtp_rtcp);
     }
@@ -342,14 +391,10 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
         rtp_rtcp->DeregisterSendRtpHeaderExtension(
             kRtpExtensionAbsoluteSendTime);
       }
-      rtp_rtcp->RegisterSendFrameCountObserver(
-          rtp_rtcp_->GetSendFrameCountObserver());
       rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(
           rtp_rtcp_->GetSendChannelRtcpStatisticsCallback());
       rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
           rtp_rtcp_->GetSendChannelRtpStatisticsCallback());
-      rtp_rtcp->RegisterVideoBitrateObserver(
-          rtp_rtcp_->GetVideoBitrateObserver());
     }
     // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
     // modules can be deleted after this step.
@@ -360,28 +405,14 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
       module_process_thread_.DeRegisterModule(rtp_rtcp);
       rtp_rtcp->SetSendingStatus(false);
       rtp_rtcp->SetSendingMediaStatus(false);
-      rtp_rtcp->RegisterSendFrameCountObserver(NULL);
       rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
       rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
-      rtp_rtcp->RegisterVideoBitrateObserver(NULL);
       simulcast_rtp_rtcp_.pop_back();
       removed_rtp_rtcp_.push_front(rtp_rtcp);
     }
     // Clear any previous modules.
     vie_receiver_.RegisterSimulcastRtpRtcpModules(simulcast_rtp_rtcp_);
   }
-  // Enable this if H264 is available.
-  // This sets the wanted packetization mode.
-  // if (video_codec.plType == kVideoCodecH264) {
-  //   if (video_codec.codecSpecific.H264.packetization ==  kH264SingleMode) {
-  //     rtp_rtcp_->SetH264PacketizationMode(H264_SINGLE_NAL_MODE);
-  //   } else {
-  //     rtp_rtcp_->SetH264PacketizationMode(H264_NON_INTERLEAVED_MODE);
-  //   }
-  //   if (video_codec.codecSpecific.H264.configParametersSize > 0) {
-  //     rtp_rtcp_->SetH264SendModeNALU_PPS_SPS(true);
-  //   }
-  // }
 
   // Don't log this error, no way to check in advance if this pl_type is
   // registered or not...
@@ -408,7 +439,7 @@ int32_t ViEChannel::SetReceiveCodec(const VideoCodec& video_codec) {
   if (video_codec.codecType != kVideoCodecRED &&
       video_codec.codecType != kVideoCodecULPFEC) {
     // Register codec type with VCM, but do not register RED or ULPFEC.
-    if (vcm_.RegisterReceiveCodec(&video_codec, number_of_cores_,
+    if (vcm_->RegisterReceiveCodec(&video_codec, number_of_cores_,
                                   wait_for_key_frame_) != VCM_OK) {
       return -1;
     }
@@ -417,7 +448,7 @@ int32_t ViEChannel::SetReceiveCodec(const VideoCodec& video_codec) {
 }
 
 int32_t ViEChannel::GetReceiveCodec(VideoCodec* video_codec) {
-  if (vcm_.ReceiveCodec(video_codec) != 0) {
+  if (vcm_->ReceiveCodec(video_codec) != 0) {
     return -1;
   }
   return 0;
@@ -442,24 +473,24 @@ int32_t ViEChannel::RegisterExternalDecoder(const uint8_t pl_type,
                                             bool buffered_rendering,
                                             int32_t render_delay) {
   int32_t result;
-  result = vcm_.RegisterExternalDecoder(decoder, pl_type, buffered_rendering);
+  result = vcm_->RegisterExternalDecoder(decoder, pl_type, buffered_rendering);
   if (result != VCM_OK) {
     return result;
   }
-  return vcm_.SetRenderDelay(render_delay);
+  return vcm_->SetRenderDelay(render_delay);
 }
 
 int32_t ViEChannel::DeRegisterExternalDecoder(const uint8_t pl_type) {
   VideoCodec current_receive_codec;
   int32_t result = 0;
-  result = vcm_.ReceiveCodec(&current_receive_codec);
-  if (vcm_.RegisterExternalDecoder(NULL, pl_type, false) != VCM_OK) {
+  result = vcm_->ReceiveCodec(&current_receive_codec);
+  if (vcm_->RegisterExternalDecoder(NULL, pl_type, false) != VCM_OK) {
     return -1;
   }
 
   if (result == 0 && current_receive_codec.plType == pl_type) {
-    result = vcm_.RegisterReceiveCodec(&current_receive_codec, number_of_cores_,
-                                       wait_for_key_frame_);
+    result = vcm_->RegisterReceiveCodec(
+        &current_receive_codec, number_of_cores_, wait_for_key_frame_);
   }
   return result;
 }
@@ -467,7 +498,7 @@ int32_t ViEChannel::DeRegisterExternalDecoder(const uint8_t pl_type) {
 int32_t ViEChannel::ReceiveCodecStatistics(uint32_t* num_key_frames,
                                            uint32_t* num_delta_frames) {
   VCMFrameCount received_frames;
-  if (vcm_.ReceivedFrameCount(received_frames) != VCM_OK) {
+  if (vcm_->ReceivedFrameCount(received_frames) != VCM_OK) {
     return -1;
   }
   *num_key_frames = received_frames.numKeyFrames;
@@ -476,11 +507,11 @@ int32_t ViEChannel::ReceiveCodecStatistics(uint32_t* num_key_frames,
 }
 
 uint32_t ViEChannel::DiscardedPackets() const {
-  return vcm_.DiscardedPackets();
+  return vcm_->DiscardedPackets();
 }
 
 int ViEChannel::ReceiveDelay() const {
-  return vcm_.Delay();
+  return vcm_->Delay();
 }
 
 int32_t ViEChannel::WaitForKeyFrame(bool wait) {
@@ -492,19 +523,19 @@ int32_t ViEChannel::SetSignalPacketLossStatus(bool enable,
                                               bool only_key_frames) {
   if (enable) {
     if (only_key_frames) {
-      vcm_.SetVideoProtection(kProtectionKeyOnLoss, false);
-      if (vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, true) != VCM_OK) {
+      vcm_->SetVideoProtection(kProtectionKeyOnLoss, false);
+      if (vcm_->SetVideoProtection(kProtectionKeyOnKeyLoss, true) != VCM_OK) {
         return -1;
       }
     } else {
-      vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, false);
-      if (vcm_.SetVideoProtection(kProtectionKeyOnLoss, true) != VCM_OK) {
+      vcm_->SetVideoProtection(kProtectionKeyOnKeyLoss, false);
+      if (vcm_->SetVideoProtection(kProtectionKeyOnLoss, true) != VCM_OK) {
         return -1;
       }
     }
   } else {
-    vcm_.SetVideoProtection(kProtectionKeyOnLoss, false);
-    vcm_.SetVideoProtection(kProtectionKeyOnKeyLoss, false);
+    vcm_->SetVideoProtection(kProtectionKeyOnLoss, false);
+    vcm_->SetVideoProtection(kProtectionKeyOnKeyLoss, false);
   }
   return 0;
 }
@@ -527,7 +558,7 @@ int32_t ViEChannel::GetRTCPMode(RTCPMethod* rtcp_mode) {
 
 int32_t ViEChannel::SetNACKStatus(const bool enable) {
   // Update the decoding VCM.
-  if (vcm_.SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
+  if (vcm_->SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
     return -1;
   }
   if (enable) {
@@ -535,7 +566,7 @@ int32_t ViEChannel::SetNACKStatus(const bool enable) {
     SetFECStatus(false, 0, 0);
   }
   // Update the decoding VCM.
-  if (vcm_.SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
+  if (vcm_->SetVideoProtection(kProtectionNack, enable) != VCM_OK) {
     return -1;
   }
   return ProcessNACKRequest(enable);
@@ -549,7 +580,7 @@ int32_t ViEChannel::ProcessNACKRequest(const bool enable) {
     }
     vie_receiver_.SetNackStatus(true, max_nack_reordering_threshold_);
     rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
-    vcm_.RegisterPacketRequestCallback(this);
+    vcm_->RegisterPacketRequestCallback(this);
 
     CriticalSectionScoped cs(rtp_rtcp_cs_.get());
 
@@ -560,7 +591,7 @@ int32_t ViEChannel::ProcessNACKRequest(const bool enable) {
       rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
     }
     // Don't introduce errors when NACK is enabled.
-    vcm_.SetDecodeErrorMode(kNoErrors);
+    vcm_->SetDecodeErrorMode(kNoErrors);
   } else {
     CriticalSectionScoped cs(rtp_rtcp_cs_.get());
     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
@@ -571,14 +602,14 @@ int32_t ViEChannel::ProcessNACKRequest(const bool enable) {
         rtp_rtcp->SetStorePacketsStatus(false, 0);
       }
     }
-    vcm_.RegisterPacketRequestCallback(NULL);
+    vcm_->RegisterPacketRequestCallback(NULL);
     if (paced_sender_ == NULL) {
       rtp_rtcp_->SetStorePacketsStatus(false, 0);
     }
     vie_receiver_.SetNackStatus(false, max_nack_reordering_threshold_);
     // When NACK is off, allow decoding with errors. Otherwise, the video
     // will freeze, and will only recover with a complete key frame.
-    vcm_.SetDecodeErrorMode(kWithErrors);
+    vcm_->SetDecodeErrorMode(kWithErrors);
   }
   return 0;
 }
@@ -616,7 +647,7 @@ int32_t ViEChannel::SetHybridNACKFECStatus(
     const bool enable,
     const unsigned char payload_typeRED,
     const unsigned char payload_typeFEC) {
-  if (vcm_.SetVideoProtection(kProtectionNackFEC, enable) != VCM_OK) {
+  if (vcm_->SetVideoProtection(kProtectionNackFEC, enable) != VCM_OK) {
     return -1;
   }
 
@@ -668,9 +699,9 @@ int ViEChannel::SetReceiverBufferingMode(int target_delay_ms) {
     max_incomplete_time_ms = static_cast<int>(kMaxIncompleteTimeMultiplier *
         target_delay_ms + 0.5f);
   }
-  vcm_.SetNackSettings(max_nack_list_size, max_nack_reordering_threshold_,
+  vcm_->SetNackSettings(max_nack_list_size, max_nack_reordering_threshold_,
                        max_incomplete_time_ms);
-  vcm_.SetMinReceiverDelay(target_delay_ms);
+  vcm_->SetMinReceiverDelay(target_delay_ms);
   if (vie_sync_.SetTargetBufferingDelay(target_delay_ms) < 0)
     return -1;
   return 0;
@@ -792,54 +823,31 @@ int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) {
 int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
                             const StreamType usage,
                             const uint8_t simulcast_idx) {
-  int rtx_settings = kRtxRetransmitted;
-  if (config_.Get<PaddingStrategy>().redundant_payloads)
-    rtx_settings |= kRtxRedundantPayloads;
-  if (simulcast_idx == 0) {
-    if (usage == kViEStreamTypeRtx) {
-      return rtp_rtcp_->SetRTXSendStatus(rtx_settings, true, SSRC);
-    }
-    return rtp_rtcp_->SetSSRC(SSRC);
-  }
   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-  if (simulcast_idx > simulcast_rtp_rtcp_.size()) {
-      return -1;
-  }
-  std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
-  for (int i = 1; i < simulcast_idx; ++i, ++it) {
-    if (it ==  simulcast_rtp_rtcp_.end()) {
-      return -1;
-    }
-  }
-  RtpRtcp* rtp_rtcp_module = *it;
+  ReserveRtpRtcpModules(simulcast_idx + 1);
+  RtpRtcp* rtp_rtcp = GetRtpRtcpModule(simulcast_idx);
+  if (rtp_rtcp == NULL)
+    return -1;
   if (usage == kViEStreamTypeRtx) {
-    return rtp_rtcp_module->SetRTXSendStatus(rtx_settings, true, SSRC);
+    rtp_rtcp->SetRtxSsrc(SSRC);
+  } else {
+    rtp_rtcp->SetSSRC(SSRC);
   }
-  return rtp_rtcp_module->SetSSRC(SSRC);
+  return 0;
 }
 
 int32_t ViEChannel::SetRemoteSSRCType(const StreamType usage,
                                       const uint32_t SSRC) {
-  vie_receiver_.SetRtxStatus(true, SSRC);
+  vie_receiver_.SetRtxSsrc(SSRC);
   return 0;
 }
 
 int32_t ViEChannel::GetLocalSSRC(uint8_t idx, unsigned int* ssrc) {
-  if (idx == 0) {
-    *ssrc = rtp_rtcp_->SSRC();
-    return 0;
-  }
   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-  if (idx > simulcast_rtp_rtcp_.size()) {
+  RtpRtcp* rtp_rtcp = GetRtpRtcpModule(idx);
+  if (rtp_rtcp == NULL)
     return -1;
-  }
-  std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
-  for (int i = 1; i < idx; ++i, ++it) {
-    if (it ==  simulcast_rtp_rtcp_.end()) {
-      return -1;
-    }
-  }
-  *ssrc = (*it)->SSRC();
+  *ssrc = rtp_rtcp->SSRC();
   return 0;
 }
 
@@ -859,19 +867,48 @@ int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) {
   return 0;
 }
 
-int ViEChannel::SetRtxSendPayloadType(int payload_type) {
-  if (rtp_rtcp_->Sending()) {
-    return -1;
+void ViEChannel::SetPadWithRedundantPayloads(bool enable) {
+  {
+    CriticalSectionScoped cs(callback_cs_.get());
+    pad_with_redundant_payloads_ = enable;
+  }
+  int mode;
+  uint32_t ssrc;
+  int payload_type;
+  rtp_rtcp_->RTXSendStatus(&mode, &ssrc, &payload_type);
+  if (mode != kRtxOff) {
+    // Since RTX was already enabled we have to reset it with payload-based
+    // padding on.
+    SetRtxSendStatus(true);
   }
+}
+
+int ViEChannel::SetRtxSendPayloadType(int payload_type) {
   rtp_rtcp_->SetRtxSendPayloadType(payload_type);
-  CriticalSectionScoped cs(rtp_rtcp_cs_.get());
   for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
        it != simulcast_rtp_rtcp_.end(); it++) {
     (*it)->SetRtxSendPayloadType(payload_type);
   }
+  SetRtxSendStatus(true);
   return 0;
 }
 
+void ViEChannel::SetRtxSendStatus(bool enable) {
+  int rtx_settings = kRtxOff;
+  if (enable) {
+    CriticalSectionScoped cs(callback_cs_.get());
+    rtx_settings = kRtxRetransmitted;
+    if (pad_with_redundant_payloads_)
+      rtx_settings |= kRtxRedundantPayloads;
+  }
+  rtp_rtcp_->SetRTXSendStatus(rtx_settings);
+  CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+  for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
+       it != simulcast_rtp_rtcp_.end(); it++) {
+    (*it)->SetRTXSendStatus(rtx_settings);
+  }
+}
+
 void ViEChannel::SetRtxReceivePayloadType(int payload_type) {
   vie_receiver_.SetRtxPayloadType(payload_type);
 }
@@ -883,6 +920,21 @@ int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) {
   return rtp_rtcp_->SetSequenceNumber(sequence_number);
 }
 
+void ViEChannel::SetRtpStateForSsrc(uint32_t ssrc, const RtpState& rtp_state) {
+  assert(!rtp_rtcp_->Sending());
+  default_rtp_rtcp_->SetRtpStateForSsrc(ssrc, rtp_state);
+}
+
+RtpState ViEChannel::GetRtpStateForSsrc(uint32_t ssrc) {
+  assert(!rtp_rtcp_->Sending());
+
+  RtpState rtp_state;
+  if (!default_rtp_rtcp_->GetRtpStateForSsrc(ssrc, &rtp_state)) {
+    LOG(LS_ERROR) << "Couldn't get RTP state for ssrc: " << ssrc;
+  }
+  return rtp_state;
+}
+
 int32_t ViEChannel::SetRTCPCName(const char rtcp_cname[]) {
   if (rtp_rtcp_->Sending()) {
     return -1;
@@ -890,10 +942,6 @@ int32_t ViEChannel::SetRTCPCName(const char rtcp_cname[]) {
   return rtp_rtcp_->SetCNAME(rtcp_cname);
 }
 
-int32_t ViEChannel::GetRTCPCName(char rtcp_cname[]) {
-  return rtp_rtcp_->CNAME(rtcp_cname);
-}
-
 int32_t ViEChannel::GetRemoteRTCPCName(char rtcp_cname[]) {
   uint32_t remoteSSRC = vie_receiver_.GetRemoteSsrc();
   return rtp_rtcp_->RemoteCNAME(remoteSSRC, rtcp_cname);
@@ -961,44 +1009,46 @@ int32_t ViEChannel::GetSendRtcpStatistics(uint16_t* fraction_lost,
                                           uint32_t* extended_max,
                                           uint32_t* jitter_samples,
                                           int32_t* rtt_ms) {
-  // TODO(pwestin) how do we do this for simulcast ? average for all
-  // except cumulative_lost that is the sum ?
-  // CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-
-  // for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
-  //      it != simulcast_rtp_rtcp_.end();
-  //      it++) {
-  //   RtpRtcp* rtp_rtcp = *it;
-  // }
-  uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
+  // Aggregate the report blocks associated with streams sent on this channel.
+  std::vector<RTCPReportBlock> report_blocks;
+  rtp_rtcp_->RemoteRTCPStat(&report_blocks);
+  {
+    CriticalSectionScoped lock(rtp_rtcp_cs_.get());
+    for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
+        it != simulcast_rtp_rtcp_.end();
+        ++it) {
+      (*it)->RemoteRTCPStat(&report_blocks);
+    }
+  }
 
-  // Get all RTCP receiver report blocks that have been received on this
-  // channel. If we receive RTP packets from a remote source we know the
-  // remote SSRC and use the report block from him.
-  // Otherwise use the first report block.
-  std::vector<RTCPReportBlock> remote_stats;
-  if (rtp_rtcp_->RemoteRTCPStat(&remote_stats) != 0 || remote_stats.empty()) {
+  if (report_blocks.empty())
     return -1;
-  }
-  std::vector<RTCPReportBlock>::const_iterator statistics =
-      remote_stats.begin();
-  for (; statistics != remote_stats.end(); ++statistics) {
-    if (statistics->remoteSSRC == remote_ssrc)
+
+  uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
+  std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
+  for (; it != report_blocks.end(); ++it) {
+    if (it->remoteSSRC == remote_ssrc)
       break;
   }
-
-  if (statistics == remote_stats.end()) {
-    // If we have not received any RTCP packets from this SSRC it probably means
-    // we have not received any RTP packets.
-    // Use the first received report block instead.
-    statistics = remote_stats.begin();
-    remote_ssrc = statistics->remoteSSRC;
+  if (it == report_blocks.end()) {
+    // We have not received packets with an SSRC matching the report blocks. To
+    // have a chance of calculating an RTT we will try with the SSRC of the
+    // first report block received.
+    // This is very important for send-only channels where we don't know the
+    // SSRC of the other end.
+    remote_ssrc = report_blocks[0].remoteSSRC;
   }
 
-  *fraction_lost = statistics->fractionLost;
-  *cumulative_lost = statistics->cumulativeLost;
-  *extended_max = statistics->extendedHighSeqNum;
-  *jitter_samples = statistics->jitter;
+  RTCPReportBlock report;
+  if (report_blocks.size() > 1)
+    report = AggregateReportBlocks(report_blocks, &prev_report_blocks_);
+  else
+    report = report_blocks[0];
+
+  *fraction_lost = report.fractionLost;
+  *cumulative_lost = report.cumulativeLost;
+  *extended_max = report.extendedHighSeqNum;
+  *jitter_samples = report.jitter;
 
   uint16_t dummy;
   uint16_t rtt = 0;
@@ -1185,15 +1235,14 @@ bool ViEChannel::GetSendSideDelay(int* avg_send_delay,
   return valid_estimate;
 }
 
+void ViEChannel::RegisterSendSideDelayObserver(
+    SendSideDelayObserver* observer) {
+  send_side_delay_observer_.Set(observer);
+}
+
 void ViEChannel::RegisterSendBitrateObserver(
     BitrateStatisticsObserver* observer) {
-  rtp_rtcp_->RegisterVideoBitrateObserver(observer);
-  CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-  for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
-       it != simulcast_rtp_rtcp_.end();
-       it++) {
-    (*it)->RegisterVideoBitrateObserver(observer);
-  }
+  send_bitrate_observer_.Set(observer);
 }
 
 void ViEChannel::GetReceiveBandwidthEstimatorStats(
@@ -1288,7 +1337,7 @@ int32_t ViEChannel::StartReceive() {
 int32_t ViEChannel::StopReceive() {
   vie_receiver_.StopReceive();
   StopDecodeThread();
-  vcm_.ResetDecoder();
+  vcm_->ResetDecoder();
   return 0;
 }
 
@@ -1492,12 +1541,66 @@ bool ViEChannel::ChannelDecodeThreadFunction(void* obj) {
 }
 
 bool ViEChannel::ChannelDecodeProcess() {
-  vcm_.Decode(kMaxDecodeWaitTimeMs);
+  vcm_->Decode(kMaxDecodeWaitTimeMs);
   return true;
 }
 
 void ViEChannel::OnRttUpdate(uint32_t rtt) {
-  vcm_.SetReceiveChannelParameters(rtt);
+  vcm_->SetReceiveChannelParameters(rtt);
+}
+
+void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) {
+  for (size_t total_modules =
+           1 + simulcast_rtp_rtcp_.size() + removed_rtp_rtcp_.size();
+       total_modules < num_modules;
+       ++total_modules) {
+    RtpRtcp* rtp_rtcp = CreateRtpRtcpModule();
+    rtp_rtcp->SetSendingStatus(false);
+    rtp_rtcp->SetSendingMediaStatus(false);
+    rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
+    rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
+    removed_rtp_rtcp_.push_back(rtp_rtcp);
+  }
+}
+
+RtpRtcp* ViEChannel::GetRtpRtcpModule(size_t index) const {
+  if (index == 0)
+    return rtp_rtcp_.get();
+  if (index <= simulcast_rtp_rtcp_.size()) {
+    std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
+    for (size_t i = 1; i < index; ++i) {
+      ++it;
+    }
+    return *it;
+  }
+
+  // If the requested module exists it must be in the removed list. Index
+  // translation to this list must remove the default module as well as all
+  // active simulcast modules.
+  size_t removed_idx = index - simulcast_rtp_rtcp_.size() - 1;
+  if (removed_idx >= removed_rtp_rtcp_.size())
+    return NULL;
+
+  std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
+  while (removed_idx-- > 0)
+    ++it;
+
+  return *it;
+}
+
+RtpRtcp* ViEChannel::CreateRtpRtcpModule() {
+  RtpRtcp::Configuration configuration;
+  configuration.id = ViEModuleId(engine_id_, channel_id_);
+  configuration.audio = false;  // Video.
+  configuration.default_module = default_rtp_rtcp_;
+  configuration.outgoing_transport = &vie_sender_;
+  configuration.intra_frame_callback = intra_frame_observer_;
+  configuration.bandwidth_callback = bandwidth_observer_.get();
+  configuration.rtt_stats = rtt_stats_;
+  configuration.paced_sender = paced_sender_;
+  configuration.send_side_delay_observer = &send_side_delay_observer_;
+
+  return RtpRtcp::CreateRtpRtcp(configuration);
 }
 
 int32_t ViEChannel::StartDecodeThread() {
@@ -1574,8 +1677,7 @@ void ViEChannel::RegisterPreRenderCallback(
 
 void ViEChannel::RegisterPreDecodeImageCallback(
     EncodedImageCallback* pre_decode_callback) {
-  CriticalSectionScoped cs(callback_cs_.get());
-  vcm_.RegisterPreDecodeImageCallback(pre_decode_callback);
+  vcm_->RegisterPreDecodeImageCallback(pre_decode_callback);
 }
 
 void ViEChannel::OnApplicationDataReceived(const int32_t id,
@@ -1605,7 +1707,7 @@ int32_t ViEChannel::OnInitializeDecoder(
     const uint32_t rate) {
   LOG(LS_INFO) << "OnInitializeDecoder " << payload_type << " "
                << payload_name;
-  vcm_.ResetDecoder();
+  vcm_->ResetDecoder();
 
   CriticalSectionScoped cs(callback_cs_.get());
   decoder_reset_ = true;
@@ -1645,13 +1747,7 @@ void ViEChannel::ResetStatistics(uint32_t ssrc) {
 
 void ViEChannel::RegisterSendFrameCountObserver(
     FrameCountObserver* observer) {
-  rtp_rtcp_->RegisterSendFrameCountObserver(observer);
-  CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-  for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
-       it != simulcast_rtp_rtcp_.end();
-       it++) {
-    (*it)->RegisterSendFrameCountObserver(observer);
-  }
+  send_frame_count_observer_.Set(observer);
 }
 
 void ViEChannel::ReceivedBWEPacket(int64_t arrival_time_ms,