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