Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 26 Oct 2011 00:09:31 +0000 (02:09 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 26 Oct 2011 00:36:07 +0000 (02:36 +0200)
* qatar/master: (22 commits)
  g722dec: check output buffer size before decoding
  g722dec: cosmetics: reindent/linewrap
  g722dec: remove the use of lowres for half-rate decoding.
  tta: check for extradata allocation failure in tta demuxer
  tta: check for allocation failure of decode_buffer
  tta: use correct frame_length calculation.
  tta: add support for decoding 24-bit sample format
  cosmetics: indentation
  tta: remove pointless braces
  tta: check output buffer size after adjusting frame length for last frame
  tta: fix reading of format in TTA header.
  tta: remove useless commented-out lines
  tta: check remaining bitstream size while reading unary value
  lavf: deprecate AVStream.stream_copy
  avconc: split choose_codec() to choose_decoder/choose_encoder.
  lavf: simplify by using FFMAX/FFMIN.
  mpegenc: add preload private option.
  cosmetics: simplify latm_decode_init
  latm: avoid unnecessary reinit of the aac decoder
  aacdec: initialize sbr context only in new channel elements
  ...

Conflicts:
avconv.c
libavcodec/resample.c
libavcodec/tta.c
libavformat/utils.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
avconv.c
ffmpeg.c
libavcodec/aacdec.c
libavcodec/resample.c
libavcodec/tta.c
libavformat/avformat.h
libavformat/mpegenc.c
libavformat/tta.c
libavformat/utils.c
libavformat/version.h

diff --cc avconv.c
+++ b/avconv.c
@@@ -243,13 -227,9 +243,14 @@@ typedef struct OutputStream 
     int64_t sws_flags;
     AVDictionary *opts;
     int is_past_recording_time;
+    int stream_copy;
  } OutputStream;
  
 +#if HAVE_TERMIOS_H
 +
 +/* init terminal so that we can grab keys */
 +static struct termios oldtty;
 +#endif
  
  typedef struct OutputFile {
      AVFormatContext *ctx;
@@@ -3516,13 -3394,12 +3517,13 @@@ static int read_ffserver_streams(Option
  
          // 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 && !st->stream_copy)
+         if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
              choose_sample_fmt(st, codec);
-         else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st->stream_copy)
+         else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
              choose_pixel_fmt(st, codec);
      }
  
@@@ -3678,8 -3571,13 +3679,12 @@@ static void opt_output_file(void *optct
          }
      }
  
-     oc->preload   = (int)(o->mux_preload   * AV_TIME_BASE);
+     if (o->mux_preload) {
+         uint8_t buf[64];
+         snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
+         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) {
diff --cc ffmpeg.c
+++ b/ffmpeg.c
@@@ -248,177 -290,46 +248,177 @@@ typedef struct OutputStream 
      AVFilterGraph *graph;
  #endif
  
 -   int sws_flags;
 +   int64_t sws_flags;
     AVDictionary *opts;
 +   int is_past_recording_time;
++   int stream_copy;
  } 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;
  
