Added RTCMediaStreamTrackStats.jitterBufferDelay for audio
Description of this stat can be found here:
https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-jitterbufferdelay
Bug: webrtc:8281
Change-Id: Ib2e8174f3449e68ad419ae2d58d5565fc9854023
Reviewed-on: https://webrtc-review.googlesource.com/3381
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20069}
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index d999df0..085e77a 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -337,6 +337,7 @@
acm_stat->totalSamplesReceived = neteq_lifetime_stat.total_samples_received;
acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples;
acm_stat->concealmentEvents = neteq_lifetime_stat.concealment_events;
+ acm_stat->jitterBufferDelayMs = neteq_lifetime_stat.jitter_buffer_delay_ms;
}
int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h
index b349f20..e6cafa8 100644
--- a/modules/audio_coding/neteq/include/neteq.h
+++ b/modules/audio_coding/neteq/include/neteq.h
@@ -66,6 +66,7 @@
uint64_t total_samples_received = 0;
uint64_t concealed_samples = 0;
uint64_t concealment_events = 0;
+ uint64_t jitter_buffer_delay_ms = 0;
};
enum NetEqPlayoutMode {
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 2d50225..36d6b27 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -1950,7 +1950,8 @@
assert(false); // Should always be able to extract a packet here.
return -1;
}
- stats_.StoreWaitingTime(packet->waiting_time->ElapsedMs());
+ const uint64_t waiting_time_ms = packet->waiting_time->ElapsedMs();
+ stats_.StoreWaitingTime(waiting_time_ms);
RTC_DCHECK(!packet->empty());
if (first_packet) {
@@ -1990,6 +1991,8 @@
}
extracted_samples = packet->timestamp - first_timestamp + packet_duration;
+ stats_.JitterBufferDelay(extracted_samples, waiting_time_ms);
+
packet_list->push_back(std::move(*packet)); // Store packet in list.
packet = rtc::Optional<Packet>(); // Ensure it's never used after the move.
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index 5b92217..9dd60eb 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -522,6 +522,7 @@
NetEqDecodingTestFaxMode() : NetEqDecodingTest() {
config_.playout_mode = kPlayoutFax;
}
+ void TestJitterBufferDelay(bool apply_packet_loss);
};
TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) {
@@ -1684,4 +1685,64 @@
EXPECT_EQ(kNumConcealmentEvents, static_cast<int>(stats.concealment_events));
}
+// Test that the jitter buffer delay stat is computed correctly.
+void NetEqDecodingTestFaxMode::TestJitterBufferDelay(bool apply_packet_loss) {
+ const int kNumPackets = 10;
+ const int kDelayInNumPackets = 2;
+ const int kPacketLenMs = 10; // All packets are of 10 ms size.
+ const size_t kSamples = kPacketLenMs * 16;
+ const size_t kPayloadBytes = kSamples * 2;
+ RTPHeader rtp_info;
+ rtp_info.ssrc = 0x1234; // Just an arbitrary SSRC.
+ rtp_info.payloadType = 94; // PCM16b WB codec.
+ rtp_info.markerBit = 0;
+ const uint8_t payload[kPayloadBytes] = {0};
+ bool muted;
+ int packets_sent = 0;
+ int packets_received = 0;
+ int expected_delay = 0;
+ while (packets_received < kNumPackets) {
+ // Insert packet.
+ if (packets_sent < kNumPackets) {
+ rtp_info.sequenceNumber = packets_sent++;
+ rtp_info.timestamp = rtp_info.sequenceNumber * kSamples;
+ neteq_->InsertPacket(rtp_info, payload, 0);
+ }
+
+ // Get packet.
+ if (packets_sent > kDelayInNumPackets) {
+ neteq_->GetAudio(&out_frame_, &muted);
+ packets_received++;
+
+ // The delay reported by the jitter buffer never exceeds
+ // the number of samples previously fetched with GetAudio
+ // (hence the min()).
+ int packets_delay = std::min(packets_received, kDelayInNumPackets + 1);
+
+ // The increase of the expected delay is the product of
+ // the current delay of the jitter buffer in ms * the
+ // number of samples that are sent for play out.
+ int current_delay_ms = packets_delay * kPacketLenMs;
+ expected_delay += current_delay_ms * kSamples;
+ }
+ }
+
+ if (apply_packet_loss) {
+ // Extra call to GetAudio to cause concealment.
+ neteq_->GetAudio(&out_frame_, &muted);
+ }
+
+ // Check jitter buffer delay.
+ NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
+ EXPECT_EQ(expected_delay, static_cast<int>(stats.jitter_buffer_delay_ms));
+}
+
+TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithoutLoss) {
+ TestJitterBufferDelay(false);
+}
+
+TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithLoss) {
+ TestJitterBufferDelay(true);
+}
+
} // namespace webrtc
diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc
index 4e034e6..70a15ae 100644
--- a/modules/audio_coding/neteq/statistics_calculator.cc
+++ b/modules/audio_coding/neteq/statistics_calculator.cc
@@ -229,6 +229,11 @@
lifetime_stats_.total_samples_received += num_samples;
}
+void StatisticsCalculator::JitterBufferDelay(size_t num_samples,
+ uint64_t waiting_time_ms) {
+ lifetime_stats_.jitter_buffer_delay_ms += waiting_time_ms * num_samples;
+}
+
void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
secondary_decoded_samples_ += num_samples;
}
diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h
index 5c2fbf3..c3d5c86 100644
--- a/modules/audio_coding/neteq/statistics_calculator.h
+++ b/modules/audio_coding/neteq/statistics_calculator.h
@@ -75,6 +75,9 @@
// time is increasing.
void IncreaseCounter(size_t num_samples, int fs_hz);
+ // Update jitter buffer delay counter.
+ void JitterBufferDelay(size_t num_samples, uint64_t waiting_time_ms);
+
// Stores new packet waiting time in waiting time statistics.
void StoreWaitingTime(int waiting_time_ms);