Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 6 Dec 2011 00:37:27 +0000 (01:37 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 6 Dec 2011 00:37:27 +0000 (01:37 +0100)
* qatar/master:
  mov: Don't av_malloc(0).
  avconv: only allocate 1 AVFrame per input stream
  avconv: fix memleaks due to not freeing the AVFrame for audio
  h264-fate: remove -strict 1 except where necessary (mr4/5-tandberg).
  misc Doxygen markup improvements
  doxygen: eliminate Qt-style doxygen syntax
  g722: Add a regression test for muxing/demuxing in wav
  g722: Change bits per sample to 4
  g722dec: Signal skipping the lower bits via AVOptions instead of bits_per_coded_sample
  api-example: update to use avcodec_decode_audio4()
  avplay: use avcodec_decode_audio4()
  avplay: use a separate buffer for playing silence
  avformat: use avcodec_decode_audio4() in avformat_find_stream_info()
  avconv: use avcodec_decode_audio4() instead of avcodec_decode_audio3()
  mov: Allow empty stts atom.
  doc: document preferred Doxygen syntax and make patcheck detect it

Conflicts:
avconv.c
ffplay.c
libavcodec/mlpdec.c
libavcodec/version.h
libavformat/mov.c
tests/codec-regression.sh
tests/fate/h264.mak

Merged-by: Michael Niedermayer <michaelni@gmx.at>
31 files changed:
1  2 
avconv.c
cmdutils.h
doc/developer.texi
doc/examples/decoding_encoding.c
ffmpeg.c
ffplay.c
libavcodec/amrnbdec.c
libavcodec/cinepak.c
libavcodec/eamad.c
libavcodec/ivi_common.h
libavcodec/lsp.c
libavcodec/mlpdec.c
libavcodec/qcelpdata.h
libavcodec/rtjpeg.c
libavcodec/utils.c
libavcodec/version.h
libavdevice/pulse.c
libavdevice/x11grab.c
libavformat/avformat.h
libavformat/matroskadec.c
libavformat/mov.c
libavformat/nuv.c
libavformat/oggdec.c
libavformat/utils.c
libavutil/lzo.c
libavutil/lzo.h
libpostproc/postprocess.c
tests/codec-regression.sh
tests/fate/h264.mak
tests/ref/acodec/g722
tools/patcheck

diff --combined avconv.c
+++ b/avconv.c
@@@ -1,21 -1,21 +1,21 @@@
  /*
 - * avconv main
 - * Copyright (c) 2000-2011 The libav developers.
 + * ffmpeg main
 + * Copyright (c) 2000-2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "libavutil/libm.h"
  #include "libavformat/os_support.h"
  
 +#include "libavformat/ffm.h" // not public API
 +
  #if CONFIG_AVFILTER
 +# include "libavfilter/avcodec.h"
  # include "libavfilter/avfilter.h"
  # include "libavfilter/avfiltergraph.h"
 +# include "libavfilter/buffersink.h"
  # include "libavfilter/vsrc_buffer.h"
  #endif
  
  #include <sys/select.h>
  #endif
  
 +#if HAVE_TERMIOS_H
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <sys/time.h>
 +#include <termios.h>
 +#elif HAVE_KBHIT
 +#include <conio.h>
 +#endif
  #include <time.h>
  
  #include "cmdutils.h"
@@@ -109,9 -97,6 +109,9 @@@ typedef struct MetadataMap 
  
  static const OptionDef options[];
  
 +#define MAX_STREAMS 1024    /* arbitrary sanity check value */
 +
 +static int frame_bits_per_raw_sample = 0;
  static int video_discard = 0;
  static int same_quant = 0;
  static int do_deinterlace = 0;
@@@ -119,12 -104,11 +119,12 @@@ static int intra_dc_precision = 8
  static int qp_hist = 0;
  
  static int file_overwrite = 0;
 +static int no_file_overwrite = 0;
  static int do_benchmark = 0;
  static int do_hex_dump = 0;
  static int do_pkt_dump = 0;
  static int do_pass = 0;
 -static char *pass_logfilename_prefix = NULL;
 +static const char *pass_logfilename_prefix;
  static int video_sync_method= -1;
  static int audio_sync_method= 0;
  static float audio_drift_threshold= 0.1;
@@@ -138,8 -122,6 +138,8 @@@ static int audio_volume = 256
  
  static int exit_on_error = 0;
  static int using_stdin = 0;
 +static int run_as_daemon  = 0;
 +static int q_pressed = 0;
  static int64_t video_size = 0;
  static int64_t audio_size = 0;
  static int64_t extra_size = 0;
@@@ -155,8 -137,6 +155,6 @@@ static uint8_t *audio_buf
  static uint8_t *audio_out;
  static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
  
- static void *samples;
  #define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
  
  typedef struct InputStream {
      int discard;             /* true if stream data should be discarded */
      int decoding_needed;     /* true if the packets must be decoded in 'raw_fifo' */
      AVCodec *dec;
+     AVFrame *decoded_frame;
+     AVFrame *filtered_frame;
  
      int64_t       start;     /* time when read started */
      int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
                                  is not defined */
      int64_t       pts;       /* current pts */
 -    PtsCorrectionContext pts_ctx;
      double ts_scale;
      int is_start;            /* is 1 at the start and after a discontinuity */
      int showed_multi_packet_warning;
@@@ -205,7 -188,7 +205,7 @@@ typedef struct OutputStream 
  
      /* video only */
      int video_resample;
 -    AVFrame pict_tmp;      /* temporary image for resampling */
 +    AVFrame resample_frame;              /* temporary frame for image resampling */
      struct SwsContext *img_resample_ctx; /* for image resampling */
      int resample_height;
      int resample_width;
      int copy_initial_nonkeyframes;
  } OutputStream;
  
 +#if HAVE_TERMIOS_H
 +
 +/* init terminal so that we can grab keys */
 +static struct termios oldtty;
 +#endif
  
  typedef struct OutputFile {
      AVFormatContext *ctx;
@@@ -422,8 -400,7 +422,8 @@@ static int configure_video_filters(Inpu
      /** filter graph containing all filters including input & output */
      AVCodecContext *codec = ost->st->codec;
      AVCodecContext *icodec = ist->st->codec;
 -    FFSinkContext ffsink_ctx = { .pix_fmt = codec->pix_fmt };
 +    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;
                                         "src", args, NULL, ost->graph);
      if (ret < 0)
          return ret;
 -    ret = avfilter_graph_create_filter(&ost->output_video_filter, &ffsink,
 -                                       "out", NULL, &ffsink_ctx, ost->graph);
 +#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;
      ost->graph->scale_sws_opts = av_strdup(args);
  
      if (ost->avfilter) {
 -        AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
 -        AVFilterInOut *inputs  = av_malloc(sizeof(AVFilterInOut));
 +        AVFilterInOut *outputs = avfilter_inout_alloc();
 +        AVFilterInOut *inputs  = avfilter_inout_alloc();
  
          outputs->name    = av_strdup("in");
          outputs->filter_ctx = last_filter;
          inputs->pad_idx = 0;
          inputs->next    = NULL;
  
 -        if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, inputs, outputs, NULL)) < 0)
 +        if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
              return ret;
          av_freep(&ost->avfilter);
      } else {
  
  static void term_exit(void)
  {
 -    av_log(NULL, AV_LOG_QUIET, "");
 +    av_log(NULL, AV_LOG_QUIET, "%s", "");
 +#if HAVE_TERMIOS_H
 +    if(!run_as_daemon)
 +        tcsetattr (0, TCSANOW, &oldtty);
 +#endif
  }
  
  static volatile int received_sigterm = 0;
 -static volatile int received_nb_signals = 0;
  
  static void
  sigterm_handler(int sig)
  {
      received_sigterm = sig;
 -    received_nb_signals++;
 +    q_pressed++;
      term_exit();
  }
  
  static void term_init(void)
  {
 +#if HAVE_TERMIOS_H
 +    if(!run_as_daemon){
 +    struct termios tty;
 +
 +    tcgetattr (0, &tty);
 +    oldtty = tty;
 +    atexit(term_exit);
 +
 +    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
 +                          |INLCR|IGNCR|ICRNL|IXON);
 +    tty.c_oflag |= OPOST;
 +    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
 +    tty.c_cflag &= ~(CSIZE|PARENB);
 +    tty.c_cflag |= CS8;
 +    tty.c_cc[VMIN] = 1;
 +    tty.c_cc[VTIME] = 0;
 +
 +    tcsetattr (0, TCSANOW, &tty);
 +    signal(SIGQUIT, sigterm_handler); /* Quit (POSIX).  */
 +    }
 +#endif
 +
      signal(SIGINT , sigterm_handler); /* Interrupt (ANSI).  */
      signal(SIGTERM, sigterm_handler); /* Termination (ANSI).  */
  #ifdef SIGXCPU
  #endif
  }
  
 +/* read a key without blocking */
 +static int read_key(void)
 +{
 +#if HAVE_TERMIOS_H
 +    int n = 1;
 +    unsigned char ch;
 +    struct timeval tv;
 +    fd_set rfds;
 +
 +    if(run_as_daemon)
 +        return -1;
 +
 +    FD_ZERO(&rfds);
 +    FD_SET(0, &rfds);
 +    tv.tv_sec = 0;
 +    tv.tv_usec = 0;
 +    n = select(1, &rfds, NULL, NULL, &tv);
 +    if (n > 0) {
 +        n = read(0, &ch, 1);
 +        if (n == 1)
 +            return ch;
 +
 +        return n;
 +    }
 +#elif HAVE_KBHIT
 +    if(kbhit())
 +        return(getch());
 +#endif
 +    return -1;
 +}
 +
  static int decode_interrupt_cb(void *ctx)
  {
 -    return received_nb_signals > 1;
 +    q_pressed += read_key() == 'q';
 +    return q_pressed > 1;
  }
  
  static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
@@@ -612,8 -525,11 +612,11 @@@ void exit_program(int ret
      for(i=0;i<nb_input_files;i++) {
          av_close_input_file(input_files[i].ctx);
      }
-     for (i = 0; i < nb_input_streams; i++)
+     for (i = 0; i < nb_input_streams; i++) {
+         av_freep(&input_streams[i].decoded_frame);
+         av_freep(&input_streams[i].filtered_frame);
          av_dict_free(&input_streams[i].opts);
+     }
  
      if (vstats_file)
          fclose(vstats_file);
      av_free(audio_buf);
      av_free(audio_out);
      allocated_audio_buf_size= allocated_audio_out_size= 0;
-     av_free(samples);
  
  #if CONFIG_AVFILTER
      avfilter_uninit();
@@@ -679,9 -594,6 +681,9 @@@ static void choose_sample_fmt(AVStream 
                  break;
          }
          if (*p == -1) {
 +            if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
 +                av_log(NULL, AV_LOG_ERROR, "Convertion will not be lossless'\n");
 +            if(av_get_sample_fmt_name(st->codec->sample_fmt))
              av_log(NULL, AV_LOG_WARNING,
                     "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
                     av_get_sample_fmt_name(st->codec->sample_fmt),
      }
  }
  
 -/**
 - * Update the requested input sample format based on the output sample format.
 - * This is currently only used to request float output from decoders which
 - * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT.
 - * Ideally this will be removed in the future when decoders do not do format
 - * conversion and only output in their native format.
 - */
 -static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec,
 -                              AVCodecContext *enc)
 -{
 -    /* if sample formats match or a decoder sample format has already been
 -       requested, just return */
 -    if (enc->sample_fmt == dec->sample_fmt ||
 -        dec->request_sample_fmt > AV_SAMPLE_FMT_NONE)
 -        return;
 -
 -    /* if decoder supports more than one output format */
 -    if (dec_codec && dec_codec->sample_fmts &&
 -        dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE &&
 -        dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) {
 -        const enum AVSampleFormat *p;
 -        int min_dec = -1, min_inc = -1;
 -
 -        /* find a matching sample format in the encoder */
 -        for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) {
 -            if (*p == enc->sample_fmt) {
 -                dec->request_sample_fmt = *p;
 -                return;
 -            } else if (*p > enc->sample_fmt) {
 -                min_inc = FFMIN(min_inc, *p - enc->sample_fmt);
 -            } else
 -                min_dec = FFMIN(min_dec, enc->sample_fmt - *p);
 -        }
 -
 -        /* if none match, provide the one that matches quality closest */
 -        dec->request_sample_fmt = min_inc > 0 ? enc->sample_fmt + min_inc :
 -                                  enc->sample_fmt - min_dec;
 -    }
 -}
 -
  static void choose_sample_rate(AVStream *st, AVCodec *codec)
  {
      if(codec && codec->supported_samplerates){
@@@ -787,14 -739,11 +789,11 @@@ static void generate_silence(uint8_t* b
      memset(buf, fill_char, size);
  }
  
- static void do_audio_out(AVFormatContext *s,
-                          OutputStream *ost,
-                          InputStream *ist,
-                          unsigned char *buf, int size)
+ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
+                          InputStream *ist, AVFrame *decoded_frame)
  {
      uint8_t *buftmp;
      int64_t audio_out_size, audio_buf_size;
-     int64_t allocated_for_size= size;
  
      int size_out, frame_bytes, ret, resample_changed;
      AVCodecContext *enc= ost->st->codec;
      int osize = av_get_bytes_per_sample(enc->sample_fmt);
      int isize = av_get_bytes_per_sample(dec->sample_fmt);
      const int coded_bps = av_get_bits_per_sample(enc->codec->id);
+     uint8_t *buf = decoded_frame->data[0];
+     int size     = decoded_frame->nb_samples * dec->channels * isize;
+     int64_t allocated_for_size = size;
  
  need_realloc:
      audio_buf_size= (allocated_for_size + isize*dec->channels - 1) / (isize*dec->channels);
          exit_program(1);
      }
  
 -    if (enc->channels != dec->channels || enc->sample_rate != dec->sample_rate)
 +    if (enc->channels != dec->channels)
          ost->audio_resample = 1;
  
      resample_changed = ost->resample_sample_fmt  != dec->sample_fmt ||
              ost->resample_sample_rate == enc->sample_rate) {
              ost->resample = NULL;
              ost->audio_resample = 0;
 -        } else if (ost->audio_resample) {
 +        } else {
              if (dec->sample_fmt != AV_SAMPLE_FMT_S16)
                  av_log(NULL, AV_LOG_WARNING, "Using s16 intermediate sample format for resampling\n");
              ost->resample = av_audio_resample_init(enc->channels,    dec->channels,
@@@ -1142,46 -1094,36 +1144,46 @@@ static void do_video_resample(OutputStr
  {
      int resample_changed = 0;
      AVCodecContext *dec = ist->st->codec;
 +    AVCodecContext *enc = ost->st->codec;
      *out_picture = in_picture;
  
      resample_changed = ost->resample_width   != dec->width  ||
                         ost->resample_height  != dec->height ||
                         ost->resample_pix_fmt != dec->pix_fmt;
  
 +#if !CONFIG_AVFILTER
      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",
                 ist->file_index, ist->st->index,
                 ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
                 dec->width         , dec->height         , av_get_pix_fmt_name(dec->pix_fmt));
 -        if(!ost->video_resample)
 -            ost->video_resample = 1;
 +        ost->resample_width   = dec->width;
 +        ost->resample_height  = dec->height;
 +        ost->resample_pix_fmt = dec->pix_fmt;
      }
  
 -#if !CONFIG_AVFILTER
 +    ost->video_resample = dec->width   != enc->width  ||
 +                          dec->height  != enc->height ||
 +                          dec->pix_fmt != enc->pix_fmt;
 +
      if (ost->video_resample) {
 -        *out_picture = &ost->pict_tmp;
 -        if (resample_changed) {
 +        *out_picture = &ost->resample_frame;
 +        if (!ost->img_resample_ctx || resample_changed) {
 +            /* initialize the destination picture */
 +            if (!ost->resample_frame.data[0]) {
 +                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");
 +                    exit_program(1);
 +                }
 +            }
              /* initialize a new scaler context */
              sws_freeContext(ost->img_resample_ctx);
 -            ost->img_resample_ctx = sws_getContext(
 -                ist->st->codec->width,
 -                ist->st->codec->height,
 -                ist->st->codec->pix_fmt,
 -                ost->st->codec->width,
 -                ost->st->codec->height,
 -                ost->st->codec->pix_fmt,
 -                ost->sws_flags, NULL, NULL, NULL);
 +            ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt,
 +                                                   enc->width, enc->height, enc->pix_fmt,
 +                                                   ost->sws_flags, NULL, NULL, NULL);
              if (ost->img_resample_ctx == NULL) {
                  av_log(NULL, AV_LOG_FATAL, "Cannot get resampling context\n");
                  exit_program(1);
@@@ -1394,11 -1336,9 +1396,11 @@@ static void print_report(OutputFile *ou
      int64_t total_size;
      AVCodecContext *enc;
      int frame_number, vid, i;
 -    double bitrate, ti1, pts;
 +    double bitrate;
 +    int64_t pts = INT64_MAX;
      static int64_t last_time = -1;
      static int qp_histogram[52];
 +    int hours, mins, secs, us;
  
      if (!print_stats && !is_last_report)
          return;
          total_size= avio_tell(oc->pb);
  
      buf[0] = '\0';
 -    ti1 = 1e10;
      vid = 0;
      for(i=0;i<nb_ostreams;i++) {
          float q = -1;
              vid = 1;
          }
          /* compute min output value */
 -        pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
 -        if ((pts < ti1) && (pts > 0))
 -            ti1 = pts;
 +        pts = FFMIN(pts, av_rescale_q(ost->st->pts.val,
 +                                      ost->st->time_base, AV_TIME_BASE_Q));
      }
 -    if (ti1 < 0.01)
 -        ti1 = 0.01;
  
 -    bitrate = (double)(total_size * 8) / ti1 / 1000.0;
 +    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),
 -            "size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
 -            (double)total_size / 1024, ti1, bitrate);
 +             "bitrate=%6.1fkbits/s", bitrate);
  
      if (nb_frames_dup || nb_frames_drop)
          snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
@@@ -1628,7 -1561,6 +1630,7 @@@ static void do_streamcopy(InputStream *
  {
      OutputFile *of = &output_files[ost->file_index];
      int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
 +    AVPicture pict;
      AVPacket opkt;
  
      av_init_packet(&opkt);
          opkt.data = pkt->data;
          opkt.size = pkt->size;
      }
 +    if (of->ctx->oformat->flags & AVFMT_RAWPICTURE) {
 +        /* store AVPicture in AVPacket, as expected by the output format */
 +        avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
 +        opkt.data = (uint8_t *)&pict;
 +        opkt.size = sizeof(AVPicture);
 +        opkt.flags |= AV_PKT_FLAG_KEY;
 +    }
  
      write_frame(of->ctx, &opkt, ost->st->codec, ost->bitstream_filters);
      ost->st->codec->frame_number++;
@@@ -1697,39 -1622,42 +1699,42 @@@ static void rate_emu_sleep(InputStream 
  
  static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
  {
-     static unsigned int samples_size = 0;
+     AVFrame *decoded_frame;
+     AVCodecContext *avctx = ist->st->codec;
      int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
-     uint8_t *decoded_data_buf  = NULL;
-     int      decoded_data_size = 0;
      int i, ret;
  
-     if (pkt && samples_size < FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE)) {
-         av_free(samples);
-         samples_size = FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE);
-         samples      = av_malloc(samples_size);
-     }
-     decoded_data_size = samples_size;
+     if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
+         return AVERROR(ENOMEM);
+     else
+         avcodec_get_frame_defaults(ist->decoded_frame);
+     decoded_frame = ist->decoded_frame;
  
-     ret = avcodec_decode_audio3(ist->st->codec, samples, &decoded_data_size,
-                                 pkt);
-     if (ret < 0)
+     ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
+     if (ret < 0) {
          return ret;
-     *got_output  = decoded_data_size > 0;
+     }
  
-     /* Some bug in mpeg audio decoder gives */
-     /* decoded_data_size < 0, it seems they are overflows */
      if (!*got_output) {
          /* no audio frame */
          return ret;
      }
  
-     decoded_data_buf = (uint8_t *)samples;
-     ist->next_pts   += ((int64_t)AV_TIME_BASE/bps * decoded_data_size) /
-                        (ist->st->codec->sample_rate * ist->st->codec->channels);
+     /* if the decoder provides a pts, use it instead of the last packet pts.
+        the decoder could be delaying output by a packet or more. */
+     if (decoded_frame->pts != AV_NOPTS_VALUE)
+         ist->next_pts = decoded_frame->pts;
+     /* increment next_pts to use for the case where the input stream does not
+        have timestamps or there are multiple frames in the packet */
+     ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
+                      avctx->sample_rate;
  
      // preprocess audio (volume)
      if (audio_volume != 256) {
-         switch (ist->st->codec->sample_fmt) {
+         int decoded_data_size = decoded_frame->nb_samples * avctx->channels * bps;
+         void *samples = decoded_frame->data[0];
+         switch (avctx->sample_fmt) {
          case AV_SAMPLE_FMT_U8:
          {
              uint8_t *volp = samples;
  
          if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
              continue;
-         do_audio_out(output_files[ost->file_index].ctx, ost, ist,
-                      decoded_data_buf, decoded_data_size);
+         do_audio_out(output_files[ost->file_index].ctx, ost, ist, decoded_frame);
      }
      return ret;
  }
  
@@@ -1806,8 -1734,11 +1811,11 @@@ static int transcode_video(InputStream 
      int frame_available = 1;
  #endif
  
-     if (!(decoded_frame = avcodec_alloc_frame()))
+     if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
          return AVERROR(ENOMEM);
+     else
+         avcodec_get_frame_defaults(ist->decoded_frame);
+     decoded_frame = ist->decoded_frame;
      pkt->pts  = *pkt_pts;
      pkt->dts  = ist->pts;
      *pkt_pts  = AV_NOPTS_VALUE;
      ret = avcodec_decode_video2(ist->st->codec,
                                  decoded_frame, got_output, pkt);
      if (ret < 0)
-         goto fail;
+         return ret;
  
      quality = same_quant ? decoded_frame->quality : 0;
      if (!*got_output) {
          /* no picture yet */
-         av_freep(&decoded_frame);
          return ret;
      }
 -    ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts,
 -                                                 decoded_frame->pkt_dts);
 +    ist->next_pts = ist->pts = decoded_frame->best_effort_timestamp;
      if (pkt->duration)
          ist->next_pts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
      else if (ist->st->codec->time_base.num != 0) {
  
  #if CONFIG_AVFILTER
          if (ost->input_video_filter) {
 -            AVRational sar;
 -            if (ist->st->sample_aspect_ratio.num)
 -                sar = ist->st->sample_aspect_ratio;
 -            else
 -                sar = ist->st->codec->sample_aspect_ratio;
 -            av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, ist->pts, sar);
 +            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, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
-             if (!(filtered_frame = avcodec_alloc_frame())) {
-                 ret = AVERROR(ENOMEM);
-                 goto fail;
-             }
+             if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
+                 av_free(buffer_to_free);
+                 return AVERROR(ENOMEM);
+             } else
+                 avcodec_get_frame_defaults(ist->filtered_frame);
+             filtered_frame = ist->filtered_frame;
              frame_available = avfilter_poll_frame(ost->output_video_filter->inputs[0]);
          }
          while (frame_available) {
 -            AVRational ist_pts_tb;
 -            if (ost->output_video_filter)
 -                get_filtered_video_frame(ost->output_video_filter, filtered_frame, &ost->picref, &ist_pts_tb);
 -            if (ost->picref)
 -                ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
 +            if (ost->output_video_filter) {
 +                AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
 +                if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
 +                    goto cont;
 +                if (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);
 +                }
 +            }
              if (ost->picref->video && !ost->frame_aspect_ratio)
 -                ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect;
 +                ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
  #else
              filtered_frame = decoded_frame;
  #endif
              if (vstats_filename && frame_size)
                  do_video_stats(output_files[ost->file_index].ctx, ost, frame_size);
  #if CONFIG_AVFILTER
 +            cont:
              frame_available = ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
              if (ost->picref)
                  avfilter_unref_buffer(ost->picref);
          }
-         av_freep(&filtered_frame);
  #endif
      }
  
- fail:
      av_free(buffer_to_free);
-     av_freep(&decoded_frame);
      return ret;
  }
  
@@@ -2047,6 -1973,16 +2053,6 @@@ static int init_input_stream(int ist_in
              return AVERROR(EINVAL);
          }
  
 -        /* update requested sample format for the decoder based on the
 -           corresponding encoder sample format */
 -        for (i = 0; i < nb_output_streams; i++) {
 -            OutputStream *ost = &output_streams[i];
 -            if (ost->source_index == ist_index) {
 -                update_sample_fmt(ist->st->codec, codec, ost->st->codec);
 -                break;
 -            }
 -        }
 -
          if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
              snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d",
                      ist->file_index, ist->st->index);
  
      ist->pts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames*AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
      ist->next_pts = AV_NOPTS_VALUE;
 -    init_pts_correction(&ist->pts_ctx);
      ist->is_start = 1;
  
      return 0;
