Split stats generation for MediaChannel into sender and receiver APIs

This is in preparation for splitting MediaChannel into sender and
receiver channels, with independent objects.

Bug: webrtc:13931
Change-Id: I8e34b0c80b4d76132394efcda658a8face3ab873
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/288750
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38998}
This commit is contained in:
Harald Alvestrand 2023-01-04 12:42:56 +00:00 committed by WebRTC LUCI CQ
parent 9253240305
commit 1251c6418e
18 changed files with 811 additions and 401 deletions

View File

@ -187,8 +187,11 @@ absl::optional<int> FakeVoiceMediaChannel::GetBaseMinimumPlayoutDelayMs(
} }
return absl::nullopt; return absl::nullopt;
} }
bool FakeVoiceMediaChannel::GetStats(VoiceMediaInfo* info, bool FakeVoiceMediaChannel::GetSendStats(VoiceMediaSendInfo* info) {
bool get_and_clear_legacy_stats) { return false;
}
bool FakeVoiceMediaChannel::GetReceiveStats(VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) {
return false; return false;
} }
void FakeVoiceMediaChannel::SetRawAudioSink( void FakeVoiceMediaChannel::SetRawAudioSink(
@ -367,7 +370,10 @@ bool FakeVideoMediaChannel::RemoveRecvStream(uint32_t ssrc) {
} }
void FakeVideoMediaChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) { void FakeVideoMediaChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
} }
bool FakeVideoMediaChannel::GetStats(VideoMediaInfo* info) { bool FakeVideoMediaChannel::GetSendStats(VideoMediaSendInfo* info) {
return false;
}
bool FakeVideoMediaChannel::GetReceiveStats(VideoMediaReceiveInfo* info) {
return false; return false;
} }
std::vector<webrtc::RtpSource> FakeVideoMediaChannel::GetSources( std::vector<webrtc::RtpSource> FakeVideoMediaChannel::GetSources(

View File

@ -381,7 +381,9 @@ class FakeVoiceMediaChannel : public RtpHelper<VoiceMediaChannel> {
absl::optional<int> GetBaseMinimumPlayoutDelayMs( absl::optional<int> GetBaseMinimumPlayoutDelayMs(
uint32_t ssrc) const override; uint32_t ssrc) const override;
bool GetStats(VoiceMediaInfo* info, bool get_and_clear_legacy_stats) override; bool GetSendStats(VoiceMediaSendInfo* info) override;
bool GetReceiveStats(VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) override;
void SetRawAudioSink( void SetRawAudioSink(
uint32_t ssrc, uint32_t ssrc,
@ -473,7 +475,8 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
bool RemoveRecvStream(uint32_t ssrc) override; bool RemoveRecvStream(uint32_t ssrc) override;
void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override; void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override;
bool GetStats(VideoMediaInfo* info) override; bool GetSendStats(VideoMediaSendInfo* info) override;
bool GetReceiveStats(VideoMediaReceiveInfo* info) override;
std::vector<webrtc::RtpSource> GetSources(uint32_t ssrc) const override; std::vector<webrtc::RtpSource> GetSources(uint32_t ssrc) const override;

View File

@ -676,8 +676,41 @@ struct BandwidthEstimationInfo {
// Maps from payload type to `RtpCodecParameters`. // Maps from payload type to `RtpCodecParameters`.
typedef std::map<int, webrtc::RtpCodecParameters> RtpCodecParametersMap; typedef std::map<int, webrtc::RtpCodecParameters> RtpCodecParametersMap;
// Stats returned from VoiceMediaSendChannel.GetStats()
struct VoiceMediaSendInfo {
VoiceMediaSendInfo();
~VoiceMediaSendInfo();
void Clear() {
senders.clear();
send_codecs.clear();
}
std::vector<VoiceSenderInfo> senders;
RtpCodecParametersMap send_codecs;
};
// Stats returned from VoiceMediaReceiveChannel.GetStats()
struct VoiceMediaReceiveInfo {
VoiceMediaReceiveInfo();
~VoiceMediaReceiveInfo();
void Clear() {
receivers.clear();
receive_codecs.clear();
}
std::vector<VoiceReceiverInfo> receivers;
RtpCodecParametersMap receive_codecs;
int32_t device_underrun_count = 0;
};
// Combined VoiceMediaSendInfo and VoiceMediaReceiveInfo
// Returned from Transceiver.getStats()
struct VoiceMediaInfo { struct VoiceMediaInfo {
VoiceMediaInfo(); VoiceMediaInfo();
VoiceMediaInfo(VoiceMediaSendInfo&& send, VoiceMediaReceiveInfo&& receive)
: senders(std::move(send.senders)),
receivers(std::move(receive.receivers)),
send_codecs(std::move(send.send_codecs)),
receive_codecs(std::move(receive.receive_codecs)),
device_underrun_count(receive.device_underrun_count) {}
~VoiceMediaInfo(); ~VoiceMediaInfo();
void Clear() { void Clear() {
senders.clear(); senders.clear();
@ -692,8 +725,49 @@ struct VoiceMediaInfo {
int32_t device_underrun_count = 0; int32_t device_underrun_count = 0;
}; };
// Stats for a VideoMediaSendChannel
struct VideoMediaSendInfo {
VideoMediaSendInfo();
~VideoMediaSendInfo();
void Clear() {
senders.clear();
aggregated_senders.clear();
send_codecs.clear();
}
// Each sender info represents one "outbound-rtp" stream.In non - simulcast,
// this means one info per RtpSender but if simulcast is used this means
// one info per simulcast layer.
std::vector<VideoSenderInfo> senders;
// Used for legacy getStats() API's "ssrc" stats and modern getStats() API's
// "track" stats. If simulcast is used, instead of having one sender info per
// simulcast layer, the metrics of all layers of an RtpSender are aggregated
// into a single sender info per RtpSender.
std::vector<VideoSenderInfo> aggregated_senders;
RtpCodecParametersMap send_codecs;
};
// Stats for a VideoMediaReceiveChannel
struct VideoMediaReceiveInfo {
VideoMediaReceiveInfo();
~VideoMediaReceiveInfo();
void Clear() {
receivers.clear();
receive_codecs.clear();
}
std::vector<VideoReceiverInfo> receivers;
RtpCodecParametersMap receive_codecs;
};
// Combined VideoMediaSenderInfo and VideoMediaReceiverInfo.
// Returned from channel.GetStats()
struct VideoMediaInfo { struct VideoMediaInfo {
VideoMediaInfo(); VideoMediaInfo();
VideoMediaInfo(VideoMediaSendInfo&& send, VideoMediaReceiveInfo&& receive)
: senders(std::move(send.senders)),
aggregated_senders(std::move(send.aggregated_senders)),
receivers(std::move(receive.receivers)),
send_codecs(std::move(send.send_codecs)),
receive_codecs(std::move(receive.receive_codecs)) {}
~VideoMediaInfo(); ~VideoMediaInfo();
void Clear() { void Clear() {
senders.clear(); senders.clear();
@ -801,6 +875,7 @@ class VoiceMediaSendChannelInterface : public MediaSendChannelInterface {
// The valid value for the `event` are 0 to 15 which corresponding to // The valid value for the `event` are 0 to 15 which corresponding to
// DTMF event 0-9, *, #, A-D. // DTMF event 0-9, *, #, A-D.
virtual bool InsertDtmf(uint32_t ssrc, int event, int duration) = 0; virtual bool InsertDtmf(uint32_t ssrc, int event, int duration) = 0;
virtual bool GetStats(VoiceMediaSendInfo* stats) = 0;
}; };
class VoiceMediaReceiveChannelInterface : public MediaReceiveChannelInterface { class VoiceMediaReceiveChannelInterface : public MediaReceiveChannelInterface {
@ -824,6 +899,7 @@ class VoiceMediaReceiveChannelInterface : public MediaReceiveChannelInterface {
std::unique_ptr<webrtc::AudioSinkInterface> sink) = 0; std::unique_ptr<webrtc::AudioSinkInterface> sink) = 0;
virtual void SetDefaultRawAudioSink( virtual void SetDefaultRawAudioSink(
std::unique_ptr<webrtc::AudioSinkInterface> sink) = 0; std::unique_ptr<webrtc::AudioSinkInterface> sink) = 0;
virtual bool GetStats(VoiceMediaReceiveInfo* stats, bool reset_legacy) = 0;
}; };
// TODO(deadbeef): Rename to VideoSenderParameters, since they're intended to // TODO(deadbeef): Rename to VideoSenderParameters, since they're intended to
@ -865,6 +941,8 @@ class VideoMediaSendChannelInterface : public MediaSendChannelInterface {
const std::vector<std::string>& rids) = 0; const std::vector<std::string>& rids) = 0;
// Enable network condition based codec switching. // Enable network condition based codec switching.
virtual void SetVideoCodecSwitchingEnabled(bool enabled) = 0; virtual void SetVideoCodecSwitchingEnabled(bool enabled) = 0;
virtual bool GetStats(VideoMediaSendInfo* stats) = 0;
virtual void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) = 0;
}; };
class VideoMediaReceiveChannelInterface : public MediaReceiveChannelInterface { class VideoMediaReceiveChannelInterface : public MediaReceiveChannelInterface {
@ -893,6 +971,7 @@ class VideoMediaReceiveChannelInterface : public MediaReceiveChannelInterface {
std::function<void(const webrtc::RecordableEncodedFrame&)> callback) = 0; std::function<void(const webrtc::RecordableEncodedFrame&)> callback) = 0;
// Clear recordable encoded frame callback for `ssrc` // Clear recordable encoded frame callback for `ssrc`
virtual void ClearRecordableEncodedFrameCallback(uint32_t ssrc) = 0; virtual void ClearRecordableEncodedFrameCallback(uint32_t ssrc) = 0;
virtual bool GetStats(VideoMediaReceiveInfo* stats) = 0;
}; };
// Info about data received in DataMediaChannel. For use in // Info about data received in DataMediaChannel. For use in

View File

@ -265,6 +265,18 @@ VoiceMediaInfo::~VoiceMediaInfo() = default;
VideoMediaInfo::VideoMediaInfo() = default; VideoMediaInfo::VideoMediaInfo() = default;
VideoMediaInfo::~VideoMediaInfo() = default; VideoMediaInfo::~VideoMediaInfo() = default;
VideoMediaSendInfo::VideoMediaSendInfo() = default;
VideoMediaSendInfo::~VideoMediaSendInfo() = default;
VoiceMediaSendInfo::VoiceMediaSendInfo() = default;
VoiceMediaSendInfo::~VoiceMediaSendInfo() = default;
VideoMediaReceiveInfo::VideoMediaReceiveInfo() = default;
VideoMediaReceiveInfo::~VideoMediaReceiveInfo() = default;
VoiceMediaReceiveInfo::VoiceMediaReceiveInfo() = default;
VoiceMediaReceiveInfo::~VoiceMediaReceiveInfo() = default;
AudioSendParameters::AudioSendParameters() = default; AudioSendParameters::AudioSendParameters() = default;
AudioSendParameters::~AudioSendParameters() = default; AudioSendParameters::~AudioSendParameters() = default;

View File

@ -221,11 +221,23 @@ class VideoMediaChannel : public MediaChannel,
// need access to bitrates of the streams, or change the (RTC)StatsCollector // need access to bitrates of the streams, or change the (RTC)StatsCollector
// so that it's getting the send stream stats separately by calling // so that it's getting the send stream stats separately by calling
// GetStats(), and merges with BandwidthEstimationInfo by itself. // GetStats(), and merges with BandwidthEstimationInfo by itself.
virtual void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) = 0; void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override = 0;
// Gets quality stats for the channel. // Gets quality stats for the channel.
virtual bool GetStats(VideoMediaInfo* info) = 0; virtual bool GetSendStats(VideoMediaSendInfo* info) = 0;
virtual bool GetReceiveStats(VideoMediaReceiveInfo* info) = 0;
// Enable network condition based codec switching. // Enable network condition based codec switching.
void SetVideoCodecSwitchingEnabled(bool enabled) override; void SetVideoCodecSwitchingEnabled(bool enabled) override;
private:
// Functions not implemented on this interface
bool GetStats(VideoMediaSendInfo* info) override {
RTC_CHECK_NOTREACHED();
return false;
}
bool GetStats(VideoMediaReceiveInfo* info) override {
RTC_CHECK_NOTREACHED();
return false;
}
}; };
// Base class for implementation classes // Base class for implementation classes
@ -261,8 +273,21 @@ class VoiceMediaChannel : public MediaChannel,
} }
// Gets quality stats for the channel. // Gets quality stats for the channel.
virtual bool GetStats(VoiceMediaInfo* info, virtual bool GetSendStats(VoiceMediaSendInfo* info) = 0;
bool get_and_clear_legacy_stats) = 0; virtual bool GetReceiveStats(VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) = 0;
private:
// Functions not implemented on this interface
bool GetStats(VoiceMediaSendInfo* info) override {
RTC_CHECK_NOTREACHED();
return false;
}
bool GetStats(VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) override {
RTC_CHECK_NOTREACHED();
return false;
}
}; };
// The externally exposed objects that support the Send and Receive interfaces. // The externally exposed objects that support the Send and Receive interfaces.
@ -345,6 +370,9 @@ class VoiceMediaSendChannel : public VoiceMediaSendChannelInterface {
bool InsertDtmf(uint32_t ssrc, int event, int duration) override { bool InsertDtmf(uint32_t ssrc, int event, int duration) override {
return impl()->InsertDtmf(ssrc, event, duration); return impl()->InsertDtmf(ssrc, event, duration);
} }
bool GetStats(VoiceMediaSendInfo* info) override {
return impl_->GetSendStats(info);
}
private: private:
VoiceMediaSendChannelInterface* impl() { return impl_; } VoiceMediaSendChannelInterface* impl() { return impl_; }
@ -438,6 +466,9 @@ class VoiceMediaReceiveChannel : public VoiceMediaReceiveChannelInterface {
std::unique_ptr<webrtc::AudioSinkInterface> sink) override { std::unique_ptr<webrtc::AudioSinkInterface> sink) override {
return impl()->SetDefaultRawAudioSink(std::move(sink)); return impl()->SetDefaultRawAudioSink(std::move(sink));
} }
bool GetStats(VoiceMediaReceiveInfo* info, bool reset_legacy) override {
return impl_->GetReceiveStats(info, reset_legacy);
}
private: private:
VoiceMediaReceiveChannelInterface* impl() { return impl_; } VoiceMediaReceiveChannelInterface* impl() { return impl_; }
@ -456,7 +487,7 @@ class VideoMediaSendChannel : public VideoMediaSendChannelInterface {
} }
// Implementation of MediaBaseChannelInterface // Implementation of MediaBaseChannelInterface
cricket::MediaType media_type() const override { return MEDIA_TYPE_AUDIO; } cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(rtc::CopyOnWriteBuffer packet,
int64_t packet_time_us) override { int64_t packet_time_us) override {
impl()->OnPacketReceived(packet, packet_time_us); impl()->OnPacketReceived(packet, packet_time_us);
@ -528,6 +559,12 @@ class VideoMediaSendChannel : public VideoMediaSendChannelInterface {
void SetVideoCodecSwitchingEnabled(bool enabled) override { void SetVideoCodecSwitchingEnabled(bool enabled) override {
return impl()->SetVideoCodecSwitchingEnabled(enabled); return impl()->SetVideoCodecSwitchingEnabled(enabled);
} }
bool GetStats(VideoMediaSendInfo* info) override {
return impl_->GetSendStats(info);
}
void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override {
return impl_->FillBitrateInfo(bwe_info);
}
private: private:
VideoMediaSendChannelInterface* impl() { return impl_; } VideoMediaSendChannelInterface* impl() { return impl_; }
@ -539,7 +576,7 @@ class VideoMediaReceiveChannel : public VideoMediaReceiveChannelInterface {
public: public:
explicit VideoMediaReceiveChannel(VideoMediaChannel* impl) : impl_(impl) {} explicit VideoMediaReceiveChannel(VideoMediaChannel* impl) : impl_(impl) {}
// Implementation of MediaBaseChannelInterface // Implementation of MediaBaseChannelInterface
cricket::MediaType media_type() const override { return MEDIA_TYPE_AUDIO; } cricket::MediaType media_type() const override { return MEDIA_TYPE_VIDEO; }
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(rtc::CopyOnWriteBuffer packet,
int64_t packet_time_us) override { int64_t packet_time_us) override {
impl()->OnPacketReceived(packet, packet_time_us); impl()->OnPacketReceived(packet, packet_time_us);
@ -565,6 +602,9 @@ class VideoMediaReceiveChannel : public VideoMediaReceiveChannelInterface {
return impl()->GetBaseMinimumPlayoutDelayMs(ssrc); return impl()->GetBaseMinimumPlayoutDelayMs(ssrc);
} }
// Implementation of MediaReceiveChannelInterface // Implementation of MediaReceiveChannelInterface
VideoMediaReceiveChannelInterface* AsVideoReceiveChannel() override {
return this;
}
bool AddRecvStream(const StreamParams& sp) override { bool AddRecvStream(const StreamParams& sp) override {
return impl()->AddRecvStream(sp); return impl()->AddRecvStream(sp);
} }
@ -626,6 +666,9 @@ class VideoMediaReceiveChannel : public VideoMediaReceiveChannelInterface {
void ClearRecordableEncodedFrameCallback(uint32_t ssrc) override { void ClearRecordableEncodedFrameCallback(uint32_t ssrc) override {
impl()->ClearRecordableEncodedFrameCallback(ssrc); impl()->ClearRecordableEncodedFrameCallback(ssrc);
} }
bool GetStats(VideoMediaReceiveInfo* info) override {
return impl_->GetReceiveStats(info);
}
private: private:
VideoMediaReceiveChannelInterface* impl() { return impl_; } VideoMediaReceiveChannelInterface* impl() { return impl_; }

View File

@ -1600,9 +1600,9 @@ void WebRtcVideoChannel::SetDefaultSink(
default_unsignalled_ssrc_handler_.SetDefaultSink(this, sink); default_unsignalled_ssrc_handler_.SetDefaultSink(this, sink);
} }
bool WebRtcVideoChannel::GetStats(VideoMediaInfo* info) { bool WebRtcVideoChannel::GetSendStats(VideoMediaSendInfo* info) {
RTC_DCHECK_RUN_ON(&thread_checker_); RTC_DCHECK_RUN_ON(&thread_checker_);
TRACE_EVENT0("webrtc", "WebRtcVideoChannel::GetStats"); TRACE_EVENT0("webrtc", "WebRtcVideoChannel::GetSendStats");
// Log stats periodically. // Log stats periodically.
bool log_stats = false; bool log_stats = false;
@ -1615,8 +1615,7 @@ bool WebRtcVideoChannel::GetStats(VideoMediaInfo* info) {
info->Clear(); info->Clear();
FillSenderStats(info, log_stats); FillSenderStats(info, log_stats);
FillReceiverStats(info, log_stats); FillSendCodecStats(info);
FillSendAndReceiveCodecStats(info);
// TODO(holmer): We should either have rtt available as a metric on // TODO(holmer): We should either have rtt available as a metric on
// VideoSend/ReceiveStreams, or we should remove rtt from VideoSenderInfo. // VideoSend/ReceiveStreams, or we should remove rtt from VideoSenderInfo.
webrtc::Call::Stats stats = call_->GetStats(); webrtc::Call::Stats stats = call_->GetStats();
@ -1634,8 +1633,27 @@ bool WebRtcVideoChannel::GetStats(VideoMediaInfo* info) {
return true; return true;
} }
bool WebRtcVideoChannel::GetReceiveStats(VideoMediaReceiveInfo* info) {
RTC_DCHECK_RUN_ON(&thread_checker_);
TRACE_EVENT0("webrtc", "WebRtcVideoChannel::GetReceiveStats");
void WebRtcVideoChannel::FillSenderStats(VideoMediaInfo* video_media_info, // Log stats periodically.
bool log_stats = false;
int64_t now_ms = rtc::TimeMillis();
if (last_stats_log_ms_ == -1 ||
now_ms - last_stats_log_ms_ > kStatsLogIntervalMs) {
last_stats_log_ms_ = now_ms;
log_stats = true;
}
info->Clear();
FillReceiverStats(info, log_stats);
FillReceiveCodecStats(info);
return true;
}
void WebRtcVideoChannel::FillSenderStats(VideoMediaSendInfo* video_media_info,
bool log_stats) { bool log_stats) {
for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
send_streams_.begin(); send_streams_.begin();
@ -1651,8 +1669,9 @@ void WebRtcVideoChannel::FillSenderStats(VideoMediaInfo* video_media_info,
} }
} }
void WebRtcVideoChannel::FillReceiverStats(VideoMediaInfo* video_media_info, void WebRtcVideoChannel::FillReceiverStats(
bool log_stats) { VideoMediaReceiveInfo* video_media_info,
bool log_stats) {
for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it = for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
receive_streams_.begin(); receive_streams_.begin();
it != receive_streams_.end(); ++it) { it != receive_streams_.end(); ++it) {
@ -1670,13 +1689,18 @@ void WebRtcVideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
} }
} }
void WebRtcVideoChannel::FillSendAndReceiveCodecStats( void WebRtcVideoChannel::FillSendCodecStats(
VideoMediaInfo* video_media_info) { VideoMediaSendInfo* video_media_info) {
for (const VideoCodec& codec : send_params_.codecs) { for (const VideoCodec& codec : send_params_.codecs) {
webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters(); webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
video_media_info->send_codecs.insert( video_media_info->send_codecs.insert(
std::make_pair(codec_params.payload_type, std::move(codec_params))); std::make_pair(codec_params.payload_type, std::move(codec_params)));
} }
}
void WebRtcVideoChannel::FillReceiveCodecStats(
VideoMediaReceiveInfo* video_media_info) {
// TODO(bugs.webrtc.org/14808): Don't copy codec info around - reference it.
for (const VideoCodec& codec : recv_params_.codecs) { for (const VideoCodec& codec : recv_params_.codecs) {
webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters(); webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
video_media_info->receive_codecs.insert( video_media_info->receive_codecs.insert(

View File

@ -172,7 +172,8 @@ class WebRtcVideoChannel : public VideoMediaChannel,
void SetDefaultSink( void SetDefaultSink(
rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override; rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override;
void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override; void FillBitrateInfo(BandwidthEstimationInfo* bwe_info) override;
bool GetStats(VideoMediaInfo* info) override; bool GetSendStats(VideoMediaSendInfo* info) override;
bool GetReceiveStats(VideoMediaReceiveInfo* info) override;
void OnPacketReceived(rtc::CopyOnWriteBuffer packet, void OnPacketReceived(rtc::CopyOnWriteBuffer packet,
int64_t packet_time_us) override; int64_t packet_time_us) override;
@ -574,14 +575,16 @@ class WebRtcVideoChannel : public VideoMediaChannel,
std::vector<VideoCodecSettings> before, std::vector<VideoCodecSettings> before,
std::vector<VideoCodecSettings> after); std::vector<VideoCodecSettings> after);
void FillSenderStats(VideoMediaInfo* info, bool log_stats) void FillSenderStats(VideoMediaSendInfo* info, bool log_stats)
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_); RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
void FillReceiverStats(VideoMediaInfo* info, bool log_stats) void FillReceiverStats(VideoMediaReceiveInfo* info, bool log_stats)
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_); RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
void FillBandwidthEstimationStats(const webrtc::Call::Stats& stats, void FillBandwidthEstimationStats(const webrtc::Call::Stats& stats,
VideoMediaInfo* info) VideoMediaInfo* info)
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_); RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
void FillSendAndReceiveCodecStats(VideoMediaInfo* video_media_info) void FillSendCodecStats(VideoMediaSendInfo* video_media_info)
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
void FillReceiveCodecStats(VideoMediaReceiveInfo* video_media_info)
RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_); RTC_EXCLUSIVE_LOCKS_REQUIRED(thread_checker_);
webrtc::TaskQueueBase* const worker_thread_; webrtc::TaskQueueBase* const worker_thread_;

View File

@ -563,8 +563,10 @@ TEST_F(WebRtcVideoEngineTest, GetStatsWithoutSendCodecsSetDoesNotCrash) {
auto send_channel = std::make_unique<VideoMediaSendChannel>(channel.get()); auto send_channel = std::make_unique<VideoMediaSendChannel>(channel.get());
EXPECT_TRUE(send_channel->AddSendStream(StreamParams::CreateLegacy(123))); EXPECT_TRUE(send_channel->AddSendStream(StreamParams::CreateLegacy(123)));
VideoMediaInfo info; VideoMediaSendInfo send_info;
channel->GetStats(&info); VideoMediaReceiveInfo receive_info;
channel->GetSendStats(&send_info);
channel->GetReceiveStats(&receive_info);
} }
TEST_F(WebRtcVideoEngineTest, UseFactoryForVp8WhenSupported) { TEST_F(WebRtcVideoEngineTest, UseFactoryForVp8WhenSupported) {
@ -1727,14 +1729,14 @@ class WebRtcVideoChannelBaseTest : public ::testing::Test {
} }
cricket::VideoSenderInfo GetSenderStats(size_t i) { cricket::VideoSenderInfo GetSenderStats(size_t i) {
cricket::VideoMediaInfo info; VideoMediaSendInfo send_info;
EXPECT_TRUE(channel_->GetStats(&info)); EXPECT_TRUE(channel_->GetSendStats(&send_info));
return info.senders[i]; return send_info.senders[i];
} }
cricket::VideoReceiverInfo GetReceiverStats(size_t i) { cricket::VideoReceiverInfo GetReceiverStats(size_t i) {
cricket::VideoMediaInfo info; cricket::VideoMediaReceiveInfo info;
EXPECT_TRUE(channel_->GetStats(&info)); EXPECT_TRUE(channel_->GetReceiveStats(&info));
return info.receivers[i]; return info.receivers[i];
} }
@ -1827,54 +1829,57 @@ TEST_F(WebRtcVideoChannelBaseTest, GetStats) {
const int kFps = 10; const int kFps = 10;
SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps); SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
EXPECT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(1U, info.senders.size()); ASSERT_EQ(1U, send_info.senders.size());
// TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload? // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
// For webrtc, bytes_sent does not include the RTP header length. // For webrtc, bytes_sent does not include the RTP header length.
EXPECT_EQ(info.senders[0].payload_bytes_sent, EXPECT_EQ(send_info.senders[0].payload_bytes_sent,
NumRtpBytes() - kRtpHeaderSize * NumRtpPackets()); NumRtpBytes() - kRtpHeaderSize * NumRtpPackets());
EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent); EXPECT_EQ(NumRtpPackets(), send_info.senders[0].packets_sent);
EXPECT_EQ(0.0, info.senders[0].fraction_lost); EXPECT_EQ(0.0, send_info.senders[0].fraction_lost);
ASSERT_TRUE(info.senders[0].codec_payload_type); ASSERT_TRUE(send_info.senders[0].codec_payload_type);
EXPECT_EQ(DefaultCodec().id, *info.senders[0].codec_payload_type); EXPECT_EQ(DefaultCodec().id, *send_info.senders[0].codec_payload_type);
EXPECT_EQ(0, info.senders[0].firs_rcvd); EXPECT_EQ(0, send_info.senders[0].firs_rcvd);
EXPECT_EQ(0, info.senders[0].plis_rcvd); EXPECT_EQ(0, send_info.senders[0].plis_rcvd);
EXPECT_EQ(0u, info.senders[0].nacks_rcvd); EXPECT_EQ(0u, send_info.senders[0].nacks_rcvd);
EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width); EXPECT_EQ(kVideoWidth, send_info.senders[0].send_frame_width);
EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height); EXPECT_EQ(kVideoHeight, send_info.senders[0].send_frame_height);
EXPECT_GT(info.senders[0].framerate_input, 0); EXPECT_GT(send_info.senders[0].framerate_input, 0);
EXPECT_GT(info.senders[0].framerate_sent, 0); EXPECT_GT(send_info.senders[0].framerate_sent, 0);
EXPECT_EQ(1U, info.send_codecs.count(DefaultCodec().id)); EXPECT_EQ(1U, send_info.send_codecs.count(DefaultCodec().id));
EXPECT_EQ(DefaultCodec().ToCodecParameters(), EXPECT_EQ(DefaultCodec().ToCodecParameters(),
info.send_codecs[DefaultCodec().id]); send_info.send_codecs[DefaultCodec().id]);
ASSERT_EQ(1U, info.receivers.size()); ASSERT_EQ(1U, receive_info.receivers.size());
EXPECT_EQ(1U, info.senders[0].ssrcs().size()); EXPECT_EQ(1U, send_info.senders[0].ssrcs().size());
EXPECT_EQ(1U, info.receivers[0].ssrcs().size()); EXPECT_EQ(1U, receive_info.receivers[0].ssrcs().size());
EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]); EXPECT_EQ(send_info.senders[0].ssrcs()[0],
ASSERT_TRUE(info.receivers[0].codec_payload_type); receive_info.receivers[0].ssrcs()[0]);
EXPECT_EQ(DefaultCodec().id, *info.receivers[0].codec_payload_type); ASSERT_TRUE(receive_info.receivers[0].codec_payload_type);
EXPECT_EQ(DefaultCodec().id, *receive_info.receivers[0].codec_payload_type);
EXPECT_EQ(NumRtpBytes() - kRtpHeaderSize * NumRtpPackets(), EXPECT_EQ(NumRtpBytes() - kRtpHeaderSize * NumRtpPackets(),
info.receivers[0].payload_bytes_rcvd); receive_info.receivers[0].payload_bytes_rcvd);
EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd); EXPECT_EQ(NumRtpPackets(), receive_info.receivers[0].packets_rcvd);
EXPECT_EQ(0, info.receivers[0].packets_lost); EXPECT_EQ(0, receive_info.receivers[0].packets_lost);
// TODO(asapersson): Not set for webrtc. Handle missing stats. // TODO(asapersson): Not set for webrtc. Handle missing stats.
// EXPECT_EQ(0, info.receivers[0].packets_concealed); // EXPECT_EQ(0, receive_info.receivers[0].packets_concealed);
EXPECT_EQ(0, info.receivers[0].firs_sent); EXPECT_EQ(0, receive_info.receivers[0].firs_sent);
EXPECT_EQ(0, info.receivers[0].plis_sent); EXPECT_EQ(0, receive_info.receivers[0].plis_sent);
EXPECT_EQ(0U, info.receivers[0].nacks_sent); EXPECT_EQ(0U, receive_info.receivers[0].nacks_sent);
EXPECT_EQ(kVideoWidth, info.receivers[0].frame_width); EXPECT_EQ(kVideoWidth, receive_info.receivers[0].frame_width);
EXPECT_EQ(kVideoHeight, info.receivers[0].frame_height); EXPECT_EQ(kVideoHeight, receive_info.receivers[0].frame_height);
EXPECT_GT(info.receivers[0].framerate_rcvd, 0); EXPECT_GT(receive_info.receivers[0].framerate_rcvd, 0);
EXPECT_GT(info.receivers[0].framerate_decoded, 0); EXPECT_GT(receive_info.receivers[0].framerate_decoded, 0);
EXPECT_GT(info.receivers[0].framerate_output, 0); EXPECT_GT(receive_info.receivers[0].framerate_output, 0);
EXPECT_EQ(1U, info.receive_codecs.count(DefaultCodec().id)); EXPECT_EQ(1U, receive_info.receive_codecs.count(DefaultCodec().id));
EXPECT_EQ(DefaultCodec().ToCodecParameters(), EXPECT_EQ(DefaultCodec().ToCodecParameters(),
info.receive_codecs[DefaultCodec().id]); receive_info.receive_codecs[DefaultCodec().id]);
} }
// Test that stats work properly for a conf call with multiple recv streams. // Test that stats work properly for a conf call with multiple recv streams.
@ -1906,9 +1911,12 @@ TEST_F(WebRtcVideoChannelBaseTest, GetStatsMultipleRecvStreams) {
EXPECT_TRUE(channel_->SetSend(false)); EXPECT_TRUE(channel_->SetSend(false));
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
EXPECT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(1U, info.senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(1U, send_info.senders.size());
// TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload? // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
// For webrtc, bytes_sent does not include the RTP header length. // For webrtc, bytes_sent does not include the RTP header length.
EXPECT_EQ_WAIT(NumRtpBytes() - kRtpHeaderSize * NumRtpPackets(), EXPECT_EQ_WAIT(NumRtpBytes() - kRtpHeaderSize * NumRtpPackets(),
@ -1917,8 +1925,8 @@ TEST_F(WebRtcVideoChannelBaseTest, GetStatsMultipleRecvStreams) {
EXPECT_EQ(kVideoWidth, GetSenderStats(0).send_frame_width); EXPECT_EQ(kVideoWidth, GetSenderStats(0).send_frame_width);
EXPECT_EQ(kVideoHeight, GetSenderStats(0).send_frame_height); EXPECT_EQ(kVideoHeight, GetSenderStats(0).send_frame_height);
ASSERT_EQ(2U, info.receivers.size()); ASSERT_EQ(2U, receive_info.receivers.size());
for (size_t i = 0; i < info.receivers.size(); ++i) { for (size_t i = 0; i < receive_info.receivers.size(); ++i) {
EXPECT_EQ(1U, GetReceiverStats(i).ssrcs().size()); EXPECT_EQ(1U, GetReceiverStats(i).ssrcs().size());
EXPECT_EQ(i + 1, GetReceiverStats(i).ssrcs()[0]); EXPECT_EQ(i + 1, GetReceiverStats(i).ssrcs()[0]);
EXPECT_EQ_WAIT(NumRtpBytes() - kRtpHeaderSize * NumRtpPackets(), EXPECT_EQ_WAIT(NumRtpBytes() - kRtpHeaderSize * NumRtpPackets(),
@ -1966,29 +1974,30 @@ TEST_F(WebRtcVideoChannelBaseTest, GetStatsMultipleSendStreams) {
// Get stats, and make sure they are correct for two senders. We wait until // Get stats, and make sure they are correct for two senders. We wait until
// the number of expected packets have been sent to avoid races where we // the number of expected packets have been sent to avoid races where we
// check stats before it has been updated. // check stats before it has been updated.
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
for (uint32_t i = 0; i < kTimeout; ++i) { for (uint32_t i = 0; i < kTimeout; ++i) {
rtc::Thread::Current()->ProcessMessages(1); rtc::Thread::Current()->ProcessMessages(1);
EXPECT_TRUE(channel_->GetStats(&info)); EXPECT_TRUE(channel_->GetSendStats(&send_info));
ASSERT_EQ(2U, info.senders.size());
if (info.senders[0].packets_sent + info.senders[1].packets_sent == ASSERT_EQ(2U, send_info.senders.size());
if (send_info.senders[0].packets_sent + send_info.senders[1].packets_sent ==
NumRtpPackets()) { NumRtpPackets()) {
// Stats have been updated for both sent frames, expectations can be // Stats have been updated for both sent frames, expectations can be
// checked now. // checked now.
break; break;
} }
} }
EXPECT_EQ(NumRtpPackets(), EXPECT_EQ(NumRtpPackets(), send_info.senders[0].packets_sent +
info.senders[0].packets_sent + info.senders[1].packets_sent) send_info.senders[1].packets_sent)
<< "Timed out while waiting for packet counts for all sent packets."; << "Timed out while waiting for packet counts for all sent packets.";
EXPECT_EQ(1U, info.senders[0].ssrcs().size()); EXPECT_EQ(1U, send_info.senders[0].ssrcs().size());
EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]); EXPECT_EQ(1234U, send_info.senders[0].ssrcs()[0]);
EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width); EXPECT_EQ(kVideoWidth, send_info.senders[0].send_frame_width);
EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height); EXPECT_EQ(kVideoHeight, send_info.senders[0].send_frame_height);
EXPECT_EQ(1U, info.senders[1].ssrcs().size()); EXPECT_EQ(1U, send_info.senders[1].ssrcs().size());
EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]); EXPECT_EQ(5678U, send_info.senders[1].ssrcs()[0]);
EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width); EXPECT_EQ(kTestWidth, send_info.senders[1].send_frame_width);
EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height); EXPECT_EQ(kTestHeight, send_info.senders[1].send_frame_height);
// The capturer must be unregistered here as it runs out of it's scope next. // The capturer must be unregistered here as it runs out of it's scope next.
channel_->SetVideoSend(5678, nullptr, nullptr); channel_->SetVideoSend(5678, nullptr, nullptr);
} }
@ -4049,10 +4058,14 @@ TEST_F(WebRtcVideoChannelTest, EstimatesNtpStartTimeCorrectly) {
EXPECT_EQ(2, renderer.num_rendered_frames()); EXPECT_EQ(2, renderer.num_rendered_frames());
// Verify that NTP time has been correctly deduced. // Verify that NTP time has been correctly deduced.
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(1u, info.receivers.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(kInitialNtpTimeMs, info.receivers[0].capture_start_ntp_time_ms); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(1u, receive_info.receivers.size());
EXPECT_EQ(kInitialNtpTimeMs,
receive_info.receivers[0].capture_start_ntp_time_ms);
} }
TEST_F(WebRtcVideoChannelTest, SetDefaultSendCodecs) { TEST_F(WebRtcVideoChannelTest, SetDefaultSendCodecs) {
@ -5436,9 +5449,12 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsSentCodecName) {
AddSendStream(); AddSendStream();
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ("VP8", info.senders[0].codec_name); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ("VP8", send_info.senders[0].codec_name);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsEncoderImplementationName) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsEncoderImplementationName) {
@ -5447,10 +5463,13 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsEncoderImplementationName) {
stats.encoder_implementation_name = "encoder_implementation_name"; stats.encoder_implementation_name = "encoder_implementation_name";
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.encoder_implementation_name, EXPECT_EQ(stats.encoder_implementation_name,
info.senders[0].encoder_implementation_name); send_info.senders[0].encoder_implementation_name);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsPowerEfficientEncoder) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsPowerEfficientEncoder) {
@ -5459,9 +5478,12 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsPowerEfficientEncoder) {
stats.power_efficient_encoder = true; stats.power_efficient_encoder = true;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(info.senders[0].power_efficient_encoder); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_TRUE(send_info.senders[0].power_efficient_encoder);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuOveruseMetrics) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuOveruseMetrics) {
@ -5471,10 +5493,14 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuOveruseMetrics) {
stats.encode_usage_percent = 42; stats.encode_usage_percent = 42;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(stats.avg_encode_time_ms, info.senders[0].avg_encode_ms); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(stats.encode_usage_percent, info.senders[0].encode_usage_percent); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.avg_encode_time_ms, send_info.senders[0].avg_encode_ms);
EXPECT_EQ(stats.encode_usage_percent,
send_info.senders[0].encode_usage_percent);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsFramesEncoded) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsFramesEncoded) {
@ -5483,9 +5509,12 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsFramesEncoded) {
stats.frames_encoded = 13; stats.frames_encoded = 13;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(stats.frames_encoded, info.senders[0].frames_encoded); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.frames_encoded, send_info.senders[0].frames_encoded);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsKeyFramesEncoded) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsKeyFramesEncoded) {
@ -5495,12 +5524,15 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsKeyFramesEncoded) {
stats.substreams[456].frame_counts.key_frames = 87; stats.substreams[456].frame_counts.key_frames = 87;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(info.senders.size(), 2u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(10u, info.senders[0].key_frames_encoded); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(87u, info.senders[1].key_frames_encoded);
EXPECT_EQ(97u, info.aggregated_senders[0].key_frames_encoded); EXPECT_EQ(send_info.senders.size(), 2u);
EXPECT_EQ(10u, send_info.senders[0].key_frames_encoded);
EXPECT_EQ(87u, send_info.senders[1].key_frames_encoded);
EXPECT_EQ(97u, send_info.aggregated_senders[0].key_frames_encoded);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsPerLayerQpSum) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsPerLayerQpSum) {
@ -5510,12 +5542,15 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsPerLayerQpSum) {
stats.substreams[456].qp_sum = 11; stats.substreams[456].qp_sum = 11;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(info.senders.size(), 2u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(stats.substreams[123].qp_sum, info.senders[0].qp_sum); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.substreams[456].qp_sum, info.senders[1].qp_sum);
EXPECT_EQ(*info.aggregated_senders[0].qp_sum, 26u); EXPECT_EQ(send_info.senders.size(), 2u);
EXPECT_EQ(stats.substreams[123].qp_sum, send_info.senders[0].qp_sum);
EXPECT_EQ(stats.substreams[456].qp_sum, send_info.senders[1].qp_sum);
EXPECT_EQ(*send_info.aggregated_senders[0].qp_sum, 26u);
} }
webrtc::VideoSendStream::Stats GetInitialisedStats() { webrtc::VideoSendStream::Stats GetInitialisedStats() {
@ -5559,10 +5594,13 @@ TEST_F(WebRtcVideoChannelTest, GetAggregatedStatsReportWithoutSubStreams) {
FakeVideoSendStream* stream = AddSendStream(); FakeVideoSendStream* stream = AddSendStream();
auto stats = GetInitialisedStats(); auto stats = GetInitialisedStats();
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&video_media_info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(video_media_info.aggregated_senders.size(), 1u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
auto& sender = video_media_info.aggregated_senders[0]; EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(send_info.aggregated_senders.size(), 1u);
auto& sender = send_info.aggregated_senders[0];
// MediaSenderInfo // MediaSenderInfo
@ -5669,10 +5707,13 @@ TEST_F(WebRtcVideoChannelTest, GetAggregatedStatsReportForSubStreams) {
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&video_media_info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(video_media_info.aggregated_senders.size(), 1u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
auto& sender = video_media_info.aggregated_senders[0]; EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(send_info.aggregated_senders.size(), 1u);
auto& sender = send_info.aggregated_senders[0];
// MediaSenderInfo // MediaSenderInfo
@ -5792,10 +5833,13 @@ TEST_F(WebRtcVideoChannelTest, GetPerLayerStatsReportForSubStreams) {
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&video_media_info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(video_media_info.senders.size(), 2u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
auto& sender = video_media_info.senders[0]; EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(send_info.senders.size(), 2u);
auto& sender = send_info.senders[0];
// MediaSenderInfo // MediaSenderInfo
@ -5896,13 +5940,16 @@ TEST_F(WebRtcVideoChannelTest,
stream->SetStats(stats); stream->SetStats(stats);
// GetStats() and ensure `active` matches `encodings` for each SSRC. // GetStats() and ensure `active` matches `encodings` for each SSRC.
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&video_media_info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(video_media_info.senders.size(), 2u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
ASSERT_TRUE(video_media_info.senders[0].active.has_value()); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_FALSE(video_media_info.senders[0].active.value());
ASSERT_TRUE(video_media_info.senders[1].active.has_value()); ASSERT_EQ(send_info.senders.size(), 2u);
EXPECT_TRUE(video_media_info.senders[1].active.value()); ASSERT_TRUE(send_info.senders[0].active.has_value());
EXPECT_FALSE(send_info.senders[0].active.value());
ASSERT_TRUE(send_info.senders[1].active.has_value());
EXPECT_TRUE(send_info.senders[1].active.value());
} }
TEST_F(WebRtcVideoChannelTest, OutboundRtpIsActiveComesFromAnyEncodingInSvc) { TEST_F(WebRtcVideoChannelTest, OutboundRtpIsActiveComesFromAnyEncodingInSvc) {
@ -5939,12 +5986,15 @@ TEST_F(WebRtcVideoChannelTest, OutboundRtpIsActiveComesFromAnyEncodingInSvc) {
stream->SetStats(stats); stream->SetStats(stats);
// GetStats() and ensure `active` is true if ANY encoding is active. // GetStats() and ensure `active` is true if ANY encoding is active.
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&video_media_info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(video_media_info.senders.size(), 1u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(send_info.senders.size(), 1u);
// Middle layer is active. // Middle layer is active.
ASSERT_TRUE(video_media_info.senders[0].active.has_value()); ASSERT_TRUE(send_info.senders[0].active.has_value());
EXPECT_TRUE(video_media_info.senders[0].active.value()); EXPECT_TRUE(send_info.senders[0].active.value());
parameters = send_channel_->GetRtpSendParameters(kSsrc1); parameters = send_channel_->GetRtpSendParameters(kSsrc1);
ASSERT_EQ(3u, parameters.encodings.size()); ASSERT_EQ(3u, parameters.encodings.size());
@ -5952,11 +6002,13 @@ TEST_F(WebRtcVideoChannelTest, OutboundRtpIsActiveComesFromAnyEncodingInSvc) {
parameters.encodings[1].active = false; parameters.encodings[1].active = false;
parameters.encodings[2].active = false; parameters.encodings[2].active = false;
send_channel_->SetRtpSendParameters(kSsrc1, parameters); send_channel_->SetRtpSendParameters(kSsrc1, parameters);
ASSERT_TRUE(channel_->GetStats(&video_media_info)); EXPECT_TRUE(channel_->GetSendStats(&send_info));
ASSERT_EQ(video_media_info.senders.size(), 1u); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(send_info.senders.size(), 1u);
// No layer is active. // No layer is active.
ASSERT_TRUE(video_media_info.senders[0].active.has_value()); ASSERT_TRUE(send_info.senders[0].active.has_value());
EXPECT_FALSE(video_media_info.senders[0].active.value()); EXPECT_FALSE(send_info.senders[0].active.value());
} }
TEST_F(WebRtcVideoChannelTest, MediaSubstreamMissingProducesEmpyStats) { TEST_F(WebRtcVideoChannelTest, MediaSubstreamMissingProducesEmpyStats) {
@ -5975,9 +6027,12 @@ TEST_F(WebRtcVideoChannelTest, MediaSubstreamMissingProducesEmpyStats) {
substream.referenced_media_ssrc = kMissingMediaSsrc; substream.referenced_media_ssrc = kMissingMediaSsrc;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&video_media_info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(video_media_info.senders.empty()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_TRUE(send_info.senders.empty());
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsUpperResolution) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsUpperResolution) {
@ -5991,18 +6046,21 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsUpperResolution) {
stats.substreams[11].height = 90; stats.substreams[11].height = 90;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(1u, info.aggregated_senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
ASSERT_EQ(3u, info.senders.size()); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(123, info.senders[1].send_frame_width);
EXPECT_EQ(40, info.senders[1].send_frame_height); ASSERT_EQ(1u, send_info.aggregated_senders.size());
EXPECT_EQ(80, info.senders[2].send_frame_width); ASSERT_EQ(3u, send_info.senders.size());
EXPECT_EQ(31, info.senders[2].send_frame_height); EXPECT_EQ(123, send_info.senders[1].send_frame_width);
EXPECT_EQ(20, info.senders[0].send_frame_width); EXPECT_EQ(40, send_info.senders[1].send_frame_height);
EXPECT_EQ(90, info.senders[0].send_frame_height); EXPECT_EQ(80, send_info.senders[2].send_frame_width);
EXPECT_EQ(123, info.aggregated_senders[0].send_frame_width); EXPECT_EQ(31, send_info.senders[2].send_frame_height);
EXPECT_EQ(90, info.aggregated_senders[0].send_frame_height); EXPECT_EQ(20, send_info.senders[0].send_frame_width);
EXPECT_EQ(90, send_info.senders[0].send_frame_height);
EXPECT_EQ(123, send_info.aggregated_senders[0].send_frame_width);
EXPECT_EQ(90, send_info.aggregated_senders[0].send_frame_height);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuAdaptationStats) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuAdaptationStats) {
@ -6012,11 +6070,16 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsCpuAdaptationStats) {
stats.cpu_limited_resolution = true; stats.cpu_limited_resolution = true;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
EXPECT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(1U, info.senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU, info.senders[0].adapt_reason); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.number_of_cpu_adapt_changes, info.senders[0].adapt_changes);
ASSERT_EQ(1U, send_info.senders.size());
EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU,
send_info.senders[0].adapt_reason);
EXPECT_EQ(stats.number_of_cpu_adapt_changes,
send_info.senders[0].adapt_changes);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsReportsAdaptationAndBandwidthStats) { TEST_F(WebRtcVideoChannelTest, GetStatsReportsAdaptationAndBandwidthStats) {
@ -6027,13 +6090,17 @@ TEST_F(WebRtcVideoChannelTest, GetStatsReportsAdaptationAndBandwidthStats) {
stats.bw_limited_resolution = true; stats.bw_limited_resolution = true;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
EXPECT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(1U, info.senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(1U, send_info.senders.size());
EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU | EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_CPU |
WebRtcVideoChannel::ADAPTREASON_BANDWIDTH, WebRtcVideoChannel::ADAPTREASON_BANDWIDTH,
info.senders[0].adapt_reason); send_info.senders[0].adapt_reason);
EXPECT_EQ(stats.number_of_cpu_adapt_changes, info.senders[0].adapt_changes); EXPECT_EQ(stats.number_of_cpu_adapt_changes,
send_info.senders[0].adapt_changes);
} }
TEST(WebRtcVideoChannelHelperTest, MergeInfoAboutOutboundRtpSubstreams) { TEST(WebRtcVideoChannelHelperTest, MergeInfoAboutOutboundRtpSubstreams) {
@ -6198,20 +6265,23 @@ TEST_F(WebRtcVideoChannelTest,
stats.substreams[301].referenced_media_ssrc = 201; stats.substreams[301].referenced_media_ssrc = 201;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(info.senders.size(), 2u); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(15u, info.senders[0].header_and_padding_bytes_sent); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(30u, info.senders[0].payload_bytes_sent);
EXPECT_EQ(4, info.senders[0].packets_sent);
EXPECT_EQ(10u, info.senders[0].retransmitted_bytes_sent);
EXPECT_EQ(1u, info.senders[0].retransmitted_packets_sent);
EXPECT_EQ(45u, info.senders[1].header_and_padding_bytes_sent); EXPECT_EQ(send_info.senders.size(), 2u);
EXPECT_EQ(77u, info.senders[1].payload_bytes_sent); EXPECT_EQ(15u, send_info.senders[0].header_and_padding_bytes_sent);
EXPECT_EQ(16, info.senders[1].packets_sent); EXPECT_EQ(30u, send_info.senders[0].payload_bytes_sent);
EXPECT_EQ(20u, info.senders[1].retransmitted_bytes_sent); EXPECT_EQ(4, send_info.senders[0].packets_sent);
EXPECT_EQ(4u, info.senders[1].retransmitted_packets_sent); EXPECT_EQ(10u, send_info.senders[0].retransmitted_bytes_sent);
EXPECT_EQ(1u, send_info.senders[0].retransmitted_packets_sent);
EXPECT_EQ(45u, send_info.senders[1].header_and_padding_bytes_sent);
EXPECT_EQ(77u, send_info.senders[1].payload_bytes_sent);
EXPECT_EQ(16, send_info.senders[1].packets_sent);
EXPECT_EQ(20u, send_info.senders[1].retransmitted_bytes_sent);
EXPECT_EQ(4u, send_info.senders[1].retransmitted_packets_sent);
} }
TEST_F(WebRtcVideoChannelTest, TEST_F(WebRtcVideoChannelTest,
@ -6221,11 +6291,14 @@ TEST_F(WebRtcVideoChannelTest,
stats.bw_limited_resolution = true; stats.bw_limited_resolution = true;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
EXPECT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(1U, info.senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(1U, send_info.senders.size());
EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_BANDWIDTH, EXPECT_EQ(WebRtcVideoChannel::ADAPTREASON_BANDWIDTH,
info.senders[0].adapt_reason); send_info.senders[0].adapt_reason);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesSendRtcpPacketTypesCorrectly) { TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
@ -6241,19 +6314,22 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesSendRtcpPacketTypesCorrectly) {
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(2, info.senders[0].firs_rcvd); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(3u, info.senders[0].nacks_rcvd); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(4, info.senders[0].plis_rcvd);
EXPECT_EQ(5, info.senders[1].firs_rcvd); EXPECT_EQ(2, send_info.senders[0].firs_rcvd);
EXPECT_EQ(7u, info.senders[1].nacks_rcvd); EXPECT_EQ(3u, send_info.senders[0].nacks_rcvd);
EXPECT_EQ(9, info.senders[1].plis_rcvd); EXPECT_EQ(4, send_info.senders[0].plis_rcvd);
EXPECT_EQ(7, info.aggregated_senders[0].firs_rcvd); EXPECT_EQ(5, send_info.senders[1].firs_rcvd);
EXPECT_EQ(10u, info.aggregated_senders[0].nacks_rcvd); EXPECT_EQ(7u, send_info.senders[1].nacks_rcvd);
EXPECT_EQ(13, info.aggregated_senders[0].plis_rcvd); EXPECT_EQ(9, send_info.senders[1].plis_rcvd);
EXPECT_EQ(7, send_info.aggregated_senders[0].firs_rcvd);
EXPECT_EQ(10u, send_info.aggregated_senders[0].nacks_rcvd);
EXPECT_EQ(13, send_info.aggregated_senders[0].plis_rcvd);
} }
TEST_F(WebRtcVideoChannelTest, TEST_F(WebRtcVideoChannelTest,
@ -6265,14 +6341,19 @@ TEST_F(WebRtcVideoChannelTest,
stats.rtcp_packet_type_counts.pli_packets = 4; stats.rtcp_packet_type_counts.pli_packets = 4;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(stats.rtcp_packet_type_counts.fir_packets, EXPECT_TRUE(channel_->GetSendStats(&send_info));
rtc::checked_cast<unsigned int>(info.receivers[0].firs_sent)); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(
stats.rtcp_packet_type_counts.fir_packets,
rtc::checked_cast<unsigned int>(receive_info.receivers[0].firs_sent));
EXPECT_EQ(stats.rtcp_packet_type_counts.nack_packets, EXPECT_EQ(stats.rtcp_packet_type_counts.nack_packets,
info.receivers[0].nacks_sent); receive_info.receivers[0].nacks_sent);
EXPECT_EQ(stats.rtcp_packet_type_counts.pli_packets, EXPECT_EQ(
rtc::checked_cast<unsigned int>(info.receivers[0].plis_sent)); stats.rtcp_packet_type_counts.pli_packets,
rtc::checked_cast<unsigned int>(receive_info.receivers[0].plis_sent));
} }
TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) { TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
@ -6301,36 +6382,42 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesDecodeStatsCorrectly) {
stats.power_efficient_decoder = true; stats.power_efficient_decoder = true;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.decoder_implementation_name, EXPECT_EQ(stats.decoder_implementation_name,
info.receivers[0].decoder_implementation_name); receive_info.receivers[0].decoder_implementation_name);
EXPECT_EQ(stats.decode_ms, info.receivers[0].decode_ms); EXPECT_EQ(stats.decode_ms, receive_info.receivers[0].decode_ms);
EXPECT_EQ(stats.max_decode_ms, info.receivers[0].max_decode_ms); EXPECT_EQ(stats.max_decode_ms, receive_info.receivers[0].max_decode_ms);
EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms); EXPECT_EQ(stats.current_delay_ms, receive_info.receivers[0].current_delay_ms);
EXPECT_EQ(stats.target_delay_ms, info.receivers[0].target_delay_ms); EXPECT_EQ(stats.target_delay_ms, receive_info.receivers[0].target_delay_ms);
EXPECT_EQ(stats.jitter_buffer_ms, info.receivers[0].jitter_buffer_ms); EXPECT_EQ(stats.jitter_buffer_ms, receive_info.receivers[0].jitter_buffer_ms);
EXPECT_EQ(stats.jitter_buffer_delay_seconds, EXPECT_EQ(stats.jitter_buffer_delay_seconds,
info.receivers[0].jitter_buffer_delay_seconds); receive_info.receivers[0].jitter_buffer_delay_seconds);
EXPECT_EQ(stats.jitter_buffer_emitted_count, EXPECT_EQ(stats.jitter_buffer_emitted_count,
info.receivers[0].jitter_buffer_emitted_count); receive_info.receivers[0].jitter_buffer_emitted_count);
EXPECT_EQ(stats.min_playout_delay_ms, info.receivers[0].min_playout_delay_ms); EXPECT_EQ(stats.min_playout_delay_ms,
EXPECT_EQ(stats.render_delay_ms, info.receivers[0].render_delay_ms); receive_info.receivers[0].min_playout_delay_ms);
EXPECT_EQ(stats.width, info.receivers[0].frame_width); EXPECT_EQ(stats.render_delay_ms, receive_info.receivers[0].render_delay_ms);
EXPECT_EQ(stats.height, info.receivers[0].frame_height); EXPECT_EQ(stats.width, receive_info.receivers[0].frame_width);
EXPECT_EQ(stats.height, receive_info.receivers[0].frame_height);
EXPECT_EQ(rtc::checked_cast<unsigned int>(stats.frame_counts.key_frames + EXPECT_EQ(rtc::checked_cast<unsigned int>(stats.frame_counts.key_frames +
stats.frame_counts.delta_frames), stats.frame_counts.delta_frames),
info.receivers[0].frames_received); receive_info.receivers[0].frames_received);
EXPECT_EQ(stats.frames_rendered, info.receivers[0].frames_rendered); EXPECT_EQ(stats.frames_rendered, receive_info.receivers[0].frames_rendered);
EXPECT_EQ(stats.frames_decoded, info.receivers[0].frames_decoded); EXPECT_EQ(stats.frames_decoded, receive_info.receivers[0].frames_decoded);
EXPECT_EQ(rtc::checked_cast<unsigned int>(stats.frame_counts.key_frames), EXPECT_EQ(rtc::checked_cast<unsigned int>(stats.frame_counts.key_frames),
info.receivers[0].key_frames_decoded); receive_info.receivers[0].key_frames_decoded);
EXPECT_EQ(stats.qp_sum, info.receivers[0].qp_sum); EXPECT_EQ(stats.qp_sum, receive_info.receivers[0].qp_sum);
EXPECT_EQ(stats.total_decode_time, info.receivers[0].total_decode_time); EXPECT_EQ(stats.total_decode_time,
EXPECT_EQ(stats.total_assembly_time, info.receivers[0].total_assembly_time); receive_info.receivers[0].total_decode_time);
EXPECT_EQ(stats.total_assembly_time,
receive_info.receivers[0].total_assembly_time);
EXPECT_EQ(stats.frames_assembled_from_multiple_packets, EXPECT_EQ(stats.frames_assembled_from_multiple_packets,
info.receivers[0].frames_assembled_from_multiple_packets); receive_info.receivers[0].frames_assembled_from_multiple_packets);
EXPECT_TRUE(info.receivers[0].power_efficient_decoder); EXPECT_TRUE(receive_info.receivers[0].power_efficient_decoder);
} }
TEST_F(WebRtcVideoChannelTest, TEST_F(WebRtcVideoChannelTest,
@ -6341,12 +6428,15 @@ TEST_F(WebRtcVideoChannelTest,
stats.total_squared_inter_frame_delay = 0.00456; stats.total_squared_inter_frame_delay = 0.00456;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.total_inter_frame_delay, EXPECT_EQ(stats.total_inter_frame_delay,
info.receivers[0].total_inter_frame_delay); receive_info.receivers[0].total_inter_frame_delay);
EXPECT_EQ(stats.total_squared_inter_frame_delay, EXPECT_EQ(stats.total_squared_inter_frame_delay,
info.receivers[0].total_squared_inter_frame_delay); receive_info.receivers[0].total_squared_inter_frame_delay);
} }
TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesReceivePacketStatsCorrectly) { TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesReceivePacketStatsCorrectly) {
@ -6359,13 +6449,19 @@ TEST_F(WebRtcVideoChannelTest, GetStatsTranslatesReceivePacketStatsCorrectly) {
stats.rtp_stats.packets_lost = 6; stats.rtp_stats.packets_lost = 6;
stream->SetStats(stats); stream->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_EQ(stats.rtp_stats.packet_counter.payload_bytes, EXPECT_TRUE(channel_->GetSendStats(&send_info));
rtc::checked_cast<size_t>(info.receivers[0].payload_bytes_rcvd)); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.rtp_stats.packet_counter.packets,
rtc::checked_cast<unsigned int>(info.receivers[0].packets_rcvd)); EXPECT_EQ(
EXPECT_EQ(stats.rtp_stats.packets_lost, info.receivers[0].packets_lost); stats.rtp_stats.packet_counter.payload_bytes,
rtc::checked_cast<size_t>(receive_info.receivers[0].payload_bytes_rcvd));
EXPECT_EQ(
stats.rtp_stats.packet_counter.packets,
rtc::checked_cast<unsigned int>(receive_info.receivers[0].packets_rcvd));
EXPECT_EQ(stats.rtp_stats.packets_lost,
receive_info.receivers[0].packets_lost);
} }
TEST_F(WebRtcVideoChannelTest, TranslatesCallStatsCorrectly) { TEST_F(WebRtcVideoChannelTest, TranslatesCallStatsCorrectly) {
@ -6375,11 +6471,14 @@ TEST_F(WebRtcVideoChannelTest, TranslatesCallStatsCorrectly) {
stats.rtt_ms = 123; stats.rtt_ms = 123;
fake_call_->SetStats(stats); fake_call_->SetStats(stats);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(2u, info.senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_EQ(stats.rtt_ms, info.senders[0].rtt_ms); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_EQ(stats.rtt_ms, info.senders[1].rtt_ms);
ASSERT_EQ(2u, send_info.senders.size());
EXPECT_EQ(stats.rtt_ms, send_info.senders[0].rtt_ms);
EXPECT_EQ(stats.rtt_ms, send_info.senders[1].rtt_ms);
} }
TEST_F(WebRtcVideoChannelTest, TranslatesSenderBitrateStatsCorrectly) { TEST_F(WebRtcVideoChannelTest, TranslatesSenderBitrateStatsCorrectly) {
@ -6403,18 +6502,21 @@ TEST_F(WebRtcVideoChannelTest, TranslatesSenderBitrateStatsCorrectly) {
stats2.substreams[21].retransmit_bitrate_bps = 8; stats2.substreams[21].retransmit_bitrate_bps = 8;
stream2->SetStats(stats2); stream2->SetStats(stats2);
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
ASSERT_EQ(2u, info.aggregated_senders.size()); EXPECT_TRUE(channel_->GetSendStats(&send_info));
ASSERT_EQ(4u, info.senders.size()); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(2u, send_info.aggregated_senders.size());
ASSERT_EQ(4u, send_info.senders.size());
BandwidthEstimationInfo bwe_info; BandwidthEstimationInfo bwe_info;
channel_->FillBitrateInfo(&bwe_info); channel_->FillBitrateInfo(&bwe_info);
// Assuming stream and stream2 corresponds to senders[0] and [1] respectively // Assuming stream and stream2 corresponds to senders[0] and [1] respectively
// is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs. // is OK as std::maps are sorted and AddSendStream() gives increasing SSRCs.
EXPECT_EQ(stats.media_bitrate_bps, EXPECT_EQ(stats.media_bitrate_bps,
info.aggregated_senders[0].nominal_bitrate); send_info.aggregated_senders[0].nominal_bitrate);
EXPECT_EQ(stats2.media_bitrate_bps, EXPECT_EQ(stats2.media_bitrate_bps,
info.aggregated_senders[1].nominal_bitrate); send_info.aggregated_senders[1].nominal_bitrate);
EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps, EXPECT_EQ(stats.target_media_bitrate_bps + stats2.target_media_bitrate_bps,
bwe_info.target_enc_bitrate); bwe_info.target_enc_bitrate);
EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps, EXPECT_EQ(stats.media_bitrate_bps + stats2.media_bitrate_bps,
@ -6540,38 +6642,47 @@ TEST_F(WebRtcVideoChannelTest, ReportsSsrcGroupsInStats) {
"cname", MAKE_VECTOR(kReceiverSsrcs), MAKE_VECTOR(kReceiverRtxSsrcs)); "cname", MAKE_VECTOR(kReceiverSsrcs), MAKE_VECTOR(kReceiverRtxSsrcs));
EXPECT_TRUE(receive_channel_->AddRecvStream(receiver_sp)); EXPECT_TRUE(receive_channel_->AddRecvStream(receiver_sp));
cricket::VideoMediaInfo info; cricket::VideoMediaSendInfo send_info;
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
ASSERT_EQ(1u, info.senders.size()); ASSERT_EQ(1u, send_info.senders.size());
ASSERT_EQ(1u, info.receivers.size()); ASSERT_EQ(1u, receive_info.receivers.size());
EXPECT_NE(sender_sp.ssrc_groups, receiver_sp.ssrc_groups); EXPECT_NE(sender_sp.ssrc_groups, receiver_sp.ssrc_groups);
EXPECT_EQ(sender_sp.ssrc_groups, info.senders[0].ssrc_groups); EXPECT_EQ(sender_sp.ssrc_groups, send_info.senders[0].ssrc_groups);
EXPECT_EQ(receiver_sp.ssrc_groups, info.receivers[0].ssrc_groups); EXPECT_EQ(receiver_sp.ssrc_groups, receive_info.receivers[0].ssrc_groups);
} }
TEST_F(WebRtcVideoChannelTest, MapsReceivedPayloadTypeToCodecName) { TEST_F(WebRtcVideoChannelTest, MapsReceivedPayloadTypeToCodecName) {
FakeVideoReceiveStream* stream = AddRecvStream(); FakeVideoReceiveStream* stream = AddRecvStream();
webrtc::VideoReceiveStreamInterface::Stats stats; webrtc::VideoReceiveStreamInterface::Stats stats;
cricket::VideoMediaInfo info;
// Report no codec name before receiving. // Report no codec name before receiving.
stream->SetStats(stats); stream->SetStats(stats);
ASSERT_TRUE(channel_->GetStats(&info)); cricket::VideoMediaSendInfo send_info;
EXPECT_STREQ("", info.receivers[0].codec_name.c_str()); cricket::VideoMediaReceiveInfo receive_info;
EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_STREQ("", receive_info.receivers[0].codec_name.c_str());
// Report VP8 if we're receiving it. // Report VP8 if we're receiving it.
stats.current_payload_type = GetEngineCodec("VP8").id; stats.current_payload_type = GetEngineCodec("VP8").id;
stream->SetStats(stats); stream->SetStats(stats);
ASSERT_TRUE(channel_->GetStats(&info)); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_STREQ(kVp8CodecName, info.receivers[0].codec_name.c_str()); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_STREQ(kVp8CodecName, receive_info.receivers[0].codec_name.c_str());
// Report no codec name for unknown playload types. // Report no codec name for unknown playload types.
stats.current_payload_type = 3; stats.current_payload_type = 3;
stream->SetStats(stats); stream->SetStats(stats);
ASSERT_TRUE(channel_->GetStats(&info)); EXPECT_TRUE(channel_->GetSendStats(&send_info));
EXPECT_STREQ("", info.receivers[0].codec_name.c_str()); EXPECT_TRUE(channel_->GetReceiveStats(&receive_info));
EXPECT_STREQ("", receive_info.receivers[0].codec_name.c_str());
} }
// Tests that when we add a stream without SSRCs, but contains a stream_id // Tests that when we add a stream without SSRCs, but contains a stream_id

View File

@ -2262,9 +2262,8 @@ void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
ready ? webrtc::kNetworkUp : webrtc::kNetworkDown); ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
} }
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info, bool WebRtcVoiceMediaChannel::GetSendStats(VoiceMediaSendInfo* info) {
bool get_and_clear_legacy_stats) { TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetSendStats");
TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
RTC_DCHECK_RUN_ON(worker_thread_); RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK(info); RTC_DCHECK(info);
@ -2304,6 +2303,21 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info,
info->senders.push_back(sinfo); info->senders.push_back(sinfo);
} }
// Get codec info
for (const AudioCodec& codec : send_codecs_) {
webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
info->send_codecs.insert(
std::make_pair(codec_params.payload_type, std::move(codec_params)));
}
return true;
}
bool WebRtcVoiceMediaChannel::GetReceiveStats(VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) {
TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetReceiveStats");
RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK(info);
// Get SSRC and stats for each receiver. // Get SSRC and stats for each receiver.
RTC_DCHECK_EQ(info->receivers.size(), 0U); RTC_DCHECK_EQ(info->receivers.size(), 0U);
for (const auto& stream : recv_streams_) { for (const auto& stream : recv_streams_) {
@ -2403,11 +2417,6 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info,
} }
// Get codec info // Get codec info
for (const AudioCodec& codec : send_codecs_) {
webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
info->send_codecs.insert(
std::make_pair(codec_params.payload_type, std::move(codec_params)));
}
for (const AudioCodec& codec : recv_codecs_) { for (const AudioCodec& codec : recv_codecs_) {
webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters(); webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
info->receive_codecs.insert( info->receive_codecs.insert(

View File

@ -207,7 +207,9 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
void OnNetworkRouteChanged(absl::string_view transport_name, void OnNetworkRouteChanged(absl::string_view transport_name,
const rtc::NetworkRoute& network_route) override; const rtc::NetworkRoute& network_route) override;
void OnReadyToSend(bool ready) override; void OnReadyToSend(bool ready) override;
bool GetStats(VoiceMediaInfo* info, bool get_and_clear_legacy_stats) override; bool GetSendStats(VoiceMediaSendInfo* info) override;
bool GetReceiveStats(VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) override;
// Set the audio sink for an existing stream. // Set the audio sink for an existing stream.
void SetRawAudioSink( void SetRawAudioSink(

View File

@ -753,17 +753,20 @@ class WebRtcVoiceEngineTestFake : public ::testing::TestWithParam<bool> {
EXPECT_EQ(info.decoding_muted_output, stats.decoding_muted_output); EXPECT_EQ(info.decoding_muted_output, stats.decoding_muted_output);
EXPECT_EQ(info.capture_start_ntp_time_ms, stats.capture_start_ntp_time_ms); EXPECT_EQ(info.capture_start_ntp_time_ms, stats.capture_start_ntp_time_ms);
} }
void VerifyVoiceSendRecvCodecs(const cricket::VoiceMediaInfo& info) const { void VerifyVoiceSendRecvCodecs(
EXPECT_EQ(send_parameters_.codecs.size(), info.send_codecs.size()); const cricket::VoiceMediaSendInfo& send_info,
const cricket::VoiceMediaReceiveInfo& receive_info) const {
EXPECT_EQ(send_parameters_.codecs.size(), send_info.send_codecs.size());
for (const cricket::AudioCodec& codec : send_parameters_.codecs) { for (const cricket::AudioCodec& codec : send_parameters_.codecs) {
ASSERT_EQ(info.send_codecs.count(codec.id), 1U); ASSERT_EQ(send_info.send_codecs.count(codec.id), 1U);
EXPECT_EQ(info.send_codecs.find(codec.id)->second, EXPECT_EQ(send_info.send_codecs.find(codec.id)->second,
codec.ToCodecParameters()); codec.ToCodecParameters());
} }
EXPECT_EQ(recv_parameters_.codecs.size(), info.receive_codecs.size()); EXPECT_EQ(recv_parameters_.codecs.size(),
receive_info.receive_codecs.size());
for (const cricket::AudioCodec& codec : recv_parameters_.codecs) { for (const cricket::AudioCodec& codec : recv_parameters_.codecs) {
ASSERT_EQ(info.receive_codecs.count(codec.id), 1U); ASSERT_EQ(receive_info.receive_codecs.count(codec.id), 1U);
EXPECT_EQ(info.receive_codecs.find(codec.id)->second, EXPECT_EQ(receive_info.receive_codecs.find(codec.id)->second,
codec.ToCodecParameters()); codec.ToCodecParameters());
} }
} }
@ -2321,46 +2324,55 @@ TEST_P(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
// Check stats for the added streams. // Check stats for the added streams.
{ {
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
cricket::VoiceMediaInfo info; cricket::VoiceMediaSendInfo send_info;
EXPECT_EQ(true, cricket::VoiceMediaReceiveInfo receive_info;
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); EXPECT_EQ(true, channel_->GetSendStats(&send_info));
EXPECT_EQ(true, channel_->GetReceiveStats(
&receive_info, /*get_and_clear_legacy_stats=*/true));
// We have added 4 send streams. We should see empty stats for all. // We have added 4 send streams. We should see empty stats for all.
EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size()); EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)),
for (const auto& sender : info.senders) { send_info.senders.size());
for (const auto& sender : send_info.senders) {
VerifyVoiceSenderInfo(sender, false); VerifyVoiceSenderInfo(sender, false);
} }
VerifyVoiceSendRecvCodecs(info); VerifyVoiceSendRecvCodecs(send_info, receive_info);
// We have added one receive stream. We should see empty stats. // We have added one receive stream. We should see empty stats.
EXPECT_EQ(info.receivers.size(), 1u); EXPECT_EQ(receive_info.receivers.size(), 1u);
EXPECT_EQ(info.receivers[0].ssrc(), 0u); EXPECT_EQ(receive_info.receivers[0].ssrc(), 0u);
} }
// Remove the kSsrcY stream. No receiver stats. // Remove the kSsrcY stream. No receiver stats.
{ {
cricket::VoiceMediaInfo info; cricket::VoiceMediaReceiveInfo receive_info;
cricket::VoiceMediaSendInfo send_info;
EXPECT_TRUE(receive_channel_->RemoveRecvStream(kSsrcY)); EXPECT_TRUE(receive_channel_->RemoveRecvStream(kSsrcY));
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
EXPECT_EQ(true, EXPECT_EQ(true, channel_->GetSendStats(&send_info));
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); EXPECT_EQ(true, channel_->GetReceiveStats(
EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size()); &receive_info, /*get_and_clear_legacy_stats=*/true));
EXPECT_EQ(0u, info.receivers.size()); EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)),
send_info.senders.size());
EXPECT_EQ(0u, receive_info.receivers.size());
} }
// Deliver a new packet - a default receive stream should be created and we // Deliver a new packet - a default receive stream should be created and we
// should see stats again. // should see stats again.
{ {
cricket::VoiceMediaInfo info; cricket::VoiceMediaSendInfo send_info;
cricket::VoiceMediaReceiveInfo receive_info;
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
SetAudioReceiveStreamStats(); SetAudioReceiveStreamStats();
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
EXPECT_EQ(true, EXPECT_EQ(true, channel_->GetSendStats(&send_info));
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); EXPECT_EQ(true, channel_->GetReceiveStats(
EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size()); &receive_info, /*get_and_clear_legacy_stats=*/true));
EXPECT_EQ(1u, info.receivers.size()); EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)),
VerifyVoiceReceiverInfo(info.receivers[0]); send_info.senders.size());
VerifyVoiceSendRecvCodecs(info); EXPECT_EQ(1u, receive_info.receivers.size());
VerifyVoiceReceiverInfo(receive_info.receivers[0]);
VerifyVoiceSendRecvCodecs(send_info, receive_info);
} }
} }
@ -2466,53 +2478,61 @@ TEST_P(WebRtcVoiceEngineTestFake, GetStats) {
// Check stats for the added streams. // Check stats for the added streams.
{ {
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
cricket::VoiceMediaInfo info; cricket::VoiceMediaSendInfo send_info;
EXPECT_EQ(true, cricket::VoiceMediaReceiveInfo receive_info;
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); EXPECT_EQ(true, channel_->GetSendStats(&send_info));
EXPECT_EQ(true, channel_->GetReceiveStats(
&receive_info, /*get_and_clear_legacy_stats=*/true));
// We have added one send stream. We should see the stats we've set. // We have added one send stream. We should see the stats we've set.
EXPECT_EQ(1u, info.senders.size()); EXPECT_EQ(1u, send_info.senders.size());
VerifyVoiceSenderInfo(info.senders[0], false); VerifyVoiceSenderInfo(send_info.senders[0], false);
// We have added one receive stream. We should see empty stats. // We have added one receive stream. We should see empty stats.
EXPECT_EQ(info.receivers.size(), 1u); EXPECT_EQ(receive_info.receivers.size(), 1u);
EXPECT_EQ(info.receivers[0].ssrc(), 0u); EXPECT_EQ(receive_info.receivers[0].ssrc(), 0u);
} }
// Start sending - this affects some reported stats. // Start sending - this affects some reported stats.
{ {
cricket::VoiceMediaInfo info;
SetSend(true); SetSend(true);
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
EXPECT_EQ(true, cricket::VoiceMediaSendInfo send_info;
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); cricket::VoiceMediaReceiveInfo receive_info;
VerifyVoiceSenderInfo(info.senders[0], true); EXPECT_EQ(true, channel_->GetSendStats(&send_info));
VerifyVoiceSendRecvCodecs(info); EXPECT_EQ(true, channel_->GetReceiveStats(
&receive_info, /*get_and_clear_legacy_stats=*/true));
VerifyVoiceSenderInfo(send_info.senders[0], true);
VerifyVoiceSendRecvCodecs(send_info, receive_info);
} }
// Remove the kSsrcY stream. No receiver stats. // Remove the kSsrcY stream. No receiver stats.
{ {
cricket::VoiceMediaInfo info;
EXPECT_TRUE(receive_channel_->RemoveRecvStream(kSsrcY)); EXPECT_TRUE(receive_channel_->RemoveRecvStream(kSsrcY));
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
EXPECT_EQ(true, cricket::VoiceMediaSendInfo send_info;
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); cricket::VoiceMediaReceiveInfo receive_info;
EXPECT_EQ(1u, info.senders.size()); EXPECT_EQ(true, channel_->GetSendStats(&send_info));
EXPECT_EQ(0u, info.receivers.size()); EXPECT_EQ(true, channel_->GetReceiveStats(
&receive_info, /*get_and_clear_legacy_stats=*/true));
EXPECT_EQ(1u, send_info.senders.size());
EXPECT_EQ(0u, receive_info.receivers.size());
} }
// Deliver a new packet - a default receive stream should be created and we // Deliver a new packet - a default receive stream should be created and we
// should see stats again. // should see stats again.
{ {
cricket::VoiceMediaInfo info;
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
SetAudioReceiveStreamStats(); SetAudioReceiveStreamStats();
EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0)); EXPECT_CALL(*adm_, GetPlayoutUnderrunCount()).WillOnce(Return(0));
EXPECT_EQ(true, cricket::VoiceMediaSendInfo send_info;
channel_->GetStats(&info, /*get_and_clear_legacy_stats=*/true)); cricket::VoiceMediaReceiveInfo receive_info;
EXPECT_EQ(1u, info.senders.size()); EXPECT_EQ(true, channel_->GetSendStats(&send_info));
EXPECT_EQ(1u, info.receivers.size()); EXPECT_EQ(true, channel_->GetReceiveStats(
VerifyVoiceReceiverInfo(info.receivers[0]); &receive_info, /*get_and_clear_legacy_stats=*/true));
VerifyVoiceSendRecvCodecs(info); EXPECT_EQ(1u, send_info.senders.size());
EXPECT_EQ(1u, receive_info.receivers.size());
VerifyVoiceReceiverInfo(receive_info.receivers[0]);
VerifyVoiceSendRecvCodecs(send_info, receive_info);
} }
} }

