X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=07c3ac41f48a68f1e268a5a135ea676389308cc7;hb=e748e34dd6427271b779978a61156e47bfab3c8e;hp=516156511069594f3c3a68849ad02e3ea32f80a2;hpb=8767060cd2e5f9a29251f90b98b0f0cdafad93ef;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index 51615651106..07c3ac41f48 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* needed for usleep() */ +#define _XOPEN_SOURCE 500 + #include "config.h" #include #include @@ -27,33 +30,35 @@ #include #include #include -#include "avformat.h" -#include "avdevice.h" -#include "swscale.h" -#include "framehook.h" -#include "opt.h" -#include "fifo.h" -#include "avstring.h" -#include "os_support.h" - -#if !defined(HAVE_GETRUSAGE) && defined(HAVE_GETPROCESSTIMES) +#include +#include "libavformat/avformat.h" +#include "libavdevice/avdevice.h" +#include "libswscale/swscale.h" +#include "libavformat/framehook.h" +#include "libavcodec/opt.h" +#include "libavcodec/audioconvert.h" +#include "libavutil/fifo.h" +#include "libavutil/avstring.h" +#include "libavformat/os_support.h" + +#ifdef HAVE_SYS_RESOURCE_H +#include +#include +#elif defined(HAVE_GETPROCESSTIMES) #include #endif #if defined(HAVE_TERMIOS_H) -#include #include #include #include #include -#include #elif defined(HAVE_CONIO_H) #include #endif #undef time //needed because HAVE_AV_CONFIG_H is defined on top #include -#include "version.h" #include "cmdutils.h" #undef NDEBUG @@ -61,8 +66,8 @@ #undef exit -static const char program_name[] = "FFmpeg"; -static const int program_birth_year = 2000; +const char program_name[] = "FFmpeg"; +const int program_birth_year = 2000; /* select an input stream for an output stream */ typedef struct AVStreamMap { @@ -78,18 +83,19 @@ typedef struct AVMetaDataMap { int in_file; } AVMetaDataMap; -extern const OptionDef options[]; +static const OptionDef options[]; #define MAX_FILES 20 static AVFormatContext *input_files[MAX_FILES]; static int64_t input_files_ts_offset[MAX_FILES]; +static double input_files_ts_scale[MAX_FILES][MAX_STREAMS]; static int nb_input_files = 0; static AVFormatContext *output_files[MAX_FILES]; static int nb_output_files = 0; -static AVStreamMap stream_maps[MAX_FILES]; +static AVStreamMap stream_maps[MAX_FILES*MAX_STREAMS]; static int nb_stream_maps; static AVMetaDataMap meta_data_maps[MAX_FILES]; @@ -101,6 +107,7 @@ static int frame_width = 0; static int frame_height = 0; static float frame_aspect_ratio = 0; static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE; +static enum SampleFormat audio_sample_fmt = SAMPLE_FMT_NONE; static int frame_padtop = 0; static int frame_padbottom = 0; static int frame_padleft = 0; @@ -111,9 +118,8 @@ static int frame_bottomBand = 0; static int frame_leftBand = 0; static int frame_rightBand = 0; static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX}; -static AVRational frame_rate = (AVRational) {0,0}; +static AVRational frame_rate; static float video_qscale = 0; -static int video_qdiff = 3; static uint16_t *intra_matrix = NULL; static uint16_t *inter_matrix = NULL; #if 0 //experimental, (can be removed) @@ -128,7 +134,6 @@ static char *video_codec_name = NULL; static int video_codec_tag = 0; static int same_quality = 0; static int do_deinterlace = 0; -static int strict = 0; static int top_field_first = -1; static int me_threshold = 0; static int intra_dc_precision = 8; @@ -153,7 +158,7 @@ static char *subtitle_language = NULL; static float mux_preload= 0.5; static float mux_max_delay= 0.7; -static int64_t recording_time = 0; +static int64_t recording_time = INT64_MAX; static int64_t start_time = 0; static int64_t rec_timestamp = 0; static int64_t input_ts_offset = 0; @@ -173,7 +178,7 @@ static char *pass_logfilename = NULL; static int audio_stream_copy = 0; static int video_stream_copy = 0; static int subtitle_stream_copy = 0; -static int video_sync_method= 1; +static int video_sync_method= -1; static int audio_sync_method= 0; static float audio_drift_threshold= 0.1; static int copy_ts= 0; @@ -255,6 +260,8 @@ typedef struct AVOutputStream { /* audio only */ int audio_resample; ReSampleContext *resample; /* for audio resampling */ + int reformat_pair; + AVAudioConvert *reformat_ctx; AVFifoBuffer fifo; /* for compression: one audio fifo per codec */ FILE *logfile; } AVOutputStream; @@ -391,8 +398,6 @@ static int av_exit(int ret) for(i=0;icodec = avcodec_alloc_context(); memcpy(st->codec, ic->streams[i]->codec, sizeof(AVCodecContext)); s->streams[i] = st; + + if (st->codec->codec_type == CODEC_TYPE_AUDIO && audio_stream_copy) + st->stream_copy = 1; + else if (st->codec->codec_type == CODEC_TYPE_VIDEO && video_stream_copy) + st->stream_copy = 1; + + if(!st->codec->thread_count) + st->codec->thread_count = 1; + if(st->codec->thread_count>1) + avcodec_thread_init(st->codec, st->codec->thread_count); + + if(st->codec->flags & CODEC_FLAG_BITEXACT) + nopts = 1; } + if (!nopts) + s->timestamp = av_gettime(); + av_close_input_file(ic); return 0; } @@ -496,6 +518,7 @@ static void do_audio_out(AVFormatContext *s, uint8_t *buftmp; static uint8_t *audio_buf = NULL; static uint8_t *audio_out = NULL; + static uint8_t *audio_out2 = NULL; const int audio_out_size= 4*MAX_AUDIO_PACKET_SIZE; int size_out, frame_bytes, ret; @@ -524,6 +547,26 @@ static void do_audio_out(AVFormatContext *s, } } +#define MAKE_SFMT_PAIR(a,b) ((a)+SAMPLE_FMT_NB*(b)) + if (dec->sample_fmt!=enc->sample_fmt && + MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) { + if (!audio_out2) + audio_out2 = av_malloc(audio_out_size); + if (!audio_out2) + av_exit(1); + if (ost->reformat_ctx) + av_audio_convert_free(ost->reformat_ctx); + ost->reformat_ctx = av_audio_convert_alloc(enc->sample_fmt, 1, + dec->sample_fmt, 1, NULL, 0); + if (!ost->reformat_ctx) { + fprintf(stderr, "Cannot convert %s sample format to %s sample format\n", + avcodec_get_sample_fmt_name(dec->sample_fmt), + avcodec_get_sample_fmt_name(enc->sample_fmt)); + av_exit(1); + } + ost->reformat_pair=MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt); + } + if(audio_sync_method){ double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts - av_fifo_size(&ost->fifo)/(ost->st->codec->channels * 2); @@ -582,18 +625,36 @@ static void do_audio_out(AVFormatContext *s, size_out = size; } + if (dec->sample_fmt!=enc->sample_fmt) { + const void *ibuf[6]= {buftmp}; + void *obuf[6]= {audio_out2}; + int istride[6]= {av_get_bits_per_sample_format(dec->sample_fmt)/8}; + int ostride[6]= {av_get_bits_per_sample_format(enc->sample_fmt)/8}; + int len= size_out/istride[0]; + if (av_audio_convert(ost->reformat_ctx, obuf, ostride, ibuf, istride, len)<0) { + printf("av_audio_convert() failed\n"); + return; + } + buftmp = audio_out2; + /* FIXME: existing code assume that size_out equals framesize*channels*2 + remove this legacy cruft */ + size_out = len*2; + } + /* now encode as many frames as possible */ if (enc->frame_size > 1) { /* output resampled raw samples */ - av_fifo_realloc(&ost->fifo, av_fifo_size(&ost->fifo) + size_out + 1); - av_fifo_write(&ost->fifo, buftmp, size_out); + av_fifo_realloc(&ost->fifo, av_fifo_size(&ost->fifo) + size_out); + av_fifo_generic_write(&ost->fifo, buftmp, size_out, NULL); frame_bytes = enc->frame_size * 2 * enc->channels; - while (av_fifo_read(&ost->fifo, audio_buf, frame_bytes) == 0) { + while (av_fifo_size(&ost->fifo) >= frame_bytes) { AVPacket pkt; av_init_packet(&pkt); + av_fifo_read(&ost->fifo, audio_buf, frame_bytes); + //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio() ret = avcodec_encode_audio(enc, audio_out, audio_out_size, @@ -622,6 +683,7 @@ static void do_audio_out(AVFormatContext *s, case CODEC_ID_PCM_S32BE: case CODEC_ID_PCM_U32LE: case CODEC_ID_PCM_U32BE: + case CODEC_ID_PCM_F32BE: size_out = size_out << 1; break; case CODEC_ID_PCM_S24LE: @@ -780,7 +842,7 @@ static void do_video_out(AVFormatContext *s, *frame_size = 0; - if(video_sync_method){ + if(video_sync_method>0 || (video_sync_method && av_q2d(enc->time_base) > 0.001)){ double vdelta; vdelta = get_sync_ipts(ost) / av_q2d(enc->time_base) - ost->sync_opts; //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c @@ -900,16 +962,17 @@ static void do_video_out(AVFormatContext *s, if(ret>0){ pkt.data= bit_buffer; pkt.size= ret; - if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) + if(enc->coded_frame->pts != AV_NOPTS_VALUE) pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); /*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n", pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1, pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/ - if(enc->coded_frame && enc->coded_frame->key_frame) + if(enc->coded_frame->key_frame) pkt.flags |= PKT_FLAG_KEY; write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]); *frame_size = ret; + video_size += ret; //fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d", // enc->frame_number-1, enc->real_pict_num, ret, // enc->pict_type); @@ -1008,7 +1071,7 @@ static void print_report(AVFormatContext **output_files, enc = ost->st->codec; if (vid && enc->codec_type == CODEC_TYPE_VIDEO) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", - enc->coded_frame && !ost->st->stream_copy ? + !ost->st->stream_copy ? enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1); } if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) { @@ -1017,11 +1080,11 @@ static void print_report(AVFormatContext **output_files, frame_number = ost->frame_number; snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ", frame_number, (t>1)?(int)(frame_number/t+0.5) : 0, - enc->coded_frame && !ost->st->stream_copy ? + !ost->st->stream_copy ? enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1); if(is_last_report) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L"); - if(qp_hist && enc->coded_frame){ + if(qp_hist){ int j; int qp= lrintf(enc->coded_frame->quality/(float)FF_QP2LAMBDA); if(qp>=0 && qp 1) @@ -1122,7 +1185,9 @@ static int output_packet(AVInputStream *ist, int ist_index, len = pkt->size; ptr = pkt->data; - while (len > 0) { + + //while we have more to decode or while the decoder did output something on EOF + while (len > 0 || (!pkt && ist->next_pts != ist->pts)) { handle_eof: ist->pts= ist->next_pts; @@ -1136,8 +1201,11 @@ static int output_packet(AVInputStream *ist, int ist_index, if (ist->decoding_needed) { switch(ist->st->codec->codec_type) { case CODEC_TYPE_AUDIO:{ - if(pkt) - samples= av_fast_realloc(samples, &samples_size, FFMAX(pkt->size*sizeof(*samples), AVCODEC_MAX_AUDIO_FRAME_SIZE)); + if(pkt && samples_size < FFMAX(pkt->size*sizeof(*samples), AVCODEC_MAX_AUDIO_FRAME_SIZE)) { + samples_size = FFMAX(pkt->size*sizeof(*samples), AVCODEC_MAX_AUDIO_FRAME_SIZE); + av_free(samples); + samples= av_malloc(samples_size); + } data_size= samples_size; /* XXX: could avoid copy if PCM 16 bits with same endianness as CPU */ @@ -1281,7 +1349,6 @@ static int output_packet(AVInputStream *ist, int ist_index, break; case CODEC_TYPE_VIDEO: do_video_out(os, ost, ist, &picture, &frame_size); - video_size += frame_size; if (vstats_filename && frame_size) do_video_stats(os, ost, frame_size); break; @@ -1320,10 +1387,10 @@ static int output_packet(AVInputStream *ist, int ist_index, else opkt.pts= AV_NOPTS_VALUE; - if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->next_pts, AV_TIME_BASE_Q, ost->st->time_base); - else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); + if (pkt->dts == AV_NOPTS_VALUE) + opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); + else + opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); opkt.flags= pkt->flags; @@ -1383,9 +1450,8 @@ static int output_packet(AVInputStream *ist, int ist_index, if(fifo_bytes > 0 && enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { int fs_tmp = enc->frame_size; enc->frame_size = fifo_bytes / (2 * enc->channels); - if(av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes) == 0) { + av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes); ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples); - } enc->frame_size = fs_tmp; } if(ret <= 0) { @@ -1578,6 +1644,8 @@ static int av_encode(AVFormatContext **output_files, /* Sanity check that the stream types match */ if (ist_table[ost->source_index]->st->codec->codec_type != ost->st->codec->codec_type) { + int i= ost->file_index; + dump_format(output_files[i], i, output_files[i]->filename, 1); 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); @@ -1618,6 +1686,8 @@ static int av_encode(AVFormatContext **output_files, } } if (!found) { + int i= ost->file_index; + dump_format(output_files[i], i, output_files[i]->filename, 1); fprintf(stderr, "Could not find input stream matching output stream #%d.%d\n", ost->file_index, ost->index); av_exit(1); @@ -1668,12 +1738,18 @@ static int av_encode(AVFormatContext **output_files, codec->time_base = ist->st->time_base; switch(codec->codec_type) { case CODEC_TYPE_AUDIO: + if(audio_volume != 256) { + fprintf(stderr,"-acodec copy and -vol are incompatible (frames are not decoded)\n"); + av_exit(1); + } codec->sample_rate = icodec->sample_rate; codec->channels = icodec->channels; codec->frame_size = icodec->frame_size; codec->block_align= icodec->block_align; if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3) codec->block_align= 0; + if(codec->codec_id == CODEC_ID_AC3) + codec->block_align= 0; break; case CODEC_TYPE_VIDEO: if(using_vhook) { @@ -1695,6 +1771,7 @@ static int av_encode(AVFormatContext **output_files, case CODEC_TYPE_AUDIO: if (av_fifo_init(&ost->fifo, 1024)) goto fail; + ost->reformat_pair = MAKE_SFMT_PAIR(SAMPLE_FMT_NONE,SAMPLE_FMT_NONE); ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1; icodec->request_channels = codec->channels; ist->decoding_needed = 1; @@ -1721,15 +1798,15 @@ static int av_encode(AVFormatContext **output_files, ost->padright = frame_padright; if (!ost->video_resample) { avcodec_get_frame_defaults(&ost->pict_tmp); - if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, codec->pix_fmt, - codec->width, codec->height ) ) + if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt, + codec->width, codec->height)) goto fail; } } if (ost->video_resample) { avcodec_get_frame_defaults(&ost->pict_tmp); - if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, codec->pix_fmt, - codec->width, codec->height ) ) { + if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt, + codec->width, codec->height)) { fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n"); av_exit(1); } @@ -1891,12 +1968,12 @@ static int av_encode(AVFormatContext **output_files, int out_file_index = meta_data_maps[i].out_file; int in_file_index = meta_data_maps[i].in_file; - if ( out_file_index < 0 || out_file_index >= nb_output_files ) { + if (out_file_index < 0 || out_file_index >= nb_output_files) { fprintf(stderr, "Invalid output file index %d map_meta_data(%d,%d)\n", out_file_index, out_file_index, in_file_index); ret = AVERROR(EINVAL); goto fail; } - if ( in_file_index < 0 || in_file_index >= nb_input_files ) { + if (in_file_index < 0 || in_file_index >= nb_input_files) { fprintf(stderr, "Invalid input file index %d map_meta_data(%d,%d)\n", in_file_index, out_file_index, in_file_index); ret = AVERROR(EINVAL); goto fail; @@ -1931,7 +2008,7 @@ static int av_encode(AVFormatContext **output_files, print_sdp(output_files, nb_output_files); } - if ( !using_stdin && verbose >= 0) { + if (!using_stdin && verbose >= 0) { fprintf(stderr, "Press [q] to stop encoding\n"); url_set_interrupt_cb(decode_interrupt_cb); } @@ -1993,7 +2070,7 @@ static int av_encode(AVFormatContext **output_files, } /* finish if recording time exhausted */ - if (recording_time > 0 && opts_min >= (recording_time / 1000000.0)) + if (opts_min >= (recording_time / 1000000.0)) break; /* finish if limit size exhausted */ @@ -2027,6 +2104,13 @@ static int av_encode(AVFormatContext **output_files, if (pkt.pts != AV_NOPTS_VALUE) pkt.pts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base); + if(input_files_ts_scale[file_index][pkt.stream_index]){ + if(pkt.pts != AV_NOPTS_VALUE) + pkt.pts *= input_files_ts_scale[file_index][pkt.stream_index]; + if(pkt.dts != AV_NOPTS_VALUE) + pkt.dts *= input_files_ts_scale[file_index][pkt.stream_index]; + } + // fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type); if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE) { int64_t pkt_dts= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); @@ -2124,6 +2208,8 @@ static int av_encode(AVFormatContext **output_files, sws_freeContext(ost->img_resample_ctx); if (ost->resample) audio_resample_close(ost->resample); + if (ost->reformat_ctx) + av_audio_convert_free(ost->reformat_ctx); av_free(ost); } } @@ -2175,8 +2261,6 @@ static void opt_format(const char *arg) } } -extern int ffm_nopts; - static int opt_default(const char *opt, const char *arg){ int type; const AVOption *o= NULL; @@ -2185,36 +2269,30 @@ static int opt_default(const char *opt, const char *arg){ for(type=0; typename; -#if defined(CONFIG_FFM_DEMUXER) || defined(CONFIG_FFM_MUXER) - /* disable generate of real time pts in ffm (need to be supressed anyway) */ - if(avctx_opts[0]->flags & CODEC_FLAG_BITEXACT) - ffm_nopts = 1; -#endif - - if(avctx_opts[0]->debug) + if(avctx_opts[0]->debug || avformat_opts->debug) av_log_set_level(AV_LOG_DEBUG); return 0; } @@ -2224,15 +2302,17 @@ static void opt_video_rc_override_string(const char *arg) video_rc_override_string = arg; } -static void opt_me_threshold(const char *arg) +static int opt_me_threshold(const char *opt, const char *arg) { - me_threshold = atoi(arg); + me_threshold = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); + return 0; } -static void opt_verbose(const char *arg) +static int opt_verbose(const char *opt, const char *arg) { - verbose = atoi(arg); + verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10); av_log_set_level(verbose); + return 0; } static void opt_frame_rate(const char *arg) @@ -2425,13 +2505,13 @@ static void opt_frame_pad_right(const char *arg) } } -void list_pix_fmts(void) +static void list_fmts(void (*get_fmt_string)(char *buf, int buf_size, int fmt), int nb_fmts) { int i; - char pix_fmt_str[128]; - for (i=-1; i < PIX_FMT_NB; i++) { - avcodec_pix_fmt_string (pix_fmt_str, sizeof(pix_fmt_str), i); - fprintf(stdout, "%s\n", pix_fmt_str); + char fmt_str[128]; + for (i=-1; i < nb_fmts; i++) { + get_fmt_string (fmt_str, sizeof(fmt_str), i); + fprintf(stdout, "%s\n", fmt_str); } } @@ -2440,7 +2520,7 @@ static void opt_frame_pix_fmt(const char *arg) if (strcmp(arg, "list")) frame_pix_fmt = avcodec_get_pix_fmt(arg); else { - list_pix_fmts(); + list_fmts(avcodec_pix_fmt_string, PIX_FMT_NB); av_exit(0); } } @@ -2479,43 +2559,41 @@ static void opt_qscale(const char *arg) } } -static void opt_qdiff(const char *arg) -{ - video_qdiff = atoi(arg); - if (video_qdiff < 0 || - video_qdiff > 31) { - fprintf(stderr, "qdiff must be >= 1 and <= 31\n"); - av_exit(1); - } -} - -static void opt_strict(const char *arg) -{ - strict= atoi(arg); -} - static void opt_top_field_first(const char *arg) { top_field_first= atoi(arg); } -static void opt_thread_count(const char *arg) +static int opt_thread_count(const char *opt, const char *arg) { - thread_count= atoi(arg); + thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); #if !defined(HAVE_THREADS) if (verbose >= 0) fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n"); #endif + return 0; +} + +static void opt_audio_sample_fmt(const char *arg) +{ + if (strcmp(arg, "list")) + audio_sample_fmt = avcodec_get_sample_fmt(arg); + else { + list_fmts(avcodec_sample_fmt_string, SAMPLE_FMT_NB); + av_exit(0); + } } -static void opt_audio_rate(const char *arg) +static int opt_audio_rate(const char *opt, const char *arg) { - audio_sample_rate = atoi(arg); + audio_sample_rate = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); + return 0; } -static void opt_audio_channels(const char *arg) +static int opt_audio_channels(const char *opt, const char *arg) { - audio_channels = atoi(arg); + audio_channels = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); + return 0; } static void opt_video_channel(const char *arg) @@ -2633,6 +2711,23 @@ static void opt_map_meta_data(const char *arg) m->in_file = strtol(p, &p, 0); } +static void opt_input_ts_scale(const char *arg) +{ + unsigned int stream; + double scale; + char *p; + + stream = strtol(arg, &p, 0); + if (*p) + p++; + scale= strtod(p, &p); + + if(stream >= MAX_STREAMS) + av_exit(1); + + input_files_ts_scale[nb_input_files][stream]= scale; +} + static int opt_recording_time(const char *opt, const char *arg) { recording_time = parse_time_or_die(opt, arg, 1); @@ -2678,6 +2773,19 @@ static enum CodecID find_codec_or_die(const char *name, int type, int encoder) return codec->id; } +static void set_context_opts(void *ctx, void *opts_ctx, int flags) +{ + int i; + for(i=0; iflags & flags) == flags)) + av_set_string2(ctx, opt_names[i], str, 1); + } +} + static void opt_input_file(const char *filename) { AVFormatContext *ic; @@ -2689,7 +2797,7 @@ static void opt_input_file(const char *filename) filename = "pipe:"; using_stdin |= !strncmp(filename, "pipe:", 5) || - !strcmp( filename, "/dev/stdin" ); + !strcmp(filename, "/dev/stdin"); /* get default parameters from command line */ ic = av_alloc_format_context(); @@ -2703,6 +2811,7 @@ static void opt_input_file(const char *filename) ap->width = frame_width + frame_padleft + frame_padright; ap->height = frame_height + frame_padtop + frame_padbottom; ap->pix_fmt = frame_pix_fmt; + // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat ap->channel = video_channel; ap->standard = video_standard; ap->video_codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 0); @@ -2710,13 +2819,7 @@ static void opt_input_file(const char *filename) if(pgmyuv_compatibility_hack) ap->video_codec_id= CODEC_ID_PGMYUV; - for(i=0; iflags & AV_OPT_FLAG_DECODING_PARAM)) - av_set_string(ic, opt_names[i], str); - } + set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM); ic->video_codec_id = find_codec_or_die(video_codec_name , CODEC_TYPE_VIDEO , 0); ic->audio_codec_id = find_codec_or_die(audio_codec_name , CODEC_TYPE_AUDIO , 0); @@ -2763,34 +2866,22 @@ static void opt_input_file(const char *filename) /* update the current parameters so that they match the one of the input stream */ for(i=0;inb_streams;i++) { - int j; AVCodecContext *enc = ic->streams[i]->codec; if(thread_count>1) avcodec_thread_init(enc, thread_count); enc->thread_count= thread_count; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: - for(j=0; jflags & AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags & AV_OPT_FLAG_DECODING_PARAM)) - av_set_string(enc, opt_names[j], str); - } + set_context_opts(enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM); //fprintf(stderr, "\nInput Audio channels: %d", enc->channels); audio_channels = enc->channels; audio_sample_rate = enc->sample_rate; + audio_sample_fmt = enc->sample_fmt; if(audio_disable) ic->streams[i]->discard= AVDISCARD_ALL; break; case CODEC_TYPE_VIDEO: - for(j=0; jflags & AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags & AV_OPT_FLAG_DECODING_PARAM)) - av_set_string(enc, opt_names[j], str); - } + set_context_opts(enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM); frame_height = enc->height; frame_width = enc->width; frame_aspect_ratio = av_q2d(enc->sample_aspect_ratio) * enc->width / enc->height; @@ -2937,13 +3028,7 @@ static void new_video_stream(AVFormatContext *oc) video_enc->codec_id = codec_id; codec = avcodec_find_encoder(codec_id); - for(i=0; iflags & AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM)) - av_set_string(video_enc, opt_names[i], str); - } + set_context_opts(video_enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); video_enc->time_base.den = fps.num; video_enc->time_base.num = fps.den; @@ -2991,7 +3076,6 @@ static void new_video_stream(AVFormatContext *oc) if(inter_matrix) video_enc->inter_matrix = inter_matrix; - video_enc->max_qdiff = video_qdiff; video_enc->thread_count = thread_count; p= video_rc_override_string; for(i=0; p; i++){ @@ -3022,7 +3106,6 @@ static void new_video_stream(AVFormatContext *oc) video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4; video_enc->me_threshold= me_threshold; video_enc->intra_dc_precision= intra_dc_precision - 8; - video_enc->strict_std_compliance = strict; if (do_psnr) video_enc->flags|= CODEC_FLAG_PSNR; @@ -3047,7 +3130,7 @@ static void new_audio_stream(AVFormatContext *oc) { AVStream *st; AVCodecContext *audio_enc; - int codec_id, i; + int codec_id; st = av_new_stream(oc, oc->nb_streams); if (!st) { @@ -3064,7 +3147,6 @@ static void new_audio_stream(AVFormatContext *oc) audio_enc = st->codec; audio_enc->codec_type = CODEC_TYPE_AUDIO; - audio_enc->strict_std_compliance = strict; if(audio_codec_tag) audio_enc->codec_tag= audio_codec_tag; @@ -3077,19 +3159,15 @@ static void new_audio_stream(AVFormatContext *oc) st->stream_copy = 1; audio_enc->channels = audio_channels; } else { + AVCodec *codec; codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_AUDIO); - for(i=0; iflags & AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM)) - av_set_string(audio_enc, opt_names[i], str); - } + set_context_opts(audio_enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); if (audio_codec_name) codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1); audio_enc->codec_id = codec_id; + codec = avcodec_find_encoder(codec_id); if (audio_qscale > QSCALE_NONE) { audio_enc->flags |= CODEC_FLAG_QSCALE; @@ -3097,6 +3175,17 @@ static void new_audio_stream(AVFormatContext *oc) } audio_enc->thread_count = thread_count; audio_enc->channels = audio_channels; + audio_enc->sample_fmt = audio_sample_fmt; + + if(codec && codec->sample_fmts){ + const enum SampleFormat *p= codec->sample_fmts; + for(; *p!=-1; p++){ + if(*p == audio_enc->sample_fmt) + break; + } + if(*p == -1) + audio_enc->sample_fmt = codec->sample_fmts[0]; + } } audio_enc->sample_rate = audio_sample_rate; audio_enc->time_base= (AVRational){1, audio_sample_rate}; @@ -3116,7 +3205,6 @@ static void new_subtitle_stream(AVFormatContext *oc) { AVStream *st; AVCodecContext *subtitle_enc; - int i; st = av_new_stream(oc, oc->nb_streams); if (!st) { @@ -3133,13 +3221,7 @@ static void new_subtitle_stream(AVFormatContext *oc) if (subtitle_stream_copy) { st->stream_copy = 1; } else { - for(i=0; iflags & AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM)) - av_set_string(subtitle_enc, opt_names[i], str); - } + set_context_opts(avctx_opts[CODEC_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM); subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 1); } @@ -3191,7 +3273,7 @@ static void opt_output_file(const char *filename) { AVFormatContext *oc; int use_video, use_audio, use_subtitle; - int input_has_video, input_has_audio, input_has_subtitle, i; + int input_has_video, input_has_audio, input_has_subtitle; AVFormatParameters params, *ap = ¶ms; if (!strcmp(filename, "-")) @@ -3215,8 +3297,9 @@ static void opt_output_file(const char *filename) av_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); + int err = read_ffserver_streams(oc, filename); + if (err < 0) { + print_error(filename, err); av_exit(1); } } else { @@ -3295,7 +3378,7 @@ static void opt_output_file(const char *filename) if (url_exist(filename)) { int c; - if ( !using_stdin ) { + if (!using_stdin) { fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); fflush(stderr); c = getchar(); @@ -3303,11 +3386,11 @@ static void opt_output_file(const char *filename) fprintf(stderr, "Not overwriting - exiting\n"); av_exit(1); } - } - else { + } + else { fprintf(stderr,"File '%s' already exists. Exiting.\n", filename); av_exit(1); - } + } } } @@ -3329,13 +3412,7 @@ static void opt_output_file(const char *filename) oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE); oc->loop_output = loop_output; - for(i=0; iflags & AV_OPT_FLAG_ENCODING_PARAM)) - av_set_string(oc, opt_names[i], str); - } + set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM); /* reset some options */ file_oformat = NULL; @@ -3372,129 +3449,6 @@ static int64_t getutime(void) #endif } -static void opt_show_formats(void) -{ - AVInputFormat *ifmt=NULL; - AVOutputFormat *ofmt=NULL; - URLProtocol *up=NULL; - AVCodec *p=NULL, *p2; - AVBitStreamFilter *bsf=NULL; - const char *last_name; - - printf("File formats:\n"); - last_name= "000"; - for(;;){ - int decode=0; - int encode=0; - const char *name=NULL; - const char *long_name=NULL; - - while((ofmt= av_oformat_next(ofmt))) { - if((name == NULL || strcmp(ofmt->name, name)<0) && - strcmp(ofmt->name, last_name)>0){ - name= ofmt->name; - long_name= ofmt->long_name; - encode=1; - } - } - while((ifmt= av_iformat_next(ifmt))) { - if((name == NULL || strcmp(ifmt->name, name)<0) && - strcmp(ifmt->name, last_name)>0){ - name= ifmt->name; - long_name= ifmt->long_name; - encode=0; - } - if(name && strcmp(ifmt->name, name)==0) - decode=1; - } - if(name==NULL) - break; - last_name= name; - - printf( - " %s%s %-15s %s\n", - decode ? "D":" ", - encode ? "E":" ", - name, - long_name ? long_name:" "); - } - printf("\n"); - - printf("Codecs:\n"); - last_name= "000"; - for(;;){ - int decode=0; - int encode=0; - int cap=0; - const char *type_str; - - p2=NULL; - while((p= av_codec_next(p))) { - if((p2==NULL || strcmp(p->name, p2->name)<0) && - strcmp(p->name, last_name)>0){ - p2= p; - decode= encode= cap=0; - } - if(p2 && strcmp(p->name, p2->name)==0){ - if(p->decode) decode=1; - if(p->encode) encode=1; - cap |= p->capabilities; - } - } - if(p2==NULL) - break; - last_name= p2->name; - - switch(p2->type) { - case CODEC_TYPE_VIDEO: - type_str = "V"; - break; - case CODEC_TYPE_AUDIO: - type_str = "A"; - break; - case CODEC_TYPE_SUBTITLE: - type_str = "S"; - break; - default: - type_str = "?"; - break; - } - printf( - " %s%s%s%s%s%s %s", - decode ? "D": (/*p2->decoder ? "d":*/" "), - encode ? "E":" ", - type_str, - cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S":" ", - cap & CODEC_CAP_DR1 ? "D":" ", - cap & CODEC_CAP_TRUNCATED ? "T":" ", - p2->name); - /* if(p2->decoder && decode==0) - printf(" use %s for decoding", p2->decoder->name);*/ - printf("\n"); - } - printf("\n"); - - printf("Bitstream filters:\n"); - while((bsf = av_bitstream_filter_next(bsf))) - printf(" %s", bsf->name); - printf("\n"); - - printf("Supported file protocols:\n"); - while((up = av_protocol_next(up))) - printf(" %s:", up->name); - printf("\n"); - - printf("Frame size, frame rate abbreviations:\n ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n"); - printf("\n"); - printf( -"Note, the names of encoders and decoders do not always match, so there are\n" -"several cases where the above table shows encoder only or decoder only entries\n" -"even though both encoding and decoding are supported. For example, the h263\n" -"decoder corresponds to the h263 and h263p encoders, for file formats it is even\n" -"worse.\n"); - av_exit(0); -} - static void parse_matrix_coeffs(uint16_t *dest, const char *str) { int i; @@ -3540,7 +3494,10 @@ static void show_help(void) "Hyper fast Audio and Video encoder\n"); printf("\n"); show_help_options(options, "Main options:\n", - OPT_EXPERT | OPT_AUDIO | OPT_VIDEO, 0); + OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, 0); + show_help_options(options, "\nAdvanced options:\n", + OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, + OPT_EXPERT); show_help_options(options, "\nVideo options:\n", OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB, OPT_VIDEO); @@ -3559,20 +3516,14 @@ static void show_help(void) 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); + printf("\n"); av_opt_show(avctx_opts[0], NULL); + printf("\n"); av_opt_show(avformat_opts, NULL); + printf("\n"); av_opt_show(sws_opts, NULL); } -static void opt_show_help(void) -{ - show_help(); - av_exit(0); -} - static void opt_target(const char *arg) { int norm = -1; @@ -3756,24 +3707,60 @@ static int opt_bsf(const char *opt, const char *arg) return 0; } -static void opt_show_license(void) +static int opt_preset(const char *opt, const char *arg) { - show_license(); - av_exit(0); -} + FILE *f=NULL; + char tmp[1000], tmp2[1000]; + int i; + const char *base[3]= { getenv("HOME"), + "/usr/local/share", + "/usr/share", + }; -static void opt_show_version(void) -{ - show_version(program_name); - av_exit(0); + for(i=!base[0]; i<3 && !f; i++){ + snprintf(tmp, sizeof(tmp), "%s/%sffmpeg/%s.ffpreset", base[i], i ? "" : ".", arg); + f= fopen(tmp, "r"); + if(!f){ + char *codec_name= *opt == 'v' ? video_codec_name : + *opt == 'a' ? audio_codec_name : + subtitle_codec_name; + snprintf(tmp, sizeof(tmp), "%s/%sffmpeg/%s-%s.ffpreset", base[i], i ? "" : ".", codec_name, arg); + f= fopen(tmp, "r"); + } + } + + if(!f){ + fprintf(stderr, "Preset file not found\n"); + av_exit(1); + } + + while(!feof(f)){ + int e= fscanf(f, "%999[^=]=%999[^\n]\n", tmp, tmp2); + if(e!=2){ + fprintf(stderr, "Preset file invalid\n"); + av_exit(1); + } + if(!strcmp(tmp, "acodec")){ + opt_audio_codec(tmp2); + }else if(!strcmp(tmp, "vcodec")){ + opt_video_codec(tmp2); + }else if(!strcmp(tmp, "scodec")){ + opt_subtitle_codec(tmp2); + }else + opt_default(tmp, tmp2); + } + + fclose(f); + + return 0; } -const OptionDef options[] = { +static const OptionDef options[] = { /* main options */ - { "L", 0, {(void*)opt_show_license}, "show license" }, - { "h", 0, {(void*)opt_show_help}, "show help" }, - { "version", 0, {(void*)opt_show_version}, "show version" }, - { "formats", 0, {(void*)opt_show_formats}, "show available formats, codecs, protocols, ..." }, + { "L", OPT_EXIT, {(void*)show_license}, "show license" }, + { "h", OPT_EXIT, {(void*)show_help}, "show help" }, + { "version", OPT_EXIT, {(void*)show_version}, "show version" }, + { "formats", OPT_EXIT, {(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" }, @@ -3783,6 +3770,7 @@ const OptionDef options[] = { { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, // { "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, { "itsoffset", OPT_FUNC2 | HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, + { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" }, { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" }, { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp", "time" }, { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" }, @@ -3790,6 +3778,7 @@ const OptionDef options[] = { { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" }, { "genre", HAS_ARG | OPT_STRING, {(void*)&str_genre}, "set the genre", "string" }, { "album", HAS_ARG | OPT_STRING, {(void*)&str_album}, "set the album", "string" }, + { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, "add timings for benchmarking" }, { "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump}, @@ -3799,9 +3788,9 @@ const OptionDef options[] = { { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" }, { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" }, { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "number of times to loop output in formats that support looping (0 loops forever)", "" }, - { "v", HAS_ARG, {(void*)opt_verbose}, "set the logging verbosity level", "number" }, + { "v", HAS_ARG | OPT_FUNC2, {(void*)opt_verbose}, "set the logging verbosity level", "number" }, { "target", HAS_ARG, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, - { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" }, + { "threads", OPT_FUNC2 | HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" }, { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, @@ -3815,7 +3804,6 @@ const OptionDef options[] = { { "b", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" }, { "vb", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" }, { "vframes", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&max_frames[CODEC_TYPE_VIDEO]}, "set the number of video frames to record", "number" }, - { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "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" }, @@ -3833,11 +3821,9 @@ const OptionDef options[] = { { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" }, { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" }, { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" }, - { "qdiff", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qdiff}, "max difference between the quantizer scale (VBR)", "q" }, { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" }, { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" }, - { "me_threshold", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold", "threshold" }, - { "strict", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_strict}, "how strictly to follow the standards", "strictness" }, + { "me_threshold", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold", "threshold" }, { "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" }, @@ -3862,14 +3848,15 @@ const OptionDef options[] = { { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" }, { "aframes", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&max_frames[CODEC_TYPE_AUDIO]}, "set the number of audio frames to record", "number" }, { "aq", OPT_FLOAT | HAS_ARG | OPT_AUDIO, {(void*)&audio_qscale}, "set audio quality (codec-specific)", "quality", }, - { "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" }, + { "ar", HAS_ARG | OPT_FUNC2 | OPT_AUDIO, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" }, + { "ac", HAS_ARG | OPT_FUNC2 | 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" }, { "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_tag}, "force audio tag/fourcc", "fourcc/tag" }, { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, // { "newaudio", OPT_AUDIO, {(void*)opt_new_audio_stream}, "add a new audio stream to the current output stream" }, { "alang", HAS_ARG | OPT_STRING | OPT_AUDIO, {(void *)&audio_language}, "set the ISO 639 language code (3 letters) of the current audio stream" , "code" }, + { "sample_fmt", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_sample_fmt}, "set sample format, 'list' as argument shows all the sample formats supported", "format" }, /* subtitle options */ { "sn", OPT_BOOL | OPT_SUBTITLE, {(void*)&subtitle_disable}, "disable subtitle" }, @@ -3886,9 +3873,13 @@ const OptionDef options[] = { { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_max_delay}, "set the maximum demux-decode delay", "seconds" }, { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_preload}, "set the initial demux-decode delay", "seconds" }, - { "absf", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream filter" }, - { "vbsf", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream filter" }, - { "sbsf", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream filter" }, + { "absf", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream_filter" }, + { "vbsf", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream_filter" }, + { "sbsf", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream_filter" }, + + { "apre", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_preset}, "", "preset" }, + { "vpre", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_preset}, "", "preset" }, + { "spre", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_preset}, "", "preset" }, { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" }, { NULL, }, @@ -3903,13 +3894,16 @@ int main(int argc, char **argv) avdevice_register_all(); av_register_all(); + if(isatty(STDIN_FILENO)) + url_set_interrupt_cb(decode_interrupt_cb); + for(i=0; i