@@@ -2136,7 -2073,6 +2142,7 @@@ static int transcode_init(OutputFile *o
                  return AVERROR(ENOMEM);
              }
              memcpy(codec->extradata, icodec->extradata, icodec->extradata_size);
 +
              codec->extradata_size = icodec->extradata_size;
              if (!copy_tb) {
                  codec->time_base      = icodec->time_base;
                      codec->sample_fmt = icodec->sample_fmt;
                  choose_sample_fmt(ost->st, ost->enc);
  
 -                if (!codec->channels)
 +                if (!codec->channels) {
                      codec->channels = icodec->channels;
 -                codec->channel_layout = icodec->channel_layout;
 +                    codec->channel_layout = icodec->channel_layout;
 +                }
                  if (av_get_channel_layout_nb_channels(codec->channel_layout) != codec->channels)
                      codec->channel_layout = 0;
  
                                        codec->height  != icodec->height ||
                                        codec->pix_fmt != icodec->pix_fmt;
                  if (ost->video_resample) {
 -#if !CONFIG_AVFILTER
 -                    avcodec_get_frame_defaults(&ost->pict_tmp);
 -                    if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt,
 -                                       codec->width, codec->height)) {
 -                        av_log(NULL, AV_LOG_FATAL, "Cannot allocate temp picture, check pix fmt\n");
 -                        exit_program(1);
 -                    }
 -                    ost->img_resample_ctx = sws_getContext(
 -                        icodec->width,
 -                        icodec->height,
 -                        icodec->pix_fmt,
 -                        codec->width,
 -                        codec->height,
 -                        codec->pix_fmt,
 -                        ost->sws_flags, NULL, NULL, NULL);
 -                    if (ost->img_resample_ctx == NULL) {
 -                        av_log(NULL, AV_LOG_FATAL, "Cannot get resampling context\n");
 -                        exit_program(1);
 -                    }
 -#endif
 -                    codec->bits_per_raw_sample= 0;
 +                    codec->bits_per_raw_sample= frame_bits_per_raw_sample;
                  }
  
                  ost->resample_height  = icodec->height;
                      ost->frame_rate = ost->enc->supported_framerates[idx];
                  }
                  codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
 +                if(   av_q2d(codec->time_base) < 0.001 && video_sync_method
 +                   && (video_sync_method==1 || (video_sync_method<0 && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
 +                    av_log(oc, 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");
 +                }
  
  #if CONFIG_AVFILTER
                  if (configure_video_filters(ist, ost)) {
                  break;
              }
              /* two pass mode */
 -            if ((codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
 +            if (codec->codec_id != CODEC_ID_H264 &&
 +                (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
                  char logfilename[1024];
                  FILE *f;
  
              }
          }
          if(codec->codec_type == AVMEDIA_TYPE_VIDEO){
 +            /* maximum video buffer size is 6-bytes per pixel, plus DPX header size */
              int        size = codec->width * codec->height;
 -            bit_buffer_size = FFMAX(bit_buffer_size, 6*size + 200);
 +            bit_buffer_size = FFMAX(bit_buffer_size, 6*size + 1664);
          }
      }
  
              ret = AVERROR(EINVAL);
              goto dump_format;
          }
 -        assert_avoptions(output_files[i].opts);
 +//        assert_avoptions(output_files[i].opts);
          if (strcmp(oc->oformat->name, "rtp")) {
              want_sdp = 0;
          }
@@@ -2453,7 -2401,6 +2459,7 @@@ static int transcode(OutputFile *output
      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);
      if (ret < 0)
          goto fail;
  
 -    av_log(NULL, AV_LOG_INFO, "Press ctrl-c to stop encoding\n");
 +    if (!using_stdin) {
 +        av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
 +        avio_set_interrupt_cb(decode_interrupt_cb);
 +    }
      term_init();
  
      timer_start = av_gettime();
  
          ipts_min = INT64_MAX;
          opts_min= 1e100;
 +        /* if 'q' pressed, exits */
 +        if (!using_stdin) {
 +            if (q_pressed)
 +                break;
 +            /* read_key() returns 0 on EOF */
 +            key = read_key();
 +            if (key == 'q')
 +                break;
 +            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){
 +                    do_hex_dump = do_pkt_dump = 0;
 +                } else if(do_pkt_dump){
 +                    do_hex_dump = 1;
 +                } else
 +                    do_pkt_dump = 1;
 +                av_log_set_level(AV_LOG_DEBUG);
 +            }
 +            if (key == 'd' || key == 'D'){
 +                int debug=0;
 +                if(key == 'D') {
 +                    debug = input_streams[0].st->codec->debug<<1;
 +                    if(!debug) debug = 1;
 +                    while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
 +                        debug += debug;
 +                }else
 +                    scanf("%d", &debug);
 +                for(i=0;i<nb_input_streams;i++) {
 +                    input_streams[i].st->codec->debug = debug;
 +                }
 +                for(i=0;i<nb_output_streams;i++) {
 +                    ost = &output_streams[i];
 +                    ost->st->codec->debug = debug;
 +                }
 +                if(debug) av_log_set_level(AV_LOG_DEBUG);
 +                fprintf(stderr,"debug=%d\n", debug);
 +            }
 +            if (key == '?'){
 +                fprintf(stderr, "key    function\n"
 +                                "?      show this help\n"
 +                                "+      increase verbosity\n"
 +                                "-      decrease verbosity\n"
 +                                "D      cycle through available debug modes\n"
 +                                "h      dump packets/hex press to cycle through the 3 states\n"
 +                                "q      quit\n"
 +                                "s      Show QP histogram\n"
 +                );
 +            }
 +        }
  
          /* select the stream that we must read now by looking at the
             smallest output pts */
                  av_fifo_free(ost->fifo); /* works even if fifo is not
                                               initialized but set to zero */
                  av_freep(&ost->st->codec->subtitle_header);
 -                av_free(ost->pict_tmp.data[0]);
 +                av_free(ost->resample_frame.data[0]);
                  av_free(ost->forced_kf_pts);
                  if (ost->video_resample)
                      sws_freeContext(ost->img_resample_ctx);
@@@ -2958,7 -2851,7 +2964,7 @@@ static void add_input_streams(OptionsCo
          ist->st = st;
          ist->file_index = nb_input_files;
          ist->discard = 1;
 -        ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
 +        ist->opts = filter_codec_opts(codec_opts, choose_decoder(o, ic, st), ic, st);
  
          ist->ts_scale = 1.0;
          MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
  
          switch (dec->codec_type) {
          case AVMEDIA_TYPE_AUDIO:
 -            if (o->audio_disable)
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            if(o->audio_disable)
                  st->discard= AVDISCARD_ALL;
              break;
          case AVMEDIA_TYPE_VIDEO:
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
              rfps      = ic->streams[i]->r_frame_rate.num;
              rfps_base = ic->streams[i]->r_frame_rate.den;
              if (dec->lowres) {
                  dec->flags |= CODEC_FLAG_EMU_EDGE;
 -                dec->height >>= dec->lowres;
 -                dec->width  >>= dec->lowres;
              }
  
              if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
          case AVMEDIA_TYPE_DATA:
              break;
          case AVMEDIA_TYPE_SUBTITLE:
 -            if (o->subtitle_disable)
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            if(o->subtitle_disable)
                  st->discard = AVDISCARD_ALL;
              break;
          case AVMEDIA_TYPE_ATTACHMENT:
  
  static void assert_file_overwrite(const char *filename)
  {
 -    if (!file_overwrite &&
 +    if ((!file_overwrite || no_file_overwrite) &&
          (strchr(filename, ':') == NULL || filename[1] == ':' ||
           av_strstart(filename, "file:", NULL))) {
          if (avio_check(filename, 0) == 0) {
 -            if (!using_stdin) {
 +            if (!using_stdin && (!no_file_overwrite || file_overwrite)) {
                  fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
                  fflush(stderr);
                  if (!read_yesno()) {
@@@ -3297,7 -3186,7 +3303,7 @@@ static OutputStream *new_output_stream(
      st->codec->codec_type = type;
      choose_encoder(o, oc, ost);
      if (ost->enc) {
 -        ost->opts  = filter_codec_opts(codec_opts, ost->enc->id, oc, st);
 +        ost->opts  = filter_codec_opts(codec_opts, ost->enc, oc, st);
      }
  
      avcodec_get_context_defaults3(st->codec, ost->enc);
@@@ -3583,7 -3472,7 +3589,7 @@@ static int opt_streamid(OptionsContext 
          exit_program(1);
      }
      *p++ = '\0';
 -    idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, INT_MAX);
 +    idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
      o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1);
      o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
      return 0;
@@@ -3629,7 -3518,7 +3635,7 @@@ static int copy_chapters(InputFile *ifi
      return 0;
  }
  
 -static int read_avserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
 +static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
  {
      int i, err;
      AVFormatContext *ic = avformat_alloc_context();
  
          // FIXME: a more elegant solution is needed
          memcpy(st, ic->streams[i], sizeof(AVStream));
 -        st->info = NULL;
 +        st->info = av_malloc(sizeof(*st->info));
 +        memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
          avcodec_copy_context(st->codec, ic->streams[i]->codec);
  
          if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
@@@ -3676,20 -3564,36 +3682,20 @@@ static void opt_output_file(void *optct
      if (!strcmp(filename, "-"))
          filename = "pipe:";
  
 -    oc = avformat_alloc_context();
 +    err = avformat_alloc_output_context2(&oc, NULL, o->format, filename);
      if (!oc) {
 -        print_error(filename, AVERROR(ENOMEM));
 +        print_error(filename, err);
          exit_program(1);
      }
  
 -    if (o->format) {
 -        file_oformat = av_guess_format(o->format, NULL, NULL);
 -        if (!file_oformat) {
 -            av_log(NULL, AV_LOG_FATAL, "Requested output format '%s' is not a suitable output format\n", o->format);
 -            exit_program(1);
 -        }
 -    } else {
 -        file_oformat = av_guess_format(NULL, filename, NULL);
 -        if (!file_oformat) {
 -            av_log(NULL, AV_LOG_FATAL, "Unable to find a suitable output format for '%s'\n",
 -                   filename);
 -            exit_program(1);
 -        }
 -    }
 -
 -    oc->oformat = file_oformat;
 +    file_oformat= oc->oformat;
      oc->interrupt_callback = int_cb;
 -    av_strlcpy(oc->filename, filename, sizeof(oc->filename));
  
      if (!strcmp(file_oformat->name, "ffm") &&
          av_strstart(filename, "http:", NULL)) {
 -        /* special case for files sent to avserver: we get the stream
 -           parameters from avserver */
 -        int err = read_avserver_streams(o, oc, filename);
 +        /* special case for files sent to ffserver: we get the stream
 +           parameters from ffserver */
 +        int err = read_ffserver_streams(o, oc, filename);
          if (err < 0) {
              print_error(filename, err);
              exit_program(1);
          av_dict_set(&output_files[nb_output_files - 1].opts, "preload", buf, 0);
      }
      oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
 -    oc->flags |= AVFMT_FLAG_NONBLOCK;
  
      /* copy chapters */
      if (o->chapters_input_file >= nb_input_files) {
@@@ -4018,7 -3923,7 +4024,7 @@@ static void show_usage(void
      printf("\n");
  }
  
 -static void show_help(void)
 +static int opt_help(const char *opt, const char *arg)
  {
      int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
      av_log_set_callback(log_callback_help);
      show_help_children(avcodec_get_class(), flags);
      show_help_children(avformat_get_class(), flags);
      show_help_children(sws_get_class(), flags);
 +
 +    return 0;
  }
  
  static int opt_target(OptionsContext *o, const char *opt, const char *arg)
@@@ -4223,20 -4126,6 +4229,20 @@@ static int opt_data_frames(OptionsConte
      return parse_option(o, "frames:d", arg, options);
  }
  
 +static void log_callback_null(void* ptr, int level, const char* fmt, va_list vl)
 +{
 +}
 +
 +static int opt_passlogfile(const char *opt, const char *arg)
 +{
 +    pass_logfilename_prefix = arg;
 +#if CONFIG_LIBX264_ENCODER
 +    return opt_default("passlogfile", arg);
 +#else
 +    return 0;
 +#endif
 +}
 +
  static int opt_video_tag(OptionsContext *o, const char *opt, const char *arg)
  {
      return parse_option(o, "tag:v", arg, options);
@@@ -4264,7 -4153,6 +4270,7 @@@ static const OptionDef options[] = 
      { "f", HAS_ARG | OPT_STRING | OPT_OFFSET, {.off = OFFSET(format)}, "force format", "fmt" },
      { "i", HAS_ARG | OPT_FUNC2, {(void*)opt_input_file}, "input file name", "filename" },
      { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
 +    { "n", OPT_BOOL, {(void*)&no_file_overwrite}, "do not overwrite output files" },
      { "c", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
      { "codec", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
      { "pre", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(presets)}, "preset name", "preset" },
      { "s", HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(frame_sizes)}, "set frame size (WxH or abbreviation)", "size" },
      { "aspect", HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(frame_aspect_ratios)}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
      { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(frame_pix_fmts)}, "set pixel format", "format" },
 +    { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&frame_bits_per_raw_sample}, "set the number of bits per raw sample", "number" },
      { "vn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, {.off = OFFSET(video_disable)}, "disable video" },
      { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
      { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(rc_overrides)}, "rate control override for specific intervals", "override" },
      { "same_quant", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant},
        "use same quantizer as source (implies VBR)" },
      { "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" },
 -    { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" },
 +    { "passlogfile", HAS_ARG | OPT_VIDEO, {(void*)&opt_passlogfile}, "select two pass log file name prefix", "prefix" },
      { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace},
        "deinterlace pictures" },
      { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
@@@ -4382,13 -4269,6 +4388,13 @@@ int main(int argc, char **argv
      av_log_set_flags(AV_LOG_SKIP_REPEATED);
      parse_loglevel(argc, argv, options);
  
 +    if(argc>1 && !strcmp(argv[1], "-d")){
 +        run_as_daemon=1;
 +        av_log_set_callback(log_callback_null);
 +        argc--;
 +        argv++;
 +    }
 +
      avcodec_register_all();
  #if CONFIG_AVDEVICE
      avdevice_register_all();
diff --combined cmdutils.h
@@@ -2,25 -2,25 +2,25 @@@
   * Various utilities for command line tools
   * copyright (c) 2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 -#ifndef LIBAV_CMDUTILS_H
 -#define LIBAV_CMDUTILS_H
 +#ifndef FFMPEG_CMDUTILS_H
 +#define FFMPEG_CMDUTILS_H
  
  #include <stdint.h>
  
  #include "libavformat/avformat.h"
  #include "libswscale/swscale.h"
  
 +#ifdef __MINGW32__
 +#undef main /* We don't want SDL to override our main() */
 +#endif
 +
  /**
   * program name, defined by the program for show_version().
   */
@@@ -61,7 -57,7 +61,7 @@@ void uninit_opts(void)
  
  /**
   * Trivial log callback.
 - * Only suitable for show_help and similar since it lacks prefix handling.
 + * Only suitable for opt_help and similar since it lacks prefix handling.
   */
  void log_callback_help(void* ptr, int level, const char* fmt, va_list vl);
  
@@@ -76,8 -72,6 +76,8 @@@ int opt_default(const char *opt, const 
   */
  int opt_loglevel(const char *opt, const char *arg);
  
 +int opt_codec_debug(const char *opt, const char *arg);
 +
  /**
   * Limit the execution time.
   */
@@@ -196,7 -190,7 +196,7 @@@ void parse_loglevel(int argc, char **ar
   *
   * @param s  Corresponding format context.
   * @param st Stream from s to be checked.
-  * @param spec A stream specifier of the [v|a|s|d]:[<stream index>] form.
+  * @param spec A stream specifier of the [v|a|s|d]:[\<stream index\>] form.
   *
   * @return 1 if the stream matches, 0 if it doesn't, <0 on error
   */
@@@ -212,7 -206,7 +212,7 @@@ int check_stream_specifier(AVFormatCont
   * @param st A stream from s for which the options should be filtered.
   * @return a pointer to the created dictionary
   */
 -AVDictionary *filter_codec_opts(AVDictionary *opts, enum CodecID codec_id, AVFormatContext *s, AVStream *st);
 +AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodec *codec, AVFormatContext *s, AVStream *st);
  
  /**
   * Setup AVCodecContext options for avformat_find_stream_info().
@@@ -249,58 -243,50 +249,58 @@@ void show_banner(void)
   * Print the version of the program to stdout. The version message
   * depends on the current versions of the repository and of the libav*
   * libraries.
 + * This option processing function does not utilize the arguments.
   */
 -void show_version(void);
 +int opt_version(const char *opt, const char *arg);
  
  /**
   * Print the license of the program to stdout. The license depends on
   * the license of the libraries compiled into the program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_license(void);
 +int opt_license(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the formats supported by the
   * program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_formats(void);
 +int opt_formats(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the codecs supported by the
   * program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_codecs(void);
 +int opt_codecs(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the filters supported by the
   * program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_filters(void);
 +int opt_filters(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the bit stream filters supported by the
   * program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_bsfs(void);
 +int opt_bsfs(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the protocols supported by the
   * program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_protocols(void);
 +int opt_protocols(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the pixel formats supported by the
   * program.
 + * This option processing function does not utilize the arguments.
   */
 -void show_pix_fmts(void);
 +int opt_pix_fmts(const char *opt, const char *arg);
  
  /**
   * Print a listing containing all the sample formats supported by the
@@@ -325,14 -311,37 +325,14 @@@ int read_yesno(void)
   */
  int cmdutils_read_file(const char *filename, char **bufptr, size_t *size);
  
 -typedef struct {
 -    int64_t num_faulty_pts; /// Number of incorrect PTS values so far
 -    int64_t num_faulty_dts; /// Number of incorrect DTS values so far
 -    int64_t last_pts;       /// PTS of the last frame
 -    int64_t last_dts;       /// DTS of the last frame
 -} PtsCorrectionContext;
 -
 -/**
 - * Reset the state of the PtsCorrectionContext.
 - */
 -void init_pts_correction(PtsCorrectionContext *ctx);
 -
 -/**
 - * Attempt to guess proper monotonic timestamps for decoded video frames
 - * which might have incorrect times. Input timestamps may wrap around, in
 - * which case the output will as well.
 - *
 - * @param pts the pts field of the decoded AVPacket, as passed through
 - * AVCodecContext.reordered_opaque
 - * @param dts the dts field of the decoded AVPacket
 - * @return one of the input values, may be AV_NOPTS_VALUE
 - */
 -int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t pts, int64_t dts);
 -
  /**
   * Get a file corresponding to a preset file.
   *
   * If is_path is non-zero, look for the file in the path preset_name.
   * Otherwise search for a file named arg.ffpreset in the directories
 - * $AVCONV_DATADIR (if set), $HOME/.avconv, and in the datadir defined
 - * at configuration time, in that order. If no such file is found and
 + * $FFMPEG_DATADIR (if set), $HOME/.ffmpeg, and in the datadir defined
 + * at configuration time or in a "ffpresets" folder along the executable
 + * on win32, in that order. If no such file is found and
   * codec_name is defined, then search for a file named
   * codec_name-preset_name.ffpreset in the above-mentioned directories.
   *
  FILE *get_preset_file(char *filename, size_t filename_size,
                        const char *preset_name, int is_path, const char *codec_name);
  
 -typedef struct {
 -    enum PixelFormat pix_fmt;
 -} FFSinkContext;
 -
 -extern AVFilter ffsink;
 -
 -/**
 - * Extract a frame from sink.
 - *
 - * @return a negative error in case of failure, 1 if one frame has
 - * been extracted successfully.
 - */
 -int get_filtered_video_frame(AVFilterContext *sink, AVFrame *frame,
 -                             AVFilterBufferRef **picref, AVRational *pts_tb);
 -
  /**
   * Do all the necessary cleanup and abort.
   * This function is implemented in the avtools, not cmdutils.
@@@ -362,4 -386,4 +362,4 @@@ void exit_program(int ret)
   */
  void *grow_array(void *array, int elem_size, int *size, int new_size);
  
 -#endif /* LIBAV_CMDUTILS_H */
 +#endif /* CMDUTILS_H */
diff --combined doc/developer.texi
  decoding). Look at @file{libavcodec/apiexample.c} to see how to use it.
  
  @item libavformat is the library containing the file format handling (mux and
 -demux code for several formats). Look at @file{avplay.c} to use it in a
 +demux code for several formats). Look at @file{ffplay.c} to use it in a
  player. See @file{libavformat/output-example.c} to use it to generate
  audio or video streams.
  
  @end itemize
  
 -@section Integrating libav in your program
 -
 -Shared libraries should be used whenever is possible in order to reduce
 -the effort distributors have to pour to support programs and to ensure
 -only the public api is used.
 -
 -You can use Libav in your commercial program, but you must abide to the
 -license, LGPL or GPL depending on the specific features used, please refer
 -to @uref{http://libav.org/legal.html, our legal page} for a quick checklist and to
 -the following links for the exact text of each license:
 -@uref{http://git.libav.org/?p=libav.git;a=blob;f=COPYING.GPLv2, GPL version 2},
 -@uref{http://git.libav.org/?p=libav.git;a=blob;f=COPYING.GPLv3, GPL version 3},
 -@uref{http://git.libav.org/?p=libav.git;a=blob;f=COPYING.LGPLv2.1, LGPL version 2.1},
 -@uref{http://git.libav.org/?p=libav.git;a=blob;f=COPYING.LGPLv3, LGPL version 3}.
 -Any modification to the source code can be suggested for inclusion.
 -The best way to proceed is to send your patches to the
 -@uref{https://lists.libav.org/mailman/listinfo/libav-devel, libav-devel}
 -mailing list.
 +@section Integrating libavcodec or libavformat in your program
 +
 +You can integrate all the source code of the libraries to link them
 +statically to avoid any version problem. All you need is to provide a
 +'config.mak' and a 'config.h' in the parent directory. See the defines
 +generated by ./configure to understand what is needed.
 +
 +You can use libavcodec or libavformat in your commercial program, but
 +@emph{any patch you make must be published}. The best way to proceed is
 +to send your patches to the FFmpeg mailing list.
 +
 +@section Contributing
 +
 +There are 3 ways by which code gets into ffmpeg.
 +@itemize @bullet
 +@item Submitting Patches to the main developer mailing list
 +      see @ref{Submitting patches} for details.
 +@item Directly committing changes to the main tree.
 +@item Committing changes to a git clone, for example on github.com or
 +      gitorious.org. And asking us to merge these changes.
 +@end itemize
 +
 +Whichever way, changes should be reviewed by the maintainer of the code
 +before they are committed. And they should follow the @ref{Coding Rules}.
 +The developer making the commit and the author are responsible for their changes
 +and should try to fix issues their commit causes.
  
  @anchor{Coding Rules}
  @section Coding Rules
  
  @subsection Code formatting conventions
 -The code is written in K&R C style. That means the following:
 -@itemize @bullet
 -@item
 -The control statements are formatted by putting space betwen the statement
 -and parenthesis in the following way:
 -@example
 -for (i = 0; i < filter->input_count; i++) @{
 -@end example
 -@item
 -The case statement is always located at the same level as the switch itself:
 -@example
 -switch (link->init_state) @{
 -case AVLINK_INIT:
 -    continue;
 -case AVLINK_STARTINIT:
 -    av_log(filter, AV_LOG_INFO, "circular filter chain detected");
 -    return 0;
 -@end example
 -@item
 -Braces in function declarations are written on the new line:
 -@example
 -const char *avfilter_configuration(void)
 -@{
 -    return LIBAV_CONFIGURATION;
 -@}
 -@end example
 -@item
 -In case of a single-statement if, no curly braces are required:
 -@example
 -if (!pic || !picref)
 -    goto fail;
 -@end example
 -@item
 -Do not put spaces immediately inside parenthesis. @samp{if (ret)} is
 -a valid style; @samp{if ( ret )} is not.
 -@end itemize
  
  There are the following guidelines regarding the indentation in files:
  @itemize @bullet
@@@ -69,7 -97,7 +69,7 @@@ and only if this improves readability
  @end itemize
  The presentation is one inspired by 'indent -i4 -kr -nut'.
  
 -The main priority in Libav is simplicity and small code size in order to
 +The main priority in FFmpeg is simplicity and small code size in order to
  minimize the bug count.
  
  @subsection Comments
@@@ -77,6 -105,11 +77,11 @@@ Use the JavaDoc/Doxygen  format (see ex
  can be generated automatically. All nontrivial functions should have a comment
  above them explaining what the function does, even if it is just one sentence.
  All structures and their member variables should be documented, too.
+ Avoid Qt-style and similar Doxygen syntax with @code{!} in it, i.e. replace
+ @code{//!} with @code{///} and similar.  Also @@ syntax should be employed
+ for markup commands, i.e. use @code{@@param} and not @code{\param}.
  @example
  /**
   * @@file
@@@ -109,7 -142,7 +114,7 @@@ int myfunc(int my_parameter
  
  @subsection C language features
  
 -Libav is programmed in the ISO C90 language with a few additional
 +FFmpeg is programmed in the ISO C90 language with a few additional
  features from ISO C99, namely:
  @itemize @bullet
  @item
@@@ -141,10 -174,10 +146,10 @@@ GCC statement expressions (@samp{(x = (
  @end itemize
  
  @subsection Naming conventions
 -All names are using underscores (_), not CamelCase. For example,
 -@samp{avfilter_get_video_buffer} is a valid function name and
 -@samp{AVFilterGetVideo} is not. The only exception from this are structure
 -names; they should always be in the CamelCase
 +All names are using underscores (_), not CamelCase. For example, @samp{avfilter_get_video_buffer} is
 +a valid function name and @samp{AVFilterGetVideo} is not. The exception from this are type names, like
 +for example structs and enums; they should always be in the CamelCase
 +
  
  There are following conventions for naming variables and functions:
  @itemize @bullet
@@@ -183,17 -216,33 +188,17 @@@ should also be avoided if they don't ma
     an "or any later version" clause is also acceptable, but LGPL is
     preferred.
  @item
 -   All the patches MUST be reviewed in the mailing list before they are
 -   committed.
 -@item
 -   The Libav coding style should remain consistent. Changes to
 -   conform will be suggested during the review or implemented on commit.
 -@item
 -   Patches should be generated using @code{git format-patch} or directly sent
 -   using @code{git send-email}.
 -   Please make sure you give the proper credit by setting the correct author
 -   in the commit.
 -@item
 -   The commit message should have a short first line in the form of
 -   @samp{topic: short description} as header, separated by a newline
 -   from the body consting in few lines explaining the reason of the patch.
 -   Referring to the issue on the bug tracker does not exempt to report an
 -   excerpt of the bug.
 -@item
 -   Work in progress patches should be sent to the mailing list with the [WIP]
 -   or the [RFC] tag.
 +   You must not commit code which breaks FFmpeg! (Meaning unfinished but
 +   enabled code which breaks compilation or compiles but does not work or
 +   breaks the regression tests)
 +   You can commit unfinished stuff (for testing etc), but it must be disabled
 +   (#ifdef etc) by default so it does not interfere with other developers'
 +   work.
  @item
 -   Branches in public personal repos are advised as way to
 -   work on issues collaboratively.
 -@item
 -   You do not have to over-test things. If it works for you and you think it
 -   should work for others, send it to the mailing list for review.
 -   If you have doubt about portability please state it in the submission so
 -   people with specific hardware could test it.
 +   You do not have to over-test things. If it works for you, and you think it
 +   should work for others, then commit. If your code has problems
 +   (portability, triggers compiler bugs, unusual environment etc) they will be
 +   reported and eventually fixed.
  @item
     Do not commit unrelated changes together, split them into self-contained
     pieces. Also do not forget that if part B depends on part A, but A does not
     Keeping changes well split into self-contained parts makes reviewing and
     understanding them on the commit log mailing list easier. This also helps
     in case of debugging later on.
 -@item
 -   Patches that change behavior of the programs (renaming options etc) or
 -   public API or ABI should be discussed in depth and possible few days should
 -   pass between discussion and commit.
 -   Changes to the build system (Makefiles, configure script) which alter
 -   the expected behavior should be considered in the same regard.
 +   Also if you have doubts about splitting or not splitting, do not hesitate to
 +   ask/discuss it on the developer mailing list.
 +@item
 +   Do not change behavior of the programs (renaming options etc) or public
 +   API or ABI without first discussing it on the ffmpeg-devel mailing list.
 +   Do not remove functionality from the code. Just improve!
 +
 +   Note: Redundant code can be removed.
 +@item
 +   Do not commit changes to the build system (Makefiles, configure script)
 +   which change behavior, defaults etc, without asking first. The same
 +   applies to compiler warning fixes, trivial looking fixes and to code
 +   maintained by other developers. We usually have a reason for doing things
 +   the way we do. Send your changes as patches to the ffmpeg-devel mailing
 +   list, and if the code maintainers say OK, you may commit. This does not
 +   apply to files you wrote and/or maintain.
 +@item
 +   We refuse source indentation and other cosmetic changes if they are mixed
 +   with functional changes, such commits will be rejected and removed. Every
 +   developer has his own indentation style, you should not change it. Of course
 +   if you (re)write something, you can use your own style, even though we would
 +   prefer if the indentation throughout FFmpeg was consistent (Many projects
 +   force a given indentation style - we do not.). If you really need to make
 +   indentation changes (try to avoid this), separate them strictly from real
 +   changes.
 +
 +   NOTE: If you had to put if()@{ .. @} over a large (> 5 lines) chunk of code,
 +   then either do NOT change the indentation of the inner part within (do not
 +   move it to the right)! or do so in a separate commit
 +@item
 +   Always fill out the commit log message. Describe in a few lines what you
 +   changed and why. You can refer to mailing list postings if you fix a
 +   particular bug. Comments such as "fixed!" or "Changed it." are unacceptable.
 +   Recommended format:
 +   area changed: Short 1 line description
 +
 +   details describing what and why and giving references.
 +@item
 +   Make sure the author of the commit is set correctly. (see git commit --author)
 +   If you apply a patch, send an
 +   answer to ffmpeg-devel (or wherever you got the patch from) saying that
 +   you applied the patch.
  @item
     When applying patches that have been discussed (at length) on the mailing
     list, reference the thread in the log message.
  @item
 -    Subscribe to the
 -    @uref{https://lists.libav.org/mailman/listinfo/libav-devel, libav-devel} and
 -    @uref{https://lists.libav.org/mailman/listinfo/libav-commits, libav-commits}
 -    mailing lists.
 -    Bugs and possible improvements or general questions regarding commits
 -    are discussed on libav-devel. We expect you to react if problems with
 -    your code are uncovered.
 +    Do NOT commit to code actively maintained by others without permission.
 +    Send a patch to ffmpeg-devel instead. If no one answers within a reasonable
 +    timeframe (12h for build failures and security fixes, 3 days small changes,
 +    1 week for big patches) then commit your patch if you think it is OK.
 +    Also note, the maintainer can simply ask for more time to review!
 +@item
 +    Subscribe to the ffmpeg-cvslog mailing list. The diffs of all commits
 +    are sent there and reviewed by all the other developers. Bugs and possible
 +    improvements or general questions regarding commits are discussed there. We
 +    expect you to react if problems with your code are uncovered.
  @item
      Update the documentation if you change behavior or add features. If you are
 -    unsure how best to do this, send an [RFC] patch to libav-devel.
 +    unsure how best to do this, send a patch to ffmpeg-devel, the documentation
 +    maintainer(s) will review and commit your stuff.
  @item
 -    All discussions and decisions should be reported on the public developer
 -    mailing list, so that there is a reference to them.
 -    Other media (e.g. IRC) should be used for coordination and immediate
 -    collaboration.
 +    Try to keep important discussions and requests (also) on the public
 +    developer mailing list, so that all developers can benefit from them.
  @item
      Never write to unallocated memory, never write over the end of arrays,
      always check values read from some untrusted source before using them
 -    as array index or other risky things. Always use valgrind to doublecheck.
 +    as array index or other risky things.
  @item
      Remember to check if you need to bump versions for the specific libav
      parts (libavutil, libavcodec, libavformat) you are changing. You need
      Incrementing the third component means a noteworthy binary compatible
      change (e.g. encoder bug fix that matters for the decoder).
  @item
 -    Compiler warnings indicate potential bugs or code with bad style.
 +    Compiler warnings indicate potential bugs or code with bad style. If a type of
 +    warning always points to correct and clean code, that warning should
 +    be disabled, not the code changed.
 +    Thus the remaining warnings can either be bugs or correct code.
      If it is a bug, the bug has to be fixed. If it is not, the code should
      be changed to not generate a warning unless that causes a slowdown
      or obfuscates the code.
 -    If a type of warning leads to too many false positives, that warning
 -    should be disabled, not the code changed.
  @item
      If you add a new file, give it a proper license header. Do not copy and
      paste it from a random place, use an existing file as template.
  
  We think our rules are not too hard. If you have comments, contact us.
  
 -Note, some rules were borrowed from the MPlayer project.
 +Note, these rules are mostly borrowed from the MPlayer project.
  
 +@anchor{Submitting patches}
  @section Submitting patches
  
  First, read the @ref{Coding Rules} above if you did not yet, in particular
  the rules regarding patch submission.
  
 -As stated already, please do not submit a patch which contains several
 -unrelated changes.
 +When you submit your patch, please use @code{git format-patch} or
 +@code{git send-email}. We cannot read other diffs :-)
 +
 +Also please do not submit a patch which contains several unrelated changes.
  Split it into separate, self-contained pieces. This does not mean splitting
  file by file. Instead, make the patch as small as possible while still
  keeping it as a logical unit that contains an individual change, even
  if it spans multiple files. This makes reviewing your patches much easier
  for us and greatly increases your chances of getting your patch applied.
  
 -Use the patcheck tool of Libav to check your patch.
 +Use the patcheck tool of FFmpeg to check your patch.
  The tool is located in the tools directory.
  
  Run the @ref{Regression Tests} before submitting a patch in order to verify
@@@ -320,21 -327,26 +325,21 @@@ it does not cause unexpected problems
  
  Patches should be posted as base64 encoded attachments (or any other
  encoding which ensures that the patch will not be trashed during
 -transmission) to the
 -@uref{https://lists.libav.org/mailman/listinfo/libav-devel, libav-devel}
 -mailing list.
 +transmission) to the ffmpeg-devel mailing list, see
 +@url{http://lists.ffmpeg.org/mailman/listinfo/ffmpeg-devel}
  
  It also helps quite a bit if you tell us what the patch does (for example
  'replaces lrint by lrintf'), and why (for example '*BSD isn't C99 compliant
 -and has no lrint()'). This kind of explanation should be the body of the
 -commit message.
 +and has no lrint()')
  
  Also please if you send several patches, send each patch as a separate mail,
  do not attach several unrelated patches to the same mail.
  
 -Use @code{git send-email} when possible since it will properly send patches
 -without requiring extra care.
 -
  Your patch will be reviewed on the mailing list. You will likely be asked
  to make some changes and are expected to send in an improved version that
  incorporates the requests from the review. This process may go through
 -several iterations. Once your patch is deemed good enough, it will be
 -committed to the official Libav tree.
 +several iterations. Once your patch is deemed good enough, some developer
 +will pick it up and commit it to the official FFmpeg tree.
  
  Give us a few days to react. But if some time passes without reaction,
  send a reminder by email. Your patch should eventually be dealt with.
  @item
      Did you add the CodecID to @file{avcodec.h}?
  @item
 -    If it has a fourcc, did you add it to @file{libavformat/riff.c},
 +    If it has a fourCC, did you add it to @file{libavformat/riff.c},
      even if it is only a decoder?
  @item
      Did you add a rule to compile the appropriate files in the Makefile?
 -    Remember to do this even if you are just adding a format to a file that
 -    is already being compiled by some other rule, like a raw demuxer.
 +    Remember to do this even if you're just adding a format to a file that is
 +    already being compiled by some other rule, like a raw demuxer.
  @item
      Did you add an entry to the table of supported formats or codecs in
      @file{doc/general.texi}?
  @item
      Does @code{make fate} pass with the patch applied?
  @item
 -    Does @code{make checkheaders} pass with the patch applied?
 +    Was the patch generated with git format-patch or send-email?
  @item
 -    Is the patch against latest Libav git master branch?
 +    Did you sign off your patch? (git commit -s)
 +    See @url{http://kerneltrap.org/files/Jeremy/DCO.txt} for the meaning
 +    of sign off.
  @item
 -    Are you subscribed to the
 -    @uref{https://lists.libav.org/mailman/listinfo/libav-devel, libav-devel}
 -    mailing list? (Only list subscribers are allowed to post.)
 +    Did you provide a clear git commit log message?
 +@item
 +    Is the patch against latest FFmpeg git master branch?
 +@item
 +    Are you subscribed to ffmpeg-devel?
 +    (the list is subscribers only due to spam)
  @item
      Have you checked that the changes are minimal, so that the same cannot be
      achieved with a smaller patch and/or simpler final code?
      If the patch fixes a bug, did you provide enough information, including
      a sample, so the bug can be reproduced and the fix can be verified?
      Note please do not attach samples >100k to mails but rather provide a
 -    URL, you can upload to ftp://upload.libav.org
 +    URL, you can upload to ftp://upload.ffmpeg.org
  @item
      Did you provide a verbose summary about what the patch does change?
  @item
      patch easily?
  @item
      If you added a new file, did you insert a license header? It should be
 -    taken from Libav, not randomly copied and pasted from somewhere else.
 +    taken from FFmpeg, not randomly copied and pasted from somewhere else.
  @item
      You should maintain alphabetical order in alphabetically ordered lists as
      long as doing so does not break API/ABI compatibility.
  @item
      Lines with similar content should be aligned vertically when doing so
      improves readability.
 +@item
 +    Consider to add a regression test for your code.
 +@item
 +    If you added YASM code please check that things still work with --disable-yasm
  @end enumerate
  
  @section Patch review process
  
 -All patches posted to the
 -@uref{https://lists.libav.org/mailman/listinfo/libav-devel, libav-devel}
 -mailing list will be reviewed, unless they contain a
 +All patches posted to ffmpeg-devel will be reviewed, unless they contain a
  clear note that the patch is not for the git master branch.
  Reviews and comments will be posted as replies to the patch on the
  mailing list. The patch submitter then has to take care of every comment,
@@@ -468,25 -473,22 +473,25 @@@ After a patch is approved it will be co
  We will review all submitted patches, but sometimes we are quite busy so
  especially for large patches this can take several weeks.
  
 -When resubmitting patches, if their size grew or during the review different
 -issues arisen please split the patch so each issue has a specific patch.
 +If you feel that the review process is too slow and you are willing to try to
 +take over maintainership of the area of code you change then just clone
 +git master and maintain the area of code there. We will merge each area from
 +where its best maintained.
  
 -@anchor{Regression Tests}
 -@section Regression Tests
 +When resubmitting patches, please do not make any significant changes
 +not related to the comments received during review. Such patches will
 +be rejected. Instead, submit significant changes or new features as
 +separate patches.
  
 -Before submitting a patch (or committing to the repository), you should at
 -least make sure that it does not break anything.
 +@section Regression tests
  
 -If the code changed has already a test present in FATE you should run it,
 -otherwise it is advised to add it.
 +Before submitting a patch (or committing to the repository), you should at least
 +test that you did not break anything.
  
 -Improvements to codec or demuxer might change the FATE results. Make sure
 -to commit the update reference with the change and to explain in the comment
 -why the expected result changed.
 +Running 'make fate' accomplishes this, please see @file{doc/fate.txt} for details.
  
 -Please refer to @file{doc/fate.txt}.
 +[Of course, some patches may change the results of the regression tests. In
 +this case, the reference results of the regression tests shall be modified
 +accordingly].
  
  @bye
@@@ -1,38 -1,44 +1,39 @@@
  /*
 - * copyright (c) 2001 Fabrice Bellard
 + * Copyright (c) 2001 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * Permission is hereby granted, free of charge, to any person obtaining a copy
 + * of this software and associated documentation files (the "Software"), to deal
 + * in the Software without restriction, including without limitation the rights
 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 + * copies of the Software, and to permit persons to whom the Software is
 + * furnished to do so, subject to the following conditions:
   *
 - * Libav is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation; either
 - * version 2.1 of the License, or (at your option) any later version.
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
   *
 - * Libav is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - *
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 + * THE SOFTWARE.
   */
  
  /**
   * @file
   * libavcodec API use example.
   *
 - * @example libavcodec/api-example.c
 - * Note that this library only handles codecs (mpeg, mpeg4, etc...),
 - * not file formats (avi, vob, etc...). See library 'libavformat' for the
 + * Note that libavcodec only handles codecs (mpeg, mpeg4, etc...),
 + * not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the
   * format handling
   */
  
 -#include <stdlib.h>
 -#include <stdio.h>
 -#include <string.h>
 -
 -#ifdef HAVE_AV_CONFIG_H
 -#undef HAVE_AV_CONFIG_H
 -#endif
 -
 +#include "libavutil/imgutils.h"
 +#include "libavutil/opt.h"
  #include "libavcodec/avcodec.h"
  #include "libavutil/mathematics.h"
+ #include "libavutil/samplefmt.h"
  
  #define INBUF_SIZE 4096
  #define AUDIO_INBUF_SIZE 20480
@@@ -66,7 -72,6 +67,7 @@@ static void audio_encode_example(const 
      c->bit_rate = 64000;
      c->sample_rate = 44100;
      c->channels = 2;
 +    c->sample_fmt = AV_SAMPLE_FMT_S16;
  
      /* open it */
      if (avcodec_open(c, codec) < 0) {
@@@ -114,11 -119,11 +115,11 @@@ static void audio_decode_example(const 
  {
      AVCodec *codec;
      AVCodecContext *c= NULL;
-     int out_size, len;
+     int len;
      FILE *f, *outfile;
-     uint8_t *outbuf;
      uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
      AVPacket avpkt;
+     AVFrame *decoded_frame = NULL;
  
      av_init_packet(&avpkt);
  
          exit(1);
      }
  
-     outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
      f = fopen(filename, "rb");
      if (!f) {
          fprintf(stderr, "could not open %s\n", filename);
      avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
  
      while (avpkt.size > 0) {
-         out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
-         len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
+         int got_frame = 0;
+         if (!decoded_frame) {
+             if (!(decoded_frame = avcodec_alloc_frame())) {
+                 fprintf(stderr, "out of memory\n");
+                 exit(1);
+             }
+         } else
+             avcodec_get_frame_defaults(decoded_frame);
+         len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
          if (len < 0) {
              fprintf(stderr, "Error while decoding\n");
              exit(1);
          }
-         if (out_size > 0) {
+         if (got_frame) {
              /* if a frame has been decoded, output it */
-             fwrite(outbuf, 1, out_size, outfile);
+             int data_size = av_samples_get_buffer_size(NULL, c->channels,
+                                                        decoded_frame->nb_samples,
+                                                        c->sample_fmt, 1);
+             fwrite(decoded_frame->data[0], 1, data_size, outfile);
          }
          avpkt.size -= len;
          avpkt.data += len;
  
      fclose(outfile);
      fclose(f);
-     free(outbuf);
  
      avcodec_close(c);
      av_free(c);
+     av_free(decoded_frame);
  }
  
  /*
   * Video encoding example
   */
 -static void video_encode_example(const char *filename)
 +static void video_encode_example(const char *filename, int codec_id)
  {
      AVCodec *codec;
      AVCodecContext *c= NULL;
      int i, out_size, size, x, y, outbuf_size;
      FILE *f;
      AVFrame *picture;
 -    uint8_t *outbuf, *picture_buf;
 +    uint8_t *outbuf;
  
      printf("Video encoding\n");
  
      /* find the mpeg1 video encoder */
 -    codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
 +    codec = avcodec_find_encoder(codec_id);
      if (!codec) {
          fprintf(stderr, "codec not found\n");
          exit(1);
      c->max_b_frames=1;
      c->pix_fmt = PIX_FMT_YUV420P;
  
 +    if(codec_id == CODEC_ID_H264)
 +        av_opt_set(c->priv_data, "preset", "slow", 0);
 +
      /* open it */
      if (avcodec_open(c, codec) < 0) {
          fprintf(stderr, "could not open codec\n");
      /* alloc image and output buffer */
      outbuf_size = 100000;
      outbuf = malloc(outbuf_size);
 -    size = c->width * c->height;
 -    picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
  
 -    picture->data[0] = picture_buf;
 -    picture->data[1] = picture->data[0] + size;
 -    picture->data[2] = picture->data[1] + size / 4;
 -    picture->linesize[0] = c->width;
 -    picture->linesize[1] = c->width / 2;
 -    picture->linesize[2] = c->width / 2;
 +    /* the image can be allocated by any means and av_image_alloc() is
 +     * just the most convenient way if av_malloc() is to be used */
 +    av_image_alloc(picture->data, picture->linesize,
 +                   c->width, c->height, c->pix_fmt, 1);
  
      /* encode 1 second of video */
      for(i=0;i<25;i++) {
      outbuf[3] = 0xb7;
      fwrite(outbuf, 1, 4, f);
      fclose(f);
 -    free(picture_buf);
      free(outbuf);
  
      avcodec_close(c);
      av_free(c);
 +    av_free(picture->data[0]);
      av_free(picture);
      printf("\n");
  }
@@@ -450,8 -466,7 +461,8 @@@ int main(int argc, char **argv
          audio_encode_example("/tmp/test.mp2");
          audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
  
 -        video_encode_example("/tmp/test.mpg");
 +        video_encode_example("/tmp/test.h264", CODEC_ID_H264);
 +        video_encode_example("/tmp/test.mpg", CODEC_ID_MPEG1VIDEO);
          filename = "/tmp/test.mpg";
      } else {
          filename = argv[1];
diff --combined ffmpeg.c
+++ b/ffmpeg.c
@@@ -2,20 -2,20 +2,20 @@@
   * ffmpeg main
   * Copyright (c) 2000-2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "libavutil/avstring.h"
  #include "libavutil/libm.h"
  #include "libavformat/os_support.h"
 +#include "libswresample/swresample.h"
 +
 +#include "libavformat/ffm.h" // not public API
  
  #if CONFIG_AVFILTER
 +# include "libavfilter/avcodec.h"
  # include "libavfilter/avfilter.h"
  # include "libavfilter/avfiltergraph.h"
 +# include "libavfilter/buffersink.h"
  # include "libavfilter/vsrc_buffer.h"
  #endif
  
  #include <sys/select.h>
  #endif
  
 +#if HAVE_TERMIOS_H
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <sys/time.h>
 +#include <termios.h>
 +#elif HAVE_KBHIT
 +#include <conio.h>
 +#endif
  #include <time.h>
  
  #include "cmdutils.h"
@@@ -92,18 -79,12 +92,18 @@@ const int program_birth_year = 2000
  
  /* select an input stream for an output stream */
  typedef struct StreamMap {
 +    int disabled;           /** 1 is this mapping is disabled by a negative map */
      int file_index;
      int stream_index;
      int sync_file_index;
      int sync_stream_index;
  } StreamMap;
  
 +typedef struct {
 +    int  file_idx,  stream_idx,  channel_idx; // input
 +    int ofile_idx, ostream_idx;               // output
 +} AudioChannelMap;
 +
  /**
   * select an input file for an output file
   */
@@@ -113,93 -94,151 +113,94 @@@ typedef struct MetadataMap 
      int  index;     ///< stream/chapter/program number
  } MetadataMap;
  
 -typedef struct ChapterMap {
 -    int in_file;
 -    int out_file;
 -} ChapterMap;
 -
  static const OptionDef options[];
  
 -#define MAX_FILES 100
 -
 -static const char *last_asked_format = NULL;
 -static double *ts_scale;
 -static int  nb_ts_scale;
 -
 -static AVFormatContext *output_files[MAX_FILES];
 -static AVDictionary *output_opts[MAX_FILES];
 -static int nb_output_files = 0;
 -
 -static StreamMap *stream_maps = NULL;
 -static int nb_stream_maps;
 -
 -/* 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 ChapterMap *chapter_maps = NULL;
 -static int nb_chapter_maps;
 -
 -/* 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 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;
 +#define MAX_STREAMS 1024    /* arbitrary sanity check value */
 +
 +static int frame_bits_per_raw_sample = 0;
  static int video_discard = 0;
 -static char *video_codec_name = NULL;
 -static unsigned int video_codec_tag = 0;
 -static char *video_language = NULL;
 -static int same_quality = 0;
 +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 char  *audio_codec_name = NULL;
 -static unsigned int audio_codec_tag = 0;
 -static char *audio_language = NULL;
 -
 -static int subtitle_disable = 0;
 -static char *subtitle_codec_name = NULL;
 -static char *subtitle_language = NULL;
 -static unsigned int subtitle_codec_tag = 0;
 -
 -static int data_disable = 0;
 -static char *data_codec_name = NULL;
 -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 no_file_overwrite = 0;
  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 char *pass_logfilename_prefix = NULL;
 -static int audio_stream_copy = 0;
 -static int video_stream_copy = 0;
 -static int subtitle_stream_copy = 0;
 -static int data_stream_copy = 0;
 +static const char *pass_logfilename_prefix;
  static int video_sync_method= -1;
  static int audio_sync_method= 0;
  static float audio_drift_threshold= 0.1;
  static int copy_ts= 0;
 -static int copy_tb;
 +static int copy_tb= -1;
  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 thread_count= 1;
 +static int run_as_daemon  = 0;
 +static volatile int received_nb_signals = 0;
  static int64_t video_size = 0;
  static int64_t audio_size = 0;
  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;
  
 -static int64_t timer_start;
 +static int print_stats = 1;
  
  static uint8_t *audio_buf;
  static uint8_t *audio_out;
  static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
  
- static void *samples;
 -static short *samples;
 -
 -static AVBitStreamFilterContext *video_bitstream_filters=NULL;
 -static AVBitStreamFilterContext *audio_bitstream_filters=NULL;
 -static AVBitStreamFilterContext *subtitle_bitstream_filters=NULL;
 +static uint8_t *input_tmp= NULL;
  
  #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
  
 -struct InputStream;
 +typedef struct InputStream {
 +    int file_index;
 +    AVStream *st;
 +    int discard;             /* true if stream data should be discarded */
 +    int decoding_needed;     /* true if the packets must be decoded in 'raw_fifo' */
 +    AVCodec *dec;
++    AVFrame *decoded_frame;
++    AVFrame *filtered_frame;
 +
 +    int64_t       start;     /* time when read started */
 +    int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
 +                                is not defined */
 +    int64_t       pts;       /* current pts */
 +    double ts_scale;
 +    int is_start;            /* is 1 at the start and after a discontinuity */
 +    int showed_multi_packet_warning;
 +    AVDictionary *opts;
 +} InputStream;
 +
 +typedef struct InputFile {
 +    AVFormatContext *ctx;
 +    int eof_reached;      /* true if eof reached */
 +    int ist_index;        /* index of first stream in input_streams */
 +    int buffer_size;      /* current total buffer size */
 +    int64_t ts_offset;
 +    int nb_streams;       /* number of stream that ffmpeg 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 {
      int file_index;          /* file index */
      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;
 -    AVFrame pict_tmp;      /* temporary image for resampling */
 +    AVFrame resample_frame;              /* temporary frame for image resampling */
      struct SwsContext *img_resample_ctx; /* for image resampling */
      int resample_height;
      int resample_width;
      int resample_pix_fmt;
      AVRational frame_rate;
 +    int force_fps;
 +    int top_field_first;
  
      float frame_aspect_ratio;
  
  
      /* audio only */
      int audio_resample;
 -    ReSampleContext *resample; /* for audio resampling */
 +    int audio_channels_map[SWR_CH_MAX];  ///< list of the channels id to pick from the source stream
 +    int audio_channels_mapped;           ///< number of channels in audio_channels_map
      int resample_sample_fmt;
      int resample_channels;
      int resample_sample_rate;
 -    int reformat_pair;
 -    AVAudioConvert *reformat_ctx;
 +    float rematrix_volume;
      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;
      AVFilterGraph *graph;
  #endif
  
 -   int sws_flags;
 -   AVDictionary *opts;
 +    int64_t sws_flags;
 +    AVDictionary *opts;
 +    int is_past_recording_time;
 +    int stream_copy;
 +    const char *attachment_filename;
 +    int copy_initial_nonkeyframes;
  } OutputStream;
  
 -static OutputStream **output_streams_for_file[MAX_FILES] = { NULL };
 -static int nb_output_streams_for_file[MAX_FILES] = { 0 };
  
 -typedef struct InputStream {
 -    int file_index;
 -    AVStream *st;
 -    int discard;             /* true if stream data should be discarded */
 -    int decoding_needed;     /* true if the packets must be decoded in 'raw_fifo' */
 -    AVCodec *dec;
 +#if HAVE_TERMIOS_H
  
 -    int64_t       start;     /* time when read started */
 -    int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
 -                                is not defined */
 -    int64_t       pts;       /* current pts */
 -    PtsCorrectionContext pts_ctx;
 -    double ts_scale;
 -    int is_start;            /* is 1 at the start and after a discontinuity */
 -    int showed_multi_packet_warning;
 -    int is_past_recording_time;
 -    AVDictionary *opts;
 -} InputStream;
 +/* init terminal so that we can grab keys */
 +static struct termios oldtty;
 +#endif
  
 -typedef struct InputFile {
 +typedef struct OutputFile {
      AVFormatContext *ctx;
 -    int eof_reached;      /* true if eof reached */
 -    int ist_index;        /* index of first stream in ist_table */
 -    int buffer_size;      /* current total buffer size */
 -    int64_t ts_offset;
 -    int nb_streams;       /* nb streams we are aware of */
 -} InputFile;
 +    AVDictionary *opts;
 +    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;
  static int         nb_input_streams = 0;
  static InputFile   *input_files   = NULL;
  static int         nb_input_files   = 0;
  
 +static OutputStream *output_streams = NULL;
 +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 *rematrix_volume;
 +    int        nb_rematrix_volume;
 +    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;
 +    SpecifierOpt *dump_attachment;
 +    int        nb_dump_attachment;
 +
 +    /* output options */
 +    StreamMap *stream_maps;
 +    int     nb_stream_maps;
 +    AudioChannelMap *audio_channel_maps; ///< one info entry per -map_channel
 +    int           nb_audio_channel_maps; ///< number of (valid) -map_channel settings
 +    /* 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;
 +    const char **attachments;
 +    int       nb_attachments;
 +
 +    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;
 +    SpecifierOpt *presets;
 +    int        nb_presets;
 +    SpecifierOpt *copy_initial_nonkeyframes;
 +    int        nb_copy_initial_nonkeyframes;
 +#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->audio_channel_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_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)
      /** filter graph containing all filters including input & output */
      AVCodecContext *codec = ost->st->codec;
      AVCodecContext *icodec = ist->st->codec;
 -    FFSinkContext ffsink_ctx = { .pix_fmt = codec->pix_fmt };
 +    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;
                                         "src", args, NULL, ost->graph);
      if (ret < 0)
          return ret;
 -    ret = avfilter_graph_create_filter(&ost->output_video_filter, &ffsink,
 -                                       "out", NULL, &ffsink_ctx, ost->graph);
 +#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;
          snprintf(args, 255, "%d:%d:flags=0x%X",
                   codec->width,
                   codec->height,
 -                 ost->sws_flags);
 +                 (unsigned)ost->sws_flags);
          if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
                                                  NULL, args, NULL, ost->graph)) < 0)
              return ret;
          last_filter = filter;
      }
  
 -    snprintf(args, sizeof(args), "flags=0x%X", ost->sws_flags);
 +    snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
      ost->graph->scale_sws_opts = av_strdup(args);
  
      if (ost->avfilter) {
 -        AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
 -        AVFilterInOut *inputs  = av_malloc(sizeof(AVFilterInOut));
 +        AVFilterInOut *outputs = avfilter_inout_alloc();
 +        AVFilterInOut *inputs  = avfilter_inout_alloc();
  
          outputs->name    = av_strdup("in");
          outputs->filter_ctx = last_filter;
          inputs->pad_idx = 0;
          inputs->next    = NULL;
  
 -        if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, inputs, outputs, NULL)) < 0)
 +        if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
              return ret;
          av_freep(&ost->avfilter);
      } else {
      codec->width  = ost->output_video_filter->inputs[0]->w;
      codec->height = ost->output_video_filter->inputs[0]->h;
      codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
 -        ost->frame_aspect_ratio ? // overriden by the -aspect cli option
 +        ost->frame_aspect_ratio ? // overridden by the -aspect cli option
          av_d2q(ost->frame_aspect_ratio*codec->height/codec->width, 255) :
          ost->output_video_filter->inputs[0]->sample_aspect_ratio;
  
  
  static void term_exit(void)
  {
 -    av_log(NULL, AV_LOG_QUIET, "");
 +    av_log(NULL, AV_LOG_QUIET, "%s", "");
 +#if HAVE_TERMIOS_H
 +    if(!run_as_daemon)
 +        tcsetattr (0, TCSANOW, &oldtty);
 +#endif
  }
  
  static volatile int received_sigterm = 0;
 -static volatile int received_nb_signals = 0;
  
 -static void
 -sigterm_handler(int sig)
 +static void sigterm_handler(int sig)
  {
      received_sigterm = sig;
      received_nb_signals++;
  
  static void term_init(void)
  {
 +#if HAVE_TERMIOS_H
 +    if(!run_as_daemon){
 +    struct termios tty;
 +
 +    tcgetattr (0, &tty);
 +    oldtty = tty;
 +    atexit(term_exit);
 +
 +    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
 +                          |INLCR|IGNCR|ICRNL|IXON);
 +    tty.c_oflag |= OPOST;
 +    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
 +    tty.c_cflag &= ~(CSIZE|PARENB);
 +    tty.c_cflag |= CS8;
 +    tty.c_cc[VMIN] = 1;
 +    tty.c_cc[VTIME] = 0;
 +
 +    tcsetattr (0, TCSANOW, &tty);
 +    signal(SIGQUIT, sigterm_handler); /* Quit (POSIX).  */
 +    }
 +#endif
 +    avformat_network_deinit();
 +
      signal(SIGINT , sigterm_handler); /* Interrupt (ANSI).  */
      signal(SIGTERM, sigterm_handler); /* Termination (ANSI).  */
  #ifdef SIGXCPU
  #endif
  }
  
 -static int decode_interrupt_cb(void)
 +/* read a key without blocking */
 +static int read_key(void)
 +{
 +    unsigned char ch;
 +#if HAVE_TERMIOS_H
 +    int n = 1;
 +    struct timeval tv;
 +    fd_set rfds;
 +
 +    FD_ZERO(&rfds);
 +    FD_SET(0, &rfds);
 +    tv.tv_sec = 0;
 +    tv.tv_usec = 0;
 +    n = select(1, &rfds, NULL, NULL, &tv);
 +    if (n > 0) {
 +        n = read(0, &ch, 1);
 +        if (n == 1)
 +            return ch;
 +
 +        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
 +    return -1;
 +}
 +
 +static int decode_interrupt_cb(void *ctx)
  {
      return received_nb_signals > 1;
  }
  
 -void exit_program(int ret)
 +static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
 +
 +void av_noreturn exit_program(int ret)
  {
      int i;
  
      /* close files */
      for(i=0;i<nb_output_files;i++) {
 -        AVFormatContext *s = output_files[i];
 +        AVFormatContext *s = output_files[i].ctx;
          if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
              avio_close(s->pb);
          avformat_free_context(s);
 -        av_free(output_streams_for_file[i]);
 -        av_dict_free(&output_opts[i]);
 +        av_dict_free(&output_files[i].opts);
      }
      for(i=0;i<nb_input_files;i++) {
          av_close_input_file(input_files[i].ctx);
      }
--    for (i = 0; i < nb_input_streams; i++)
++    for (i = 0; i < nb_input_streams; i++) {
++        av_freep(&input_streams[i].decoded_frame);
++        av_freep(&input_streams[i].filtered_frame);
          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(streamid_map);
 -    av_free(stream_maps);
 -    av_free(meta_data_maps);
 -
      av_freep(&input_streams);
      av_freep(&input_files);
 -
 -    av_free(video_codec_name);
 -    av_free(audio_codec_name);
 -    av_free(subtitle_codec_name);
 -    av_free(data_codec_name);
 +    av_freep(&output_streams);
 +    av_freep(&output_files);
  
      uninit_opts();
      av_free(audio_buf);
      av_free(audio_out);
      allocated_audio_buf_size= allocated_audio_out_size= 0;
--    av_free(samples);
  
  #if CONFIG_AVFILTER
      avfilter_uninit();
  #endif
      avformat_network_deinit();
  
 +    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);
      }
  
@@@ -696,7 -509,7 +699,7 @@@ static void assert_avoptions(AVDictiona
  {
      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);
      }
  }
@@@ -707,12 -520,12 +710,12 @@@ static void assert_codec_experimental(A
      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);
      }
@@@ -727,9 -540,6 +730,9 @@@ static void choose_sample_fmt(AVStream 
                  break;
          }
          if (*p == -1) {
 +            if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
 +                av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
 +            if(av_get_sample_fmt_name(st->codec->sample_fmt))
              av_log(NULL, AV_LOG_WARNING,
                     "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
                     av_get_sample_fmt_name(st->codec->sample_fmt),
      }
  }
  
 -/**
 - * Update the requested input sample format based on the output sample format.
 - * This is currently only used to request float output from decoders which
 - * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT.
 - * Ideally this will be removed in the future when decoders do not do format
 - * conversion and only output in their native format.
 - */
 -static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec,
 -                              AVCodecContext *enc)
 -{
 -    /* if sample formats match or a decoder sample format has already been
 -       requested, just return */
 -    if (enc->sample_fmt == dec->sample_fmt ||
 -        dec->request_sample_fmt > AV_SAMPLE_FMT_NONE)
 -        return;
 -
 -    /* if decoder supports more than one output format */
 -    if (dec_codec && dec_codec->sample_fmts &&
 -        dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE &&
 -        dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) {
 -        const enum AVSampleFormat *p;
 -        int min_dec = -1, min_inc = -1;
 -
 -        /* find a matching sample format in the encoder */
 -        for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) {
 -            if (*p == enc->sample_fmt) {
 -                dec->request_sample_fmt = *p;
 -                return;
 -            } else if (*p > enc->sample_fmt) {
 -                min_inc = FFMIN(min_inc, *p - enc->sample_fmt);
 -            } else
 -                min_dec = FFMIN(min_dec, enc->sample_fmt - *p);
 -        }
 -
 -        /* if none match, provide the one that matches quality closest */
 -        dec->request_sample_fmt = min_inc > 0 ? enc->sample_fmt + min_inc :
 -                                  enc->sample_fmt - min_dec;
 -    }
 -}
 -
  static void choose_sample_rate(AVStream *st, AVCodec *codec)
  {
      if(codec && codec->supported_samplerates){
@@@ -764,8 -614,6 +767,8 @@@ static void choose_pixel_fmt(AVStream *
  {
      if(codec && codec->pix_fmts){
          const enum PixelFormat *p= codec->pix_fmts;
 +        int has_alpha= av_pix_fmt_descriptors[st->codec->pix_fmt].nb_components % 2 == 0;
 +        enum PixelFormat best= PIX_FMT_NONE;
          if(st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL){
              if(st->codec->codec_id==CODEC_ID_MJPEG){
                  p= (const enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE};
                  p= (const enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE};
              }
          }
 -        for(; *p!=-1; p++){
 +        for (; *p != PIX_FMT_NONE; p++) {
 +            best= avcodec_find_best_pix_fmt2(best, *p, st->codec->pix_fmt, has_alpha, NULL);
              if(*p == st->codec->pix_fmt)
                  break;
          }
 -        if (*p == -1) {
 +        if (*p == PIX_FMT_NONE) {
              if(st->codec->pix_fmt != PIX_FMT_NONE)
                  av_log(NULL, AV_LOG_WARNING,
                          "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
                          av_pix_fmt_descriptors[st->codec->pix_fmt].name,
                          codec->name,
 -                        av_pix_fmt_descriptors[codec->pix_fmts[0]].name);
 -            st->codec->pix_fmt = codec->pix_fmts[0];
 -        }
 -    }
 -}
 -
 -static OutputStream *new_output_stream(AVFormatContext *oc, int file_idx, AVCodec *codec)
 -{
 -    OutputStream *ost;
 -    AVStream *st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
 -    int idx      = oc->nb_streams - 1;
 -
 -    if (!st) {
 -        av_log(NULL, AV_LOG_ERROR, "Could not alloc stream.\n");
 -        exit_program(1);
 -    }
 -
 -    output_streams_for_file[file_idx] =
 -        grow_array(output_streams_for_file[file_idx],
 -                   sizeof(*output_streams_for_file[file_idx]),
 -                   &nb_output_streams_for_file[file_idx],
 -                   oc->nb_streams);
 -    ost = output_streams_for_file[file_idx][idx] =
 -        av_mallocz(sizeof(OutputStream));
 -    if (!ost) {
 -        fprintf(stderr, "Could not alloc output stream\n");
 -        exit_program(1);
 -    }
 -    ost->file_index = file_idx;
 -    ost->index = idx;
 -    ost->st    = st;
 -    ost->enc   = codec;
 -    if (codec)
 -        ost->opts  = filter_codec_opts(codec_opts, codec->id, oc, st);
 -
 -    avcodec_get_context_defaults3(st->codec, codec);
 -
 -    ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
 -    return ost;
 -}
 -
 -static int read_avserver_streams(AVFormatContext *s, const char *filename)
 -{
 -    int i, err;
 -    AVFormatContext *ic = NULL;
 -
 -    err = avformat_open_input(&ic, filename, NULL, NULL);
 -    if (err < 0)
 -        return err;
 -    /* copy stream format */
 -    for(i=0;i<ic->nb_streams;i++) {
 -        AVStream *st;
 -        OutputStream *ost;
 -        AVCodec *codec;
 -
 -        codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
 -        ost   = new_output_stream(s, nb_output_files, codec);
 -        st    = ost->st;
 -
 -        // FIXME: a more elegant solution is needed
 -        memcpy(st, ic->streams[i], sizeof(AVStream));
 -        st->info = NULL;
 -        avcodec_copy_context(st->codec, ic->streams[i]->codec);
 -
 -        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
 -            if (audio_stream_copy) {
 -                st->stream_copy = 1;
 -            } else
 -                choose_sample_fmt(st, codec);
 -        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 -            if (video_stream_copy) {
 -                st->stream_copy = 1;
 -            } else
 -                choose_pixel_fmt(st, codec);
 +                        av_pix_fmt_descriptors[best].name);
 +            st->codec->pix_fmt = best;
          }
      }
 -
 -    av_close_input_file(ic);
 -    return 0;
  }
  
 -static double
 -get_sync_ipts(const OutputStream *ost)
 +static double get_sync_ipts(const OutputStream *ost)
  {
      const InputStream *ist = ost->sync_ist;
 -    return (double)(ist->pts - start_time)/AV_TIME_BASE;
 +    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){
              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);
      }
  }
  
 -#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
 +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)
 +        fill_char = 0x80;
 +    memset(buf, fill_char, size);
 +}
  
--static void do_audio_out(AVFormatContext *s,
--                         OutputStream *ost,
--                         InputStream *ist,
--                         unsigned char *buf, int size)
++static void do_audio_out(AVFormatContext *s, OutputStream *ost,
++                         InputStream *ist, AVFrame *decoded_frame)
  {
      uint8_t *buftmp;
      int64_t audio_out_size, audio_buf_size;
--    int64_t allocated_for_size= size;
  
      int size_out, frame_bytes, ret, resample_changed;
      AVCodecContext *enc= ost->st->codec;
      int osize = av_get_bytes_per_sample(enc->sample_fmt);
      int isize = av_get_bytes_per_sample(dec->sample_fmt);
      const int coded_bps = av_get_bits_per_sample(enc->codec->id);
++    uint8_t *buf = decoded_frame->data[0];
++    int size     = decoded_frame->nb_samples * dec->channels * isize;
++    int64_t allocated_for_size = size;
  
  need_realloc:
      audio_buf_size= (allocated_for_size + isize*dec->channels - 1) / (isize*dec->channels);
      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 || enc->sample_rate != dec->sample_rate)
 +    if (enc->channels != dec->channels
 +     || enc->sample_fmt != dec->sample_fmt
 +     || enc->sample_rate!= dec->sample_rate
 +    )
          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 || ost->audio_channels_mapped) {
          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",
 +            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,
                     ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt), ost->resample_channels,
                     dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt), dec->channels);
              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 &&
 +        if (audio_sync_method <= 1 && !ost->audio_channels_mapped &&
              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 (ost->audio_resample) {
 -            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",
 +        } else {
 +            ost->swr = swr_alloc_set_opts(ost->swr,
 +                                          enc->channel_layout, enc->sample_fmt, enc->sample_rate,
 +                                          dec->channel_layout, dec->sample_fmt, dec->sample_rate,
 +                                          0, NULL);
 +            if (ost->audio_channels_mapped)
 +                swr_set_channel_mapping(ost->swr, ost->audio_channels_map);
 +            av_opt_set_double(ost->swr, "rmvol", ost->rematrix_volume, 0);
 +            if (ost->audio_channels_mapped) {
 +                av_opt_set_int(ost->swr, "icl", av_get_default_channel_layout(ost->audio_channels_mapped), 0);
 +                av_opt_set_int(ost->swr, "uch", ost->audio_channels_mapped, 0);
 +            }
 +            av_opt_set_int(ost->swr, "ich", dec->channels, 0);
 +            av_opt_set_int(ost->swr, "och", enc->channels, 0);
 +            if(audio_sync_method>1) av_opt_set_int(ost->swr, "flags", SWR_FLAG_RESAMPLE, 0);
 +            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);
          }
      }
  
 -#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
 -                - av_fifo_size(ost->fifo)/(enc->channels * 2);
 -        double idelta= delta*dec->sample_rate / enc->sample_rate;
 -        int byte_delta= ((int)idelta)*2*dec->channels;
 +                - av_fifo_size(ost->fifo)/(enc->channels * osize);
 +        int idelta = delta * dec->sample_rate / enc->sample_rate;
 +        int byte_delta = idelta * isize * dec->channels;
  
          //FIXME resample delay
          if(fabs(delta) > 50){
                      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",
 +                           -byte_delta / (isize * dec->channels));
                      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){
                      }
                      ist->is_start=0;
  
 -                    memset(input_tmp, 0, byte_delta);
 +                    generate_silence(input_tmp, dec->sample_fmt, byte_delta);
                      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", idelta);
                  }
              }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
          ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
 -                        - av_fifo_size(ost->fifo)/(enc->channels * 2); //FIXME wrong
 +                        - av_fifo_size(ost->fifo)/(enc->channels * osize); //FIXME wrong
  
      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);
              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;
              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);
          }
  
          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;
@@@ -1091,7 -1022,7 +1094,7 @@@ static void pre_process_video_frame(Inp
          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;
      *bufp = buf;
  }
  
 -/* we begin to correct av delay at this threshold */
 -#define AV_DELAY_MAX 0.100
 -
  static void do_subtitle_out(AVFormatContext *s,
                              OutputStream *ost,
                              InputStream *ist,
      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;
          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);
          }
  
  static int bit_buffer_size= 1024*256;
  static uint8_t *bit_buffer= NULL;
  
 +static void do_video_resample(OutputStream *ost,
 +                              InputStream *ist,
 +                              AVFrame *in_picture,
 +                              AVFrame **out_picture)
 +{
 +#if CONFIG_AVFILTER
 +    *out_picture = in_picture;
 +#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",
 +               ist->file_index, ist->st->index,
 +               ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
 +               dec->width         , dec->height         , av_get_pix_fmt_name(dec->pix_fmt));
 +        ost->resample_width   = dec->width;
 +        ost->resample_height  = dec->height;
 +        ost->resample_pix_fmt = dec->pix_fmt;
 +    }
 +
 +    ost->video_resample = dec->width   != enc->width  ||
 +                          dec->height  != enc->height ||
 +                          dec->pix_fmt != enc->pix_fmt;
 +
 +    if (ost->video_resample) {
 +        *out_picture = &ost->resample_frame;
 +        if (!ost->img_resample_ctx || resample_changed) {
 +            /* initialize the destination picture */
 +            if (!ost->resample_frame.data[0]) {
 +                avcodec_get_frame_defaults(&ost->resample_frame);
 +                if (avpicture_alloc((AVPicture *)&ost->resample_frame, enc->pix_fmt,
 +                                    enc->width, enc->height)) {
 +                    av_log(NULL, AV_LOG_FATAL, "Cannot allocate temp picture, check pix fmt\n");
 +                    exit_program(1);
 +                }
 +            }
 +            /* initialize a new scaler context */
 +            sws_freeContext(ost->img_resample_ctx);
 +            ost->img_resample_ctx = sws_getContext(dec->width, dec->height, dec->pix_fmt,
 +                                                   enc->width, enc->height, enc->pix_fmt,
 +                                                   ost->sws_flags, NULL, NULL, NULL);
 +            if (ost->img_resample_ctx == NULL) {
 +                av_log(NULL, AV_LOG_FATAL, "Cannot get resampling context\n");
 +                exit_program(1);
 +            }
 +        }
 +        sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize,
 +              0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize);
 +    }
 +#endif
 +}
 +
 +
  static void do_video_out(AVFormatContext *s,
                           OutputStream *ost,
                           InputStream *ist,
                           AVFrame *in_picture,
                           int *frame_size, float quality)
  {
 -    int nb_frames, i, ret, resample_changed;
 -    AVFrame *final_picture, *formatted_picture;
 -    AVCodecContext *enc, *dec;
 +    int nb_frames, i, ret, format_video_sync;
 +    AVFrame *final_picture;
 +    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);
  
  
      *frame_size = 0;
  
 -    if(video_sync_method){
 -        double vdelta = sync_ipts - ost->sync_opts;
 +    format_video_sync = video_sync_method;
 +    if (format_video_sync < 0)
 +        format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? 0 : 2) : 1;
 +
 +    if (format_video_sync) {
 +        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;
 -        else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){
 +        else if (format_video_sync == 2) {
              if(vdelta<=-0.6){
                  nb_frames=0;
              }else if(vdelta>0.6)
  //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;
  
 -    formatted_picture = in_picture;
 -    final_picture = formatted_picture;
 -
 -    resample_changed = ost->resample_width   != dec->width  ||
 -                       ost->resample_height  != dec->height ||
 -                       ost->resample_pix_fmt != dec->pix_fmt;
 -
 -    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",
 -               ist->file_index, ist->st->index,
 -               ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt),
 -               dec->width         , dec->height         , av_get_pix_fmt_name(dec->pix_fmt));
 -        if(!ost->video_resample)
 -            exit_program(1);
 -    }
 -
 -#if !CONFIG_AVFILTER
 -    if (ost->video_resample) {
 -        final_picture = &ost->pict_tmp;
 -        if (resample_changed) {
 -            /* initialize a new scaler context */
 -            sws_freeContext(ost->img_resample_ctx);
 -            ost->img_resample_ctx = sws_getContext(
 -                ist->st->codec->width,
 -                ist->st->codec->height,
 -                ist->st->codec->pix_fmt,
 -                ost->st->codec->width,
 -                ost->st->codec->height,
 -                ost->st->codec->pix_fmt,
 -                ost->sws_flags, NULL, NULL, NULL);
 -            if (ost->img_resample_ctx == NULL) {
 -                fprintf(stderr, "Cannot get resampling context\n");
 -                exit_program(1);
 -            }
 -        }
 -        sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize,
 -              0, ost->resample_height, final_picture->data, final_picture->linesize);
 -    }
 -#endif
 +    do_video_resample(ost, ist, in_picture, &final_picture);
  
      /* duplicates frame if needed */
      for(i=0;i<nb_frames;i++) {
          av_init_packet(&pkt);
          pkt.stream_index= ost->index;
  
 -        if (s->oformat->flags & AVFMT_RAWPICTURE) {
 +        if (s->oformat->flags & AVFMT_RAWPICTURE &&
 +            enc->codec->id == CODEC_ID_RAWVIDEO) {
              /* raw pictures are written as AVPicture structure to
 -               avoid any copies. We support temorarily the older
 +               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;
  
                 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 sameq here. This is not correct because it may
 +            /* 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;
                                         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);
              }
  
      }
  }
  
 -static double psnr(double d){
 +static double psnr(double d)
 +{
      return -10.0*log(d)/log(10.0);
  }
  
@@@ -1416,9 -1319,9 +1419,9 @@@ static void do_video_stats(AVFormatCont
      }
  }
  
 -static void print_report(AVFormatContext **output_files,
 -                         OutputStream **ost_table, int nb_ostreams,
 -                         int is_last_report)
 +static void print_report(OutputFile *output_files,
 +                         OutputStream *ost_table, int nb_ostreams,
 +                         int is_last_report, int64_t timer_start, int64_t cur_time)
  {
      char buf[1024];
      OutputStream *ost;
      int64_t total_size;
      AVCodecContext *enc;
      int frame_number, vid, i;
 -    double bitrate, ti1, pts;
 +    double bitrate;
 +    int64_t pts = INT64_MAX;
      static int64_t last_time = -1;
      static int qp_histogram[52];
 +    int hours, mins, secs, us;
 +
 +    if (!print_stats && !is_last_report)
 +        return;
  
      if (!is_last_report) {
 -        int64_t cur_time;
 -        /* display the report every 0.5 seconds */
 -        cur_time = av_gettime();
          if (last_time == -1) {
              last_time = cur_time;
              return;
      }
  
  
 -    oc = output_files[0];
 +    oc = output_files[0].ctx;
  
      total_size = avio_size(oc->pb);
 -    if(total_size<0) // FIXME improve avio_size() so it works with non seekable output too
 +    if (total_size < 0) { // FIXME improve avio_size() so it works with non seekable output too
          total_size= avio_tell(oc->pb);
 +        if (total_size < 0)
 +            total_size = 0;
 +    }
  
      buf[0] = '\0';
 -    ti1 = 1e10;
      vid = 0;
      for(i=0;i<nb_ostreams;i++) {
          float q = -1;
 -        ost = ost_table[i];
 +        ost = &ost_table[i];
          enc = ost->st->codec;
 -        if (!ost->st->stream_copy && enc->coded_frame)
 +        if (!ost->stream_copy && enc->coded_frame)
              q = enc->coded_frame->quality/(float)FF_QP2LAMBDA;
          if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
              snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
          }
          if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
 -            float t = (av_gettime()-timer_start) / 1000000.0;
 +            float t = (cur_time-timer_start) / 1000000.0;
  
              frame_number = ost->frame_number;
              snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
              vid = 1;
          }
          /* compute min output value */
 -        pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
 -        if ((pts < ti1) && (pts > 0))
 -            ti1 = pts;
 +        pts = FFMIN(pts, av_rescale_q(ost->st->pts.val,
 +                                      ost->st->time_base, AV_TIME_BASE_Q));
      }
 -    if (ti1 < 0.01)
 -        ti1 = 0.01;
  
 -    if (verbose > 0 || is_last_report) {
 -        bitrate = (double)(total_size * 8) / ti1 / 1000.0;
 +    secs = pts / AV_TIME_BASE;
 +    us = pts % AV_TIME_BASE;
 +    mins = secs / 60;
 +    secs %= 60;
 +    hours = mins / 60;
 +    mins %= 60;
  
 -        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
 -            "size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
 -            (double)total_size / 1024, ti1, bitrate);
 +    bitrate = pts ? total_size * 8 / (pts / 1000.0) : 0;
  
 -        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);
 +    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 (verbose >= 0)
 -            fprintf(stderr, "%s    \r", buf);
 +    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);
  
 -        fflush(stderr);
 -    }
 +    av_log(NULL, 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
          );
 +        if(video_size + audio_size + extra_size == 0){
 +            av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)\n");
 +        }
      }
  }
  
 -static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size)
 +static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
  {
 -    int fill_char = 0x00;
 -    if (sample_fmt == AV_SAMPLE_FMT_U8)
 -        fill_char = 0x80;
 -    memset(buf, fill_char, size);
 -}
 +    int i, ret;
  
 -/* pkt = NULL means EOF (needed to flush decoder buffers) */
 -static int output_packet(InputStream *ist, int ist_index,
 -                         OutputStream **ost_table, int nb_ostreams,
 -                         const AVPacket *pkt)
 -{
 -    AVFormatContext *os;
 -    OutputStream *ost;
 -    int ret, i;
 -    int got_output;
 -    AVFrame picture;
 -    void *buffer_to_free = NULL;
 -    static unsigned int samples_size= 0;
 -    AVSubtitle subtitle, *subtitle_to_free;
 -    int64_t pkt_pts = AV_NOPTS_VALUE;
 -#if CONFIG_AVFILTER
 -    int frame_available;
 -#endif
 -    float quality;
 -
 -    AVPacket avpkt;
 -    int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
 -
 -    if(ist->next_pts == AV_NOPTS_VALUE)
 -        ist->next_pts= ist->pts;
 +    for (i = 0; i < nb_ostreams; i++) {
 +        OutputStream   *ost = &ost_table[i];
 +        AVCodecContext *enc = ost->st->codec;
 +        AVFormatContext *os = output_files[ost->file_index].ctx;
  
 -    if (pkt == NULL) {
 -        /* EOF handling */
 -        av_init_packet(&avpkt);
 -        avpkt.data = NULL;
 -        avpkt.size = 0;
 -        goto handle_eof;
 -    } else {
 -        avpkt = *pkt;
 -    }
 +        if (!ost->encoding_needed)
 +            continue;
  
 -    if(pkt->dts != AV_NOPTS_VALUE)
 -        ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 -    if(pkt->pts != AV_NOPTS_VALUE)
 -        pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
 +        if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1)
 +            continue;
 +        if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == CODEC_ID_RAWVIDEO)
 +            continue;
  
 -    //while we have more to decode or while the decoder did output something on EOF
 -    while (avpkt.size > 0 || (!pkt && got_output)) {
 -        uint8_t *data_buf, *decoded_data_buf;
 -        int data_size, decoded_data_size;
 -    handle_eof:
 -        ist->pts= ist->next_pts;
 +        for(;;) {
 +            AVPacket pkt;
 +            int fifo_bytes;
 +            av_init_packet(&pkt);
 +            pkt.stream_index= ost->index;
  
 -        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);
 -            ist->showed_multi_packet_warning=1;
 -        }
 +            switch (ost->st->codec->codec_type) {
 +            case AVMEDIA_TYPE_AUDIO:
 +                fifo_bytes = av_fifo_size(ost->fifo);
 +                ret = 0;
 +                /* encode any samples remaining in fifo */
 +                if (fifo_bytes > 0) {
 +                    int osize = av_get_bytes_per_sample(enc->sample_fmt);
 +                    int fs_tmp = enc->frame_size;
 +
 +                    av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
 +                    if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
 +                        enc->frame_size = fifo_bytes / (osize * enc->channels);
 +                    } else { /* pad */
 +                        int frame_bytes = enc->frame_size*osize*enc->channels;
 +                        if (allocated_audio_buf_size < frame_bytes)
 +                            exit_program(1);
 +                        generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
 +                    }
  
 -        /* decode the packet if needed */
 -        decoded_data_buf = NULL; /* fail safe */
 -        decoded_data_size= 0;
 -        data_buf  = avpkt.data;
 -        data_size = avpkt.size;
 -        subtitle_to_free = NULL;
 -        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);
 -                    av_free(samples);
 -                    samples= av_malloc(samples_size);
 +                    ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf);
 +                    pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den,
 +                                              ost->st->time_base.num, enc->sample_rate);
 +                    enc->frame_size = fs_tmp;
                  }
 -                decoded_data_size= samples_size;
 -                    /* XXX: could avoid copy if PCM 16 bits with same
 -                       endianness as CPU */
 -                ret = avcodec_decode_audio3(ist->st->codec, samples, &decoded_data_size,
 -                                            &avpkt);
 -                if (ret < 0)
 -                    return ret;
 -                avpkt.data += ret;
 -                avpkt.size -= ret;
 -                data_size   = ret;
 -                got_output  = decoded_data_size > 0;
 -                /* Some bug in mpeg audio decoder gives */
 -                /* decoded_data_size < 0, it seems they are overflows */
 -                if (!got_output) {
 -                    /* no audio frame */
 -                    continue;
 +                if (ret <= 0) {
 +                    ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
                  }
 -                decoded_data_buf = (uint8_t *)samples;
 -                ist->next_pts += ((int64_t)AV_TIME_BASE/bps * decoded_data_size) /
 -                    (ist->st->codec->sample_rate * ist->st->codec->channels);
 -                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);
 -                    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_quality ? picture.quality : 0;
 -                    if (ret < 0)
 -                        return ret;
 -                    if (!got_output) {
 -                        /* no picture yet */
 -                        goto discard_packet;
 -                    }
 -                    ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts);
 -                    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 *
 -                                          ist->st->codec->time_base.num * ticks) /
 -                            ist->st->codec->time_base.den;
 -                    }
 -                    avpkt.size = 0;
 -                    buffer_to_free = NULL;
 -                    pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free);
 -                    break;
 -            case AVMEDIA_TYPE_SUBTITLE:
 -                ret = avcodec_decode_subtitle2(ist->st->codec,
 -                                               &subtitle, &got_output, &avpkt);
 -                if (ret < 0)
 -                    return ret;
 -                if (!got_output) {
 -                    goto discard_packet;
 +                if (ret < 0) {
 +                    av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
 +                    exit_program(1);
                  }
 -                subtitle_to_free = &subtitle;
 -                avpkt.size = 0;
 -                break;
 -            default:
 -                return -1;
 -            }
 -        } else {
 -            switch(ist->st->codec->codec_type) {
 -            case AVMEDIA_TYPE_AUDIO:
 -                ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
 -                    ist->st->codec->sample_rate;
 +                audio_size += ret;
 +                pkt.flags |= AV_PKT_FLAG_KEY;
                  break;
              case AVMEDIA_TYPE_VIDEO:
 -                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 *
 -                                      ist->st->codec->time_base.num * ticks) /
 -                        ist->st->codec->time_base.den;
 +                ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
 +                if (ret < 0) {
 +                    av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
 +                    exit_program(1);
 +                }
 +                video_size += ret;
 +                if(enc->coded_frame && enc->coded_frame->key_frame)
 +                    pkt.flags |= AV_PKT_FLAG_KEY;
 +                if (ost->logfile && enc->stats_out) {
 +                    fprintf(ost->logfile, "%s", enc->stats_out);
                  }
                  break;
 +            default:
 +                ret=-1;
              }
 -            ret = avpkt.size;
 -            avpkt.size = 0;
 +
 +            if (ret <= 0)
 +                break;
 +            pkt.data = bit_buffer;
 +            pkt.size = ret;
 +            if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
 +                pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
 +            write_frame(os, &pkt, ost->st->codec, ost->bitstream_filters);
          }
 +    }
 +}
  
 -#if CONFIG_AVFILTER
 -        if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 -            for (i = 0; i < nb_ostreams; i++) {
 -                ost = ost_table[i];
 -                if (ost->input_video_filter && ost->source_index == ist_index) {
 -                    AVRational sar;
 -                    if (ist->st->sample_aspect_ratio.num)
 -                        sar = ist->st->sample_aspect_ratio;
 -                    else
 -                        sar = ist->st->codec->sample_aspect_ratio;
 -                    // add it to be filtered
 -                    av_vsrc_buffer_add_frame(ost->input_video_filter, &picture,
 -                                             ist->pts,
 -                                             sar);
 -                }
 +/*
 + * Check whether a packet from ist should be written into ost at this time
 + */
 +static int check_output_constraints(InputStream *ist, OutputStream *ost)
 +{
 +    OutputFile *of = &output_files[ost->file_index];
 +    int ist_index  = ist - input_streams;
 +
 +    if (ost->source_index != ist_index)
 +        return 0;
 +
 +    if (of->start_time && ist->pts < of->start_time)
 +        return 0;
 +
 +    if (of->recording_time != INT64_MAX &&
 +        av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
 +                      (AVRational){1, 1000000}) >= 0) {
 +        ost->is_past_recording_time = 1;
 +        return 0;
 +    }
 +
 +    return 1;
 +}
 +
 +static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
 +{
 +    OutputFile *of = &output_files[ost->file_index];
 +    int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
 +    AVPicture pict;
 +    AVPacket opkt;
 +
 +    av_init_packet(&opkt);
 +
 +    if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
 +        !ost->copy_initial_nonkeyframes)
 +        return;
 +
 +    /* force the input stream PTS */
 +    if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 +        audio_size += pkt->size;
 +    else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 +        video_size += pkt->size;
 +        ost->sync_opts++;
 +    }
 +
 +    opkt.stream_index = ost->index;
 +    if (pkt->pts != AV_NOPTS_VALUE)
 +        opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
 +    else
 +        opkt.pts = AV_NOPTS_VALUE;
 +
 +    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.dts -= ost_tb_start_time;
 +
 +    opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
 +    opkt.flags    = pkt->flags;
 +
 +    //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
 +    if(   ost->st->codec->codec_id != CODEC_ID_H264
 +       && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
 +       && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
 +       ) {
 +        if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY))
 +            opkt.destruct = av_destruct_packet;
 +    } else {
 +        opkt.data = pkt->data;
 +        opkt.size = pkt->size;
 +    }
 +    if (of->ctx->oformat->flags & AVFMT_RAWPICTURE) {
 +        /* store AVPicture in AVPacket, as expected by the output format */
 +        avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
 +        opkt.data = (uint8_t *)&pict;
 +        opkt.size = sizeof(AVPicture);
 +        opkt.flags |= AV_PKT_FLAG_KEY;
 +    }
 +
 +    write_frame(of->ctx, &opkt, ost->st->codec, ost->bitstream_filters);
 +    ost->st->codec->frame_number++;
 +    ost->frame_number++;
 +    av_free_packet(&opkt);
 +}
 +
 +static void rate_emu_sleep(InputStream *ist)
 +{
 +    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)
 +            usleep(pts - now);
 +    }
 +}
 +
 +static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
 +{
-     static unsigned int samples_size = 0;
++    AVFrame *decoded_frame;
++    AVCodecContext *avctx = ist->st->codec;
 +    int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
-     uint8_t *decoded_data_buf  = NULL;
-     int      decoded_data_size = 0;
 +    int i, ret;
 +
-     if (pkt && samples_size < FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE)) {
-         av_free(samples);
-         samples_size = FFMAX(pkt->size * bps, AVCODEC_MAX_AUDIO_FRAME_SIZE);
-         samples      = av_malloc(samples_size);
-     }
-     decoded_data_size = samples_size;
++    if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
++        return AVERROR(ENOMEM);
++    else
++        avcodec_get_frame_defaults(ist->decoded_frame);
++    decoded_frame = ist->decoded_frame;
 +
