Newer
Older
Max Krasnyansky
committed
grab_device = NULL;
video_channel = 0;
Max Krasnyansky
committed
rate_emu = 0;
static void opt_grab(const char *arg)
{
file_iformat = av_find_input_format(arg);
opt_input_file("");
}
static void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr)
Fabrice Bellard
committed
{
int has_video, has_audio, i, j;
AVFormatContext *ic;
has_video = 0;
has_audio = 0;
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 CODEC_TYPE_AUDIO:
has_audio = 1;
break;
case CODEC_TYPE_VIDEO:
has_video = 1;
break;
Wolfram Gloger
committed
case CODEC_TYPE_DATA:
case CODEC_TYPE_UNKNOWN:
Fabrice Bellard
committed
case CODEC_TYPE_SUBTITLE:
Wolfram Gloger
committed
break;
default:
av_abort();
Fabrice Bellard
committed
}
}
}
*has_video_ptr = has_video;
*has_audio_ptr = has_audio;
}
Fabrice Bellard
committed
static void new_video_stream(AVFormatContext *oc)
Fabrice Bellard
committed
AVCodecContext *video_enc;
int codec_id;
Fabrice Bellard
committed
st = av_new_stream(oc, oc->nb_streams);
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
#if defined(HAVE_THREADS)
if(thread_count>1)
Michael Niedermayer
committed
avcodec_thread_init(st->codec, thread_count);
Fabrice Bellard
committed
#endif
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;
avctx_opts->flags|= CODEC_FLAG_GLOBAL_HEADER;
}
if(video_global_header&2){
Michael Niedermayer
committed
video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
avctx_opts->flags2|= CODEC_FLAG2_LOCAL_HEADER;
}
Michael Niedermayer
committed
Fabrice Bellard
committed
if (video_stream_copy) {
st->stream_copy = 1;
video_enc->codec_type = CODEC_TYPE_VIDEO;
} else {
char *p;
int i;
AVCodec *codec;
Fabrice Bellard
committed
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
if (video_codec_id != CODEC_ID_NONE)
codec_id = video_codec_id;
Fabrice Bellard
committed
video_enc->codec_id = codec_id;
codec = avcodec_find_encoder(codec_id);
for(i=0; i<opt_name_count; i++){
AVOption *opt;
double d= av_get_double(avctx_opts, opt_names[i], &opt);
if(d==d && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(video_enc, opt_names[i], d);
}
Fabrice Bellard
committed
video_enc->bit_rate = video_bit_rate;
video_enc->bit_rate_tolerance = video_bit_rate_tolerance;
video_enc->time_base.den = frame_rate;
video_enc->time_base.num = frame_rate_base;
Fabrice Bellard
committed
if(codec && codec->supported_framerates){
const AVRational *p= codec->supported_framerates;
AVRational req= (AVRational){frame_rate, frame_rate_base};
const AVRational *best=NULL;
AVRational best_error= (AVRational){INT_MAX, 1};
for(; p->den!=0; p++){
AVRational error= av_sub_q(req, *p);
if(error.num <0) error.num *= -1;
if(av_cmp_q(error, best_error) < 0){
best_error= error;
best= p;
}
}
video_enc->time_base.den= best->num;
video_enc->time_base.num= best->den;
}
Fabrice Bellard
committed
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
video_enc->width = frame_width + frame_padright + frame_padleft;
video_enc->height = frame_height + frame_padtop + frame_padbottom;
video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
video_enc->pix_fmt = frame_pix_fmt;
if(codec && codec->pix_fmts){
const enum PixelFormat *p= codec->pix_fmts;
for(; *p!=-1; p++){
if(*p == video_enc->pix_fmt)
break;
}
if(*p == -1)
video_enc->pix_fmt = codec->pix_fmts[0];
}
if (!intra_only)
video_enc->gop_size = gop_size;
else
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;
video_enc->pre_me = pre_me;
Fabrice Bellard
committed
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
if (b_frames) {
video_enc->max_b_frames = b_frames;
video_enc->b_quant_factor = 2.0;
}
video_enc->qmin = video_qmin;
video_enc->qmax = video_qmax;
video_enc->lmin = video_lmin;
video_enc->lmax = video_lmax;
video_enc->rc_qsquish = video_qsquish;
video_enc->mb_lmin = video_mb_lmin;
video_enc->mb_lmax = video_mb_lmax;
video_enc->max_qdiff = video_qdiff;
video_enc->qblur = video_qblur;
video_enc->qcompress = video_qcomp;
video_enc->rc_eq = video_rc_eq;
video_enc->workaround_bugs = workaround_bugs;
video_enc->thread_count = thread_count;
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");
exit(1);
}
video_enc->rc_override=
av_realloc(video_enc->rc_override,
Fabrice Bellard
committed
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
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;
video_enc->rc_max_rate = video_rc_max_rate;
video_enc->rc_min_rate = video_rc_min_rate;
video_enc->rc_buffer_size = video_rc_buffer_size;
video_enc->rc_initial_buffer_occupancy = video_rc_buffer_size*3/4;
video_enc->rc_buffer_aggressivity= video_rc_buffer_aggressivity;
video_enc->rc_initial_cplx= video_rc_initial_cplx;
video_enc->i_quant_factor = video_i_qfactor;
video_enc->b_quant_factor = video_b_qfactor;
video_enc->i_quant_offset = video_i_qoffset;
video_enc->b_quant_offset = video_b_qoffset;
video_enc->intra_quant_bias = video_intra_quant_bias;
video_enc->inter_quant_bias = video_inter_quant_bias;
video_enc->me_threshold= me_threshold;
video_enc->mb_threshold= mb_threshold;
video_enc->intra_dc_precision= intra_dc_precision - 8;
video_enc->strict_std_compliance = strict;
video_enc->error_rate = error_rate;
video_enc->scenechange_threshold= sc_threshold;
video_enc->me_range = me_range;
video_enc->me_penalty_compensation= me_penalty_compensation;
video_enc->frame_skip_threshold= frame_skip_threshold;
video_enc->frame_skip_factor= frame_skip_factor;
video_enc->frame_skip_exp= frame_skip_exp;
if(packet_size){
video_enc->rtp_mode= 1;
video_enc->rtp_payload_size= packet_size;
}
Fabrice Bellard
committed
if (do_psnr)
video_enc->flags|= CODEC_FLAG_PSNR;
Fabrice Bellard
committed
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
video_enc->me_method = me_method;
/* two pass mode */
if (do_pass) {
if (do_pass == 1) {
video_enc->flags |= CODEC_FLAG_PASS1;
} else {
video_enc->flags |= CODEC_FLAG_PASS2;
}
}
}
/* reset some key parameters */
video_disable = 0;
video_codec_id = CODEC_ID_NONE;
video_stream_copy = 0;
}
static void new_audio_stream(AVFormatContext *oc)
{
AVStream *st;
AVCodecContext *audio_enc;
Fabrice Bellard
committed
st = av_new_stream(oc, oc->nb_streams);
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
#if defined(HAVE_THREADS)
if(thread_count>1)
Michael Niedermayer
committed
avcodec_thread_init(st->codec, thread_count);
Fabrice Bellard
committed
#endif
Michael Niedermayer
committed
audio_enc = st->codec;
Fabrice Bellard
committed
audio_enc->codec_type = CODEC_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;
avctx_opts->flags|= CODEC_FLAG_GLOBAL_HEADER;
}
Fabrice Bellard
committed
if (audio_stream_copy) {
st->stream_copy = 1;
audio_enc->channels = audio_channels;
} else {
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_AUDIO);
for(i=0; i<opt_name_count; i++){
AVOption *opt;
double d= av_get_double(avctx_opts, opt_names[i], &opt);
if(d==d && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(audio_enc, opt_names[i], d);
}
Fabrice Bellard
committed
if (audio_codec_id != CODEC_ID_NONE)
codec_id = audio_codec_id;
audio_enc->codec_id = codec_id;
Fabrice Bellard
committed
audio_enc->bit_rate = audio_bit_rate;
if (audio_qscale > QSCALE_NONE) {
audio_enc->flags |= CODEC_FLAG_QSCALE;
audio_enc->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
}
Fabrice Bellard
committed
audio_enc->strict_std_compliance = strict;
audio_enc->thread_count = thread_count;
/* For audio codecs other than AC3 or DTS we limit */
/* the number of coded channels to stereo */
if (audio_channels > 2 && codec_id != CODEC_ID_AC3
&& codec_id != CODEC_ID_DTS) {
audio_enc->channels = 2;
} else
audio_enc->channels = audio_channels;
}
audio_enc->sample_rate = audio_sample_rate;
Michael Niedermayer
committed
audio_enc->time_base= (AVRational){1, audio_sample_rate};
Fabrice Bellard
committed
if (audio_language) {
pstrcpy(st->language, sizeof(st->language), audio_language);
av_free(audio_language);
audio_language = NULL;
}
/* reset some key parameters */
audio_disable = 0;
audio_codec_id = CODEC_ID_NONE;
audio_stream_copy = 0;
}
static void opt_new_subtitle_stream(void)
{
AVFormatContext *oc;
AVStream *st;
AVCodecContext *subtitle_enc;
Fabrice Bellard
committed
if (nb_output_files <= 0) {
fprintf(stderr, "At least one output file must be specified\n");
exit(1);
}
oc = output_files[nb_output_files - 1];
st = av_new_stream(oc, oc->nb_streams);
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
Michael Niedermayer
committed
subtitle_enc = st->codec;
Fabrice Bellard
committed
subtitle_enc->codec_type = CODEC_TYPE_SUBTITLE;
if (subtitle_stream_copy) {
st->stream_copy = 1;
} else {
for(i=0; i<opt_name_count; i++){
AVOption *opt;
double d= av_get_double(avctx_opts, opt_names[i], &opt);
if(d==d && (opt->flags&AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(subtitle_enc, opt_names[i], d);
}
Fabrice Bellard
committed
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
subtitle_enc->codec_id = subtitle_codec_id;
}
if (subtitle_language) {
pstrcpy(st->language, sizeof(st->language), subtitle_language);
av_free(subtitle_language);
subtitle_language = NULL;
}
subtitle_codec_id = CODEC_ID_NONE;
subtitle_stream_copy = 0;
}
static void opt_new_audio_stream(void)
{
AVFormatContext *oc;
if (nb_output_files <= 0) {
fprintf(stderr, "At least one output file must be specified\n");
exit(1);
}
oc = output_files[nb_output_files - 1];
new_audio_stream(oc);
}
static void opt_new_video_stream(void)
{
AVFormatContext *oc;
if (nb_output_files <= 0) {
fprintf(stderr, "At least one output file must be specified\n");
exit(1);
}
oc = output_files[nb_output_files - 1];
new_video_stream(oc);
}
static void opt_output_file(const char *filename)
{
AVFormatContext *oc;
int use_video, use_audio, input_has_video, input_has_audio;
Fabrice Bellard
committed
AVFormatParameters params, *ap = ¶ms;
oc = av_alloc_format_context();
if (!file_oformat) {
file_oformat = guess_format(NULL, filename, NULL);
if (!file_oformat) {
fprintf(stderr, "Unable for find a suitable output format for '%s'\n",
filename);
exit(1);
}
oc->oformat = file_oformat;
Fabrice Bellard
committed
pstrcpy(oc->filename, sizeof(oc->filename), filename);
if (!strcmp(file_oformat->name, "ffm") &&
strstart(filename, "http:", NULL)) {
/* special case for files sent to ffserver: we get the stream
parameters from ffserver */
if (read_ffserver_streams(oc, filename) < 0) {
fprintf(stderr, "Could not read stream parameters from '%s'\n", filename);
exit(1);
}
} else {
Luca Abeni
committed
use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_id != CODEC_ID_NONE;
use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_id != CODEC_ID_NONE;
Fabrice Bellard
committed
/* disable if no corresponding type found and at least one
input file */
if (nb_input_files > 0) {
check_audio_video_inputs(&input_has_video, &input_has_audio);
if (!input_has_video)
use_video = 0;
if (!input_has_audio)
use_audio = 0;
}
Fabrice Bellard
committed
/* manual disable */
if (audio_disable) {
use_audio = 0;
}
if (video_disable) {
use_video = 0;
}
Fabrice Bellard
committed
new_video_stream(oc);
Fabrice Bellard
committed
new_audio_stream(oc);
Fabrice Bellard
committed
if (!oc->nb_streams) {
Fabrice Bellard
committed
fprintf(stderr, "No audio or video streams available\n");
oc->timestamp = rec_timestamp;
pstrcpy(oc->title, sizeof(oc->title), str_title);
pstrcpy(oc->author, sizeof(oc->author), str_author);
pstrcpy(oc->copyright, sizeof(oc->copyright), str_copyright);
pstrcpy(oc->comment, sizeof(oc->comment), str_comment);
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) {
if (filename_number_test(oc->filename) < 0) {
print_error(oc->filename, AVERROR_NUMEXPECTED);
Fabrice Bellard
committed
exit(1);
Fabrice Bellard
committed
}
if (!(oc->oformat->flags & AVFMT_NOFILE)) {
/* test if it already exists to avoid loosing precious files */
(strchr(filename, ':') == NULL ||
strstart(filename, "file:", NULL))) {
if (url_exist(filename)) {
int c;
if ( !using_stdin ) {
fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
fflush(stderr);
c = getchar();
if (toupper(c) != 'Y') {
fprintf(stderr, "Not overwriting - exiting\n");
exit(1);
}
fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
/* open the file */
if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
fprintf(stderr, "Could not open '%s'\n", filename);
exit(1);
}
}
Fabrice Bellard
committed
memset(ap, 0, sizeof(*ap));
ap->image_format = image_format;
if (av_set_parameters(oc, ap) < 0) {
fprintf(stderr, "%s: Invalid encoding parameters\n",
oc->filename);
exit(1);
}
oc->packet_size= mux_packet_size;
oc->mux_rate= mux_rate;
oc->preload= (int)(mux_preload*AV_TIME_BASE);
oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
oc->loop_output = loop_output;
file_oformat = NULL;
file_iformat = NULL;
Fabrice Bellard
committed
image_format = NULL;
/* prepare dummy protocols for grab */
static void prepare_grab(void)
{
int has_video, has_audio, i, j;
AVFormatContext *oc;
AVFormatContext *ic;
Fabrice Bellard
committed
AVFormatParameters vp1, *vp = &vp1;
AVFormatParameters ap1, *ap = &ap1;
/* see if audio/video inputs are needed */
has_video = 0;
has_audio = 0;
memset(ap, 0, sizeof(*ap));
Fabrice Bellard
committed
memset(vp, 0, sizeof(*vp));
for(j=0;j<nb_output_files;j++) {
oc = output_files[j];
for(i=0;i<oc->nb_streams;i++) {
Michael Niedermayer
committed
AVCodecContext *enc = oc->streams[i]->codec;
switch(enc->codec_type) {
case CODEC_TYPE_AUDIO:
if (enc->sample_rate > ap->sample_rate)
ap->sample_rate = enc->sample_rate;
if (enc->channels > ap->channels)
ap->channels = enc->channels;
has_audio = 1;
break;
case CODEC_TYPE_VIDEO:
Fabrice Bellard
committed
if (enc->width > vp->width)
vp->width = enc->width;
if (enc->height > vp->height)
vp->height = enc->height;
if (vp->time_base.num*(int64_t)enc->time_base.den > enc->time_base.num*(int64_t)vp->time_base.den){
vp->time_base = enc->time_base;
Michael Niedermayer
committed
}
has_video = 1;
break;
default:
av_abort();
}
}
}
if (has_video == 0 && has_audio == 0) {
fprintf(stderr, "Output file must have at least one audio or video stream\n");
exit(1);
}
if (has_video) {
AVInputFormat *fmt1;
fmt1 = av_find_input_format(video_grab_format);
Fabrice Bellard
committed
vp->device = video_device;
vp->channel = video_channel;
vp->standard = video_standard;
vp->pix_fmt = frame_pix_fmt;
Fabrice Bellard
committed
if (av_open_input_file(&ic, "", fmt1, 0, vp) < 0) {
fprintf(stderr, "Could not find video grab device\n");
exit(1);
}
/* If not enough info to get the stream parameters, we decode the
first frames to get it. */
if ((ic->ctx_flags & AVFMTCTX_NOHEADER) && av_find_stream_info(ic) < 0) {
fprintf(stderr, "Could not find video grab parameters\n");
exit(1);
}
/* by now video grab has one stream */
ic->streams[0]->r_frame_rate.num = vp->time_base.den;
ic->streams[0]->r_frame_rate.den = vp->time_base.num;
input_files[nb_input_files] = ic;
if (verbose >= 0)
dump_format(ic, nb_input_files, "", 0);
nb_input_files++;
}
if (has_audio && audio_grab_format) {
AVInputFormat *fmt1;
fmt1 = av_find_input_format(audio_grab_format);
Fabrice Bellard
committed
ap->device = audio_device;
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
fprintf(stderr, "Could not find audio grab device\n");
exit(1);
}
input_files[nb_input_files] = ic;
if (verbose >= 0)
dump_format(ic, nb_input_files, "", 0);
nb_input_files++;
}
}
/* 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");
exit(1);
}
do_pass = pass;
}
#if defined(CONFIG_WIN32) || defined(CONFIG_OS2)
return av_gettime();
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
extern int ffm_nopts;
static void show_formats(void)
AVInputFormat *ifmt;
AVOutputFormat *ofmt;
Fabrice Bellard
committed
AVImageFormat *image_fmt;
AVCodec *p, *p2;
const char **pp, *last_name;
printf("File formats:\n");
last_name= "000";
for(;;){
int decode=0;
int encode=0;
const char *name=NULL;
Michael Niedermayer
committed
const char *long_name=NULL;
for(ofmt = first_oformat; ofmt != NULL; ofmt = ofmt->next) {
if((name == NULL || strcmp(ofmt->name, name)<0) &&
strcmp(ofmt->name, last_name)>0){
name= ofmt->name;
Michael Niedermayer
committed
long_name= ofmt->long_name;
encode=1;
}
}
for(ifmt = first_iformat; ifmt != NULL; ifmt = ifmt->next) {
if((name == NULL || strcmp(ifmt->name, name)<0) &&
strcmp(ifmt->name, last_name)>0){
name= ifmt->name;
Michael Niedermayer
committed
long_name= ifmt->long_name;
encode=0;
}
if(name && strcmp(ifmt->name, name)==0)
decode=1;
}
if(name==NULL)
break;
last_name= name;
" %s%s %-15s %s\n",
decode ? "D":" ",
encode ? "E":" ",
Michael Niedermayer
committed
name,
long_name ? long_name:" ");
Fabrice Bellard
committed
}
printf("\n");
Michael Niedermayer
committed
printf("Image formats (filename extensions, if any, follow):\n");
for(image_fmt = first_image_format; image_fmt != NULL;
Fabrice Bellard
committed
image_fmt = image_fmt->next) {
Michael Niedermayer
committed
" %s%s %-6s %s\n",
image_fmt->img_read ? "D":" ",
image_fmt->img_write ? "E":" ",
Michael Niedermayer
committed
image_fmt->name,
image_fmt->extensions ? image_fmt->extensions:" ");
Fabrice Bellard
committed
}
printf("\n");
last_name= "000";
for(;;){
int decode=0;
int encode=0;
int cap=0;
Fabrice Bellard
committed
const char *type_str;
p2=NULL;
for(p = first_avcodec; p != NULL; p = p->next) {
if((p2==NULL || strcmp(p->name, p2->name)<0) &&
strcmp(p->name, last_name)>0){
p2= p;
decode= encode= cap=0;
}
if(p2 && strcmp(p->name, p2->name)==0){
if(p->decode) decode=1;
if(p->encode) encode=1;
cap |= p->capabilities;
}
}
if(p2==NULL)
break;
last_name= p2->name;
Fabrice Bellard
committed
switch(p2->type) {
case CODEC_TYPE_VIDEO:
type_str = "V";
break;
case CODEC_TYPE_AUDIO:
type_str = "A";
break;
case CODEC_TYPE_SUBTITLE:
type_str = "S";
break;
default:
type_str = "?";
break;
}
" %s%s%s%s%s%s %s",
decode ? "D": (/*p2->decoder ? "d":*/" "),
encode ? "E":" ",
Fabrice Bellard
committed
type_str,
cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ",
cap & CODEC_CAP_DR1 ? "D":" ",
cap & CODEC_CAP_TRUNCATED ? "T":" ",
p2->name);
/* if(p2->decoder && decode==0)
printf(" use %s for decoding", p2->decoder->name);*/
printf("\n");
printf("Supported file protocols:\n");
for(up = first_protocol; up != NULL; up = up->next)
printf(" %s:", up->name);
printf("\n");
printf("Frame size, frame rate abbreviations:\n ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n");
printf("Motion estimation methods:\n");
if ((pp - motion_str + 1) == ME_ZERO)
else if ((pp - motion_str + 1) == ME_FULL)
else if ((pp - motion_str + 1) == ME_EPZS)
printf("\n\n");
printf(
"Note, the names of encoders and decoders dont always match, so there are\n"
"several cases where the above table shows encoder only or decoder only entries\n"
"even though both encoding and decoding are supported for example, the h263\n"
"decoder corresponds to the h263 and h263p encoders, for file formats its even\n"
"worse\n");
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);
exit(1);
}
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);
}
static void opt_target(const char *arg)
{
int norm = -1;
static const char *const frame_rates[] = {"25", "30000/1001", "24000/1001"};
if(!strncmp(arg, "pal-", 4)) {
norm = 0;
arg += 4;
} else if(!strncmp(arg, "ntsc-", 5)) {
norm = 1;
arg += 5;
} else if(!strncmp(arg, "film-", 5)) {
norm = 2;
arg += 5;
} else {
int fr;
/* Calculate FR via float to avoid int overflow */
fr = (int)(frame_rate * 1000.0 / frame_rate_base);
if(fr == 25000) {
norm = 0;
} else if((fr == 29970) || (fr == 23976)) {
norm = 1;
} 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 != CODEC_TYPE_VIDEO)
continue;
fr = c->time_base.den * 1000 / c->time_base.num;
if(fr == 25000) {
norm = 0;
break;
} else if((fr == 29970) || (fr == 23976)) {
norm = 1;
break;
}
}
if(norm >= 0)
break;
}
}
}
if(verbose && norm >= 0)
Roine Gustafsson
committed
fprintf(stderr, "Assuming %s for target.\n", norm ? "NTSC" : "PAL");
}
if(norm < 0) {
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");
exit(1);
}
if(!strcmp(arg, "vcd")) {
opt_video_codec("mpeg1video");
opt_audio_codec("mp2");
opt_format("vcd");
opt_frame_size(norm ? "352x240" : "352x288");
opt_frame_rate(frame_rates[norm]);
Panagiotis Issaris
committed
opt_gop_size(norm ? "18" : "15");
video_bit_rate = 1150000;
video_rc_max_rate = 1150000;
video_rc_min_rate = 1150000;
audio_bit_rate = 224000;
audio_sample_rate = 44100;
mux_packet_size= 2324;
mux_rate= 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
} else if(!strcmp(arg, "svcd")) {
opt_video_codec("mpeg2video");
opt_audio_codec("mp2");
opt_format("svcd");
opt_frame_size(norm ? "480x480" : "480x576");
opt_frame_rate(frame_rates[norm]);
opt_gop_size(norm ? "18" : "15");
video_bit_rate = 2040000;
video_rc_max_rate = 2516000;
Michael Niedermayer
committed
video_rc_min_rate = 0; //1145000;
opt_default("flags", "+SCAN_OFFSET");
audio_bit_rate = 224000;
audio_sample_rate = 44100;
mux_packet_size= 2324;
} else if(!strcmp(arg, "dvd")) {
opt_video_codec("mpeg2video");
opt_audio_codec("ac3");
Paul Curtis
committed
opt_format("dvd");
opt_frame_size(norm ? "720x480" : "720x576");
opt_frame_rate(frame_rates[norm]);
opt_gop_size(norm ? "18" : "15");
video_bit_rate = 6000000;
video_rc_max_rate = 9000000;
Michael Niedermayer
committed
video_rc_min_rate = 0; //1500000;
Michael Niedermayer
committed
mux_packet_size= 2048; // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
mux_rate = 10080000; // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
audio_bit_rate = 448000;
audio_sample_rate = 48000;
Panagiotis Issaris
committed
} else if(!strcmp(arg, "dv")) {
opt_format("dv");
opt_frame_size(norm ? "720x480" : "720x576");
opt_frame_rate(frame_rates[norm]);
audio_sample_rate = 48000;
audio_channels = 2;
} else {
fprintf(stderr, "Unknown target: %s\n", arg);
exit(1);
}
}
/* TODO: add function interface to avutil and avformat */
Roine Gustafsson
committed
fprintf(stderr, "ffmpeg " FFMPEG_VERSION "\n"
LIBAVUTIL_BUILD, avcodec_build(), LIBAVFORMAT_BUILD);
static int opt_default(const char *opt, const char *arg){
AVOption *o= av_set_string(avctx_opts, opt, arg);
if(!o)
return -1;
// av_log(NULL, AV_LOG_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avctx_opts, opt, NULL), (int)av_get_int(avctx_opts, opt, NULL));
//FIXME we should always use avctx_opts, ... for storing options so there wont be any need to keep track of whats set over this
opt_names= av_realloc(opt_names, sizeof(void*)*(opt_name_count+1));
opt_names[opt_name_count++]= o->name;
/* disable generate of real time pts in ffm (need to be supressed anyway) */
if(avctx_opts->flags & CODEC_FLAG_BITEXACT)
ffm_nopts = 1;
if(avctx_opts->debug)
av_log_set_level(AV_LOG_DEBUG);
/* main options */
{ "L", 0, {(void*)show_license}, "show license" },
{ "version", 0, {(void*)show_version}, "show version" },
{ "formats", 0, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
{ "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
Fabrice Bellard
committed
{ "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
{ "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
{ "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
{ "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
Patrice Bensoussan
committed
{ "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
{ "t", HAS_ARG, {(void*)opt_recording_time}, "set the recording time", "duration" },
{ "fs", HAS_ARG | OPT_INT, {(void*)&limit_filesize}, "set the limit file size", "limit_size" }, //
{ "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },