Add support for the Halton sequence
Bug: b/358039777 Change-Id: Id191d584e22cf82384a5d16ed355f41c0bb32b7b Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/358981 Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Fanny Linderborg <linderborg@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42764}
This commit is contained in:
parent
06163404a5
commit
c2a82417e9
@ -959,6 +959,7 @@ if (rtc_include_tests) {
|
||||
"config:encoder_config",
|
||||
"config:streams_config",
|
||||
"config:video_config_tests",
|
||||
"corruption_detection:corruption_detection_tests",
|
||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||
"//third_party/abseil-cpp/absl/functional:any_invocable",
|
||||
"//third_party/abseil-cpp/absl/memory",
|
||||
|
||||
34
video/corruption_detection/BUILD.gn
Normal file
34
video/corruption_detection/BUILD.gn
Normal file
@ -0,0 +1,34 @@
|
||||
# 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.
|
||||
|
||||
import("../../webrtc.gni")
|
||||
|
||||
rtc_library("halton_sequence") {
|
||||
sources = [
|
||||
"halton_sequence.cc",
|
||||
"halton_sequence.h",
|
||||
]
|
||||
deps = [ "../../rtc_base:checks" ]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_library("halton_sequence_unittest") {
|
||||
testonly = true
|
||||
sources = [ "halton_sequence_unittest.cc" ]
|
||||
deps = [
|
||||
":halton_sequence",
|
||||
"../../test/:test_support",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("corruption_detection_tests") {
|
||||
testonly = true
|
||||
sources = []
|
||||
deps = [ ":halton_sequence_unittest" ]
|
||||
}
|
||||
}
|
||||
66
video/corruption_detection/halton_sequence.cc
Normal file
66
video/corruption_detection/halton_sequence.cc
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 "video/corruption_detection/halton_sequence.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
static constexpr int kMaxDimensions = 5;
|
||||
const int kBases[kMaxDimensions] = {2, 3, 5, 7, 11};
|
||||
|
||||
double GetVanDerCorputSequenceElement(int sequence_idx, int base) {
|
||||
if (sequence_idx < 0 || base < 2) {
|
||||
sequence_idx = 0;
|
||||
base = 2;
|
||||
}
|
||||
double element = 0.0;
|
||||
double positional_value = 1.0;
|
||||
int left = sequence_idx;
|
||||
while (left > 0) {
|
||||
positional_value /= base;
|
||||
element += positional_value * (left % base);
|
||||
left /= base;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
HaltonSequence::HaltonSequence(int num_dimensions)
|
||||
: num_dimensions_(num_dimensions), current_idx_(0) {
|
||||
RTC_CHECK_GE(num_dimensions_, 1)
|
||||
<< "num_dimensions must be >= 1. Will be set to 1.";
|
||||
RTC_CHECK_LE(num_dimensions_, kMaxDimensions)
|
||||
<< "num_dimensions must be <= " << kMaxDimensions << ". Will be set to "
|
||||
<< kMaxDimensions << ".";
|
||||
num_dimensions_ = std::clamp(num_dimensions_, 1, kMaxDimensions);
|
||||
}
|
||||
|
||||
std::vector<double> HaltonSequence::GetNext() {
|
||||
std::vector<double> point = {};
|
||||
point.reserve(num_dimensions_);
|
||||
for (int i = 0; i < num_dimensions_; ++i) {
|
||||
point.push_back(GetVanDerCorputSequenceElement(current_idx_, kBases[i]));
|
||||
}
|
||||
++current_idx_;
|
||||
return point;
|
||||
}
|
||||
|
||||
void HaltonSequence::Reset() {
|
||||
HaltonSequence::current_idx_ = 0;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
48
video/corruption_detection/halton_sequence.h
Normal file
48
video/corruption_detection/halton_sequence.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 VIDEO_CORRUPTION_DETECTION_HALTON_SEQUENCE_H_
|
||||
#define VIDEO_CORRUPTION_DETECTION_HALTON_SEQUENCE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Generates the Halton sequence: a low discrepancy sequence of doubles in the
|
||||
// half-open interval [0,1). See https://en.wikipedia.org/wiki/Halton_sequence
|
||||
// for information on how the sequence is constructed.
|
||||
class HaltonSequence {
|
||||
public:
|
||||
// Creates a sequence in `num_dimensions` number of dimensions. Possible
|
||||
// values are [1, 5].
|
||||
explicit HaltonSequence(int num_dimensions);
|
||||
// Creates a default sequence in a single dimension.
|
||||
HaltonSequence() = default;
|
||||
HaltonSequence(const HaltonSequence&) = default;
|
||||
HaltonSequence(HaltonSequence&&) = default;
|
||||
HaltonSequence& operator=(const HaltonSequence&) = default;
|
||||
HaltonSequence& operator=(HaltonSequence&&) = default;
|
||||
~HaltonSequence() = default;
|
||||
|
||||
// Gets the next point in the sequence where each value is in the half-open
|
||||
// interval [0,1).
|
||||
std::vector<double> GetNext();
|
||||
int GetCurrentIndex() const { return current_idx_; }
|
||||
void SetCurrentIndex(int idx) { current_idx_ = idx; }
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
int num_dimensions_ = 1;
|
||||
int current_idx_ = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // VIDEO_CORRUPTION_DETECTION_HALTON_SEQUENCE_H_
|
||||
73
video/corruption_detection/halton_sequence_unittest.cc
Normal file
73
video/corruption_detection/halton_sequence_unittest.cc
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 "video/corruption_detection/halton_sequence.h"
|
||||
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using ::testing::DoubleEq;
|
||||
using ::testing::ElementsAre;
|
||||
|
||||
TEST(HaltonSequenceTest, ShouldGenerateBase2SequenceByDefault) {
|
||||
HaltonSequence halton_sequence;
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(0.0)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(1.0 / 2)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(1.0 / 4)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(3.0 / 4)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(1.0 / 8)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(5.0 / 8)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(3.0 / 8)));
|
||||
}
|
||||
|
||||
TEST(HaltonSequenceTest,
|
||||
ShouldGenerateBase2Base3SequencesWhenCreatedAs2Dimensional) {
|
||||
HaltonSequence halton_sequence(2);
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(0.0), DoubleEq(0.0)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(1.0 / 2), DoubleEq(1.0 / 3)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(1.0 / 4), DoubleEq(2.0 / 3)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(3.0 / 4), DoubleEq(1.0 / 9)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(1.0 / 8), DoubleEq(4.0 / 9)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(5.0 / 8), DoubleEq(7.0 / 9)));
|
||||
EXPECT_THAT(halton_sequence.GetNext(),
|
||||
ElementsAre(DoubleEq(3.0 / 8), DoubleEq(2.0 / 9)));
|
||||
}
|
||||
|
||||
TEST(HaltonSequenceTest, ShouldRestartSequenceWhenResetIsCalled) {
|
||||
HaltonSequence halton_sequence;
|
||||
EXPECT_THAT(halton_sequence.GetCurrentIndex(), 0);
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(0.0)));
|
||||
EXPECT_THAT(halton_sequence.GetCurrentIndex(), 1);
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(1.0 / 2)));
|
||||
EXPECT_THAT(halton_sequence.GetCurrentIndex(), 2);
|
||||
halton_sequence.Reset();
|
||||
EXPECT_THAT(halton_sequence.GetCurrentIndex(), 0);
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(0.0)));
|
||||
}
|
||||
|
||||
TEST(HaltonSequenceTest, ShouldSetCurrentIndexWhenSetCurrentIndexIsCalled) {
|
||||
HaltonSequence halton_sequence;
|
||||
EXPECT_THAT(halton_sequence.GetCurrentIndex(), 0);
|
||||
halton_sequence.SetCurrentIndex(3);
|
||||
EXPECT_THAT(halton_sequence.GetCurrentIndex(), 3);
|
||||
EXPECT_THAT(halton_sequence.GetNext(), ElementsAre(DoubleEq(3.0 / 4)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
Loading…
x
Reference in New Issue
Block a user