X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=43d8b771c851dbefd44e10c31db6d6faa9384ca0;hb=6638207bce4eabd3f99295c1ab096d2815eff3ce;hp=824ea8bf6611601fe99d9e9cb1e6d498955222c8;hpb=6e6ccf0d56d81f4bb0472c3974e10e620fcffa04;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index 824ea8bf661..43d8b771c85 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -45,6 +45,7 @@ #include "libavutil/avstring.h" #include "libavutil/libm.h" #include "libavformat/os_support.h" +#include "libswresample/swresample.h" #include "libavformat/ffm.h" // not public API @@ -52,7 +53,7 @@ # include "libavfilter/avcodec.h" # include "libavfilter/avfilter.h" # include "libavfilter/avfiltergraph.h" -# include "libavfilter/vsink_buffer.h" +# include "libavfilter/buffersink.h" # include "libavfilter/vsrc_buffer.h" #endif @@ -110,83 +111,24 @@ typedef struct MetadataMap { static const OptionDef options[]; #define MAX_STREAMS 1024 /* arbitrary sanity check value */ -static const char *last_asked_format = NULL; -static AVDictionary *ts_scale; -static StreamMap *stream_maps = NULL; -static int nb_stream_maps; - -static AVDictionary *codec_names; - -/* first item specifies output metadata, second is input */ -static MetadataMap (*meta_data_maps)[2] = NULL; -static int nb_meta_data_maps; -static int metadata_global_autocopy = 1; -static int metadata_streams_autocopy = 1; -static int metadata_chapters_autocopy = 1; - -static int chapters_input_file = INT_MAX; - -/* indexed by output file stream index */ -static int *streamid_map = NULL; -static int nb_streamid_map = 0; - -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 int frame_bits_per_raw_sample = 0; -static enum AVSampleFormat audio_sample_fmt = AV_SAMPLE_FMT_NONE; -static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX}; -static AVRational frame_rate; -static float video_qscale = 0; -static uint16_t *intra_matrix = NULL; -static uint16_t *inter_matrix = NULL; -static const char *video_rc_override_string=NULL; -static int video_disable = 0; static int video_discard = 0; -static unsigned int video_codec_tag = 0; -static char *video_language = NULL; static int same_quant = 0; static int do_deinterlace = 0; -static int top_field_first = -1; -static int me_threshold = 0; static int intra_dc_precision = 8; static int loop_input = 0; static int loop_output = AVFMT_NOOUTPUTLOOP; static int qp_hist = 0; -#if CONFIG_AVFILTER -static char *vfilters = NULL; -#endif - static int intra_only = 0; -static int audio_sample_rate = 0; -#define QSCALE_NONE -99999 -static float audio_qscale = QSCALE_NONE; -static int audio_disable = 0; -static int audio_channels = 0; -static unsigned int audio_codec_tag = 0; -static char *audio_language = NULL; - -static int subtitle_disable = 0; -static char *subtitle_language = NULL; -static unsigned int subtitle_codec_tag = 0; - -static int data_disable = 0; -static unsigned int data_codec_tag = 0; - -static float mux_preload= 0.5; -static float mux_max_delay= 0.7; - -static int64_t recording_time = INT64_MAX; -static int64_t start_time = 0; -static int64_t input_ts_offset = 0; +static const char *video_codec_name = NULL; +static const char *audio_codec_name = NULL; +static const char *subtitle_codec_name = NULL; + static int file_overwrite = 0; -static AVDictionary *metadata; static int do_benchmark = 0; static int do_hex_dump = 0; static int do_pkt_dump = 0; -static int do_psnr = 0; static int do_pass = 0; static const char *pass_logfilename_prefix; static int video_sync_method= -1; @@ -197,18 +139,13 @@ static int copy_tb= 0; static int opt_shortest = 0; static char *vstats_filename; static FILE *vstats_file; -static int opt_programid = 0; static int copy_initial_nonkeyframes = 0; -static int rate_emu = 0; - static int audio_volume = 256; static int exit_on_error = 0; static int using_stdin = 0; -static int verbose = 1; static int run_as_daemon = 0; -static int thread_count= 1; static int q_pressed = 0; static int64_t video_size = 0; static int64_t audio_size = 0; @@ -216,9 +153,6 @@ static int64_t extra_size = 0; static int nb_frames_dup = 0; static int nb_frames_drop = 0; static int input_sync; -static uint64_t limit_filesize = 0; -static int force_fps = 0; -static char *forced_key_frames = NULL; static float dts_delta_threshold = 10; @@ -226,11 +160,8 @@ static uint8_t *audio_buf; static uint8_t *audio_out; static unsigned int allocated_audio_out_size, allocated_audio_buf_size; -static short *samples; - -static AVBitStreamFilterContext *video_bitstream_filters=NULL; -static AVBitStreamFilterContext *audio_bitstream_filters=NULL; -static AVBitStreamFilterContext *subtitle_bitstream_filters=NULL; +static void *samples; +static uint8_t *input_tmp= NULL; #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" @@ -256,8 +187,10 @@ typedef struct InputFile { int eof_reached; /* true if eof reached */ int ist_index; /* index of first stream in ist_table */ int buffer_size; /* current total buffer size */ - int nb_streams; int64_t ts_offset; + int nb_streams; /* number of stream that avconv is aware of; may be different + from ctx.nb_streams if new streams appear during av_read_frame() */ + int rate_emu; } InputFile; typedef struct OutputStream { @@ -274,6 +207,7 @@ typedef struct OutputStream { int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number AVBitStreamFilterContext *bitstream_filters; AVCodec *enc; + int64_t max_frames; /* video only */ int video_resample; @@ -283,6 +217,8 @@ typedef struct OutputStream { int resample_width; int resample_pix_fmt; AVRational frame_rate; + int force_fps; + int top_field_first; float frame_aspect_ratio; @@ -293,15 +229,14 @@ typedef struct OutputStream { /* audio only */ int audio_resample; - ReSampleContext *resample; /* for audio resampling */ int resample_sample_fmt; int resample_channels; int resample_sample_rate; - int reformat_pair; - AVAudioConvert *reformat_ctx; AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */ FILE *logfile; + struct SwrContext *swr; + #if CONFIG_AVFILTER AVFilterContext *output_video_filter; AVFilterContext *input_video_filter; @@ -328,6 +263,7 @@ typedef struct OutputFile { int ost_index; /* index of the first stream in output_streams */ int64_t recording_time; /* desired length of the resulting file in microseconds */ int64_t start_time; /* start time in microseconds */ + uint64_t limit_filesize; } OutputFile; static InputStream *input_streams = NULL; @@ -340,6 +276,142 @@ static int nb_output_streams = 0; static OutputFile *output_files = NULL; static int nb_output_files = 0; +typedef struct OptionsContext { + /* input/output options */ + int64_t start_time; + const char *format; + + SpecifierOpt *codec_names; + int nb_codec_names; + SpecifierOpt *audio_channels; + int nb_audio_channels; + SpecifierOpt *audio_sample_rate; + int nb_audio_sample_rate; + SpecifierOpt *frame_rates; + int nb_frame_rates; + SpecifierOpt *frame_sizes; + int nb_frame_sizes; + SpecifierOpt *frame_pix_fmts; + int nb_frame_pix_fmts; + + /* input options */ + int64_t input_ts_offset; + int rate_emu; + + SpecifierOpt *ts_scale; + int nb_ts_scale; + + /* output options */ + StreamMap *stream_maps; + int nb_stream_maps; + /* first item specifies output metadata, second is input */ + MetadataMap (*meta_data_maps)[2]; + int nb_meta_data_maps; + int metadata_global_manual; + int metadata_streams_manual; + int metadata_chapters_manual; + + int chapters_input_file; + + int64_t recording_time; + uint64_t limit_filesize; + float mux_preload; + float mux_max_delay; + + int video_disable; + int audio_disable; + int subtitle_disable; + int data_disable; + + /* indexed by output file stream index */ + int *streamid_map; + int nb_streamid_map; + + SpecifierOpt *metadata; + int nb_metadata; + SpecifierOpt *max_frames; + int nb_max_frames; + SpecifierOpt *bitstream_filters; + int nb_bitstream_filters; + SpecifierOpt *codec_tags; + int nb_codec_tags; + SpecifierOpt *sample_fmts; + int nb_sample_fmts; + SpecifierOpt *qscale; + int nb_qscale; + SpecifierOpt *forced_key_frames; + int nb_forced_key_frames; + SpecifierOpt *force_fps; + int nb_force_fps; + SpecifierOpt *frame_aspect_ratios; + int nb_frame_aspect_ratios; + SpecifierOpt *rc_overrides; + int nb_rc_overrides; + SpecifierOpt *intra_matrices; + int nb_intra_matrices; + SpecifierOpt *inter_matrices; + int nb_inter_matrices; + SpecifierOpt *top_field_first; + int nb_top_field_first; +#if CONFIG_AVFILTER + SpecifierOpt *filters; + int nb_filters; +#endif +} OptionsContext; + +#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\ +{\ + int i, ret;\ + for (i = 0; i < o->nb_ ## name; i++) {\ + char *spec = o->name[i].specifier;\ + if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\ + outvar = o->name[i].u.type;\ + else if (ret < 0)\ + exit_program(1);\ + }\ +} + +static void reset_options(OptionsContext *o, int is_input) +{ + const OptionDef *po = options; + OptionsContext bak= *o; + + /* all OPT_SPEC and OPT_STRING can be freed in generic way */ + while (po->name) { + void *dst = (uint8_t*)o + po->u.off; + + if (po->flags & OPT_SPEC) { + SpecifierOpt **so = dst; + int i, *count = (int*)(so + 1); + for (i = 0; i < *count; i++) { + av_freep(&(*so)[i].specifier); + if (po->flags & OPT_STRING) + av_freep(&(*so)[i].u.str); + } + av_freep(so); + *count = 0; + } else if (po->flags & OPT_OFFSET && po->flags & OPT_STRING) + av_freep(dst); + po++; + } + + av_freep(&o->stream_maps); + av_freep(&o->meta_data_maps); + av_freep(&o->streamid_map); + + memset(o, 0, sizeof(*o)); + + if(is_input) o->recording_time = bak.recording_time; + else o->recording_time = INT64_MAX; + o->mux_preload = 0.5; + o->mux_max_delay = 0.7; + o->limit_filesize = UINT64_MAX; + o->chapters_input_file = INT_MAX; + + uninit_opts(); + init_opts(); +} + #if CONFIG_AVFILTER static int configure_video_filters(InputStream *ist, OutputStream *ost) @@ -349,6 +421,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) AVCodecContext *codec = ost->st->codec; AVCodecContext *icodec = ist->st->codec; enum PixelFormat pix_fmts[] = { codec->pix_fmt, PIX_FMT_NONE }; + AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc(); AVRational sample_aspect_ratio; char args[255]; int ret; @@ -368,8 +441,15 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) "src", args, NULL, ost->graph); if (ret < 0) return ret; +#if FF_API_OLD_VSINK_API ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, ost->graph); +#else + buffersink_params->pixel_fmts = pix_fmts; + ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"), + "out", NULL, buffersink_params, ost->graph); +#endif + av_freep(&buffersink_params); if (ret < 0) return ret; last_filter = ost->input_video_filter; @@ -437,8 +517,7 @@ static void term_exit(void) static volatile int received_sigterm = 0; -static void -sigterm_handler(int sig) +static void sigterm_handler(int sig) { received_sigterm = sig; q_pressed++; @@ -479,9 +558,9 @@ static void term_init(void) /* read a key without blocking */ static int read_key(void) { + unsigned char ch; #if HAVE_TERMIOS_H int n = 1; - unsigned char ch; struct timeval tv; fd_set rfds; @@ -501,6 +580,32 @@ static int read_key(void) return n; } #elif HAVE_KBHIT +# if HAVE_PEEKNAMEDPIPE + static int is_pipe; + static HANDLE input_handle; + DWORD dw, nchars; + if(!input_handle){ + input_handle = GetStdHandle(STD_INPUT_HANDLE); + is_pipe = !GetConsoleMode(input_handle, &dw); + } + + if (stdin->_cnt > 0) { + read(0, &ch, 1); + return ch; + } + if (is_pipe) { + /* When running under a GUI, you will end here. */ + if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL)) + return -1; + //Read it + if(nchars != 0) { + read(0, &ch, 1); + return ch; + }else{ + return -1; + } + } +# endif if(kbhit()) return(getch()); #endif @@ -513,7 +618,7 @@ static int decode_interrupt_cb(void) return q_pressed > 1; } -static int exit_program(int ret) +void exit_program(int ret) { int i; @@ -531,15 +636,10 @@ static int exit_program(int ret) for (i = 0; i < nb_input_streams; i++) av_dict_free(&input_streams[i].opts); - av_free(intra_matrix); - av_free(inter_matrix); - if (vstats_file) fclose(vstats_file); av_free(vstats_filename); - av_free(meta_data_maps); - av_freep(&input_streams); av_freep(&input_files); av_freep(&output_streams); @@ -555,22 +655,22 @@ static int exit_program(int ret) avfilter_uninit(); #endif + av_freep(&input_tmp); + if (received_sigterm) { - fprintf(stderr, - "Received signal %d: terminating.\n", - (int) received_sigterm); + av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n", + (int) received_sigterm); exit (255); } exit(ret); /* not all OS-es handle main() return value */ - return ret; } static void assert_avoptions(AVDictionary *m) { AVDictionaryEntry *t; if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) { - av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key); + av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key); exit_program(1); } } @@ -581,37 +681,17 @@ static void assert_codec_experimental(AVCodecContext *c, int encoder) AVCodec *codec; if (c->codec->capabilities & CODEC_CAP_EXPERIMENTAL && c->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(NULL, AV_LOG_ERROR, "%s '%s' is experimental and might produce bad " + av_log(NULL, AV_LOG_FATAL, "%s '%s' is experimental and might produce bad " "results.\nAdd '-strict experimental' if you want to use it.\n", codec_string, c->codec->name); codec = encoder ? avcodec_find_encoder(c->codec->id) : avcodec_find_decoder(c->codec->id); if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL)) - av_log(NULL, AV_LOG_ERROR, "Or use the non experimental %s '%s'.\n", + av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n", codec_string, codec->name); exit_program(1); } } -/* similar to ff_dynarray_add() and av_fast_realloc() */ -static void *grow_array(void *array, int elem_size, int *size, int new_size) -{ - if (new_size >= INT_MAX / elem_size) { - fprintf(stderr, "Array too big.\n"); - exit_program(1); - } - if (*size < new_size) { - uint8_t *tmp = av_realloc(array, new_size*elem_size); - if (!tmp) { - fprintf(stderr, "Could not alloc buffer.\n"); - exit_program(1); - } - memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size); - *size = new_size; - return tmp; - } - return array; -} - static void choose_sample_fmt(AVStream *st, AVCodec *codec) { if(codec && codec->sample_fmts){ @@ -681,15 +761,15 @@ static void choose_pixel_fmt(AVStream *st, AVCodec *codec) } } -static double -get_sync_ipts(const OutputStream *ost) +static double get_sync_ipts(const OutputStream *ost) { const InputStream *ist = ost->sync_ist; OutputFile *of = &output_files[ost->file_index]; return (double)(ist->pts - of->start_time)/AV_TIME_BASE; } -static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){ +static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc) +{ int ret; while(bsfc){ @@ -702,9 +782,9 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx av_free_packet(pkt); new_pkt.destruct= av_destruct_packet; } else if(a<0){ - fprintf(stderr, "%s failed for stream %d, codec %s", - bsfc->filter->name, pkt->stream_index, - avctx->codec ? avctx->codec->name : "copy"); + av_log(NULL, AV_LOG_ERROR, "%s failed for stream %d, codec %s", + bsfc->filter->name, pkt->stream_index, + avctx->codec ? avctx->codec->name : "copy"); print_error("", a); if (exit_on_error) exit_program(1); @@ -750,25 +830,26 @@ need_realloc: audio_out_size += FF_MIN_BUFFER_SIZE; if(audio_out_size > INT_MAX || audio_buf_size > INT_MAX){ - fprintf(stderr, "Buffer sizes too large\n"); + av_log(NULL, AV_LOG_FATAL, "Buffer sizes too large\n"); exit_program(1); } av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size); av_fast_malloc(&audio_out, &allocated_audio_out_size, audio_out_size); if (!audio_buf || !audio_out){ - fprintf(stderr, "Out of memory in do_audio_out\n"); + av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n"); exit_program(1); } - if (enc->channels != dec->channels) + if (enc->channels != dec->channels + || enc->sample_fmt != dec->sample_fmt) ost->audio_resample = 1; resample_changed = ost->resample_sample_fmt != dec->sample_fmt || ost->resample_channels != dec->channels || ost->resample_sample_rate != dec->sample_rate; - if ((ost->audio_resample && !ost->resample) || resample_changed) { + if ((ost->audio_resample && !ost->swr) || resample_changed) { if (resample_changed) { av_log(NULL, AV_LOG_INFO, "Input stream #%d.%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n", ist->file_index, ist->st->index, @@ -777,25 +858,30 @@ need_realloc: ost->resample_sample_fmt = dec->sample_fmt; ost->resample_channels = dec->channels; ost->resample_sample_rate = dec->sample_rate; - if (ost->resample) - audio_resample_close(ost->resample); + swr_free(&ost->swr); } /* if audio_sync_method is >1 the resampler is needed for audio drift compensation */ if (audio_sync_method <= 1 && ost->resample_sample_fmt == enc->sample_fmt && ost->resample_channels == enc->channels && ost->resample_sample_rate == enc->sample_rate) { - ost->resample = NULL; + //ost->swr = NULL; ost->audio_resample = 0; } else { - if (dec->sample_fmt != AV_SAMPLE_FMT_S16) - fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n"); - ost->resample = av_audio_resample_init(enc->channels, dec->channels, - enc->sample_rate, dec->sample_rate, - enc->sample_fmt, dec->sample_fmt, - 16, 10, 0, 0.8); - if (!ost->resample) { - fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n", + ost->swr = swr_alloc2(ost->swr, + enc->channel_layout, enc->sample_fmt, enc->sample_rate, + dec->channel_layout, dec->sample_fmt, dec->sample_rate, + 0, NULL); + av_set_int(ost->swr, "ich", dec->channels); + av_set_int(ost->swr, "och", enc->channels); + if(audio_sync_method>1) av_set_int(ost->swr, "flags", SWR_FLAG_RESAMPLE); + if(ost->swr && swr_init(ost->swr) < 0){ + av_log(NULL, AV_LOG_FATAL, "swr_init() failed\n"); + swr_free(&ost->swr); + } + + if (!ost->swr) { + av_log(NULL, AV_LOG_FATAL, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n", dec->channels, dec->sample_rate, enc->channels, enc->sample_rate); exit_program(1); @@ -803,21 +889,7 @@ need_realloc: } } -#define MAKE_SFMT_PAIR(a,b) ((a)+AV_SAMPLE_FMT_NB*(b)) - if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt && - MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt)!=ost->reformat_pair) { - 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", - av_get_sample_fmt_name(dec->sample_fmt), - av_get_sample_fmt_name(enc->sample_fmt)); - exit_program(1); - } - ost->reformat_pair=MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt); - } + av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt); if(audio_sync_method){ double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts @@ -832,13 +904,11 @@ need_realloc: byte_delta= FFMAX(byte_delta, -size); size += byte_delta; buf -= byte_delta; - if(verbose > 2) - fprintf(stderr, "discarding %d audio samples\n", (int)-delta); + av_log(NULL, AV_LOG_VERBOSE, "discarding %d audio samples\n", (int)-delta); if(!size) return; ist->is_start=0; }else{ - static uint8_t *input_tmp= NULL; input_tmp= av_realloc(input_tmp, byte_delta + size); if(byte_delta > allocated_for_size - size){ @@ -851,16 +921,15 @@ need_realloc: memcpy(input_tmp + byte_delta, buf, size); buf= input_tmp; size += byte_delta; - if(verbose > 2) - fprintf(stderr, "adding %d audio samples of silence\n", (int)delta); + av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", (int)delta); } }else if(audio_sync_method>1){ int comp= av_clip(delta, -audio_sync_method, audio_sync_method); av_assert0(ost->audio_resample); - if(verbose > 2) - fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate); + av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n", + delta, comp, enc->sample_rate); // fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2)); - av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate); + swr_compensate(ost->swr, comp, enc->sample_rate); } } }else @@ -869,36 +938,21 @@ need_realloc: if (ost->audio_resample) { buftmp = audio_buf; - size_out = audio_resample(ost->resample, - (short *)buftmp, (short *)buf, - size / (dec->channels * isize)); + size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp}, audio_buf_size / (enc->channels * osize), + (const uint8_t*[]){buf }, size / (dec->channels * isize)); size_out = size_out * enc->channels * osize; } else { buftmp = buf; size_out = size; } - if (!ost->audio_resample && dec->sample_fmt!=enc->sample_fmt) { - const void *ibuf[6]= {buftmp}; - void *obuf[6]= {audio_buf}; - int istride[6]= {isize}; - int ostride[6]= {osize}; - 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"); - if (exit_on_error) - exit_program(1); - return; - } - buftmp = audio_buf; - size_out = len*osize; - } + av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt); /* now encode as many frames as possible */ if (enc->frame_size > 1) { /* output resampled raw samples */ if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) { - fprintf(stderr, "av_fifo_realloc2() failed\n"); + av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n"); exit_program(1); } av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL); @@ -916,7 +970,7 @@ need_realloc: ret = avcodec_encode_audio(enc, audio_out, audio_out_size, (short *)audio_buf); if (ret < 0) { - fprintf(stderr, "Audio encoding failed\n"); + av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); exit_program(1); } audio_size += ret; @@ -943,7 +997,7 @@ need_realloc: size_out = size_out*coded_bps/8; if(size_out > audio_out_size){ - fprintf(stderr, "Internal error, buffer size too small\n"); + av_log(NULL, AV_LOG_FATAL, "Internal error, buffer size too small\n"); exit_program(1); } @@ -951,7 +1005,7 @@ need_realloc: ret = avcodec_encode_audio(enc, audio_out, size_out, (short *)buftmp); if (ret < 0) { - fprintf(stderr, "Audio encoding failed\n"); + av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); exit_program(1); } audio_size += ret; @@ -990,7 +1044,7 @@ static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void * if(avpicture_deinterlace(picture2, picture, dec->pix_fmt, dec->width, dec->height) < 0) { /* if error, do not deinterlace */ - fprintf(stderr, "Deinterlacing failed\n"); + av_log(NULL, AV_LOG_WARNING, "Deinterlacing failed\n"); av_free(buf); buf = NULL; picture2 = picture; @@ -1017,7 +1071,7 @@ static void do_subtitle_out(AVFormatContext *s, AVPacket pkt; if (pts == AV_NOPTS_VALUE) { - fprintf(stderr, "Subtitle packets must have a pts\n"); + av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n"); if (exit_on_error) exit_program(1); return; @@ -1046,7 +1100,7 @@ static void do_subtitle_out(AVFormatContext *s, subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out, subtitle_out_max_size, sub); if (subtitle_out_size < 0) { - fprintf(stderr, "Subtitle encoding failed\n"); + av_log(NULL, AV_LOG_FATAL, "Subtitle encoding failed\n"); exit_program(1); } @@ -1075,14 +1129,16 @@ static void do_video_resample(OutputStream *ost, AVFrame *in_picture, AVFrame **out_picture) { - int resample_changed = 0; - AVCodecContext *dec = ist->st->codec; +#if CONFIG_AVFILTER *out_picture = in_picture; -#if !CONFIG_AVFILTER - resample_changed = ost->resample_width != dec->width || - ost->resample_height != dec->height || - ost->resample_pix_fmt != dec->pix_fmt; +#else + AVCodecContext *dec = ist->st->codec; + AVCodecContext *enc = ost->st->codec; + int resample_changed = ost->resample_width != dec->width || + ost->resample_height != dec->height || + ost->resample_pix_fmt != dec->pix_fmt; + *out_picture = in_picture; if (resample_changed) { av_log(NULL, AV_LOG_INFO, "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", @@ -1106,7 +1162,7 @@ static void do_video_resample(OutputStream *ost, avcodec_get_frame_defaults(&ost->resample_frame); if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt, enc->width, enc->height)) { - fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n"); + av_log(NULL, AV_LOG_FATAL, "Cannot allocate temp picture, check pix fmt\n"); exit_program(1); } } @@ -1116,7 +1172,7 @@ static void do_video_resample(OutputStream *ost, enc->width, enc->height, enc->pix_fmt, ost->sws_flags, NULL, NULL, NULL); if (ost->img_resample_ctx == NULL) { - fprintf(stderr, "Cannot get resampling context\n"); + av_log(NULL, AV_LOG_FATAL, "Cannot get resampling context\n"); exit_program(1); } } @@ -1135,11 +1191,19 @@ static void do_video_out(AVFormatContext *s, { int nb_frames, i, ret, format_video_sync; AVFrame *final_picture; - AVCodecContext *enc, *dec; + AVCodecContext *enc; double sync_ipts; + double duration = 0; enc = ost->st->codec; - dec = ist->st->codec; + + if (ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) { + duration = FFMAX(av_q2d(ist->st->time_base), av_q2d(ist->st->codec->time_base)); + if(ist->st->avg_frame_rate.num) + duration= FFMAX(duration, 1/av_q2d(ist->st->avg_frame_rate)); + + duration /= av_q2d(enc->time_base); + } sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base); @@ -1153,7 +1217,7 @@ static void do_video_out(AVFormatContext *s, format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1; if (format_video_sync) { - double vdelta = sync_ipts - ost->sync_opts; + double vdelta = sync_ipts - ost->sync_opts + duration; //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; @@ -1167,17 +1231,15 @@ static void do_video_out(AVFormatContext *s, //fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames); if (nb_frames == 0){ ++nb_frames_drop; - if (verbose>2) - fprintf(stderr, "*** drop!\n"); + av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n"); }else if (nb_frames > 1) { nb_frames_dup += nb_frames - 1; - if (verbose>2) - fprintf(stderr, "*** %d dup!\n", nb_frames-1); + av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames-1); } }else ost->sync_opts= lrintf(sync_ipts); - nb_frames= FFMIN(nb_frames, max_frames[AVMEDIA_TYPE_VIDEO] - ost->frame_number); + nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number); if (nb_frames <= 0) return; @@ -1193,15 +1255,14 @@ static void do_video_out(AVFormatContext *s, /* raw pictures are written as AVPicture structure to avoid any copies. We support temporarily the older method. */ - AVFrame* old_frame = enc->coded_frame; - enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack + enc->coded_frame->interlaced_frame = in_picture->interlaced_frame; + enc->coded_frame->top_field_first = in_picture->top_field_first; pkt.data= (uint8_t *)final_picture; pkt.size= sizeof(AVPicture); pkt.pts= av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters); - enc->coded_frame = old_frame; } else { AVFrame big_picture; @@ -1210,16 +1271,16 @@ static void do_video_out(AVFormatContext *s, settings */ big_picture.interlaced_frame = in_picture->interlaced_frame; if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) { - if(top_field_first == -1) + if (ost->top_field_first == -1) big_picture.top_field_first = in_picture->top_field_first; else - big_picture.top_field_first = top_field_first; + big_picture.top_field_first = !!ost->top_field_first; } /* handles same_quant here. This is not correct because it may not be a global option */ big_picture.quality = quality; - if(!me_threshold) + if (!enc->me_threshold) big_picture.pict_type = 0; // big_picture.pts = AV_NOPTS_VALUE; big_picture.pts= ost->sync_opts; @@ -1234,7 +1295,7 @@ static void do_video_out(AVFormatContext *s, bit_buffer, bit_buffer_size, &big_picture); if (ret < 0) { - fprintf(stderr, "Video encoding failed\n"); + av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); exit_program(1); } @@ -1265,7 +1326,8 @@ static void do_video_out(AVFormatContext *s, } } -static double psnr(double d){ +static double psnr(double d) +{ return -10.0*log(d)/log(10.0); } @@ -1320,6 +1382,7 @@ static void print_report(OutputFile *output_files, int64_t pts = INT64_MAX; static int64_t last_time = -1; static int qp_histogram[52]; + int hours, mins, secs, us; if (!is_last_report) { int64_t cur_time; @@ -1396,48 +1459,44 @@ static void print_report(OutputFile *output_files, ost->st->time_base, AV_TIME_BASE_Q)); } - if (verbose > 0 || is_last_report) { - int hours, mins, secs, us; - secs = pts / AV_TIME_BASE; - us = pts % AV_TIME_BASE; - mins = secs / 60; - secs %= 60; - hours = mins / 60; - mins %= 60; - - bitrate = pts ? total_size * 8 / (pts / 1000.0) : 0; - - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "size=%8.0fkB time=", total_size / 1024.0); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%02d:%02d:%02d.%02d ", hours, mins, secs, - (100 * us) / AV_TIME_BASE); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "bitrate=%6.1fkbits/s", bitrate); - - if (nb_frames_dup || nb_frames_drop) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d", - nb_frames_dup, nb_frames_drop); - - if (verbose >= 0) - fprintf(stderr, "%s \r", buf); - - fflush(stderr); - } + secs = pts / AV_TIME_BASE; + us = pts % AV_TIME_BASE; + mins = secs / 60; + secs %= 60; + hours = mins / 60; + mins %= 60; + + bitrate = pts ? total_size * 8 / (pts / 1000.0) : 0; + + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "size=%8.0fkB time=", total_size / 1024.0); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "%02d:%02d:%02d.%02d ", hours, mins, secs, + (100 * us) / AV_TIME_BASE); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "bitrate=%6.1fkbits/s", bitrate); + + if (nb_frames_dup || nb_frames_drop) + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d", + nb_frames_dup, nb_frames_drop); + + av_log(NULL, is_last_report ? AV_LOG_WARNING : AV_LOG_INFO, "%s \r", buf); - if (is_last_report && verbose >= 0){ + fflush(stderr); + + if (is_last_report) { int64_t raw= audio_size + video_size + extra_size; - fprintf(stderr, "\n"); - fprintf(stderr, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n", - video_size/1024.0, - audio_size/1024.0, - extra_size/1024.0, - 100.0*(total_size - raw)/raw + av_log(NULL, AV_LOG_INFO, "\n"); + av_log(NULL, AV_LOG_INFO, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n", + video_size/1024.0, + audio_size/1024.0, + extra_size/1024.0, + 100.0*(total_size - raw)/raw ); } } -static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size) +static void generate_silence(uint8_t *buf, enum AVSampleFormat sample_fmt, size_t size) { int fill_char = 0x00; if (sample_fmt == AV_SAMPLE_FMT_U8) @@ -1445,7 +1504,7 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_ memset(buf, fill_char, size); } -static void flush_encoders(int ist_index, OutputStream *ost_table, int nb_ostreams) +static void flush_encoders(OutputStream *ost_table, int nb_ostreams) { int i, ret; @@ -1454,7 +1513,7 @@ static void flush_encoders(int ist_index, OutputStream *ost_table, int nb_ostrea AVCodecContext *enc = ost->st->codec; AVFormatContext *os = output_files[ost->file_index].ctx; - if (ost->source_index != ist_index || !ost->encoding_needed) + if (!ost->encoding_needed) continue; if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1) @@ -1496,7 +1555,7 @@ static void flush_encoders(int ist_index, OutputStream *ost_table, int nb_ostrea ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL); } if (ret < 0) { - fprintf(stderr, "Audio encoding failed\n"); + av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); exit_program(1); } audio_size += ret; @@ -1505,7 +1564,7 @@ static void flush_encoders(int ist_index, OutputStream *ost_table, int nb_ostrea case AVMEDIA_TYPE_VIDEO: ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL); if (ret < 0) { - fprintf(stderr, "Video encoding failed\n"); + av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); exit_program(1); } video_size += ret; @@ -1537,9 +1596,8 @@ static int output_packet(InputStream *ist, int ist_index, { AVFormatContext *os; OutputStream *ost; - int ret, i; + int ret = 0, i; int got_output; - AVFrame picture; void *buffer_to_free = NULL; static unsigned int samples_size= 0; AVSubtitle subtitle, *subtitle_to_free; @@ -1574,16 +1632,17 @@ static int output_packet(InputStream *ist, int ist_index, while (avpkt.size > 0 || (!pkt && got_output)) { uint8_t *data_buf, *decoded_data_buf; int data_size, decoded_data_size; + AVFrame *decoded_frame, *filtered_frame; handle_eof: ist->pts= ist->next_pts; - if(avpkt.size && avpkt.size != pkt->size && - ((!ist->showed_multi_packet_warning && verbose>0) || verbose>1)){ - fprintf(stderr, "Multiple frames in a packet from stream %d\n", pkt->stream_index); + if(avpkt.size && avpkt.size != pkt->size) + av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING, + "Multiple frames in a packet from stream %d\n", pkt->stream_index); ist->showed_multi_packet_warning=1; - } /* decode the packet if needed */ + decoded_frame = filtered_frame = NULL; decoded_data_buf = NULL; /* fail safe */ decoded_data_size= 0; data_buf = avpkt.data; @@ -1592,8 +1651,8 @@ static int output_packet(InputStream *ist, int ist_index, if (ist->decoding_needed) { switch(ist->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO:{ - 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); + if(pkt && samples_size < FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE)) { + samples_size = FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE); av_free(samples); samples= av_malloc(samples_size); } @@ -1620,22 +1679,23 @@ static int output_packet(InputStream *ist, int ist_index, break;} case AVMEDIA_TYPE_VIDEO: decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2; - /* XXX: allocate picture correctly */ - avcodec_get_frame_defaults(&picture); + if (!(decoded_frame = avcodec_alloc_frame())) + return AVERROR(ENOMEM); avpkt.pts = pkt_pts; avpkt.dts = ist->pts; pkt_pts = AV_NOPTS_VALUE; ret = avcodec_decode_video2(ist->st->codec, - &picture, &got_output, &avpkt); - quality = same_quant ? picture.quality : 0; + decoded_frame, &got_output, &avpkt); + quality = same_quant ? decoded_frame->quality : 0; if (ret < 0) - return ret; + goto fail; if (!got_output) { /* no picture yet */ + av_freep(&decoded_frame); goto discard_packet; } - ist->next_pts = ist->pts = picture.best_effort_timestamp; + ist->next_pts = ist->pts = decoded_frame->best_effort_timestamp; if (ist->st->codec->time_base.num != 0) { int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * @@ -1644,7 +1704,7 @@ static int output_packet(InputStream *ist, int ist_index, } avpkt.size = 0; buffer_to_free = NULL; - pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free); + pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free); break; case AVMEDIA_TYPE_SUBTITLE: ret = avcodec_decode_subtitle2(ist->st->codec, @@ -1675,21 +1735,21 @@ static int output_packet(InputStream *ist, int ist_index, } break; } - ret = avpkt.size; avpkt.size = 0; } #if CONFIG_AVFILTER if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) - if (start_time == 0 || ist->pts >= start_time) { - for(i=0;istart_time == 0 || ist->pts >= of->start_time) { ost = &ost_table[i]; if (ost->input_video_filter && ost->source_index == ist_index) { - if (!picture.sample_aspect_ratio.num) - picture.sample_aspect_ratio = ist->st->sample_aspect_ratio; - picture.pts = ist->pts; + if (!decoded_frame->sample_aspect_ratio.num) + decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; + decoded_frame->pts = ist->pts; - av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE); + av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE); } } } @@ -1698,19 +1758,63 @@ static int output_packet(InputStream *ist, int ist_index, // preprocess audio (volume) if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if (audio_volume != 256) { - short *volp; - volp = samples; - for(i=0;i<(decoded_data_size / sizeof(short));i++) { - int v = ((*volp) * audio_volume + 128) >> 8; - if (v < -32768) v = -32768; - if (v > 32767) v = 32767; - *volp++ = v; + switch (ist->st->codec->sample_fmt) { + case AV_SAMPLE_FMT_U8: + { + uint8_t *volp = samples; + for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { + int v = (((*volp - 128) * audio_volume + 128) >> 8) + 128; + *volp++ = av_clip_uint8(v); + } + break; + } + case AV_SAMPLE_FMT_S16: + { + int16_t *volp = samples; + for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { + int v = ((*volp) * audio_volume + 128) >> 8; + *volp++ = av_clip_int16(v); + } + break; + } + case AV_SAMPLE_FMT_S32: + { + int32_t *volp = samples; + for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { + int64_t v = (((int64_t)*volp * audio_volume + 128) >> 8); + *volp++ = av_clipl_int32(v); + } + break; + } + case AV_SAMPLE_FMT_FLT: + { + float *volp = samples; + float scale = audio_volume / 256.f; + for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { + *volp++ *= scale; + } + break; + } + case AV_SAMPLE_FMT_DBL: + { + double *volp = samples; + double scale = audio_volume / 256.; + for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { + *volp++ *= scale; + } + break; + } + default: + av_log(NULL, AV_LOG_FATAL, + "Audio volume adjustment on sample format %s is not supported.\n", + av_get_sample_fmt_name(ist->st->codec->sample_fmt)); + exit_program(1); } } } /* frame rate emulation */ - if (rate_emu) { + if (input_files[ist->file_index].rate_emu) { int64_t pts = av_rescale(ist->pts, 1000000, AV_TIME_BASE); int64_t now = av_gettime() - ist->start; if (pts > now) @@ -1742,13 +1846,20 @@ static int output_packet(InputStream *ist, int ist_index, while (frame_available) { if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) { AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base; - if (av_vsink_buffer_get_video_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0) + if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0) goto cont; + if (!filtered_frame && !(filtered_frame = avcodec_alloc_frame())) { + ret = AVERROR(ENOMEM); + goto fail; + } + *filtered_frame= *decoded_frame; //for me_threshold if (ost->picref) { - avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref); + avfilter_fill_frame_from_video_buffer_ref(filtered_frame, ost->picref); ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); } } +#else + filtered_frame = decoded_frame; #endif os = output_files[ost->file_index].ctx; @@ -1766,8 +1877,8 @@ static int output_packet(InputStream *ist, int ist_index, if (ost->picref->video && !ost->frame_aspect_ratio) ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio; #endif - do_video_out(os, ost, ist, &picture, &frame_size, - same_quant ? quality : ost->st->codec->global_quality); + do_video_out(os, ost, ist, filtered_frame, &frame_size, + same_quant ? quality : ost->st->codec->global_quality); if (vstats_filename && frame_size) do_video_stats(os, ost, frame_size); break; @@ -1779,7 +1890,6 @@ static int output_packet(InputStream *ist, int ist_index, abort(); } } else { - AVFrame avframe; //FIXME/XXX remove this AVPicture pict; AVPacket opkt; int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); @@ -1795,10 +1905,6 @@ static int output_packet(InputStream *ist, int ist_index, /* no reencoding needed : output the packet directly */ /* force the input stream PTS */ - avcodec_get_frame_defaults(&avframe); - ost->st->codec->coded_frame= &avframe; - avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY; - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_size += data_size; else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -1851,21 +1957,22 @@ static int output_packet(InputStream *ist, int ist_index, ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); avfilter_unref_buffer(ost->picref); } + av_freep(&filtered_frame); #endif } +fail: av_free(buffer_to_free); /* XXX: allocate the subtitles in the codec ? */ if (subtitle_to_free) { avsubtitle_free(subtitle_to_free); subtitle_to_free = NULL; } + av_freep(&decoded_frame); + if (ret < 0) + return ret; } discard_packet: - if (pkt == NULL) { - /* EOF handling */ - flush_encoders(ist_index, ost_table, nb_ostreams); - } return 0; } @@ -1890,19 +1997,16 @@ static void print_sdp(OutputFile *output_files, int n) static int init_input_stream(int ist_index, OutputStream *output_streams, int nb_output_streams, char *error, int error_len) { - int i; InputStream *ist = &input_streams[ist_index]; if (ist->decoding_needed) { AVCodec *codec = ist->dec; - if (!codec) - codec = avcodec_find_decoder(ist->st->codec->codec_id); if (!codec) { - snprintf(error, sizeof(error), "Decoder (codec %s) not found for input stream #%d.%d", + snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d.%d", avcodec_get_name(ist->st->codec->codec_id), ist->file_index, ist->st->index); return AVERROR(EINVAL); } if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { - snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d", + snprintf(error, error_len, "Error while opening decoder for input stream #%d.%d", ist->file_index, ist->st->index); return AVERROR(EINVAL); } @@ -1917,41 +2021,32 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb return 0; } -/* - * The following code is the main loop of the file converter - */ -static int transcode(OutputFile *output_files, - int nb_output_files, - InputFile *input_files, - int nb_input_files) +static int transcode_init(OutputFile *output_files, int nb_output_files, + InputFile *input_files, int nb_input_files) { - int ret = 0, i; - AVFormatContext *is, *os; + int ret = 0, i, j, k; + AVFormatContext *os; AVCodecContext *codec, *icodec; OutputStream *ost; InputStream *ist; char error[1024]; - int key; int want_sdp = 1; - uint8_t *no_packet; - int no_packet_count=0; - int64_t timer_start; - - if (!(no_packet = av_mallocz(nb_input_files))) - exit_program(1); - if (rate_emu) - for (i = 0; i < nb_input_streams; i++) - input_streams[i].start = av_gettime(); + /* init framerate emulation */ + for (i = 0; i < nb_input_files; i++) { + InputFile *ifile = &input_files[i]; + if (ifile->rate_emu) + for (j = 0; j < ifile->nb_streams; j++) + input_streams[j + ifile->ist_index].start = av_gettime(); + } /* output stream init */ for(i=0;inb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) { av_dump_format(os, i, os->filename, 1); - fprintf(stderr, "Output file #%d does not contain any stream\n", i); - ret = AVERROR(EINVAL); - goto fail; + av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i); + return AVERROR(EINVAL); } } @@ -1971,8 +2066,9 @@ static int transcode(OutputFile *output_files, if (ost->st->stream_copy) { uint64_t extra_size = (uint64_t)icodec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; - if (extra_size > INT_MAX) - goto fail; + if (extra_size > INT_MAX) { + return AVERROR(EINVAL); + } /* if stream_copy is selected, no need to decode or encode */ codec->codec_id = icodec->codec_id; @@ -1989,8 +2085,9 @@ static int transcode(OutputFile *output_files, codec->rc_max_rate = icodec->rc_max_rate; codec->rc_buffer_size = icodec->rc_buffer_size; codec->extradata= av_mallocz(extra_size); - if (!codec->extradata) - goto fail; + if (!codec->extradata) { + return AVERROR(ENOMEM); + } memcpy(codec->extradata, icodec->extradata, icodec->extradata_size); codec->extradata_size= icodec->extradata_size; @@ -2013,7 +2110,7 @@ static int transcode(OutputFile *output_files, switch(codec->codec_type) { case AVMEDIA_TYPE_AUDIO: if(audio_volume != 256) { - fprintf(stderr,"-acodec copy and -vol are incompatible (frames are not decoded)\n"); + av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n"); exit_program(1); } codec->channel_layout = icodec->channel_layout; @@ -2045,6 +2142,7 @@ static int transcode(OutputFile *output_files, codec->height = icodec->height; break; case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_ATTACHMENT: break; default: abort(); @@ -2055,9 +2153,9 @@ static int transcode(OutputFile *output_files, switch(codec->codec_type) { case AVMEDIA_TYPE_AUDIO: ost->fifo= av_fifo_alloc(1024); - if(!ost->fifo) - goto fail; - ost->reformat_pair = MAKE_SFMT_PAIR(AV_SAMPLE_FMT_NONE,AV_SAMPLE_FMT_NONE); + if (!ost->fifo) { + return AVERROR(ENOMEM); + } if (!codec->sample_rate) { codec->sample_rate = icodec->sample_rate; } @@ -2073,6 +2171,8 @@ static int transcode(OutputFile *output_files, if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels) codec->channel_layout = 0; ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1; + ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt + || codec->channel_layout != icodec->channel_layout; icodec->request_channels = codec->channels; ist->decoding_needed = 1; ost->encoding_needed = 1; @@ -2086,7 +2186,7 @@ static int transcode(OutputFile *output_files, choose_pixel_fmt(ost->st, ost->enc); if (ost->st->codec->pix_fmt == PIX_FMT_NONE) { - fprintf(stderr, "Video pixel format is unknown, stream cannot be encoded\n"); + av_log(NULL, AV_LOG_FATAL, "Video pixel format is unknown, stream cannot be encoded\n"); exit_program(1); } @@ -2110,7 +2210,7 @@ static int transcode(OutputFile *output_files, if (!ost->frame_rate.num) ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25,1}; - if (ost->enc && ost->enc->supported_framerates && !force_fps) { + if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) { int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); ost->frame_rate = ost->enc->supported_framerates[idx]; } @@ -2120,10 +2220,14 @@ static int transcode(OutputFile *output_files, av_log(os, AV_LOG_WARNING, "Frame rate very high for a muxer not effciciently supporting it.\n" "Please consider specifiying a lower framerate, a different muxer or -vsync 2\n"); } + for (j = 0; j < ost->forced_kf_count; j++) + ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j], + AV_TIME_BASE_Q, + codec->time_base); #if CONFIG_AVFILTER if (configure_video_filters(ist, ost)) { - fprintf(stderr, "Error opening filters!\n"); + av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n"); exit(1); } #endif @@ -2148,7 +2252,8 @@ static int transcode(OutputFile *output_files, if (codec->flags & CODEC_FLAG_PASS1) { f = fopen(logfilename, "wb"); if (!f) { - fprintf(stderr, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno)); + av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", + logfilename, strerror(errno)); exit_program(1); } ost->logfile = f; @@ -2156,7 +2261,8 @@ static int transcode(OutputFile *output_files, char *logbuffer; size_t logbuffer_size; if (read_file(logfilename, &logbuffer, &logbuffer_size) < 0) { - fprintf(stderr, "Error reading log file '%s' for pass-2 encoding\n", logfilename); + av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", + logfilename); exit_program(1); } codec->stats_in = logbuffer; @@ -2164,19 +2270,18 @@ static int transcode(OutputFile *output_files, } } if(codec->codec_type == AVMEDIA_TYPE_VIDEO){ - /* maximum video buffer size is 6-bytes per pixel, plus DPX header size */ + /* maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)*/ int size= codec->width * codec->height; - bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 1664); + bit_buffer_size= FFMAX(bit_buffer_size, 7*size + 10000); } } if (!bit_buffer) bit_buffer = av_malloc(bit_buffer_size); if (!bit_buffer) { - fprintf(stderr, "Cannot allocate %d bytes output buffer\n", - bit_buffer_size); - ret = AVERROR(ENOMEM); - goto fail; + av_log(NULL, AV_LOG_ERROR, "Cannot allocate %d bytes output buffer\n", + bit_buffer_size); + return AVERROR(ENOMEM); } /* open each encoder */ @@ -2212,14 +2317,33 @@ static int transcode(OutputFile *output_files, av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." "It takes bits/s as argument, not kbits/s\n"); extra_size += ost->st->codec->extradata_size; + + if (ost->st->codec->me_threshold) + input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV; } } /* init input streams */ for (i = 0; i < nb_input_streams; i++) - if ((ret = init_input_stream(i, output_streams, nb_output_streams, error, sizeof(error)) < 0)) + if ((ret = init_input_stream(i, output_streams, nb_output_streams, error, sizeof(error))) < 0) goto dump_format; + /* discard unused programs */ + for (i = 0; i < nb_input_files; i++) { + InputFile *ifile = &input_files[i]; + for (j = 0; j < ifile->ctx->nb_programs; j++) { + AVProgram *p = ifile->ctx->programs[j]; + int discard = AVDISCARD_ALL; + + for (k = 0; k < p->nb_stream_indexes; k++) + if (!input_streams[ifile->ist_index + p->stream_index[k]].discard) { + discard = AVDISCARD_DEFAULT; + break; + } + p->discard = discard; + } + } + /* open files and write file headers */ for (i = 0; i < nb_output_files; i++) { os = output_files[i].ctx; @@ -2242,42 +2366,63 @@ static int transcode(OutputFile *output_files, } /* dump the stream mapping */ - if (verbose >= 0) { - fprintf(stderr, "Stream mapping:\n"); - for (i = 0; i < nb_output_streams;i ++) { - ost = &output_streams[i]; - fprintf(stderr, " Stream #%d.%d -> #%d.%d", - input_streams[ost->source_index].file_index, - input_streams[ost->source_index].st->index, - ost->file_index, - ost->index); - if (ost->sync_ist != &input_streams[ost->source_index]) - fprintf(stderr, " [sync #%d.%d]", - ost->sync_ist->file_index, - ost->sync_ist->st->index); - if(ost->encoding_needed) - fprintf(stderr, ": %s -> %s", - input_streams[ost->source_index].dec ? - input_streams[ost->source_index].dec->name : "?", - ost->enc ? ost->enc->name : "?"); - else - fprintf(stderr, ": copy"); - fprintf(stderr, "\n"); - } + av_log(NULL, AV_LOG_INFO, "Stream mapping:\n"); + for (i = 0; i < nb_output_streams; i++) { + ost = &output_streams[i]; + av_log(NULL, AV_LOG_INFO, " Stream #%d.%d -> #%d.%d", + input_streams[ost->source_index].file_index, + input_streams[ost->source_index].st->index, + ost->file_index, + ost->index); + if (ost->sync_ist != &input_streams[ost->source_index]) + av_log(NULL, AV_LOG_INFO, " [sync #%d.%d]", + ost->sync_ist->file_index, + ost->sync_ist->st->index); + if (ost->st->stream_copy) + av_log(NULL, AV_LOG_INFO, " (copy)"); + else + av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index].dec ? + input_streams[ost->source_index].dec->name : "?", + ost->enc ? ost->enc->name : "?"); + av_log(NULL, AV_LOG_INFO, "\n"); } if (ret) { - fprintf(stderr, "%s\n", error); - goto fail; + av_log(NULL, AV_LOG_ERROR, "%s\n", error); + return ret; } if (want_sdp) { print_sdp(output_files, nb_output_files); } + return 0; +} + +/* + * The following code is the main loop of the file converter + */ +static int transcode(OutputFile *output_files, int nb_output_files, + InputFile *input_files, int nb_input_files) +{ + int ret, i; + AVFormatContext *is, *os; + OutputStream *ost; + InputStream *ist; + uint8_t *no_packet; + int no_packet_count=0; + int64_t timer_start; + int key; + + if (!(no_packet = av_mallocz(nb_input_files))) + exit_program(1); + + ret = transcode_init(output_files, nb_output_files, input_files, nb_input_files); + if (ret < 0) + goto fail; + if (!using_stdin) { - if(verbose >= 0) - fprintf(stderr, "Press [q] to stop, [?] for help\n"); + av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n"); avio_set_interrupt_cb(decode_interrupt_cb); } term_init(); @@ -2290,7 +2435,6 @@ static int transcode(OutputFile *output_files, int64_t ipts_min; double opts_min; - redo: ipts_min= INT64_MAX; opts_min= 1e100; /* if 'q' pressed, exits */ @@ -2301,8 +2445,8 @@ static int transcode(OutputFile *output_files, key = read_key(); if (key == 'q') break; - if (key == '+') verbose++; - if (key == '-') verbose--; + if (key == '+') av_log_set_level(av_log_get_level()+10); + if (key == '-') av_log_set_level(av_log_get_level()-10); if (key == 's') qp_hist ^= 1; if (key == 'h'){ if (do_hex_dump){ @@ -2313,27 +2457,40 @@ static int transcode(OutputFile *output_files, do_pkt_dump = 1; av_log_set_level(AV_LOG_DEBUG); } +#if CONFIG_AVFILTER if (key == 'c' || key == 'C'){ - char ret[4096], target[64], cmd[256], arg[256]={0}; - double ts; + char buf[4096], target[64], command[256], arg[256] = {0}; + double time; + int k, n = 0; fprintf(stderr, "\nEnter command: