vpxdec: rework default output parameters
This patch reworks the default behavior of the tool to output Y4M instead of writing individual raw frames. The relevant controls are now: --yv12, --i420 - These options change the output format to be raw planar data. The output will be Y4M unless one of these options is specified. --flipuv - Swaps the chroma planes. Works with Y4M output. -o, --output - Sets the output filename. Defaults to stdout if not specified. Supports escape character expansion for frame width (%w) height (%h) and sequence number (%1..%9). The --prefix option has been removed in favor of this escape expansion. Since the output defaults to stdout if -o is not specified, an error will be thrown if stdout is not connected to a pipe. This can be overridden by specifying '-o -'. Change-Id: I94e42c57ca75721fdd57a6129e79bcdb2afe5d4d
This commit is contained in:
parent
4b578ea6c4
commit
933d44b818
197
vpxdec.c
197
vpxdec.c
@ -16,6 +16,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <io.h>
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define isatty _isatty
|
||||||
|
#define fileno _fileno
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#define VPX_CODEC_DISABLE_COMPAT 1
|
#define VPX_CODEC_DISABLE_COMPAT 1
|
||||||
#include "vpx_config.h"
|
#include "vpx_config.h"
|
||||||
#include "vpx/vpx_decoder.h"
|
#include "vpx/vpx_decoder.h"
|
||||||
@ -28,6 +37,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "nestegg/include/nestegg/nestegg.h"
|
#include "nestegg/include/nestegg/nestegg.h"
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 256
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *exec_name;
|
static const char *exec_name;
|
||||||
|
|
||||||
#define VP8_FOURCC (0x00385056)
|
#define VP8_FOURCC (0x00385056)
|
||||||
@ -47,14 +60,12 @@ static const struct
|
|||||||
#include "args.h"
|
#include "args.h"
|
||||||
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
|
static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
|
||||||
"Codec to use");
|
"Codec to use");
|
||||||
static const arg_def_t prefixarg = ARG_DEF("p", "prefix", 1,
|
|
||||||
"Prefix to use when saving frames");
|
|
||||||
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
|
static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
|
||||||
"Output file is YV12 ");
|
"Output raw YV12 frames");
|
||||||
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
|
static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
|
||||||
"Output file is I420 (default)");
|
"Output raw I420 frames");
|
||||||
static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
|
static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
|
||||||
"Synonym for --yv12");
|
"Flip the chroma planes in the output");
|
||||||
static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
|
static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
|
||||||
"Don't process the decoded frames");
|
"Don't process the decoded frames");
|
||||||
static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
|
static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
|
||||||
@ -66,9 +77,7 @@ static const arg_def_t postprocarg = ARG_DEF(NULL, "postproc", 0,
|
|||||||
static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
|
static const arg_def_t summaryarg = ARG_DEF(NULL, "summary", 0,
|
||||||
"Show timing summary");
|
"Show timing summary");
|
||||||
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
|
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
|
||||||
"Output raw yv12 file instead of images");
|
"Output file name pattern (see below)");
|
||||||
static const arg_def_t usey4marg = ARG_DEF("y", "y4m", 0,
|
|
||||||
"Output file is YUV4MPEG2");
|
|
||||||
static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
|
static const arg_def_t threadsarg = ARG_DEF("t", "threads", 1,
|
||||||
"Max threads to use");
|
"Max threads to use");
|
||||||
static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
|
static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
|
||||||
@ -80,9 +89,9 @@ static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
|
|||||||
#endif
|
#endif
|
||||||
static const arg_def_t *all_args[] =
|
static const arg_def_t *all_args[] =
|
||||||
{
|
{
|
||||||
&codecarg, &prefixarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
|
&codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
|
||||||
&progressarg, &limitarg, &postprocarg, &summaryarg, &outputfile,
|
&progressarg, &limitarg, &postprocarg, &summaryarg, &outputfile,
|
||||||
&usey4marg, &threadsarg, &verbosearg,
|
&threadsarg, &verbosearg,
|
||||||
#if CONFIG_MD5
|
#if CONFIG_MD5
|
||||||
&md5arg,
|
&md5arg,
|
||||||
#endif
|
#endif
|
||||||
@ -118,6 +127,20 @@ static void usage_exit()
|
|||||||
fprintf(stderr, "\nVP8 Postprocessing Options:\n");
|
fprintf(stderr, "\nVP8 Postprocessing Options:\n");
|
||||||
arg_show_usage(stderr, vp8_pp_args);
|
arg_show_usage(stderr, vp8_pp_args);
|
||||||
#endif
|
#endif
|
||||||
|
fprintf(stderr,
|
||||||
|
"\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"
|
||||||
|
"\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(stderr, "\nIncluded decoders:\n\n");
|
||||||
|
|
||||||
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
|
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
|
||||||
@ -586,10 +609,74 @@ void show_progress(int frame_in, int frame_out, unsigned long dx_time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void generate_filename(const char *pattern, char *out, size_t q_len,
|
||||||
|
unsigned int d_w, unsigned int d_h,
|
||||||
|
unsigned int frame_in)
|
||||||
|
{
|
||||||
|
const char *p = pattern;
|
||||||
|
char *q = out;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char *next_pat = strchr(p, '%');
|
||||||
|
|
||||||
|
if(p == next_pat)
|
||||||
|
{
|
||||||
|
size_t pat_len;
|
||||||
|
|
||||||
|
// parse the pattern
|
||||||
|
q[q_len - 1] = '\0';
|
||||||
|
switch(p[1])
|
||||||
|
{
|
||||||
|
case 'w': snprintf(q, q_len - 1, "%d", d_w); break;
|
||||||
|
case 'h': snprintf(q, q_len - 1, "%d", d_h); break;
|
||||||
|
case '1': snprintf(q, q_len - 1, "%d", frame_in); break;
|
||||||
|
case '2': snprintf(q, q_len - 1, "%02d", frame_in); break;
|
||||||
|
case '3': snprintf(q, q_len - 1, "%03d", frame_in); break;
|
||||||
|
case '4': snprintf(q, q_len - 1, "%04d", frame_in); break;
|
||||||
|
case '5': snprintf(q, q_len - 1, "%05d", frame_in); break;
|
||||||
|
case '6': snprintf(q, q_len - 1, "%06d", frame_in); break;
|
||||||
|
case '7': snprintf(q, q_len - 1, "%07d", frame_in); break;
|
||||||
|
case '8': snprintf(q, q_len - 1, "%08d", frame_in); break;
|
||||||
|
case '9': snprintf(q, q_len - 1, "%09d", frame_in); break;
|
||||||
|
default:
|
||||||
|
die("Unrecognized pattern %%%c\n", p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pat_len = strlen(q);
|
||||||
|
if(pat_len >= q_len - 1)
|
||||||
|
die("Output filename too long.\n");
|
||||||
|
q += pat_len;
|
||||||
|
p += 2;
|
||||||
|
q_len -= pat_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t copy_len;
|
||||||
|
|
||||||
|
// copy the next segment
|
||||||
|
if(!next_pat)
|
||||||
|
copy_len = strlen(p);
|
||||||
|
else
|
||||||
|
copy_len = next_pat - p;
|
||||||
|
|
||||||
|
if(copy_len >= q_len - 1)
|
||||||
|
die("Output filename too long.\n");
|
||||||
|
|
||||||
|
memcpy(q, p, copy_len);
|
||||||
|
q[copy_len] = '\0';
|
||||||
|
q += copy_len;
|
||||||
|
p += copy_len;
|
||||||
|
q_len -= copy_len;
|
||||||
|
}
|
||||||
|
} while(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, const char **argv_)
|
int main(int argc, const char **argv_)
|
||||||
{
|
{
|
||||||
vpx_codec_ctx_t decoder;
|
vpx_codec_ctx_t decoder;
|
||||||
char *prefix = NULL, *fn = NULL;
|
char *fn = NULL;
|
||||||
int i;
|
int i;
|
||||||
uint8_t *buf = NULL;
|
uint8_t *buf = NULL;
|
||||||
size_t buf_sz = 0, buf_alloc_sz = 0;
|
size_t buf_sz = 0, buf_alloc_sz = 0;
|
||||||
@ -601,8 +688,10 @@ int main(int argc, const char **argv_)
|
|||||||
unsigned long dx_time = 0;
|
unsigned long dx_time = 0;
|
||||||
struct arg arg;
|
struct arg arg;
|
||||||
char **argv, **argi, **argj;
|
char **argv, **argi, **argj;
|
||||||
const char *fn2 = 0;
|
const char *outfile_pattern = 0;
|
||||||
int use_y4m = 0;
|
char outfile[PATH_MAX];
|
||||||
|
int single_file;
|
||||||
|
int use_y4m = 1;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int fps_den;
|
unsigned int fps_den;
|
||||||
@ -638,15 +727,17 @@ int main(int argc, const char **argv_)
|
|||||||
arg.val);
|
arg.val);
|
||||||
}
|
}
|
||||||
else if (arg_match(&arg, &outputfile, argi))
|
else if (arg_match(&arg, &outputfile, argi))
|
||||||
fn2 = arg.val;
|
outfile_pattern = arg.val;
|
||||||
else if (arg_match(&arg, &usey4marg, argi))
|
|
||||||
use_y4m = 1;
|
|
||||||
else if (arg_match(&arg, &prefixarg, argi))
|
|
||||||
prefix = strdup(arg.val);
|
|
||||||
else if (arg_match(&arg, &use_yv12, argi))
|
else if (arg_match(&arg, &use_yv12, argi))
|
||||||
|
{
|
||||||
|
use_y4m = 0;
|
||||||
flipuv = 1;
|
flipuv = 1;
|
||||||
|
}
|
||||||
else if (arg_match(&arg, &use_i420, argi))
|
else if (arg_match(&arg, &use_i420, argi))
|
||||||
|
{
|
||||||
|
use_y4m = 0;
|
||||||
flipuv = 0;
|
flipuv = 0;
|
||||||
|
}
|
||||||
else if (arg_match(&arg, &flipuvarg, argi))
|
else if (arg_match(&arg, &flipuvarg, argi))
|
||||||
flipuv = 1;
|
flipuv = 1;
|
||||||
else if (arg_match(&arg, &noblitarg, argi))
|
else if (arg_match(&arg, &noblitarg, argi))
|
||||||
@ -711,20 +802,24 @@ int main(int argc, const char **argv_)
|
|||||||
if (!fn)
|
if (!fn)
|
||||||
usage_exit();
|
usage_exit();
|
||||||
|
|
||||||
if (!prefix)
|
|
||||||
prefix = strdup("img");
|
|
||||||
|
|
||||||
/* Open file */
|
/* Open file */
|
||||||
infile = strcmp(fn, "-") ? fopen(fn, "rb") : stdin;
|
infile = strcmp(fn, "-") ? fopen(fn, "rb") : stdin;
|
||||||
|
|
||||||
if (!infile)
|
if (!infile)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to open file");
|
fprintf(stderr, "Failed to open file '%s'",
|
||||||
|
strcmp(fn, "-") ? fn : "stdin");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn2)
|
/* Make sure we don't dump to the terminal, unless forced to with -o - */
|
||||||
out = out_open(fn2, do_md5);
|
if(!outfile_pattern && isatty(fileno(stdout)) && !do_md5)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Not dumping raw video to your terminal. Use '-o -' to "
|
||||||
|
"override.\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
input.infile = infile;
|
input.infile = infile;
|
||||||
if(file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
|
if(file_is_ivf(infile, &fourcc, &width, &height, &fps_den,
|
||||||
@ -740,12 +835,41 @@ int main(int argc, const char **argv_)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_y4m)
|
/* If the output file is not set or doesn't have a sequence number in
|
||||||
|
* it, then we only open it once.
|
||||||
|
*/
|
||||||
|
outfile_pattern = outfile_pattern ? outfile_pattern : "-";
|
||||||
|
single_file = 1;
|
||||||
|
{
|
||||||
|
const char *p = outfile_pattern;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p = strchr(p, '%');
|
||||||
|
if(p && p[1] >= '1' && p[1] <= '9')
|
||||||
|
{
|
||||||
|
// pattern contains sequence number, so it's not unique.
|
||||||
|
single_file = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(p)
|
||||||
|
p++;
|
||||||
|
} while(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(single_file && !noblit)
|
||||||
|
{
|
||||||
|
generate_filename(outfile_pattern, outfile, sizeof(outfile)-1,
|
||||||
|
width, height, 0);
|
||||||
|
out = out_open(outfile, do_md5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_y4m && !noblit)
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
if (!fn2)
|
if (!single_file)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "YUV4MPEG2 output only supported with -o.\n");
|
fprintf(stderr, "YUV4MPEG2 not supported with output patterns,"
|
||||||
|
" try --i420 or --yv12.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -832,14 +956,16 @@ int main(int argc, const char **argv_)
|
|||||||
if (img)
|
if (img)
|
||||||
{
|
{
|
||||||
unsigned int y;
|
unsigned int y;
|
||||||
char out_fn[128+24];
|
char out_fn[PATH_MAX];
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
const char *sfx = flipuv ? "yv12" : "i420";
|
|
||||||
|
|
||||||
if (!fn2)
|
if (!single_file)
|
||||||
{
|
{
|
||||||
sprintf(out_fn, "%s-%dx%d-%04d.%s",
|
size_t len = sizeof(out_fn)-1;
|
||||||
prefix, img->d_w, img->d_h, frame_in, sfx);
|
|
||||||
|
out_fn[len] = '\0';
|
||||||
|
generate_filename(outfile_pattern, out_fn, len-1,
|
||||||
|
img->d_w, img->d_h, frame_in);
|
||||||
out = out_open(out_fn, do_md5);
|
out = out_open(out_fn, do_md5);
|
||||||
}
|
}
|
||||||
else if(use_y4m)
|
else if(use_y4m)
|
||||||
@ -869,7 +995,7 @@ int main(int argc, const char **argv_)
|
|||||||
buf += img->stride[VPX_PLANE_V];
|
buf += img->stride[VPX_PLANE_V];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fn2)
|
if (!single_file)
|
||||||
out_close(out, out_fn, do_md5);
|
out_close(out, out_fn, do_md5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -892,15 +1018,14 @@ fail:
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn2)
|
if (single_file && !noblit)
|
||||||
out_close(out, fn2, do_md5);
|
out_close(out, outfile, do_md5);
|
||||||
|
|
||||||
if(input.nestegg_ctx)
|
if(input.nestegg_ctx)
|
||||||
nestegg_destroy(input.nestegg_ctx);
|
nestegg_destroy(input.nestegg_ctx);
|
||||||
if(input.kind != WEBM_FILE)
|
if(input.kind != WEBM_FILE)
|
||||||
free(buf);
|
free(buf);
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
free(prefix);
|
|
||||||
free(argv);
|
free(argv);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user