/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "common_types.h"
#include "rtp_rtcp_impl.h"
#include "trace.h"

#ifdef MATLAB
#include "../test/BWEStandAlone/MatlabPlot.h"
extern MatlabEngine eng; // global variable defined elsewhere
#endif

#include <string.h> //memcpy
#include <cassert> //assert

// local for this file
namespace {

const float FracMS = 4.294967296E6f;

}  // namepace

#ifdef _WIN32
// disable warning C4355: 'this' : used in base member initializer list
#pragma warning(disable : 4355)
#endif

namespace webrtc {

const WebRtc_UWord16 kDefaultRtt = 200;

RtpRtcp* RtpRtcp::CreateRtpRtcp(const WebRtc_Word32 id,
                                bool audio) {
  if(audio) {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id, "CreateRtpRtcp(audio)");
  } else {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id, "CreateRtpRtcp(video)");
  }
  // ModuleRTPUtility::GetSystemClock() creates a new instance of a system
  // clock implementation. The OwnsClock() function informs the module that
  // it is responsible for deleting the instance.
  ModuleRtpRtcpImpl* rtp_rtcp_instance = new ModuleRtpRtcpImpl(id,
      audio, ModuleRTPUtility::GetSystemClock());
  rtp_rtcp_instance->OwnsClock();
  return rtp_rtcp_instance;
}

RtpRtcp* RtpRtcp::CreateRtpRtcp(const WebRtc_Word32 id,
                                const bool audio,
                                RtpRtcpClock* clock) {
  if (audio) {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 id,
                 "CreateRtpRtcp(audio)");
  } else {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 id,
                 "CreateRtpRtcp(video)");
  }
  return new ModuleRtpRtcpImpl(id, audio, clock);
}

void RtpRtcp::DestroyRtpRtcp(RtpRtcp* module) {
  if (module) {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 static_cast<ModuleRtpRtcpImpl*>(module)->Id(),
                 "DestroyRtpRtcp()");
    delete static_cast<ModuleRtpRtcpImpl*>(module);
  }
}

ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id,
                                     const bool audio,
                                     RtpRtcpClock* clock):
  TMMBRHelp(audio),
  _rtpSender(id, audio, clock),
  _rtpReceiver(id, audio, clock, this),
  _rtcpSender(id, audio, clock, this),
  _rtcpReceiver(id, clock, this),
  _owns_clock(false),
  _clock(*clock),
  _id(id),
  _audio(audio),
  _collisionDetected(false),
  _lastProcessTime(clock->GetTimeInMS()),
  _lastBitrateProcessTime(clock->GetTimeInMS()),
  _lastPacketTimeoutProcessTime(clock->GetTimeInMS()),
  _packetOverHead(28), // IPV4 UDP
  _criticalSectionModulePtrs(CriticalSectionWrapper::CreateCriticalSection()),
  _criticalSectionModulePtrsFeedback(
    CriticalSectionWrapper::CreateCriticalSection()),
  _defaultModule(NULL),
  _audioModule(NULL),
  _videoModule(NULL),
  _deadOrAliveActive(false),
  _deadOrAliveTimeoutMS(0),
  _deadOrAliveLastTimer(0),
  _bandwidthManagement(id),
  _receivedNTPsecsAudio(0),
  _receivedNTPfracAudio(0),
  _RTCPArrivalTimeSecsAudio(0),
  _RTCPArrivalTimeFracAudio(0),
  _nackMethod(kNackOff),
  _nackLastTimeSent(0),
  _nackLastSeqNumberSent(0),
  _simulcast(false),
  _keyFrameReqMethod(kKeyFrameReqFirRtp)
#ifdef MATLAB
  , _plot1(NULL)
#endif
{
  _sendVideoCodec.codecType = kVideoCodecUnknown;
  // make sure that RTCP objects are aware of our SSRC
  WebRtc_UWord32 SSRC = _rtpSender.SSRC();
  _rtcpSender.SetSSRC(SSRC);

  WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
}

ModuleRtpRtcpImpl::~ModuleRtpRtcpImpl() {
  WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);

  // make sure to unregister this module from other modules

  const bool defaultInstance(_childModules.empty() ? false : true);

  if (defaultInstance) {
    // deregister for the default module
    // will go in to the child modules and remove it self
    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      _childModules.erase(it);
      if (module) {
        module->DeRegisterDefaultModule();
      }
      it = _childModules.begin();
    }
  } else {
    // deregister for the child modules
    // will go in to the default and remove it self
    DeRegisterDefaultModule();
  }

  if (_audio) {
    DeRegisterVideoModule();
  } else {
    DeRegisterSyncModule();
  }

#ifdef MATLAB
  if (_plot1) {
    eng.DeletePlot(_plot1);
    _plot1 = NULL;
  }
#endif

  delete _criticalSectionModulePtrs;
  delete _criticalSectionModulePtrsFeedback;
  if (_owns_clock) {
    delete &_clock;
  }
}

WebRtc_Word32 ModuleRtpRtcpImpl::ChangeUniqueId(const WebRtc_Word32 id) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "ChangeUniqueId(new id:%d)", id);

  _id = id;

  _rtpReceiver.ChangeUniqueId(id);
  _rtcpReceiver.ChangeUniqueId(id);
  _rtpSender.ChangeUniqueId(id);
  _rtcpSender.ChangeUniqueId(id);
  return 0;
}

// default encoder that we need to multiplex out
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterDefaultModule(RtpRtcp* module) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterDefaultModule(module:0x%x)", module);

  if (module == NULL) {
    return -1;
  }
  if (module == this) {
    WEBRTC_TRACE(kTraceError,
                 kTraceRtpRtcp,
                 _id,
                 "RegisterDefaultModule can't register self as default");
    return -1;
  }
  CriticalSectionScoped lock(_criticalSectionModulePtrs);

  if (_defaultModule) {
    _defaultModule->DeRegisterChildModule(this);
  }
  _defaultModule = (ModuleRtpRtcpImpl*)module;
  _defaultModule->RegisterChildModule(this);
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterDefaultModule() {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DeRegisterDefaultModule()");

  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  if (_defaultModule) {
    _defaultModule->DeRegisterChildModule(this);
    _defaultModule = NULL;
  }
  return 0;
}

bool ModuleRtpRtcpImpl::DefaultModuleRegistered() {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DefaultModuleRegistered()");

  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  if (_defaultModule) {
    return true;
  }
  return false;
}

WebRtc_UWord32 ModuleRtpRtcpImpl::NumberChildModules() {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "NumberChildModules");

  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
  // we use two locks for protecting _childModules one
  // (_criticalSectionModulePtrsFeedback) for incoming  messages
  // (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs for
  //  all outgoing messages sending packets etc

  return _childModules.size();
}

void ModuleRtpRtcpImpl::RegisterChildModule(RtpRtcp* module) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterChildModule(module:0x%x)",
               module);

  CriticalSectionScoped lock(_criticalSectionModulePtrs);

  CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
  // we use two locks for protecting _childModules one
  // (_criticalSectionModulePtrsFeedback) for incoming
  // messages (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs
  //  for all outgoing messages sending packets etc
  _childModules.push_back((ModuleRtpRtcpImpl*)module);
}

void ModuleRtpRtcpImpl::DeRegisterChildModule(RtpRtcp* removeModule) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DeRegisterChildModule(module:0x%x)", removeModule);

  CriticalSectionScoped lock(_criticalSectionModulePtrs);

  CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);

  std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
  while (it != _childModules.end()) {
    RtpRtcp* module = *it;
    if (module == removeModule) {
      _childModules.erase(it);
      return;
    }
    it++;
  }
}

// Lip-sync between voice-video engine,
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSyncModule(RtpRtcp* audioModule) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterSyncModule(module:0x%x)",
               audioModule);

  if (audioModule == NULL) {
    return -1;
  }
  if (_audio) {
    return -1;
  }
  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  _audioModule = (ModuleRtpRtcpImpl*)audioModule;
  return _audioModule->RegisterVideoModule(this);
}

WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterSyncModule() {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DeRegisterSyncModule()");

  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  if (_audioModule) {
    ModuleRtpRtcpImpl* audioModule = _audioModule;
    _audioModule = NULL;
    _receivedNTPsecsAudio = 0;
    _receivedNTPfracAudio = 0;
    _RTCPArrivalTimeSecsAudio = 0;
    _RTCPArrivalTimeFracAudio = 0;
    audioModule->DeRegisterVideoModule();
  }
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterVideoModule(RtpRtcp* videoModule) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterVideoModule(module:0x%x)",
               videoModule);

  if (videoModule == NULL) {
    return -1;
  }
  if (!_audio) {
    return -1;
  }
  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  _videoModule = (ModuleRtpRtcpImpl*)videoModule;
  return 0;
}

void ModuleRtpRtcpImpl::DeRegisterVideoModule() {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DeRegisterVideoModule()");

  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  if (_videoModule) {
    ModuleRtpRtcpImpl* videoModule = _videoModule;
    _videoModule = NULL;
    videoModule->DeRegisterSyncModule();
  }
}

// returns the number of milliseconds until the module want a worker thread
// to call Process
WebRtc_Word32 ModuleRtpRtcpImpl::TimeUntilNextProcess() {
  const WebRtc_UWord32 now = _clock.GetTimeInMS();
  return kRtpRtcpMaxIdleTimeProcess - (now - _lastProcessTime);
}

// Process any pending tasks such as timeouts
// non time critical events
WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
  const WebRtc_UWord32 now = _clock.GetTimeInMS();
  _lastProcessTime = now;

  _rtpSender.ProcessSendToNetwork();

  if (now >= _lastPacketTimeoutProcessTime +
      kRtpRtcpPacketTimeoutProcessTimeMs) {
    _rtpReceiver.PacketTimeout();
    _rtcpReceiver.PacketTimeout();
    _lastPacketTimeoutProcessTime = now;
  }

  if (now >= _lastBitrateProcessTime + kRtpRtcpBitrateProcessTimeMs) {
    _rtpSender.ProcessBitrate();
    _rtpReceiver.ProcessBitrate();
    _lastBitrateProcessTime = now;
  }

  ProcessDeadOrAliveTimer();

  const bool defaultInstance(_childModules.empty() ? false : true);
  if (!defaultInstance && _rtcpSender.TimeToSendRTCPReport()) {
    WebRtc_UWord16 max_rtt = 0;
    if (_rtcpSender.Sending()) {
      std::vector<RTCPReportBlock> receive_blocks;
      _rtcpReceiver.StatisticsReceived(&receive_blocks);
      for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin();
           it != receive_blocks.end(); ++it) {
        WebRtc_UWord16 rtt = 0;
        _rtcpReceiver.RTT(it->remoteSSRC, &max_rtt, NULL, NULL, NULL);
        max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
      }
    } else {
      // We're only receiving, i.e. this module doesn't have its own RTT
      // estimate. Use the RTT set by a sending channel using the same default
      // module.
      max_rtt = _rtcpReceiver.RTT();
    }
    if (max_rtt == 0) {
      // No valid estimate available, i.e. no sending channel using the same
      // default module or no RTCP received yet.
      max_rtt = kDefaultRtt;
    }
    if (REMB() && _rtcpSender.ValidBitrateEstimate()) {
      unsigned int target_bitrate =
        _rtcpSender.CalculateNewTargetBitrate(max_rtt);
      _rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
    } else if (TMMBR()) {
      _rtcpSender.CalculateNewTargetBitrate(max_rtt);
    }
    _rtcpSender.SendRTCP(kRtcpReport);
  }

  if (_rtpSender.RTPKeepalive()) {
    // check time to send RTP keep alive
    if (_rtpSender.TimeToSendRTPKeepalive()) {
      _rtpSender.SendRTPKeepalivePacket();
    }
  }

  if (UpdateRTCPReceiveInformationTimers()) {
    // a receiver has timed out
    UpdateTMMBR();
  }
  return 0;
}