-     o->mux_preload    = 0.5;
 +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;
 +
 +    /* output options */
 +    StreamMap *stream_maps;
 +    int     nb_stream_maps;
 +    /* first item specifies output metadata, second is input */
 +    MetadataMap (*meta_data_maps)[2];
 +    int nb_meta_data_maps;
 +    int metadata_global_manual;
 +    int metadata_streams_manual;
 +    int metadata_chapters_manual;
 +
 +    int chapters_input_file;
 +
 +    int64_t recording_time;
 +    uint64_t limit_filesize;
 +    float mux_preload;
 +    float mux_max_delay;
 +
 +    int video_disable;
 +    int audio_disable;
 +    int subtitle_disable;
 +    int data_disable;
 +
 +    /* indexed by output file stream index */
 +    int   *streamid_map;
 +    int nb_streamid_map;
 +
 +    SpecifierOpt *metadata;
 +    int        nb_metadata;
 +    SpecifierOpt *max_frames;
 +    int        nb_max_frames;
 +    SpecifierOpt *bitstream_filters;
 +    int        nb_bitstream_filters;
 +    SpecifierOpt *codec_tags;
 +    int        nb_codec_tags;
 +    SpecifierOpt *sample_fmts;
 +    int        nb_sample_fmts;
 +    SpecifierOpt *qscale;
 +    int        nb_qscale;
 +    SpecifierOpt *forced_key_frames;
 +    int        nb_forced_key_frames;
 +    SpecifierOpt *force_fps;
 +    int        nb_force_fps;
 +    SpecifierOpt *frame_aspect_ratios;
 +    int        nb_frame_aspect_ratios;
 +    SpecifierOpt *rc_overrides;
 +    int        nb_rc_overrides;
 +    SpecifierOpt *intra_matrices;
 +    int        nb_intra_matrices;
 +    SpecifierOpt *inter_matrices;
 +    int        nb_inter_matrices;
 +    SpecifierOpt *top_field_first;
 +    int        nb_top_field_first;
 +    SpecifierOpt *presets;
 +    int        nb_presets;
 +#if CONFIG_AVFILTER
 +    SpecifierOpt *filters;
 +    int        nb_filters;
 +#endif
 +} OptionsContext;
 +
 +#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
 +{\
 +    int i, ret;\
 +    for (i = 0; i < o->nb_ ## name; i++) {\
 +        char *spec = o->name[i].specifier;\
 +        if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\
 +            outvar = o->name[i].u.type;\
 +        else if (ret < 0)\
 +            exit_program(1);\
 +    }\
 +}
 +
 +static void reset_options(OptionsContext *o, int is_input)
 +{
 +    const OptionDef *po = options;
 +    OptionsContext bak= *o;
 +
 +    /* all OPT_SPEC and OPT_STRING can be freed in generic way */
 +    while (po->name) {
 +        void *dst = (uint8_t*)o + po->u.off;
 +
 +        if (po->flags & OPT_SPEC) {
 +            SpecifierOpt **so = dst;
 +            int i, *count = (int*)(so + 1);
 +            for (i = 0; i < *count; i++) {
 +                av_freep(&(*so)[i].specifier);
 +                if (po->flags & OPT_STRING)
 +                    av_freep(&(*so)[i].u.str);
 +            }
 +            av_freep(so);
 +            *count = 0;
 +        } else if (po->flags & OPT_OFFSET && po->flags & OPT_STRING)
 +            av_freep(dst);
 +        po++;
 +    }
 +
 +    av_freep(&o->stream_maps);
 +    av_freep(&o->meta_data_maps);
 +    av_freep(&o->streamid_map);
 +
 +    memset(o, 0, sizeof(*o));
 +
 +    if(is_input) o->recording_time = bak.recording_time;
 +    else         o->recording_time = INT64_MAX;
 +    o->mux_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)
@@@ -1412,9 -1356,10 +1412,9 @@@ static void print_report(OutputFile *ou
      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);
@@@ -2066,12 -2083,11 +2066,12 @@@ static int transcode_init(OutputFile *o
          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;
              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;
 +                if (!ost->fifo) {
 +                    return AVERROR(ENOMEM);
                  }
-                 if (!codec->sample_rate) {
++                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)
      }
  
      /* 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];
 +        av_log(NULL, AV_LOG_INFO, "  Stream #%d.%d -> #%d.%d",
 +               input_streams[ost->source_index].file_index,
 +               input_streams[ost->source_index].st->index,
 +               ost->file_index,
 +               ost->index);
 +        if (ost->sync_ist != &input_streams[ost->source_index])
 +            av_log(NULL, AV_LOG_INFO, " [sync #%d.%d]",
 +                   ost->sync_ist->file_index,
 +                   ost->sync_ist->st->index);
-         if (ost->st->stream_copy)
++        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) {
@@@ -2695,13 -2706,12 +2694,13 @@@ static int transcode(OutputFile *output
  
   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);
@@@ -2944,13 -3104,19 +2943,11 @@@ static int opt_recording_timestamp(Opti
      return 0;
  }
  
- static enum CodecID find_codec_or_die(const char *name, enum AVMediaType type, int encoder)
 -static int opt_input_ts_offset(const char *opt, const char *arg)
 -{
 -    input_ts_offset = parse_time_or_die(opt, arg, 1);
 -    return 0;
 -}
 -
 -static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
++static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder)
  {
      const char *codec_string = encoder ? "encoder" : "decoder";
      AVCodec *codec;
  
--    if(!name)
--        return CODEC_ID_NONE;
      codec = encoder ?
          avcodec_find_encoder_by_name(name) :
          avcodec_find_decoder_by_name(name);
          exit_program(1);
      }
      if(codec->type != type) {
 -        fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name);
 +        av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name);
          exit_program(1);
      }
--    return codec->id;
++    return codec;
 +}
 +
- static AVCodec *choose_codec(OptionsContext *o, AVFormatContext *s, AVStream *st, enum AVMediaType type)
++static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st)
 +{
 +    char *codec_name = NULL;
 +
 +    MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st);
-     if (!codec_name) {
-         if (s->oformat) {
-             st->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename, NULL, type);
-             return avcodec_find_encoder(st->codec->codec_id);
-         }
-     } else if (!strcmp(codec_name, "copy"))
-         st->stream_copy = 1;
-     else {
-         st->codec->codec_id = find_codec_or_die(codec_name, type, s->iformat == NULL);
-         return s->oformat ? avcodec_find_encoder_by_name(codec_name) :
-                             avcodec_find_decoder_by_name(codec_name);
-     }
-     return NULL;
++    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);
 +}
 +
 +/**
 + * 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)
 +{
 +    int i, rfps, rfps_base;
 +    char *next, *codec_tag = NULL;
 +
 +    for (i = 0; i < ic->nb_streams; i++) {
 +        AVStream *st = ic->streams[i];
 +        AVCodecContext *dec = st->codec;
 +        InputStream *ist;
 +        double scale = 1.0;
 +
 +        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);
 +
 +        MATCH_PER_STREAM_OPT(ts_scale, dbl, scale, ic, st);
 +        ist->ts_scale = scale;
 +
 +        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_codec(o, ic, st, dec->codec_type);
-         if (!ist->dec)
-             ist->dec = avcodec_find_decoder(dec->codec_id);
++        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:
 +            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_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;
          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 (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);
 +    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   =
-         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->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;
  
 +    if (loop_input) {
 +        av_log(NULL, AV_LOG_WARNING, "-loop_input is deprecated, use -loop 1\n");
 +        ic->loop_input = loop_input;
 +    }
 +
      /* open the input file with generic libav function */
      err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
      if (err < 0) {
      }
      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_codec(o, ic, ic->streams[i], ic->streams[i]->codec->codec_type);
