summaryrefslogtreecommitdiff
path: root/examples/vp9_spatial_scalable_encoder.c
diff options
context:
space:
mode:
authorMinghai Shang <minghai@google.com>2014-03-07 14:02:35 -0800
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>2014-03-07 14:02:35 -0800
commit274050714265729578bc48130dfdbd568299d061 (patch)
treec96f458b12d13703ea85659ed750da3ee99fbe57 /examples/vp9_spatial_scalable_encoder.c
parent6849cde89328b70ed2fd0ffd9cd225ead6025fd9 (diff)
parentb0c146eea9cdd3f43dbf82574ab037e08f1da55c (diff)
downloadlibvpx-274050714265729578bc48130dfdbd568299d061.tar
libvpx-274050714265729578bc48130dfdbd568299d061.tar.gz
libvpx-274050714265729578bc48130dfdbd568299d061.tar.bz2
libvpx-274050714265729578bc48130dfdbd568299d061.zip
Merge "[svc] 1. Add two pass RC options in vp9_spatial_scalable_encoder. 2. Add read/write for RC stats file The two pass RC for svc does not work yet. This is just the first step. We need further development to make it working. Change-Id: I8ef0e177dff0b5ed3c97a916beea5123717cc6f2"
Diffstat (limited to 'examples/vp9_spatial_scalable_encoder.c')
-rw-r--r--examples/vp9_spatial_scalable_encoder.c95
1 files changed, 84 insertions, 11 deletions
diff --git a/examples/vp9_spatial_scalable_encoder.c b/examples/vp9_spatial_scalable_encoder.c
index 98dc3f5f9..5333b11f1 100644
--- a/examples/vp9_spatial_scalable_encoder.c
+++ b/examples/vp9_spatial_scalable_encoder.c
@@ -26,6 +26,7 @@
#include "vpx/svc_context.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
+#include "./vpxstats.h"
static const struct arg_enum_list encoding_mode_enum[] = {
{"i", INTER_LAYER_PREDICTION_I},
@@ -60,12 +61,19 @@ static const arg_def_t quantizers_arg =
static const arg_def_t quantizers_keyframe_arg =
ARG_DEF("qn", "quantizers-keyframe", 1, "quantizers for key frames (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 =
+ ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)");
+static const arg_def_t fpf_name_arg =
+ ARG_DEF(NULL, "fpf", 1, "First pass statistics file name");
static const arg_def_t *svc_args[] = {
&encoding_mode_arg, &frames_arg, &width_arg, &height_arg,
&timebase_arg, &bitrate_arg, &skip_frames_arg, &layers_arg,
&kf_dist_arg, &scale_factors_arg, &quantizers_arg,
- &quantizers_keyframe_arg, NULL
+ &quantizers_keyframe_arg, &passes_arg, &pass_arg,
+ &fpf_name_arg, NULL
};
static const SVC_ENCODING_MODE default_encoding_mode =
@@ -85,6 +93,10 @@ typedef struct {
const char *output_filename;
uint32_t frames_to_code;
uint32_t frames_to_skip;
+ struct VpxInputContext input_ctx;
+ stats_io_t rc_stats;
+ int passes;
+ int pass;
} AppInput;
static const char *exec_name;
@@ -105,6 +117,9 @@ static void parse_command_line(int argc, const char **argv_,
char **argi = NULL;
char **argj = NULL;
vpx_codec_err_t res;
+ int passes = 0;
+ int pass = 0;
+ const char *fpf_file_name = NULL;
// initialize SvcContext with parameters that will be passed to vpx_svc_init
svc_ctx->log_level = SVC_LOG_DEBUG;
@@ -159,11 +174,53 @@ static void parse_command_line(int argc, const char **argv_,
vpx_svc_set_quantizers(svc_ctx, arg.val, 0);
} else if (arg_match(&arg, &quantizers_keyframe_arg, argi)) {
vpx_svc_set_quantizers(svc_ctx, arg.val, 1);
+ } else if (arg_match(&arg, &passes_arg, argi)) {
+ passes = arg_parse_uint(&arg);
+ if (passes < 1 || passes > 2) {
+ die("Error: Invalid number of passes (%d)\n", passes);
+ }
+ } else if (arg_match(&arg, &pass_arg, argi)) {
+ pass = arg_parse_uint(&arg);
+ if (pass < 1 || pass > 2) {
+ die("Error: Invalid pass selected (%d)\n", pass);
+ }
+ } else if (arg_match(&arg, &fpf_name_arg, argi)) {
+ fpf_file_name = arg.val;
} else {
++argj;
}
}
+ if (passes == 0 || passes == 1) {
+ if (pass) {
+ fprintf(stderr, "pass is ignored since there's only one pass\n");
+ }
+ enc_cfg->g_pass = VPX_RC_ONE_PASS;
+ } else {
+ if (pass == 0) {
+ die("pass must be specified when passes is 2\n");
+ }
+
+ if (fpf_file_name == NULL) {
+ die("fpf must be specified when passes is 2\n");
+ }
+
+ if (pass == 1) {
+ enc_cfg->g_pass = VPX_RC_FIRST_PASS;
+ if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 0)) {
+ fatal("Failed to open statistics store");
+ }
+ } else {
+ enc_cfg->g_pass = VPX_RC_LAST_PASS;
+ if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 1)) {
+ fatal("Failed to open statistics store");
+ }
+ enc_cfg->rc_twopass_stats_in = stats_get(&app_input->rc_stats);
+ }
+ app_input->passes = passes;
+ app_input->pass = pass;
+ }
+
// Check for unrecognized options
for (argi = argv; *argi; ++argi)
if (argi[0][0] == '-' && strlen(argi[0]) > 1)
@@ -234,10 +291,14 @@ int main(int argc, const char **argv) {
VPX_CODEC_OK) {
die("Failed to get output resolution");
}
- writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF,
- &info);
- if (!writer)
- die("Failed to open %s for writing\n", app_input.output_filename);
+
+ if (!(app_input.passes == 2 && app_input.pass == 1)) {
+ // We don't save the bitstream for the 1st pass on two pass rate control
+ writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF,
+ &info);
+ if (!writer)
+ die("Failed to open %s for writing\n", app_input.output_filename);
+ }
// skip initial frames
for (i = 0; i < app_input.frames_to_skip; ++i)
@@ -254,11 +315,18 @@ int main(int argc, const char **argv) {
if (res != VPX_CODEC_OK) {
die_codec(&codec, "Failed to encode frame");
}
- if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
- vpx_video_writer_write_frame(writer,
- vpx_svc_get_buffer(&svc_ctx),
- vpx_svc_get_frame_size(&svc_ctx),
- pts);
+ if (!(app_input.passes == 2 && app_input.pass == 1)) {
+ if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
+ vpx_video_writer_write_frame(writer,
+ vpx_svc_get_buffer(&svc_ctx),
+ vpx_svc_get_frame_size(&svc_ctx),
+ pts);
+ }
+ }
+ 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));
}
++frame_cnt;
pts += frame_duration;
@@ -269,7 +337,12 @@ int main(int argc, const char **argv) {
fclose(infile);
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
- vpx_video_writer_close(writer);
+ if (app_input.passes == 2)
+ stats_close(&app_input.rc_stats, 1);
+
+ if (writer) {
+ vpx_video_writer_close(writer);
+ }
vpx_img_free(&raw);