/**
*   Receiver
*/

WebRtc_Word32 ModuleRtpRtcpImpl::InitReceiver() {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "InitReceiver()");

  _packetOverHead = 28; // default is IPV4 UDP
  _receivedNTPsecsAudio = 0;
  _receivedNTPfracAudio = 0;
  _RTCPArrivalTimeSecsAudio = 0;
  _RTCPArrivalTimeFracAudio = 0;

  WebRtc_Word32 ret = _rtpReceiver.Init();
  if (ret < 0) {
    return ret;
  }
  _rtpReceiver.SetPacketOverHead(_packetOverHead);
  return ret;
}

void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() {
  if (_deadOrAliveActive) {
    const WebRtc_UWord32 now = _clock.GetTimeInMS();
    if (now > _deadOrAliveTimeoutMS + _deadOrAliveLastTimer) {
      // RTCP is alive if we have received a report the last 12 seconds
      _deadOrAliveLastTimer += _deadOrAliveTimeoutMS;

      bool RTCPalive = false;
      if (_rtcpReceiver.LastReceived() + 12000 > now) {
        RTCPalive = true;
      }
      _rtpReceiver.ProcessDeadOrAlive(RTCPalive, now);
    }
  }
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetPeriodicDeadOrAliveStatus(
  const bool enable,
  const WebRtc_UWord8 sampleTimeSeconds) {
  if (enable) {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetPeriodicDeadOrAliveStatus(enable, %d)",
                 sampleTimeSeconds);
  } else {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetPeriodicDeadOrAliveStatus(disable)");
  }
  if (sampleTimeSeconds == 0) {
    return -1;
  }
  _deadOrAliveActive = enable;
  _deadOrAliveTimeoutMS = sampleTimeSeconds * 1000;
  // trigger the first after one period
  _deadOrAliveLastTimer = _clock.GetTimeInMS();
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::PeriodicDeadOrAliveStatus(
    bool& enable,
    WebRtc_UWord8& sampleTimeSeconds) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "PeriodicDeadOrAliveStatus()");

  enable = _deadOrAliveActive;
  sampleTimeSeconds = (WebRtc_UWord8)(_deadOrAliveTimeoutMS / 1000);
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetPacketTimeout(
    const WebRtc_UWord32 RTPtimeoutMS,
    const WebRtc_UWord32 RTCPtimeoutMS) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetPacketTimeout(%u,%u)",
               RTPtimeoutMS,
               RTCPtimeoutMS);

  if (_rtpReceiver.SetPacketTimeout(RTPtimeoutMS) == 0) {
    return _rtcpReceiver.SetPacketTimeout(RTCPtimeoutMS);
  }
  return -1;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceivePayload(
  const CodecInst& voiceCodec) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterReceivePayload(voiceCodec)");

  return _rtpReceiver.RegisterReceivePayload(
           voiceCodec.plname,
           voiceCodec.pltype,
           voiceCodec.plfreq,
           voiceCodec.channels,
           (voiceCodec.rate < 0) ? 0 : voiceCodec.rate);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceivePayload(
  const VideoCodec& videoCodec) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterReceivePayload(videoCodec)");

  return _rtpReceiver.RegisterReceivePayload(videoCodec.plName,
                                             videoCodec.plType,
                                             90000,
                                             0,
                                             videoCodec.maxBitrate);
}

WebRtc_Word32 ModuleRtpRtcpImpl::ReceivePayloadType(
  const CodecInst& voiceCodec,
  WebRtc_Word8* plType) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "ReceivePayloadType(voiceCodec)");

  return _rtpReceiver.ReceivePayloadType(
           voiceCodec.plname,
           voiceCodec.plfreq,
           voiceCodec.channels,
           (voiceCodec.rate < 0) ? 0 : voiceCodec.rate,
           plType);
}

WebRtc_Word32 ModuleRtpRtcpImpl::ReceivePayloadType(
  const VideoCodec& videoCodec,
  WebRtc_Word8* plType) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "ReceivePayloadType(videoCodec)");

  return _rtpReceiver.ReceivePayloadType(videoCodec.plName,
                                         90000,
                                         0,
                                         videoCodec.maxBitrate,
                                         plType);
}

WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterReceivePayload(
    const WebRtc_Word8 payloadType) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DeRegisterReceivePayload(%d)",
               payloadType);

  return _rtpReceiver.DeRegisterReceivePayload(payloadType);
}

// get the currently configured SSRC filter
WebRtc_Word32 ModuleRtpRtcpImpl::SSRCFilter(WebRtc_UWord32& allowedSSRC) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SSRCFilter()");

  return _rtpReceiver.SSRCFilter(allowedSSRC);
}

// set a SSRC to be used as a filter for incoming RTP streams
WebRtc_Word32 ModuleRtpRtcpImpl::SetSSRCFilter(
  const bool enable,
  const WebRtc_UWord32 allowedSSRC) {
  if (enable) {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetSSRCFilter(enable, 0x%x)",
                 allowedSSRC);
  } else {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetSSRCFilter(disable)");
  }

  return _rtpReceiver.SetSSRCFilter(enable, allowedSSRC);
}

// Get last received remote timestamp
WebRtc_UWord32 ModuleRtpRtcpImpl::RemoteTimestamp() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteTimestamp()");

  return _rtpReceiver.TimeStamp();
}

// Get the current estimated remote timestamp
WebRtc_Word32 ModuleRtpRtcpImpl::EstimatedRemoteTimeStamp(
    WebRtc_UWord32& timestamp) const {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "EstimatedRemoteTimeStamp()");

  return _rtpReceiver.EstimatedRemoteTimeStamp(timestamp);
}

// Get incoming SSRC
WebRtc_UWord32 ModuleRtpRtcpImpl::RemoteSSRC() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteSSRC()");

  return _rtpReceiver.SSRC();
}

// Get remote CSRC
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteCSRCs(
    WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize]) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteCSRCs()");

  return _rtpReceiver.CSRCs(arrOfCSRC);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetRTXSendStatus(
  const bool enable,
  const bool setSSRC,
  const WebRtc_UWord32 SSRC) {
  _rtpSender.SetRTXStatus(enable, setSSRC, SSRC);
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RTXSendStatus(bool* enable,
                                               WebRtc_UWord32* SSRC) const {
  _rtpSender.RTXStatus(enable, SSRC);
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetRTXReceiveStatus(
  const bool enable,
  const WebRtc_UWord32 SSRC) {
  _rtpReceiver.SetRTXStatus(enable, SSRC);
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RTXReceiveStatus(bool* enable,
                                                  WebRtc_UWord32* SSRC) const {
  _rtpReceiver.RTXStatus(enable, SSRC);
  return 0;
}

// called by the network module when we receive a packet
WebRtc_Word32 ModuleRtpRtcpImpl::IncomingPacket(
    const WebRtc_UWord8* incomingPacket,
    const WebRtc_UWord16 incomingPacketLength) {
  WEBRTC_TRACE(kTraceStream,
               kTraceRtpRtcp,
               _id,
               "IncomingPacket(packetLength:%u)",
               incomingPacketLength);

  // minimum RTP is 12 bytes
  // minimum RTCP is 8 bytes (RTCP BYE)
  if (incomingPacketLength < 8 || incomingPacket == NULL) {
    WEBRTC_TRACE(kTraceDebug,
                 kTraceRtpRtcp,
                 _id,
                 "IncomingPacket invalid buffer or length");
    return -1;
  }
  // check RTP version
  const WebRtc_UWord8  version  = incomingPacket[0] >> 6 ;
  if (version != 2) {
    WEBRTC_TRACE(kTraceDebug,
                 kTraceRtpRtcp,
                 _id,
                 "IncomingPacket invalid RTP version");
    return -1;
  }

  ModuleRTPUtility::RTPHeaderParser rtpParser(incomingPacket,
                                              incomingPacketLength);

  if (rtpParser.RTCP()) {
    // Allow receive of non-compound RTCP packets.
    RTCPUtility::RTCPParserV2 rtcpParser(incomingPacket,
                                         incomingPacketLength,
                                         true);

    const bool validRTCPHeader = rtcpParser.IsValid();
    if (!validRTCPHeader) {
      WEBRTC_TRACE(kTraceDebug,
                   kTraceRtpRtcp,
                   _id,
                   "IncomingPacket invalid RTCP packet");
      return -1;
    }
    RTCPHelp::RTCPPacketInformation rtcpPacketInformation;
    WebRtc_Word32 retVal = _rtcpReceiver.IncomingRTCPPacket(
                             rtcpPacketInformation,
                             &rtcpParser);
    if (retVal == 0) {
      _rtcpReceiver.TriggerCallbacksFromRTCPPacket(rtcpPacketInformation);
    }
    return retVal;

  } else {
    WebRtcRTPHeader rtpHeader;
    memset(&rtpHeader, 0, sizeof(rtpHeader));

    RtpHeaderExtensionMap map;
    _rtpReceiver.GetHeaderExtensionMapCopy(&map);

    const bool validRTPHeader = rtpParser.Parse(rtpHeader, &map);
    if (!validRTPHeader) {
      WEBRTC_TRACE(kTraceDebug,
                   kTraceRtpRtcp,
                   _id,
                   "IncomingPacket invalid RTP header");
      return -1;
    }
    return _rtpReceiver.IncomingRTPPacket(&rtpHeader,
                                          incomingPacket,
                                          incomingPacketLength);
  }
}

WebRtc_Word32 ModuleRtpRtcpImpl::IncomingAudioNTP(
  const WebRtc_UWord32 audioReceivedNTPsecs,
  const WebRtc_UWord32 audioReceivedNTPfrac,
  const WebRtc_UWord32 audioRTCPArrivalTimeSecs,
  const WebRtc_UWord32 audioRTCPArrivalTimeFrac) {
  _receivedNTPsecsAudio = audioReceivedNTPsecs;
  _receivedNTPfracAudio = audioReceivedNTPfrac;
  _RTCPArrivalTimeSecsAudio = audioRTCPArrivalTimeSecs;
  _RTCPArrivalTimeFracAudio = audioRTCPArrivalTimeFrac;
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingDataCallback(
  RtpData* incomingDataCallback) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterIncomingDataCallback(incomingDataCallback:0x%x)",
               incomingDataCallback);

  return _rtpReceiver.RegisterIncomingDataCallback(incomingDataCallback);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingRTPCallback(
  RtpFeedback* incomingMessagesCallback) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterIncomingRTPCallback(incomingMessagesCallback:0x%x)",
               incomingMessagesCallback);

  return _rtpReceiver.RegisterIncomingRTPCallback(incomingMessagesCallback);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingRTCPCallback(
  RtcpFeedback* incomingMessagesCallback) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterIncomingRTCPCallback(incomingMessagesCallback:0x%x)",
               incomingMessagesCallback);

  return _rtcpReceiver.RegisterIncomingRTCPCallback(incomingMessagesCallback);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingVideoCallback(
  RtpVideoFeedback* incomingMessagesCallback) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterIncomingVideoCallback(incomingMessagesCallback:0x%x)",
               incomingMessagesCallback);

  if (_rtcpReceiver.RegisterIncomingVideoCallback(incomingMessagesCallback)
      == 0) {
    return _rtpReceiver.RegisterIncomingVideoCallback(
             incomingMessagesCallback);
  }
  return -1;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterAudioCallback(
  RtpAudioFeedback* messagesCallback) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterAudioCallback(messagesCallback:0x%x)",
               messagesCallback);

  if (_rtpSender.RegisterAudioCallback(messagesCallback) == 0) {
    return _rtpReceiver.RegisterIncomingAudioCallback(messagesCallback);
  }
  return -1;
}