-     ret = avcodec_decode_audio3(ist->st->codec, samples, &decoded_data_size,
-                                 pkt);
-     if (ret < 0)
++    ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
++    if (ret < 0) {
 +        return ret;
-     *got_output  = decoded_data_size > 0;
++    }
 +
-     /* Some bug in mpeg audio decoder gives */
-     /* decoded_data_size < 0, it seems they are overflows */
 +    if (!*got_output) {
 +        /* no audio frame */
 +        return ret;
 +    }
 +
-     decoded_data_buf = (uint8_t *)samples;
-     ist->next_pts   += ((int64_t)AV_TIME_BASE/bps * decoded_data_size) /
-                        (ist->st->codec->sample_rate * ist->st->codec->channels);
++    /* if the decoder provides a pts, use it instead of the last packet pts.
++       the decoder could be delaying output by a packet or more. */
++    if (decoded_frame->pts != AV_NOPTS_VALUE)
++        ist->next_pts = decoded_frame->pts;
++
++    /* increment next_pts to use for the case where the input stream does not
++       have timestamps or there are multiple frames in the packet */
++    ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
++                     avctx->sample_rate;
 +
 +    // preprocess audio (volume)
 +    if (audio_volume != 256) {
-         switch (ist->st->codec->sample_fmt) {
++        int decoded_data_size = decoded_frame->nb_samples * avctx->channels * bps;
++        void *samples = decoded_frame->data[0];
++        switch (avctx->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;
          }
 -#endif
 -
 -        // 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;
 -                }
 +        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;
          }
 -
 -        /* frame rate emulation */
 -        if (rate_emu) {
 -            int64_t pts = av_rescale(ist->pts, 1000000, AV_TIME_BASE);
 -            int64_t now = av_gettime() - ist->start;
 -            if (pts > now)
 -                usleep(pts - now);
 +        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;
          }
 -        /* if output time reached then transcode raw format,
 -           encode packets and output them */
 -        if (start_time == 0 || ist->pts >= start_time)
 -            for(i=0;i<nb_ostreams;i++) {
 -                int frame_size;
 -
 -                ost = ost_table[i];
 -                if (ost->source_index == ist_index) {
 -#if CONFIG_AVFILTER
 -                frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
 -                    !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]);
 -                while (frame_available) {
 -                    AVRational ist_pts_tb;
 -                    if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter)
 -                        get_filtered_video_frame(ost->output_video_filter, &picture, &ost->picref, &ist_pts_tb);
 -                    if (ost->picref)
 -                        ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
 -#endif
 -                    os = output_files[ost->file_index];
 -
 -                    /* set the input output pts pairs */
 -                    //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE;
 -
 -                    if (ost->encoding_needed) {
 -                        av_assert0(ist->decoding_needed);
 -                        switch(ost->st->codec->codec_type) {
 -                        case AVMEDIA_TYPE_AUDIO:
 -                            do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size);
 -                            break;
 -                        case AVMEDIA_TYPE_VIDEO:
 +        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);
 +        }
 +    }
 +
 +    rate_emu_sleep(ist);
 +
 +    for (i = 0; i < nb_output_streams; i++) {
 +        OutputStream *ost = &output_streams[i];
 +
 +        if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
 +            continue;
-         do_audio_out(output_files[ost->file_index].ctx, ost, ist,
-                      decoded_data_buf, decoded_data_size);
++        do_audio_out(output_files[ost->file_index].ctx, ost, ist, decoded_frame);
 +    }
