Piping audio interruption metrics to API layer
Bug: webrtc:10549
Change-Id: Ie6abe5819c5b73dc5f5f89bdc375bad77f44ce97
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/134303
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27788}
diff --git a/api/stats_types.cc b/api/stats_types.cc
index 4c69a82..cbc3b81 100644
--- a/api/stats_types.cc
+++ b/api/stats_types.cc
@@ -565,6 +565,8 @@
return "googInitiator";
case kStatsValueNameInterframeDelayMaxMs:
return "googInterframeDelayMax";
+ case kStatsValueNameInterruptionCount:
+ return "googInterruptionCount";
case kStatsValueNameIssuerId:
return "googIssuerId";
case kStatsValueNameJitterReceived:
@@ -647,6 +649,8 @@
return "googTrackId";
case kStatsValueNameTimingFrameInfo:
return "googTimingFrameInfo";
+ case kStatsValueNameTotalInterruptionDurationMs:
+ return "googTotalInterruptionDurationMs";
case kStatsValueNameTypingNoiseState:
return "googTypingNoiseState";
case kStatsValueNameWritable:
diff --git a/api/stats_types.h b/api/stats_types.h
index 0e97eaf..0631339 100644
--- a/api/stats_types.h
+++ b/api/stats_types.h
@@ -192,6 +192,7 @@
kStatsValueNameHugeFramesSent,
kStatsValueNameInitiator,
kStatsValueNameInterframeDelayMaxMs, // Max over last 10 seconds.
+ kStatsValueNameInterruptionCount,
kStatsValueNameIssuerId,
kStatsValueNameJitterBufferMs,
kStatsValueNameJitterReceived,
@@ -232,6 +233,7 @@
kStatsValueNameTargetDelayMs,
kStatsValueNameTargetEncBitrate,
kStatsValueNameTimingFrameInfo, // Result of |TimingFrameInfo::ToString|
+ kStatsValueNameTotalInterruptionDurationMs,
kStatsValueNameTrackId,
kStatsValueNameTransmitBitrate,
kStatsValueNameTransportType,
diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc
index b4948ee..677ee20 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -226,6 +226,8 @@
stats.relative_packet_arrival_delay_seconds =
static_cast<double>(ns.relativePacketArrivalDelayMs) /
static_cast<double>(rtc::kNumMillisecsPerSec);
+ stats.interruption_count = ns.interruptionCount;
+ stats.total_interruption_duration_ms = ns.totalInterruptionDurationMs;
auto ds = channel_receive_->GetDecodingCallStatistics();
stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h
index 257042b..9091afd 100644
--- a/call/audio_receive_stream.h
+++ b/call/audio_receive_stream.h
@@ -79,6 +79,8 @@
absl::optional<int64_t> last_packet_received_timestamp_ms;
uint64_t jitter_buffer_flushes = 0;
double relative_packet_arrival_delay_seconds = 0.0;
+ int32_t interruption_count = 0;
+ int32_t total_interruption_duration_ms = 0;
};
struct Config {
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index 710fd1a..69570e7 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -514,6 +514,10 @@
uint64_t delayed_packet_outage_samples = 0;
// Arrival delay of received audio packets.
double relative_packet_arrival_delay_seconds = 0.0;
+ // Count and total duration of audio interruptions (loss-concealement periods
+ // longer than 150 ms).
+ int32_t interruption_count = 0;
+ int32_t total_interruption_duration_ms = 0;
};
struct VideoSenderInfo : public MediaSenderInfo {
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc
index 9110d55..3e4c6bd 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -2274,6 +2274,8 @@
rinfo.jitter_buffer_flushes = stats.jitter_buffer_flushes;
rinfo.relative_packet_arrival_delay_seconds =
stats.relative_packet_arrival_delay_seconds;
+ rinfo.interruption_count = stats.interruption_count;
+ rinfo.total_interruption_duration_ms = stats.total_interruption_duration_ms;
info->receivers.push_back(rinfo);
}
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index da7d621..c10a71c 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -259,6 +259,9 @@
neteq_lifetime_stat.delayed_packet_outage_samples;
acm_stat->relativePacketArrivalDelayMs =
neteq_lifetime_stat.relative_packet_arrival_delay_ms;
+ acm_stat->interruptionCount = neteq_lifetime_stat.interruption_count;
+ acm_stat->totalInterruptionDurationMs =
+ neteq_lifetime_stat.total_interruption_duration_ms;
NetEqOperationsAndState neteq_operations_and_state =
neteq_->GetOperationsAndState();
diff --git a/modules/audio_coding/include/audio_coding_module_typedefs.h b/modules/audio_coding/include/audio_coding_module_typedefs.h
index 8063a29..621c478 100644
--- a/modules/audio_coding/include/audio_coding_module_typedefs.h
+++ b/modules/audio_coding/include/audio_coding_module_typedefs.h
@@ -130,6 +130,10 @@
uint64_t delayedPacketOutageSamples;
// arrival delay of incoming packets
uint64_t relativePacketArrivalDelayMs;
+ // number of audio interruptions
+ int32_t interruptionCount;
+ // total duration of audio interruptions
+ int32_t totalInterruptionDurationMs;
};
} // namespace webrtc
diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h
index c0c836f..d91850f 100644
--- a/modules/audio_coding/neteq/include/neteq.h
+++ b/modules/audio_coding/neteq/include/neteq.h
@@ -90,8 +90,8 @@
// An interruption is a loss-concealment event lasting at least 150 ms. The
// two stats below count the number os such events and the total duration of
// these events.
- uint64_t interruption_count = 0;
- uint64_t total_interruption_duration_ms = 0;
+ int32_t interruption_count = 0;
+ int32_t total_interruption_duration_ms = 0;
};
// Metrics that describe the operations performed in NetEq, and the internal
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 025ed69..8269526 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -745,7 +745,7 @@
}
auto lifetime_stats = neteq_->GetLifetimeStatistics();
- EXPECT_EQ(0u, lifetime_stats.interruption_count);
+ EXPECT_EQ(0, lifetime_stats.interruption_count);
}
// This test verifies that NetEq can handle comfort noise and enters/quits codec
diff --git a/modules/audio_coding/neteq/statistics_calculator_unittest.cc b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
index a851074..abfa3c5 100644
--- a/modules/audio_coding/neteq/statistics_calculator_unittest.cc
+++ b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
@@ -135,31 +135,31 @@
stats.DecodedOutputPlayed();
stats.EndExpandEvent(fs_hz);
auto lts = stats.GetLifetimeStatistics();
- EXPECT_EQ(0u, lts.interruption_count);
- EXPECT_EQ(0u, lts.total_interruption_duration_ms);
+ EXPECT_EQ(0, lts.interruption_count);
+ EXPECT_EQ(0, lts.total_interruption_duration_ms);
// Add an event that is shorter than 150 ms. Should not be logged.
stats.ExpandedVoiceSamples(10 * fs_khz, false); // 10 ms.
stats.ExpandedNoiseSamples(139 * fs_khz, false); // 139 ms.
stats.EndExpandEvent(fs_hz);
lts = stats.GetLifetimeStatistics();
- EXPECT_EQ(0u, lts.interruption_count);
+ EXPECT_EQ(0, lts.interruption_count);
// Add an event that is longer than 150 ms. Should be logged.
stats.ExpandedVoiceSamples(140 * fs_khz, false); // 140 ms.
stats.ExpandedNoiseSamples(11 * fs_khz, false); // 11 ms.
stats.EndExpandEvent(fs_hz);
lts = stats.GetLifetimeStatistics();
- EXPECT_EQ(1u, lts.interruption_count);
- EXPECT_EQ(151u, lts.total_interruption_duration_ms);
+ EXPECT_EQ(1, lts.interruption_count);
+ EXPECT_EQ(151, lts.total_interruption_duration_ms);
// Add one more long event.
stats.ExpandedVoiceSamples(100 * fs_khz, false); // 100 ms.
stats.ExpandedNoiseSamples(5000 * fs_khz, false); // 5000 ms.
stats.EndExpandEvent(fs_hz);
lts = stats.GetLifetimeStatistics();
- EXPECT_EQ(2u, lts.interruption_count);
- EXPECT_EQ(5100u + 151u, lts.total_interruption_duration_ms);
+ EXPECT_EQ(2, lts.interruption_count);
+ EXPECT_EQ(5100 + 151, lts.total_interruption_duration_ms);
}
TEST(StatisticsCalculator, InterruptionCounterDoNotLogBeforeDecoding) {
@@ -172,7 +172,7 @@
stats.ExpandedVoiceSamples(151 * fs_khz, false); // 151 ms.
stats.EndExpandEvent(fs_hz);
auto lts = stats.GetLifetimeStatistics();
- EXPECT_EQ(0u, lts.interruption_count);
+ EXPECT_EQ(0, lts.interruption_count);
// Call DecodedOutputPlayed(). Logging should happen after this.
stats.DecodedOutputPlayed();
@@ -181,7 +181,7 @@
stats.ExpandedVoiceSamples(151 * fs_khz, false); // 151 ms.
stats.EndExpandEvent(fs_hz);
lts = stats.GetLifetimeStatistics();
- EXPECT_EQ(1u, lts.interruption_count);
+ EXPECT_EQ(1, lts.interruption_count);
}
} // namespace webrtc
diff --git a/modules/audio_coding/neteq/tools/neteq_stats_plotter.cc b/modules/audio_coding/neteq/tools/neteq_stats_plotter.cc
index c7bec9c..7c3aed8 100644
--- a/modules/audio_coding/neteq/tools/neteq_stats_plotter.cc
+++ b/modules/audio_coding/neteq/tools/neteq_stats_plotter.cc
@@ -79,9 +79,8 @@
const auto lifetime_stats_vector = stats_getter_->lifetime_stats();
if (!lifetime_stats_vector->empty()) {
auto lifetime_stats = lifetime_stats_vector->back().second;
- printf(" num_interruptions: %" PRId64 "\n",
- lifetime_stats.interruption_count);
- printf(" sum_interruption_length_ms: %" PRId64 " ms\n",
+ printf(" num_interruptions: %d\n", lifetime_stats.interruption_count);
+ printf(" sum_interruption_length_ms: %d ms\n",
lifetime_stats.total_interruption_duration_ms);
printf(" interruption ratio: %f%%\n",
100.0 * lifetime_stats.total_interruption_duration_ms /
diff --git a/pc/stats_collector.cc b/pc/stats_collector.cc
index e1930a1..91afe26 100644
--- a/pc/stats_collector.cc
+++ b/pc/stats_collector.cc
@@ -165,6 +165,9 @@
{StatsReport::kStatsValueNamePacketsReceived, info.packets_rcvd},
{StatsReport::kStatsValueNamePreferredJitterBufferMs,
info.jitter_buffer_preferred_ms},
+ {StatsReport::kStatsValueNameInterruptionCount, info.interruption_count},
+ {StatsReport::kStatsValueNameTotalInterruptionDurationMs,
+ info.total_interruption_duration_ms},
};
for (const auto& f : floats)
diff --git a/pc/stats_collector_unittest.cc b/pc/stats_collector_unittest.cc
index 3118ef9..9a514f0 100644
--- a/pc/stats_collector_unittest.cc
+++ b/pc/stats_collector_unittest.cc
@@ -383,6 +383,14 @@
EXPECT_EQ(rtc::ToString(info.decoding_muted_output), value_in_report);
EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
&value_in_report));
+ EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameInterruptionCount,
+ &value_in_report));
+ EXPECT_EQ(rtc::ToString(info.interruption_count), value_in_report);
+ EXPECT_TRUE(GetValue(report,
+ StatsReport::kStatsValueNameTotalInterruptionDurationMs,
+ &value_in_report));
+ EXPECT_EQ(rtc::ToString(info.total_interruption_duration_ms),
+ value_in_report);
}
void VerifyVoiceSenderInfoReport(const StatsReport* report,