/**
*   Sender
*/

WebRtc_Word32 ModuleRtpRtcpImpl::InitSender() {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "InitSender()");

  _collisionDetected = false;

  // if we are already receiving inform our sender to avoid collision
  if (_rtpSender.Init(_rtpReceiver.SSRC()) != 0) {
    return -1;
  }
  WebRtc_Word32 retVal = _rtcpSender.Init();

  // make sure that RTCP objects are aware of our SSRC
  // (it could have changed due to collision)
  WebRtc_UWord32 SSRC = _rtpSender.SSRC();
  _rtcpReceiver.SetSSRC(SSRC);
  _rtcpSender.SetSSRC(SSRC);
  return retVal;
}

bool ModuleRtpRtcpImpl::RTPKeepalive() const {
  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "RTPKeepalive()");

  return _rtpSender.RTPKeepalive();
}

WebRtc_Word32 ModuleRtpRtcpImpl::RTPKeepaliveStatus(
    bool* enable,
    WebRtc_Word8* unknownPayloadType,
    WebRtc_UWord16* deltaTransmitTimeMS) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTPKeepaliveStatus()");

  return _rtpSender.RTPKeepaliveStatus(enable,
                                       unknownPayloadType,
                                       deltaTransmitTimeMS);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetRTPKeepaliveStatus(
  bool enable,
  WebRtc_Word8 unknownPayloadType,
  WebRtc_UWord16 deltaTransmitTimeMS) {
  if (enable) {
    WEBRTC_TRACE(
      kTraceModuleCall,
      kTraceRtpRtcp,
      _id,
      "SetRTPKeepaliveStatus(true, plType:%d deltaTransmitTimeMS:%u)",
      unknownPayloadType,
      deltaTransmitTimeMS);

    // check the transmit keepalive delta time [1,60]
    if (deltaTransmitTimeMS < 1000 || deltaTransmitTimeMS > 60000) {
      WEBRTC_TRACE(kTraceError,
                   kTraceRtpRtcp,
                   _id,
                   "\tinvalid deltaTransmitTimeSeconds (%d)",
                   deltaTransmitTimeMS);
      return -1;
    }

    // check the payload time [0,127]
    if (unknownPayloadType < 0) {
      WEBRTC_TRACE(kTraceError,
                   kTraceRtpRtcp,
                   _id,
                   "\tinvalid unknownPayloadType (%d)",
                   unknownPayloadType);
      return -1;
    }
    // enable RTP keepalive mechanism
    return _rtpSender.EnableRTPKeepalive(unknownPayloadType,
                                         deltaTransmitTimeMS);
  } else {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetRTPKeepaliveStatus(disable)");
    return _rtpSender.DisableRTPKeepalive();
  }
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendPayload(
  const CodecInst& voiceCodec) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterSendPayload(plName:%s plType:%d frequency:%u)",
               voiceCodec.plname,
               voiceCodec.pltype,
               voiceCodec.plfreq);

  return _rtpSender.RegisterPayload(
           voiceCodec.plname,
           voiceCodec.pltype,
           voiceCodec.plfreq,
           voiceCodec.channels,
           (voiceCodec.rate < 0) ? 0 : voiceCodec.rate);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendPayload(
  const VideoCodec& videoCodec) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterSendPayload(plName:%s plType:%d)",
               videoCodec.plName,
               videoCodec.plType);

  _sendVideoCodec = videoCodec;
  _simulcast = (videoCodec.numberOfSimulcastStreams > 1) ? true : false;
  return _rtpSender.RegisterPayload(videoCodec.plName,
                                    videoCodec.plType,
                                    90000,
                                    0,
                                    videoCodec.maxBitrate);
}

WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterSendPayload(
    const WebRtc_Word8 payloadType) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "DeRegisterSendPayload(%d)", payloadType);

  return _rtpSender.DeRegisterSendPayload(payloadType);
}

WebRtc_Word8 ModuleRtpRtcpImpl::SendPayloadType() const {
  return _rtpSender.SendPayloadType();
}

WebRtc_UWord32 ModuleRtpRtcpImpl::StartTimestamp() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "StartTimestamp()");

  return _rtpSender.StartTimestamp();
}

// configure start timestamp, default is a random number
WebRtc_Word32 ModuleRtpRtcpImpl::SetStartTimestamp(
    const WebRtc_UWord32 timestamp) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetStartTimestamp(%d)",
               timestamp);

  return _rtpSender.SetStartTimestamp(timestamp, true);
}

WebRtc_UWord16 ModuleRtpRtcpImpl::SequenceNumber() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SequenceNumber()");

  return _rtpSender.SequenceNumber();
}

// Set SequenceNumber, default is a random number
WebRtc_Word32 ModuleRtpRtcpImpl::SetSequenceNumber(
    const WebRtc_UWord16 seqNum) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetSequenceNumber(%d)",
               seqNum);

  return _rtpSender.SetSequenceNumber(seqNum);
}

WebRtc_UWord32 ModuleRtpRtcpImpl::SSRC() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SSRC()");

  return _rtpSender.SSRC();
}

// configure SSRC, default is a random number
WebRtc_Word32 ModuleRtpRtcpImpl::SetSSRC(const WebRtc_UWord32 ssrc) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSSRC(%d)", ssrc);

  if (_rtpSender.SetSSRC(ssrc) == 0) {
    _rtcpReceiver.SetSSRC(ssrc);
    _rtcpSender.SetSSRC(ssrc);
    return 0;
  }
  return -1;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetCSRCStatus(const bool include) {
  _rtcpSender.SetCSRCStatus(include);
  return _rtpSender.SetCSRCStatus(include);
}

WebRtc_Word32 ModuleRtpRtcpImpl::CSRCs(
    WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize]) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "CSRCs()");

  return _rtpSender.CSRCs(arrOfCSRC);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetCSRCs(
    const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
    const WebRtc_UWord8 arrLength) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetCSRCs(arrLength:%d)",
               arrLength);

  const bool defaultInstance(_childModules.empty() ? false : true);

  if (defaultInstance) {
    // for default we need to update all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);

    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        module->SetCSRCs(arrOfCSRC, arrLength);
      }
      it++;
    }
    return 0;

  } else {
    for (int i = 0; i < arrLength; i++) {
      WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "\tidx:%d CSRC:%u", i,
                   arrOfCSRC[i]);
    }
    _rtcpSender.SetCSRCs(arrOfCSRC, arrLength);
    return _rtpSender.SetCSRCs(arrOfCSRC, arrLength);
  }
}

WebRtc_UWord32 ModuleRtpRtcpImpl::PacketCountSent() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "PacketCountSent()");

  return _rtpSender.Packets();
}

WebRtc_UWord32 ModuleRtpRtcpImpl::ByteCountSent() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ByteCountSent()");

  return _rtpSender.Bytes();
}

int ModuleRtpRtcpImpl::CurrentSendFrequencyHz() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "CurrentSendFrequencyHz()");

  return _rtpSender.SendPayloadFrequency();
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) {
  if (sending) {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetSendingStatus(sending)");
  } else {
    if (_rtpSender.RTPKeepalive()) {
      WEBRTC_TRACE(
          kTraceWarning,
          kTraceRtpRtcp,
          _id,
          "Can't SetSendingStatus(stopped) when RTP Keepalive is active");
      return -1;
    }
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetSendingStatus(stopped)");
  }
  if (_rtcpSender.Sending() != sending) {
    // sends RTCP BYE when going from true to false
    if (_rtcpSender.SetSendingStatus(sending) != 0) {
      WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
                   "Failed to send RTCP BYE");
    }

    _collisionDetected = false;

    // generate a new timeStamp if true and not configured via API
    // generate a new SSRC for the next "call" if false
    _rtpSender.SetSendingStatus(sending);

    // make sure that RTCP objects are aware of our SSRC (it could have changed
    // due to collision)
    WebRtc_UWord32 SSRC = _rtpSender.SSRC();
    _rtcpReceiver.SetSSRC(SSRC);
    _rtcpSender.SetSSRC(SSRC);
    return 0;
  }
  return 0;
}

bool ModuleRtpRtcpImpl::Sending() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Sending()");

  return _rtcpSender.Sending();
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetSendingMediaStatus(const bool sending) {
  if (sending) {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetSendingMediaStatus(sending)");
  } else {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetSendingMediaStatus(stopped)");
  }
  _rtpSender.SetSendingMediaStatus(sending);
  return 0;
}

bool ModuleRtpRtcpImpl::SendingMedia() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Sending()");

  const bool haveChildModules(_childModules.empty() ? false : true);
  if (!haveChildModules) {
    return _rtpSender.SendingMedia();
  }

  CriticalSectionScoped lock(_criticalSectionModulePtrs);
  std::list<ModuleRtpRtcpImpl*>::const_iterator it = _childModules.begin();
  while (it != _childModules.end()) {
    RTPSender& rtpSender = (*it)->_rtpSender;
    if (rtpSender.SendingMedia()) {
      return true;
    }
    it++;
  }
  return false;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendTransport(
  Transport* outgoingTransport) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RegisterSendTransport(0x%x)", outgoingTransport);

  if (_rtpSender.RegisterSendTransport(outgoingTransport) == 0) {
    return _rtcpSender.RegisterSendTransport(outgoingTransport);
  }
  return -1;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SendOutgoingData(
    FrameType frameType,
    WebRtc_Word8 payloadType,
    WebRtc_UWord32 timeStamp,
    const WebRtc_UWord8* payloadData,
    WebRtc_UWord32 payloadSize,
    const RTPFragmentationHeader* fragmentation,
    const RTPVideoHeader* rtpVideoHdr) {
  WEBRTC_TRACE(
    kTraceStream,
    kTraceRtpRtcp,
    _id,
    "SendOutgoingData(frameType:%d payloadType:%d timeStamp:%u size:%u)",
    frameType, payloadType, timeStamp, payloadSize);

  const bool haveChildModules(_childModules.empty() ? false : true);
  if (!haveChildModules) {
    // Don't sent RTCP from default module
    if (_rtcpSender.TimeToSendRTCPReport(kVideoFrameKey == frameType)) {
      _rtcpSender.SendRTCP(kRtcpReport);
    }
    return _rtpSender.SendOutgoingData(frameType,
                                       payloadType,
                                       timeStamp,
                                       payloadData,
                                       payloadSize,
                                       fragmentation,
                                       NULL,
                                       &(rtpVideoHdr->codecHeader));
  }
  WebRtc_Word32 retVal = -1;
  if (_simulcast) {
    if (rtpVideoHdr == NULL) {
      return -1;
    }
    int idx = 0;
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    for (; idx < rtpVideoHdr->simulcastIdx; idx++) {
      it++;
      if (it == _childModules.end()) {
        return -1;
      }
    }
    RTPSender& rtpSender = (*it)->_rtpSender;
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SendOutgoingData(SimulcastIdx:%u size:%u, ssrc:0x%x)",
                 idx, payloadSize, rtpSender.SSRC());
    return rtpSender.SendOutgoingData(frameType,
                                      payloadType,
                                      timeStamp,
                                      payloadData,
                                      payloadSize,
                                      fragmentation,
                                      NULL,
                                      &(rtpVideoHdr->codecHeader));
  } else {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    // TODO(pwestin) remove codecInfo from SendOutgoingData
    VideoCodecInformation* codecInfo = NULL;

    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    if (it != _childModules.end()) {
      RTPSender& rtpSender = (*it)->_rtpSender;
      retVal = rtpSender.SendOutgoingData(frameType,
                                          payloadType,
                                          timeStamp,
                                          payloadData,
                                          payloadSize,
                                          fragmentation,
                                          NULL,
                                          &(rtpVideoHdr->codecHeader));

      it++;
    }

    // send to all remaining "child" modules
    while (it != _childModules.end()) {
      RTPSender& rtpSender = (*it)->_rtpSender;
      retVal = rtpSender.SendOutgoingData(frameType,
                                          payloadType,
                                          timeStamp,
                                          payloadData,
                                          payloadSize,
                                          fragmentation,
                                          codecInfo,
                                          &(rtpVideoHdr->codecHeader));

      it++;
    }
  }
  return retVal;
}

WebRtc_UWord16 ModuleRtpRtcpImpl::MaxPayloadLength() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "MaxPayloadLength()");

  return _rtpSender.MaxPayloadLength();
}

WebRtc_UWord16 ModuleRtpRtcpImpl::MaxDataPayloadLength() const {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "MaxDataPayloadLength()");

  WebRtc_UWord16 minDataPayloadLength = IP_PACKET_SIZE - 28; // Assuming IP/UDP

  const bool defaultInstance(_childModules.empty() ? false : true);
  if (defaultInstance) {
    // for default we need to update all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    std::list<ModuleRtpRtcpImpl*>::const_iterator it =
      _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        WebRtc_UWord16 dataPayloadLength =
          module->MaxDataPayloadLength();
        if (dataPayloadLength < minDataPayloadLength) {
          minDataPayloadLength = dataPayloadLength;
        }
      }
      it++;
    }
  }

  WebRtc_UWord16 dataPayloadLength = _rtpSender.MaxDataPayloadLength();
  if (dataPayloadLength < minDataPayloadLength) {
    minDataPayloadLength = dataPayloadLength;
  }
  return minDataPayloadLength;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetTransportOverhead(
  const bool TCP,
  const bool IPV6,
  const WebRtc_UWord8 authenticationOverhead) {
  WEBRTC_TRACE(
    kTraceModuleCall,
    kTraceRtpRtcp,
    _id,
    "SetTransportOverhead(TCP:%d, IPV6:%d authenticationOverhead:%u)",
    TCP, IPV6, authenticationOverhead);

  WebRtc_UWord16 packetOverHead = 0;
  if (IPV6) {
    packetOverHead = 40;
  } else {
    packetOverHead = 20;
  }
  if (TCP) {
    // TCP
    packetOverHead += 20;
  } else {
    // UDP
    packetOverHead += 8;
  }
  packetOverHead += authenticationOverhead;

  if (packetOverHead == _packetOverHead) {
    // ok same as before
    return 0;
  }
  // calc diff
  WebRtc_Word16 packetOverHeadDiff = packetOverHead - _packetOverHead;

  // store new
  _packetOverHead = packetOverHead;

  _rtpReceiver.SetPacketOverHead(_packetOverHead);
  WebRtc_UWord16 length = _rtpSender.MaxPayloadLength() - packetOverHeadDiff;
  return _rtpSender.SetMaxPayloadLength(length, _packetOverHead);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetMaxTransferUnit(const WebRtc_UWord16 MTU) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetMaxTransferUnit(%u)",
               MTU);

  if (MTU > IP_PACKET_SIZE) {
    WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
                 "Invalid in argument to SetMaxTransferUnit(%u)", MTU);
    return -1;
  }
  return _rtpSender.SetMaxPayloadLength(MTU - _packetOverHead,
                                        _packetOverHead);
}

/*
*   RTCP
*/
RTCPMethod ModuleRtpRtcpImpl::RTCP() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTCP()");

  if (_rtcpSender.Status() != kRtcpOff) {
    return _rtcpReceiver.Status();
  }
  return kRtcpOff;
}

// configure RTCP status i.e on/off
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPStatus(const RTCPMethod method) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTCPStatus(%d)",
               method);

  if (_rtcpSender.SetRTCPStatus(method) == 0) {
    return _rtcpReceiver.SetRTCPStatus(method);
  }
  return -1;
}

// only for internal test
WebRtc_UWord32 ModuleRtpRtcpImpl::LastSendReport(WebRtc_UWord32& lastRTCPTime) {
  return _rtcpSender.LastSendReport(lastRTCPTime);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetCNAME(%s)", cName);
  return _rtcpSender.SetCNAME(cName);
}

WebRtc_Word32 ModuleRtpRtcpImpl::CNAME(char cName[RTCP_CNAME_SIZE]) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "CNAME()");
  return _rtcpSender.CNAME(cName);
}

WebRtc_Word32 ModuleRtpRtcpImpl::AddMixedCNAME(
  const WebRtc_UWord32 SSRC,
  const char cName[RTCP_CNAME_SIZE]) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "AddMixedCNAME(SSRC:%u)", SSRC);

  return _rtcpSender.AddMixedCNAME(SSRC, cName);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RemoveMixedCNAME(const WebRtc_UWord32 SSRC) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "RemoveMixedCNAME(SSRC:%u)", SSRC);
  return _rtcpSender.RemoveMixedCNAME(SSRC);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RemoteCNAME(
  const WebRtc_UWord32 remoteSSRC,
  char cName[RTCP_CNAME_SIZE]) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "RemoteCNAME(SSRC:%u)", remoteSSRC);

  return _rtcpReceiver.CNAME(remoteSSRC, cName);
}

WebRtc_UWord16 ModuleRtpRtcpImpl::RemoteSequenceNumber() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteSequenceNumber()");

  return _rtpReceiver.SequenceNumber();
}

WebRtc_Word32 ModuleRtpRtcpImpl::RemoteNTP(
    WebRtc_UWord32* receivedNTPsecs,
    WebRtc_UWord32* receivedNTPfrac,
    WebRtc_UWord32* RTCPArrivalTimeSecs,
    WebRtc_UWord32* RTCPArrivalTimeFrac) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteNTP()");

  return _rtcpReceiver.NTP(receivedNTPsecs,
                           receivedNTPfrac,
                           RTCPArrivalTimeSecs,
                           RTCPArrivalTimeFrac);
}

// Get RoundTripTime
WebRtc_Word32 ModuleRtpRtcpImpl::RTT(const WebRtc_UWord32 remoteSSRC,
                                     WebRtc_UWord16* RTT,
                                     WebRtc_UWord16* avgRTT,
                                     WebRtc_UWord16* minRTT,
                                     WebRtc_UWord16* maxRTT) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTT()");

  return _rtcpReceiver.RTT(remoteSSRC, RTT, avgRTT, minRTT, maxRTT);
}

// Reset RoundTripTime statistics
WebRtc_Word32
ModuleRtpRtcpImpl::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ResetRTT(SSRC:%u)",
               remoteSSRC);

  return _rtcpReceiver.ResetRTT(remoteSSRC);
}

// Reset RTP statistics
WebRtc_Word32
ModuleRtpRtcpImpl::ResetStatisticsRTP() {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ResetStatisticsRTP()");

  return _rtpReceiver.ResetStatistics();
}

// Reset RTP data counters for the receiving side
WebRtc_Word32 ModuleRtpRtcpImpl::ResetReceiveDataCountersRTP() {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "ResetReceiveDataCountersRTP()");

  return _rtpReceiver.ResetDataCounters();
}

// Reset RTP data counters for the sending side
WebRtc_Word32 ModuleRtpRtcpImpl::ResetSendDataCountersRTP() {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "ResetSendDataCountersRTP()");

  return _rtpSender.ResetDataCounters();
}

// Force a send of an RTCP packet
// normal SR and RR are triggered via the process function
WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCP(WebRtc_UWord32 rtcpPacketType) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendRTCP(0x%x)",
               rtcpPacketType);

  return  _rtcpSender.SendRTCP(rtcpPacketType);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPApplicationSpecificData(
    const WebRtc_UWord8 subType,
    const WebRtc_UWord32 name,
    const WebRtc_UWord8* data,
    const WebRtc_UWord16 length) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "SetRTCPApplicationSpecificData(subType:%d name:0x%x)", subType,
               name);

  return  _rtcpSender.SetApplicationSpecificData(subType, name, data, length);
}

/*
*   (XR) VOIP metric
*/
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPVoIPMetrics(
    const RTCPVoIPMetric* VoIPMetric) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTCPVoIPMetrics()");

  return  _rtcpSender.SetRTCPVoIPMetrics(VoIPMetric);
}

// our localy created statistics of the received RTP stream
WebRtc_Word32 ModuleRtpRtcpImpl::StatisticsRTP(
    WebRtc_UWord8*  fraction_lost,
    WebRtc_UWord32* cum_lost,
    WebRtc_UWord32* ext_max,
    WebRtc_UWord32* jitter,
    WebRtc_UWord32* max_jitter) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "StatisticsRTP()");

  WebRtc_UWord32 jitter_transmission_time_offset = 0;

  WebRtc_Word32 retVal = _rtpReceiver.Statistics(
      fraction_lost,
      cum_lost,
      ext_max,
      jitter,
      max_jitter,
      &jitter_transmission_time_offset,
      (_rtcpSender.Status() == kRtcpOff));
  if (retVal == -1) {
    WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
                 "StatisticsRTP() no statisitics availble");
  }
  return retVal;
}

WebRtc_Word32 ModuleRtpRtcpImpl::DataCountersRTP(
    WebRtc_UWord32* bytesSent,
    WebRtc_UWord32* packetsSent,
    WebRtc_UWord32* bytesReceived,
    WebRtc_UWord32* packetsReceived) const {
  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "DataCountersRTP()");

  if (bytesSent) {
    *bytesSent = _rtpSender.Bytes();
  }
  if (packetsSent) {
    *packetsSent = _rtpSender.Packets();
  }
  return _rtpReceiver.DataCounters(bytesReceived, packetsReceived);
}

