X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=0b6da2e62baba91141ea49d549380f865ff8097d;hb=8d876a433cd0b8137a952e36a8ebd2ed5a42cd21;hp=eae34d6e6c89e1e728c92b9697fb31e1d6393508;hpb=f560dd8279e84c85f9d75cf411e2eb7316662a0b;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index eae34d6e6c8..0b6da2e62ba 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -1,6 +1,6 @@ /* * FFmpeg main - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2000-2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,8 +17,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define HAVE_AV_CONFIG_H +#include "common.h" #include "avformat.h" #include "framehook.h" +/* usleep() */ +#include "os_support.h" #ifndef CONFIG_WIN32 #include @@ -27,32 +30,22 @@ #include #include #include +#include +#endif +#ifdef CONFIG_OS2 +#include +#include +#include #endif #include #include +#include "cmdutils.h" + #if !defined(INFINITY) && defined(HUGE_VAL) #define INFINITY HUGE_VAL #endif -#define MAXINT64 INT64_C(0x7fffffffffffffff) - -typedef struct { - const char *name; - int flags; -#define HAS_ARG 0x0001 -#define OPT_BOOL 0x0002 -#define OPT_EXPERT 0x0004 -#define OPT_STRING 0x0008 - union { - void (*func_arg)(); - int *int_arg; - char **str_arg; - } u; - const char *help; - const char *argname; -} OptionDef; - /* select an input stream for an output stream */ typedef struct AVStreamMap { int file_index; @@ -61,7 +54,8 @@ typedef struct AVStreamMap { extern const OptionDef options[]; -void show_help(void); +static void show_help(void); +static void show_license(void); #define MAX_FILES 20 @@ -76,14 +70,17 @@ static int nb_stream_maps; static AVInputFormat *file_iformat; static AVOutputFormat *file_oformat; +static AVImageFormat *image_format; static int frame_width = 160; static int frame_height = 128; +static float frame_aspect_ratio = 0; +static enum PixelFormat frame_pix_fmt = PIX_FMT_YUV420P; static int frame_topBand = 0; static int frame_bottomBand = 0; static int frame_leftBand = 0; static int frame_rightBand = 0; -static int frame_rate = 25 * FRAME_RATE_BASE; -extern int emulate_frame_rate; +static int frame_rate = 25; +static int frame_rate_base = 1; static int video_bit_rate = 200*1000; static int video_bit_rate_tolerance = 4000*1000; static int video_qscale = 0; @@ -110,13 +107,15 @@ static float video_b_qfactor = 1.25; static float video_b_qoffset = 1.25; static float video_i_qfactor = -0.8; static float video_i_qoffset = 0.0; -static int me_method = 0; +static int me_method = ME_EPZS; static int video_disable = 0; static int video_codec_id = CODEC_ID_NONE; static int same_quality = 0; static int b_frames = 0; -static int use_hq = 0; +static int mb_decision = FF_MB_DECISION_SIMPLE; static int use_4mv = 0; +static int use_aic = 0; +static int use_umv = 0; static int do_deinterlace = 0; static int workaround_bugs = FF_BUG_AUTODETECT; static int error_resilience = 2; @@ -127,6 +126,7 @@ static int use_part = 0; static int packet_size = 0; static int strict = 0; static int debug = 0; +extern int loop_input; /* currently a hack */ static int gop_size = 12; static int intra_only = 0; @@ -136,7 +136,7 @@ static int audio_disable = 0; static int audio_channels = 1; static int audio_codec_id = CODEC_ID_NONE; -static INT64 recording_time = 0; +static int64_t recording_time = 0; static int file_overwrite = 0; static char *str_title = NULL; static char *str_author = NULL; @@ -144,22 +144,27 @@ static char *str_copyright = NULL; static char *str_comment = NULL; static int do_benchmark = 0; static int do_hex_dump = 0; -static int do_play = 0; static int do_psnr = 0; static int do_vstats = 0; static int do_pass = 0; +static int bitexact = 0; static char *pass_logfilename = NULL; static int audio_stream_copy = 0; static int video_stream_copy = 0; -#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass" +static int rate_emu = 0; -#if !defined(CONFIG_AUDIO_OSS) && !defined(CONFIG_AUDIO_BEOS) -const char *audio_device = "none"; -#endif -#ifndef CONFIG_VIDEO4LINUX -const char *v4l_device = "none"; -#endif +static char *video_grab_format = "video4linux"; +static char *video_device = NULL; +static int video_channel = 0; +static char *video_standard = "ntsc"; + +static char *audio_grab_format = "audio_device"; +static char *audio_device = NULL; + +static int using_stdin = 0; + +#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass" typedef struct AVOutputStream { int file_index; /* file index */ @@ -172,7 +177,7 @@ typedef struct AVOutputStream { for A/V sync */ double sync_ipts; double sync_ipts_offset; - INT64 sync_opts; + int64_t sync_opts; /* video only */ int video_resample; /* video_resample and video_crop are mutually exclusive */ AVPicture pict_tmp; /* temporary image for resampling */ @@ -195,8 +200,13 @@ typedef struct AVInputStream { AVStream *st; int discard; /* true if stream data should be discarded */ int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */ - INT64 sample_index; /* current sample */ + int64_t sample_index; /* current sample */ int frame_decoded; /* true if a video or audio frame has been decoded */ + + int64_t start; /* time when read started */ + unsigned long frame; /* current frame */ + AVFrac next_pts; /* synthetic pts for cases where pkt.pts == 0 */ + int64_t pts; /* current pts */ } AVInputStream; typedef struct AVInputFile { @@ -218,6 +228,15 @@ static void term_exit(void) tcsetattr (0, TCSANOW, &oldtty); } +static volatile sig_atomic_t received_sigterm = 0; + +static void +sigterm_handler(int sig) +{ + received_sigterm = sig; + term_exit(); +} + static void term_init(void) { struct termios tty; @@ -236,6 +255,12 @@ static void term_init(void) tcsetattr (0, TCSANOW, &tty); + signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */ + signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */ + signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */ + /* + register a function to be called at normal program termination + */ atexit(term_exit); #ifdef CONFIG_BEOS_NETSERVER fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); @@ -285,7 +310,7 @@ static int read_key(void) #endif -int read_ffserver_streams(AVFormatContext *s, const char *filename) +static int read_ffserver_streams(AVFormatContext *s, const char *filename) { int i, err; AVFormatContext *ic; @@ -298,7 +323,7 @@ int read_ffserver_streams(AVFormatContext *s, const char *filename) for(i=0;inb_streams;i++) { AVStream *st; - st = av_mallocz(sizeof(AVFormatContext)); + st = av_mallocz(sizeof(AVStream)); memcpy(st, ic->streams[i], sizeof(AVStream)); s->streams[i] = st; } @@ -307,19 +332,30 @@ int read_ffserver_streams(AVFormatContext *s, const char *filename) return 0; } -#define MAX_AUDIO_PACKET_SIZE 16384 +#define MAX_AUDIO_PACKET_SIZE (128 * 1024) static void do_audio_out(AVFormatContext *s, AVOutputStream *ost, AVInputStream *ist, unsigned char *buf, int size) { - UINT8 *buftmp; - UINT8 audio_buf[2*MAX_AUDIO_PACKET_SIZE]; /* XXX: allocate it */ - UINT8 audio_out[4*MAX_AUDIO_PACKET_SIZE]; /* XXX: allocate it - yep really WMA */ + uint8_t *buftmp; + static uint8_t *audio_buf = NULL; + static uint8_t *audio_out = NULL; + const int audio_out_size= 4*MAX_AUDIO_PACKET_SIZE; + int size_out, frame_bytes, ret; AVCodecContext *enc; + /* SC: dynamic allocation of buffers */ + if (!audio_buf) + audio_buf = av_malloc(2*MAX_AUDIO_PACKET_SIZE); + if (!audio_out) + audio_out = av_malloc(audio_out_size); + if (!audio_buf || !audio_out) + return; /* Should signal an error ! */ + + enc = &ost->st->codec; if (ost->audio_resample) { @@ -343,7 +379,7 @@ static void do_audio_out(AVFormatContext *s, while (fifo_read(&ost->fifo, audio_buf, frame_bytes, &ost->fifo.rptr) == 0) { - ret = avcodec_encode_audio(enc, audio_out, sizeof(audio_out), + ret = avcodec_encode_audio(enc, audio_out, audio_out_size, (short *)audio_buf); av_write_frame(s, ost->index, audio_out, ret); } @@ -366,108 +402,12 @@ static void do_audio_out(AVFormatContext *s, } } -/* write a picture to a raw mux */ -static void write_picture(AVFormatContext *s, int index, AVPicture *picture, - int pix_fmt, int w, int h) -{ - UINT8 *buf, *src, *dest; - int size, j, i; - - /* XXX: not efficient, should add test if we can take - directly the AVPicture */ - switch(pix_fmt) { - case PIX_FMT_YUV420P: - size = avpicture_get_size(pix_fmt, w, h); - buf = av_malloc(size); - if (!buf) - return; - dest = buf; - for(i=0;i<3;i++) { - if (i == 1) { - w >>= 1; - h >>= 1; - } - src = picture->data[i]; - for(j=0;jlinesize[i]; - } - } - break; - case PIX_FMT_YUV422P: - size = (w * h) * 2; - buf = av_malloc(size); - if (!buf) - return; - dest = buf; - for(i=0;i<3;i++) { - if (i == 1) { - w >>= 1; - } - src = picture->data[i]; - for(j=0;jlinesize[i]; - } - } - break; - case PIX_FMT_YUV444P: - size = (w * h) * 3; - buf = av_malloc(size); - if (!buf) - return; - dest = buf; - for(i=0;i<3;i++) { - src = picture->data[i]; - for(j=0;jlinesize[i]; - } - } - break; - case PIX_FMT_YUV422: - size = (w * h) * 2; - buf = av_malloc(size); - if (!buf) - return; - dest = buf; - src = picture->data[0]; - for(j=0;jlinesize[0]; - } - break; - case PIX_FMT_RGB24: - case PIX_FMT_BGR24: - size = (w * h) * 3; - buf = av_malloc(size); - if (!buf) - return; - dest = buf; - src = picture->data[0]; - for(j=0;jlinesize[0]; - } - break; - default: - return; - } - av_write_frame(s, index, buf, size); - av_free(buf); -} - static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void **bufp) { AVCodecContext *dec; AVPicture *picture2; AVPicture picture_tmp; - UINT8 *buf = 0; + uint8_t *buf = 0; dec = &ist->st->codec; @@ -514,8 +454,8 @@ static void do_video_out(AVFormatContext *s, int nb_frames, i, ret; AVPicture *final_picture, *formatted_picture; AVPicture picture_format_temp, picture_crop_temp; - static UINT8 *video_buffer; - UINT8 *buf = NULL, *buf1 = NULL; + static uint8_t *video_buffer; + uint8_t *buf = NULL, *buf1 = NULL; AVCodecContext *enc, *dec; #define VIDEO_BUFFER_SIZE (1024*1024) @@ -526,57 +466,55 @@ static void do_video_out(AVFormatContext *s, /* by default, we output a single frame */ nb_frames = 1; + *frame_size = 0; + /* NOTE: the A/V sync is always done by considering the audio is the master clock. It is suffisant for transcoding or playing, but not for the general case */ if (audio_sync) { /* compute the A-V delay and duplicate/remove frames if needed */ - double adelta, vdelta, apts, vpts, av_delay; - - if (audio_sync->sync_ipts != AV_NOPTS_VALUE && - ost->sync_ipts != AV_NOPTS_VALUE) { - - adelta = (double)(ost->st->pts.val - audio_sync->sync_opts) * - s->pts_num / s->pts_den; - apts = audio_sync->sync_ipts + adelta; - - vdelta = (double)(ost->st->pts.val - ost->sync_opts) * - s->pts_num / s->pts_den; - vpts = ost->sync_ipts + vdelta; - - av_delay = apts - vpts; - // printf("delay=%f\n", av_delay); - if (av_delay < -AV_DELAY_MAX) - nb_frames = 2; - else if (av_delay > AV_DELAY_MAX) - nb_frames = 0; - } + double adelta, vdelta, av_delay; + + adelta = audio_sync->sync_ipts - ((double)audio_sync->sync_opts * + s->pts_num / s->pts_den); + + vdelta = ost->sync_ipts - ((double)ost->sync_opts * + s->pts_num / s->pts_den); + + av_delay = adelta - vdelta; + // printf("delay=%f\n", av_delay); + if (av_delay < -AV_DELAY_MAX) + nb_frames = 2; + else if (av_delay > AV_DELAY_MAX) + nb_frames = 0; } else { double vdelta; - if (ost->sync_ipts != AV_NOPTS_VALUE) { - vdelta = (double)(ost->st->pts.val) * s->pts_num / s->pts_den - (ost->sync_ipts - ost->sync_ipts_offset); - if (vdelta < 100 && vdelta > -100 && ost->sync_ipts_offset) { - if (vdelta < -AV_DELAY_MAX) - nb_frames = 2; - else if (vdelta > AV_DELAY_MAX) - nb_frames = 0; - } else { - ost->sync_ipts_offset -= vdelta; - if (!ost->sync_ipts_offset) - ost->sync_ipts_offset = 0.000001; /* one microsecond */ - } - -#if defined(PJSG) - { - static char *action[] = { "drop frame", "copy frame", "dup frame" }; - printf("Input PTS %12.6f, output PTS %12.6f: %s\n", - (double) ost->sync_ipts, (double) ost->st->pts.val * s->pts_num / s->pts_den, - action[nb_frames]); - } -#endif + vdelta = (double)(ost->st->pts.val) * s->pts_num / s->pts_den - (ost->sync_ipts - ost->sync_ipts_offset); + if (vdelta < 100 && vdelta > -100 && ost->sync_ipts_offset) { + if (vdelta < -AV_DELAY_MAX) + nb_frames = 2; + else if (vdelta > AV_DELAY_MAX) + nb_frames = 0; + } else { + ost->sync_ipts_offset -= vdelta; + if (!ost->sync_ipts_offset) + ost->sync_ipts_offset = 0.000001; /* one microsecond */ } } + +#if defined(AVSYNC_DEBUG) + static char *action[] = { "drop frame", "copy frame", "dup frame" }; + if (audio_sync) + fprintf(stderr, "Input APTS %12.6f, output APTS %12.6f, ", + (double) audio_sync->sync_ipts, + (double) audio_sync->st->pts.val * s->pts_num / s->pts_den); + fprintf(stderr, "Input VPTS %12.6f, output VPTS %12.6f: %s\n", + (double) ost->sync_ipts, + (double) ost->st->pts.val * s->pts_num / s->pts_den, + action[nb_frames]); +#endif + if (nb_frames <= 0) return; @@ -635,7 +573,13 @@ static void do_video_out(AVFormatContext *s, /* duplicates frame if needed */ /* XXX: pb because no interleaving */ for(i=0;icodec_id != CODEC_ID_RAWVIDEO) { + if (s->oformat->flags & AVFMT_RAWPICTURE) { + /* raw pictures are written as AVPicture structure to + avoid any copies. We support temorarily the older + method. */ + av_write_frame(s, ost->index, + (uint8_t *)final_picture, sizeof(AVPicture)); + } else { AVFrame big_picture; memset(&big_picture, 0, sizeof(AVFrame)); @@ -661,17 +605,6 @@ static void do_video_out(AVFormatContext *s, if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } - } else { - if (s->oformat->flags & AVFMT_RAWPICTURE) { - /* raw pictures are written as AVPicture structure to - avoid any copies. We support temorarily the older - method. */ - av_write_frame(s, ost->index, - (UINT8 *)final_picture, sizeof(AVPicture)); - } else { - write_picture(s, ost->index, final_picture, enc->pix_fmt, - enc->width, enc->height); - } } ost->frame_number++; } @@ -682,20 +615,20 @@ static void do_video_out(AVFormatContext *s, static double psnr(double d){ if(d==0) return INFINITY; - return -10.0*log(d)/log(10); + return -10.0*log(d)/log(10.0); } static void do_video_stats(AVFormatContext *os, AVOutputStream *ost, int frame_size) { static FILE *fvstats=NULL; - static INT64 total_size = 0; + static int64_t total_size = 0; char filename[40]; time_t today2; struct tm *today; AVCodecContext *enc; int frame_number; - INT64 ti; + int64_t ti; double ti1, bitrate, avg_bitrate; if (!fvstats) { @@ -726,29 +659,29 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost, if (ti1 < 0.01) ti1 = 0.01; - bitrate = (double)(frame_size * 8) * enc->frame_rate / FRAME_RATE_BASE / 1000.0; + bitrate = (double)(frame_size * 8) * enc->frame_rate / enc->frame_rate_base / 1000.0; avg_bitrate = (double)(total_size * 8) / ti1 / 1000.0; fprintf(fvstats, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", (double)total_size / 1024, ti1, bitrate, avg_bitrate); - fprintf(fvstats,"type= %s\n", enc->coded_frame->key_frame == 1 ? "I" : "P"); + fprintf(fvstats,"type= %c\n", av_get_pict_type_char(enc->coded_frame->pict_type)); } } -void print_report(AVFormatContext **output_files, - AVOutputStream **ost_table, int nb_ostreams, - int is_last_report) +static void print_report(AVFormatContext **output_files, + AVOutputStream **ost_table, int nb_ostreams, + int is_last_report) { char buf[1024]; AVOutputStream *ost; AVFormatContext *oc, *os; - INT64 total_size; + int64_t total_size; AVCodecContext *enc; int frame_number, vid, i; double bitrate, ti1, pts; - static INT64 last_time = -1; + static int64_t last_time = -1; if (!is_last_report) { - INT64 cur_time; + int64_t cur_time; /* display the report every 0.5 seconds */ cur_time = av_gettime(); if (last_time == -1) { @@ -816,7 +749,7 @@ static int av_encode(AVFormatContext **output_files, int nb_input_files, AVStreamMap *stream_maps, int nb_stream_maps) { - int ret, i, j, k, n, nb_istreams = 0, nb_ostreams = 0, pts_set; + int ret, i, j, k, n, nb_istreams = 0, nb_ostreams = 0; AVFormatContext *is, *os; AVCodecContext *codec, *icodec; AVOutputStream *ost, **ost_table = NULL; @@ -859,6 +792,11 @@ static int av_encode(AVFormatContext **output_files, ist->index = k; ist->discard = 1; /* the stream is discarded by default (changed later) */ + + if (ist->st->codec.rate_emu) { + ist->start = av_gettime(); + ist->frame = 0; + } } } @@ -873,6 +811,18 @@ static int av_encode(AVFormatContext **output_files, exit(1); } + /* Sanity check the mapping args -- do the input files & streams exist? */ + for(i=0;i nb_input_files - 1 || + si < 0 || si > file_table[fi].nb_streams - 1) { + fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si); + exit(1); + } + } + ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams); if (!ost_table) goto fail; @@ -895,6 +845,15 @@ static int av_encode(AVFormatContext **output_files, if (nb_stream_maps > 0) { ost->source_index = file_table[stream_maps[n-1].file_index].ist_index + stream_maps[n-1].stream_index; + + /* Sanity check that the stream types match */ + if (ist_table[ost->source_index]->st->codec.codec_type != ost->st->codec.codec_type) { + fprintf(stderr, "Codec type mismatch for mapping #%d.%d -> #%d.%d\n", + stream_maps[n-1].file_index, stream_maps[n-1].stream_index, + ost->file_index, ost->index); + exit(1); + } + } else { /* get corresponding input stream index : we select the first one with the right type */ found = 0; @@ -949,6 +908,7 @@ static int av_encode(AVFormatContext **output_files, break; case CODEC_TYPE_VIDEO: codec->frame_rate = icodec->frame_rate; + codec->frame_rate_base = icodec->frame_rate_base; codec->width = icodec->width; codec->height = icodec->height; break; @@ -978,6 +938,11 @@ static int av_encode(AVFormatContext **output_files, ost->resample = audio_resample_init(codec->channels, icodec->channels, codec->sample_rate, icodec->sample_rate); + if(!ost->resample) + { + printf("Can't resample. Aborting.\n"); + av_abort(); + } } /* Request specific number of channels */ icodec->channels = codec->channels; @@ -986,6 +951,11 @@ static int av_encode(AVFormatContext **output_files, ost->resample = audio_resample_init(codec->channels, icodec->channels, codec->sample_rate, icodec->sample_rate); + if(!ost->resample) + { + printf("Can't resample. Aborting.\n"); + av_abort(); + } } } ist->decoding_needed = 1; @@ -1011,7 +981,7 @@ static int av_encode(AVFormatContext **output_files, ost->topBand = frame_topBand; ost->leftBand = frame_leftBand; } else { - UINT8 *buf; + uint8_t *buf; ost->video_resample = 1; ost->video_crop = 0; // cropping is handled as part of resample buf = av_malloc((codec->width * codec->height * 3) / 2); @@ -1139,6 +1109,20 @@ static int av_encode(AVFormatContext **output_files, /* init pts */ for(i=0;ifile_index]; + ist->pts = 0; + switch (ist->st->codec.codec_type) { + case CODEC_TYPE_AUDIO: + av_frac_init(&ist->next_pts, + 0, 0, is->pts_num * ist->st->codec.sample_rate); + break; + case CODEC_TYPE_VIDEO: + av_frac_init(&ist->next_pts, + 0, 0, is->pts_num * ist->st->codec.frame_rate); + break; + default: + break; + } } /* compute buffer size max (should use a complete heuristic) */ @@ -1157,23 +1141,20 @@ static int av_encode(AVFormatContext **output_files, } #ifndef CONFIG_WIN32 - if (!do_play) { + if ( !using_stdin ) fprintf(stderr, "Press [q] to stop encoding\n"); - } else { - fprintf(stderr, "Press [q] to stop playing\n"); - } #endif term_init(); stream_no_data = 0; key = -1; - for(;;) { + for(; received_sigterm == 0;) { int file_index, ist_index; AVPacket pkt; - UINT8 *ptr; + uint8_t *ptr; int len; - UINT8 *data_buf; + uint8_t *data_buf; int data_size, got_picture; AVPicture picture; short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2]; @@ -1182,7 +1163,7 @@ static int av_encode(AVFormatContext **output_files, redo: /* if 'q' pressed, exits */ - if (key) { + if (!using_stdin) { /* read_key() returns 0 on EOF */ key = read_key(); if (key == 'q') @@ -1225,6 +1206,10 @@ static int av_encode(AVFormatContext **output_files, } else { stream_no_data = 0; } + if (do_hex_dump) { + printf("stream #%d, size=%d:\n", pkt.stream_index, pkt.size); + av_hex_dump(pkt.data, pkt.size); + } /* the following test is needed in case new streams appear dynamically in stream : we ignore them */ if (pkt.stream_index >= file_table[file_index].nb_streams) @@ -1234,21 +1219,11 @@ static int av_encode(AVFormatContext **output_files, if (ist->discard) goto discard_packet; - if (do_hex_dump) { - printf("stream #%d, size=%d:\n", pkt.stream_index, pkt.size); - av_hex_dump(pkt.data, pkt.size); - } - // printf("read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size); len = pkt.size; ptr = pkt.data; - pts_set = 0; while (len > 0) { - INT64 ipts; - - ipts = AV_NOPTS_VALUE; - /* decode the packet if needed */ data_buf = NULL; /* fail safe */ data_size = 0; @@ -1257,12 +1232,17 @@ static int av_encode(AVFormatContext **output_files, frame has begun (MPEG semantics) */ /* NOTE2: even if the fraction is not initialized, av_frac_set can be used to set the integer part */ - if (ist->frame_decoded && - pkt.pts != AV_NOPTS_VALUE && - !pts_set) { - ipts = pkt.pts; + if (ist->frame_decoded) { + /* If pts is unavailable -- we have to use synthetic one */ + if( pkt.pts != AV_NOPTS_VALUE ) + { + ist->pts = ist->next_pts.val = pkt.pts; + } + else + { + ist->pts = ist->next_pts.val; + } ist->frame_decoded = 0; - pts_set = 1; } switch(ist->st->codec.codec_type) { @@ -1281,19 +1261,12 @@ static int av_encode(AVFormatContext **output_files, len -= ret; continue; } - data_buf = (UINT8 *)samples; + data_buf = (uint8_t *)samples; + av_frac_add(&ist->next_pts, + is->pts_den * data_size / (2 * ist->st->codec.channels)); break; case CODEC_TYPE_VIDEO: - if (ist->st->codec.codec_id == CODEC_ID_RAWVIDEO) { - int size; - - size = (ist->st->codec.width * ist->st->codec.height); - avpicture_fill(&picture, ptr, - ist->st->codec.pix_fmt, - ist->st->codec.width, - ist->st->codec.height); - ret = len; - } else { + { AVFrame big_picture; data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2; @@ -1314,7 +1287,8 @@ static int av_encode(AVFormatContext **output_files, len -= ret; continue; } - + av_frac_add(&ist->next_pts, + is->pts_den * ist->st->codec.frame_rate_base); } break; default: @@ -1335,13 +1309,23 @@ static int av_encode(AVFormatContext **output_files, ist->frame_decoded = 1; + /* frame rate emulation */ + if (ist->st->codec.rate_emu) { + int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate); + int64_t now = av_gettime() - ist->start; + if (pts > now) + usleep(pts - now); + + ist->frame++; + } + #if 0 /* mpeg PTS deordering : if it is a P or I frame, the PTS is the one of the next displayed one */ /* XXX: add mpeg4 too ? */ if (ist->st->codec.codec_id == CODEC_ID_MPEG1VIDEO) { if (ist->st->codec.pict_type != B_TYPE) { - INT64 tmp; + int64_t tmp; tmp = ist->last_ip_pts; ist->last_ip_pts = ist->frac_pts.val; ist->frac_pts.val = tmp; @@ -1357,23 +1341,17 @@ static int av_encode(AVFormatContext **output_files, if (ost->source_index == ist_index) { os = output_files[ost->file_index]; - if (ipts != AV_NOPTS_VALUE) { #if 0 - printf("%d: got pts=%f %f\n", - i, pkt.pts / 90000.0, - (ipts - ost->st->pts.val) / 90000.0); + printf("%d: got pts=%f %f\n", i, pkt.pts / 90000.0, + (ist->pts - ost->st->pts.val) / 90000.0); #endif - /* set the input output pts pairs */ - ost->sync_ipts = (double)ipts * is->pts_num / - is->pts_den; - /* XXX: take into account the various fifos, - in particular for audio */ - ost->sync_opts = ost->st->pts.val; - //printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt.pts=%lld\n", ipts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts); - } else { - //printf("pts.val=%lld\n", ost->st->pts.val); - ost->sync_ipts = AV_NOPTS_VALUE; - } + /* set the input output pts pairs */ + ost->sync_ipts = (double)ist->pts * is->pts_num / + is->pts_den; + /* XXX: take into account the various fifos, + in particular for audio */ + ost->sync_opts = ost->st->pts.val; + //printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt.pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts); if (ost->encoding_needed) { switch(ost->st->codec.codec_type) { @@ -1396,7 +1374,7 @@ static int av_encode(AVFormatContext **output_files, } do_video_out(os, ost, ist, &picture, &frame_size, audio_sync); - if (do_vstats) + if (do_vstats && frame_size) do_video_stats(os, ost, frame_size); } break; @@ -1409,9 +1387,9 @@ static int av_encode(AVFormatContext **output_files, /* no reencoding needed : output the packet directly */ /* force the input stream PTS */ - //XXX/FIXME set keyframe flag from demuxer (or optionally from decoder) memset(&avframe, 0, sizeof(AVFrame)); ost->st->codec.coded_frame= &avframe; + avframe.key_frame = pkt.flags & PKT_FLAG_KEY; av_write_frame(os, ost->index, data_buf, data_size); ost->st->codec.frame_number++; @@ -1420,7 +1398,6 @@ static int av_encode(AVFormatContext **output_files, } } av_free(buffer_to_free); - ipts = AV_NOPTS_VALUE; } discard_packet: av_free_packet(&pkt); @@ -1517,30 +1494,29 @@ int file_read(const char *filename) } #endif -void show_licence(void) +static void opt_image_format(const char *arg) { - printf( - "ffmpeg version " FFMPEG_VERSION "\n" - "Copyright (c) 2000, 2001, 2002 Fabrice Bellard\n" - "This library is free software; you can redistribute it and/or\n" - "modify it under the terms of the GNU Lesser General Public\n" - "License as published by the Free Software Foundation; either\n" - "version 2 of the License, or (at your option) any later version.\n" - "\n" - "This library is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" - "Lesser General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU Lesser General Public\n" - "License along with this library; if not, write to the Free Software\n" - "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" - ); - exit(1); + AVImageFormat *f; + + for(f = first_image_format; f != NULL; f = f->next) { + if (!strcmp(arg, f->name)) + break; + } + if (!f) { + fprintf(stderr, "Unknown image format: '%s'\n", arg); + exit(1); + } + image_format = f; } -void opt_format(const char *arg) +static void opt_format(const char *arg) { + /* compatibility stuff for pgmyuv */ + if (!strcmp(arg, "pgmyuv")) { + opt_image_format(arg); + arg = "image"; + } + file_iformat = av_find_input_format(arg); file_oformat = guess_format(arg, NULL, NULL); if (!file_iformat && !file_oformat) { @@ -1549,80 +1525,82 @@ void opt_format(const char *arg) } } -void opt_video_bitrate(const char *arg) +static void opt_video_bitrate(const char *arg) { video_bit_rate = atoi(arg) * 1000; } -void opt_video_bitrate_tolerance(const char *arg) +static void opt_video_bitrate_tolerance(const char *arg) { video_bit_rate_tolerance = atoi(arg) * 1000; } -void opt_video_bitrate_max(const char *arg) +static void opt_video_bitrate_max(const char *arg) { video_rc_max_rate = atoi(arg) * 1000; } -void opt_video_bitrate_min(const char *arg) +static void opt_video_bitrate_min(const char *arg) { video_rc_min_rate = atoi(arg) * 1000; } -void opt_video_buffer_size(const char *arg) +static void opt_video_buffer_size(const char *arg) { video_rc_buffer_size = atoi(arg) * 1000; } -void opt_video_rc_eq(char *arg) +static void opt_video_rc_eq(char *arg) { video_rc_eq = arg; } -void opt_video_rc_override_string(char *arg) +static void opt_video_rc_override_string(char *arg) { video_rc_override_string = arg; } -void opt_workaround_bugs(const char *arg) +static void opt_workaround_bugs(const char *arg) { workaround_bugs = atoi(arg); } -void opt_dct_algo(const char *arg) +static void opt_dct_algo(const char *arg) { dct_algo = atoi(arg); } -void opt_idct_algo(const char *arg) +static void opt_idct_algo(const char *arg) { idct_algo = atoi(arg); } -void opt_error_resilience(const char *arg) +static void opt_error_resilience(const char *arg) { error_resilience = atoi(arg); } -void opt_error_concealment(const char *arg) +static void opt_error_concealment(const char *arg) { error_concealment = atoi(arg); } -void opt_debug(const char *arg) +static void opt_debug(const char *arg) { debug = atoi(arg); } -void opt_frame_rate(const char *arg) +static void opt_frame_rate(const char *arg) { - frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE); + if (parse_frame_rate(&frame_rate, &frame_rate_base, arg) < 0) { + fprintf(stderr, "Incorrect frame rate\n"); + exit(1); + } } - -void opt_frame_crop_top(const char *arg) +static void opt_frame_crop_top(const char *arg) { frame_topBand = atoi(arg); if (frame_topBand < 0) { @@ -1640,7 +1618,7 @@ void opt_frame_crop_top(const char *arg) frame_height -= frame_topBand; } -void opt_frame_crop_bottom(const char *arg) +static void opt_frame_crop_bottom(const char *arg) { frame_bottomBand = atoi(arg); if (frame_bottomBand < 0) { @@ -1658,7 +1636,7 @@ void opt_frame_crop_bottom(const char *arg) frame_height -= frame_bottomBand; } -void opt_frame_crop_left(const char *arg) +static void opt_frame_crop_left(const char *arg) { frame_leftBand = atoi(arg); if (frame_leftBand < 0) { @@ -1676,7 +1654,7 @@ void opt_frame_crop_left(const char *arg) frame_width -= frame_leftBand; } -void opt_frame_crop_right(const char *arg) +static void opt_frame_crop_right(const char *arg) { frame_rightBand = atoi(arg); if (frame_rightBand < 0) { @@ -1694,10 +1672,9 @@ void opt_frame_crop_right(const char *arg) frame_width -= frame_rightBand; } -void opt_frame_size(const char *arg) +static void opt_frame_size(const char *arg) { - parse_image_size(&frame_width, &frame_height, arg); - if (frame_width <= 0 || frame_height <= 0) { + if (parse_image_size(&frame_width, &frame_height, arg) < 0) { fprintf(stderr, "Incorrect frame size\n"); exit(1); } @@ -1707,12 +1684,40 @@ void opt_frame_size(const char *arg) } } -void opt_gop_size(const char *arg) +static void opt_frame_pix_fmt(const char *arg) +{ + frame_pix_fmt = avcodec_get_pix_fmt(arg); +} + +static void opt_frame_aspect_ratio(const char *arg) +{ + int x = 0, y = 0; + double ar = 0; + const char *p; + + p = strchr(arg, ':'); + if (p) { + x = strtol(arg, (char **)&arg, 10); + if (arg == p) + y = strtol(arg+1, (char **)&arg, 10); + if (x > 0 && y > 0) + ar = (double)x / (double)y; + } else + ar = strtod(arg, (char **)&arg); + + if (!ar) { + fprintf(stderr, "Incorrect aspect ratio specification.\n"); + exit(1); + } + frame_aspect_ratio = ar; +} + +static void opt_gop_size(const char *arg) { gop_size = atoi(arg); } -void opt_b_frames(const char *arg) +static void opt_b_frames(const char *arg) { b_frames = atoi(arg); if (b_frames > FF_MAX_B_FRAMES) { @@ -1724,7 +1729,12 @@ void opt_b_frames(const char *arg) } } -void opt_qscale(const char *arg) +static void opt_mb_decision(const char *arg) +{ + mb_decision = atoi(arg); +} + +static void opt_qscale(const char *arg) { video_qscale = atoi(arg); if (video_qscale < 0 || @@ -1734,7 +1744,7 @@ void opt_qscale(const char *arg) } } -void opt_qmin(const char *arg) +static void opt_qmin(const char *arg) { video_qmin = atoi(arg); if (video_qmin < 0 || @@ -1744,7 +1754,7 @@ void opt_qmin(const char *arg) } } -void opt_qmax(const char *arg) +static void opt_qmax(const char *arg) { video_qmax = atoi(arg); if (video_qmax < 0 || @@ -1754,7 +1764,7 @@ void opt_qmax(const char *arg) } } -void opt_mb_qmin(const char *arg) +static void opt_mb_qmin(const char *arg) { video_mb_qmin = atoi(arg); if (video_mb_qmin < 0 || @@ -1764,7 +1774,7 @@ void opt_mb_qmin(const char *arg) } } -void opt_mb_qmax(const char *arg) +static void opt_mb_qmax(const char *arg) { video_mb_qmax = atoi(arg); if (video_mb_qmax < 0 || @@ -1774,7 +1784,7 @@ void opt_mb_qmax(const char *arg) } } -void opt_qdiff(const char *arg) +static void opt_qdiff(const char *arg) { video_qdiff = atoi(arg); if (video_qdiff < 0 || @@ -1784,73 +1794,89 @@ void opt_qdiff(const char *arg) } } -void opt_qblur(const char *arg) +static void opt_qblur(const char *arg) { video_qblur = atof(arg); } -void opt_qcomp(const char *arg) +static void opt_qcomp(const char *arg) { video_qcomp = atof(arg); } -void opt_rc_initial_cplx(const char *arg) +static void opt_rc_initial_cplx(const char *arg) { video_rc_initial_cplx = atof(arg); } -void opt_b_qfactor(const char *arg) +static void opt_b_qfactor(const char *arg) { video_b_qfactor = atof(arg); } -void opt_i_qfactor(const char *arg) +static void opt_i_qfactor(const char *arg) { video_i_qfactor = atof(arg); } -void opt_b_qoffset(const char *arg) +static void opt_b_qoffset(const char *arg) { video_b_qoffset = atof(arg); } -void opt_i_qoffset(const char *arg) +static void opt_i_qoffset(const char *arg) { video_i_qoffset = atof(arg); } -void opt_packet_size(const char *arg) +static void opt_packet_size(const char *arg) { packet_size= atoi(arg); } -void opt_strict(const char *arg) +static void opt_strict(const char *arg) { strict= atoi(arg); } -void opt_audio_bitrate(const char *arg) +static void opt_audio_bitrate(const char *arg) { audio_bit_rate = atoi(arg) * 1000; } -void opt_audio_rate(const char *arg) +static void opt_audio_rate(const char *arg) { audio_sample_rate = atoi(arg); } -void opt_audio_channels(const char *arg) +static void opt_audio_channels(const char *arg) { audio_channels = atoi(arg); } -void opt_video_device(const char *arg) +static void opt_video_device(const char *arg) { - v4l_device = strdup(arg); + video_device = av_strdup(arg); } -void opt_audio_device(const char *arg) +static void opt_video_channel(const char *arg) { - audio_device = strdup(arg); + video_channel = strtol(arg, NULL, 0); } -void opt_audio_codec(const char *arg) +static void opt_video_standard(const char *arg) +{ + video_standard = av_strdup(arg); +} + +static void opt_audio_device(const char *arg) +{ + audio_device = av_strdup(arg); +} + +static void opt_dv1394(const char *arg) +{ + video_grab_format = "dv1394"; + audio_grab_format = NULL; +} + +static void opt_audio_codec(const char *arg) { AVCodec *p; @@ -1872,12 +1898,12 @@ void opt_audio_codec(const char *arg) } } -void add_frame_hooker(const char *arg) +static void add_frame_hooker(const char *arg) { int argc = 0; char *argv[64]; int i; - char *args = strdup(arg); + char *args = av_strdup(arg); argv[0] = strtok(args, " "); while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) { @@ -1901,7 +1927,7 @@ const char *motion_str[] = { NULL, }; -void opt_motion_estimation(const char *arg) +static void opt_motion_estimation(const char *arg) { const char **p; p = motion_str; @@ -1917,7 +1943,7 @@ void opt_motion_estimation(const char *arg) me_method = (p - motion_str) + 1; } -void opt_video_codec(const char *arg) +static void opt_video_codec(const char *arg) { AVCodec *p; @@ -1939,7 +1965,7 @@ void opt_video_codec(const char *arg) } } -void opt_map(const char *arg) +static void opt_map(const char *arg) { AVStreamMap *m; const char *p; @@ -1954,49 +1980,33 @@ void opt_map(const char *arg) m->stream_index = strtol(p, (char **)&p, 0); } -void opt_recording_time(const char *arg) +static void opt_recording_time(const char *arg) { recording_time = parse_date(arg, 1); } -void print_error(const char *filename, int err) -{ - switch(err) { - case AVERROR_NUMEXPECTED: - fprintf(stderr, "%s: Incorrect image filename syntax.\n" - "Use '%%d' to specify the image number:\n" - " for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';\n" - " for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.\n", - filename); - break; - case AVERROR_INVALIDDATA: - fprintf(stderr, "%s: Error while parsing header\n", filename); - break; - case AVERROR_NOFMT: - fprintf(stderr, "%s: Unknown format\n", filename); - break; - default: - fprintf(stderr, "%s: Error while opening file\n", filename); - break; - } -} - -void opt_input_file(const char *filename) +static void opt_input_file(const char *filename) { AVFormatContext *ic; AVFormatParameters params, *ap = ¶ms; - int err, i, ret, rfps; + int err, i, ret, rfps, rfps_base; if (!strcmp(filename, "-")) filename = "pipe:"; + using_stdin |= !strcmp(filename, "pipe:" ) || + !strcmp( filename, "/dev/stdin" ); + /* get default parameters from command line */ memset(ap, 0, sizeof(*ap)); ap->sample_rate = audio_sample_rate; ap->channels = audio_channels; ap->frame_rate = frame_rate; + ap->frame_rate_base = frame_rate_base; ap->width = frame_width; ap->height = frame_height; + ap->image_format = image_format; + ap->pix_fmt = frame_pix_fmt; /* open the input file with generic libav function */ err = av_open_input_file(&ic, filename, file_iformat, 0, ap); @@ -2025,7 +2035,10 @@ void opt_input_file(const char *filename) case CODEC_TYPE_VIDEO: frame_height = enc->height; frame_width = enc->width; - rfps = ic->streams[i]->r_frame_rate; + frame_aspect_ratio = enc->aspect_ratio; + frame_pix_fmt = enc->pix_fmt; + rfps = ic->streams[i]->r_frame_rate; + rfps_base = ic->streams[i]->r_frame_rate_base; enc->workaround_bugs = workaround_bugs; enc->error_resilience = error_resilience; enc->error_concealment = error_concealment; @@ -2033,16 +2046,23 @@ void opt_input_file(const char *filename) enc->debug= debug; /* 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) + if(/*enc->codec_id==CODEC_ID_MPEG4 || */enc->codec_id==CODEC_ID_MPEG1VIDEO || enc->codec_id==CODEC_ID_H264) enc->flags|= CODEC_FLAG_TRUNCATED; + + if(bitexact) + enc->flags|= CODEC_FLAG_BITEXACT; - if (enc->frame_rate != rfps) { + assert(enc->frame_rate_base == rfps_base); // should be true for now + 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); + i, (float)enc->frame_rate / enc->frame_rate_base, + (float)rfps / rfps_base); } /* update the current frame rate to match the stream frame rate */ - frame_rate = rfps; + frame_rate = rfps; + frame_rate_base = rfps_base; + + enc->rate_emu = rate_emu; break; default: av_abort(); @@ -2055,9 +2075,12 @@ void opt_input_file(const char *filename) nb_input_files++; file_iformat = NULL; file_oformat = NULL; + image_format = NULL; + + rate_emu = 0; } -void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr) +static void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr) { int has_video, has_audio, i, j; AVFormatContext *ic; @@ -2084,12 +2107,13 @@ void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr) *has_audio_ptr = has_audio; } -void opt_output_file(const char *filename) +static void opt_output_file(const char *filename) { AVStream *st; AVFormatContext *oc; int use_video, use_audio, nb_streams, input_has_video, input_has_audio; int codec_id; + AVFormatParameters params, *ap = ¶ms; if (!strcmp(filename, "-")) filename = "pipe:"; @@ -2165,9 +2189,12 @@ void opt_output_file(const char *filename) video_enc->bit_rate = video_bit_rate; video_enc->bit_rate_tolerance = video_bit_rate_tolerance; video_enc->frame_rate = frame_rate; + video_enc->frame_rate_base = frame_rate_base; video_enc->width = frame_width; video_enc->height = frame_height; + video_enc->aspect_ratio = frame_aspect_ratio; + video_enc->pix_fmt = frame_pix_fmt; if (!intra_only) video_enc->gop_size = gop_size; @@ -2177,13 +2204,20 @@ void opt_output_file(const char *filename) video_enc->flags |= CODEC_FLAG_QSCALE; st->quality = video_qscale; } - - if (use_hq) { - video_enc->flags |= CODEC_FLAG_HQ; + + if(bitexact) + video_enc->flags |= CODEC_FLAG_BITEXACT; + + video_enc->mb_decision = mb_decision; + + if (use_umv) { + video_enc->flags |= CODEC_FLAG_H263P_UMV; + } + if (use_aic) { + video_enc->flags |= CODEC_FLAG_H263P_AIC; } - if (use_4mv) { - video_enc->flags |= CODEC_FLAG_HQ; + video_enc->mb_decision = FF_MB_DECISION_BITS; //FIXME remove video_enc->flags |= CODEC_FLAG_4MV; } @@ -2192,10 +2226,6 @@ void opt_output_file(const char *filename) 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; @@ -2220,7 +2250,8 @@ void opt_output_file(const char *filename) exit(1); } video_enc->rc_override= - realloc(video_enc->rc_override, sizeof(RcOverride)*(i+1)); + av_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){ @@ -2266,11 +2297,6 @@ void opt_output_file(const char *filename) 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++; @@ -2346,13 +2372,19 @@ void opt_output_file(const char *filename) 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"); + 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); + } + } + else { + fprintf(stderr,"File '%s' already exists. Exiting.\n", filename); exit(1); - } + } } } @@ -2363,9 +2395,18 @@ void opt_output_file(const char *filename) } } + 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); + } + /* reset some options */ file_oformat = NULL; file_iformat = NULL; + image_format = NULL; audio_disable = 0; video_disable = 0; audio_codec_id = CODEC_ID_NONE; @@ -2375,17 +2416,19 @@ void opt_output_file(const char *filename) } /* prepare dummy protocols for grab */ -void prepare_grab(void) +static void prepare_grab(void) { int has_video, has_audio, i, j; AVFormatContext *oc; AVFormatContext *ic; + 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)); + memset(vp, 0, sizeof(*vp)); for(j=0;jnb_streams;i++) { @@ -2399,12 +2442,16 @@ void prepare_grab(void) 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; + if (enc->width > vp->width) + vp->width = enc->width; + if (enc->height > vp->height) + vp->height = enc->height; + + assert(enc->frame_rate_base == DEFAULT_FRAME_RATE_BASE); + if (enc->frame_rate > vp->frame_rate){ + vp->frame_rate = enc->frame_rate; + vp->frame_rate_base = enc->frame_rate_base; + } has_video = 1; break; default: @@ -2420,45 +2467,37 @@ void prepare_grab(void) if (has_video) { AVInputFormat *fmt1; - fmt1 = av_find_input_format("video_grab_device"); - if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) { + fmt1 = av_find_input_format(video_grab_format); + vp->device = video_device; + vp->channel = video_channel; + vp->standard = video_standard; + if (av_open_input_file(&ic, "", fmt1, 0, vp) < 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; + ic->streams[0]->r_frame_rate = vp->frame_rate; + ic->streams[0]->r_frame_rate_base = vp->frame_rate_base; input_files[nb_input_files] = ic; - dump_format(ic, nb_input_files, v4l_device, 0); + dump_format(ic, nb_input_files, "", 0); nb_input_files++; } - if (has_audio) { + if (has_audio && audio_grab_format) { AVInputFormat *fmt1; - fmt1 = av_find_input_format("audio_device"); + fmt1 = av_find_input_format(audio_grab_format); + 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; - dump_format(ic, nb_input_files, audio_device, 0); + dump_format(ic, nb_input_files, "", 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) +static void opt_pass(const char *pass_str) { int pass; pass = atoi(pass_str); @@ -2469,50 +2508,67 @@ void opt_pass(const char *pass_str) do_pass = pass; } -#ifndef CONFIG_WIN32 -INT64 getutime(void) +#if defined(CONFIG_WIN32) || defined(CONFIG_OS2) +static int64_t getutime(void) +{ + return av_gettime(); +} +#else +static int64_t getutime(void) { struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec; } -#else -INT64 getutime(void) -{ - return av_gettime(); -} #endif extern int ffm_nopts; -void opt_bitexact(void) +static void opt_bitexact(void) { - avcodec_set_bit_exact(); + bitexact=1; /* disable generate of real time pts in ffm (need to be supressed anyway) */ ffm_nopts = 1; } -void show_formats(void) +static void show_formats(void) { AVInputFormat *ifmt; AVOutputFormat *ofmt; + AVImageFormat *image_fmt; URLProtocol *up; AVCodec *p; const char **pp; - printf("File formats:\n"); - printf(" Encoding:"); + printf("Output audio/video file formats:"); for(ofmt = first_oformat; ofmt != NULL; ofmt = ofmt->next) { printf(" %s", ofmt->name); } printf("\n"); - printf(" Decoding:"); + + printf("Input audio/video file formats:"); for(ifmt = first_iformat; ifmt != NULL; ifmt = ifmt->next) { printf(" %s", ifmt->name); } printf("\n"); + printf("Output image formats:"); + for(image_fmt = first_image_format; image_fmt != NULL; + image_fmt = image_fmt->next) { + if (image_fmt->img_write) + printf(" %s", image_fmt->name); + } + printf("\n"); + + printf("Input image formats:"); + for(image_fmt = first_image_format; image_fmt != NULL; + image_fmt = image_fmt->next) { + if (image_fmt->img_read) + printf(" %s", image_fmt->name); + } + printf("\n"); + printf("Codecs:\n"); printf(" Encoders:"); for(p = first_avcodec; p != NULL; p = p->next) { @@ -2533,7 +2589,7 @@ void show_formats(void) printf(" %s:", up->name); printf("\n"); - printf("Frame size abbreviations: sqcif qcif cif 4cif\n"); + printf("Frame size, frame rate abbreviations: ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n"); printf("Motion estimation methods:"); pp = motion_str; while (*pp) { @@ -2550,52 +2606,13 @@ void show_formats(void) exit(1); } -void show_help(void) -{ - const char *prog; - const OptionDef *po; - int i, expert; - - 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" - "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" }, + /* main options */ + { "L", 0, {(void*)show_license}, "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" }, + { "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" }, @@ -2604,155 +2621,172 @@ const OptionDef options[] = { { "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" }, - /* video options */ - { "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" }, - { "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" }, - { "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", - "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)" }, - { "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" }, - { "strict", HAS_ARG | OPT_EXPERT, {(void*)opt_strict}, "strictness", "how strictly to follow the standarts" }, - { "sameq", OPT_BOOL, {(void*)&same_quality}, - "use same video quality as source (implies VBR)" }, { "debug", HAS_ARG | OPT_EXPERT, {(void*)opt_debug}, "print specific debug info", "" }, - /* 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}, "add timings for benchmarking" }, { "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" }, + { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" }, + { "loop", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" }, + + /* video options */ + { "b", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate}, "set video bitrate (in kbit/s)", "bitrate" }, + { "r", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_rate}, "set frame rate (Hz value, fraction or abbreviation)", "rate" }, + { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" }, + { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" }, + { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format", "format" }, + { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_top}, "set top crop band size (in pixels)", "size" }, + { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" }, + { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" }, + { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" }, + { "g", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_gop_size}, "set the group of picture size", "gop_size" }, + { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"}, + { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" }, + { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantiser scale (VBR)", "q" }, + { "qmin", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qmin}, "min video quantiser scale (VBR)", "q" }, + { "qmax", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qmax}, "max video quantiser scale (VBR)", "q" }, + { "mbqmin", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_qmin}, "min macroblock quantiser scale (VBR)", "q" }, + { "mbqmax", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_qmax}, "max macroblock quantiser scale (VBR)", "q" }, + { "qdiff", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qdiff}, "max difference between the quantiser scale (VBR)", "q" }, + { "qblur", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qblur}, "video quantiser scale blur (VBR)", "blur" }, + { "qcomp", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qcomp}, "video quantiser scale compression (VBR)", "compression" }, + { "rc_init_cplx", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_rc_initial_cplx}, "initial complexity for 1-pass encoding", "complexity" }, + { "b_qfactor", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_b_qfactor}, "qp factor between p and b frames", "factor" }, + { "i_qfactor", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_i_qfactor}, "qp factor between p and i frames", "factor" }, + { "b_qoffset", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_b_qoffset}, "qp offset between p and b frames", "offset" }, + { "i_qoffset", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(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 | OPT_VIDEO, {(void*)opt_video_rc_eq}, "set rate control equation", "equation" }, + { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" }, + { "bt", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate_tolerance}, "set video bitrate tolerance (in kbit/s)", "tolerance" }, + { "maxrate", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate_max}, "set max video bitrate tolerance (in kbit/s)", "bitrate" }, + { "minrate", HAS_ARG | OPT_VIDEO, {(void*)opt_video_bitrate_min}, "set min video bitrate tolerance (in kbit/s)", "bitrate" }, + { "bufsize", HAS_ARG | OPT_VIDEO, {(void*)opt_video_buffer_size}, "set ratecontrol buffere size (in kbit)", "size" }, + { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" }, + { "me", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_motion_estimation}, "set motion estimation method", + "method" }, + { "dct_algo", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_dct_algo}, "set dct algo", "algo" }, + { "idct_algo", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_idct_algo}, "set idct algo", "algo" }, + { "er", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_error_resilience}, "set error resilience", "n" }, + { "ec", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_error_concealment}, "set error concealment", "bit_mask" }, + { "bf", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_b_frames}, "use 'frames' B frames (only MPEG-4)", "frames" }, + { "hq", OPT_BOOL, {(void*)&mb_decision}, "activate high quality settings" }, + { "mbd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_mb_decision}, "macroblock decision", "mode" }, + { "4mv", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_4mv}, "use four motion vector by macroblock (only MPEG-4)" }, + { "part", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_part}, "use data partitioning (only MPEG-4)" }, + { "bug", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_workaround_bugs}, "workaround not auto detected encoder bugs", "param" }, + { "ps", HAS_ARG | OPT_EXPERT, {(void*)opt_packet_size}, "set packet size in bits", "size" }, + { "strict", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_strict}, "how strictly to follow the standarts", "strictness" }, + { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality}, + "use same video quality as source (implies VBR)" }, + { "pass", HAS_ARG | OPT_VIDEO, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" }, + { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename}, "select two pass log file name", "file" }, + { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace}, + "deinterlace pictures" }, + { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" }, + { "vstats", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_vstats}, "dump video coding statistics to file" }, + { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" }, + { "aic", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_aic}, "enable Advanced intra coding (h263+)" }, + { "umv", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&use_umv}, "enable Unlimited Motion Vector (h263+)" }, + + /* audio options */ + { "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", }, + { "ar", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" }, + { "ac", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_channels}, "set number of audio channels", "channels" }, + { "an", OPT_BOOL | OPT_AUDIO, {(void*)&audio_disable}, "disable audio" }, + { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" }, + + /* grab options */ + { "vd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_device}, "set video grab device", "device" }, + { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" }, + { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" }, + { "dv1394", OPT_EXPERT | OPT_GRAB, {(void*)opt_dv1394}, "set DV1394 grab", "" }, + { "ad", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_GRAB, {(void*)opt_audio_device}, "set audio device", "device" }, { NULL, }, }; +static void show_banner(void) +{ + printf("ffmpeg version " FFMPEG_VERSION ", Copyright (c) 2000-2003 Fabrice Bellard\n"); +} + +static void show_license(void) +{ + show_banner(); + printf( + "This library is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Lesser General Public\n" + "License as published by the Free Software Foundation; either\n" + "version 2 of the License, or (at your option) any later version.\n" + "\n" + "This library is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "Lesser General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU Lesser General Public\n" + "License along with this library; if not, write to the Free Software\n" + "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" + ); + exit(1); +} + +static void show_help(void) +{ + show_banner(); + printf("usage: ffmpeg [[options] -i input_file]... {[options] outfile}...\n" + "Hyper fast Audio and Video encoder\n"); + printf("\n"); + show_help_options(options, "Main options:\n", + OPT_EXPERT | OPT_AUDIO | OPT_VIDEO, 0); + 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, "\nAudio/Video grab options:\n", + OPT_GRAB, + OPT_GRAB); + show_help_options(options, "\nAdvanced options:\n", + OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB, + OPT_EXPERT); + exit(1); +} + +void parse_arg_file(const char *filename) +{ + opt_output_file(filename); +} + int main(int argc, char **argv) { - int optindex, i; - const char *opt, *arg; - const OptionDef *po; - INT64 ti; - - av_register_all(); + int i; + int64_t ti; - /* detect if invoked as player */ - i = strlen(argv[0]); - if (i >= 6 && !strcmp(argv[0] + i - 6, "ffplay")) - do_play = 1; + av_register_all(); if (argc <= 1) show_help(); /* 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) { - arg = argv[optindex++]; - 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); - } - } - } - + parse_options(argc, argv, options); - 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(); + /* 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(); } ti = getutime(); @@ -2778,5 +2812,21 @@ int main(int argc, char **argv) av_close_input_file(input_files[i]); av_free_static(); + + +#ifdef POWERPC_PERFORMANCE_REPORT + extern void powerpc_display_perf_report(void); + powerpc_display_perf_report(); +#endif /* POWERPC_PERFORMANCE_REPORT */ + +#ifndef CONFIG_WIN32 + if (received_sigterm) { + fprintf(stderr, + "Received signal %d: terminating.\n", + (int) received_sigterm); + exit (255); + } +#endif + exit(0); /* not all OS-es handle main() return value */ return 0; }