OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 "video/send_statistics_proxy.h" | 11 #include "video/send_statistics_proxy.h" |
12 | 12 |
13 #include <map> | 13 #include <map> |
14 #include <memory> | 14 #include <memory> |
15 #include <string> | 15 #include <string> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "system_wrappers/include/metrics.h" | 18 #include "system_wrappers/include/metrics.h" |
19 #include "system_wrappers/include/metrics_default.h" | 19 #include "system_wrappers/include/metrics_default.h" |
| 20 #include "test/field_trial.h" |
20 #include "test/gtest.h" | 21 #include "test/gtest.h" |
21 | 22 |
22 namespace webrtc { | 23 namespace webrtc { |
23 namespace { | 24 namespace { |
24 const uint32_t kFirstSsrc = 17; | 25 const uint32_t kFirstSsrc = 17; |
25 const uint32_t kSecondSsrc = 42; | 26 const uint32_t kSecondSsrc = 42; |
26 const uint32_t kFirstRtxSsrc = 18; | 27 const uint32_t kFirstRtxSsrc = 18; |
27 const uint32_t kSecondRtxSsrc = 43; | 28 const uint32_t kSecondRtxSsrc = 43; |
28 const uint32_t kFlexFecSsrc = 55; | 29 const uint32_t kFlexFecSsrc = 55; |
29 const int kFpsPeriodicIntervalMs = 2000; | 30 const int kFpsPeriodicIntervalMs = 2000; |
30 const int kWidth = 640; | 31 const int kWidth = 640; |
31 const int kHeight = 480; | 32 const int kHeight = 480; |
32 const int kQpIdx0 = 21; | 33 const int kQpIdx0 = 21; |
33 const int kQpIdx1 = 39; | 34 const int kQpIdx1 = 39; |
| 35 const int kMinFirstFallbackIntervalMs = 1500; |
34 const CodecSpecificInfo kDefaultCodecInfo = []() { | 36 const CodecSpecificInfo kDefaultCodecInfo = []() { |
35 CodecSpecificInfo codec_info; | 37 CodecSpecificInfo codec_info; |
36 codec_info.codecType = kVideoCodecVP8; | 38 codec_info.codecType = kVideoCodecVP8; |
37 codec_info.codecSpecific.VP8.simulcastIdx = 0; | 39 codec_info.codecSpecific.VP8.simulcastIdx = 0; |
38 return codec_info; | 40 return codec_info; |
39 }(); | 41 }(); |
40 } // namespace | 42 } // namespace |
41 | 43 |
42 class SendStatisticsProxyTest : public ::testing::Test { | 44 class SendStatisticsProxyTest : public ::testing::Test { |
43 public: | 45 public: |
44 SendStatisticsProxyTest() | 46 SendStatisticsProxyTest() : SendStatisticsProxyTest("") {} |
45 : fake_clock_(1234), config_(GetTestConfig()), avg_delay_ms_(0), | 47 explicit SendStatisticsProxyTest(const std::string& field_trials) |
| 48 : override_field_trials_(field_trials), |
| 49 fake_clock_(1234), |
| 50 config_(GetTestConfig()), |
| 51 avg_delay_ms_(0), |
46 max_delay_ms_(0) {} | 52 max_delay_ms_(0) {} |
47 virtual ~SendStatisticsProxyTest() {} | 53 virtual ~SendStatisticsProxyTest() {} |
48 | 54 |
49 protected: | 55 protected: |
50 virtual void SetUp() { | 56 virtual void SetUp() { |
51 metrics::Reset(); | 57 metrics::Reset(); |
52 statistics_proxy_.reset(new SendStatisticsProxy( | 58 statistics_proxy_.reset(new SendStatisticsProxy( |
53 &fake_clock_, GetTestConfig(), | 59 &fake_clock_, GetTestConfig(), |
54 VideoEncoderConfig::ContentType::kRealtimeVideo)); | 60 VideoEncoderConfig::ContentType::kRealtimeVideo)); |
55 expected_ = VideoSendStream::Stats(); | 61 expected_ = VideoSendStream::Stats(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets); | 139 EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets); |
134 | 140 |
135 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost); | 141 EXPECT_EQ(a.rtcp_stats.fraction_lost, b.rtcp_stats.fraction_lost); |
136 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost); | 142 EXPECT_EQ(a.rtcp_stats.packets_lost, b.rtcp_stats.packets_lost); |
137 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number, | 143 EXPECT_EQ(a.rtcp_stats.extended_highest_sequence_number, |
138 b.rtcp_stats.extended_highest_sequence_number); | 144 b.rtcp_stats.extended_highest_sequence_number); |
139 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter); | 145 EXPECT_EQ(a.rtcp_stats.jitter, b.rtcp_stats.jitter); |
140 } | 146 } |
141 } | 147 } |
142 | 148 |
| 149 test::ScopedFieldTrials override_field_trials_; |
143 SimulatedClock fake_clock_; | 150 SimulatedClock fake_clock_; |
144 std::unique_ptr<SendStatisticsProxy> statistics_proxy_; | 151 std::unique_ptr<SendStatisticsProxy> statistics_proxy_; |
145 VideoSendStream::Config config_; | 152 VideoSendStream::Config config_; |
146 int avg_delay_ms_; | 153 int avg_delay_ms_; |
147 int max_delay_ms_; | 154 int max_delay_ms_; |
148 VideoSendStream::Stats expected_; | 155 VideoSendStream::Stats expected_; |
149 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator | 156 typedef std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator |
150 StreamIterator; | 157 StreamIterator; |
151 }; | 158 }; |
152 | 159 |
(...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1792 // Advance one interval and update counters. | 1799 // Advance one interval and update counters. |
1793 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs); | 1800 fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs); |
1794 proxy->DataCountersUpdated(counters, kFirstSsrc); | 1801 proxy->DataCountersUpdated(counters, kFirstSsrc); |
1795 } | 1802 } |
1796 | 1803 |
1797 // FEC not enabled. | 1804 // FEC not enabled. |
1798 statistics_proxy_.reset(); | 1805 statistics_proxy_.reset(); |
1799 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps")); | 1806 EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps")); |
1800 } | 1807 } |
1801 | 1808 |
| 1809 TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) { |
| 1810 const char* kName = "encoderName"; |
| 1811 EncodedImage encoded_image; |
| 1812 CodecSpecificInfo codec_info; |
| 1813 codec_info.codec_name = kName; |
| 1814 statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info); |
| 1815 EXPECT_STREQ( |
| 1816 kName, statistics_proxy_->GetStats().encoder_implementation_name.c_str()); |
| 1817 } |
| 1818 |
| 1819 class ForcedFallbackTest : public SendStatisticsProxyTest { |
| 1820 public: |
| 1821 explicit ForcedFallbackTest(const std::string& field_trials) |
| 1822 : SendStatisticsProxyTest(field_trials) { |
| 1823 codec_info_.codecType = kVideoCodecVP8; |
| 1824 codec_info_.codecSpecific.VP8.simulcastIdx = 0; |
| 1825 codec_info_.codecSpecific.VP8.temporalIdx = 0; |
| 1826 codec_info_.codec_name = "fake_codec"; |
| 1827 } |
| 1828 |
| 1829 ~ForcedFallbackTest() override {} |
| 1830 |
| 1831 protected: |
| 1832 void InsertEncodedFrames(int num_frames, int interval_ms) { |
| 1833 // First frame is not updating stats, insert initial frame. |
| 1834 if (statistics_proxy_->GetStats().frames_encoded == 0) { |
| 1835 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_); |
| 1836 } |
| 1837 for (int i = 0; i < num_frames; ++i) { |
| 1838 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_); |
| 1839 fake_clock_.AdvanceTimeMilliseconds(interval_ms); |
| 1840 } |
| 1841 // Add frame to include last time interval. |
| 1842 statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_); |
| 1843 } |
| 1844 |
| 1845 EncodedImage encoded_image_; |
| 1846 CodecSpecificInfo codec_info_; |
| 1847 const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw"; |
| 1848 const int kFrameIntervalMs = 1000; |
| 1849 const int kMinFrames = 20; // Min run time 20 sec. |
| 1850 }; |
| 1851 |
| 1852 class ForcedFallbackDisabled : public ForcedFallbackTest { |
| 1853 public: |
| 1854 ForcedFallbackDisabled() |
| 1855 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder/Disabled/") {} |
| 1856 }; |
| 1857 |
| 1858 class ForcedFallbackEnabled : public ForcedFallbackTest { |
| 1859 public: |
| 1860 ForcedFallbackEnabled() |
| 1861 : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder/Enabled-1,2," + |
| 1862 std::to_string(kMinFirstFallbackIntervalMs) + |
| 1863 ",4/") {} |
| 1864 }; |
| 1865 |
| 1866 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) { |
| 1867 InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1); |
| 1868 statistics_proxy_.reset(); |
| 1869 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1870 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1871 } |
| 1872 |
| 1873 TEST_F(ForcedFallbackEnabled, StatsUpdated) { |
| 1874 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1875 statistics_proxy_.reset(); |
| 1876 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1877 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0)); |
| 1878 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1879 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0)); |
| 1880 } |
| 1881 |
| 1882 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) { |
| 1883 codec_info_.codecType = kVideoCodecVP9; |
| 1884 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1885 statistics_proxy_.reset(); |
| 1886 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1887 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1888 } |
| 1889 |
| 1890 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) { |
| 1891 codec_info_.codecSpecific.VP8.temporalIdx = 1; |
| 1892 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1893 statistics_proxy_.reset(); |
| 1894 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1895 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1896 } |
| 1897 |
| 1898 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) { |
| 1899 codec_info_.codecSpecific.VP8.simulcastIdx = 1; |
| 1900 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1901 statistics_proxy_.reset(); |
| 1902 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1903 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1904 } |
| 1905 |
| 1906 TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) { |
| 1907 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1908 statistics_proxy_.reset(); |
| 1909 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1910 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1911 } |
| 1912 |
| 1913 TEST_F(ForcedFallbackEnabled, OneFallbackEvent) { |
| 1914 // One change. Video: 20000 ms, fallback: 5000 ms (25%). |
| 1915 InsertEncodedFrames(15, 1000); |
| 1916 codec_info_.codec_name = "libvpx"; |
| 1917 InsertEncodedFrames(5, 1000); |
| 1918 |
| 1919 statistics_proxy_.reset(); |
| 1920 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1921 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25)); |
| 1922 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1923 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3)); |
| 1924 } |
| 1925 |
| 1926 TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) { |
| 1927 codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx; // Should work. |
| 1928 const int kMaxFrameDiffMs = 2000; |
| 1929 |
| 1930 // Three changes. Video: 60000 ms, fallback: 15000 ms (25%). |
| 1931 InsertEncodedFrames(10, 1000); |
| 1932 codec_info_.codec_name = "libvpx"; |
| 1933 InsertEncodedFrames(15, 500); |
| 1934 codec_info_.codec_name = "notlibvpx"; |
| 1935 InsertEncodedFrames(20, 1000); |
| 1936 InsertEncodedFrames(3, kMaxFrameDiffMs); // Should not be included. |
| 1937 InsertEncodedFrames(10, 1000); |
| 1938 codec_info_.codec_name = "notlibvpx2"; |
| 1939 InsertEncodedFrames(10, 500); |
| 1940 codec_info_.codec_name = "libvpx"; |
| 1941 InsertEncodedFrames(15, 500); |
| 1942 |
| 1943 statistics_proxy_.reset(); |
| 1944 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1945 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25)); |
| 1946 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1947 EXPECT_EQ(1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3)); |
| 1948 } |
| 1949 |
| 1950 TEST_F(ForcedFallbackEnabled, NoFallbackIfMinIntervalHasNotPassed) { |
| 1951 InsertEncodedFrames(1, kMinFirstFallbackIntervalMs - 1); |
| 1952 codec_info_.codec_name = "libvpx"; |
| 1953 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1954 |
| 1955 statistics_proxy_.reset(); |
| 1956 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1957 EXPECT_EQ(0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1958 } |
| 1959 |
| 1960 TEST_F(ForcedFallbackEnabled, FallbackIfMinIntervalPassed) { |
| 1961 InsertEncodedFrames(1, kMinFirstFallbackIntervalMs); |
| 1962 codec_info_.codec_name = "libvpx"; |
| 1963 InsertEncodedFrames(kMinFrames, kFrameIntervalMs); |
| 1964 |
| 1965 statistics_proxy_.reset(); |
| 1966 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8")); |
| 1967 EXPECT_EQ(1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8")); |
| 1968 } |
| 1969 |
1802 } // namespace webrtc | 1970 } // namespace webrtc |
OLD | NEW |