Added support for new RTCP message REMB (remote estimated max bitrate)

Review URL: http://webrtc-codereview.appspot.com/149001

git-svn-id: http://webrtc.googlecode.com/svn/trunk@628 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pwestin@webrtc.org 2011-09-20 13:52:04 +00:00
parent 679e64d1fc
commit 741da942ec
19 changed files with 696 additions and 315 deletions

View File

@ -749,6 +749,16 @@ public:
*/
virtual WebRtc_Word32 SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) = 0;
/*
* (REMB) Receiver Estimated Max Bitrate
*/
virtual bool REMB() const = 0;;
virtual WebRtc_Word32 SetREMBStatus(const bool enable) = 0;
virtual WebRtc_Word32 SetREMBData(const WebRtc_UWord32 bitrate,
const WebRtc_UWord8 numberOfSSRC,
const WebRtc_UWord32* SSRC) = 0;
/*
* (TMMBR) Temporary Max Media Bit Rate
*/

View File

@ -55,12 +55,12 @@ enum RTCPPacketType
kRtcpFir = 0x0040,
kRtcpTmmbr = 0x0080,
kRtcpTmmbn = 0x0100,
kRtcpSrReq = 0x0200,
kRtcpXrVoipMetric = 0x0400,
kRtcpSrReq = 0x0200,
kRtcpXrVoipMetric = 0x0400,
kRtcpApp = 0x0800,
kRtcpAppBwe = 0x0801,
kRtcpSli = 0x4000,
kRtcpRpsi = 0x8000
kRtcpRpsi = 0x8000,
kRtcpRemb = 0x10000
};
enum KeyFrameRequestMethod
@ -104,9 +104,10 @@ struct RTCPReportBlock
class RtpData
{
public:
virtual WebRtc_Word32 OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
const WebRtcRTPHeader* rtpHeader) = 0;
virtual WebRtc_Word32 OnReceivedPayloadData(
const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
const WebRtcRTPHeader* rtpHeader) = 0;
protected:
virtual ~RtpData() {}
};
@ -124,9 +125,10 @@ public:
const WebRtc_UWord16 /*length*/,
const WebRtc_UWord8* /*data*/) {};
virtual void OnXRVoIPMetricReceived(const WebRtc_Word32 /*id*/,
const RTCPVoIPMetric* /*metric*/,
const WebRtc_Word8 /*VoIPmetricBuffer*/[28]) {};
virtual void OnXRVoIPMetricReceived(
const WebRtc_Word32 /*id*/,
const RTCPVoIPMetric* /*metric*/,
const WebRtc_Word8 /*VoIPmetricBuffer*/[28]) {};
virtual void OnRTCPPacketTimeout(const WebRtc_Word32 /*id*/) {};
@ -139,6 +141,10 @@ public:
virtual void OnRPSIReceived(const WebRtc_Word32 /*id*/,
const WebRtc_UWord64 /*pictureId*/) {};
virtual void OnReceiverEstimatedMaxBitrateReceived(
const WebRtc_Word32 /*id*/,
const WebRtc_UWord32 /*bitRate*/) {};
virtual void OnSendReportReceived(const WebRtc_Word32 id,
const WebRtc_UWord32 senderSSRC) {};
@ -156,12 +162,13 @@ public:
/*
* channels - number of channels in codec (1 = mono, 2 = stereo)
*/
virtual WebRtc_Word32 OnInitializeDecoder(const WebRtc_Word32 id,
const WebRtc_Word8 payloadType,
const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE],
const int frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate) = 0;
virtual WebRtc_Word32 OnInitializeDecoder(
const WebRtc_Word32 id,
const WebRtc_Word8 payloadType,
const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE],
const int frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate) = 0;
virtual void OnPacketTimeout(const WebRtc_Word32 id) = 0;
@ -203,8 +210,9 @@ class RtpVideoFeedback
{
public:
// this function should call codec module to inform it about the request
virtual void OnReceivedIntraFrameRequest(const WebRtc_Word32 id,
const WebRtc_UWord8 message = 0) = 0;
virtual void OnReceivedIntraFrameRequest(
const WebRtc_Word32 id,
const WebRtc_UWord8 message = 0) = 0;
virtual void OnNetworkChanged(const WebRtc_Word32 id,
const WebRtc_UWord32 minBitrateBps,

View File

@ -0,0 +1,117 @@
/*
* 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
* 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 <gtest/gtest.h>
#include "typedefs.h"
#include "common_types.h"
#include "rtp_utility.h"
#include "rtcp_sender.h"
#include "rtcp_receiver.h"
#include "rtp_rtcp_impl.h"
#include "bwe_defines.h"
namespace {
using namespace webrtc;
class TestTransport : public Transport {
public:
TestTransport(RTCPReceiver* rtcp_receiver) :
rtcp_receiver_(rtcp_receiver) {
}
virtual int SendPacket(int /*channel*/, const void* /*data*/, int /*len*/) {
return -1;
}
virtual int SendRTCPPacket(int /*channel*/,
const void *packet,
int packetLength) {
RTCPUtility::RTCPParserV2 rtcpParser((WebRtc_UWord8*)packet,
(WebRtc_Word32)packetLength,
true); // Allow non-compound RTCP
EXPECT_EQ(true, rtcpParser.IsValid());
RTCPHelp::RTCPPacketInformation rtcpPacketInformation;
EXPECT_EQ(0, rtcp_receiver_->IncomingRTCPPacket(rtcpPacketInformation,
&rtcpParser));
EXPECT_EQ((WebRtc_UWord32)kRtcpRemb,
rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb);
EXPECT_EQ((WebRtc_UWord32)1234,
rtcpPacketInformation.receiverEstimatedMaxBitrate);
return packetLength;
}
private:
RTCPReceiver* rtcp_receiver_;
};
class RtcpFormatRembTest : public ::testing::Test {
protected:
RtcpFormatRembTest() {};
virtual void SetUp();
virtual void TearDown();
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
RTCPSender* rtcp_sender_;
RTCPReceiver* rtcp_receiver_;
TestTransport* test_transport_;
};
void RtcpFormatRembTest::SetUp() {
dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(0, false);
rtcp_sender_ = new RTCPSender(0, false, dummy_rtp_rtcp_impl_);
rtcp_receiver_ = new RTCPReceiver(0, dummy_rtp_rtcp_impl_);
test_transport_ = new TestTransport(rtcp_receiver_);
EXPECT_EQ(0, rtcp_sender_->Init());
EXPECT_EQ(0, rtcp_sender_->RegisterSendTransport(test_transport_));
}
void RtcpFormatRembTest::TearDown() {
delete rtcp_sender_;
delete rtcp_receiver_;
delete dummy_rtp_rtcp_impl_;
delete test_transport_;
}
TEST_F(RtcpFormatRembTest, TestBasicAPI) {
EXPECT_EQ(false, rtcp_sender_->REMB());
EXPECT_EQ(0, rtcp_sender_->SetREMBStatus(true));
EXPECT_EQ(true, rtcp_sender_->REMB());
EXPECT_EQ(0, rtcp_sender_->SetREMBStatus(false));
EXPECT_EQ(false, rtcp_sender_->REMB());
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 0, NULL));
}
TEST_F(RtcpFormatRembTest, TestNonCompund) {
WebRtc_UWord32 SSRC = 456789;
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpNonCompound));
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 1, &SSRC));
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb));
}
TEST_F(RtcpFormatRembTest, TestCompund) {
WebRtc_UWord32 SSRCs[2] = {456789, 98765};
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 2, SSRCs));
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb));
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
} // namespace

View File

