OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM 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 /* | 11 /* |
12 * This is an example demonstrating how to implement a multi-layer | 12 * This is an example demonstrating how to implement a multi-layer |
13 * VP9 encoding scheme based on spatial scalability for video applications | 13 * VP9 encoding scheme based on spatial scalability for video applications |
14 * that benefit from a scalable bitstream. | 14 * that benefit from a scalable bitstream. |
15 */ | 15 */ |
16 | 16 |
17 #include <stdarg.h> | 17 #include <stdarg.h> |
18 #include <stdlib.h> | 18 #include <stdlib.h> |
19 #include <string.h> | 19 #include <string.h> |
20 #include <time.h> | 20 #include <time.h> |
21 | 21 |
22 #include "./args.h" | 22 #include "./args.h" |
23 #include "./tools_common.h" | 23 #include "./tools_common.h" |
24 #include "./video_writer.h" | 24 #include "./video_writer.h" |
25 | 25 |
26 #include "vpx/svc_context.h" | 26 #include "vpx/svc_context.h" |
27 #include "vpx/vp8cx.h" | 27 #include "vpx/vp8cx.h" |
28 #include "vpx/vpx_encoder.h" | 28 #include "vpx/vpx_encoder.h" |
| 29 #include "./vpxstats.h" |
29 | 30 |
30 static const struct arg_enum_list encoding_mode_enum[] = { | 31 static const struct arg_enum_list encoding_mode_enum[] = { |
31 {"i", INTER_LAYER_PREDICTION_I}, | 32 {"i", INTER_LAYER_PREDICTION_I}, |
32 {"alt-ip", ALT_INTER_LAYER_PREDICTION_IP}, | 33 {"alt-ip", ALT_INTER_LAYER_PREDICTION_IP}, |
33 {"ip", INTER_LAYER_PREDICTION_IP}, | 34 {"ip", INTER_LAYER_PREDICTION_IP}, |
34 {"gf", USE_GOLDEN_FRAME}, | 35 {"gf", USE_GOLDEN_FRAME}, |
35 {NULL, 0} | 36 {NULL, 0} |
36 }; | 37 }; |
37 | 38 |
38 static const arg_def_t encoding_mode_arg = ARG_DEF_ENUM( | 39 static const arg_def_t encoding_mode_arg = ARG_DEF_ENUM( |
(...skipping 14 matching lines...) Expand all Loading... |
53 ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes"); | 54 ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes"); |
54 static const arg_def_t scale_factors_arg = | 55 static const arg_def_t scale_factors_arg = |
55 ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)"); | 56 ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)"); |
56 static const arg_def_t quantizers_arg = | 57 static const arg_def_t quantizers_arg = |
57 ARG_DEF("q", "quantizers", 1, "quantizers for non key frames, also will " | 58 ARG_DEF("q", "quantizers", 1, "quantizers for non key frames, also will " |
58 "be applied to key frames if -qn is not specified (lowest to " | 59 "be applied to key frames if -qn is not specified (lowest to " |
59 "highest layer)"); | 60 "highest layer)"); |
60 static const arg_def_t quantizers_keyframe_arg = | 61 static const arg_def_t quantizers_keyframe_arg = |
61 ARG_DEF("qn", "quantizers-keyframe", 1, "quantizers for key frames (lowest " | 62 ARG_DEF("qn", "quantizers-keyframe", 1, "quantizers for key frames (lowest " |
62 "to highest layer)"); | 63 "to highest layer)"); |
| 64 static const arg_def_t passes_arg = |
| 65 ARG_DEF("p", "passes", 1, "Number of passes (1/2)"); |
| 66 static const arg_def_t pass_arg = |
| 67 ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)"); |
| 68 static const arg_def_t fpf_name_arg = |
| 69 ARG_DEF(NULL, "fpf", 1, "First pass statistics file name"); |
| 70 static const arg_def_t min_q_arg = |
| 71 ARG_DEF(NULL, "min-q", 1, "Minimum quantizer"); |
| 72 static const arg_def_t max_q_arg = |
| 73 ARG_DEF(NULL, "max-q", 1, "Maximum quantizer"); |
| 74 static const arg_def_t min_bitrate_arg = |
| 75 ARG_DEF(NULL, "min-bitrate", 1, "Minimum bitrate"); |
| 76 static const arg_def_t max_bitrate_arg = |
| 77 ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate"); |
63 | 78 |
64 static const arg_def_t *svc_args[] = { | 79 static const arg_def_t *svc_args[] = { |
65 &encoding_mode_arg, &frames_arg, &width_arg, &height_arg, | 80 &encoding_mode_arg, &frames_arg, &width_arg, &height_arg, |
66 &timebase_arg, &bitrate_arg, &skip_frames_arg, &layers_arg, | 81 &timebase_arg, &bitrate_arg, &skip_frames_arg, &layers_arg, |
67 &kf_dist_arg, &scale_factors_arg, &quantizers_arg, | 82 &kf_dist_arg, &scale_factors_arg, &quantizers_arg, |
68 &quantizers_keyframe_arg, NULL | 83 &quantizers_keyframe_arg, &passes_arg, &pass_arg, |
| 84 &fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg, |
| 85 &max_bitrate_arg, NULL |
69 }; | 86 }; |
70 | 87 |
71 static const SVC_ENCODING_MODE default_encoding_mode = | 88 static const SVC_ENCODING_MODE default_encoding_mode = |
72 INTER_LAYER_PREDICTION_IP; | 89 INTER_LAYER_PREDICTION_IP; |
73 static const uint32_t default_frames_to_skip = 0; | 90 static const uint32_t default_frames_to_skip = 0; |
74 static const uint32_t default_frames_to_code = 60 * 60; | 91 static const uint32_t default_frames_to_code = 60 * 60; |
75 static const uint32_t default_width = 1920; | 92 static const uint32_t default_width = 1920; |
76 static const uint32_t default_height = 1080; | 93 static const uint32_t default_height = 1080; |
77 static const uint32_t default_timebase_num = 1; | 94 static const uint32_t default_timebase_num = 1; |
78 static const uint32_t default_timebase_den = 60; | 95 static const uint32_t default_timebase_den = 60; |
79 static const uint32_t default_bitrate = 1000; | 96 static const uint32_t default_bitrate = 1000; |
80 static const uint32_t default_spatial_layers = 5; | 97 static const uint32_t default_spatial_layers = 5; |
81 static const uint32_t default_kf_dist = 100; | 98 static const uint32_t default_kf_dist = 100; |
82 | 99 |
83 typedef struct { | 100 typedef struct { |
84 const char *input_filename; | 101 const char *input_filename; |
85 const char *output_filename; | 102 const char *output_filename; |
86 uint32_t frames_to_code; | 103 uint32_t frames_to_code; |
87 uint32_t frames_to_skip; | 104 uint32_t frames_to_skip; |
| 105 struct VpxInputContext input_ctx; |
| 106 stats_io_t rc_stats; |
| 107 int passes; |
| 108 int pass; |
88 } AppInput; | 109 } AppInput; |
89 | 110 |
90 static const char *exec_name; | 111 static const char *exec_name; |
91 | 112 |
92 void usage_exit() { | 113 void usage_exit() { |
93 fprintf(stderr, "Usage: %s <options> input_filename output_filename\n", | 114 fprintf(stderr, "Usage: %s <options> input_filename output_filename\n", |
94 exec_name); | 115 exec_name); |
95 fprintf(stderr, "Options:\n"); | 116 fprintf(stderr, "Options:\n"); |
96 arg_show_usage(stderr, svc_args); | 117 arg_show_usage(stderr, svc_args); |
97 exit(EXIT_FAILURE); | 118 exit(EXIT_FAILURE); |
98 } | 119 } |
99 | 120 |
100 static void parse_command_line(int argc, const char **argv_, | 121 static void parse_command_line(int argc, const char **argv_, |
101 AppInput *app_input, SvcContext *svc_ctx, | 122 AppInput *app_input, SvcContext *svc_ctx, |
102 vpx_codec_enc_cfg_t *enc_cfg) { | 123 vpx_codec_enc_cfg_t *enc_cfg) { |
103 struct arg arg = {0}; | 124 struct arg arg = {0}; |
104 char **argv = NULL; | 125 char **argv = NULL; |
105 char **argi = NULL; | 126 char **argi = NULL; |
106 char **argj = NULL; | 127 char **argj = NULL; |
107 vpx_codec_err_t res; | 128 vpx_codec_err_t res; |
| 129 int passes = 0; |
| 130 int pass = 0; |
| 131 const char *fpf_file_name = NULL; |
| 132 unsigned int min_bitrate = 0; |
| 133 unsigned int max_bitrate = 0; |
108 | 134 |
109 // initialize SvcContext with parameters that will be passed to vpx_svc_init | 135 // initialize SvcContext with parameters that will be passed to vpx_svc_init |
110 svc_ctx->log_level = SVC_LOG_DEBUG; | 136 svc_ctx->log_level = SVC_LOG_DEBUG; |
111 svc_ctx->spatial_layers = default_spatial_layers; | 137 svc_ctx->spatial_layers = default_spatial_layers; |
112 svc_ctx->encoding_mode = default_encoding_mode; | 138 svc_ctx->encoding_mode = default_encoding_mode; |
113 | 139 |
114 // start with default encoder configuration | 140 // start with default encoder configuration |
115 res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0); | 141 res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0); |
116 if (res) { | 142 if (res) { |
117 die("Failed to get config: %s\n", vpx_codec_err_to_string(res)); | 143 die("Failed to get config: %s\n", vpx_codec_err_to_string(res)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 svc_ctx->spatial_layers = arg_parse_uint(&arg); | 178 svc_ctx->spatial_layers = arg_parse_uint(&arg); |
153 } else if (arg_match(&arg, &kf_dist_arg, argi)) { | 179 } else if (arg_match(&arg, &kf_dist_arg, argi)) { |
154 enc_cfg->kf_min_dist = arg_parse_uint(&arg); | 180 enc_cfg->kf_min_dist = arg_parse_uint(&arg); |
155 enc_cfg->kf_max_dist = enc_cfg->kf_min_dist; | 181 enc_cfg->kf_max_dist = enc_cfg->kf_min_dist; |
156 } else if (arg_match(&arg, &scale_factors_arg, argi)) { | 182 } else if (arg_match(&arg, &scale_factors_arg, argi)) { |
157 vpx_svc_set_scale_factors(svc_ctx, arg.val); | 183 vpx_svc_set_scale_factors(svc_ctx, arg.val); |
158 } else if (arg_match(&arg, &quantizers_arg, argi)) { | 184 } else if (arg_match(&arg, &quantizers_arg, argi)) { |
159 vpx_svc_set_quantizers(svc_ctx, arg.val, 0); | 185 vpx_svc_set_quantizers(svc_ctx, arg.val, 0); |
160 } else if (arg_match(&arg, &quantizers_keyframe_arg, argi)) { | 186 } else if (arg_match(&arg, &quantizers_keyframe_arg, argi)) { |
161 vpx_svc_set_quantizers(svc_ctx, arg.val, 1); | 187 vpx_svc_set_quantizers(svc_ctx, arg.val, 1); |
| 188 } else if (arg_match(&arg, &passes_arg, argi)) { |
| 189 passes = arg_parse_uint(&arg); |
| 190 if (passes < 1 || passes > 2) { |
| 191 die("Error: Invalid number of passes (%d)\n", passes); |
| 192 } |
| 193 } else if (arg_match(&arg, &pass_arg, argi)) { |
| 194 pass = arg_parse_uint(&arg); |
| 195 if (pass < 1 || pass > 2) { |
| 196 die("Error: Invalid pass selected (%d)\n", pass); |
| 197 } |
| 198 } else if (arg_match(&arg, &fpf_name_arg, argi)) { |
| 199 fpf_file_name = arg.val; |
| 200 } else if (arg_match(&arg, &min_q_arg, argi)) { |
| 201 enc_cfg->rc_min_quantizer = arg_parse_uint(&arg); |
| 202 } else if (arg_match(&arg, &max_q_arg, argi)) { |
| 203 enc_cfg->rc_max_quantizer = arg_parse_uint(&arg); |
| 204 } else if (arg_match(&arg, &min_bitrate_arg, argi)) { |
| 205 min_bitrate = arg_parse_uint(&arg); |
| 206 } else if (arg_match(&arg, &max_bitrate_arg, argi)) { |
| 207 max_bitrate = arg_parse_uint(&arg); |
162 } else { | 208 } else { |
163 ++argj; | 209 ++argj; |
164 } | 210 } |
165 } | 211 } |
166 | 212 |
| 213 if (passes == 0 || passes == 1) { |
| 214 if (pass) { |
| 215 fprintf(stderr, "pass is ignored since there's only one pass\n"); |
| 216 } |
| 217 enc_cfg->g_pass = VPX_RC_ONE_PASS; |
| 218 } else { |
| 219 if (pass == 0) { |
| 220 die("pass must be specified when passes is 2\n"); |
| 221 } |
| 222 |
| 223 if (fpf_file_name == NULL) { |
| 224 die("fpf must be specified when passes is 2\n"); |
| 225 } |
| 226 |
| 227 if (pass == 1) { |
| 228 enc_cfg->g_pass = VPX_RC_FIRST_PASS; |
| 229 if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 0)) { |
| 230 fatal("Failed to open statistics store"); |
| 231 } |
| 232 } else { |
| 233 enc_cfg->g_pass = VPX_RC_LAST_PASS; |
| 234 if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 1)) { |
| 235 fatal("Failed to open statistics store"); |
| 236 } |
| 237 enc_cfg->rc_twopass_stats_in = stats_get(&app_input->rc_stats); |
| 238 } |
| 239 app_input->passes = passes; |
| 240 app_input->pass = pass; |
| 241 } |
| 242 |
| 243 if (enc_cfg->rc_target_bitrate > 0) { |
| 244 if (min_bitrate > 0) { |
| 245 enc_cfg->rc_2pass_vbr_minsection_pct = |
| 246 min_bitrate * 100 / enc_cfg->rc_target_bitrate; |
| 247 } |
| 248 if (max_bitrate > 0) { |
| 249 enc_cfg->rc_2pass_vbr_maxsection_pct = |
| 250 max_bitrate * 100 / enc_cfg->rc_target_bitrate; |
| 251 } |
| 252 } |
| 253 |
167 // Check for unrecognized options | 254 // Check for unrecognized options |
168 for (argi = argv; *argi; ++argi) | 255 for (argi = argv; *argi; ++argi) |
169 if (argi[0][0] == '-' && strlen(argi[0]) > 1) | 256 if (argi[0][0] == '-' && strlen(argi[0]) > 1) |
170 die("Error: Unrecognized option %s\n", *argi); | 257 die("Error: Unrecognized option %s\n", *argi); |
171 | 258 |
172 if (argv[0] == NULL || argv[1] == 0) { | 259 if (argv[0] == NULL || argv[1] == 0) { |
173 usage_exit(); | 260 usage_exit(); |
174 } | 261 } |
175 app_input->input_filename = argv[0]; | 262 app_input->input_filename = argv[0]; |
176 app_input->output_filename = argv[1]; | 263 app_input->output_filename = argv[1]; |
(...skipping 23 matching lines...) Expand all Loading... |
200 vpx_codec_ctx_t codec; | 287 vpx_codec_ctx_t codec; |
201 vpx_codec_enc_cfg_t enc_cfg; | 288 vpx_codec_enc_cfg_t enc_cfg; |
202 SvcContext svc_ctx; | 289 SvcContext svc_ctx; |
203 uint32_t i; | 290 uint32_t i; |
204 uint32_t frame_cnt = 0; | 291 uint32_t frame_cnt = 0; |
205 vpx_image_t raw; | 292 vpx_image_t raw; |
206 vpx_codec_err_t res; | 293 vpx_codec_err_t res; |
207 int pts = 0; /* PTS starts at 0 */ | 294 int pts = 0; /* PTS starts at 0 */ |
208 int frame_duration = 1; /* 1 timebase tick per frame */ | 295 int frame_duration = 1; /* 1 timebase tick per frame */ |
209 FILE *infile = NULL; | 296 FILE *infile = NULL; |
| 297 int end_of_stream = 0; |
210 | 298 |
211 memset(&svc_ctx, 0, sizeof(svc_ctx)); | 299 memset(&svc_ctx, 0, sizeof(svc_ctx)); |
212 svc_ctx.log_print = 1; | 300 svc_ctx.log_print = 1; |
213 exec_name = argv[0]; | 301 exec_name = argv[0]; |
214 parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg); | 302 parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg); |
215 | 303 |
216 // Allocate image buffer | 304 // Allocate image buffer |
217 if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32)) | 305 if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32)) |
218 die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h); | 306 die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h); |
219 | 307 |
220 if (!(infile = fopen(app_input.input_filename, "rb"))) | 308 if (!(infile = fopen(app_input.input_filename, "rb"))) |
221 die("Failed to open %s for reading\n", app_input.input_filename); | 309 die("Failed to open %s for reading\n", app_input.input_filename); |
222 | 310 |
223 // Initialize codec | 311 // Initialize codec |
224 if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) != | 312 if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) != |
225 VPX_CODEC_OK) | 313 VPX_CODEC_OK) |
226 die("Failed to initialize encoder\n"); | 314 die("Failed to initialize encoder\n"); |
227 | 315 |
228 info.codec_fourcc = VP9_FOURCC; | 316 info.codec_fourcc = VP9_FOURCC; |
229 info.time_base.numerator = enc_cfg.g_timebase.num; | 317 info.time_base.numerator = enc_cfg.g_timebase.num; |
230 info.time_base.denominator = enc_cfg.g_timebase.den; | 318 info.time_base.denominator = enc_cfg.g_timebase.den; |
231 if (vpx_svc_get_layer_resolution(&svc_ctx, svc_ctx.spatial_layers - 1, | 319 if (vpx_svc_get_layer_resolution(&svc_ctx, svc_ctx.spatial_layers - 1, |
232 (unsigned int *)&info.frame_width, | 320 (unsigned int *)&info.frame_width, |
233 (unsigned int *)&info.frame_height) != | 321 (unsigned int *)&info.frame_height) != |
234 VPX_CODEC_OK) { | 322 VPX_CODEC_OK) { |
235 die("Failed to get output resolution"); | 323 die("Failed to get output resolution"); |
236 } | 324 } |
237 writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF, | 325 |
238 &info); | 326 if (!(app_input.passes == 2 && app_input.pass == 1)) { |
239 if (!writer) | 327 // We don't save the bitstream for the 1st pass on two pass rate control |
240 die("Failed to open %s for writing\n", app_input.output_filename); | 328 writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF, |
| 329 &info); |
| 330 if (!writer) |
| 331 die("Failed to open %s for writing\n", app_input.output_filename); |
| 332 } |
241 | 333 |
242 // skip initial frames | 334 // skip initial frames |
243 for (i = 0; i < app_input.frames_to_skip; ++i) | 335 for (i = 0; i < app_input.frames_to_skip; ++i) |
244 vpx_img_read(&raw, infile); | 336 vpx_img_read(&raw, infile); |
245 | 337 |
246 // Encode frames | 338 // Encode frames |
247 while (frame_cnt < app_input.frames_to_code) { | 339 while (!end_of_stream) { |
248 if (!vpx_img_read(&raw, infile)) | 340 if (frame_cnt >= app_input.frames_to_code || !vpx_img_read(&raw, infile)) { |
249 break; | 341 // We need one extra vpx_svc_encode call at end of stream to flush |
| 342 // encoder and get remaining data |
| 343 end_of_stream = 1; |
| 344 } |
250 | 345 |
251 res = vpx_svc_encode(&svc_ctx, &codec, &raw, pts, frame_duration, | 346 res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw), |
252 VPX_DL_REALTIME); | 347 pts, frame_duration, VPX_DL_REALTIME); |
253 printf("%s", vpx_svc_get_message(&svc_ctx)); | 348 printf("%s", vpx_svc_get_message(&svc_ctx)); |
254 if (res != VPX_CODEC_OK) { | 349 if (res != VPX_CODEC_OK) { |
255 die_codec(&codec, "Failed to encode frame"); | 350 die_codec(&codec, "Failed to encode frame"); |
256 } | 351 } |
257 if (vpx_svc_get_frame_size(&svc_ctx) > 0) { | 352 if (!(app_input.passes == 2 && app_input.pass == 1)) { |
258 vpx_video_writer_write_frame(writer, | 353 if (vpx_svc_get_frame_size(&svc_ctx) > 0) { |
259 vpx_svc_get_buffer(&svc_ctx), | 354 vpx_video_writer_write_frame(writer, |
260 vpx_svc_get_frame_size(&svc_ctx), | 355 vpx_svc_get_buffer(&svc_ctx), |
261 pts); | 356 vpx_svc_get_frame_size(&svc_ctx), |
| 357 pts); |
| 358 } |
262 } | 359 } |
263 ++frame_cnt; | 360 if (vpx_svc_get_rc_stats_buffer_size(&svc_ctx) > 0) { |
264 pts += frame_duration; | 361 stats_write(&app_input.rc_stats, |
| 362 vpx_svc_get_rc_stats_buffer(&svc_ctx), |
| 363 vpx_svc_get_rc_stats_buffer_size(&svc_ctx)); |
| 364 } |
| 365 if (!end_of_stream) { |
| 366 ++frame_cnt; |
| 367 pts += frame_duration; |
| 368 } |
265 } | 369 } |
266 | 370 |
267 printf("Processed %d frames\n", frame_cnt); | 371 printf("Processed %d frames\n", frame_cnt); |
268 | 372 |
269 fclose(infile); | 373 fclose(infile); |
270 if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); | 374 if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec"); |
271 | 375 |
272 vpx_video_writer_close(writer); | 376 if (app_input.passes == 2) |
| 377 stats_close(&app_input.rc_stats, 1); |
| 378 |
| 379 if (writer) { |
| 380 vpx_video_writer_close(writer); |
| 381 } |
273 | 382 |
274 vpx_img_free(&raw); | 383 vpx_img_free(&raw); |
275 | 384 |
276 // display average size, psnr | 385 // display average size, psnr |
277 printf("%s", vpx_svc_dump_statistics(&svc_ctx)); | 386 printf("%s", vpx_svc_dump_statistics(&svc_ctx)); |
278 | 387 |
279 vpx_svc_release(&svc_ctx); | 388 vpx_svc_release(&svc_ctx); |
280 | 389 |
281 return EXIT_SUCCESS; | 390 return EXIT_SUCCESS; |
282 } | 391 } |
OLD | NEW |