[DVQA] Add QP metric to the video analyzer.

Bug: b/240540204
Change-Id: I43fbb779bac10e27f2607ce1545476b1389d7c69
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/283763
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38686}
This commit is contained in:
Artem Titov
2022-11-18 18:41:22 +01:00
committed by WebRTC LUCI CQ
parent bf28277774
commit 4440426792
12 changed files with 89 additions and 6 deletions

View File

@ -62,6 +62,8 @@ class VideoQualityAnalyzerInterface
// https://crbug.com/webrtc/11443: improve stats API to make available
// there.
uint32_t target_encode_bitrate = 0;
// Encoder quantizer value.
int qp = -1;
};
// Contains extra statistic provided by video decoder.
struct DecoderStats {

View File

@ -653,6 +653,7 @@ if (rtc_include_tests && !build_with_chromium) {
"../rtc_base/synchronization:mutex",
"../rtc_base/system:file_wrapper",
"pc/e2e:e2e_unittests",
"pc/e2e/analyzer/video:video_analyzer_unittests",
"peer_scenario/tests",
"scenario:scenario_unittests",
"time_controller:time_controller",

View File

@ -347,9 +347,9 @@ void DefaultVideoQualityAnalyzer::OnFrameEncoded(
used_encoder.last_frame_id = frame_id;
used_encoder.switched_on_at = now;
used_encoder.switched_from_at = now;
frame_in_flight.OnFrameEncoded(now, encoded_image._frameType,
DataSize::Bytes(encoded_image.size()),
stats.target_encode_bitrate, used_encoder);
frame_in_flight.OnFrameEncoded(
now, encoded_image._frameType, DataSize::Bytes(encoded_image.size()),
stats.target_encode_bitrate, stats.qp, used_encoder);
if (options_.report_infra_metrics) {
analyzer_stats_.on_frame_encoded_processing_time_ms.AddSample(
@ -1132,6 +1132,9 @@ void DefaultVideoQualityAnalyzer::ReportResults(
"target_encode_bitrate", test_case_name,
stats.target_encode_bitrate / 1000, Unit::kKilobitsPerSecond,
ImprovementDirection::kNeitherIsBetter, metric_metadata);
metrics_logger_->LogMetric("qp", test_case_name, stats.qp, Unit::kUnitless,
ImprovementDirection::kSmallerIsBetter,
metric_metadata);
metrics_logger_->LogSingleValueMetric(
"actual_encode_bitrate", test_case_name,
static_cast<double>(stats.total_encoded_images_payload) /

View File

@ -88,11 +88,13 @@ void FrameInFlight::OnFrameEncoded(webrtc::Timestamp time,
VideoFrameType frame_type,
DataSize encoded_image_size,
uint32_t target_encode_bitrate,
int qp,
StreamCodecInfo used_encoder) {
encoded_time_ = time;
frame_type_ = frame_type;
encoded_image_size_ = encoded_image_size;
target_encode_bitrate_ += target_encode_bitrate;
qp_values_.push_back(qp);
// Update used encoder info. If simulcast/SVC is used, this method can
// be called multiple times, in such case we should preserve the value
// of `used_encoder_.switched_on_at` from the first invocation as the
@ -182,6 +184,8 @@ FrameStats FrameInFlight::GetStatsForPeer(size_t peer) const {
stats.encoded_frame_type = frame_type_;
stats.encoded_image_size = encoded_image_size_;
stats.used_encoder = used_encoder_;
stats.qp_values.insert(stats.qp_values.begin(), qp_values_.begin(),
qp_values_.end());
absl::optional<ReceiverFrameStats> receiver_stats =
MaybeGetValue<ReceiverFrameStats>(receiver_stats_, peer);

View File

@ -87,6 +87,7 @@ class FrameInFlight {
VideoFrameType frame_type,
DataSize encoded_image_size,
uint32_t target_encode_bitrate,
int qp,
StreamCodecInfo used_encoder);
bool HasEncodedTime() const { return encoded_time_.IsFinite(); }
@ -152,6 +153,7 @@ class FrameInFlight {
VideoFrameType frame_type_ = VideoFrameType::kEmptyFrame;
DataSize encoded_image_size_ = DataSize::Bytes(0);
uint32_t target_encode_bitrate_ = 0;
std::vector<int> qp_values_;
// Can be not set if frame was dropped by encoder.
absl::optional<StreamCodecInfo> used_encoder_ = absl::nullopt;
// Map from the receiver peer's index to frame stats for that peer.

View File

@ -470,6 +470,9 @@ void DefaultVideoQualityAnalyzerFramesComparator::ProcessComparison(
frame_stats.encoded_image_size.bytes();
stats->target_encode_bitrate.AddSample(StatsSample(
frame_stats.target_encode_bitrate, frame_stats.encoded_time, metadata));
for (const int qp : frame_stats.qp_values) {
stats->qp.AddSample(StatsSample(qp, frame_stats.encoded_time, metadata));
}
// Stats sliced on encoded frame type.
if (frame_stats.encoded_frame_type == VideoFrameType::kVideoFrameKey) {

View File

@ -377,6 +377,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
expectEmpty(stats.target_encode_bitrate);
expectEmpty(stats.qp);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 0);
@ -436,6 +437,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
expectEmpty(stats.target_encode_bitrate);
expectEmpty(stats.qp);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 0);
@ -476,6 +478,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
comparator.Start(/*max_threads_count=*/1);
comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2,
@ -503,6 +506,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -544,6 +548,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameDelta;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
comparator.Start(/*max_threads_count=*/1);
comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2,
@ -571,6 +576,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -612,6 +618,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -644,6 +651,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.recv_key_frame_size_bytes), 500.0);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -685,6 +693,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -724,6 +733,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
EXPECT_GE(GetFirstOrDie(stats.resolution_of_decoded_frame), 200 * 100.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.recv_key_frame_size_bytes), 500.0);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -766,6 +776,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -802,6 +813,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.recv_key_frame_size_bytes), 500.0);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -864,6 +876,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
expectEmpty(stats.target_encode_bitrate);
expectEmpty(stats.qp);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 0);
@ -923,6 +936,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
expectEmpty(stats.target_encode_bitrate);
expectEmpty(stats.qp);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 0);
@ -963,6 +977,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
comparator.Start(/*max_threads_count=*/1);
comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2,
@ -990,6 +1005,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -1031,6 +1047,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameDelta;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
comparator.Start(/*max_threads_count=*/1);
comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2,
@ -1058,6 +1075,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -1105,6 +1123,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -1143,6 +1162,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
expectEmpty(stats.recv_key_frame_size_bytes);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -1185,6 +1205,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -1221,6 +1242,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
expectEmpty(stats.resolution_of_decoded_frame);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.recv_key_frame_size_bytes), 500.0);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -1267,6 +1289,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -1307,6 +1330,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
expectEmpty(stats.time_between_freezes_ms);
EXPECT_GE(GetFirstOrDie(stats.resolution_of_decoded_frame), 200 * 100.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.qp), 5.0);
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.recv_key_frame_size_bytes), 500.0);
expectEmpty(stats.recv_delta_frame_size_bytes);
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
@ -1350,6 +1374,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, AllStatsHaveMetadataSet) {
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.encoded_image_size = DataSize::Bytes(1000);
frame_stats.target_encode_bitrate = 2000;
frame_stats.qp_values = {5, 5};
// Frame pre decoded
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
@ -1386,6 +1411,7 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, AllStatsHaveMetadataSet) {
AssertFirstMetadataHasField(stats.resolution_of_decoded_frame, "frame_id",
"1");
AssertFirstMetadataHasField(stats.target_encode_bitrate, "frame_id", "1");
AssertFirstMetadataHasField(stats.qp, "frame_id", "1");
AssertFirstMetadataHasField(stats.recv_key_frame_size_bytes, "frame_id", "1");
expectEmpty(stats.recv_delta_frame_size_bytes);

View File

@ -14,6 +14,7 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "api/units/data_size.h"
@ -62,6 +63,10 @@ struct FrameStats {
VideoFrameType pre_decoded_frame_type = VideoFrameType::kEmptyFrame;
DataSize pre_decoded_image_size = DataSize::Bytes(0);
uint32_t target_encode_bitrate = 0;
// There can be multiple qp values for single video frame when simulcast
// or SVC is used. In such case multiple EncodedImage's are created by encoder
// and each of it will have its own qp value.
std::vector<int> qp_values;
absl::optional<int> decoded_frame_width = absl::nullopt;
absl::optional<int> decoded_frame_height = absl::nullopt;

View File

@ -277,6 +277,11 @@ TEST(DefaultVideoQualityAnalyzerMetricNamesTest, MetricNamesForP2PAreCorrect) {
.name = "target_encode_bitrate",
.unit = Unit::kKilobitsPerSecond,
.improvement_direction = ImprovementDirection::kNeitherIsBetter},
MetricValidationInfo{
.test_case = "test_case/alice_video",
.name = "qp",
.unit = Unit::kUnitless,
.improvement_direction = ImprovementDirection::kSmallerIsBetter},
MetricValidationInfo{
.test_case = "test_case/alice_video",
.name = "actual_encode_bitrate",
@ -446,6 +451,11 @@ TEST(DefaultVideoQualityAnalyzerMetricNamesTest,
.name = "target_encode_bitrate",
.unit = Unit::kKilobitsPerSecond,
.improvement_direction = ImprovementDirection::kNeitherIsBetter},
MetricValidationInfo{
.test_case = "test_case/alice_video_alice_bob",
.name = "qp",
.unit = Unit::kUnitless,
.improvement_direction = ImprovementDirection::kSmallerIsBetter},
MetricValidationInfo{
.test_case = "test_case/alice_video_alice_bob",
.name = "actual_encode_bitrate",
@ -583,6 +593,11 @@ TEST(DefaultVideoQualityAnalyzerMetricNamesTest,
.name = "target_encode_bitrate",
.unit = Unit::kKilobitsPerSecond,
.improvement_direction = ImprovementDirection::kNeitherIsBetter},
MetricValidationInfo{
.test_case = "test_case/alice_video_alice_charlie",
.name = "qp",
.unit = Unit::kUnitless,
.improvement_direction = ImprovementDirection::kSmallerIsBetter},
MetricValidationInfo{
.test_case = "test_case/alice_video_alice_charlie",
.name = "actual_encode_bitrate",
@ -656,10 +671,10 @@ TEST(DefaultVideoQualityAnalyzerMetricNamesTest,
std::vector<std::string> metrics =
ToTestCases(metrics_logger.GetCollectedMetrics());
EXPECT_THAT(metrics, SizeIs(55));
EXPECT_THAT(metrics, Contains("test_case/alice_video_alice_bob").Times(27));
EXPECT_THAT(metrics, SizeIs(57));
EXPECT_THAT(metrics, Contains("test_case/alice_video_alice_bob").Times(28));
EXPECT_THAT(metrics,
Contains("test_case/alice_video_alice_charlie").Times(27));
Contains("test_case/alice_video_alice_charlie").Times(28));
EXPECT_THAT(metrics, Contains("test_case").Times(1));
}

View File

@ -145,6 +145,7 @@ struct StreamStats {
SamplesStatsCounter time_between_freezes_ms;
SamplesStatsCounter resolution_of_decoded_frame;
SamplesStatsCounter target_encode_bitrate;
SamplesStatsCounter qp;
int64_t total_encoded_images_payload = 0;
// Counters on which phase how many frames were dropped.

View File

@ -290,6 +290,7 @@ EncodedImageCallback::Result QualityAnalyzingVideoEncoder::OnEncodedImage(
VideoQualityAnalyzerInterface::EncoderStats stats;
stats.encoder_name = codec_name;
stats.target_encode_bitrate = target_encode_bitrate;
stats.qp = encoded_image.qp_;
analyzer_->OnFrameEncoded(peer_name_, frame_id, encoded_image, stats,
discard);

View File

@ -466,6 +466,16 @@ TEST(PeerConnectionE2EQualityTestMetricNamesTest,
"alice_video"},
{MetricMetadataKey::kSenderMetadataKey, "alice"},
{MetricMetadataKey::kReceiverMetadataKey, "bob"}}},
MetricValidationInfo{
.test_case = "test_case/alice_video",
.name = "qp",
.unit = Unit::kUnitless,
.improvement_direction = ImprovementDirection::kSmallerIsBetter,
.metadata = {{MetricMetadataKey::kPeerMetadataKey, "alice"},
{MetricMetadataKey::kVideoStreamMetadataKey,
"alice_video"},
{MetricMetadataKey::kSenderMetadataKey, "alice"},
{MetricMetadataKey::kReceiverMetadataKey, "bob"}}},
MetricValidationInfo{
.test_case = "test_case/alice_video",
.name = "actual_encode_bitrate",
@ -676,6 +686,16 @@ TEST(PeerConnectionE2EQualityTestMetricNamesTest,
"bob_video"},
{MetricMetadataKey::kSenderMetadataKey, "bob"},
{MetricMetadataKey::kReceiverMetadataKey, "alice"}}},
MetricValidationInfo{
.test_case = "test_case/bob_video",
.name = "qp",
.unit = Unit::kUnitless,
.improvement_direction = ImprovementDirection::kSmallerIsBetter,
.metadata = {{MetricMetadataKey::kPeerMetadataKey, "bob"},
{MetricMetadataKey::kVideoStreamMetadataKey,
"bob_video"},
{MetricMetadataKey::kSenderMetadataKey, "bob"},
{MetricMetadataKey::kReceiverMetadataKey, "alice"}}},
MetricValidationInfo{
.test_case = "test_case",
.name = "cpu_usage_%",