X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=vpxenc.c;h=d4bb034a413524cab1cc9fcd92fd3c6c4e1b5570;hb=6e0748e1423270b5b57177ee8941fa890d217b50;hp=28d43f28b2c41d3a1539d37f3d03f2e299187873;hpb=5ac6d9778fcd610f9fd9c82fd25b350e23ca40bb;p=libvpx diff --git a/vpxenc.c b/vpxenc.c index 28d43f28b..d4bb034a4 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -133,6 +133,10 @@ static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, "Input file is YV12 "); static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0, "Input file is I420 (default)"); +static const arg_def_t use_i422 = ARG_DEF(NULL, "i422", 0, + "Input file is I422"); +static const arg_def_t use_i444 = ARG_DEF(NULL, "i444", 0, + "Input file is I444"); static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, "Codec to use"); static const arg_def_t passes = ARG_DEF("p", "passes", 1, @@ -141,6 +145,10 @@ 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_DEF(NULL, "fpf", 1, "First pass statistics file name"); +#if CONFIG_FP_MB_STATS +static const arg_def_t fpmbf_name = ARG_DEF(NULL, "fpmbf", 1, + "First pass block statistics file name"); +#endif static const arg_def_t limit = ARG_DEF(NULL, "limit", 1, "Stop encoding after n input frames"); static const arg_def_t skip = ARG_DEF(NULL, "skip", 1, @@ -229,7 +237,8 @@ static const arg_def_t lag_in_frames = ARG_DEF(NULL, "lag-in-frames", 1, "Max number of frames to lag"); static const arg_def_t *global_args[] = { - &use_yv12, &use_i420, &usage, &threads, &profile, + &use_yv12, &use_i420, &use_i422, &use_i444, + &usage, &threads, &profile, &width, &height, #if CONFIG_WEBM_IO &stereo_mode, @@ -422,7 +431,7 @@ void usage_exit() { for (i = 0; i < get_vpx_encoder_count(); ++i) { const VpxInterface *const encoder = get_vpx_encoder_by_index(i); fprintf(stderr, " %-6s - %s\n", - encoder->name, vpx_codec_iface_name(encoder->interface())); + encoder->name, vpx_codec_iface_name(encoder->codec_interface())); } exit(EXIT_FAILURE); @@ -572,6 +581,9 @@ struct stream_config { struct vpx_codec_enc_cfg cfg; const char *out_fn; const char *stats_fn; +#if CONFIG_FP_MB_STATS + const char *fpmb_stats_fn; +#endif stereo_format_t stereo_fmt; int arg_ctrls[ARG_CTRL_CNT_MAX][2]; int arg_ctrl_cnt; @@ -597,6 +609,9 @@ struct stream_state { uint64_t cx_time; size_t nbytes; stats_io_t stats; +#if CONFIG_FP_MB_STATS + stats_io_t fpmb_stats; +#endif struct vpx_image *img; vpx_codec_ctx_t decoder; int mismatch_seen; @@ -626,7 +641,7 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) { memset(global, 0, sizeof(*global)); global->codec = get_vpx_encoder_by_index(0); global->passes = 0; - global->use_i420 = 1; + global->color_type = I420; /* Assign default deadline to good quality */ global->deadline = VPX_DL_GOOD_QUALITY; @@ -659,9 +674,13 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) { else if (arg_match(&arg, &rt_dl, argi)) global->deadline = VPX_DL_REALTIME; else if (arg_match(&arg, &use_yv12, argi)) - global->use_i420 = 0; + global->color_type = YV12; else if (arg_match(&arg, &use_i420, argi)) - global->use_i420 = 1; + global->color_type = I420; + else if (arg_match(&arg, &use_i422, argi)) + global->color_type = I422; + else if (arg_match(&arg, &use_i444, argi)) + global->color_type = I444; else if (arg_match(&arg, &quietarg, argi)) global->quiet = 1; else if (arg_match(&arg, &verbosearg, argi)) @@ -756,6 +775,7 @@ void open_input_file(struct VpxInputContext *input) { input->framerate.numerator = input->y4m.fps_n; input->framerate.denominator = input->y4m.fps_d; input->fmt = input->y4m.vpx_fmt; + input->bit_depth = input->y4m.bit_depth; } else fatal("Unsupported Y4M stream."); } else if (input->detect.buf_read == 4 && fourcc_is_ivf(input->detect.buf)) { @@ -787,7 +807,7 @@ static struct stream_state *new_stream(struct VpxEncoderConfig *global, vpx_codec_err_t res; /* Populate encoder configuration */ - res = vpx_codec_enc_config_default(global->codec->interface(), + res = vpx_codec_enc_config_default(global->codec->codec_interface(), &stream->config.cfg, global->usage); if (res) @@ -872,6 +892,10 @@ static int parse_stream_params(struct VpxEncoderConfig *global, config->out_fn = arg.val; } else if (arg_match(&arg, &fpf_name, argi)) { config->stats_fn = arg.val; +#if CONFIG_FP_MB_STATS + } else if (arg_match(&arg, &fpmbf_name, argi)) { + config->fpmb_stats_fn = arg.val; +#endif } else if (arg_match(&arg, &use_ivf, argi)) { config->write_webm = 0; } else if (arg_match(&arg, &threads, argi)) { @@ -964,8 +988,8 @@ static int parse_stream_params(struct VpxEncoderConfig *global, break; /* Update/insert */ - assert(j < ARG_CTRL_CNT_MAX); - if (j < ARG_CTRL_CNT_MAX) { + assert(j < (int)ARG_CTRL_CNT_MAX); + if (j < (int)ARG_CTRL_CNT_MAX) { config->arg_ctrls[j][0] = ctrl_args_map[i]; config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg); if (j == config->arg_ctrl_cnt) @@ -1028,6 +1052,17 @@ static void validate_stream_config(const struct stream_state *stream, fatal("Stream %d: duplicate stats file (from stream %d)", streami->index, stream->index); } + +#if CONFIG_FP_MB_STATS + /* Check for two streams sharing a mb stats file. */ + if (streami != stream) { + const char *a = stream->config.fpmb_stats_fn; + const char *b = streami->config.fpmb_stats_fn; + if (a && b && !strcmp(a, b)) + fatal("Stream %d: duplicate mb stats file (from stream %d)", + streami->index, stream->index); + } +#endif } } @@ -1086,7 +1121,7 @@ static void show_stream_config(struct stream_state *stream, if (stream->index == 0) { fprintf(stderr, "Codec: %s\n", - vpx_codec_iface_name(global->codec->interface())); + vpx_codec_iface_name(global->codec->codec_interface())); fprintf(stderr, "Source file: %s File Type: %s Format: %s\n", input->filename, file_type_to_string(input->file_type), @@ -1199,11 +1234,27 @@ static void setup_pass(struct stream_state *stream, fatal("Failed to open statistics store"); } +#if CONFIG_FP_MB_STATS + if (stream->config.fpmb_stats_fn) { + if (!stats_open_file(&stream->fpmb_stats, + stream->config.fpmb_stats_fn, pass)) + fatal("Failed to open mb statistics store"); + } else { + if (!stats_open_mem(&stream->fpmb_stats, pass)) + fatal("Failed to open mb statistics store"); + } +#endif + stream->config.cfg.g_pass = global->passes == 2 ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS : VPX_RC_ONE_PASS; - if (pass) + if (pass) { stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats); +#if CONFIG_FP_MB_STATS + stream->config.cfg.rc_firstpass_mb_stats_in = + stats_get(&stream->fpmb_stats); +#endif + } stream->cx_time = 0; stream->nbytes = 0; @@ -1220,7 +1271,7 @@ static void initialize_encoder(struct stream_state *stream, flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0; /* Construct Encoder Context */ - vpx_codec_enc_init(&stream->encoder, global->codec->interface(), + vpx_codec_enc_init(&stream->encoder, global->codec->codec_interface(), &stream->config.cfg, flags); ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder"); @@ -1241,7 +1292,7 @@ static void initialize_encoder(struct stream_state *stream, #if CONFIG_DECODERS if (global->test_decode != TEST_DECODE_OFF) { const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name); - vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0); + vpx_codec_dec_init(&stream->decoder, decoder->codec_interface(), NULL, 0); } #endif } @@ -1264,6 +1315,11 @@ static void encode_frame(struct stream_state *stream, /* Scale if necessary */ if (img && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) { + if (img->fmt != VPX_IMG_FMT_I420 && img->fmt != VPX_IMG_FMT_YV12) { + fprintf(stderr, "%s can only scale 4:2:0 8bpp inputs\n", exec_name); + exit(EXIT_FAILURE); + } +#if CONFIG_LIBYUV if (!stream->img) stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, cfg->g_w, cfg->g_h, 16); @@ -1279,8 +1335,15 @@ static void encode_frame(struct stream_state *stream, stream->img->stride[VPX_PLANE_V], stream->img->d_w, stream->img->d_h, kFilterBox); - img = stream->img; +#else + stream->encoder.err = 1; + ctx_exit_on_error(&stream->encoder, + "Stream %d: Failed to encode frame.\n" + "Scaling disabled in this configuration. \n" + "To enable, configure with --enable-libyuv\n", + stream->index); +#endif } vpx_usec_timer_start(&timer); @@ -1375,6 +1438,14 @@ static void get_cx_data(struct stream_state *stream, pkt->data.twopass_stats.sz); stream->nbytes += pkt->data.raw.sz; break; +#if CONFIG_FP_MB_STATS + case VPX_CODEC_FPMB_STATS_PKT: + stats_write(&stream->fpmb_stats, + pkt->data.firstpass_mb_stats.buf, + pkt->data.firstpass_mb_stats.sz); + stream->nbytes += pkt->data.raw.sz; + break; +#endif case VPX_CODEC_PSNR_PKT: if (global->show_psnr) { @@ -1504,7 +1575,7 @@ int main(int argc, const char **argv_) { vpx_image_t raw; int frame_avail, got_data; - struct VpxInputContext input = {0}; + struct VpxInputContext input; struct VpxEncoderConfig global; struct stream_state *streams = NULL; char **argv, **argi; @@ -1512,6 +1583,7 @@ int main(int argc, const char **argv_) { int stream_cnt = 0; int res = 0; + memset(&input, 0, sizeof(input)); exec_name = argv_[0]; if (argc < 3) @@ -1521,6 +1593,7 @@ int main(int argc, const char **argv_) { input.framerate.numerator = 30; input.framerate.denominator = 1; input.only_i420 = 1; + input.bit_depth = 0; /* First parse the global configuration values, because we want to apply * other parameters on top of the default configuration provided by the @@ -1529,7 +1602,20 @@ int main(int argc, const char **argv_) { argv = argv_dup(argc - 1, argv_ + 1); parse_global_config(&global, argv); - input.fmt = global.use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12; + switch (global.color_type) { + case I420: + input.fmt = VPX_IMG_FMT_I420; + break; + case I422: + input.fmt = VPX_IMG_FMT_I422; + break; + case I444: + input.fmt = VPX_IMG_FMT_I444; + break; + case YV12: + input.fmt = VPX_IMG_FMT_YV12; + break; + } { /* Now parse each stream's parameters. Using a local scope here @@ -1672,7 +1758,6 @@ int main(int argc, const char **argv_) { fps >= 1.0 ? fps : fps * 60, fps >= 1.0 ? "fps" : "fpm"); print_time("ETA", estimated_time_left); - fprintf(stderr, "\033[K"); } } else @@ -1723,6 +1808,8 @@ int main(int argc, const char **argv_) { } fflush(stdout); + if (!global.quiet) + fprintf(stderr, "\033[K"); } if (stream_cnt > 1) @@ -1762,6 +1849,10 @@ int main(int argc, const char **argv_) { FOREACH_STREAM(stats_close(&stream->stats, global.passes - 1)); +#if CONFIG_FP_MB_STATS + FOREACH_STREAM(stats_close(&stream->fpmb_stats, global.passes - 1)); +#endif + if (global.pass) break; }