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}
diff --git a/common_video/corruption_detection_converters.cc b/common_video/corruption_detection_converters.cc
index 74e978d..ad35b25 100644
--- a/common_video/corruption_detection_converters.cc
+++ b/common_video/corruption_detection_converters.cc
@@ -11,6 +11,7 @@
#include "common_video/corruption_detection_converters.h"
#include <optional>
+#include <vector>
#include "common_video/corruption_detection_message.h"
#include "common_video/frame_instrumentation_data.h"
@@ -20,6 +21,30 @@
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,
bool communicate_upper_bits) {
return communicate_upper_bits ? (sequence_index >> 7)
@@ -28,6 +53,31 @@
} // 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>
ConvertFrameInstrumentationDataToCorruptionDetectionMessage(
const FrameInstrumentationData& data) {
diff --git a/common_video/corruption_detection_converters.h b/common_video/corruption_detection_converters.h
index 7387fee..a8c8640 100644
--- a/common_video/corruption_detection_converters.h
+++ b/common_video/corruption_detection_converters.h
@@ -18,6 +18,10 @@
namespace webrtc {
+std::optional<FrameInstrumentationData>
+ConvertCorruptionDetectionMessageToFrameInstrumentationData(
+ const CorruptionDetectionMessage& message,
+ int previous_sequence_index);
std::optional<CorruptionDetectionMessage>
ConvertFrameInstrumentationDataToCorruptionDetectionMessage(
const FrameInstrumentationData& frame_instrumentation_data);
diff --git a/common_video/corruption_detection_converters_unittest.cc b/common_video/corruption_detection_converters_unittest.cc
index eccd5f8..a4b717f 100644
--- a/common_video/corruption_detection_converters_unittest.cc
+++ b/common_video/corruption_detection_converters_unittest.cc
@@ -11,6 +11,7 @@
#include "common_video/corruption_detection_converters.h"
#include <optional>
+#include <vector>
#include "common_video/corruption_detection_message.h"
#include "common_video/frame_instrumentation_data.h"
@@ -23,7 +24,8 @@
using ::testing::_;
using ::testing::ElementsAre;
-TEST(CorruptionDetectionConvertersTest, ConvertsValidData) {
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
+ ConvertsValidData) {
FrameInstrumentationData data = {.sequence_index = 1,
.communicate_upper_bits = false,
.std_dev = 1.0,
@@ -42,7 +44,7 @@
EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0));
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSequenceIndexIsNegative) {
FrameInstrumentationData data = {.sequence_index = -1,
.communicate_upper_bits = false,
@@ -56,7 +58,7 @@
ASSERT_FALSE(message.has_value());
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSequenceIndexIsTooLarge) {
// Sequence index must be at max 14 bits.
FrameInstrumentationData data = {.sequence_index = 0x4000,
@@ -71,7 +73,7 @@
ASSERT_FALSE(message.has_value());
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenThereAreNoSampleValues) {
// FrameInstrumentationData must by definition have at least one sample value.
FrameInstrumentationData data = {.sequence_index = 1,
@@ -86,7 +88,7 @@
ASSERT_FALSE(message.has_value());
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenNotSpecifyingSampleValues) {
FrameInstrumentationData data = {.sequence_index = 1,
.communicate_upper_bits = false,
@@ -99,7 +101,7 @@
ASSERT_FALSE(message.has_value());
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ConvertsSequenceIndexWhenSetToUseUpperBits) {
FrameInstrumentationData data = {.sequence_index = 0b0000'0110'0000'0101,
.communicate_upper_bits = true,
@@ -119,7 +121,7 @@
EXPECT_THAT(message->sample_values(), ElementsAre(1.0, 2.0, 3.0, 4.0, 5.0));
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationDataToCorruptionDetectionMessageTest,
ConvertsSequenceIndexWhenSetToUseLowerBits) {
FrameInstrumentationData data = {.sequence_index = 0b0000'0110'0000'0101,
.communicate_upper_bits = false,
@@ -139,7 +141,8 @@
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,
.communicate_upper_bits = true};
@@ -151,7 +154,8 @@
}
#if GTEST_HAS_DEATH_TEST
-TEST(CorruptionDetectionConvertersTest, FailsWhenSetToNotCommunicateUpperBits) {
+TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
+ FailsWhenSetToNotCommunicateUpperBits) {
FrameInstrumentationSyncData data = {.sequence_index = 1,
.communicate_upper_bits = false};
@@ -160,7 +164,7 @@
}
#endif // GTEST_HAS_DEATH_TEST
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSyncSequenceIndexIsNegative) {
FrameInstrumentationSyncData data = {.sequence_index = -1,
.communicate_upper_bits = true};
@@ -170,7 +174,7 @@
ASSERT_FALSE(message.has_value());
}
-TEST(CorruptionDetectionConvertersTest,
+TEST(FrameInstrumentationSyncDataToCorruptionDetectionMessageTest,
ReturnsNulloptWhenSyncSequenceIndexIsTooLarge) {
FrameInstrumentationSyncData data = {.sequence_index = 0x4000,
.communicate_upper_bits = true};
@@ -180,5 +184,123 @@
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 webrtc