| 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 |