Newer
Older
static void opt_input_ts_scale(const char *arg)
{
unsigned int stream;
double scale;
char *p;
stream = strtol(arg, &p, 0);
if (*p)
p++;
scale= strtod(p, &p);
if(stream >= MAX_STREAMS)
input_files_ts_scale[nb_input_files] = grow_array(input_files_ts_scale[nb_input_files], sizeof(*input_files_ts_scale[nb_input_files]), &nb_input_files_ts_scale[nb_input_files], stream + 1);
input_files_ts_scale[nb_input_files][stream]= scale;
}
static int opt_recording_time(const char *opt, const char *arg)
recording_time = parse_time_or_die(opt, arg, 1);
return 0;
static int opt_start_time(const char *opt, const char *arg)
start_time = parse_time_or_die(opt, arg, 1);
return 0;
static int opt_recording_timestamp(const char *opt, const char *arg)
{
recording_timestamp = parse_time_or_die(opt, arg, 0) / 1000000;
return 0;
}
static int opt_input_ts_offset(const char *opt, const char *arg)
input_ts_offset = parse_time_or_die(opt, arg, 1);
return 0;
Janne Grunau
committed
static enum CodecID find_codec_or_die(const char *name, int type, int encoder, int strict)
{
const char *codec_string = encoder ? "encoder" : "decoder";
AVCodec *codec;
if(!name)
return CODEC_ID_NONE;
codec = encoder ?
avcodec_find_encoder_by_name(name) :
avcodec_find_decoder_by_name(name);
if(!codec) {
fprintf(stderr, "Unknown %s '%s'\n", codec_string, name);
}
if(codec->type != type) {
fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name);
}
Janne Grunau
committed
if(codec->capabilities & CODEC_CAP_EXPERIMENTAL &&
strict > FF_COMPLIANCE_EXPERIMENTAL) {
fprintf(stderr, "%s '%s' is experimental and might produce bad "
"results.\nAdd '-strict experimental' if you want to use it.\n",
codec_string, codec->name);
codec = encoder ?
avcodec_find_encoder(codec->id) :
avcodec_find_decoder(codec->id);
if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL))
fprintf(stderr, "Or use the non experimental %s '%s'.\n",
codec_string, codec->name);
Janne Grunau
committed
}
return codec->id;
}
static void opt_input_file(const char *filename)
{
AVFormatContext *ic;
AVFormatParameters params, *ap = ¶ms;
AVInputFormat *file_iformat = NULL;
Michael Niedermayer
committed
int err, i, ret, rfps, rfps_base;
if (last_asked_format) {
if (!(file_iformat = av_find_input_format(last_asked_format))) {
fprintf(stderr, "Unknown input format: '%s'\n", last_asked_format);
last_asked_format = NULL;
}
if (!strcmp(filename, "-"))
filename = "pipe:";
using_stdin |= !strncmp(filename, "pipe:", 5) ||
!strcmp(filename, "/dev/stdin");
ic = avformat_alloc_context();
if (!ic) {
print_error(filename, AVERROR(ENOMEM));
memset(ap, 0, sizeof(*ap));
ap->prealloced_context = 1;
ap->sample_rate = audio_sample_rate;
ap->channels = audio_channels;
ap->time_base.den = frame_rate.num;
ap->time_base.num = frame_rate.den;
ap->width = frame_width;
ap->height = frame_height;
ap->pix_fmt = frame_pix_fmt;
// ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat
ap->channel = video_channel;
ap->standard = video_standard;
set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
Janne Grunau
committed
ic->video_codec_id =
find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0,
avcodec_opts[AVMEDIA_TYPE_VIDEO ]->strict_std_compliance);
ic->audio_codec_id =
find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0,
avcodec_opts[AVMEDIA_TYPE_AUDIO ]->strict_std_compliance);
ic->subtitle_codec_id=
find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0,
avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
/* open the input file with generic libav function */
err = av_open_input_file(&ic, filename, file_iformat, 0, ap);
print_error(filename, err);
Nico Sabbi
committed
if(opt_programid) {
int i, j;
int found=0;
for(i=0; i<ic->nb_streams; i++){
ic->streams[i]->discard= AVDISCARD_ALL;
}
for(i=0; i<ic->nb_programs; i++){
AVProgram *p= ic->programs[i];
if(p->id != opt_programid){
p->discard = AVDISCARD_ALL;
}else{
found=1;
for(j=0; j<p->nb_stream_indexes; j++){
ic->streams[p->stream_index[j]]->discard= AVDISCARD_DEFAULT;
}
}
}
if(!found){
fprintf(stderr, "Specified program id not found\n");
Nico Sabbi
committed
}
ic->loop_input = loop_input;
/* If not enough info to get the stream parameters, we decode the
first frames to get it. (used in mpeg case for example) */
ret = av_find_stream_info(ic);
if (ret < 0 && verbose >= 0) {
fprintf(stderr, "%s: could not find codec parameters\n", filename);
av_close_input_file(ic);
timestamp = start_time;
/* add the stream start time */
if (ic->start_time != AV_NOPTS_VALUE)
timestamp += ic->start_time;
/* if seeking requested, we execute it */
if (start_time != 0) {
ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
if (ret < 0) {
fprintf(stderr, "%s: could not seek to position %0.3f\n",
filename, (double)timestamp / AV_TIME_BASE);
}
/* reset seek info */
start_time = 0;
}
/* update the current parameters so that they match the one of the input stream */
for(i=0;i<ic->nb_streams;i++) {
AVCodecContext *dec = st->codec;
input_codecs = grow_array(input_codecs, sizeof(*input_codecs), &nb_input_codecs, nb_input_codecs + 1);
switch (dec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(audio_codec_name);
set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
//fprintf(stderr, "\nInput Audio channels: %d", dec->channels);
channel_layout = dec->channel_layout;
audio_channels = dec->channels;
audio_sample_rate = dec->sample_rate;
audio_sample_fmt = dec->sample_fmt;
Martin Storsjö
committed
/* Note that av_find_stream_info can add more streams, and we
* currently have no chance of setting up lowres decoding
* early enough for them. */
if (dec->lowres)
audio_sample_rate >>= dec->lowres;
case AVMEDIA_TYPE_VIDEO:
input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(video_codec_name);
set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
frame_height = dec->height;
frame_width = dec->width;
if(ic->streams[i]->sample_aspect_ratio.num)
frame_aspect_ratio=av_q2d(ic->streams[i]->sample_aspect_ratio);
else
frame_aspect_ratio=av_q2d(dec->sample_aspect_ratio);
frame_aspect_ratio *= (float) dec->width / dec->height;
frame_pix_fmt = dec->pix_fmt;
rfps = ic->streams[i]->r_frame_rate.num;
rfps_base = ic->streams[i]->r_frame_rate.den;
if (dec->lowres) {
dec->flags |= CODEC_FLAG_EMU_EDGE;
frame_height >>= dec->lowres;
frame_width >>= dec->lowres;
dec->height = frame_height;
dec->width = frame_width;
Michael Niedermayer
committed
if(me_threshold)
dec->debug |= FF_DEBUG_MV;
if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
if (verbose >= 0)
Baptiste Coudurier
committed
fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
(float)rfps / rfps_base, rfps, rfps_base);
/* update the current frame rate to match the stream frame rate */
frame_rate.num = rfps;
frame_rate.den = rfps_base;
Max Krasnyansky
committed
case AVMEDIA_TYPE_DATA:
break;
case AVMEDIA_TYPE_SUBTITLE:
input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(subtitle_codec_name);
if(subtitle_disable)
Fabrice Bellard
committed
break;
case AVMEDIA_TYPE_ATTACHMENT:
case AVMEDIA_TYPE_UNKNOWN:
break;
default:
input_files_ts_offset[nb_input_files] = input_ts_offset - (copy_ts ? 0 : timestamp);
if (verbose >= 0)
av_dump_format(ic, nb_input_files, filename, 0);
Max Krasnyansky
committed
Baptiste Coudurier
committed
av_freep(&video_codec_name);
av_freep(&audio_codec_name);
av_freep(&subtitle_codec_name);
static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
int *has_subtitle_ptr)
Fabrice Bellard
committed
{
int has_video, has_audio, has_subtitle, i, j;
Fabrice Bellard
committed
AVFormatContext *ic;
has_video = 0;
has_audio = 0;
has_subtitle = 0;
Fabrice Bellard
committed
for(j=0;j<nb_input_files;j++) {
ic = input_files[j];
for(i=0;i<ic->nb_streams;i++) {
Michael Niedermayer
committed
AVCodecContext *enc = ic->streams[i]->codec;
Fabrice Bellard
committed
switch(enc->codec_type) {
case AVMEDIA_TYPE_AUDIO:
Fabrice Bellard
committed
has_audio = 1;
break;
case AVMEDIA_TYPE_VIDEO:
Fabrice Bellard
committed
has_video = 1;
break;
case AVMEDIA_TYPE_SUBTITLE:
has_subtitle = 1;
break;
case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_ATTACHMENT:
case AVMEDIA_TYPE_UNKNOWN:
Wolfram Gloger
committed
break;
default:
Fabrice Bellard
committed
}
}
}
*has_video_ptr = has_video;
*has_audio_ptr = has_audio;
*has_subtitle_ptr = has_subtitle;
Fabrice Bellard
committed
}
static void new_video_stream(AVFormatContext *oc, int file_idx)
AVOutputStream *ost;
Fabrice Bellard
committed
AVCodecContext *video_enc;
AVCodec *codec= NULL;
st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
Fabrice Bellard
committed
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
Fabrice Bellard
committed
}
ost = new_output_stream(oc, file_idx);
output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
if(!video_stream_copy){
if (video_codec_name) {
codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1,
avcodec_opts[AVMEDIA_TYPE_VIDEO]->strict_std_compliance);
codec = avcodec_find_encoder_by_name(video_codec_name);
output_codecs[nb_output_codecs-1] = codec;
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
codec = avcodec_find_encoder(codec_id);
}
}
avcodec_get_context_defaults3(st->codec, codec);
ost->bitstream_filters = video_bitstream_filters;
Michael Niedermayer
committed
video_bitstream_filters= NULL;
st->codec->thread_count= thread_count;
Michael Niedermayer
committed
video_enc = st->codec;
Fabrice Bellard
committed
if(video_codec_tag)
video_enc->codec_tag= video_codec_tag;
Michael Niedermayer
committed
if( (video_global_header&1)
|| (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER))){
Fabrice Bellard
committed
video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
avcodec_opts[AVMEDIA_TYPE_VIDEO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
}
if(video_global_header&2){
Michael Niedermayer
committed
video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
avcodec_opts[AVMEDIA_TYPE_VIDEO]->flags2|= CODEC_FLAG2_LOCAL_HEADER;
Michael Niedermayer
committed
Fabrice Bellard
committed
if (video_stream_copy) {
st->stream_copy = 1;
video_enc->codec_type = AVMEDIA_TYPE_VIDEO;
video_enc->sample_aspect_ratio =
st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
Fabrice Bellard
committed
} else {
Fabrice Bellard
committed
int i;
AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1};
Fabrice Bellard
committed
video_enc->codec_id = codec_id;
set_context_opts(video_enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
if (codec && codec->supported_framerates && !force_fps)
fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)];
video_enc->time_base.den = fps.num;
video_enc->time_base.num = fps.den;
video_enc->width = frame_width;
video_enc->height = frame_height;
video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255);
Fabrice Bellard
committed
video_enc->pix_fmt = frame_pix_fmt;
st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
Fabrice Bellard
committed
Ronald S. Bultje
committed
choose_pixel_fmt(st, codec);
Fabrice Bellard
committed
if (intra_only)
Fabrice Bellard
committed
video_enc->gop_size = 0;
if (video_qscale || same_quality) {
video_enc->flags |= CODEC_FLAG_QSCALE;
Fabrice Bellard
committed
st->quality = FF_QP2LAMBDA * video_qscale;
}
if(intra_matrix)
video_enc->intra_matrix = intra_matrix;
if(inter_matrix)
video_enc->inter_matrix = inter_matrix;
p= video_rc_override_string;
for(i=0; p; i++){
int start, end, q;
int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
if(e!=3){
fprintf(stderr, "error parsing rc_override\n");
Fabrice Bellard
committed
}
video_enc->rc_override=
av_realloc(video_enc->rc_override,
Fabrice Bellard
committed
sizeof(RcOverride)*(i+1));
video_enc->rc_override[i].start_frame= start;
video_enc->rc_override[i].end_frame = end;
if(q>0){
video_enc->rc_override[i].qscale= q;
video_enc->rc_override[i].quality_factor= 1.0;
}
else{
video_enc->rc_override[i].qscale= 0;
video_enc->rc_override[i].quality_factor= -q/100.0;
}
p= strchr(p, '/');
if(p) p++;
}
video_enc->rc_override_count=i;
if (!video_enc->rc_initial_buffer_occupancy)
video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4;
Fabrice Bellard
committed
video_enc->me_threshold= me_threshold;
video_enc->intra_dc_precision= intra_dc_precision - 8;
if (do_psnr)
video_enc->flags|= CODEC_FLAG_PSNR;
Fabrice Bellard
committed
/* two pass mode */
if (do_pass) {
if (do_pass == 1) {
video_enc->flags |= CODEC_FLAG_PASS1;
} else {
video_enc->flags |= CODEC_FLAG_PASS2;
}
}
if (forced_key_frames)
parse_forced_key_frames(forced_key_frames, ost, video_enc);
Fabrice Bellard
committed
}
if (video_language) {
av_metadata_set2(&st->metadata, "language", video_language, 0);
av_freep(&video_language);
}
Fabrice Bellard
committed
/* reset some key parameters */
video_disable = 0;
av_freep(&video_codec_name);
av_freep(&forced_key_frames);
Fabrice Bellard
committed
video_stream_copy = 0;
frame_pix_fmt = PIX_FMT_NONE;
Fabrice Bellard
committed
}
static void new_audio_stream(AVFormatContext *oc, int file_idx)
Fabrice Bellard
committed
{
AVStream *st;
AVOutputStream *ost;
AVCodec *codec= NULL;
Fabrice Bellard
committed
AVCodecContext *audio_enc;
st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
Fabrice Bellard
committed
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
Fabrice Bellard
committed
}
ost = new_output_stream(oc, file_idx);
output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
if(!audio_stream_copy){
if (audio_codec_name) {
codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1,
avcodec_opts[AVMEDIA_TYPE_AUDIO]->strict_std_compliance);
codec = avcodec_find_encoder_by_name(audio_codec_name);
output_codecs[nb_output_codecs-1] = codec;
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
codec = avcodec_find_encoder(codec_id);
}
}
avcodec_get_context_defaults3(st->codec, codec);
Michael Niedermayer
committed
ost->bitstream_filters = audio_bitstream_filters;
Michael Niedermayer
committed
audio_bitstream_filters= NULL;
st->codec->thread_count= thread_count;
Michael Niedermayer
committed
audio_enc = st->codec;
audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
Fabrice Bellard
committed
if(audio_codec_tag)
audio_enc->codec_tag= audio_codec_tag;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
Fabrice Bellard
committed
audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
avcodec_opts[AVMEDIA_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
Fabrice Bellard
committed
if (audio_stream_copy) {
st->stream_copy = 1;
audio_enc->channels = audio_channels;
Michael Niedermayer
committed
audio_enc->sample_rate = audio_sample_rate;
Fabrice Bellard
committed
} else {
audio_enc->codec_id = codec_id;
set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
if (audio_qscale > QSCALE_NONE) {
audio_enc->flags |= CODEC_FLAG_QSCALE;
audio_enc->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
}
audio_enc->channels = audio_channels;
audio_enc->sample_fmt = audio_sample_fmt;
Michael Niedermayer
committed
audio_enc->sample_rate = audio_sample_rate;
audio_enc->channel_layout = channel_layout;
if (av_get_channel_layout_nb_channels(channel_layout) != audio_channels)
audio_enc->channel_layout = 0;
Ronald S. Bultje
committed
choose_sample_fmt(st, codec);
Michael Niedermayer
committed
choose_sample_rate(st, codec);
Fabrice Bellard
committed
}
Michael Niedermayer
committed
audio_enc->time_base= (AVRational){1, audio_sample_rate};
Fabrice Bellard
committed
if (audio_language) {
av_metadata_set2(&st->metadata, "language", audio_language, 0);
av_freep(&audio_language);
Fabrice Bellard
committed
}
/* reset some key parameters */
audio_disable = 0;
av_freep(&audio_codec_name);
Fabrice Bellard
committed
audio_stream_copy = 0;
}
static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
Fabrice Bellard
committed
{
AVStream *st;
AVOutputStream *ost;
AVCodec *codec=NULL;
Fabrice Bellard
committed
AVCodecContext *subtitle_enc;
st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
Fabrice Bellard
committed
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
Fabrice Bellard
committed
}
ost = new_output_stream(oc, file_idx);
subtitle_enc = st->codec;
output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
if(!subtitle_stream_copy){
if (subtitle_codec_name) {
codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1,
avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
codec= output_codecs[nb_output_codecs-1] = avcodec_find_encoder_by_name(subtitle_codec_name);
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_SUBTITLE);
codec = avcodec_find_encoder(codec_id);
}
}
avcodec_get_context_defaults3(st->codec, codec);
Fabrice Bellard
committed
ost->bitstream_filters = subtitle_bitstream_filters;
subtitle_bitstream_filters= NULL;
subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
if(subtitle_codec_tag)
subtitle_enc->codec_tag= subtitle_codec_tag;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
subtitle_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
Fabrice Bellard
committed
if (subtitle_stream_copy) {
st->stream_copy = 1;
} else {
set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
Fabrice Bellard
committed
}
if (subtitle_language) {
av_metadata_set2(&st->metadata, "language", subtitle_language, 0);
av_freep(&subtitle_language);
Fabrice Bellard
committed
}
subtitle_disable = 0;
av_freep(&subtitle_codec_name);
Fabrice Bellard
committed
subtitle_stream_copy = 0;
}
Aurelien Jacobs
committed
static int opt_new_stream(const char *opt, const char *arg)
Fabrice Bellard
committed
{
AVFormatContext *oc;
int file_idx = nb_output_files - 1;
Fabrice Bellard
committed
if (nb_output_files <= 0) {
fprintf(stderr, "At least one output file must be specified\n");
Fabrice Bellard
committed
}
oc = output_files[file_idx];
Fabrice Bellard
committed
if (!strcmp(opt, "newvideo" )) new_video_stream (oc, file_idx);
else if (!strcmp(opt, "newaudio" )) new_audio_stream (oc, file_idx);
else if (!strcmp(opt, "newsubtitle")) new_subtitle_stream(oc, file_idx);
Aurelien Jacobs
committed
return 0;
/* arg format is "output-stream-index:streamid-value". */
Aurelien Jacobs
committed
static int opt_streamid(const char *opt, const char *arg)
{
int idx;
char *p;
char idx_str[16];
strncpy(idx_str, arg, sizeof(idx_str));
idx_str[sizeof(idx_str)-1] = '\0';
p = strchr(idx_str, ':');
if (!p) {
fprintf(stderr,
"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);
streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1);
streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
Aurelien Jacobs
committed
return 0;
}
Fabrice Bellard
committed
static void opt_output_file(const char *filename)
{
AVFormatContext *oc;
int err, use_video, use_audio, use_subtitle;
int input_has_video, input_has_audio, input_has_subtitle;
Fabrice Bellard
committed
AVFormatParameters params, *ap = ¶ms;
AVOutputFormat *file_oformat;
oc = avformat_alloc_context();
if (!oc) {
print_error(filename, AVERROR(ENOMEM));
if (last_asked_format) {
file_oformat = av_guess_format(last_asked_format, NULL, NULL);
if (!file_oformat) {
fprintf(stderr, "Requested output format '%s' is not a suitable output format\n", last_asked_format);
}
last_asked_format = NULL;
} else {
file_oformat = av_guess_format(NULL, filename, NULL);
if (!file_oformat) {
fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
filename);
oc->oformat = file_oformat;
av_strlcpy(oc->filename, filename, sizeof(oc->filename));
if (!strcmp(file_oformat->name, "ffm") &&
av_strstart(filename, "http:", NULL)) {
/* special case for files sent to ffserver: we get the stream
parameters from ffserver */
int err = read_ffserver_streams(oc, filename);
if (err < 0) {
print_error(filename, err);
use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
Fabrice Bellard
committed
/* disable if no corresponding type found and at least one
input file */
if (nb_input_files > 0) {
check_audio_video_sub_inputs(&input_has_video, &input_has_audio,
&input_has_subtitle);
if (!input_has_video)
use_video = 0;
if (!input_has_audio)
use_audio = 0;
if (!input_has_subtitle)
use_subtitle = 0;
Fabrice Bellard
committed
/* manual disable */
if (audio_disable) use_audio = 0;
if (video_disable) use_video = 0;
if (subtitle_disable) use_subtitle = 0;
if (use_video) new_video_stream(oc, nb_output_files);
if (use_audio) new_audio_stream(oc, nb_output_files);
if (use_subtitle) new_subtitle_stream(oc, nb_output_files);
oc->timestamp = recording_timestamp;
Ronald S. Bultje
committed
av_metadata_copy(&oc->metadata, metadata, 0);
av_metadata_free(&metadata);
output_files[nb_output_files++] = oc;
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_NUMEXPECTED);
Fabrice Bellard
committed
}
if (!(oc->oformat->flags & AVFMT_NOFILE)) {
/* test if it already exists to avoid loosing precious files */
filename[1] == ':' ||
av_strstart(filename, "file:", NULL))) {
if (!using_stdin) {
fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
fflush(stderr);
fprintf(stderr, "Not overwriting - exiting\n");
}
else {
fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
}
if ((err = avio_open(&oc->pb, filename, URL_WRONLY)) < 0) {
print_error(filename, err);
Fabrice Bellard
committed
memset(ap, 0, sizeof(*ap));
if (av_set_parameters(oc, ap) < 0) {
fprintf(stderr, "%s: Invalid encoding parameters\n",
oc->filename);
Fabrice Bellard
committed
}
oc->preload= (int)(mux_preload*AV_TIME_BASE);
oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
oc->loop_output = loop_output;
set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
av_freep(&forced_key_frames);
/* same option as mencoder */
static void opt_pass(const char *pass_str)
{
int pass;
pass = atoi(pass_str);
if (pass != 1 && pass != 2) {
fprintf(stderr, "pass number can be only 1 or 2\n");
}
do_pass = pass;
}
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
#elif HAVE_GETPROCESSTIMES
HANDLE proc;
FILETIME c, e, k, u;
proc = GetCurrentProcess();
GetProcessTimes(proc, &c, &e, &k, &u);
return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
#else
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 void parse_matrix_coeffs(uint16_t *dest, const char *str)
Vidar Madsen
committed
{
int i;
const char *p = str;
for(i = 0;; i++) {
dest[i] = atoi(p);
if(i == 63)
break;
p = strchr(p, ',');
if(!p) {
fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
Vidar Madsen
committed
}
p++;
}
}
static void opt_inter_matrix(const char *arg)
Vidar Madsen
committed
{
inter_matrix = av_mallocz(sizeof(uint16_t) * 64);
parse_matrix_coeffs(inter_matrix, arg);
}
static void opt_intra_matrix(const char *arg)
Vidar Madsen
committed
{
intra_matrix = av_mallocz(sizeof(uint16_t) * 64);
parse_matrix_coeffs(intra_matrix, arg);
}
printf("Hyper fast Audio and Video encoder\n");
printf("usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...\n");
printf("\n");
}
static void show_help(void)
{
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");
av_opt_show2(avcodec_opts[0], NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
printf("\n");
/* individual codec options */
c = NULL;
while ((c = av_codec_next(c))) {
if (c->priv_class) {
av_opt_show2(&c->priv_class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
printf("\n");
}
}
av_opt_show2(avformat_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
printf("\n");
/* individual muxer options */
while ((oformat = av_oformat_next(oformat))) {
if (oformat->priv_class) {
av_opt_show2(&oformat->priv_class, NULL, AV_OPT_FLAG_ENCODING_PARAM, 0);
printf("\n");
}
}
av_opt_show2(sws_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
static void opt_target(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 {
int fr;
/* Calculate FR via float to avoid int overflow */
fr = (int)(frame_rate.num * 1000.0 / frame_rate.den);
if(fr == 25000) {
Stefano Sabatini
committed
norm = PAL;
} else if((fr == 29970) || (fr == 23976)) {
Stefano Sabatini
committed
norm = NTSC;
} else {
/* Try to determine PAL/NTSC by peeking in the input files */
if(nb_input_files) {
int i, j;
for(j = 0; j < nb_input_files; j++) {
for(i = 0; i < input_files[j]->nb_streams; i++) {
Michael Niedermayer
committed
AVCodecContext *c = input_files[j]->streams[i]->codec;
if(c->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
fr = c->time_base.den * 1000 / c->time_base.num;
if(fr == 25000) {
Stefano Sabatini
committed
norm = PAL;
break;
} else if((fr == 29970) || (fr == 23976)) {
Stefano Sabatini
committed
norm = NTSC;
break;
}
}
Stefano Sabatini
committed
if(norm != UNKNOWN)
break;
}
}
}
Stefano Sabatini
committed
if(verbose && norm != UNKNOWN)
fprintf(stderr, "Assuming %s for target.\n", norm == PAL ? "PAL" : "NTSC");
Stefano Sabatini
committed
if(norm == UNKNOWN) {
fprintf(stderr, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
fprintf(stderr, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
fprintf(stderr, "or set a framerate with \"-r xxx\".\n");
}
if(!strcmp(arg, "vcd")) {
opt_video_codec("mpeg1video");
opt_audio_codec("mp2");
opt_format("vcd");
opt_frame_size(norm == PAL ? "352x288" : "352x240");
opt_frame_rate(NULL, frame_rates[norm]);
opt_default("g", norm == PAL ? "15" : "18");
Panagiotis Issaris
committed
opt_default("b", "1150000");
Panagiotis Issaris
committed
opt_default("maxrate", "1150000");
opt_default("minrate", "1150000");
Panagiotis Issaris
committed
opt_default("bufsize", "327680"); // 40*1024*8;
Benoit Fouet
committed
opt_default("ab", "224000");
audio_sample_rate = 44100;
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. */
mux_preload= (36000+3*1200) / 90000.0; //0.44