++        choose_decoder(o, ic, ic->streams[i]);
  
      /* Set AVCodecContext options for avformat_find_stream_info */
      opts = setup_find_stream_info_opts(ic, codec_opts);
      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_open(s, filename, AVIO_FLAG_READ);
 +        }
 +        if (ret) {
 +            snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
 +                     i != 1 ? "" : "/.avconv", preset_name);
 +            ret = avio_open(s, filename, AVIO_FLAG_READ);
          }
      }
 -    *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;
 +    int64_t max_frames = INT64_MAX;
 +    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);
 +    }
 +
 +    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;
-     ost->enc = choose_codec(o, oc, st, type);
++    choose_encoder(o, oc, ost);
 +    if (ost->enc) {
 +        ost->opts  = filter_codec_opts(codec_opts, ost->enc->id, 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);
 +    }
 +
 +    MATCH_PER_STREAM_OPT(max_frames, i64, max_frames, oc, st);
 +    ost->max_frames = max_frames;
 +
 +    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;
 +
 +        bsfc_prev = bsfc;
 +        bsf       = next;
      }
  
 -    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
 +    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;
      }
  
 -    ost->bitstream_filters = video_bitstream_filters;
 -    video_bitstream_filters= NULL;
 +    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;
 +    }
  
 -    st->codec->thread_count= thread_count;
 +    if (oc->oformat->flags & AVFMT_GLOBALHEADER)
 +        st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  
 +    av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags);
 +    return ost;
 +}
 +
 +static void parse_matrix_coeffs(uint16_t *dest, const char *str)
 +{
 +    int i;
 +    const char *p = str;
 +    for(i = 0;; i++) {
 +        dest[i] = atoi(p);
 +        if(i == 63)
 +            break;
 +        p = strchr(p, ',');
 +        if(!p) {
 +            av_log(NULL, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
 +            exit_program(1);
 +        }
 +        p++;
 +    }
 +}
 +
 +static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
 +{
 +    AVStream *st;
 +    OutputStream *ost;
 +    AVCodecContext *video_enc;
 +
 +    ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO);
 +    st  = ost->st;
      video_enc = st->codec;
  
-     if (!st->stream_copy) {
 -    if(video_codec_tag)
 -        video_enc->codec_tag= video_codec_tag;
++    if (!ost->stream_copy) {
 +        const char *p = NULL;
 +        char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL;
 +        char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
 +        char *intra_matrix = NULL, *inter_matrix = NULL, *filters = NULL;
 +        int i, force_fps = 0, top_field_first = -1;
  
 -    if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
 -        video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
 -    }
 +        MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
 +        if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) {
 +            av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
 +            exit_program(1);
 +        }
  
 -    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;
 -        int i;
 +        MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st);
 +        if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) {
 +            av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size);
 +            exit_program(1);
 +        }
  
 -        if (frame_rate.num)
 -            ost->frame_rate = frame_rate;
 -        video_enc->codec_id = codec_id;
 +        MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
 +        if (frame_aspect_ratio)
 +            ost->frame_aspect_ratio = parse_frame_aspect_ratio(frame_aspect_ratio);
  
 -        video_enc->width = frame_width;
 -        video_enc->height = frame_height;
 -        video_enc->pix_fmt = frame_pix_fmt;
 +        video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
 +        MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
 +        if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == PIX_FMT_NONE) {
 +            av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt);
 +            exit_program(1);
 +        }
          st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
  
          if (intra_only)
