ivfenc: support reading/writing from a pipe
Use - for the filename to use stdin/stdout. Update to avoid opening the file multiple times. Change-Id: I356356fa16bb334d4b22abc531dc03c0d95917a3
This commit is contained in:
Родитель
db0f26c0e2
Коммит
3245d463c4
180
ivfenc.c
180
ivfenc.c
|
@ -55,8 +55,8 @@ void die(const char *fmt, ...)
|
|||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
printf("\n");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
usage_exit();
|
||||
}
|
||||
|
||||
|
@ -66,10 +66,10 @@ static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s)
|
|||
{
|
||||
const char *detail = vpx_codec_error_detail(ctx);
|
||||
|
||||
printf("%s: %s\n", s, vpx_codec_error(ctx));
|
||||
fprintf(stderr, "%s: %s\n", s, vpx_codec_error(ctx));
|
||||
|
||||
if (detail)
|
||||
printf(" %s\n", detail);
|
||||
fprintf(stderr, " %s\n", detail);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -226,9 +226,15 @@ enum video_file_type
|
|||
FILE_TYPE_Y4M
|
||||
};
|
||||
|
||||
struct detect_buffer {
|
||||
char buf[4];
|
||||
int valid;
|
||||
};
|
||||
|
||||
|
||||
#define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
|
||||
static int read_frame(FILE *f, vpx_image_t *img, unsigned int file_type,
|
||||
y4m_input *y4m)
|
||||
y4m_input *y4m, struct detect_buffer *detect)
|
||||
{
|
||||
int plane = 0;
|
||||
|
||||
|
@ -275,7 +281,15 @@ static int read_frame(FILE *f, vpx_image_t *img, unsigned int file_type,
|
|||
|
||||
for (r = 0; r < h; r++)
|
||||
{
|
||||
if (detect->valid)
|
||||
{
|
||||
memcpy(ptr, detect->buf, 4);
|
||||
fread(ptr+4, 1, w-4, f);
|
||||
detect->valid = 0;
|
||||
}
|
||||
else
|
||||
fread(ptr, 1, w, f);
|
||||
|
||||
ptr += img->stride[plane];
|
||||
}
|
||||
}
|
||||
|
@ -286,16 +300,14 @@ static int read_frame(FILE *f, vpx_image_t *img, unsigned int file_type,
|
|||
|
||||
|
||||
unsigned int file_is_y4m(FILE *infile,
|
||||
y4m_input *y4m)
|
||||
y4m_input *y4m,
|
||||
char detect[4])
|
||||
{
|
||||
char raw_hdr[4];
|
||||
if (fread(raw_hdr, 1, 4, infile) == 4 &&
|
||||
memcmp(raw_hdr, "YUV4", 4) == 0 &&
|
||||
y4m_input_open(y4m, infile, raw_hdr, 4) >= 0)
|
||||
if(memcmp(detect, "YUV4", 4) == 0 &&
|
||||
y4m_input_open(y4m, infile, detect, 4) >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
rewind(infile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -303,18 +315,21 @@ unsigned int file_is_y4m(FILE *infile,
|
|||
unsigned int file_is_ivf(FILE *infile,
|
||||
unsigned int *fourcc,
|
||||
unsigned int *width,
|
||||
unsigned int *height)
|
||||
unsigned int *height,
|
||||
char detect[4])
|
||||
{
|
||||
char raw_hdr[IVF_FILE_HDR_SZ];
|
||||
int is_ivf = 0;
|
||||
|
||||
if(memcmp(detect, "DKIF", 4) != 0)
|
||||
return 0;
|
||||
|
||||
/* See write_ivf_file_header() for more documentation on the file header
|
||||
* layout.
|
||||
*/
|
||||
if (fread(raw_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ)
|
||||
if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
|
||||
== IVF_FILE_HDR_SZ - 4)
|
||||
{
|
||||
if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K'
|
||||
&& raw_hdr[2] == 'I' && raw_hdr[3] == 'F')
|
||||
{
|
||||
is_ivf = 1;
|
||||
|
||||
|
@ -331,8 +346,6 @@ unsigned int file_is_ivf(FILE *infile,
|
|||
*width = mem_get_le16(raw_hdr + 12);
|
||||
*height = mem_get_le16(raw_hdr + 14);
|
||||
}
|
||||
else
|
||||
rewind(infile);
|
||||
|
||||
return is_ivf;
|
||||
}
|
||||
|
@ -546,28 +559,28 @@ static void usage_exit()
|
|||
{
|
||||
int i;
|
||||
|
||||
printf("Usage: %s <options> src_filename dst_filename\n", exec_name);
|
||||
fprintf(stderr, "Usage: %s <options> src_filename dst_filename\n", exec_name);
|
||||
|
||||
printf("\n_options:\n");
|
||||
fprintf(stderr, "\n_options:\n");
|
||||
arg_show_usage(stdout, main_args);
|
||||
printf("\n_encoder Global Options:\n");
|
||||
fprintf(stderr, "\n_encoder Global Options:\n");
|
||||
arg_show_usage(stdout, global_args);
|
||||
printf("\n_rate Control Options:\n");
|
||||
fprintf(stderr, "\n_rate Control Options:\n");
|
||||
arg_show_usage(stdout, rc_args);
|
||||
printf("\n_twopass Rate Control Options:\n");
|
||||
fprintf(stderr, "\n_twopass Rate Control Options:\n");
|
||||
arg_show_usage(stdout, rc_twopass_args);
|
||||
printf("\n_keyframe Placement Options:\n");
|
||||
fprintf(stderr, "\n_keyframe Placement Options:\n");
|
||||
arg_show_usage(stdout, kf_args);
|
||||
#if CONFIG_VP8_ENCODER
|
||||
printf("\n_vp8 Specific Options:\n");
|
||||
fprintf(stderr, "\n_vp8 Specific Options:\n");
|
||||
arg_show_usage(stdout, vp8_args);
|
||||
#endif
|
||||
printf("\n"
|
||||
fprintf(stderr, "\n"
|
||||
"Included encoders:\n"
|
||||
"\n");
|
||||
|
||||
for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
|
||||
printf(" %-6s - %s\n",
|
||||
fprintf(stderr, " %-6s - %s\n",
|
||||
codecs[i].name,
|
||||
vpx_codec_iface_name(codecs[i].iface));
|
||||
|
||||
|
@ -687,7 +700,7 @@ int main(int argc, const char **argv_)
|
|||
/* DWIM: Assume the user meant passes=2 if pass=2 is specified */
|
||||
if (one_pass_only > arg_passes)
|
||||
{
|
||||
printf("Warning: Assuming --pass=%d implies --passes=%d\n",
|
||||
fprintf(stderr, "Warning: Assuming --pass=%d implies --passes=%d\n",
|
||||
one_pass_only, one_pass_only);
|
||||
arg_passes = one_pass_only;
|
||||
}
|
||||
|
@ -701,7 +714,8 @@ int main(int argc, const char **argv_)
|
|||
|
||||
if (res)
|
||||
{
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
fprintf(stderr, "Failed to get config: %s\n",
|
||||
vpx_codec_err_to_string(res));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -761,7 +775,8 @@ int main(int argc, const char **argv_)
|
|||
cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
|
||||
|
||||
if (arg_passes < 2)
|
||||
printf("Warning: option %s ignored in one-pass mode.\n",
|
||||
fprintf(stderr,
|
||||
"Warning: option %s ignored in one-pass mode.\n",
|
||||
arg.name);
|
||||
}
|
||||
else if (arg_match(&arg, &minsection_pct, argi))
|
||||
|
@ -769,7 +784,8 @@ int main(int argc, const char **argv_)
|
|||
cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
|
||||
|
||||
if (arg_passes < 2)
|
||||
printf("Warning: option %s ignored in one-pass mode.\n",
|
||||
fprintf(stderr,
|
||||
"Warning: option %s ignored in one-pass mode.\n",
|
||||
arg.name);
|
||||
}
|
||||
else if (arg_match(&arg, &maxsection_pct, argi))
|
||||
|
@ -777,7 +793,8 @@ int main(int argc, const char **argv_)
|
|||
cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
|
||||
|
||||
if (arg_passes < 2)
|
||||
printf("Warning: option %s ignored in one-pass mode.\n",
|
||||
fprintf(stderr,
|
||||
"Warning: option %s ignored in one-pass mode.\n",
|
||||
arg.name);
|
||||
}
|
||||
else if (arg_match(&arg, &kf_min_dist, argi))
|
||||
|
@ -826,7 +843,7 @@ int main(int argc, const char **argv_)
|
|||
|
||||
/* Check for unrecognized options */
|
||||
for (argi = argv; *argi; argi++)
|
||||
if (argi[0][0] == '-')
|
||||
if (argi[0][0] == '-' && argi[0][1])
|
||||
die("Error: Unrecognized option %s\n", *argi);
|
||||
|
||||
/* Handle non-option arguments */
|
||||
|
@ -836,16 +853,27 @@ int main(int argc, const char **argv_)
|
|||
if (!in_fn || !out_fn)
|
||||
usage_exit();
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
for (pass = one_pass_only ? one_pass_only - 1 : 0; pass < arg_passes; pass++)
|
||||
{
|
||||
int frames_in = 0, frames_out = 0;
|
||||
unsigned long nbytes = 0;
|
||||
struct detect_buffer detect;
|
||||
|
||||
/* Parse certain options from the input file, if possible */
|
||||
infile = fopen(in_fn, "rb");
|
||||
infile = strcmp(in_fn, "-") ? fopen(in_fn, "rb") : stdin;
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
printf("Failed to open input file");
|
||||
fprintf(stderr, "Failed to open input file\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (file_is_y4m(infile, &y4m))
|
||||
fread(detect.buf, 1, 4, infile);
|
||||
detect.valid = 0;
|
||||
|
||||
if (file_is_y4m(infile, &y4m, detect.buf))
|
||||
{
|
||||
file_type = FILE_TYPE_Y4M;
|
||||
cfg.g_w = y4m.pic_w;
|
||||
|
@ -860,7 +888,7 @@ int main(int argc, const char **argv_)
|
|||
}
|
||||
arg_use_i420 = 0;
|
||||
}
|
||||
else if (file_is_ivf(infile, &fourcc, &cfg.g_w, &cfg.g_h))
|
||||
else if (file_is_ivf(infile, &fourcc, &cfg.g_w, &cfg.g_h, detect.buf))
|
||||
{
|
||||
file_type = FILE_TYPE_IVF;
|
||||
switch (fourcc)
|
||||
|
@ -872,24 +900,24 @@ int main(int argc, const char **argv_)
|
|||
arg_use_i420 = 1;
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported fourcc (%08x) in IVF\n", fourcc);
|
||||
fprintf(stderr, "Unsupported fourcc (%08x) in IVF\n", fourcc);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
file_type = FILE_TYPE_RAW;
|
||||
|
||||
fclose(infile);
|
||||
|
||||
|
||||
#define SHOW(field) printf(" %-28s = %d\n", #field, cfg.field)
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
printf("Codec: %s\n", vpx_codec_iface_name(codec->iface));
|
||||
printf("Source file: %s Format: %s\n", in_fn, arg_use_i420 ? "I420" : "YV12");
|
||||
printf("Destination file: %s\n", out_fn);
|
||||
printf("Encoder parameters:\n");
|
||||
file_type = FILE_TYPE_RAW;
|
||||
detect.valid = 1;
|
||||
}
|
||||
#define SHOW(field) fprintf(stderr, " %-28s = %d\n", #field, cfg.field)
|
||||
|
||||
if (verbose && pass == 0)
|
||||
{
|
||||
fprintf(stderr, "Codec: %s\n", vpx_codec_iface_name(codec->iface));
|
||||
fprintf(stderr, "Source file: %s Format: %s\n", in_fn,
|
||||
arg_use_i420 ? "I420" : "YV12");
|
||||
fprintf(stderr, "Destination file: %s\n", out_fn);
|
||||
fprintf(stderr, "Encoder parameters:\n");
|
||||
|
||||
SHOW(g_usage);
|
||||
SHOW(g_threads);
|
||||
|
@ -922,6 +950,7 @@ int main(int argc, const char **argv_)
|
|||
SHOW(kf_max_dist);
|
||||
}
|
||||
|
||||
if(pass == 0) {
|
||||
if (file_type == FILE_TYPE_Y4M)
|
||||
/*The Y4M reader does its own allocation.
|
||||
Just initialize this here to avoid problems if we never read any
|
||||
|
@ -937,39 +966,13 @@ int main(int argc, const char **argv_)
|
|||
// only be 1 alt-ref frame ( current bitstream) multiplying by 2
|
||||
// gives us enough room.
|
||||
cfg.g_timebase.den *= 2;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
for (pass = one_pass_only ? one_pass_only - 1 : 0; pass < arg_passes; pass++)
|
||||
{
|
||||
int frames_in = 0, frames_out = 0;
|
||||
unsigned long nbytes = 0;
|
||||
|
||||
infile = fopen(in_fn, "rb");
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
printf("Failed to open input file");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/*Skip the file header.*/
|
||||
if (file_type == FILE_TYPE_IVF)
|
||||
{
|
||||
char raw_hdr[IVF_FILE_HDR_SZ];
|
||||
(void)fread(raw_hdr, 1, IVF_FILE_HDR_SZ, infile);
|
||||
}
|
||||
else if(file_type == FILE_TYPE_Y4M)
|
||||
{
|
||||
char buffer[80];
|
||||
(void)fgets(buffer, sizeof(buffer)/sizeof(*buffer) - 1, infile);
|
||||
}
|
||||
|
||||
outfile = fopen(out_fn, "wb");
|
||||
outfile = strcmp(out_fn, "-") ? fopen(out_fn, "wb") : stdout;
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
printf("Failed to open output file");
|
||||
fprintf(stderr, "Failed to open output file\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -977,7 +980,7 @@ int main(int argc, const char **argv_)
|
|||
{
|
||||
if (!stats_open_file(&stats, stats_fn, pass))
|
||||
{
|
||||
printf("Failed to open statistics store\n");
|
||||
fprintf(stderr, "Failed to open statistics store\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -985,7 +988,7 @@ int main(int argc, const char **argv_)
|
|||
{
|
||||
if (!stats_open_mem(&stats, pass))
|
||||
{
|
||||
printf("Failed to open statistics store\n");
|
||||
fprintf(stderr, "Failed to open statistics store\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -1020,7 +1023,7 @@ int main(int argc, const char **argv_)
|
|||
for (i = 0; i < arg_ctrl_cnt; i++)
|
||||
{
|
||||
if (vpx_codec_control_(&encoder, arg_ctrls[i][0], arg_ctrls[i][1]))
|
||||
printf("Error: Tried to set control %d = %d\n",
|
||||
fprintf(stderr, "Error: Tried to set control %d = %d\n",
|
||||
arg_ctrls[i][0], arg_ctrls[i][1]);
|
||||
|
||||
ctx_exit_on_error(&encoder, "Failed to control codec");
|
||||
|
@ -1037,12 +1040,14 @@ int main(int argc, const char **argv_)
|
|||
|
||||
if (!arg_limit || frames_in < arg_limit)
|
||||
{
|
||||
frame_avail = read_frame(infile, &raw, file_type, &y4m);
|
||||
frame_avail = read_frame(infile, &raw, file_type, &y4m,
|
||||
&detect);
|
||||
|
||||
if (frame_avail)
|
||||
frames_in++;
|
||||
|
||||
printf("\rPass %d/%d frame %4d/%-4d %7ldB \033[K", pass + 1,
|
||||
fprintf(stderr,
|
||||
"\rPass %d/%d frame %4d/%-4d %7ldB \033[K", pass + 1,
|
||||
arg_passes, frames_in, frames_out, nbytes);
|
||||
}
|
||||
else
|
||||
|
@ -1067,7 +1072,7 @@ int main(int argc, const char **argv_)
|
|||
{
|
||||
case VPX_CODEC_CX_FRAME_PKT:
|
||||
frames_out++;
|
||||
printf(" %6luF",
|
||||
fprintf(stderr, " %6luF",
|
||||
(unsigned long)pkt->data.frame.sz);
|
||||
write_ivf_frame_header(outfile, pkt);
|
||||
fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile);
|
||||
|
@ -1075,7 +1080,7 @@ int main(int argc, const char **argv_)
|
|||
break;
|
||||
case VPX_CODEC_STATS_PKT:
|
||||
frames_out++;
|
||||
printf(" %6luS",
|
||||
fprintf(stderr, " %6luS",
|
||||
(unsigned long)pkt->data.twopass_stats.sz);
|
||||
stats_write(&stats,
|
||||
pkt->data.twopass_stats.buf,
|
||||
|
@ -1089,7 +1094,7 @@ int main(int argc, const char **argv_)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%.3lf ", pkt->data.psnr.psnr[i]);
|
||||
fprintf(stderr, "%.3lf ", pkt->data.psnr.psnr[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1104,7 +1109,8 @@ int main(int argc, const char **argv_)
|
|||
/* this bitrate calc is simplified and relies on the fact that this
|
||||
* application uses 1/timebase for framerate.
|
||||
*/
|
||||
printf("\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
|
||||
fprintf(stderr,
|
||||
"\rPass %d/%d frame %4d/%-4d %7ldB %7ldb/f %7"PRId64"b/s"
|
||||
" %7lu %s (%.2f fps)\033[K", pass + 1,
|
||||
arg_passes, frames_in, frames_out, nbytes, nbytes * 8 / frames_in,
|
||||
nbytes * 8 *(int64_t)cfg.g_timebase.den/2/ cfg.g_timebase.num / frames_in,
|
||||
|
@ -1121,7 +1127,7 @@ int main(int argc, const char **argv_)
|
|||
|
||||
fclose(outfile);
|
||||
stats_close(&stats);
|
||||
printf("\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if (one_pass_only)
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче