diff --git a/tools_common.c b/tools_common.c index 8825528a5..b481579b4 100644 --- a/tools_common.c +++ b/tools_common.c @@ -83,7 +83,7 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) { struct FileTypeDetectionBuffer *detect = &input_ctx->detect; int plane = 0; int shortread = 0; - const int bytespp = (input_ctx->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1; + const int bytespp = (yuv_frame->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1; for (plane = 0; plane < 3; ++plane) { uint8_t *ptr; diff --git a/vpxdec.c b/vpxdec.c index 7cbcd92fe..30b55fd6f 100644 --- a/vpxdec.c +++ b/vpxdec.c @@ -55,6 +55,8 @@ static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0, "Output raw I420 frames"); static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0, "Flip the chroma planes in the output"); +static const arg_def_t rawvideo = ARG_DEF(NULL, "rawvideo", 0, + "Output raw YUV frames"); static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0, "Don't process the decoded frames"); static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0, @@ -90,7 +92,7 @@ static const arg_def_t outbitdeptharg = ARG_DEF( #endif static const arg_def_t *all_args[] = { - &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg, + &codecarg, &use_yv12, &use_i420, &flipuvarg, &rawvideo, &noblitarg, &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile, &threadsarg, &verbosearg, &scalearg, &fb_arg, &md5arg, @@ -710,6 +712,8 @@ int main_loop(int argc, const char **argv_) { int single_file; int use_y4m = 1; + int opt_yv12 = 0; + int opt_i420 = 0; vpx_codec_dec_cfg_t cfg = {0}; #if CONFIG_VP9_HIGH int out_bit_depth = 0; @@ -766,11 +770,19 @@ int main_loop(int argc, const char **argv_) { else if (arg_match(&arg, &use_yv12, argi)) { use_y4m = 0; flipuv = 1; + opt_yv12 = 1; +#if CONFIG_VP9_HIGH + out_bit_depth = 8; // For yv12 8-bit depth output is assumed +#endif } else if (arg_match(&arg, &use_i420, argi)) { use_y4m = 0; flipuv = 0; + opt_i420 = 1; } else if (arg_match(&arg, &flipuvarg, argi)) flipuv = 1; + else if (arg_match(&arg, &rawvideo, argi)) { + use_y4m = 0; + } else if (arg_match(&arg, &noblitarg, argi)) noblit = 1; else if (arg_match(&arg, &progressarg, argi)) @@ -1161,6 +1173,27 @@ int main_loop(int argc, const char **argv_) { } else { fputs(buf, outfile); } + } else { + if (frame_out == 1) { + // Check if --yv12 or --i420 options are consistent with the + // bit-stream. + if (opt_i420) { + if (img->fmt != VPX_IMG_FMT_I420 && + img->fmt != VPX_IMG_FMT_I42016) { + fprintf(stderr, + "Cannot produce i420 output for bit-stream.\n"); + goto fail; + } + } + if (opt_yv12) { + if ((img->fmt != VPX_IMG_FMT_I420 && + img->fmt != VPX_IMG_FMT_YV12) || img->bit_depth != 8) { + fprintf(stderr, + "Cannot produce yv12 output for bit-stream.\n"); + goto fail; + } + } + } } if (do_md5) { diff --git a/vpxenc.c b/vpxenc.c index 747590241..3ce74680d 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, @@ -234,8 +238,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, - &width, &height, + &use_yv12, &use_i420, &use_i422, &use_i444, &usage, &threads, + &profile, &width, &height, #if CONFIG_WEBM_IO &stereo_mode, #endif @@ -765,7 +769,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; @@ -798,9 +802,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)) @@ -1440,6 +1448,11 @@ static void encode_frame(struct stream_state *stream, if (img) { if ((img->fmt & VPX_IMG_FMT_HIGH) && (img->d_w != cfg->g_w || img->d_h != cfg->g_h)) { + if (img->fmt != VPX_IMG_FMT_I42016) { + fprintf(stderr, "%s can only scale 4:2:0 inputs\n", exec_name); + exit(EXIT_FAILURE); + } +#if CONFIG_LIBYUV if (!stream->img) stream->img = vpx_img_alloc(NULL, VPX_IMG_FMT_I42016, cfg->g_w, cfg->g_h, 16); @@ -1459,6 +1472,14 @@ static void encode_frame(struct stream_state *stream, 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 } } #endif @@ -1894,7 +1915,14 @@ 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; + if (global.color_type == I420) + input.fmt = VPX_IMG_FMT_I420; + else if (global.color_type == I422) + input.fmt = VPX_IMG_FMT_I422; + else if (global.color_type == I444) + input.fmt = VPX_IMG_FMT_I444; + else if (global.color_type == YV12) + input.fmt = VPX_IMG_FMT_YV12; { /* Now parse each stream's parameters. Using a local scope here diff --git a/vpxenc.h b/vpxenc.h index a8c3722bd..55964067a 100644 --- a/vpxenc.h +++ b/vpxenc.h @@ -22,6 +22,13 @@ enum TestDecodeFatality { TEST_DECODE_WARN, }; +typedef enum { + I420, // 4:2:0 8+ bit-depth + I422, // 4:2:2 8+ bit-depth + I444, // 4:4:4 8+ bit-depth + YV12, // 4:2:0 with uv flipped, only 8 bit-depth +} ColorInputType; + struct VpxInterface; /* Configuration elements common to all streams. */ @@ -31,7 +38,7 @@ struct VpxEncoderConfig { int pass; int usage; int deadline; - int use_i420; + ColorInputType color_type; int quiet; int verbose; int limit;