Revert 1961 - Clean up TMMBR handling.
Review URL: https://webrtc-codereview.appspot.com/465001

TBR=pwestin@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/473001

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1967 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/modules/rtp_rtcp/interface/rtp_rtcp.h b/src/modules/rtp_rtcp/interface/rtp_rtcp.h
index db3453e..12fa090 100644
--- a/src/modules/rtp_rtcp/interface/rtp_rtcp.h
+++ b/src/modules/rtp_rtcp/interface/rtp_rtcp.h
@@ -808,6 +808,14 @@
     virtual WebRtc_Word32 SetTMMBRStatus(const bool enable) = 0;
 
     /*
+    *    local bw estimation changed
+    *
+    *    for video called by internal estimator
+    *    for audio (iSAC) called by engine, geting the data from the decoder
+    */
+    virtual void OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit) = 0;
+
+    /*
     *   (NACK)
     */
     virtual NACKMethod NACK() const  = 0;
diff --git a/src/modules/rtp_rtcp/source/rtcp_receiver.cc b/src/modules/rtp_rtcp/source/rtcp_receiver.cc
index d9fdcbf..f4eca71 100644
--- a/src/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/src/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -27,28 +27,28 @@
 using namespace RTCPUtility;
 using namespace RTCPHelp;
 
-RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
-                           ModuleRtpRtcpImpl* owner)
-    : TMMBRHelp(),
-      _id(id),
-      _clock(*clock),
-      _method(kRtcpOff),
-      _lastReceived(0),
-      _rtpRtcp(*owner),
-      _criticalSectionFeedbacks(
-          CriticalSectionWrapper::CreateCriticalSection()),
-      _cbRtcpFeedback(NULL),
-      _cbVideoFeedback(NULL),
-      _criticalSectionRTCPReceiver(
-          CriticalSectionWrapper::CreateCriticalSection()),
-      _SSRC(0),
-      _remoteSSRC(0),
-      _remoteSenderInfo(),
-      _lastReceivedSRNTPsecs(0),
-      _lastReceivedSRNTPfrac(0),
-      _receivedInfoMap(),
-      _packetTimeOutMS(0),
-      _rtt(0) {
+RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id,
+                           RtpRtcpClock* clock,
+                           ModuleRtpRtcpImpl* owner) :
+    _id(id),
+    _clock(*clock),
+    _method(kRtcpOff),
+    _lastReceived(0),
+    _rtpRtcp(*owner),
+    _criticalSectionFeedbacks(CriticalSectionWrapper::CreateCriticalSection()),
+    _cbRtcpFeedback(NULL),
+    _cbVideoFeedback(NULL),
+    _criticalSectionRTCPReceiver(
+        CriticalSectionWrapper::CreateCriticalSection()),
+    _SSRC(0),
+    _remoteSSRC(0),
+    _remoteSenderInfo(),
+    _lastReceivedSRNTPsecs(0),
+    _lastReceivedSRNTPfrac(0),
+    _receivedInfoMap(),
+    _packetTimeOutMS(0),
+    _rtt(0)
+{
     memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
     WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
 }
@@ -1224,63 +1224,15 @@
     }
 }
 
-void RTCPReceiver::OnReceivedReferencePictureSelectionIndication(
-    const WebRtc_UWord64 pitureID) const {
-  CriticalSectionScoped lock(_criticalSectionFeedbacks);
+void
+RTCPReceiver::OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pitureID) const
+{
+    CriticalSectionScoped lock(_criticalSectionFeedbacks);
 
-  if (_cbRtcpFeedback) {
-    _cbRtcpFeedback->OnRPSIReceived(_id, pitureID);
-  }
-}
-
-WebRtc_Word32 RTCPReceiver::UpdateTMMBR() {
-  WebRtc_Word32 numBoundingSet = 0;
-  WebRtc_Word32 newBitrates = 0;
-  WebRtc_UWord32 minBitrateKbit = 0;
-  WebRtc_UWord32 maxBitrateKbit = 0;
-  WebRtc_UWord32 accNumCandidates = 0;
-
-  WebRtc_Word32 size = TMMBRReceived(0, 0, NULL);
-  if (size > 0) {
-    TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
-    // get candidate set from receiver
-    accNumCandidates = 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
-  _rtpRtcp.SetTMMBN(boundingSet);
-
-  // 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 = CalcMinBitRate(static_cast<WebRtc_UWord32>(numBoundingSet),
-                               &minBitrateKbit);
-
-  // no critsect when calling out to "unknown" code
-  if (newBitrates == 0) {
-    // we have a new bandwidth estimate on this channel
-    _rtpRtcp.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;
+    if(_cbRtcpFeedback)
+    {
+        _cbRtcpFeedback->OnRPSIReceived(_id, pitureID);
+    }
 }
 
 // Holding no Critical section
@@ -1295,7 +1247,7 @@
                      "SIG [RTCP] Incoming TMMBR to id:%d", _id);
 
         // Might trigger a OnReceivedBandwidthEstimateUpdate.