@@@ -3502,50 -3547,76 +3505,48 @@@ static OutputStream *new_audio_stream(O
      audio_enc = st->codec;
      audio_enc->codec_type = AVMEDIA_TYPE_AUDIO;
  
-     if (!st->stream_copy) {
 -    if(audio_codec_tag)
 -        audio_enc->codec_tag= audio_codec_tag;
++    if (!ost->stream_copy) {
 +        char *sample_fmt = NULL;
  
 -    if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
 -        audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
 -    }
 -    if (audio_stream_copy) {
 -        st->stream_copy = 1;
 -    } else {
 -        audio_enc->codec_id = codec_id;
 +        MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
  
 -        if (audio_qscale > QSCALE_NONE) {
 -            audio_enc->flags |= CODEC_FLAG_QSCALE;
 -            audio_enc->global_quality = FF_QP2LAMBDA * audio_qscale;
 +        MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
 +        if (sample_fmt &&
 +            (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) {
 +            av_log(NULL, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt);
 +            exit_program(1);
          }
 -        if (audio_channels)
 -            audio_enc->channels = audio_channels;
 -        if (audio_sample_fmt != AV_SAMPLE_FMT_NONE)
 -            audio_enc->sample_fmt = audio_sample_fmt;
 -        if (audio_sample_rate)
 -            audio_enc->sample_rate = audio_sample_rate;
 -    }
 -    if (audio_language) {
 -        av_dict_set(&st->metadata, "language", audio_language, 0);
 -        av_freep(&audio_language);
 +
 +        MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
 +
 +        ost->rematrix_volume=1.0;
 +        MATCH_PER_STREAM_OPT(rematrix_volume, f, ost->rematrix_volume, oc, st);
      }
  
 -    /* reset some key parameters */
 -    audio_disable = 0;
 -    av_freep(&audio_codec_name);
 -    audio_stream_copy = 0;
 +    return ost;
  }
  
 -static void new_data_stream(AVFormatContext *oc, int file_idx)
 +static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc)
  {
--    AVStream *st;
      OutputStream *ost;
 -    AVCodecContext *data_enc;
  
 -    ost = new_output_stream(oc, file_idx, NULL);
 -    st  = ost->st;
 -    data_enc = st->codec;
 -    if (!data_stream_copy) {
 -        fprintf(stderr, "Data stream encoding not supported yet (only streamcopy)\n");
 +    ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA);
-     st  = ost->st;
-     if (!st->stream_copy) {
++    if (!ost->stream_copy) {
 +        av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
          exit_program(1);
      }
  
 -    data_enc->codec_type = AVMEDIA_TYPE_DATA;
 -
 -    if (data_codec_tag)
 -        data_enc->codec_tag= data_codec_tag;
 -
 -    if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
 -        data_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
 -    }
 -    if (data_stream_copy) {
 -        st->stream_copy = 1;
 -    }
 +    return ost;
 +}
  
 -    data_disable = 0;
 -    av_freep(&data_codec_name);
 -    data_stream_copy = 0;
 +static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc)
 +{
 +    OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT);
-     ost->st->stream_copy = 1;
++    ost->stream_copy = 1;
 +    return ost;
  }
  
 -static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
 +static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc)
  {
      AVStream *st;
      OutputStream *ost;
@@@ -3576,83 -3698,9 +3577,83 @@@ static int opt_streamid(OptionsContext 
          exit_program(1);
      }
      *p++ = '\0';
 -    idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, INT_MAX);
 -    streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1);
 -    streamid_map[idx] = parse_number_or_die(opt, p, 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;
 +}
 +
 +static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
 +{
 +    AVFormatContext *is = ifile->ctx;
 +    AVFormatContext *os = ofile->ctx;
 +    int i;
 +
 +    for (i = 0; i < is->nb_chapters; i++) {
 +        AVChapter *in_ch = is->chapters[i], *out_ch;
 +        int64_t ts_off   = av_rescale_q(ofile->start_time - ifile->ts_offset,
 +                                      AV_TIME_BASE_Q, in_ch->time_base);
 +        int64_t rt       = (ofile->recording_time == INT64_MAX) ? INT64_MAX :
 +                           av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base);
 +
 +
 +        if (in_ch->end < ts_off)
 +            continue;
 +        if (rt != INT64_MAX && in_ch->start > rt + ts_off)
 +            break;
 +
 +        out_ch = av_mallocz(sizeof(AVChapter));
 +        if (!out_ch)
 +            return AVERROR(ENOMEM);
 +
 +        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);
 +
 +        if (copy_metadata)
 +            av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
 +
 +        os->nb_chapters++;
 +        os->chapters = av_realloc_f(os->chapters, os->nb_chapters, sizeof(AVChapter));
 +        if (!os->chapters)
 +            return AVERROR(ENOMEM);
 +        os->chapters[os->nb_chapters - 1] = out_ch;
 +    }
 +    return 0;
 +}
 +
 +static int read_ffserver_streams(OptionsContext *o, 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(o, s, codec->type);
 +        st    = ost->st;
 +
 +        // FIXME: a more elegant solution is needed
 +        memcpy(st, ic->streams[i], sizeof(AVStream));
 +        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 && !st->stream_copy)
