| Index: source/libvpx/examples/vp9_spatial_svc_encoder.c
|
| ===================================================================
|
| --- source/libvpx/examples/vp9_spatial_svc_encoder.c (revision 292072)
|
| +++ source/libvpx/examples/vp9_spatial_svc_encoder.c (working copy)
|
| @@ -46,10 +46,6 @@
|
| ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
|
| static const arg_def_t scale_factors_arg =
|
| ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)");
|
| -static const arg_def_t quantizers_arg =
|
| - ARG_DEF("q", "quantizers", 1, "quantizers for non key frames, also will "
|
| - "be applied to key frames if -qn is not specified (lowest to "
|
| - "highest layer)");
|
| static const arg_def_t passes_arg =
|
| ARG_DEF("p", "passes", 1, "Number of passes (1/2)");
|
| static const arg_def_t pass_arg =
|
| @@ -68,10 +64,9 @@
|
| static const arg_def_t *svc_args[] = {
|
| &frames_arg, &width_arg, &height_arg,
|
| &timebase_arg, &bitrate_arg, &skip_frames_arg, &spatial_layers_arg,
|
| - &kf_dist_arg, &scale_factors_arg, &quantizers_arg, &passes_arg,
|
| - &pass_arg, &fpf_name_arg, &min_q_arg, &max_q_arg,
|
| - &min_bitrate_arg, &max_bitrate_arg, &temporal_layers_arg,
|
| - NULL
|
| + &kf_dist_arg, &scale_factors_arg, &passes_arg, &pass_arg,
|
| + &fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg,
|
| + &max_bitrate_arg, &temporal_layers_arg, NULL
|
| };
|
|
|
| static const uint32_t default_frames_to_skip = 0;
|
| @@ -119,6 +114,7 @@
|
| const char *fpf_file_name = NULL;
|
| unsigned int min_bitrate = 0;
|
| unsigned int max_bitrate = 0;
|
| + char string_options[1024] = {0};
|
|
|
| // initialize SvcContext with parameters that will be passed to vpx_svc_init
|
| svc_ctx->log_level = SVC_LOG_DEBUG;
|
| @@ -169,9 +165,8 @@
|
| enc_cfg->kf_min_dist = arg_parse_uint(&arg);
|
| enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
|
| } else if (arg_match(&arg, &scale_factors_arg, argi)) {
|
| - vpx_svc_set_scale_factors(svc_ctx, arg.val);
|
| - } else if (arg_match(&arg, &quantizers_arg, argi)) {
|
| - vpx_svc_set_quantizers(svc_ctx, arg.val);
|
| + snprintf(string_options, 1024, "%s scale-factors=%s",
|
| + string_options, arg.val);
|
| } else if (arg_match(&arg, &passes_arg, argi)) {
|
| passes = arg_parse_uint(&arg);
|
| if (passes < 1 || passes > 2) {
|
| @@ -185,9 +180,11 @@
|
| } else if (arg_match(&arg, &fpf_name_arg, argi)) {
|
| fpf_file_name = arg.val;
|
| } else if (arg_match(&arg, &min_q_arg, argi)) {
|
| - enc_cfg->rc_min_quantizer = arg_parse_uint(&arg);
|
| + snprintf(string_options, 1024, "%s min-quantizers=%s",
|
| + string_options, arg.val);
|
| } else if (arg_match(&arg, &max_q_arg, argi)) {
|
| - enc_cfg->rc_max_quantizer = arg_parse_uint(&arg);
|
| + snprintf(string_options, 1024, "%s max-quantizers=%s",
|
| + string_options, arg.val);
|
| } else if (arg_match(&arg, &min_bitrate_arg, argi)) {
|
| min_bitrate = arg_parse_uint(&arg);
|
| } else if (arg_match(&arg, &max_bitrate_arg, argi)) {
|
| @@ -197,6 +194,10 @@
|
| }
|
| }
|
|
|
| + // There will be a space in front of the string options
|
| + if (strlen(string_options) > 0)
|
| + vpx_svc_set_options(svc_ctx, string_options + 1);
|
| +
|
| if (passes == 0 || passes == 1) {
|
| if (pass) {
|
| fprintf(stderr, "pass is ignored since there's only one pass\n");
|
| @@ -282,7 +283,7 @@
|
| int frame_duration = 1; /* 1 timebase tick per frame */
|
| FILE *infile = NULL;
|
| int end_of_stream = 0;
|
| - int frame_size;
|
| + int frames_received = 0;
|
|
|
| memset(&svc_ctx, 0, sizeof(svc_ctx));
|
| svc_ctx.log_print = 1;
|
| @@ -304,12 +305,6 @@
|
| info.codec_fourcc = VP9_FOURCC;
|
| info.time_base.numerator = enc_cfg.g_timebase.num;
|
| info.time_base.denominator = enc_cfg.g_timebase.den;
|
| - if (vpx_svc_get_layer_resolution(&svc_ctx, svc_ctx.spatial_layers - 1,
|
| - (unsigned int *)&info.frame_width,
|
| - (unsigned int *)&info.frame_height) !=
|
| - VPX_CODEC_OK) {
|
| - die("Failed to get output resolution");
|
| - }
|
|
|
| if (!(app_input.passes == 2 && app_input.pass == 1)) {
|
| // We don't save the bitstream for the 1st pass on two pass rate control
|
| @@ -325,6 +320,8 @@
|
|
|
| // Encode frames
|
| while (!end_of_stream) {
|
| + vpx_codec_iter_t iter = NULL;
|
| + const vpx_codec_cx_pkt_t *cx_pkt;
|
| if (frame_cnt >= app_input.frames_to_code || !vpx_img_read(&raw, infile)) {
|
| // We need one extra vpx_svc_encode call at end of stream to flush
|
| // encoder and get remaining data
|
| @@ -337,18 +334,34 @@
|
| if (res != VPX_CODEC_OK) {
|
| die_codec(&codec, "Failed to encode frame");
|
| }
|
| - if (!(app_input.passes == 2 && app_input.pass == 1)) {
|
| - while ((frame_size = vpx_svc_get_frame_size(&svc_ctx)) > 0) {
|
| - vpx_video_writer_write_frame(writer,
|
| - vpx_svc_get_buffer(&svc_ctx),
|
| - frame_size, pts);
|
| +
|
| + while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
|
| + switch (cx_pkt->kind) {
|
| + case VPX_CODEC_CX_FRAME_PKT: {
|
| + if (cx_pkt->data.frame.sz > 0)
|
| + vpx_video_writer_write_frame(writer,
|
| + cx_pkt->data.frame.buf,
|
| + cx_pkt->data.frame.sz,
|
| + cx_pkt->data.frame.pts);
|
| +
|
| + printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
|
| + !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
|
| + (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
|
| + ++frames_received;
|
| + break;
|
| + }
|
| + case VPX_CODEC_STATS_PKT: {
|
| + stats_write(&app_input.rc_stats,
|
| + cx_pkt->data.twopass_stats.buf,
|
| + cx_pkt->data.twopass_stats.sz);
|
| + break;
|
| + }
|
| + default: {
|
| + break;
|
| + }
|
| }
|
| }
|
| - if (vpx_svc_get_rc_stats_buffer_size(&svc_ctx) > 0) {
|
| - stats_write(&app_input.rc_stats,
|
| - vpx_svc_get_rc_stats_buffer(&svc_ctx),
|
| - vpx_svc_get_rc_stats_buffer_size(&svc_ctx));
|
| - }
|
| +
|
| if (!end_of_stream) {
|
| ++frame_cnt;
|
| pts += frame_duration;
|
|
|