-        UpdateTMMBR();
+        _rtpRtcp.OnReceivedTMMBR();
     }
     if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb)
     {
@@ -1435,6 +1387,18 @@
     }
 }
 
+void
+RTCPReceiver::UpdateBandwidthEstimate(const WebRtc_UWord16 bwEstimateKbit)
+{
+    CriticalSectionScoped lock(_criticalSectionFeedbacks);
+
+    if(_cbRtcpFeedback)
+    {
+        _cbRtcpFeedback->OnTMMBRReceived(_id, bwEstimateKbit);
+    }
+
+}
+
 WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
                                   char cName[RTCP_CNAME_SIZE]) const {
   if (cName == NULL) {
diff --git a/src/modules/rtp_rtcp/source/rtcp_receiver.h b/src/modules/rtp_rtcp/source/rtcp_receiver.h
index 1e67b44..eb1b658 100644
--- a/src/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/src/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -19,12 +19,11 @@
 #include "rtcp_utility.h"
 #include "rtp_rtcp_defines.h"
 #include "rtcp_receiver_help.h"
-#include "tmmbr_help.h"
 
 namespace webrtc {
 class ModuleRtpRtcpImpl;
 
-class RTCPReceiver : public TMMBRHelp
+class RTCPReceiver
 {
 public:
     RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
@@ -98,9 +97,10 @@
 
     bool UpdateRTCPReceiveInformationTimers();
 
-    WebRtc_Word32 BoundingSet(bool &tmmbrOwner, TMMBRSet*& boundingSetRec);
+    void UpdateBandwidthEstimate(const WebRtc_UWord16 bwEstimateKbit);
 
-    WebRtc_Word32 UpdateTMMBR();
+    WebRtc_Word32 BoundingSet(bool &tmmbrOwner,
+                              TMMBRSet*& boundingSetRec);
 
     WebRtc_Word32 SetPacketTimeout(const WebRtc_UWord32 timeoutMS);
     void PacketTimeout();
diff --git a/src/modules/rtp_rtcp/source/rtcp_sender.cc b/src/modules/rtp_rtcp/source/rtcp_sender.cc
index 78af109..58e849f 100644
--- a/src/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/src/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -68,7 +68,7 @@
     _rembBitrate(0),
     _bitrate_observer(NULL),
 
-    _tmmbrHelp(),
+    _tmmbrHelp(audio),
     _tmmbr_Send(0),
     _packetOH_Send(0),
     _remoteRateControl(),
@@ -2165,6 +2165,20 @@
     return -1;
 }
 
+WebRtc_Word32
+RTCPSender::RequestTMMBR(WebRtc_UWord32 estimatedBW, WebRtc_UWord32 packetOH)
+{
+    CriticalSectionScoped lock(_criticalSectionRTCPSender);
+    if(_TMMBR)
+    {
+        _tmmbr_Send = estimatedBW;
+        _packetOH_Send = packetOH;
+
+        return 0;
+    }
+    return -1;
+}
+
 RateControlRegion
 RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
 {
diff --git a/src/modules/rtp_rtcp/source/rtcp_sender.h b/src/modules/rtp_rtcp/source/rtcp_sender.h
index 38a264e..966b64f 100644
--- a/src/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/src/modules/rtp_rtcp/source/rtcp_sender.h
@@ -103,6 +103,9 @@
     WebRtc_Word32 SetTMMBN(const TMMBRSet* boundingSet,
                            const WebRtc_UWord32 maxBitrateKbit);
 
+    WebRtc_Word32 RequestTMMBR(const WebRtc_UWord32 estimatedBW,
+                               const WebRtc_UWord32 packetOH);
+
     /*
     *   Extended jitter report
     */
diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 84f3eef..5fb591e 100644
--- a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -82,6 +82,7 @@
 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),
@@ -265,7 +266,7 @@
   CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
   // we use two locks for protecting _childModules one
   // (_criticalSectionModulePtrsFeedback) for incoming
-  // messages (BitrateSent) and _criticalSectionModulePtrs
+  // messages (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs
   //  for all outgoing messages sending packets etc
   _childModules.push_back((ModuleRtpRtcpImpl*)module);
 }
@@ -414,21 +415,19 @@
       // default module or no RTCP received yet.
       max_rtt = kDefaultRtt;
     }
-    if (_rtcpSender.ValidBitrateEstimate()) {
-      if (REMB()) {
-        uint32_t target_bitrate =
-            _rtcpSender.CalculateNewTargetBitrate(max_rtt);
-        _rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
-      } else if (TMMBR()) {
+    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 (UpdateRTCPReceiveInformationTimers()) {
     // a receiver has timed out
-    _rtcpReceiver.UpdateTMMBR();
+    UpdateTMMBR();
   }
   return 0;
 }
@@ -1671,13 +1670,29 @@
   return _rtcpSender.SetTMMBRStatus(enable);
 }
 
-WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBN(const TMMBRSet* boundingSet) {
+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()");
 
-  WebRtc_UWord32 maxBitrateKbit = _rtpSender.MaxConfiguredBitrateVideo() / 1000;
   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
 */
@@ -2284,6 +2299,48 @@
   }
 }
 
