Newer
Older
/* 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) {
fprintf(stderr, "%s: could not find codec parameters\n", filename);
exit(1);
}
/* update the current parameters so that they match the one of the input stream */
for(i=0;i<ic->nb_streams;i++) {
AVCodecContext *enc = &ic->streams[i]->codec;
switch(enc->codec_type) {
case CODEC_TYPE_AUDIO:
//fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
audio_channels = enc->channels;
audio_sample_rate = enc->sample_rate;
break;
case CODEC_TYPE_VIDEO:
frame_height = enc->height;
frame_width = enc->width;
rfps = ic->streams[i]->r_frame_rate;
Michael Niedermayer
committed
enc->workaround_bugs = workaround_bugs;
enc->error_resilience = error_resilience;
enc->error_concealment = error_concealment;
enc->idct_algo= idct_algo;
/* if(enc->codec->capabilities & CODEC_CAP_TRUNCATED)
enc->flags|= CODEC_FLAG_TRUNCATED; */
if(/*enc->codec_id==CODEC_ID_MPEG4 || */enc->codec_id==CODEC_ID_MPEG1VIDEO)
enc->flags|= CODEC_FLAG_TRUNCATED;
if (enc->frame_rate != rfps) {
fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n",
i, (float)enc->frame_rate / FRAME_RATE_BASE,
(float)rfps / FRAME_RATE_BASE);
/* update the current frame rate to match the stream frame rate */
frame_rate = rfps;
default:
av_abort();
}
}
input_files[nb_input_files] = ic;
/* dump the file content */
dump_format(ic, nb_input_files, filename, 0);
nb_input_files++;
file_iformat = NULL;
file_oformat = NULL;
Fabrice Bellard
committed
void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr)
{
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++) {
AVCodecContext *enc = &ic->streams[i]->codec;
switch(enc->codec_type) {
case CODEC_TYPE_AUDIO:
has_audio = 1;
break;
case CODEC_TYPE_VIDEO:
has_video = 1;
break;
default:
av_abort();
Fabrice Bellard
committed
}
}
}
*has_video_ptr = has_video;
*has_audio_ptr = has_audio;
}
void opt_output_file(const char *filename)
{
AVStream *st;
AVFormatContext *oc;
Fabrice Bellard
committed
int use_video, use_audio, nb_streams, input_has_video, input_has_audio;
int codec_id;
if (!strcmp(filename, "-"))
filename = "pipe:";
oc = av_mallocz(sizeof(AVFormatContext));
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;
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 {
use_video = file_oformat->video_codec != CODEC_ID_NONE;
use_audio = file_oformat->audio_codec != 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;
}
nb_streams = 0;
if (use_video) {
AVCodecContext *video_enc;
st = av_mallocz(sizeof(AVStream));
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
video_enc = &st->codec;
if (video_stream_copy) {
st->stream_copy = 1;
video_enc->codec_type = CODEC_TYPE_VIDEO;
} else {
char *p;
int i;
codec_id = file_oformat->video_codec;
if (video_codec_id != CODEC_ID_NONE)
codec_id = video_codec_id;
video_enc->codec_id = codec_id;
video_enc->bit_rate = video_bit_rate;
video_enc->bit_rate_tolerance = video_bit_rate_tolerance;
video_enc->frame_rate = frame_rate;
video_enc->width = frame_width;
video_enc->height = frame_height;
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;
}
if (use_hq) {
video_enc->flags |= CODEC_FLAG_HQ;
}
if (use_4mv) {
video_enc->flags |= CODEC_FLAG_HQ;
video_enc->flags |= CODEC_FLAG_4MV;
}
if(use_part)
video_enc->flags |= CODEC_FLAG_PART;
if (b_frames) {
if (codec_id != CODEC_ID_MPEG4) {
fprintf(stderr, "\nB frames encoding only supported by MPEG-4.\n");
exit(1);
}
video_enc->max_b_frames = b_frames;
video_enc->b_frame_strategy = 0;
video_enc->b_quant_factor = 2.0;
video_enc->qmin = video_qmin;
video_enc->qmax = video_qmax;
video_enc->mb_qmin = video_mb_qmin;
video_enc->mb_qmax = video_mb_qmax;
video_enc->max_qdiff = video_qdiff;
video_enc->qblur = video_qblur;
video_enc->qcompress = video_qcomp;
video_enc->rc_eq = video_rc_eq;
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
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=
realloc(video_enc->rc_override, 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_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->dct_algo = dct_algo;
video_enc->idct_algo = idct_algo;
if(packet_size){
video_enc->rtp_mode= 1;
video_enc->rtp_payload_size= packet_size;
}
if (do_psnr)
video_enc->flags|= CODEC_FLAG_PSNR;
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;
}
/* XXX: need to find a way to set codec parameters */
if (oc->oformat->flags & AVFMT_RGB24) {
video_enc->pix_fmt = PIX_FMT_RGB24;
}
oc->streams[nb_streams] = st;
nb_streams++;
}
if (use_audio) {
AVCodecContext *audio_enc;
st = av_mallocz(sizeof(AVStream));
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
audio_enc = &st->codec;
audio_enc->codec_type = CODEC_TYPE_AUDIO;
if (audio_stream_copy) {
st->stream_copy = 1;
} else {
codec_id = file_oformat->audio_codec;
if (audio_codec_id != CODEC_ID_NONE)
codec_id = audio_codec_id;
audio_enc->codec_id = codec_id;
audio_enc->bit_rate = audio_bit_rate;
audio_enc->sample_rate = audio_sample_rate;
/* For audio codecs other than AC3 we limit */
/* the number of coded channels to stereo */
if (audio_channels > 2 && codec_id != CODEC_ID_AC3) {
audio_enc->channels = 2;
} else
audio_enc->channels = audio_channels;
}
oc->streams[nb_streams] = st;
nb_streams++;
}
oc->nb_streams = nb_streams;
if (!nb_streams) {
Fabrice Bellard
committed
fprintf(stderr, "No audio or video streams available\n");
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)) {
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
/* test if it already exists to avoid loosing precious files */
if (!file_overwrite &&
(strchr(filename, ':') == NULL ||
strstart(filename, "file:", NULL))) {
if (url_exist(filename)) {
int c;
printf("File '%s' already exists. Overwrite ? [y/N] ", filename);
fflush(stdout);
c = getchar();
if (toupper(c) != 'Y') {
fprintf(stderr, "Not overwriting - exiting\n");
exit(1);
}
}
}
/* open the file */
if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
fprintf(stderr, "Could not open '%s'\n", filename);
exit(1);
}
}
/* reset some options */
file_oformat = NULL;
file_iformat = NULL;
audio_disable = 0;
video_disable = 0;
audio_codec_id = CODEC_ID_NONE;
video_codec_id = CODEC_ID_NONE;
audio_stream_copy = 0;
video_stream_copy = 0;
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
/* prepare dummy protocols for grab */
void prepare_grab(void)
{
int has_video, has_audio, i, j;
AVFormatContext *oc;
AVFormatContext *ic;
AVFormatParameters ap1, *ap = &ap1;
/* see if audio/video inputs are needed */
has_video = 0;
has_audio = 0;
memset(ap, 0, sizeof(*ap));
for(j=0;j<nb_output_files;j++) {
oc = output_files[j];
for(i=0;i<oc->nb_streams;i++) {
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:
if (enc->width > ap->width)
ap->width = enc->width;
if (enc->height > ap->height)
ap->height = enc->height;
if (enc->frame_rate > ap->frame_rate)
ap->frame_rate = enc->frame_rate;
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_device");
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
fprintf(stderr, "Could not find video grab device\n");
exit(1);
}
/* by now video grab has one stream */
ic->streams[0]->r_frame_rate = ap->frame_rate;
input_files[nb_input_files] = ic;
dump_format(ic, nb_input_files, v4l_device, 0);
nb_input_files++;
}
if (has_audio) {
AVInputFormat *fmt1;
fmt1 = av_find_input_format("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;
dump_format(ic, nb_input_files, audio_device, 0);
nb_input_files++;
}
}
/* open the necessary output devices for playing */
void prepare_play(void)
{
file_iformat = NULL;
file_oformat = guess_format("audio_device", NULL, NULL);
if (!file_oformat) {
fprintf(stderr, "Could not find audio device\n");
exit(1);
}
opt_output_file(audio_device);
}
/* same option as mencoder */
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;
}
INT64 getutime(void)
{
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
}
return av_gettime();
extern int ffm_nopts;
void opt_bitexact(void)
{
avcodec_set_bit_exact();
/* disable generate of real time pts in ffm (need to be supressed anyway) */
ffm_nopts = 1;
}
AVInputFormat *ifmt;
AVOutputFormat *ofmt;
URLProtocol *up;
AVCodec *p;
const char **pp;
printf("File formats:\n");
printf(" Encoding:");
for(ofmt = first_oformat; ofmt != NULL; ofmt = ofmt->next) {
printf(" %s", ofmt->name);
for(ifmt = first_iformat; ifmt != NULL; ifmt = ifmt->next) {
printf(" %s", ifmt->name);
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
}
printf("\n");
printf("Codecs:\n");
printf(" Encoders:");
for(p = first_avcodec; p != NULL; p = p->next) {
if (p->encode)
printf(" %s", p->name);
}
printf("\n");
printf(" Decoders:");
for(p = first_avcodec; p != NULL; p = p->next) {
if (p->decode)
printf(" %s", p->name);
}
printf("\n");
printf("Supported file protocols:");
for(up = first_protocol; up != NULL; up = up->next)
printf(" %s:", up->name);
printf("\n");
printf("Frame size abbreviations: sqcif qcif cif 4cif\n");
printf("Motion estimation methods:");
pp = motion_str;
while (*pp) {
printf(" %s", *pp);
if ((pp - motion_str + 1) == ME_ZERO)
else if ((pp - motion_str + 1) == ME_FULL)
else if ((pp - motion_str + 1) == ME_EPZS)
printf("(default)");
pp++;
}
printf("\n");
exit(1);
}
void show_help(void)
{
const char *prog;
prog = do_play ? "ffplay" : "ffmpeg";
printf("%s version " FFMPEG_VERSION ", Copyright (c) 2000, 2001, 2002 Fabrice Bellard\n",
prog);
if (!do_play) {
printf("usage: ffmpeg [[options] -i input_file]... {[options] outfile}...\n"
"Hyper fast MPEG1/MPEG4/H263/RV and AC3/MPEG audio encoder\n");
} else {
printf("usage: ffplay [options] input_file...\n"
"Simple audio player\n");
}
printf("\n"
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
"Main options are:\n");
for(i=0;i<2;i++) {
if (i == 1)
printf("\nAdvanced options are:\n");
for(po = options; po->name != NULL; po++) {
char buf[64];
expert = (po->flags & OPT_EXPERT) != 0;
if (expert == i) {
strcpy(buf, po->name);
if (po->flags & HAS_ARG) {
strcat(buf, " ");
strcat(buf, po->argname);
}
printf("-%-17s %s\n", buf, po->help);
}
}
}
exit(1);
}
const OptionDef options[] = {
{ "L", 0, {(void*)show_licence}, "show license" },
{ "h", 0, {(void*)show_help}, "show help" },
{ "formats", 0, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
{ "f", HAS_ARG, {(void*)opt_format}, "force format", "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" },
{ "t", HAS_ARG, {(void*)opt_recording_time}, "set the recording time", "duration" },
{ "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" },
{ "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" },
{ "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" },
{ "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" },
{ "pass", HAS_ARG, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" },
{ "passlogfile", HAS_ARG | OPT_STRING, {(void*)&pass_logfilename}, "select two pass log file name", "file" },
{ "b", HAS_ARG, {(void*)opt_video_bitrate}, "set video bitrate (in kbit/s)", "bitrate" },
{ "r", HAS_ARG, {(void*)opt_frame_rate}, "set frame rate (in Hz)", "rate" },
Philip Gladstone
committed
{ "em_rate", OPT_BOOL|OPT_EXPERT, {(void*)&emulate_frame_rate}, "makes img reading happen at nominal frame rate" },
{ "s", HAS_ARG, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
Michael Niedermayer
committed
{ "croptop", HAS_ARG, {(void*)opt_frame_crop_top}, "set top crop band size (in pixels)", "size" },
{ "cropbottom", HAS_ARG, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" },
{ "cropleft", HAS_ARG, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" },
{ "cropright", HAS_ARG, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" },
{ "g", HAS_ARG | OPT_EXPERT, {(void*)opt_gop_size}, "set the group of picture size", "gop_size" },
{ "intra", OPT_BOOL | OPT_EXPERT, {(void*)&intra_only}, "use only intra frames"},
{ "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
{ "qscale", HAS_ARG | OPT_EXPERT, {(void*)opt_qscale}, "use fixed video quantiser scale (VBR)", "q" },
{ "qmin", HAS_ARG | OPT_EXPERT, {(void*)opt_qmin}, "min video quantiser scale (VBR)", "q" },
{ "qmax", HAS_ARG | OPT_EXPERT, {(void*)opt_qmax}, "max video quantiser scale (VBR)", "q" },
{ "mbqmin", HAS_ARG | OPT_EXPERT, {(void*)opt_mb_qmin}, "min macroblock quantiser scale (VBR)", "q" },
{ "mbqmax", HAS_ARG | OPT_EXPERT, {(void*)opt_mb_qmax}, "max macroblock quantiser scale (VBR)", "q" },
{ "qdiff", HAS_ARG | OPT_EXPERT, {(void*)opt_qdiff}, "max difference between the quantiser scale (VBR)", "q" },
{ "qblur", HAS_ARG | OPT_EXPERT, {(void*)opt_qblur}, "video quantiser scale blur (VBR)", "blur" },
{ "qcomp", HAS_ARG | OPT_EXPERT, {(void*)opt_qcomp}, "video quantiser scale compression (VBR)", "compression" },
{ "rc_init_cplx", HAS_ARG | OPT_EXPERT, {(void*)opt_rc_initial_cplx}, "initial complexity for 1-pass encoding", "complexity" },
{ "b_qfactor", HAS_ARG | OPT_EXPERT, {(void*)opt_b_qfactor}, "qp factor between p and b frames", "factor" },
{ "i_qfactor", HAS_ARG | OPT_EXPERT, {(void*)opt_i_qfactor}, "qp factor between p and i frames", "factor" },
{ "b_qoffset", HAS_ARG | OPT_EXPERT, {(void*)opt_b_qoffset}, "qp offset between p and b frames", "offset" },
{ "i_qoffset", HAS_ARG | OPT_EXPERT, {(void*)opt_i_qoffset}, "qp offset between p and i frames", "offset" },
// { "b_strategy", HAS_ARG | OPT_EXPERT, {(void*)opt_b_strategy}, "dynamic b frame selection strategy", "strategy" },
{ "rc_eq", HAS_ARG | OPT_EXPERT, {(void*)opt_video_rc_eq}, "", "equation" },
{ "rc_override", HAS_ARG | OPT_EXPERT, {(void*)opt_video_rc_override_string}, "Rate control override", "qualities for specific intervals" },
{ "bt", HAS_ARG, {(void*)opt_video_bitrate_tolerance}, "set video bitrate tolerance (in kbit/s)", "tolerance" },
{ "maxrate", HAS_ARG, {(void*)opt_video_bitrate_max}, "set max video bitrate tolerance (in kbit/s)", "bitrate" },
{ "minrate", HAS_ARG, {(void*)opt_video_bitrate_min}, "set min video bitrate tolerance (in kbit/s)", "bitrate" },
{ "bufsize", HAS_ARG, {(void*)opt_video_buffer_size}, "set ratecontrol buffere size (in kbit)", "size" },
{ "vd", HAS_ARG | OPT_EXPERT, {(void*)opt_video_device}, "set video grab device", "device" },
{ "vcodec", HAS_ARG | OPT_EXPERT, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
{ "me", HAS_ARG | OPT_EXPERT, {(void*)opt_motion_estimation}, "set motion estimation method",
{ "dct_algo", HAS_ARG | OPT_EXPERT, {(void*)opt_dct_algo}, "set dct algo", "algo" },
{ "idct_algo", HAS_ARG | OPT_EXPERT, {(void*)opt_idct_algo}, "set idct algo", "algo" },
{ "er", HAS_ARG | OPT_EXPERT, {(void*)opt_error_resilience}, "set error resilience", "" },
{ "ec", HAS_ARG | OPT_EXPERT, {(void*)opt_error_concealment}, "set error concealment", "" },
{ "bf", HAS_ARG | OPT_EXPERT, {(void*)opt_b_frames}, "use 'frames' B frames (only MPEG-4)", "frames" },
{ "hq", OPT_BOOL | OPT_EXPERT, {(void*)&use_hq}, "activate high quality settings" },
{ "4mv", OPT_BOOL | OPT_EXPERT, {(void*)&use_4mv}, "use four motion vector by macroblock (only MPEG-4)" },
{ "part", OPT_BOOL | OPT_EXPERT, {(void*)&use_part}, "use data partitioning (only MPEG-4)" },
Michael Niedermayer
committed
{ "bug", HAS_ARG | OPT_EXPERT, {(void*)opt_workaround_bugs}, "workaround not auto detected encoder bugs", "param" },
{ "ps", HAS_ARG | OPT_EXPERT, {(void*)opt_packet_size}, "packet size", "size in bits" },
{ "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" },
{ "ab", HAS_ARG, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", },
{ "ar", HAS_ARG, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" },
{ "ac", HAS_ARG, {(void*)opt_audio_channels}, "set number of audio channels", "channels" },
{ "an", OPT_BOOL, {(void*)&audio_disable}, "disable audio" },
{ "ad", HAS_ARG | OPT_EXPERT, {(void*)opt_audio_device}, "set audio device", "device" },
{ "acodec", HAS_ARG | OPT_EXPERT, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
{ "deinterlace", OPT_BOOL | OPT_EXPERT, {(void*)&do_deinterlace},
"deinterlace pictures" },
{ "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
{ "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
"dump each input packet" },
{ "psnr", OPT_BOOL | OPT_EXPERT, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
{ "vstats", OPT_BOOL | OPT_EXPERT, {(void*)&do_vstats}, "dump video coding statistics to file" },
{ "bitexact", OPT_EXPERT, {(void*)opt_bitexact}, "only use bit exact algorithms (for codec testing)" },
{ "vhook", HAS_ARG | OPT_EXPERT, {(void*)add_frame_hooker}, "insert video processing module", "module name and parameters" },
{ NULL, },
};
int main(int argc, char **argv)
{
int optindex, i;
const char *opt, *arg;
const OptionDef *po;
INT64 ti;
av_register_all();
/* detect if invoked as player */
i = strlen(argv[0]);
if (i >= 6 && !strcmp(argv[0] + i - 6, "ffplay"))
do_play = 1;
/* parse options */
optindex = 1;
while (optindex < argc) {
opt = argv[optindex++];
if (opt[0] == '-' && opt[1] != '\0') {
po = options;
while (po->name != NULL) {
if (!strcmp(opt + 1, po->name))
break;
po++;
}
if (!po->name) {
fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], opt);
exit(1);
}
arg = NULL;
if (po->flags & HAS_ARG) {
if (!arg) {
fprintf(stderr, "%s: missing argument for option '%s'\n", argv[0], opt);
exit(1);
}
}
if (po->flags & OPT_STRING) {
char *str;
str = strdup(arg);
*po->u.str_arg = str;
} else if (po->flags & OPT_BOOL) {
*po->u.int_arg = 1;
} else {
po->u.func_arg(arg);
}
} else {
if (!do_play) {
opt_output_file(opt);
} else {
opt_input_file(opt);
}
if (!do_play) {
/* file converter / grab */
if (nb_output_files <= 0) {
fprintf(stderr, "Must supply at least one output file\n");
exit(1);
}
if (nb_input_files == 0) {
prepare_grab();
} else {
/* player */
if (nb_input_files <= 0) {
fprintf(stderr, "Must supply at least one input file\n");
exit(1);
}
prepare_play();
}
ti = getutime();
av_encode(output_files, nb_output_files, input_files, nb_input_files,
stream_maps, nb_stream_maps);
ti = getutime() - ti;
if (do_benchmark) {
printf("bench: utime=%0.3fs\n", ti / 1000000.0);
}
/* close files */
for(i=0;i<nb_output_files;i++) {
/* maybe av_close_output_file ??? */
AVFormatContext *s = output_files[i];
int j;
if (!(s->oformat->flags & AVFMT_NOFILE))
url_fclose(&s->pb);
for(j=0;j<s->nb_streams;j++)
av_free(s->streams[j]);
av_free(s);
for(i=0;i<nb_input_files;i++)
av_close_input_file(input_files[i]);
av_free_static();