Add converter from CorruptionDetectionMessage To FrameInstrumentationData

Bug: webrtc:358039777
Change-Id: I041b9a84e1f93d7e7a3d31b8f0f33c94eeca76a6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/363700
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Auto-Submit: Fanny Linderborg <linderborg@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43081}
This commit is contained in:
Fanny Linderborg 2024-09-25 14:34:42 +02:00 committed by WebRTC LUCI CQ
parent b04af61b4e
commit a2d515584e
3 changed files with 187 additions and 11 deletions

View File

@ -11,6 +11,7 @@
#include "common_video/corruption_detection_converters.h" #include "common_video/corruption_detection_converters.h"
#include <optional> #include <optional>
#include <vector>
#include "common_video/corruption_detection_message.h" #include "common_video/corruption_detection_message.h"
#include "common_video/frame_instrumentation_data.h" #include "common_video/frame_instrumentation_data.h"
@ -20,6 +21,30 @@ namespace webrtc {
namespace { namespace {
int GetFullSequenceIndex(int previous_sequence_index,
int sequence_index_update,
bool update_the_most_significant_bits) {
RTC_CHECK_GE(previous_sequence_index, 0)
<< "previous_sequence_index must not be negative";
RTC_CHECK_LE(previous_sequence_index, 0x7FFF)
<< "previous_sequence_index must be at most 15 bits";
RTC_CHECK_GE(sequence_index_update, 0)
<< "sequence_index_update must not be negative";
RTC_CHECK_LE(sequence_index_update, 0b0111'1111)
<< "sequence_index_update must be at most 7 bits";
if (update_the_most_significant_bits) {
// Reset LSB.
return sequence_index_update << 7;
}
int upper_bits = previous_sequence_index & 0b0011'1111'1000'0000;
if (sequence_index_update < (previous_sequence_index & 0b0111'1111)) {
// Assume one and only one wraparound has happened.
upper_bits += 0b1000'0000;
}
// Replace the lowest bits with the bits from the update.
return upper_bits + sequence_index_update;
}
int GetSequenceIndexForMessage(int sequence_index, int GetSequenceIndexForMessage(int sequence_index,
bool communicate_upper_bits) { bool communicate_upper_bits) {
return communicate_upper_bits ? (sequence_index >> 7) return communicate_upper_bits ? (sequence_index >> 7)
@ -28,6 +53,31 @@ int GetSequenceIndexForMessage(int sequence_index,
} // namespace } // namespace
std::optional<FrameInstrumentationData>
ConvertCorruptionDetectionMessageToFrameInstrumentationData(
const CorruptionDetectionMessage& message,
int previous_sequence_index) {
if (previous_sequence_index < 0) {
return std::nullopt;
}
if (message.sample_values().empty()) {
return std::nullopt;
}
int full_sequence_index = GetFullSequenceIndex(
previous_sequence_index, message.sequence_index(),
message.interpret_sequence_index_as_most_significant_bits());
std::vector<double> sample_values(message.sample_values().cbegin(),
message.sample_values().cend());
return FrameInstrumentationData{
.sequence_index = full_sequence_index,
.communicate_upper_bits =
message.interpret_sequence_index_as_most_significant_bits(),
.std_dev = message.std_dev(),
.luma_error_threshold = message.luma_error_threshold(),
.chroma_error_threshold = message.chroma_error_threshold(),
.sample_values = sample_values};
}
std::optional<CorruptionDetectionMessage> std::optional<CorruptionDetectionMessage>
ConvertFrameInstrumentationDataToCorruptionDetectionMessage( ConvertFrameInstrumentationDataToCorruptionDetectionMessage(
const FrameInstrumentationData& data) { const FrameInstrumentationData& data) {

View File

@ -18,6 +18,10 @@
namespace webrtc { namespace webrtc {
std::optional<FrameInstrumentationData>
ConvertCorruptionDetectionMessageToFrameInstrumentationData(
const CorruptionDetectionMessage& message,
int previous_sequence_index);
std::optional<CorruptionDetectionMessage> std::optional<CorruptionDetectionMessage>
ConvertFrameInstrumentationDataToCorruptionDetectionMessage( ConvertFrameInstrumentationDataToCorruptionDetectionMessage(
const FrameInstrumentationData& frame_instrumentation_data); const FrameInstrumentationData& frame_instrumentation_data);

View File

@ -11,6 +11,7 @@
#include "common_video/corruption_detection_converters.h" #include "common_video/corruption_detection_converters.h"
#include <optional> #include <optional>
#include <vector>
#include "common_video/corruption_detection_message.h" #include "common_video/corruption_detection_message.h"
#include "common_video/frame_instrumentation_data.h" #include "common_video/frame_instrumentation_data.h"
@ -23,7 +24,8 @@ namespace {
using ::testing::_; using ::testing::_;
using ::testing::ElementsAre; using ::testing::ElementsAre;
TEST(CorruptionDetectionConvertersTest, ConvertsValidData) { TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ConvertsValidData) {
FrameInstrumentationData data = {.sequence_index = 1, FrameInstrumentationData data = {.sequence_index = 1,
.communicate_upper_bits = false, .communicate_upper_bits = false,
.std_dev = 1.0, .std_dev = 1.0,
@ -42,7 +44,7 @@ TEST(CorruptionDetectionConvertersTest, ConvertsValidData) {
EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0)); EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0));
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSequenceIndexIsNegative) { ReturnsNulloptWhenSequenceIndexIsNegative) {
FrameInstrumentationData data = {.sequence_index = -1, FrameInstrumentationData data = {.sequence_index = -1,
.communicate_upper_bits = false, .communicate_upper_bits = false,
@ -56,7 +58,7 @@ TEST(CorruptionDetectionConvertersTest,
ASSERT_FALSE(message.has_value()); ASSERT_FALSE(message.has_value());
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSequenceIndexIsTooLarge) { ReturnsNulloptWhenSequenceIndexIsTooLarge) {
// Sequence index must be at max 14 bits. // Sequence index must be at max 14 bits.
FrameInstrumentationData data = {.sequence_index = 0x4000, FrameInstrumentationData data = {.sequence_index = 0x4000,
@ -71,7 +73,7 @@ TEST(CorruptionDetectionConvertersTest,
ASSERT_FALSE(message.has_value()); ASSERT_FALSE(message.has_value());
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenThereAreNoSampleValues) { ReturnsNulloptWhenThereAreNoSampleValues) {
// FrameInstrumentationData must by definition have at least one sample value. // FrameInstrumentationData must by definition have at least one sample value.
FrameInstrumentationData data = {.sequence_index = 1, FrameInstrumentationData data = {.sequence_index = 1,
@ -86,7 +88,7 @@ TEST(CorruptionDetectionConvertersTest,
ASSERT_FALSE(message.has_value()); ASSERT_FALSE(message.has_value());
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenNotSpecifyingSampleValues) { ReturnsNulloptWhenNotSpecifyingSampleValues) {
FrameInstrumentationData data = {.sequence_index = 1, FrameInstrumentationData data = {.sequence_index = 1,
.communicate_upper_bits = false, .communicate_upper_bits = false,
@ -99,7 +101,7 @@ TEST(CorruptionDetectionConvertersTest,
ASSERT_FALSE(message.has_value()); ASSERT_FALSE(message.has_value());
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ConvertsSequenceIndexWhenSetToUseUpperBits) { ConvertsSequenceIndexWhenSetToUseUpperBits) {
FrameInstrumentationData data = {.sequence_index = 0b0000'0110'0000'0101, FrameInstrumentationData data = {.sequence_index = 0b0000'0110'0000'0101,
.communicate_upper_bits = true, .communicate_upper_bits = true,
@ -119,7 +121,7 @@ TEST(CorruptionDetectionConvertersTest,
EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0)); EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0));
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ConvertsSequenceIndexWhenSetToUseLowerBits) { ConvertsSequenceIndexWhenSetToUseLowerBits) {
FrameInstrumentationData data = {.sequence_index = 0b0000'0110'0000'0101, FrameInstrumentationData data = {.sequence_index = 0b0000'0110'0000'0101,
.communicate_upper_bits = false, .communicate_upper_bits = false,
@ -139,7 +141,8 @@ TEST(CorruptionDetectionConvertersTest,
EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0)); EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0));
} }
TEST(CorruptionDetectionConvertersTest, ConvertsValidSyncData) { TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
ConvertsValidSyncData) {
FrameInstrumentationSyncData data = {.sequence_index = 1, FrameInstrumentationSyncData data = {.sequence_index = 1,
.communicate_upper_bits = true}; .communicate_upper_bits = true};
@ -151,7 +154,8 @@ TEST(CorruptionDetectionConvertersTest, ConvertsValidSyncData) {
} }
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
TEST(CorruptionDetectionConvertersTest, FailsWhenSetToNotCommunicateUpperBits) { TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
FailsWhenSetToNotCommunicateUpperBits) {
FrameInstrumentationSyncData data = {.sequence_index = 1, FrameInstrumentationSyncData data = {.sequence_index = 1,
.communicate_upper_bits = false}; .communicate_upper_bits = false};
@ -160,7 +164,7 @@ TEST(CorruptionDetectionConvertersTest, FailsWhenSetToNotCommunicateUpperBits) {
} }
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSyncSequenceIndexIsNegative) { ReturnsNulloptWhenSyncSequenceIndexIsNegative) {
FrameInstrumentationSyncData data = {.sequence_index = -1, FrameInstrumentationSyncData data = {.sequence_index = -1,
.communicate_upper_bits = true}; .communicate_upper_bits = true};
@ -170,7 +174,7 @@ TEST(CorruptionDetectionConvertersTest,
ASSERT_FALSE(message.has_value()); ASSERT_FALSE(message.has_value());
} }
TEST(CorruptionDetectionConvertersTest, TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSyncSequenceIndexIsTooLarge) { ReturnsNulloptWhenSyncSequenceIndexIsTooLarge) {
FrameInstrumentationSyncData data = {.sequence_index = 0x4000, FrameInstrumentationSyncData data = {.sequence_index = 0x4000,
.communicate_upper_bits = true}; .communicate_upper_bits = true};
@ -180,5 +184,123 @@ TEST(CorruptionDetectionConvertersTest,
ASSERT_FALSE(message.has_value()); ASSERT_FALSE(message.has_value());
} }
TEST(CorruptionDetectionMessageToFrameInstrumentationData,
FailWhenPreviousSequenceIndexIsNegative) {
std::vector<double> sample_values = {1.0, 2.0, 3.0, 4.0, 5.0};
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder()
.WithSampleValues(sample_values)
.Build();
ASSERT_TRUE(message.has_value());
EXPECT_FALSE(
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message, -1)
.has_value());
}
TEST(CorruptionDetectionMessageToFrameInstrumentationData,
FailWhenNoSampleValuesAreProvided) {
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder().Build();
ASSERT_TRUE(message.has_value());
EXPECT_FALSE(
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message, 0)
.has_value());
}
TEST(CorruptionDetectionMessageToFrameInstrumentationData,
IgnorePreviousSequenceIndexWhenSetToUpdateTheMostSignificantBits) {
std::vector<double> sample_values = {1.0, 2.0, 3.0, 4.0, 5.0};
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder()
.WithSequenceIndex(11)
.WithInterpretSequenceIndexAsMostSignificantBits(true)
.WithSampleValues(sample_values)
.Build();
ASSERT_TRUE(message.has_value());
std::optional<FrameInstrumentationData> data =
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message, 12);
ASSERT_TRUE(data.has_value());
EXPECT_EQ(data->sequence_index, 0b0101'1000'0000);
}
TEST(CorruptionDetectionMessageToFrameInstrumentationData,
UseMessageSequenceIndexWhenHigherThanPrevious) {
std::vector<double> sample_values = {1.0, 2.0, 3.0, 4.0, 5.0};
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder()
.WithSequenceIndex(11)
.WithInterpretSequenceIndexAsMostSignificantBits(false)
.WithSampleValues(sample_values)
.Build();
ASSERT_TRUE(message.has_value());
std::optional<FrameInstrumentationData> data =
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message, 0);
ASSERT_TRUE(data.has_value());
EXPECT_EQ(data->sequence_index, 11);
}
TEST(CorruptionDetectionMessageToFrameInstrumentationData,
IncreaseThePreviousIdxUntilLsbsAreEqualToTheUpdateWhenTheUpdateIsLsbs) {
std::vector<double> sample_values = {1.0, 2.0, 3.0, 4.0, 5.0};
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder()
.WithSequenceIndex(11)
.WithInterpretSequenceIndexAsMostSignificantBits(false)
.WithSampleValues(sample_values)
.Build();
ASSERT_TRUE(message.has_value());
std::optional<FrameInstrumentationData> data =
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message,
1 + 128);
ASSERT_TRUE(data.has_value());
EXPECT_EQ(data->sequence_index, 11 + 128);
}
TEST(CorruptionDetectionMessageToFrameInstrumentationData,
IgnoreIndexUpdateWhenTheLowerBitsSuppliedAreTheSameAsInThePreviousIndex) {
std::vector<double> sample_values = {1.0, 2.0, 3.0, 4.0, 5.0};
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder()
.WithSequenceIndex(11)
.WithInterpretSequenceIndexAsMostSignificantBits(false)
.WithSampleValues(sample_values)
.Build();
ASSERT_TRUE(message.has_value());
std::optional<FrameInstrumentationData> data =
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message,
11 + 128);
ASSERT_TRUE(data.has_value());
EXPECT_EQ(data->sequence_index, 11 + 128);
}
TEST(
CorruptionDetectionMessageToFrameInstrumentationData,
IncreaseTheMsbsByOneAndSetTheMessagesLsbWhenMessageLsbIsLowerThanPrevious) {
std::vector<double> sample_values = {1.0, 2.0, 3.0, 4.0, 5.0};
std::optional<CorruptionDetectionMessage> message =
CorruptionDetectionMessage::Builder()
.WithSequenceIndex(11)
.WithInterpretSequenceIndexAsMostSignificantBits(false)
.WithSampleValues(sample_values)
.Build();
ASSERT_TRUE(message.has_value());
std::optional<FrameInstrumentationData> data =
ConvertCorruptionDetectionMessageToFrameInstrumentationData(*message, 12);
ASSERT_TRUE(data.has_value());
EXPECT_EQ(data->sequence_index, 11 + 128);
}
} // namespace } // namespace
} // namespace webrtc } // namespace webrtc