Add video send bitrates to histogram stats:
- total bitrate ("WebRTC.Video.BitrateSentInKbps") - media bitrate ("WebRTC.Video.MediaBitrateSentInKbps") - rtx bitrate ("WebRTC.Video.RtxBitrateSentInKbps") - padding bitrate ("WebRTC.Video.PaddingBitrateSentInKbps") - retransmitted bitrate ("WebRTC.Video.RetransmittedBitrateInKbps") Add retransmitted bytes to StreamDataCounters. Change in UpdateRtpStats to also update counters for retransmitted packet. BUG=crbug/419657 R=mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/30199004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7838 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
7ba9f27f2b
commit
97d0489058
@ -229,13 +229,16 @@ struct RtcpPacketTypeCounter {
|
||||
uint32_t unique_nack_requests; // Number of unique NACKed RTP packets.
|
||||
};
|
||||
|
||||
// Data usage statistics for a (rtp) stream
|
||||
// Data usage statistics for a (rtp) stream.
|
||||
struct StreamDataCounters {
|
||||
StreamDataCounters()
|
||||
: bytes(0),
|
||||
header_bytes(0),
|
||||
padding_bytes(0),
|
||||
packets(0),
|
||||
retransmitted_bytes(0),
|
||||
retransmitted_header_bytes(0),
|
||||
retransmitted_padding_bytes(0),
|
||||
retransmitted_packets(0),
|
||||
fec_packets(0) {}
|
||||
|
||||
@ -244,15 +247,34 @@ struct StreamDataCounters {
|
||||
header_bytes += other.header_bytes;
|
||||
padding_bytes += other.padding_bytes;
|
||||
packets += other.packets;
|
||||
retransmitted_bytes += other.retransmitted_bytes;
|
||||
retransmitted_header_bytes += other.retransmitted_header_bytes;
|
||||
retransmitted_padding_bytes += other.retransmitted_padding_bytes;
|
||||
retransmitted_packets += other.retransmitted_packets;
|
||||
fec_packets += other.fec_packets;
|
||||
}
|
||||
|
||||
size_t TotalBytes() const {
|
||||
return bytes + header_bytes + padding_bytes;
|
||||
}
|
||||
|
||||
size_t RetransmittedBytes() const {
|
||||
return retransmitted_bytes + retransmitted_header_bytes +
|
||||
retransmitted_padding_bytes;
|
||||
}
|
||||
|
||||
size_t MediaPayloadBytes() const {
|
||||
return bytes - retransmitted_bytes;
|
||||
}
|
||||
|
||||
// TODO(pbos): Rename bytes -> media_bytes.
|
||||
size_t bytes; // Payload bytes, excluding RTP headers and padding.
|
||||
size_t header_bytes; // Number of bytes used by RTP headers.
|
||||
size_t padding_bytes; // Number of padding bytes.
|
||||
uint32_t packets; // Number of packets.
|
||||
size_t retransmitted_bytes; // Number of retransmitted payload bytes.
|
||||
size_t retransmitted_header_bytes; // Retransmitted bytes used by RTP header.
|
||||
size_t retransmitted_padding_bytes; // Retransmitted padding bytes.
|
||||
uint32_t retransmitted_packets; // Number of retransmitted packets.
|
||||
uint32_t fec_packets; // Number of redundancy packets.
|
||||
};
|
||||
|
@ -57,7 +57,7 @@ class ReceiveStatistics : public Module {
|
||||
|
||||
// Updates the receive statistics with this packet.
|
||||
virtual void IncomingPacket(const RTPHeader& rtp_header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) = 0;
|
||||
|
||||
// Increment counter for number of FEC packets received.
|
||||
@ -85,7 +85,7 @@ class ReceiveStatistics : public Module {
|
||||
class NullReceiveStatistics : public ReceiveStatistics {
|
||||
public:
|
||||
virtual void IncomingPacket(const RTPHeader& rtp_header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) OVERRIDE;
|
||||
virtual void FecPacketReceived(uint32_t ssrc) OVERRIDE;
|
||||
virtual StatisticianMap GetActiveStatisticians() const OVERRIDE;
|
||||
|
@ -434,13 +434,21 @@ class RtpRtcp : public Module {
|
||||
virtual int32_t ResetSendDataCountersRTP() = 0;
|
||||
|
||||
/*
|
||||
* statistics of the amount of data sent and received
|
||||
* Statistics of the amount of data sent
|
||||
*
|
||||
* return -1 on failure else 0
|
||||
*/
|
||||
virtual int32_t DataCountersRTP(
|
||||
size_t* bytesSent,
|
||||
uint32_t* packetsSent) const = 0;
|
||||
|
||||
/*
|
||||
* Get send statistics for the RTP and RTX stream.
|
||||
*/
|
||||
virtual void GetSendStreamDataCounters(
|
||||
StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const = 0;
|
||||
|
||||
/*
|
||||
* Get received RTCP sender info
|
||||
*
|
||||
@ -455,6 +463,7 @@ class RtpRtcp : public Module {
|
||||
*/
|
||||
virtual int32_t RemoteRTCPStat(
|
||||
std::vector<RTCPReportBlock>* receiveBlocks) const = 0;
|
||||
|
||||
/*
|
||||
* Set received RTCP report block
|
||||
*
|
||||
|
@ -172,6 +172,8 @@ class MockRtpRtcp : public RtpRtcp {
|
||||
int32_t());
|
||||
MOCK_CONST_METHOD2(DataCountersRTP,
|
||||
int32_t(size_t *bytesSent, uint32_t *packetsSent));
|
||||
MOCK_CONST_METHOD2(GetSendStreamDataCounters,
|
||||
void(StreamDataCounters*, StreamDataCounters*));
|
||||
MOCK_METHOD1(RemoteRTCPStat,
|
||||
int32_t(RTCPSenderInfo* senderInfo));
|
||||
MOCK_CONST_METHOD1(RemoteRTCPStat,
|
||||
|
@ -68,26 +68,30 @@ void StreamStatisticianImpl::ResetStatistics() {
|
||||
}
|
||||
|
||||
void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) {
|
||||
UpdateCounters(header, bytes, retransmitted);
|
||||
UpdateCounters(header, packet_length, retransmitted);
|
||||
NotifyRtpCallback();
|
||||
}
|
||||
|
||||
void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) {
|
||||
CriticalSectionScoped cs(stream_lock_.get());
|
||||
bool in_order = InOrderPacketInternal(header.sequenceNumber);
|
||||
ssrc_ = header.ssrc;
|
||||
incoming_bitrate_.Update(bytes);
|
||||
incoming_bitrate_.Update(packet_length);
|
||||
receive_counters_.bytes +=
|
||||
bytes - (header.paddingLength + header.headerLength);
|
||||
packet_length - (header.paddingLength + header.headerLength);
|
||||
receive_counters_.header_bytes += header.headerLength;
|
||||
receive_counters_.padding_bytes += header.paddingLength;
|
||||
++receive_counters_.packets;
|
||||
if (!in_order && retransmitted) {
|
||||
++receive_counters_.retransmitted_packets;
|
||||
receive_counters_.retransmitted_bytes +=
|
||||
packet_length - (header.paddingLength + header.headerLength);
|
||||
receive_counters_.retransmitted_header_bytes += header.headerLength;
|
||||
receive_counters_.retransmitted_padding_bytes += header.paddingLength;
|
||||
}
|
||||
|
||||
if (receive_counters_.packets == 1) {
|
||||
@ -414,7 +418,7 @@ ReceiveStatisticsImpl::~ReceiveStatisticsImpl() {
|
||||
}
|
||||
|
||||
void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) {
|
||||
StreamStatisticianImpl* impl;
|
||||
{
|
||||
@ -431,7 +435,7 @@ void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
|
||||
// this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has
|
||||
// it's own locking so don't hold receive_statistics_lock_ (potential
|
||||
// deadlock).
|
||||
impl->IncomingPacket(header, bytes, retransmitted);
|
||||
impl->IncomingPacket(header, packet_length, retransmitted);
|
||||
}
|
||||
|
||||
void ReceiveStatisticsImpl::FecPacketReceived(uint32_t ssrc) {
|
||||
@ -527,7 +531,7 @@ void ReceiveStatisticsImpl::DataCountersUpdated(const StreamDataCounters& stats,
|
||||
}
|
||||
|
||||
void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) {}
|
||||
|
||||
void NullReceiveStatistics::FecPacketReceived(uint32_t ssrc) {}
|
||||
|
@ -42,7 +42,7 @@ class StreamStatisticianImpl : public StreamStatistician {
|
||||
virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE;
|
||||
|
||||
void IncomingPacket(const RTPHeader& rtp_header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted);
|
||||
void FecPacketReceived();
|
||||
void SetMaxReorderingThreshold(int max_reordering_threshold);
|
||||
@ -56,7 +56,7 @@ class StreamStatisticianImpl : public StreamStatistician {
|
||||
uint32_t receive_time_secs,
|
||||
uint32_t receive_time_frac);
|
||||
void UpdateCounters(const RTPHeader& rtp_header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted);
|
||||
void NotifyRtpCallback() LOCKS_EXCLUDED(stream_lock_.get());
|
||||
void NotifyRtcpCallback() LOCKS_EXCLUDED(stream_lock_.get());
|
||||
@ -108,7 +108,7 @@ class ReceiveStatisticsImpl : public ReceiveStatistics,
|
||||
|
||||
// Implement ReceiveStatistics.
|
||||
virtual void IncomingPacket(const RTPHeader& header,
|
||||
size_t bytes,
|
||||
size_t packet_length,
|
||||
bool retransmitted) OVERRIDE;
|
||||
virtual void FecPacketReceived(uint32_t ssrc) OVERRIDE;
|
||||
virtual StatisticianMap GetActiveStatisticians() const OVERRIDE;
|
||||
|
@ -132,6 +132,23 @@ TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
|
||||
EXPECT_EQ(2u, packets_received);
|
||||
}
|
||||
|
||||
TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
|
||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
|
||||
StreamStatistician* statistician =
|
||||
receive_statistics_->GetStatistician(kSsrc1);
|
||||
ASSERT_TRUE(statistician != NULL);
|
||||
|
||||
StreamDataCounters counters;
|
||||
statistician->GetReceiveStreamDataCounters(&counters);
|
||||
EXPECT_EQ(1u, counters.packets);
|
||||
|
||||
// GetReceiveStreamDataCounters includes reset counter values.
|
||||
statistician->ResetStatistics();
|
||||
receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
|
||||
statistician->GetReceiveStreamDataCounters(&counters);
|
||||
EXPECT_EQ(2u, counters.packets);
|
||||
}
|
||||
|
||||
TEST_F(ReceiveStatisticsTest, RtcpCallbacks) {
|
||||
class TestCallback : public RtcpStatisticsCallback {
|
||||
public:
|
||||
@ -232,20 +249,22 @@ class RtpTestCallback : public StreamDataCountersCallback {
|
||||
++num_calls_;
|
||||
}
|
||||
|
||||
void ExpectMatches(uint32_t num_calls,
|
||||
uint32_t ssrc,
|
||||
size_t bytes,
|
||||
size_t padding,
|
||||
uint32_t packets,
|
||||
uint32_t retransmits,
|
||||
uint32_t fec) {
|
||||
void Matches(uint32_t num_calls,
|
||||
uint32_t ssrc,
|
||||
const StreamDataCounters& expected) {
|
||||
EXPECT_EQ(num_calls, num_calls_);
|
||||
EXPECT_EQ(ssrc, ssrc_);
|
||||
EXPECT_EQ(bytes, stats_.bytes);
|
||||
EXPECT_EQ(padding, stats_.padding_bytes);
|
||||
EXPECT_EQ(packets, stats_.packets);
|
||||
EXPECT_EQ(retransmits, stats_.retransmitted_packets);
|
||||
EXPECT_EQ(fec, stats_.fec_packets);
|
||||
EXPECT_EQ(expected.bytes, stats_.bytes);
|
||||
EXPECT_EQ(expected.header_bytes, stats_.header_bytes);
|
||||
EXPECT_EQ(expected.padding_bytes, stats_.padding_bytes);
|
||||
EXPECT_EQ(expected.packets, stats_.packets);
|
||||
EXPECT_EQ(expected.retransmitted_bytes, stats_.retransmitted_bytes);
|
||||
EXPECT_EQ(expected.retransmitted_header_bytes,
|
||||
stats_.retransmitted_header_bytes);
|
||||
EXPECT_EQ(expected.retransmitted_padding_bytes,
|
||||
stats_.retransmitted_padding_bytes);
|
||||
EXPECT_EQ(expected.retransmitted_packets, stats_.retransmitted_packets);
|
||||
EXPECT_EQ(expected.fec_packets, stats_.fec_packets);
|
||||
}
|
||||
|
||||
uint32_t num_calls_;
|
||||
@ -264,7 +283,17 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
|
||||
header1_.headerLength = kHeaderLength;
|
||||
receive_statistics_->IncomingPacket(
|
||||
header1_, kPacketSize1 + kHeaderLength, false);
|
||||
callback.ExpectMatches(1, kSsrc1, kPacketSize1, 0, 1, 0, 0);
|
||||
StreamDataCounters expected;
|
||||
expected.bytes = kPacketSize1;
|
||||
expected.header_bytes = kHeaderLength;
|
||||
expected.padding_bytes = 0;
|
||||
expected.packets = 1;
|
||||
expected.retransmitted_bytes = 0;
|
||||
expected.retransmitted_header_bytes = 0;
|
||||
expected.retransmitted_padding_bytes = 0;
|
||||
expected.retransmitted_packets = 0;
|
||||
expected.fec_packets = 0;
|
||||
callback.Matches(1, kSsrc1, expected);
|
||||
|
||||
++header1_.sequenceNumber;
|
||||
clock_.AdvanceTimeMilliseconds(5);
|
||||
@ -272,14 +301,25 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
|
||||
// Another packet of size kPacketSize1 with 9 bytes padding.
|
||||
receive_statistics_->IncomingPacket(
|
||||
header1_, kPacketSize1 + kHeaderLength + kPaddingLength, false);
|
||||
callback.ExpectMatches(2, kSsrc1, 2 * kPacketSize1, kPaddingLength, 2, 0, 0);
|
||||
expected.bytes = kPacketSize1 * 2;
|
||||
expected.header_bytes = kHeaderLength * 2;
|
||||
expected.padding_bytes = kPaddingLength;
|
||||
expected.packets = 2;
|
||||
callback.Matches(2, kSsrc1, expected);
|
||||
|
||||
clock_.AdvanceTimeMilliseconds(5);
|
||||
// Retransmit last packet.
|
||||
receive_statistics_->IncomingPacket(
|
||||
header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
|
||||
callback.ExpectMatches(
|
||||
3, kSsrc1, 3 * kPacketSize1, kPaddingLength * 2, 3, 1, 0);
|
||||
expected.bytes = kPacketSize1 * 3;
|
||||
expected.header_bytes = kHeaderLength * 3;
|
||||
expected.padding_bytes = kPaddingLength * 2;
|
||||
expected.packets = 3;
|
||||
expected.retransmitted_bytes = kPacketSize1;
|
||||
expected.retransmitted_header_bytes = kHeaderLength;
|
||||
expected.retransmitted_padding_bytes = kPaddingLength;
|
||||
expected.retransmitted_packets = 1;
|
||||
callback.Matches(3, kSsrc1, expected);
|
||||
|
||||
header1_.paddingLength = 0;
|
||||
++header1_.sequenceNumber;
|
||||
@ -288,8 +328,11 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
|
||||
receive_statistics_->IncomingPacket(
|
||||
header1_, kPacketSize1 + kHeaderLength, false);
|
||||
receive_statistics_->FecPacketReceived(kSsrc1);
|
||||
callback.ExpectMatches(
|
||||
5, kSsrc1, 4 * kPacketSize1, kPaddingLength * 2, 4, 1, 1);
|
||||
expected.bytes = kPacketSize1 * 4;
|
||||
expected.header_bytes = kHeaderLength * 4;
|
||||
expected.packets = 4;
|
||||
expected.fec_packets = 1;
|
||||
callback.Matches(5, kSsrc1, expected);
|
||||
|
||||
receive_statistics_->RegisterRtpStatisticsCallback(NULL);
|
||||
|
||||
@ -298,8 +341,7 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
|
||||
clock_.AdvanceTimeMilliseconds(5);
|
||||
receive_statistics_->IncomingPacket(
|
||||
header1_, kPacketSize1 + kHeaderLength, true);
|
||||
callback.ExpectMatches(
|
||||
5, kSsrc1, 4 * kPacketSize1, kPaddingLength * 2, 4, 1, 1);
|
||||
callback.Matches(5, kSsrc1, expected);
|
||||
}
|
||||
|
||||
TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
|
||||
@ -315,9 +357,16 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) {
|
||||
header1_.headerLength = kHeaderLength;
|
||||
receive_statistics_->IncomingPacket(
|
||||
header1_, kPacketSize1 + kHeaderLength, false);
|
||||
callback.ExpectMatches(1, kSsrc1, kPacketSize1, 0, 1, 0, 0);
|
||||
StreamDataCounters expected;
|
||||
expected.bytes = kPacketSize1;
|
||||
expected.header_bytes = kHeaderLength;
|
||||
expected.padding_bytes = 0;
|
||||
expected.packets = 1;
|
||||
expected.fec_packets = 0;
|
||||
callback.Matches(1, kSsrc1, expected);
|
||||
|
||||
receive_statistics_->FecPacketReceived(kSsrc1);
|
||||
callback.ExpectMatches(2, kSsrc1, kPacketSize1, 0, 1, 0, 1);
|
||||
expected.fec_packets = 1;
|
||||
callback.Matches(2, kSsrc1, expected);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -803,6 +803,7 @@ bool ModuleRtpRtcpImpl::RtcpXrRrtrStatus() const {
|
||||
return rtcp_sender_.RtcpXrReceiverReferenceTime();
|
||||
}
|
||||
|
||||
// TODO(asapersson): Replace this method with the one below.
|
||||
int32_t ModuleRtpRtcpImpl::DataCountersRTP(
|
||||
size_t* bytes_sent,
|
||||
uint32_t* packets_sent) const {
|
||||
@ -821,6 +822,12 @@ int32_t ModuleRtpRtcpImpl::DataCountersRTP(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModuleRtpRtcpImpl::GetSendStreamDataCounters(
|
||||
StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const {
|
||||
rtp_sender_.GetDataCounters(rtp_counters, rtx_counters);
|
||||
}
|
||||
|
||||
int32_t ModuleRtpRtcpImpl::RemoteRTCPStat(RTCPSenderInfo* sender_info) {
|
||||
return rtcp_receiver_.SenderInfoReceived(sender_info);
|
||||
}
|
||||
|
@ -177,6 +177,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
||||
virtual int32_t DataCountersRTP(size_t* bytes_sent,
|
||||
uint32_t* packets_sent) const OVERRIDE;
|
||||
|
||||
virtual void GetSendStreamDataCounters(
|
||||
StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const OVERRIDE;
|
||||
|
||||
// Get received RTCP report, sender info.
|
||||
virtual int32_t RemoteRTCPStat(RTCPSenderInfo* sender_info) OVERRIDE;
|
||||
|
||||
|
@ -890,7 +890,7 @@ bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
|
||||
}
|
||||
|
||||
void RTPSender::UpdateRtpStats(const uint8_t* buffer,
|
||||
size_t size,
|
||||
size_t packet_length,
|
||||
const RTPHeader& header,
|
||||
bool is_rtx,
|
||||
bool is_retransmit) {
|
||||
@ -905,7 +905,7 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer,
|
||||
counters = &rtp_stats_;
|
||||
}
|
||||
|
||||
total_bitrate_sent_.Update(size);
|
||||
total_bitrate_sent_.Update(packet_length);
|
||||
++counters->packets;
|
||||
if (IsFecPacket(buffer, header)) {
|
||||
++counters->fec_packets;
|
||||
@ -913,11 +913,15 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer,
|
||||
|
||||
if (is_retransmit) {
|
||||
++counters->retransmitted_packets;
|
||||
} else {
|
||||
counters->bytes += size - (header.headerLength + header.paddingLength);
|
||||
counters->header_bytes += header.headerLength;
|
||||
counters->padding_bytes += header.paddingLength;
|
||||
counters->retransmitted_bytes +=
|
||||
packet_length - (header.headerLength + header.paddingLength);
|
||||
counters->retransmitted_header_bytes += header.headerLength;
|
||||
counters->retransmitted_padding_bytes += header.paddingLength;
|
||||
}
|
||||
counters->bytes +=
|
||||
packet_length - (header.headerLength + header.paddingLength);
|
||||
counters->header_bytes += header.headerLength;
|
||||
counters->padding_bytes += header.paddingLength;
|
||||
|
||||
if (rtp_stats_callback_) {
|
||||
rtp_stats_callback_->DataCountersUpdated(*counters, ssrc);
|
||||
|
@ -327,7 +327,7 @@ class RTPSender : public RTPSenderInterface {
|
||||
const int64_t now_ms) const;
|
||||
|
||||
void UpdateRtpStats(const uint8_t* buffer,
|
||||
size_t size,
|
||||
size_t packet_length,
|
||||
const RTPHeader& header,
|
||||
bool is_rtx,
|
||||
bool is_retransmit);
|
||||
|
@ -927,16 +927,20 @@ TEST_F(RtpSenderTest, StreamDataCountersCallbacks) {
|
||||
|
||||
uint32_t ssrc_;
|
||||
StreamDataCounters counters_;
|
||||
bool Matches(uint32_t ssrc, size_t bytes, size_t header_bytes,
|
||||
size_t padding, uint32_t packets, uint32_t retransmits,
|
||||
uint32_t fec) {
|
||||
return ssrc_ == ssrc &&
|
||||
counters_.bytes == bytes &&
|
||||
counters_.header_bytes == header_bytes &&
|
||||
counters_.padding_bytes == padding &&
|
||||
counters_.packets == packets &&
|
||||
counters_.retransmitted_packets == retransmits &&
|
||||
counters_.fec_packets == fec;
|
||||
void Matches(uint32_t ssrc, const StreamDataCounters& counters) {
|
||||
EXPECT_EQ(ssrc, ssrc_);
|
||||
EXPECT_EQ(counters.bytes, counters_.bytes);
|
||||
EXPECT_EQ(counters.header_bytes, counters_.header_bytes);
|
||||
EXPECT_EQ(counters.padding_bytes, counters_.padding_bytes);
|
||||
EXPECT_EQ(counters.packets, counters_.packets);
|
||||
EXPECT_EQ(counters.retransmitted_bytes, counters_.retransmitted_bytes);
|
||||
EXPECT_EQ(counters.retransmitted_header_bytes,
|
||||
counters_.retransmitted_header_bytes);
|
||||
EXPECT_EQ(counters.retransmitted_padding_bytes,
|
||||
counters_.retransmitted_padding_bytes);
|
||||
EXPECT_EQ(counters.retransmitted_packets,
|
||||
counters_.retransmitted_packets);
|
||||
EXPECT_EQ(counters.fec_packets, counters_.fec_packets);
|
||||
}
|
||||
|
||||
} callback;
|
||||
@ -957,21 +961,37 @@ TEST_F(RtpSenderTest, StreamDataCountersCallbacks) {
|
||||
ASSERT_EQ(0, rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234,
|
||||
4321, payload, sizeof(payload),
|
||||
NULL));
|
||||
|
||||
// {bytes = 6, header = 12, padding = 0, packets = 1, retrans = 0, fec = 0}
|
||||
EXPECT_TRUE(callback.Matches(ssrc, 6, 12, 0, 1, 0, 0));
|
||||
StreamDataCounters expected;
|
||||
expected.bytes = 6;
|
||||
expected.header_bytes = 12;
|
||||
expected.padding_bytes = 0;
|
||||
expected.packets = 1;
|
||||
expected.retransmitted_bytes = 0;
|
||||
expected.retransmitted_header_bytes = 0;
|
||||
expected.retransmitted_padding_bytes = 0;
|
||||
expected.retransmitted_packets = 0;
|
||||
expected.fec_packets = 0;
|
||||
callback.Matches(ssrc, expected);
|
||||
|
||||
// Retransmit a frame.
|
||||
uint16_t seqno = rtp_sender_->SequenceNumber() - 1;
|
||||
rtp_sender_->ReSendPacket(seqno, 0);
|
||||
|
||||
// bytes = 6, header = 12, padding = 0, packets = 2, retrans = 1, fec = 0}
|
||||
EXPECT_TRUE(callback.Matches(ssrc, 6, 12, 0, 2, 1, 0));
|
||||
expected.bytes = 12;
|
||||
expected.header_bytes = 24;
|
||||
expected.packets = 2;
|
||||
expected.retransmitted_bytes = 6;
|
||||
expected.retransmitted_header_bytes = 12;
|
||||
expected.retransmitted_padding_bytes = 0;
|
||||
expected.retransmitted_packets = 1;
|
||||
callback.Matches(ssrc, expected);
|
||||
|
||||
// Send padding.
|
||||
rtp_sender_->TimeToSendPadding(kMaxPaddingSize);
|
||||
// {bytes = 6, header = 24, padding = 224, packets = 3, retrans = 1, fec = 0}
|
||||
EXPECT_TRUE(callback.Matches(ssrc, 6, 24, kMaxPaddingSize, 3, 1, 0));
|
||||
expected.bytes = 12;
|
||||
expected.header_bytes = 36;
|
||||
expected.padding_bytes = kMaxPaddingSize;
|
||||
expected.packets = 3;
|
||||
callback.Matches(ssrc, expected);
|
||||
|
||||
// Send FEC.
|
||||
rtp_sender_->SetGenericFECStatus(true, kRedPayloadType, kUlpfecPayloadType);
|
||||
@ -984,9 +1004,11 @@ TEST_F(RtpSenderTest, StreamDataCountersCallbacks) {
|
||||
ASSERT_EQ(0, rtp_sender_->SendOutgoingData(kVideoFrameDelta, payload_type,
|
||||
1234, 4321, payload,
|
||||
sizeof(payload), NULL));
|
||||
|
||||
// {bytes = 34, header = 48, padding = 224, packets = 5, retrans = 1, fec = 1}
|
||||
EXPECT_TRUE(callback.Matches(ssrc, 34, 48, kMaxPaddingSize, 5, 1, 1));
|
||||
expected.bytes = 40;
|
||||
expected.header_bytes = 60;
|
||||
expected.packets = 5;
|
||||
expected.fec_packets = 1;
|
||||
callback.Matches(ssrc, expected);
|
||||
|
||||
rtp_sender_->RegisterRtpStatisticsCallback(NULL);
|
||||
}
|
||||
@ -1147,9 +1169,12 @@ TEST_F(RtpSenderTest, BytesReportedCorrectly) {
|
||||
EXPECT_EQ(rtx_stats.header_bytes, 24u);
|
||||
EXPECT_EQ(rtx_stats.padding_bytes, 2 * kMaxPaddingSize);
|
||||
|
||||
EXPECT_EQ(rtp_stats.TotalBytes(),
|
||||
rtp_stats.bytes + rtp_stats.header_bytes + rtp_stats.padding_bytes);
|
||||
EXPECT_EQ(rtx_stats.TotalBytes(),
|
||||
rtx_stats.bytes + rtx_stats.header_bytes + rtx_stats.padding_bytes);
|
||||
|
||||
EXPECT_EQ(transport_.total_bytes_sent_,
|
||||
rtp_stats.bytes + rtp_stats.header_bytes + rtp_stats.padding_bytes +
|
||||
rtx_stats.bytes + rtx_stats.header_bytes +
|
||||
rtx_stats.padding_bytes);
|
||||
rtp_stats.TotalBytes() + rtx_stats.TotalBytes());
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -78,6 +78,9 @@
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 10000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) RTC_HISTOGRAM_COUNTS( \
|
||||
name, sample, 1, 100000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCounts( \
|
||||
|
@ -148,7 +148,8 @@ ViEChannel::ViEChannel(int32_t channel_id,
|
||||
nack_history_size_sender_(kSendSidePacketHistorySize),
|
||||
max_nack_reordering_threshold_(kMaxPacketAgeToNack),
|
||||
pre_render_callback_(NULL),
|
||||
start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()) {
|
||||
start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()),
|
||||
start_send_ms_(0) {
|
||||
RtpRtcp::Configuration configuration = CreateRtpRtcpConfiguration();
|
||||
configuration.remote_bitrate_estimator = remote_bitrate_estimator;
|
||||
configuration.receive_statistics = vie_receiver_.GetReceiveStatistics();
|
||||
@ -236,6 +237,7 @@ ViEChannel::~ViEChannel() {
|
||||
}
|
||||
|
||||
void ViEChannel::UpdateHistograms() {
|
||||
// TODO(asapersson): Use time from first sent/received packet.
|
||||
float elapsed_minutes =
|
||||
(Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 60000.0f;
|
||||
if (elapsed_minutes < metrics::kMinRunTimeInSeconds / 60.0f) {
|
||||
@ -271,29 +273,55 @@ void ViEChannel::UpdateHistograms() {
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute",
|
||||
rtcp_sent.pli_packets / elapsed_minutes);
|
||||
|
||||
StreamDataCounters data;
|
||||
StreamDataCounters rtx_data;
|
||||
GetReceiveStreamDataCounters(&data, &rtx_data);
|
||||
uint32_t media_bytes = data.bytes;
|
||||
uint32_t rtx_bytes =
|
||||
rtx_data.bytes + rtx_data.header_bytes + rtx_data.padding_bytes;
|
||||
uint32_t total_bytes = data.bytes + data.header_bytes + data.padding_bytes;
|
||||
total_bytes += rtx_bytes;
|
||||
uint32_t padding_bytes = data.padding_bytes + rtx_data.padding_bytes;
|
||||
StreamDataCounters rtp;
|
||||
StreamDataCounters rtx;
|
||||
GetReceiveStreamDataCounters(&rtp, &rtx);
|
||||
StreamDataCounters rtp_rtx = rtp;
|
||||
rtp_rtx.Add(rtx);
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.BitrateReceivedInKbps",
|
||||
total_bytes * 8 / (elapsed_minutes * 60) / 1000);
|
||||
rtp_rtx.TotalBytes() * 8 / (elapsed_minutes * 60) / 1000);
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps",
|
||||
media_bytes * 8 / (elapsed_minutes * 60) / 1000);
|
||||
rtp.MediaPayloadBytes() * 8 / (elapsed_minutes * 60) / 1000);
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PaddingBitrateReceivedInKbps",
|
||||
padding_bytes * 8 / (elapsed_minutes * 60) / 1000);
|
||||
rtp_rtx.padding_bytes * 8 / (elapsed_minutes * 60) / 1000);
|
||||
RTC_HISTOGRAM_COUNTS_10000(
|
||||
"WebRTC.Video.RetransmittedBitrateReceivedInKbps",
|
||||
rtp_rtx.RetransmittedBytes() * 8 / (elapsed_minutes * 60) / 1000);
|
||||
uint32_t ssrc = 0;
|
||||
if (vie_receiver_.GetRtxSsrc(&ssrc)) {
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps",
|
||||
rtx_bytes * 8 / (elapsed_minutes * 60) / 1000);
|
||||
rtx.TotalBytes() * 8 / (elapsed_minutes * 60) / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViEChannel::UpdateHistogramsAtStopSend() {
|
||||
// TODO(asapersson): Use time from first sent packet.
|
||||
int64_t elapsed_sec =
|
||||
(Clock::GetRealTimeClock()->TimeInMilliseconds() - start_send_ms_) / 1000;
|
||||
if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
|
||||
return;
|
||||
}
|
||||
StreamDataCounters rtp;
|
||||
StreamDataCounters rtx;
|
||||
GetSendStreamDataCounters(&rtp, &rtx);
|
||||
StreamDataCounters rtp_rtx = rtp;
|
||||
rtp_rtx.Add(rtx);
|
||||
RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.BitrateSentInKbps",
|
||||
rtp_rtx.TotalBytes() * 8 / elapsed_sec / 1000);
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateSentInKbps",
|
||||
rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000);
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PaddingBitrateSentInKbps",
|
||||
rtp_rtx.padding_bytes * 8 / elapsed_sec / 1000);
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RetransmittedBitrateSentInKbps",
|
||||
rtp_rtx.RetransmittedBytes() * 8 / elapsed_sec / 1000);
|
||||
uint32_t ssrc = 0;
|
||||
if (vie_receiver_.GetRtxSsrc(&ssrc)) {
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateSentInKbps",
|
||||
rtx.TotalBytes() * 8 / elapsed_sec / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
|
||||
bool new_stream) {
|
||||
if (!sender_) {
|
||||
@ -1174,20 +1202,44 @@ int32_t ViEChannel::GetRtpStatistics(size_t* bytes_sent,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ViEChannel::GetSendStreamDataCounters(
|
||||
StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const {
|
||||
rtp_rtcp_->GetSendStreamDataCounters(rtp_counters, rtx_counters);
|
||||
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
|
||||
for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
|
||||
it != simulcast_rtp_rtcp_.end();
|
||||
it++) {
|
||||
StreamDataCounters rtp_data;
|
||||
StreamDataCounters rtx_data;
|
||||
(*it)->GetSendStreamDataCounters(&rtp_data, &rtx_data);
|
||||
rtp_counters->Add(rtp_data);
|
||||
rtx_counters->Add(rtx_data);
|
||||
}
|
||||
for (std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
|
||||
it != removed_rtp_rtcp_.end(); ++it) {
|
||||
StreamDataCounters rtp_data;
|
||||
StreamDataCounters rtx_data;
|
||||
(*it)->GetSendStreamDataCounters(&rtp_data, &rtx_data);
|
||||
rtp_counters->Add(rtp_data);
|
||||
rtx_counters->Add(rtx_data);
|
||||
}
|
||||
}
|
||||
|
||||
void ViEChannel::GetReceiveStreamDataCounters(
|
||||
StreamDataCounters* data,
|
||||
StreamDataCounters* rtx_data) const {
|
||||
StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const {
|
||||
StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->
|
||||
GetStatistician(vie_receiver_.GetRemoteSsrc());
|
||||
if (statistician) {
|
||||
statistician->GetReceiveStreamDataCounters(data);
|
||||
statistician->GetReceiveStreamDataCounters(rtp_counters);
|
||||
}
|
||||
uint32_t rtx_ssrc = 0;
|
||||
if (vie_receiver_.GetRtxSsrc(&rtx_ssrc)) {
|
||||
StreamStatistician* statistician =
|
||||
vie_receiver_.GetReceiveStatistics()->GetStatistician(rtx_ssrc);
|
||||
if (statistician) {
|
||||
statistician->GetReceiveStreamDataCounters(rtx_data);
|
||||
statistician->GetReceiveStreamDataCounters(rtx_counters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1341,10 +1393,12 @@ int32_t ViEChannel::StartSend() {
|
||||
rtp_rtcp->SetSendingMediaStatus(true);
|
||||
rtp_rtcp->SetSendingStatus(true);
|
||||
}
|
||||
start_send_ms_ = Clock::GetRealTimeClock()->TimeInMilliseconds();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ViEChannel::StopSend() {
|
||||
UpdateHistogramsAtStopSend();
|
||||
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
|
||||
rtp_rtcp_->SetSendingMediaStatus(false);
|
||||
for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
|
||||
|
@ -194,9 +194,13 @@ class ViEChannel
|
||||
size_t* bytes_received,
|
||||
uint32_t* packets_received) const;
|
||||
|
||||
// Gets send statistics for the rtp and rtx stream.
|
||||
void GetSendStreamDataCounters(StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const;
|
||||
|
||||
// Gets received stream data counters.
|
||||
void GetReceiveStreamDataCounters(StreamDataCounters* data,
|
||||
StreamDataCounters* rtx_data) const;
|
||||
void GetReceiveStreamDataCounters(StreamDataCounters* rtp_counters,
|
||||
StreamDataCounters* rtx_counters) const;
|
||||
|
||||
// Called on update of RTP statistics.
|
||||
void RegisterSendChannelRtpStatisticsCallback(
|
||||
@ -379,6 +383,7 @@ class ViEChannel
|
||||
void SetRtxSendStatus(bool enable);
|
||||
|
||||
void UpdateHistograms();
|
||||
void UpdateHistogramsAtStopSend();
|
||||
|
||||
// ViEChannel exposes methods that allow to modify observers and callbacks
|
||||
// to be modified. Such an API-style is cumbersome to implement and maintain
|
||||
@ -498,6 +503,7 @@ class ViEChannel
|
||||
int max_nack_reordering_threshold_;
|
||||
I420FrameCallback* pre_render_callback_;
|
||||
const int64_t start_ms_;
|
||||
int64_t start_send_ms_;
|
||||
|
||||
std::map<uint32_t, RTCPReportBlock> prev_report_blocks_;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user