++        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
 +            choose_sample_fmt(st, codec);
-         else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st->stream_copy)
++        else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
 +            choose_pixel_fmt(st, codec);
 +    }
 +
 +    av_close_input_file(ic);
      return 0;
  }
  
@@@ -3812,9 -3824,8 +3813,13 @@@ static void opt_output_file(void *optct
          }
      }
  
-     oc->preload   = (int)(o->mux_preload   * AV_TIME_BASE);
 -    oc->preload= (int)(mux_preload*AV_TIME_BASE);
 -    oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
++    if (o->mux_preload) {
++        uint8_t buf[64];
++        snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
++        av_dict_set(&output_files[nb_output_files - 1].opts, "preload", buf, 0);
++    }
 +    oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
 +
      if (loop_output >= 0) {
          av_log(NULL, AV_LOG_WARNING, "-loop_output is deprecated, use -loop\n");
          oc->loop_output = loop_output;
@@@ -2521,8 -2509,9 +2523,9 @@@ static int latm_decode_frame(AVCodecCon
              *out_size = 0;
              return avpkt->size;
          } else {
-             aac_decode_close(avctx);
-             if ((err = aac_decode_init(avctx)) < 0)
+             if ((err = decode_audio_specific_config(
+                     &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.m4ac,
 -                    avctx->extradata, avctx->extradata_size)) < 0)
++                    avctx->extradata, avctx->extradata_size, 8*avctx->extradata_size)) < 0)
                  return err;
              latmctx->initialized = 1;
          }
Simple merge
@@@ -213,51 -203,43 +213,47 @@@ static av_cold int tta_decode_init(AVCo
      {
          /* signature */
          skip_bits(&s->gb, 32);
- //        if (get_bits_long(&s->gb, 32) != av_bswap32(AV_RL32("TTA1"))) {
- //            av_log(s->avctx, AV_LOG_ERROR, "Missing magic\n");
- //            return -1;
- //        }
-         s->flags = get_bits(&s->gb, 16);
-         if (s->flags != 1 && s->flags != 3)
-         {
-             av_log(s->avctx, AV_LOG_ERROR, "Invalid flags\n");
+         s->format = get_bits(&s->gb, 16);
+         if (s->format > 2) {
+             av_log(s->avctx, AV_LOG_ERROR, "Invalid format\n");
              return -1;
          }
-         s->is_float = (s->flags == FORMAT_FLOAT);
+         if (s->format == FORMAT_ENCRYPTED) {
+             av_log_missing_feature(s->avctx, "Encrypted TTA", 0);
+             return AVERROR(EINVAL);
+         }
          avctx->channels = s->channels = get_bits(&s->gb, 16);
 +        if (s->channels > 1 && s->channels < 9)
 +            avctx->channel_layout = tta_channel_layouts[s->channels-2];
          avctx->bits_per_coded_sample = get_bits(&s->gb, 16);
          s->bps = (avctx->bits_per_coded_sample + 7) / 8;
          avctx->sample_rate = get_bits_long(&s->gb, 32);
          s->data_length = get_bits_long(&s->gb, 32);
          skip_bits(&s->gb, 32); // CRC32 of header
  
-         if (s->is_float)
-         {
-             avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
-             av_log_ask_for_sample(s->avctx, "Unsupported sample format.\n");
-             return -1;
-         }
-         else switch(s->bps) {
-             case 1: avctx->sample_fmt = AV_SAMPLE_FMT_U8; break;
-             case 2: avctx->sample_fmt = AV_SAMPLE_FMT_S16; break;
-             case 3: avctx->bits_per_coded_sample = 24;
-             case 4: avctx->sample_fmt = AV_SAMPLE_FMT_S32; break;
-             default:
-                 av_log_ask_for_sample(s->avctx,
-                                       "Invalid/unsupported sample format.\n");
-                 return -1;
+         switch(s->bps) {
++        case 1: avctx->sample_fmt = AV_SAMPLE_FMT_U8; break;
+         case 2:
+             avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+             avctx->bits_per_raw_sample = 16;
+             break;
+         case 3:
+             avctx->sample_fmt = AV_SAMPLE_FMT_S32;
+             avctx->bits_per_raw_sample = 24;
+             break;
++        //case 4: avctx->sample_fmt = AV_SAMPLE_FMT_S32; break;
+         default:
+             av_log(avctx, AV_LOG_ERROR, "Invalid/unsupported sample format.\n");
+             return AVERROR_INVALIDDATA;
          }
  
-         // FIXME: horribly broken, but directly from reference source
- #define FRAME_TIME 1.04489795918367346939
-         s->frame_length = (int)(FRAME_TIME * avctx->sample_rate);
+         // prevent overflow
+         if (avctx->sample_rate > 0x7FFFFF) {
+             av_log(avctx, AV_LOG_ERROR, "sample_rate too large\n");
+             return AVERROR(EINVAL);
+         }
+         s->frame_length = 256 * avctx->sample_rate / 245;
  
          s->last_frame_length = s->data_length % s->frame_length;
          s->total_frames = s->data_length / s->frame_length +
              return -1;
          }
  
 -        if (s->bps == 2) {
 -            s->decode_buffer = av_mallocz(sizeof(int32_t)*s->frame_length*s->channels);
 -            if (!s->decode_buffer)
 -                return AVERROR(ENOMEM);
 -        }
 +        s->decode_buffer = av_mallocz(sizeof(int32_t)*s->frame_length*s->channels);
 +        if (!s->decode_buffer)
 +            return AVERROR(ENOMEM);
          s->ch_ctx = av_malloc(avctx->channels * sizeof(*s->ch_ctx));
-         if (!s->ch_ctx)
+         if (!s->ch_ctx) {
+             av_freep(&s->decode_buffer);
              return AVERROR(ENOMEM);
+         }
      } else {
          av_log(avctx, AV_LOG_ERROR, "Wrong extradata present\n");
          return -1;
@@@ -300,147 -286,130 +298,143 @@@ static int tta_decode_frame(AVCodecCont
      const uint8_t *buf = avpkt->data;
      int buf_size = avpkt->size;
      TTAContext *s = avctx->priv_data;
-     int i;
+     int i, out_size;
+     int cur_chan = 0, framelen = s->frame_length;
+     int32_t *p;
  
      init_get_bits(&s->gb, buf, buf_size*8);
-     {
-         int cur_chan = 0, framelen = s->frame_length;
-         int32_t *p;
  
-         if (*data_size < (framelen * s->channels * av_get_bits_per_sample_fmt(avctx->sample_fmt) / 8)) {
-             av_log(avctx, AV_LOG_ERROR, "Output buffer size is too small.\n");
-             return -1;
-         }
-         // FIXME: seeking
-         s->total_frames--;
-         if (!s->total_frames && s->last_frame_length)
-             framelen = s->last_frame_length;
-         // init per channel states
-         for (i = 0; i < s->channels; i++) {
-             s->ch_ctx[i].predictor = 0;
-             ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1][0], ttafilter_configs[s->bps-1][1]);
-             rice_init(&s->ch_ctx[i].rice, 10, 10);
+     // FIXME: seeking
+     s->total_frames--;
+     if (!s->total_frames && s->last_frame_length)
+         framelen = s->last_frame_length;
+     out_size = framelen * s->channels * av_get_bytes_per_sample(avctx->sample_fmt);
+     if (*data_size < out_size) {
+         av_log(avctx, AV_LOG_ERROR, "Output buffer size is too small.\n");
+         return -1;
+     }
+     // decode directly to output buffer for 24-bit sample format
+     if (s->bps == 3)
+         s->decode_buffer = data;
+     // init per channel states
+     for (i = 0; i < s->channels; i++) {
+         s->ch_ctx[i].predictor = 0;
+         ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1][0], ttafilter_configs[s->bps-1][1]);
+         rice_init(&s->ch_ctx[i].rice, 10, 10);
+     }
+     for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) {
+         int32_t *predictor = &s->ch_ctx[cur_chan].predictor;
+         TTAFilter *filter = &s->ch_ctx[cur_chan].filter;
+         TTARice *rice = &s->ch_ctx[cur_chan].rice;
+         uint32_t unary, depth, k;
+         int32_t value;
+         unary = tta_get_unary(&s->gb);
+         if (unary == 0) {
+             depth = 0;
+             k = rice->k0;
+         } else {
+             depth = 1;
+             k = rice->k1;
+             unary--;
          }
  
-         for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) {
-             int32_t *predictor = &s->ch_ctx[cur_chan].predictor;
-             TTAFilter *filter = &s->ch_ctx[cur_chan].filter;
-             TTARice *rice = &s->ch_ctx[cur_chan].rice;
-             uint32_t unary, depth, k;
-             int32_t value;
-             unary = tta_get_unary(&s->gb);
-             if (unary == 0) {
-                 depth = 0;
-                 k = rice->k0;
-             } else {
-                 depth = 1;
-                 k = rice->k1;
-                 unary--;
-             }
+         if (get_bits_left(&s->gb) < k)
+             return -1;
  
-             if (get_bits_left(&s->gb) < k)
+         if (k) {
+             if (k > MIN_CACHE_BITS)
                  return -1;
+             value = (unary << k) + get_bits(&s->gb, k);
+         } else
+             value = unary;
+         // FIXME: copy paste from original
+         switch (depth) {
+         case 1:
+             rice->sum1 += value - (rice->sum1 >> 4);
+             if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1])
+                 rice->k1--;
+             else if(rice->sum1 > shift_16[rice->k1 + 1])
+                 rice->k1++;
+             value += shift_1[rice->k0];
+         default:
+             rice->sum0 += value - (rice->sum0 >> 4);
+             if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0])
+                 rice->k0--;
+             else if(rice->sum0 > shift_16[rice->k0 + 1])
+                 rice->k0++;
+         }
  
