if(fwrite(header, 1, 12, outfile));
}
+static void write_ivf_frame_size(FILE *outfile, size_t size)
+{
+ char header[4];
+ mem_put_le32(header, size);
+ fwrite(header, 1, 4, outfile);
+}
+
typedef off_t EbmlLoc;
#include "args.h"
-
static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
"Debug mode (makes output deterministic)");
static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
"Stream frame rate (rate/scale)");
static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0,
"Output IVF (default is WebM)");
+static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
+ "Makes encoder output partitions. Requires IVF output!");
static const arg_def_t q_hist_n = ARG_DEF(NULL, "q-hist", 1,
"Show quantizer histogram (n-buckets)");
static const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1,
&debugmode,
&outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
&best_dl, &good_dl, &rt_dl,
- &verbosearg, &psnrarg, &use_ivf, &q_hist_n, &rate_hist_n,
+ &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
NULL
};
int show_psnr;
int have_framerate;
struct vpx_rational framerate;
+ int out_part;
int debug;
int show_q_hist_buckets;
int show_rate_hist_buckets;
int arg_ctrls[ARG_CTRL_CNT_MAX][2];
int arg_ctrl_cnt;
int write_webm;
+ int have_kf_max_dist;
};
};
+void validate_positive_rational(const char *msg,
+ struct vpx_rational *rat)
+{
+ if (rat->den < 0)
+ {
+ rat->num *= -1;
+ rat->den *= -1;
+ }
+
+ if (rat->num < 0)
+ die("Error: %s must be positive\n", msg);
+
+ if (!rat->den)
+ die("Error: %s has zero denominator\n", msg);
+}
+
+
static void parse_global_config(struct global_config *global, char **argv)
{
char **argi, **argj;
else if (arg_match(&arg, &framerate, argi))
{
global->framerate = arg_parse_rational(&arg);
+ validate_positive_rational(arg.name, &global->framerate);
global->have_framerate = 1;
}
+ else if (arg_match(&arg,&out_part, argi))
+ global->out_part = 1;
else if (arg_match(&arg, &debugmode, argi))
global->debug = 1;
else if (arg_match(&arg, &q_hist_n, argi))
stream->config.stereo_fmt = STEREO_FORMAT_MONO;
stream->config.write_webm = 1;
stream->ebml.last_pts_ms = -1;
+
+ /* Allows removal of the application version from the EBML tags */
+ stream->ebml.debug = global->debug;
}
/* Output files must be specified for each stream */
else if (arg_match(&arg, &stereo_mode, argi))
config->stereo_fmt = arg_parse_enum_or_int(&arg);
else if (arg_match(&arg, &timebase, argi))
+ {
config->cfg.g_timebase = arg_parse_rational(&arg);
+ validate_positive_rational(arg.name, &config->cfg.g_timebase);
+ }
else if (arg_match(&arg, &error_resilient, argi))
config->cfg.g_error_resilient = arg_parse_uint(&arg);
else if (arg_match(&arg, &lag_in_frames, argi))
else if (arg_match(&arg, &kf_min_dist, argi))
config->cfg.kf_min_dist = arg_parse_uint(&arg);
else if (arg_match(&arg, &kf_max_dist, argi))
+ {
config->cfg.kf_max_dist = arg_parse_uint(&arg);
+ config->have_kf_max_dist = 1;
+ }
else if (arg_match(&arg, &kf_disabled, argi))
config->cfg.kf_mode = VPX_KF_DISABLED;
else
}
+static void set_default_kf_interval(struct stream_state *stream,
+ struct global_config *global)
+{
+ /* Use a max keyframe interval of 5 seconds, if none was
+ * specified on the command line.
+ */
+ if (!stream->config.have_kf_max_dist)
+ {
+ double framerate = (double)global->framerate.num/global->framerate.den;
+ if (framerate > 0.0)
+ stream->config.cfg.kf_max_dist = 5.0*framerate;
+ }
+}
+
+
static void show_stream_config(struct stream_state *stream,
struct global_config *global,
struct input_state *input)
: VPX_RC_ONE_PASS;
if (pass)
stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
+
+ stream->cx_time = 0;
+ stream->nbytes = 0;
+ stream->frames_out = 0;
}
struct global_config *global)
{
int i;
+ int flags = 0;
+
+ flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
+ flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
/* Construct Encoder Context */
vpx_codec_enc_init(&stream->encoder, global->codec->iface,
- &stream->config.cfg,
- global->show_psnr ? VPX_CODEC_USE_PSNR : 0);
+ &stream->config.cfg, flags);
ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
/* Note that we bypass the vpx_codec_control wrapper macro because
while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter)))
{
+ static size_t fsize = 0;
+ static off_t ivf_header_pos = 0;
+
*got_data = 1;
switch (pkt->kind)
{
case VPX_CODEC_CX_FRAME_PKT:
- stream->frames_out++;
+ if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
+ {
+ stream->frames_out++;
+ }
fprintf(stderr, " %6luF",
(unsigned long)pkt->data.frame.sz);
}
else
{
- write_ivf_frame_header(stream->file, pkt);
- if(fwrite(pkt->data.frame.buf, 1,
- pkt->data.frame.sz, stream->file));
+ if (pkt->data.frame.partition_id <= 0)
+ {
+ ivf_header_pos = ftello(stream->file);
+ fsize = pkt->data.frame.sz;
+
+ write_ivf_frame_header(stream->file, pkt);
+ }
+ else
+ {
+ fsize += pkt->data.frame.sz;
+
+ if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
+ {
+ off_t currpos = ftello(stream->file);
+ fseeko(stream->file, ivf_header_pos, SEEK_SET);
+ write_ivf_frame_size(stream->file, fsize);
+ fseeko(stream->file, currpos, SEEK_SET);
+ }
+ }
+
+ fwrite(pkt->data.frame.buf, 1,
+ pkt->data.frame.sz, stream->file);
}
stream->nbytes += pkt->data.raw.sz;
break;
if (!global.have_framerate)
global.framerate = input.framerate;
+ FOREACH_STREAM(set_default_kf_interval(stream, &global));
+
/* Show configuration */
if (global.verbose && pass == 0)
FOREACH_STREAM(show_stream_config(stream, &global, &input));
fprintf(stderr,
"\rPass %d/%d frame %4d/%-4d %7"PRId64"B \033[K",
pass + 1, global.passes, frames_in,
- streams->frames_out, streams->nbytes);
+ streams->frames_out, (int64_t)streams->nbytes);
else
fprintf(stderr,
"\rPass %d/%d frame %4d %7lu %s (%.2f fps)\033[K",
FOREACH_STREAM(fprintf(
stderr,
"\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s"
- " %7lu %s (%.2f fps)\033[K\n", pass + 1,
- global.passes, frames_in, stream->frames_out, stream->nbytes,
+ " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1,
+ global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes,
frames_in ? (unsigned long)(stream->nbytes * 8 / frames_in) : 0,
- frames_in ? stream->nbytes * 8
+ frames_in ? (int64_t)stream->nbytes * 8
* (int64_t)global.framerate.num / global.framerate.den
/ frames_in
: 0,
vpx_img_free(&raw);
free(argv);
+ free(streams);
return EXIT_SUCCESS;
}