WebRtc_Word32 ModuleRtpRtcpImpl::ReportBlockStatistics(
    WebRtc_UWord8* fraction_lost,
    WebRtc_UWord32* cum_lost,
    WebRtc_UWord32* ext_max,
    WebRtc_UWord32* jitter,
    WebRtc_UWord32* jitter_transmission_time_offset) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ReportBlockStatistics()");
  WebRtc_Word32 missing = 0;
  WebRtc_Word32 ret = _rtpReceiver.Statistics(fraction_lost,
                                              cum_lost,
                                              ext_max,
                                              jitter,
                                              NULL,
                                              jitter_transmission_time_offset,
                                              &missing,
                                              true);

#ifdef MATLAB
  if (_plot1 == NULL) {
    _plot1 = eng.NewPlot(new MatlabPlot());
    _plot1->AddTimeLine(30, "b", "lost", _clock.GetTimeInMS());
  }
  _plot1->Append("lost", missing);
  _plot1->Plot();
#endif

  return ret;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat(RTCPSenderInfo* senderInfo) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");

  return _rtcpReceiver.SenderInfoReceived(senderInfo);
}

// received RTCP report
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat(
  std::vector<RTCPReportBlock>* receiveBlocks) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");

  return _rtcpReceiver.StatisticsReceived(receiveBlocks);
}

WebRtc_Word32 ModuleRtpRtcpImpl::AddRTCPReportBlock(
    const WebRtc_UWord32 SSRC,
    const RTCPReportBlock* reportBlock) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "AddRTCPReportBlock()");

  return _rtcpSender.AddReportBlock(SSRC, reportBlock);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RemoveRTCPReportBlock(
    const WebRtc_UWord32 SSRC) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoveRTCPReportBlock()");

  return _rtcpSender.RemoveReportBlock(SSRC);
}

/*
 *  (REMB) Receiver Estimated Max Bitrate
 */
bool ModuleRtpRtcpImpl::REMB() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "REMB()");

  return _rtcpSender.REMB();
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetREMBStatus(const bool enable) {
  if (enable) {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetREMBStatus(enable)");
  } else {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetREMBStatus(disable)");
  }
  return _rtcpSender.SetREMBStatus(enable);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetREMBData(const WebRtc_UWord32 bitrate,
                                             const WebRtc_UWord8 numberOfSSRC,
                                             const WebRtc_UWord32* SSRC) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "SetREMBData(bitrate:%d,?,?)", bitrate);
  return _rtcpSender.SetREMBData(bitrate, numberOfSSRC, SSRC);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetMaximumBitrateEstimate(
        const WebRtc_UWord32 bitrate) {
  if(!_rtcpSender.REMB()) {
    WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
                 "SetMaximumBitrateEstimate - REMB not enabled.");
    return -1;
  }
  OnReceivedEstimatedMaxBitrate(bitrate);
  return 0;
}

bool ModuleRtpRtcpImpl::SetRemoteBitrateObserver(
  RtpRemoteBitrateObserver* observer) {
  return _rtcpSender.SetRemoteBitrateObserver(observer);
}

/*
 *   (IJ) Extended jitter report.
 */
bool ModuleRtpRtcpImpl::IJ() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "IJ()");

  return _rtcpSender.IJ();
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetIJStatus(const bool enable) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetIJStatus(%s)", enable ? "true" : "false");

  return _rtcpSender.SetIJStatus(enable);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendRtpHeaderExtension(
  const RTPExtensionType type,
  const WebRtc_UWord8 id) {
  return _rtpSender.RegisterRtpHeaderExtension(type, id);
}

WebRtc_Word32 ModuleRtpRtcpImpl::DeregisterSendRtpHeaderExtension(
  const RTPExtensionType type) {
  return _rtpSender.DeregisterRtpHeaderExtension(type);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceiveRtpHeaderExtension(
  const RTPExtensionType type,
  const WebRtc_UWord8 id) {
  return _rtpReceiver.RegisterRtpHeaderExtension(type, id);
}

WebRtc_Word32 ModuleRtpRtcpImpl::DeregisterReceiveRtpHeaderExtension(
  const RTPExtensionType type) {
  return _rtpReceiver.DeregisterRtpHeaderExtension(type);
}

void ModuleRtpRtcpImpl::SetTransmissionSmoothingStatus(const bool enable) {
  _rtpSender.SetTransmissionSmoothingStatus(enable);
}

bool ModuleRtpRtcpImpl::TransmissionSmoothingStatus() const {
  return _rtpSender.TransmissionSmoothingStatus();
}

/*
*   (TMMBR) Temporary Max Media Bit Rate
*/
bool ModuleRtpRtcpImpl::TMMBR() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TMMBR()");

  return _rtcpSender.TMMBR();
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBRStatus(const bool enable) {
  if (enable) {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetTMMBRStatus(enable)");
  } else {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetTMMBRStatus(disable)");
  }
  return _rtcpSender.SetTMMBRStatus(enable);
}

WebRtc_Word32 ModuleRtpRtcpImpl::TMMBRReceived(
    const WebRtc_UWord32 size,
    const WebRtc_UWord32 accNumCandidates,
    TMMBRSet* candidateSet) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TMMBRReceived()");

  return _rtcpReceiver.TMMBRReceived(size, accNumCandidates, candidateSet);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBN(const TMMBRSet* boundingSet,
                                          const WebRtc_UWord32 maxBitrateKbit) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetTMMBN()");

  return _rtcpSender.SetTMMBN(boundingSet, maxBitrateKbit);
}

WebRtc_Word32 ModuleRtpRtcpImpl::RequestTMMBR(const WebRtc_UWord32 estimatedBW,
                                              const WebRtc_UWord32 packetOH) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RequestTMMBR()");

  return _rtcpSender.RequestTMMBR(estimatedBW, packetOH);
}

/*
*   (NACK) Negative acknowledgement
*/

// Is Negative acknowledgement requests on/off?
NACKMethod ModuleRtpRtcpImpl::NACK() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "NACK()");

  NACKMethod childMethod = kNackOff;
  const bool defaultInstance(_childModules.empty() ? false : true);
  if (defaultInstance) {
    // for default we need to check all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    std::list<ModuleRtpRtcpImpl*>::const_iterator it =
      _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        NACKMethod nackMethod = module->NACK();
        if (nackMethod != kNackOff) {
          childMethod = nackMethod;
          break;
        }
      }
      it++;
    }
  }

  NACKMethod method = _nackMethod;
  if (childMethod != kNackOff) {
    method = childMethod;
  }
  return method;
}

// Turn negative acknowledgement requests on/off
WebRtc_Word32 ModuleRtpRtcpImpl::SetNACKStatus(NACKMethod method) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetNACKStatus(%u)", method);

  _nackMethod = method;
  _rtpReceiver.SetNACKStatus(method);
  return 0;
}

// Returns the currently configured retransmission mode.
int ModuleRtpRtcpImpl::SelectiveRetransmissions() const {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SelectiveRetransmissions()");
  return _rtpSender.SelectiveRetransmissions();
}

// Enable or disable a retransmission mode, which decides which packets will
// be retransmitted if NACKed.
int ModuleRtpRtcpImpl::SetSelectiveRetransmissions(uint8_t settings) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetSelectiveRetransmissions(%u)",
               settings);
  return _rtpSender.SetSelectiveRetransmissions(settings);
}

// Send a Negative acknowledgement packet
WebRtc_Word32 ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList,
                                          const WebRtc_UWord16 size) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SendNACK(size:%u)", size);

  if (size > NACK_PACKETS_MAX_SIZE) {
    RequestKeyFrame();
    return -1;
  }
  WebRtc_UWord16 avgRTT = 0;
  _rtcpReceiver.RTT(_rtpReceiver.SSRC(), NULL, &avgRTT, NULL, NULL);

  WebRtc_UWord32 waitTime = 5 + ((avgRTT * 3) >> 1); // 5 + RTT*1.5
  if (waitTime == 5) {
    waitTime = 100; //During startup we don't have an RTT
  }
  const WebRtc_UWord32 now = _clock.GetTimeInMS();
  const WebRtc_UWord32 timeLimit = now - waitTime;

  if (_nackLastTimeSent < timeLimit) {
    // send list
  } else {
    // only send if extended list
    if (_nackLastSeqNumberSent == nackList[size - 1]) {
      // last seq num is the same don't send list
      return 0;
    } else {
      // send list
    }
  }
  _nackLastTimeSent =  now;
  _nackLastSeqNumberSent = nackList[size - 1];

  switch (_nackMethod) {
    case kNackRtcp:
      return _rtcpSender.SendRTCP(kRtcpNack, size, nackList);
    case kNackOff:
      return -1;
  };
  return -1;
}

// Store the sent packets, needed to answer to a Negative acknowledgement
// requests
WebRtc_Word32 ModuleRtpRtcpImpl::SetStorePacketsStatus(
  const bool enable,
  const WebRtc_UWord16 numberToStore) {
  if (enable) {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetStorePacketsStatus(enable, numberToStore:%d)",
                 numberToStore);
  } else {
    WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
                 "SetStorePacketsStatus(disable)");
  }
  return _rtpSender.SetStorePacketsStatus(enable, numberToStore);
}

/*
*   Audio
*/

// Outband TelephoneEvent detection
WebRtc_Word32 ModuleRtpRtcpImpl::SetTelephoneEventStatus(
  const bool enable,
  const bool forwardToDecoder,
  const bool detectEndOfTone) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "SetTelephoneEventStatus(enable:%d forwardToDecoder:%d"
               " detectEndOfTone:%d)", enable, forwardToDecoder,
               detectEndOfTone);

  return _rtpReceiver.SetTelephoneEventStatus(enable, forwardToDecoder,
                                              detectEndOfTone);
}

// Is outband TelephoneEvent turned on/off?
bool ModuleRtpRtcpImpl::TelephoneEvent() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TelephoneEvent()");

  return _rtpReceiver.TelephoneEvent();
}

// Is forwarding of outband telephone events turned on/off?
bool ModuleRtpRtcpImpl::TelephoneEventForwardToDecoder() const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "TelephoneEventForwardToDecoder()");

  return _rtpReceiver.TelephoneEventForwardToDecoder();
}

// Send a TelephoneEvent tone using RFC 2833 (4733)
WebRtc_Word32 ModuleRtpRtcpImpl::SendTelephoneEventOutband(
    const WebRtc_UWord8 key,
    const WebRtc_UWord16 timeMs,
    const WebRtc_UWord8 level) {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
               "SendTelephoneEventOutband(key:%u, timeMs:%u, level:%u)", key,
               timeMs, level);

  return _rtpSender.SendTelephoneEvent(key, timeMs, level);
}

bool ModuleRtpRtcpImpl::SendTelephoneEventActive(
  WebRtc_Word8& telephoneEvent) const {

  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SendTelephoneEventActive()");

  return _rtpSender.SendTelephoneEventActive(telephoneEvent);
}