@ -9,13 +9,14 @@
*/
#include "rtcp_receiver.h"
#include "rtcp_utility.h"
#include <string.h> //memset
#include <cassert> //assert
#include "trace.h"
#include "critical_section_wrapper.h"
#include "rtcp_utility.h"
#include "rtp_rtcp_impl.h"
namespace
{
@ -26,11 +27,11 @@ namespace webrtc {
using namespace RTCPUtility;
using namespace RTCPHelp;
RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, ModuleRtpRtcpPrivate& callback) :
RTCPReceiver::RTCPReceiver(const WebRtc_Word32 id, ModuleRtpRtcpImpl* owner) :
_id(id),
_method(kRtcpOff),
_lastReceived(0),
_cbRtcpPrivate(callback),
_rtpRtcp(*owner),
_criticalSectionFeedbacks(*CriticalSectionWrapper::CreateCriticalSection()),
_cbRtcpFeedback(NULL),
_cbVideoFeedback(NULL),
@ -354,6 +355,9 @@ RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
case RTCPUtility::kRtcpPsfbFirCode:
HandleFIR(*rtcpParser, rtcpPacketInformation);
break;
case RTCPUtility::kRtcpPsfbAppCode:
HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
break;
case RTCPUtility::kRtcpAppCode:
// generic application messages
HandleAPP(*rtcpParser, rtcpPacketInformation);
@ -477,7 +481,8 @@ RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
_criticalSectionRTCPReceiver.Leave();
// to avoid problem with accuireing _criticalSectionRTCPSender while holding _criticalSectionRTCPReceiver
WebRtc_UWord32 sendTimeMS = _cbRtcpPrivate.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
WebRtc_UWord32 sendTimeMS =
_rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
_criticalSectionRTCPReceiver.Enter();
@ -1129,6 +1134,30 @@ RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
}
}
// no need for critsect we have _criticalSectionRTCPReceiver
void
RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPPacketInformation& rtcpPacketInformation)
{
RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
if (pktType == RTCPUtility::kRtcpPsfbRembItemCode)
{
HandleREMBItem(rtcpParser, rtcpPacketInformation);
}
}
void
RTCPReceiver::HandleREMBItem(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPPacketInformation& rtcpPacketInformation)
{
rtcpParser.Iterate();
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
rtcpPacketInformation.receiverEstimatedMaxBitrate = rtcpPacket.REMB.BitRate;
// TODO send up SSRCs and do a sanity check
}
// no need for critsect we have _criticalSectionRTCPReceiver
void
RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
@ -1248,26 +1277,27 @@ RTCPReceiver::TriggerCallbacksFromRTCPPacket(RTCPPacketInformation& rtcpPacketIn
{
if(rtcpPacketInformation.reportBlock)
{
_cbRtcpPrivate.OnPacketLossStatisticsUpdate(rtcpPacketInformation.fractionLost,
rtcpPacketInformation.roundTripTime,
rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
rtcpPacketInformation.jitter);
_rtpRtcp.OnPacketLossStatisticsUpdate(
rtcpPacketInformation.fractionLost,
rtcpPacketInformation.roundTripTime,
rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
rtcpPacketInformation.jitter);
}
}
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr)
{
_cbRtcpPrivate.OnReceivedNTP();
_rtpRtcp.OnReceivedNTP();
}
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq)
{
_cbRtcpPrivate.OnRequestSendReport();
_rtpRtcp.OnRequestSendReport();
}
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack)
{
if (rtcpPacketInformation.nackSequenceNumbersLength > 0)
{
WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id, "SIG [RTCP] Incoming NACK to id:%d", _id);
_cbRtcpPrivate.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbersLength,
_rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbersLength,
rtcpPacketInformation.nackSequenceNumbers);
}
}
@ -1276,7 +1306,7 @@ RTCPReceiver::TriggerCallbacksFromRTCPPacket(RTCPPacketInformation& rtcpPacketIn
WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id, "SIG [RTCP] Incoming TMMBR to id:%d", _id);
// might trigger a OnReceivedBandwidthEstimateUpdate
_cbRtcpPrivate.OnReceivedTMMBR();
_rtpRtcp.OnReceivedTMMBR();
}
if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir))
@ -1289,17 +1319,18 @@ RTCPReceiver::TriggerCallbacksFromRTCPPacket(RTCPPacketInformation& rtcpPacketIn
WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id, "SIG [RTCP] Incoming FIR to id:%d", _id);
}
// we need use a bounce it up to handle default channel
_cbRtcpPrivate.OnReceivedIntraFrameRequest(0);
_rtpRtcp.OnReceivedIntraFrameRequest(0);
}
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli)
{
// we need use a bounce it up to handle default channel
_cbRtcpPrivate.OnReceivedSliceLossIndication(rtcpPacketInformation.sliPictureId);
_rtpRtcp.OnReceivedSliceLossIndication(rtcpPacketInformation.sliPictureId);
}
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi)
{
// we need use a bounce it up to handle default channel
_cbRtcpPrivate.OnReceivedReferencePictureSelectionIndication(rtcpPacketInformation.rpsiPictureId);
_rtpRtcp.OnReceivedReferencePictureSelectionIndication(
rtcpPacketInformation.rpsiPictureId);
}
{
CriticalSectionScoped lock(_criticalSectionFeedbacks);
@ -1317,6 +1348,11 @@ RTCPReceiver::TriggerCallbacksFromRTCPPacket(RTCPPacketInformation& rtcpPacketIn
{
_cbRtcpFeedback->OnReceiveReportReceived(_id, rtcpPacketInformation.remoteSSRC);
}
if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb)
{
_cbRtcpFeedback->OnReceiverEstimatedMaxBitrateReceived(_id,
rtcpPacketInformation.receiverEstimatedMaxBitrate);
}
if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric)
{
WebRtc_Word8 VoIPmetricBuffer[7*4];

View File

@ -16,14 +16,15 @@
#include "rtp_utility.h"
#include "rtcp_utility.h"
#include "rtp_rtcp_defines.h"
#include "rtp_rtcp_private.h"
#include "rtcp_receiver_help.h"
namespace webrtc {
class ModuleRtpRtcpImpl;
class RTCPReceiver
{
public:
RTCPReceiver(const WebRtc_Word32 id, ModuleRtpRtcpPrivate& callback);
RTCPReceiver(const WebRtc_Word32 id, ModuleRtpRtcpImpl* owner);
virtual ~RTCPReceiver();
void ChangeUniqueId(const WebRtc_Word32 id);
@ -50,20 +51,20 @@ public:
// get received cname
WebRtc_Word32 CNAME(const WebRtc_UWord32 remoteSSRC,
WebRtc_Word8 cName[RTCP_CNAME_SIZE]) const;
WebRtc_Word8 cName[RTCP_CNAME_SIZE]) const;
// get received NTP
WebRtc_Word32 NTP(WebRtc_UWord32 *ReceivedNTPsecs,
WebRtc_UWord32 *ReceivedNTPfrac,
WebRtc_UWord32 *RTCPArrivalTimeSecs,
WebRtc_UWord32 *RTCPArrivalTimeFrac) const;
WebRtc_UWord32 *ReceivedNTPfrac,
WebRtc_UWord32 *RTCPArrivalTimeSecs,
WebRtc_UWord32 *RTCPArrivalTimeFrac) const;
// get rtt
WebRtc_Word32 RTT(const WebRtc_UWord32 remoteSSRC,
WebRtc_UWord16* RTT,
WebRtc_UWord16* avgRTT,
WebRtc_UWord16* minRTT,
WebRtc_UWord16* maxRTT) const;
WebRtc_UWord16* RTT,
WebRtc_UWord16* avgRTT,
WebRtc_UWord16* minRTT,
WebRtc_UWord16* maxRTT) const;
WebRtc_Word32 ResetRTT(const WebRtc_UWord32 remoteSSRC);
@ -140,6 +141,12 @@ protected:
void HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
void HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
void HandleREMBItem(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
void HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
@ -170,18 +177,18 @@ protected:
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
private:
WebRtc_Word32 _id;
RTCPMethod _method;
WebRtc_UWord32 _lastReceived;
ModuleRtpRtcpPrivate& _cbRtcpPrivate;
WebRtc_Word32 _id;
RTCPMethod _method;
WebRtc_UWord32 _lastReceived;
ModuleRtpRtcpImpl& _rtpRtcp;
CriticalSectionWrapper& _criticalSectionFeedbacks;
RtcpFeedback* _cbRtcpFeedback;
RtpVideoFeedback* _cbVideoFeedback;
CriticalSectionWrapper& _criticalSectionFeedbacks;
RtcpFeedback* _cbRtcpFeedback;
RtpVideoFeedback* _cbVideoFeedback;
CriticalSectionWrapper& _criticalSectionRTCPReceiver;
WebRtc_UWord32 _SSRC;
WebRtc_UWord32 _remoteSSRC;
CriticalSectionWrapper& _criticalSectionRTCPReceiver;
WebRtc_UWord32 _SSRC;
WebRtc_UWord32 _remoteSSRC;
// Received send report
RTCPSenderInfo _remoteSenderInfo;

View File

@ -51,7 +51,7 @@ public:
WebRtc_UWord8* applicationData;
WebRtc_UWord16 applicationLength;
bool reportBlock;
bool reportBlock;
WebRtc_UWord8 fractionLost;
WebRtc_UWord16 roundTripTime;
WebRtc_UWord32 lastReceivedExtendedHighSeqNum;
@ -59,6 +59,7 @@ public:
WebRtc_UWord8 sliPictureId;
WebRtc_UWord64 rpsiPictureId;
WebRtc_UWord32 receiverEstimatedMaxBitrate;
RTCPVoIPMetric* VoIPMetric;
};

