Revert r4322 "Support sending multiple report blocks and keeping track of statistics on
several SSRCs" R=pwestin@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1774006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4344 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
6f5707e184
commit
b7eda43810
@ -171,7 +171,6 @@
|
|||||||
'rtp_rtcp/source/nack_rtx_unittest.cc',
|
'rtp_rtcp/source/nack_rtx_unittest.cc',
|
||||||
'rtp_rtcp/source/producer_fec_unittest.cc',
|
'rtp_rtcp/source/producer_fec_unittest.cc',
|
||||||
'rtp_rtcp/source/receiver_fec_unittest.cc',
|
'rtp_rtcp/source/receiver_fec_unittest.cc',
|
||||||
'rtp_rtcp/source/receive_statistics_unittest.cc',
|
|
||||||
'rtp_rtcp/source/rtcp_format_remb_unittest.cc',
|
'rtp_rtcp/source/rtcp_format_remb_unittest.cc',
|
||||||
'rtp_rtcp/source/rtcp_sender_unittest.cc',
|
'rtp_rtcp/source/rtcp_sender_unittest.cc',
|
||||||
'rtp_rtcp/source/rtcp_receiver_unittest.cc',
|
'rtp_rtcp/source/rtcp_receiver_unittest.cc',
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_
|
#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_
|
||||||
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_
|
#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "webrtc/modules/interface/module.h"
|
#include "webrtc/modules/interface/module.h"
|
||||||
#include "webrtc/modules/interface/module_common_types.h"
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
#include "webrtc/typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
@ -21,16 +19,9 @@ namespace webrtc {
|
|||||||
|
|
||||||
class Clock;
|
class Clock;
|
||||||
|
|
||||||
class StreamStatistician {
|
class ReceiveStatistics : public Module {
|
||||||
public:
|
public:
|
||||||
struct Statistics {
|
struct RtpReceiveStatistics {
|
||||||
Statistics()
|
|
||||||
: fraction_lost(0),
|
|
||||||
cumulative_lost(0),
|
|
||||||
extended_max_sequence_number(0),
|
|
||||||
jitter(0),
|
|
||||||
max_jitter(0) {}
|
|
||||||
|
|
||||||
uint8_t fraction_lost;
|
uint8_t fraction_lost;
|
||||||
uint32_t cumulative_lost;
|
uint32_t cumulative_lost;
|
||||||
uint32_t extended_max_sequence_number;
|
uint32_t extended_max_sequence_number;
|
||||||
@ -38,36 +29,26 @@ class StreamStatistician {
|
|||||||
uint32_t max_jitter;
|
uint32_t max_jitter;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~StreamStatistician();
|
|
||||||
|
|
||||||
virtual bool GetStatistics(Statistics* statistics, bool reset) = 0;
|
|
||||||
virtual void GetDataCounters(uint32_t* bytes_received,
|
|
||||||
uint32_t* packets_received) const = 0;
|
|
||||||
virtual uint32_t BitrateReceived() const = 0;
|
|
||||||
// Resets all statistics.
|
|
||||||
virtual void ResetStatistics() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReceiveStatistics : public Module {
|
|
||||||
public:
|
|
||||||
typedef std::map<uint32_t, StreamStatistician*> StatisticianMap;
|
|
||||||
|
|
||||||
virtual ~ReceiveStatistics() {}
|
virtual ~ReceiveStatistics() {}
|
||||||
|
|
||||||
static ReceiveStatistics* Create(Clock* clock);
|
static ReceiveStatistics* Create(Clock* clock);
|
||||||
|
|
||||||
// Updates the receive statistics with this packet.
|
|
||||||
virtual void IncomingPacket(const RTPHeader& rtp_header, size_t bytes,
|
virtual void IncomingPacket(const RTPHeader& rtp_header, size_t bytes,
|
||||||
bool retransmitted, bool in_order) = 0;
|
bool retransmitted, bool in_order) = 0;
|
||||||
|
|
||||||
// Returns a map of all statisticians which have seen an incoming packet
|
virtual bool Statistics(RtpReceiveStatistics* statistics, bool reset) = 0;
|
||||||
// during the last two seconds.
|
|
||||||
virtual void GetActiveStatisticians(
|
|
||||||
StatisticianMap* statisticians) const = 0;
|
|
||||||
|
|
||||||
// Returns a pointer to the statistician of an ssrc.
|
virtual bool Statistics(RtpReceiveStatistics* statistics, int32_t* missing,
|
||||||
virtual StreamStatistician* GetStatistician(uint32_t ssrc) const = 0;
|
bool reset) = 0;
|
||||||
|
|
||||||
|
virtual void GetDataCounters(uint32_t* bytes_received,
|
||||||
|
uint32_t* packets_received) const = 0;
|
||||||
|
|
||||||
|
virtual uint32_t BitrateReceived() = 0;
|
||||||
|
|
||||||
|
virtual void ResetStatistics() = 0;
|
||||||
|
|
||||||
|
virtual void ResetDataCounters() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_
|
#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_
|
||||||
|
@ -205,13 +205,13 @@ public:
|
|||||||
const uint32_t rate) = 0;
|
const uint32_t rate) = 0;
|
||||||
|
|
||||||
virtual void OnIncomingSSRCChanged( const int32_t id,
|
virtual void OnIncomingSSRCChanged( const int32_t id,
|
||||||
const uint32_t ssrc) = 0;
|
const uint32_t SSRC) = 0;
|
||||||
|
|
||||||
virtual void OnIncomingCSRCChanged( const int32_t id,
|
virtual void OnIncomingCSRCChanged( const int32_t id,
|
||||||
const uint32_t CSRC,
|
const uint32_t CSRC,
|
||||||
const bool added) = 0;
|
const bool added) = 0;
|
||||||
|
|
||||||
virtual void OnResetStatistics(uint32_t ssrc) = 0;
|
virtual void OnResetStatistics() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~RtpFeedback() {}
|
virtual ~RtpFeedback() {}
|
||||||
@ -281,13 +281,13 @@ class NullRtpFeedback : public RtpFeedback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnIncomingSSRCChanged(const int32_t id,
|
virtual void OnIncomingSSRCChanged(const int32_t id,
|
||||||
const uint32_t ssrc) {}
|
const uint32_t SSRC) {}
|
||||||
|
|
||||||
virtual void OnIncomingCSRCChanged(const int32_t id,
|
virtual void OnIncomingCSRCChanged(const int32_t id,
|
||||||
const uint32_t CSRC,
|
const uint32_t CSRC,
|
||||||
const bool added) {}
|
const bool added) {}
|
||||||
|
|
||||||
virtual void OnResetStatistics(uint32_t ssrc) {}
|
virtual void OnResetStatistics() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Null object version of RtpData.
|
// Null object version of RtpData.
|
||||||
|
@ -56,8 +56,8 @@ class TestRtpFeedback : public NullRtpFeedback {
|
|||||||
virtual ~TestRtpFeedback() {}
|
virtual ~TestRtpFeedback() {}
|
||||||
|
|
||||||
virtual void OnIncomingSSRCChanged(const int32_t id,
|
virtual void OnIncomingSSRCChanged(const int32_t id,
|
||||||
const uint32_t ssrc) {
|
const uint32_t SSRC) {
|
||||||
rtp_rtcp_->SetRemoteSSRC(ssrc);
|
rtp_rtcp_->SetRemoteSSRC(SSRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -17,39 +17,41 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
const int64_t kStatisticsTimeoutMs = 8000;
|
enum { kRateUpdateIntervalMs = 1000 };
|
||||||
const int kStatisticsProcessIntervalMs = 1000;
|
|
||||||
|
|
||||||
StreamStatistician::~StreamStatistician() {}
|
ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) {
|
||||||
|
return new ReceiveStatisticsImpl(clock);
|
||||||
|
}
|
||||||
|
|
||||||
StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock)
|
ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
|
||||||
: clock_(clock),
|
: crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
clock_(clock),
|
||||||
incoming_bitrate_(clock),
|
incoming_bitrate_(clock),
|
||||||
ssrc_(0),
|
ssrc_(0),
|
||||||
jitter_q4_(0),
|
jitter_q4_(0),
|
||||||
jitter_max_q4_(0),
|
jitter_max_q4_(0),
|
||||||
cumulative_loss_(0),
|
cumulative_loss_(0),
|
||||||
jitter_q4_transmission_time_offset_(0),
|
jitter_q4_transmission_time_offset_(0),
|
||||||
last_receive_time_secs_(0),
|
local_time_last_received_timestamp_(0),
|
||||||
last_receive_time_frac_(0),
|
|
||||||
last_received_timestamp_(0),
|
last_received_timestamp_(0),
|
||||||
last_received_transmission_time_offset_(0),
|
last_received_transmission_time_offset_(0),
|
||||||
|
|
||||||
received_seq_first_(0),
|
received_seq_first_(0),
|
||||||
received_seq_max_(0),
|
received_seq_max_(0),
|
||||||
received_seq_wraps_(0),
|
received_seq_wraps_(0),
|
||||||
first_packet_(true),
|
|
||||||
received_packet_oh_(12),
|
received_packet_oh_(12), // RTP header.
|
||||||
received_byte_count_(0),
|
received_byte_count_(0),
|
||||||
received_retransmitted_packets_(0),
|
received_retransmitted_packets_(0),
|
||||||
received_inorder_packet_count_(0),
|
received_inorder_packet_count_(0),
|
||||||
|
|
||||||
last_report_inorder_packets_(0),
|
last_report_inorder_packets_(0),
|
||||||
last_report_old_packets_(0),
|
last_report_old_packets_(0),
|
||||||
last_report_seq_max_(0),
|
last_report_seq_max_(0),
|
||||||
last_reported_statistics_() {}
|
last_reported_statistics_() {}
|
||||||
|
|
||||||
void StreamStatisticianImpl::ResetStatistics() {
|
void ReceiveStatisticsImpl::ResetStatistics() {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
last_report_inorder_packets_ = 0;
|
last_report_inorder_packets_ = 0;
|
||||||
last_report_old_packets_ = 0;
|
last_report_old_packets_ = 0;
|
||||||
last_report_seq_max_ = 0;
|
last_report_seq_max_ = 0;
|
||||||
@ -64,33 +66,33 @@ void StreamStatisticianImpl::ResetStatistics() {
|
|||||||
received_byte_count_ = 0;
|
received_byte_count_ = 0;
|
||||||
received_retransmitted_packets_ = 0;
|
received_retransmitted_packets_ = 0;
|
||||||
received_inorder_packet_count_ = 0;
|
received_inorder_packet_count_ = 0;
|
||||||
first_packet_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamStatisticianImpl::ResetDataCounters() {
|
void ReceiveStatisticsImpl::ResetDataCounters() {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
received_byte_count_ = 0;
|
received_byte_count_ = 0;
|
||||||
received_retransmitted_packets_ = 0;
|
received_retransmitted_packets_ = 0;
|
||||||
received_inorder_packet_count_ = 0;
|
received_inorder_packet_count_ = 0;
|
||||||
last_report_inorder_packets_ = 0;
|
last_report_inorder_packets_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
|
||||||
size_t bytes,
|
size_t bytes,
|
||||||
bool retransmitted,
|
bool retransmitted,
|
||||||
bool in_order) {
|
bool in_order) {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
ssrc_ = header.ssrc;
|
ssrc_ = header.ssrc;
|
||||||
incoming_bitrate_.Update(bytes);
|
incoming_bitrate_.Update(bytes);
|
||||||
|
|
||||||
received_byte_count_ += bytes;
|
received_byte_count_ += bytes;
|
||||||
|
|
||||||
if (first_packet_) {
|
if (received_seq_max_ == 0 && received_seq_wraps_ == 0) {
|
||||||
first_packet_ = false;
|
|
||||||
// This is the first received report.
|
// This is the first received report.
|
||||||
received_seq_first_ = header.sequenceNumber;
|
received_seq_first_ = header.sequenceNumber;
|
||||||
received_seq_max_ = header.sequenceNumber;
|
received_seq_max_ = header.sequenceNumber;
|
||||||
received_inorder_packet_count_ = 1;
|
received_inorder_packet_count_ = 1;
|
||||||
clock_->CurrentNtp(last_receive_time_secs_, last_receive_time_frac_);
|
// Current time in samples.
|
||||||
|
local_time_last_received_timestamp_ =
|
||||||
|
ModuleRTPUtility::GetCurrentRTP(clock_, header.payload_type_frequency);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,9 +100,8 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
|||||||
// are received, 4 will be ignored.
|
// are received, 4 will be ignored.
|
||||||
if (in_order) {
|
if (in_order) {
|
||||||
// Current time in samples.
|
// Current time in samples.
|
||||||
uint32_t receive_time_secs;
|
const uint32_t RTPtime =
|
||||||
uint32_t receive_time_frac;
|
ModuleRTPUtility::GetCurrentRTP(clock_, header.payload_type_frequency);
|
||||||
clock_->CurrentNtp(receive_time_secs, receive_time_frac);
|
|
||||||
received_inorder_packet_count_++;
|
received_inorder_packet_count_++;
|
||||||
|
|
||||||
// Wrong if we use RetransmitOfOldPacket.
|
// Wrong if we use RetransmitOfOldPacket.
|
||||||
@ -115,12 +116,8 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
|||||||
|
|
||||||
if (header.timestamp != last_received_timestamp_ &&
|
if (header.timestamp != last_received_timestamp_ &&
|
||||||
received_inorder_packet_count_ > 1) {
|
received_inorder_packet_count_ > 1) {
|
||||||
uint32_t receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP(
|
int32_t time_diff_samples =
|
||||||
receive_time_secs, receive_time_frac, header.payload_type_frequency);
|
(RTPtime - local_time_last_received_timestamp_) -
|
||||||
uint32_t last_receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP(
|
|
||||||
last_receive_time_secs_, last_receive_time_frac_,
|
|
||||||
header.payload_type_frequency);
|
|
||||||
int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) -
|
|
||||||
(header.timestamp - last_received_timestamp_);
|
(header.timestamp - last_received_timestamp_);
|
||||||
|
|
||||||
time_diff_samples = abs(time_diff_samples);
|
time_diff_samples = abs(time_diff_samples);
|
||||||
@ -137,7 +134,7 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
|||||||
// Extended jitter report, RFC 5450.
|
// Extended jitter report, RFC 5450.
|
||||||
// Actual network jitter, excluding the source-introduced jitter.
|
// Actual network jitter, excluding the source-introduced jitter.
|
||||||
int32_t time_diff_samples_ext =
|
int32_t time_diff_samples_ext =
|
||||||
(receive_time_rtp - last_receive_time_rtp) -
|
(RTPtime - local_time_last_received_timestamp_) -
|
||||||
((header.timestamp +
|
((header.timestamp +
|
||||||
header.extension.transmissionTimeOffset) -
|
header.extension.transmissionTimeOffset) -
|
||||||
(last_received_timestamp_ +
|
(last_received_timestamp_ +
|
||||||
@ -153,8 +150,7 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_received_timestamp_ = header.timestamp;
|
last_received_timestamp_ = header.timestamp;
|
||||||
last_receive_time_secs_ = receive_time_secs;
|
local_time_last_received_timestamp_ = RTPtime;
|
||||||
last_receive_time_frac_ = receive_time_frac;
|
|
||||||
} else {
|
} else {
|
||||||
if (retransmitted) {
|
if (retransmitted) {
|
||||||
received_retransmitted_packets_++;
|
received_retransmitted_packets_++;
|
||||||
@ -170,8 +166,19 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
|||||||
received_packet_oh_ = (15 * received_packet_oh_ + packet_oh) >> 4;
|
received_packet_oh_ = (15 * received_packet_oh_ + packet_oh) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) {
|
bool ReceiveStatisticsImpl::Statistics(RtpReceiveStatistics* statistics,
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
bool reset) {
|
||||||
|
int32_t missing;
|
||||||
|
return Statistics(statistics, &missing, reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReceiveStatisticsImpl::Statistics(RtpReceiveStatistics* statistics,
|
||||||
|
int32_t* missing, bool reset) {
|
||||||
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
|
||||||
|
if (missing == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (received_seq_first_ == 0 && received_byte_count_ == 0) {
|
if (received_seq_first_ == 0 && received_byte_count_ == 0) {
|
||||||
// We have not received anything.
|
// We have not received anything.
|
||||||
return false;
|
return false;
|
||||||
@ -216,19 +223,19 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) {
|
|||||||
received_retransmitted_packets_ - last_report_old_packets_;
|
received_retransmitted_packets_ - last_report_old_packets_;
|
||||||
rec_since_last += retransmitted_packets;
|
rec_since_last += retransmitted_packets;
|
||||||
|
|
||||||
int32_t missing = 0;
|
*missing = 0;
|
||||||
if (exp_since_last > rec_since_last) {
|
if (exp_since_last > rec_since_last) {
|
||||||
missing = (exp_since_last - rec_since_last);
|
*missing = (exp_since_last - rec_since_last);
|
||||||
}
|
}
|
||||||
uint8_t local_fraction_lost = 0;
|
uint8_t local_fraction_lost = 0;
|
||||||
if (exp_since_last) {
|
if (exp_since_last) {
|
||||||
// Scale 0 to 255, where 255 is 100% loss.
|
// Scale 0 to 255, where 255 is 100% loss.
|
||||||
local_fraction_lost = (uint8_t)((255 * (missing)) / exp_since_last);
|
local_fraction_lost = (uint8_t)((255 * (*missing)) / exp_since_last);
|
||||||
}
|
}
|
||||||
statistics->fraction_lost = local_fraction_lost;
|
statistics->fraction_lost = local_fraction_lost;
|
||||||
|
|
||||||
// We need a counter for cumulative loss too.
|
// We need a counter for cumulative loss too.
|
||||||
cumulative_loss_ += missing;
|
cumulative_loss_ += *missing;
|
||||||
|
|
||||||
if (jitter_q4_ > jitter_max_q4_) {
|
if (jitter_q4_ > jitter_max_q4_) {
|
||||||
jitter_max_q4_ = jitter_q4_;
|
jitter_max_q4_ = jitter_q4_;
|
||||||
@ -251,9 +258,10 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamStatisticianImpl::GetDataCounters(
|
void ReceiveStatisticsImpl::GetDataCounters(
|
||||||
uint32_t* bytes_received, uint32_t* packets_received) const {
|
uint32_t* bytes_received, uint32_t* packets_received) const {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped lock(crit_sect_.get());
|
||||||
|
|
||||||
if (bytes_received) {
|
if (bytes_received) {
|
||||||
*bytes_received = received_byte_count_;
|
*bytes_received = received_byte_count_;
|
||||||
}
|
}
|
||||||
@ -263,105 +271,19 @@ void StreamStatisticianImpl::GetDataCounters(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t StreamStatisticianImpl::BitrateReceived() const {
|
uint32_t ReceiveStatisticsImpl::BitrateReceived() {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
return incoming_bitrate_.BitrateNow();
|
return incoming_bitrate_.BitrateNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamStatisticianImpl::ProcessBitrate() {
|
int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
int time_since_last_update = clock_->TimeInMilliseconds() -
|
||||||
incoming_bitrate_.Process();
|
incoming_bitrate_.time_last_rate_update();
|
||||||
}
|
return std::max(kRateUpdateIntervalMs - time_since_last_update, 0);
|
||||||
|
|
||||||
void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs,
|
|
||||||
uint32_t* frac) const {
|
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
*secs = last_receive_time_secs_;
|
|
||||||
*frac = last_receive_time_frac_;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) {
|
|
||||||
return new ReceiveStatisticsImpl(clock);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
|
|
||||||
: clock_(clock),
|
|
||||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
|
||||||
last_rate_update_ms_(0) {}
|
|
||||||
|
|
||||||
ReceiveStatisticsImpl::~ReceiveStatisticsImpl() {
|
|
||||||
while (!statisticians_.empty()) {
|
|
||||||
delete statisticians_.begin()->second;
|
|
||||||
statisticians_.erase(statisticians_.begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
|
|
||||||
size_t bytes, bool old_packet,
|
|
||||||
bool in_order) {
|
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
StatisticianImplMap::iterator it = statisticians_.find(header.ssrc);
|
|
||||||
if (it == statisticians_.end()) {
|
|
||||||
std::pair<StatisticianImplMap::iterator, uint32_t> insert_result =
|
|
||||||
statisticians_.insert(std::make_pair(
|
|
||||||
header.ssrc, new StreamStatisticianImpl(clock_)));
|
|
||||||
it = insert_result.first;
|
|
||||||
}
|
|
||||||
statisticians_[header.ssrc]->IncomingPacket(header, bytes, old_packet,
|
|
||||||
in_order);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReceiveStatisticsImpl::ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc) {
|
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
StatisticianImplMap::iterator from_it = statisticians_.find(from_ssrc);
|
|
||||||
if (from_it == statisticians_.end())
|
|
||||||
return;
|
|
||||||
if (statisticians_.find(to_ssrc) != statisticians_.end())
|
|
||||||
return;
|
|
||||||
statisticians_[to_ssrc] = from_it->second;
|
|
||||||
statisticians_.erase(from_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReceiveStatisticsImpl::GetActiveStatisticians(
|
|
||||||
StatisticianMap* statisticians) const {
|
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
statisticians->clear();
|
|
||||||
for (StatisticianImplMap::const_iterator it = statisticians_.begin();
|
|
||||||
it != statisticians_.end(); ++it) {
|
|
||||||
uint32_t secs;
|
|
||||||
uint32_t frac;
|
|
||||||
it->second->LastReceiveTimeNtp(&secs, &frac);
|
|
||||||
if (clock_->CurrentNtpInMilliseconds() -
|
|
||||||
Clock::NtpToMs(secs, frac) < kStatisticsTimeoutMs) {
|
|
||||||
(*statisticians)[it->first] = it->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamStatistician* ReceiveStatisticsImpl::GetStatistician(
|
|
||||||
uint32_t ssrc) const {
|
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
StatisticianImplMap::const_iterator it = statisticians_.find(ssrc);
|
|
||||||
if (it == statisticians_.end())
|
|
||||||
return NULL;
|
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ReceiveStatisticsImpl::Process() {
|
int32_t ReceiveStatisticsImpl::Process() {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
incoming_bitrate_.Process();
|
||||||
for (StatisticianImplMap::iterator it = statisticians_.begin();
|
|
||||||
it != statisticians_.end(); ++it) {
|
|
||||||
it->second->ProcessBitrate();
|
|
||||||
}
|
|
||||||
last_rate_update_ms_ = clock_->TimeInMilliseconds();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() {
|
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
|
||||||
int time_since_last_update = clock_->TimeInMilliseconds() -
|
|
||||||
last_rate_update_ms_;
|
|
||||||
return std::max(kStatisticsProcessIntervalMs - time_since_last_update, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -23,43 +23,43 @@ namespace webrtc {
|
|||||||
|
|
||||||
class CriticalSectionWrapper;
|
class CriticalSectionWrapper;
|
||||||
|
|
||||||
class StreamStatisticianImpl : public StreamStatistician {
|
class ReceiveStatisticsImpl : public ReceiveStatistics {
|
||||||
public:
|
public:
|
||||||
explicit StreamStatisticianImpl(Clock* clock);
|
explicit ReceiveStatisticsImpl(Clock* clock);
|
||||||
|
|
||||||
virtual ~StreamStatisticianImpl() {}
|
// Implements ReceiveStatistics.
|
||||||
|
void IncomingPacket(const RTPHeader& header, size_t bytes,
|
||||||
void IncomingPacket(const RTPHeader& rtp_header, size_t bytes,
|
bool old_packet, bool in_order);
|
||||||
bool retransmitted, bool in_order);
|
bool Statistics(RtpReceiveStatistics* statistics, bool reset);
|
||||||
bool GetStatistics(Statistics* statistics, bool reset);
|
bool Statistics(RtpReceiveStatistics* statistics, int32_t* missing,
|
||||||
|
bool reset);
|
||||||
void GetDataCounters(uint32_t* bytes_received,
|
void GetDataCounters(uint32_t* bytes_received,
|
||||||
uint32_t* packets_received) const;
|
uint32_t* packets_received) const;
|
||||||
void ProcessBitrate();
|
uint32_t BitrateReceived();
|
||||||
uint32_t BitrateReceived() const;
|
|
||||||
void ResetStatistics();
|
void ResetStatistics();
|
||||||
void ResetDataCounters();
|
void ResetDataCounters();
|
||||||
void LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const;
|
|
||||||
|
// Implements Module.
|
||||||
|
int32_t TimeUntilNextProcess();
|
||||||
|
int32_t Process();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Clock* clock_;
|
|
||||||
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
||||||
|
Clock* clock_;
|
||||||
Bitrate incoming_bitrate_;
|
Bitrate incoming_bitrate_;
|
||||||
uint32_t ssrc_;
|
uint32_t ssrc_;
|
||||||
|
|
||||||
// Stats on received RTP packets.
|
// Stats on received RTP packets.
|
||||||
uint32_t jitter_q4_;
|
uint32_t jitter_q4_;
|
||||||
uint32_t jitter_max_q4_;
|
uint32_t jitter_max_q4_;
|
||||||
uint32_t cumulative_loss_;
|
uint32_t cumulative_loss_;
|
||||||
uint32_t jitter_q4_transmission_time_offset_;
|
uint32_t jitter_q4_transmission_time_offset_;
|
||||||
|
|
||||||
uint32_t last_receive_time_secs_;
|
uint32_t local_time_last_received_timestamp_;
|
||||||
uint32_t last_receive_time_frac_;
|
|
||||||
uint32_t last_received_timestamp_;
|
uint32_t last_received_timestamp_;
|
||||||
int32_t last_received_transmission_time_offset_;
|
int32_t last_received_transmission_time_offset_;
|
||||||
uint16_t received_seq_first_;
|
uint16_t received_seq_first_;
|
||||||
uint16_t received_seq_max_;
|
uint16_t received_seq_max_;
|
||||||
uint16_t received_seq_wraps_;
|
uint16_t received_seq_wraps_;
|
||||||
bool first_packet_;
|
|
||||||
|
|
||||||
// Current counter values.
|
// Current counter values.
|
||||||
uint16_t received_packet_oh_;
|
uint16_t received_packet_oh_;
|
||||||
@ -71,35 +71,7 @@ class StreamStatisticianImpl : public StreamStatistician {
|
|||||||
uint32_t last_report_inorder_packets_;
|
uint32_t last_report_inorder_packets_;
|
||||||
uint32_t last_report_old_packets_;
|
uint32_t last_report_old_packets_;
|
||||||
uint16_t last_report_seq_max_;
|
uint16_t last_report_seq_max_;
|
||||||
Statistics last_reported_statistics_;
|
RtpReceiveStatistics last_reported_statistics_;
|
||||||
};
|
|
||||||
|
|
||||||
class ReceiveStatisticsImpl : public ReceiveStatistics {
|
|
||||||
public:
|
|
||||||
explicit ReceiveStatisticsImpl(Clock* clock);
|
|
||||||
|
|
||||||
~ReceiveStatisticsImpl();
|
|
||||||
|
|
||||||
// Implement ReceiveStatistics.
|
|
||||||
void IncomingPacket(const RTPHeader& header, size_t bytes,
|
|
||||||
bool old_packet, bool in_order);
|
|
||||||
void ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc);
|
|
||||||
void GetActiveStatisticians(StatisticianMap* statisticians) const;
|
|
||||||
StreamStatistician* GetStatistician(uint32_t ssrc) const;
|
|
||||||
void ResetStatistics(uint32_t ssrc);
|
|
||||||
void ResetDataCounters(uint32_t ssrc);
|
|
||||||
|
|
||||||
// Implement Module.
|
|
||||||
int32_t Process();
|
|
||||||
int32_t TimeUntilNextProcess();
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::map<uint32_t, StreamStatisticianImpl*> StatisticianImplMap;
|
|
||||||
|
|
||||||
Clock* clock_;
|
|
||||||
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
|
||||||
int64_t last_rate_update_ms_;
|
|
||||||
StatisticianImplMap statisticians_;
|
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
|
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
|
|
||||||
#include "webrtc/system_wrappers/interface/clock.h"
|
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
const int kPacketSize1 = 100;
|
|
||||||
const int kPacketSize2 = 300;
|
|
||||||
const uint32_t kSsrc1 = 1;
|
|
||||||
const uint32_t kSsrc2 = 2;
|
|
||||||
const uint32_t kSsrc3 = 3;
|
|
||||||
|
|
||||||
class ReceiveStatisticsTest : public ::testing::Test {
|
|
||||||
public:
|
|
||||||
ReceiveStatisticsTest() :
|
|
||||||
clock_(0),
|
|
||||||
receive_statistics_(ReceiveStatistics::Create(&clock_)) {
|
|
||||||
memset(&header1_, 0, sizeof(header1_));
|
|
||||||
header1_.ssrc = kSsrc1;
|
|
||||||
header1_.sequenceNumber = 0;
|
|
||||||
memset(&header2_, 0, sizeof(header2_));
|
|
||||||
header2_.ssrc = kSsrc2;
|
|
||||||
header2_.sequenceNumber = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SimulatedClock clock_;
|
|
||||||
scoped_ptr<ReceiveStatistics> receive_statistics_;
|
|
||||||
RTPHeader header1_;
|
|
||||||
RTPHeader header2_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
|
|
||||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true);
|
|
||||||
++header1_.sequenceNumber;
|
|
||||||
receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true);
|
|
||||||
++header2_.sequenceNumber;
|
|
||||||
clock_.AdvanceTimeMilliseconds(100);
|
|
||||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true);
|
|
||||||
++header1_.sequenceNumber;
|
|
||||||
receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true);
|
|
||||||
++header2_.sequenceNumber;
|
|
||||||
|
|
||||||
StreamStatistician* statistician =
|
|
||||||
receive_statistics_->GetStatistician(kSsrc1);
|
|
||||||
ASSERT_TRUE(statistician != NULL);
|
|
||||||
EXPECT_GT(statistician->BitrateReceived(), 0u);
|
|
||||||
uint32_t bytes_received = 0;
|
|
||||||
uint32_t packets_received = 0;
|
|
||||||
statistician->GetDataCounters(&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(200u, bytes_received);
|
|
||||||
EXPECT_EQ(2u, packets_received);
|
|
||||||
|
|
||||||
statistician =
|
|
||||||
receive_statistics_->GetStatistician(kSsrc2);
|
|
||||||
ASSERT_TRUE(statistician != NULL);
|
|
||||||
EXPECT_GT(statistician->BitrateReceived(), 0u);
|
|
||||||
statistician->GetDataCounters(&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(600u, bytes_received);
|
|
||||||
EXPECT_EQ(2u, packets_received);
|
|
||||||
|
|
||||||
ReceiveStatistics::StatisticianMap statisticians;
|
|
||||||
receive_statistics_->GetActiveStatisticians(&statisticians);
|
|
||||||
EXPECT_EQ(2u, statisticians.size());
|
|
||||||
// Add more incoming packets and verify that they are registered in both
|
|
||||||
// access methods.
|
|
||||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true);
|
|
||||||
++header1_.sequenceNumber;
|
|
||||||
receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true);
|
|
||||||
++header2_.sequenceNumber;
|
|
||||||
|
|
||||||
statisticians[kSsrc1]->GetDataCounters(&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(300u, bytes_received);
|
|
||||||
EXPECT_EQ(3u, packets_received);
|
|
||||||
statisticians[kSsrc2]->GetDataCounters(&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(900u, bytes_received);
|
|
||||||
EXPECT_EQ(3u, packets_received);
|
|
||||||
|
|
||||||
receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
|
|
||||||
&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(300u, bytes_received);
|
|
||||||
EXPECT_EQ(3u, packets_received);
|
|
||||||
receive_statistics_->GetStatistician(kSsrc2)->GetDataCounters(
|
|
||||||
&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(900u, bytes_received);
|
|
||||||
EXPECT_EQ(3u, packets_received);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
|
|
||||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true);
|
|
||||||
++header1_.sequenceNumber;
|
|
||||||
clock_.AdvanceTimeMilliseconds(1000);
|
|
||||||
receive_statistics_->IncomingPacket(header2_, kPacketSize2, false, true);
|
|
||||||
++header2_.sequenceNumber;
|
|
||||||
ReceiveStatistics::StatisticianMap statisticians;
|
|
||||||
receive_statistics_->GetActiveStatisticians(&statisticians);
|
|
||||||
// Nothing should time out since only 1000 ms has passed since the first
|
|
||||||
// packet came in.
|
|
||||||
EXPECT_EQ(2u, statisticians.size());
|
|
||||||
|
|
||||||
clock_.AdvanceTimeMilliseconds(7000);
|
|
||||||
// kSsrc1 should have timed out.
|
|
||||||
receive_statistics_->GetActiveStatisticians(&statisticians);
|
|
||||||
EXPECT_EQ(1u, statisticians.size());
|
|
||||||
|
|
||||||
clock_.AdvanceTimeMilliseconds(1000);
|
|
||||||
// kSsrc2 should have timed out.
|
|
||||||
receive_statistics_->GetActiveStatisticians(&statisticians);
|
|
||||||
EXPECT_EQ(0u, statisticians.size());
|
|
||||||
|
|
||||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false, true);
|
|
||||||
++header1_.sequenceNumber;
|
|
||||||
// kSsrc1 should be active again and the data counters should have survived.
|
|
||||||
receive_statistics_->GetActiveStatisticians(&statisticians);
|
|
||||||
EXPECT_EQ(1u, statisticians.size());
|
|
||||||
StreamStatistician* statistician =
|
|
||||||
receive_statistics_->GetStatistician(kSsrc1);
|
|
||||||
ASSERT_TRUE(statistician != NULL);
|
|
||||||
uint32_t bytes_received = 0;
|
|
||||||
uint32_t packets_received = 0;
|
|
||||||
statistician->GetDataCounters(&bytes_received, &packets_received);
|
|
||||||
EXPECT_EQ(200u, bytes_received);
|
|
||||||
EXPECT_EQ(2u, packets_received);
|
|
||||||
}
|
|
||||||
} // namespace webrtc
|
|
@ -61,7 +61,6 @@ class RtcpFormatRembTest : public ::testing::Test {
|
|||||||
RtcpFormatRembTest()
|
RtcpFormatRembTest()
|
||||||
: over_use_detector_options_(),
|
: over_use_detector_options_(),
|
||||||
system_clock_(Clock::GetRealTimeClock()),
|
system_clock_(Clock::GetRealTimeClock()),
|
||||||
receive_statistics_(ReceiveStatistics::Create(system_clock_)),
|
|
||||||
remote_bitrate_observer_(),
|
remote_bitrate_observer_(),
|
||||||
remote_bitrate_estimator_(
|
remote_bitrate_estimator_(
|
||||||
RemoteBitrateEstimatorFactory().Create(
|
RemoteBitrateEstimatorFactory().Create(
|
||||||
@ -73,7 +72,6 @@ class RtcpFormatRembTest : public ::testing::Test {
|
|||||||
OverUseDetectorOptions over_use_detector_options_;
|
OverUseDetectorOptions over_use_detector_options_;
|
||||||
Clock* system_clock_;
|
Clock* system_clock_;
|
||||||
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
|
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
|
||||||
scoped_ptr<ReceiveStatistics> receive_statistics_;
|
|
||||||
RTCPSender* rtcp_sender_;
|
RTCPSender* rtcp_sender_;
|
||||||
RTCPReceiver* rtcp_receiver_;
|
RTCPReceiver* rtcp_receiver_;
|
||||||
TestTransport* test_transport_;
|
TestTransport* test_transport_;
|
||||||
@ -88,8 +86,7 @@ void RtcpFormatRembTest::SetUp() {
|
|||||||
configuration.clock = system_clock_;
|
configuration.clock = system_clock_;
|
||||||
configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get();
|
configuration.remote_bitrate_estimator = remote_bitrate_estimator_.get();
|
||||||
dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
|
dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
|
||||||
rtcp_sender_ = new RTCPSender(0, false, system_clock_, dummy_rtp_rtcp_impl_,
|
rtcp_sender_ = new RTCPSender(0, false, system_clock_, dummy_rtp_rtcp_impl_);
|
||||||
receive_statistics_.get());
|
|
||||||
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, dummy_rtp_rtcp_impl_);
|
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, dummy_rtp_rtcp_impl_);
|
||||||
test_transport_ = new TestTransport(rtcp_receiver_);
|
test_transport_ = new TestTransport(rtcp_receiver_);
|
||||||
|
|
||||||
@ -118,13 +115,15 @@ TEST_F(RtcpFormatRembTest, TestNonCompund) {
|
|||||||
uint32_t SSRC = 456789;
|
uint32_t SSRC = 456789;
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpNonCompound));
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpNonCompound));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 1, &SSRC));
|
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 1, &SSRC));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb));
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RtcpFormatRembTest, TestCompund) {
|
TEST_F(RtcpFormatRembTest, TestCompund) {
|
||||||
uint32_t SSRCs[2] = {456789, 98765};
|
uint32_t SSRCs[2] = {456789, 98765};
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 2, SSRCs));
|
EXPECT_EQ(0, rtcp_sender_->SetREMBData(1234, 2, SSRCs));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb));
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
memset(&receive_stats, 0, sizeof(receive_stats));
|
||||||
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRemb, &receive_stats));
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -406,6 +406,7 @@ RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
|
|||||||
TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
|
TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
|
||||||
"remote_ssrc", remoteSSRC,
|
"remote_ssrc", remoteSSRC,
|
||||||
"ssrc", _SSRC);
|
"ssrc", _SSRC);
|
||||||
|
|
||||||
if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
|
if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
|
||||||
{
|
{
|
||||||
// only signal that we have received a SR when we accept one
|
// only signal that we have received a SR when we accept one
|
||||||
|
@ -65,8 +65,7 @@ std::string NACKStringBuilder::GetResult()
|
|||||||
RTCPSender::RTCPSender(const int32_t id,
|
RTCPSender::RTCPSender(const int32_t id,
|
||||||
const bool audio,
|
const bool audio,
|
||||||
Clock* clock,
|
Clock* clock,
|
||||||
ModuleRtpRtcpImpl* owner,
|
ModuleRtpRtcpImpl* owner) :
|
||||||
ReceiveStatistics* receive_statistics) :
|
|
||||||
_id(id),
|
_id(id),
|
||||||
_audio(audio),
|
_audio(audio),
|
||||||
_clock(clock),
|
_clock(clock),
|
||||||
@ -90,9 +89,7 @@ RTCPSender::RTCPSender(const int32_t id,
|
|||||||
_SSRC(0),
|
_SSRC(0),
|
||||||
_remoteSSRC(0),
|
_remoteSSRC(0),
|
||||||
_CNAME(),
|
_CNAME(),
|
||||||
receive_statistics_(receive_statistics),
|
_reportBlocks(),
|
||||||
internal_report_blocks_(),
|
|
||||||
external_report_blocks_(),
|
|
||||||
_csrcCNAMEs(),
|
_csrcCNAMEs(),
|
||||||
|
|
||||||
_cameraDelayMS(0),
|
_cameraDelayMS(0),
|
||||||
@ -137,15 +134,11 @@ RTCPSender::~RTCPSender() {
|
|||||||
delete [] _rembSSRC;
|
delete [] _rembSSRC;
|
||||||
delete [] _appData;
|
delete [] _appData;
|
||||||
|
|
||||||
while (!internal_report_blocks_.empty()) {
|
while (!_reportBlocks.empty()) {
|
||||||
delete internal_report_blocks_.begin()->second;
|
|
||||||
internal_report_blocks_.erase(internal_report_blocks_.begin());
|
|
||||||
}
|
|
||||||
while (!external_report_blocks_.empty()) {
|
|
||||||
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
||||||
external_report_blocks_.begin();
|
_reportBlocks.begin();
|
||||||
delete it->second;
|
delete it->second;
|
||||||
external_report_blocks_.erase(it);
|
_reportBlocks.erase(it);
|
||||||
}
|
}
|
||||||
while (!_csrcCNAMEs.empty()) {
|
while (!_csrcCNAMEs.empty()) {
|
||||||
std::map<uint32_t, RTCPCnameInformation*>::iterator it =
|
std::map<uint32_t, RTCPCnameInformation*>::iterator it =
|
||||||
@ -275,7 +268,7 @@ RTCPSender::SetSendingStatus(const bool sending)
|
|||||||
}
|
}
|
||||||
if(sendRTCPBye)
|
if(sendRTCPBye)
|
||||||
{
|
{
|
||||||
return SendRTCP(kRtcpBye);
|
return SendRTCP(kRtcpBye, NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -563,59 +556,52 @@ RTCPSender::SendTimeOfSendReport(const uint32_t sendReport)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RTCPSender::AddExternalReportBlock(
|
int32_t RTCPSender::AddReportBlock(const uint32_t SSRC,
|
||||||
uint32_t SSRC,
|
|
||||||
const RTCPReportBlock* reportBlock) {
|
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
|
||||||
return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t RTCPSender::AddReportBlock(
|
|
||||||
uint32_t SSRC,
|
|
||||||
std::map<uint32_t, RTCPReportBlock*>* report_blocks,
|
|
||||||
const RTCPReportBlock* reportBlock) {
|
const RTCPReportBlock* reportBlock) {
|
||||||
if (reportBlock == NULL) {
|
if (reportBlock == NULL) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
"%s invalid argument", __FUNCTION__);
|
"%s invalid argument", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
||||||
|
|
||||||
if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
|
if (_reportBlocks.size() >= RTCP_MAX_REPORT_BLOCKS) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
"%s invalid argument", __FUNCTION__);
|
"%s invalid argument", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
||||||
report_blocks->find(SSRC);
|
_reportBlocks.find(SSRC);
|
||||||
if (it != report_blocks->end()) {
|
if (it != _reportBlocks.end()) {
|
||||||
delete it->second;
|
delete it->second;
|
||||||
report_blocks->erase(it);
|
_reportBlocks.erase(it);
|
||||||
}
|
}
|
||||||
RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
|
RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
|
||||||
memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
|
memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
|
||||||
(*report_blocks)[SSRC] = copyReportBlock;
|
_reportBlocks[SSRC] = copyReportBlock;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
|
int32_t RTCPSender::RemoveReportBlock(const uint32_t SSRC) {
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
||||||
|
|
||||||
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
||||||
external_report_blocks_.find(SSRC);
|
_reportBlocks.find(SSRC);
|
||||||
|
|
||||||
if (it == external_report_blocks_.end()) {
|
if (it == _reportBlocks.end()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
delete it->second;
|
delete it->second;
|
||||||
external_report_blocks_.erase(it);
|
_reportBlocks.erase(it);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildSR(uint8_t* rtcpbuffer,
|
RTCPSender::BuildSR(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint32_t NTPsec,
|
const uint32_t NTPsec,
|
||||||
const uint32_t NTPfrac)
|
const uint32_t NTPfrac,
|
||||||
|
const RTCPReportBlock* received)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 52 >= IP_PACKET_SIZE)
|
if(pos + 52 >= IP_PACKET_SIZE)
|
||||||
@ -683,15 +669,12 @@ RTCPSender::BuildSR(uint8_t* rtcpbuffer,
|
|||||||
pos += 4;
|
pos += 4;
|
||||||
|
|
||||||
uint8_t numberOfReportBlocks = 0;
|
uint8_t numberOfReportBlocks = 0;
|
||||||
int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
|
int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
|
||||||
numberOfReportBlocks,
|
|
||||||
NTPsec, NTPfrac);
|
|
||||||
if(retVal < 0)
|
if(retVal < 0)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
return retVal ;
|
return retVal ;
|
||||||
}
|
}
|
||||||
pos = retVal;
|
|
||||||
rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
|
rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
|
||||||
|
|
||||||
uint16_t len = uint16_t((pos/4) -1);
|
uint16_t len = uint16_t((pos/4) -1);
|
||||||
@ -701,7 +684,7 @@ RTCPSender::BuildSR(uint8_t* rtcpbuffer,
|
|||||||
|
|
||||||
|
|
||||||
int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
|
int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
|
||||||
int& pos) {
|
uint32_t& pos) {
|
||||||
size_t lengthCname = strlen(_CNAME);
|
size_t lengthCname = strlen(_CNAME);
|
||||||
assert(lengthCname < RTCP_CNAME_SIZE);
|
assert(lengthCname < RTCP_CNAME_SIZE);
|
||||||
|
|
||||||
@ -796,9 +779,10 @@ int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer,
|
|||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildRR(uint8_t* rtcpbuffer,
|
RTCPSender::BuildRR(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint32_t NTPsec,
|
const uint32_t NTPsec,
|
||||||
const uint32_t NTPfrac)
|
const uint32_t NTPfrac,
|
||||||
|
const RTCPReportBlock* received)
|
||||||
{
|
{
|
||||||
// sanity one block
|
// sanity one block
|
||||||
if(pos + 32 >= IP_PACKET_SIZE)
|
if(pos + 32 >= IP_PACKET_SIZE)
|
||||||
@ -819,14 +803,11 @@ RTCPSender::BuildRR(uint8_t* rtcpbuffer,
|
|||||||
pos += 4;
|
pos += 4;
|
||||||
|
|
||||||
uint8_t numberOfReportBlocks = 0;
|
uint8_t numberOfReportBlocks = 0;
|
||||||
int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
|
int32_t retVal = AddReportBlocks(rtcpbuffer, pos, numberOfReportBlocks, received, NTPsec, NTPfrac);
|
||||||
numberOfReportBlocks,
|
|
||||||
NTPsec, NTPfrac);
|
|
||||||
if(retVal < 0)
|
if(retVal < 0)
|
||||||
{
|
{
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
pos = retVal;
|
|
||||||
rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
|
rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
|
||||||
|
|
||||||
uint16_t len = uint16_t((pos)/4 -1);
|
uint16_t len = uint16_t((pos)/4 -1);
|
||||||
@ -855,10 +836,10 @@ RTCPSender::BuildRR(uint8_t* rtcpbuffer,
|
|||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildExtendedJitterReport(
|
RTCPSender::BuildExtendedJitterReport(
|
||||||
uint8_t* rtcpbuffer,
|
uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint32_t jitterTransmissionTimeOffset)
|
const uint32_t jitterTransmissionTimeOffset)
|
||||||
{
|
{
|
||||||
if (external_report_blocks_.size() > 0)
|
if (_reportBlocks.size() > 0)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
|
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Not implemented.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -886,7 +867,7 @@ RTCPSender::BuildExtendedJitterReport(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 12 >= IP_PACKET_SIZE)
|
if(pos + 12 >= IP_PACKET_SIZE)
|
||||||
@ -913,7 +894,7 @@ RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
|
int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
bool repeat) {
|
bool repeat) {
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 20 >= IP_PACKET_SIZE) {
|
if(pos + 20 >= IP_PACKET_SIZE) {
|
||||||
@ -962,7 +943,7 @@ int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
*/
|
*/
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
|
RTCPSender::BuildSLI(uint8_t* rtcpbuffer, uint32_t& pos, const uint8_t pictureID)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 16 >= IP_PACKET_SIZE)
|
if(pos + 16 >= IP_PACKET_SIZE)
|
||||||
@ -1009,7 +990,7 @@ RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, const uint8_t pictureID)
|
|||||||
*/
|
*/
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
|
RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint64_t pictureID,
|
const uint64_t pictureID,
|
||||||
const uint8_t payloadType)
|
const uint8_t payloadType)
|
||||||
{
|
{
|
||||||
@ -1085,7 +1066,7 @@ RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
|
if(pos + 20 + 4 * _lengthRembSSRC >= IP_PACKET_SIZE)
|
||||||
@ -1146,7 +1127,7 @@ RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
// Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
|
// Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
|
||||||
// If the sender is an owner of the TMMBN -> send TMMBR
|
// If the sender is an owner of the TMMBN -> send TMMBR
|
||||||
@ -1252,7 +1233,7 @@ RTCPSender::BuildTMMBR(uint8_t* rtcpbuffer, int& pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
|
TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
|
||||||
if(boundingSet == NULL)
|
if(boundingSet == NULL)
|
||||||
@ -1324,7 +1305,7 @@ RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(_appData == NULL)
|
if(_appData == NULL)
|
||||||
@ -1362,7 +1343,7 @@ RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
|
|||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
|
RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const int32_t nackSize,
|
const int32_t nackSize,
|
||||||
const uint16_t* nackList,
|
const uint16_t* nackList,
|
||||||
std::string* nackString)
|
std::string* nackString)
|
||||||
@ -1432,7 +1413,7 @@ RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 8 >= IP_PACKET_SIZE)
|
if(pos + 8 >= IP_PACKET_SIZE)
|
||||||
@ -1477,7 +1458,7 @@ RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
|
RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos)
|
||||||
{
|
{
|
||||||
// sanity
|
// sanity
|
||||||
if(pos + 44 >= IP_PACKET_SIZE)
|
if(pos + 44 >= IP_PACKET_SIZE)
|
||||||
@ -1552,11 +1533,26 @@ RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
|
|||||||
int32_t
|
int32_t
|
||||||
RTCPSender::SendRTCP(
|
RTCPSender::SendRTCP(
|
||||||
uint32_t packetTypeFlags,
|
uint32_t packetTypeFlags,
|
||||||
|
const ReceiveStatistics::RtpReceiveStatistics* receive_stats,
|
||||||
int32_t nackSize,
|
int32_t nackSize,
|
||||||
const uint16_t* nackList,
|
const uint16_t* nackList,
|
||||||
bool repeat,
|
bool repeat,
|
||||||
uint64_t pictureID)
|
uint64_t pictureID)
|
||||||
{
|
{
|
||||||
|
uint32_t rtcpPacketTypeFlags = packetTypeFlags;
|
||||||
|
uint32_t pos = 0;
|
||||||
|
uint8_t rtcpbuffer[IP_PACKET_SIZE];
|
||||||
|
|
||||||
|
do // only to be able to use break :) (and the critsect must be inside its own scope)
|
||||||
|
{
|
||||||
|
// collect the received information
|
||||||
|
RTCPReportBlock received;
|
||||||
|
bool hasReceived = false;
|
||||||
|
uint32_t NTPsec = 0;
|
||||||
|
uint32_t NTPfrac = 0;
|
||||||
|
bool rtcpCompound = false;
|
||||||
|
uint32_t jitterTransmissionOffset = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
||||||
if(_method == kRtcpOff)
|
if(_method == kRtcpOff)
|
||||||
@ -1565,39 +1561,64 @@ RTCPSender::SendRTCP(
|
|||||||
"%s invalid state", __FUNCTION__);
|
"%s invalid state", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
rtcpCompound = (_method == kRtcpCompound) ? true : false;
|
||||||
}
|
}
|
||||||
uint8_t rtcp_buffer[IP_PACKET_SIZE];
|
|
||||||
int rtcp_length = PrepareRTCP(packetTypeFlags, nackSize, nackList, repeat,
|
|
||||||
pictureID, rtcp_buffer, IP_PACKET_SIZE);
|
|
||||||
if (rtcp_length < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Sanity don't send empty packets.
|
|
||||||
if (rtcp_length == 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return SendToNetwork(rtcp_buffer, static_cast<uint16_t>(rtcp_length));
|
|
||||||
}
|
|
||||||
|
|
||||||
int RTCPSender::PrepareRTCP(
|
if (rtcpCompound ||
|
||||||
uint32_t packetTypeFlags,
|
rtcpPacketTypeFlags & kRtcpReport ||
|
||||||
int32_t nackSize,
|
rtcpPacketTypeFlags & kRtcpSr ||
|
||||||
const uint16_t* nackList,
|
rtcpPacketTypeFlags & kRtcpRr)
|
||||||
bool repeat,
|
{
|
||||||
uint64_t pictureID,
|
// Do we have receive statistics to send?
|
||||||
uint8_t* rtcp_buffer,
|
if (receive_stats)
|
||||||
int buffer_size) {
|
{
|
||||||
uint32_t rtcpPacketTypeFlags = packetTypeFlags;
|
received.fractionLost = receive_stats->fraction_lost;
|
||||||
// Collect the received information.
|
received.cumulativeLost = receive_stats->cumulative_lost;
|
||||||
uint32_t NTPsec = 0;
|
received.extendedHighSeqNum =
|
||||||
uint32_t NTPfrac = 0;
|
receive_stats->extended_max_sequence_number;
|
||||||
uint32_t jitterTransmissionOffset = 0;
|
received.jitter = receive_stats->jitter;
|
||||||
int position = 0;
|
jitterTransmissionOffset = 0;
|
||||||
|
hasReceived = true;
|
||||||
|
|
||||||
|
uint32_t lastReceivedRRNTPsecs = 0;
|
||||||
|
uint32_t lastReceivedRRNTPfrac = 0;
|
||||||
|
uint32_t remoteSR = 0;
|
||||||
|
|
||||||
|
// ok even if we have not received a SR, we will send 0 in that case
|
||||||
|
_rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
|
||||||
|
lastReceivedRRNTPfrac,
|
||||||
|
remoteSR);
|
||||||
|
|
||||||
|
// get our NTP as late as possible to avoid a race
|
||||||
|
_clock->CurrentNtp(NTPsec, NTPfrac);
|
||||||
|
|
||||||
|
// Delay since last received report
|
||||||
|
uint32_t delaySinceLastReceivedSR = 0;
|
||||||
|
if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0))
|
||||||
|
{
|
||||||
|
// get the 16 lowest bits of seconds and the 16 higest bits of fractions
|
||||||
|
uint32_t now=NTPsec&0x0000FFFF;
|
||||||
|
now <<=16;
|
||||||
|
now += (NTPfrac&0xffff0000)>>16;
|
||||||
|
|
||||||
|
uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
|
||||||
|
receiveTime <<=16;
|
||||||
|
receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
|
||||||
|
|
||||||
|
delaySinceLastReceivedSR = now-receiveTime;
|
||||||
|
}
|
||||||
|
received.delaySinceLastSR = delaySinceLastReceivedSR;
|
||||||
|
received.lastSR = remoteSR;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// we need to send our NTP even if we dont have received any reports
|
||||||
|
_clock->CurrentNtp(NTPsec, NTPfrac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
CriticalSectionScoped lock(_criticalSectionRTCPSender);
|
||||||
|
|
||||||
if(_TMMBR ) // Attach TMMBR to send and receive reports.
|
if(_TMMBR ) // attach TMMBR to send and receive reports
|
||||||
{
|
{
|
||||||
rtcpPacketTypeFlags |= kRtcpTmmbr;
|
rtcpPacketTypeFlags |= kRtcpTmmbr;
|
||||||
}
|
}
|
||||||
@ -1617,7 +1638,7 @@ int RTCPSender::PrepareRTCP(
|
|||||||
rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
|
rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
|
||||||
_xrSendVoIPMetric = false;
|
_xrSendVoIPMetric = false;
|
||||||
}
|
}
|
||||||
if(_sendTMMBN) // Set when having received a TMMBR.
|
if(_sendTMMBN) // set when having received a TMMBR
|
||||||
{
|
{
|
||||||
rtcpPacketTypeFlags |= kRtcpTmmbn;
|
rtcpPacketTypeFlags |= kRtcpTmmbn;
|
||||||
_sendTMMBN = false;
|
_sendTMMBN = false;
|
||||||
@ -1632,6 +1653,10 @@ int RTCPSender::PrepareRTCP(
|
|||||||
{
|
{
|
||||||
rtcpPacketTypeFlags |= kRtcpRr;
|
rtcpPacketTypeFlags |= kRtcpRr;
|
||||||
}
|
}
|
||||||
|
if (_IJ && hasReceived)
|
||||||
|
{
|
||||||
|
rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
|
||||||
|
}
|
||||||
} else if(_method == kRtcpNonCompound)
|
} else if(_method == kRtcpNonCompound)
|
||||||
{
|
{
|
||||||
if(rtcpPacketTypeFlags & kRtcpReport)
|
if(rtcpPacketTypeFlags & kRtcpReport)
|
||||||
@ -1655,14 +1680,13 @@ int RTCPSender::PrepareRTCP(
|
|||||||
|
|
||||||
if(_audio)
|
if(_audio)
|
||||||
{
|
{
|
||||||
timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
|
timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) + (RTCP_INTERVAL_AUDIO_MS*random/1000);
|
||||||
(RTCP_INTERVAL_AUDIO_MS*random/1000);
|
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
|
uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
|
||||||
if(_sending)
|
if(_sending)
|
||||||
{
|
{
|
||||||
// Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
|
// calc bw for video 360/sendBW in kbit/s
|
||||||
uint32_t sendBitrateKbit = 0;
|
uint32_t sendBitrateKbit = 0;
|
||||||
uint32_t videoRate = 0;
|
uint32_t videoRate = 0;
|
||||||
uint32_t fecRate = 0;
|
uint32_t fecRate = 0;
|
||||||
@ -1686,61 +1710,60 @@ int RTCPSender::PrepareRTCP(
|
|||||||
_nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
|
_nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the data does not fit in the packet we fill it as much as possible.
|
// if the data does not fitt in the packet we fill it as much as possible
|
||||||
int32_t buildVal = 0;
|
int32_t buildVal = 0;
|
||||||
|
|
||||||
if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
|
|
||||||
ReceiveStatistics::StatisticianMap statisticians;
|
|
||||||
receive_statistics_->GetActiveStatisticians(&statisticians);
|
|
||||||
if (statisticians.empty()) {
|
|
||||||
// We need to send our NTP even if we dont have received any
|
|
||||||
// reports.
|
|
||||||
_clock->CurrentNtp(NTPsec, NTPfrac);
|
|
||||||
} else {
|
|
||||||
ReceiveStatistics::StatisticianMap::const_iterator it;
|
|
||||||
int i;
|
|
||||||
for (it = statisticians.begin(), i = 0; it != statisticians.end();
|
|
||||||
++it, ++i) {
|
|
||||||
RTCPReportBlock report_block;
|
|
||||||
if (PrepareReport(it->second, &report_block, &NTPsec, &NTPfrac))
|
|
||||||
AddReportBlock(it->first, &internal_report_blocks_, &report_block);
|
|
||||||
}
|
|
||||||
if (_IJ && !statisticians.empty())
|
|
||||||
{
|
|
||||||
rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
|
|
||||||
}
|
|
||||||
_lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rtcpPacketTypeFlags & kRtcpSr)
|
if(rtcpPacketTypeFlags & kRtcpSr)
|
||||||
{
|
{
|
||||||
buildVal = BuildSR(rtcp_buffer, position, NTPsec, NTPfrac);
|
if(hasReceived)
|
||||||
if (buildVal == -1) {
|
{
|
||||||
return -1;
|
buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac, &received);
|
||||||
} else if (buildVal == -2) {
|
} else
|
||||||
return position;
|
{
|
||||||
|
buildVal = BuildSR(rtcpbuffer, pos, NTPsec, NTPfrac);
|
||||||
}
|
}
|
||||||
buildVal = BuildSDEC(rtcp_buffer, position);
|
if(buildVal == -1)
|
||||||
if (buildVal == -1) {
|
{
|
||||||
return -1;
|
return -1; // error
|
||||||
} else if (buildVal == -2) {
|
|
||||||
return position;
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
|
buildVal = BuildSDEC(rtcpbuffer, pos);
|
||||||
|
if(buildVal == -1)
|
||||||
|
{
|
||||||
|
return -1; // error
|
||||||
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
|
}
|
||||||
|
|
||||||
}else if(rtcpPacketTypeFlags & kRtcpRr)
|
}else if(rtcpPacketTypeFlags & kRtcpRr)
|
||||||
{
|
{
|
||||||
buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
|
if(hasReceived)
|
||||||
if (buildVal == -1) {
|
{
|
||||||
return -1;
|
buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac,&received);
|
||||||
} else if (buildVal == -2) {
|
}else
|
||||||
return position;
|
{
|
||||||
|
buildVal = BuildRR(rtcpbuffer, pos, NTPsec, NTPfrac);
|
||||||
|
}
|
||||||
|
if(buildVal == -1)
|
||||||
|
{
|
||||||
|
return -1; // error
|
||||||
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
// only of set
|
// only of set
|
||||||
if(_CNAME[0] != 0)
|
if(_CNAME[0] != 0)
|
||||||
{
|
{
|
||||||
buildVal = BuildSDEC(rtcp_buffer, position);
|
buildVal = BuildSDEC(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
|
return -1; // error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1748,22 +1771,28 @@ int RTCPSender::PrepareRTCP(
|
|||||||
{
|
{
|
||||||
// If present, this RTCP packet must be placed after a
|
// If present, this RTCP packet must be placed after a
|
||||||
// receiver report.
|
// receiver report.
|
||||||
buildVal = BuildExtendedJitterReport(rtcp_buffer,
|
buildVal = BuildExtendedJitterReport(rtcpbuffer,
|
||||||
position,
|
pos,
|
||||||
jitterTransmissionOffset);
|
jitterTransmissionOffset);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
}
|
||||||
|
else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpPli)
|
if(rtcpPacketTypeFlags & kRtcpPli)
|
||||||
{
|
{
|
||||||
buildVal = BuildPLI(rtcp_buffer, position);
|
buildVal = BuildPLI(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
|
TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::PLI");
|
||||||
_pliCount++;
|
_pliCount++;
|
||||||
@ -1771,11 +1800,14 @@ int RTCPSender::PrepareRTCP(
|
|||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpFir)
|
if(rtcpPacketTypeFlags & kRtcpFir)
|
||||||
{
|
{
|
||||||
buildVal = BuildFIR(rtcp_buffer, position, repeat);
|
buildVal = BuildFIR(rtcpbuffer, pos, repeat);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
|
TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::FIR");
|
||||||
_fullIntraRequestCount++;
|
_fullIntraRequestCount++;
|
||||||
@ -1784,82 +1816,106 @@ int RTCPSender::PrepareRTCP(
|
|||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpSli)
|
if(rtcpPacketTypeFlags & kRtcpSli)
|
||||||
{
|
{
|
||||||
buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
|
buildVal = BuildSLI(rtcpbuffer, pos, (uint8_t)pictureID);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpRpsi)
|
if(rtcpPacketTypeFlags & kRtcpRpsi)
|
||||||
{
|
{
|
||||||
const int8_t payloadType = _rtpRtcp.SendPayloadType();
|
const int8_t payloadType = _rtpRtcp.SendPayloadType();
|
||||||
if (payloadType == -1) {
|
if(payloadType == -1)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
|
buildVal = BuildRPSI(rtcpbuffer, pos, pictureID, (uint8_t)payloadType);
|
||||||
(uint8_t)payloadType);
|
if(buildVal == -1)
|
||||||
if (buildVal == -1) {
|
{
|
||||||
return -1;
|
return -1; // error
|
||||||
} else if (buildVal == -2) {
|
|
||||||
return position;
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpRemb)
|
if(rtcpPacketTypeFlags & kRtcpRemb)
|
||||||
{
|
{
|
||||||
buildVal = BuildREMB(rtcp_buffer, position);
|
buildVal = BuildREMB(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
|
TRACE_EVENT_INSTANT0("webrtc_rtp", "RTCPSender::REMB");
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpBye)
|
if(rtcpPacketTypeFlags & kRtcpBye)
|
||||||
{
|
{
|
||||||
buildVal = BuildBYE(rtcp_buffer, position);
|
buildVal = BuildBYE(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpApp)
|
if(rtcpPacketTypeFlags & kRtcpApp)
|
||||||
{
|
{
|
||||||
buildVal = BuildAPP(rtcp_buffer, position);
|
buildVal = BuildAPP(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpTmmbr)
|
if(rtcpPacketTypeFlags & kRtcpTmmbr)
|
||||||
{
|
{
|
||||||
buildVal = BuildTMMBR(rtcp_buffer, position);
|
buildVal = BuildTMMBR(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpTmmbn)
|
if(rtcpPacketTypeFlags & kRtcpTmmbn)
|
||||||
{
|
{
|
||||||
buildVal = BuildTMMBN(rtcp_buffer, position);
|
buildVal = BuildTMMBN(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpNack)
|
if(rtcpPacketTypeFlags & kRtcpNack)
|
||||||
{
|
{
|
||||||
std::string nackString;
|
std::string nackString;
|
||||||
buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
|
buildVal = BuildNACK(rtcpbuffer, pos, nackSize, nackList,
|
||||||
&nackString);
|
&nackString);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
return -1;
|
{
|
||||||
} else if (buildVal == -2) {
|
return -1; // error
|
||||||
return position;
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
}
|
}
|
||||||
TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
|
TRACE_EVENT_INSTANT1("webrtc_rtp", "RTCPSender::NACK",
|
||||||
"nacks", TRACE_STR_COPY(nackString.c_str()));
|
"nacks", TRACE_STR_COPY(nackString.c_str()));
|
||||||
@ -1868,65 +1924,23 @@ int RTCPSender::PrepareRTCP(
|
|||||||
}
|
}
|
||||||
if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
|
if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
|
||||||
{
|
{
|
||||||
buildVal = BuildVoIPMetric(rtcp_buffer, position);
|
buildVal = BuildVoIPMetric(rtcpbuffer, pos);
|
||||||
if (buildVal == -1) {
|
if(buildVal == -1)
|
||||||
|
{
|
||||||
|
return -1; // error
|
||||||
|
|
||||||
|
}else if(buildVal == -2)
|
||||||
|
{
|
||||||
|
break; // out of buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}while (false);
|
||||||
|
// Sanity don't send empty packets.
|
||||||
|
if (pos == 0)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
} else if (buildVal == -2) {
|
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
}
|
return SendToNetwork(rtcpbuffer, (uint16_t)pos);
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
|
|
||||||
return Status() == kRtcpCompound ||
|
|
||||||
(rtcp_packet_type & kRtcpReport) ||
|
|
||||||
(rtcp_packet_type & kRtcpSr) ||
|
|
||||||
(rtcp_packet_type & kRtcpRr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RTCPSender::PrepareReport(StreamStatistician* statistician,
|
|
||||||
RTCPReportBlock* report_block,
|
|
||||||
uint32_t* ntp_secs, uint32_t* ntp_frac) {
|
|
||||||
// Do we have receive statistics to send?
|
|
||||||
StreamStatistician::Statistics stats;
|
|
||||||
if (!statistician->GetStatistics(&stats, true))
|
|
||||||
return false;
|
|
||||||
report_block->fractionLost = stats.fraction_lost;
|
|
||||||
report_block->cumulativeLost = stats.cumulative_lost;
|
|
||||||
report_block->extendedHighSeqNum =
|
|
||||||
stats.extended_max_sequence_number;
|
|
||||||
report_block->jitter = stats.jitter;
|
|
||||||
|
|
||||||
uint32_t lastReceivedRRNTPsecs = 0;
|
|
||||||
uint32_t lastReceivedRRNTPfrac = 0;
|
|
||||||
uint32_t remoteSR = 0;
|
|
||||||
|
|
||||||
// ok even if we have not received a SR, we will send 0 in that case
|
|
||||||
_rtpRtcp.LastReceivedNTP(lastReceivedRRNTPsecs,
|
|
||||||
lastReceivedRRNTPfrac,
|
|
||||||
remoteSR);
|
|
||||||
|
|
||||||
// get our NTP as late as possible to avoid a race
|
|
||||||
_clock->CurrentNtp(*ntp_secs, *ntp_frac);
|
|
||||||
|
|
||||||
// Delay since last received report
|
|
||||||
uint32_t delaySinceLastReceivedSR = 0;
|
|
||||||
if((lastReceivedRRNTPsecs !=0) || (lastReceivedRRNTPfrac !=0)) {
|
|
||||||
// get the 16 lowest bits of seconds and the 16 higest bits of fractions
|
|
||||||
uint32_t now=*ntp_secs&0x0000FFFF;
|
|
||||||
now <<=16;
|
|
||||||
now += (*ntp_frac&0xffff0000)>>16;
|
|
||||||
|
|
||||||
uint32_t receiveTime = lastReceivedRRNTPsecs&0x0000FFFF;
|
|
||||||
receiveTime <<=16;
|
|
||||||
receiveTime += (lastReceivedRRNTPfrac&0xffff0000)>>16;
|
|
||||||
|
|
||||||
delaySinceLastReceivedSR = now-receiveTime;
|
|
||||||
}
|
|
||||||
report_block->delaySinceLastSR = delaySinceLastReceivedSR;
|
|
||||||
report_block->lastSR = remoteSR;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
@ -2010,10 +2024,10 @@ RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called under critsect _criticalSectionRTCPSender
|
// called under critsect _criticalSectionRTCPSender
|
||||||
int32_t RTCPSender::WriteAllReportBlocksToBuffer(
|
int32_t RTCPSender::AddReportBlocks(uint8_t* rtcpbuffer,
|
||||||
uint8_t* rtcpbuffer,
|
uint32_t& pos,
|
||||||
int pos,
|
|
||||||
uint8_t& numberOfReportBlocks,
|
uint8_t& numberOfReportBlocks,
|
||||||
|
const RTCPReportBlock* received,
|
||||||
const uint32_t NTPsec,
|
const uint32_t NTPsec,
|
||||||
const uint32_t NTPfrac) {
|
const uint32_t NTPfrac) {
|
||||||
// sanity one block
|
// sanity one block
|
||||||
@ -2022,64 +2036,91 @@ int32_t RTCPSender::WriteAllReportBlocksToBuffer(
|
|||||||
"%s invalid argument", __FUNCTION__);
|
"%s invalid argument", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
numberOfReportBlocks = external_report_blocks_.size();
|
numberOfReportBlocks = _reportBlocks.size();
|
||||||
numberOfReportBlocks += internal_report_blocks_.size();
|
if (received) {
|
||||||
if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
|
// add our multiple RR to numberOfReportBlocks
|
||||||
|
numberOfReportBlocks++;
|
||||||
|
}
|
||||||
|
if (received) {
|
||||||
|
// answer to the one that sends to me
|
||||||
|
_lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
|
||||||
|
|
||||||
|
// Remote SSRC
|
||||||
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, _remoteSSRC);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
// fraction lost
|
||||||
|
rtcpbuffer[pos++]=received->fractionLost;
|
||||||
|
|
||||||
|
// cumulative loss
|
||||||
|
ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
|
||||||
|
received->cumulativeLost);
|
||||||
|
pos += 3;
|
||||||
|
// extended highest seq_no, contain the highest sequence number received
|
||||||
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
|
||||||
|
received->extendedHighSeqNum);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
//Jitter
|
||||||
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->jitter);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
// Last SR timestamp, our NTP time when we received the last report
|
||||||
|
// This is the value that we read from the send report packet not when we
|
||||||
|
// received it...
|
||||||
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, received->lastSR);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
// Delay since last received report,time since we received the report
|
||||||
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
|
||||||
|
received->delaySinceLastSR);
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
if ((pos + _reportBlocks.size() * 24) >= IP_PACKET_SIZE) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
"%s invalid argument", __FUNCTION__);
|
"%s invalid argument", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
|
std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
||||||
while (!internal_report_blocks_.empty()) {
|
_reportBlocks.begin();
|
||||||
delete internal_report_blocks_.begin()->second;
|
|
||||||
internal_report_blocks_.erase(internal_report_blocks_.begin());
|
|
||||||
}
|
|
||||||
pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t RTCPSender::WriteReportBlocksToBuffer(
|
for (; it != _reportBlocks.end(); it++) {
|
||||||
uint8_t* rtcpbuffer,
|
// we can have multiple report block in a conference
|
||||||
int32_t position,
|
|
||||||
const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
|
|
||||||
std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
|
|
||||||
report_blocks.begin();
|
|
||||||
for (; it != report_blocks.end(); it++) {
|
|
||||||
uint32_t remoteSSRC = it->first;
|
uint32_t remoteSSRC = it->first;
|
||||||
RTCPReportBlock* reportBlock = it->second;
|
RTCPReportBlock* reportBlock = it->second;
|
||||||
if (reportBlock) {
|
if (reportBlock) {
|
||||||
// Remote SSRC
|
// Remote SSRC
|
||||||
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position, remoteSSRC);
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, remoteSSRC);
|
||||||
position += 4;
|
pos += 4;
|
||||||
|
|
||||||
// fraction lost
|
// fraction lost
|
||||||
rtcpbuffer[position++] = reportBlock->fractionLost;
|
rtcpbuffer[pos++] = reportBlock->fractionLost;
|
||||||
|
|
||||||
// cumulative loss
|
// cumulative loss
|
||||||
ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+position,
|
ModuleRTPUtility::AssignUWord24ToBuffer(rtcpbuffer+pos,
|
||||||
reportBlock->cumulativeLost);
|
reportBlock->cumulativeLost);
|
||||||
position += 3;
|
pos += 3;
|
||||||
|
|
||||||
// extended highest seq_no, contain the highest sequence number received
|
// extended highest seq_no, contain the highest sequence number received
|
||||||
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
|
||||||
reportBlock->extendedHighSeqNum);
|
reportBlock->extendedHighSeqNum);
|
||||||
position += 4;
|
pos += 4;
|
||||||
|
|
||||||
// Jitter
|
//Jitter
|
||||||
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
|
||||||
reportBlock->jitter);
|
reportBlock->jitter);
|
||||||
position += 4;
|
pos += 4;
|
||||||
|
|
||||||
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
|
||||||
reportBlock->lastSR);
|
reportBlock->lastSR);
|
||||||
position += 4;
|
pos += 4;
|
||||||
|
|
||||||
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+position,
|
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos,
|
||||||
reportBlock->delaySinceLastSR);
|
reportBlock->delaySinceLastSR);
|
||||||
position += 4;
|
pos += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return position;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no callbacks allowed inside this function
|
// no callbacks allowed inside this function
|
||||||
|
@ -47,8 +47,7 @@ class RTCPSender
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RTCPSender(const int32_t id, const bool audio,
|
RTCPSender(const int32_t id, const bool audio,
|
||||||
Clock* clock, ModuleRtpRtcpImpl* owner,
|
Clock* clock, ModuleRtpRtcpImpl* owner);
|
||||||
ReceiveStatistics* receive_statistics);
|
|
||||||
virtual ~RTCPSender();
|
virtual ~RTCPSender();
|
||||||
|
|
||||||
void ChangeUniqueId(const int32_t id);
|
void ChangeUniqueId(const int32_t id);
|
||||||
@ -92,16 +91,16 @@ public:
|
|||||||
|
|
||||||
int32_t SendRTCP(
|
int32_t SendRTCP(
|
||||||
uint32_t rtcpPacketTypeFlags,
|
uint32_t rtcpPacketTypeFlags,
|
||||||
|
const ReceiveStatistics::RtpReceiveStatistics* receive_stats,
|
||||||
int32_t nackSize = 0,
|
int32_t nackSize = 0,
|
||||||
const uint16_t* nackList = 0,
|
const uint16_t* nackList = 0,
|
||||||
bool repeat = false,
|
bool repeat = false,
|
||||||
uint64_t pictureID = 0);
|
uint64_t pictureID = 0);
|
||||||
|
|
||||||
int32_t AddExternalReportBlock(
|
int32_t AddReportBlock(const uint32_t SSRC,
|
||||||
uint32_t SSRC,
|
|
||||||
const RTCPReportBlock* receiveBlock);
|
const RTCPReportBlock* receiveBlock);
|
||||||
|
|
||||||
int32_t RemoveExternalReportBlock(uint32_t SSRC);
|
int32_t RemoveReportBlock(const uint32_t SSRC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* REMB
|
* REMB
|
||||||
@ -154,71 +153,49 @@ private:
|
|||||||
|
|
||||||
void UpdatePacketRate();
|
void UpdatePacketRate();
|
||||||
|
|
||||||
int32_t WriteAllReportBlocksToBuffer(uint8_t* rtcpbuffer,
|
int32_t AddReportBlocks(uint8_t* rtcpbuffer,
|
||||||
int pos,
|
uint32_t& pos,
|
||||||
uint8_t& numberOfReportBlocks,
|
uint8_t& numberOfReportBlocks,
|
||||||
|
const RTCPReportBlock* received,
|
||||||
const uint32_t NTPsec,
|
const uint32_t NTPsec,
|
||||||
const uint32_t NTPfrac);
|
const uint32_t NTPfrac);
|
||||||
|
|
||||||
int32_t WriteReportBlocksToBuffer(
|
|
||||||
uint8_t* rtcpbuffer,
|
|
||||||
int32_t position,
|
|
||||||
const std::map<uint32_t, RTCPReportBlock*>& report_blocks);
|
|
||||||
|
|
||||||
int32_t AddReportBlock(
|
|
||||||
uint32_t SSRC,
|
|
||||||
std::map<uint32_t, RTCPReportBlock*>* report_blocks,
|
|
||||||
const RTCPReportBlock* receiveBlock);
|
|
||||||
|
|
||||||
bool PrepareReport(StreamStatistician* statistician,
|
|
||||||
RTCPReportBlock* report_block,
|
|
||||||
uint32_t* ntp_secs, uint32_t* ntp_frac);
|
|
||||||
|
|
||||||
int32_t BuildSR(uint8_t* rtcpbuffer,
|
int32_t BuildSR(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint32_t NTPsec,
|
const uint32_t NTPsec,
|
||||||
const uint32_t NTPfrac);
|
const uint32_t NTPfrac,
|
||||||
|
const RTCPReportBlock* received = NULL);
|
||||||
|
|
||||||
int32_t BuildRR(uint8_t* rtcpbuffer,
|
int32_t BuildRR(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint32_t NTPsec,
|
const uint32_t NTPsec,
|
||||||
const uint32_t NTPfrac);
|
const uint32_t NTPfrac,
|
||||||
|
const RTCPReportBlock* received = NULL);
|
||||||
int PrepareRTCP(
|
|
||||||
uint32_t packetTypeFlags,
|
|
||||||
int32_t nackSize,
|
|
||||||
const uint16_t* nackList,
|
|
||||||
bool repeat,
|
|
||||||
uint64_t pictureID,
|
|
||||||
uint8_t* rtcp_buffer,
|
|
||||||
int buffer_size);
|
|
||||||
|
|
||||||
bool ShouldSendReportBlocks(uint32_t rtcp_packet_type) const;
|
|
||||||
|
|
||||||
int32_t BuildExtendedJitterReport(
|
int32_t BuildExtendedJitterReport(
|
||||||
uint8_t* rtcpbuffer,
|
uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint32_t jitterTransmissionTimeOffset);
|
const uint32_t jitterTransmissionTimeOffset);
|
||||||
|
|
||||||
int32_t BuildSDEC(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildSDEC(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildPLI(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildPLI(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildREMB(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildREMB(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildTMMBR(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildTMMBR(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildTMMBN(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildTMMBN(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildAPP(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildAPP(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildVoIPMetric(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildBYE(uint8_t* rtcpbuffer, int& pos);
|
int32_t BuildBYE(uint8_t* rtcpbuffer, uint32_t& pos);
|
||||||
int32_t BuildFIR(uint8_t* rtcpbuffer, int& pos, bool repeat);
|
int32_t BuildFIR(uint8_t* rtcpbuffer, uint32_t& pos, bool repeat);
|
||||||
int32_t BuildSLI(uint8_t* rtcpbuffer,
|
int32_t BuildSLI(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint8_t pictureID);
|
const uint8_t pictureID);
|
||||||
int32_t BuildRPSI(uint8_t* rtcpbuffer,
|
int32_t BuildRPSI(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const uint64_t pictureID,
|
const uint64_t pictureID,
|
||||||
const uint8_t payloadType);
|
const uint8_t payloadType);
|
||||||
|
|
||||||
int32_t BuildNACK(uint8_t* rtcpbuffer,
|
int32_t BuildNACK(uint8_t* rtcpbuffer,
|
||||||
int& pos,
|
uint32_t& pos,
|
||||||
const int32_t nackSize,
|
const int32_t nackSize,
|
||||||
const uint16_t* nackList,
|
const uint16_t* nackList,
|
||||||
std::string* nackString);
|
std::string* nackString);
|
||||||
@ -252,10 +229,7 @@ private:
|
|||||||
uint32_t _remoteSSRC; // SSRC that we receive on our RTP channel
|
uint32_t _remoteSSRC; // SSRC that we receive on our RTP channel
|
||||||
char _CNAME[RTCP_CNAME_SIZE];
|
char _CNAME[RTCP_CNAME_SIZE];
|
||||||
|
|
||||||
|
std::map<uint32_t, RTCPReportBlock*> _reportBlocks;
|
||||||
ReceiveStatistics* receive_statistics_;
|
|
||||||
std::map<uint32_t, RTCPReportBlock*> internal_report_blocks_;
|
|
||||||
std::map<uint32_t, RTCPReportBlock*> external_report_blocks_;
|
|
||||||
std::map<uint32_t, RTCPUtility::RTCPCnameInformation*> _csrcCNAMEs;
|
std::map<uint32_t, RTCPUtility::RTCPCnameInformation*> _csrcCNAMEs;
|
||||||
|
|
||||||
int32_t _cameraDelayMS;
|
int32_t _cameraDelayMS;
|
||||||
|
@ -285,8 +285,7 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
remote_bitrate_estimator_(
|
remote_bitrate_estimator_(
|
||||||
RemoteBitrateEstimatorFactory().Create(
|
RemoteBitrateEstimatorFactory().Create(
|
||||||
&remote_bitrate_observer_,
|
&remote_bitrate_observer_,
|
||||||
system_clock_)),
|
system_clock_)) {
|
||||||
receive_statistics_(ReceiveStatistics::Create(system_clock_)) {
|
|
||||||
test_transport_ = new TestTransport();
|
test_transport_ = new TestTransport();
|
||||||
|
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
@ -299,8 +298,7 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
|
rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
|
||||||
rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
|
rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver(
|
||||||
0, system_clock_, test_transport_, NULL, rtp_payload_registry_.get()));
|
0, system_clock_, test_transport_, NULL, rtp_payload_registry_.get()));
|
||||||
rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_,
|
rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_);
|
||||||
receive_statistics_.get());
|
|
||||||
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, rtp_rtcp_impl_);
|
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, rtp_rtcp_impl_);
|
||||||
test_transport_->SetRTCPReceiver(rtcp_receiver_);
|
test_transport_->SetRTCPReceiver(rtcp_receiver_);
|
||||||
// Initialize
|
// Initialize
|
||||||
@ -330,7 +328,6 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
TestTransport* test_transport_;
|
TestTransport* test_transport_;
|
||||||
MockRemoteBitrateObserver remote_bitrate_observer_;
|
MockRemoteBitrateObserver remote_bitrate_observer_;
|
||||||
scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
|
scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
|
||||||
scoped_ptr<ReceiveStatistics> receive_statistics_;
|
|
||||||
|
|
||||||
enum {kMaxPacketLength = 1500};
|
enum {kMaxPacketLength = 1500};
|
||||||
uint8_t packet_[kMaxPacketLength];
|
uint8_t packet_[kMaxPacketLength];
|
||||||
@ -338,7 +335,7 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
|
|
||||||
TEST_F(RtcpSenderTest, RtcpOff) {
|
TEST_F(RtcpSenderTest, RtcpOff) {
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpOff));
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpOff));
|
||||||
EXPECT_EQ(-1, rtcp_sender_->SendRTCP(kRtcpSr));
|
EXPECT_EQ(-1, rtcp_sender_->SendRTCP(kRtcpSr, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RtcpSenderTest, IJStatus) {
|
TEST_F(RtcpSenderTest, IJStatus) {
|
||||||
@ -375,13 +372,14 @@ TEST_F(RtcpSenderTest, TestCompound) {
|
|||||||
PayloadUnion payload_specific;
|
PayloadUnion payload_specific;
|
||||||
EXPECT_TRUE(rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
|
EXPECT_TRUE(rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
|
||||||
&payload_specific));
|
&payload_specific));
|
||||||
receive_statistics_->IncomingPacket(header, packet_length, false, true);
|
|
||||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(&header, packet_, packet_length,
|
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(&header, packet_, packet_length,
|
||||||
payload_specific, true));
|
payload_specific, true));
|
||||||
|
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true));
|
EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr));
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
memset(&receive_stats, 0, sizeof(receive_stats));
|
||||||
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr, &receive_stats));
|
||||||
|
|
||||||
// Transmission time offset packet should be received.
|
// Transmission time offset packet should be received.
|
||||||
ASSERT_TRUE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags &
|
ASSERT_TRUE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags &
|
||||||
@ -391,7 +389,9 @@ TEST_F(RtcpSenderTest, TestCompound) {
|
|||||||
TEST_F(RtcpSenderTest, TestCompound_NoRtpReceived) {
|
TEST_F(RtcpSenderTest, TestCompound_NoRtpReceived) {
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true));
|
EXPECT_EQ(0, rtcp_sender_->SetIJStatus(true));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
|
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr));
|
// |receive_stats| is NULL since no data has been received.
|
||||||
|
ReceiveStatistics::RtpReceiveStatistics* receive_stats = NULL;
|
||||||
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpRr, receive_stats));
|
||||||
|
|
||||||
// Transmission time offset packet should not be received.
|
// Transmission time offset packet should not be received.
|
||||||
ASSERT_FALSE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags &
|
ASSERT_FALSE(test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags &
|
||||||
@ -409,7 +409,9 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndEmpty) {
|
|||||||
TMMBRSet bounding_set;
|
TMMBRSet bounding_set;
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3));
|
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3));
|
||||||
ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr));
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
memset(&receive_stats, 0, sizeof(receive_stats));
|
||||||
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr, &receive_stats));
|
||||||
// We now expect the packet to show up in the rtcp_packet_info_ of
|
// We now expect the packet to show up in the rtcp_packet_info_ of
|
||||||
// test_transport_.
|
// test_transport_.
|
||||||
ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
||||||
@ -431,7 +433,9 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) {
|
|||||||
|
|
||||||
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3));
|
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3));
|
||||||
ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr));
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
memset(&receive_stats, 0, sizeof(receive_stats));
|
||||||
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(kRtcpSr, &receive_stats));
|
||||||
// We now expect the packet to show up in the rtcp_packet_info_ of
|
// We now expect the packet to show up in the rtcp_packet_info_ of
|
||||||
// test_transport_.
|
// test_transport_.
|
||||||
ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
ASSERT_NE(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
|
||||||
|
@ -282,7 +282,7 @@ bool RtpReceiverImpl::IncomingRtpPacket(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (should_reset_statistics) {
|
if (should_reset_statistics) {
|
||||||
cb_rtp_feedback_->OnResetStatistics(ssrc_);
|
cb_rtp_feedback_->OnResetStatistics();
|
||||||
}
|
}
|
||||||
WebRtcRTPHeader webrtc_rtp_header;
|
WebRtcRTPHeader webrtc_rtp_header;
|
||||||
memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header));
|
memset(&webrtc_rtp_header, 0, sizeof(webrtc_rtp_header));
|
||||||
@ -413,7 +413,7 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader* rtp_header) {
|
|||||||
// We need the payload_type_ to make the call if the remote SSRC is 0.
|
// We need the payload_type_ to make the call if the remote SSRC is 0.
|
||||||
new_ssrc = true;
|
new_ssrc = true;
|
||||||
|
|
||||||
cb_rtp_feedback_->OnResetStatistics(ssrc_);
|
cb_rtp_feedback_->OnResetStatistics();
|
||||||
|
|
||||||
last_received_timestamp_ = 0;
|
last_received_timestamp_ = 0;
|
||||||
last_received_sequence_number_ = 0;
|
last_received_sequence_number_ = 0;
|
||||||
|
@ -41,7 +41,7 @@ RtpRtcp::Configuration::Configuration()
|
|||||||
audio(false),
|
audio(false),
|
||||||
clock(NULL),
|
clock(NULL),
|
||||||
default_module(NULL),
|
default_module(NULL),
|
||||||
receive_statistics(),
|
receive_statistics(NULL),
|
||||||
outgoing_transport(NULL),
|
outgoing_transport(NULL),
|
||||||
rtcp_feedback(NULL),
|
rtcp_feedback(NULL),
|
||||||
intra_frame_callback(NULL),
|
intra_frame_callback(NULL),
|
||||||
@ -74,9 +74,10 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
|
|||||||
configuration.audio_messages,
|
configuration.audio_messages,
|
||||||
configuration.paced_sender),
|
configuration.paced_sender),
|
||||||
rtcp_sender_(configuration.id, configuration.audio, configuration.clock,
|
rtcp_sender_(configuration.id, configuration.audio, configuration.clock,
|
||||||
this, configuration.receive_statistics),
|
this),
|
||||||
rtcp_receiver_(configuration.id, configuration.clock, this),
|
rtcp_receiver_(configuration.id, configuration.clock, this),
|
||||||
clock_(configuration.clock),
|
clock_(configuration.clock),
|
||||||
|
receive_statistics_(configuration.receive_statistics),
|
||||||
id_(configuration.id),
|
id_(configuration.id),
|
||||||
audio_(configuration.audio),
|
audio_(configuration.audio),
|
||||||
collision_detected_(false),
|
collision_detected_(false),
|
||||||
@ -241,7 +242,12 @@ int32_t ModuleRtpRtcpImpl::Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rtcp_sender_.TimeToSendRTCPReport()) {
|
if (rtcp_sender_.TimeToSendRTCPReport()) {
|
||||||
rtcp_sender_.SendRTCP(kRtcpReport);
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
if (receive_statistics_->Statistics(&receive_stats, true)) {
|
||||||
|
rtcp_sender_.SendRTCP(kRtcpReport, &receive_stats);
|
||||||
|
} else {
|
||||||
|
rtcp_sender_.SendRTCP(kRtcpReport, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,7 +576,12 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData(
|
|||||||
if (!have_child_modules) {
|
if (!have_child_modules) {
|
||||||
// Don't send RTCP from default module.
|
// Don't send RTCP from default module.
|
||||||
if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) {
|
if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) {
|
||||||
rtcp_sender_.SendRTCP(kRtcpReport);
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
if (receive_statistics_->Statistics(&receive_stats, true)) {
|
||||||
|
rtcp_sender_.SendRTCP(kRtcpReport, &receive_stats);
|
||||||
|
} else {
|
||||||
|
rtcp_sender_.SendRTCP(kRtcpReport, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rtp_sender_.SendOutgoingData(frame_type,
|
return rtp_sender_.SendOutgoingData(frame_type,
|
||||||
payload_type,
|
payload_type,
|
||||||
@ -926,7 +937,18 @@ int32_t ModuleRtpRtcpImpl::ResetSendDataCountersRTP() {
|
|||||||
int32_t ModuleRtpRtcpImpl::SendRTCP(uint32_t rtcp_packet_type) {
|
int32_t ModuleRtpRtcpImpl::SendRTCP(uint32_t rtcp_packet_type) {
|
||||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SendRTCP(0x%x)",
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "SendRTCP(0x%x)",
|
||||||
rtcp_packet_type);
|
rtcp_packet_type);
|
||||||
return rtcp_sender_.SendRTCP(kRtcpReport);
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
if (rtcp_sender_.Status() == kRtcpCompound ||
|
||||||
|
(rtcp_packet_type & kRtcpReport) ||
|
||||||
|
(rtcp_packet_type & kRtcpSr) ||
|
||||||
|
(rtcp_packet_type & kRtcpRr)) {
|
||||||
|
if (receive_statistics_->Statistics(&receive_stats, true)) {
|
||||||
|
return rtcp_sender_.SendRTCP(rtcp_packet_type, &receive_stats);
|
||||||
|
} else {
|
||||||
|
return rtcp_sender_.SendRTCP(rtcp_packet_type, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rtcp_sender_.SendRTCP(rtcp_packet_type, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::SetRTCPApplicationSpecificData(
|
int32_t ModuleRtpRtcpImpl::SetRTCPApplicationSpecificData(
|
||||||
@ -982,14 +1004,14 @@ int32_t ModuleRtpRtcpImpl::AddRTCPReportBlock(
|
|||||||
const RTCPReportBlock* report_block) {
|
const RTCPReportBlock* report_block) {
|
||||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "AddRTCPReportBlock()");
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "AddRTCPReportBlock()");
|
||||||
|
|
||||||
return rtcp_sender_.AddExternalReportBlock(ssrc, report_block);
|
return rtcp_sender_.AddReportBlock(ssrc, report_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::RemoveRTCPReportBlock(
|
int32_t ModuleRtpRtcpImpl::RemoveRTCPReportBlock(
|
||||||
const uint32_t ssrc) {
|
const uint32_t ssrc) {
|
||||||
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "RemoveRTCPReportBlock()");
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_, "RemoveRTCPReportBlock()");
|
||||||
|
|
||||||
return rtcp_sender_.RemoveExternalReportBlock(ssrc);
|
return rtcp_sender_.RemoveReportBlock(ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (REMB) Receiver Estimated Max Bitrate.
|
// (REMB) Receiver Estimated Max Bitrate.
|
||||||
@ -1143,7 +1165,15 @@ int32_t ModuleRtpRtcpImpl::SendNACK(const uint16_t* nack_list,
|
|||||||
}
|
}
|
||||||
nack_last_seq_number_sent_ = nack_list[start_id + nackLength - 1];
|
nack_last_seq_number_sent_ = nack_list[start_id + nackLength - 1];
|
||||||
|
|
||||||
return rtcp_sender_.SendRTCP(kRtcpNack, nackLength, &nack_list[start_id]);
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
if (rtcp_sender_.Status() == kRtcpCompound &&
|
||||||
|
receive_statistics_->Statistics(&receive_stats, true)) {
|
||||||
|
return rtcp_sender_.SendRTCP(kRtcpNack, &receive_stats, nackLength,
|
||||||
|
&nack_list[start_id]);
|
||||||
|
} else {
|
||||||
|
return rtcp_sender_.SendRTCP(kRtcpNack, NULL, nackLength,
|
||||||
|
&nack_list[start_id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the sent packets, needed to answer to a Negative acknowledgment
|
// Store the sent packets, needed to answer to a Negative acknowledgment
|
||||||
@ -1334,8 +1364,14 @@ int32_t ModuleRtpRtcpImpl::SendRTCPSliceLossIndication(
|
|||||||
id_,
|
id_,
|
||||||
"SendRTCPSliceLossIndication (picture_id:%d)",
|
"SendRTCPSliceLossIndication (picture_id:%d)",
|
||||||
picture_id);
|
picture_id);
|
||||||
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
return rtcp_sender_.SendRTCP(kRtcpSli, 0, 0, false, picture_id);
|
if (rtcp_sender_.Status() == kRtcpCompound &&
|
||||||
|
receive_statistics_->Statistics(&receive_stats, true)) {
|
||||||
|
return rtcp_sender_.SendRTCP(kRtcpSli, &receive_stats, 0, 0, false,
|
||||||
|
picture_id);
|
||||||
|
} else {
|
||||||
|
return rtcp_sender_.SendRTCP(kRtcpSli, NULL, 0, 0, false, picture_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::SetCameraDelay(const int32_t delay_ms) {
|
int32_t ModuleRtpRtcpImpl::SetCameraDelay(const int32_t delay_ms) {
|
||||||
@ -1533,7 +1569,14 @@ void ModuleRtpRtcpImpl::OnRequestSendReport() {
|
|||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(
|
int32_t ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(
|
||||||
const uint64_t picture_id) {
|
const uint64_t picture_id) {
|
||||||
return rtcp_sender_.SendRTCP(kRtcpRpsi, 0, 0, false, picture_id);
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
|
if (rtcp_sender_.Status() == kRtcpCompound &&
|
||||||
|
receive_statistics_->Statistics(&receive_stats, true)) {
|
||||||
|
return rtcp_sender_.SendRTCP(kRtcpRpsi, &receive_stats, 0, 0, false,
|
||||||
|
picture_id);
|
||||||
|
} else {
|
||||||
|
return rtcp_sender_.SendRTCP(kRtcpRpsi, NULL, 0, 0, false, picture_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ModuleRtpRtcpImpl::SendTimeOfSendReport(
|
uint32_t ModuleRtpRtcpImpl::SendTimeOfSendReport(
|
||||||
|
@ -374,6 +374,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
|||||||
private:
|
private:
|
||||||
int64_t RtcpReportInterval();
|
int64_t RtcpReportInterval();
|
||||||
|
|
||||||
|
ReceiveStatistics* receive_statistics_;
|
||||||
|
|
||||||
int32_t id_;
|
int32_t id_;
|
||||||
const bool audio_;
|
const bool audio_;
|
||||||
bool collision_detected_;
|
bool collision_detected_;
|
||||||
|
@ -76,8 +76,8 @@ class TestRtpFeedback : public NullRtpFeedback {
|
|||||||
virtual ~TestRtpFeedback() {}
|
virtual ~TestRtpFeedback() {}
|
||||||
|
|
||||||
virtual void OnIncomingSSRCChanged(const int32_t id,
|
virtual void OnIncomingSSRCChanged(const int32_t id,
|
||||||
const uint32_t ssrc) {
|
const uint32_t SSRC) {
|
||||||
rtp_rtcp_->SetRemoteSSRC(ssrc);
|
rtp_rtcp_->SetRemoteSSRC(SSRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -334,10 +334,8 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
|||||||
EXPECT_EQ(static_cast<uint32_t>(0),
|
EXPECT_EQ(static_cast<uint32_t>(0),
|
||||||
reportBlockReceived.cumulativeLost);
|
reportBlockReceived.cumulativeLost);
|
||||||
|
|
||||||
StreamStatistician *statistician =
|
ReceiveStatistics::RtpReceiveStatistics stats;
|
||||||
receive_statistics2_->GetStatistician(reportBlockReceived.sourceSSRC);
|
EXPECT_TRUE(receive_statistics2_->Statistics(&stats, true));
|
||||||
StreamStatistician::Statistics stats;
|
|
||||||
EXPECT_TRUE(statistician->GetStatistics(&stats, true));
|
|
||||||
EXPECT_EQ(0, stats.fraction_lost);
|
EXPECT_EQ(0, stats.fraction_lost);
|
||||||
EXPECT_EQ((uint32_t)0, stats.cumulative_lost);
|
EXPECT_EQ((uint32_t)0, stats.cumulative_lost);
|
||||||
EXPECT_EQ(test_sequence_number, stats.extended_max_sequence_number);
|
EXPECT_EQ(test_sequence_number, stats.extended_max_sequence_number);
|
||||||
|
@ -1247,12 +1247,10 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost,
|
|||||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
|
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
"%s", __FUNCTION__);
|
"%s", __FUNCTION__);
|
||||||
|
|
||||||
uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
|
|
||||||
uint8_t frac_lost = 0;
|
uint8_t frac_lost = 0;
|
||||||
StreamStatistician* statistician =
|
ReceiveStatistics* receive_statistics = vie_receiver_.GetReceiveStatistics();
|
||||||
vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc);
|
ReceiveStatistics::RtpReceiveStatistics receive_stats;
|
||||||
StreamStatistician::Statistics receive_stats;
|
if (!receive_statistics || !receive_statistics->Statistics(
|
||||||
if (!statistician || !statistician->GetStatistics(
|
|
||||||
&receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) {
|
&receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
|
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
"%s: Could not get received RTP statistics", __FUNCTION__);
|
"%s: Could not get received RTP statistics", __FUNCTION__);
|
||||||
@ -1264,6 +1262,7 @@ int32_t ViEChannel::GetReceivedRtcpStatistics(uint16_t* fraction_lost,
|
|||||||
*jitter_samples = receive_stats.jitter;
|
*jitter_samples = receive_stats.jitter;
|
||||||
*fraction_lost = frac_lost;
|
*fraction_lost = frac_lost;
|
||||||
|
|
||||||
|
uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
|
||||||
uint16_t dummy = 0;
|
uint16_t dummy = 0;
|
||||||
uint16_t rtt = 0;
|
uint16_t rtt = 0;
|
||||||
if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) {
|
if (rtp_rtcp_->RTT(remote_ssrc, &rtt, &dummy, &dummy, &dummy) != 0) {
|
||||||
@ -1281,12 +1280,8 @@ int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent,
|
|||||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
|
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
|
|
||||||
StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->
|
ReceiveStatistics* receive_statistics = vie_receiver_.GetReceiveStatistics();
|
||||||
GetStatistician(vie_receiver_.GetRemoteSsrc());
|
receive_statistics->GetDataCounters(bytes_received, packets_received);
|
||||||
*bytes_received = 0;
|
|
||||||
*packets_received = 0;
|
|
||||||
if (statistician)
|
|
||||||
statistician->GetDataCounters(bytes_received, packets_received);
|
|
||||||
if (rtp_rtcp_->DataCountersRTP(bytes_sent, packets_sent) != 0) {
|
if (rtp_rtcp_->DataCountersRTP(bytes_sent, packets_sent) != 0) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
|
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
"%s: Could not get counters", __FUNCTION__);
|
"%s: Could not get counters", __FUNCTION__);
|
||||||
@ -1866,7 +1861,8 @@ int32_t ViEChannel::OnInitializeDecoder(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) {
|
void ViEChannel::OnIncomingSSRCChanged(const int32_t id,
|
||||||
|
const uint32_t SSRC) {
|
||||||
if (channel_id_ != ChannelId(id)) {
|
if (channel_id_ != ChannelId(id)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
|
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
@ -1875,14 +1871,14 @@ void ViEChannel::OnIncomingSSRCChanged(const int32_t id, const uint32_t ssrc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
|
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
"%s: %u", __FUNCTION__, ssrc);
|
"%s: %u", __FUNCTION__, SSRC);
|
||||||
|
|
||||||
rtp_rtcp_->SetRemoteSSRC(ssrc);
|
rtp_rtcp_->SetRemoteSSRC(SSRC);
|
||||||
|
|
||||||
CriticalSectionScoped cs(callback_cs_.get());
|
CriticalSectionScoped cs(callback_cs_.get());
|
||||||
{
|
{
|
||||||
if (rtp_observer_) {
|
if (rtp_observer_) {
|
||||||
rtp_observer_->IncomingSSRCChanged(channel_id_, ssrc);
|
rtp_observer_->IncomingSSRCChanged(channel_id_, SSRC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1911,11 +1907,8 @@ void ViEChannel::OnIncomingCSRCChanged(const int32_t id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEChannel::OnResetStatistics(uint32_t ssrc) {
|
void ViEChannel::OnResetStatistics() {
|
||||||
StreamStatistician* statistician =
|
vie_receiver_.GetReceiveStatistics()->ResetStatistics();
|
||||||
vie_receiver_.GetReceiveStatistics()->GetStatistician(ssrc);
|
|
||||||
if (statistician)
|
|
||||||
statistician->ResetStatistics();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -209,11 +209,11 @@ class ViEChannel
|
|||||||
const uint8_t channels,
|
const uint8_t channels,
|
||||||
const uint32_t rate);
|
const uint32_t rate);
|
||||||
virtual void OnIncomingSSRCChanged(const int32_t id,
|
virtual void OnIncomingSSRCChanged(const int32_t id,
|
||||||
const uint32_t ssrc);
|
const uint32_t SSRC);
|
||||||
virtual void OnIncomingCSRCChanged(const int32_t id,
|
virtual void OnIncomingCSRCChanged(const int32_t id,
|
||||||
const uint32_t CSRC,
|
const uint32_t CSRC,
|
||||||
const bool added);
|
const bool added);
|
||||||
virtual void OnResetStatistics(uint32_t);
|
virtual void OnResetStatistics();
|
||||||
|
|
||||||
int32_t SetLocalReceiver(const uint16_t rtp_port,
|
int32_t SetLocalReceiver(const uint16_t rtp_port,
|
||||||
const uint16_t rtcp_port,
|
const uint16_t rtcp_port,
|
||||||
|
@ -412,10 +412,8 @@ bool ViEReceiver::IsPacketRetransmitted(const RTPHeader& header) const {
|
|||||||
rtp_receiver_->RTXStatus(&rtx_enabled, &rtx_ssrc, &rtx_payload_type);
|
rtp_receiver_->RTXStatus(&rtx_enabled, &rtx_ssrc, &rtx_payload_type);
|
||||||
if (!rtx_enabled) {
|
if (!rtx_enabled) {
|
||||||
// Check if this is a retransmission.
|
// Check if this is a retransmission.
|
||||||
StreamStatistician::Statistics stats;
|
ReceiveStatistics::RtpReceiveStatistics stats;
|
||||||
StreamStatistician* statistician =
|
if (rtp_receive_statistics_->Statistics(&stats, false)) {
|
||||||
rtp_receive_statistics_->GetStatistician(header.ssrc);
|
|
||||||
if (statistician && statistician->GetStatistics(&stats, false)) {
|
|
||||||
uint16_t min_rtt = 0;
|
uint16_t min_rtt = 0;
|
||||||
rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
|
rtp_rtcp_->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
|
||||||
return rtp_receiver_->RetransmitOfOldPacket(header, stats.jitter,
|
return rtp_receiver_->RetransmitOfOldPacket(header, stats.jitter,
|
||||||
|
@ -360,15 +360,20 @@ Channel::OnPlayTelephoneEvent(int32_t id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc)
|
Channel::OnIncomingSSRCChanged(int32_t id,
|
||||||
|
uint32_t SSRC)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
|
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
|
||||||
"Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
|
"Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
|
||||||
id, ssrc);
|
id, SSRC);
|
||||||
|
|
||||||
int32_t channel = VoEChannelId(id);
|
int32_t channel = VoEChannelId(id);
|
||||||
assert(channel == _channelId);
|
assert(channel == _channelId);
|
||||||
|
|
||||||
|
// Reset RTP-module counters since a new incoming RTP stream is detected
|
||||||
|
rtp_receive_statistics_->ResetDataCounters();
|
||||||
|
rtp_receive_statistics_->ResetStatistics();
|
||||||
|
|
||||||
if (_rtpObserver)
|
if (_rtpObserver)
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(&_callbackCritSect);
|
CriticalSectionScoped cs(&_callbackCritSect);
|
||||||
@ -376,7 +381,7 @@ Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc)
|
|||||||
if (_rtpObserverPtr)
|
if (_rtpObserverPtr)
|
||||||
{
|
{
|
||||||
// Send new SSRC to registered observer using callback
|
// Send new SSRC to registered observer using callback
|
||||||
_rtpObserverPtr->OnIncomingSSRCChanged(channel, ssrc);
|
_rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -403,12 +408,8 @@ void Channel::OnIncomingCSRCChanged(int32_t id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::OnResetStatistics(uint32_t ssrc) {
|
void Channel::OnResetStatistics() {
|
||||||
StreamStatistician* statistician =
|
rtp_receive_statistics_->ResetStatistics();
|
||||||
rtp_receive_statistics_->GetStatistician(ssrc);
|
|
||||||
if (statistician) {
|
|
||||||
statistician->ResetStatistics();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2216,10 +2217,8 @@ bool Channel::IsPacketRetransmitted(const RTPHeader& header) const {
|
|||||||
rtp_receiver_->RTXStatus(&rtx_enabled, &rtx_ssrc, &rtx_payload_type);
|
rtp_receiver_->RTXStatus(&rtx_enabled, &rtx_ssrc, &rtx_payload_type);
|
||||||
if (!rtx_enabled) {
|
if (!rtx_enabled) {
|
||||||
// Check if this is a retransmission.
|
// Check if this is a retransmission.
|
||||||
StreamStatistician::Statistics stats;
|
ReceiveStatistics::RtpReceiveStatistics stats;
|
||||||
StreamStatistician* statistician =
|
if (rtp_receive_statistics_->Statistics(&stats, false)) {
|
||||||
rtp_receive_statistics_->GetStatistician(header.ssrc);
|
|
||||||
if (statistician && statistician->GetStatistics(&stats, false)) {
|
|
||||||
uint16_t min_rtt = 0;
|
uint16_t min_rtt = 0;
|
||||||
_rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
|
_rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
|
||||||
return rtp_receiver_->RetransmitOfOldPacket(header, stats.jitter,
|
return rtp_receiver_->RetransmitOfOldPacket(header, stats.jitter,
|
||||||
@ -3908,10 +3907,8 @@ Channel::GetRTPStatistics(
|
|||||||
{
|
{
|
||||||
// The jitter statistics is updated for each received RTP packet and is
|
// The jitter statistics is updated for each received RTP packet and is
|
||||||
// based on received packets.
|
// based on received packets.
|
||||||
StreamStatistician::Statistics statistics;
|
ReceiveStatistics::RtpReceiveStatistics statistics;
|
||||||
StreamStatistician* statistician =
|
if (!rtp_receive_statistics_->Statistics(
|
||||||
rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
|
|
||||||
if (!statistician || !statistician->GetStatistics(
|
|
||||||
&statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
|
&statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
|
||||||
_engineStatisticsPtr->SetLastError(
|
_engineStatisticsPtr->SetLastError(
|
||||||
VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
|
VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
|
||||||
@ -4005,10 +4002,8 @@ Channel::GetRTPStatistics(CallStatistics& stats)
|
|||||||
|
|
||||||
// The jitter statistics is updated for each received RTP packet and is
|
// The jitter statistics is updated for each received RTP packet and is
|
||||||
// based on received packets.
|
// based on received packets.
|
||||||
StreamStatistician::Statistics statistics;
|
ReceiveStatistics::RtpReceiveStatistics statistics;
|
||||||
StreamStatistician* statistician =
|
if (!rtp_receive_statistics_->Statistics(
|
||||||
rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
|
|
||||||
if (!statistician || !statistician->GetStatistics(
|
|
||||||
&statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
|
&statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
|
||||||
_engineStatisticsPtr->SetLastError(
|
_engineStatisticsPtr->SetLastError(
|
||||||
VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
|
VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
|
||||||
@ -4078,9 +4073,7 @@ Channel::GetRTPStatistics(CallStatistics& stats)
|
|||||||
uint32_t bytesReceived(0);
|
uint32_t bytesReceived(0);
|
||||||
uint32_t packetsReceived(0);
|
uint32_t packetsReceived(0);
|
||||||
|
|
||||||
if (statistician) {
|
rtp_receive_statistics_->GetDataCounters(&bytesReceived, &packetsReceived);
|
||||||
statistician->GetDataCounters(&bytesReceived, &packetsReceived);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
|
if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
|
||||||
&packetsSent) != 0)
|
&packetsSent) != 0)
|
||||||
|
@ -329,12 +329,12 @@ public:
|
|||||||
RTPAliveType alive);
|
RTPAliveType alive);
|
||||||
|
|
||||||
void OnIncomingSSRCChanged(int32_t id,
|
void OnIncomingSSRCChanged(int32_t id,
|
||||||
uint32_t ssrc);
|
uint32_t SSRC);
|
||||||
|
|
||||||
void OnIncomingCSRCChanged(int32_t id,
|
void OnIncomingCSRCChanged(int32_t id,
|
||||||
uint32_t CSRC, bool added);
|
uint32_t CSRC, bool added);
|
||||||
|
|
||||||
void OnResetStatistics(uint32_t ssrc);
|
void OnResetStatistics();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// From RtcpFeedback in the RTP/RTCP module
|
// From RtcpFeedback in the RTP/RTCP module
|
||||||
|
Loading…
x
Reference in New Issue
Block a user