+// 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) {
 
@@ -2449,32 +2506,34 @@
 
 void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
   const WebRtc_UWord16 bwEstimateKbit) {
+
   // We received a TMMBR
-  if (_audio) {
-    return;
-  }
   const bool defaultInstance(_childModules.empty() ? false : true);
   if (defaultInstance) {
     ProcessDefaultModuleBandwidth();
     return;
   }
-  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 (_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) {
@@ -2709,16 +2768,88 @@
   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);
+  return _rtcpReceiver.BoundingSet(tmmbrOwner,
+                                   boundingSet);
 }
 
 void ModuleRtpRtcpImpl::SendKeyFrame() {
diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index 0dca764..9236061 100644
--- a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -26,7 +26,7 @@
 
 namespace webrtc {
 
-class ModuleRtpRtcpImpl : public RtpRtcp
+class ModuleRtpRtcpImpl : public RtpRtcp, private TMMBRHelp
 {
 public:
     ModuleRtpRtcpImpl(const WebRtc_Word32 id,
@@ -341,7 +341,15 @@
 
     virtual WebRtc_Word32 SetTMMBRStatus(const bool enable);
 
-    WebRtc_Word32 SetTMMBN(const TMMBRSet* boundingSet);
+    virtual WebRtc_Word32 TMMBRReceived(const WebRtc_UWord32 size,
+                                      const WebRtc_UWord32 accNumCandidates,
+                                      TMMBRSet* candidateSet) const;
+
+    virtual WebRtc_Word32 SetTMMBN(const TMMBRSet* boundingSet,
+                                 const WebRtc_UWord32 maxBitrateKbit);
+
+    virtual WebRtc_Word32 RequestTMMBR(const WebRtc_UWord32 estimatedBW,
+                                     const WebRtc_UWord32 packetOH);
 
     virtual WebRtc_UWord16 MaxPayloadLength() const;
 
@@ -488,6 +496,8 @@
     // good state of RTP receiver inform sender
     virtual WebRtc_Word32 SendRTCPReferencePictureSelection(const WebRtc_UWord64 pictureID);
 
+    virtual void OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit);
+
     void OnReceivedNTP() ;
 
     // bw estimation
@@ -537,6 +547,8 @@
     // Get remote SequenceNumber
     WebRtc_UWord16 RemoteSequenceNumber() const;
 
+    WebRtc_Word32 UpdateTMMBR();
+
     // only for internal testing
     WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime);
 
diff --git a/src/modules/rtp_rtcp/source/tmmbr_help.cc b/src/modules/rtp_rtcp/source/tmmbr_help.cc
index cb7943b..cf34e08 100644
--- a/src/modules/rtp_rtcp/source/tmmbr_help.cc
+++ b/src/modules/rtp_rtcp/source/tmmbr_help.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *  Copyright (c) 2011 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
@@ -61,21 +61,24 @@
     lengthOfSet = 0;
 }
 
-TMMBRHelp::TMMBRHelp()
-    : _criticalSection(CriticalSectionWrapper::CreateCriticalSection()),
-      _candidateSet(),
-      _boundingSet(),
-      _boundingSetToSend(),
-      _ptrIntersectionBoundingSet(NULL),
-      _ptrMaxPRBoundingSet(NULL) {
+TMMBRHelp::TMMBRHelp(const bool audio) :
+    _criticalSection(CriticalSectionWrapper::CreateCriticalSection()),
+    _audio(audio),
+    _candidateSet(),
+    _boundingSet(),
+    _boundingSetToSend(),
+    _ptrIntersectionBoundingSet(NULL),
+    _ptrMaxPRBoundingSet(NULL)
+{
 }
 
-TMMBRHelp::~TMMBRHelp() {
-  delete [] _ptrIntersectionBoundingSet;
-  delete [] _ptrMaxPRBoundingSet;
-  _ptrIntersectionBoundingSet = 0;
-  _ptrMaxPRBoundingSet = 0;
-  delete _criticalSection;
+TMMBRHelp::~TMMBRHelp()
+{
+    delete [] _ptrIntersectionBoundingSet;
+    delete [] _ptrMaxPRBoundingSet;
+    _ptrIntersectionBoundingSet = 0;
+    _ptrMaxPRBoundingSet = 0;
+    delete _criticalSection;
 }
 
 TMMBRSet*
@@ -98,8 +101,10 @@
     return &_boundingSet;
 }
 
-TMMBRSet* TMMBRHelp::BoundingSet() {
-  return &_boundingSet;
+TMMBRSet*
+TMMBRHelp::BoundingSet()
+{
+    return &_boundingSet;
 }
 
 WebRtc_Word32
@@ -408,49 +413,95 @@
     return numBoundingSet;
 }
 
-bool TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
-                        const WebRtc_UWord32 length) const {
-  CriticalSectionScoped lock(_criticalSection);
+bool
+TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
+                   const WebRtc_UWord32 length) const
+{
+    CriticalSectionScoped lock(_criticalSection);
 
-  if (length == 0) {
-    // empty bounding set
-    return false;
-  }
-  for(WebRtc_UWord32 i = 0; (i < length) && (i < _boundingSet.sizeOfSet); ++i) {
-    if(_boundingSet.ptrSsrcSet[i] == ssrc) {
-      return true;
+    if (length == 0)
+    {
+        // empty bounding set
+        return false;
     }
-  }
-  return false;
+
+    for(WebRtc_UWord32 i = 0; (i < length) && (i < _boundingSet.sizeOfSet); ++i)
+    {
+        if(_boundingSet.ptrSsrcSet[i] == ssrc)
+        {
+            return true;
+        }
+    }
+    return false;
 }
 
-WebRtc_Word32 TMMBRHelp::CalcMinBitRate(
-    const WebRtc_UWord32 lengthOfBoundingSet,
-    WebRtc_UWord32* minBitrateKbit) const {
-  CriticalSectionScoped lock(_criticalSection);
+WebRtc_Word32
+TMMBRHelp::CalcMinMaxBitRate(const WebRtc_UWord32 totalPacketRate,
+                             const WebRtc_UWord32 lengthOfBoundingSet,
+                             WebRtc_UWord32& minBitrateKbit,
+                             WebRtc_UWord32& maxBitrateKbit) const
+{
+    CriticalSectionScoped lock(_criticalSection);
 
-  if (lengthOfBoundingSet <= 0 || _candidateSet.sizeOfSet == 0) {
-    // empty bounding set
-    return -1;
-  }
-  *minBitrateKbit = 0xFFFFFFFF;
-
-  for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; ++i) {
-    if (_candidateSet.ptrTmmbrSet[i]) {
-      WebRtc_Word32 curNetBitRate =
-          static_cast<WebRtc_Word32>(_candidateSet.ptrTmmbrSet[i] * 1000.0);
-
-      if (curNetBitRate < 0) {
-        // could be negative for a large packet rate
-        curNetBitRate = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
-      }
-      *minBitrateKbit = (WebRtc_UWord32(curNetBitRate) < *minBitrateKbit) ?
-          curNetBitRate : *minBitrateKbit;
+    if (lengthOfBoundingSet <= 0 || _candidateSet.sizeOfSet == 0)
+    {
+        // empty bounding set
+        return -1;
     }
-  }
-  if (*minBitrateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
-    *minBitrateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
-  }
-  return 0;
+
+    minBitrateKbit = 0xFFFFFFFF;
+    maxBitrateKbit = 0;
+
+    for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; ++i)
+    {
+        if (_candidateSet.ptrTmmbrSet[i])
+        {
+            WebRtc_Word32 curNetBitRate = static_cast<WebRtc_Word32>((_candidateSet.ptrTmmbrSet[i]*1000.0
+                            - (totalPacketRate * (_candidateSet.ptrPacketOHSet[i] << 3)))/1000 + 0.5);
+
+        if (curNetBitRate < 0)
+        {
+            // could be negative for a large packet rate
+            if(_audio)
+            {
+                curNetBitRate = MIN_AUDIO_BW_MANAGEMENT_BITRATE;
+            }else
+            {
+                curNetBitRate = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
+            }
+        }
+            minBitrateKbit = (WebRtc_UWord32(curNetBitRate) < minBitrateKbit) ? curNetBitRate : minBitrateKbit;
+        }
+    }
+    maxBitrateKbit = minBitrateKbit;
+
+    if (maxBitrateKbit == 0 || maxBitrateKbit < minBitrateKbit)
+    {
+        return -1;
+    }
+
+    if(_audio)
+    {
+        if (minBitrateKbit < MIN_AUDIO_BW_MANAGEMENT_BITRATE)
+        {
+            minBitrateKbit = MIN_AUDIO_BW_MANAGEMENT_BITRATE;
+        }
+        if (maxBitrateKbit < MIN_AUDIO_BW_MANAGEMENT_BITRATE)
+        {
+            maxBitrateKbit = MIN_AUDIO_BW_MANAGEMENT_BITRATE;
+        }
+    }else
+    {
+        if (minBitrateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE)
+        {
+            minBitrateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
+        }
+        if (maxBitrateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE)
+        {
+            maxBitrateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
+        }
+    }
+
+    return 0;
 }
 } // namespace webrtc
diff --git a/src/modules/rtp_rtcp/source/tmmbr_help.h b/src/modules/rtp_rtcp/source/tmmbr_help.h
index b0fb69f..35704fe 100644
--- a/src/modules/rtp_rtcp/source/tmmbr_help.h
+++ b/src/modules/rtp_rtcp/source/tmmbr_help.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *  Copyright (c) 2011 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
@@ -38,7 +38,7 @@
 class TMMBRHelp
 {
 public:
-    TMMBRHelp();
+    TMMBRHelp(const bool audio);
     virtual ~TMMBRHelp();
 
     TMMBRSet* BoundingSet(); // used for debuging
@@ -47,14 +47,16 @@
 
     TMMBRSet* VerifyAndAllocateCandidateSet(const WebRtc_UWord32 minimumSize);
     WebRtc_Word32 FindTMMBRBoundingSet(TMMBRSet*& boundingSet);
-    WebRtc_Word32 SetTMMBRBoundingSetToSend(
-        const TMMBRSet* boundingSetToSend,
-        const WebRtc_UWord32 maxBitrateKbit);
+    WebRtc_Word32 SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
+                                          const WebRtc_UWord32 maxBitrateKbit);
 
-    bool IsOwner(const WebRtc_UWord32 ssrc, const WebRtc_UWord32 length) const;
+    bool        IsOwner(const WebRtc_UWord32 ssrc,
+                        const WebRtc_UWord32 length) const;
 
-    WebRtc_Word32 CalcMinBitRate(const WebRtc_UWord32 lengthOfBoundingSet,
-                                 WebRtc_UWord32* minBitrateKbit) const;
+    WebRtc_Word32 CalcMinMaxBitRate(const WebRtc_UWord32 totalPacketRate,
+                                  const WebRtc_UWord32 lengthOfBoundingSet,
+                                  WebRtc_UWord32& minBitrateKbit,
+                                  WebRtc_UWord32& maxBitrateKbit) const;
 
 protected:
     TMMBRSet*   VerifyAndAllocateBoundingSet(WebRtc_UWord32 minimumSize);
@@ -64,6 +66,7 @@
 
 private:
     CriticalSectionWrapper* _criticalSection;
+    const bool              _audio;
     TMMBRSet                _candidateSet;
     TMMBRSet                _boundingSet;
     TMMBRSet                _boundingSetToSend;