OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 <assert.h> | 11 #include <assert.h> |
12 #include <stdio.h> | 12 #include <stdio.h> |
13 #include <time.h> | 13 #include <time.h> |
14 | 14 |
15 #include <stdarg.h> | 15 #include <stdarg.h> |
16 #include <sys/stat.h> // To check for directory existence. | 16 #include <sys/stat.h> // To check for directory existence. |
17 | 17 |
18 #ifndef S_ISDIR // Not defined in stat.h on Windows. | 18 #ifndef S_ISDIR // Not defined in stat.h on Windows. |
19 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) | 19 #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) |
20 #endif | 20 #endif |
21 | 21 |
22 #include "gflags/gflags.h" | 22 #include "gflags/gflags.h" |
23 #include "webrtc/base/format_macros.h" | 23 #include "webrtc/base/format_macros.h" |
24 #include "webrtc/common_types.h" | 24 #include "webrtc/common_types.h" |
25 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" | 25 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" |
26 #include "webrtc/modules/video_coding/codecs/test/stats.h" | 26 #include "webrtc/modules/video_coding/codecs/test/stats.h" |
27 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" | 27 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" |
28 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" | 28 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" |
29 #include "webrtc/modules/video_coding/include/video_coding.h" | 29 #include "webrtc/modules/video_coding/include/video_coding.h" |
30 #include "webrtc/system_wrappers/include/trace.h" | 30 #include "webrtc/system_wrappers/include/trace.h" |
31 #include "webrtc/test/testsupport/frame_reader.h" | 31 #include "webrtc/test/testsupport/frame_reader.h" |
32 #include "webrtc/test/testsupport/frame_writer.h" | 32 #include "webrtc/test/testsupport/frame_writer.h" |
33 #include "webrtc/test/testsupport/metrics/video_metrics.h" | 33 #include "webrtc/test/testsupport/metrics/video_metrics.h" |
34 #include "webrtc/test/testsupport/packet_reader.h" | 34 #include "webrtc/test/testsupport/packet_reader.h" |
35 | 35 |
36 DEFINE_string(test_name, "Quality test", "The name of the test to run. "); | 36 DEFINE_string(test_name, "Quality test", "The name of the test to run. "); |
37 DEFINE_string(test_description, "", "A more detailed description about what " | 37 DEFINE_string(test_description, |
| 38 "", |
| 39 "A more detailed description about what " |
38 "the current test is about."); | 40 "the current test is about."); |
39 DEFINE_string(input_filename, "", "Input file. " | 41 DEFINE_string(input_filename, |
| 42 "", |
| 43 "Input file. " |
40 "The source video file to be encoded and decoded. Must be in " | 44 "The source video file to be encoded and decoded. Must be in " |
41 ".yuv format"); | 45 ".yuv format"); |
42 DEFINE_int32(width, -1, "Width in pixels of the frames in the input file."); | 46 DEFINE_int32(width, -1, "Width in pixels of the frames in the input file."); |
43 DEFINE_int32(height, -1, "Height in pixels of the frames in the input file."); | 47 DEFINE_int32(height, -1, "Height in pixels of the frames in the input file."); |
44 DEFINE_int32(framerate, 30, "Frame rate of the input file, in FPS " | 48 DEFINE_int32(framerate, |
| 49 30, |
| 50 "Frame rate of the input file, in FPS " |
45 "(frames-per-second). "); | 51 "(frames-per-second). "); |
46 DEFINE_string(output_dir, ".", "Output directory. " | 52 DEFINE_string(output_dir, |
| 53 ".", |
| 54 "Output directory. " |
47 "The directory where the output file will be put. Must already " | 55 "The directory where the output file will be put. Must already " |
48 "exist."); | 56 "exist."); |
49 DEFINE_bool(use_single_core, false, "Force using a single core. If set to " | 57 DEFINE_bool(use_single_core, |
| 58 false, |
| 59 "Force using a single core. If set to " |
50 "true, only one core will be used for processing. Using a single " | 60 "true, only one core will be used for processing. Using a single " |
51 "core is necessary to get a deterministic behavior for the" | 61 "core is necessary to get a deterministic behavior for the" |
52 "encoded frames - using multiple cores will produce different " | 62 "encoded frames - using multiple cores will produce different " |
53 "encoded frames since multiple cores are competing to consume the " | 63 "encoded frames since multiple cores are competing to consume the " |
54 "byte budget for each frame in parallel. If set to false, " | 64 "byte budget for each frame in parallel. If set to false, " |
55 "the maximum detected number of cores will be used. "); | 65 "the maximum detected number of cores will be used. "); |
56 DEFINE_bool(disable_fixed_random_seed , false, "Set this flag to disable the" | 66 DEFINE_bool(disable_fixed_random_seed, |
| 67 false, |
| 68 "Set this flag to disable the" |
57 "usage of a fixed random seed for the random generator used " | 69 "usage of a fixed random seed for the random generator used " |
58 "for packet loss. Disabling this will cause consecutive runs " | 70 "for packet loss. Disabling this will cause consecutive runs " |
59 "loose packets at different locations, which is bad for " | 71 "loose packets at different locations, which is bad for " |
60 "reproducibility."); | 72 "reproducibility."); |
61 DEFINE_string(output_filename, "", "Output file. " | 73 DEFINE_string(output_filename, |
| 74 "", |
| 75 "Output file. " |
62 "The name of the output video file resulting of the processing " | 76 "The name of the output video file resulting of the processing " |
63 "of the source file. By default this is the same name as the " | 77 "of the source file. By default this is the same name as the " |
64 "input file with '_out' appended before the extension."); | 78 "input file with '_out' appended before the extension."); |
65 DEFINE_int32(bitrate, 500, "Bit rate in kilobits/second."); | 79 DEFINE_int32(bitrate, 500, "Bit rate in kilobits/second."); |
66 DEFINE_int32(keyframe_interval, 0, "Forces a keyframe every Nth frame. " | 80 DEFINE_int32(keyframe_interval, |
| 81 0, |
| 82 "Forces a keyframe every Nth frame. " |
67 "0 means the encoder decides when to insert keyframes. Note that " | 83 "0 means the encoder decides when to insert keyframes. Note that " |
68 "the encoder may create a keyframe in other locations in addition " | 84 "the encoder may create a keyframe in other locations in addition " |
69 "to the interval that is set using this parameter."); | 85 "to the interval that is set using this parameter."); |
70 DEFINE_int32(temporal_layers, 0, "The number of temporal layers to use " | 86 DEFINE_int32(temporal_layers, |
| 87 0, |
| 88 "The number of temporal layers to use " |
71 "(VP8 specific codec setting). Must be 0-4."); | 89 "(VP8 specific codec setting). Must be 0-4."); |
72 DEFINE_int32(packet_size, 1500, "Simulated network packet size in bytes (MTU). " | 90 DEFINE_int32(packet_size, |
| 91 1500, |
| 92 "Simulated network packet size in bytes (MTU). " |
73 "Used for packet loss simulation."); | 93 "Used for packet loss simulation."); |
74 DEFINE_int32(max_payload_size, 1440, "Max payload size in bytes for the " | 94 DEFINE_int32(max_payload_size, |
| 95 1440, |
| 96 "Max payload size in bytes for the " |
75 "encoder."); | 97 "encoder."); |
76 DEFINE_string(packet_loss_mode, "uniform", "Packet loss mode. Two different " | 98 DEFINE_string(packet_loss_mode, |
| 99 "uniform", |
| 100 "Packet loss mode. Two different " |
77 "packet loss models are supported: uniform or burst. This " | 101 "packet loss models are supported: uniform or burst. This " |
78 "setting has no effect unless packet_loss_rate is >0. "); | 102 "setting has no effect unless packet_loss_rate is >0. "); |
79 DEFINE_double(packet_loss_probability, 0.0, "Packet loss probability. A value " | 103 DEFINE_double(packet_loss_probability, |
| 104 0.0, |
| 105 "Packet loss probability. A value " |
80 "between 0.0 and 1.0 that defines the probability of a packet " | 106 "between 0.0 and 1.0 that defines the probability of a packet " |
81 "being lost. 0.1 means 10% and so on."); | 107 "being lost. 0.1 means 10% and so on."); |
82 DEFINE_int32(packet_loss_burst_length, 1, "Packet loss burst length. Defines " | 108 DEFINE_int32(packet_loss_burst_length, |
| 109 1, |
| 110 "Packet loss burst length. Defines " |
83 "how many packets will be lost in a burst when a packet has been " | 111 "how many packets will be lost in a burst when a packet has been " |
84 "decided to be lost. Must be >=1."); | 112 "decided to be lost. Must be >=1."); |
85 DEFINE_bool(csv, false, "CSV output. Enabling this will output all frame " | 113 DEFINE_bool(csv, |
| 114 false, |
| 115 "CSV output. Enabling this will output all frame " |
86 "statistics at the end of execution. Recommended to run combined " | 116 "statistics at the end of execution. Recommended to run combined " |
87 "with --noverbose to avoid mixing output."); | 117 "with --noverbose to avoid mixing output."); |
88 DEFINE_bool(python, false, "Python output. Enabling this will output all frame " | 118 DEFINE_bool(python, |
| 119 false, |
| 120 "Python output. Enabling this will output all frame " |
89 "statistics as a Python script at the end of execution. " | 121 "statistics as a Python script at the end of execution. " |
90 "Recommended to run combine with --noverbose to avoid mixing " | 122 "Recommended to run combine with --noverbose to avoid mixing " |
91 "output."); | 123 "output."); |
92 DEFINE_bool(verbose, true, "Verbose mode. Prints a lot of debugging info. " | 124 DEFINE_bool(verbose, |
| 125 true, |
| 126 "Verbose mode. Prints a lot of debugging info. " |
93 "Suitable for tracking progress but not for capturing output. " | 127 "Suitable for tracking progress but not for capturing output. " |
94 "Disable with --noverbose flag."); | 128 "Disable with --noverbose flag."); |
95 | 129 |
96 // Custom log method that only prints if the verbose flag is given. | 130 // Custom log method that only prints if the verbose flag is given. |
97 // Supports all the standard printf parameters and formatting (just forwarded). | 131 // Supports all the standard printf parameters and formatting (just forwarded). |
98 int Log(const char *format, ...) { | 132 int Log(const char* format, ...) { |
99 int result = 0; | 133 int result = 0; |
100 if (FLAGS_verbose) { | 134 if (FLAGS_verbose) { |
101 va_list args; | 135 va_list args; |
102 va_start(args, format); | 136 va_start(args, format); |
103 result = vprintf(format, args); | 137 result = vprintf(format, args); |
104 va_end(args); | 138 va_end(args); |
105 } | 139 } |
106 return result; | 140 return result; |
107 } | 141 } |
108 | 142 |
(...skipping 16 matching lines...) Expand all Loading... |
125 fprintf(stderr, "Cannot read the specified input file: %s\n", | 159 fprintf(stderr, "Cannot read the specified input file: %s\n", |
126 FLAGS_input_filename.c_str()); | 160 FLAGS_input_filename.c_str()); |
127 return 2; | 161 return 2; |
128 } | 162 } |
129 fclose(test_file); | 163 fclose(test_file); |
130 config->input_filename = FLAGS_input_filename; | 164 config->input_filename = FLAGS_input_filename; |
131 | 165 |
132 // Verify the output dir exists. | 166 // Verify the output dir exists. |
133 struct stat dir_info; | 167 struct stat dir_info; |
134 if (!(stat(FLAGS_output_dir.c_str(), &dir_info) == 0 && | 168 if (!(stat(FLAGS_output_dir.c_str(), &dir_info) == 0 && |
135 S_ISDIR(dir_info.st_mode))) { | 169 S_ISDIR(dir_info.st_mode))) { |
136 fprintf(stderr, "Cannot find output directory: %s\n", | 170 fprintf(stderr, "Cannot find output directory: %s\n", |
137 FLAGS_output_dir.c_str()); | 171 FLAGS_output_dir.c_str()); |
138 return 3; | 172 return 3; |
139 } | 173 } |
140 config->output_dir = FLAGS_output_dir; | 174 config->output_dir = FLAGS_output_dir; |
141 | 175 |
142 // Manufacture an output filename if none was given. | 176 // Manufacture an output filename if none was given. |
143 if (FLAGS_output_filename.empty()) { | 177 if (FLAGS_output_filename.empty()) { |
144 // Cut out the filename without extension from the given input file | 178 // Cut out the filename without extension from the given input file |
145 // (which may include a path) | 179 // (which may include a path) |
146 int startIndex = FLAGS_input_filename.find_last_of("/") + 1; | 180 int startIndex = FLAGS_input_filename.find_last_of("/") + 1; |
147 if (startIndex == 0) { | 181 if (startIndex == 0) { |
148 startIndex = 0; | 182 startIndex = 0; |
149 } | 183 } |
150 FLAGS_output_filename = | 184 FLAGS_output_filename = |
151 FLAGS_input_filename.substr(startIndex, | 185 FLAGS_input_filename.substr( |
152 FLAGS_input_filename.find_last_of(".") | 186 startIndex, FLAGS_input_filename.find_last_of(".") - startIndex) + |
153 - startIndex) + "_out.yuv"; | 187 "_out.yuv"; |
154 } | 188 } |
155 | 189 |
156 // Verify output file can be written. | 190 // Verify output file can be written. |
157 if (FLAGS_output_dir == ".") { | 191 if (FLAGS_output_dir == ".") { |
158 config->output_filename = FLAGS_output_filename; | 192 config->output_filename = FLAGS_output_filename; |
159 } else { | 193 } else { |
160 config->output_filename = FLAGS_output_dir + "/"+ FLAGS_output_filename; | 194 config->output_filename = FLAGS_output_dir + "/" + FLAGS_output_filename; |
161 } | 195 } |
162 test_file = fopen(config->output_filename.c_str(), "wb"); | 196 test_file = fopen(config->output_filename.c_str(), "wb"); |
163 if (test_file == NULL) { | 197 if (test_file == NULL) { |
164 fprintf(stderr, "Cannot write output file: %s\n", | 198 fprintf(stderr, "Cannot write output file: %s\n", |
165 config->output_filename.c_str()); | 199 config->output_filename.c_str()); |
166 return 4; | 200 return 4; |
167 } | 201 } |
168 fclose(test_file); | 202 fclose(test_file); |
169 | 203 |
170 // Check single core flag. | 204 // Check single core flag. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 config->codec_settings->height = FLAGS_height; | 259 config->codec_settings->height = FLAGS_height; |
226 config->codec_settings->maxFramerate = FLAGS_framerate; | 260 config->codec_settings->maxFramerate = FLAGS_framerate; |
227 | 261 |
228 // Calculate the size of each frame to read (according to YUV spec). | 262 // Calculate the size of each frame to read (according to YUV spec). |
229 config->frame_length_in_bytes = | 263 config->frame_length_in_bytes = |
230 3 * config->codec_settings->width * config->codec_settings->height / 2; | 264 3 * config->codec_settings->width * config->codec_settings->height / 2; |
231 | 265 |
232 // Check packet loss settings | 266 // Check packet loss settings |
233 if (FLAGS_packet_loss_mode != "uniform" && | 267 if (FLAGS_packet_loss_mode != "uniform" && |
234 FLAGS_packet_loss_mode != "burst") { | 268 FLAGS_packet_loss_mode != "burst") { |
235 fprintf(stderr, "Unsupported packet loss mode, must be 'uniform' or " | 269 fprintf(stderr, |
| 270 "Unsupported packet loss mode, must be 'uniform' or " |
236 "'burst'\n."); | 271 "'burst'\n."); |
237 return 10; | 272 return 10; |
238 } | 273 } |
239 config->networking_config.packet_loss_mode = webrtc::test::kUniform; | 274 config->networking_config.packet_loss_mode = webrtc::test::kUniform; |
240 if (FLAGS_packet_loss_mode == "burst") { | 275 if (FLAGS_packet_loss_mode == "burst") { |
241 config->networking_config.packet_loss_mode = webrtc::test::kBurst; | 276 config->networking_config.packet_loss_mode = webrtc::test::kBurst; |
242 } | 277 } |
243 | 278 |
244 if (FLAGS_packet_loss_probability < 0.0 || | 279 if (FLAGS_packet_loss_probability < 0.0 || |
245 FLAGS_packet_loss_probability > 1.0) { | 280 FLAGS_packet_loss_probability > 1.0) { |
246 fprintf(stderr, "Invalid packet loss probability. Must be 0.0 - 1.0, " | 281 fprintf(stderr, |
247 "was: %f\n", FLAGS_packet_loss_probability); | 282 "Invalid packet loss probability. Must be 0.0 - 1.0, " |
| 283 "was: %f\n", |
| 284 FLAGS_packet_loss_probability); |
248 return 11; | 285 return 11; |
249 } | 286 } |
250 config->networking_config.packet_loss_probability = | 287 config->networking_config.packet_loss_probability = |
251 FLAGS_packet_loss_probability; | 288 FLAGS_packet_loss_probability; |
252 | 289 |
253 if (FLAGS_packet_loss_burst_length < 1) { | 290 if (FLAGS_packet_loss_burst_length < 1) { |
254 fprintf(stderr, "Invalid packet loss burst length, must be >=1, " | 291 fprintf(stderr, |
255 "was: %d\n", FLAGS_packet_loss_burst_length); | 292 "Invalid packet loss burst length, must be >=1, " |
| 293 "was: %d\n", |
| 294 FLAGS_packet_loss_burst_length); |
256 return 12; | 295 return 12; |
257 } | 296 } |
258 config->networking_config.packet_loss_burst_length = | 297 config->networking_config.packet_loss_burst_length = |
259 FLAGS_packet_loss_burst_length; | 298 FLAGS_packet_loss_burst_length; |
260 config->verbose = FLAGS_verbose; | 299 config->verbose = FLAGS_verbose; |
261 return 0; | 300 return 0; |
262 } | 301 } |
263 | 302 |
264 void CalculateSsimVideoMetrics(webrtc::test::TestConfig* config, | 303 void CalculateSsimVideoMetrics(webrtc::test::TestConfig* config, |
265 webrtc::test::QualityMetricsResult* result) { | 304 webrtc::test::QualityMetricsResult* result) { |
266 Log("Calculating SSIM...\n"); | 305 Log("Calculating SSIM...\n"); |
267 I420SSIMFromFiles(config->input_filename.c_str(), | 306 I420SSIMFromFiles( |
268 config->output_filename.c_str(), | 307 config->input_filename.c_str(), config->output_filename.c_str(), |
269 config->codec_settings->width, | 308 config->codec_settings->width, config->codec_settings->height, result); |
270 config->codec_settings->height, result); | |
271 Log(" Average: %3.2f\n", result->average); | 309 Log(" Average: %3.2f\n", result->average); |
272 Log(" Min : %3.2f (frame %d)\n", result->min, result->min_frame_number); | 310 Log(" Min : %3.2f (frame %d)\n", result->min, result->min_frame_number); |
273 Log(" Max : %3.2f (frame %d)\n", result->max, result->max_frame_number); | 311 Log(" Max : %3.2f (frame %d)\n", result->max, result->max_frame_number); |
274 } | 312 } |
275 | 313 |
276 void CalculatePsnrVideoMetrics(webrtc::test::TestConfig* config, | 314 void CalculatePsnrVideoMetrics(webrtc::test::TestConfig* config, |
277 webrtc::test::QualityMetricsResult* result) { | 315 webrtc::test::QualityMetricsResult* result) { |
278 Log("Calculating PSNR...\n"); | 316 Log("Calculating PSNR...\n"); |
279 I420PSNRFromFiles(config->input_filename.c_str(), | 317 I420PSNRFromFiles( |
280 config->output_filename.c_str(), | 318 config->input_filename.c_str(), config->output_filename.c_str(), |
281 config->codec_settings->width, | 319 config->codec_settings->width, config->codec_settings->height, result); |
282 config->codec_settings->height, result); | |
283 Log(" Average: %3.2f\n", result->average); | 320 Log(" Average: %3.2f\n", result->average); |
284 Log(" Min : %3.2f (frame %d)\n", result->min, result->min_frame_number); | 321 Log(" Min : %3.2f (frame %d)\n", result->min, result->min_frame_number); |
285 Log(" Max : %3.2f (frame %d)\n", result->max, result->max_frame_number); | 322 Log(" Max : %3.2f (frame %d)\n", result->max, result->max_frame_number); |
286 } | 323 } |
287 | 324 |
288 void PrintConfigurationSummary(const webrtc::test::TestConfig& config) { | 325 void PrintConfigurationSummary(const webrtc::test::TestConfig& config) { |
289 Log("Quality test with parameters:\n"); | 326 Log("Quality test with parameters:\n"); |
290 Log(" Test name : %s\n", config.name.c_str()); | 327 Log(" Test name : %s\n", config.name.c_str()); |
291 Log(" Description : %s\n", config.description.c_str()); | 328 Log(" Description : %s\n", config.description.c_str()); |
292 Log(" Input filename : %s\n", config.input_filename.c_str()); | 329 Log(" Input filename : %s\n", config.input_filename.c_str()); |
293 Log(" Output directory : %s\n", config.output_dir.c_str()); | 330 Log(" Output directory : %s\n", config.output_dir.c_str()); |
294 Log(" Output filename : %s\n", config.output_filename.c_str()); | 331 Log(" Output filename : %s\n", config.output_filename.c_str()); |
295 Log(" Frame length : %" PRIuS " bytes\n", config.frame_length_in_bytes); | 332 Log(" Frame length : %" PRIuS " bytes\n", config.frame_length_in_bytes); |
296 Log(" Packet size : %" PRIuS " bytes\n", | 333 Log(" Packet size : %" PRIuS " bytes\n", |
297 config.networking_config.packet_size_in_bytes); | 334 config.networking_config.packet_size_in_bytes); |
298 Log(" Max payload size : %" PRIuS " bytes\n", | 335 Log(" Max payload size : %" PRIuS " bytes\n", |
299 config.networking_config.max_payload_size_in_bytes); | 336 config.networking_config.max_payload_size_in_bytes); |
300 Log(" Packet loss:\n"); | 337 Log(" Packet loss:\n"); |
301 Log(" Mode : %s\n", | 338 Log(" Mode : %s\n", |
302 PacketLossModeToStr(config.networking_config.packet_loss_mode)); | 339 PacketLossModeToStr(config.networking_config.packet_loss_mode)); |
303 Log(" Probability : %2.1f\n", | 340 Log(" Probability : %2.1f\n", |
304 config.networking_config.packet_loss_probability); | 341 config.networking_config.packet_loss_probability); |
305 Log(" Burst length : %d packets\n", | 342 Log(" Burst length : %d packets\n", |
306 config.networking_config.packet_loss_burst_length); | 343 config.networking_config.packet_loss_burst_length); |
307 } | 344 } |
308 | 345 |
309 void PrintCsvOutput(const webrtc::test::Stats& stats, | 346 void PrintCsvOutput(const webrtc::test::Stats& stats, |
310 const webrtc::test::QualityMetricsResult& ssim_result, | 347 const webrtc::test::QualityMetricsResult& ssim_result, |
311 const webrtc::test::QualityMetricsResult& psnr_result) { | 348 const webrtc::test::QualityMetricsResult& psnr_result) { |
312 Log("\nCSV output (recommended to run with --noverbose to skip the " | 349 Log( |
313 "above output)\n"); | 350 "\nCSV output (recommended to run with --noverbose to skip the " |
314 printf("frame_number encoding_successful decoding_successful " | 351 "above output)\n"); |
| 352 printf( |
| 353 "frame_number encoding_successful decoding_successful " |
315 "encode_return_code decode_return_code " | 354 "encode_return_code decode_return_code " |
316 "encode_time_in_us decode_time_in_us " | 355 "encode_time_in_us decode_time_in_us " |
317 "bit_rate_in_kbps encoded_frame_length_in_bytes frame_type " | 356 "bit_rate_in_kbps encoded_frame_length_in_bytes frame_type " |
318 "packets_dropped total_packets " | 357 "packets_dropped total_packets " |
319 "ssim psnr\n"); | 358 "ssim psnr\n"); |
320 | 359 |
321 for (unsigned int i = 0; i < stats.stats_.size(); ++i) { | 360 for (unsigned int i = 0; i < stats.stats_.size(); ++i) { |
322 const webrtc::test::FrameStatistic& f = stats.stats_[i]; | 361 const webrtc::test::FrameStatistic& f = stats.stats_[i]; |
323 const webrtc::test::FrameResult& ssim = ssim_result.frames[i]; | 362 const webrtc::test::FrameResult& ssim = ssim_result.frames[i]; |
324 const webrtc::test::FrameResult& psnr = psnr_result.frames[i]; | 363 const webrtc::test::FrameResult& psnr = psnr_result.frames[i]; |
325 printf("%4d, %d, %d, %2d, %2d, %6d, %6d, %5d, %7" PRIuS ", %d, %2d, %2" | 364 printf("%4d, %d, %d, %2d, %2d, %6d, %6d, %5d, %7" PRIuS |
326 PRIuS ", %5.3f, %5.2f\n", | 365 ", %d, %2d, %2" PRIuS ", %5.3f, %5.2f\n", |
327 f.frame_number, | 366 f.frame_number, f.encoding_successful, f.decoding_successful, |
328 f.encoding_successful, | 367 f.encode_return_code, f.decode_return_code, f.encode_time_in_us, |
329 f.decoding_successful, | 368 f.decode_time_in_us, f.bit_rate_in_kbps, |
330 f.encode_return_code, | 369 f.encoded_frame_length_in_bytes, f.frame_type, f.packets_dropped, |
331 f.decode_return_code, | 370 f.total_packets, ssim.value, psnr.value); |
332 f.encode_time_in_us, | |
333 f.decode_time_in_us, | |
334 f.bit_rate_in_kbps, | |
335 f.encoded_frame_length_in_bytes, | |
336 f.frame_type, | |
337 f.packets_dropped, | |
338 f.total_packets, | |
339 ssim.value, | |
340 psnr.value); | |
341 } | 371 } |
342 } | 372 } |
343 | 373 |
344 void PrintPythonOutput(const webrtc::test::TestConfig& config, | 374 void PrintPythonOutput(const webrtc::test::TestConfig& config, |
345 const webrtc::test::Stats& stats, | 375 const webrtc::test::Stats& stats, |
346 const webrtc::test::QualityMetricsResult& ssim_result, | 376 const webrtc::test::QualityMetricsResult& ssim_result, |
347 const webrtc::test::QualityMetricsResult& psnr_result) { | 377 const webrtc::test::QualityMetricsResult& psnr_result) { |
348 Log("\nPython output (recommended to run with --noverbose to skip the " | 378 Log( |
349 "above output)\n"); | 379 "\nPython output (recommended to run with --noverbose to skip the " |
350 printf("test_configuration = [" | 380 "above output)\n"); |
351 "{'name': 'name', 'value': '%s'},\n" | 381 printf( |
352 "{'name': 'description', 'value': '%s'},\n" | 382 "test_configuration = [" |
353 "{'name': 'test_number', 'value': '%d'},\n" | 383 "{'name': 'name', 'value': '%s'},\n" |
354 "{'name': 'input_filename', 'value': '%s'},\n" | 384 "{'name': 'description', 'value': '%s'},\n" |
355 "{'name': 'output_filename', 'value': '%s'},\n" | 385 "{'name': 'test_number', 'value': '%d'},\n" |
356 "{'name': 'output_dir', 'value': '%s'},\n" | 386 "{'name': 'input_filename', 'value': '%s'},\n" |
357 "{'name': 'packet_size_in_bytes', 'value': '%" PRIuS "'},\n" | 387 "{'name': 'output_filename', 'value': '%s'},\n" |
358 "{'name': 'max_payload_size_in_bytes', 'value': '%" PRIuS "'},\n" | 388 "{'name': 'output_dir', 'value': '%s'},\n" |
359 "{'name': 'packet_loss_mode', 'value': '%s'},\n" | 389 "{'name': 'packet_size_in_bytes', 'value': '%" PRIuS |
360 "{'name': 'packet_loss_probability', 'value': '%f'},\n" | 390 "'},\n" |
361 "{'name': 'packet_loss_burst_length', 'value': '%d'},\n" | 391 "{'name': 'max_payload_size_in_bytes', 'value': '%" PRIuS |
362 "{'name': 'exclude_frame_types', 'value': '%s'},\n" | 392 "'},\n" |
363 "{'name': 'frame_length_in_bytes', 'value': '%" PRIuS "'},\n" | 393 "{'name': 'packet_loss_mode', 'value': '%s'},\n" |
364 "{'name': 'use_single_core', 'value': '%s'},\n" | 394 "{'name': 'packet_loss_probability', 'value': '%f'},\n" |
365 "{'name': 'keyframe_interval;', 'value': '%d'},\n" | 395 "{'name': 'packet_loss_burst_length', 'value': '%d'},\n" |
366 "{'name': 'video_codec_type', 'value': '%s'},\n" | 396 "{'name': 'exclude_frame_types', 'value': '%s'},\n" |
367 "{'name': 'width', 'value': '%d'},\n" | 397 "{'name': 'frame_length_in_bytes', 'value': '%" PRIuS |
368 "{'name': 'height', 'value': '%d'},\n" | 398 "'},\n" |
369 "{'name': 'bit_rate_in_kbps', 'value': '%d'},\n" | 399 "{'name': 'use_single_core', 'value': '%s'},\n" |
370 "]\n", | 400 "{'name': 'keyframe_interval;', 'value': '%d'},\n" |
371 config.name.c_str(), | 401 "{'name': 'video_codec_type', 'value': '%s'},\n" |
372 config.description.c_str(), | 402 "{'name': 'width', 'value': '%d'},\n" |
373 config.test_number, | 403 "{'name': 'height', 'value': '%d'},\n" |
374 config.input_filename.c_str(), | 404 "{'name': 'bit_rate_in_kbps', 'value': '%d'},\n" |
375 config.output_filename.c_str(), | 405 "]\n", |
376 config.output_dir.c_str(), | 406 config.name.c_str(), config.description.c_str(), config.test_number, |
377 config.networking_config.packet_size_in_bytes, | 407 config.input_filename.c_str(), config.output_filename.c_str(), |
378 config.networking_config.max_payload_size_in_bytes, | 408 config.output_dir.c_str(), config.networking_config.packet_size_in_bytes, |
379 PacketLossModeToStr(config.networking_config.packet_loss_mode), | 409 config.networking_config.max_payload_size_in_bytes, |
380 config.networking_config.packet_loss_probability, | 410 PacketLossModeToStr(config.networking_config.packet_loss_mode), |
381 config.networking_config.packet_loss_burst_length, | 411 config.networking_config.packet_loss_probability, |
382 ExcludeFrameTypesToStr(config.exclude_frame_types), | 412 config.networking_config.packet_loss_burst_length, |
383 config.frame_length_in_bytes, | 413 ExcludeFrameTypesToStr(config.exclude_frame_types), |
384 config.use_single_core ? "True " : "False", | 414 config.frame_length_in_bytes, config.use_single_core ? "True " : "False", |
385 config.keyframe_interval, | 415 config.keyframe_interval, |
386 webrtc::test::VideoCodecTypeToStr(config.codec_settings->codecType), | 416 webrtc::test::VideoCodecTypeToStr(config.codec_settings->codecType), |
387 config.codec_settings->width, | 417 config.codec_settings->width, config.codec_settings->height, |
388 config.codec_settings->height, | 418 config.codec_settings->startBitrate); |
389 config.codec_settings->startBitrate); | 419 printf( |
390 printf("frame_data_types = {" | 420 "frame_data_types = {" |
391 "'frame_number': ('number', 'Frame number'),\n" | 421 "'frame_number': ('number', 'Frame number'),\n" |
392 "'encoding_successful': ('boolean', 'Encoding successful?'),\n" | 422 "'encoding_successful': ('boolean', 'Encoding successful?'),\n" |
393 "'decoding_successful': ('boolean', 'Decoding successful?'),\n" | 423 "'decoding_successful': ('boolean', 'Decoding successful?'),\n" |
394 "'encode_time': ('number', 'Encode time (us)'),\n" | 424 "'encode_time': ('number', 'Encode time (us)'),\n" |
395 "'decode_time': ('number', 'Decode time (us)'),\n" | 425 "'decode_time': ('number', 'Decode time (us)'),\n" |
396 "'encode_return_code': ('number', 'Encode return code'),\n" | 426 "'encode_return_code': ('number', 'Encode return code'),\n" |
397 "'decode_return_code': ('number', 'Decode return code'),\n" | 427 "'decode_return_code': ('number', 'Decode return code'),\n" |
398 "'bit_rate': ('number', 'Bit rate (kbps)'),\n" | 428 "'bit_rate': ('number', 'Bit rate (kbps)'),\n" |
399 "'encoded_frame_length': " | 429 "'encoded_frame_length': " |
400 "('number', 'Encoded frame length (bytes)'),\n" | 430 "('number', 'Encoded frame length (bytes)'),\n" |
401 "'frame_type': ('string', 'Frame type'),\n" | 431 "'frame_type': ('string', 'Frame type'),\n" |
402 "'packets_dropped': ('number', 'Packets dropped'),\n" | 432 "'packets_dropped': ('number', 'Packets dropped'),\n" |
403 "'total_packets': ('number', 'Total packets'),\n" | 433 "'total_packets': ('number', 'Total packets'),\n" |
404 "'ssim': ('number', 'SSIM'),\n" | 434 "'ssim': ('number', 'SSIM'),\n" |
405 "'psnr': ('number', 'PSNR (dB)'),\n" | 435 "'psnr': ('number', 'PSNR (dB)'),\n" |
406 "}\n"); | 436 "}\n"); |
407 printf("frame_data = ["); | 437 printf("frame_data = ["); |
408 for (unsigned int i = 0; i < stats.stats_.size(); ++i) { | 438 for (unsigned int i = 0; i < stats.stats_.size(); ++i) { |
409 const webrtc::test::FrameStatistic& f = stats.stats_[i]; | 439 const webrtc::test::FrameStatistic& f = stats.stats_[i]; |
410 const webrtc::test::FrameResult& ssim = ssim_result.frames[i]; | 440 const webrtc::test::FrameResult& ssim = ssim_result.frames[i]; |
411 const webrtc::test::FrameResult& psnr = psnr_result.frames[i]; | 441 const webrtc::test::FrameResult& psnr = psnr_result.frames[i]; |
412 printf("{'frame_number': %d, " | 442 printf( |
413 "'encoding_successful': %s, 'decoding_successful': %s, " | 443 "{'frame_number': %d, " |
414 "'encode_time': %d, 'decode_time': %d, " | 444 "'encoding_successful': %s, 'decoding_successful': %s, " |
415 "'encode_return_code': %d, 'decode_return_code': %d, " | 445 "'encode_time': %d, 'decode_time': %d, " |
416 "'bit_rate': %d, 'encoded_frame_length': %" PRIuS ", " | 446 "'encode_return_code': %d, 'decode_return_code': %d, " |
417 "'frame_type': %s, 'packets_dropped': %d, " | 447 "'bit_rate': %d, 'encoded_frame_length': %" PRIuS |
418 "'total_packets': %" PRIuS ", 'ssim': %f, 'psnr': %f},\n", | 448 ", " |
419 f.frame_number, | 449 "'frame_type': %s, 'packets_dropped': %d, " |
420 f.encoding_successful ? "True " : "False", | 450 "'total_packets': %" PRIuS ", 'ssim': %f, 'psnr': %f},\n", |
421 f.decoding_successful ? "True " : "False", | 451 f.frame_number, f.encoding_successful ? "True " : "False", |
422 f.encode_time_in_us, | 452 f.decoding_successful ? "True " : "False", f.encode_time_in_us, |
423 f.decode_time_in_us, | 453 f.decode_time_in_us, f.encode_return_code, f.decode_return_code, |
424 f.encode_return_code, | 454 f.bit_rate_in_kbps, f.encoded_frame_length_in_bytes, |
425 f.decode_return_code, | 455 f.frame_type == webrtc::kVideoFrameDelta ? "'Delta'" : "'Other'", |
426 f.bit_rate_in_kbps, | 456 f.packets_dropped, f.total_packets, ssim.value, psnr.value); |
427 f.encoded_frame_length_in_bytes, | |
428 f.frame_type == webrtc::kVideoFrameDelta ? "'Delta'" : "'Other'", | |
429 f.packets_dropped, | |
430 f.total_packets, | |
431 ssim.value, | |
432 psnr.value); | |
433 } | 457 } |
434 printf("]\n"); | 458 printf("]\n"); |
435 } | 459 } |
436 | 460 |
437 // Runs a quality measurement on the input file supplied to the program. | 461 // Runs a quality measurement on the input file supplied to the program. |
438 // The input file must be in YUV format. | 462 // The input file must be in YUV format. |
439 int main(int argc, char* argv[]) { | 463 int main(int argc, char* argv[]) { |
440 std::string program_name = argv[0]; | 464 std::string program_name = argv[0]; |
441 std::string usage = "Quality test application for video comparisons.\n" | 465 std::string usage = |
442 "Run " + program_name + " --helpshort for usage.\n" | 466 "Quality test application for video comparisons.\n" |
443 "Example usage:\n" + program_name + | 467 "Run " + |
444 " --input_filename=filename.yuv --width=352 --height=288\n"; | 468 program_name + |
| 469 " --helpshort for usage.\n" |
| 470 "Example usage:\n" + |
| 471 program_name + |
| 472 " --input_filename=filename.yuv --width=352 --height=288\n"; |
445 google::SetUsageMessage(usage); | 473 google::SetUsageMessage(usage); |
446 | 474 |
447 google::ParseCommandLineFlags(&argc, &argv, true); | 475 google::ParseCommandLineFlags(&argc, &argv, true); |
448 | 476 |
449 // Create TestConfig and codec settings struct. | 477 // Create TestConfig and codec settings struct. |
450 webrtc::test::TestConfig config; | 478 webrtc::test::TestConfig config; |
451 webrtc::VideoCodec codec_settings; | 479 webrtc::VideoCodec codec_settings; |
452 config.codec_settings = &codec_settings; | 480 config.codec_settings = &codec_settings; |
453 | 481 |
454 int return_code = HandleCommandLineFlags(&config); | 482 int return_code = HandleCommandLineFlags(&config); |
(...skipping 16 matching lines...) Expand all Loading... |
471 webrtc::test::PacketReader packet_reader; | 499 webrtc::test::PacketReader packet_reader; |
472 | 500 |
473 webrtc::test::PacketManipulatorImpl packet_manipulator( | 501 webrtc::test::PacketManipulatorImpl packet_manipulator( |
474 &packet_reader, config.networking_config, config.verbose); | 502 &packet_reader, config.networking_config, config.verbose); |
475 // By default the packet manipulator is seeded with a fixed random. | 503 // By default the packet manipulator is seeded with a fixed random. |
476 // If disabled we must generate a new seed. | 504 // If disabled we must generate a new seed. |
477 if (FLAGS_disable_fixed_random_seed) { | 505 if (FLAGS_disable_fixed_random_seed) { |
478 packet_manipulator.InitializeRandomSeed(time(NULL)); | 506 packet_manipulator.InitializeRandomSeed(time(NULL)); |
479 } | 507 } |
480 webrtc::test::VideoProcessor* processor = | 508 webrtc::test::VideoProcessor* processor = |
481 new webrtc::test::VideoProcessorImpl(encoder, decoder, | 509 new webrtc::test::VideoProcessorImpl(encoder, decoder, &frame_reader, |
482 &frame_reader, | 510 &frame_writer, &packet_manipulator, |
483 &frame_writer, | |
484 &packet_manipulator, | |
485 config, &stats); | 511 config, &stats); |
486 processor->Init(); | 512 processor->Init(); |
487 | 513 |
488 int frame_number = 0; | 514 int frame_number = 0; |
489 while (processor->ProcessFrame(frame_number)) { | 515 while (processor->ProcessFrame(frame_number)) { |
490 if (frame_number % 80 == 0) { | 516 if (frame_number % 80 == 0) { |
491 Log("\n"); // make the output a bit nicer. | 517 Log("\n"); // make the output a bit nicer. |
492 } | 518 } |
493 Log("."); | 519 Log("."); |
494 frame_number++; | 520 frame_number++; |
(...skipping 24 matching lines...) Expand all Loading... |
519 } | 545 } |
520 if (FLAGS_python) { | 546 if (FLAGS_python) { |
521 PrintPythonOutput(config, stats, ssim_result, psnr_result); | 547 PrintPythonOutput(config, stats, ssim_result, psnr_result); |
522 } | 548 } |
523 delete processor; | 549 delete processor; |
524 delete encoder; | 550 delete encoder; |
525 delete decoder; | 551 delete decoder; |
526 Log("Quality test finished!"); | 552 Log("Quality test finished!"); |
527 return 0; | 553 return 0; |
528 } | 554 } |
OLD | NEW |