++
 +    return ret;
 +}
 +
 +static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *pkt_pts, int64_t *pkt_dts)
 +{
 +    AVFrame *decoded_frame, *filtered_frame = NULL;
 +    void *buffer_to_free = NULL;
 +    int i, ret = 0;
 +    float quality = 0;
  #if CONFIG_AVFILTER
 -                            if (ost->picref->video && !ost->frame_aspect_ratio)
 -                                ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect;
 +    int frame_available = 1;
  #endif
 -                            do_video_out(os, ost, ist, &picture, &frame_size,
 -                                         same_quality ? quality : ost->st->codec->global_quality);
 -                            if (vstats_filename && frame_size)
 -                                do_video_stats(os, ost, frame_size);
 -                            break;
 -                        case AVMEDIA_TYPE_SUBTITLE:
 -                            do_subtitle_out(os, ost, ist, &subtitle,
 -                                            pkt->pts);
 -                            break;
 -                        default:
 -                            abort();
 -                        }
 -                    } else {
 -                        AVFrame avframe; //FIXME/XXX remove this
 -                        AVPacket opkt;
 -                        int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base);
 +    int duration=0;
 +    int64_t *best_effort_timestamp;
 +    AVRational *frame_sample_aspect;
  
-     if (!(decoded_frame = avcodec_alloc_frame()))
 -                        av_init_packet(&opkt);
