2011-07-07 08:21:25 +00:00
|
|
|
/*
|
2012-01-24 17:16:59 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2011-07-07 08:21:25 +00:00
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "common_types.h"
|
|
|
|
|
#include "rtp_rtcp_impl.h"
|
|
|
|
|
#include "trace.h"
|
|
|
|
|
|
|
|
|
|
#ifdef MATLAB
|
|
|
|
|
#include "../test/BWEStandAlone/MatlabPlot.h"
|
|
|
|
|
extern MatlabEngine eng; // global variable defined elsewhere
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <string.h> //memcpy
|
|
|
|
|
#include <cassert> //assert
|
|
|
|
|
|
|
|
|
|
// local for this file
|
2012-02-08 23:41:49 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
const float FracMS = 4.294967296E6f;
|
|
|
|
|
|
|
|
|
|
} // namepace
|
2011-07-07 08:21:25 +00:00
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
2012-02-08 23:41:49 +00:00
|
|
|
// disable warning C4355: 'this' : used in base member initializer list
|
|
|
|
|
#pragma warning(disable : 4355)
|
2011-07-07 08:21:25 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2012-02-14 12:49:59 +00:00
|
|
|
const WebRtc_UWord16 kDefaultRtt = 200;
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
RtpRtcp* RtpRtcp::CreateRtpRtcp(const WebRtc_Word32 id,
|
|
|
|
|
bool audio) {
|
|
|
|
|
if(audio) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id, "CreateRtpRtcp(audio)");
|
2012-02-15 23:54:59 +00:00
|
|
|
} else {
|
2012-05-10 23:01:04 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id, "CreateRtpRtcp(video)");
|
|
|
|
|
}
|
|
|
|
|
// ModuleRTPUtility::GetSystemClock() creates a new instance of a system
|
|
|
|
|
// clock implementation. The OwnsClock() function informs the module that
|
|
|
|
|
// it is responsible for deleting the instance.
|
|
|
|
|
ModuleRtpRtcpImpl* rtp_rtcp_instance = new ModuleRtpRtcpImpl(id,
|
|
|
|
|
audio, ModuleRTPUtility::GetSystemClock());
|
|
|
|
|
rtp_rtcp_instance->OwnsClock();
|
|
|
|
|
return rtp_rtcp_instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RtpRtcp* RtpRtcp::CreateRtpRtcp(const WebRtc_Word32 id,
|
|
|
|
|
const bool audio,
|
|
|
|
|
RtpRtcpClock* clock) {
|
|
|
|
|
if (audio) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
id,
|
|
|
|
|
"CreateRtpRtcp(audio)");
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
id,
|
|
|
|
|
"CreateRtpRtcp(video)");
|
|
|
|
|
}
|
|
|
|
|
return new ModuleRtpRtcpImpl(id, audio, clock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RtpRtcp::DestroyRtpRtcp(RtpRtcp* module) {
|
|
|
|
|
if (module) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
static_cast<ModuleRtpRtcpImpl*>(module)->Id(),
|
|
|
|
|
"DestroyRtpRtcp()");
|
|
|
|
|
delete static_cast<ModuleRtpRtcpImpl*>(module);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id,
|
|
|
|
|
const bool audio,
|
|
|
|
|
RtpRtcpClock* clock):
|
|
|
|
|
_rtpSender(id, audio, clock),
|
|
|
|
|
_rtpReceiver(id, audio, clock, this),
|
|
|
|
|
_rtcpSender(id, audio, clock, this),
|
|
|
|
|
_rtcpReceiver(id, clock, this),
|
|
|
|
|
_owns_clock(false),
|
|
|
|
|
_clock(*clock),
|
|
|
|
|
_id(id),
|
|
|
|
|
_audio(audio),
|
|
|
|
|
_collisionDetected(false),
|
|
|
|
|
_lastProcessTime(clock->GetTimeInMS()),
|
|
|
|
|
_lastBitrateProcessTime(clock->GetTimeInMS()),
|
|
|
|
|
_lastPacketTimeoutProcessTime(clock->GetTimeInMS()),
|
|
|
|
|
_packetOverHead(28), // IPV4 UDP
|
|
|
|
|
_criticalSectionModulePtrs(CriticalSectionWrapper::CreateCriticalSection()),
|
|
|
|
|
_criticalSectionModulePtrsFeedback(
|
|
|
|
|
CriticalSectionWrapper::CreateCriticalSection()),
|
|
|
|
|
_defaultModule(NULL),
|
|
|
|
|
_audioModule(NULL),
|
|
|
|
|
_videoModule(NULL),
|
|
|
|
|
_deadOrAliveActive(false),
|
|
|
|
|
_deadOrAliveTimeoutMS(0),
|
|
|
|
|
_deadOrAliveLastTimer(0),
|
|
|
|
|
_receivedNTPsecsAudio(0),
|
|
|
|
|
_receivedNTPfracAudio(0),
|
|
|
|
|
_RTCPArrivalTimeSecsAudio(0),
|
|
|
|
|
_RTCPArrivalTimeFracAudio(0),
|
|
|
|
|
_nackMethod(kNackOff),
|
|
|
|
|
_nackLastTimeSent(0),
|
|
|
|
|
_nackLastSeqNumberSent(0),
|
|
|
|
|
_simulcast(false),
|
|
|
|
|
_keyFrameReqMethod(kKeyFrameReqFirRtp)
|
2011-07-07 08:21:25 +00:00
|
|
|
#ifdef MATLAB
|
2012-05-10 23:01:04 +00:00
|
|
|
, _plot1(NULL)
|
2011-07-07 08:21:25 +00:00
|
|
|
#endif
|
|
|
|
|
{
|
2012-02-08 23:41:49 +00:00
|
|
|
_sendVideoCodec.codecType = kVideoCodecUnknown;
|
|
|
|
|
// make sure that RTCP objects are aware of our SSRC
|
|
|
|
|
WebRtc_UWord32 SSRC = _rtpSender.SSRC();
|
|
|
|
|
_rtcpSender.SetSSRC(SSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
ModuleRtpRtcpImpl::~ModuleRtpRtcpImpl() {
|
|
|
|
|
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
// make sure to unregister this module from other modules
|
2012-02-08 23:41:49 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// deregister for the default module
|
|
|
|
|
// will go in to the child modules and remove it self
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
_childModules.erase(it);
|
|
|
|
|
if (module) {
|
|
|
|
|
module->DeRegisterDefaultModule();
|
|
|
|
|
}
|
|
|
|
|
it = _childModules.begin();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// deregister for the child modules
|
|
|
|
|
// will go in to the default and remove it self
|
|
|
|
|
DeRegisterDefaultModule();
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2012-05-10 23:01:04 +00:00
|
|
|
|
|
|
|
|
if (_audio) {
|
|
|
|
|
DeRegisterVideoModule();
|
|
|
|
|
} else {
|
|
|
|
|
DeRegisterSyncModule();
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-07 08:21:25 +00:00
|
|
|
#ifdef MATLAB
|
2012-02-08 23:41:49 +00:00
|
|
|
if (_plot1) {
|
|
|
|
|
eng.DeletePlot(_plot1);
|
|
|
|
|
_plot1 = NULL;
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
#endif
|
2012-05-10 23:01:04 +00:00
|
|
|
|
|
|
|
|
delete _criticalSectionModulePtrs;
|
|
|
|
|
delete _criticalSectionModulePtrsFeedback;
|
2012-02-15 23:54:59 +00:00
|
|
|
if (_owns_clock) {
|
|
|
|
|
delete &_clock;
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::ChangeUniqueId(const WebRtc_Word32 id) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"ChangeUniqueId(new id:%d)", id);
|
|
|
|
|
|
|
|
|
|
_id = id;
|
|
|
|
|
|
|
|
|
|
_rtpReceiver.ChangeUniqueId(id);
|
|
|
|
|
_rtcpReceiver.ChangeUniqueId(id);
|
|
|
|
|
_rtpSender.ChangeUniqueId(id);
|
|
|
|
|
_rtcpSender.ChangeUniqueId(id);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// default encoder that we need to multiplex out
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterDefaultModule(RtpRtcp* module) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterDefaultModule(module:0x%x)", module);
|
|
|
|
|
|
|
|
|
|
if (module == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (module == this) {
|
|
|
|
|
WEBRTC_TRACE(kTraceError,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterDefaultModule can't register self as default");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
|
|
|
|
|
if (_defaultModule) {
|
|
|
|
|
_defaultModule->DeRegisterChildModule(this);
|
|
|
|
|
}
|
|
|
|
|
_defaultModule = (ModuleRtpRtcpImpl*)module;
|
|
|
|
|
_defaultModule->RegisterChildModule(this);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterDefaultModule() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DeRegisterDefaultModule()");
|
|
|
|
|
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
if (_defaultModule) {
|
|
|
|
|
_defaultModule->DeRegisterChildModule(this);
|
|
|
|
|
_defaultModule = NULL;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ModuleRtpRtcpImpl::DefaultModuleRegistered() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DefaultModuleRegistered()");
|
|
|
|
|
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
if (_defaultModule) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::NumberChildModules() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "NumberChildModules");
|
|
|
|
|
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
|
|
|
|
|
// we use two locks for protecting _childModules one
|
|
|
|
|
// (_criticalSectionModulePtrsFeedback) for incoming messages
|
|
|
|
|
// (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs for
|
|
|
|
|
// all outgoing messages sending packets etc
|
|
|
|
|
|
|
|
|
|
return _childModules.size();
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
void ModuleRtpRtcpImpl::RegisterChildModule(RtpRtcp* module) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterChildModule(module:0x%x)",
|
|
|
|
|
module);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
|
2012-02-08 23:41:49 +00:00
|
|
|
// we use two locks for protecting _childModules one
|
|
|
|
|
// (_criticalSectionModulePtrsFeedback) for incoming
|
2012-04-05 08:30:10 +00:00
|
|
|
// messages (BitrateSent) and _criticalSectionModulePtrs
|
2012-02-08 23:41:49 +00:00
|
|
|
// for all outgoing messages sending packets etc
|
|
|
|
|
_childModules.push_back((ModuleRtpRtcpImpl*)module);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
void ModuleRtpRtcpImpl::DeRegisterChildModule(RtpRtcp* removeModule) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DeRegisterChildModule(module:0x%x)", removeModule);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module == removeModule) {
|
|
|
|
|
_childModules.erase(it);
|
|
|
|
|
return;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
it++;
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
// Lip-sync between voice-video engine,
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSyncModule(RtpRtcp* audioModule) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterSyncModule(module:0x%x)",
|
|
|
|
|
audioModule);
|
|
|
|
|
|
|
|
|
|
if (audioModule == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (_audio) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
_audioModule = (ModuleRtpRtcpImpl*)audioModule;
|
|
|
|
|
return _audioModule->RegisterVideoModule(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterSyncModule() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DeRegisterSyncModule()");
|
|
|
|
|
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
if (_audioModule) {
|
|
|
|
|
ModuleRtpRtcpImpl* audioModule = _audioModule;
|
|
|
|
|
_audioModule = NULL;
|
|
|
|
|
_receivedNTPsecsAudio = 0;
|
|
|
|
|
_receivedNTPfracAudio = 0;
|
|
|
|
|
_RTCPArrivalTimeSecsAudio = 0;
|
|
|
|
|
_RTCPArrivalTimeFracAudio = 0;
|
|
|
|
|
audioModule->DeRegisterVideoModule();
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterVideoModule(RtpRtcp* videoModule) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterVideoModule(module:0x%x)",
|
|
|
|
|
videoModule);
|
|
|
|
|
|
|
|
|
|
if (videoModule == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (!_audio) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
_videoModule = (ModuleRtpRtcpImpl*)videoModule;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModuleRtpRtcpImpl::DeRegisterVideoModule() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DeRegisterVideoModule()");
|
|
|
|
|
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
if (_videoModule) {
|
|
|
|
|
ModuleRtpRtcpImpl* videoModule = _videoModule;
|
|
|
|
|
_videoModule = NULL;
|
|
|
|
|
videoModule->DeRegisterSyncModule();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
// returns the number of milliseconds until the module want a worker thread
|
|
|
|
|
// to call Process
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::TimeUntilNextProcess() {
|
|
|
|
|
const WebRtc_UWord32 now = _clock.GetTimeInMS();
|
|
|
|
|
return kRtpRtcpMaxIdleTimeProcess - (now - _lastProcessTime);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process any pending tasks such as timeouts
|
|
|
|
|
// non time critical events
|
2012-01-16 11:06:31 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
|
|
|
|
|
const WebRtc_UWord32 now = _clock.GetTimeInMS();
|
|
|
|
|
_lastProcessTime = now;
|
|
|
|
|
|
|
|
|
|
_rtpSender.ProcessSendToNetwork();
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
if (now >= _lastPacketTimeoutProcessTime +
|
|
|
|
|
kRtpRtcpPacketTimeoutProcessTimeMs) {
|
2011-07-07 08:21:25 +00:00
|
|
|
_rtpReceiver.PacketTimeout();
|
|
|
|
|
_rtcpReceiver.PacketTimeout();
|
2012-01-16 11:06:31 +00:00
|
|
|
_lastPacketTimeoutProcessTime = now;
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
if (now >= _lastBitrateProcessTime + kRtpRtcpBitrateProcessTimeMs) {
|
2011-07-07 08:21:25 +00:00
|
|
|
_rtpSender.ProcessBitrate();
|
|
|
|
|
_rtpReceiver.ProcessBitrate();
|
2012-01-16 11:06:31 +00:00
|
|
|
_lastBitrateProcessTime = now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProcessDeadOrAliveTimer();
|
|
|
|
|
|
|
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
2012-02-08 23:41:49 +00:00
|
|
|
if (!defaultInstance && _rtcpSender.TimeToSendRTCPReport()) {
|
2012-02-14 12:49:59 +00:00
|
|
|
WebRtc_UWord16 max_rtt = 0;
|
|
|
|
|
if (_rtcpSender.Sending()) {
|
|
|
|
|
std::vector<RTCPReportBlock> receive_blocks;
|
|
|
|
|
_rtcpReceiver.StatisticsReceived(&receive_blocks);
|
|
|
|
|
for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin();
|
|
|
|
|
it != receive_blocks.end(); ++it) {
|
|
|
|
|
WebRtc_UWord16 rtt = 0;
|
|
|
|
|
_rtcpReceiver.RTT(it->remoteSSRC, &max_rtt, NULL, NULL, NULL);
|
|
|
|
|
max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// We're only receiving, i.e. this module doesn't have its own RTT
|
|
|
|
|
// estimate. Use the RTT set by a sending channel using the same default
|
|
|
|
|
// module.
|
|
|
|
|
max_rtt = _rtcpReceiver.RTT();
|
|
|
|
|
}
|
|
|
|
|
if (max_rtt == 0) {
|
|
|
|
|
// No valid estimate available, i.e. no sending channel using the same
|
|
|
|
|
// default module or no RTCP received yet.
|
|
|
|
|
max_rtt = kDefaultRtt;
|
|
|
|
|
}
|
2012-04-05 08:30:10 +00:00
|
|
|
if (_rtcpSender.ValidBitrateEstimate()) {
|
|
|
|
|
if (REMB()) {
|
|
|
|
|
uint32_t target_bitrate =
|
|
|
|
|
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
|
|
|
|
|
_rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
|
|
|
|
|
} else if (TMMBR()) {
|
2012-02-14 12:49:59 +00:00
|
|
|
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
|
2012-04-05 08:30:10 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2012-02-10 12:13:12 +00:00
|
|
|
_rtcpSender.SendRTCP(kRtcpReport);
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (UpdateRTCPReceiveInformationTimers()) {
|
|
|
|
|
// a receiver has timed out
|
2012-04-05 08:30:10 +00:00
|
|
|
_rtcpReceiver.UpdateTMMBR();
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/**
|
|
|
|
|
* Receiver
|
|
|
|
|
*/
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::InitReceiver() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "InitReceiver()");
|
|
|
|
|
|
|
|
|
|
_packetOverHead = 28; // default is IPV4 UDP
|
|
|
|
|
_receivedNTPsecsAudio = 0;
|
|
|
|
|
_receivedNTPfracAudio = 0;
|
|
|
|
|
_RTCPArrivalTimeSecsAudio = 0;
|
|
|
|
|
_RTCPArrivalTimeFracAudio = 0;
|
|
|
|
|
|
|
|
|
|
_rtpReceiver.Init();
|
|
|
|
|
_rtpReceiver.SetPacketOverHead(_packetOverHead);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() {
|
|
|
|
|
if (_deadOrAliveActive) {
|
|
|
|
|
const WebRtc_UWord32 now = _clock.GetTimeInMS();
|
|
|
|
|
if (now > _deadOrAliveTimeoutMS + _deadOrAliveLastTimer) {
|
|
|
|
|
// RTCP is alive if we have received a report the last 12 seconds
|
|
|
|
|
_deadOrAliveLastTimer += _deadOrAliveTimeoutMS;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
bool RTCPalive = false;
|
|
|
|
|
if (_rtcpReceiver.LastReceived() + 12000 > now) {
|
|
|
|
|
RTCPalive = true;
|
|
|
|
|
}
|
|
|
|
|
_rtpReceiver.ProcessDeadOrAlive(RTCPalive, now);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetPeriodicDeadOrAliveStatus(
|
|
|
|
|
const bool enable,
|
|
|
|
|
const WebRtc_UWord8 sampleTimeSeconds) {
|
|
|
|
|
if (enable) {
|
2011-10-13 15:19:55 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
2012-02-08 23:41:49 +00:00
|
|
|
"SetPeriodicDeadOrAliveStatus(enable, %d)",
|
|
|
|
|
sampleTimeSeconds);
|
|
|
|
|
} else {
|
2011-10-13 15:19:55 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
2012-02-08 23:41:49 +00:00
|
|
|
"SetPeriodicDeadOrAliveStatus(disable)");
|
|
|
|
|
}
|
|
|
|
|
if (sampleTimeSeconds == 0) {
|
2011-07-07 08:21:25 +00:00
|
|
|
return -1;
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
_deadOrAliveActive = enable;
|
|
|
|
|
_deadOrAliveTimeoutMS = sampleTimeSeconds * 1000;
|
|
|
|
|
// trigger the first after one period
|
|
|
|
|
_deadOrAliveLastTimer = _clock.GetTimeInMS();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::PeriodicDeadOrAliveStatus(
|
|
|
|
|
bool& enable,
|
|
|
|
|
WebRtc_UWord8& sampleTimeSeconds) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"PeriodicDeadOrAliveStatus()");
|
|
|
|
|
|
|
|
|
|
enable = _deadOrAliveActive;
|
|
|
|
|
sampleTimeSeconds = (WebRtc_UWord8)(_deadOrAliveTimeoutMS / 1000);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetPacketTimeout(
|
|
|
|
|
const WebRtc_UWord32 RTPtimeoutMS,
|
|
|
|
|
const WebRtc_UWord32 RTCPtimeoutMS) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetPacketTimeout(%u,%u)",
|
|
|
|
|
RTPtimeoutMS,
|
|
|
|
|
RTCPtimeoutMS);
|
|
|
|
|
|
|
|
|
|
if (_rtpReceiver.SetPacketTimeout(RTPtimeoutMS) == 0) {
|
|
|
|
|
return _rtcpReceiver.SetPacketTimeout(RTCPtimeoutMS);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceivePayload(
|
2012-02-08 23:41:49 +00:00
|
|
|
const CodecInst& voiceCodec) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterReceivePayload(voiceCodec)");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.RegisterReceivePayload(
|
|
|
|
|
voiceCodec.plname,
|
|
|
|
|
voiceCodec.pltype,
|
|
|
|
|
voiceCodec.plfreq,
|
|
|
|
|
voiceCodec.channels,
|
|
|
|
|
(voiceCodec.rate < 0) ? 0 : voiceCodec.rate);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceivePayload(
|
2012-02-08 23:41:49 +00:00
|
|
|
const VideoCodec& videoCodec) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterReceivePayload(videoCodec)");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.RegisterReceivePayload(videoCodec.plName,
|
|
|
|
|
videoCodec.plType,
|
|
|
|
|
90000,
|
|
|
|
|
0,
|
|
|
|
|
videoCodec.maxBitrate);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::ReceivePayloadType(
|
2012-02-08 23:41:49 +00:00
|
|
|
const CodecInst& voiceCodec,
|
|
|
|
|
WebRtc_Word8* plType) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"ReceivePayloadType(voiceCodec)");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.ReceivePayloadType(
|
|
|
|
|
voiceCodec.plname,
|
|
|
|
|
voiceCodec.plfreq,
|
|
|
|
|
voiceCodec.channels,
|
|
|
|
|
(voiceCodec.rate < 0) ? 0 : voiceCodec.rate,
|
|
|
|
|
plType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::ReceivePayloadType(
|
2012-02-08 23:41:49 +00:00
|
|
|
const VideoCodec& videoCodec,
|
|
|
|
|
WebRtc_Word8* plType) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"ReceivePayloadType(videoCodec)");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.ReceivePayloadType(videoCodec.plName,
|
|
|
|
|
90000,
|
|
|
|
|
0,
|
|
|
|
|
videoCodec.maxBitrate,
|
|
|
|
|
plType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterReceivePayload(
|
|
|
|
|
const WebRtc_Word8 payloadType) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DeRegisterReceivePayload(%d)",
|
|
|
|
|
payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.DeRegisterReceivePayload(payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// get the currently configured SSRC filter
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SSRCFilter(WebRtc_UWord32& allowedSSRC) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SSRCFilter()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.SSRCFilter(allowedSSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// set a SSRC to be used as a filter for incoming RTP streams
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetSSRCFilter(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const WebRtc_UWord32 allowedSSRC) {
|
|
|
|
|
if (enable) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetSSRCFilter(enable, 0x%x)",
|
|
|
|
|
allowedSSRC);
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetSSRCFilter(disable)");
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.SetSSRCFilter(enable, allowedSSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get last received remote timestamp
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::RemoteTimestamp() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteTimestamp()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.TimeStamp();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the current estimated remote timestamp
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::EstimatedRemoteTimeStamp(
|
|
|
|
|
WebRtc_UWord32& timestamp) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"EstimatedRemoteTimeStamp()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.EstimatedRemoteTimeStamp(timestamp);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get incoming SSRC
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::RemoteSSRC() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteSSRC()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.SSRC();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get remote CSRC
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteCSRCs(
|
|
|
|
|
WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize]) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteCSRCs()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.CSRCs(arrOfCSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-10 14:09:18 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTXSendStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const bool setSSRC,
|
|
|
|
|
const WebRtc_UWord32 SSRC) {
|
2012-01-10 14:09:18 +00:00
|
|
|
_rtpSender.SetRTXStatus(enable, setSSRC, SSRC);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RTXSendStatus(bool* enable,
|
|
|
|
|
WebRtc_UWord32* SSRC) const {
|
|
|
|
|
_rtpSender.RTXStatus(enable, SSRC);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTXReceiveStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const WebRtc_UWord32 SSRC) {
|
2012-01-10 14:09:18 +00:00
|
|
|
_rtpReceiver.SetRTXStatus(enable, SSRC);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RTXReceiveStatus(bool* enable,
|
|
|
|
|
WebRtc_UWord32* SSRC) const {
|
|
|
|
|
_rtpReceiver.RTXStatus(enable, SSRC);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-07 08:21:25 +00:00
|
|
|
// called by the network module when we receive a packet
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::IncomingPacket(
|
|
|
|
|
const WebRtc_UWord8* incomingPacket,
|
|
|
|
|
const WebRtc_UWord16 incomingPacketLength) {
|
|
|
|
|
WEBRTC_TRACE(kTraceStream,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"IncomingPacket(packetLength:%u)",
|
|
|
|
|
incomingPacketLength);
|
2012-05-10 22:54:39 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// minimum RTP is 12 bytes
|
|
|
|
|
// minimum RTCP is 8 bytes (RTCP BYE)
|
|
|
|
|
if (incomingPacketLength < 8 || incomingPacket == NULL) {
|
|
|
|
|
WEBRTC_TRACE(kTraceDebug,
|
2011-10-13 15:19:55 +00:00
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
2012-02-08 23:41:49 +00:00
|
|
|
"IncomingPacket invalid buffer or length");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// check RTP version
|
|
|
|
|
const WebRtc_UWord8 version = incomingPacket[0] >> 6 ;
|
|
|
|
|
if (version != 2) {
|
|
|
|
|
WEBRTC_TRACE(kTraceDebug,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"IncomingPacket invalid RTP version");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
ModuleRTPUtility::RTPHeaderParser rtpParser(incomingPacket,
|
2011-07-07 08:21:25 +00:00
|
|
|
incomingPacketLength);
|
2012-02-08 23:41:49 +00:00
|
|
|
|
|
|
|
|
if (rtpParser.RTCP()) {
|
|
|
|
|
// Allow receive of non-compound RTCP packets.
|
|
|
|
|
RTCPUtility::RTCPParserV2 rtcpParser(incomingPacket,
|
|
|
|
|
incomingPacketLength,
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
const bool validRTCPHeader = rtcpParser.IsValid();
|
|
|
|
|
if (!validRTCPHeader) {
|
|
|
|
|
WEBRTC_TRACE(kTraceDebug,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"IncomingPacket invalid RTCP packet");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
RTCPHelp::RTCPPacketInformation rtcpPacketInformation;
|
|
|
|
|
WebRtc_Word32 retVal = _rtcpReceiver.IncomingRTCPPacket(
|
|
|
|
|
rtcpPacketInformation,
|
|
|
|
|
&rtcpParser);
|
|
|
|
|
if (retVal == 0) {
|
|
|
|
|
_rtcpReceiver.TriggerCallbacksFromRTCPPacket(rtcpPacketInformation);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
return retVal;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
WebRtcRTPHeader rtpHeader;
|
|
|
|
|
memset(&rtpHeader, 0, sizeof(rtpHeader));
|
|
|
|
|
|
|
|
|
|
RtpHeaderExtensionMap map;
|
|
|
|
|
_rtpReceiver.GetHeaderExtensionMapCopy(&map);
|
|
|
|
|
|
|
|
|
|
const bool validRTPHeader = rtpParser.Parse(rtpHeader, &map);
|
|
|
|
|
if (!validRTPHeader) {
|
|
|
|
|
WEBRTC_TRACE(kTraceDebug,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"IncomingPacket invalid RTP header");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return _rtpReceiver.IncomingRTPPacket(&rtpHeader,
|
|
|
|
|
incomingPacket,
|
|
|
|
|
incomingPacketLength);
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::IncomingAudioNTP(
|
|
|
|
|
const WebRtc_UWord32 audioReceivedNTPsecs,
|
|
|
|
|
const WebRtc_UWord32 audioReceivedNTPfrac,
|
|
|
|
|
const WebRtc_UWord32 audioRTCPArrivalTimeSecs,
|
|
|
|
|
const WebRtc_UWord32 audioRTCPArrivalTimeFrac) {
|
|
|
|
|
_receivedNTPsecsAudio = audioReceivedNTPsecs;
|
|
|
|
|
_receivedNTPfracAudio = audioReceivedNTPfrac;
|
|
|
|
|
_RTCPArrivalTimeSecsAudio = audioRTCPArrivalTimeSecs;
|
|
|
|
|
_RTCPArrivalTimeFracAudio = audioRTCPArrivalTimeFrac;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingDataCallback(
|
|
|
|
|
RtpData* incomingDataCallback) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterIncomingDataCallback(incomingDataCallback:0x%x)",
|
|
|
|
|
incomingDataCallback);
|
|
|
|
|
|
|
|
|
|
return _rtpReceiver.RegisterIncomingDataCallback(incomingDataCallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingRTPCallback(
|
|
|
|
|
RtpFeedback* incomingMessagesCallback) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterIncomingRTPCallback(incomingMessagesCallback:0x%x)",
|
|
|
|
|
incomingMessagesCallback);
|
|
|
|
|
|
|
|
|
|
return _rtpReceiver.RegisterIncomingRTPCallback(incomingMessagesCallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModuleRtpRtcpImpl::RegisterRtcpObservers(
|
|
|
|
|
RtcpIntraFrameObserver* intra_frame_callback,
|
|
|
|
|
RtcpBandwidthObserver* bandwidth_callback,
|
|
|
|
|
RtcpFeedback* feedback_callback) {
|
|
|
|
|
_rtcpReceiver.RegisterRtcpObservers(intra_frame_callback, bandwidth_callback,
|
|
|
|
|
feedback_callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterAudioCallback(
|
|
|
|
|
RtpAudioFeedback* messagesCallback) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterAudioCallback(messagesCallback:0x%x)",
|
|
|
|
|
messagesCallback);
|
|
|
|
|
|
|
|
|
|
if (_rtpSender.RegisterAudioCallback(messagesCallback) == 0) {
|
|
|
|
|
return _rtpReceiver.RegisterIncomingAudioCallback(messagesCallback);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/**
|
|
|
|
|
* Sender
|
|
|
|
|
*/
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::InitSender() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "InitSender()");
|
|
|
|
|
|
|
|
|
|
_collisionDetected = false;
|
|
|
|
|
|
|
|
|
|
// if we are already receiving inform our sender to avoid collision
|
|
|
|
|
if (_rtpSender.Init(_rtpReceiver.SSRC()) != 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
WebRtc_Word32 retVal = _rtcpSender.Init();
|
|
|
|
|
|
|
|
|
|
// make sure that RTCP objects are aware of our SSRC
|
|
|
|
|
// (it could have changed due to collision)
|
|
|
|
|
WebRtc_UWord32 SSRC = _rtpSender.SSRC();
|
|
|
|
|
_rtcpReceiver.SetSSRC(SSRC);
|
|
|
|
|
_rtcpSender.SetSSRC(SSRC);
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendPayload(
|
|
|
|
|
const CodecInst& voiceCodec) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterSendPayload(plName:%s plType:%d frequency:%u)",
|
|
|
|
|
voiceCodec.plname,
|
|
|
|
|
voiceCodec.pltype,
|
|
|
|
|
voiceCodec.plfreq);
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.RegisterPayload(
|
|
|
|
|
voiceCodec.plname,
|
|
|
|
|
voiceCodec.pltype,
|
|
|
|
|
voiceCodec.plfreq,
|
|
|
|
|
voiceCodec.channels,
|
|
|
|
|
(voiceCodec.rate < 0) ? 0 : voiceCodec.rate);
|
2011-10-13 15:19:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendPayload(
|
2012-02-08 23:41:49 +00:00
|
|
|
const VideoCodec& videoCodec) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterSendPayload(plName:%s plType:%d)",
|
|
|
|
|
videoCodec.plName,
|
|
|
|
|
videoCodec.plType);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
_sendVideoCodec = videoCodec;
|
|
|
|
|
_simulcast = (videoCodec.numberOfSimulcastStreams > 1) ? true : false;
|
|
|
|
|
return _rtpSender.RegisterPayload(videoCodec.plName,
|
|
|
|
|
videoCodec.plType,
|
|
|
|
|
90000,
|
|
|
|
|
0,
|
|
|
|
|
videoCodec.maxBitrate);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterSendPayload(
|
|
|
|
|
const WebRtc_Word8 payloadType) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"DeRegisterSendPayload(%d)", payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.DeRegisterSendPayload(payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word8 ModuleRtpRtcpImpl::SendPayloadType() const {
|
|
|
|
|
return _rtpSender.SendPayloadType();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::StartTimestamp() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "StartTimestamp()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.StartTimestamp();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// configure start timestamp, default is a random number
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetStartTimestamp(
|
|
|
|
|
const WebRtc_UWord32 timestamp) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetStartTimestamp(%d)",
|
|
|
|
|
timestamp);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SetStartTimestamp(timestamp, true);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord16 ModuleRtpRtcpImpl::SequenceNumber() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SequenceNumber()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SequenceNumber();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Set SequenceNumber, default is a random number
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetSequenceNumber(
|
|
|
|
|
const WebRtc_UWord16 seqNum) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetSequenceNumber(%d)",
|
|
|
|
|
seqNum);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SetSequenceNumber(seqNum);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::SSRC() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SSRC()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SSRC();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// configure SSRC, default is a random number
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetSSRC(const WebRtc_UWord32 ssrc) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSSRC(%d)", ssrc);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (_rtpSender.SetSSRC(ssrc) == 0) {
|
|
|
|
|
_rtcpReceiver.SetSSRC(ssrc);
|
|
|
|
|
_rtcpSender.SetSSRC(ssrc);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetCSRCStatus(const bool include) {
|
|
|
|
|
_rtcpSender.SetCSRCStatus(include);
|
|
|
|
|
return _rtpSender.SetCSRCStatus(include);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::CSRCs(
|
|
|
|
|
WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize]) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "CSRCs()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.CSRCs(arrOfCSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetCSRCs(
|
|
|
|
|
const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize],
|
|
|
|
|
const WebRtc_UWord8 arrLength) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetCSRCs(arrLength:%d)",
|
|
|
|
|
arrLength);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// for default we need to update all child modules too
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
|
|
|
|
module->SetCSRCs(arrOfCSRC, arrLength);
|
|
|
|
|
}
|
|
|
|
|
it++;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < arrLength; i++) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "\tidx:%d CSRC:%u", i,
|
|
|
|
|
arrOfCSRC[i]);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
_rtcpSender.SetCSRCs(arrOfCSRC, arrLength);
|
|
|
|
|
return _rtpSender.SetCSRCs(arrOfCSRC, arrLength);
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::PacketCountSent() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "PacketCountSent()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.Packets();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::ByteCountSent() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ByteCountSent()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.Bytes();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
int ModuleRtpRtcpImpl::CurrentSendFrequencyHz() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"CurrentSendFrequencyHz()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SendPayloadFrequency();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) {
|
|
|
|
|
if (sending) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetSendingStatus(sending)");
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetSendingStatus(stopped)");
|
|
|
|
|
}
|
|
|
|
|
if (_rtcpSender.Sending() != sending) {
|
|
|
|
|
// sends RTCP BYE when going from true to false
|
|
|
|
|
if (_rtcpSender.SetSendingStatus(sending) != 0) {
|
|
|
|
|
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
|
|
|
|
|
"Failed to send RTCP BYE");
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
_collisionDetected = false;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// generate a new timeStamp if true and not configured via API
|
|
|
|
|
// generate a new SSRC for the next "call" if false
|
|
|
|
|
_rtpSender.SetSendingStatus(sending);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// make sure that RTCP objects are aware of our SSRC (it could have changed
|
|
|
|
|
// due to collision)
|
|
|
|
|
WebRtc_UWord32 SSRC = _rtpSender.SSRC();
|
|
|
|
|
_rtcpReceiver.SetSSRC(SSRC);
|
|
|
|
|
_rtcpSender.SetSSRC(SSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
return 0;
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
bool ModuleRtpRtcpImpl::Sending() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Sending()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.Sending();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetSendingMediaStatus(const bool sending) {
|
|
|
|
|
if (sending) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetSendingMediaStatus(sending)");
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetSendingMediaStatus(stopped)");
|
|
|
|
|
}
|
|
|
|
|
_rtpSender.SetSendingMediaStatus(sending);
|
|
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
bool ModuleRtpRtcpImpl::SendingMedia() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Sending()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool haveChildModules(_childModules.empty() ? false : true);
|
|
|
|
|
if (!haveChildModules) {
|
|
|
|
|
return _rtpSender.SendingMedia();
|
|
|
|
|
}
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::const_iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RTPSender& rtpSender = (*it)->_rtpSender;
|
|
|
|
|
if (rtpSender.SendingMedia()) {
|
|
|
|
|
return true;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
it++;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendTransport(
|
|
|
|
|
Transport* outgoingTransport) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"RegisterSendTransport(0x%x)", outgoingTransport);
|
|
|
|
|
|
|
|
|
|
if (_rtpSender.RegisterSendTransport(outgoingTransport) == 0) {
|
|
|
|
|
return _rtcpSender.RegisterSendTransport(outgoingTransport);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendOutgoingData(
|
|
|
|
|
FrameType frameType,
|
|
|
|
|
WebRtc_Word8 payloadType,
|
|
|
|
|
WebRtc_UWord32 timeStamp,
|
|
|
|
|
const WebRtc_UWord8* payloadData,
|
|
|
|
|
WebRtc_UWord32 payloadSize,
|
|
|
|
|
const RTPFragmentationHeader* fragmentation,
|
|
|
|
|
const RTPVideoHeader* rtpVideoHdr) {
|
|
|
|
|
WEBRTC_TRACE(
|
|
|
|
|
kTraceStream,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SendOutgoingData(frameType:%d payloadType:%d timeStamp:%u size:%u)",
|
|
|
|
|
frameType, payloadType, timeStamp, payloadSize);
|
|
|
|
|
|
|
|
|
|
const bool haveChildModules(_childModules.empty() ? false : true);
|
|
|
|
|
if (!haveChildModules) {
|
|
|
|
|
// Don't sent RTCP from default module
|
|
|
|
|
if (_rtcpSender.TimeToSendRTCPReport(kVideoFrameKey == frameType)) {
|
2012-02-10 12:13:12 +00:00
|
|
|
_rtcpSender.SendRTCP(kRtcpReport);
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
return _rtpSender.SendOutgoingData(frameType,
|
|
|
|
|
payloadType,
|
|
|
|
|
timeStamp,
|
|
|
|
|
payloadData,
|
|
|
|
|
payloadSize,
|
|
|
|
|
fragmentation,
|
|
|
|
|
NULL,
|
|
|
|
|
&(rtpVideoHdr->codecHeader));
|
|
|
|
|
}
|
|
|
|
|
WebRtc_Word32 retVal = -1;
|
|
|
|
|
if (_simulcast) {
|
|
|
|
|
if (rtpVideoHdr == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int idx = 0;
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
for (; idx < rtpVideoHdr->simulcastIdx; idx++) {
|
|
|
|
|
it++;
|
|
|
|
|
if (it == _childModules.end()) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RTPSender& rtpSender = (*it)->_rtpSender;
|
2011-10-13 15:19:55 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
2012-02-08 23:41:49 +00:00
|
|
|
"SendOutgoingData(SimulcastIdx:%u size:%u, ssrc:0x%x)",
|
|
|
|
|
idx, payloadSize, rtpSender.SSRC());
|
|
|
|
|
return rtpSender.SendOutgoingData(frameType,
|
|
|
|
|
payloadType,
|
|
|
|
|
timeStamp,
|
|
|
|
|
payloadData,
|
|
|
|
|
payloadSize,
|
|
|
|
|
fragmentation,
|
|
|
|
|
NULL,
|
|
|
|
|
&(rtpVideoHdr->codecHeader));
|
|
|
|
|
} else {
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
// TODO(pwestin) remove codecInfo from SendOutgoingData
|
|
|
|
|
VideoCodecInformation* codecInfo = NULL;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
if (it != _childModules.end()) {
|
|
|
|
|
RTPSender& rtpSender = (*it)->_rtpSender;
|
|
|
|
|
retVal = rtpSender.SendOutgoingData(frameType,
|
|
|
|
|
payloadType,
|
|
|
|
|
timeStamp,
|
|
|
|
|
payloadData,
|
|
|
|
|
payloadSize,
|
|
|
|
|
fragmentation,
|
|
|
|
|
NULL,
|
|
|
|
|
&(rtpVideoHdr->codecHeader));
|
|
|
|
|
|
|
|
|
|
it++;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
|
|
|
|
|
// send to all remaining "child" modules
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RTPSender& rtpSender = (*it)->_rtpSender;
|
|
|
|
|
retVal = rtpSender.SendOutgoingData(frameType,
|
2011-10-13 15:19:55 +00:00
|
|
|
payloadType,
|
|
|
|
|
timeStamp,
|
|
|
|
|
payloadData,
|
|
|
|
|
payloadSize,
|
|
|
|
|
fragmentation,
|
2012-02-08 23:41:49 +00:00
|
|
|
codecInfo,
|
2011-10-13 15:19:55 +00:00
|
|
|
&(rtpVideoHdr->codecHeader));
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
it++;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
return retVal;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord16 ModuleRtpRtcpImpl::MaxPayloadLength() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "MaxPayloadLength()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.MaxPayloadLength();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord16 ModuleRtpRtcpImpl::MaxDataPayloadLength() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"MaxDataPayloadLength()");
|
|
|
|
|
|
|
|
|
|
WebRtc_UWord16 minDataPayloadLength = IP_PACKET_SIZE - 28; // Assuming IP/UDP
|
|
|
|
|
|
|
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// for default we need to update all child modules too
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::const_iterator it =
|
|
|
|
|
_childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
|
|
|
|
WebRtc_UWord16 dataPayloadLength =
|
|
|
|
|
module->MaxDataPayloadLength();
|
|
|
|
|
if (dataPayloadLength < minDataPayloadLength) {
|
|
|
|
|
minDataPayloadLength = dataPayloadLength;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
it++;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord16 dataPayloadLength = _rtpSender.MaxDataPayloadLength();
|
|
|
|
|
if (dataPayloadLength < minDataPayloadLength) {
|
|
|
|
|
minDataPayloadLength = dataPayloadLength;
|
|
|
|
|
}
|
|
|
|
|
return minDataPayloadLength;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetTransportOverhead(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool TCP,
|
|
|
|
|
const bool IPV6,
|
|
|
|
|
const WebRtc_UWord8 authenticationOverhead) {
|
|
|
|
|
WEBRTC_TRACE(
|
|
|
|
|
kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetTransportOverhead(TCP:%d, IPV6:%d authenticationOverhead:%u)",
|
|
|
|
|
TCP, IPV6, authenticationOverhead);
|
|
|
|
|
|
|
|
|
|
WebRtc_UWord16 packetOverHead = 0;
|
|
|
|
|
if (IPV6) {
|
|
|
|
|
packetOverHead = 40;
|
|
|
|
|
} else {
|
|
|
|
|
packetOverHead = 20;
|
|
|
|
|
}
|
|
|
|
|
if (TCP) {
|
|
|
|
|
// TCP
|
|
|
|
|
packetOverHead += 20;
|
|
|
|
|
} else {
|
|
|
|
|
// UDP
|
|
|
|
|
packetOverHead += 8;
|
|
|
|
|
}
|
|
|
|
|
packetOverHead += authenticationOverhead;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (packetOverHead == _packetOverHead) {
|
|
|
|
|
// ok same as before
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// calc diff
|
|
|
|
|
WebRtc_Word16 packetOverHeadDiff = packetOverHead - _packetOverHead;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// store new
|
|
|
|
|
_packetOverHead = packetOverHead;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
_rtpReceiver.SetPacketOverHead(_packetOverHead);
|
|
|
|
|
WebRtc_UWord16 length = _rtpSender.MaxPayloadLength() - packetOverHeadDiff;
|
|
|
|
|
return _rtpSender.SetMaxPayloadLength(length, _packetOverHead);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetMaxTransferUnit(const WebRtc_UWord16 MTU) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetMaxTransferUnit(%u)",
|
|
|
|
|
MTU);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (MTU > IP_PACKET_SIZE) {
|
|
|
|
|
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
|
|
|
|
|
"Invalid in argument to SetMaxTransferUnit(%u)", MTU);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return _rtpSender.SetMaxPayloadLength(MTU - _packetOverHead,
|
|
|
|
|
_packetOverHead);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/*
|
|
|
|
|
* RTCP
|
|
|
|
|
*/
|
|
|
|
|
RTCPMethod ModuleRtpRtcpImpl::RTCP() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTCP()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (_rtcpSender.Status() != kRtcpOff) {
|
|
|
|
|
return _rtcpReceiver.Status();
|
|
|
|
|
}
|
|
|
|
|
return kRtcpOff;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// configure RTCP status i.e on/off
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPStatus(const RTCPMethod method) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTCPStatus(%d)",
|
|
|
|
|
method);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (_rtcpSender.SetRTCPStatus(method) == 0) {
|
|
|
|
|
return _rtcpReceiver.SetRTCPStatus(method);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2011-07-07 08:21:25 +00:00
|
|
|
// only for internal test
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::LastSendReport(WebRtc_UWord32& lastRTCPTime) {
|
|
|
|
|
return _rtcpSender.LastSendReport(lastRTCPTime);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetCNAME(%s)", cName);
|
|
|
|
|
return _rtcpSender.SetCNAME(cName);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::CNAME(char cName[RTCP_CNAME_SIZE]) {
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "CNAME()");
|
|
|
|
|
return _rtcpSender.CNAME(cName);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::AddMixedCNAME(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord32 SSRC,
|
|
|
|
|
const char cName[RTCP_CNAME_SIZE]) {
|
2012-01-24 17:16:59 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"AddMixedCNAME(SSRC:%u)", SSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
return _rtcpSender.AddMixedCNAME(SSRC, cName);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoveMixedCNAME(const WebRtc_UWord32 SSRC) {
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"RemoveMixedCNAME(SSRC:%u)", SSRC);
|
|
|
|
|
return _rtcpSender.RemoveMixedCNAME(SSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteCNAME(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord32 remoteSSRC,
|
|
|
|
|
char cName[RTCP_CNAME_SIZE]) const {
|
2012-01-24 17:16:59 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"RemoteCNAME(SSRC:%u)", remoteSSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-01-24 17:16:59 +00:00
|
|
|
return _rtcpReceiver.CNAME(remoteSSRC, cName);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord16 ModuleRtpRtcpImpl::RemoteSequenceNumber() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteSequenceNumber()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.SequenceNumber();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteNTP(
|
|
|
|
|
WebRtc_UWord32* receivedNTPsecs,
|
|
|
|
|
WebRtc_UWord32* receivedNTPfrac,
|
|
|
|
|
WebRtc_UWord32* RTCPArrivalTimeSecs,
|
|
|
|
|
WebRtc_UWord32* RTCPArrivalTimeFrac) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteNTP()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpReceiver.NTP(receivedNTPsecs,
|
|
|
|
|
receivedNTPfrac,
|
|
|
|
|
RTCPArrivalTimeSecs,
|
|
|
|
|
RTCPArrivalTimeFrac);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get RoundTripTime
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RTT(const WebRtc_UWord32 remoteSSRC,
|
|
|
|
|
WebRtc_UWord16* RTT,
|
|
|
|
|
WebRtc_UWord16* avgRTT,
|
|
|
|
|
WebRtc_UWord16* minRTT,
|
|
|
|
|
WebRtc_UWord16* maxRTT) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTT()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpReceiver.RTT(remoteSSRC, RTT, avgRTT, minRTT, maxRTT);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Reset RoundTripTime statistics
|
2011-07-07 08:21:25 +00:00
|
|
|
WebRtc_Word32
|
2012-02-08 23:41:49 +00:00
|
|
|
ModuleRtpRtcpImpl::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ResetRTT(SSRC:%u)",
|
|
|
|
|
remoteSSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpReceiver.ResetRTT(remoteSSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Reset RTP statistics
|
2011-07-07 08:21:25 +00:00
|
|
|
WebRtc_Word32
|
2012-02-08 23:41:49 +00:00
|
|
|
ModuleRtpRtcpImpl::ResetStatisticsRTP() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ResetStatisticsRTP()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.ResetStatistics();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Reset RTP data counters for the receiving side
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::ResetReceiveDataCountersRTP() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"ResetReceiveDataCountersRTP()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.ResetDataCounters();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Reset RTP data counters for the sending side
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::ResetSendDataCountersRTP() {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"ResetSendDataCountersRTP()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.ResetDataCounters();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Force a send of an RTCP packet
|
|
|
|
|
// normal SR and RR are triggered via the process function
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCP(WebRtc_UWord32 rtcpPacketType) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendRTCP(0x%x)",
|
|
|
|
|
rtcpPacketType);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.SendRTCP(rtcpPacketType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPApplicationSpecificData(
|
|
|
|
|
const WebRtc_UWord8 subType,
|
|
|
|
|
const WebRtc_UWord32 name,
|
|
|
|
|
const WebRtc_UWord8* data,
|
|
|
|
|
const WebRtc_UWord16 length) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetRTCPApplicationSpecificData(subType:%d name:0x%x)", subType,
|
|
|
|
|
name);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.SetApplicationSpecificData(subType, name, data, length);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/*
|
|
|
|
|
* (XR) VOIP metric
|
|
|
|
|
*/
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPVoIPMetrics(
|
|
|
|
|
const RTCPVoIPMetric* VoIPMetric) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTCPVoIPMetrics()");
|
|
|
|
|
|
|
|
|
|
return _rtcpSender.SetRTCPVoIPMetrics(VoIPMetric);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// our localy created statistics of the received RTP stream
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::StatisticsRTP(
|
|
|
|
|
WebRtc_UWord8* fraction_lost,
|
|
|
|
|
WebRtc_UWord32* cum_lost,
|
|
|
|
|
WebRtc_UWord32* ext_max,
|
|
|
|
|
WebRtc_UWord32* jitter,
|
|
|
|
|
WebRtc_UWord32* max_jitter) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "StatisticsRTP()");
|
|
|
|
|
|
|
|
|
|
WebRtc_UWord32 jitter_transmission_time_offset = 0;
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 retVal = _rtpReceiver.Statistics(
|
|
|
|
|
fraction_lost,
|
|
|
|
|
cum_lost,
|
|
|
|
|
ext_max,
|
|
|
|
|
jitter,
|
|
|
|
|
max_jitter,
|
|
|
|
|
&jitter_transmission_time_offset,
|
|
|
|
|
(_rtcpSender.Status() == kRtcpOff));
|
|
|
|
|
if (retVal == -1) {
|
|
|
|
|
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
|
|
|
|
|
"StatisticsRTP() no statisitics availble");
|
|
|
|
|
}
|
|
|
|
|
return retVal;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DataCountersRTP(
|
|
|
|
|
WebRtc_UWord32* bytesSent,
|
|
|
|
|
WebRtc_UWord32* packetsSent,
|
|
|
|
|
WebRtc_UWord32* bytesReceived,
|
|
|
|
|
WebRtc_UWord32* packetsReceived) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "DataCountersRTP()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (bytesSent) {
|
|
|
|
|
*bytesSent = _rtpSender.Bytes();
|
|
|
|
|
}
|
|
|
|
|
if (packetsSent) {
|
|
|
|
|
*packetsSent = _rtpSender.Packets();
|
|
|
|
|
}
|
|
|
|
|
return _rtpReceiver.DataCounters(bytesReceived, packetsReceived);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::ReportBlockStatistics(
|
|
|
|
|
WebRtc_UWord8* fraction_lost,
|
|
|
|
|
WebRtc_UWord32* cum_lost,
|
|
|
|
|
WebRtc_UWord32* ext_max,
|
|
|
|
|
WebRtc_UWord32* jitter,
|
|
|
|
|
WebRtc_UWord32* jitter_transmission_time_offset) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ReportBlockStatistics()");
|
|
|
|
|
WebRtc_Word32 missing = 0;
|
|
|
|
|
WebRtc_Word32 ret = _rtpReceiver.Statistics(fraction_lost,
|
|
|
|
|
cum_lost,
|
|
|
|
|
ext_max,
|
|
|
|
|
jitter,
|
|
|
|
|
NULL,
|
|
|
|
|
jitter_transmission_time_offset,
|
|
|
|
|
&missing,
|
|
|
|
|
true);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
|
|
|
|
#ifdef MATLAB
|
2012-02-08 23:41:49 +00:00
|
|
|
if (_plot1 == NULL) {
|
|
|
|
|
_plot1 = eng.NewPlot(new MatlabPlot());
|
|
|
|
|
_plot1->AddTimeLine(30, "b", "lost", _clock.GetTimeInMS());
|
|
|
|
|
}
|
|
|
|
|
_plot1->Append("lost", missing);
|
|
|
|
|
_plot1->Plot();
|
2011-07-07 08:21:25 +00:00
|
|
|
#endif
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return ret;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat(RTCPSenderInfo* senderInfo) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpReceiver.SenderInfoReceived(senderInfo);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// received RTCP report
|
2012-01-11 13:00:08 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat(
|
|
|
|
|
std::vector<RTCPReportBlock>* receiveBlocks) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-01-11 13:00:08 +00:00
|
|
|
return _rtcpReceiver.StatisticsReceived(receiveBlocks);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::AddRTCPReportBlock(
|
|
|
|
|
const WebRtc_UWord32 SSRC,
|
|
|
|
|
const RTCPReportBlock* reportBlock) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "AddRTCPReportBlock()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.AddReportBlock(SSRC, reportBlock);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RemoveRTCPReportBlock(
|
|
|
|
|
const WebRtc_UWord32 SSRC) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoveRTCPReportBlock()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.RemoveReportBlock(SSRC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-12-22 10:26:13 +00:00
|
|
|
/*
|
|
|
|
|
* (REMB) Receiver Estimated Max Bitrate
|
|
|
|
|
*/
|
2012-02-08 23:41:49 +00:00
|
|
|
bool ModuleRtpRtcpImpl::REMB() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "REMB()");
|
2011-09-20 13:52:04 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.REMB();
|
2011-09-20 13:52:04 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
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);
|
2011-09-20 13:52:04 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetREMBData(const WebRtc_UWord32 bitrate,
|
|
|
|
|
const WebRtc_UWord8 numberOfSSRC,
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord32* SSRC) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetREMBData(bitrate:%d,?,?)", bitrate);
|
|
|
|
|
return _rtcpSender.SetREMBData(bitrate, numberOfSSRC, SSRC);
|
2011-09-20 13:52:04 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
bool ModuleRtpRtcpImpl::SetRemoteBitrateObserver(
|
|
|
|
|
RtpRemoteBitrateObserver* observer) {
|
|
|
|
|
return _rtcpSender.SetRemoteBitrateObserver(observer);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-22 10:26:13 +00:00
|
|
|
/*
|
|
|
|
|
* (IJ) Extended jitter report.
|
|
|
|
|
*/
|
2012-02-08 23:41:49 +00:00
|
|
|
bool ModuleRtpRtcpImpl::IJ() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "IJ()");
|
2011-12-16 14:31:37 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.IJ();
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetIJStatus(const bool enable) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetIJStatus(%s)", enable ? "true" : "false");
|
2011-12-16 14:31:37 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.SetIJStatus(enable);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendRtpHeaderExtension(
|
2012-02-08 23:41:49 +00:00
|
|
|
const RTPExtensionType type,
|
|
|
|
|
const WebRtc_UWord8 id) {
|
|
|
|
|
return _rtpSender.RegisterRtpHeaderExtension(type, id);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DeregisterSendRtpHeaderExtension(
|
2012-02-08 23:41:49 +00:00
|
|
|
const RTPExtensionType type) {
|
|
|
|
|
return _rtpSender.DeregisterRtpHeaderExtension(type);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceiveRtpHeaderExtension(
|
2012-02-08 23:41:49 +00:00
|
|
|
const RTPExtensionType type,
|
|
|
|
|
const WebRtc_UWord8 id) {
|
|
|
|
|
return _rtpReceiver.RegisterRtpHeaderExtension(type, id);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::DeregisterReceiveRtpHeaderExtension(
|
2012-02-08 23:41:49 +00:00
|
|
|
const RTPExtensionType type) {
|
|
|
|
|
return _rtpReceiver.DeregisterRtpHeaderExtension(type);
|
2011-12-16 14:31:37 +00:00
|
|
|
}
|
|
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
void ModuleRtpRtcpImpl::SetTransmissionSmoothingStatus(const bool enable) {
|
|
|
|
|
_rtpSender.SetTransmissionSmoothingStatus(enable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ModuleRtpRtcpImpl::TransmissionSmoothingStatus() const {
|
|
|
|
|
return _rtpSender.TransmissionSmoothingStatus();
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/*
|
|
|
|
|
* (TMMBR) Temporary Max Media Bit Rate
|
|
|
|
|
*/
|
|
|
|
|
bool ModuleRtpRtcpImpl::TMMBR() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TMMBR()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.TMMBR();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBRStatus(const bool enable) {
|
|
|
|
|
if (enable) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetTMMBRStatus(enable)");
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetTMMBRStatus(disable)");
|
|
|
|
|
}
|
|
|
|
|
return _rtcpSender.SetTMMBRStatus(enable);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-05 08:30:10 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBN(const TMMBRSet* boundingSet) {
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetTMMBN()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-04-05 08:30:10 +00:00
|
|
|
WebRtc_UWord32 maxBitrateKbit = _rtpSender.MaxConfiguredBitrateVideo() / 1000;
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.SetTMMBN(boundingSet, maxBitrateKbit);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/*
|
|
|
|
|
* (NACK) Negative acknowledgement
|
|
|
|
|
*/
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Is Negative acknowledgement requests on/off?
|
|
|
|
|
NACKMethod ModuleRtpRtcpImpl::NACK() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "NACK()");
|
|
|
|
|
|
|
|
|
|
NACKMethod childMethod = kNackOff;
|
|
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// for default we need to check all child modules too
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::const_iterator it =
|
|
|
|
|
_childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
|
|
|
|
NACKMethod nackMethod = module->NACK();
|
|
|
|
|
if (nackMethod != kNackOff) {
|
|
|
|
|
childMethod = nackMethod;
|
|
|
|
|
break;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
it++;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
NACKMethod method = _nackMethod;
|
|
|
|
|
if (childMethod != kNackOff) {
|
|
|
|
|
method = childMethod;
|
|
|
|
|
}
|
|
|
|
|
return method;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Turn negative acknowledgement requests on/off
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetNACKStatus(NACKMethod method) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetNACKStatus(%u)", method);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
_nackMethod = method;
|
|
|
|
|
_rtpReceiver.SetNACKStatus(method);
|
|
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-12-22 12:52:41 +00:00
|
|
|
// Returns the currently configured retransmission mode.
|
|
|
|
|
int ModuleRtpRtcpImpl::SelectiveRetransmissions() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SelectiveRetransmissions()");
|
|
|
|
|
return _rtpSender.SelectiveRetransmissions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Enable or disable a retransmission mode, which decides which packets will
|
|
|
|
|
// be retransmitted if NACKed.
|
|
|
|
|
int ModuleRtpRtcpImpl::SetSelectiveRetransmissions(uint8_t settings) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetSelectiveRetransmissions(%u)",
|
|
|
|
|
settings);
|
|
|
|
|
return _rtpSender.SetSelectiveRetransmissions(settings);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Send a Negative acknowledgement packet
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList,
|
|
|
|
|
const WebRtc_UWord16 size) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SendNACK(size:%u)", size);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
if (size > NACK_PACKETS_MAX_SIZE) {
|
2012-02-10 12:13:12 +00:00
|
|
|
RequestKeyFrame();
|
2012-02-08 23:41:49 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
WebRtc_UWord16 avgRTT = 0;
|
|
|
|
|
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), NULL, &avgRTT, NULL, NULL);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32 waitTime = 5 + ((avgRTT * 3) >> 1); // 5 + RTT*1.5
|
|
|
|
|
if (waitTime == 5) {
|
|
|
|
|
waitTime = 100; //During startup we don't have an RTT
|
|
|
|
|
}
|
|
|
|
|
const WebRtc_UWord32 now = _clock.GetTimeInMS();
|
|
|
|
|
const WebRtc_UWord32 timeLimit = now - waitTime;
|
|
|
|
|
|
|
|
|
|
if (_nackLastTimeSent < timeLimit) {
|
|
|
|
|
// send list
|
|
|
|
|
} else {
|
|
|
|
|
// only send if extended list
|
|
|
|
|
if (_nackLastSeqNumberSent == nackList[size - 1]) {
|
|
|
|
|
// last seq num is the same don't send list
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
// send list
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
_nackLastTimeSent = now;
|
|
|
|
|
_nackLastSeqNumberSent = nackList[size - 1];
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
switch (_nackMethod) {
|
2011-07-07 08:21:25 +00:00
|
|
|
case kNackRtcp:
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.SendRTCP(kRtcpNack, size, nackList);
|
2011-07-07 08:21:25 +00:00
|
|
|
case kNackOff:
|
2012-02-08 23:41:49 +00:00
|
|
|
return -1;
|
|
|
|
|
};
|
|
|
|
|
return -1;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Store the sent packets, needed to answer to a Negative acknowledgement
|
|
|
|
|
// requests
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetStorePacketsStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const WebRtc_UWord16 numberToStore) {
|
|
|
|
|
if (enable) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetStorePacketsStatus(enable, numberToStore:%d)",
|
|
|
|
|
numberToStore);
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetStorePacketsStatus(disable)");
|
|
|
|
|
}
|
|
|
|
|
return _rtpSender.SetStorePacketsStatus(enable, numberToStore);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/*
|
|
|
|
|
* Audio
|
|
|
|
|
*/
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Outband TelephoneEvent detection
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetTelephoneEventStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const bool forwardToDecoder,
|
|
|
|
|
const bool detectEndOfTone) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetTelephoneEventStatus(enable:%d forwardToDecoder:%d"
|
|
|
|
|
" detectEndOfTone:%d)", enable, forwardToDecoder,
|
|
|
|
|
detectEndOfTone);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.SetTelephoneEventStatus(enable, forwardToDecoder,
|
|
|
|
|
detectEndOfTone);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Is outband TelephoneEvent turned on/off?
|
|
|
|
|
bool ModuleRtpRtcpImpl::TelephoneEvent() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TelephoneEvent()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.TelephoneEvent();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Is forwarding of outband telephone events turned on/off?
|
|
|
|
|
bool ModuleRtpRtcpImpl::TelephoneEventForwardToDecoder() const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"TelephoneEventForwardToDecoder()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.TelephoneEventForwardToDecoder();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Send a TelephoneEvent tone using RFC 2833 (4733)
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendTelephoneEventOutband(
|
|
|
|
|
const WebRtc_UWord8 key,
|
|
|
|
|
const WebRtc_UWord16 timeMs,
|
|
|
|
|
const WebRtc_UWord8 level) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SendTelephoneEventOutband(key:%u, timeMs:%u, level:%u)", key,
|
|
|
|
|
timeMs, level);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SendTelephoneEvent(key, timeMs, level);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
bool ModuleRtpRtcpImpl::SendTelephoneEventActive(
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word8& telephoneEvent) const {
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SendTelephoneEventActive()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SendTelephoneEventActive(telephoneEvent);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
// set audio packet size, used to determine when it's time to send a DTMF
|
|
|
|
|
// packet in silence (CNG)
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetAudioPacketSize(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord16 packetSizeSamples) {
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetAudioPacketSize(%u)",
|
|
|
|
|
packetSizeSamples);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SetAudioPacketSize(packetSizeSamples);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetRTPAudioLevelIndicationStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const WebRtc_UWord8 ID) {
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2012-01-04 17:04:51 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetRTPAudioLevelIndicationStatus(enable=%d, ID=%u)",
|
|
|
|
|
enable,
|
|
|
|
|
ID);
|
|
|
|
|
|
|
|
|
|
if (enable) {
|
|
|
|
|
_rtpReceiver.RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, ID);
|
|
|
|
|
} else {
|
|
|
|
|
_rtpReceiver.DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
|
|
|
|
|
}
|
|
|
|
|
return _rtpSender.SetAudioLevelIndicationStatus(enable, ID);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::GetRTPAudioLevelIndicationStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
bool& enable,
|
|
|
|
|
WebRtc_UWord8& ID) const {
|
2011-10-13 15:19:55 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"GetRTPAudioLevelIndicationStatus()");
|
|
|
|
|
return _rtpSender.AudioLevelIndicationStatus(enable, ID);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetAudioLevel(const WebRtc_UWord8 level_dBov) {
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetAudioLevel(level_dBov:%u)",
|
|
|
|
|
level_dBov);
|
|
|
|
|
return _rtpSender.SetAudioLevel(level_dBov);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Set payload type for Redundant Audio Data RFC 2198
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetSendREDPayloadType(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_Word8 payloadType) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetSendREDPayloadType(%d)",
|
|
|
|
|
payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SetRED(payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
// Get payload type for Redundant Audio Data RFC 2198
|
|
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendREDPayloadType(
|
|
|
|
|
WebRtc_Word8& payloadType) const {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendREDPayloadType()");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.RED(payloadType);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
/*
|
|
|
|
|
* Video
|
|
|
|
|
*/
|
2011-10-13 15:19:55 +00:00
|
|
|
RtpVideoCodecTypes ModuleRtpRtcpImpl::ReceivedVideoCodec() const {
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.VideoCodecType();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
RtpVideoCodecTypes ModuleRtpRtcpImpl::SendVideoCodec() const {
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.VideoCodecType();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-27 05:25:53 +00:00
|
|
|
void ModuleRtpRtcpImpl::SetTargetSendBitrate(const uint32_t bitrate) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
|
|
|
|
|
"SetTargetSendBitrate: %ubit", bitrate);
|
2012-02-08 23:41:49 +00:00
|
|
|
|
2012-04-27 05:25:53 +00:00
|
|
|
const bool haveChildModules(_childModules.empty() ? false : true);
|
|
|
|
|
if (haveChildModules) {
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-04-27 05:25:53 +00:00
|
|
|
if (_simulcast) {
|
|
|
|
|
uint32_t bitrate_remainder = bitrate;
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
for (int i = 0; it != _childModules.end() &&
|
|
|
|
|
i < _sendVideoCodec.numberOfSimulcastStreams; ++it, ++i) {
|
|
|
|
|
RTPSender& rtpSender = (*it)->_rtpSender;
|
|
|
|
|
if (_sendVideoCodec.simulcastStream[i].maxBitrate > bitrate_remainder) {
|
|
|
|
|
rtpSender.SetTargetSendBitrate(
|
|
|
|
|
_sendVideoCodec.simulcastStream[i].maxBitrate);
|
|
|
|
|
bitrate_remainder -= _sendVideoCodec.simulcastStream[i].maxBitrate;
|
|
|
|
|
} else {
|
|
|
|
|
rtpSender.SetTargetSendBitrate(bitrate_remainder);
|
|
|
|
|
bitrate_remainder = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
for (; it != _childModules.end(); ++it) {
|
|
|
|
|
RTPSender& rtpSender = (*it)->_rtpSender;
|
|
|
|
|
rtpSender.SetTargetSendBitrate(bitrate);
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-04-27 05:25:53 +00:00
|
|
|
} else {
|
|
|
|
|
_rtpSender.SetTargetSendBitrate(bitrate);
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetKeyFrameRequestMethod(
|
2012-02-08 23:41:49 +00:00
|
|
|
const KeyFrameRequestMethod method) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetKeyFrameRequestMethod(method:%u)",
|
|
|
|
|
method);
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
_keyFrameReqMethod = method;
|
|
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-10 12:13:12 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::RequestKeyFrame() {
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
2012-02-10 12:13:12 +00:00
|
|
|
"RequestKeyFrame");
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-02-08 23:41:49 +00:00
|
|
|
switch (_keyFrameReqMethod) {
|
2011-07-07 08:21:25 +00:00
|
|
|
case kKeyFrameReqFirRtp:
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpSender.SendRTPIntraRequest();
|
2011-07-07 08:21:25 +00:00
|
|
|
case kKeyFrameReqPliRtcp:
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtcpSender.SendRTCP(kRtcpPli);
|
2012-02-10 12:13:12 +00:00
|
|
|
case kKeyFrameReqFirRtcp:
|
|
|
|
|
return _rtcpSender.SendRTCP(kRtcpFir);
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
return -1;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCPSliceLossIndication(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord8 pictureID) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SendRTCPSliceLossIndication (pictureID:%d)",
|
|
|
|
|
pictureID);
|
2012-02-10 12:13:12 +00:00
|
|
|
return _rtcpSender.SendRTCP(kRtcpSli, 0, 0, false, pictureID);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetCameraDelay(const WebRtc_Word32 delayMS) {
|
2012-02-08 23:41:49 +00:00
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetCameraDelay(%d)",
|
|
|
|
|
delayMS);
|
|
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
|
|
|
|
|
if (defaultInstance) {
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
|
|
|
|
module->SetCameraDelay(delayMS);
|
|
|
|
|
}
|
|
|
|
|
it++;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return _rtcpSender.SetCameraDelay(delayMS);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetGenericFECStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool enable,
|
|
|
|
|
const WebRtc_UWord8 payloadTypeRED,
|
|
|
|
|
const WebRtc_UWord8 payloadTypeFEC) {
|
|
|
|
|
if (enable) {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetGenericFECStatus(enable, %u)",
|
|
|
|
|
payloadTypeRED);
|
|
|
|
|
} else {
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall,
|
|
|
|
|
kTraceRtpRtcp,
|
|
|
|
|
_id,
|
|
|
|
|
"SetGenericFECStatus(disable)");
|
|
|
|
|
}
|
|
|
|
|
return _rtpSender.SetGenericFECStatus(enable,
|
|
|
|
|
payloadTypeRED,
|
|
|
|
|
payloadTypeFEC);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::GenericFECStatus(
|
2012-02-08 23:41:49 +00:00
|
|
|
bool& enable,
|
|
|
|
|
WebRtc_UWord8& payloadTypeRED,
|
|
|
|
|
WebRtc_UWord8& payloadTypeFEC) {
|
|
|
|
|
|
|
|
|
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "GenericFECStatus()");
|
|
|
|
|
|
|
|
|
|
bool childEnabled = false;
|
|
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// for default we need to check all child modules too
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
|
|
|
|
bool enabled = false;
|
|
|
|
|
WebRtc_UWord8 dummyPTypeRED = 0;
|
|
|
|
|
WebRtc_UWord8 dummyPTypeFEC = 0;
|
|
|
|
|
if (module->GenericFECStatus(enabled,
|
|
|
|
|
dummyPTypeRED,
|
|
|
|
|
dummyPTypeFEC) == 0 && enabled) {
|
|
|
|
|
childEnabled = true;
|
|
|
|
|
break;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
it++;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
WebRtc_Word32 retVal = _rtpSender.GenericFECStatus(enable,
|
|
|
|
|
payloadTypeRED,
|
|
|
|
|
payloadTypeFEC);
|
|
|
|
|
if (childEnabled) {
|
|
|
|
|
// returns true if enabled for any child module
|
|
|
|
|
enable = childEnabled;
|
|
|
|
|
}
|
|
|
|
|
return retVal;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-20 22:10:56 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SetFecParameters(
|
|
|
|
|
const FecProtectionParams* delta_params,
|
|
|
|
|
const FecProtectionParams* key_params) {
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// for default we need to update all child modules too
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
2012-02-08 23:41:49 +00:00
|
|
|
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
2012-03-20 22:10:56 +00:00
|
|
|
module->SetFecParameters(delta_params, key_params);
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
it++;
|
2011-07-15 21:32:40 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2012-03-20 22:10:56 +00:00
|
|
|
return _rtpSender.SetFecParameters(delta_params, key_params);
|
2011-07-15 21:32:40 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
void ModuleRtpRtcpImpl::SetRemoteSSRC(const WebRtc_UWord32 SSRC) {
|
2012-02-08 23:41:49 +00:00
|
|
|
// inform about the incoming SSRC
|
|
|
|
|
_rtcpSender.SetRemoteSSRC(SSRC);
|
|
|
|
|
_rtcpReceiver.SetRemoteSSRC(SSRC);
|
|
|
|
|
|
|
|
|
|
// check for a SSRC collision
|
|
|
|
|
if (_rtpSender.SSRC() == SSRC && !_collisionDetected) {
|
|
|
|
|
// if we detect a collision change the SSRC but only once
|
|
|
|
|
_collisionDetected = true;
|
|
|
|
|
WebRtc_UWord32 newSSRC = _rtpSender.GenerateNewSSRC();
|
|
|
|
|
if (newSSRC == 0) {
|
|
|
|
|
// configured via API ignore
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (kRtcpOff != _rtcpSender.Status()) {
|
|
|
|
|
// send RTCP bye on the current SSRC
|
|
|
|
|
_rtcpSender.SendRTCP(kRtcpBye);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
// change local SSRC
|
|
|
|
|
|
|
|
|
|
// inform all objects about the new SSRC
|
|
|
|
|
_rtcpSender.SetSSRC(newSSRC);
|
|
|
|
|
_rtcpReceiver.SetSSRC(newSSRC);
|
|
|
|
|
}
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::BitrateReceivedNow() const {
|
2012-02-08 23:41:49 +00:00
|
|
|
return _rtpReceiver.BitrateNow();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-14 14:24:54 +00:00
|
|
|
void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
|
2011-10-27 16:08:29 +00:00
|
|
|
WebRtc_UWord32* videoRate,
|
|
|
|
|
WebRtc_UWord32* fecRate,
|
|
|
|
|
WebRtc_UWord32* nackRate) const {
|
2012-02-08 23:41:49 +00:00
|
|
|
const bool defaultInstance(_childModules.empty() ? false : true);
|
|
|
|
|
|
|
|
|
|
if (defaultInstance) {
|
|
|
|
|
// for default we need to update the send bitrate
|
2012-05-10 23:01:04 +00:00
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);
|
2012-02-08 23:41:49 +00:00
|
|
|
|
2011-10-14 14:24:54 +00:00
|
|
|
if (totalRate != NULL)
|
2012-02-08 23:41:49 +00:00
|
|
|
*totalRate = 0;
|
2011-10-27 16:08:29 +00:00
|
|
|
if (videoRate != NULL)
|
2012-02-08 23:41:49 +00:00
|
|
|
*videoRate = 0;
|
2011-10-14 14:24:54 +00:00
|
|
|
if (fecRate != NULL)
|
2012-02-08 23:41:49 +00:00
|
|
|
*fecRate = 0;
|
2011-10-14 14:24:54 +00:00
|
|
|
if (nackRate != NULL)
|
2012-02-08 23:41:49 +00:00
|
|
|
*nackRate = 0;
|
|
|
|
|
|
|
|
|
|
std::list<ModuleRtpRtcpImpl*>::const_iterator it =
|
|
|
|
|
_childModules.begin();
|
|
|
|
|
while (it != _childModules.end()) {
|
|
|
|
|
RtpRtcp* module = *it;
|
|
|
|
|
if (module) {
|
|
|
|
|
WebRtc_UWord32 childTotalRate = 0;
|
|
|
|
|
WebRtc_UWord32 childVideoRate = 0;
|
|
|
|
|
WebRtc_UWord32 childFecRate = 0;
|
|
|
|
|
WebRtc_UWord32 childNackRate = 0;
|
|
|
|
|
module->BitrateSent(&childTotalRate,
|
|
|
|
|
&childVideoRate,
|
|
|
|
|
&childFecRate,
|
|
|
|
|
&childNackRate);
|
|
|
|
|
if (totalRate != NULL && childTotalRate > *totalRate)
|
|
|
|
|
*totalRate = childTotalRate;
|
|
|
|
|
if (videoRate != NULL && childVideoRate > *videoRate)
|
|
|
|
|
*videoRate = childVideoRate;
|
|
|
|
|
if (fecRate != NULL && childFecRate > *fecRate)
|
|
|
|
|
*fecRate = childFecRate;
|
|
|
|
|
if (nackRate != NULL && childNackRate > *nackRate)
|
|
|
|
|
*nackRate = childNackRate;
|
|
|
|
|
}
|
|
|
|
|
it++;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (totalRate != NULL)
|
|
|
|
|
*totalRate = _rtpSender.BitrateLast();
|
|
|
|
|
if (videoRate != NULL)
|
|
|
|
|
*videoRate = _rtpSender.VideoBitrateSent();
|
|
|
|
|
if (fecRate != NULL)
|
|
|
|
|
*fecRate = _rtpSender.FecOverheadRate();
|
|
|
|
|
if (nackRate != NULL)
|
|
|
|
|
*nackRate = _rtpSender.NackOverheadRate();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-16 14:45:37 +00:00
|
|
|
int ModuleRtpRtcpImpl::EstimatedReceiveBandwidth(
|
|
|
|
|
WebRtc_UWord32* available_bandwidth) const {
|
|
|
|
|
if (!_rtcpSender.ValidBitrateEstimate())
|
|
|
|
|
return -1;
|
|
|
|
|
*available_bandwidth = _rtcpSender.LatestBandwidthEstimate();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-10 23:01:04 +00:00
|
|
|
// for lip sync
|
|
|
|
|
void ModuleRtpRtcpImpl::OnReceivedNTP() {
|
|
|
|
|
// don't do anything if we are the audio module
|
|
|
|
|
// video module is responsible for sync
|
|
|
|
|
if (!_audio) {
|
|
|
|
|
WebRtc_Word32 diff = 0;
|
|
|
|
|
WebRtc_UWord32 receivedNTPsecs = 0;
|
|
|
|
|
WebRtc_UWord32 receivedNTPfrac = 0;
|
|
|
|
|
WebRtc_UWord32 RTCPArrivalTimeSecs = 0;
|
|
|
|
|
WebRtc_UWord32 RTCPArrivalTimeFrac = 0;
|
|
|
|
|
|
|
|
|
|
if (0 == _rtcpReceiver.NTP(&receivedNTPsecs,
|
|
|
|
|
&receivedNTPfrac,
|
|
|
|
|
&RTCPArrivalTimeSecs,
|
|
|
|
|
&RTCPArrivalTimeFrac)) {
|
|
|
|
|
CriticalSectionScoped lock(_criticalSectionModulePtrs);
|
|
|
|
|
|
|
|
|
|
if (_audioModule) {
|
|
|
|
|
if (0 != _audioModule->RemoteNTP(&_receivedNTPsecsAudio,
|
|
|
|
|
&_receivedNTPfracAudio,
|
|
|
|
|
&_RTCPArrivalTimeSecsAudio,
|
|
|
|
|
&_RTCPArrivalTimeFracAudio)) {
|
|
|
|
|
// failed ot get audio NTP
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (_receivedNTPfracAudio != 0) {
|
|
|
|
|
// ReceivedNTPxxx is NTP at sender side when sent.
|
|
|
|
|
// RTCPArrivalTimexxx is NTP at receiver side when received.
|
|
|
|
|
// can't use ConvertNTPTimeToMS since calculation can be
|
|
|
|
|
// negative
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 NTPdiff = (WebRtc_Word32)
|
|
|
|
|
((_receivedNTPsecsAudio - receivedNTPsecs) *
|
|
|
|
|
1000); // ms
|
|
|
|
|
NTPdiff += (WebRtc_Word32)
|
|
|
|
|
(_receivedNTPfracAudio / FracMS - receivedNTPfrac / FracMS);
|
|
|
|
|
|
|
|
|
|
WebRtc_Word32 RTCPdiff =
|
|
|
|
|
static_cast<WebRtc_Word32> ((_RTCPArrivalTimeSecsAudio -
|
|
|
|
|
RTCPArrivalTimeSecs) * 1000);
|
|
|
|
|
RTCPdiff += (WebRtc_Word32)
|
|
|
|
|
(_RTCPArrivalTimeFracAudio / FracMS -
|
|
|
|
|
RTCPArrivalTimeFrac / FracMS);
|
|
|
|
|
|
|
|
|
|
diff = NTPdiff - RTCPdiff;
|
|
|
|
|
// if diff is + video is behind
|
|
|
|
|
if (diff < -1000 || diff > 1000) {
|
|
|
|
|
// unresonable ignore value.
|
|
|
|
|
diff = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// export via callback
|
|
|
|
|
// after release of critsect
|
|
|
|
|
_rtcpReceiver.UpdateLipSync(diff);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate(
|
2012-02-08 23:41:49 +00:00
|
|
|
const RateControlInput& rateControlInput) {
|
|
|
|
|
|
|
|
|
|
bool firstOverUse = false;
|
|
|
|
|
RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput,
|
|
|
|
|
firstOverUse);
|
|
|
|
|
if (firstOverUse) {
|
|
|
|
|
// Send TMMBR or REMB immediately.
|
|
|
|
|
WebRtc_UWord16 RTT = 0;
|
|
|
|
|
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL);
|
|
|
|
|
// About to send TMMBR, first run remote rate control
|
|
|
|
|
// to get a target bit rate.
|
|
|
|
|
unsigned int target_bitrate =
|
|
|
|
|
_rtcpSender.CalculateNewTargetBitrate(RTT);
|
|
|
|
|
if (REMB()) {
|
|
|
|
|
_rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
|
|
|
|
|
} else if (TMMBR()) {
|
|
|
|
|
_rtcpSender.SendRTCP(kRtcpTmmbr);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2012-02-08 23:41:49 +00:00
|
|
|
}
|
|
|
|
|
return region;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// bad state of RTP receiver request a keyframe
|
2012-02-10 12:13:12 +00:00
|
|
|
void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
|
|
|
|
|
RequestKeyFrame();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
void ModuleRtpRtcpImpl::OnRequestSendReport() {
|
2012-02-08 23:41:49 +00:00
|
|
|
_rtcpSender.SendRTCP(kRtcpSr);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord64 pictureID) {
|
2012-02-10 12:13:12 +00:00
|
|
|
return _rtcpSender.SendRTCP(kRtcpRpsi, 0, 0, false, pictureID);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_UWord32 ModuleRtpRtcpImpl::SendTimeOfSendReport(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord32 sendReport) {
|
|
|
|
|
return _rtcpSender.SendTimeOfSendReport(sendReport);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
void ModuleRtpRtcpImpl::OnReceivedNACK(
|
2012-02-08 23:41:49 +00:00
|
|
|
const WebRtc_UWord16 nackSequenceNumbersLength,
|
|
|
|
|
const WebRtc_UWord16* nackSequenceNumbers) {
|
|
|
|
|
if (!_rtpSender.StorePackets() ||
|
|
|
|
|
nackSequenceNumbers == NULL ||
|
|
|
|
|
nackSequenceNumbersLength == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
WebRtc_UWord16 avgRTT = 0;
|
|
|
|
|
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), NULL, &avgRTT, NULL, NULL);
|
|
|
|
|
_rtpSender.OnReceivedNACK(nackSequenceNumbersLength,
|
|
|
|
|
nackSequenceNumbers,
|
|
|
|
|
avgRTT);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::LastReceivedNTP(
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_UWord32& RTCPArrivalTimeSecs, // when we received the last report
|
|
|
|
|
WebRtc_UWord32& RTCPArrivalTimeFrac,
|
|
|
|
|
WebRtc_UWord32& remoteSR) {
|
|
|
|
|
// remote SR: NTP inside the last received (mid 16 bits from sec and frac)
|
|
|
|
|
WebRtc_UWord32 NTPsecs = 0;
|
|
|
|
|
WebRtc_UWord32 NTPfrac = 0;
|
|
|
|
|
|
|
|
|
|
if (-1 == _rtcpReceiver.NTP(&NTPsecs,
|
|
|
|
|
&NTPfrac,
|
|
|
|
|
&RTCPArrivalTimeSecs,
|
|
|
|
|
&RTCPArrivalTimeFrac)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
remoteSR = ((NTPsecs & 0x0000ffff) << 16) + ((NTPfrac & 0xffff0000) >> 16);
|
|
|
|
|
return 0;
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-13 15:19:55 +00:00
|
|
|
bool ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() {
|
2012-02-08 23:41:49 +00:00
|
|
|
// if this returns true this channel has timed out
|
|
|
|
|
// periodically check if this is true and if so call UpdateTMMBR
|
|
|
|
|
return _rtcpReceiver.UpdateRTCPReceiveInformationTimers();
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// called from RTCPsender
|
2012-02-08 23:41:49 +00:00
|
|
|
WebRtc_Word32 ModuleRtpRtcpImpl::BoundingSet(bool& tmmbrOwner,
|
2011-10-13 15:19:55 +00:00
|
|
|
TMMBRSet*& boundingSet) {
|
2012-04-05 08:30:10 +00:00
|
|
|
return _rtcpReceiver.BoundingSet(tmmbrOwner, boundingSet);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
2011-10-13 15:19:55 +00:00
|
|
|
} // namespace webrtc
|