// set audio packet size, used to determine when it's time to send a DTMF
// packet in silence (CNG)
WebRtc_Word32 ModuleRtpRtcpImpl::SetAudioPacketSize(
  const WebRtc_UWord16 packetSizeSamples) {

  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetAudioPacketSize(%u)",
               packetSizeSamples);

  return _rtpSender.SetAudioPacketSize(packetSizeSamples);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetRTPAudioLevelIndicationStatus(
  const bool enable,
  const WebRtc_UWord8 ID) {

  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetRTPAudioLevelIndicationStatus(enable=%d, ID=%u)",
               enable,
               ID);

  if (enable) {
    _rtpReceiver.RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, ID);
  } else {
    _rtpReceiver.DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
  }
  return _rtpSender.SetAudioLevelIndicationStatus(enable, ID);
}

WebRtc_Word32 ModuleRtpRtcpImpl::GetRTPAudioLevelIndicationStatus(
  bool& enable,
  WebRtc_UWord8& ID) const {

  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "GetRTPAudioLevelIndicationStatus()");
  return _rtpSender.AudioLevelIndicationStatus(enable, ID);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetAudioLevel(const WebRtc_UWord8 level_dBov) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetAudioLevel(level_dBov:%u)",
               level_dBov);
  return _rtpSender.SetAudioLevel(level_dBov);
}

// Set payload type for Redundant Audio Data RFC 2198
WebRtc_Word32 ModuleRtpRtcpImpl::SetSendREDPayloadType(
  const WebRtc_Word8 payloadType) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetSendREDPayloadType(%d)",
               payloadType);

  return _rtpSender.SetRED(payloadType);
}

// Get payload type for Redundant Audio Data RFC 2198
WebRtc_Word32 ModuleRtpRtcpImpl::SendREDPayloadType(
    WebRtc_Word8& payloadType) const {
  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendREDPayloadType()");

  return _rtpSender.RED(payloadType);
}


/*
*   Video
*/
RtpVideoCodecTypes ModuleRtpRtcpImpl::ReceivedVideoCodec() const {
  return _rtpReceiver.VideoCodecType();
}

RtpVideoCodecTypes ModuleRtpRtcpImpl::SendVideoCodec() const {
  return _rtpSender.VideoCodecType();
}

void ModuleRtpRtcpImpl::SetSendBitrate(const WebRtc_UWord32 startBitrate,
                                       const WebRtc_UWord16 minBitrateKbit,
                                       const WebRtc_UWord16 maxBitrateKbit) {

  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetSendBitrate start:%ubit/s min:%uKbit/s max:%uKbit/s",
               startBitrate, minBitrateKbit, maxBitrateKbit);

  const bool defaultInstance(_childModules.empty() ? false : true);

  if (defaultInstance) {
    // for default we need to update all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);

    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        module->SetSendBitrate(startBitrate,
                               minBitrateKbit,
                               maxBitrateKbit);
      }
      it++;
    }
  }
  // TODO(henrike): this function also returns a value. It never fails so
  // make it return void.
  _rtpSender.SetTargetSendBitrate(startBitrate);

  _bandwidthManagement.SetSendBitrate(startBitrate, minBitrateKbit,
                                      maxBitrateKbit);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetKeyFrameRequestMethod(
  const KeyFrameRequestMethod method) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetKeyFrameRequestMethod(method:%u)",
               method);

  _keyFrameReqMethod = method;
  return 0;
}

WebRtc_Word32 ModuleRtpRtcpImpl::RequestKeyFrame() {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "RequestKeyFrame");

  switch (_keyFrameReqMethod) {
    case kKeyFrameReqFirRtp:
      return _rtpSender.SendRTPIntraRequest();
    case kKeyFrameReqPliRtcp:
      return _rtcpSender.SendRTCP(kRtcpPli);
    case kKeyFrameReqFirRtcp:
      return _rtcpSender.SendRTCP(kRtcpFir);
  }
  return -1;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCPSliceLossIndication(
  const WebRtc_UWord8 pictureID) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SendRTCPSliceLossIndication (pictureID:%d)",
               pictureID);
  return _rtcpSender.SendRTCP(kRtcpSli, 0, 0, false, pictureID);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetCameraDelay(const WebRtc_Word32 delayMS) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetCameraDelay(%d)",
               delayMS);
  const bool defaultInstance(_childModules.empty() ? false : true);

  if (defaultInstance) {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);

    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        module->SetCameraDelay(delayMS);
      }
      it++;
    }
    return 0;
  }
  return _rtcpSender.SetCameraDelay(delayMS);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetGenericFECStatus(
  const bool enable,
  const WebRtc_UWord8 payloadTypeRED,
  const WebRtc_UWord8 payloadTypeFEC) {
  if (enable) {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetGenericFECStatus(enable, %u)",
                 payloadTypeRED);
  } else {
    WEBRTC_TRACE(kTraceModuleCall,
                 kTraceRtpRtcp,
                 _id,
                 "SetGenericFECStatus(disable)");
  }
  return _rtpSender.SetGenericFECStatus(enable,
                                        payloadTypeRED,
                                        payloadTypeFEC);
}

WebRtc_Word32 ModuleRtpRtcpImpl::GenericFECStatus(
  bool& enable,
  WebRtc_UWord8& payloadTypeRED,
  WebRtc_UWord8& payloadTypeFEC) {

  WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "GenericFECStatus()");

  bool childEnabled = false;
  const bool defaultInstance(_childModules.empty() ? false : true);
  if (defaultInstance) {
    // for default we need to check all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module)  {
        bool enabled = false;
        WebRtc_UWord8 dummyPTypeRED = 0;
        WebRtc_UWord8 dummyPTypeFEC = 0;
        if (module->GenericFECStatus(enabled,
                                     dummyPTypeRED,
                                     dummyPTypeFEC) == 0 && enabled) {
          childEnabled = true;
          break;
        }
      }
      it++;
    }
  }
  WebRtc_Word32 retVal = _rtpSender.GenericFECStatus(enable,
                                                     payloadTypeRED,
                                                     payloadTypeFEC);
  if (childEnabled) {
    // returns true if enabled for any child module
    enable = childEnabled;
  }
  return retVal;
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetFECCodeRate(
  const WebRtc_UWord8 keyFrameCodeRate,
  const WebRtc_UWord8 deltaFrameCodeRate) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp,
               _id,
               "SetFECCodeRate(%u, %u)",
               keyFrameCodeRate,
               deltaFrameCodeRate);

  const bool defaultInstance(_childModules.empty() ? false : true);
  if (defaultInstance)  {
    // for default we need to update all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);

    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        module->SetFECCodeRate(keyFrameCodeRate, deltaFrameCodeRate);
      }
      it++;
    }
    return 0;
  }
  return _rtpSender.SetFECCodeRate(keyFrameCodeRate, deltaFrameCodeRate);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SetFECUepProtection(
  const bool keyUseUepProtection,
  const bool deltaUseUepProtection) {
  WEBRTC_TRACE(kTraceModuleCall,
               kTraceRtpRtcp, _id,
               "SetFECUepProtection(%d, %d)",
               keyUseUepProtection,
               deltaUseUepProtection);

  const bool defaultInstance(_childModules.empty() ? false : true);
  if (defaultInstance)  {
    // for default we need to update all child modules too
    CriticalSectionScoped lock(_criticalSectionModulePtrs);

    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        module->SetFECUepProtection(keyUseUepProtection,
                                    deltaUseUepProtection);
      }
      it++;
    }
    return 0;
  }
  return _rtpSender.SetFECUepProtection(keyUseUepProtection,
                                        deltaUseUepProtection);
}

void ModuleRtpRtcpImpl::SetRemoteSSRC(const WebRtc_UWord32 SSRC) {
  // inform about the incoming SSRC
  _rtcpSender.SetRemoteSSRC(SSRC);
  _rtcpReceiver.SetRemoteSSRC(SSRC);

  // check for a SSRC collision
  if (_rtpSender.SSRC() == SSRC && !_collisionDetected) {
    // if we detect a collision change the SSRC but only once
    _collisionDetected = true;
    WebRtc_UWord32 newSSRC = _rtpSender.GenerateNewSSRC();
    if (newSSRC == 0) {
      // configured via API ignore
      return;
    }
    if (kRtcpOff != _rtcpSender.Status()) {
      // send RTCP bye on the current SSRC
      _rtcpSender.SendRTCP(kRtcpBye);
    }
    // change local SSRC

    // inform all objects about the new SSRC
    _rtcpSender.SetSSRC(newSSRC);
    _rtcpReceiver.SetSSRC(newSSRC);
  }
}

WebRtc_UWord32 ModuleRtpRtcpImpl::BitrateReceivedNow() const {
  return _rtpReceiver.BitrateNow();
}

void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
                                    WebRtc_UWord32* videoRate,
                                    WebRtc_UWord32* fecRate,
                                    WebRtc_UWord32* nackRate) const {
  const bool defaultInstance(_childModules.empty() ? false : true);

  if (defaultInstance) {
    // for default we need to update the send bitrate
    CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);

    if (totalRate != NULL)
      *totalRate = 0;
    if (videoRate != NULL)
      *videoRate = 0;
    if (fecRate != NULL)
      *fecRate = 0;
    if (nackRate != NULL)
      *nackRate = 0;

    std::list<ModuleRtpRtcpImpl*>::const_iterator it =
      _childModules.begin();
    while (it != _childModules.end()) {
      RtpRtcp* module = *it;
      if (module) {
        WebRtc_UWord32 childTotalRate = 0;
        WebRtc_UWord32 childVideoRate = 0;
        WebRtc_UWord32 childFecRate = 0;
        WebRtc_UWord32 childNackRate = 0;
        module->BitrateSent(&childTotalRate,
                            &childVideoRate,
                            &childFecRate,
                            &childNackRate);
        if (totalRate != NULL && childTotalRate > *totalRate)
          *totalRate = childTotalRate;
        if (videoRate != NULL && childVideoRate > *videoRate)
          *videoRate = childVideoRate;
        if (fecRate != NULL && childFecRate > *fecRate)
          *fecRate = childFecRate;
        if (nackRate != NULL && childNackRate > *nackRate)
          *nackRate = childNackRate;
      }
      it++;
    }
    return;
  }
  if (totalRate != NULL)
    *totalRate = _rtpSender.BitrateLast();
  if (videoRate != NULL)
    *videoRate = _rtpSender.VideoBitrateSent();
  if (fecRate != NULL)
    *fecRate = _rtpSender.FecOverheadRate();
  if (nackRate != NULL)
    *nackRate = _rtpSender.NackOverheadRate();
}

int ModuleRtpRtcpImpl::EstimatedSendBandwidth(
    WebRtc_UWord32* available_bandwidth) const {
  return _bandwidthManagement.AvailableBandwidth(available_bandwidth);
}

int ModuleRtpRtcpImpl::EstimatedReceiveBandwidth(
    WebRtc_UWord32* available_bandwidth) const {
  if (!_rtcpSender.ValidBitrateEstimate())
    return -1;
  *available_bandwidth = _rtcpSender.LatestBandwidthEstimate();
  return 0;
}