-             if (k) {
-                 if (k > MIN_CACHE_BITS)
-                     return -1;
-                 value = (unary << k) + get_bits(&s->gb, k);
-             } else
-                 value = unary;
-             // FIXME: copy paste from original
-             switch (depth) {
-             case 1:
-                 rice->sum1 += value - (rice->sum1 >> 4);
-                 if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1])
-                     rice->k1--;
-                 else if(rice->sum1 > shift_16[rice->k1 + 1])
-                     rice->k1++;
-                 value += shift_1[rice->k0];
-             default:
-                 rice->sum0 += value - (rice->sum0 >> 4);
-                 if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0])
-                     rice->k0--;
-                 else if(rice->sum0 > shift_16[rice->k0 + 1])
-                     rice->k0++;
-             }
-             // extract coded value
+         // extract coded value
  #define UNFOLD(x) (((x)&1) ? (++(x)>>1) : (-(x)>>1))
-             *p = UNFOLD(value);
+         *p = UNFOLD(value);
  
-             // run hybrid filter
-             ttafilter_process(filter, p, 0);
+         // run hybrid filter
+         ttafilter_process(filter, p, 0);
  
-             // fixed order prediction
+         // fixed order prediction
  #define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k)
-             switch (s->bps) {
-                 case 1: *p += PRED(*predictor, 4); break;
-                 case 2:
-                 case 3: *p += PRED(*predictor, 5); break;
-                 case 4: *p += *predictor; break;
-             }
-             *predictor = *p;
-             /*if ((get_bits_count(&s->gb)+7)/8 > buf_size)
-             {
-                 av_log(NULL, AV_LOG_INFO, "overread!!\n");
-                 break;
-             }*/
-             // flip channels
-             if (cur_chan < (s->channels-1))
-                 cur_chan++;
-             else {
-                 // decorrelate in case of stereo integer
-                 if (!s->is_float && (s->channels > 1)) {
-                     int32_t *r = p - 1;
-                     for (*p += *r / 2; r > p - s->channels; r--)
-                         *r = *(r + 1) - *r;
-                 }
-                 cur_chan = 0;
+         switch (s->bps) {
+             case 1: *p += PRED(*predictor, 4); break;
+             case 2:
+             case 3: *p += PRED(*predictor, 5); break;
+             case 4: *p += *predictor; break;
+         }
+         *predictor = *p;
+         // flip channels
+         if (cur_chan < (s->channels-1))
+             cur_chan++;
+         else {
+             // decorrelate in case of stereo integer
+             if (s->channels > 1) {
+                 int32_t *r = p - 1;
+                 for (*p += *r / 2; r > p - s->channels; r--)
+                     *r = *(r + 1) - *r;
              }
+             cur_chan = 0;
          }
+     }
  
