VoipStatistics subAPI and implementation.
- Adding an interface that fetches lifetime NetEq statistics struct. Bug: webrtc:11989 Change-Id: I871455bccdd53a33dd260f744e03ec81d29fbfd8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/190200 Commit-Queue: Tim Na <natim@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32516}
This commit is contained in:
parent
e9bb49a09c
commit
f4347f7bac
@ -16,10 +16,12 @@ rtc_source_set("voip_api") {
|
||||
"voip_dtmf.h",
|
||||
"voip_engine.h",
|
||||
"voip_network.h",
|
||||
"voip_statistics.h",
|
||||
]
|
||||
deps = [
|
||||
"..:array_view",
|
||||
"../audio_codecs:audio_codecs_api",
|
||||
"../neteq:neteq_api",
|
||||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ class VoipBase;
|
||||
class VoipCodec;
|
||||
class VoipNetwork;
|
||||
class VoipDtmf;
|
||||
class VoipStatistics;
|
||||
|
||||
// VoipEngine is the main interface serving as the entry point for all VoIP
|
||||
// APIs. A single instance of VoipEngine should suffice the most of the need for
|
||||
@ -84,6 +85,10 @@ class VoipEngine {
|
||||
|
||||
// VoipDtmf provides DTMF event APIs to register and send DTMF events.
|
||||
virtual VoipDtmf& Dtmf() = 0;
|
||||
|
||||
// VoipStatistics provides performance metrics around audio decoding module
|
||||
// and jitter buffer (NetEq).
|
||||
virtual VoipStatistics& Statistics() = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
34
api/voip/voip_statistics.h
Normal file
34
api/voip/voip_statistics.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_VOIP_VOIP_STATISTICS_H_
|
||||
#define API_VOIP_VOIP_STATISTICS_H_
|
||||
|
||||
#include "api/neteq/neteq.h"
|
||||
#include "api/voip/voip_base.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// VoipStatistics interface provides the interfaces for querying metrics around
|
||||
// the jitter buffer (NetEq) performance.
|
||||
class VoipStatistics {
|
||||
public:
|
||||
// Gets the statistics from NetEq. Returns absl::nullopt when channel_id is
|
||||
// invalid.
|
||||
virtual absl::optional<NetEqLifetimeStatistics> GetNetEqStatistics(
|
||||
ChannelId channel_id) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VoipStatistics() = default;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VOIP_VOIP_STATISTICS_H_
|
||||
@ -129,4 +129,29 @@ void AudioChannel::StopPlay() {
|
||||
}
|
||||
}
|
||||
|
||||
NetEqLifetimeStatistics AudioChannel::GetNetEqStatistics() {
|
||||
NetEqLifetimeStatistics neteq_stats;
|
||||
NetworkStatistics stats = ingress_->GetNetworkStatistics();
|
||||
neteq_stats.total_samples_received = stats.totalSamplesReceived;
|
||||
neteq_stats.concealed_samples = stats.concealedSamples;
|
||||
neteq_stats.concealment_events = stats.concealmentEvents;
|
||||
neteq_stats.jitter_buffer_delay_ms = stats.jitterBufferDelayMs;
|
||||
neteq_stats.jitter_buffer_emitted_count = stats.jitterBufferEmittedCount;
|
||||
neteq_stats.jitter_buffer_target_delay_ms = stats.jitterBufferTargetDelayMs;
|
||||
neteq_stats.inserted_samples_for_deceleration =
|
||||
stats.insertedSamplesForDeceleration;
|
||||
neteq_stats.removed_samples_for_acceleration =
|
||||
stats.removedSamplesForAcceleration;
|
||||
neteq_stats.silent_concealed_samples = stats.silentConcealedSamples;
|
||||
neteq_stats.fec_packets_received = stats.fecPacketsReceived;
|
||||
neteq_stats.fec_packets_discarded = stats.fecPacketsDiscarded;
|
||||
neteq_stats.delayed_packet_outage_samples = stats.delayedPacketOutageSamples;
|
||||
neteq_stats.relative_packet_arrival_delay_ms =
|
||||
stats.relativePacketArrivalDelayMs;
|
||||
neteq_stats.interruption_count = stats.interruptionCount;
|
||||
neteq_stats.total_interruption_duration_ms =
|
||||
stats.totalInterruptionDurationMs;
|
||||
return neteq_stats;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/voip/voip_base.h"
|
||||
#include "api/voip/voip_statistics.h"
|
||||
#include "audio/voip/audio_egress.h"
|
||||
#include "audio/voip/audio_ingress.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
|
||||
@ -81,6 +82,7 @@ class AudioChannel : public rtc::RefCountInterface {
|
||||
void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs) {
|
||||
ingress_->SetReceiveCodecs(codecs);
|
||||
}
|
||||
NetEqLifetimeStatistics GetNetEqStatistics();
|
||||
|
||||
private:
|
||||
// ChannelId that this audio channel belongs for logging purpose.
|
||||
|
||||
@ -82,12 +82,8 @@ class AudioIngress : public AudioMixer::Source {
|
||||
|
||||
NetworkStatistics GetNetworkStatistics() const {
|
||||
NetworkStatistics stats;
|
||||
acm_receiver_.GetNetworkStatistics(&stats);
|
||||
return stats;
|
||||
}
|
||||
AudioDecodingCallStats GetDecodingStatistics() const {
|
||||
AudioDecodingCallStats stats;
|
||||
acm_receiver_.GetDecodingCallStatistics(&stats);
|
||||
acm_receiver_.GetNetworkStatistics(&stats,
|
||||
/*get_and_clear_legacy_stats=*/false);
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
||||
@ -139,5 +139,36 @@ TEST_F(AudioChannelTest, VerifyLocalSsrcAsAssigned) {
|
||||
EXPECT_EQ(rtp.Ssrc(), kLocalSsrc);
|
||||
}
|
||||
|
||||
// Check metrics after processing an RTP packet.
|
||||
TEST_F(AudioChannelTest, TestAudioStatistics) {
|
||||
rtc::Event event;
|
||||
auto loop_rtp = [&](const uint8_t* packet, size_t length, Unused) {
|
||||
audio_channel_->ReceivedRTPPacket(
|
||||
rtc::ArrayView<const uint8_t>(packet, length));
|
||||
event.Set();
|
||||
return true;
|
||||
};
|
||||
EXPECT_CALL(transport_, SendRtp).WillOnce(Invoke(loop_rtp));
|
||||
|
||||
auto audio_sender = audio_channel_->GetAudioSender();
|
||||
audio_sender->SendAudioData(GetAudioFrame(0));
|
||||
audio_sender->SendAudioData(GetAudioFrame(1));
|
||||
|
||||
event.Wait(/*give_up_after_ms=*/1000);
|
||||
|
||||
AudioFrame audio_frame;
|
||||
audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame);
|
||||
|
||||
// Check a few fields as we wouldn't have enough samples verify most of them
|
||||
// here.
|
||||
absl::optional<NetEqLifetimeStatistics> neteq_stats =
|
||||
audio_channel_->GetNetEqStatistics();
|
||||
EXPECT_TRUE(neteq_stats);
|
||||
EXPECT_EQ(neteq_stats->total_samples_received, 80ULL);
|
||||
EXPECT_EQ(neteq_stats->concealed_samples, 0ULL);
|
||||
EXPECT_EQ(neteq_stats->jitter_buffer_delay_ms, 1600ULL);
|
||||
EXPECT_EQ(neteq_stats->interruption_count, 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
|
||||
@ -382,4 +382,12 @@ bool VoipCore::SendDtmfEvent(ChannelId channel,
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::optional<NetEqLifetimeStatistics> VoipCore::GetNetEqStatistics(
|
||||
ChannelId channel) {
|
||||
if (auto audio_channel = GetChannel(channel)) {
|
||||
return audio_channel->GetNetEqStatistics();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "api/voip/voip_dtmf.h"
|
||||
#include "api/voip/voip_engine.h"
|
||||
#include "api/voip/voip_network.h"
|
||||
#include "api/voip/voip_statistics.h"
|
||||
#include "audio/audio_transport_impl.h"
|
||||
#include "audio/voip/audio_channel.h"
|
||||
#include "modules/audio_device/include/audio_device.h"
|
||||
@ -47,7 +48,8 @@ class VoipCore : public VoipEngine,
|
||||
public VoipBase,
|
||||
public VoipNetwork,
|
||||
public VoipCodec,
|
||||
public VoipDtmf {
|
||||
public VoipDtmf,
|
||||
public VoipStatistics {
|
||||
public:
|
||||
~VoipCore() override = default;
|
||||
|
||||
@ -70,6 +72,7 @@ class VoipCore : public VoipEngine,
|
||||
VoipNetwork& Network() override { return *this; }
|
||||
VoipCodec& Codec() override { return *this; }
|
||||
VoipDtmf& Dtmf() override { return *this; }
|
||||
VoipStatistics& Statistics() override { return *this; }
|
||||
|
||||
// Implements VoipBase interfaces.
|
||||
absl::optional<ChannelId> CreateChannel(
|
||||
@ -103,6 +106,10 @@ class VoipCore : public VoipEngine,
|
||||
DtmfEvent dtmf_event,
|
||||
int duration_ms) override;
|
||||
|
||||
// Implements VoipStatistics interfaces.
|
||||
absl::optional<NetEqLifetimeStatistics> GetNetEqStatistics(
|
||||
ChannelId channel) override;
|
||||
|
||||
private:
|
||||
// Fetches the corresponding AudioChannel assigned with given |channel|.
|
||||
// Returns nullptr if not found.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user