// for lip sync
void ModuleRtpRtcpImpl::OnReceivedNTP() {
  // don't do anything if we are the audio module
  // video module is responsible for sync
  if (!_audio) {
    WebRtc_Word32 diff = 0;
    WebRtc_UWord32 receivedNTPsecs = 0;
    WebRtc_UWord32 receivedNTPfrac = 0;
    WebRtc_UWord32 RTCPArrivalTimeSecs = 0;
    WebRtc_UWord32 RTCPArrivalTimeFrac = 0;

    if (0 == _rtcpReceiver.NTP(&receivedNTPsecs,
                               &receivedNTPfrac,
                               &RTCPArrivalTimeSecs,
                               &RTCPArrivalTimeFrac)) {
      CriticalSectionScoped lock(_criticalSectionModulePtrs);

      if (_audioModule) {
        if (0 != _audioModule->RemoteNTP(&_receivedNTPsecsAudio,
                                         &_receivedNTPfracAudio,
                                         &_RTCPArrivalTimeSecsAudio,
                                         &_RTCPArrivalTimeFracAudio)) {
          // failed ot get audio NTP
          return;
        }
      }
      if (_receivedNTPfracAudio != 0) {
        // ReceivedNTPxxx is NTP at sender side when sent.
        // RTCPArrivalTimexxx is NTP at receiver side when received.
        // can't use ConvertNTPTimeToMS since calculation can be
        //  negative

        WebRtc_Word32 NTPdiff = (WebRtc_Word32)
                                ((_receivedNTPsecsAudio - receivedNTPsecs) *
                                 1000); // ms
        NTPdiff += (WebRtc_Word32)
                   (_receivedNTPfracAudio / FracMS - receivedNTPfrac / FracMS);

        WebRtc_Word32 RTCPdiff =
            static_cast<WebRtc_Word32> ((_RTCPArrivalTimeSecsAudio -
                                         RTCPArrivalTimeSecs) * 1000);
        RTCPdiff += (WebRtc_Word32)
                    (_RTCPArrivalTimeFracAudio / FracMS -
                     RTCPArrivalTimeFrac / FracMS);

        diff = NTPdiff - RTCPdiff;
        // if diff is + video is behind
        if (diff < -1000 || diff > 1000) {
          // unresonable ignore value.
          diff = 0;
          return;
        }
      }
    }
    // export via callback
    // after release of critsect
    _rtcpReceiver.UpdateLipSync(diff);
  }
}

// our local BW estimate is updated
void ModuleRtpRtcpImpl::OnBandwidthEstimateUpdate(
  WebRtc_UWord16 bandWidthKbit) {

  WebRtc_UWord32 maxBitrateKbit = _rtpReceiver.MaxConfiguredBitrate() / 1000;
  if (maxBitrateKbit) {
    // the app has set a max bitrate
    if (maxBitrateKbit < bandWidthKbit) {
      // cap TMMBR at max configured bitrate
      bandWidthKbit = (WebRtc_UWord16)maxBitrateKbit;
    }
  }
  if (_rtcpSender.TMMBR()) {
    /* Maximum total media bit rate:
        The upper limit on total media bit rate for a given media
        stream at a particular receiver and for its selected protocol
        layer.  Note that this value cannot be measured on the
        received media stream.  Instead, it needs to be calculated or
        determined through other means, such as quality of service
        (QoS) negotiations or local resource limitations.  Also note
        that this value is an average (on a timescale that is
        reasonable for the application) and that it may be different
        from the instantaneous bit rate seen by packets in the media
        stream.
    */
    /* Overhead:
        All protocol header information required to convey a packet
        with media data from sender to receiver, from the application
        layer down to a pre-defined protocol level (for example, down
        to, and including, the IP header).  Overhead may include, for
        example, IP, UDP, and RTP headers, any layer 2 headers, any
        Contributing Sources (CSRCs), RTP padding, and RTP header
        extensions.  Overhead excludes any RTP payload headers and the
        payload itself.
    */
    _rtpReceiver.PacketOHReceived();

    // call RequestTMMBR when our localy created estimate changes
    _rtcpSender.RequestTMMBR(bandWidthKbit, 0);
  }
}

RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate(
  const RateControlInput& rateControlInput) {

  bool firstOverUse = false;
  RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput,
                                                            firstOverUse);
  if (firstOverUse) {
    // Send TMMBR or REMB immediately.
    WebRtc_UWord16 RTT = 0;
    _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL);
    // About to send TMMBR, first run remote rate control
    // to get a target bit rate.
    unsigned int target_bitrate =
      _rtcpSender.CalculateNewTargetBitrate(RTT);
    if (REMB()) {
      _rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
    } else if (TMMBR()) {
      _rtcpSender.SendRTCP(kRtcpTmmbr);
    }
  }
  return region;
}

// bad state of RTP receiver request a keyframe
void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
  RequestKeyFrame();
}

void ModuleRtpRtcpImpl::OnReceivedIntraFrameRequest(const RtpRtcp* caller) {
  if (_defaultModule) {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    if (_defaultModule) {
      // if we use a default module pass this info to the default module
      _defaultModule->OnReceivedIntraFrameRequest(caller);
      return;
    }
  }

  WebRtc_UWord8 streamIdx = 0;
  FrameType frameType = kVideoFrameKey;
  if (_simulcast) {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    // loop though child modules and count idx
    std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
    while (it != _childModules.end()) {
      ModuleRtpRtcpImpl* childModule = *it;
      if (childModule == caller) {
        break;
      }
      streamIdx++;
      it++;
    }
  }
  _rtcpReceiver.OnReceivedIntraFrameRequest(frameType, streamIdx);
}

void ModuleRtpRtcpImpl::OnReceivedEstimatedMaxBitrate(
  const WebRtc_UWord32 maxBitrate) {
  // TODO(mflodman) Split this function in two parts. One for the child module
  // and one for the default module.

  // We received a REMB.
  if (_defaultModule) {
    // Send this update to the REMB instance to take actions.
    _rtcpSender.ReceivedRemb(maxBitrate);
    return;
  }

  WebRtc_UWord32 newBitrate = 0;
  WebRtc_UWord8 fractionLost = 0;
  WebRtc_UWord16 roundTripTime = 0;
  WebRtc_UWord16 bwEstimateKbit = WebRtc_UWord16(maxBitrate / 1000);
  if (_bandwidthManagement.UpdateBandwidthEstimate(bwEstimateKbit,
                                                   &newBitrate,
                                                   &fractionLost,
                                                   &roundTripTime) == 0) {
    _rtpReceiver.UpdateBandwidthManagement(newBitrate,
                                           fractionLost,
                                           roundTripTime);

    // We've received a new bandwidth estimate lower than the current send
    // bitrate. For simulcast we need to update the sending bitrate for all
    // streams.
    if (_simulcast) {
      CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);
      WebRtc_UWord8 idx = 0;
      for (std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
           it != _childModules.end(); ++it) {
        // sanity
        if (idx >= (_sendVideoCodec.numberOfSimulcastStreams - 1)) {
          return;
        }
        ModuleRtpRtcpImpl* module = *it;
        if (newBitrate >= _sendVideoCodec.simulcastStream[idx].maxBitrate) {
          module->_bandwidthManagement.SetSendBitrate(
            _sendVideoCodec.simulcastStream[idx].maxBitrate, 0, 0);
          module->_rtpSender.SetTargetSendBitrate(
            _sendVideoCodec.simulcastStream[idx].maxBitrate);

          newBitrate -= _sendVideoCodec.simulcastStream[idx].maxBitrate;
        } else {
          module->_bandwidthManagement.SetSendBitrate(newBitrate, 0, 0);
          module->_rtpSender.SetTargetSendBitrate(newBitrate);
          newBitrate -= newBitrate;
        }
        idx++;
      }
    }
  }
  // For non-simulcast, update all child modules with the new bandwidth estimate
  // regardless of the new estimate.
  if (!_simulcast) {
    // Update all child modules with the new max bitrate before exiting.
    CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);
    for (std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
         it != _childModules.end(); ++it) {
      // Update all child modules with the maximum bitrate estimate.
      ModuleRtpRtcpImpl* module = *it;
      WebRtc_UWord32 ignoreBitrate = 0;
      WebRtc_UWord8 ignoreFractionLost = 0;
      WebRtc_UWord16 ignoreRoundTripTime = 0;
      module->_bandwidthManagement.UpdateBandwidthEstimate(
        bwEstimateKbit,
        &ignoreBitrate,
        &ignoreFractionLost,
        &ignoreRoundTripTime);
      // We don't need to take care of a possible lowered bitrate, that is
      // handled earlier in this function for the default module.
    }
  }
}

// received a request for a new SLI
void ModuleRtpRtcpImpl::OnReceivedSliceLossIndication(
  const WebRtc_UWord8 pictureID) {

  if (_defaultModule) {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    if (_defaultModule) {
      // if we use a default module pass this info to the default module
      _defaultModule->OnReceivedSliceLossIndication(pictureID);
      return;
    }
  }
  _rtcpReceiver.OnReceivedSliceLossIndication(pictureID);
}

// received a new refereence frame
void ModuleRtpRtcpImpl::OnReceivedReferencePictureSelectionIndication(
  const WebRtc_UWord64 pictureID) {

  if (_defaultModule) {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    if (_defaultModule) {
      // if we use a default module pass this info to the default module
      _defaultModule->OnReceivedReferencePictureSelectionIndication(
        pictureID);
      return;
    }
  }
  _rtcpReceiver.OnReceivedReferencePictureSelectionIndication(pictureID);
}

void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
  const WebRtc_UWord16 bwEstimateKbit) {

  // We received a TMMBR
  const bool defaultInstance(_childModules.empty() ? false : true);
  if (defaultInstance) {
    ProcessDefaultModuleBandwidth();
    return;
  }
  if (_audio) {
    _rtcpReceiver.UpdateBandwidthEstimate(bwEstimateKbit);
  } else {
    WebRtc_UWord32 newBitrate = 0;
    WebRtc_UWord8 fractionLost = 0;
    WebRtc_UWord16 roundTripTime = 0;
    if (_bandwidthManagement.UpdateBandwidthEstimate(bwEstimateKbit,
                                                     &newBitrate,
                                                     &fractionLost,
                                                     &roundTripTime) == 0) {
      if (!_defaultModule) {
        // No default module check if we should trigger OnNetworkChanged
        // via video callback
        _rtpReceiver.UpdateBandwidthManagement(newBitrate,
                                               fractionLost,
                                               roundTripTime);
      }
      if (newBitrate > 0) {
        // update bitrate
        _rtpSender.SetTargetSendBitrate(newBitrate);
      }
    }
  }
  if (_defaultModule) {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    if (_defaultModule) {
      // if we use a default module pass this info to the default module
      _defaultModule->OnReceivedBandwidthEstimateUpdate(bwEstimateKbit);
      return;
    }
  }
}