++    if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
 +        return AVERROR(ENOMEM);
++    else
++        avcodec_get_frame_defaults(ist->decoded_frame);
++    decoded_frame = ist->decoded_frame;
 +    pkt->pts  = *pkt_pts;
 +    pkt->dts  = *pkt_dts;
 +    *pkt_pts  = AV_NOPTS_VALUE;
 +
 +    if (pkt->duration) {
 +        duration = av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
 +    } else 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;
 +        duration = ((int64_t)AV_TIME_BASE *
 +                          ist->st->codec->time_base.num * ticks) /
 +                          ist->st->codec->time_base.den;
 +    }
  
 -                        if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes)
 -#if !CONFIG_AVFILTER
 -                            continue;
 -#else
 -                            goto cont;
 -#endif
 +    if(*pkt_dts != AV_NOPTS_VALUE && duration) {
 +        *pkt_dts += duration;
 +    }else
 +        *pkt_dts = AV_NOPTS_VALUE;
 +
 +    ret = avcodec_decode_video2(ist->st->codec,
 +                                decoded_frame, got_output, pkt);
 +    if (ret < 0)
-         goto fail;
++        return ret;
  
 -                        /* no reencoding needed : output the packet directly */
 -                        /* force the input stream PTS */
 +    quality = same_quant ? decoded_frame->quality : 0;
 +    if (!*got_output) {
 +        /* no picture yet */
-         av_freep(&decoded_frame);
 +        return ret;
 +    }
  
 -                        avcodec_get_frame_defaults(&avframe);
 -                        ost->st->codec->coded_frame= &avframe;
 -                        avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY;
 +    best_effort_timestamp= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "best_effort_timestamp");
 +    if(*best_effort_timestamp != AV_NOPTS_VALUE)
 +        ist->next_pts = ist->pts = *best_effort_timestamp;
  
 -                        if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 -                            audio_size += data_size;
 -                        else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 -                            video_size += data_size;
 -                            ost->sync_opts++;
 -                        }
 +    ist->next_pts += duration;
 +    pkt->size = 0;
  
 -                        opkt.stream_index= ost->index;
 -                        if(pkt->pts != AV_NOPTS_VALUE)
 -                            opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
 -                        else
 -                            opkt.pts= AV_NOPTS_VALUE;
 -
 -                        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.dts -= ost_tb_start_time;
 -
 -                        opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
 -                        opkt.flags= pkt->flags;
 -
 -                        //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
 -                        if(   ost->st->codec->codec_id != CODEC_ID_H264
 -                           && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
 -                           && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
 -                           ) {
 -                            if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY))
 -                                opkt.destruct= av_destruct_packet;
 -                        } else {
 -                            opkt.data = data_buf;
 -                            opkt.size = data_size;
 -                        }
 +    pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
  
 -                        write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
 -                        ost->st->codec->frame_number++;
 -                        ost->frame_number++;
 -                        av_free_packet(&opkt);
 -                    }
  #if CONFIG_AVFILTER
 -                    cont:
 -                    frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
 -                                       ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
 -                    if (ost->picref)
 -                        avfilter_unref_buffer(ost->picref);
 -                }
 -#endif
 -                }
 -            }
 -
 -        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;
 +    frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
 +    for(i=0;i<nb_output_streams;i++) {
 +        OutputStream *ost = ost = &output_streams[i];
 +        if(check_output_constraints(ist, ost)){
 +            if (!frame_sample_aspect->num)
 +                *frame_sample_aspect = ist->st->sample_aspect_ratio;
 +            decoded_frame->pts = ist->pts;
 +
 +            av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE);
          }
      }
 - discard_packet:
 -    if (pkt == NULL) {
 -        /* EOF handling */
 +#endif
  
 -        for(i=0;i<nb_ostreams;i++) {
 -            ost = ost_table[i];
 -            if (ost->source_index == ist_index) {
 -                AVCodecContext *enc= ost->st->codec;
 -                os = output_files[ost->file_index];
 -
 -                if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1)
 -                    continue;
 -                if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE))
 -                    continue;
 -
 -                if (ost->encoding_needed) {
 -                    for(;;) {
 -                        AVPacket pkt;
 -                        int fifo_bytes;
 -                        av_init_packet(&pkt);
 -                        pkt.stream_index= ost->index;
 -
 -                        switch(ost->st->codec->codec_type) {
 -                        case AVMEDIA_TYPE_AUDIO:
 -                            fifo_bytes = av_fifo_size(ost->fifo);
 -                            ret = 0;
 -                            /* encode any samples remaining in fifo */
 -                            if (fifo_bytes > 0) {
 -                                int osize = av_get_bytes_per_sample(enc->sample_fmt);
 -                                int fs_tmp = enc->frame_size;
 -
 -                                av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL);
 -                                if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
 -                                    enc->frame_size = fifo_bytes / (osize * enc->channels);
 -                                } else { /* pad */
 -                                    int frame_bytes = enc->frame_size*osize*enc->channels;
 -                                    if (allocated_audio_buf_size < frame_bytes)
 -                                        exit_program(1);
 -                                    generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes);
 -                                }
 -
 -                                ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf);
 -                                pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den,
 -                                                          ost->st->time_base.num, enc->sample_rate);
 -                                enc->frame_size = fs_tmp;
 -                            }
 -                            if(ret <= 0) {
 -                                ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
 -                            }
 -                            if (ret < 0) {
 -                                fprintf(stderr, "Audio encoding failed\n");
 -                                exit_program(1);
 -                            }
 -                            audio_size += ret;
 -                            pkt.flags |= AV_PKT_FLAG_KEY;
 -                            break;
 -                        case AVMEDIA_TYPE_VIDEO:
 -                            ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
 -                            if (ret < 0) {
 -                                fprintf(stderr, "Video encoding failed\n");
 -                                exit_program(1);
 -                            }
 -                            video_size += ret;
 -                            if(enc->coded_frame && enc->coded_frame->key_frame)
 -                                pkt.flags |= AV_PKT_FLAG_KEY;
 -                            if (ost->logfile && enc->stats_out) {
 -                                fprintf(ost->logfile, "%s", enc->stats_out);
 -                            }
 -                            break;
 -                        default:
 -                            ret=-1;
 -                        }
 +    rate_emu_sleep(ist);
  
 -                        if(ret<=0)
 -                            break;
 -                        pkt.data= bit_buffer;
 -                        pkt.size= ret;
 -                        if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
 -                            pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
 -                        write_frame(os, &pkt, ost->st->codec, ost->bitstream_filters);
 -                    }
 +    for (i = 0; i < nb_output_streams; i++) {
 +        OutputStream *ost = &output_streams[i];
 +        int frame_size;
 +
 +        if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
 +            continue;
 +
 +#if CONFIG_AVFILTER
 +        if (ost->input_video_filter) {
 +            frame_available = avfilter_poll_frame(ost->output_video_filter->inputs[0]);
 +        }
 +        while (frame_available) {
 +            if (ost->output_video_filter) {
 +                AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
 +                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;
-                 }
++                if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
++                    av_free(buffer_to_free);
++                    return AVERROR(ENOMEM);
++                } else
++                    avcodec_get_frame_defaults(ist->filtered_frame);
++                filtered_frame = ist->filtered_frame;
 +                *filtered_frame= *decoded_frame; //for me_threshold
 +                if (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);
                  }
              }
 +            if (ost->picref->video && !ost->frame_aspect_ratio)
 +                ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
 +#else
 +            filtered_frame = decoded_frame;
 +#endif
 +
 +            do_video_out(output_files[ost->file_index].ctx, ost, ist, filtered_frame, &frame_size,
 +                         same_quant ? quality : ost->st->codec->global_quality);
 +            if (vstats_filename && frame_size)
 +                do_video_stats(output_files[ost->file_index].ctx, ost, frame_size);
 +#if CONFIG_AVFILTER
 +            cont:
 +            frame_available = ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
 +            avfilter_unref_buffer(ost->picref);
          }
-         av_freep(&filtered_frame);
 +#endif
      }
  
- fail:
 -    return 0;
 +    av_free(buffer_to_free);
