Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(503)

Side by Side Diff: webrtc/media/base/videocapturer_unittest.cc

Issue 2017443003: Implement timestamp translation/filter in VideoCapturer. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Parameterize tests of timestamp filter. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2008 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2008 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include <stdio.h> 11 #include <stdio.h>
12 12
13 #include <memory> 13 #include <memory>
14 #include <vector> 14 #include <vector>
15 15
16 #include "webrtc/base/gunit.h" 16 #include "webrtc/base/gunit.h"
17 #include "webrtc/base/logging.h" 17 #include "webrtc/base/logging.h"
18 #include "webrtc/base/random.h"
18 #include "webrtc/base/thread.h" 19 #include "webrtc/base/thread.h"
19 #include "webrtc/media/base/fakevideocapturer.h" 20 #include "webrtc/media/base/fakevideocapturer.h"
20 #include "webrtc/media/base/fakevideorenderer.h" 21 #include "webrtc/media/base/fakevideorenderer.h"
21 #include "webrtc/media/base/testutils.h" 22 #include "webrtc/media/base/testutils.h"
22 #include "webrtc/media/base/videocapturer.h" 23 #include "webrtc/media/base/videocapturer.h"
23 24
24 using cricket::FakeVideoCapturer; 25 using cricket::FakeVideoCapturer;
25 26
26 namespace { 27 namespace {
27 28
(...skipping 20 matching lines...) Expand all
48 &VideoCapturerTest::OnStateChange); 49 &VideoCapturerTest::OnStateChange);
49 capturer_->AddOrUpdateSink(&renderer_, rtc::VideoSinkWants()); 50 capturer_->AddOrUpdateSink(&renderer_, rtc::VideoSinkWants());
50 } 51 }
51 void InitScreencast() { InitCapturer(true); } 52 void InitScreencast() { InitCapturer(true); }
52 53
53 void OnStateChange(cricket::VideoCapturer*, 54 void OnStateChange(cricket::VideoCapturer*,
54 cricket::CaptureState capture_state) { 55 cricket::CaptureState capture_state) {
55 capture_state_ = capture_state; 56 capture_state_ = capture_state;
56 ++num_state_changes_; 57 ++num_state_changes_;
57 } 58 }
59 void TestTimestampFilter(double rel_freq_error);
60
58 cricket::CaptureState capture_state() { return capture_state_; } 61 cricket::CaptureState capture_state() { return capture_state_; }
59 int num_state_changes() { return num_state_changes_; } 62 int num_state_changes() { return num_state_changes_; }
60 63
61 std::unique_ptr<cricket::FakeVideoCapturer> capturer_; 64 std::unique_ptr<cricket::FakeVideoCapturer> capturer_;
62 cricket::CaptureState capture_state_; 65 cricket::CaptureState capture_state_;
63 int num_state_changes_; 66 int num_state_changes_;
64 cricket::FakeVideoRenderer renderer_; 67 cricket::FakeVideoRenderer renderer_;
65 bool expects_rotation_applied_; 68 bool expects_rotation_applied_;
66 }; 69 };
67 70
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 capturer_->set_enable_camera_list(true); 777 capturer_->set_enable_camera_list(true);
775 capturer_->ConstrainSupportedFormats(vga_format); 778 capturer_->ConstrainSupportedFormats(vga_format);
776 EXPECT_EQ(2u, capturer_->GetSupportedFormats()->size()); 779 EXPECT_EQ(2u, capturer_->GetSupportedFormats()->size());
777 // To make sure it's not just the camera list being broken, add in VGA and 780 // To make sure it's not just the camera list being broken, add in VGA and
778 // try again. This time, only the VGA format should be there. 781 // try again. This time, only the VGA format should be there.
779 supported_formats.push_back(vga_format); 782 supported_formats.push_back(vga_format);
780 capturer_->ResetSupportedFormats(supported_formats); 783 capturer_->ResetSupportedFormats(supported_formats);
781 ASSERT_EQ(1u, capturer_->GetSupportedFormats()->size()); 784 ASSERT_EQ(1u, capturer_->GetSupportedFormats()->size());
782 EXPECT_EQ(vga_format.height, capturer_->GetSupportedFormats()->at(0).height); 785 EXPECT_EQ(vga_format.height, capturer_->GetSupportedFormats()->at(0).height);
783 } 786 }
787
788 namespace {
789 // Computes the difference x_k - mean(x), when x_k is the linear sequence x_k =
790 // k, and the "mean" is plain mean for the first |window_size| samples, followed
791 // by exponential averaging with weight 1/|window_size| for each new sample.
792 // This is needed to predict the effect of camera clock drift on the timestamp
793 // translation. See the comment on VideoCapturer::UpdateOffset for more context.
794 double MeanTimeDifference(int nsamples, int window_size) {
795 if (nsamples <= window_size) {
796 // Plain averaging.
797 return nsamples / 2.0;
798 } else {
799 // Exponential convergence towards
800 // interval_error * (window_size - 1)
801 double alpha = 1.0 - 1.0 / window_size;
802
803 return ((window_size - 1) -
804 (window_size / 2.0 - 1) * pow(alpha, nsamples - window_size));
805 }
806 }
807
808 } // Anonymous namespace
809
810 void VideoCapturerTest::TestTimestampFilter(double rel_freq_error) {
811 const int kWidth = 800;
812 const int kHeight = 400;
813
814 const int64_t kEpoch = 10000;
815 const int64_t kJitterUs = 5000;
816 const int64_t kIntervalUs = 33333; // 30 FPS
817 const int kWindowSize = 100;
818 const int kNumFrames = 3 * kWindowSize;
819
820 int64_t interval_error_us = kIntervalUs * rel_freq_error;
821 int64_t system_start_us = rtc::TimeMicros();
822 webrtc::Random random(17);
823
824 int64_t prev_translated_time_us = system_start_us;
825
826 for (int i = 0; i < kNumFrames; i++) {
827 // Camera time subject to drift.
828 int64_t camera_time_us = kEpoch + i * (kIntervalUs + interval_error_us);
829 int64_t system_time_us = system_start_us + i * kIntervalUs;
830 // And system time readings are subject to jitter.
831 int64_t system_measured_us = system_time_us + random.Rand(kJitterUs);
832
833 int out_width;
834 int out_height;
835 int crop_width;
836 int crop_height;
837 int crop_x;
838 int crop_y;
839 int64_t translated_time_us;
840
841 EXPECT_TRUE(capturer_->AdaptFrame(kWidth, kHeight,
842 camera_time_us, system_measured_us,
843 &out_width, &out_height,
844 &crop_width, &crop_height,
845 &crop_x, &crop_y, &translated_time_us));
846
847 EXPECT_LE(translated_time_us, system_measured_us);
848 EXPECT_GE(translated_time_us, prev_translated_time_us);
849
850 // The relative frequency error contributes to the expected error
851 // by a factor which is the difference between the current time
852 // and the average of earlier sample times.
853 int64_t expected_error_us =
854 kJitterUs / 2 +
855 rel_freq_error * kIntervalUs * MeanTimeDifference(i, kWindowSize);
856
857 int64_t bias_us = capturer_->clip_bias_us();
858 EXPECT_GE(bias_us, 0);
859
860 if (i == 0) {
861 EXPECT_EQ(translated_time_us, system_measured_us);
862 } else {
863 EXPECT_NEAR(translated_time_us + bias_us,
864 system_time_us + expected_error_us,
865 2.0 * kJitterUs / sqrt(std::max(i, kWindowSize)));
866 }
867 // If the camera clock runs too fast (rel_freq_error > 0.0), The
868 // bias is expected to roughly cancel the expected error from the
869 // clock drift, as this grows. Otherwise, it reflects the
870 // measurement noise. The tolerances here were selected after some
871 // trial and error.
872 if (i < 10 || rel_freq_error <= 0.0) {
873 EXPECT_LE(bias_us, 3000);
874 } else {
875 EXPECT_NEAR(bias_us, expected_error_us, 1500);
876 }
877 prev_translated_time_us = translated_time_us;
878 }
879 }
880
881 TEST_F(VideoCapturerTest, AttenuateTimestampJitterNoDrift) {
882 TestTimestampFilter(0.0);
883 }
884
885 // 100 ppm is a worst case for a reasonable crystal.
886 TEST_F(VideoCapturerTest, AttenuateTimestampJitterSmallPosDrift) {
887 TestTimestampFilter(0.0001);
888 }
889
890 TEST_F(VideoCapturerTest, AttenuateTimestampJitterSmallNegDrift) {
891 TestTimestampFilter(-0.0001);
892 }
893
894 // 3000 ppm, 3 ms / s, is the worst observed drift, see
895 // https://bugs.chromium.org/p/webrtc/issues/detail?id=5456
896 TEST_F(VideoCapturerTest, AttenuateTimestampJitterLargePosDrift) {
897 TestTimestampFilter(0.003);
898 }
899
900 TEST_F(VideoCapturerTest, AttenuateTimestampJitterLargeNegDrift) {
901 TestTimestampFilter(-0.003);
902 }
OLDNEW
« webrtc/media/base/videocapturer.cc ('K') | « webrtc/media/base/videocapturer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698