blob: 2d409f88d875b16962f9ac72ed6e3c3fbd1edd44 [file] [log] [blame]
/*
* 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 <optional>
#include <string>
#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,
std::optional<int> spatial_layer,
std::optional<int> temporal_layer,
std::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