-         if (get_bits_left(&s->gb) < 32)
-             return -1;
-         skip_bits(&s->gb, 32); // frame crc
+     if (get_bits_left(&s->gb) < 32)
+         return -1;
+     skip_bits(&s->gb, 32); // frame crc
  
 -    // convert to output buffer
 -    if (s->bps == 2) {
 -        int16_t *samples = data;
 -        for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++)
 -            *samples++ = *p;
 -    } else {
 -        // shift samples for 24-bit sample format
 -        int32_t *samples = data;
 -        for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++)
 -            *samples++ <<= 8;
 -        // reset decode buffer
 -        s->decode_buffer = NULL;
 -    }
 +        // convert to output buffer
 +        switch(s->bps) {
 +            case 1: {
 +                uint8_t *samples = data;
 +                for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++)
 +                    *samples++ = *p + 0x80;
-                 *data_size = samples - (uint8_t *)data;
 +                break;
 +            }
 +            case 2: {
 +                uint16_t *samples = data;
-                 for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) {
- //                    *samples++ = (unsigned char)*p;
- //                    *samples++ = (unsigned char)(*p >> 8);
++                for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++)
 +                    *samples++ = *p;
-                 }
-                 *data_size = (uint8_t *)samples - (uint8_t *)data;
 +                break;
 +            }
 +            case 3: {
++                // shift samples for 24-bit sample format
 +                int32_t *samples = data;
 +                for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++)
-                     *samples++ = AV_RN32(p) << 8;
-                 *data_size = (uint8_t *)samples - (uint8_t *)data;
++                    *samples++ <<= 8;
++                // reset decode buffer
++                s->decode_buffer = NULL;
 +                break;
 +            }
 +            default:
 +                av_log(s->avctx, AV_LOG_ERROR, "Error, only 16bit samples supported!\n");
 +        }
-     }
  
- //    return get_bits_count(&s->gb)+7)/8;
+     *data_size = out_size;
      return buf_size;
  }
  
Simple merge
Simple merge
Simple merge
@@@ -1928,12 -1848,7 +1928,11 @@@ static void update_stream_timings(AVFor
          st = ic->streams[i];
          if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
              start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
-             if (start_time1 < start_time)
-                 start_time = start_time1;
 +            if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
 +                if (start_time1 < start_time_text)
 +                    start_time_text = start_time1;
 +            } else
+             start_time = FFMIN(start_time, start_time1);
              if (st->duration != AV_NOPTS_VALUE) {
                  end_time1 = start_time1
                            + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
          }
          if (st->duration != AV_NOPTS_VALUE) {
              duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q);
-             if (duration1 > duration)
-                 duration = duration1;
+             duration = FFMAX(duration, duration1);
          }
      }
 +    if (start_time == INT64_MAX || (start_time > start_time_text && start_time - start_time_text < AV_TIME_BASE))
 +        start_time = start_time_text;
      if (start_time != INT64_MAX) {
          ic->start_time = start_time;
-         if (end_time != INT64_MIN) {
-             if (end_time - start_time > duration)
-                 duration = end_time - start_time;
-         }
+         if (end_time != INT64_MIN)
+             duration = FFMAX(duration, end_time - start_time);
      }
 -    if (duration != INT64_MIN) {
 +    if (duration != INT64_MIN && ic->duration == AV_NOPTS_VALUE) {
          ic->duration = duration;
 -        if (ic->pb && (filesize = avio_size(ic->pb)) > 0) {
 +    }
 +        if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration != AV_NOPTS_VALUE) {
              /* compute the bitrate */
              ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE /
                  (double)ic->duration;
Simple merge