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
This commit is contained in:
parent
3a6080d4c0
commit
0ad51862dc
@ -807,6 +807,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual WebRtc_Word32 SetTMMBRStatus(const bool enable) = 0;
|
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)
|
* (NACK)
|
||||||
*/
|
*/
|
||||||
|
@ -27,16 +27,15 @@ namespace webrtc {
|
|||||||
using namespace RTCPUtility;
|
using namespace RTCPUtility;
|
||||||
using namespace RTCPHelp;
|
using namespace RTCPHelp;
|
||||||
|
|
||||||
RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
|
RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id,
|
||||||
ModuleRtpRtcpImpl* owner)
|
RtpRtcpClock* clock,
|
||||||
: TMMBRHelp(),
|
ModuleRtpRtcpImpl* owner) :
|
||||||
_id(id),
|
_id(id),
|
||||||
_clock(*clock),
|
_clock(*clock),
|
||||||
_method(kRtcpOff),
|
_method(kRtcpOff),
|
||||||
_lastReceived(0),
|
_lastReceived(0),
|
||||||
_rtpRtcp(*owner),
|
_rtpRtcp(*owner),
|
||||||
_criticalSectionFeedbacks(
|
_criticalSectionFeedbacks(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
CriticalSectionWrapper::CreateCriticalSection()),
|
|
||||||
_cbRtcpFeedback(NULL),
|
_cbRtcpFeedback(NULL),
|
||||||
_cbVideoFeedback(NULL),
|
_cbVideoFeedback(NULL),
|
||||||
_criticalSectionRTCPReceiver(
|
_criticalSectionRTCPReceiver(
|
||||||
@ -48,7 +47,8 @@ RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
|
|||||||
_lastReceivedSRNTPfrac(0),
|
_lastReceivedSRNTPfrac(0),
|
||||||
_receivedInfoMap(),
|
_receivedInfoMap(),
|
||||||
_packetTimeOutMS(0),
|
_packetTimeOutMS(0),
|
||||||
_rtt(0) {
|
_rtt(0)
|
||||||
|
{
|
||||||
memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
|
memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
|
||||||
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
|
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
|
||||||
}
|
}
|
||||||
@ -1224,65 +1224,17 @@ RTCPReceiver::OnReceivedSliceLossIndication(const WebRtc_UWord8 pitureID) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTCPReceiver::OnReceivedReferencePictureSelectionIndication(
|
void
|
||||||
const WebRtc_UWord64 pitureID) const {
|
RTCPReceiver::OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pitureID) const
|
||||||
|
{
|
||||||
CriticalSectionScoped lock(_criticalSectionFeedbacks);
|
CriticalSectionScoped lock(_criticalSectionFeedbacks);
|
||||||
|
|
||||||
if (_cbRtcpFeedback) {
|
if(_cbRtcpFeedback)
|
||||||
|
{
|
||||||
_cbRtcpFeedback->OnRPSIReceived(_id, pitureID);
|
_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Holding no Critical section
|
// Holding no Critical section
|
||||||
void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
||||||
RTCPPacketInformation& rtcpPacketInformation)
|
RTCPPacketInformation& rtcpPacketInformation)
|
||||||
@ -1295,7 +1247,7 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
|||||||
"SIG [RTCP] Incoming TMMBR to id:%d", _id);
|
"SIG [RTCP] Incoming TMMBR to id:%d", _id);
|
||||||
|
|
||||||
// Might trigger a OnReceivedBandwidthEstimateUpdate.
|
// Might trigger a OnReceivedBandwidthEstimateUpdate.
|
||||||
UpdateTMMBR();
|
_rtpRtcp.OnReceivedTMMBR();
|
||||||
}
|
}
|
||||||
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb)
|
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb)
|
||||||
{
|
{
|
||||||
@ -1435,6 +1387,18 @@ void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RTCPReceiver::UpdateBandwidthEstimate(const WebRtc_UWord16 bwEstimateKbit)
|
||||||
|
{
|
||||||
|
CriticalSectionScoped lock(_criticalSectionFeedbacks);
|
||||||
|
|
||||||
|
if(_cbRtcpFeedback)
|
||||||
|
{
|
||||||
|
_cbRtcpFeedback->OnTMMBRReceived(_id, bwEstimateKbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
|
WebRtc_Word32 RTCPReceiver::CNAME(const WebRtc_UWord32 remoteSSRC,
|
||||||
char cName[RTCP_CNAME_SIZE]) const {
|
char cName[RTCP_CNAME_SIZE]) const {
|
||||||
if (cName == NULL) {
|
if (cName == NULL) {
|
||||||
|
@ -19,12 +19,11 @@
|
|||||||
#include "rtcp_utility.h"
|
#include "rtcp_utility.h"
|
||||||
#include "rtp_rtcp_defines.h"
|
#include "rtp_rtcp_defines.h"
|
||||||
#include "rtcp_receiver_help.h"
|
#include "rtcp_receiver_help.h"
|
||||||
#include "tmmbr_help.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
class ModuleRtpRtcpImpl;
|
class ModuleRtpRtcpImpl;
|
||||||
|
|
||||||
class RTCPReceiver : public TMMBRHelp
|
class RTCPReceiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
|
RTCPReceiver(const WebRtc_Word32 id, RtpRtcpClock* clock,
|
||||||
@ -98,9 +97,10 @@ public:
|
|||||||
|
|
||||||
bool UpdateRTCPReceiveInformationTimers();
|
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);
|
WebRtc_Word32 SetPacketTimeout(const WebRtc_UWord32 timeoutMS);
|
||||||
void PacketTimeout();
|
void PacketTimeout();
|
||||||
|
@ -68,7 +68,7 @@ RTCPSender::RTCPSender(const WebRtc_Word32 id,
|
|||||||
_rembBitrate(0),
|
_rembBitrate(0),
|
||||||
_bitrate_observer(NULL),
|
_bitrate_observer(NULL),
|
||||||
|
|
||||||
_tmmbrHelp(),
|
_tmmbrHelp(audio),
|
||||||
_tmmbr_Send(0),
|
_tmmbr_Send(0),
|
||||||
_packetOH_Send(0),
|
_packetOH_Send(0),
|
||||||
_remoteRateControl(),
|
_remoteRateControl(),
|
||||||
@ -2165,6 +2165,20 @@ RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
|
|||||||
return -1;
|
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
|
RateControlRegion
|
||||||
RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
|
RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
|
||||||
{
|
{
|
||||||
|
@ -103,6 +103,9 @@ public:
|
|||||||
WebRtc_Word32 SetTMMBN(const TMMBRSet* boundingSet,
|
WebRtc_Word32 SetTMMBN(const TMMBRSet* boundingSet,
|
||||||
const WebRtc_UWord32 maxBitrateKbit);
|
const WebRtc_UWord32 maxBitrateKbit);
|
||||||
|
|
||||||
|
WebRtc_Word32 RequestTMMBR(const WebRtc_UWord32 estimatedBW,
|
||||||
|
const WebRtc_UWord32 packetOH);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extended jitter report
|
* Extended jitter report
|
||||||
*/
|
*/
|
||||||
|
@ -82,6 +82,7 @@ void RtpRtcp::DestroyRtpRtcp(RtpRtcp* module) {
|
|||||||
ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id,
|
ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id,
|
||||||
const bool audio,
|
const bool audio,
|
||||||
RtpRtcpClock* clock):
|
RtpRtcpClock* clock):
|
||||||
|
TMMBRHelp(audio),
|
||||||
_rtpSender(id, audio, clock),
|
_rtpSender(id, audio, clock),
|
||||||
_rtpReceiver(id, audio, clock, this),
|
_rtpReceiver(id, audio, clock, this),
|
||||||
_rtcpSender(id, audio, clock, this),
|
_rtcpSender(id, audio, clock, this),
|
||||||
@ -265,7 +266,7 @@ void ModuleRtpRtcpImpl::RegisterChildModule(RtpRtcp* module) {
|
|||||||
CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
|
CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
|
||||||
// we use two locks for protecting _childModules one
|
// we use two locks for protecting _childModules one
|
||||||
// (_criticalSectionModulePtrsFeedback) for incoming
|
// (_criticalSectionModulePtrsFeedback) for incoming
|
||||||
// messages (BitrateSent) and _criticalSectionModulePtrs
|
// messages (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs
|
||||||
// for all outgoing messages sending packets etc
|
// for all outgoing messages sending packets etc
|
||||||
_childModules.push_back((ModuleRtpRtcpImpl*)module);
|
_childModules.push_back((ModuleRtpRtcpImpl*)module);
|
||||||
}
|
}
|
||||||
@ -414,21 +415,19 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
|
|||||||
// default module or no RTCP received yet.
|
// default module or no RTCP received yet.
|
||||||
max_rtt = kDefaultRtt;
|
max_rtt = kDefaultRtt;
|
||||||
}
|
}
|
||||||
if (_rtcpSender.ValidBitrateEstimate()) {
|
if (REMB() && _rtcpSender.ValidBitrateEstimate()) {
|
||||||
if (REMB()) {
|
unsigned int target_bitrate =
|
||||||
uint32_t target_bitrate =
|
|
||||||
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
|
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
|
||||||
_rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
|
_rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
|
||||||
} else if (TMMBR()) {
|
} else if (TMMBR()) {
|
||||||
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
|
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_rtcpSender.SendRTCP(kRtcpReport);
|
_rtcpSender.SendRTCP(kRtcpReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UpdateRTCPReceiveInformationTimers()) {
|
if (UpdateRTCPReceiveInformationTimers()) {
|
||||||
// a receiver has timed out
|
// a receiver has timed out
|
||||||
_rtcpReceiver.UpdateTMMBR();
|
UpdateTMMBR();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1671,13 +1670,29 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBRStatus(const bool enable) {
|
|||||||
return _rtcpSender.SetTMMBRStatus(enable);
|
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_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetTMMBN()");
|
||||||
|
|
||||||
WebRtc_UWord32 maxBitrateKbit = _rtpSender.MaxConfiguredBitrateVideo() / 1000;
|
|
||||||
return _rtcpSender.SetTMMBN(boundingSet, maxBitrateKbit);
|
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
|
* (NACK) Negative acknowledgement
|
||||||
*/
|
*/
|
||||||
@ -2284,6 +2299,48 @@ void ModuleRtpRtcpImpl::OnReceivedNTP() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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(
|
RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate(
|
||||||
const RateControlInput& rateControlInput) {
|
const RateControlInput& rateControlInput) {
|
||||||
|
|
||||||
@ -2449,15 +2506,16 @@ void ModuleRtpRtcpImpl::OnReceivedReferencePictureSelectionIndication(
|
|||||||
|
|
||||||
void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
|
void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
|
||||||
const WebRtc_UWord16 bwEstimateKbit) {
|
const WebRtc_UWord16 bwEstimateKbit) {
|
||||||
|
|
||||||
// We received a TMMBR
|
// We received a TMMBR
|
||||||
if (_audio) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const bool defaultInstance(_childModules.empty() ? false : true);
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
||||||
if (defaultInstance) {
|
if (defaultInstance) {
|
||||||
ProcessDefaultModuleBandwidth();
|
ProcessDefaultModuleBandwidth();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_audio) {
|
||||||
|
_rtcpReceiver.UpdateBandwidthEstimate(bwEstimateKbit);
|
||||||
|
} else {
|
||||||
WebRtc_UWord32 newBitrate = 0;
|
WebRtc_UWord32 newBitrate = 0;
|
||||||
WebRtc_UWord8 fractionLost = 0;
|
WebRtc_UWord8 fractionLost = 0;
|
||||||
WebRtc_UWord16 roundTripTime = 0;
|
WebRtc_UWord16 roundTripTime = 0;
|
||||||
@ -2477,6 +2535,7 @@ void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
|
|||||||
_rtpSender.SetTargetSendBitrate(newBitrate);
|
_rtpSender.SetTargetSendBitrate(newBitrate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (_defaultModule) {
|
if (_defaultModule) {
|
||||||
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
||||||
if (_defaultModule) {
|
if (_defaultModule) {
|
||||||
@ -2709,16 +2768,88 @@ WebRtc_Word32 ModuleRtpRtcpImpl::LastReceivedNTP(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleRtpRtcpImpl::OnReceivedTMMBR() {
|
||||||
|
// we received a TMMBR in a RTCP packet
|
||||||
|
// answer with a TMMBN
|
||||||
|
UpdateTMMBR();
|
||||||
|
}
|
||||||
|
|
||||||
bool ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() {
|
bool ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() {
|
||||||
// if this returns true this channel has timed out
|
// if this returns true this channel has timed out
|
||||||
// periodically check if this is true and if so call UpdateTMMBR
|
// periodically check if this is true and if so call UpdateTMMBR
|
||||||
return _rtcpReceiver.UpdateRTCPReceiveInformationTimers();
|
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
|
// called from RTCPsender
|
||||||
WebRtc_Word32 ModuleRtpRtcpImpl::BoundingSet(bool& tmmbrOwner,
|
WebRtc_Word32 ModuleRtpRtcpImpl::BoundingSet(bool& tmmbrOwner,
|
||||||
TMMBRSet*& boundingSet) {
|
TMMBRSet*& boundingSet) {
|
||||||
return _rtcpReceiver.BoundingSet(tmmbrOwner, boundingSet);
|
return _rtcpReceiver.BoundingSet(tmmbrOwner,
|
||||||
|
boundingSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleRtpRtcpImpl::SendKeyFrame() {
|
void ModuleRtpRtcpImpl::SendKeyFrame() {
|
||||||
|
@ -26,7 +26,7 @@ class MatlabPlot;
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class ModuleRtpRtcpImpl : public RtpRtcp
|
class ModuleRtpRtcpImpl : public RtpRtcp, private TMMBRHelp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModuleRtpRtcpImpl(const WebRtc_Word32 id,
|
ModuleRtpRtcpImpl(const WebRtc_Word32 id,
|
||||||
@ -341,7 +341,15 @@ public:
|
|||||||
|
|
||||||
virtual WebRtc_Word32 SetTMMBRStatus(const bool enable);
|
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;
|
virtual WebRtc_UWord16 MaxPayloadLength() const;
|
||||||
|
|
||||||
@ -488,6 +496,8 @@ public:
|
|||||||
// good state of RTP receiver inform sender
|
// good state of RTP receiver inform sender
|
||||||
virtual WebRtc_Word32 SendRTCPReferencePictureSelection(const WebRtc_UWord64 pictureID);
|
virtual WebRtc_Word32 SendRTCPReferencePictureSelection(const WebRtc_UWord64 pictureID);
|
||||||
|
|
||||||
|
virtual void OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit);
|
||||||
|
|
||||||
void OnReceivedNTP() ;
|
void OnReceivedNTP() ;
|
||||||
|
|
||||||
// bw estimation
|
// bw estimation
|
||||||
@ -537,6 +547,8 @@ protected:
|
|||||||
// Get remote SequenceNumber
|
// Get remote SequenceNumber
|
||||||
WebRtc_UWord16 RemoteSequenceNumber() const;
|
WebRtc_UWord16 RemoteSequenceNumber() const;
|
||||||
|
|
||||||
|
WebRtc_Word32 UpdateTMMBR();
|
||||||
|
|
||||||
// only for internal testing
|
// only for internal testing
|
||||||
WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime);
|
WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime);
|
||||||
|
|
||||||
|
@ -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
|
* 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
|
* that can be found in the LICENSE file in the root of the source
|
||||||
@ -61,16 +61,19 @@ TMMBRSet::VerifyAndAllocateSet(WebRtc_UWord32 minimumSize)
|
|||||||
lengthOfSet = 0;
|
lengthOfSet = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TMMBRHelp::TMMBRHelp()
|
TMMBRHelp::TMMBRHelp(const bool audio) :
|
||||||
: _criticalSection(CriticalSectionWrapper::CreateCriticalSection()),
|
_criticalSection(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
|
_audio(audio),
|
||||||
_candidateSet(),
|
_candidateSet(),
|
||||||
_boundingSet(),
|
_boundingSet(),
|
||||||
_boundingSetToSend(),
|
_boundingSetToSend(),
|
||||||
_ptrIntersectionBoundingSet(NULL),
|
_ptrIntersectionBoundingSet(NULL),
|
||||||
_ptrMaxPRBoundingSet(NULL) {
|
_ptrMaxPRBoundingSet(NULL)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TMMBRHelp::~TMMBRHelp() {
|
TMMBRHelp::~TMMBRHelp()
|
||||||
|
{
|
||||||
delete [] _ptrIntersectionBoundingSet;
|
delete [] _ptrIntersectionBoundingSet;
|
||||||
delete [] _ptrMaxPRBoundingSet;
|
delete [] _ptrMaxPRBoundingSet;
|
||||||
_ptrIntersectionBoundingSet = 0;
|
_ptrIntersectionBoundingSet = 0;
|
||||||
@ -98,7 +101,9 @@ TMMBRHelp::VerifyAndAllocateBoundingSet(WebRtc_UWord32 minimumSize)
|
|||||||
return &_boundingSet;
|
return &_boundingSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
TMMBRSet* TMMBRHelp::BoundingSet() {
|
TMMBRSet*
|
||||||
|
TMMBRHelp::BoundingSet()
|
||||||
|
{
|
||||||
return &_boundingSet;
|
return &_boundingSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,49 +413,95 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
|
|||||||
return numBoundingSet;
|
return numBoundingSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
|
bool
|
||||||
const WebRtc_UWord32 length) const {
|
TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
|
||||||
|
const WebRtc_UWord32 length) const
|
||||||
|
{
|
||||||
CriticalSectionScoped lock(_criticalSection);
|
CriticalSectionScoped lock(_criticalSection);
|
||||||
|
|
||||||
if (length == 0) {
|
if (length == 0)
|
||||||
|
{
|
||||||
// empty bounding set
|
// empty bounding set
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(WebRtc_UWord32 i = 0; (i < length) && (i < _boundingSet.sizeOfSet); ++i) {
|
|
||||||
if(_boundingSet.ptrSsrcSet[i] == ssrc) {
|
for(WebRtc_UWord32 i = 0; (i < length) && (i < _boundingSet.sizeOfSet); ++i)
|
||||||
|
{
|
||||||
|
if(_boundingSet.ptrSsrcSet[i] == ssrc)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32 TMMBRHelp::CalcMinBitRate(
|
WebRtc_Word32
|
||||||
|
TMMBRHelp::CalcMinMaxBitRate(const WebRtc_UWord32 totalPacketRate,
|
||||||
const WebRtc_UWord32 lengthOfBoundingSet,
|
const WebRtc_UWord32 lengthOfBoundingSet,
|
||||||
WebRtc_UWord32* minBitrateKbit) const {
|
WebRtc_UWord32& minBitrateKbit,
|
||||||
|
WebRtc_UWord32& maxBitrateKbit) const
|
||||||
|
{
|
||||||
CriticalSectionScoped lock(_criticalSection);
|
CriticalSectionScoped lock(_criticalSection);
|
||||||
|
|
||||||
if (lengthOfBoundingSet <= 0 || _candidateSet.sizeOfSet == 0) {
|
if (lengthOfBoundingSet <= 0 || _candidateSet.sizeOfSet == 0)
|
||||||
|
{
|
||||||
// empty bounding set
|
// empty bounding set
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*minBitrateKbit = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; ++i) {
|
minBitrateKbit = 0xFFFFFFFF;
|
||||||
if (_candidateSet.ptrTmmbrSet[i]) {
|
maxBitrateKbit = 0;
|
||||||
WebRtc_Word32 curNetBitRate =
|
|
||||||
static_cast<WebRtc_Word32>(_candidateSet.ptrTmmbrSet[i] * 1000.0);
|
|
||||||
|
|
||||||
if (curNetBitRate < 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
|
// could be negative for a large packet rate
|
||||||
|
if(_audio)
|
||||||
|
{
|
||||||
|
curNetBitRate = MIN_AUDIO_BW_MANAGEMENT_BITRATE;
|
||||||
|
}else
|
||||||
|
{
|
||||||
curNetBitRate = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
|
curNetBitRate = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
|
||||||
}
|
}
|
||||||
*minBitrateKbit = (WebRtc_UWord32(curNetBitRate) < *minBitrateKbit) ?
|
}
|
||||||
curNetBitRate : *minBitrateKbit;
|
minBitrateKbit = (WebRtc_UWord32(curNetBitRate) < minBitrateKbit) ? curNetBitRate : minBitrateKbit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*minBitrateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
|
maxBitrateKbit = minBitrateKbit;
|
||||||
*minBitrateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -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
|
* 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
|
* that can be found in the LICENSE file in the root of the source
|
||||||
@ -38,7 +38,7 @@ public:
|
|||||||
class TMMBRHelp
|
class TMMBRHelp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TMMBRHelp();
|
TMMBRHelp(const bool audio);
|
||||||
virtual ~TMMBRHelp();
|
virtual ~TMMBRHelp();
|
||||||
|
|
||||||
TMMBRSet* BoundingSet(); // used for debuging
|
TMMBRSet* BoundingSet(); // used for debuging
|
||||||
@ -47,14 +47,16 @@ public:
|
|||||||
|
|
||||||
TMMBRSet* VerifyAndAllocateCandidateSet(const WebRtc_UWord32 minimumSize);
|
TMMBRSet* VerifyAndAllocateCandidateSet(const WebRtc_UWord32 minimumSize);
|
||||||
WebRtc_Word32 FindTMMBRBoundingSet(TMMBRSet*& boundingSet);
|
WebRtc_Word32 FindTMMBRBoundingSet(TMMBRSet*& boundingSet);
|
||||||
WebRtc_Word32 SetTMMBRBoundingSetToSend(
|
WebRtc_Word32 SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
|
||||||
const TMMBRSet* boundingSetToSend,
|
|
||||||
const WebRtc_UWord32 maxBitrateKbit);
|
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_Word32 CalcMinMaxBitRate(const WebRtc_UWord32 totalPacketRate,
|
||||||
WebRtc_UWord32* minBitrateKbit) const;
|
const WebRtc_UWord32 lengthOfBoundingSet,
|
||||||
|
WebRtc_UWord32& minBitrateKbit,
|
||||||
|
WebRtc_UWord32& maxBitrateKbit) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TMMBRSet* VerifyAndAllocateBoundingSet(WebRtc_UWord32 minimumSize);
|
TMMBRSet* VerifyAndAllocateBoundingSet(WebRtc_UWord32 minimumSize);
|
||||||
@ -64,6 +66,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
CriticalSectionWrapper* _criticalSection;
|
CriticalSectionWrapper* _criticalSection;
|
||||||
|
const bool _audio;
|
||||||
TMMBRSet _candidateSet;
|
TMMBRSet _candidateSet;
|
||||||
TMMBRSet _boundingSet;
|
TMMBRSet _boundingSet;
|
||||||
TMMBRSet _boundingSetToSend;
|
TMMBRSet _boundingSetToSend;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user