View File

@ -20,14 +20,16 @@
#include "common_types.h"
#include "critical_section_wrapper.h"
#include "rtp_rtcp_impl.h"
namespace webrtc {
RTCPSender::RTCPSender(const WebRtc_Word32 id,
const bool audio,
ModuleRtpRtcpPrivate& callback) :
ModuleRtpRtcpImpl* owner) :
_id(id),
_audio(audio),
_method(kRtcpOff),
_cbRtcpPrivate(callback),
_rtpRtcp(*owner),
_criticalSectionTransport(*CriticalSectionWrapper::CreateCriticalSection()),
_cbTransport(NULL),
@ -35,6 +37,8 @@ RTCPSender::RTCPSender(const WebRtc_Word32 id,
_usingNack(false),
_sending(false),
_sendTMMBN(false),
_REMB(false),
_sendREMB(false),
_TMMBR(false),
_nextTimeToSendRTCP(0),
_SSRC(0),
@ -55,6 +59,11 @@ RTCPSender::RTCPSender(const WebRtc_Word32 id,
_sequenceNumberFIR(0),
_lastTimeFIR(0),
_lengthRembSSRC(0),
_sizeRembSSRC(0),
_rembSSRC(NULL),
_rembBitrate(0),
_tmmbrHelp(audio),
_tmmbr_Send(0),
_packetOH_Send(0),
@ -77,10 +86,8 @@ RTCPSender::RTCPSender(const WebRtc_Word32 id,
RTCPSender::~RTCPSender()
{
if(_appData)
{
delete [] _appData;
}
delete [] _rembSSRC;
delete [] _appData;
MapItem* item = _reportBlocks.First();
while(item)
@ -121,6 +128,8 @@ RTCPSender::Init()
_sending = false;
_sendTMMBN = false;
_TMMBR = false;
_REMB = false;
_sendREMB = false;
_SSRC = 0;
_remoteSSRC = 0;
_cameraDelayMS = 0;
@ -219,6 +228,44 @@ RTCPSender::SetSendingStatus(const bool sending)
return 0;
}
bool
RTCPSender::REMB() const
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
return _REMB;
}
WebRtc_Word32
RTCPSender::SetREMBStatus(const bool enable)
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
_REMB = enable;
return 0;
}
WebRtc_Word32
RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
const WebRtc_UWord8 numberOfSSRC,
const WebRtc_UWord32* SSRC)
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
_rembBitrate = bitrate;
if(_sizeRembSSRC < numberOfSSRC)
{
delete [] _rembSSRC;
_rembSSRC = new WebRtc_UWord32[numberOfSSRC];
_sizeRembSSRC = numberOfSSRC;
}
_lengthRembSSRC = numberOfSSRC;
for (int i = 0; i < numberOfSSRC; i++)
{
_rembSSRC[i] = SSRC[i];
}
return 0;
}
bool
RTCPSender::TMMBR() const
{
@ -585,7 +632,7 @@ RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
WebRtc_UWord32 freqHz = 90000; // For video
if(_audio)
{
freqHz = _cbRtcpPrivate.CurrentSendFrequencyHz();
freqHz = _rtpRtcp.CurrentSendFrequencyHz();
RTPtime = ModuleRTPUtility::CurrentRTP(freqHz);
}
else // video
@ -615,11 +662,11 @@ RTCPSender::BuildSR(WebRtc_UWord8* rtcpbuffer,
pos += 4;
//sender's packet count
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _cbRtcpPrivate.PacketCountSent());
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.PacketCountSent());
pos += 4;
//sender's octet count
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _cbRtcpPrivate.ByteCountSent());
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rtpRtcp.ByteCountSent());
pos += 4;
WebRtc_UWord8 numberOfReportBlocks = 0;
@ -1000,23 +1047,81 @@ RTCPSender::BuildRPSI(WebRtc_UWord8* rtcpbuffer,
}
WebRtc_Word32
RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, WebRtc_UWord32 RTT)
RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
{
// sanity
if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
{
return -2;
}
// add application layer feedback
WebRtc_UWord8 FMT = 15;
rtcpbuffer[pos++]=(WebRtc_UWord8)0x80 + FMT;
rtcpbuffer[pos++]=(WebRtc_UWord8)206;
rtcpbuffer[pos++]=(WebRtc_UWord8)0;
rtcpbuffer[pos++]=_lengthRembSSRC + 4;
// Add our own SSRC
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _SSRC);
pos += 4;
// Remote SSRC must be 0
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, 0);
pos += 4;
rtcpbuffer[pos++]='R';
rtcpbuffer[pos++]='E';
rtcpbuffer[pos++]='M';
rtcpbuffer[pos++]='B';
rtcpbuffer[pos++] = _lengthRembSSRC;
// 6 bit Exp
// 18 bit mantissa
WebRtc_UWord8 brExp = 0;
for(WebRtc_UWord32 i=0; i<64; i++)
{
if(_rembBitrate <= ((WebRtc_UWord32)262143 << i))
{
brExp = i;
break;
}
}
const WebRtc_UWord32 brMantissa = (_rembBitrate >> brExp);
rtcpbuffer[pos++]=(WebRtc_UWord8)((brExp << 2) + ((brMantissa >> 16) & 0x03));
rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa >> 8);
rtcpbuffer[pos++]=(WebRtc_UWord8)(brMantissa);
for (int i = 0; i < _lengthRembSSRC; i++)
{
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _rembSSRC[i]);
pos += 4;
}
return 0;
}
WebRtc_UWord32
RTCPSender::CalculateNewTargetBitrate(WebRtc_UWord32 RTT)
{
WebRtc_UWord32 target_bitrate = _remoteRateControl.TargetBitRate(RTT);
_tmmbr_Send = target_bitrate / 1000;
return target_bitrate;
}
WebRtc_Word32
RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
{
// Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
// If the sender is an owner of the TMMBN -> send TMMBR
// If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
// About to send TMMBR, first run remote rate control
// to get a target bit rate.
_tmmbr_Send = _remoteRateControl.TargetBitRate(RTT) / 1000;
// get current bounding set from RTCP receiver
bool tmmbrOwner = false;
TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet(); // store in candidateSet, allocates one extra slot
// holding _criticalSectionRTCPSender while calling RTCPreceiver which will accuire _criticalSectionRTCPReceiver
// is a potental deadlock but since RTCPreceiver is not doing the revese we should be fine
WebRtc_Word32 lengthOfBoundingSet = _cbRtcpPrivate.BoundingSet(tmmbrOwner, candidateSet);
WebRtc_Word32 lengthOfBoundingSet = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
if(lengthOfBoundingSet > 0)
{
@ -1479,10 +1584,10 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
rtcpPacketTypeFlags & kRtcpRr)
{
// get statistics from our RTPreceiver outside critsect
if(_cbRtcpPrivate.ReportBlockStatistics(&received.fractionLost,
&received.cumulativeLost,
&received.extendedHighSeqNum,
&received.jitter) == 0)
if(_rtpRtcp.ReportBlockStatistics(&received.fractionLost,
&received.cumulativeLost,
&received.extendedHighSeqNum,
&received.jitter) == 0)
{
hasReceived = true;
@ -1491,7 +1596,9 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
WebRtc_UWord32 remoteSR = 0;
// ok even if we have not received a SR, we will send 0 in that case
_cbRtcpPrivate.LastReceivedNTP(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac, remoteSR);
_rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
lastReceivedRRNTPfrac,
remoteSR);
// get our NTP as late as possible to avoid a race
ModuleRTPUtility::CurrentNTP(NTPsec, NTPfrac);
@ -1531,6 +1638,11 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
rtcpPacketTypeFlags |= kRtcpApp;
_appSend = false;
}
if(_REMB && _sendREMB)
{
rtcpPacketTypeFlags |= kRtcpRemb;
_sendREMB = false;
}
if(_xrSendVoIPMetric)
{
rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
@ -1581,7 +1693,7 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
if(_sending)
{
// calc bw for video 360/sendBW in kbit/s
WebRtc_Word32 sendBitrateKbit = _cbRtcpPrivate.BitrateSent()/1000;
WebRtc_Word32 sendBitrateKbit = _rtpRtcp.BitrateSent()/1000;
if(sendBitrateKbit != 0)
{
minIntervalMs = 360000/sendBitrateKbit;
@ -1691,7 +1803,7 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
}
if(rtcpPacketTypeFlags & kRtcpRpsi)
{
const WebRtc_Word8 payloadType = _cbRtcpPrivate.SendPayloadType();
const WebRtc_Word8 payloadType = _rtpRtcp.SendPayloadType();
if(payloadType == -1)
{
return -1;
@ -1706,6 +1818,18 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
break; // out of buffer
}
}
if(rtcpPacketTypeFlags & kRtcpRemb)
{
buildVal = BuildREMB(rtcpbuffer, pos);
if(buildVal == -1)
{
return -1; // error
}else if(buildVal == -2)
{
break; // out of buffer
}
}
if(rtcpPacketTypeFlags & kRtcpBye)
{
buildVal = BuildBYE(rtcpbuffer, pos);
@ -1732,7 +1856,7 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
}
if(rtcpPacketTypeFlags & kRtcpTmmbr)
{
buildVal = BuildTMMBR(rtcpbuffer, pos, RTT);
buildVal = BuildTMMBR(rtcpbuffer, pos);
if(buildVal == -1)
{
return -1; // error

View File

@ -15,14 +15,17 @@
#include "rtp_utility.h"
#include "map_wrapper.h"
#include "rtp_rtcp_defines.h"
#include "rtp_rtcp_private.h"
#include "remote_rate_control.h"
#include "tmmbr_help.h"
namespace webrtc {
class ModuleRtpRtcpImpl;
class RTCPSender
{
public:
RTCPSender(const WebRtc_Word32 id, const bool audio, ModuleRtpRtcpPrivate& callback);
RTCPSender(const WebRtc_Word32 id, const bool audio, ModuleRtpRtcpImpl* owner);
virtual ~RTCPSender();
void ChangeUniqueId(const WebRtc_Word32 id);
@ -60,16 +63,26 @@ public:
WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime);
WebRtc_Word32 SendRTCP(const WebRtc_UWord32 rtcpPacketTypeFlags,
const WebRtc_Word32 nackSize = 0,
const WebRtc_UWord16* nackList = 0,
const WebRtc_UWord32 RTT = 0,
const WebRtc_UWord64 pictureID = 0);
const WebRtc_Word32 nackSize = 0,
const WebRtc_UWord16* nackList = 0,
const WebRtc_UWord32 RTT = 0,
const WebRtc_UWord64 pictureID = 0);
WebRtc_Word32 AddReportBlock(const WebRtc_UWord32 SSRC,
const RTCPReportBlock* receiveBlock);
WebRtc_Word32 RemoveReportBlock(const WebRtc_UWord32 SSRC);
/*
* REMB
*/
bool REMB() const;
WebRtc_Word32 SetREMBStatus(const bool enable);
WebRtc_Word32 SetREMBData(const WebRtc_UWord32 bitrate,
const WebRtc_UWord8 numberOfSSRC,
const WebRtc_UWord32* SSRC);
/*
* TMMBR
*/
@ -78,24 +91,24 @@ public:
WebRtc_Word32 SetTMMBRStatus(const bool enable);
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);
const WebRtc_UWord32 packetOH);
/*
*
*/
WebRtc_Word32 SetApplicationSpecificData(const WebRtc_UWord8 subType,
const WebRtc_UWord32 name,
const WebRtc_UWord8* data,
const WebRtc_UWord16 length);
const WebRtc_UWord32 name,
const WebRtc_UWord8* data,
const WebRtc_UWord16 length);
WebRtc_Word32 SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric);
WebRtc_Word32 SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
const WebRtc_UWord8 arrLength);
const WebRtc_UWord8 arrLength);
WebRtc_Word32 SetCSRCStatus(const bool include);
@ -105,6 +118,8 @@ public:
RateControlRegion UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse);
WebRtc_UWord32 CalculateNewTargetBitrate(WebRtc_UWord32 RTT);
private:
WebRtc_Word32 SendToNetwork(const WebRtc_UWord8* dataBuffer,
const WebRtc_UWord16 length);
@ -132,7 +147,8 @@ private:
WebRtc_Word32 BuildSDEC(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
WebRtc_Word32 BuildPLI(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
WebRtc_Word32 BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos, WebRtc_UWord32 RTT);
WebRtc_Word32 BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
WebRtc_Word32 BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
WebRtc_Word32 BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
WebRtc_Word32 BuildAPP(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
WebRtc_Word32 BuildVoIPMetric(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos);
@ -154,19 +170,21 @@ private:
const WebRtc_UWord16* nackList);
private:
WebRtc_Word32 _id;
const bool _audio;
RTCPMethod _method;
WebRtc_Word32 _id;
const bool _audio;
RTCPMethod _method;
ModuleRtpRtcpPrivate& _cbRtcpPrivate;
ModuleRtpRtcpImpl& _rtpRtcp;
CriticalSectionWrapper& _criticalSectionTransport;
Transport* _cbTransport;
CriticalSectionWrapper& _criticalSectionTransport;
Transport* _cbTransport;
CriticalSectionWrapper& _criticalSectionRTCPSender;
CriticalSectionWrapper& _criticalSectionRTCPSender;
bool _usingNack;
bool _sending;
bool _sendTMMBN;
bool _REMB;
bool _sendREMB;
bool _TMMBR;
WebRtc_UWord32 _nextTimeToSendRTCP;
@ -193,7 +211,12 @@ private:
WebRtc_UWord8 _sequenceNumberFIR;
WebRtc_UWord32 _lastTimeFIR;
// TMMBR
// REMB
WebRtc_UWord8 _lengthRembSSRC;
WebRtc_UWord8 _sizeRembSSRC;
WebRtc_UWord32* _rembSSRC;
WebRtc_UWord32 _rembBitrate;
TMMBRHelp _tmmbrHelp;
WebRtc_UWord32 _tmmbr_Send;
WebRtc_UWord32 _packetOH_Send;

View File

@ -118,6 +118,12 @@ RTCPUtility::RTCPParserV2::Iterate()
case State_PSFB_FIRItem:
IterateFIRItem();
break;
case State_PSFB_AppItem:
IteratePsfbAppItem();
break;
case State_PSFB_REMBItem:
IteratePsfbREMBItem();
break;
case State_AppItem:
IterateAppItem();
break;
@ -320,6 +326,26 @@ RTCPUtility::RTCPParserV2::IterateFIRItem()
}
}
void
RTCPUtility::RTCPParserV2::IteratePsfbAppItem()
{
const bool success = ParsePsfbAppItem();
if (!success)
{
Iterate();
}
}
void
RTCPUtility::RTCPParserV2::IteratePsfbREMBItem()
{
const bool success = ParsePsfbREMBItem();
if (!success)
{
Iterate();
}
}
void
RTCPUtility::RTCPParserV2::IterateAppItem()
{
@ -340,8 +366,8 @@ RTCPUtility::RTCPParserV2::Validate()
RTCPCommonHeader header;
const bool success = RTCPParseCommonHeader(_ptrRTCPDataBegin,
_ptrRTCPDataEnd,
header);
_ptrRTCPDataEnd,
header);
if (!success)
{
@ -1010,6 +1036,11 @@ RTCPUtility::RTCPParserV2::ParseFBCommon(const RTCPCommonHeader& header)
_state = State_PSFB_FIRItem;
return true;
case 15:
_packetType = kRtcpPsfbAppCode;
_state = State_PSFB_AppItem;
return true;
default:
break;
}
@ -1094,6 +1125,78 @@ RTCPUtility::RTCPParserV2::ParseNACKItem()
return true;
}
bool
RTCPUtility::RTCPParserV2::ParsePsfbAppItem()
{
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 4)
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
if(*_ptrRTCPData++ != 'R')
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
if(*_ptrRTCPData++ != 'E')
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
if(*_ptrRTCPData++ != 'M')
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
if(*_ptrRTCPData++ != 'B')
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
_packetType = kRtcpPsfbRembItemCode;
_state = State_PSFB_REMBItem;
return true;
}
bool
RTCPUtility::RTCPParserV2::ParsePsfbREMBItem()
{
const ptrdiff_t length = _ptrRTCPBlockEnd - _ptrRTCPData;
if (length < 4)
{
_state = State_TopLevel;
EndCurrentBlock();
return false;
}
const WebRtc_UWord8 numSSRC = *_ptrRTCPData++;
const WebRtc_UWord8 brExp = (_ptrRTCPData[0] >> 2) & 0x3F;
WebRtc_UWord32 brMantissa = (_ptrRTCPData[0] & 0x03) << 16;
brMantissa += (_ptrRTCPData[1] << 8);
brMantissa += (_ptrRTCPData[2]);
_ptrRTCPData += 3; // Fwd read data
_packet.REMB.BitRate = (brMantissa << brExp);
_ptrRTCPData += 4 * numSSRC; // Ignore the SSRCs for now
return true;
}
bool
RTCPUtility::RTCPParserV2::ParseTMMBRItem()
{

View File

@ -177,11 +177,14 @@ namespace RTCPUtility {
// RFC4585
WebRtc_UWord32 SenderSSRC;
WebRtc_UWord32 MediaSSRC;
WebRtc_UWord8 PayloadType;
WebRtc_UWord16 NumberOfValidBits;
WebRtc_UWord8 PayloadType;
WebRtc_UWord16 NumberOfValidBits;
WebRtc_UWord8 NativeBitString[RTCP_RPSI_DATA_SIZE];
};
struct RTCPPacketPSFBREMB
{
WebRtc_UWord32 BitRate;
};
// generic name APP
struct RTCPPacketAPP
{
@ -207,6 +210,7 @@ namespace RTCPUtility {
RTCPPacketPSFBSLI SLI;
RTCPPacketPSFBSLIItem SLIItem;
RTCPPacketPSFBRPSI RPSI;
RTCPPacketPSFBREMB REMB;
RTCPPacketRTPFBTMMBR TMMBR;
RTCPPacketRTPFBTMMBRItem TMMBRItem;
@ -242,6 +246,8 @@ namespace RTCPUtility {
kRtcpPsfbRpsiCode,
kRtcpPsfbSliCode,
kRtcpPsfbSliItemCode,
kRtcpPsfbAppCode,
kRtcpPsfbRembItemCode,
// RFC5104
kRtcpRtpfbTmmbrCode,
@ -329,6 +335,8 @@ namespace RTCPUtility {
State_PSFB_SLIItem, // SLI FCI item
State_PSFB_RPSIItem, // RPSI FCI item
State_PSFB_FIRItem, // FIR FCI item
State_PSFB_AppItem, // Application specific FCI item
State_PSFB_REMBItem, // Application specific REMB item
State_XRItem,
State_AppItem
};
@ -344,6 +352,8 @@ namespace RTCPUtility {
void IterateSLIItem();
void IterateRPSIItem();
void IterateFIRItem();
void IteratePsfbAppItem();
void IteratePsfbREMBItem();
void IterateAppItem();
void Validate();
@ -371,6 +381,8 @@ namespace RTCPUtility {
bool ParseSLIItem();
bool ParseRPSIItem();
bool ParseFIRItem();
bool ParsePsfbAppItem();
bool ParsePsfbREMBItem();
bool ParseAPP(const RTCPCommonHeader& header);
bool ParseAPPItem();

View File

@ -12,6 +12,7 @@
#include "rtp_receiver.h"
#include "rtp_rtcp_defines.h"
#include "rtp_rtcp_impl.h"
#include "critical_section_wrapper.h"
#include <cassert>
@ -22,13 +23,13 @@
namespace webrtc {
RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
const bool audio,
ModuleRtpRtcpPrivate& callback) :
ModuleRtpRtcpImpl* owner) :
RTPReceiverAudio(id),
RTPReceiverVideo(id, callback),
RTPReceiverVideo(id, owner),
_id(id),
_audio(audio),
_rtpRtcp(*owner),
_criticalSectionCbs(*CriticalSectionWrapper::CreateCriticalSection()),
_cbPrivateFeedback(callback),
_cbRtpFeedback(NULL),
_cbRtpData(NULL),
@ -956,7 +957,7 @@ RTPReceiver::RetransmitOfOldPacket(const WebRtc_UWord16 sequenceNumber,
WebRtc_Word32 rtpTimeStampDiffMS = ((WebRtc_Word32)(rtpTimeStamp - _lastReceivedTimestamp))/90; // diff in time stamp since last received in order
WebRtc_UWord16 minRTT = 0;
_cbPrivateFeedback.RTT(_SSRC,NULL,NULL,&minRTT, NULL);
_rtpRtcp.RTT(_SSRC,NULL,NULL,&minRTT, NULL);
if(minRTT == 0)
{
// no update
@ -1154,7 +1155,7 @@ RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader)
{
// we need to get this to our RTCP sender and receiver
// need to do this outside critical section
_cbPrivateFeedback.SetRemoteSSRC(rtpHeader->header.ssrc);
_rtpRtcp.SetRemoteSSRC(rtpHeader->header.ssrc);
}
CriticalSectionScoped lock(_criticalSectionCbs);

View File

@ -22,6 +22,7 @@
namespace webrtc {
class RtpRtcpFeedback;
class ModuleRtpRtcpImpl;
class Trace;
class RTPReceiver : public RTPReceiverAudio, public RTPReceiverVideo, public Bitrate
@ -29,7 +30,7 @@ class RTPReceiver : public RTPReceiverAudio, public RTPReceiverVideo, public Bit
public:
RTPReceiver(const WebRtc_Word32 id,
const bool audio,
ModuleRtpRtcpPrivate& callback);
ModuleRtpRtcpImpl* owner);
virtual ~RTPReceiver();
@ -104,22 +105,22 @@ public:
WebRtc_Word32 SetSSRCFilter(const bool enable, const WebRtc_UWord32 allowedSSRC);
WebRtc_Word32 Statistics(WebRtc_UWord8 *fraction_lost,
WebRtc_UWord32 *cum_lost,
WebRtc_UWord32 *ext_max,
WebRtc_UWord32 *jitter, // will be moved from JB
WebRtc_UWord32 *max_jitter,
bool reset = false) const;
WebRtc_UWord32 *cum_lost,
WebRtc_UWord32 *ext_max,
WebRtc_UWord32 *jitter, // will be moved from JB
WebRtc_UWord32 *max_jitter,
bool reset = false) const;
WebRtc_Word32 Statistics(WebRtc_UWord8 *fraction_lost,
WebRtc_UWord32 *cum_lost,
WebRtc_UWord32 *ext_max,
WebRtc_UWord32 *jitter, // will be moved from JB
WebRtc_UWord32 *max_jitter,
WebRtc_Word32 *missing,
bool reset = false) const;
WebRtc_UWord32 *cum_lost,
WebRtc_UWord32 *ext_max,
WebRtc_UWord32 *jitter, // will be moved from JB
WebRtc_UWord32 *max_jitter,
WebRtc_Word32 *missing,
bool reset = false) const;
WebRtc_Word32 DataCounters(WebRtc_UWord32 *bytesReceived,
WebRtc_UWord32 *packetsReceived) const;
WebRtc_UWord32 *packetsReceived) const;
WebRtc_Word32 ResetStatistics();
@ -132,12 +133,12 @@ public:
WebRtc_UWord32 ByteCountReceived() const;
virtual WebRtc_UWord32 PayloadTypeToPayload(const WebRtc_UWord8 payloadType,
ModuleRTPUtility::Payload*& payload) const;
ModuleRTPUtility::Payload*& payload) const;
protected:
virtual WebRtc_Word32 CallbackOfReceivedPayloadData(const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
const WebRtcRTPHeader* rtpHeader);
const WebRtc_UWord16 payloadSize,
const WebRtcRTPHeader* rtpHeader);
virtual bool RetransmitOfOldPacket(const WebRtc_UWord16 sequenceNumber,
const WebRtc_UWord32 rtpTimeStamp) const;
@ -158,20 +159,20 @@ private:
void CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader);
void CheckCSRC(const WebRtcRTPHeader* rtpHeader);
WebRtc_Word32 CheckPayloadChanged(const WebRtcRTPHeader* rtpHeader,
const WebRtc_Word8 firstPayloadByte,
bool& isRED,
ModuleRTPUtility::AudioPayload& audioSpecific,
ModuleRTPUtility::VideoPayload& videoSpecific);
const WebRtc_Word8 firstPayloadByte,
bool& isRED,
ModuleRTPUtility::AudioPayload& audioSpecific,
ModuleRTPUtility::VideoPayload& videoSpecific);
void UpdateNACKBitRate(WebRtc_Word32 bytes, WebRtc_UWord32 now);
bool ProcessNACKBitRate(WebRtc_UWord32 now);
private:
WebRtc_Word32 _id;
WebRtc_Word32 _id;
const bool _audio;
ModuleRtpRtcpImpl& _rtpRtcp;
CriticalSectionWrapper& _criticalSectionCbs;
ModuleRtpRtcpPrivate& _cbPrivateFeedback;
RtpFeedback* _cbRtpFeedback;
RtpData* _cbRtpData;

