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

Side by Side Diff: webrtc/video/overuse_frame_detector_unittest.cc

Issue 1569853002: Measure encoding time on encode callbacks. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: feedback Created 4 years, 10 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
« no previous file with comments | « webrtc/video/overuse_frame_detector.cc ('k') | webrtc/video/send_statistics_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "webrtc/video/overuse_frame_detector.h" 11 #include "webrtc/video/overuse_frame_detector.h"
12 12
13 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
15 15
16 #include "webrtc/base/scoped_ptr.h" 16 #include "webrtc/base/scoped_ptr.h"
17 #include "webrtc/system_wrappers/include/clock.h" 17 #include "webrtc/system_wrappers/include/clock.h"
18 #include "webrtc/video_frame.h"
18 19
19 namespace webrtc { 20 namespace webrtc {
20 namespace { 21 namespace {
21 const int kWidth = 640; 22 const int kWidth = 640;
22 const int kHeight = 480; 23 const int kHeight = 480;
23 const int kFrameInterval33ms = 33; 24 const int kFrameInterval33ms = 33;
24 const int kProcessIntervalMs = 5000; 25 const int kProcessIntervalMs = 5000;
25 const int kProcessTime5ms = 5; 26 const int kProcessTime5ms = 5;
26 } // namespace 27 } // namespace
27 28
(...skipping 24 matching lines...) Expand all
52 public CpuOveruseMetricsObserver { 53 public CpuOveruseMetricsObserver {
53 protected: 54 protected:
54 virtual void SetUp() { 55 virtual void SetUp() {
55 clock_.reset(new SimulatedClock(1234)); 56 clock_.reset(new SimulatedClock(1234));
56 observer_.reset(new MockCpuOveruseObserver()); 57 observer_.reset(new MockCpuOveruseObserver());
57 options_.min_process_count = 0; 58 options_.min_process_count = 0;
58 ReinitializeOveruseDetector(); 59 ReinitializeOveruseDetector();
59 } 60 }
60 61
61 void ReinitializeOveruseDetector() { 62 void ReinitializeOveruseDetector() {
62 overuse_detector_.reset(new OveruseFrameDetector(clock_.get(), options_, 63 overuse_detector_.reset(new OveruseFrameDetector(
63 observer_.get(), this)); 64 clock_.get(), options_, observer_.get(), nullptr, this));
64 } 65 }
65 66
66 void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override { 67 void OnEncodedFrameTimeMeasured(int encode_time_ms,
68 const CpuOveruseMetrics& metrics) override {
67 metrics_ = metrics; 69 metrics_ = metrics;
68 } 70 }
69 71
70 int InitialUsage() { 72 int InitialUsage() {
71 return ((options_.low_encode_usage_threshold_percent + 73 return ((options_.low_encode_usage_threshold_percent +
72 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5; 74 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5;
73 } 75 }
74 76
75 void InsertAndSendFramesWithInterval( 77 void InsertAndSendFramesWithInterval(int num_frames,
76 int num_frames, int interval_ms, int width, int height, int delay_ms) { 78 int interval_ms,
79 int width,
80 int height,
81 int delay_ms) {
82 VideoFrame frame;
83 frame.CreateEmptyFrame(width, height, width, width / 2, width / 2);
84 uint32_t timestamp = 0;
77 while (num_frames-- > 0) { 85 while (num_frames-- > 0) {
78 int64_t capture_time_ms = clock_->TimeInMilliseconds(); 86 frame.set_timestamp(timestamp);
79 overuse_detector_->FrameCaptured(width, height, capture_time_ms); 87 overuse_detector_->FrameCaptured(frame);
80 clock_->AdvanceTimeMilliseconds(delay_ms); 88 clock_->AdvanceTimeMilliseconds(delay_ms);
81 overuse_detector_->FrameSent(capture_time_ms); 89 overuse_detector_->FrameSent(timestamp);
82 clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms); 90 clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms);
91 timestamp += interval_ms * 90;
83 } 92 }
84 } 93 }
85 94
95 void ForceUpdate(int width, int height) {
96 const int kOveruseDurationMs = 1000;
åsapersson 2016/01/27 16:47:12 could perhaps be confused with triggering overuse
pbos-webrtc 2016/02/01 16:09:12 Done.
97 // Insert one frame, wait a second and then put in another to force update
98 // the usage. From the tests where these are used, adding another sample
99 // doesn't affect the expected outcome (this is mainly to check initial
100 // values and whether the overuse detector has been reset or not).
101 InsertAndSendFramesWithInterval(2, kOveruseDurationMs, width, height,
102 kFrameInterval33ms);
103 }
86 void TriggerOveruse(int num_times) { 104 void TriggerOveruse(int num_times) {
87 const int kDelayMs = 32; 105 const int kDelayMs = 32;
88 for (int i = 0; i < num_times; ++i) { 106 for (int i = 0; i < num_times; ++i) {
89 InsertAndSendFramesWithInterval( 107 InsertAndSendFramesWithInterval(
90 1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs); 108 1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs);
91 overuse_detector_->Process(); 109 overuse_detector_->Process();
92 } 110 }
93 } 111 }
94 112
95 void TriggerUnderuse() { 113 void TriggerUnderuse() {
(...skipping 28 matching lines...) Expand all
124 // usage > high => overuse 142 // usage > high => overuse
125 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 143 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1);
126 TriggerOveruse(options_.high_threshold_consecutive_count); 144 TriggerOveruse(options_.high_threshold_consecutive_count);
127 // usage < low => underuse 145 // usage < low => underuse
128 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 146 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1));
129 TriggerUnderuse(); 147 TriggerUnderuse();
130 } 148 }
131 149
132 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { 150 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) {
133 overuse_detector_.reset( 151 overuse_detector_.reset(
134 new OveruseFrameDetector(clock_.get(), options_, nullptr, this)); 152 new OveruseFrameDetector(clock_.get(), options_, nullptr, nullptr, this));
135 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); 153 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0);
136 TriggerOveruse(options_.high_threshold_consecutive_count); 154 TriggerOveruse(options_.high_threshold_consecutive_count);
137 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 155 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0);
138 TriggerUnderuse(); 156 TriggerUnderuse();
139 } 157 }
140 158
141 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { 159 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
142 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); 160 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2);
143 TriggerOveruse(options_.high_threshold_consecutive_count); 161 TriggerOveruse(options_.high_threshold_consecutive_count);
144 TriggerOveruse(options_.high_threshold_consecutive_count); 162 TriggerOveruse(options_.high_threshold_consecutive_count);
145 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 163 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1));
146 TriggerUnderuse(); 164 TriggerUnderuse();
147 } 165 }
148 166
149 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { 167 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
150 options_.min_process_count = 1; 168 options_.min_process_count = 1;
151 CpuOveruseObserverImpl overuse_observer; 169 CpuOveruseObserverImpl overuse_observer;
152 overuse_detector_.reset(new OveruseFrameDetector(clock_.get(), options_, 170 overuse_detector_.reset(new OveruseFrameDetector(
153 &overuse_observer, this)); 171 clock_.get(), options_, &overuse_observer, nullptr, this));
154 InsertAndSendFramesWithInterval( 172 InsertAndSendFramesWithInterval(
155 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 173 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
156 overuse_detector_->Process(); 174 overuse_detector_->Process();
157 EXPECT_EQ(0, overuse_observer.normaluse_); 175 EXPECT_EQ(0, overuse_observer.normaluse_);
158 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); 176 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs);
159 overuse_detector_->Process(); 177 overuse_detector_->Process();
160 EXPECT_EQ(1, overuse_observer.normaluse_); 178 EXPECT_EQ(1, overuse_observer.normaluse_);
161 } 179 }
162 180
163 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { 181 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
(...skipping 18 matching lines...) Expand all
182 TriggerOveruse(1); 200 TriggerOveruse(1);
183 } 201 }
184 202
185 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) { 203 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
186 InsertAndSendFramesWithInterval( 204 InsertAndSendFramesWithInterval(
187 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 205 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
188 EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent()); 206 EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent());
189 } 207 }
190 208
191 TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) { 209 TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
210 ForceUpdate(kWidth, kHeight);
192 EXPECT_EQ(InitialUsage(), UsagePercent()); 211 EXPECT_EQ(InitialUsage(), UsagePercent());
193 InsertAndSendFramesWithInterval( 212 InsertAndSendFramesWithInterval(
194 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 213 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
195 EXPECT_NE(InitialUsage(), UsagePercent()); 214 EXPECT_NE(InitialUsage(), UsagePercent());
196 // Verify reset. 215 // Verify reset (with new width/height).
197 InsertAndSendFramesWithInterval( 216 ForceUpdate(kWidth, kHeight + 1);
198 1, kFrameInterval33ms, kWidth, kHeight + 1, kProcessTime5ms);
199 EXPECT_EQ(InitialUsage(), UsagePercent()); 217 EXPECT_EQ(InitialUsage(), UsagePercent());
200 } 218 }
201 219
202 TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) { 220 TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
221 ForceUpdate(kWidth, kHeight);
203 EXPECT_EQ(InitialUsage(), UsagePercent()); 222 EXPECT_EQ(InitialUsage(), UsagePercent());
204 InsertAndSendFramesWithInterval( 223 InsertAndSendFramesWithInterval(
205 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 224 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
206 EXPECT_NE(InitialUsage(), UsagePercent()); 225 EXPECT_NE(InitialUsage(), UsagePercent());
207 InsertAndSendFramesWithInterval( 226 InsertAndSendFramesWithInterval(
208 2, options_.frame_timeout_interval_ms, kWidth, kHeight, kProcessTime5ms); 227 2, options_.frame_timeout_interval_ms, kWidth, kHeight, kProcessTime5ms);
209 EXPECT_NE(InitialUsage(), UsagePercent()); 228 EXPECT_NE(InitialUsage(), UsagePercent());
210 // Verify reset. 229 // Verify reset.
211 InsertAndSendFramesWithInterval( 230 InsertAndSendFramesWithInterval(
212 2, options_.frame_timeout_interval_ms + 1, kWidth, kHeight, 231 2, options_.frame_timeout_interval_ms + 1, kWidth, kHeight,
213 kProcessTime5ms); 232 kProcessTime5ms);
233 ForceUpdate(kWidth, kHeight);
214 EXPECT_EQ(InitialUsage(), UsagePercent()); 234 EXPECT_EQ(InitialUsage(), UsagePercent());
215 } 235 }
216 236
217 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) { 237 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
218 options_.min_frame_samples = 40; 238 options_.min_frame_samples = 40;
219 ReinitializeOveruseDetector(); 239 ReinitializeOveruseDetector();
220 InsertAndSendFramesWithInterval( 240 InsertAndSendFramesWithInterval(
221 40, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 241 40, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
222 EXPECT_EQ(InitialUsage(), UsagePercent()); 242 EXPECT_EQ(InitialUsage(), UsagePercent());
243 // Pass time far enough to digest all previous samples.
244 clock_->AdvanceTimeMilliseconds(1000);
245 InsertAndSendFramesWithInterval(
246 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
247 // The last sample has not been processed here.
248 EXPECT_EQ(InitialUsage(), UsagePercent());
249
250 // Pass time far enough to digest all previous samples, 41 in total.
251 clock_->AdvanceTimeMilliseconds(1000);
223 InsertAndSendFramesWithInterval( 252 InsertAndSendFramesWithInterval(
224 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 253 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
225 EXPECT_NE(InitialUsage(), UsagePercent()); 254 EXPECT_NE(InitialUsage(), UsagePercent());
226 } 255 }
227 256
228 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) { 257 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
258 ForceUpdate(kWidth, kHeight);
229 EXPECT_EQ(InitialUsage(), UsagePercent()); 259 EXPECT_EQ(InitialUsage(), UsagePercent());
230 } 260 }
231 261
232 TEST_F(OveruseFrameDetectorTest, FrameDelay_OneFrame) { 262 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
233 const int kProcessingTimeMs = 100; 263 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1));
234 overuse_detector_->FrameCaptured(kWidth, kHeight, 33); 264 static const int kIntervalMs = 33;
235 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs); 265 static const size_t kNumFramesEncodingDelay = 3;
236 EXPECT_EQ(-1, overuse_detector_->LastProcessingTimeMs()); 266 VideoFrame frame;
237 overuse_detector_->FrameSent(33); 267 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2);
238 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs()); 268 for (size_t i = 0; i < 1000; ++i) {
239 EXPECT_EQ(0, overuse_detector_->FramesInQueue()); 269 // Unique timestamps.
270 frame.set_timestamp(static_cast<uint32_t>(i));
271 overuse_detector_->FrameCaptured(frame);
272 clock_->AdvanceTimeMilliseconds(kIntervalMs);
273 if (i > kNumFramesEncodingDelay) {
274 overuse_detector_->FrameSent(
275 static_cast<uint32_t>(i - kNumFramesEncodingDelay));
276 }
277 overuse_detector_->Process();
278 }
240 } 279 }
241 280
242 TEST_F(OveruseFrameDetectorTest, FrameDelay_TwoFrames) { 281 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
243 const int kProcessingTimeMs1 = 100; 282 // >85% encoding time should trigger overuse.
244 const int kProcessingTimeMs2 = 50; 283 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1));
245 const int kTimeBetweenFramesMs = 200; 284 static const int kIntervalMs = 33;
246 overuse_detector_->FrameCaptured(kWidth, kHeight, 33); 285 static const int kDelayMs = 30;
247 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs1); 286 VideoFrame frame;
248 overuse_detector_->FrameSent(33); 287 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2);
249 EXPECT_EQ(kProcessingTimeMs1, overuse_detector_->LastProcessingTimeMs()); 288 uint32_t timestamp = 0;
250 clock_->AdvanceTimeMilliseconds(kTimeBetweenFramesMs); 289 for (size_t i = 0; i < 1000; ++i) {
251 overuse_detector_->FrameCaptured(kWidth, kHeight, 66); 290 frame.set_timestamp(timestamp);
252 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs2); 291 overuse_detector_->FrameCaptured(frame);
253 overuse_detector_->FrameSent(66); 292 // Encode and send first parts almost instantly.
254 EXPECT_EQ(kProcessingTimeMs2, overuse_detector_->LastProcessingTimeMs()); 293 clock_->AdvanceTimeMilliseconds(1);
255 } 294 overuse_detector_->FrameSent(timestamp);
256 295 // Encode heavier part, resulting in >85% usage total.
257 TEST_F(OveruseFrameDetectorTest, FrameDelay_MaxQueueSize) { 296 clock_->AdvanceTimeMilliseconds(kDelayMs - 1);
258 const int kMaxQueueSize = 91; 297 overuse_detector_->FrameSent(timestamp);
259 for (int i = 0; i < kMaxQueueSize * 2; ++i) { 298 clock_->AdvanceTimeMilliseconds(kIntervalMs - kDelayMs);
260 overuse_detector_->FrameCaptured(kWidth, kHeight, i); 299 timestamp += kIntervalMs * 90;
300 overuse_detector_->Process();
261 } 301 }
262 EXPECT_EQ(kMaxQueueSize, overuse_detector_->FramesInQueue());
263 }
264
265 TEST_F(OveruseFrameDetectorTest, FrameDelay_NonProcessedFramesRemoved) {
266 const int kProcessingTimeMs = 100;
267 overuse_detector_->FrameCaptured(kWidth, kHeight, 33);
268 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
269 overuse_detector_->FrameCaptured(kWidth, kHeight, 35);
270 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
271 overuse_detector_->FrameCaptured(kWidth, kHeight, 66);
272 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
273 overuse_detector_->FrameCaptured(kWidth, kHeight, 99);
274 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
275 EXPECT_EQ(-1, overuse_detector_->LastProcessingTimeMs());
276 EXPECT_EQ(4, overuse_detector_->FramesInQueue());
277 overuse_detector_->FrameSent(66);
278 // Frame 33, 35 removed, 66 processed, 99 not processed.
279 EXPECT_EQ(2 * kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
280 EXPECT_EQ(1, overuse_detector_->FramesInQueue());
281 overuse_detector_->FrameSent(99);
282 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
283 EXPECT_EQ(0, overuse_detector_->FramesInQueue());
284 }
285
286 TEST_F(OveruseFrameDetectorTest, FrameDelay_ResetClearsFrames) {
287 const int kProcessingTimeMs = 100;
288 overuse_detector_->FrameCaptured(kWidth, kHeight, 33);
289 EXPECT_EQ(1, overuse_detector_->FramesInQueue());
290 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
291 // Verify reset (resolution changed).
292 overuse_detector_->FrameCaptured(kWidth, kHeight + 1, 66);
293 EXPECT_EQ(1, overuse_detector_->FramesInQueue());
294 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
295 overuse_detector_->FrameSent(66);
296 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
297 EXPECT_EQ(0, overuse_detector_->FramesInQueue());
298 }
299
300 TEST_F(OveruseFrameDetectorTest, FrameDelay_NonMatchingSendFrameIgnored) {
301 const int kProcessingTimeMs = 100;
302 overuse_detector_->FrameCaptured(kWidth, kHeight, 33);
303 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
304 overuse_detector_->FrameSent(34);
305 EXPECT_EQ(-1, overuse_detector_->LastProcessingTimeMs());
306 overuse_detector_->FrameSent(33);
307 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
308 } 302 }
309 303
310 } // namespace webrtc 304 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/overuse_frame_detector.cc ('k') | webrtc/video/send_statistics_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698