struct WebmInputContext *webm_ctx;
};
+static const arg_def_t help =
+ ARG_DEF(NULL, "help", 0, "Show usage options and exit");
static const arg_def_t looparg =
ARG_DEF(NULL, "loops", 1, "Number of times to decode the file");
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, "Codec to use");
NULL, "svc-decode-layer", 1, "Decode SVC stream up to given spatial layer");
static const arg_def_t framestatsarg =
ARG_DEF(NULL, "framestats", 1, "Output per-frame stats (.csv format)");
-
-static const arg_def_t *all_args[] = {
- &codecarg, &use_yv12, &use_i420,
- &flipuvarg, &rawvideo, &noblitarg,
- &progressarg, &limitarg, &skiparg,
- &postprocarg, &summaryarg, &outputfile,
- &threadsarg, &frameparallelarg, &verbosearg,
- &scalearg, &fb_arg, &md5arg,
- &error_concealment, &continuearg,
+static const arg_def_t rowmtarg =
+ ARG_DEF(NULL, "row-mt", 1, "Enable multi-threading to run row-wise in VP9");
+static const arg_def_t lpfoptarg =
+ ARG_DEF(NULL, "lpf-opt", 1,
+ "Do loopfilter without waiting for all threads to sync.");
+
+static const arg_def_t *all_args[] = { &help,
+ &codecarg,
+ &use_yv12,
+ &use_i420,
+ &flipuvarg,
+ &rawvideo,
+ &noblitarg,
+ &progressarg,
+ &limitarg,
+ &skiparg,
+ &postprocarg,
+ &summaryarg,
+ &outputfile,
+ &threadsarg,
+ &frameparallelarg,
+ &verbosearg,
+ &scalearg,
+ &fb_arg,
+ &md5arg,
+ &error_concealment,
+ &continuearg,
#if CONFIG_VP9_HIGHBITDEPTH
- &outbitdeptharg,
+ &outbitdeptharg,
#endif
- &svcdecodingarg, &framestatsarg, NULL
-};
+ &svcdecodingarg,
+ &framestatsarg,
+ &rowmtarg,
+ &lpfoptarg,
+ NULL };
#if CONFIG_VP8_DECODER
static const arg_def_t addnoise_level =
dst->d_h, mode);
}
#endif
-
-void usage_exit(void) {
+static void show_help(FILE *fout, int shorthelp) {
int i;
- fprintf(stderr,
- "Usage: %s <options> filename\n\n"
- "Options:\n",
- exec_name);
- arg_show_usage(stderr, all_args);
+ fprintf(fout, "Usage: %s <options> filename\n\n", exec_name);
+
+ if (shorthelp) {
+ fprintf(fout, "Use --help to see the full list of options.\n");
+ return;
+ }
+
+ fprintf(fout, "Options:\n");
+ arg_show_usage(fout, all_args);
#if CONFIG_VP8_DECODER
- fprintf(stderr, "\nVP8 Postprocessing Options:\n");
- arg_show_usage(stderr, vp8_pp_args);
+ fprintf(fout, "\nVP8 Postprocessing Options:\n");
+ arg_show_usage(fout, vp8_pp_args);
#endif
- fprintf(stderr,
+ fprintf(fout,
"\nOutput File Patterns:\n\n"
" The -o argument specifies the name of the file(s) to "
"write to. If the\n argument does not include any escape "
"characters, the output will be\n written to a single file. "
"Otherwise, the filename will be calculated by\n expanding "
"the following escape characters:\n");
- fprintf(stderr,
+ fprintf(fout,
"\n\t%%w - Frame width"
"\n\t%%h - Frame height"
"\n\t%%<n> - Frame number, zero padded to <n> places (1..9)"
"\n\n Pattern arguments are only supported in conjunction "
"with the --yv12 and\n --i420 options. If the -o option is "
"not specified, the output will be\n directed to stdout.\n");
- fprintf(stderr, "\nIncluded decoders:\n\n");
+ fprintf(fout, "\nIncluded decoders:\n\n");
for (i = 0; i < get_vpx_decoder_count(); ++i) {
const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
- fprintf(stderr, " %-6s - %s\n", decoder->name,
+ fprintf(fout, " %-6s - %s\n", decoder->name,
vpx_codec_iface_name(decoder->codec_interface()));
}
+}
+void usage_exit(void) {
+ show_help(stderr, 1);
exit(EXIT_FAILURE);
}
return 1;
}
*bytes_read = frame_size;
+ return 0;
}
- return 0;
+ return 1;
}
-static int read_frame(struct VpxDecInputContext *input, uint8_t **buf,
- size_t *bytes_in_buffer, size_t *buffer_size) {
+static int dec_read_frame(struct VpxDecInputContext *input, uint8_t **buf,
+ size_t *bytes_in_buffer, size_t *buffer_size) {
switch (input->vpx_input_ctx->file_type) {
#if CONFIG_WEBM_IO
case FILE_TYPE_WEBM:
int arg_skip = 0;
int ec_enabled = 0;
int keep_going = 0;
+ int enable_row_mt = 0;
+ int enable_lpf_opt = 0;
const VpxInterface *interface = NULL;
const VpxInterface *fourcc_interface = NULL;
uint64_t dx_time = 0;
memset(&arg, 0, sizeof(arg));
arg.argv_step = 1;
- if (arg_match(&arg, &codecarg, argi)) {
+ if (arg_match(&arg, &help, argi)) {
+ show_help(stdout, 0);
+ exit(EXIT_SUCCESS);
+ } else if (arg_match(&arg, &codecarg, argi)) {
interface = get_vpx_decoder_by_name(arg.val);
if (!interface)
die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
die("Error: Could not open --framestats file (%s) for writing.\n",
arg.val);
}
+ } else if (arg_match(&arg, &rowmtarg, argi)) {
+ enable_row_mt = arg_parse_uint(&arg);
+ } else if (arg_match(&arg, &lpfoptarg, argi)) {
+ enable_lpf_opt = arg_parse_uint(&arg);
}
#if CONFIG_VP8_DECODER
else if (arg_match(&arg, &addnoise_level, argi)) {
if (!fn) {
free(argv);
+ fprintf(stderr, "No input file specified!\n");
usage_exit();
}
/* Open file */
#if !CONFIG_WEBM_IO
fprintf(stderr, "vpxdec was built without WebM container support.\n");
#endif
+ free(argv);
return EXIT_FAILURE;
}
goto fail;
}
}
+ if (interface->fourcc == VP9_FOURCC &&
+ vpx_codec_control(&decoder, VP9D_SET_ROW_MT, enable_row_mt)) {
+ fprintf(stderr, "Failed to set decoder in row multi-thread mode: %s\n",
+ vpx_codec_error(&decoder));
+ goto fail;
+ }
+ if (interface->fourcc == VP9_FOURCC &&
+ vpx_codec_control(&decoder, VP9D_SET_LOOP_FILTER_OPT, enable_lpf_opt)) {
+ fprintf(stderr, "Failed to set decoder in optimized loopfilter mode: %s\n",
+ vpx_codec_error(&decoder));
+ goto fail;
+ }
if (!quiet) fprintf(stderr, "%s\n", decoder.name);
#if CONFIG_VP8_DECODER
if (arg_skip) fprintf(stderr, "Skipping first %d frames.\n", arg_skip);
while (arg_skip) {
- if (read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) break;
+ if (dec_read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) break;
arg_skip--;
}
ext_fb_list.num_external_frame_buffers = num_external_frame_buffers;
ext_fb_list.ext_fb = (struct ExternalFrameBuffer *)calloc(
num_external_frame_buffers, sizeof(*ext_fb_list.ext_fb));
+ if (!ext_fb_list.ext_fb) {
+ fprintf(stderr, "Failed to allocate ExternalFrameBuffer\n");
+ goto fail;
+ }
if (vpx_codec_set_frame_buffer_functions(&decoder, get_vp9_frame_buffer,
release_vp9_frame_buffer,
&ext_fb_list)) {
frame_avail = 0;
if (!stop_after || frame_in < stop_after) {
- if (!read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) {
+ if (!dec_read_frame(&input, &buf, &bytes_in_buffer, &buffer_size)) {
frame_avail = 1;
frame_in++;
}
scaled_img =
vpx_img_alloc(NULL, img->fmt, render_width, render_height, 16);
+ if (!scaled_img) {
+ fprintf(stderr, "Failed to allocate scaled image (%d x %d)\n",
+ render_width, render_height);
+ goto fail;
+ }
scaled_img->bit_depth = img->bit_depth;
}
if (!img_shifted) {
img_shifted =
vpx_img_alloc(NULL, shifted_fmt, img->d_w, img->d_h, 16);
+ if (!img_shifted) {
+ fprintf(stderr, "Failed to allocate image\n");
+ goto fail;
+ }
img_shifted->bit_depth = output_bit_depth;
}
if (output_bit_depth > img->bit_depth) {