// bw estimation
// We received a RTCP report block
void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate(
  const WebRtc_UWord8 fractionLost,
  const WebRtc_UWord16 roundTripTime,
  const WebRtc_UWord32 lastReceivedExtendedHighSeqNum) {

  const bool defaultInstance(_childModules.empty() ? false : true);
  if (!defaultInstance) {
    WebRtc_UWord32 newBitrate = 0;
    WebRtc_UWord8 loss = fractionLost;  // local copy since it can change
    WebRtc_UWord32 videoRate = 0;
    WebRtc_UWord32 fecRate = 0;
    WebRtc_UWord32 nackRate = 0;
    BitrateSent(NULL, &videoRate, &fecRate, &nackRate);
    if (_bandwidthManagement.UpdatePacketLoss(
          lastReceivedExtendedHighSeqNum,
          videoRate + fecRate + nackRate,
          roundTripTime,
          &loss,
          &newBitrate,
          _clock.GetTimeInMS()) != 0) {
      // ignore this update
      return;
    }
    // We need to do update RTP sender before calling default module in
    // case we'll strip any layers.
    if (!_simulcast) {
      // the default module will inform all child modules about
      //  their bitrate
      _rtpSender.SetTargetSendBitrate(newBitrate);
    }
    if (_defaultModule) {
      // if we have a default module update it
      CriticalSectionScoped lock(_criticalSectionModulePtrs);
      if (_defaultModule) {  // we need to check again inside the critsect
        // if we use a default module pass this info to the
        // default module
        _defaultModule->OnPacketLossStatisticsUpdate(
          loss,  // send in the filtered loss
          roundTripTime,
          lastReceivedExtendedHighSeqNum);
      }
      return;
    }
    _rtpReceiver.UpdateBandwidthManagement(newBitrate,
                                           fractionLost,
                                           roundTripTime);
  } else {
    if (!_simulcast) {
      ProcessDefaultModuleBandwidth();
    } else {
      // default and simulcast
      WebRtc_UWord32 newBitrate = 0;
      WebRtc_UWord8 loss = fractionLost;  // local copy
      WebRtc_UWord32 videoRate = 0;
      WebRtc_UWord32 fecRate = 0;
      WebRtc_UWord32 nackRate = 0;
      BitrateSent(NULL, &videoRate, &fecRate, &nackRate);
      if (_bandwidthManagement.UpdatePacketLoss(0,  // we can't use this
                                                videoRate + fecRate + nackRate,
                                                roundTripTime,
                                                &loss,
                                                &newBitrate,
                                                _clock.GetTimeInMS()) != 0) {
        // ignore this update
        return;
      }
      _rtpSender.SetTargetSendBitrate(newBitrate);
      _rtpReceiver.UpdateBandwidthManagement(newBitrate,
                                             loss,
                                             roundTripTime);
      // sanity
      if (_sendVideoCodec.codecType == kVideoCodecUnknown) {
        return;
      }
      CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);
      std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
      WebRtc_UWord8 idx = 0;
      while (it != _childModules.end()) {
        // sanity
        if (idx >= (_sendVideoCodec.numberOfSimulcastStreams - 1)) {
          return;
        }
        ModuleRtpRtcpImpl* module = *it;
        // update all child modules
        if (newBitrate >=
            _sendVideoCodec.simulcastStream[idx].maxBitrate) {
          module->_bandwidthManagement.SetSendBitrate(
            _sendVideoCodec.simulcastStream[idx].maxBitrate, 0, 0);
          module->_rtpSender.SetTargetSendBitrate(
            _sendVideoCodec.simulcastStream[idx].maxBitrate);

          newBitrate -=
            _sendVideoCodec.simulcastStream[idx].maxBitrate;
        } else {
          module->_bandwidthManagement.SetSendBitrate(newBitrate,
                                                      0,
                                                      0);
          module->_rtpSender.SetTargetSendBitrate(newBitrate);
          newBitrate -= newBitrate;
        }
        idx++;
      }
    }
  }
}

void ModuleRtpRtcpImpl::ProcessDefaultModuleBandwidth() {

  WebRtc_UWord32 minBitrateBps = 0xffffffff;
  WebRtc_UWord32 maxBitrateBps = 0;
  WebRtc_UWord32 count = 0;
  WebRtc_UWord32 fractionLostAcc = 0;
  WebRtc_UWord16 maxRoundTripTime = 0;
  {
    // get min and max for the sending channels
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    for (std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
         it != _childModules.end(); ++ it) {
      // Get child RTP sender and ask for bitrate estimate.
      ModuleRtpRtcpImpl* childModule = *it;
      if (childModule->Sending()) {
        RTPSender& childRtpSender = (*it)->_rtpSender;
        const WebRtc_UWord32 childEstimateBps =
          1000 * childRtpSender.TargetSendBitrateKbit();
        if (childEstimateBps < minBitrateBps) {
          minBitrateBps = childEstimateBps;
        }
        if (childEstimateBps > maxBitrateBps) {
          maxBitrateBps = childEstimateBps;
        }
        RTCPReceiver& childRtcpReceiver = (*it)->_rtcpReceiver;

        std::vector<RTCPReportBlock> rtcp_blocks;
        childRtcpReceiver.StatisticsReceived(&rtcp_blocks);
        for (std::vector<RTCPReportBlock>::iterator rit = rtcp_blocks.begin();
             rit != rtcp_blocks.end(); ++rit) {
          count++;
          fractionLostAcc += rit->fractionLost;
          WebRtc_UWord16 RTT = 0;
          childRtcpReceiver.RTT(rit->remoteSSRC, &RTT, NULL, NULL, NULL);
          maxRoundTripTime = (RTT > maxRoundTripTime) ? RTT : maxRoundTripTime;
        }
      }
    }
  }  // end critsect

  if (count == 0) {
    // No sending modules and no bitrate estimate.
    return;
  }

  // Update RTT to all receive only child modules, they won't have their own RTT
  // estimate. Assume the receive only channels are on similar links as the
  // sending channel and have approximately the same RTT.
  {
    CriticalSectionScoped lock(_criticalSectionModulePtrs);
    for (std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
        it != _childModules.end(); ++it) {
      if (!(*it)->Sending()) {
        (*it)->_rtcpReceiver.SetRTT(maxRoundTripTime);
      }
    }
  }

  _bandwidthManagement.SetSendBitrate(minBitrateBps, 0, 0);

  // Update default module bitrate. Don't care about min max.
  WebRtc_UWord8 fractionLostAvg = WebRtc_UWord8(fractionLostAcc / count);
  _rtpReceiver.UpdateBandwidthManagement(minBitrateBps,
                                         fractionLostAvg ,
                                         maxRoundTripTime);
}

void ModuleRtpRtcpImpl::OnRequestSendReport() {
  _rtcpSender.SendRTCP(kRtcpSr);
}

WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(
  const WebRtc_UWord64 pictureID) {
  return _rtcpSender.SendRTCP(kRtcpRpsi, 0, 0, false, pictureID);
}

WebRtc_UWord32 ModuleRtpRtcpImpl::SendTimeOfSendReport(
  const WebRtc_UWord32 sendReport) {
  return _rtcpSender.SendTimeOfSendReport(sendReport);
}

void ModuleRtpRtcpImpl::OnReceivedNACK(
  const WebRtc_UWord16 nackSequenceNumbersLength,
  const WebRtc_UWord16* nackSequenceNumbers) {
  if (!_rtpSender.StorePackets() ||
      nackSequenceNumbers == NULL ||
      nackSequenceNumbersLength == 0) {
    return;
  }
  WebRtc_UWord16 avgRTT = 0;
  _rtcpReceiver.RTT(_rtpReceiver.SSRC(), NULL, &avgRTT, NULL, NULL);
  _rtpSender.OnReceivedNACK(nackSequenceNumbersLength,
                            nackSequenceNumbers,
                            avgRTT);
}

WebRtc_Word32 ModuleRtpRtcpImpl::LastReceivedNTP(
  WebRtc_UWord32& RTCPArrivalTimeSecs,  // when we received the last report
  WebRtc_UWord32& RTCPArrivalTimeFrac,
  WebRtc_UWord32& remoteSR) {
  // remote SR: NTP inside the last received (mid 16 bits from sec and frac)
  WebRtc_UWord32 NTPsecs = 0;
  WebRtc_UWord32 NTPfrac = 0;

  if (-1 == _rtcpReceiver.NTP(&NTPsecs,
                              &NTPfrac,
                              &RTCPArrivalTimeSecs,
                              &RTCPArrivalTimeFrac)) {
    return -1;
  }
  remoteSR = ((NTPsecs & 0x0000ffff) << 16) + ((NTPfrac & 0xffff0000) >> 16);
  return 0;
}

void ModuleRtpRtcpImpl::OnReceivedTMMBR() {
  // we received a TMMBR in a RTCP packet
  // answer with a TMMBN
  UpdateTMMBR();
}

bool ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() {
  // if this returns true this channel has timed out
  // periodically check if this is true and if so call UpdateTMMBR
  return _rtcpReceiver.UpdateRTCPReceiveInformationTimers();
}

WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() {
  WebRtc_Word32 numBoundingSet = 0;
  WebRtc_Word32 newBitrates = 0;
  WebRtc_UWord32 minBitrateKbit = 0;
  WebRtc_UWord32 maxBitrateKbit = 0;
  WebRtc_UWord32 accNumCandidates = 0;

  if (!_childModules.empty()) {
    // Default module should not handle this
    return -1;
  }

  WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0, 0, NULL);
  if (size > 0) {
    TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
    // get candidate set from receiver
    accNumCandidates = _rtcpReceiver.TMMBRReceived(size,
                                                   accNumCandidates,
                                                   candidateSet);
  } else {
    // candidate set empty
    VerifyAndAllocateCandidateSet(0);  // resets candidate set
  }
  // Find bounding set
  TMMBRSet* boundingSet = NULL;
  numBoundingSet = FindTMMBRBoundingSet(boundingSet);
  if (numBoundingSet == -1) {
    WEBRTC_TRACE(kTraceWarning,
                 kTraceRtpRtcp,
                 _id,
                 "Failed to find TMMBR bounding set.");
    return -1;
  }
  // Set bounding set
  // Inform remote clients about the new bandwidth
  // inform the remote client
  _rtcpSender.SetTMMBN(boundingSet,
                       _rtpSender.MaxConfiguredBitrateVideo() / 1000);
  // might trigger a TMMBN
  if (numBoundingSet == 0) {
    // owner of max bitrate request has timed out
    // empty bounding set has been sent
    return 0;
  }
  // Get net bitrate from bounding set depending on sent packet rate
  newBitrates = CalcMinMaxBitRate(_rtpSender.PacketRate(),
                                  (WebRtc_UWord32)numBoundingSet,
                                  minBitrateKbit,
                                  maxBitrateKbit);

  // no critsect when calling out to "unknown" code
  if (newBitrates == 0) {
    // we have new bitrate
    // Set new max bitrate
    // we have a new bandwidth estimate on this channel
    OnReceivedBandwidthEstimateUpdate((WebRtc_UWord16)minBitrateKbit);
    WEBRTC_TRACE(kTraceStream,
                 kTraceRtpRtcp,
                 _id,
                 "Set TMMBR request min:%d kbps max:%d kbps, channel: %d",
                 minBitrateKbit, maxBitrateKbit, _id);
  }
  return 0;
}

// called from RTCPsender
WebRtc_Word32 ModuleRtpRtcpImpl::BoundingSet(bool& tmmbrOwner,
                                             TMMBRSet*& boundingSet) {
  return _rtcpReceiver.BoundingSet(tmmbrOwner,
                                   boundingSet);
}

void ModuleRtpRtcpImpl::SendKeyFrame() {
  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "SendKeyFrame()");
  OnReceivedIntraFrameRequest(0);
}

}  // namespace webrtc