View File

@ -65,6 +65,8 @@ namespace cricket {
// and methods with _s suffix on signaling thread. // and methods with _s suffix on signaling thread.
// Network and worker threads may be the same thread. // Network and worker threads may be the same thread.
// //
class VideoChannel;
class VoiceChannel;
class BaseChannel : public ChannelInterface, class BaseChannel : public ChannelInterface,
// TODO(tommi): Remove has_slots inheritance. // TODO(tommi): Remove has_slots inheritance.
@ -375,6 +377,12 @@ class VoiceChannel : public BaseChannel {
rtc::UniqueRandomIdGenerator* ssrc_generator); rtc::UniqueRandomIdGenerator* ssrc_generator);
~VoiceChannel(); ~VoiceChannel();
VideoChannel* AsVideoChannel() override {
RTC_CHECK_NOTREACHED();
return nullptr;
}
VoiceChannel* AsVoiceChannel() override { return this; }
VoiceMediaSendChannelInterface* media_send_channel() override { VoiceMediaSendChannelInterface* media_send_channel() override {
return &send_channel_; return &send_channel_;
} }
@ -430,22 +438,26 @@ class VideoChannel : public BaseChannel {
rtc::UniqueRandomIdGenerator* ssrc_generator); rtc::UniqueRandomIdGenerator* ssrc_generator);
~VideoChannel(); ~VideoChannel();
// downcasts a MediaChannel VideoChannel* AsVideoChannel() override { return this; }
VoiceChannel* AsVoiceChannel() override {
RTC_CHECK_NOTREACHED();
return nullptr;
}
VideoMediaSendChannelInterface* media_send_channel() override { VideoMediaSendChannelInterface* media_send_channel() override {
return media_channel()->AsVideoChannel()->AsVideoSendChannel(); return &send_channel_;
} }
VideoMediaSendChannelInterface* video_media_send_channel() override { VideoMediaSendChannelInterface* video_media_send_channel() override {
return media_send_channel(); return &send_channel_;
} }
// downcasts a MediaChannel
VideoMediaReceiveChannelInterface* media_receive_channel() override { VideoMediaReceiveChannelInterface* media_receive_channel() override {
return media_channel()->AsVideoChannel()->AsVideoReceiveChannel(); return &receive_channel_;
} }
VideoMediaReceiveChannelInterface* video_media_receive_channel() override { VideoMediaReceiveChannelInterface* video_media_receive_channel() override {
return media_receive_channel(); return &receive_channel_;
} }
cricket::MediaType media_type() const override { cricket::MediaType media_type() const override {

View File

@ -29,6 +29,8 @@ class VideoBitrateAllocatorFactory;
namespace cricket { namespace cricket {
class MediaChannel; class MediaChannel;
class VoiceChannel;
class VideoChannel;
class MediaContentDescription; class MediaContentDescription;
struct MediaConfig; struct MediaConfig;
@ -48,6 +50,9 @@ class ChannelInterface {
virtual ~ChannelInterface() = default; virtual ~ChannelInterface() = default;
virtual cricket::MediaType media_type() const = 0; virtual cricket::MediaType media_type() const = 0;
virtual VideoChannel* AsVideoChannel() = 0;
virtual VoiceChannel* AsVoiceChannel() = 0;
// Temporary fix while MediaChannel is being reconstructed // Temporary fix while MediaChannel is being reconstructed
virtual MediaChannel* media_channel() = 0; virtual MediaChannel* media_channel() = 0;
virtual MediaSendChannelInterface* media_send_channel() = 0; virtual MediaSendChannelInterface* media_send_channel() = 0;

View File

@ -38,6 +38,7 @@
#include "modules/audio_processing/include/audio_processing_statistics.h" #include "modules/audio_processing/include/audio_processing_statistics.h"
#include "p2p/base/ice_transport_internal.h" #include "p2p/base/ice_transport_internal.h"
#include "p2p/base/p2p_constants.h" #include "p2p/base/p2p_constants.h"
#include "pc/channel.h"
#include "pc/channel_interface.h" #include "pc/channel_interface.h"
#include "pc/data_channel_utils.h" #include "pc/data_channel_utils.h"
#include "pc/rtp_receiver.h" #include "pc/rtp_receiver.h"
@ -1036,15 +1037,14 @@ void LegacyStatsCollector::ExtractBweInfo() {
// Fill in target encoder bitrate, actual encoder bitrate, rtx bitrate, etc. // Fill in target encoder bitrate, actual encoder bitrate, rtx bitrate, etc.
// TODO(holmer): Also fill this in for audio. // TODO(holmer): Also fill this in for audio.
auto transceivers = pc_->GetTransceiversInternal(); auto transceivers = pc_->GetTransceiversInternal();
std::vector<cricket::VideoMediaChannel*> video_media_channels; std::vector<cricket::VideoMediaSendChannelInterface*> video_media_channels;
for (const auto& transceiver : transceivers) { for (const auto& transceiver : transceivers) {
if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO) { if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO) {
continue; continue;
} }
auto* video_channel = transceiver->internal()->channel(); auto* video_channel = transceiver->internal()->channel();
if (video_channel) { if (video_channel) {
video_media_channels.push_back(static_cast<cricket::VideoMediaChannel*>( video_media_channels.push_back(video_channel->video_media_send_channel());
video_channel->video_media_send_channel()));
} }
} }
@ -1063,9 +1063,9 @@ void LegacyStatsCollector::ExtractBweInfo() {
namespace { namespace {
class MediaChannelStatsGatherer { class ChannelStatsGatherer {
public: public:
virtual ~MediaChannelStatsGatherer() = default; virtual ~ChannelStatsGatherer() = default;
virtual bool GetStatsOnWorkerThread() = 0; virtual bool GetStatsOnWorkerThread() = 0;
@ -1094,17 +1094,26 @@ class MediaChannelStatsGatherer {
} }
}; };
class VoiceMediaChannelStatsGatherer final : public MediaChannelStatsGatherer { class VoiceChannelStatsGatherer final : public ChannelStatsGatherer {
public: public:
VoiceMediaChannelStatsGatherer( explicit VoiceChannelStatsGatherer(cricket::VoiceChannel* voice_channel)
cricket::VoiceMediaChannel* voice_media_channel) : voice_channel_(voice_channel) {
: voice_media_channel_(voice_media_channel) { RTC_DCHECK(voice_channel_);
RTC_DCHECK(voice_media_channel_);
} }
bool GetStatsOnWorkerThread() override { bool GetStatsOnWorkerThread() override {
return voice_media_channel_->GetStats(&voice_media_info, cricket::VoiceMediaSendInfo send_info;
/*get_and_clear_legacy_stats=*/true); cricket::VoiceMediaReceiveInfo receive_info;
bool success =
voice_channel_->voice_media_send_channel()->GetStats(&send_info);
success &= voice_channel_->voice_media_receive_channel()->GetStats(
&receive_info,
/*get_and_clear_legacy_stats=*/true);
if (success) {
voice_media_info = cricket::VoiceMediaInfo(std::move(send_info),
std::move(receive_info));
}
return success;
} }
void ExtractStats(LegacyStatsCollector* collector) const override { void ExtractStats(LegacyStatsCollector* collector) const override {
@ -1123,20 +1132,29 @@ class VoiceMediaChannelStatsGatherer final : public MediaChannelStatsGatherer {
} }
private: private:
cricket::VoiceMediaChannel* voice_media_channel_; cricket::VoiceChannel* voice_channel_;
cricket::VoiceMediaInfo voice_media_info; cricket::VoiceMediaInfo voice_media_info;
}; };
class VideoMediaChannelStatsGatherer final : public MediaChannelStatsGatherer { class VideoChannelStatsGatherer final : public ChannelStatsGatherer {
public: public:
VideoMediaChannelStatsGatherer( explicit VideoChannelStatsGatherer(cricket::VideoChannel* video_channel)
cricket::VideoMediaChannel* video_media_channel) : video_channel_(video_channel) {
: video_media_channel_(video_media_channel) { RTC_DCHECK(video_channel_);
RTC_DCHECK(video_media_channel_);
} }
bool GetStatsOnWorkerThread() override { bool GetStatsOnWorkerThread() override {
return video_media_channel_->GetStats(&video_media_info); cricket::VideoMediaSendInfo send_info;
cricket::VideoMediaReceiveInfo receive_info;
bool success =
video_channel_->video_media_send_channel()->GetStats(&send_info);
success &=
video_channel_->video_media_receive_channel()->GetStats(&receive_info);
if (success) {
video_media_info = cricket::VideoMediaInfo(std::move(send_info),
std::move(receive_info));
}
return success;
} }
void ExtractStats(LegacyStatsCollector* collector) const override { void ExtractStats(LegacyStatsCollector* collector) const override {
@ -1147,19 +1165,19 @@ class VideoMediaChannelStatsGatherer final : public MediaChannelStatsGatherer {
bool HasRemoteAudio() const override { return false; } bool HasRemoteAudio() const override { return false; }
private: private:
cricket::VideoMediaChannel* video_media_channel_; cricket::VideoChannel* video_channel_;
cricket::VideoMediaInfo video_media_info; cricket::VideoMediaInfo video_media_info;
}; };
std::unique_ptr<MediaChannelStatsGatherer> CreateMediaChannelStatsGatherer( std::unique_ptr<ChannelStatsGatherer> CreateChannelStatsGatherer(
cricket::MediaChannel* channel) { cricket::ChannelInterface* channel) {
RTC_DCHECK(channel); RTC_DCHECK(channel);
if (channel->media_type() == cricket::MEDIA_TYPE_AUDIO) { if (channel->media_type() == cricket::MEDIA_TYPE_AUDIO) {
return std::make_unique<VoiceMediaChannelStatsGatherer>( return std::make_unique<VoiceChannelStatsGatherer>(
channel->AsVoiceChannel()); channel->AsVoiceChannel());
} else { } else {
RTC_DCHECK_EQ(channel->media_type(), cricket::MEDIA_TYPE_VIDEO); RTC_DCHECK_EQ(channel->media_type(), cricket::MEDIA_TYPE_VIDEO);
return std::make_unique<VideoMediaChannelStatsGatherer>( return std::make_unique<VideoChannelStatsGatherer>(
channel->AsVideoChannel()); channel->AsVideoChannel());
} }
} }
@ -1170,7 +1188,7 @@ void LegacyStatsCollector::ExtractMediaInfo(
const std::map<std::string, std::string>& transport_names_by_mid) { const std::map<std::string, std::string>& transport_names_by_mid) {
RTC_DCHECK_RUN_ON(pc_->signaling_thread()); RTC_DCHECK_RUN_ON(pc_->signaling_thread());
std::vector<std::unique_ptr<MediaChannelStatsGatherer>> gatherers; std::vector<std::unique_ptr<ChannelStatsGatherer>> gatherers;
auto transceivers = pc_->GetTransceiversInternal(); auto transceivers = pc_->GetTransceiversInternal();
{ {
@ -1180,8 +1198,8 @@ void LegacyStatsCollector::ExtractMediaInfo(
if (!channel) { if (!channel) {
continue; continue;
} }
std::unique_ptr<MediaChannelStatsGatherer> gatherer = std::unique_ptr<ChannelStatsGatherer> gatherer =
CreateMediaChannelStatsGatherer(channel->media_channel()); CreateChannelStatsGatherer(channel);
gatherer->mid = channel->mid(); gatherer->mid = channel->mid();
gatherer->transport_name = transport_names_by_mid.at(gatherer->mid); gatherer->transport_name = transport_names_by_mid.at(gatherer->mid);
@ -1208,7 +1226,7 @@ void LegacyStatsCollector::ExtractMediaInfo(
cricket::ChannelInterface* channel = transceiver->internal()->channel(); cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (!channel) if (!channel)
continue; continue;
MediaChannelStatsGatherer* gatherer = gatherers[i++].get(); ChannelStatsGatherer* gatherer = gatherers[i++].get();
RTC_DCHECK_EQ(gatherer->mid, channel->mid()); RTC_DCHECK_EQ(gatherer->mid, channel->mid());
for (const auto& receiver : transceiver->internal()->receivers()) { for (const auto& receiver : transceiver->internal()->receivers()) {
@ -1219,7 +1237,7 @@ void LegacyStatsCollector::ExtractMediaInfo(
for (auto it = gatherers.begin(); it != gatherers.end(); for (auto it = gatherers.begin(); it != gatherers.end();
/* incremented manually */) { /* incremented manually */) {
MediaChannelStatsGatherer* gatherer = it->get(); ChannelStatsGatherer* gatherer = it->get();
if (!gatherer->GetStatsOnWorkerThread()) { if (!gatherer->GetStatsOnWorkerThread()) {
RTC_LOG(LS_ERROR) << "Failed to get media channel stats for mid=" RTC_LOG(LS_ERROR) << "Failed to get media channel stats for mid="
<< gatherer->mid; << gatherer->mid;

View File

@ -2333,15 +2333,24 @@ void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() {
transceiver_stats_infos_.clear(); transceiver_stats_infos_.clear();
// These are used to invoke GetStats for all the media channels together in // These are used to invoke GetStats for all the media channels together in
// one worker thread hop. // one worker thread hop.
std::map<cricket::VoiceMediaChannel*, cricket::VoiceMediaInfo> voice_stats; std::map<cricket::VoiceMediaSendChannelInterface*,
std::map<cricket::VideoMediaChannel*, cricket::VideoMediaInfo> video_stats; cricket::VoiceMediaSendInfo>
voice_send_stats;
std::map<cricket::VideoMediaSendChannelInterface*,
cricket::VideoMediaSendInfo>
video_send_stats;
std::map<cricket::VoiceMediaReceiveChannelInterface*,
cricket::VoiceMediaReceiveInfo>
voice_receive_stats;
std::map<cricket::VideoMediaReceiveChannelInterface*,
cricket::VideoMediaReceiveInfo>
video_receive_stats;
auto transceivers = pc_->GetTransceiversInternal(); auto transceivers = pc_->GetTransceiversInternal();
// TODO(tommi): See if we can avoid synchronously blocking the signaling // TODO(tommi): See if we can avoid synchronously blocking the signaling
// thread while we do this (or avoid the BlockingCall at all). // thread while we do this (or avoid the BlockingCall at all).
network_thread_->BlockingCall([this, &transceivers, &voice_stats, network_thread_->BlockingCall([&] {
&video_stats] {
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
for (const auto& transceiver_proxy : transceivers) { for (const auto& transceiver_proxy : transceivers) {
@ -2365,17 +2374,28 @@ void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() {
stats.transport_name = std::string(channel->transport_name()); stats.transport_name = std::string(channel->transport_name());
if (media_type == cricket::MEDIA_TYPE_AUDIO) { if (media_type == cricket::MEDIA_TYPE_AUDIO) {
cricket::VoiceMediaChannel* voice_channel = auto voice_send_channel = channel->voice_media_send_channel();
channel->media_channel()->AsVoiceChannel(); RTC_DCHECK(voice_send_stats.find(voice_send_channel) ==
RTC_DCHECK(voice_stats.find(voice_channel) == voice_stats.end()); voice_send_stats.end());
voice_stats.insert( voice_send_stats.insert(
std::make_pair(voice_channel, cricket::VoiceMediaInfo())); std::make_pair(voice_send_channel, cricket::VoiceMediaSendInfo()));
auto voice_receive_channel = channel->voice_media_receive_channel();
RTC_DCHECK(voice_receive_stats.find(voice_receive_channel) ==
voice_receive_stats.end());
voice_receive_stats.insert(std::make_pair(
voice_receive_channel, cricket::VoiceMediaReceiveInfo()));
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) { } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
cricket::VideoMediaChannel* video_channel = auto video_send_channel = channel->video_media_send_channel();
channel->media_channel()->AsVideoChannel(); RTC_DCHECK(video_send_stats.find(video_send_channel) ==
RTC_DCHECK(video_stats.find(video_channel) == video_stats.end()); video_send_stats.end());
video_stats.insert( video_send_stats.insert(
std::make_pair(video_channel, cricket::VideoMediaInfo())); std::make_pair(video_send_channel, cricket::VideoMediaSendInfo()));
auto video_receive_channel = channel->video_media_receive_channel();
RTC_DCHECK(video_receive_stats.find(video_receive_channel) ==
video_receive_stats.end());
video_receive_stats.insert(std::make_pair(
video_receive_channel, cricket::VideoMediaReceiveInfo()));
} else { } else {
RTC_DCHECK_NOTREACHED(); RTC_DCHECK_NOTREACHED();
} }
@ -2389,15 +2409,25 @@ void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() {
worker_thread_->BlockingCall([&] { worker_thread_->BlockingCall([&] {
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
for (auto& pair : voice_stats) { for (auto& pair : voice_send_stats) {
if (!pair.first->GetStats(&pair.second, if (!pair.first->GetStats(&pair.second)) {
/*get_and_clear_legacy_stats=*/false)) { RTC_LOG(LS_WARNING) << "Failed to get voice send stats.";
RTC_LOG(LS_WARNING) << "Failed to get voice stats.";
} }
} }
for (auto& pair : video_stats) { for (auto& pair : voice_receive_stats) {
if (!pair.first->GetStats(&pair.second,
/*get_and_clear_legacy_stats=*/false)) {
RTC_LOG(LS_WARNING) << "Failed to get voice receive stats.";
}
}
for (auto& pair : video_send_stats) {
if (!pair.first->GetStats(&pair.second)) { if (!pair.first->GetStats(&pair.second)) {
RTC_LOG(LS_WARNING) << "Failed to get video stats."; RTC_LOG(LS_WARNING) << "Failed to get video send stats.";
}
}
for (auto& pair : video_receive_stats) {
if (!pair.first->GetStats(&pair.second)) {
RTC_LOG(LS_WARNING) << "Failed to get video receive stats.";
} }
} }
@ -2410,15 +2440,17 @@ void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w_n() {
if (channel) { if (channel) {
cricket::MediaType media_type = transceiver->media_type(); cricket::MediaType media_type = transceiver->media_type();
if (media_type == cricket::MEDIA_TYPE_AUDIO) { if (media_type == cricket::MEDIA_TYPE_AUDIO) {
cricket::VoiceMediaChannel* voice_channel = auto voice_send_channel = channel->voice_media_send_channel();
channel->media_channel()->AsVoiceChannel(); auto voice_receive_channel = channel->voice_media_receive_channel();
RTC_DCHECK(voice_stats.find(voice_channel) != voice_stats.end()); voice_media_info = cricket::VoiceMediaInfo(
voice_media_info = std::move(voice_stats[voice_channel]); std::move(voice_send_stats[voice_send_channel]),
std::move(voice_receive_stats[voice_receive_channel]));
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) { } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
cricket::VideoMediaChannel* video_channel = auto video_send_channel = channel->video_media_send_channel();
channel->media_channel()->AsVideoChannel(); auto video_receive_channel = channel->video_media_receive_channel();
RTC_DCHECK(video_stats.find(video_channel) != video_stats.end()); video_media_info = cricket::VideoMediaInfo(
video_media_info = std::move(video_stats[video_channel]); std::move(video_send_stats[video_send_channel]),
std::move(video_receive_stats[video_receive_channel]));
} }
} }
std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders; std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders;

View File

@ -35,21 +35,35 @@ class FakeVoiceMediaChannelForStats : public cricket::FakeVoiceMediaChannel {
network_thread) {} network_thread) {}
void SetStats(const cricket::VoiceMediaInfo& voice_info) { void SetStats(const cricket::VoiceMediaInfo& voice_info) {
stats_ = voice_info; send_stats_ = cricket::VoiceMediaSendInfo();
send_stats_->senders = voice_info.senders;
send_stats_->send_codecs = voice_info.send_codecs;
receive_stats_ = cricket::VoiceMediaReceiveInfo();
receive_stats_->receivers = voice_info.receivers;
receive_stats_->receive_codecs = voice_info.receive_codecs;
receive_stats_->device_underrun_count = voice_info.device_underrun_count;
} }
// VoiceMediaChannel overrides. // VoiceMediaChannel overrides.
bool GetStats(cricket::VoiceMediaInfo* info, bool GetSendStats(cricket::VoiceMediaSendInfo* info) override {
bool get_and_clear_legacy_stats) override { if (send_stats_) {
if (stats_) { *info = *send_stats_;
*info = *stats_; return true;
}
return false;
}
bool GetReceiveStats(cricket::VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) override {
if (receive_stats_) {
*info = *receive_stats_;
return true; return true;
} }
return false; return false;
} }
private: private:
absl::optional<cricket::VoiceMediaInfo> stats_; absl::optional<cricket::VoiceMediaSendInfo> send_stats_;
absl::optional<cricket::VoiceMediaReceiveInfo> receive_stats_;
}; };
// Fake VideoMediaChannel where the result of GetStats can be configured. // Fake VideoMediaChannel where the result of GetStats can be configured.
@ -61,20 +75,34 @@ class FakeVideoMediaChannelForStats : public cricket::FakeVideoMediaChannel {
network_thread) {} network_thread) {}
void SetStats(const cricket::VideoMediaInfo& video_info) { void SetStats(const cricket::VideoMediaInfo& video_info) {
stats_ = video_info; send_stats_ = cricket::VideoMediaSendInfo();
send_stats_->senders = video_info.senders;
send_stats_->aggregated_senders = video_info.aggregated_senders;
send_stats_->send_codecs = video_info.send_codecs;
receive_stats_ = cricket::VideoMediaReceiveInfo();
receive_stats_->receivers = video_info.receivers;
receive_stats_->receive_codecs = video_info.receive_codecs;
} }
// VideoMediaChannel overrides. // VideoMediaChannel overrides.
bool GetStats(cricket::VideoMediaInfo* info) override { bool GetSendStats(cricket::VideoMediaSendInfo* info) override {
if (stats_) { if (send_stats_) {
*info = *stats_; *info = *send_stats_;
return true;
}
return false;
}
bool GetReceiveStats(cricket::VideoMediaReceiveInfo* info) override {
if (receive_stats_) {
*info = *receive_stats_;
return true; return true;
} }
return false; return false;
} }
private: private:
absl::optional<cricket::VideoMediaInfo> stats_; absl::optional<cricket::VideoMediaSendInfo> send_stats_;
absl::optional<cricket::VideoMediaReceiveInfo> receive_stats_;
}; };
constexpr bool kDefaultRtcpMuxRequired = true; constexpr bool kDefaultRtcpMuxRequired = true;

View File

@ -25,6 +25,8 @@ namespace cricket {
class MockChannelInterface : public cricket::ChannelInterface { class MockChannelInterface : public cricket::ChannelInterface {
public: public:
MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); MOCK_METHOD(cricket::MediaType, media_type, (), (const, override));
MOCK_METHOD(VideoChannel*, AsVideoChannel, (), (override));
MOCK_METHOD(VoiceChannel*, AsVoiceChannel, (), (override));
MOCK_METHOD(MediaChannel*, media_channel, (), (override)); MOCK_METHOD(MediaChannel*, media_channel, (), (override));
MOCK_METHOD(MediaChannel*, media_send_channel, (), (override)); MOCK_METHOD(MediaChannel*, media_send_channel, (), (override));
MOCK_METHOD(VoiceMediaChannel*, voice_media_send_channel, (), (override)); MOCK_METHOD(VoiceMediaChannel*, voice_media_send_channel, (), (override));

View File

@ -126,9 +126,10 @@ class MockVoiceMediaChannel : public VoiceMediaChannel {
InsertDtmf, InsertDtmf,
(uint32_t ssrc, int event, int duration), (uint32_t ssrc, int event, int duration),
(override)); (override));
MOCK_METHOD(bool, GetSendStats, (VoiceMediaSendInfo * info), (override));
MOCK_METHOD(bool, MOCK_METHOD(bool,
GetStats, GetReceiveStats,
(VoiceMediaInfo * info, bool get_and_clear_legacy_stats), (VoiceMediaReceiveInfo * info, bool get_and_clear_legacy_stats),
(override)); (override));
MOCK_METHOD(void, MOCK_METHOD(void,
SetRawAudioSink, SetRawAudioSink,