1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <memory>
12 #include <vector>
13
14 #include "api/test/create_videocodec_test_fixture.h"
15 #include "api/test/video/function_video_encoder_factory.h"
16 #include "api/video_codecs/sdp_video_format.h"
17 #include "media/base/media_constants.h"
18 #include "media/engine/internal_decoder_factory.h"
19 #include "media/engine/internal_encoder_factory.h"
20 #include "media/engine/simulcast_encoder_adapter.h"
21 #include "modules/video_coding/utility/vp8_header_parser.h"
22 #include "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
23 #include "test/gtest.h"
24 #include "test/testsupport/file_utils.h"
25
26 namespace webrtc {
27 namespace test {
28
29 using VideoStatistics = VideoCodecTestStats::VideoStatistics;
30
31 namespace {
32 // Codec settings.
33 const int kCifWidth = 352;
34 const int kCifHeight = 288;
35 const int kNumFramesShort = 100;
36 const int kNumFramesLong = 300;
37 const size_t kBitrateRdPerfKbps[] = {100, 200, 300, 400, 500, 600,
38 700, 800, 1000, 1250, 1400, 1600,
39 1800, 2000, 2200, 2500};
40 const size_t kNumFirstFramesToSkipAtRdPerfAnalysis = 60;
41
42 class QpFrameChecker : public VideoCodecTestFixture::EncodedFrameChecker {
43 public:
CheckEncodedFrame(webrtc::VideoCodecType codec,const EncodedImage & encoded_frame) const44 void CheckEncodedFrame(webrtc::VideoCodecType codec,
45 const EncodedImage& encoded_frame) const override {
46 int qp;
47 if (codec == kVideoCodecVP8) {
48 EXPECT_TRUE(vp8::GetQp(encoded_frame.data(), encoded_frame.size(), &qp));
49 } else if (codec == kVideoCodecVP9) {
50 EXPECT_TRUE(vp9::GetQp(encoded_frame.data(), encoded_frame.size(), &qp));
51 } else {
52 RTC_DCHECK_NOTREACHED();
53 }
54 EXPECT_EQ(encoded_frame.qp_, qp) << "Encoder QP != parsed bitstream QP.";
55 }
56 };
57
CreateConfig()58 VideoCodecTestFixture::Config CreateConfig() {
59 VideoCodecTestFixture::Config config;
60 config.filename = "foreman_cif";
61 config.filepath = ResourcePath(config.filename, "yuv");
62 config.num_frames = kNumFramesLong;
63 config.use_single_core = true;
64 return config;
65 }
66
PrintRdPerf(std::map<size_t,std::vector<VideoStatistics>> rd_stats)67 void PrintRdPerf(std::map<size_t, std::vector<VideoStatistics>> rd_stats) {
68 printf("--> Summary\n");
69 printf("%11s %5s %6s %11s %12s %11s %13s %13s %5s %7s %7s %7s %13s %13s\n",
70 "uplink_kbps", "width", "height", "spatial_idx", "temporal_idx",
71 "target_kbps", "downlink_kbps", "framerate_fps", "psnr", "psnr_y",
72 "psnr_u", "psnr_v", "enc_speed_fps", "dec_speed_fps");
73 for (const auto& rd_stat : rd_stats) {
74 const size_t bitrate_kbps = rd_stat.first;
75 for (const auto& layer_stat : rd_stat.second) {
76 printf(
77 "%11zu %5zu %6zu %11zu %12zu %11zu %13zu %13.2f %5.2f %7.2f %7.2f "
78 "%7.2f"
79 "%13.2f %13.2f\n",
80 bitrate_kbps, layer_stat.width, layer_stat.height,
81 layer_stat.spatial_idx, layer_stat.temporal_idx,
82 layer_stat.target_bitrate_kbps, layer_stat.bitrate_kbps,
83 layer_stat.framerate_fps, layer_stat.avg_psnr, layer_stat.avg_psnr_y,
84 layer_stat.avg_psnr_u, layer_stat.avg_psnr_v,
85 layer_stat.enc_speed_fps, layer_stat.dec_speed_fps);
86 }
87 }
88 }
89 } // namespace
90
91 #if defined(RTC_ENABLE_VP9)
TEST(VideoCodecTestLibvpx,HighBitrateVP9)92 TEST(VideoCodecTestLibvpx, HighBitrateVP9) {
93 auto config = CreateConfig();
94 config.SetCodecSettings(cricket::kVp9CodecName, 1, 1, 1, false, true, false,
95 kCifWidth, kCifHeight);
96 config.num_frames = kNumFramesShort;
97 const auto frame_checker = std::make_unique<QpFrameChecker>();
98 config.encoded_frame_checker = frame_checker.get();
99 auto fixture = CreateVideoCodecTestFixture(config);
100
101 std::vector<RateProfile> rate_profiles = {{500, 30, 0}};
102
103 std::vector<RateControlThresholds> rc_thresholds = {
104 {5, 1, 0, 1, 0.3, 0.1, 0, 1}};
105
106 std::vector<QualityThresholds> quality_thresholds = {{37, 36, 0.94, 0.92}};
107
108 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
109 }
110
TEST(VideoCodecTestLibvpx,ChangeBitrateVP9)111 TEST(VideoCodecTestLibvpx, ChangeBitrateVP9) {
112 auto config = CreateConfig();
113 config.SetCodecSettings(cricket::kVp9CodecName, 1, 1, 1, false, true, false,
114 kCifWidth, kCifHeight);
115 const auto frame_checker = std::make_unique<QpFrameChecker>();
116 config.encoded_frame_checker = frame_checker.get();
117 auto fixture = CreateVideoCodecTestFixture(config);
118
119 std::vector<RateProfile> rate_profiles = {
120 {200, 30, 0}, // target_kbps, input_fps, frame_num
121 {700, 30, 100},
122 {500, 30, 200}};
123
124 std::vector<RateControlThresholds> rc_thresholds = {
125 {5, 2, 0, 1, 0.5, 0.1, 0, 1},
126 {15, 3, 0, 1, 0.5, 0.1, 0, 0},
127 {11, 2, 0, 1, 0.5, 0.1, 0, 0}};
128
129 std::vector<QualityThresholds> quality_thresholds = {
130 {34, 33, 0.90, 0.88}, {38, 35, 0.95, 0.91}, {35, 34, 0.93, 0.90}};
131
132 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
133 }
134
TEST(VideoCodecTestLibvpx,ChangeFramerateVP9)135 TEST(VideoCodecTestLibvpx, ChangeFramerateVP9) {
136 auto config = CreateConfig();
137 config.SetCodecSettings(cricket::kVp9CodecName, 1, 1, 1, false, true, false,
138 kCifWidth, kCifHeight);
139 const auto frame_checker = std::make_unique<QpFrameChecker>();
140 config.encoded_frame_checker = frame_checker.get();
141 auto fixture = CreateVideoCodecTestFixture(config);
142
143 std::vector<RateProfile> rate_profiles = {
144 {100, 24, 0}, // target_kbps, input_fps, frame_num
145 {100, 15, 100},
146 {100, 10, 200}};
147
148 // Framerate mismatch should be lower for lower framerate.
149 std::vector<RateControlThresholds> rc_thresholds = {
150 {10, 2, 40, 1, 0.5, 0.2, 0, 1},
151 {8, 2, 5, 1, 0.5, 0.2, 0, 0},
152 {5, 2, 0, 1, 0.5, 0.3, 0, 0}};
153
154 // Quality should be higher for lower framerates for the same content.
155 std::vector<QualityThresholds> quality_thresholds = {
156 {33, 32, 0.88, 0.86}, {33.5, 32, 0.90, 0.86}, {33.5, 31.5, 0.90, 0.85}};
157
158 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
159 }
160
TEST(VideoCodecTestLibvpx,DenoiserOnVP9)161 TEST(VideoCodecTestLibvpx, DenoiserOnVP9) {
162 auto config = CreateConfig();
163 config.SetCodecSettings(cricket::kVp9CodecName, 1, 1, 1, true, true, false,
164 kCifWidth, kCifHeight);
165 config.num_frames = kNumFramesShort;
166 const auto frame_checker = std::make_unique<QpFrameChecker>();
167 config.encoded_frame_checker = frame_checker.get();
168 auto fixture = CreateVideoCodecTestFixture(config);
169
170 std::vector<RateProfile> rate_profiles = {{500, 30, 0}};
171
172 std::vector<RateControlThresholds> rc_thresholds = {
173 {5, 1, 0, 1, 0.3, 0.1, 0, 1}};
174
175 std::vector<QualityThresholds> quality_thresholds = {{37.5, 36, 0.94, 0.93}};
176
177 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
178 }
179
TEST(VideoCodecTestLibvpx,VeryLowBitrateVP9)180 TEST(VideoCodecTestLibvpx, VeryLowBitrateVP9) {
181 auto config = CreateConfig();
182 config.SetCodecSettings(cricket::kVp9CodecName, 1, 1, 1, false, true, true,
183 kCifWidth, kCifHeight);
184 const auto frame_checker = std::make_unique<QpFrameChecker>();
185 config.encoded_frame_checker = frame_checker.get();
186 auto fixture = CreateVideoCodecTestFixture(config);
187
188 std::vector<RateProfile> rate_profiles = {{50, 30, 0}};
189
190 std::vector<RateControlThresholds> rc_thresholds = {
191 {15, 3, 75, 1, 0.5, 0.4, 2, 1}};
192
193 std::vector<QualityThresholds> quality_thresholds = {{28, 25, 0.80, 0.65}};
194
195 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
196 }
197
198 // TODO(marpan): Add temporal layer test for VP9, once changes are in
199 // vp9 wrapper for this.
200
201 #endif // defined(RTC_ENABLE_VP9)
202
TEST(VideoCodecTestLibvpx,HighBitrateVP8)203 TEST(VideoCodecTestLibvpx, HighBitrateVP8) {
204 auto config = CreateConfig();
205 config.SetCodecSettings(cricket::kVp8CodecName, 1, 1, 1, true, true, false,
206 kCifWidth, kCifHeight);
207 config.num_frames = kNumFramesShort;
208 const auto frame_checker = std::make_unique<QpFrameChecker>();
209 config.encoded_frame_checker = frame_checker.get();
210 auto fixture = CreateVideoCodecTestFixture(config);
211
212 std::vector<RateProfile> rate_profiles = {{500, 30, 0}};
213
214 std::vector<RateControlThresholds> rc_thresholds = {
215 {5, 1, 0, 1, 0.2, 0.1, 0, 1}};
216
217 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
218 std::vector<QualityThresholds> quality_thresholds = {{35, 33, 0.91, 0.89}};
219 #else
220 std::vector<QualityThresholds> quality_thresholds = {{37, 35, 0.93, 0.91}};
221 #endif
222 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
223 }
224
TEST(VideoCodecTestLibvpx,MAYBE_ChangeBitrateVP8)225 TEST(VideoCodecTestLibvpx, MAYBE_ChangeBitrateVP8) {
226 auto config = CreateConfig();
227 config.SetCodecSettings(cricket::kVp8CodecName, 1, 1, 1, true, true, false,
228 kCifWidth, kCifHeight);
229 const auto frame_checker = std::make_unique<QpFrameChecker>();
230 config.encoded_frame_checker = frame_checker.get();
231 auto fixture = CreateVideoCodecTestFixture(config);
232
233 std::vector<RateProfile> rate_profiles = {
234 {200, 30, 0}, // target_kbps, input_fps, frame_num
235 {800, 30, 100},
236 {500, 30, 200}};
237
238 std::vector<RateControlThresholds> rc_thresholds = {
239 {5, 1, 0, 1, 0.2, 0.1, 0, 1},
240 {15.5, 1, 0, 1, 0.2, 0.1, 0, 0},
241 {15, 1, 0, 1, 0.2, 0.1, 0, 0}};
242
243 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
244 std::vector<QualityThresholds> quality_thresholds = {
245 {31.8, 31, 0.86, 0.85}, {36, 34.8, 0.92, 0.90}, {33.5, 32, 0.90, 0.88}};
246 #else
247 std::vector<QualityThresholds> quality_thresholds = {
248 {33, 32, 0.89, 0.88}, {38, 36, 0.94, 0.93}, {35, 34, 0.92, 0.91}};
249 #endif
250 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
251 }
252
TEST(VideoCodecTestLibvpx,MAYBE_ChangeFramerateVP8)253 TEST(VideoCodecTestLibvpx, MAYBE_ChangeFramerateVP8) {
254 auto config = CreateConfig();
255 config.SetCodecSettings(cricket::kVp8CodecName, 1, 1, 1, true, true, false,
256 kCifWidth, kCifHeight);
257 const auto frame_checker = std::make_unique<QpFrameChecker>();
258 config.encoded_frame_checker = frame_checker.get();
259 auto fixture = CreateVideoCodecTestFixture(config);
260
261 std::vector<RateProfile> rate_profiles = {
262 {80, 24, 0}, // target_kbps, input_fps, frame_index_rate_update
263 {80, 15, 100},
264 {80, 10, 200}};
265
266 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
267 std::vector<RateControlThresholds> rc_thresholds = {
268 {10, 2.42, 60, 1, 0.3, 0.3, 0, 1},
269 {10, 2, 30, 1, 0.3, 0.3, 0, 0},
270 {10, 2, 10, 1, 0.3, 0.2, 0, 0}};
271 #else
272 std::vector<RateControlThresholds> rc_thresholds = {
273 {10, 2, 20, 1, 0.3, 0.15, 0, 1},
274 {5, 2, 5, 1, 0.3, 0.15, 0, 0},
275 {4, 2, 1, 1, 0.3, 0.2, 0, 0}};
276 #endif
277
278 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
279 std::vector<QualityThresholds> quality_thresholds = {
280 {31, 30, 0.85, 0.84}, {31.4, 30.5, 0.86, 0.84}, {30.5, 29, 0.83, 0.78}};
281 #else
282 std::vector<QualityThresholds> quality_thresholds = {
283 {31, 30, 0.87, 0.85}, {32, 31, 0.88, 0.85}, {32, 30, 0.87, 0.82}};
284 #endif
285 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
286 }
287
288 #if defined(WEBRTC_ANDROID)
289 #define MAYBE_TemporalLayersVP8 DISABLED_TemporalLayersVP8
290 #else
291 #define MAYBE_TemporalLayersVP8 TemporalLayersVP8
292 #endif
TEST(VideoCodecTestLibvpx,MAYBE_TemporalLayersVP8)293 TEST(VideoCodecTestLibvpx, MAYBE_TemporalLayersVP8) {
294 auto config = CreateConfig();
295 config.SetCodecSettings(cricket::kVp8CodecName, 1, 1, 3, true, true, false,
296 kCifWidth, kCifHeight);
297 const auto frame_checker = std::make_unique<QpFrameChecker>();
298 config.encoded_frame_checker = frame_checker.get();
299 auto fixture = CreateVideoCodecTestFixture(config);
300
301 std::vector<RateProfile> rate_profiles = {{200, 30, 0}, {400, 30, 150}};
302
303 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
304 std::vector<RateControlThresholds> rc_thresholds = {
305 {10, 1, 2.1, 1, 0.2, 0.1, 0, 1}, {12, 2, 3, 1, 0.2, 0.1, 0, 1}};
306 #else
307 std::vector<RateControlThresholds> rc_thresholds = {
308 {5, 1, 0, 1, 0.2, 0.1, 0, 1}, {10, 2, 0, 1, 0.2, 0.1, 0, 1}};
309 #endif
310 // Min SSIM drops because of high motion scene with complex backgound (trees).
311 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
312 std::vector<QualityThresholds> quality_thresholds = {{31, 30, 0.85, 0.83},
313 {31, 28, 0.85, 0.75}};
314 #else
315 std::vector<QualityThresholds> quality_thresholds = {{32, 30, 0.88, 0.85},
316 {33, 30, 0.89, 0.83}};
317 #endif
318 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
319 }
320
321 #if defined(WEBRTC_ANDROID)
322 #define MAYBE_MultiresVP8 DISABLED_MultiresVP8
323 #else
324 #define MAYBE_MultiresVP8 MultiresVP8
325 #endif
TEST(VideoCodecTestLibvpx,MAYBE_MultiresVP8)326 TEST(VideoCodecTestLibvpx, MAYBE_MultiresVP8) {
327 auto config = CreateConfig();
328 config.filename = "ConferenceMotion_1280_720_50";
329 config.filepath = ResourcePath(config.filename, "yuv");
330 config.num_frames = 100;
331 config.SetCodecSettings(cricket::kVp8CodecName, 3, 1, 3, true, true, false,
332 1280, 720);
333 const auto frame_checker = std::make_unique<QpFrameChecker>();
334 config.encoded_frame_checker = frame_checker.get();
335 auto fixture = CreateVideoCodecTestFixture(config);
336
337 std::vector<RateProfile> rate_profiles = {{1500, 30, 0}};
338 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64)
339 std::vector<RateControlThresholds> rc_thresholds = {
340 {4.1, 1.04, 7, 0.18, 0.14, 0.08, 0, 1}};
341 #else
342 std::vector<RateControlThresholds> rc_thresholds = {
343 {5, 1, 5, 1, 0.3, 0.1, 0, 1}};
344 #endif
345 std::vector<QualityThresholds> quality_thresholds = {{34, 32, 0.90, 0.88}};
346
347 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
348 }
349
350 #if defined(WEBRTC_ANDROID)
351 #define MAYBE_SimulcastVP8 DISABLED_SimulcastVP8
352 #else
353 #define MAYBE_SimulcastVP8 SimulcastVP8
354 #endif
TEST(VideoCodecTestLibvpx,MAYBE_SimulcastVP8)355 TEST(VideoCodecTestLibvpx, MAYBE_SimulcastVP8) {
356 auto config = CreateConfig();
357 config.filename = "ConferenceMotion_1280_720_50";
358 config.filepath = ResourcePath(config.filename, "yuv");
359 config.num_frames = 100;
360 config.SetCodecSettings(cricket::kVp8CodecName, 3, 1, 3, true, true, false,
361 1280, 720);
362 const auto frame_checker = std::make_unique<QpFrameChecker>();
363 config.encoded_frame_checker = frame_checker.get();
364
365 InternalEncoderFactory internal_encoder_factory;
366 std::unique_ptr<VideoEncoderFactory> adapted_encoder_factory =
367 std::make_unique<FunctionVideoEncoderFactory>([&]() {
368 return std::make_unique<SimulcastEncoderAdapter>(
369 &internal_encoder_factory, SdpVideoFormat(cricket::kVp8CodecName));
370 });
371 std::unique_ptr<InternalDecoderFactory> internal_decoder_factory(
372 new InternalDecoderFactory());
373
374 auto fixture =
375 CreateVideoCodecTestFixture(config, std::move(internal_decoder_factory),
376 std::move(adapted_encoder_factory));
377
378 std::vector<RateProfile> rate_profiles = {{1500, 30, 0}};
379
380 std::vector<RateControlThresholds> rc_thresholds = {
381 {20, 5, 90, 1, 0.5, 0.3, 0, 1}};
382 std::vector<QualityThresholds> quality_thresholds = {{34, 32, 0.90, 0.88}};
383
384 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
385 }
386
387 #if defined(WEBRTC_ANDROID)
388 #define MAYBE_SvcVP9 DISABLED_SvcVP9
389 #else
390 #define MAYBE_SvcVP9 SvcVP9
391 #endif
TEST(VideoCodecTestLibvpx,MAYBE_SvcVP9)392 TEST(VideoCodecTestLibvpx, MAYBE_SvcVP9) {
393 auto config = CreateConfig();
394 config.filename = "ConferenceMotion_1280_720_50";
395 config.filepath = ResourcePath(config.filename, "yuv");
396 config.num_frames = 100;
397 config.SetCodecSettings(cricket::kVp9CodecName, 1, 3, 3, true, true, false,
398 1280, 720);
399 const auto frame_checker = std::make_unique<QpFrameChecker>();
400 config.encoded_frame_checker = frame_checker.get();
401 auto fixture = CreateVideoCodecTestFixture(config);
402
403 std::vector<RateProfile> rate_profiles = {{1500, 30, 0}};
404
405 std::vector<RateControlThresholds> rc_thresholds = {
406 {5, 1, 5, 1, 0.3, 0.1, 0, 1}};
407 std::vector<QualityThresholds> quality_thresholds = {{36, 34, 0.93, 0.90}};
408
409 fixture->RunTest(rate_profiles, &rc_thresholds, &quality_thresholds, nullptr);
410 }
411
TEST(VideoCodecTestLibvpx,DISABLED_MultiresVP8RdPerf)412 TEST(VideoCodecTestLibvpx, DISABLED_MultiresVP8RdPerf) {
413 auto config = CreateConfig();
414 config.filename = "FourPeople_1280x720_30";
415 config.filepath = ResourcePath(config.filename, "yuv");
416 config.num_frames = 300;
417 config.print_frame_level_stats = true;
418 config.SetCodecSettings(cricket::kVp8CodecName, 3, 1, 3, true, true, false,
419 1280, 720);
420 const auto frame_checker = std::make_unique<QpFrameChecker>();
421 config.encoded_frame_checker = frame_checker.get();
422 auto fixture = CreateVideoCodecTestFixture(config);
423
424 std::map<size_t, std::vector<VideoStatistics>> rd_stats;
425 for (size_t bitrate_kbps : kBitrateRdPerfKbps) {
426 std::vector<RateProfile> rate_profiles = {{bitrate_kbps, 30, 0}};
427
428 fixture->RunTest(rate_profiles, nullptr, nullptr, nullptr);
429
430 rd_stats[bitrate_kbps] =
431 fixture->GetStats().SliceAndCalcLayerVideoStatistic(
432 kNumFirstFramesToSkipAtRdPerfAnalysis, config.num_frames - 1);
433 }
434
435 PrintRdPerf(rd_stats);
436 }
437
TEST(VideoCodecTestLibvpx,DISABLED_SvcVP9RdPerf)438 TEST(VideoCodecTestLibvpx, DISABLED_SvcVP9RdPerf) {
439 auto config = CreateConfig();
440 config.filename = "FourPeople_1280x720_30";
441 config.filepath = ResourcePath(config.filename, "yuv");
442 config.num_frames = 300;
443 config.print_frame_level_stats = true;
444 config.SetCodecSettings(cricket::kVp9CodecName, 1, 3, 3, true, true, false,
445 1280, 720);
446 const auto frame_checker = std::make_unique<QpFrameChecker>();
447 config.encoded_frame_checker = frame_checker.get();
448 auto fixture = CreateVideoCodecTestFixture(config);
449
450 std::map<size_t, std::vector<VideoStatistics>> rd_stats;
451 for (size_t bitrate_kbps : kBitrateRdPerfKbps) {
452 std::vector<RateProfile> rate_profiles = {{bitrate_kbps, 30, 0}};
453
454 fixture->RunTest(rate_profiles, nullptr, nullptr, nullptr);
455
456 rd_stats[bitrate_kbps] =
457 fixture->GetStats().SliceAndCalcLayerVideoStatistic(
458 kNumFirstFramesToSkipAtRdPerfAnalysis, config.num_frames - 1);
459 }
460
461 PrintRdPerf(rd_stats);
462 }
463
464 } // namespace test
465 } // namespace webrtc
466