Wire up bandwidth stats to the new API and webrtcvideoengine2.
Adds stats to verify bandwidth and pacer stats. BUG=1788 R=mflodman@webrtc.org, pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/24969004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7634 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
a22a628356
commit
0bae1fab4a
@ -1202,7 +1202,21 @@ void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
|
||||
|
||||
void WebRtcVideoChannel2::FillBandwidthEstimationStats(
|
||||
VideoMediaInfo* video_media_info) {
|
||||
// TODO(pbos): Implement.
|
||||
BandwidthEstimationInfo bwe_info;
|
||||
webrtc::Call::Stats stats = call_->GetStats();
|
||||
bwe_info.available_send_bandwidth = stats.send_bandwidth_bps;
|
||||
bwe_info.available_recv_bandwidth = stats.recv_bandwidth_bps;
|
||||
bwe_info.bucket_delay = stats.pacer_delay_ms;
|
||||
|
||||
// Get send stream bitrate stats.
|
||||
rtc::CritScope stream_lock(&stream_crit_);
|
||||
for (std::map<uint32, WebRtcVideoSendStream*>::iterator stream =
|
||||
send_streams_.begin();
|
||||
stream != send_streams_.end();
|
||||
++stream) {
|
||||
stream->second->FillBandwidthEstimationInfo(&bwe_info);
|
||||
}
|
||||
video_media_info->bw_estimations.push_back(bwe_info);
|
||||
}
|
||||
|
||||
bool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
|
||||
@ -1842,12 +1856,12 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
info.framerate_input = stats.input_frame_rate;
|
||||
info.framerate_sent = stats.encode_frame_rate;
|
||||
|
||||
for (std::map<uint32_t, webrtc::StreamStats>::iterator it =
|
||||
for (std::map<uint32_t, webrtc::SsrcStats>::iterator it =
|
||||
stats.substreams.begin();
|
||||
it != stats.substreams.end();
|
||||
++it) {
|
||||
// TODO(pbos): Wire up additional stats, such as padding bytes.
|
||||
webrtc::StreamStats stream_stats = it->second;
|
||||
webrtc::SsrcStats stream_stats = it->second;
|
||||
info.bytes_sent += stream_stats.rtp_stats.bytes +
|
||||
stream_stats.rtp_stats.header_bytes +
|
||||
stream_stats.rtp_stats.padding_bytes;
|
||||
@ -1857,7 +1871,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
|
||||
if (!stats.substreams.empty()) {
|
||||
// TODO(pbos): Report fraction lost per SSRC.
|
||||
webrtc::StreamStats first_stream_stats = stats.substreams.begin()->second;
|
||||
webrtc::SsrcStats first_stream_stats = stats.substreams.begin()->second;
|
||||
info.fraction_lost =
|
||||
static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
|
||||
(1 << 8);
|
||||
@ -1884,6 +1898,23 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
|
||||
BandwidthEstimationInfo* bwe_info) {
|
||||
rtc::CritScope cs(&lock_);
|
||||
if (stream_ == NULL) {
|
||||
return;
|
||||
}
|
||||
webrtc::VideoSendStream::Stats stats = stream_->GetStats();
|
||||
for (std::map<uint32_t, webrtc::SsrcStats>::iterator it =
|
||||
stats.substreams.begin();
|
||||
it != stats.substreams.end();
|
||||
++it) {
|
||||
bwe_info->transmit_bitrate += it->second.total_bitrate_bps;
|
||||
bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps;
|
||||
}
|
||||
bwe_info->actual_enc_bitrate = stats.media_bitrate_bps;
|
||||
}
|
||||
|
||||
void WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest(
|
||||
CoordinatedVideoAdapter::AdaptRequest adapt_request) {
|
||||
rtc::CritScope cs(&lock_);
|
||||
|
@ -315,6 +315,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
|
||||
void Stop();
|
||||
|
||||
VideoSenderInfo GetVideoSenderInfo();
|
||||
void FillBandwidthEstimationInfo(BandwidthEstimationInfo* bwe_info);
|
||||
|
||||
void OnCpuResolutionRequest(
|
||||
CoordinatedVideoAdapter::AdaptRequest adapt_request);
|
||||
|
@ -294,12 +294,9 @@ webrtc::PacketReceiver* FakeCall::Receiver() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t FakeCall::SendBitrateEstimate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t FakeCall::ReceiveBitrateEstimate() {
|
||||
return 0;
|
||||
webrtc::Call::Stats FakeCall::GetStats() const {
|
||||
webrtc::Call::Stats stats;
|
||||
return stats;
|
||||
}
|
||||
|
||||
void FakeCall::SignalNetworkState(webrtc::Call::NetworkState state) {
|
||||
|
@ -127,8 +127,7 @@ class FakeCall : public webrtc::Call {
|
||||
webrtc::VideoReceiveStream* receive_stream) OVERRIDE;
|
||||
virtual webrtc::PacketReceiver* Receiver() OVERRIDE;
|
||||
|
||||
virtual uint32_t SendBitrateEstimate() OVERRIDE;
|
||||
virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
|
||||
virtual webrtc::Call::Stats GetStats() const OVERRIDE;
|
||||
|
||||
virtual void SignalNetworkState(webrtc::Call::NetworkState state) OVERRIDE;
|
||||
|
||||
|
@ -88,6 +88,14 @@ class Call {
|
||||
int stream_start_bitrate_bps;
|
||||
};
|
||||
|
||||
struct Stats {
|
||||
Stats() : send_bandwidth_bps(0), recv_bandwidth_bps(0), pacer_delay_ms(0) {}
|
||||
|
||||
int send_bandwidth_bps;
|
||||
int recv_bandwidth_bps;
|
||||
int pacer_delay_ms;
|
||||
};
|
||||
|
||||
static Call* Create(const Call::Config& config);
|
||||
|
||||
static Call* Create(const Call::Config& config,
|
||||
@ -109,13 +117,9 @@ class Call {
|
||||
// Call instance exists.
|
||||
virtual PacketReceiver* Receiver() = 0;
|
||||
|
||||
// Returns the estimated total send bandwidth. Note: this can differ from the
|
||||
// actual encoded bitrate.
|
||||
virtual uint32_t SendBitrateEstimate() = 0;
|
||||
|
||||
// Returns the total estimated receive bandwidth for the call. Note: this can
|
||||
// differ from the actual receive bitrate.
|
||||
virtual uint32_t ReceiveBitrateEstimate() = 0;
|
||||
// Returns the call statistics, such as estimated send and receive bandwidth,
|
||||
// pacing delay, etc.
|
||||
virtual Stats GetStats() const = 0;
|
||||
|
||||
virtual void SignalNetworkState(NetworkState state) = 0;
|
||||
|
||||
|
@ -271,7 +271,9 @@ class BitrateStatisticsObserver {
|
||||
public:
|
||||
virtual ~BitrateStatisticsObserver() {}
|
||||
|
||||
virtual void Notify(const BitrateStatistics& stats, uint32_t ssrc) = 0;
|
||||
virtual void Notify(const BitrateStatistics& total_stats,
|
||||
const BitrateStatistics& retransmit_stats,
|
||||
uint32_t ssrc) = 0;
|
||||
};
|
||||
|
||||
// Callback, used to notify an observer whenever frame counts have been updated
|
||||
|
@ -33,16 +33,19 @@ struct RtpStatistics {
|
||||
int extended_max_sequence_number;
|
||||
};
|
||||
|
||||
struct StreamStats {
|
||||
StreamStats()
|
||||
struct SsrcStats {
|
||||
SsrcStats()
|
||||
: key_frames(0),
|
||||
delta_frames(0),
|
||||
bitrate_bps(0),
|
||||
total_bitrate_bps(0),
|
||||
retransmit_bitrate_bps(0),
|
||||
avg_delay_ms(0),
|
||||
max_delay_ms(0) {}
|
||||
uint32_t key_frames;
|
||||
uint32_t delta_frames;
|
||||
int32_t bitrate_bps;
|
||||
// TODO(holmer): Move bitrate_bps out to the webrtc::Call layer.
|
||||
int total_bitrate_bps;
|
||||
int retransmit_bitrate_bps;
|
||||
int avg_delay_ms;
|
||||
int max_delay_ms;
|
||||
StreamDataCounters rtp_stats;
|
||||
|
@ -40,6 +40,57 @@ const char* FrameTypeToString(const FrameType frame_type) {
|
||||
|
||||
} // namespace
|
||||
|
||||
class BitrateAggregator {
|
||||
public:
|
||||
explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback)
|
||||
: callback_(bitrate_callback),
|
||||
total_bitrate_observer_(*this),
|
||||
retransmit_bitrate_observer_(*this),
|
||||
ssrc_(0) {}
|
||||
|
||||
void OnStatsUpdated() const {
|
||||
if (callback_)
|
||||
callback_->Notify(total_bitrate_observer_.statistics(),
|
||||
retransmit_bitrate_observer_.statistics(),
|
||||
ssrc_);
|
||||
}
|
||||
|
||||
Bitrate::Observer* total_bitrate_observer() {
|
||||
return &total_bitrate_observer_;
|
||||
}
|
||||
Bitrate::Observer* retransmit_bitrate_observer() {
|
||||
return &retransmit_bitrate_observer_;
|
||||
}
|
||||
|
||||
void set_ssrc(uint32_t ssrc) { ssrc_ = ssrc; }
|
||||
|
||||
private:
|
||||
// We assume that these observers are called on the same thread, which is
|
||||
// true for RtpSender as they are called on the Process thread.
|
||||
class BitrateObserver : public Bitrate::Observer {
|
||||
public:
|
||||
explicit BitrateObserver(const BitrateAggregator& aggregator)
|
||||
: aggregator_(aggregator) {}
|
||||
|
||||
// Implements Bitrate::Observer.
|
||||
virtual void BitrateUpdated(const BitrateStatistics& stats) OVERRIDE {
|
||||
statistics_ = stats;
|
||||
aggregator_.OnStatsUpdated();
|
||||
}
|
||||
|
||||
BitrateStatistics statistics() const { return statistics_; }
|
||||
|
||||
private:
|
||||
BitrateStatistics statistics_;
|
||||
const BitrateAggregator& aggregator_;
|
||||
};
|
||||
|
||||
BitrateStatisticsObserver* const callback_;
|
||||
BitrateObserver total_bitrate_observer_;
|
||||
BitrateObserver retransmit_bitrate_observer_;
|
||||
uint32_t ssrc_;
|
||||
};
|
||||
|
||||
RTPSender::RTPSender(const int32_t id,
|
||||
const bool audio,
|
||||
Clock* clock,
|
||||
@ -54,7 +105,8 @@ RTPSender::RTPSender(const int32_t id,
|
||||
// TickTime.
|
||||
clock_delta_ms_(clock_->TimeInMilliseconds() -
|
||||
TickTime::MillisecondTimestamp()),
|
||||
bitrate_sent_(clock, this),
|
||||
bitrates_(new BitrateAggregator(bitrate_callback)),
|
||||
total_bitrate_sent_(clock, bitrates_->total_bitrate_observer()),
|
||||
id_(id),
|
||||
audio_configured_(audio),
|
||||
audio_(NULL),
|
||||
@ -74,12 +126,11 @@ RTPSender::RTPSender(const int32_t id,
|
||||
// NACK.
|
||||
nack_byte_count_times_(),
|
||||
nack_byte_count_(),
|
||||
nack_bitrate_(clock, NULL),
|
||||
nack_bitrate_(clock, bitrates_->retransmit_bitrate_observer()),
|
||||
packet_history_(clock),
|
||||
// Statistics
|
||||
statistics_crit_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
rtp_stats_callback_(NULL),
|
||||
bitrate_callback_(bitrate_callback),
|
||||
frame_count_observer_(frame_count_observer),
|
||||
send_side_delay_observer_(send_side_delay_observer),
|
||||
// RTP variables
|
||||
@ -108,6 +159,7 @@ RTPSender::RTPSender(const int32_t id,
|
||||
srand(static_cast<uint32_t>(clock_->TimeInMilliseconds()));
|
||||
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
|
||||
ssrc_rtx_ = ssrc_db_.CreateSSRC(); // Can't be 0.
|
||||
bitrates_->set_ssrc(ssrc_);
|
||||
// Random start, 16 bits. Can't be 0.
|
||||
sequence_number_rtx_ = static_cast<uint16_t>(rand() + 1) & 0x7FFF;
|
||||
sequence_number_ = static_cast<uint16_t>(rand() + 1) & 0x7FFF;
|
||||
@ -149,7 +201,7 @@ uint32_t RTPSender::GetTargetBitrate() {
|
||||
}
|
||||
|
||||
uint16_t RTPSender::ActualSendBitrateKbit() const {
|
||||
return (uint16_t)(bitrate_sent_.BitrateNow() / 1000);
|
||||
return (uint16_t)(total_bitrate_sent_.BitrateNow() / 1000);
|
||||
}
|
||||
|
||||
uint32_t RTPSender::VideoBitrateSent() const {
|
||||
@ -864,7 +916,7 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer,
|
||||
counters = &rtp_stats_;
|
||||
}
|
||||
|
||||
bitrate_sent_.Update(size);
|
||||
total_bitrate_sent_.Update(size);
|
||||
++counters->packets;
|
||||
if (IsFecPacket(buffer, header)) {
|
||||
++counters->fec_packets;
|
||||
@ -997,7 +1049,7 @@ void RTPSender::UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms) {
|
||||
|
||||
void RTPSender::ProcessBitrate() {
|
||||
CriticalSectionScoped cs(send_critsect_);
|
||||
bitrate_sent_.Process();
|
||||
total_bitrate_sent_.Process();
|
||||
nack_bitrate_.Process();
|
||||
if (audio_configured_) {
|
||||
return;
|
||||
@ -1420,6 +1472,7 @@ void RTPSender::SetSendingStatus(bool enabled) {
|
||||
// Generate a new SSRC.
|
||||
ssrc_db_.ReturnSSRC(ssrc_);
|
||||
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
|
||||
bitrates_->set_ssrc(ssrc_);
|
||||
}
|
||||
// Don't initialize seq number if SSRC passed externally.
|
||||
if (!sequence_number_forced_ && !ssrc_forced_) {
|
||||
@ -1470,6 +1523,7 @@ uint32_t RTPSender::GenerateNewSSRC() {
|
||||
return 0;
|
||||
}
|
||||
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
|
||||
bitrates_->set_ssrc(ssrc_);
|
||||
return ssrc_;
|
||||
}
|
||||
|
||||
@ -1484,6 +1538,7 @@ void RTPSender::SetSSRC(uint32_t ssrc) {
|
||||
ssrc_db_.ReturnSSRC(ssrc_);
|
||||
ssrc_db_.RegisterSSRC(ssrc);
|
||||
ssrc_ = ssrc;
|
||||
bitrates_->set_ssrc(ssrc_);
|
||||
if (!sequence_number_forced_) {
|
||||
sequence_number_ =
|
||||
rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER); // NOLINT
|
||||
@ -1681,17 +1736,8 @@ StreamDataCountersCallback* RTPSender::GetRtpStatisticsCallback() const {
|
||||
return rtp_stats_callback_;
|
||||
}
|
||||
|
||||
uint32_t RTPSender::BitrateSent() const { return bitrate_sent_.BitrateLast(); }
|
||||
|
||||
void RTPSender::BitrateUpdated(const BitrateStatistics& stats) {
|
||||
uint32_t ssrc;
|
||||
{
|
||||
CriticalSectionScoped ssrc_lock(send_critsect_);
|
||||
ssrc = ssrc_;
|
||||
}
|
||||
if (bitrate_callback_) {
|
||||
bitrate_callback_->Notify(stats, ssrc);
|
||||
}
|
||||
uint32_t RTPSender::BitrateSent() const {
|
||||
return total_bitrate_sent_.BitrateLast();
|
||||
}
|
||||
|
||||
void RTPSender::SetRtpState(const RtpState& rtp_state) {
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class BitrateAggregator;
|
||||
class CriticalSectionWrapper;
|
||||
class RTPSenderAudio;
|
||||
class RTPSenderVideo;
|
||||
@ -65,7 +66,7 @@ class RTPSenderInterface {
|
||||
PacedSender::Priority priority) = 0;
|
||||
};
|
||||
|
||||
class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
|
||||
class RTPSender : public RTPSenderInterface {
|
||||
public:
|
||||
RTPSender(const int32_t id, const bool audio, Clock *clock,
|
||||
Transport *transport, RtpAudioFeedback *audio_feedback,
|
||||
@ -276,8 +277,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
|
||||
|
||||
uint32_t BitrateSent() const;
|
||||
|
||||
virtual void BitrateUpdated(const BitrateStatistics& stats) OVERRIDE;
|
||||
|
||||
void SetRtpState(const RtpState& rtp_state);
|
||||
RtpState GetRtpState() const;
|
||||
void SetRtxRtpState(const RtpState& rtp_state);
|
||||
@ -337,7 +336,9 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
|
||||
|
||||
Clock* clock_;
|
||||
int64_t clock_delta_ms_;
|
||||
Bitrate bitrate_sent_;
|
||||
|
||||
scoped_ptr<BitrateAggregator> bitrates_;
|
||||
Bitrate total_bitrate_sent_;
|
||||
|
||||
int32_t id_;
|
||||
const bool audio_configured_;
|
||||
@ -375,7 +376,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
|
||||
StreamDataCounters rtp_stats_ GUARDED_BY(statistics_crit_);
|
||||
StreamDataCounters rtx_rtp_stats_ GUARDED_BY(statistics_crit_);
|
||||
StreamDataCountersCallback* rtp_stats_callback_ GUARDED_BY(statistics_crit_);
|
||||
BitrateStatisticsObserver* const bitrate_callback_;
|
||||
FrameCountObserver* const frame_count_observer_;
|
||||
SendSideDelayObserver* const send_side_delay_observer_;
|
||||
|
||||
|
@ -855,20 +855,22 @@ TEST_F(RtpSenderTest, FrameCountCallbacks) {
|
||||
TEST_F(RtpSenderTest, BitrateCallbacks) {
|
||||
class TestCallback : public BitrateStatisticsObserver {
|
||||
public:
|
||||
TestCallback()
|
||||
: BitrateStatisticsObserver(), num_calls_(0), ssrc_(0), bitrate_() {}
|
||||
TestCallback() : BitrateStatisticsObserver(), num_calls_(0), ssrc_(0) {}
|
||||
virtual ~TestCallback() {}
|
||||
|
||||
virtual void Notify(const BitrateStatistics& stats,
|
||||
virtual void Notify(const BitrateStatistics& total_stats,
|
||||
const BitrateStatistics& retransmit_stats,
|
||||
uint32_t ssrc) OVERRIDE {
|
||||
++num_calls_;
|
||||
ssrc_ = ssrc;
|
||||
bitrate_ = stats;
|
||||
total_stats_ = total_stats;
|
||||
retransmit_stats_ = retransmit_stats;
|
||||
}
|
||||
|
||||
uint32_t num_calls_;
|
||||
uint32_t ssrc_;
|
||||
BitrateStatistics bitrate_;
|
||||
BitrateStatistics total_stats_;
|
||||
BitrateStatistics retransmit_stats_;
|
||||
} callback;
|
||||
rtp_sender_.reset(new RTPSender(0, false, &fake_clock_, &transport_, NULL,
|
||||
&mock_paced_sender_, &callback, NULL, NULL));
|
||||
@ -909,13 +911,15 @@ TEST_F(RtpSenderTest, BitrateCallbacks) {
|
||||
|
||||
const uint32_t expected_packet_rate = 1000 / kPacketInterval;
|
||||
|
||||
EXPECT_EQ(1U, callback.num_calls_);
|
||||
// We get one call for every stats updated, thus two calls since both the
|
||||
// stream stats and the retransmit stats are updated once.
|
||||
EXPECT_EQ(2u, callback.num_calls_);
|
||||
EXPECT_EQ(ssrc, callback.ssrc_);
|
||||
EXPECT_EQ(start_time + (kNumPackets * kPacketInterval),
|
||||
callback.bitrate_.timestamp_ms);
|
||||
EXPECT_EQ(expected_packet_rate, callback.bitrate_.packet_rate);
|
||||
callback.total_stats_.timestamp_ms);
|
||||
EXPECT_EQ(expected_packet_rate, callback.total_stats_.packet_rate);
|
||||
EXPECT_EQ((kPacketOverhead + sizeof(payload)) * 8 * expected_packet_rate,
|
||||
callback.bitrate_.bitrate_bps);
|
||||
callback.total_stats_.bitrate_bps);
|
||||
|
||||
rtp_sender_.reset();
|
||||
}
|
||||
|
@ -542,7 +542,7 @@ void MediaOptimization::UpdateSentBitrate(int64_t now_ms) {
|
||||
now_ms - encoded_frame_samples_.front().time_complete_ms);
|
||||
if (denom >= 1.0f) {
|
||||
avg_sent_bit_rate_bps_ =
|
||||
static_cast<uint32_t>(framesize_sum * 8 * 1000 / denom + 0.5f);
|
||||
static_cast<uint32_t>(framesize_sum * 8.0f * 1000.0f / denom + 0.5f);
|
||||
} else {
|
||||
avg_sent_bit_rate_bps_ = framesize_sum * 8;
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ int32_t FakeEncoder::Encode(
|
||||
assert(config_.maxFramerate > 0);
|
||||
int time_since_last_encode_ms = 1000 / config_.maxFramerate;
|
||||
int64_t time_now_ms = clock_->TimeInMilliseconds();
|
||||
if (last_encode_time_ms_ > 0) {
|
||||
const bool first_encode = last_encode_time_ms_ == 0;
|
||||
if (!first_encode) {
|
||||
// For all frames but the first we can estimate the display time by looking
|
||||
// at the display time of the previous frame.
|
||||
time_since_last_encode_ms = time_now_ms - last_encode_time_ms_;
|
||||
@ -80,6 +81,12 @@ int32_t FakeEncoder::Encode(
|
||||
int stream_bits = (bits_available > max_stream_bits) ? max_stream_bits :
|
||||
bits_available;
|
||||
int stream_bytes = (stream_bits + 7) / 8;
|
||||
if (first_encode) {
|
||||
// The first frame is a key frame and should be larger.
|
||||
// TODO(holmer): The FakeEncoder should store the bits_available between
|
||||
// encodes so that it can compensate for oversized frames.
|
||||
stream_bytes *= 10;
|
||||
}
|
||||
if (static_cast<size_t>(stream_bytes) > sizeof(encoded_buffer_))
|
||||
stream_bytes = sizeof(encoded_buffer_);
|
||||
|
||||
@ -96,7 +103,6 @@ int32_t FakeEncoder::Encode(
|
||||
assert(callback_ != NULL);
|
||||
if (callback_->Encoded(encoded, &specifics, NULL) != 0)
|
||||
return -1;
|
||||
|
||||
bits_available -= encoded._length * 8;
|
||||
}
|
||||
return 0;
|
||||
|
@ -114,8 +114,7 @@ class Call : public webrtc::Call, public PacketReceiver {
|
||||
virtual void DestroyVideoReceiveStream(
|
||||
webrtc::VideoReceiveStream* receive_stream) OVERRIDE;
|
||||
|
||||
virtual uint32_t SendBitrateEstimate() OVERRIDE;
|
||||
virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
|
||||
virtual Stats GetStats() const OVERRIDE;
|
||||
|
||||
virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
|
||||
size_t length) OVERRIDE;
|
||||
@ -321,14 +320,26 @@ void Call::DestroyVideoReceiveStream(
|
||||
delete receive_stream_impl;
|
||||
}
|
||||
|
||||
uint32_t Call::SendBitrateEstimate() {
|
||||
// TODO(pbos): Return send-bitrate estimate
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Call::ReceiveBitrateEstimate() {
|
||||
// TODO(pbos): Return receive-bitrate estimate
|
||||
return 0;
|
||||
Call::Stats Call::GetStats() const {
|
||||
Stats stats;
|
||||
// Ignoring return values.
|
||||
uint32_t send_bandwidth = 0;
|
||||
rtp_rtcp_->GetEstimatedSendBandwidth(base_channel_id_, &send_bandwidth);
|
||||
stats.send_bandwidth_bps = send_bandwidth;
|
||||
uint32_t recv_bandwidth = 0;
|
||||
rtp_rtcp_->GetEstimatedReceiveBandwidth(base_channel_id_, &recv_bandwidth);
|
||||
stats.recv_bandwidth_bps = recv_bandwidth;
|
||||
{
|
||||
ReadLockScoped read_lock(*send_crit_);
|
||||
for (std::map<uint32_t, VideoSendStream*>::const_iterator it =
|
||||
send_ssrcs_.begin();
|
||||
it != send_ssrcs_.end();
|
||||
++it) {
|
||||
stats.pacer_delay_ms =
|
||||
std::max(it->second->GetPacerQueuingDelayMs(), stats.pacer_delay_ms);
|
||||
}
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
void Call::SignalNetworkState(NetworkState state) {
|
||||
|
@ -502,7 +502,8 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
|
||||
VideoSendStream::Stats stats = send_stream_->GetStats();
|
||||
if (stats.substreams.size() > 0) {
|
||||
assert(stats.substreams.size() == 1);
|
||||
int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000;
|
||||
int bitrate_kbps =
|
||||
stats.substreams.begin()->second.total_bitrate_bps / 1000;
|
||||
if (bitrate_kbps > 0) {
|
||||
test::PrintResult(
|
||||
"bitrate_stats_",
|
||||
|
@ -1202,6 +1202,53 @@ TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
|
||||
TEST_F(EndToEndTest, VerifyBandwidthStats) {
|
||||
class RtcpObserver : public test::EndToEndTest, public PacketReceiver {
|
||||
public:
|
||||
RtcpObserver()
|
||||
: EndToEndTest(kDefaultTimeoutMs),
|
||||
sender_call_(NULL),
|
||||
receiver_call_(NULL),
|
||||
has_seen_pacer_delay_(false) {}
|
||||
|
||||
virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
|
||||
size_t length) OVERRIDE {
|
||||
Call::Stats sender_stats = sender_call_->GetStats();
|
||||
Call::Stats receiver_stats = receiver_call_->GetStats();
|
||||
if (!has_seen_pacer_delay_)
|
||||
has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
|
||||
if (sender_stats.send_bandwidth_bps > 0 &&
|
||||
receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_)
|
||||
observation_complete_->Set();
|
||||
return receiver_call_->Receiver()->DeliverPacket(packet, length);
|
||||
}
|
||||
|
||||
virtual void OnCallsCreated(Call* sender_call,
|
||||
Call* receiver_call) OVERRIDE {
|
||||
sender_call_ = sender_call;
|
||||
receiver_call_ = receiver_call;
|
||||
}
|
||||
|
||||
virtual void PerformTest() OVERRIDE {
|
||||
EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
|
||||
"non-zero bandwidth stats.";
|
||||
}
|
||||
|
||||
virtual void SetReceivers(
|
||||
PacketReceiver* send_transport_receiver,
|
||||
PacketReceiver* receive_transport_receiver) OVERRIDE {
|
||||
test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
|
||||
}
|
||||
|
||||
private:
|
||||
Call* sender_call_;
|
||||
Call* receiver_call_;
|
||||
bool has_seen_pacer_delay_;
|
||||
} test;
|
||||
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
|
||||
void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
|
||||
static const int kNumRtcpReportPacketsToObserve = 5;
|
||||
class RtcpXrObserver : public test::EndToEndTest {
|
||||
@ -1434,7 +1481,7 @@ TEST_F(EndToEndTest, GetStats) {
|
||||
// Make sure all fields have been populated.
|
||||
|
||||
receive_stats_filled_["IncomingRate"] |=
|
||||
stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
|
||||
stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
|
||||
|
||||
receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
|
||||
|
||||
@ -1465,7 +1512,7 @@ TEST_F(EndToEndTest, GetStats) {
|
||||
send_stats_filled_["NumStreams"] |=
|
||||
stats.substreams.size() == expected_send_ssrcs_.size();
|
||||
|
||||
for (std::map<uint32_t, StreamStats>::const_iterator it =
|
||||
for (std::map<uint32_t, SsrcStats>::const_iterator it =
|
||||
stats.substreams.begin();
|
||||
it != stats.substreams.end();
|
||||
++it) {
|
||||
@ -1475,7 +1522,7 @@ TEST_F(EndToEndTest, GetStats) {
|
||||
send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
|
||||
stats.input_frame_rate != 0;
|
||||
|
||||
const StreamStats& stream_stats = it->second;
|
||||
const SsrcStats& stream_stats = it->second;
|
||||
|
||||
send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
|
||||
stream_stats.rtcp_stats.cumulative_lost != 0 ||
|
||||
@ -1490,7 +1537,7 @@ TEST_F(EndToEndTest, GetStats) {
|
||||
|
||||
send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
|
||||
it->first)] |=
|
||||
stream_stats.bitrate_bps != 0;
|
||||
stream_stats.total_bitrate_bps != 0;
|
||||
|
||||
send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
|
||||
stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
|
||||
|
@ -58,10 +58,10 @@ std::string ReceiveStatisticsProxy::GetCName() const {
|
||||
|
||||
void ReceiveStatisticsProxy::IncomingRate(const int video_channel,
|
||||
const unsigned int framerate,
|
||||
const unsigned int bitrate) {
|
||||
const unsigned int bitrate_bps) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
stats_.network_frame_rate = framerate;
|
||||
stats_.bitrate_bps = bitrate;
|
||||
stats_.total_bitrate_bps = bitrate_bps;
|
||||
}
|
||||
|
||||
void ReceiveStatisticsProxy::StatisticsUpdated(
|
||||
|
@ -52,7 +52,7 @@ class ReceiveStatisticsProxy : public ViEDecoderObserver,
|
||||
const VideoCodec& video_codec) OVERRIDE {}
|
||||
virtual void IncomingRate(const int video_channel,
|
||||
const unsigned int framerate,
|
||||
const unsigned int bitrate) OVERRIDE;
|
||||
const unsigned int bitrate_bps) OVERRIDE;
|
||||
virtual void DecoderTiming(int decode_ms,
|
||||
int max_decode_ms,
|
||||
int current_delay_ms,
|
||||
|
@ -29,6 +29,7 @@ void SendStatisticsProxy::OutgoingRate(const int video_channel,
|
||||
const unsigned int bitrate) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
stats_.encode_frame_rate = framerate;
|
||||
stats_.media_bitrate_bps = bitrate;
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::SuspendChange(int video_channel, bool is_suspended) {
|
||||
@ -47,8 +48,8 @@ VideoSendStream::Stats SendStatisticsProxy::GetStats() const {
|
||||
return stats_;
|
||||
}
|
||||
|
||||
StreamStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) {
|
||||
std::map<uint32_t, StreamStats>::iterator it = stats_.substreams.find(ssrc);
|
||||
SsrcStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) {
|
||||
std::map<uint32_t, SsrcStats>::iterator it = stats_.substreams.find(ssrc);
|
||||
if (it != stats_.substreams.end())
|
||||
return &it->second;
|
||||
|
||||
@ -66,7 +67,7 @@ StreamStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) {
|
||||
void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
|
||||
uint32_t ssrc) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
StreamStats* stats = GetStatsEntry(ssrc);
|
||||
SsrcStats* stats = GetStatsEntry(ssrc);
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
@ -77,28 +78,30 @@ void SendStatisticsProxy::DataCountersUpdated(
|
||||
const StreamDataCounters& counters,
|
||||
uint32_t ssrc) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
StreamStats* stats = GetStatsEntry(ssrc);
|
||||
SsrcStats* stats = GetStatsEntry(ssrc);
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
stats->rtp_stats = counters;
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::Notify(const BitrateStatistics& bitrate,
|
||||
void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
|
||||
const BitrateStatistics& retransmit_stats,
|
||||
uint32_t ssrc) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
StreamStats* stats = GetStatsEntry(ssrc);
|
||||
SsrcStats* stats = GetStatsEntry(ssrc);
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
stats->bitrate_bps = bitrate.bitrate_bps;
|
||||
stats->total_bitrate_bps = total_stats.bitrate_bps;
|
||||
stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::FrameCountUpdated(FrameType frame_type,
|
||||
uint32_t frame_count,
|
||||
const unsigned int ssrc) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
StreamStats* stats = GetStatsEntry(ssrc);
|
||||
SsrcStats* stats = GetStatsEntry(ssrc);
|
||||
if (stats == NULL)
|
||||
return;
|
||||
|
||||
@ -120,7 +123,7 @@ void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
|
||||
int max_delay_ms,
|
||||
uint32_t ssrc) {
|
||||
CriticalSectionScoped lock(crit_.get());
|
||||
StreamStats* stats = GetStatsEntry(ssrc);
|
||||
SsrcStats* stats = GetStatsEntry(ssrc);
|
||||
if (stats == NULL)
|
||||
return;
|
||||
stats->avg_delay_ms = avg_delay_ms;
|
||||
|
@ -46,7 +46,9 @@ class SendStatisticsProxy : public RtcpStatisticsCallback,
|
||||
uint32_t ssrc) OVERRIDE;
|
||||
|
||||
// From BitrateStatisticsObserver.
|
||||
virtual void Notify(const BitrateStatistics& stats, uint32_t ssrc) OVERRIDE;
|
||||
virtual void Notify(const BitrateStatistics& total_stats,
|
||||
const BitrateStatistics& retransmit_stats,
|
||||
uint32_t ssrc) OVERRIDE;
|
||||
|
||||
// From FrameCountObserver.
|
||||
virtual void FrameCountUpdated(FrameType frame_type,
|
||||
@ -75,7 +77,7 @@ class SendStatisticsProxy : public RtcpStatisticsCallback,
|
||||
uint32_t ssrc) OVERRIDE;
|
||||
|
||||
private:
|
||||
StreamStats* GetStatsEntry(uint32_t ssrc) EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
SsrcStats* GetStatsEntry(uint32_t ssrc) EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
const VideoSendStream::Config config_;
|
||||
scoped_ptr<CriticalSectionWrapper> crit_;
|
||||
|
@ -44,22 +44,23 @@ class SendStatisticsProxyTest : public ::testing::Test {
|
||||
void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
|
||||
EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
|
||||
EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
|
||||
EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
|
||||
EXPECT_EQ(one.suspended, other.suspended);
|
||||
|
||||
EXPECT_EQ(one.substreams.size(), other.substreams.size());
|
||||
for (std::map<uint32_t, StreamStats>::const_iterator it =
|
||||
for (std::map<uint32_t, SsrcStats>::const_iterator it =
|
||||
one.substreams.begin();
|
||||
it != one.substreams.end();
|
||||
++it) {
|
||||
std::map<uint32_t, StreamStats>::const_iterator corresponding_it =
|
||||
std::map<uint32_t, SsrcStats>::const_iterator corresponding_it =
|
||||
other.substreams.find(it->first);
|
||||
ASSERT_TRUE(corresponding_it != other.substreams.end());
|
||||
const StreamStats& a = it->second;
|
||||
const StreamStats& b = corresponding_it->second;
|
||||
const SsrcStats& a = it->second;
|
||||
const SsrcStats& b = corresponding_it->second;
|
||||
|
||||
EXPECT_EQ(a.key_frames, b.key_frames);
|
||||
EXPECT_EQ(a.delta_frames, b.delta_frames);
|
||||
EXPECT_EQ(a.bitrate_bps, b.bitrate_bps);
|
||||
EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
|
||||
EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
|
||||
EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
|
||||
|
||||
@ -84,7 +85,7 @@ class SendStatisticsProxyTest : public ::testing::Test {
|
||||
int avg_delay_ms_;
|
||||
int max_delay_ms_;
|
||||
VideoSendStream::Stats expected_;
|
||||
typedef std::map<uint32_t, StreamStats>::const_iterator StreamIterator;
|
||||
typedef std::map<uint32_t, SsrcStats>::const_iterator StreamIterator;
|
||||
};
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
|
||||
@ -93,7 +94,7 @@ TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
|
||||
it != config_.rtp.ssrcs.end();
|
||||
++it) {
|
||||
const uint32_t ssrc = *it;
|
||||
StreamStats& ssrc_stats = expected_.substreams[ssrc];
|
||||
SsrcStats& ssrc_stats = expected_.substreams[ssrc];
|
||||
|
||||
// Add statistics with some arbitrary, but unique, numbers.
|
||||
uint32_t offset = ssrc * sizeof(RtcpStatistics);
|
||||
@ -107,7 +108,7 @@ TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
|
||||
it != config_.rtp.rtx.ssrcs.end();
|
||||
++it) {
|
||||
const uint32_t ssrc = *it;
|
||||
StreamStats& ssrc_stats = expected_.substreams[ssrc];
|
||||
SsrcStats& ssrc_stats = expected_.substreams[ssrc];
|
||||
|
||||
// Add statistics with some arbitrary, but unique, numbers.
|
||||
uint32_t offset = ssrc * sizeof(RtcpStatistics);
|
||||
@ -121,17 +122,25 @@ TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
|
||||
ExpectEqual(expected_, stats);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, FrameRates) {
|
||||
TEST_F(SendStatisticsProxyTest, CaptureFramerate) {
|
||||
const int capture_fps = 31;
|
||||
const int encode_fps = 29;
|
||||
|
||||
ViECaptureObserver* capture_observer = statistics_proxy_.get();
|
||||
capture_observer->CapturedFrameRate(0, capture_fps);
|
||||
ViEEncoderObserver* encoder_observer = statistics_proxy_.get();
|
||||
encoder_observer->OutgoingRate(0, encode_fps, 0);
|
||||
|
||||
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
|
||||
EXPECT_EQ(capture_fps, stats.input_frame_rate);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, EncodedBitrateAndFramerate) {
|
||||
const int media_bitrate_bps = 500;
|
||||
const int encode_fps = 29;
|
||||
|
||||
ViEEncoderObserver* encoder_observer = statistics_proxy_.get();
|
||||
encoder_observer->OutgoingRate(0, encode_fps, media_bitrate_bps);
|
||||
|
||||
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
|
||||
EXPECT_EQ(media_bitrate_bps, stats.media_bitrate_bps);
|
||||
EXPECT_EQ(encode_fps, stats.encode_frame_rate);
|
||||
}
|
||||
|
||||
@ -156,8 +165,8 @@ TEST_F(SendStatisticsProxyTest, FrameCounts) {
|
||||
++it) {
|
||||
const uint32_t ssrc = *it;
|
||||
// Add statistics with some arbitrary, but unique, numbers.
|
||||
StreamStats& stats = expected_.substreams[ssrc];
|
||||
uint32_t offset = ssrc * sizeof(StreamStats);
|
||||
SsrcStats& stats = expected_.substreams[ssrc];
|
||||
uint32_t offset = ssrc * sizeof(SsrcStats);
|
||||
stats.key_frames = offset;
|
||||
stats.delta_frames = offset + 1;
|
||||
observer->FrameCountUpdated(kVideoFrameKey, stats.key_frames, ssrc);
|
||||
@ -168,8 +177,8 @@ TEST_F(SendStatisticsProxyTest, FrameCounts) {
|
||||
++it) {
|
||||
const uint32_t ssrc = *it;
|
||||
// Add statistics with some arbitrary, but unique, numbers.
|
||||
StreamStats& stats = expected_.substreams[ssrc];
|
||||
uint32_t offset = ssrc * sizeof(StreamStats);
|
||||
SsrcStats& stats = expected_.substreams[ssrc];
|
||||
uint32_t offset = ssrc * sizeof(SsrcStats);
|
||||
stats.key_frames = offset;
|
||||
stats.delta_frames = offset + 1;
|
||||
observer->FrameCountUpdated(kVideoFrameKey, stats.key_frames, ssrc);
|
||||
@ -223,21 +232,27 @@ TEST_F(SendStatisticsProxyTest, Bitrate) {
|
||||
it != config_.rtp.ssrcs.end();
|
||||
++it) {
|
||||
const uint32_t ssrc = *it;
|
||||
BitrateStatistics bitrate;
|
||||
BitrateStatistics total;
|
||||
BitrateStatistics retransmit;
|
||||
// Use ssrc as bitrate_bps to get a unique value for each stream.
|
||||
bitrate.bitrate_bps = ssrc;
|
||||
observer->Notify(bitrate, ssrc);
|
||||
expected_.substreams[ssrc].bitrate_bps = ssrc;
|
||||
total.bitrate_bps = ssrc;
|
||||
retransmit.bitrate_bps = ssrc + 1;
|
||||
observer->Notify(total, retransmit, ssrc);
|
||||
expected_.substreams[ssrc].total_bitrate_bps = total.bitrate_bps;
|
||||
expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit.bitrate_bps;
|
||||
}
|
||||
for (std::vector<uint32_t>::const_iterator it = config_.rtp.rtx.ssrcs.begin();
|
||||
it != config_.rtp.rtx.ssrcs.end();
|
||||
++it) {
|
||||
const uint32_t ssrc = *it;
|
||||
BitrateStatistics bitrate;
|
||||
BitrateStatistics total;
|
||||
BitrateStatistics retransmit;
|
||||
// Use ssrc as bitrate_bps to get a unique value for each stream.
|
||||
bitrate.bitrate_bps = ssrc;
|
||||
observer->Notify(bitrate, ssrc);
|
||||
expected_.substreams[ssrc].bitrate_bps = ssrc;
|
||||
total.bitrate_bps = ssrc;
|
||||
retransmit.bitrate_bps = ssrc + 1;
|
||||
observer->Notify(total, retransmit, ssrc);
|
||||
expected_.substreams[ssrc].total_bitrate_bps = total.bitrate_bps;
|
||||
expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit.bitrate_bps;
|
||||
}
|
||||
|
||||
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
|
||||
@ -292,9 +307,10 @@ TEST_F(SendStatisticsProxyTest, NoSubstreams) {
|
||||
rtp_callback->DataCountersUpdated(rtp_stats, exluded_ssrc);
|
||||
|
||||
// From BitrateStatisticsObserver.
|
||||
BitrateStatistics bitrate;
|
||||
BitrateStatistics total;
|
||||
BitrateStatistics retransmit;
|
||||
BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
|
||||
bitrate_observer->Notify(bitrate, exluded_ssrc);
|
||||
bitrate_observer->Notify(total, retransmit, exluded_ssrc);
|
||||
|
||||
// From FrameCountObserver.
|
||||
FrameCountObserver* fps_observer = statistics_proxy_.get();
|
||||
|
@ -492,5 +492,12 @@ void VideoSendStream::SignalNetworkState(Call::NetworkState state) {
|
||||
rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNone);
|
||||
}
|
||||
|
||||
int VideoSendStream::GetPacerQueuingDelayMs() const {
|
||||
int pacer_delay_ms = 0;
|
||||
if (rtp_rtcp_->GetPacerQueuingDelayMs(channel_, &pacer_delay_ms) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return pacer_delay_ms;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
@ -74,6 +74,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
|
||||
void SignalNetworkState(Call::NetworkState state);
|
||||
|
||||
int GetPacerQueuingDelayMs() const;
|
||||
|
||||
private:
|
||||
void ConfigureSsrcs();
|
||||
TransportAdapter transport_adapter_;
|
||||
|
@ -962,8 +962,8 @@ TEST_F(VideoSendStreamTest, ProducesStats) {
|
||||
config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc));
|
||||
// Check for data populated by various sources. RTCP excluded as this
|
||||
// data is received from remote side. Tested in call tests instead.
|
||||
const StreamStats& entry = stats.substreams[ssrc];
|
||||
if (entry.key_frames > 0u && entry.bitrate_bps > 0 &&
|
||||
const SsrcStats& entry = stats.substreams[ssrc];
|
||||
if (entry.key_frames > 0u && entry.total_bitrate_bps > 0 &&
|
||||
entry.rtp_stats.packets > 0u && entry.avg_delay_ms > 0 &&
|
||||
entry.max_delay_ms > 0) {
|
||||
return true;
|
||||
@ -1045,20 +1045,20 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
|
||||
VideoSendStream::Stats stats = stream_->GetStats();
|
||||
if (!stats.substreams.empty()) {
|
||||
EXPECT_EQ(1u, stats.substreams.size());
|
||||
int bitrate_bps = stats.substreams.begin()->second.bitrate_bps;
|
||||
test::PrintResult(
|
||||
"bitrate_stats_",
|
||||
"min_transmit_bitrate_low_remb",
|
||||
"bitrate_bps",
|
||||
static_cast<size_t>(bitrate_bps),
|
||||
"bps",
|
||||
false);
|
||||
if (bitrate_bps > kHighBitrateBps) {
|
||||
int total_bitrate_bps =
|
||||
stats.substreams.begin()->second.total_bitrate_bps;
|
||||
test::PrintResult("bitrate_stats_",
|
||||
"min_transmit_bitrate_low_remb",
|
||||
"bitrate_bps",
|
||||
static_cast<size_t>(total_bitrate_bps),
|
||||
"bps",
|
||||
false);
|
||||
if (total_bitrate_bps > kHighBitrateBps) {
|
||||
rtp_rtcp_->SetREMBData(kRembBitrateBps, 1, &header.ssrc);
|
||||
rtp_rtcp_->Process();
|
||||
bitrate_capped_ = true;
|
||||
} else if (bitrate_capped_ &&
|
||||
bitrate_bps < kRembRespectedBitrateBps) {
|
||||
total_bitrate_bps < kRembRespectedBitrateBps) {
|
||||
observation_complete_->Set();
|
||||
}
|
||||
}
|
||||
|
@ -415,10 +415,12 @@ class ViEChannel
|
||||
|
||||
class RegisterableBitrateStatisticsObserver:
|
||||
public RegisterableCallback<BitrateStatisticsObserver> {
|
||||
virtual void Notify(const BitrateStatistics& stats, uint32_t ssrc) {
|
||||
virtual void Notify(const BitrateStatistics& total_stats,
|
||||
const BitrateStatistics& retransmit_stats,
|
||||
uint32_t ssrc) {
|
||||
CriticalSectionScoped cs(critsect_.get());
|
||||
if (callback_)
|
||||
callback_->Notify(stats, ssrc);
|
||||
callback_->Notify(total_stats, retransmit_stats, ssrc);
|
||||
}
|
||||
}
|
||||
send_bitrate_observer_;
|
||||
|
@ -63,7 +63,7 @@ class VideoReceiveStream {
|
||||
int expected_delay_ms;
|
||||
};
|
||||
|
||||
struct Stats : public StreamStats {
|
||||
struct Stats : public SsrcStats {
|
||||
Stats()
|
||||
: network_frame_rate(0),
|
||||
decode_frame_rate(0),
|
||||
|
@ -41,11 +41,13 @@ class VideoSendStream {
|
||||
Stats()
|
||||
: input_frame_rate(0),
|
||||
encode_frame_rate(0),
|
||||
media_bitrate_bps(0),
|
||||
suspended(false) {}
|
||||
int input_frame_rate;
|
||||
int encode_frame_rate;
|
||||
int media_bitrate_bps;
|
||||
bool suspended;
|
||||
std::map<uint32_t, StreamStats> substreams;
|
||||
std::map<uint32_t, SsrcStats> substreams;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
|
Loading…
x
Reference in New Issue
Block a user