Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: source/libvpx/examples/vp9_spatial_scalable_encoder.c

Issue 232133009: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « source/libvpx/examples/vp8cx_set_ref.c ('k') | source/libvpx/examples/vpx_temporal_scalable_patterns.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698