Add header extension reader/writer for automatic corruption detection
R=sprang@webrtc.org Bug: b/358039777 Change-Id: I84f447edf0524d4ac6c55cfd96cffe6abb77aaa9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/359760 Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Fanny Linderborg <linderborg@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42791}
This commit is contained in:
parent
97ba6afb37
commit
aa9e557c81
@ -523,6 +523,21 @@ rtc_library("rtp_packetizer_av1_test_helper") {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("corruption_detection_extension") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"source/corruption_detection_extension.cc",
|
||||
"source/corruption_detection_extension.h",
|
||||
]
|
||||
deps = [
|
||||
":rtp_rtcp_format",
|
||||
"../../api:array_view",
|
||||
"../../common_video:common_video",
|
||||
"//third_party/abseil-cpp/absl/container:inlined_vector",
|
||||
"//third_party/abseil-cpp/absl/strings:string_view",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
if (!build_with_chromium) {
|
||||
rtc_executable("test_packet_masks_metrics") {
|
||||
@ -652,6 +667,7 @@ if (rtc_include_tests) {
|
||||
}
|
||||
|
||||
deps = [
|
||||
":corruption_detection_extension_unittest",
|
||||
":fec_test_helper",
|
||||
":frame_transformer_factory_unittest",
|
||||
":leb128",
|
||||
@ -752,4 +768,15 @@ if (rtc_include_tests) {
|
||||
"//third_party/abseil-cpp/absl/memory",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("corruption_detection_extension_unittest") {
|
||||
testonly = true
|
||||
sources = [ "source/corruption_detection_extension_unittest.cc" ]
|
||||
deps = [
|
||||
":corruption_detection_extension",
|
||||
"../../common_video:common_video",
|
||||
"../../test:test_support",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
126
modules/rtp_rtcp/source/corruption_detection_extension.cc
Normal file
126
modules/rtp_rtcp/source/corruption_detection_extension.cc
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2024 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 "modules/rtp_rtcp/source/corruption_detection_extension.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/container/inlined_vector.h"
|
||||
#include "api/array_view.h"
|
||||
#include "common_video/corruption_detection_message.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
constexpr size_t kMandatoryPayloadBytes = 1;
|
||||
constexpr size_t kConfigurationBytes = 3;
|
||||
constexpr double kMaxValueForStdDev = 40.0;
|
||||
|
||||
} // namespace
|
||||
|
||||
// The message format of the header extension:
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |B| seq# index | kernel size | Y err | UV err| sample 0 |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | sample 1 | sample 2 | … up to sample <=12
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// * B (1 bit): If the sequence number should be interpreted as the MSB or LSB
|
||||
// of the full size 14 bit sequence index described in the next point.
|
||||
// * seq# index (7 bits): The index into the Halton sequence (used to locate
|
||||
// where the samples should be drawn from).
|
||||
// * If B is set: the 7 most significant bits of the true index. The 7 least
|
||||
// significant bits of the true index shall be interpreted as 0. This is
|
||||
// because this is the point where we can guarantee that the sender and
|
||||
// receiver has the same full index). For this reason, B must only be set
|
||||
// for key frames.
|
||||
// * If B is not set: The 7 LSB of the true index. The 7 most significant bits
|
||||
// should be inferred based on the most recent message.
|
||||
// * kernel size (8 bits): The standard deviation of the gaussian filter used
|
||||
// to weigh the samples. The value is scaled using a linear map:
|
||||
// 0 = 0.0 to 255 = 40.0. A kernel size of 0 is interpreted as directly using
|
||||
// just the sample value at the desired coordinate, without any weighting.
|
||||
// * Y err (4 bits): The allowed error for the luma channel.
|
||||
// * UV err (4 bits): The allowed error for the chroma channels.
|
||||
// * Sample N (8 bits): The N:th filtered sample from the input image. Each
|
||||
// sample represents a new point in one of the image planes, the plane and
|
||||
// coordinates being determined by index into the Halton sequence (starting at
|
||||
// seq# index and is incremented by one for each sample). Each sample has gone
|
||||
// through a Gaussian filter with the kernel size specified above. The samples
|
||||
// have been floored to the nearest integer.
|
||||
//
|
||||
// A special case is so called "synchronization" messages. These are messages
|
||||
// that only contains the first byte. They always have B set and are used to
|
||||
// keep the sender and receiver in sync even if no "full" messages have been
|
||||
// sent for a while.
|
||||
|
||||
bool CorruptionDetectionExtension::Parse(rtc::ArrayView<const uint8_t> data,
|
||||
CorruptionDetectionMessage* message) {
|
||||
if (message == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if ((data.size() != kMandatoryPayloadBytes &&
|
||||
data.size() <= kConfigurationBytes) ||
|
||||
data.size() > 16) {
|
||||
return false;
|
||||
}
|
||||
message->interpret_sequence_index_as_most_significant_bits_ = data[0] >> 7;
|
||||
message->sequence_index_ = data[0] & 0b0111'1111;
|
||||
if (data.size() == kMandatoryPayloadBytes) {
|
||||
return true;
|
||||
}
|
||||
message->std_dev_ = data[1] * kMaxValueForStdDev / 255.0;
|
||||
uint8_t channel_error_thresholds = data[2];
|
||||
message->luma_error_threshold_ = channel_error_thresholds >> 4;
|
||||
message->chroma_error_threshold_ = channel_error_thresholds & 0xF;
|
||||
message->sample_values_.assign(data.cbegin() + kConfigurationBytes,
|
||||
data.cend());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CorruptionDetectionExtension::Write(
|
||||
rtc::ArrayView<uint8_t> data,
|
||||
const CorruptionDetectionMessage& message) {
|
||||
if (data.size() != ValueSize(message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data[0] = message.sequence_index() & 0b0111'1111;
|
||||
if (message.interpret_sequence_index_as_most_significant_bits()) {
|
||||
data[0] |= 0b1000'0000;
|
||||
}
|
||||
if (message.sample_values().empty()) {
|
||||
return true;
|
||||
}
|
||||
data[1] = static_cast<uint8_t>(
|
||||
std::round(message.std_dev() / kMaxValueForStdDev * 255.0));
|
||||
data[2] = (message.luma_error_threshold() << 4) |
|
||||
(message.chroma_error_threshold() & 0xF);
|
||||
rtc::ArrayView<uint8_t> sample_values = data.subview(kConfigurationBytes);
|
||||
for (size_t i = 0; i < message.sample_values().size(); ++i) {
|
||||
sample_values[i] = std::floor(message.sample_values()[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t CorruptionDetectionExtension::ValueSize(
|
||||
const CorruptionDetectionMessage& message) {
|
||||
if (message.sample_values_.empty()) {
|
||||
return kMandatoryPayloadBytes;
|
||||
}
|
||||
return kConfigurationBytes + message.sample_values_.size();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
50
modules/rtp_rtcp/source/corruption_detection_extension.h
Normal file
50
modules/rtp_rtcp/source/corruption_detection_extension.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2024 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 MODULES_RTP_RTCP_SOURCE_CORRUPTION_DETECTION_EXTENSION_H_
|
||||
#define MODULES_RTP_RTCP_SOURCE_CORRUPTION_DETECTION_EXTENSION_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/array_view.h"
|
||||
#include "common_video/corruption_detection_message.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// RTP Corruption Detection Header Extension.
|
||||
//
|
||||
// The class reads and writes the corruption detection RTP header extension.
|
||||
// The class implements traits so that the class is compatible with being an
|
||||
// argument to the templated `RtpPacket::GetExtension` and
|
||||
// `RtpPacketToSend::SetExtension` methods.
|
||||
class CorruptionDetectionExtension {
|
||||
public:
|
||||
using value_type = CorruptionDetectionMessage;
|
||||
|
||||
// TODO: b/358039777 - Change to our `RTPExtensionType` when available.
|
||||
static constexpr RTPExtensionType kId = kRtpExtensionNumberOfExtensions;
|
||||
static constexpr char kCorruptionDetectionUri[] =
|
||||
"http://www.webrtc.org/experiments/rtp-hdrext/corruption-detection";
|
||||
|
||||
static constexpr absl::string_view Uri() { return kCorruptionDetectionUri; }
|
||||
static bool Parse(rtc::ArrayView<const uint8_t> data,
|
||||
CorruptionDetectionMessage* message);
|
||||
static bool Write(rtc::ArrayView<uint8_t> data,
|
||||
const CorruptionDetectionMessage& message);
|
||||
// Size of the header extension in bytes.
|
||||
static size_t ValueSize(const CorruptionDetectionMessage& message);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_RTP_RTCP_SOURCE_CORRUPTION_DETECTION_EXTENSION_H_
|
||||
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright 2024 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 "modules/rtp_rtcp/source/corruption_detection_extension.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "common_video/corruption_detection_message.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::DoubleEq;
|
||||
using ::testing::ElementsAre;
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest, ValueSizeIs1UnlessSamplesAreSpecified) {
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
||||
.WithStdDev(8.0)
|
||||
.WithSampleValues({})
|
||||
.Build();
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_EQ(CorruptionDetectionExtension::ValueSize(*kMessage), size_t{1});
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
GivenSamplesTheValueSizeIsTheSumOfTheNumberOfSamplesPlus3) {
|
||||
const double kSampleValues[] = {1.0, 2.0, 3.0, 4.0};
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSampleValues(kSampleValues)
|
||||
.Build();
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_EQ(CorruptionDetectionExtension::ValueSize(*kMessage), size_t{7});
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
WritesMandatoryWhenEnoughMemoryIsAllocatedWithoutSamples) {
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
||||
.Build();
|
||||
uint8_t data[] = {0};
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
EXPECT_THAT(data, ElementsAre(0b1110'1111));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
FailsToWriteWhenTooMuchMemoryIsAllocatedWithoutSamples) {
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
||||
.Build();
|
||||
uint8_t data[] = {0, 0, 0};
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_FALSE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
FailsToWriteWhenTooMuchMemoryIsAllocatedWithSamples) {
|
||||
const double kSampleValues[] = {1.0};
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
||||
.WithStdDev(8.0)
|
||||
.WithSampleValues(kSampleValues)
|
||||
.Build();
|
||||
uint8_t data[] = {0, 0, 0, 0, 0};
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_FALSE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
WritesEverythingWhenEnoughMemoryIsAllocatedWithSamples) {
|
||||
const double kSampleValues[] = {1.0};
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
||||
.WithStdDev(8.0)
|
||||
.WithSampleValues(kSampleValues)
|
||||
.Build();
|
||||
uint8_t data[] = {0, 0, 0, 0};
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
EXPECT_THAT(data, ElementsAre(0b1110'1111, 51, 0, 1));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
WritesEverythingToExtensionWhenUpperBitsAreUsedForSequenceIndex) {
|
||||
const double kSampleValues[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0,
|
||||
8.0, 9.0, 10.0, 11.0, 12.0, 13.0};
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(true)
|
||||
.WithStdDev(34.5098) // 220 / (255.0 * 40.0)
|
||||
.WithLumaErrorThreshold(0b1110)
|
||||
.WithChromaErrorThreshold(0b1111)
|
||||
.WithSampleValues(kSampleValues)
|
||||
.Build();
|
||||
uint8_t data[16];
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
EXPECT_THAT(data, ElementsAre(0b1110'1111, 220, 0b1110'1111, 1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
WritesEverythingToExtensionWhenLowerBitsAreUsedForSequenceIndex) {
|
||||
const double kSampleValues[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0,
|
||||
8.0, 9.0, 10.0, 11.0, 12.0, 13.0};
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSequenceIndex(0b0110'1111)
|
||||
.WithInterpretSequenceIndexAsMostSignificantBits(false)
|
||||
.WithStdDev(34.5098) // 220 / (255.0 * 40.0)
|
||||
.WithLumaErrorThreshold(0b1110)
|
||||
.WithChromaErrorThreshold(0b1111)
|
||||
.WithSampleValues(kSampleValues)
|
||||
.Build();
|
||||
uint8_t data[16];
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
EXPECT_THAT(data, ElementsAre(0b0110'1111, 220, 0b1110'1111, 1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest, TruncatesSampleValuesWhenWriting) {
|
||||
const double kSampleValues[] = {1.4, 2.5, 3.6};
|
||||
const absl::optional<CorruptionDetectionMessage> kMessage =
|
||||
CorruptionDetectionMessage::Builder()
|
||||
.WithSampleValues(kSampleValues)
|
||||
.Build();
|
||||
uint8_t data[6];
|
||||
|
||||
ASSERT_NE(kMessage, absl::nullopt);
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Write(data, *kMessage));
|
||||
EXPECT_THAT(data, ElementsAre(0, 0, 0, 1, 2, 3));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest, ParsesMandatoryFieldsFromExtension) {
|
||||
CorruptionDetectionMessage message;
|
||||
const uint8_t kData[] = {0b1110'1111};
|
||||
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Parse(kData, &message));
|
||||
EXPECT_EQ(message.sequence_index(), 0b0110'1111);
|
||||
EXPECT_TRUE(message.interpret_sequence_index_as_most_significant_bits());
|
||||
EXPECT_THAT(message.std_dev(), DoubleEq(0.0));
|
||||
EXPECT_EQ(message.luma_error_threshold(), 0);
|
||||
EXPECT_EQ(message.chroma_error_threshold(), 0);
|
||||
EXPECT_THAT(message.sample_values(), ElementsAre());
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest, FailsToParseWhenGivenTooFewFields) {
|
||||
CorruptionDetectionMessage message;
|
||||
const uint8_t kData[] = {0b1110'1111, 8, 0};
|
||||
|
||||
EXPECT_FALSE(CorruptionDetectionExtension::Parse(kData, &message));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
ParsesEverythingFromExtensionWhenUpperBitsAreUsedForSequenceIndex) {
|
||||
CorruptionDetectionMessage message;
|
||||
const uint8_t kSampleValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
|
||||
const uint8_t kData[] = {0b1100'0100, 220,
|
||||
0b1110'1111, kSampleValues[0],
|
||||
kSampleValues[1], kSampleValues[2],
|
||||
kSampleValues[3], kSampleValues[4],
|
||||
kSampleValues[5], kSampleValues[6],
|
||||
kSampleValues[7], kSampleValues[8],
|
||||
kSampleValues[9], kSampleValues[10],
|
||||
kSampleValues[11], kSampleValues[12]};
|
||||
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Parse(kData, &message));
|
||||
EXPECT_EQ(message.sequence_index(), 0b0100'0100);
|
||||
EXPECT_TRUE(message.interpret_sequence_index_as_most_significant_bits());
|
||||
EXPECT_THAT(message.std_dev(),
|
||||
DoubleEq(34.509803921568626)); // 220 / (255.0 * 40.0)
|
||||
EXPECT_EQ(message.luma_error_threshold(), 0b1110);
|
||||
EXPECT_EQ(message.chroma_error_threshold(), 0b1111);
|
||||
EXPECT_EQ(message.sample_values().size(), sizeof(kSampleValues));
|
||||
for (size_t i = 0; i < sizeof(kSampleValues); ++i) {
|
||||
EXPECT_EQ(message.sample_values()[i], kSampleValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
ParsesEverythingFromExtensionWhenLowerBitsAreUsedForSequenceIndex) {
|
||||
CorruptionDetectionMessage message;
|
||||
const uint8_t kSampleValues[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
|
||||
const uint8_t kData[] = {0b0100'0100, 220,
|
||||
0b1110'1111, kSampleValues[0],
|
||||
kSampleValues[1], kSampleValues[2],
|
||||
kSampleValues[3], kSampleValues[4],
|
||||
kSampleValues[5], kSampleValues[6],
|
||||
kSampleValues[7], kSampleValues[8],
|
||||
kSampleValues[9], kSampleValues[10],
|
||||
kSampleValues[11], kSampleValues[12]};
|
||||
|
||||
EXPECT_TRUE(CorruptionDetectionExtension::Parse(kData, &message));
|
||||
EXPECT_EQ(message.sequence_index(), 0b0100'0100);
|
||||
EXPECT_FALSE(message.interpret_sequence_index_as_most_significant_bits());
|
||||
EXPECT_THAT(message.std_dev(),
|
||||
DoubleEq(34.509803921568626)); // 220 / (255.0 * 40.0)
|
||||
EXPECT_EQ(message.luma_error_threshold(), 0b1110);
|
||||
EXPECT_EQ(message.chroma_error_threshold(), 0b1111);
|
||||
EXPECT_EQ(message.sample_values().size(), sizeof(kSampleValues));
|
||||
for (size_t i = 0; i < sizeof(kSampleValues); ++i) {
|
||||
EXPECT_EQ(message.sample_values()[i], kSampleValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest, FailsToParseWhenGivenNullptrAsOutput) {
|
||||
const uint8_t kData[] = {0, 0, 0};
|
||||
|
||||
EXPECT_FALSE(CorruptionDetectionExtension::Parse(kData, nullptr));
|
||||
}
|
||||
|
||||
TEST(CorruptionDetectionExtensionTest,
|
||||
FailsToParseWhenTooManySamplesAreSpecified) {
|
||||
CorruptionDetectionMessage message;
|
||||
uint8_t data[17];
|
||||
|
||||
EXPECT_FALSE(CorruptionDetectionExtension::Parse(data, &message));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
Loading…
x
Reference in New Issue
Block a user