Newer
Older
st = ost->st;
subtitle_enc = st->codec;
Fabrice Bellard
committed
subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc, st);
/* arg format is "output-stream-index:streamid-value". */
static int opt_streamid(OptionsContext *o, const char *opt, const char *arg)
{
int idx;
char *p;
char idx_str[16];
av_strlcpy(idx_str, arg, sizeof(idx_str));
p = strchr(idx_str, ':');
if (!p) {
av_log(NULL, AV_LOG_FATAL,
"Invalid value '%s' for option '%s', required syntax is 'index:value'\n",
arg, opt);
}
*p++ = '\0';
idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1);
o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
Aurelien Jacobs
committed
return 0;
static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
AVFormatContext *is = ifile->ctx;
AVFormatContext *os = ofile->ctx;
int i;
for (i = 0; i < is->nb_chapters; i++) {
AVChapter *in_ch = is->chapters[i], *out_ch;
int64_t ts_off = av_rescale_q(ofile->start_time - ifile->ts_offset,
AV_TIME_BASE_Q, in_ch->time_base);
int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX :
av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base);
if (in_ch->end < ts_off)
continue;
if (rt != INT64_MAX && in_ch->start > rt + ts_off)
break;
out_ch = av_mallocz(sizeof(AVChapter));
if (!out_ch)
return AVERROR(ENOMEM);
out_ch->id = in_ch->id;
out_ch->time_base = in_ch->time_base;
out_ch->start = FFMAX(0, in_ch->start - ts_off);
out_ch->end = FFMIN(rt, in_ch->end - ts_off);
av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
os->nb_chapters++;
os->chapters = av_realloc_f(os->chapters, os->nb_chapters, sizeof(AVChapter));
if (!os->chapters)
return AVERROR(ENOMEM);
os->chapters[os->nb_chapters - 1] = out_ch;
}
return 0;
}
static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
{
int i, err;
AVFormatContext *ic = avformat_alloc_context();
ic->interrupt_callback = int_cb;
err = avformat_open_input(&ic, filename, NULL, NULL);
if (err < 0)
return err;
/* copy stream format */
for(i=0;i<ic->nb_streams;i++) {
AVStream *st;
OutputStream *ost;
AVCodec *codec;
AVCodecContext *avctx;
codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
ost = new_output_stream(o, s, codec->type, -1);
ost->enc = codec;
// FIXME: a more elegant solution is needed
memcpy(st, ic->streams[i], sizeof(AVStream));
st->cur_dts = 0;
st->info = av_malloc(sizeof(*st->info));
memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
avcodec_copy_context(st->codec, ic->streams[i]->codec);
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
choose_sample_fmt(st, codec);
else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
choose_pixel_fmt(st, codec, st->codec->pix_fmt);
avformat_close_input(&ic);
return 0;
}
static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
AVFormatContext *oc)
{
OutputStream *ost;
switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
ofilter->out_tmp->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break;
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break;
default:
av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported "
"currently.\n");
exit_program(1);
}
ost->source_index = -1;
ost->filter = ofilter;
ofilter->ost = ost;
if (ost->stream_copy) {
av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, "
"which is fed from a complex filtergraph. Filtering and streamcopy "
"cannot be used together.\n", ost->file_index, ost->index);
exit_program(1);
}
if (o->recording_time != INT64_MAX)
av_log(NULL, AV_LOG_WARNING,
"-t does not work with -filter_complex (yet).\n");
if (configure_output_filter(ofilter->graph, ofilter, ofilter->out_tmp) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error configuring filter.\n");
exit_program(1);
}
avfilter_inout_free(&ofilter->out_tmp);
}
static void opt_output_file(void *optctx, const char *filename)
Fabrice Bellard
committed
{
OptionsContext *o = optctx;
Fabrice Bellard
committed
AVFormatContext *oc;
AVOutputFormat *file_oformat;
OutputStream *ost;
InputStream *ist;
if (configure_complex_filters() < 0) {
av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
exit_program(1);
}
err = avformat_alloc_output_context2(&oc, NULL, o->format, filename);
Stefano Sabatini
committed
print_error(filename, err);
file_oformat= oc->oformat;
oc->interrupt_callback = int_cb;
/* create streams for all unlabeled output pads */
for (i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg = filtergraphs[i];
for (j = 0; j < fg->nb_outputs; j++) {
OutputFilter *ofilter = fg->outputs[j];
if (!ofilter->out_tmp || ofilter->out_tmp->name)
continue;
switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
ofilter->out_tmp->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break;
case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break;
case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
}
init_output_filter(ofilter, o, oc);
}
}
if (!strcmp(file_oformat->name, "ffm") &&
av_strstart(filename, "http:", NULL)) {
Michael Niedermayer
committed
int j;
/* special case for files sent to ffserver: we get the stream
parameters from ffserver */
int err = read_ffserver_streams(o, oc, filename);
if (err < 0) {
print_error(filename, err);
Michael Niedermayer
committed
for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
ost = output_streams[j];
Michael Niedermayer
committed
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
Michael Niedermayer
committed
if(ist->st->codec->codec_type == ost->st->codec->codec_type){
ost->sync_ist= ist;
ost->source_index= i;
if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
Michael Niedermayer
committed
ist->discard = 0;
ist->st->discard = AVDISCARD_NONE;
Michael Niedermayer
committed
break;
}
}
Michael Niedermayer
committed
if(!ost->sync_ist){
av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type));
exit_program(1);
}
Michael Niedermayer
committed
}
} else if (!o->nb_stream_maps) {
/* pick the "best" stream of each type */
/* video: highest resolution */
if (!o->video_disable && oc->oformat->video_codec != CODEC_ID_NONE) {
int area = 0, idx = -1;
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
ist->st->codec->width * ist->st->codec->height > area) {
area = ist->st->codec->width * ist->st->codec->height;
idx = i;
}
}
if (idx >= 0)
new_video_stream(o, oc, idx);
}
/* audio: most channels */
if (!o->audio_disable && oc->oformat->audio_codec != CODEC_ID_NONE) {
int channels = 0, idx = -1;
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
ist->st->codec->channels > channels) {
channels = ist->st->codec->channels;
idx = i;
}
}
if (idx >= 0)
new_audio_stream(o, oc, idx);
}
/* subtitles: pick first */
if (!o->subtitle_disable && (oc->oformat->subtitle_codec != CODEC_ID_NONE || subtitle_codec_name)) {
for (i = 0; i < nb_input_streams; i++)
if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
new_subtitle_stream(o, oc, i);
break;
}
}
/* do something with data? */
for (i = 0; i < o->nb_stream_maps; i++) {
StreamMap *map = &o->stream_maps[i];
int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
if (map->linklabel) {
FilterGraph *fg;
OutputFilter *ofilter = NULL;
int j, k;
for (j = 0; j < nb_filtergraphs; j++) {
fg = filtergraphs[j];
for (k = 0; k < fg->nb_outputs; k++) {
AVFilterInOut *out = fg->outputs[k]->out_tmp;
if (out && !strcmp(out->name, map->linklabel)) {
ofilter = fg->outputs[k];
goto loop_end;
}
}
}
loop_end:
if (!ofilter) {
av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist "
"in any defined filter graph.\n", map->linklabel);
exit_program(1);
}
init_output_filter(ofilter, o, oc);
} else {
ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
continue;
if(o-> audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
continue;
if(o-> video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
continue;
if(o-> data_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_DATA)
continue;
case AVMEDIA_TYPE_VIDEO: ost = new_video_stream (o, oc, src_idx); break;
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream (o, oc, src_idx); break;
case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream (o, oc, src_idx); break;
case AVMEDIA_TYPE_DATA: ost = new_data_stream (o, oc, src_idx); break;
case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc, src_idx); break;
default:
av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n",
for (i = nb_output_streams - oc->nb_streams; i < nb_output_streams; i++) { //for all streams of this output file
AVDictionaryEntry *e;
ost = output_streams[i];
if ( ost->stream_copy
&& (e = av_dict_get(codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX))
&& (!e->key[5] || check_stream_specifier(oc, ost->st, e->key+6)))
if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0)
exit_program(1);
}
/* handle attached files */
for (i = 0; i < o->nb_attachments; i++) {
AVIOContext *pb;
uint8_t *attachment;
const char *p;
int64_t len;
if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) {
av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n",
o->attachments[i]);
exit_program(1);
if ((len = avio_size(pb)) <= 0) {
av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n",
o->attachments[i]);
exit_program(1);
}
if (!(attachment = av_malloc(len))) {
av_log(NULL, AV_LOG_FATAL, "Attachment %s too large to fit into memory.\n",
o->attachments[i]);
exit_program(1);
}
avio_read(pb, attachment, len);
ost = new_attachment_stream(o, oc, -1);
ost->stream_copy = 0;
ost->attachment_filename = o->attachments[i];
ost->st->codec->extradata = attachment;
ost->st->codec->extradata_size = len;
p = strrchr(o->attachments[i], '/');
av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
avio_close(pb);
Anton Khirnov
committed
output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1);
if (!(output_files[nb_output_files - 1] = av_mallocz(sizeof(*output_files[0]))))
exit_program(1);
output_files[nb_output_files - 1]->ctx = oc;
output_files[nb_output_files - 1]->ost_index = nb_output_streams - oc->nb_streams;
output_files[nb_output_files - 1]->recording_time = o->recording_time;
if (o->recording_time != INT64_MAX)
oc->duration = o->recording_time;
output_files[nb_output_files - 1]->start_time = o->start_time;
output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize;
av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0);
Fabrice Bellard
committed
/* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
Michel Bardiaux
committed
if (!av_filename_number_test(oc->filename)) {
print_error(oc->filename, AVERROR(EINVAL));
Fabrice Bellard
committed
}
if (!(oc->oformat->flags & AVFMT_NOFILE)) {
/* test if it already exists to avoid losing precious files */
assert_file_overwrite(filename);
if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
&oc->interrupt_callback,
&output_files[nb_output_files - 1]->opts)) < 0) {
print_error(filename, err);
if (o->mux_preload) {
uint8_t buf[64];
snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
av_dict_set(&output_files[nb_output_files - 1]->opts, "preload", buf, 0);
oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
/* copy metadata */
for (i = 0; i < o->nb_metadata_map; i++) {
char *p;
int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0);
if (in_file_index >= nb_input_files) {
av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
exit_program(1);
}
copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, o);
/* copy chapters */
if (o->chapters_input_file >= nb_input_files) {
if (o->chapters_input_file == INT_MAX) {
/* copy chapters from the first input file that has them*/
o->chapters_input_file = -1;
for (i = 0; i < nb_input_files; i++)
if (input_files[i]->ctx->nb_chapters) {
o->chapters_input_file = i;
break;
}
} else {
av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n",
o->chapters_input_file);
exit_program(1);
}
}
if (o->chapters_input_file >= 0)
copy_chapters(input_files[o->chapters_input_file], output_files[nb_output_files - 1],
!o->metadata_chapters_manual);
/* copy global metadata by default */
if (!o->metadata_global_manual && nb_input_files){
av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
AV_DICT_DONT_OVERWRITE);
if(o->recording_time != INT64_MAX)
av_dict_set(&oc->metadata, "duration", NULL, 0);
Michael Niedermayer
committed
av_dict_set(&oc->metadata, "creation_time", NULL, 0);
if (!o->metadata_streams_manual)
for (i = output_files[nb_output_files - 1]->ost_index; i < nb_output_streams; i++) {
if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */
ist = input_streams[output_streams[i]->source_index];
av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
}
/* process manually set metadata */
for (i = 0; i < o->nb_metadata; i++) {
AVDictionary **m;
char type, *val;
const char *stream_spec;
int index = 0, j, ret = 0;
val = strchr(o->metadata[i].u.str, '=');
if (!val) {
av_log(NULL, AV_LOG_FATAL, "No '=' character in metadata string %s.\n",
o->metadata[i].u.str);
exit_program(1);
}
*val++ = 0;
parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec);
if (type == 's') {
for (j = 0; j < oc->nb_streams; j++) {
if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) {
av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0);
} else if (ret < 0)
exit_program(1);
}
else {
switch (type) {
case 'g':
m = &oc->metadata;
break;
case 'c':
if (index < 0 || index >= oc->nb_chapters) {
av_log(NULL, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index);
exit_program(1);
}
m = &oc->chapters[index]->metadata;
break;
default:
av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier);
exit_program(1);
}
av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0);
reset_options(o, 0);
/* same option as mencoder */
static int opt_pass(const char *opt, const char *arg)
do_pass = parse_number_or_die(opt, arg, OPT_INT, 1, 3);
static int64_t getmaxrss(void)
{
#if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (int64_t)rusage.ru_maxrss * 1024;
#elif HAVE_GETPROCESSMEMORYINFO
HANDLE proc;
PROCESS_MEMORY_COUNTERS memcounters;
proc = GetCurrentProcess();
memcounters.cb = sizeof(memcounters);
GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters));
return memcounters.PeakPagefileUsage;
#else
return 0;
#endif
}
static int opt_audio_qscale(OptionsContext *o, const char *opt, const char *arg)
Vidar Madsen
committed
{
return parse_option(o, "q:a", arg, options);
Vidar Madsen
committed
}
av_log(NULL, AV_LOG_INFO, "Hyper fast Audio and Video encoder\n");
av_log(NULL, AV_LOG_INFO, "usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
av_log(NULL, AV_LOG_INFO, "\n");
Jeff Downs
committed
static int opt_help(const char *opt, const char *arg)
int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
av_log_set_callback(log_callback_help);
show_usage();
show_help_options(options, "Main options:\n",
Stefano Sabatini
committed
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, 0);
show_help_options(options, "\nAdvanced options:\n",
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB,
OPT_EXPERT);
show_help_options(options, "\nVideo options:\n",
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
OPT_VIDEO);
show_help_options(options, "\nAdvanced Video options:\n",
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
OPT_VIDEO | OPT_EXPERT);
show_help_options(options, "\nAudio options:\n",
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
OPT_AUDIO);
show_help_options(options, "\nAdvanced Audio options:\n",
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
OPT_AUDIO | OPT_EXPERT);
show_help_options(options, "\nSubtitle options:\n",
OPT_SUBTITLE | OPT_GRAB,
OPT_SUBTITLE);
show_help_options(options, "\nAudio/Video grab options:\n",
OPT_GRAB,
OPT_GRAB);
printf("\n");
show_help_children(avcodec_get_class(), flags);
show_help_children(avformat_get_class(), flags);
show_help_children(sws_get_class(), flags);
show_help_children(swr_get_class(), AV_OPT_FLAG_AUDIO_PARAM);
Jeff Downs
committed
return 0;
static int opt_target(OptionsContext *o, const char *opt, const char *arg)
Stefano Sabatini
committed
enum { PAL, NTSC, FILM, UNKNOWN } norm = UNKNOWN;
static const char *const frame_rates[] = { "25", "30000/1001", "24000/1001" };
if (!strncmp(arg, "pal-", 4)) {
Stefano Sabatini
committed
norm = PAL;
arg += 4;
} else if (!strncmp(arg, "ntsc-", 5)) {
Stefano Sabatini
committed
norm = NTSC;
arg += 5;
} else if (!strncmp(arg, "film-", 5)) {
Stefano Sabatini
committed
norm = FILM;
arg += 5;
} else {
/* Try to determine PAL/NTSC by peeking in the input files */
if (nb_input_files) {
int i, j, fr;
for (j = 0; j < nb_input_files; j++) {
for (i = 0; i < input_files[j]->nb_streams; i++) {
AVCodecContext *c = input_files[j]->ctx->streams[i]->codec;
if (c->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
fr = c->time_base.den * 1000 / c->time_base.num;
} else if ((fr == 29970) || (fr == 23976)) {
}
}
if (norm != UNKNOWN)
av_log(NULL, AV_LOG_INFO, "Assuming %s for target.\n", norm == PAL ? "PAL" : "NTSC");
if (norm == UNKNOWN) {
av_log(NULL, AV_LOG_FATAL, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
av_log(NULL, AV_LOG_FATAL, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
av_log(NULL, AV_LOG_FATAL, "or set a framerate with \"-r xxx\".\n");
if (!strcmp(arg, "vcd")) {
opt_video_codec(o, "c:v", "mpeg1video");
opt_audio_codec(o, "c:a", "mp2");
parse_option(o, "f", "vcd", options);
parse_option(o, "s", norm == PAL ? "352x288" : "352x240", options);
parse_option(o, "r", frame_rates[norm], options);
opt_default("g", norm == PAL ? "15" : "18");
opt_default("b:v", "1150000");
Panagiotis Issaris
committed
opt_default("maxrate", "1150000");
opt_default("minrate", "1150000");
Panagiotis Issaris
committed
opt_default("bufsize", "327680"); // 40*1024*8;
parse_option(o, "ar", "44100", options);
parse_option(o, "ac", "2", options);
opt_default("packetsize", "2324");
opt_default("muxrate", "1411200"); // 2352 * 75 * 8;
/* We have to offset the PTS, so that it is consistent with the SCR.
SCR starts at 36000, but the first two packs contain only padding
and the first pack from the other stream, respectively, may also have
been written before.
So the real data starts at SCR 36000+3*1200. */
o->mux_preload = (36000 + 3 * 1200) / 90000.0; // 0.44
} else if (!strcmp(arg, "svcd")) {
opt_video_codec(o, "c:v", "mpeg2video");
opt_audio_codec(o, "c:a", "mp2");
parse_option(o, "f", "svcd", options);
parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options);
parse_option(o, "r", frame_rates[norm], options);
parse_option(o, "pix_fmt", "yuv420p", options);
opt_default("g", norm == PAL ? "15" : "18");
opt_default("b:v", "2040000");
Panagiotis Issaris
committed
opt_default("maxrate", "2516000");
opt_default("minrate", "0"); // 1145000;
opt_default("bufsize", "1835008"); // 224*1024*8;
parse_option(o, "ar", "44100", options);
opt_default("packetsize", "2324");
} else if (!strcmp(arg, "dvd")) {
opt_video_codec(o, "c:v", "mpeg2video");
opt_audio_codec(o, "c:a", "ac3");
parse_option(o, "f", "dvd", options);
parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
parse_option(o, "r", frame_rates[norm], options);
parse_option(o, "pix_fmt", "yuv420p", options);
opt_default("g", norm == PAL ? "15" : "18");
opt_default("b:v", "6000000");
Panagiotis Issaris
committed
opt_default("maxrate", "9000000");
opt_default("minrate", "0"); // 1500000;
opt_default("bufsize", "1835008"); // 224*1024*8;
opt_default("packetsize", "2048"); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
opt_default("muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
Michael Niedermayer
committed
parse_option(o, "ar", "48000", options);
} else if (!strncmp(arg, "dv", 2)) {
Panagiotis Issaris
committed
parse_option(o, "f", "dv", options);
Panagiotis Issaris
committed
parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
parse_option(o, "pix_fmt", !strncmp(arg, "dv50", 4) ? "yuv422p" :
norm == PAL ? "yuv420p" : "yuv411p", options);
parse_option(o, "r", frame_rates[norm], options);
Panagiotis Issaris
committed
parse_option(o, "ar", "48000", options);
parse_option(o, "ac", "2", options);
Panagiotis Issaris
committed
} else {
av_log(NULL, AV_LOG_ERROR, "Unknown target: %s\n", arg);
static int opt_vstats_file(const char *opt, const char *arg)
{
av_free (vstats_filename);
vstats_filename = av_strdup (arg);
static int opt_vstats(const char *opt, const char *arg)
{
char filename[40];
time_t today2 = time(NULL);
struct tm *today = localtime(&today2);
snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min,
today->tm_sec);
static int opt_video_frames(OptionsContext *o, const char *opt, const char *arg)
Michael Niedermayer
committed
{
return parse_option(o, "frames:v", arg, options);
}
Michael Niedermayer
committed
static int opt_audio_frames(OptionsContext *o, const char *opt, const char *arg)
{
return parse_option(o, "frames:a", arg, options);
}
static int opt_data_frames(OptionsContext *o, const char *opt, const char *arg)
{
return parse_option(o, "frames:d", arg, options);
Michael Niedermayer
committed
}
static int opt_preset(OptionsContext *o, const char *opt, const char *arg)
Michael Niedermayer
committed
{
FILE *f=NULL;
char filename[1000], line[1000], tmp_line[1000];
const char *codec_name = *opt == 'v' ? video_codec_name :
*opt == 'a' ? audio_codec_name :
subtitle_codec_name;
Michael Niedermayer
committed
if (!(f = get_preset_file(filename, sizeof(filename), arg, *opt == 'f', codec_name))) {
if(!strncmp(arg, "libx264-lossless", strlen("libx264-lossless"))){
av_log(NULL, AV_LOG_FATAL, "Please use -preset <speed> -qp 0\n");
}else
av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg);
Michael Niedermayer
committed
exit_program(1);
}
while (fgets(line, sizeof(line), f)) {
char *key = tmp_line, *value, *endptr;
if (strcspn(line, "#\n\r") == 0)
Michael Niedermayer
committed
continue;
strcpy(tmp_line, line);
if (!av_strtok(key, "=", &value) ||
!av_strtok(value, "\r\n", &endptr)) {
av_log(NULL, AV_LOG_FATAL, "%s: Invalid syntax: '%s'\n", filename, line);
Michael Niedermayer
committed
exit_program(1);
}
av_log(NULL, AV_LOG_DEBUG, "ffpreset[%s]: set '%s' = '%s'\n", filename, key, value);
if (!strcmp(key, "acodec")) opt_audio_codec (o, key, value);
else if (!strcmp(key, "vcodec")) opt_video_codec (o, key, value);
else if (!strcmp(key, "scodec")) opt_subtitle_codec(o, key, value);
else if (!strcmp(key, "dcodec")) opt_data_codec (o, key, value);
else if (opt_default(key, value) < 0) {
av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n",
filename, line, key, value);
Michael Niedermayer
committed
exit_program(1);
}
}
fclose(f);
return 0;
}
static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
{
}
Jeff Downs
committed
static int opt_passlogfile(const char *opt, const char *arg)
{
pass_logfilename_prefix = arg;
return opt_default(opt, arg);
}
static int opt_old2new(OptionsContext *o, const char *opt, const char *arg)
{
char *s = av_asprintf("%s:%c", opt + 1, *opt);
int ret = parse_option(o, s, arg, options);
av_free(s);
static int opt_bitrate(OptionsContext *o, const char *opt, const char *arg)
{
if(!strcmp(opt, "b")){
av_log(NULL, AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n");
return parse_option(o, "b:v", arg, options);
}
return opt_default(opt, arg);
}
static int opt_qscale(OptionsContext *o, const char *opt, const char *arg)
{
char *s;
int ret;
if(!strcmp(opt, "qscale")){
av_log(NULL, AV_LOG_WARNING, "Please use -q:a or -q:v, -qscale is ambiguous\n");
return parse_option(o, "q:v", arg, options);
}
s = av_asprintf("q%s", opt + 6);
ret = parse_option(o, s, arg, options);
av_free(s);
return ret;
}
static int opt_profile(OptionsContext *o, const char *opt, const char *arg)
{
if(!strcmp(opt, "profile")){
av_log(NULL, AV_LOG_WARNING, "Please use -profile:a or -profile:v, -profile is ambiguous\n");
return parse_option(o, "profile:v", arg, options);
}
return opt_default(opt, arg);
}
static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg)
{
return parse_option(o, "filter:v", arg, options);
}
static int opt_audio_filters(OptionsContext *o, const char *opt, const char *arg)
{
return parse_option(o, "filter:a", arg, options);
}
static int opt_vsync(const char *opt, const char *arg)
{
if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR;
else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR;
else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH;
else if (!av_strcasecmp(arg, "drop")) video_sync_method = VSYNC_DROP;
if (video_sync_method == VSYNC_AUTO)
video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR);
return 0;
}
static int opt_deinterlace(const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -filter:v yadif instead\n", opt);
do_deinterlace = 1;
return 0;
}
static int opt_timecode(OptionsContext *o, const char *opt, const char *arg)
{
char *tcr = av_asprintf("timecode=%s", arg);
int ret = parse_option(o, "metadata:g", tcr, options);
if (ret >= 0)
ret = opt_default("gop_timecode", arg);
av_free(tcr);
return ret;
}
static void parse_cpuflags(int argc, char **argv, const OptionDef *options)
{
int idx = locate_option(argc, argv, options, "cpuflags");
if (idx && argv[idx + 1])
opt_cpuflags("cpuflags", argv[idx + 1]);
}
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
static int opt_channel_layout(OptionsContext *o, const char *opt, const char *arg)
{
char layout_str[32];
char *stream_str;
char *ac_str;
int ret, channels, ac_str_size;
uint64_t layout;
layout = av_get_channel_layout(arg);
if (!layout) {
av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg);
return AVERROR(EINVAL);
}
snprintf(layout_str, sizeof(layout_str), "%"PRIu64, layout);
ret = opt_default(opt, layout_str);
if (ret < 0)
return ret;
/* set 'ac' option based on channel layout */
channels = av_get_channel_layout_nb_channels(layout);
snprintf(layout_str, sizeof(layout_str), "%d", channels);
stream_str = strchr(opt, ':');
ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0);
ac_str = av_mallocz(ac_str_size);
if (!ac_str)
return AVERROR(ENOMEM);
av_strlcpy(ac_str, "ac", 3);
if (stream_str)
av_strlcat(ac_str, stream_str, ac_str_size);
ret = parse_option(o, ac_str, layout_str, options);
av_free(ac_str);
return ret;
}
static int opt_filter_complex(const char *opt, const char *arg)
{
filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
&nb_filtergraphs, nb_filtergraphs + 1);
if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
return AVERROR(ENOMEM);
filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;
return 0;
}
static int opt_progress(const char *opt, const char *arg)
{
AVIOContext *avio = NULL;
int ret;
if (!strcmp(arg, "-"))
arg = "pipe:";
ret = avio_open2(&avio, arg, AVIO_FLAG_WRITE, &int_cb, NULL);
if (ret < 0) {
av_log(0, AV_LOG_ERROR, "Failed to open progress URL \"%s\": %s\n",
arg, av_err2str(ret));
return ret;
}
progress_avio = avio;
return 0;
}
#define OFFSET(x) offsetof(OptionsContext, x)
static const OptionDef real_options[] = {
#include "cmdutils_common_opts.h"
{ "f", HAS_ARG | OPT_STRING | OPT_OFFSET, {.off = OFFSET(format)}, "force format", "fmt" },
{ "i", HAS_ARG | OPT_FUNC2, {(void*)opt_input_file}, "input file name", "filename" },
{ "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
{ "n", OPT_BOOL, {(void*)&no_file_overwrite}, "do not overwrite output files" },
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
{ "codec", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
{ "pre", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(presets)}, "preset name", "preset" },
{ "map", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map}, "set input stream mapping", "[-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]]" },
{ "map_channel", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map_channel}, "map an audio channel from one stream to another", "file.stream.channel[:syncfile.syncstream]" },
{ "map_metadata", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(metadata_map)}, "set metadata information of outfile from infile",
"outfile[,metadata]:infile[,metadata]" },
{ "map_chapters", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(chapters_input_file)}, "set chapters mapping", "input_file_index" },
{ "t", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(recording_time)}, "record or transcode \"duration\" seconds of audio/video", "duration" },
{ "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET, {.off = OFFSET(limit_filesize)}, "set the limit file size in bytes", "limit_size" }, //
{ "ss", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(start_time)}, "set the start time offset", "time_off" },
{ "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(input_ts_offset)}, "set the input ts offset", "time_off" },
{ "itsscale", HAS_ARG | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(ts_scale)}, "set the input ts scale", "scale" },
{ "timestamp", HAS_ARG | OPT_FUNC2, {(void*)opt_recording_timestamp}, "set the recording timestamp ('now' to set the current time)", "time" },
{ "metadata", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(metadata)}, "add metadata", "string=string" },
{ "dframes", HAS_ARG | OPT_FUNC2, {(void*)opt_data_frames}, "set the number of data frames to record", "number" },
{ "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
{ "benchmark_all", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark_all},
"add timings for each task" },
{ "progress", HAS_ARG | OPT_EXPERT, {(void*)opt_progress},
"write program-readable progress information", "url" },
{ "stdin", OPT_BOOL | OPT_EXPERT, {(void*)&stdin_interaction},
"enable or disable interaction on standard input" },
{ "timelimit", HAS_ARG, {(void*)opt_timelimit}, "set max runtime in seconds", "limit" },
{ "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump},
"dump each input packet" },
{ "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
"when dumping packets, also dump the payload" },
{ "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" },
{ "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
{ "vsync", HAS_ARG | OPT_EXPERT, {(void*)opt_vsync}, "video sync method", "" },
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
Stefano Sabatini
committed
{ "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" },
{ "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" },