View File

@ -8,16 +8,16 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtp_receiver_video.h"
#include <cassert> //assert
#include <cstring> // memcpy()
#include <math.h>
#include "rtp_receiver_video.h"
#include "critical_section_wrapper.h"
#include "tick_util.h"
#include "receiver_fec.h"
#include "rtp_rtcp_impl.h"
namespace webrtc {
WebRtc_UWord32 BitRateBPS(WebRtc_UWord16 x )
@ -26,11 +26,11 @@ WebRtc_UWord32 BitRateBPS(WebRtc_UWord16 x )
}
RTPReceiverVideo::RTPReceiverVideo(const WebRtc_Word32 id,
ModuleRtpRtcpPrivate& callback):
ModuleRtpRtcpImpl* owner):
_id(id),
_rtpRtcp(*owner),
_criticalSectionFeedback(*CriticalSectionWrapper::CreateCriticalSection()),
_cbVideoFeedback(NULL),
_cbPrivateFeedback(callback),
_criticalSectionReceiverVideo(*CriticalSectionWrapper::CreateCriticalSection()),
_completeFrame(false),
@ -304,7 +304,7 @@ RTPReceiverVideo::ParseVideoCodecSpecific(WebRtcRTPHeader* rtpHeader,
_criticalSectionReceiverVideo.Leave();
// Call the callback outside critical section
const RateControlRegion region = _cbPrivateFeedback.OnOverUseStateUpdate(input);
const RateControlRegion region = _rtpRtcp.OnOverUseStateUpdate(input);
_criticalSectionReceiverVideo.Enter();
_overUseDetector.SetRateControlRegion(region);

View File

@ -12,7 +12,6 @@
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_VIDEO_H_
#include "rtp_rtcp_defines.h"
#include "rtp_rtcp_private.h"
#include "rtp_utility.h"
#include "typedefs.h"
@ -25,12 +24,13 @@
namespace webrtc {
class ReceiverFEC;
class ModuleRtpRtcpImpl;
class RTPReceiverVideo
{
public:
RTPReceiverVideo(const WebRtc_Word32 id,
ModuleRtpRtcpPrivate& callback);
ModuleRtpRtcpImpl* owner);
virtual ~RTPReceiverVideo();
@ -123,11 +123,10 @@ protected:
private:
WebRtc_Word32 _id;
ModuleRtpRtcpImpl& _rtpRtcp;
CriticalSectionWrapper& _criticalSectionFeedback;
RtpVideoFeedback* _cbVideoFeedback;
ModuleRtpRtcpPrivate& _cbPrivateFeedback;
CriticalSectionWrapper& _criticalSectionFeedback;
RtpVideoFeedback* _cbVideoFeedback;
CriticalSectionWrapper& _criticalSectionReceiverVideo;

View File

@ -33,7 +33,6 @@
'rtp_rtcp_config.h',
'rtp_rtcp_impl.cc',
'rtp_rtcp_impl.h',
'rtp_rtcp_private.h',
'rtcp_receiver.cc',
'rtcp_receiver.h',
'rtcp_receiver_help.cc',

View File

@ -61,7 +61,9 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id,
const bool audio):
TMMBRHelp(audio),
_rtpSender(id, audio),
_rtpReceiver(id, audio, *this),
_rtpReceiver(id, audio, this),
_rtcpSender(id, audio, this),
_rtcpReceiver(id, this),
_id(id),
_audio(audio),
_collisionDetected(false),
@ -77,13 +79,11 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id,
_deadOrAliveActive(false),
_deadOrAliveTimeoutMS(0),
_deadOrAliveLastTimer(0),
_rtcpReceiver(id,*this),
_bandwidthManagement(id),
_receivedNTPsecsAudio(0),
_receivedNTPfracAudio(0),
_RTCPArrivalTimeSecsAudio(0),
_RTCPArrivalTimeFracAudio(0),
_rtcpSender(id, audio, *this),
_nackMethod(kNackOff),
_nackLastTimeSent(0),
_nackLastSeqNumberSent(0),
@ -212,7 +212,7 @@ ModuleRtpRtcpImpl::RegisterDefaultModule(RtpRtcp* module)
{
_defaultModule->DeRegisterChildModule(this);
}
_defaultModule = (ModuleRtpRtcpPrivate*)module;
_defaultModule = (ModuleRtpRtcpImpl*)module;
_defaultModule->RegisterChildModule(this);
return 0;
}
@ -310,7 +310,7 @@ ModuleRtpRtcpImpl::RegisterSyncModule(RtpRtcp* audioModule)
return -1;
}
CriticalSectionScoped lock(_criticalSectionModulePtrs);
_audioModule = (ModuleRtpRtcpPrivate*)audioModule;
_audioModule = (ModuleRtpRtcpImpl*)audioModule;
return _audioModule->RegisterVideoModule(this);
}
@ -322,7 +322,7 @@ ModuleRtpRtcpImpl::DeRegisterSyncModule()
CriticalSectionScoped lock(_criticalSectionModulePtrs);
if(_audioModule)
{
ModuleRtpRtcpPrivate* audioModule=_audioModule;
ModuleRtpRtcpImpl* audioModule=_audioModule;
_audioModule = NULL;
_receivedNTPsecsAudio = 0;
_receivedNTPfracAudio = 0;
@ -347,7 +347,7 @@ ModuleRtpRtcpImpl::RegisterVideoModule(RtpRtcp* videoModule)
return -1;
}
CriticalSectionScoped lock(_criticalSectionModulePtrs);
_videoModule = (ModuleRtpRtcpPrivate*)videoModule;
_videoModule = (ModuleRtpRtcpImpl*)videoModule;
return 0;
}
@ -359,7 +359,7 @@ ModuleRtpRtcpImpl::DeRegisterVideoModule()
CriticalSectionScoped lock(_criticalSectionModulePtrs);
if(_videoModule)
{
ModuleRtpRtcpPrivate* videoModule=_videoModule;
ModuleRtpRtcpImpl* videoModule=_videoModule;
_videoModule=NULL;
videoModule->DeRegisterSyncModule();
}
@ -1517,6 +1517,39 @@ ModuleRtpRtcpImpl::RemoveRTCPReportBlock(const WebRtc_UWord32 SSRC)
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);
}
/*
* (TMMBR) Temporary Max Media Bit Rate
*/
@ -1538,7 +1571,6 @@ ModuleRtpRtcpImpl::SetTMMBRStatus(const bool enable)
{
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetTMMBRStatus(disable)");
}
return _rtcpSender.SetTMMBRStatus(enable);
}
@ -1642,7 +1674,7 @@ ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList,
{
waitTime = 100; //During startup we don't have an RTT
}
const WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS();
const WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS();
const WebRtc_UWord32 timeLimit = now - waitTime;
if(_nackLastTimeSent < timeLimit)
@ -2023,9 +2055,6 @@ ModuleRtpRtcpImpl::SetFECUepProtection(const bool keyUseUepProtection,
}
}
/*
* Implementation of ModuleRtpRtcpPrivate
*/
void
ModuleRtpRtcpImpl::SetRemoteSSRC(const WebRtc_UWord32 SSRC)
{
@ -2204,7 +2233,10 @@ ModuleRtpRtcpImpl::OnOverUseStateUpdate(const RateControlInput& rateControlInput
// Send TMMBR immediately
WebRtc_UWord16 RTT = 0;
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL,NULL,NULL);
_rtcpSender.SendRTCP(kRtcpTmmbr, 0, 0, RTT);
// About to send TMMBR, first run remote rate control
// to get a target bit rate.
_rtcpSender.CalculateNewTargetBitrate(RTT);
_rtcpSender.SendRTCP(kRtcpTmmbr);
}
return region;
}
@ -2370,10 +2402,12 @@ ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate(const WebRtc_UWord8 fractionLost
while(item)
{
// Get child RTP sender and ask for bitrate estimate
ModuleRtpRtcpPrivate* childModule = (ModuleRtpRtcpPrivate*)item->GetItem();
ModuleRtpRtcpImpl* childModule =
static_cast<ModuleRtpRtcpImpl*>(item->GetItem());
if (childModule->Sending())
{
RTPSender& childRtpSender = static_cast<ModuleRtpRtcpImpl*>(item->GetItem())->_rtpSender;
RTPSender& childRtpSender =
static_cast<ModuleRtpRtcpImpl*>(item->GetItem())->_rtpSender;
WebRtc_UWord32 childEstimateBps = 1000*childRtpSender.TargetSendBitrateKbit();
if (childEstimateBps < minBitrateBps)
{
@ -2504,7 +2538,7 @@ ModuleRtpRtcpImpl::UpdateTMMBR()
ListItem* item = _childModules.First();
while(item)
{
ModuleRtpRtcpPrivate* module = (ModuleRtpRtcpPrivate*)item->GetItem();
ModuleRtpRtcpImpl* module = (ModuleRtpRtcpImpl*)item->GetItem();
WebRtc_Word32 tmpSize = module->TMMBRReceived(0,0, NULL);
if(tmpSize > 0)
{
@ -2521,7 +2555,7 @@ ModuleRtpRtcpImpl::UpdateTMMBR()
item = _childModules.First();
while(item)
{
ModuleRtpRtcpPrivate* module = (ModuleRtpRtcpPrivate*)item->GetItem();
ModuleRtpRtcpImpl* module = (ModuleRtpRtcpImpl*)item->GetItem();
if(size > accNumCandidates && module)
{
WebRtc_Word32 accSize = module->TMMBRReceived(size, accNumCandidates, candidateSet);
@ -2571,7 +2605,7 @@ ModuleRtpRtcpImpl::UpdateTMMBR()
ListItem* item = _childModules.First();
while(item)
{
ModuleRtpRtcpPrivate* module = (ModuleRtpRtcpPrivate*)item->GetItem();
ModuleRtpRtcpImpl* module = (ModuleRtpRtcpImpl*)item->GetItem();
if( module)
{
module->SetTMMBN(boundingSet, _rtpSender.MaxConfiguredBitrateVideo()/1000);

View File

@ -12,7 +12,6 @@
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_IMPL_H_
#include "rtp_rtcp.h"
#include "rtp_rtcp_private.h"
#include "rtp_sender.h"
#include "rtp_receiver.h"
@ -28,7 +27,7 @@ class MatlabPlot;
namespace webrtc {
class ModuleRtpRtcpImpl : public ModuleRtpRtcpPrivate, private TMMBRHelp
class ModuleRtpRtcpImpl : public RtpRtcp, private TMMBRHelp
{
public:
ModuleRtpRtcpImpl(const WebRtc_Word32 id,
@ -317,6 +316,16 @@ public:
virtual WebRtc_Word32 RemoveRTCPReportBlock(const WebRtc_UWord32 SSRC);
/*
* (REMB) Receiver Estimated Max Bitrate
*/
virtual bool REMB() const;
virtual WebRtc_Word32 SetREMBStatus(const bool enable);
virtual WebRtc_Word32 SetREMBData(const WebRtc_UWord32 bitrate,
const WebRtc_UWord8 numberOfSSRC,
const WebRtc_UWord32* SSRC);
/*
* (TMMBR) Temporary Max Media Bit Rate
*/
@ -453,22 +462,20 @@ public:
virtual WebRtc_Word32 SetH263InverseLogic(const bool enable);
// only for internal testing
WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime);
virtual WebRtc_Word32 LastReceivedNTP(WebRtc_UWord32& NTPsecs,
WebRtc_UWord32& NTPfrac,
WebRtc_UWord32& remoteSR);
protected:
virtual void RegisterChildModule(RtpRtcp* module);
virtual WebRtc_Word32 BoundingSet(bool &tmmbrOwner,
TMMBRSet*& boundingSetRec);
virtual void DeRegisterChildModule(RtpRtcp* module);
virtual WebRtc_UWord32 BitrateSent() const;
bool UpdateRTCPReceiveInformationTimers();
void ProcessDeadOrAliveTimer();
/*
* Implementation of ModuleRtpRtcpPrivate
*/
virtual void SetRemoteSSRC(const WebRtc_UWord32 SSRC);
virtual WebRtc_UWord32 SendTimeOfSendReport(const WebRtc_UWord32 sendReport);
virtual RateControlRegion OnOverUseStateUpdate(const RateControlInput& rateControlInput);
virtual void OnReceivedNTP() ;
@ -478,7 +485,6 @@ protected:
const WebRtc_UWord32 lastReceivedExtendedHighSeqNum,
const WebRtc_UWord32 jitter);
// bw estimation
virtual void OnReceivedTMMBR();
virtual void OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit);
@ -486,8 +492,6 @@ protected:
virtual void OnReceivedBandwidthEstimateUpdate(const WebRtc_UWord16 bwEstimateMinKbit,
const WebRtc_UWord16 bwEstimateMaxKbit);
virtual RateControlRegion OnOverUseStateUpdate(const RateControlInput& rateControlInput);
// bad state of RTP receiver request a keyframe
virtual void OnRequestIntraFrame(const FrameType frameType);
@ -506,14 +510,17 @@ protected:
const WebRtc_UWord16* nackSequenceNumbers);
virtual void OnRequestSendReport();
// only for internal testing
WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime);
virtual WebRtc_UWord32 SendTimeOfSendReport(const WebRtc_UWord32 sendReport);
protected:
virtual void RegisterChildModule(RtpRtcp* module);
virtual WebRtc_Word32 LastReceivedNTP(WebRtc_UWord32& NTPsecs, // when we received the last report
WebRtc_UWord32& NTPfrac,
WebRtc_UWord32& remoteSR); // NTP inside the last received (mid 16 bits from sec and frac)
virtual void DeRegisterChildModule(RtpRtcp* module);
virtual WebRtc_UWord32 BitrateSent() const;
bool UpdateRTCPReceiveInformationTimers();
void ProcessDeadOrAliveTimer();
virtual WebRtc_UWord32 BitrateReceivedNow() const;
@ -522,35 +529,33 @@ protected:
virtual WebRtc_Word32 UpdateTMMBR();
virtual WebRtc_Word32 BoundingSet(bool &tmmbrOwner,
TMMBRSet*& boundingSetRec);
RTPSender _rtpSender;
RTPReceiver _rtpReceiver;
RTCPSender _rtcpSender;
RTCPReceiver _rtcpReceiver;
private:
void SendKeyFrame();
WebRtc_Word32 _id;
WebRtc_Word32 _id;
const bool _audio;
bool _collisionDetected;
WebRtc_UWord32 _lastProcessTime;
WebRtc_UWord16 _packetOverHead;
WebRtc_UWord32 _lastProcessTime;
WebRtc_UWord16 _packetOverHead;
CriticalSectionWrapper& _criticalSectionModulePtrs;
CriticalSectionWrapper& _criticalSectionModulePtrsFeedback;
ModuleRtpRtcpPrivate* _defaultModule;
ModuleRtpRtcpPrivate* _audioModule;
ModuleRtpRtcpPrivate* _videoModule;
ListWrapper _childModules;
CriticalSectionWrapper& _criticalSectionModulePtrs;
CriticalSectionWrapper& _criticalSectionModulePtrsFeedback;
ModuleRtpRtcpImpl* _defaultModule;
ModuleRtpRtcpImpl* _audioModule;
ModuleRtpRtcpImpl* _videoModule;
ListWrapper _childModules;
// Dead or alive
bool _deadOrAliveActive;
WebRtc_UWord32 _deadOrAliveTimeoutMS;
WebRtc_UWord32 _deadOrAliveLastTimer;
WebRtc_UWord32 _deadOrAliveTimeoutMS;
WebRtc_UWord32 _deadOrAliveLastTimer;
// receive side
RTCPReceiver _rtcpReceiver;
BandwidthManagement _bandwidthManagement;
WebRtc_UWord32 _receivedNTPsecsAudio;
@ -559,7 +564,6 @@ private:
WebRtc_UWord32 _RTCPArrivalTimeFracAudio;
// send side
RTCPSender _rtcpSender;
NACKMethod _nackMethod;
WebRtc_UWord32 _nackLastTimeSent;
WebRtc_UWord16 _nackLastSeqNumberSent;

View File

@ -1,115 +0,0 @@
/*
* 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
* 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.
*/
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_PRIVATE_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_PRIVATE_H_
#include "bwe_defines.h"
#include "rtp_rtcp.h"
#include "tmmbr_help.h"
#include "rtp_utility.h"
namespace webrtc {
class ModuleRtpRtcpPrivate : public RtpRtcp
{
public:
virtual void RegisterChildModule(RtpRtcp* module) = 0;
virtual void DeRegisterChildModule(RtpRtcp* module) = 0;
virtual WebRtc_Word32 RegisterVideoModule(RtpRtcp* videoModule) = 0;
virtual void DeRegisterVideoModule() = 0;
virtual void SetRemoteSSRC(const WebRtc_UWord32 SSRC) = 0;
virtual WebRtc_Word8 SendPayloadType() const = 0;
virtual RtpVideoCodecTypes ReceivedVideoCodec() const = 0;
virtual RtpVideoCodecTypes SendVideoCodec() const = 0;
// lipsync
virtual void OnReceivedNTP() = 0;
// bw estimation
virtual void OnPacketLossStatisticsUpdate(const WebRtc_UWord8 fractionLost,
const WebRtc_UWord16 roundTripTime,
const WebRtc_UWord32 lastReceivedExtendedHighSeqNum,
const WebRtc_UWord32 jitter) = 0;
// bw estimation
virtual void OnReceivedTMMBR() = 0;
// bw estimation
virtual void OnReceivedBandwidthEstimateUpdate( const WebRtc_UWord16 bwEstimateMinKbit,
const WebRtc_UWord16 bwEstimateMaxKbit ) = 0;
//
virtual RateControlRegion OnOverUseStateUpdate(const RateControlInput& rateControlInput) = 0;
// received a request for a new key frame
virtual void OnReceivedIntraFrameRequest(const WebRtc_UWord8 message) = 0;
// received a request for a new SLI
virtual void OnReceivedSliceLossIndication(const WebRtc_UWord8 pictureID) = 0;
// received a new refereence frame
virtual void OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pitureID) = 0;
// request for a RTCP send report
virtual void OnRequestSendReport() = 0;
// Get remote SequenceNumber
virtual WebRtc_UWord16 RemoteSequenceNumber() const = 0;
virtual WebRtc_UWord32 PacketCountSent() const = 0;
virtual int CurrentSendFrequencyHz() const = 0;
virtual WebRtc_UWord32 ByteCountSent() const = 0;
virtual WebRtc_UWord32 BitrateReceivedNow() const = 0;
virtual WebRtc_UWord32 SendTimeOfSendReport(const WebRtc_UWord32 sendReport) = 0;
virtual WebRtc_Word32 LastReceivedNTP(WebRtc_UWord32& NTPsecs, // when we received the last report
WebRtc_UWord32& NTPfrac,
WebRtc_UWord32& remoteSR) = 0; // NTP inside the last received (mid 16 bits from sec and frac)
virtual WebRtc_Word32 ReportBlockStatistics(WebRtc_UWord8 *fraction_lost,
WebRtc_UWord32 *cum_lost,
WebRtc_UWord32 *ext_max,
WebRtc_UWord32 *jitter) = 0;
// bad state of RTP receiver request a keyframe
virtual void OnRequestIntraFrame( const FrameType frameType) = 0;
/*
* NACK
*/
virtual void OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength,
const WebRtc_UWord16* nackSequenceNumbers) = 0;
/*
* TMMBR
*/
virtual WebRtc_Word32 UpdateTMMBR() = 0;
virtual WebRtc_Word32 SetTMMBN(const TMMBRSet* boundingSet,
const WebRtc_UWord32 maxBitrateKbit) = 0;
virtual WebRtc_Word32 BoundingSet(bool &tmmbrOwner,
TMMBRSet*& boundingSetRec)= 0;
virtual WebRtc_Word32 TMMBRReceived(const WebRtc_UWord32 size,
const WebRtc_UWord32 accNumCandidates,
TMMBRSet* candidateSet) const = 0;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_PRIVATE_H_

View File

@ -23,6 +23,23 @@
'rtp_format_vp8_unittest.cc',
],
},
{
'target_name': 'rtcp_format_remb_unittest',
'type': 'executable',
'dependencies': [
'rtp_rtcp',
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
'../../testing/gtest.gyp:gtest',
'../../testing/gtest.gyp:gtest_main',
],
'include_dirs': [
'.',
'../../../',
],
'sources': [
'rtcp_format_remb_unittest.cc',
],
},
{
'target_name': 'rtp_utility_test',
'type': 'executable',