Newer
Older
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->max_qdiff = video_qdiff;
video_enc->qblur = video_qblur;
video_enc->qcompress = video_qcomp;
video_enc->rc_eq = video_rc_eq;
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
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->get_psnr = 1;
else
video_enc->get_psnr = 0;
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)) {
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
/* 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;
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
/* 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);
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
}
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"
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
"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" },
{ "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" },
{ "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" },
{ "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_resilience}, "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" },
"use same video quality as source (implies VBR)" },
/* audio options */
{ "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)" },
{ 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 */
2504
2505
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
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)
arg = argv[optindex++];
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]);