-     av_freep(&decoded_frame);
 +    return ret;
  }
  
 -static void print_sdp(AVFormatContext **avc, int n)
 +static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
  {
 -    char sdp[2048];
 +    AVSubtitle subtitle;
 +    int i, ret = avcodec_decode_subtitle2(ist->st->codec,
 +                                          &subtitle, got_output, pkt);
 +    if (ret < 0)
 +        return ret;
 +    if (!*got_output)
 +        return ret;
  
 -    av_sdp_create(avc, n, sdp, sizeof(sdp));
 -    printf("SDP:\n%s\n", sdp);
 -    fflush(stdout);
 +    rate_emu_sleep(ist);
 +
 +    for (i = 0; i < nb_output_streams; i++) {
 +        OutputStream *ost = &output_streams[i];
 +
 +        if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
 +            continue;
 +
 +        do_subtitle_out(output_files[ost->file_index].ctx, ost, ist, &subtitle, pkt->pts);
 +    }
 +
 +    avsubtitle_free(&subtitle);
 +    return ret;
  }
  
 -static int copy_chapters(int infile, int outfile)
 +/* pkt = NULL means EOF (needed to flush decoder buffers) */
 +static int output_packet(InputStream *ist,
 +                         OutputStream *ost_table, int nb_ostreams,
 +                         const AVPacket *pkt)
  {
 -    AVFormatContext *is = input_files[infile].ctx;
 -    AVFormatContext *os = output_files[outfile];
 -    int i;
 +    int ret = 0, i;
 +    int got_output;
 +    int64_t pkt_dts = AV_NOPTS_VALUE;
 +    int64_t pkt_pts = AV_NOPTS_VALUE;
  
 -    for (i = 0; i < is->nb_chapters; i++) {
 -        AVChapter *in_ch = is->chapters[i], *out_ch;
 -        int64_t ts_off   = av_rescale_q(start_time - input_files[infile].ts_offset,
 -                                      AV_TIME_BASE_Q, in_ch->time_base);
 -        int64_t rt       = (recording_time == INT64_MAX) ? INT64_MAX :
 -                           av_rescale_q(recording_time, AV_TIME_BASE_Q, in_ch->time_base);
 +    AVPacket avpkt;
  
 +    if (ist->next_pts == AV_NOPTS_VALUE)
 +        ist->next_pts = ist->pts;
  
 -        if (in_ch->end < ts_off)
 -            continue;
 -        if (rt != INT64_MAX && in_ch->start > rt + ts_off)
 +    if (pkt == NULL) {
 +        /* EOF handling */
 +        av_init_packet(&avpkt);
 +        avpkt.data = NULL;
 +        avpkt.size = 0;
 +        goto handle_eof;
 +    } else {
 +        avpkt = *pkt;
 +    }
 +
 +    if(pkt->dts != AV_NOPTS_VALUE){
 +        if(ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)
 +            ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 +        pkt_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 +    }
 +    if(pkt->pts != AV_NOPTS_VALUE)
 +        pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
 +
 +    //while we have more to decode or while the decoder did output something on EOF
 +    while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
 +    handle_eof:
 +
 +        ist->pts = ist->next_pts;
 +
 +        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;
 +        }
 +
 +        switch(ist->st->codec->codec_type) {
 +        case AVMEDIA_TYPE_AUDIO:
 +            ret = transcode_audio    (ist, &avpkt, &got_output);
 +            break;
 +        case AVMEDIA_TYPE_VIDEO:
 +            ret = transcode_video    (ist, &avpkt, &got_output, &pkt_pts, &pkt_dts);
              break;
 +        case AVMEDIA_TYPE_SUBTITLE:
 +            ret = transcode_subtitles(ist, &avpkt, &got_output);
 +            break;
 +        default:
 +            return -1;
 +        }
  
 -        out_ch = av_mallocz(sizeof(AVChapter));
 -        if (!out_ch)
 -            return AVERROR(ENOMEM);
 +        if (ret < 0)
 +            return ret;
 +        // touch data and size only if not EOF
 +        if (pkt) {
 +            if(ist->st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
 +                ret = avpkt.size;
 +            avpkt.data += ret;
 +            avpkt.size -= ret;
 +        }
 +        if (!got_output) {
 +            continue;
 +        }
 +    }
  
 -        out_ch->id        = in_ch->id;
 -        out_ch->time_base = in_ch->time_base;
 -        out_ch->start     = FFMAX(0,  in_ch->start - ts_off);
 -        out_ch->end       = FFMIN(rt, in_ch->end   - ts_off);
 +    /* handle stream copy */
 +    if (!ist->decoding_needed) {
 +        rate_emu_sleep(ist);
 +        ist->pts = ist->next_pts;
 +        switch (ist->st->codec->codec_type) {
 +        case AVMEDIA_TYPE_AUDIO:
 +            ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
 +                             ist->st->codec->sample_rate;
 +            break;
 +        case AVMEDIA_TYPE_VIDEO:
 +            if (pkt->duration) {
 +                ist->next_pts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
 +            } else 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 *
 +                                  ist->st->codec->time_base.num * ticks) /
 +                                  ist->st->codec->time_base.den;
 +            }
 +            break;
 +        }
 +    }
 +    for (i = 0; pkt && i < nb_ostreams; i++) {
 +        OutputStream *ost = &ost_table[i];
  
 -        if (metadata_chapters_autocopy)
 -            av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
 +        if (!check_output_constraints(ist, ost) || ost->encoding_needed)
 +            continue;
  
 -        os->nb_chapters++;
 -        os->chapters = av_realloc(os->chapters, sizeof(AVChapter)*os->nb_chapters);
 -        if (!os->chapters)
 -            return AVERROR(ENOMEM);
 -        os->chapters[os->nb_chapters - 1] = out_ch;
 +        do_streamcopy(ist, ost, pkt);
      }
 +
      return 0;
  }
  
 -static void parse_forced_key_frames(char *kf, OutputStream *ost,
 -                                    AVCodecContext *avctx)
 +static void print_sdp(OutputFile *output_files, int n)
  {
 -    char *p;
 -    int n = 1, i;
 -    int64_t t;
 +    char sdp[2048];
 +    int i;
 +    AVFormatContext **avc = av_malloc(sizeof(*avc)*n);
  
 -    for (p = kf; *p; p++)
 -        if (*p == ',')
 -            n++;
 -    ost->forced_kf_count = n;
 -    ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
 -    if (!ost->forced_kf_pts) {
 -        av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
 +    if (!avc)
          exit_program(1);
 +    for (i = 0; i < n; i++)
 +        avc[i] = output_files[i].ctx;
 +
 +    av_sdp_create(avc, n, sdp, sizeof(sdp));
 +    printf("SDP:\n%s\n", sdp);
 +    fflush(stdout);
 +    av_freep(&avc);
 +}
 +
 +static int init_input_stream(int ist_index, OutputStream *output_streams, int nb_output_streams,
 +                             char *error, int error_len)
 +{
 +    InputStream *ist = &input_streams[ist_index];
 +    if (ist->decoding_needed) {
 +        AVCodec *codec = ist->dec;
 +        if (!codec) {
 +            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, error_len, "Error while opening decoder for input stream #%d:%d",
 +                    ist->file_index, ist->st->index);
 +            return AVERROR(EINVAL);
 +        }
 +        assert_codec_experimental(ist->st->codec, 0);
 +        assert_avoptions(ist->opts);
      }
 -    for (i = 0; i < n; i++) {
 -        p = i ? strchr(p, ',') + 1 : kf;
 -        t = parse_time_or_die("force_key_frames", p, 1);
 -        ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
 -    }
 +
 +    ist->pts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames*AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
 +    ist->next_pts = AV_NOPTS_VALUE;
 +    ist->is_start = 1;
 +
 +    return 0;
  }
  
 -/*
 - * The following code is the main loop of the file converter
 - */
 -static int transcode(AVFormatContext **output_files,
 -                     int nb_output_files,
 -                     InputFile *input_files,
 -                     int nb_input_files,
 -                     StreamMap *stream_maps, int nb_stream_maps)
 +static int transcode_init(OutputFile *output_files, int nb_output_files,
 +                          InputFile  *input_files,  int nb_input_files)
  {
 -    int ret = 0, i, j, k, n, nb_ostreams = 0;
 -    AVFormatContext *is, *os;
 +    int ret = 0, i, j, k;
 +    AVFormatContext *oc;
      AVCodecContext *codec, *icodec;
 -    OutputStream *ost, **ost_table = NULL;
 +    OutputStream *ost;
      InputStream *ist;
      char error[1024];
      int want_sdp = 1;
 -    uint8_t no_packet[MAX_FILES]={0};
 -    int no_packet_count=0;
 -
 -    if (rate_emu)
 -        for (i = 0; i < nb_input_streams; i++)
 -            input_streams[i].start = av_gettime();
 -
 -    /* output stream init */
 -    nb_ostreams = 0;
 -    for(i=0;i<nb_output_files;i++) {
 -        os = output_files[i];
 -        if (!os->nb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) {
 -            av_dump_format(output_files[i], i, output_files[i]->filename, 1);
 -            fprintf(stderr, "Output file #%d does not contain any stream\n", i);
 -            ret = AVERROR(EINVAL);
 -            goto fail;
 -        }
 -        nb_ostreams += os->nb_streams;
 -    }
 -    if (nb_stream_maps > 0 && nb_stream_maps != nb_ostreams) {
 -        fprintf(stderr, "Number of stream maps must match number of output streams\n");
 -        ret = AVERROR(EINVAL);
 -        goto fail;
 -    }
 -
 -    /* Sanity check the mapping args -- do the input files & streams exist? */
 -    for(i=0;i<nb_stream_maps;i++) {
 -        int fi = stream_maps[i].file_index;
 -        int si = stream_maps[i].stream_index;
  
 -        if (fi < 0 || fi > nb_input_files - 1 ||
 -            si < 0 || si > input_files[fi].nb_streams - 1) {
 -            fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si);
 -            ret = AVERROR(EINVAL);
 -            goto fail;
 -        }
 -        fi = stream_maps[i].sync_file_index;
 -        si = stream_maps[i].sync_stream_index;
 -        if (fi < 0 || fi > nb_input_files - 1 ||
 -            si < 0 || si > input_files[fi].nb_streams - 1) {
 -            fprintf(stderr,"Could not find sync stream #%d.%d\n", fi, si);
 -            ret = AVERROR(EINVAL);
 -            goto fail;
 -        }
 +    /* 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();
      }
  
 -    ost_table = av_mallocz(sizeof(OutputStream *) * nb_ostreams);
 -    if (!ost_table)
 -        goto fail;
 -    n = 0;
 -    for(k=0;k<nb_output_files;k++) {
 -        os = output_files[k];
 -        for(i=0;i<os->nb_streams;i++,n++) {
 -            int found;
 -            ost = ost_table[n] = output_streams_for_file[k][i];
 -            if (nb_stream_maps > 0) {
 -                ost->source_index = input_files[stream_maps[n].file_index].ist_index +
 -                    stream_maps[n].stream_index;
 -
 -                /* Sanity check that the stream types match */
 -                if (input_streams[ost->source_index].st->codec->codec_type != ost->st->codec->codec_type) {
 -                    int i= ost->file_index;
 -                    av_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].file_index, stream_maps[n].stream_index,
 -                        ost->file_index, ost->index);
 -                    exit_program(1);
 -                }
 -
 -            } else {
 -                int best_nb_frames=-1;
 -                /* get corresponding input stream index : we select the first one with the right type */
 -                found = 0;
 -                for (j = 0; j < nb_input_streams; j++) {
 -                    int skip=0;
 -                    ist = &input_streams[j];
 -                    if(opt_programid){
 -                        int pi,si;
 -                        AVFormatContext *f = input_files[ist->file_index].ctx;
 -                        skip=1;
 -                        for(pi=0; pi<f->nb_programs; pi++){
 -                            AVProgram *p= f->programs[pi];
 -                            if(p->id == opt_programid)
 -                                for(si=0; si<p->nb_stream_indexes; si++){
 -                                    if(f->streams[ p->stream_index[si] ] == ist->st)
 -                                        skip=0;
 -                                }
 -                        }
 -                    }
 -                    if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip &&
 -                        ist->st->codec->codec_type == ost->st->codec->codec_type) {
 -                        if(best_nb_frames < ist->st->codec_info_nb_frames){
 -                            best_nb_frames= ist->st->codec_info_nb_frames;
 -                            ost->source_index = j;
 -                            found = 1;
 -                        }
 -                    }
 -                }
 -
 -                if (!found) {
 -                    if(! opt_programid) {
 -                        /* try again and reuse existing stream */
 -                        for (j = 0; j < nb_input_streams; j++) {
 -                            ist = &input_streams[j];
 -                            if (   ist->st->codec->codec_type == ost->st->codec->codec_type
 -                                && ist->st->discard != AVDISCARD_ALL) {
 -                                ost->source_index = j;
 -                                found = 1;
 -                            }
 -                        }
 -                    }
 -                    if (!found) {
 -                        int i= ost->file_index;
 -                        av_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);
 -                        exit_program(1);
 -                    }
 -                }
 -            }
 -            ist = &input_streams[ost->source_index];
 -            ist->discard = 0;
 -            ost->sync_ist = (nb_stream_maps > 0) ?
 -                &input_streams[input_files[stream_maps[n].sync_file_index].ist_index +
 -                         stream_maps[n].sync_stream_index] : ist;
 +    /* output stream init */
 +    for (i = 0; i < nb_output_files; i++) {
 +        oc = output_files[i].ctx;
 +        if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
 +            av_dump_format(oc, i, oc->filename, 1);
 +            av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i);
 +            return AVERROR(EINVAL);
          }
      }
  
      /* for each output stream, we compute the right encoding parameters */
 -    for(i=0;i<nb_ostreams;i++) {
 -        ost = ost_table[i];
 -        os = output_files[ost->file_index];
 +    for (i = 0; i < nb_output_streams; i++) {
 +        ost = &output_streams[i];
 +        oc  = output_files[ost->file_index].ctx;
          ist = &input_streams[ost->source_index];
  
 -        codec = ost->st->codec;
 -        icodec = ist->st->codec;
 +        if (ost->attachment_filename)
 +            continue;
  
 -        if (metadata_streams_autocopy)
 -            av_dict_copy(&ost->st->metadata, ist->st->metadata,
 -                         AV_DICT_DONT_OVERWRITE);
 +        codec  = ost->st->codec;
 +        icodec = ist->st->codec;
  
 -        ost->st->disposition = ist->st->disposition;
 -        codec->bits_per_raw_sample= icodec->bits_per_raw_sample;
 +        ost->st->disposition          = ist->st->disposition;
 +        codec->bits_per_raw_sample    = icodec->bits_per_raw_sample;
          codec->chroma_sample_location = icodec->chroma_sample_location;
  
 -        if (ost->st->stream_copy) {
 +        if (ost->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;
 +            codec->codec_id   = icodec->codec_id;
              codec->codec_type = icodec->codec_type;
  
 -            if(!codec->codec_tag){
 -                if(   !os->oformat->codec_tag
 -                   || av_codec_get_id (os->oformat->codec_tag, icodec->codec_tag) == codec->codec_id
 -                   || av_codec_get_tag(os->oformat->codec_tag, icodec->codec_id) <= 0)
 +            if (!codec->codec_tag) {
 +                if (!oc->oformat->codec_tag ||
 +                     av_codec_get_id (oc->oformat->codec_tag, icodec->codec_tag) == codec->codec_id ||
 +                     av_codec_get_tag(oc->oformat->codec_tag, icodec->codec_id) <= 0)
                      codec->codec_tag = icodec->codec_tag;
              }
  
 -            codec->bit_rate = icodec->bit_rate;
 +            codec->bit_rate       = icodec->bit_rate;
              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;
 +            codec->extradata      = av_mallocz(extra_size);
 +            if (!codec->extradata) {
 +                return AVERROR(ENOMEM);
 +            }
              memcpy(codec->extradata, icodec->extradata, icodec->extradata_size);
              codec->extradata_size= icodec->extradata_size;
 -            if(!copy_tb && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/500){
 -                codec->time_base = icodec->time_base;
 -                codec->time_base.num *= icodec->ticks_per_frame;
 -                av_reduce(&codec->time_base.num, &codec->time_base.den,
 -                          codec->time_base.num, codec->time_base.den, INT_MAX);
 -            }else
 -                codec->time_base = ist->st->time_base;
 +
 +            codec->time_base = ist->st->time_base;
 +            if(!strcmp(oc->oformat->name, "avi")) {
 +                if (   copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > 2*av_q2d(ist->st->time_base)
 +                                 && av_q2d(ist->st->time_base) < 1.0/500
 +                    || copy_tb==0){
 +                    codec->time_base = icodec->time_base;
 +                    codec->time_base.num *= icodec->ticks_per_frame;
 +                    codec->time_base.den *= 2;
 +                }
 +            } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS)
 +                      && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp")
 +                      && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod")
 +            ) {
 +                if(   copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base)
 +                                && av_q2d(ist->st->time_base) < 1.0/500
 +                   || copy_tb==0){
 +                    codec->time_base = icodec->time_base;
 +                    codec->time_base.num *= icodec->ticks_per_frame;
 +                }
 +            }
 +            av_reduce(&codec->time_base.num, &codec->time_base.den,
 +                        codec->time_base.num, codec->time_base.den, INT_MAX);
 +
              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;
 -                codec->sample_rate = icodec->sample_rate;
 -                codec->channels = icodec->channels;
 -                codec->frame_size = icodec->frame_size;
 +                codec->channel_layout     = icodec->channel_layout;
 +                codec->sample_rate        = icodec->sample_rate;
 +                codec->channels           = icodec->channels;
 +                codec->frame_size         = icodec->frame_size;
                  codec->audio_service_type = icodec->audio_service_type;
 -                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;
 +                codec->block_align        = icodec->block_align;
                  break;
              case AVMEDIA_TYPE_VIDEO:
 -                codec->pix_fmt = icodec->pix_fmt;
 -                codec->width = icodec->width;
 -                codec->height = icodec->height;
 -                codec->has_b_frames = icodec->has_b_frames;
 +                codec->pix_fmt            = icodec->pix_fmt;
 +                codec->width              = icodec->width;
 +                codec->height             = icodec->height;
 +                codec->has_b_frames       = icodec->has_b_frames;
                  if (!codec->sample_aspect_ratio.num) {
 -                    codec->sample_aspect_ratio =
 +                    codec->sample_aspect_ratio   =
                      ost->st->sample_aspect_ratio =
                          ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio :
                          ist->st->codec->sample_aspect_ratio.num ?
                          ist->st->codec->sample_aspect_ratio : (AVRational){0, 1};
                  }
 +                ost->st->avg_frame_rate = ist->st->avg_frame_rate;
                  break;
              case AVMEDIA_TYPE_SUBTITLE:
 -                codec->width = icodec->width;
 +                codec->width  = icodec->width;
                  codec->height = icodec->height;
                  break;
              case AVMEDIA_TYPE_DATA:
 +            case AVMEDIA_TYPE_ATTACHMENT:
                  break;
              default:
                  abort();
          } else {
              if (!ost->enc)
                  ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
 +
 +            ist->decoding_needed = 1;
 +            ost->encoding_needed = 1;
 +
              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 (!codec->sample_rate) {
 -                    codec->sample_rate = icodec->sample_rate;
 -                    if (icodec->lowres)
 -                        codec->sample_rate >>= icodec->lowres;
 +                ost->fifo = av_fifo_alloc(1024);
 +                if (!ost->fifo) {
 +                    return AVERROR(ENOMEM);
                  }
 +                if (!codec->sample_rate)
 +                    codec->sample_rate = icodec->sample_rate;
                  choose_sample_rate(ost->st, ost->enc);
                  codec->time_base = (AVRational){1, codec->sample_rate};
 +
                  if (codec->sample_fmt == AV_SAMPLE_FMT_NONE)
                      codec->sample_fmt = icodec->sample_fmt;
                  choose_sample_fmt(ost->st, ost->enc);
 -                if (!codec->channels)
 +
 +                if (ost->audio_channels_mapped) {
 +                    /* the requested output channel is set to the number of
 +                     * -map_channel only if no -ac are specified */
 +                    if (!codec->channels) {
 +                        codec->channels       = ost->audio_channels_mapped;
 +                        codec->channel_layout = av_get_default_channel_layout(codec->channels);
 +                        if (!codec->channel_layout) {
 +                            av_log(NULL, AV_LOG_FATAL, "Unable to find an appropriate channel layout for requested number of channel\n");
 +                            exit_program(1);
 +                        }
 +                    }
 +                    /* fill unused channel mapping with -1 (which means a muted
 +                     * channel in case the number of output channels is bigger
 +                     * than the number of mapped channel) */
 +                    for (j = ost->audio_channels_mapped; j < FF_ARRAY_ELEMS(ost->audio_channels_map); j++)
 +                        ost->audio_channels_map[j] = -1;
 +                } else if (!codec->channels) {
                      codec->channels = icodec->channels;
 -                codec->channel_layout = icodec->channel_layout;
 +                    codec->channel_layout = icodec->channel_layout;
 +                }
                  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;
 -                icodec->request_channels = codec->channels;
 -                ist->decoding_needed = 1;
 -                ost->encoding_needed = 1;
 +
 +                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;
                  ost->resample_sample_fmt  = icodec->sample_fmt;
                  ost->resample_sample_rate = icodec->sample_rate;
                  ost->resample_channels    = icodec->channels;
                  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);
                  }
  
                                        codec->height  != icodec->height ||
                                        codec->pix_fmt != icodec->pix_fmt;
                  if (ost->video_resample) {
 -#if !CONFIG_AVFILTER
 -                    avcodec_get_frame_defaults(&ost->pict_tmp);
 -                    if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt,
 -                                       codec->width, codec->height)) {
 -                        fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");
 -                        exit_program(1);
 -                    }
 -                    ost->img_resample_ctx = sws_getContext(
 -                        icodec->width,
 -                        icodec->height,
 -                        icodec->pix_fmt,
 -                        codec->width,
 -                        codec->height,
 -                        codec->pix_fmt,
 -                        ost->sws_flags, NULL, NULL, NULL);
 -                    if (ost->img_resample_ctx == NULL) {
 -                        fprintf(stderr, "Cannot get resampling context\n");
 -                        exit_program(1);
 -                    }
 -#endif
 -                    codec->bits_per_raw_sample= 0;
 +                    codec->bits_per_raw_sample= frame_bits_per_raw_sample;
                  }
  
 -                ost->resample_height = icodec->height;
 -                ost->resample_width  = icodec->width;
 -                ost->resample_pix_fmt= icodec->pix_fmt;
 -                ost->encoding_needed = 1;
 -                ist->decoding_needed = 1;
 +                ost->resample_height  = icodec->height;
 +                ost->resample_width   = icodec->width;
 +                ost->resample_pix_fmt = icodec->pix_fmt;
  
                  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];
                  }
                  codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
 +                if(   av_q2d(codec->time_base) < 0.001 && video_sync_method
 +                   && (video_sync_method==1 || (video_sync_method<0 && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
 +                    av_log(oc, 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
                  break;
              case AVMEDIA_TYPE_SUBTITLE:
 -                ost->encoding_needed = 1;
 -                ist->decoding_needed = 1;
                  break;
              default:
                  abort();
                  break;
              }
              /* two pass mode */
 -            if (ost->encoding_needed &&
 +            if (codec->codec_id != CODEC_ID_H264 &&
                  (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
                  char logfilename[1024];
                  FILE *f;
                  snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
                           pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX,
                           i);
 -                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));
 -                        exit_program(1);
 -                    }
 -                    ost->logfile = f;
 -                } else {
 +                if (codec->flags & CODEC_FLAG_PASS2) {
                      char  *logbuffer;
                      size_t logbuffer_size;
                      if (cmdutils_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;
                  }
 +                if (codec->flags & CODEC_FLAG_PASS1) {
 +                    f = fopen(logfilename, "wb");
 +                    if (!f) {
 +                        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;
 +                }
              }
          }
          if(codec->codec_type == AVMEDIA_TYPE_VIDEO){
 -            int size= codec->width * codec->height;
 -            bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 200);
 +            /* 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, 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 */
 -    for(i=0;i<nb_ostreams;i++) {
 -        ost = ost_table[i];
 +    for (i = 0; i < nb_output_streams; i++) {
 +        ost = &output_streams[i];
          if (ost->encoding_needed) {
 -            AVCodec *codec = ost->enc;
 +            AVCodec      *codec = ost->enc;
              AVCodecContext *dec = input_streams[ost->source_index].st->codec;
              if (!codec) {
 -                snprintf(error, sizeof(error), "Encoder (codec id %d) not found for output stream #%d.%d",
 -                         ost->st->codec->codec_id, ost->file_index, ost->index);
 +                snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d",
 +                         avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
                  ret = AVERROR(EINVAL);
                  goto dump_format;
              }
                  ost->st->codec->subtitle_header_size = dec->subtitle_header_size;
              }
              if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) {
 -                snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height",
 +                snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height",
                          ost->file_index, ost->index);
                  ret = AVERROR(EINVAL);
                  goto dump_format;
              assert_avoptions(ost->opts);
              if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000)
                  av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
 -                                             "It takes bits/s as argument, not kbits/s\n");
 +                                             " It takes bits/s as argument, not kbits/s\n");
              extra_size += ost->st->codec->extradata_size;
 -        }
 -    }
 -
 -    /* open each decoder */
 -    for (i = 0; i < nb_input_streams; i++) {
 -        ist = &input_streams[i];
 -        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 id %d) not found for input stream #%d.%d",
 -                        ist->st->codec->codec_id, ist->file_index, ist->st->index);
 -                ret = AVERROR(EINVAL);
 -                goto dump_format;
 -            }
 -
 -            /* update requested sample format for the decoder based on the
 -               corresponding encoder sample format */
 -            for (j = 0; j < nb_ostreams; j++) {
 -                ost = ost_table[j];
 -                if (ost->source_index == i) {
 -                    update_sample_fmt(ist->st->codec, codec, ost->st->codec);
 -                    break;
 -                }
 -            }
  
 -            if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
 -                snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d",
 -                        ist->file_index, ist->st->index);
 -                ret = AVERROR(EINVAL);
 -                goto dump_format;
 -            }
 -            assert_codec_experimental(ist->st->codec, 0);
 -            assert_avoptions(ost->opts);
 +            if (ost->st->codec->me_threshold)
 +                input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV;
          }
      }
  
 -    /* init pts */
 -    for (i = 0; i < nb_input_streams; i++) {
 -        AVStream *st;
 -        ist = &input_streams[i];
 -        st= ist->st;
 -        ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0;
 -        ist->next_pts = AV_NOPTS_VALUE;
 -        init_pts_correction(&ist->pts_ctx);
 -        ist->is_start = 1;
 -    }
 -
 -    /* set meta data information from input file if required */
 -    for (i=0;i<nb_meta_data_maps;i++) {
 -        AVFormatContext *files[2];
 -        AVDictionary    **meta[2];
 -        int j;
 -
 -#define METADATA_CHECK_INDEX(index, nb_elems, desc)\
 -        if ((index) < 0 || (index) >= (nb_elems)) {\
 -            snprintf(error, sizeof(error), "Invalid %s index %d while processing metadata maps\n",\
 -                     (desc), (index));\
 -            ret = AVERROR(EINVAL);\
 -            goto dump_format;\
 -        }
 -
 -        int out_file_index = meta_data_maps[i][0].file;
 -        int in_file_index = meta_data_maps[i][1].file;
 -        if (in_file_index < 0 || out_file_index < 0)
 -            continue;
 -        METADATA_CHECK_INDEX(out_file_index, nb_output_files, "output file")
 -        METADATA_CHECK_INDEX(in_file_index, nb_input_files, "input file")
 -
 -        files[0] = output_files[out_file_index];
 -        files[1] = input_files[in_file_index].ctx;
 -
 -        for (j = 0; j < 2; j++) {
 -            MetadataMap *map = &meta_data_maps[i][j];
 -
 -            switch (map->type) {
 -            case 'g':
 -                meta[j] = &files[j]->metadata;
 -                break;
 -            case 's':
 -                METADATA_CHECK_INDEX(map->index, files[j]->nb_streams, "stream")
 -                meta[j] = &files[j]->streams[map->index]->metadata;
 -                break;
 -            case 'c':
 -                METADATA_CHECK_INDEX(map->index, files[j]->nb_chapters, "chapter")
 -                meta[j] = &files[j]->chapters[map->index]->metadata;
 -                break;
 -            case 'p':
 -                METADATA_CHECK_INDEX(map->index, files[j]->nb_programs, "program")
 -                meta[j] = &files[j]->programs[map->index]->metadata;
 -                break;
 -            }
 -        }
 -
 -        av_dict_copy(meta[0], *meta[1], AV_DICT_DONT_OVERWRITE);
 -    }
 -
 -    /* copy global metadata by default */
 -    if (metadata_global_autocopy) {
 -
 -        for (i = 0; i < nb_output_files; i++)
 -            av_dict_copy(&output_files[i]->metadata, input_files[0].ctx->metadata,
 -                         AV_DICT_DONT_OVERWRITE);
 -    }
 -
 -    /* copy chapters according to chapter maps */
 -    for (i = 0; i < nb_chapter_maps; i++) {
 -        int infile  = chapter_maps[i].in_file;
 -        int outfile = chapter_maps[i].out_file;
 -
 -        if (infile < 0 || outfile < 0)
 -            continue;
 -        if (infile >= nb_input_files) {
 -            snprintf(error, sizeof(error), "Invalid input file index %d in chapter mapping.\n", infile);
 -            ret = AVERROR(EINVAL);
 -            goto dump_format;
 -        }
 -        if (outfile >= nb_output_files) {
 -            snprintf(error, sizeof(error), "Invalid output file index %d in chapter mapping.\n",outfile);
 -            ret = AVERROR(EINVAL);
 +    /* 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)
              goto dump_format;
 -        }
 -        copy_chapters(infile, outfile);
 -    }
  
 -    /* copy chapters from the first input file that has them*/
 -    if (!nb_chapter_maps)
 -        for (i = 0; i < nb_input_files; i++) {
 -            if (!input_files[i].ctx->nb_chapters)
 -                continue;
 +    /* 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 (j = 0; j < nb_output_files; j++)
 -                if ((ret = copy_chapters(i, j)) < 0)
 -                    goto dump_format;
 -            break;
 +            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];
 -        if (avformat_write_header(os, &output_opts[i]) < 0) {
 +    for (i = 0; i < nb_output_files; i++) {
 +        oc = output_files[i].ctx;
 +        oc->interrupt_callback = int_cb;
 +        if (avformat_write_header(oc, &output_files[i].opts) < 0) {
              snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
              ret = AVERROR(EINVAL);
              goto dump_format;
          }
 -        assert_avoptions(output_opts[i]);
 -        if (strcmp(output_files[i]->oformat->name, "rtp")) {
 +//        assert_avoptions(output_files[i].opts);
 +        if (strcmp(oc->oformat->name, "rtp")) {
              want_sdp = 0;
          }
      }
   dump_format:
      /* dump the file output parameters - cannot be done before in case
         of stream copy */
 -    for(i=0;i<nb_output_files;i++) {
 -        av_dump_format(output_files[i], i, output_files[i]->filename, 1);
 +    for (i = 0; i < nb_output_files; i++) {
 +        av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1);
      }
  
      /* dump the stream mapping */
 -    if (verbose >= 0) {
 -        fprintf(stderr, "Stream mapping:\n");
 -        for(i=0;i<nb_ostreams;i++) {
 -            ost = ost_table[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);
 -            fprintf(stderr, "\n");
 +    av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
 +    for (i = 0; i < nb_output_streams; i++) {
 +        ost = &output_streams[i];
 +
 +        if (ost->attachment_filename) {
 +            /* an attached file */
 +            av_log(NULL, AV_LOG_INFO, "  File %s -> Stream #%d:%d\n",
 +                   ost->attachment_filename, ost->file_index, ost->index);
 +            continue;
          }
 +        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->audio_channels_mapped) {
 +            av_log(NULL, AV_LOG_INFO, " [ch:");
 +            for (j = 0; j < ost->audio_channels_mapped; j++)
 +                if (ost->audio_channels_map[j] == -1)
 +                    av_log(NULL, AV_LOG_INFO, " M");
 +                else
 +                    av_log(NULL, AV_LOG_INFO, " %d", ost->audio_channels_map[j]);
 +            av_log(NULL, AV_LOG_INFO, "]");
 +        }
 +        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->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);
      }
  
 -    if (verbose >= 0)
 -        fprintf(stderr, "Press ctrl-c to stop encoding\n");
 -    term_init();
 +    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) {
 +        av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
 +    }
  
      timer_start = av_gettime();
  
      for(; received_sigterm == 0;) {
          int file_index, ist_index;
          AVPacket pkt;
 -        double ipts_min;
 +        int64_t ipts_min;
          double opts_min;
 +        int64_t cur_time= av_gettime();
  
 -    redo:
 -        ipts_min= 1e100;
 +        ipts_min= INT64_MAX;
          opts_min= 1e100;
 +        /* if 'q' pressed, exits */
 +        if (!using_stdin) {
 +            static int64_t last_time;
 +            if (received_nb_signals)
 +                break;
 +            /* read_key() returns 0 on EOF */
 +            if(cur_time - last_time >= 100000 && !run_as_daemon){
 +                key =  read_key();
 +                last_time = cur_time;
 +            }else
 +                key = -1;
 +            if (key == 'q')
 +                break;
 +            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){
 +                    do_hex_dump = do_pkt_dump = 0;
 +                } else if(do_pkt_dump){
 +                    do_hex_dump = 1;
 +                } else
 +                    do_pkt_dump = 1;
 +                av_log_set_level(AV_LOG_DEBUG);
 +            }
 +#if CONFIG_AVFILTER
 +            if (key == 'c' || key == 'C'){
 +                char buf[4096], target[64], command[256], arg[256] = {0};
 +                double time;
 +                int k, n = 0;
 +                fprintf(stderr, "\nEnter command: <target> <time> <command>[ <argument>]\n");
 +                i = 0;
 +                while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1)
 +                    if (k > 0)
 +                        buf[i++] = k;
 +                buf[i] = 0;
 +                if (k > 0 &&
 +                    (n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
 +                    av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
 +                           target, time, command, arg);
 +                    for (i = 0; i < nb_output_streams; i++) {
 +                        ost = &output_streams[i];
 +                        if (ost->graph) {
 +                            if (time < 0) {
 +                                ret = avfilter_graph_send_command(ost->graph, target, command, arg, buf, sizeof(buf),
 +                                                                  key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0);
 +                                fprintf(stderr, "Command reply for stream %d: ret:%d res:%s\n", i, ret, buf);
 +                            } else {
 +                                ret = avfilter_graph_queue_command(ost->graph, target, command, arg, 0, time);
 +                            }
 +                        }
 +                    }
 +                } else {
 +                    av_log(NULL, AV_LOG_ERROR,
 +                           "Parse error, at least 3 arguments were expected, "
 +                           "only %d given in string '%s'\n", n, buf);
 +                }
 +            }
 +#endif
 +            if (key == 'd' || key == 'D'){
 +                int debug=0;
 +                if(key == 'D') {
 +                    debug = input_streams[0].st->codec->debug<<1;
 +                    if(!debug) debug = 1;
 +                    while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
 +                        debug += debug;
 +                }else
 +                    if(scanf("%d", &debug)!=1)
 +                        fprintf(stderr,"error parsing debug value\n");
 +                for(i=0;i<nb_input_streams;i++) {
 +                    input_streams[i].st->codec->debug = debug;
 +                }
 +                for(i=0;i<nb_output_streams;i++) {
 +                    ost = &output_streams[i];
 +                    ost->st->codec->debug = debug;
 +                }
 +                if(debug) av_log_set_level(AV_LOG_DEBUG);
 +                fprintf(stderr,"debug=%d\n", debug);
 +            }
 +            if (key == '?'){
 +                fprintf(stderr, "key    function\n"
 +                                "?      show this help\n"
 +                                "+      increase verbosity\n"
 +                                "-      decrease verbosity\n"
 +                                "c      Send command to filtergraph\n"
 +                                "D      cycle through available debug modes\n"
 +                                "h      dump packets/hex press to cycle through the 3 states\n"
 +                                "q      quit\n"
 +                                "s      Show QP histogram\n"
 +                );
 +            }
 +        }
  
          /* select the stream that we must read now by looking at the
             smallest output pts */
          file_index = -1;
 -        for(i=0;i<nb_ostreams;i++) {
 -            double ipts, opts;
 -            ost = ost_table[i];
 -            os = output_files[ost->file_index];
 +        for (i = 0; i < nb_output_streams; i++) {
 +            OutputFile *of;
 +            int64_t ipts;
 +            double  opts;
 +            ost = &output_streams[i];
 +            of = &output_files[ost->file_index];
 +            os = output_files[ost->file_index].ctx;
              ist = &input_streams[ost->source_index];
 -            if(ist->is_past_recording_time || no_packet[ist->file_index])
 +            if (ost->is_past_recording_time || no_packet[ist->file_index] ||
 +                (os->pb && avio_tell(os->pb) >= of->limit_filesize))
                  continue;
 -                opts = ost->st->pts.val * av_q2d(ost->st->time_base);
 -            ipts = (double)ist->pts;
 +            opts = ost->st->pts.val * av_q2d(ost->st->time_base);
 +            ipts = ist->pts;
              if (!input_files[ist->file_index].eof_reached){
                  if(ipts < ipts_min) {
                      ipts_min = ipts;
                      if(!input_sync) file_index = ist->file_index;
                  }
              }
 -            if(ost->frame_number >= max_frames[ost->st->codec->codec_type]){
 -                file_index= -1;
 -                break;
 +            if (ost->frame_number >= ost->max_frames) {
 +                int j;
 +                for (j = 0; j < of->ctx->nb_streams; j++)
 +                    output_streams[of->ost_index + j].is_past_recording_time = 1;
 +                continue;
              }
          }
          /* if none, if is finished */
          if (file_index < 0) {
              if(no_packet_count){
                  no_packet_count=0;
 -                memset(no_packet, 0, sizeof(no_packet));
 +                memset(no_packet, 0, nb_input_files);
                  usleep(10000);
                  continue;
              }
              break;
          }
  
 -        /* finish if limit size exhausted */
 -        if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0]->pb))
 -            break;
 -
          /* read a frame from it and output it in the fifo */
          is = input_files[file_index].ctx;
          ret= av_read_frame(is, &pkt);
          }
  
          no_packet_count=0;
 -        memset(no_packet, 0, sizeof(no_packet));
 +        memset(no_packet, 0, nb_input_files);
  
          if (do_pkt_dump) {
              av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump,
          if (pkt.pts != AV_NOPTS_VALUE)
              pkt.pts += av_rescale_q(input_files[ist->file_index].ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
  
 -        if (ist->ts_scale) {
 -            if(pkt.pts != AV_NOPTS_VALUE)
 -                pkt.pts *= ist->ts_scale;
 -            if(pkt.dts != AV_NOPTS_VALUE)
 -                pkt.dts *= ist->ts_scale;
 -        }
 +        if(pkt.pts != AV_NOPTS_VALUE)
 +            pkt.pts *= ist->ts_scale;
 +        if(pkt.dts != AV_NOPTS_VALUE)
 +            pkt.dts *= ist->ts_scale;
  
  //        fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files[ist->file_index].ts_offset, ist->st->codec->codec_type);
          if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE
              && (is->iformat->flags & AVFMT_TS_DISCONT)) {
              int64_t pkt_dts= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
              int64_t delta= pkt_dts - ist->next_pts;
 -            if((FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE || pkt_dts+1<ist->pts)&& !copy_ts){
 +            if((delta < -1LL*dts_delta_threshold*AV_TIME_BASE ||
 +                (delta > 1LL*dts_delta_threshold*AV_TIME_BASE &&
 +                 ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
 +                pkt_dts+1<ist->pts)&& !copy_ts){
                  input_files[ist->file_index].ts_offset -= delta;
 -                if (verbose > 2)
 -                    fprintf(stderr, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
 -                            delta, input_files[ist->file_index].ts_offset);
 +                av_log(NULL, AV_LOG_DEBUG, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
 +                       delta, input_files[ist->file_index].ts_offset);
                  pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
                  if(pkt.pts != AV_NOPTS_VALUE)
                      pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
              }
          }
  
 -        /* finish if recording time exhausted */
 -        if (recording_time != INT64_MAX &&
 -            av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000}) >= 0) {
 -            ist->is_past_recording_time = 1;
 -            goto discard_packet;
 -        }
 -
          //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
 -        if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
 +        if (output_packet(ist, output_streams, nb_output_streams, &pkt) < 0) {
  
 -            if (verbose >= 0)
 -                fprintf(stderr, "Error while decoding stream #%d.%d\n",
 -                        ist->file_index, ist->st->index);
 +            av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n",
 +                   ist->file_index, ist->st->index);
              if (exit_on_error)
                  exit_program(1);
              av_free_packet(&pkt);
 -            goto redo;
 +            continue;
          }
  
      discard_packet:
          av_free_packet(&pkt);
  
          /* dump report by using the output first video and audio streams */
 -        print_report(output_files, ost_table, nb_ostreams, 0);
 +        print_report(output_files, output_streams, nb_output_streams, 0, timer_start, cur_time);
      }
  
      /* at the end of stream, we must flush the decoder buffers */
      for (i = 0; i < nb_input_streams; i++) {
          ist = &input_streams[i];
          if (ist->decoding_needed) {
 -            output_packet(ist, i, ost_table, nb_ostreams, NULL);
 +            output_packet(ist, output_streams, nb_output_streams, NULL);
          }
      }
 +    flush_encoders(output_streams, nb_output_streams);
  
      term_exit();
  
      /* write the trailer if needed and close file */
      for(i=0;i<nb_output_files;i++) {
 -        os = output_files[i];
 +        os = output_files[i].ctx;
          av_write_trailer(os);
      }
  
      /* dump report by using the first video and audio streams */
 -    print_report(output_files, ost_table, nb_ostreams, 1);
 +    print_report(output_files, output_streams, nb_output_streams, 1, timer_start, av_gettime());
  
      /* close each encoder */
 -    for(i=0;i<nb_ostreams;i++) {
 -        ost = ost_table[i];
 +    for (i = 0; i < nb_output_streams; i++) {
 +        ost = &output_streams[i];
          if (ost->encoding_needed) {
              av_freep(&ost->st->codec->stats_in);
              avcodec_close(ost->st->codec);
  
   fail:
      av_freep(&bit_buffer);
 +    av_freep(&no_packet);
  
 -    if (ost_table) {
 -        for(i=0;i<nb_ostreams;i++) {
 -            ost = ost_table[i];
 +    if (output_streams) {
 +        for (i = 0; i < nb_output_streams; i++) {
 +            ost = &output_streams[i];
              if (ost) {
 -                if (ost->st->stream_copy)
 +                if (ost->stream_copy)
                      av_freep(&ost->st->codec->extradata);
                  if (ost->logfile) {
                      fclose(ost->logfile);
                  av_fifo_free(ost->fifo); /* works even if fifo is not
                                               initialized but set to zero */
                  av_freep(&ost->st->codec->subtitle_header);
 -                av_free(ost->pict_tmp.data[0]);
 +                av_free(ost->resample_frame.data[0]);
                  av_free(ost->forced_kf_pts);
                  if (ost->video_resample)
                      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);
 +                swr_free(&ost->swr);
                  av_dict_free(&ost->opts);
 -                av_free(ost);
              }
          }
 -        av_free(ost_table);
      }
      return ret;
  }
  
 -static int opt_format(const char *opt, const char *arg)
 -{
 -    last_asked_format = arg;
 -    return 0;
 -}
 -
 -static int opt_video_rc_override_string(const char *opt, const char *arg)
 -{
 -    video_rc_override_string = arg;
 -    return 0;
 -}
 -
 -static int opt_me_threshold(const char *opt, const char *arg)
 -{
 -    me_threshold = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
 -    return 0;
 -}
 -
 -static int opt_verbose(const char *opt, const char *arg)
 -{
 -    verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10);
 -    return 0;
 -}
 -
 -static int opt_frame_rate(const char *opt, const char *arg)
 -{
 -    if (av_parse_video_rate(&frame_rate, arg) < 0) {
 -        fprintf(stderr, "Incorrect value for %s: %s\n", opt, arg);
 -        exit_program(1);
 -    }
 -    return 0;
 -}
 -
  static int opt_frame_crop(const char *opt, const char *arg)
  {
 -    fprintf(stderr, "Option '%s' has been removed, use the crop filter instead\n", opt);
 +    av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the crop filter instead\n", opt);
      return AVERROR(EINVAL);
  }
  
 -static int opt_frame_size(const char *opt, const char *arg)
 +static int opt_pad(const char *opt, const char *arg)
  {
 -    if (av_parse_video_size(&frame_width, &frame_height, arg) < 0) {
 -        fprintf(stderr, "Incorrect frame size\n");
 -        return AVERROR(EINVAL);
 -    }
 -    return 0;
 -}
 -
 -static int opt_pad(const char *opt, const char *arg) {
 -    fprintf(stderr, "Option '%s' has been removed, use the pad filter instead\n", opt);
 +    av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the pad filter instead\n", opt);
      return -1;
  }
  
 -static int opt_frame_pix_fmt(const char *opt, const char *arg)
 -{
 -    if (strcmp(arg, "list")) {
 -        frame_pix_fmt = av_get_pix_fmt(arg);
 -        if (frame_pix_fmt == PIX_FMT_NONE) {
 -            fprintf(stderr, "Unknown pixel format requested: %s\n", arg);
 -            return AVERROR(EINVAL);
 -        }
 -    } else {
 -        show_pix_fmts();
 -        exit_program(0);
 -    }
 -    return 0;
 -}
 -
 -static int opt_frame_aspect_ratio(const char *opt, const char *arg)
 +static double parse_frame_aspect_ratio(const char *arg)
  {
      int x = 0, y = 0;
      double ar = 0;
          ar = strtod(arg, NULL);
  
      if (!ar) {
 -        fprintf(stderr, "Incorrect aspect ratio specification.\n");
 -        return AVERROR(EINVAL);
 -    }
 -    frame_aspect_ratio = ar;
 -    return 0;
 -}
 -
 -static int opt_metadata(const char *opt, const char *arg)
 -{
 -    char *mid= strchr(arg, '=');
 -
 -    if(!mid){
 -        fprintf(stderr, "Missing =\n");
 +        av_log(NULL, AV_LOG_FATAL, "Incorrect aspect ratio specification.\n");
          exit_program(1);
      }
 -    *mid++= 0;
 -
 -    av_dict_set(&metadata, arg, mid, 0);
 -
 -    return 0;
 +    return ar;
  }
  
 -static int opt_qscale(const char *opt, const char *arg)
 +static int opt_video_channel(const char *opt, const char *arg)
  {
 -    video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255);
 -    if (video_qscale == 0) {
 -        fprintf(stderr, "qscale must be > 0.0 and <= 255\n");
 -        return AVERROR(EINVAL);
 -    }
 -    return 0;
 +    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
 +    return opt_default("channel", arg);
  }
  
 -static int opt_top_field_first(const char *opt, const char *arg)
 +static int opt_video_standard(const char *opt, const char *arg)
  {
 -    top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1);
 -    return 0;
 +    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
 +    return opt_default("standard", arg);
  }
  
 -static int opt_thread_count(const char *opt, const char *arg)
 +static int opt_audio_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 -    thread_count= parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
 -#if !HAVE_THREADS
 -    if (verbose >= 0)
 -        fprintf(stderr, "Warning: not compiled with thread support, using thread emulation\n");
 -#endif
 -    return 0;
 +    audio_codec_name = arg;
 +    return parse_option(o, "codec:a", arg, options);
  }
  
 -static int opt_audio_sample_fmt(const char *opt, const char *arg)
 +static int opt_video_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 -    if (strcmp(arg, "list")) {
 -        audio_sample_fmt = av_get_sample_fmt(arg);
 -        if (audio_sample_fmt == AV_SAMPLE_FMT_NONE) {
 -            av_log(NULL, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
 -            return AVERROR(EINVAL);
 -        }
 -    } else {
 -        int i;
 -        char fmt_str[128];
 -        for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
 -            printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
 -        exit_program(0);
 -    }
 -    return 0;
 +    video_codec_name = arg;
 +    return parse_option(o, "codec:v", arg, options);
  }
  
 -static int opt_audio_rate(const char *opt, const char *arg)
 +static int opt_subtitle_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 -    audio_sample_rate = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
 -    return 0;
 +    subtitle_codec_name = arg;
 +    return parse_option(o, "codec:s", arg, options);
  }
  
 -static int opt_audio_channels(const char *opt, const char *arg)
 +static int opt_data_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 -    audio_channels = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
 -    return 0;
 +    return parse_option(o, "codec:d", arg, options);
  }
  
 -static int opt_video_channel(const char *opt, const char *arg)
 +static int opt_map(OptionsContext *o, const char *opt, const char *arg)
  {
 -    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
 -    opt_default("channel", arg);
 -    return 0;
 -}
 +    StreamMap *m = NULL;
 +    int i, negative = 0, file_idx;
 +    int sync_file_idx = -1, sync_stream_idx;
 +    char *p, *sync;
 +    char *map;
 +
 +    if (*arg == '-') {
 +        negative = 1;
 +        arg++;
 +    }
 +    map = av_strdup(arg);
 +
 +    /* parse sync stream first, just pick first matching stream */
 +    if (sync = strchr(map, ',')) {
 +        *sync = 0;
 +        sync_file_idx = strtol(sync + 1, &sync, 0);
 +        if (sync_file_idx >= nb_input_files || sync_file_idx < 0) {
 +            av_log(NULL, AV_LOG_FATAL, "Invalid sync file index: %d.\n", sync_file_idx);
 +            exit_program(1);
 +        }
 +        if (*sync)
 +            sync++;
 +        for (i = 0; i < input_files[sync_file_idx].nb_streams; i++)
 +            if (check_stream_specifier(input_files[sync_file_idx].ctx,
 +                                       input_files[sync_file_idx].ctx->streams[i], sync) == 1) {
 +                sync_stream_idx = i;
 +                break;
 +            }
 +        if (i == input_files[sync_file_idx].nb_streams) {
 +            av_log(NULL, AV_LOG_FATAL, "Sync stream specification in map %s does not "
 +                                       "match any streams.\n", arg);
 +            exit_program(1);
 +        }
 +    }
  
 -static int opt_video_standard(const char *opt, const char *arg)
 -{
 -    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
 -    opt_default("standard", arg);
 -    return 0;
 -}
  
 -static int opt_codec(int *pstream_copy, char **pcodec_name,
 -                      int codec_type, const char *arg)
 -{
 -    av_freep(pcodec_name);
 -    if (!strcmp(arg, "copy")) {
 -        *pstream_copy = 1;
 -    } else {
 -        *pcodec_name = av_strdup(arg);
 +    file_idx = strtol(map, &p, 0);
 +    if (file_idx >= nb_input_files || file_idx < 0) {
 +        av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx);
 +        exit_program(1);
      }
 -    return 0;
 -}
 +    if (negative)
 +        /* disable some already defined maps */
 +        for (i = 0; i < o->nb_stream_maps; i++) {
 +            m = &o->stream_maps[i];
 +            if (file_idx == m->file_index &&
 +                check_stream_specifier(input_files[m->file_index].ctx,
 +                                       input_files[m->file_index].ctx->streams[m->stream_index],
 +                                       *p == ':' ? p + 1 : p) > 0)
 +                m->disabled = 1;
 +        }
 +    else
 +        for (i = 0; i < input_files[file_idx].nb_streams; i++) {
 +            if (check_stream_specifier(input_files[file_idx].ctx, input_files[file_idx].ctx->streams[i],
 +                        *p == ':' ? p + 1 : p) <= 0)
 +                continue;
 +            o->stream_maps = grow_array(o->stream_maps, sizeof(*o->stream_maps),
 +                                        &o->nb_stream_maps, o->nb_stream_maps + 1);
 +            m = &o->stream_maps[o->nb_stream_maps - 1];
  
 -static int opt_audio_codec(const char *opt, const char *arg)
 -{
 -    return opt_codec(&audio_stream_copy, &audio_codec_name, AVMEDIA_TYPE_AUDIO, arg);
 -}
 +            m->file_index   = file_idx;
 +            m->stream_index = i;
  
 -static int opt_video_codec(const char *opt, const char *arg)
 -{
 -    return opt_codec(&video_stream_copy, &video_codec_name, AVMEDIA_TYPE_VIDEO, arg);
 -}
 +            if (sync_file_idx >= 0) {
 +                m->sync_file_index   = sync_file_idx;
 +                m->sync_stream_index = sync_stream_idx;
 +            } else {
 +                m->sync_file_index   = file_idx;
 +                m->sync_stream_index = i;
 +            }
 +        }
  
 -static int opt_subtitle_codec(const char *opt, const char *arg)
 -{
 -    return opt_codec(&subtitle_stream_copy, &subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, arg);
 -}
 +    if (!m) {
 +        av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n", arg);
 +        exit_program(1);
 +    }
  
 -static int opt_data_codec(const char *opt, const char *arg)
 -{
 -    return opt_codec(&data_stream_copy, &data_codec_name, AVMEDIA_TYPE_DATA, arg);
 +    av_freep(&map);
 +    return 0;
  }
  
 -static int opt_codec_tag(const char *opt, const char *arg)
 +static int opt_attach(OptionsContext *o, const char *opt, const char *arg)
  {
 -    char *tail;
 -    uint32_t *codec_tag;
 -
 -    codec_tag = !strcmp(opt, "atag") ? &audio_codec_tag :
 -                !strcmp(opt, "vtag") ? &video_codec_tag :
 -                !strcmp(opt, "stag") ? &subtitle_codec_tag : NULL;
 -    if (!codec_tag)
 -        return -1;
 -
 -    *codec_tag = strtol(arg, &tail, 0);
 -    if (!tail || *tail)
 -        *codec_tag = AV_RL32(arg);
 -
 +    o->attachments = grow_array(o->attachments, sizeof(*o->attachments),
 +                                &o->nb_attachments, o->nb_attachments + 1);
 +    o->attachments[o->nb_attachments - 1] = arg;
      return 0;
  }
  
 -static int opt_map(const char *opt, const char *arg)
 +static int opt_map_channel(OptionsContext *o, const char *opt, const char *arg)
  {
 -    StreamMap *m;
 -    char *p;
 +    int n;
 +    AVStream *st;
 +    AudioChannelMap *m;
 +
 +    o->audio_channel_maps =
 +        grow_array(o->audio_channel_maps, sizeof(*o->audio_channel_maps),
 +                   &o->nb_audio_channel_maps, o->nb_audio_channel_maps + 1);
 +    m = &o->audio_channel_maps[o->nb_audio_channel_maps - 1];
 +
 +    /* muted channel syntax */
 +    n = sscanf(arg, "%d:%d.%d", &m->channel_idx, &m->ofile_idx, &m->ostream_idx);
 +    if ((n == 1 || n == 3) && m->channel_idx == -1) {
 +        m->file_idx = m->stream_idx = -1;
 +        if (n == 1)
 +            m->ofile_idx = m->ostream_idx = -1;
 +        return 0;
 +    }
  
 -    stream_maps = grow_array(stream_maps, sizeof(*stream_maps), &nb_stream_maps, nb_stream_maps + 1);
 -    m = &stream_maps[nb_stream_maps-1];
 +    /* normal syntax */
 +    n = sscanf(arg, "%d.%d.%d:%d.%d",
 +               &m->file_idx,  &m->stream_idx, &m->channel_idx,
 +               &m->ofile_idx, &m->ostream_idx);
  
 -    m->file_index = strtol(arg, &p, 0);
 -    if (*p)
 -        p++;
 +    if (n != 3 && n != 5) {
 +        av_log(NULL, AV_LOG_FATAL, "Syntax error, mapchan usage: "
 +               "[file.stream.channel|-1][:syncfile:syncstream]\n");
 +        exit_program(1);
 +    }
  
 -    m->stream_index = strtol(p, &p, 0);
 -    if (*p) {
 -        p++;
 -        m->sync_file_index = strtol(p, &p, 0);
 -        if (*p)
 -            p++;
 -        m->sync_stream_index = strtol(p, &p, 0);
 -    } else {
 -        m->sync_file_index = m->file_index;
 -        m->sync_stream_index = m->stream_index;
 +    if (n != 5) // only file.stream.channel specified
 +        m->ofile_idx = m->ostream_idx = -1;
 +
 +    /* check input */
 +    if (m->file_idx < 0 || m->file_idx >= nb_input_files) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file index: %d\n",
 +               m->file_idx);
 +        exit_program(1);
 +    }
 +    if (m->stream_idx < 0 ||
 +        m->stream_idx >= input_files[m->file_idx].nb_streams) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n",
 +               m->file_idx, m->stream_idx);
 +        exit_program(1);
 +    }
 +    st = input_files[m->file_idx].ctx->streams[m->stream_idx];
 +    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
 +               m->file_idx, m->stream_idx);
 +        exit_program(1);
 +    }
 +    if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n",
 +               m->file_idx, m->stream_idx, m->channel_idx);
 +        exit_program(1);
      }
      return 0;
  }
  
 -static void parse_meta_type(char *arg, char *type, int *index, char **endptr)
 +static void parse_meta_type(char *arg, char *type, int *index)
  {
 -    *endptr = arg;
 -    if (*arg == ',') {
 -        *type = *(++arg);
 +    if (*arg) {
 +        *type = *arg;
          switch (*arg) {
          case 'g':
              break;
          case 's':
          case 'c':
          case 'p':
 -            *index = strtol(++arg, endptr, 0);
 +            if (*(++arg) == ':')
 +                *index = strtol(++arg, NULL, 0);
              break;
          default:
 -            fprintf(stderr, "Invalid metadata type %c.\n", *arg);
 +            av_log(NULL, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg);
              exit_program(1);
          }
      } else
          *type = 'g';
  }
  
 -static int opt_map_metadata(const char *opt, const char *arg)
 +static int opt_map_metadata(OptionsContext *o, const char *opt, const char *arg)
  {
      MetadataMap *m, *m1;
      char *p;
  
 -    meta_data_maps = grow_array(meta_data_maps, sizeof(*meta_data_maps),
 -                                &nb_meta_data_maps, nb_meta_data_maps + 1);
 +    o->meta_data_maps = grow_array(o->meta_data_maps, sizeof(*o->meta_data_maps),
 +                                   &o->nb_meta_data_maps, o->nb_meta_data_maps + 1);
  
 -    m = &meta_data_maps[nb_meta_data_maps - 1][0];
 +    m = &o->meta_data_maps[o->nb_meta_data_maps - 1][1];
      m->file = strtol(arg, &p, 0);
 -    parse_meta_type(p, &m->type, &m->index, &p);
 -    if (*p)
 -        p++;
 +    parse_meta_type(*p ? p + 1 : p, &m->type, &m->index);
  
 -    m1 = &meta_data_maps[nb_meta_data_maps - 1][1];
 -    m1->file = strtol(p, &p, 0);
 -    parse_meta_type(p, &m1->type, &m1->index, &p);
 +    m1 = &o->meta_data_maps[o->nb_meta_data_maps - 1][0];
 +    if (p = strchr(opt, ':'))
 +        parse_meta_type(p + 1, &m1->type, &m1->index);
 +    else
 +        m1->type = 'g';
  
      if (m->type == 'g' || m1->type == 'g')
 -        metadata_global_autocopy = 0;
 +        o->metadata_global_manual = 1;
      if (m->type == 's' || m1->type == 's')
 -        metadata_streams_autocopy = 0;
 +        o->metadata_streams_manual = 1;
      if (m->type == 'c' || m1->type == 'c')
 -        metadata_chapters_autocopy = 0;
 +        o->metadata_chapters_manual = 1;
  
      return 0;
  }
  
 -static int opt_map_meta_data(const char *opt, const char *arg)
 +static int opt_map_meta_data(OptionsContext *o, const char *opt, const char *arg)
  {
 -    fprintf(stderr, "-map_meta_data is deprecated and will be removed soon. "
 +    av_log(NULL, AV_LOG_WARNING, "-map_meta_data is deprecated and will be removed soon. "
                      "Use -map_metadata instead.\n");
 -    return opt_map_metadata(opt, arg);
 +    return opt_map_metadata(o, opt, arg);
  }
  
 -static int opt_map_chapters(const char *opt, const char *arg)
 +static int opt_recording_timestamp(OptionsContext *o, const char *opt, const char *arg)
  {
 -    ChapterMap *c;
 -    char *p;
 -
 -    chapter_maps = grow_array(chapter_maps, sizeof(*chapter_maps), &nb_chapter_maps,
 -                              nb_chapter_maps + 1);
 -    c = &chapter_maps[nb_chapter_maps - 1];
 -    c->out_file = strtol(arg, &p, 0);
 -    if (*p)
 -        p++;
 +    char buf[128];
 +    int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
 +    struct tm time = *gmtime((time_t*)&recording_timestamp);
 +    strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
 +    parse_option(o, "metadata", buf, options);
  
 -    c->in_file = strtol(p, &p, 0);
 +    av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
 +                                 "tag instead.\n", opt);
      return 0;
  }
  
 -static int opt_input_ts_scale(const char *opt, const char *arg)
 +static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder)
  {
 -    unsigned int stream;
 -    double scale;
 -    char *p;
 -
 -    stream = strtol(arg, &p, 0);
 -    if (*p)
 -        p++;
 -    scale= strtod(p, &p);
 +    const char *codec_string = encoder ? "encoder" : "decoder";
 +    AVCodec *codec;
  
 -    ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1);
 -    ts_scale[stream] = scale;
 -    return 0;
 +    codec = encoder ?
 +        avcodec_find_encoder_by_name(name) :
 +        avcodec_find_decoder_by_name(name);
 +    if(!codec) {
 +        av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name);
 +        exit_program(1);
 +    }
 +    if(codec->type != type) {
 +        av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
 +        exit_program(1);
 +    }
 +    return codec;
  }
  
 -static int opt_recording_time(const char *opt, const char *arg)
 +static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st)
  {
 -    recording_time = parse_time_or_die(opt, arg, 1);
 -    return 0;
 -}
 +    char *codec_name = NULL;
  
 -static int opt_start_time(const char *opt, const char *arg)
 -{
 -    start_time = parse_time_or_die(opt, arg, 1);
 -    return 0;
 +    MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
 +    if (codec_name) {
 +        AVCodec *codec = find_codec_or_die(codec_name, st->codec->codec_type, 0);
 +        st->codec->codec_id = codec->id;
 +        return codec;
 +    } else
 +        return avcodec_find_decoder(st->codec->codec_id);
  }
  
 -static int opt_recording_timestamp(const char *opt, const char *arg)
 +/**
 + * Add all the streams from the given input file to the global
 + * list of input streams.
 + */
 +static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
  {
 -    char buf[128];
 -    int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
 -    struct tm time = *gmtime((time_t*)&recording_timestamp);
 -    strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
 -    opt_metadata("metadata", buf);
 +    int i, rfps, rfps_base;
 +    char *next, *codec_tag = NULL;
  
 -    av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
 -                                 "tag instead.\n", opt);
 -    return 0;
 +    for (i = 0; i < ic->nb_streams; i++) {
 +        AVStream *st = ic->streams[i];
 +        AVCodecContext *dec = st->codec;
 +        InputStream *ist;
 +
 +        input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
 +        ist = &input_streams[nb_input_streams - 1];
 +        ist->st = st;
 +        ist->file_index = nb_input_files;
 +        ist->discard = 1;
 +        ist->opts = filter_codec_opts(codec_opts, choose_decoder(o, ic, st), ic, st);
 +
 +        ist->ts_scale = 1.0;
 +        MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
 +
 +        MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
 +        if (codec_tag) {
 +            uint32_t tag = strtol(codec_tag, &next, 0);
 +            if (*next)
 +                tag = AV_RL32(codec_tag);
 +            st->codec->codec_tag = tag;
 +        }
 +
 +        ist->dec = choose_decoder(o, ic, st);
 +
 +        switch (dec->codec_type) {
 +        case AVMEDIA_TYPE_AUDIO:
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            if(o->audio_disable)
 +                st->discard= AVDISCARD_ALL;
 +            break;
 +        case AVMEDIA_TYPE_VIDEO:
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            rfps      = ic->streams[i]->r_frame_rate.num;
 +            rfps_base = ic->streams[i]->r_frame_rate.den;
 +            if (dec->lowres) {
 +                dec->flags |= CODEC_FLAG_EMU_EDGE;
 +            }
 +
 +            if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
 +
 +                av_log(NULL, AV_LOG_INFO,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
 +                       i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
 +                       (float)rfps / rfps_base, rfps, rfps_base);
 +            }
 +
 +            if (o->video_disable)
 +                st->discard= AVDISCARD_ALL;
 +            else if(video_discard)
 +                st->discard= video_discard;
 +            break;
 +        case AVMEDIA_TYPE_DATA:
 +            if (o->data_disable)
 +                st->discard= AVDISCARD_ALL;
 +            break;
 +        case AVMEDIA_TYPE_SUBTITLE:
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            if(o->subtitle_disable)
 +                st->discard = AVDISCARD_ALL;
 +            break;
 +        case AVMEDIA_TYPE_ATTACHMENT:
 +        case AVMEDIA_TYPE_UNKNOWN:
 +            break;
 +        default:
 +            abort();
 +        }
 +    }
  }
  
 -static int opt_input_ts_offset(const char *opt, const char *arg)
 +static void assert_file_overwrite(const char *filename)
  {
 -    input_ts_offset = parse_time_or_die(opt, arg, 1);
 -    return 0;
 +    if ((!file_overwrite || no_file_overwrite) &&
 +        (strchr(filename, ':') == NULL || filename[1] == ':' ||
 +         av_strstart(filename, "file:", NULL))) {
 +        if (avio_check(filename, 0) == 0) {
 +            if (!using_stdin && (!no_file_overwrite || file_overwrite)) {
 +                fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
 +                fflush(stderr);
 +                term_exit();
 +                if (!read_yesno()) {
 +                    av_log(0, AV_LOG_FATAL, "Not overwriting - exiting\n");
 +                    exit_program(1);
 +                }
 +                term_init();
 +            }
 +            else {
 +                av_log(0, AV_LOG_FATAL, "File '%s' already exists. Exiting.\n", filename);
 +                exit_program(1);
 +            }
 +        }
 +    }
  }
  
 -static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
 +static void dump_attachment(AVStream *st, const char *filename)
  {
 -    const char *codec_string = encoder ? "encoder" : "decoder";
 -    AVCodec *codec;
 +    int ret;
 +    AVIOContext *out = NULL;
 +    AVDictionaryEntry *e;
  
 -    if(!name)
 -        return CODEC_ID_NONE;
 -    codec = encoder ?
 -        avcodec_find_encoder_by_name(name) :
 -        avcodec_find_decoder_by_name(name);
 -    if(!codec) {
 -        fprintf(stderr, "Unknown %s '%s'\n", codec_string, name);
 +    if (!st->codec->extradata_size) {
 +        av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n",
 +               nb_input_files - 1, st->index);
 +        return;
 +    }
 +    if (!*filename && (e = av_dict_get(st->metadata, "filename", NULL, 0)))
 +        filename = e->value;
 +    if (!*filename) {
 +        av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag"
 +               "in stream #%d:%d.\n", nb_input_files - 1, st->index);
          exit_program(1);
      }
 -    if(codec->type != type) {
 -        fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name);
 +
 +    assert_file_overwrite(filename);
 +
 +    if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) {
 +        av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n",
 +               filename);
          exit_program(1);
      }
 -    return codec->id;
 +
 +    avio_write(out, st->codec->extradata, st->codec->extradata_size);
 +    avio_flush(out);
 +    avio_close(out);
  }
  
 -static int opt_input_file(const char *opt, const char *filename)
 +static int opt_input_file(OptionsContext *o, const char *opt, const char *filename)
  {
      AVFormatContext *ic;
      AVInputFormat *file_iformat = NULL;
 -    int err, i, ret, rfps, rfps_base;
 +    int err, i, ret;
      int64_t timestamp;
      uint8_t buf[128];
      AVDictionary **opts;
      int orig_nb_streams;                     // number of streams before avformat_find_stream_info
  
 -    if (last_asked_format) {
 -        if (!(file_iformat = av_find_input_format(last_asked_format))) {
 -            fprintf(stderr, "Unknown input format: '%s'\n", last_asked_format);
 +    if (o->format) {
 +        if (!(file_iformat = av_find_input_format(o->format))) {
 +            av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format);
              exit_program(1);
          }
 -        last_asked_format = NULL;
      }
  
      if (!strcmp(filename, "-"))
          print_error(filename, AVERROR(ENOMEM));
          exit_program(1);
      }
 -    if (audio_sample_rate) {
 -        snprintf(buf, sizeof(buf), "%d", audio_sample_rate);
 +    if (o->nb_audio_sample_rate) {
 +        snprintf(buf, sizeof(buf), "%d", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i);
          av_dict_set(&format_opts, "sample_rate", buf, 0);
      }
 -    if (audio_channels) {
 -        snprintf(buf, sizeof(buf), "%d", audio_channels);
 +    if (o->nb_audio_channels) {
 +        snprintf(buf, sizeof(buf), "%d", o->audio_channels[o->nb_audio_channels - 1].u.i);
          av_dict_set(&format_opts, "channels", buf, 0);
      }
 -    if (frame_rate.num) {
 -        snprintf(buf, sizeof(buf), "%d/%d", frame_rate.num, frame_rate.den);
 -        av_dict_set(&format_opts, "framerate", buf, 0);
 +    if (o->nb_frame_rates) {
 +        av_dict_set(&format_opts, "framerate", o->frame_rates[o->nb_frame_rates - 1].u.str, 0);
      }
 -    if (frame_width && frame_height) {
 -        snprintf(buf, sizeof(buf), "%dx%d", frame_width, frame_height);
 -        av_dict_set(&format_opts, "video_size", buf, 0);
 +    if (o->nb_frame_sizes) {
 +        av_dict_set(&format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0);
 +    }
 +    if (o->nb_frame_pix_fmts)
 +        av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
 +
 +    ic->video_codec_id   = video_codec_name ?
 +        find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0)->id : CODEC_ID_NONE;
 +    ic->audio_codec_id   = audio_codec_name ?
 +        find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0)->id : CODEC_ID_NONE;
 +    ic->subtitle_codec_id= subtitle_codec_name ?
 +        find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : CODEC_ID_NONE;
 +    ic->flags |= AVFMT_FLAG_NONBLOCK;
 +    ic->interrupt_callback = int_cb;
 +
 +    if (loop_input) {
 +        av_log(NULL, AV_LOG_WARNING, "-loop_input is deprecated, use -loop 1\n");
 +        ic->loop_input = loop_input;
      }
 -    if (frame_pix_fmt != PIX_FMT_NONE)
 -        av_dict_set(&format_opts, "pixel_format", av_get_pix_fmt_name(frame_pix_fmt), 0);
 -
 -    ic->video_codec_id   =
 -        find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0);
 -    ic->audio_codec_id   =
 -        find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0);
 -    ic->subtitle_codec_id=
 -        find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
 -    ic->flags |= AVFMT_FLAG_NONBLOCK;
  
      /* open the input file with generic libav function */
      err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
      }
      assert_avoptions(format_opts);
  
 -    if(opt_programid) {
 -        int i, j;
 -        int found=0;
 -        for(i=0; i<ic->nb_streams; i++){
 -            ic->streams[i]->discard= AVDISCARD_ALL;
 -        }
 -        for(i=0; i<ic->nb_programs; i++){
 -            AVProgram *p= ic->programs[i];
 -            if(p->id != opt_programid){
 -                p->discard = AVDISCARD_ALL;
 -            }else{
 -                found=1;
 -                for(j=0; j<p->nb_stream_indexes; j++){
 -                    ic->streams[p->stream_index[j]]->discard= AVDISCARD_DEFAULT;
 -                }
 -            }
 -        }
 -        if(!found){
 -            fprintf(stderr, "Specified program id not found\n");
 -            exit_program(1);
 -        }
 -        opt_programid=0;
 -    }
 -
 -    if (loop_input) {
 -        av_log(NULL, AV_LOG_WARNING, "-loop_input is deprecated, use -loop 1\n");
 -        ic->loop_input = loop_input;
 -    }
 +    /* apply forced codec ids */
 +    for (i = 0; i < ic->nb_streams; i++)
 +        choose_decoder(o, ic, ic->streams[i]);
  
      /* Set AVCodecContext options for avformat_find_stream_info */
      opts = setup_find_stream_info_opts(ic, codec_opts);
      /* If not enough info to get the stream parameters, we decode the
         first frames to get it. (used in mpeg case for example) */
      ret = avformat_find_stream_info(ic, opts);
 -    if (ret < 0 && verbose >= 0) {
 -        fprintf(stderr, "%s: could not find codec parameters\n", filename);
 +    if (ret < 0) {
 +        av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
          av_close_input_file(ic);
          exit_program(1);
      }
  
 -    timestamp = start_time;
 +    timestamp = o->start_time;
      /* add the stream start time */
      if (ic->start_time != AV_NOPTS_VALUE)
          timestamp += ic->start_time;
  
      /* if seeking requested, we execute it */
 -    if (start_time != 0) {
 +    if (o->start_time != 0) {
          ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
          if (ret < 0) {
 -            fprintf(stderr, "%s: could not seek to position %0.3f\n",
 -                    filename, (double)timestamp / AV_TIME_BASE);
 +            av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
 +                   filename, (double)timestamp / AV_TIME_BASE);
          }
 -        /* reset seek info */
 -        start_time = 0;
      }
  
      /* update the current parameters so that they match the one of the input stream */
 -    for(i=0;i<ic->nb_streams;i++) {
 -        AVStream *st = ic->streams[i];
 -        AVCodecContext *dec = st->codec;
 -        InputStream *ist;
 -
 -        dec->thread_count = thread_count;
 -
 -        input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
 -        ist = &input_streams[nb_input_streams - 1];
 -        ist->st = st;
 -        ist->file_index = nb_input_files;
 -        ist->discard = 1;
 -        ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
 -
 -        if (i < nb_ts_scale)
 -            ist->ts_scale = ts_scale[i];
 -
 -        switch (dec->codec_type) {
 -        case AVMEDIA_TYPE_AUDIO:
 -            ist->dec = avcodec_find_decoder_by_name(audio_codec_name);
 -            if(audio_disable)
 -                st->discard= AVDISCARD_ALL;
 -            break;
 -        case AVMEDIA_TYPE_VIDEO:
 -            ist->dec = avcodec_find_decoder_by_name(video_codec_name);
 -            rfps      = ic->streams[i]->r_frame_rate.num;
 -            rfps_base = ic->streams[i]->r_frame_rate.den;
 -            if (dec->lowres) {
 -                dec->flags |= CODEC_FLAG_EMU_EDGE;
 -                dec->height >>= dec->lowres;
 -                dec->width  >>= dec->lowres;
 -            }
 -            if(me_threshold)
 -                dec->debug |= FF_DEBUG_MV;
 -
 -            if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
 -
 -                if (verbose >= 0)
 -                    fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
 -                            i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
 -
 -                    (float)rfps / rfps_base, rfps, rfps_base);
 -            }
 -
 -            if(video_disable)
 -                st->discard= AVDISCARD_ALL;
 -            else if(video_discard)
 -                st->discard= video_discard;
 -            break;
 -        case AVMEDIA_TYPE_DATA:
 -            break;
 -        case AVMEDIA_TYPE_SUBTITLE:
 -            ist->dec = avcodec_find_decoder_by_name(subtitle_codec_name);
 -            if(subtitle_disable)
 -                st->discard = AVDISCARD_ALL;
 -            break;
 -        case AVMEDIA_TYPE_ATTACHMENT:
 -        case AVMEDIA_TYPE_UNKNOWN:
 -            break;
 -        default:
 -            abort();
 -        }
 -    }
 +    add_input_streams(o, ic);
  
      /* dump the file content */
 -    if (verbose >= 0)
 -        av_dump_format(ic, nb_input_files, filename, 0);
 +    av_dump_format(ic, nb_input_files, filename, 0);
  
      input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1);
      input_files[nb_input_files - 1].ctx        = ic;
      input_files[nb_input_files - 1].ist_index  = nb_input_streams - ic->nb_streams;
 -    input_files[nb_input_files - 1].ts_offset  = input_ts_offset - (copy_ts ? 0 : timestamp);
 +    input_files[nb_input_files - 1].ts_offset  = o->input_ts_offset - (copy_ts ? 0 : timestamp);
      input_files[nb_input_files - 1].nb_streams = ic->nb_streams;
 +    input_files[nb_input_files - 1].rate_emu   = o->rate_emu;
 +
 +    for (i = 0; i < o->nb_dump_attachment; i++) {
 +        int j;
 +
 +        for (j = 0; j < ic->nb_streams; j++) {
 +            AVStream *st = ic->streams[j];
  
 -    frame_rate    = (AVRational){0, 0};
 -    frame_pix_fmt = PIX_FMT_NONE;
 -    frame_height = 0;
 -    frame_width  = 0;
 -    audio_sample_rate = 0;
 -    audio_channels    = 0;
 -    audio_sample_fmt  = AV_SAMPLE_FMT_NONE;
 -    av_freep(&ts_scale);
 -    nb_ts_scale = 0;
 +            if (check_stream_specifier(ic, st, o->dump_attachment[i].specifier) == 1)
 +                dump_attachment(st, o->dump_attachment[i].u.str);
 +        }
 +    }
  
      for (i = 0; i < orig_nb_streams; i++)
          av_dict_free(&opts[i]);
      av_freep(&opts);
 -    av_freep(&video_codec_name);
 -    av_freep(&audio_codec_name);
 -    av_freep(&subtitle_codec_name);
 -    uninit_opts();
 -    init_opts();
 +
 +    reset_options(o, 1);
      return 0;
  }
  
 -static void check_inputs(int *has_video_ptr,
 -                         int *has_audio_ptr,
 -                         int *has_subtitle_ptr,
 -                         int *has_data_ptr)
 +static void parse_forced_key_frames(char *kf, OutputStream *ost)
  {
 -    int has_video, has_audio, has_subtitle, has_data, i, j;
 -    AVFormatContext *ic;
 +    char *p;
 +    int n = 1, i;
  
 -    has_video = 0;
 -    has_audio = 0;
 -    has_subtitle = 0;
 -    has_data = 0;
 +    for (p = kf; *p; p++)
 +        if (*p == ',')
 +            n++;
 +    ost->forced_kf_count = n;
 +    ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
 +    if (!ost->forced_kf_pts) {
 +        av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
 +        exit_program(1);
 +    }
 +    for (i = 0; i < n; i++) {
 +        p = i ? strchr(p, ',') + 1 : kf;
 +        ost->forced_kf_pts[i] = parse_time_or_die("force_key_frames", p, 1);
 +    }
 +}
  
 -    for(j=0;j<nb_input_files;j++) {
 -        ic = input_files[j].ctx;
 -        for(i=0;i<ic->nb_streams;i++) {
 -            AVCodecContext *enc = ic->streams[i]->codec;
 -            switch(enc->codec_type) {
 -            case AVMEDIA_TYPE_AUDIO:
 -                has_audio = 1;
 -                break;
 -            case AVMEDIA_TYPE_VIDEO:
 -                has_video = 1;
 -                break;
 -            case AVMEDIA_TYPE_SUBTITLE:
 -                has_subtitle = 1;
 -                break;
 -            case AVMEDIA_TYPE_DATA:
 -            case AVMEDIA_TYPE_ATTACHMENT:
 -            case AVMEDIA_TYPE_UNKNOWN:
 -                has_data = 1;
 -                break;
 -            default:
 -                abort();
 -            }
 +static uint8_t *get_line(AVIOContext *s)
 +{
 +    AVIOContext *line;
 +    uint8_t *buf;
 +    char c;
 +
 +    if (avio_open_dyn_buf(&line) < 0) {
 +        av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n");
 +        exit_program(1);
 +    }
 +
 +    while ((c = avio_r8(s)) && c != '\n')
 +        avio_w8(line, c);
 +    avio_w8(line, 0);
 +    avio_close_dyn_buf(line, &buf);
 +
 +    return buf;
 +}
 +
 +static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s)
 +{
 +    int i, ret = 1;
 +    char filename[1000];
 +    const char *base[3] = { getenv("AVCONV_DATADIR"),
 +                            getenv("HOME"),
 +                            AVCONV_DATADIR,
 +                            };
 +
 +    for (i = 0; i < FF_ARRAY_ELEMS(base) && ret; i++) {
 +        if (!base[i])
 +            continue;
 +        if (codec_name) {
 +            snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i],
 +                     i != 1 ? "" : "/.avconv", codec_name, preset_name);
 +            ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
 +        }
 +        if (ret) {
 +            snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
 +                     i != 1 ? "" : "/.avconv", preset_name);
 +            ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL);
          }
      }
 -    *has_video_ptr = has_video;
 -    *has_audio_ptr = has_audio;
 -    *has_subtitle_ptr = has_subtitle;
 -    *has_data_ptr = has_data;
 +    return ret;
  }
  
 -static void new_video_stream(AVFormatContext *oc, int file_idx)
 +static void choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost)
 +{
 +    char *codec_name = NULL;
 +
 +    MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, ost->st);
 +    if (!codec_name) {
 +        ost->st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename,
 +                                                  NULL, ost->st->codec->codec_type);
 +        ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
 +    } else if (!strcmp(codec_name, "copy"))
 +        ost->stream_copy = 1;
 +    else {
 +        ost->enc = find_codec_or_die(codec_name, ost->st->codec->codec_type, 1);
 +        ost->st->codec->codec_id = ost->enc->id;
 +    }
 +}
 +
 +static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type)
  {
 -    AVStream *st;
      OutputStream *ost;
 -    AVCodecContext *video_enc;
 -    enum CodecID codec_id = CODEC_ID_NONE;
 -    AVCodec *codec= NULL;
 +    AVStream *st = avformat_new_stream(oc, NULL);
 +    int idx      = oc->nb_streams - 1, ret = 0;
 +    char *bsf = NULL, *next, *codec_tag = NULL;
 +    AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL;
 +    double qscale = -1;
 +    char *buf = NULL, *arg = NULL, *preset = NULL;
 +    AVIOContext *s = NULL;
  
 -    if(!video_stream_copy){
 -        if (video_codec_name) {
 -            codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1);
 -            codec = avcodec_find_encoder_by_name(video_codec_name);
 -        } else {
 -            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
 -            codec = avcodec_find_encoder(codec_id);
 -        }
 +    if (!st) {
 +        av_log(NULL, AV_LOG_FATAL, "Could not alloc stream.\n");
 +        exit_program(1);
      }
  
 -    ost = new_output_stream(oc, file_idx, codec);
 -    st  = ost->st;
 -    if (!video_stream_copy) {
 -        ost->frame_aspect_ratio = frame_aspect_ratio;
 -        frame_aspect_ratio = 0;
 -#if CONFIG_AVFILTER
 -        ost->avfilter= vfilters;
 -        vfilters = NULL;
 -#endif
 +    if (oc->nb_streams - 1 < o->nb_streamid_map)
 +        st->id = o->streamid_map[oc->nb_streams - 1];
 +
 +    output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams,
 +                                nb_output_streams + 1);
 +    ost = &output_streams[nb_output_streams - 1];
 +    ost->file_index = nb_output_files;
 +    ost->index = idx;
 +    ost->st    = st;
 +    st->codec->codec_type = type;
 +    choose_encoder(o, oc, ost);
 +    if (ost->enc) {
 +        ost->opts  = filter_codec_opts(codec_opts, ost->enc, oc, st);
 +    }
 +
 +    avcodec_get_context_defaults3(st->codec, ost->enc);
 +    st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
 +
 +    MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
 +    if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) {
 +        do  {
 +            buf = get_line(s);
 +            if (!buf[0] || buf[0] == '#') {
 +                av_free(buf);
 +                continue;
 +            }
 +            if (!(arg = strchr(buf, '='))) {
 +                av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
 +                exit_program(1);
 +            }
 +            *arg++ = 0;
 +            av_dict_set(&ost->opts, buf, arg, AV_DICT_DONT_OVERWRITE);
 +            av_free(buf);
 +        } while (!s->eof_reached);
 +        avio_close(s);
 +    }
 +    if (ret) {
 +        av_log(NULL, AV_LOG_FATAL,
 +               "Preset %s specified for stream %d:%d, but could not be opened.\n",
 +               preset, ost->file_index, ost->index);
 +        exit_program(1);
      }
  
 -    ost->bitstream_filters = video_bitstream_filters;
 -    video_bitstream_filters= NULL;
 +    ost->max_frames = INT64_MAX;
 +    MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st);
  
 -    st->codec->thread_count= thread_count;
 +    MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st);
 +    while (bsf) {
 +        if (next = strchr(bsf, ','))
 +            *next++ = 0;
 +        if (!(bsfc = av_bitstream_filter_init(bsf))) {
 +            av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf);
 +            exit_program(1);
 +        }
 +        if (bsfc_prev)
 +            bsfc_prev->next = bsfc;
 +        else
 +            ost->bitstream_filters = bsfc;
  
 -    video_enc = st->codec;
 +        bsfc_prev = bsfc;
 +        bsf       = next;
 +    }
  
 -    if(video_codec_tag)
 -        video_enc->codec_tag= video_codec_tag;
 +    MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st);
 +    if (codec_tag) {
 +        uint32_t tag = strtol(codec_tag, &next, 0);
 +        if (*next)
 +            tag = AV_RL32(codec_tag);
 +        st->codec->codec_tag = tag;
 +    }
  
 -    if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
 -        video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
 +    MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st);
 +    if (qscale >= 0 || same_quant) {
 +        st->codec->flags |= CODEC_FLAG_QSCALE;
 +        st->codec->global_quality = FF_QP2LAMBDA * qscale;
      }
  
 -    video_enc->codec_type = AVMEDIA_TYPE_VIDEO;
 -    if (video_stream_copy) {
 -        st->stream_copy = 1;
 -        video_enc->sample_aspect_ratio =
 -        st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
 -    } else {
 -        const char *p;
 +    if (oc->oformat->flags & AVFMT_GLOBALHEADER)
 +        st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
 +