Skip to content

Commit

Permalink
Add MovingMedianFilter to rtc_base/numerics
Browse files Browse the repository at this point in the history
This class will be used for filtering remote clock offset in rtp streams.
It is a separate wrapper around PercentileFilter because it will be used
in that form in several places.

Bug: webrtc:8468
Change-Id: If1f6c38ac1ffa02232c1aed5512b92878b1c346a
Reviewed-on: https://webrtc-review.googlesource.com/17841
Commit-Queue: Ilya Nikolaevskiy <[email protected]>
Reviewed-by: Tommi <[email protected]>
Cr-Commit-Position: refs/heads/master@{#20531}
  • Loading branch information
Ilya Nikolaevskiy authored and Commit Bot committed Nov 1, 2017
1 parent 3765199 commit b968575
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
2 changes: 2 additions & 0 deletions rtc_base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ rtc_static_library("rtc_numerics") {
sources = [
"numerics/exp_filter.cc",
"numerics/exp_filter.h",
"numerics/moving_median_filter.h",
"numerics/percentile_filter.h",
"numerics/sequence_number_util.h",
]
Expand Down Expand Up @@ -997,6 +998,7 @@ if (rtc_include_tests) {
}
sources = [
"numerics/exp_filter_unittest.cc",
"numerics/moving_median_filter_unittest.cc",
"numerics/percentile_filter_unittest.cc",
"numerics/sequence_number_util_unittest.cc",
]
Expand Down
69 changes: 69 additions & 0 deletions rtc_base/numerics/moving_median_filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017 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 RTC_BASE_NUMERICS_MOVING_MEDIAN_FILTER_H_
#define RTC_BASE_NUMERICS_MOVING_MEDIAN_FILTER_H_

#include <list>

#include "rtc_base/checks.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/numerics/percentile_filter.h"

namespace webrtc {

// Class to efficiently get moving median filter from a stream of samples.
template <typename T>
class MovingMedianFilter {
public:
// Construct filter. |window_size| is how many latest samples are stored and
// used to take median. |window_size| must be positive.
explicit MovingMedianFilter(size_t window_size);

// Insert a new sample.
void Insert(const T& value);

// Get median over the latest window.
T GetFilteredValue() const;

private:
PercentileFilter<T> percentile_filter_;
std::list<T> samples_;
size_t samples_stored_;
const size_t window_size_;

RTC_DISALLOW_COPY_AND_ASSIGN(MovingMedianFilter);
};

template <typename T>
MovingMedianFilter<T>::MovingMedianFilter(size_t window_size)
: percentile_filter_(0.5f), samples_stored_(0), window_size_(window_size) {
RTC_CHECK_GT(window_size, 0);
}

template <typename T>
void MovingMedianFilter<T>::Insert(const T& value) {
percentile_filter_.Insert(value);
samples_.emplace_back(value);
++samples_stored_;
if (samples_stored_ > window_size_) {
percentile_filter_.Erase(samples_.front());
samples_.pop_front();
--samples_stored_;
}
}

template <typename T>
T MovingMedianFilter<T>::GetFilteredValue() const {
return percentile_filter_.GetPercentileValue();
}

} // namespace webrtc
#endif // RTC_BASE_NUMERICS_MOVING_MEDIAN_FILTER_H_
51 changes: 51 additions & 0 deletions rtc_base/numerics/moving_median_filter_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2017 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 "rtc_base/numerics/moving_median_filter.h"
#include "test/gtest.h"

namespace webrtc {

TEST(MovingMedianFilterTest, ProcessesNoSamples) {
MovingMedianFilter<int> filter(2);
EXPECT_EQ(0, filter.GetFilteredValue());
}

TEST(MovingMedianFilterTest, ReturnsMovingMedianWindow5) {
MovingMedianFilter<int> filter(5);
const int64_t kSamples[5] = {1, 5, 2, 3, 4};
const int64_t kExpectedFilteredValues[5] = {1, 1, 2, 2, 3};
for (int i = 0; i < 5; ++i) {
filter.Insert(kSamples[i]);
EXPECT_EQ(kExpectedFilteredValues[i], filter.GetFilteredValue());
}
}

TEST(MovingMedianFilterTest, ReturnsMovingMedianWindow3) {
MovingMedianFilter<int> filter(3);
const int64_t kSamples[5] = {1, 5, 2, 3, 4};
const int64_t kExpectedFilteredValues[5] = {1, 1, 2, 3, 3};
for (int i = 0; i < 5; ++i) {
filter.Insert(kSamples[i]);
EXPECT_EQ(kExpectedFilteredValues[i], filter.GetFilteredValue());
}
}

TEST(MovingMedianFilterTest, ReturnsMovingMedianWindow1) {
MovingMedianFilter<int> filter(1);
const int64_t kSamples[5] = {1, 5, 2, 3, 4};
const int64_t kExpectedFilteredValues[5] = {1, 5, 2, 3, 4};
for (int i = 0; i < 5; ++i) {
filter.Insert(kSamples[i]);
EXPECT_EQ(kExpectedFilteredValues[i], filter.GetFilteredValue());
}
}

} // namespace webrtc

0 comments on commit b968575

Please sign in to comment.