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 #include <string.h> |
14 | 15 |
15 #include <stdarg.h> | 16 #include <stdarg.h> |
16 #include <sys/stat.h> // To check for directory existence. | 17 #include <sys/stat.h> // To check for directory existence. |
17 | 18 |
18 #ifndef S_ISDIR // Not defined in stat.h on Windows. | 19 #ifndef S_ISDIR // Not defined in stat.h on Windows. |
19 #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) | 20 #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) |
20 #endif | 21 #endif |
21 | 22 |
22 #include "gflags/gflags.h" | |
23 #include "webrtc/common_types.h" | 23 #include "webrtc/common_types.h" |
24 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" | 24 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" |
25 #include "webrtc/modules/video_coding/codecs/test/stats.h" | 25 #include "webrtc/modules/video_coding/codecs/test/stats.h" |
26 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" | 26 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" |
27 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" | 27 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" |
28 #include "webrtc/modules/video_coding/include/video_coding.h" | 28 #include "webrtc/modules/video_coding/include/video_coding.h" |
| 29 #include "webrtc/rtc_base/flags.h" |
29 #include "webrtc/rtc_base/format_macros.h" | 30 #include "webrtc/rtc_base/format_macros.h" |
30 #include "webrtc/test/testsupport/frame_reader.h" | 31 #include "webrtc/test/testsupport/frame_reader.h" |
31 #include "webrtc/test/testsupport/frame_writer.h" | 32 #include "webrtc/test/testsupport/frame_writer.h" |
32 #include "webrtc/test/testsupport/metrics/video_metrics.h" | 33 #include "webrtc/test/testsupport/metrics/video_metrics.h" |
33 #include "webrtc/test/testsupport/packet_reader.h" | 34 #include "webrtc/test/testsupport/packet_reader.h" |
34 #include "webrtc/test/video_codec_settings.h" | 35 #include "webrtc/test/video_codec_settings.h" |
35 | 36 |
36 DEFINE_string(test_name, "Quality test", "The name of the test to run. "); | 37 DEFINE_string(test_name, "Quality test", "The name of the test to run. "); |
37 DEFINE_string(test_description, | 38 DEFINE_string(test_description, |
38 "", | 39 "", |
39 "A more detailed description about what " | 40 "A more detailed description about what " |
40 "the current test is about."); | 41 "the current test is about."); |
41 DEFINE_string(input_filename, | 42 DEFINE_string(input_filename, |
42 "", | 43 "", |
43 "Input file. " | 44 "Input file. " |
44 "The source video file to be encoded and decoded. Must be in " | 45 "The source video file to be encoded and decoded. Must be in " |
45 ".yuv format"); | 46 ".yuv format"); |
46 DEFINE_int32(width, -1, "Width in pixels of the frames in the input file."); | 47 DEFINE_int(width, -1, "Width in pixels of the frames in the input file."); |
47 DEFINE_int32(height, -1, "Height in pixels of the frames in the input file."); | 48 DEFINE_int(height, -1, "Height in pixels of the frames in the input file."); |
48 DEFINE_int32(framerate, | 49 DEFINE_int(framerate, |
49 30, | 50 30, |
50 "Frame rate of the input file, in FPS " | 51 "Frame rate of the input file, in FPS " |
51 "(frames-per-second). "); | 52 "(frames-per-second). "); |
52 DEFINE_string(output_dir, | 53 DEFINE_string(output_dir, |
53 ".", | 54 ".", |
54 "Output directory. " | 55 "Output directory. " |
55 "The directory where the output file will be put. Must already " | 56 "The directory where the output file will be put. Must already " |
56 "exist."); | 57 "exist."); |
57 DEFINE_bool(use_single_core, | 58 DEFINE_bool(use_single_core, |
58 false, | 59 false, |
59 "Force using a single core. If set to " | 60 "Force using a single core. If set to " |
60 "true, only one core will be used for processing. Using a single " | 61 "true, only one core will be used for processing. Using a single " |
61 "core is necessary to get a deterministic behavior for the" | 62 "core is necessary to get a deterministic behavior for the" |
62 "encoded frames - using multiple cores will produce different " | 63 "encoded frames - using multiple cores will produce different " |
63 "encoded frames since multiple cores are competing to consume the " | 64 "encoded frames since multiple cores are competing to consume the " |
64 "byte budget for each frame in parallel. If set to false, " | 65 "byte budget for each frame in parallel. If set to false, " |
65 "the maximum detected number of cores will be used. "); | 66 "the maximum detected number of cores will be used. "); |
66 DEFINE_bool(disable_fixed_random_seed, | 67 DEFINE_bool(disable_fixed_random_seed, |
67 false, | 68 false, |
68 "Set this flag to disable the" | 69 "Set this flag to disable the" |
69 "usage of a fixed random seed for the random generator used " | 70 "usage of a fixed random seed for the random generator used " |
70 "for packet loss. Disabling this will cause consecutive runs " | 71 "for packet loss. Disabling this will cause consecutive runs " |
71 "loose packets at different locations, which is bad for " | 72 "loose packets at different locations, which is bad for " |
72 "reproducibility."); | 73 "reproducibility."); |
73 DEFINE_string(output_filename, | 74 DEFINE_string(output_filename, |
74 "", | 75 "", |
75 "Output file. " | 76 "Output file. " |
76 "The name of the output video file resulting of the processing " | 77 "The name of the output video file resulting of the processing " |
77 "of the source file. By default this is the same name as the " | 78 "of the source file. By default this is the same name as the " |
78 "input file with '_out' appended before the extension."); | 79 "input file with '_out' appended before the extension."); |
79 DEFINE_int32(bitrate, 500, "Bit rate in kilobits/second."); | 80 DEFINE_int(bitrate, 500, "Bit rate in kilobits/second."); |
80 DEFINE_int32(keyframe_interval, | 81 DEFINE_int(keyframe_interval, |
81 0, | 82 0, |
82 "Forces a keyframe every Nth frame. " | 83 "Forces a keyframe every Nth frame. " |
83 "0 means the encoder decides when to insert keyframes. Note that " | 84 "0 means the encoder decides when to insert keyframes. Note that " |
84 "the encoder may create a keyframe in other locations in addition " | 85 "the encoder may create a keyframe in other locations in addition " |
85 "to the interval that is set using this parameter."); | 86 "to the interval that is set using this parameter."); |
86 DEFINE_int32(temporal_layers, | 87 DEFINE_int(temporal_layers, |
87 0, | 88 0, |
88 "The number of temporal layers to use " | 89 "The number of temporal layers to use " |
89 "(VP8 specific codec setting). Must be 0-4."); | 90 "(VP8 specific codec setting). Must be 0-4."); |
90 DEFINE_int32(packet_size, | 91 DEFINE_int(packet_size, |
91 1500, | 92 1500, |
92 "Simulated network packet size in bytes (MTU). " | 93 "Simulated network packet size in bytes (MTU). " |
93 "Used for packet loss simulation."); | 94 "Used for packet loss simulation."); |
94 DEFINE_int32(max_payload_size, | 95 DEFINE_int(max_payload_size, |
95 1440, | 96 1440, |
96 "Max payload size in bytes for the " | 97 "Max payload size in bytes for the " |
97 "encoder."); | 98 "encoder."); |
98 DEFINE_string(packet_loss_mode, | 99 DEFINE_string(packet_loss_mode, |
99 "uniform", | 100 "uniform", |
100 "Packet loss mode. Two different " | 101 "Packet loss mode. Two different " |
101 "packet loss models are supported: uniform or burst. This " | 102 "packet loss models are supported: uniform or burst. This " |
102 "setting has no effect unless packet_loss_rate is >0. "); | 103 "setting has no effect unless packet_loss_rate is >0. "); |
103 DEFINE_double(packet_loss_probability, | 104 DEFINE_float(packet_loss_probability, |
104 0.0, | 105 0.0f, |
105 "Packet loss probability. A value " | 106 "Packet loss probability. A value " |
106 "between 0.0 and 1.0 that defines the probability of a packet " | 107 "between 0.0 and 1.0 that defines the probability of a packet " |
107 "being lost. 0.1 means 10% and so on."); | 108 "being lost. 0.1 means 10% and so on."); |
108 DEFINE_int32(packet_loss_burst_length, | 109 DEFINE_int(packet_loss_burst_length, |
109 1, | 110 1, |
110 "Packet loss burst length. Defines " | 111 "Packet loss burst length. Defines " |
111 "how many packets will be lost in a burst when a packet has been " | 112 "how many packets will be lost in a burst when a packet has been " |
112 "decided to be lost. Must be >=1."); | 113 "decided to be lost. Must be >=1."); |
113 DEFINE_bool(csv, | 114 DEFINE_bool(csv, |
114 false, | 115 false, |
115 "CSV output. Enabling this will output all frame " | 116 "CSV output. Enabling this will output all frame " |
116 "statistics at the end of execution. Recommended to run combined " | 117 "statistics at the end of execution. Recommended to run combined " |
117 "with --noverbose to avoid mixing output."); | 118 "with --noverbose to avoid mixing output."); |
118 DEFINE_bool(python, | 119 DEFINE_bool(python, |
119 false, | 120 false, |
120 "Python output. Enabling this will output all frame " | 121 "Python output. Enabling this will output all frame " |
121 "statistics as a Python script at the end of execution. " | 122 "statistics as a Python script at the end of execution. " |
122 "Recommended to run combine with --noverbose to avoid mixing " | 123 "Recommended to run combine with --noverbose to avoid mixing " |
123 "output."); | 124 "output."); |
124 DEFINE_bool(verbose, | 125 DEFINE_bool(verbose, |
125 true, | 126 true, |
126 "Verbose mode. Prints a lot of debugging info. " | 127 "Verbose mode. Prints a lot of debugging info. " |
127 "Suitable for tracking progress but not for capturing output. " | 128 "Suitable for tracking progress but not for capturing output. " |
128 "Disable with --noverbose flag."); | 129 "Disable with --noverbose flag."); |
| 130 DEFINE_bool(help, false, "Prints this message."); |
129 | 131 |
130 // Custom log method that only prints if the verbose flag is given. | 132 // Custom log method that only prints if the verbose flag is given. |
131 // Supports all the standard printf parameters and formatting (just forwarded). | 133 // Supports all the standard printf parameters and formatting (just forwarded). |
132 int Log(const char* format, ...) { | 134 int Log(const char* format, ...) { |
133 int result = 0; | 135 int result = 0; |
134 if (FLAGS_verbose) { | 136 if (FLAG_verbose) { |
135 va_list args; | 137 va_list args; |
136 va_start(args, format); | 138 va_start(args, format); |
137 result = vprintf(format, args); | 139 result = vprintf(format, args); |
138 va_end(args); | 140 va_end(args); |
139 } | 141 } |
140 return result; | 142 return result; |
141 } | 143 } |
142 | 144 |
143 // Validates the arguments given as command line flags and fills in the | 145 // Validates the arguments given as command line flags and fills in the |
144 // TestConfig struct with all configurations needed for video processing. | 146 // TestConfig struct with all configurations needed for video processing. |
145 // Returns 0 if everything is OK, otherwise an exit code. | 147 // Returns 0 if everything is OK, otherwise an exit code. |
146 int HandleCommandLineFlags(webrtc::test::TestConfig* config) { | 148 int HandleCommandLineFlags(webrtc::test::TestConfig* config, |
| 149 const std::string& usage) { |
147 // Validate the mandatory flags: | 150 // Validate the mandatory flags: |
148 if (FLAGS_input_filename.empty() || FLAGS_width == -1 || FLAGS_height == -1) { | 151 if (strlen(FLAG_input_filename) == 0 || |
149 printf("%s\n", google::ProgramUsage()); | 152 FLAG_width == -1 || FLAG_height == -1) { |
| 153 printf("%s\n", usage.c_str()); |
150 return 1; | 154 return 1; |
151 } | 155 } |
152 config->name = FLAGS_test_name; | 156 config->name = FLAG_test_name; |
153 config->description = FLAGS_test_description; | 157 config->description = FLAG_test_description; |
154 | 158 |
155 // Verify the input file exists and is readable. | 159 // Verify the input file exists and is readable. |
156 FILE* test_file; | 160 FILE* test_file; |
157 test_file = fopen(FLAGS_input_filename.c_str(), "rb"); | 161 test_file = fopen(FLAG_input_filename, "rb"); |
158 if (test_file == NULL) { | 162 if (test_file == NULL) { |
159 fprintf(stderr, "Cannot read the specified input file: %s\n", | 163 fprintf(stderr, "Cannot read the specified input file: %s\n", |
160 FLAGS_input_filename.c_str()); | 164 FLAG_input_filename); |
161 return 2; | 165 return 2; |
162 } | 166 } |
163 fclose(test_file); | 167 fclose(test_file); |
164 config->input_filename = FLAGS_input_filename; | 168 config->input_filename = FLAG_input_filename; |
165 | 169 |
166 // Verify the output dir exists. | 170 // Verify the output dir exists. |
167 struct stat dir_info; | 171 struct stat dir_info; |
168 if (!(stat(FLAGS_output_dir.c_str(), &dir_info) == 0 && | 172 if (!(stat(FLAG_output_dir, &dir_info) == 0 && |
169 S_ISDIR(dir_info.st_mode))) { | 173 S_ISDIR(dir_info.st_mode))) { |
170 fprintf(stderr, "Cannot find output directory: %s\n", | 174 fprintf(stderr, "Cannot find output directory: %s\n", |
171 FLAGS_output_dir.c_str()); | 175 FLAG_output_dir); |
172 return 3; | 176 return 3; |
173 } | 177 } |
174 config->output_dir = FLAGS_output_dir; | 178 config->output_dir = FLAG_output_dir; |
175 | 179 |
176 // Manufacture an output filename if none was given. | 180 // Manufacture an output filename if none was given. |
177 if (FLAGS_output_filename.empty()) { | 181 if (strlen(FLAG_output_filename) == 0) { |
178 // Cut out the filename without extension from the given input file | 182 // Cut out the filename without extension from the given input file |
179 // (which may include a path) | 183 // (which may include a path) |
180 size_t startIndex = FLAGS_input_filename.find_last_of("/") + 1; | 184 size_t startIndex = config->input_filename.find_last_of("/") + 1; |
181 if (startIndex == 0) { | 185 if (startIndex == 0) { |
182 startIndex = 0; | 186 startIndex = 0; |
183 } | 187 } |
184 FLAGS_output_filename = | 188 config->output_filename = |
185 FLAGS_input_filename.substr( | 189 config->input_filename.substr( |
186 startIndex, FLAGS_input_filename.find_last_of(".") - startIndex) + | 190 startIndex, config->input_filename.find_last_of(".") - startIndex) + |
187 "_out.yuv"; | 191 "_out.yuv"; |
| 192 } else { |
| 193 config->output_filename = FLAG_output_filename; |
188 } | 194 } |
189 | 195 |
190 // Verify output file can be written. | 196 // Verify output file can be written. |
191 if (FLAGS_output_dir == ".") { | 197 if (config->output_dir != ".") { |
192 config->output_filename = FLAGS_output_filename; | 198 config->output_filename = |
193 } else { | 199 config->output_dir + "/" + config->output_filename; |
194 config->output_filename = FLAGS_output_dir + "/" + FLAGS_output_filename; | |
195 } | 200 } |
196 test_file = fopen(config->output_filename.c_str(), "wb"); | 201 test_file = fopen(config->output_filename.c_str(), "wb"); |
197 if (test_file == NULL) { | 202 if (test_file == NULL) { |
198 fprintf(stderr, "Cannot write output file: %s\n", | 203 fprintf(stderr, "Cannot write output file: %s\n", |
199 config->output_filename.c_str()); | 204 config->output_filename.c_str()); |
200 return 4; | 205 return 4; |
201 } | 206 } |
202 fclose(test_file); | 207 fclose(test_file); |
203 | 208 |
204 // Check single core flag. | 209 // Check single core flag. |
205 config->use_single_core = FLAGS_use_single_core; | 210 config->use_single_core = FLAG_use_single_core; |
206 | 211 |
207 // Get codec specific configuration. | 212 // Get codec specific configuration. |
208 webrtc::test::CodecSettings(webrtc::kVideoCodecVP8, &config->codec_settings); | 213 webrtc::test::CodecSettings(webrtc::kVideoCodecVP8, &config->codec_settings); |
209 | 214 |
210 // Check the temporal layers. | 215 // Check the temporal layers. |
211 if (FLAGS_temporal_layers < 0 || | 216 if (FLAG_temporal_layers < 0 || |
212 FLAGS_temporal_layers > webrtc::kMaxTemporalStreams) { | 217 FLAG_temporal_layers > webrtc::kMaxTemporalStreams) { |
213 fprintf(stderr, "Temporal layers number must be 0-4, was: %d\n", | 218 fprintf(stderr, "Temporal layers number must be 0-4, was: %d\n", |
214 FLAGS_temporal_layers); | 219 FLAG_temporal_layers); |
215 return 13; | 220 return 13; |
216 } | 221 } |
217 config->codec_settings.VP8()->numberOfTemporalLayers = FLAGS_temporal_layers; | 222 config->codec_settings.VP8()->numberOfTemporalLayers = FLAG_temporal_layers; |
218 | 223 |
219 // Check the bit rate. | 224 // Check the bit rate. |
220 if (FLAGS_bitrate <= 0) { | 225 if (FLAG_bitrate <= 0) { |
221 fprintf(stderr, "Bit rate must be >0 kbps, was: %d\n", FLAGS_bitrate); | 226 fprintf(stderr, "Bit rate must be >0 kbps, was: %d\n", FLAG_bitrate); |
222 return 5; | 227 return 5; |
223 } | 228 } |
224 config->codec_settings.startBitrate = FLAGS_bitrate; | 229 config->codec_settings.startBitrate = FLAG_bitrate; |
225 | 230 |
226 // Check the keyframe interval. | 231 // Check the keyframe interval. |
227 if (FLAGS_keyframe_interval < 0) { | 232 if (FLAG_keyframe_interval < 0) { |
228 fprintf(stderr, "Keyframe interval must be >=0, was: %d\n", | 233 fprintf(stderr, "Keyframe interval must be >=0, was: %d\n", |
229 FLAGS_keyframe_interval); | 234 FLAG_keyframe_interval); |
230 return 6; | 235 return 6; |
231 } | 236 } |
232 config->keyframe_interval = FLAGS_keyframe_interval; | 237 config->keyframe_interval = FLAG_keyframe_interval; |
233 | 238 |
234 // Check packet size and max payload size. | 239 // Check packet size and max payload size. |
235 if (FLAGS_packet_size <= 0) { | 240 if (FLAG_packet_size <= 0) { |
236 fprintf(stderr, "Packet size must be >0 bytes, was: %d\n", | 241 fprintf(stderr, "Packet size must be >0 bytes, was: %d\n", |
237 FLAGS_packet_size); | 242 FLAG_packet_size); |
238 return 7; | 243 return 7; |
239 } | 244 } |
240 config->networking_config.packet_size_in_bytes = | 245 config->networking_config.packet_size_in_bytes = |
241 static_cast<size_t>(FLAGS_packet_size); | 246 static_cast<size_t>(FLAG_packet_size); |
242 | 247 |
243 if (FLAGS_max_payload_size <= 0) { | 248 if (FLAG_max_payload_size <= 0) { |
244 fprintf(stderr, "Max payload size must be >0 bytes, was: %d\n", | 249 fprintf(stderr, "Max payload size must be >0 bytes, was: %d\n", |
245 FLAGS_max_payload_size); | 250 FLAG_max_payload_size); |
246 return 8; | 251 return 8; |
247 } | 252 } |
248 config->networking_config.max_payload_size_in_bytes = | 253 config->networking_config.max_payload_size_in_bytes = |
249 static_cast<size_t>(FLAGS_max_payload_size); | 254 static_cast<size_t>(FLAG_max_payload_size); |
250 | 255 |
251 // Check the width and height | 256 // Check the width and height |
252 if (FLAGS_width <= 0 || FLAGS_height <= 0) { | 257 if (FLAG_width <= 0 || FLAG_height <= 0) { |
253 fprintf(stderr, "Width and height must be >0."); | 258 fprintf(stderr, "Width and height must be >0."); |
254 return 9; | 259 return 9; |
255 } | 260 } |
256 config->codec_settings.width = FLAGS_width; | 261 config->codec_settings.width = FLAG_width; |
257 config->codec_settings.height = FLAGS_height; | 262 config->codec_settings.height = FLAG_height; |
258 config->codec_settings.maxFramerate = FLAGS_framerate; | 263 config->codec_settings.maxFramerate = FLAG_framerate; |
259 | 264 |
260 // Calculate the size of each frame to read (according to YUV spec). | 265 // Calculate the size of each frame to read (according to YUV spec). |
261 config->frame_length_in_bytes = | 266 config->frame_length_in_bytes = |
262 3 * config->codec_settings.width * config->codec_settings.height / 2; | 267 3 * config->codec_settings.width * config->codec_settings.height / 2; |
263 | 268 |
264 // Check packet loss settings | 269 // Check packet loss settings |
265 if (FLAGS_packet_loss_mode != "uniform" && | 270 if (strcmp(FLAG_packet_loss_mode, "uniform") == 0) { |
266 FLAGS_packet_loss_mode != "burst") { | 271 config->networking_config.packet_loss_mode = webrtc::test::kUniform; |
| 272 } else if (strcmp(FLAG_packet_loss_mode, "burst") == 0) { |
| 273 config->networking_config.packet_loss_mode = webrtc::test::kBurst; |
| 274 } else { |
267 fprintf(stderr, | 275 fprintf(stderr, |
268 "Unsupported packet loss mode, must be 'uniform' or " | 276 "Unsupported packet loss mode, must be 'uniform' or " |
269 "'burst'\n."); | 277 "'burst'\n."); |
270 return 10; | 278 return 10; |
271 } | 279 } |
272 config->networking_config.packet_loss_mode = webrtc::test::kUniform; | |
273 if (FLAGS_packet_loss_mode == "burst") { | |
274 config->networking_config.packet_loss_mode = webrtc::test::kBurst; | |
275 } | |
276 | 280 |
277 if (FLAGS_packet_loss_probability < 0.0 || | 281 if (FLAG_packet_loss_probability < 0.0 || |
278 FLAGS_packet_loss_probability > 1.0) { | 282 FLAG_packet_loss_probability > 1.0) { |
279 fprintf(stderr, | 283 fprintf(stderr, |
280 "Invalid packet loss probability. Must be 0.0 - 1.0, " | 284 "Invalid packet loss probability. Must be 0.0 - 1.0, " |
281 "was: %f\n", | 285 "was: %f\n", |
282 FLAGS_packet_loss_probability); | 286 FLAG_packet_loss_probability); |
283 return 11; | 287 return 11; |
284 } | 288 } |
285 config->networking_config.packet_loss_probability = | 289 config->networking_config.packet_loss_probability = |
286 FLAGS_packet_loss_probability; | 290 FLAG_packet_loss_probability; |
287 | 291 |
288 if (FLAGS_packet_loss_burst_length < 1) { | 292 if (FLAG_packet_loss_burst_length < 1) { |
289 fprintf(stderr, | 293 fprintf(stderr, |
290 "Invalid packet loss burst length, must be >=1, " | 294 "Invalid packet loss burst length, must be >=1, " |
291 "was: %d\n", | 295 "was: %d\n", |
292 FLAGS_packet_loss_burst_length); | 296 FLAG_packet_loss_burst_length); |
293 return 12; | 297 return 12; |
294 } | 298 } |
295 config->networking_config.packet_loss_burst_length = | 299 config->networking_config.packet_loss_burst_length = |
296 FLAGS_packet_loss_burst_length; | 300 FLAG_packet_loss_burst_length; |
297 config->verbose = FLAGS_verbose; | 301 config->verbose = FLAG_verbose; |
298 return 0; | 302 return 0; |
299 } | 303 } |
300 | 304 |
301 void CalculateSsimVideoMetrics(webrtc::test::TestConfig* config, | 305 void CalculateSsimVideoMetrics(webrtc::test::TestConfig* config, |
302 webrtc::test::QualityMetricsResult* result) { | 306 webrtc::test::QualityMetricsResult* result) { |
303 Log("Calculating SSIM...\n"); | 307 Log("Calculating SSIM...\n"); |
304 I420SSIMFromFiles( | 308 I420SSIMFromFiles( |
305 config->input_filename.c_str(), config->output_filename.c_str(), | 309 config->input_filename.c_str(), config->output_filename.c_str(), |
306 config->codec_settings.width, config->codec_settings.height, result); | 310 config->codec_settings.width, config->codec_settings.height, result); |
307 Log(" Average: %3.2f\n", result->average); | 311 Log(" Average: %3.2f\n", result->average); |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 461 } |
458 | 462 |
459 // Runs a quality measurement on the input file supplied to the program. | 463 // Runs a quality measurement on the input file supplied to the program. |
460 // The input file must be in YUV format. | 464 // The input file must be in YUV format. |
461 int main(int argc, char* argv[]) { | 465 int main(int argc, char* argv[]) { |
462 std::string program_name = argv[0]; | 466 std::string program_name = argv[0]; |
463 std::string usage = | 467 std::string usage = |
464 "Quality test application for video comparisons.\n" | 468 "Quality test application for video comparisons.\n" |
465 "Run " + | 469 "Run " + |
466 program_name + | 470 program_name + |
467 " --helpshort for usage.\n" | 471 " --help for usage.\n" |
468 "Example usage:\n" + | 472 "Example usage:\n" + |
469 program_name + | 473 program_name + |
470 " --input_filename=filename.yuv --width=352 --height=288\n"; | 474 " --input_filename=filename.yuv --width=352 --height=288\n"; |
471 google::SetUsageMessage(usage); | |
472 | 475 |
473 google::ParseCommandLineFlags(&argc, &argv, true); | 476 rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true); |
| 477 if (FLAG_help) { |
| 478 rtc::FlagList::Print(nullptr, false); |
| 479 return 0; |
| 480 } |
474 | 481 |
475 // Create TestConfig. | 482 // Create TestConfig. |
476 webrtc::test::TestConfig config; | 483 webrtc::test::TestConfig config; |
477 | 484 |
478 int return_code = HandleCommandLineFlags(&config); | 485 int return_code = HandleCommandLineFlags(&config, usage); |
479 // Exit if an invalid argument is supplied. | 486 // Exit if an invalid argument is supplied. |
480 if (return_code != 0) { | 487 if (return_code != 0) { |
481 return return_code; | 488 return return_code; |
482 } | 489 } |
483 | 490 |
484 PrintConfigurationSummary(config); | 491 PrintConfigurationSummary(config); |
485 | 492 |
486 webrtc::VP8Encoder* encoder = webrtc::VP8Encoder::Create(); | 493 webrtc::VP8Encoder* encoder = webrtc::VP8Encoder::Create(); |
487 webrtc::VP8Decoder* decoder = webrtc::VP8Decoder::Create(); | 494 webrtc::VP8Decoder* decoder = webrtc::VP8Decoder::Create(); |
488 webrtc::test::Stats stats; | 495 webrtc::test::Stats stats; |
489 webrtc::test::YuvFrameReaderImpl frame_reader(config.input_filename, | 496 webrtc::test::YuvFrameReaderImpl frame_reader(config.input_filename, |
490 config.codec_settings.width, | 497 config.codec_settings.width, |
491 config.codec_settings.height); | 498 config.codec_settings.height); |
492 webrtc::test::YuvFrameWriterImpl frame_writer(config.output_filename, | 499 webrtc::test::YuvFrameWriterImpl frame_writer(config.output_filename, |
493 config.codec_settings.width, | 500 config.codec_settings.width, |
494 config.codec_settings.height); | 501 config.codec_settings.height); |
495 frame_reader.Init(); | 502 frame_reader.Init(); |
496 frame_writer.Init(); | 503 frame_writer.Init(); |
497 webrtc::test::PacketReader packet_reader; | 504 webrtc::test::PacketReader packet_reader; |
498 | 505 |
499 webrtc::test::PacketManipulatorImpl packet_manipulator( | 506 webrtc::test::PacketManipulatorImpl packet_manipulator( |
500 &packet_reader, config.networking_config, config.verbose); | 507 &packet_reader, config.networking_config, config.verbose); |
501 // By default the packet manipulator is seeded with a fixed random. | 508 // By default the packet manipulator is seeded with a fixed random. |
502 // If disabled we must generate a new seed. | 509 // If disabled we must generate a new seed. |
503 if (FLAGS_disable_fixed_random_seed) { | 510 if (FLAG_disable_fixed_random_seed) { |
504 packet_manipulator.InitializeRandomSeed(time(NULL)); | 511 packet_manipulator.InitializeRandomSeed(time(NULL)); |
505 } | 512 } |
506 webrtc::test::VideoProcessor* processor = new webrtc::test::VideoProcessor( | 513 webrtc::test::VideoProcessor* processor = new webrtc::test::VideoProcessor( |
507 encoder, decoder, &frame_reader, &frame_writer, &packet_manipulator, | 514 encoder, decoder, &frame_reader, &frame_writer, &packet_manipulator, |
508 config, &stats, nullptr /* encoded_frame_writer */, | 515 config, &stats, nullptr /* encoded_frame_writer */, |
509 nullptr /* decoded_frame_writer */); | 516 nullptr /* decoded_frame_writer */); |
510 processor->Init(); | 517 processor->Init(); |
511 | 518 |
512 const int num_frames = frame_reader.NumberOfFrames(); | 519 const int num_frames = frame_reader.NumberOfFrames(); |
513 int frame_number = 0; | 520 int frame_number = 0; |
(...skipping 18 matching lines...) Expand all Loading... |
532 frame_reader.Close(); | 539 frame_reader.Close(); |
533 frame_writer.Close(); | 540 frame_writer.Close(); |
534 | 541 |
535 stats.PrintSummary(); | 542 stats.PrintSummary(); |
536 | 543 |
537 webrtc::test::QualityMetricsResult ssim_result; | 544 webrtc::test::QualityMetricsResult ssim_result; |
538 CalculateSsimVideoMetrics(&config, &ssim_result); | 545 CalculateSsimVideoMetrics(&config, &ssim_result); |
539 webrtc::test::QualityMetricsResult psnr_result; | 546 webrtc::test::QualityMetricsResult psnr_result; |
540 CalculatePsnrVideoMetrics(&config, &psnr_result); | 547 CalculatePsnrVideoMetrics(&config, &psnr_result); |
541 | 548 |
542 if (FLAGS_csv) { | 549 if (FLAG_csv) { |
543 PrintCsvOutput(stats, ssim_result, psnr_result); | 550 PrintCsvOutput(stats, ssim_result, psnr_result); |
544 } | 551 } |
545 if (FLAGS_python) { | 552 if (FLAG_python) { |
546 PrintPythonOutput(config, stats, ssim_result, psnr_result); | 553 PrintPythonOutput(config, stats, ssim_result, psnr_result); |
547 } | 554 } |
548 delete processor; | 555 delete processor; |
549 delete encoder; | 556 delete encoder; |
550 delete decoder; | 557 delete decoder; |
551 Log("Quality test finished!"); | 558 Log("Quality test finished!"); |
552 return 0; | 559 return 0; |
553 } | 560 } |
OLD | NEW |