forked from webrtc-sdk/webrtc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement DelayVariationCalculator for events analysis.
This CL implements {,Logging}DelayVariationCalculator, whose purpose is to calculate simple inter-arrival metrics for a sequence of RTP frames. Uses could include RtcEventLog analysis and ad hoc testing. Want lgtm: asapersson Bug: webrtc:15213 Change-Id: I3f9d13a2c4fa66b6f1229c1b6fcd66a6911070de Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/306741 Commit-Queue: Rasmus Brandt <[email protected]> Reviewed-by: Åsa Persson <[email protected]> Reviewed-by: Jeremy Leconte <[email protected]> Cr-Commit-Position: refs/heads/main@{#40247}
- Loading branch information
1 parent
f99e0f4
commit cde5354
Showing
11 changed files
with
594 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Copyright (c) 2023 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. | ||
|
||
import("../../webrtc.gni") | ||
|
||
rtc_library("delay_variation_calculator") { | ||
visibility = [ "*" ] | ||
sources = [ | ||
"delay_variation_calculator.cc", | ||
"delay_variation_calculator.h", | ||
] | ||
deps = [ | ||
"../../api/numerics", | ||
"../../api/test/metrics:metrics_logger", | ||
"../../api/units:data_size", | ||
"../../api/units:frequency", | ||
"../../api/units:time_delta", | ||
"../../api/units:timestamp", | ||
"../../api/video:video_frame_type", | ||
"../../rtc_base:logging", | ||
"../../rtc_base:rtc_numerics", | ||
] | ||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] | ||
} | ||
|
||
rtc_library("logging_delay_variation_calculator") { | ||
visibility = [ "*" ] | ||
sources = [ | ||
"logging_delay_variation_calculator.cc", | ||
"logging_delay_variation_calculator.h", | ||
] | ||
deps = [ | ||
":delay_variation_calculator", | ||
"../../api/test/metrics:global_metrics_logger_and_exporter", | ||
"../../api/units:data_size", | ||
"../../api/video:video_frame_type", | ||
"../../rtc_base:logging", | ||
] | ||
absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] | ||
} | ||
|
||
if (rtc_include_tests) { | ||
rtc_library("jitter_unittests") { | ||
testonly = true | ||
sources = [ | ||
"delay_variation_calculator_unittest.cc", | ||
"logging_delay_variation_calculator_unittest.cc", | ||
] | ||
deps = [ | ||
":delay_variation_calculator", | ||
":logging_delay_variation_calculator", | ||
"../../api/numerics", | ||
"../../api/test/metrics:metrics_logger", | ||
"../../api/units:timestamp", | ||
"../../system_wrappers", | ||
"../../test:test_support", | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/* | ||
* Copyright (c) 2023 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. | ||
*/ | ||
|
||
#include "test/jitter/delay_variation_calculator.h" | ||
|
||
#include <string> | ||
|
||
#include "absl/types/optional.h" | ||
#include "api/units/frequency.h" | ||
#include "api/units/time_delta.h" | ||
#include "api/units/timestamp.h" | ||
#include "rtc_base/logging.h" | ||
|
||
namespace webrtc { | ||
namespace test { | ||
|
||
namespace { | ||
constexpr Frequency k90000Hz = Frequency::Hertz(90000); | ||
} // namespace | ||
|
||
void DelayVariationCalculator::Insert( | ||
uint32_t rtp_timestamp, | ||
Timestamp arrival_time, | ||
DataSize size, | ||
absl::optional<int> spatial_layer, | ||
absl::optional<int> temporal_layer, | ||
absl::optional<VideoFrameType> frame_type) { | ||
Frame frame{.rtp_timestamp = rtp_timestamp, | ||
.unwrapped_rtp_timestamp = unwrapper_.Unwrap(rtp_timestamp), | ||
.arrival_time = arrival_time, | ||
.size = size, | ||
.spatial_layer = spatial_layer, | ||
.temporal_layer = temporal_layer, | ||
.frame_type = frame_type}; | ||
// Using RTP timestamp as the time series sample identifier allows for | ||
// cross-correlating time series logged by different objects at different | ||
// arrival timestamps. | ||
Timestamp sample_time = | ||
Timestamp::Millis((frame.unwrapped_rtp_timestamp / k90000Hz).ms()); | ||
MetadataT sample_metadata = BuildMetadata(frame); | ||
if (!prev_frame_) { | ||
InsertFirstFrame(frame, sample_time, sample_metadata); | ||
} else { | ||
InsertFrame(frame, sample_time, sample_metadata); | ||
} | ||
prev_frame_ = frame; | ||
} | ||
|
||
void DelayVariationCalculator::InsertFirstFrame(const Frame& frame, | ||
Timestamp sample_time, | ||
MetadataT sample_metadata) { | ||
const auto s = [=](double sample_value) { | ||
return SamplesStatsCounter::StatsSample{.value = sample_value, | ||
.time = sample_time, | ||
.metadata = sample_metadata}; | ||
}; | ||
time_series_.rtp_timestamps.AddSample( | ||
s(static_cast<double>(frame.rtp_timestamp))); | ||
time_series_.arrival_times_ms.AddSample(s(frame.arrival_time.ms<double>())); | ||
time_series_.sizes_bytes.AddSample(s(frame.size.bytes<double>())); | ||
time_series_.inter_departure_times_ms.AddSample(s(0.0)); | ||
time_series_.inter_arrival_times_ms.AddSample(s(0.0)); | ||
time_series_.inter_delay_variations_ms.AddSample(s(0.0)); | ||
time_series_.inter_size_variations_bytes.AddSample(s(0.0)); | ||
} | ||
|
||
void DelayVariationCalculator::InsertFrame(const Frame& frame, | ||
Timestamp sample_time, | ||
MetadataT sample_metadata) { | ||
int64_t inter_rtp_time = | ||
frame.unwrapped_rtp_timestamp - prev_frame_->unwrapped_rtp_timestamp; | ||
TimeDelta inter_departure_time = inter_rtp_time / k90000Hz; | ||
TimeDelta inter_arrival_time = frame.arrival_time - prev_frame_->arrival_time; | ||
TimeDelta inter_delay_variation = inter_arrival_time - inter_departure_time; | ||
double inter_size_variation_bytes = | ||
frame.size.bytes<double>() - prev_frame_->size.bytes<double>(); | ||
const auto s = [=](double sample_value) { | ||
return SamplesStatsCounter::StatsSample{.value = sample_value, | ||
.time = sample_time, | ||
.metadata = sample_metadata}; | ||
}; | ||
const auto ms = [](const TimeDelta& td) { return td.ms<double>(); }; | ||
time_series_.rtp_timestamps.AddSample( | ||
s(static_cast<double>(frame.rtp_timestamp))); | ||
time_series_.arrival_times_ms.AddSample(s(frame.arrival_time.ms<double>())); | ||
time_series_.sizes_bytes.AddSample(s(frame.size.bytes<double>())); | ||
time_series_.inter_departure_times_ms.AddSample(s(ms(inter_departure_time))); | ||
time_series_.inter_arrival_times_ms.AddSample(s(ms(inter_arrival_time))); | ||
time_series_.inter_delay_variations_ms.AddSample( | ||
s(ms(inter_delay_variation))); | ||
time_series_.inter_size_variations_bytes.AddSample( | ||
s(inter_size_variation_bytes)); | ||
} | ||
|
||
DelayVariationCalculator::MetadataT DelayVariationCalculator::BuildMetadata( | ||
const Frame& frame) { | ||
MetadataT metadata; | ||
if (prev_frame_) { | ||
if (prev_frame_->spatial_layer) { | ||
metadata["sl_prev"] = std::to_string(*prev_frame_->spatial_layer); | ||
} | ||
if (prev_frame_->temporal_layer) { | ||
metadata["tl_prev"] = std::to_string(*prev_frame_->temporal_layer); | ||
} | ||
if (prev_frame_->frame_type) { | ||
metadata["frame_type_prev"] = | ||
VideoFrameTypeToString(*prev_frame_->frame_type); | ||
} | ||
} | ||
if (frame.spatial_layer) { | ||
metadata["sl"] = std::to_string(*frame.spatial_layer); | ||
} | ||
if (frame.temporal_layer) { | ||
metadata["tl"] = std::to_string(*frame.temporal_layer); | ||
} | ||
if (frame.frame_type) { | ||
metadata["frame_type"] = VideoFrameTypeToString(*frame.frame_type); | ||
} | ||
return metadata; | ||
} | ||
|
||
} // namespace test | ||
} // namespace webrtc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright (c) 2023 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 TEST_JITTER_DELAY_VARIATION_CALCULATOR_H_ | ||
#define TEST_JITTER_DELAY_VARIATION_CALCULATOR_H_ | ||
|
||
#include <stdint.h> | ||
|
||
#include <map> | ||
#include <string> | ||
|
||
#include "absl/types/optional.h" | ||
#include "api/numerics/samples_stats_counter.h" | ||
#include "api/test/metrics/metrics_logger.h" | ||
#include "api/units/data_size.h" | ||
#include "api/units/timestamp.h" | ||
#include "api/video/video_frame_type.h" | ||
#include "rtc_base/numerics/sequence_number_unwrapper.h" | ||
|
||
namespace webrtc { | ||
namespace test { | ||
|
||
// Helper class for calculating different delay variation statistics for "RTP | ||
// frame arrival events". One use case is gathering statistics from | ||
// RtcEventLogs. Another use case is online logging of data in test calls. | ||
class DelayVariationCalculator { | ||
public: | ||
struct TimeSeries { | ||
// Time series of RTP timestamps `t(n)` for each frame `n`. | ||
SamplesStatsCounter rtp_timestamps; | ||
// Time series of local arrival timestamps `r(n)` for each frame. | ||
SamplesStatsCounter arrival_times_ms; | ||
// Time series of sizes `s(n)` for each frame. | ||
SamplesStatsCounter sizes_bytes; | ||
// Time series of `d_t(n) = t(n) - t(n-1)` for each frame. | ||
SamplesStatsCounter inter_departure_times_ms; | ||
// Time series of `d_r(n) = r(n) - r(n-1)` for each frame. | ||
SamplesStatsCounter inter_arrival_times_ms; | ||
// Time series of `d_r(n) - d_t(n) = (r(n) - r(n-1)) - (t(n) - t(n-1))` | ||
// for each frame. | ||
SamplesStatsCounter inter_delay_variations_ms; | ||
// Time series of `s(n) - s(n-1)`, for each frame. | ||
SamplesStatsCounter inter_size_variations_bytes; | ||
}; | ||
|
||
DelayVariationCalculator() = default; | ||
~DelayVariationCalculator() = default; | ||
|
||
void Insert(uint32_t rtp_timestamp, | ||
Timestamp arrival_time, | ||
DataSize size, | ||
absl::optional<int> spatial_layer = absl::nullopt, | ||
absl::optional<int> temporal_layer = absl::nullopt, | ||
absl::optional<VideoFrameType> frame_type = absl::nullopt); | ||
|
||
const TimeSeries& time_series() const { return time_series_; } | ||
|
||
private: | ||
struct Frame { | ||
uint32_t rtp_timestamp; | ||
int64_t unwrapped_rtp_timestamp; | ||
Timestamp arrival_time; | ||
DataSize size; | ||
absl::optional<int> spatial_layer; | ||
absl::optional<int> temporal_layer; | ||
absl::optional<VideoFrameType> frame_type; | ||
}; | ||
using MetadataT = std::map<std::string, std::string>; | ||
|
||
void InsertFirstFrame(const Frame& frame, | ||
Timestamp sample_time, | ||
MetadataT sample_metadata); | ||
void InsertFrame(const Frame& frame, | ||
Timestamp sample_time, | ||
MetadataT sample_metadata); | ||
|
||
MetadataT BuildMetadata(const Frame& frame); | ||
|
||
RtpTimestampUnwrapper unwrapper_; | ||
absl::optional<Frame> prev_frame_ = absl::nullopt; | ||
TimeSeries time_series_; | ||
}; | ||
|
||
} // namespace test | ||
} // namespace webrtc | ||
|
||
#endif // TEST_JITTER_DELAY_VARIATION_CALCULATOR_H_ |
Oops, something went wrong.