]> git.sesse.net Git - ffmpeg/commitdiff
Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 19 Nov 2011 00:55:55 +0000 (01:55 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 19 Nov 2011 01:00:06 +0000 (02:00 +0100)
* qatar/master: (22 commits)
  configure: add check for w32threads to enable it automatically
  rtmp: do not hardcode invoke numbers
  cinepack: return non-generic errors
  fate-lavf-ts: use -mpegts_transport_stream_id option.
  Add an APIchanges entry and a minor bump for avio changes.
  avio: Mark the old interrupt callback mechanism as deprecated
  avplay: Set the new interrupt callback
  avconv: Set new interrupt callbacks for all AVFormatContexts, use avio_open2() everywhere
  cinepak: remove redundant coordinate checks
  cinepak: check strip_size
  cinepak, simplify, use AV_RB24()
  cinepak: simplify, use FFMIN()
  cinepak: Fix division by zero, ask for sample if encoded_buf_size is 0
  applehttp: Fix seeking in streams not starting at DTS=0
  http: Don't use the normal http proxy mechanism for https
  tls: Handle connection via a http proxy
  http: Reorder two code blocks
  http: Add a new protocol for opening connections via http proxies
  http: Split out the non-chunked buffer reading part from http_read
  segafilm: add support for raw videos
  ...

Conflicts:
avconv.c
configure
doc/APIchanges
libavcodec/cinepak.c
libavformat/applehttp.c
libavformat/version.h
tests/lavf-regression.sh
tests/ref/lavf/ts

Merged-by: Michael Niedermayer <michaelni@gmx.at>
19 files changed:
1  2 
avconv.c
configure
doc/APIchanges
ffmpeg.c
ffplay.c
libavcodec/cinepak.c
libavformat/allformats.c
libavformat/applehttp.c
libavformat/avio.c
libavformat/avio.h
libavformat/http.c
libavformat/rtmpproto.c
libavformat/rtpdec.c
libavformat/rtpdec.h
libavformat/rtspdec.c
libavformat/segafilm.c
libavformat/version.h
tests/lavf-regression.sh
tests/ref/lavf/ts

diff --cc avconv.c
index 76d8def806a2cd3b3ff8feda00d0ff5657aee33e,ef41245726dd3a8075881301b60a07266cd4d20c..a019ffaf6f79a8c5caf8027d188c5f45f7a2c586
+++ b/avconv.c
@@@ -557,43 -503,13 +557,45 @@@ static void term_init(void
  #endif
  }
  
- static int decode_interrupt_cb(void)
 +/* 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 };
  void exit_program(int ret)
  {
      int i;
@@@ -3585,11 -3466,12 +3589,12 @@@ 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 = NULL;
+     AVFormatContext *ic = avformat_alloc_context();
  
+     ic->interrupt_callback = int_cb;
      err = avformat_open_input(&ic, filename, NULL, NULL);
      if (err < 0)
          return err;
@@@ -3637,7 -3518,24 +3642,8 @@@ static void opt_output_file(void *optct
          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)) {
@@@ -4350,12 -4227,7 +4358,6 @@@ int main(int argc, char **argv
      av_register_all();
      avformat_network_init();
  
- #if HAVE_ISATTY
-     if(isatty(STDIN_FILENO))
-         avio_set_interrupt_cb(decode_interrupt_cb);
- #endif
--    show_banner();
  
      /* parse options */
      parse_options(&o, argc, argv, options, opt_output_file);
diff --cc configure
index 2daa079b573161f40a5e76715232ac59d470280a,61bb4dfb54770b868b14e836b746683c3fb1b087..d0376bb391f5f443f4f5f0b4472f85a787eaf82e
+++ b/configure
@@@ -2991,17 -2849,15 +2990,21 @@@ check_header X11/extensions/XvMClib.
  disabled  zlib || check_lib   zlib.h      zlibVersion -lz   || disable  zlib
  disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib
  
 +# check for VDA header
 +if ! disabled vda; then
 +    if check_header VideoDecodeAcceleration/VDADecoder.h; then
 +        enable vda
 +        add_ldflags -framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore
 +    fi
 +fi
 +
+ if ! disabled w32threads && ! enabled pthreads; then
+     check_func _beginthreadex && enable w32threads
+ fi
  # check for some common methods of building with pthread support
  # do this before the optional library checks as some of them require pthreads
 -if ! disabled pthreads && ! enabled w32threads; then
 +if ! disabled pthreads && ! enabled w32threads && ! enabled os2threads; then
      enable pthreads
      if check_func pthread_create; then
          :
diff --cc doc/APIchanges
index 03f7d460d2943d1f441e2ce6f85d83178c040334,f1913bd6deddaa0ad0f078bb1bede4c66a1147e2..2ce14618fa783d44edd831cb0903e85ac8d66fb7
@@@ -13,12 -13,16 +13,22 @@@ libavutil:   2011-04-1
  
  API changes, most recent first:
  
 +2011-11-03 - 96949da - lavu 51.23.0
 +  Add av_strcasecmp() and av_strncasecmp() to avstring.h.
 +
 +2011-10-20 - b35e9e1 - lavu 51.22.0
 +  Add av_strtok() to avstring.h.
 +
+ 2011-11-13 - lavf 53.15.0
+   New interrupt callback API, allowing per-AVFormatContext/AVIOContext
+   interrupt callbacks.
+   6aa0b98 Add AVIOInterruptCB struct and the interrupt_callback field to
+           AVFormatContext.
+   1dee0ac Add avio_open2() with additional parameters. Those are
+           an interrupt callback and an options AVDictionary.
+           This will allow passing AVOptions to protocols after lavf
+           54.0.
  2011-11-xx - xxxxxxx - lavu 51.16.0
    Add av_timegm()
  
diff --cc ffmpeg.c
index 9895fb39703646c1418248ffded0889a5bc3706c,c731cec53b4b5d0f8ae0de84ba76fa5a64e3b613..507c35dba4ec281ffcef3c5d76cd0641a5b9ba6f
+++ b/ffmpeg.c
@@@ -581,66 -441,12 +581,68 @@@ static void term_init(void
  #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)
++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;
  
@@@ -2371,39 -2331,150 +2373,40 @@@ static int transcode_init(OutputFile *o
              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);
 -        }
 -    }
 -
 -    /* 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;
 -            }
 +            if (ost->st->codec->me_threshold)
 +                input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV;
          }
 -
 -        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++) {
 +        os = output_files[i].ctx;
++        os->interrupt_callback = int_cb;
 +        if (avformat_write_header(os, &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;
          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");
-         avio_set_interrupt_cb(decode_interrupt_cb);
 +    }
  
      timer_start = av_gettime();
  
@@@ -3087,174 -3064,75 +3089,174 @@@ static int opt_recording_timestamp(Opti
      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, ist->st->codec->codec_id, 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:
 +            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 &&
 +        (strchr(filename, ':') == NULL || filename[1] == ':' ||
 +         av_strstart(filename, "file:", NULL))) {
 +        if (avio_check(filename, 0) == 0) {
 +            if (!using_stdin) {
 +                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_open (&out, filename, AVIO_FLAG_WRITE)) < 0) {
++    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;
          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   = 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;
 +    }
  
      /* open the input file with generic libav function */
      err = avformat_open_input(&ic, filename, file_iformat, &format_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);
++            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_open(s, filename, AVIO_FLAG_READ);
++            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->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);
      }
  
 -    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;
 +
 +    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 (!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;
  
 -        if (frame_rate.num)
 -            ost->frame_rate = frame_rate;
 -        video_enc->codec_id = codec_id;
 +        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->width = frame_width;
 -        video_enc->height = frame_height;
 -        video_enc->pix_fmt = frame_pix_fmt;
 +        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);
 +        }
 +
 +        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->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)
@@@ -3786,107 -3638,70 +3789,108 @@@ static OutputStream *new_subtitle_strea
      st  = ost->st;
      subtitle_enc = st->codec;
  
 -    ost->bitstream_filters = subtitle_bitstream_filters;
 -    subtitle_bitstream_filters= NULL;
 -
      subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
  
 -    if(subtitle_codec_tag)
 -        subtitle_enc->codec_tag= subtitle_codec_tag;
 +    return ost;
 +}
 +
 +/* arg format is "output-stream-index:streamid-value". */
 +static int opt_streamid(OptionsContext *o, const char *opt, const char *arg)
 +{
 +    int idx;
 +    char *p;
 +    char idx_str[16];
 +
 +    av_strlcpy(idx_str, arg, sizeof(idx_str));
 +    p = strchr(idx_str, ':');
 +    if (!p) {
 +        av_log(NULL, AV_LOG_FATAL,
 +               "Invalid value '%s' for option '%s', required syntax is 'index:value'\n",
 +               arg, opt);
 +        exit_program(1);
 +    }
 +    *p++ = '\0';
 +    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 (oc->oformat->flags & AVFMT_GLOBALHEADER) {
 -        subtitle_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
 -    }
 -    if (subtitle_stream_copy) {
 -        st->stream_copy = 1;
 -    } else {
 -        subtitle_enc->codec_id = codec_id;
 -    }
 +        if (copy_metadata)
 +            av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
  
 -    if (subtitle_language) {
 -        av_dict_set(&st->metadata, "language", subtitle_language, 0);
 -        av_freep(&subtitle_language);
 +        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;
      }
 -
 -    subtitle_disable = 0;
 -    av_freep(&subtitle_codec_name);
 -    subtitle_stream_copy = 0;
 +    return 0;
  }
  
 -static int opt_new_stream(const char *opt, const char *arg)
 +static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
  {
 -    AVFormatContext *oc;
 -    int file_idx = nb_output_files - 1;
 -    if (nb_output_files <= 0) {
 -        fprintf(stderr, "At least one output file must be specified\n");
 -        exit_program(1);
 -    }
 -    oc = output_files[file_idx];
 +    int i, err;
-     AVFormatContext *ic = NULL;
++    AVFormatContext *ic = avformat_alloc_context();
  
 -    if      (!strcmp(opt, "newvideo"   )) new_video_stream   (oc, file_idx);
 -    else if (!strcmp(opt, "newaudio"   )) new_audio_stream   (oc, file_idx);
 -    else if (!strcmp(opt, "newsubtitle")) new_subtitle_stream(oc, file_idx);
 -    else if (!strcmp(opt, "newdata"    )) new_data_stream    (oc, file_idx);
 -    else av_assert0(0);
 -    return 0;
 -}
++    ic->interrupt_callback = int_cb;
 +    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;
 +        AVCodecContext *avctx;
  
 -/* arg format is "output-stream-index:streamid-value". */
 -static int opt_streamid(const char *opt, const char *arg)
 -{
 -    int idx;
 -    char *p;
 -    char idx_str[16];
 +        codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
 +        ost   = new_output_stream(o, s, codec->type);
 +        st    = ost->st;
 +        avctx = st->codec;
  
 -    av_strlcpy(idx_str, arg, sizeof(idx_str));
 -    p = strchr(idx_str, ':');
 -    if (!p) {
 -        fprintf(stderr,
 -                "Invalid value '%s' for option '%s', required syntax is 'index:value'\n",
 -                arg, opt);
 -        exit_program(1);
 +        // 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));
 +        st->codec= avctx;
 +        avcodec_copy_context(st->codec, ic->streams[i]->codec);
 +
 +        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 && !ost->stream_copy)
 +            choose_pixel_fmt(st, codec);
      }
 -    *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);
 +
 +    av_close_input_file(ic);
      return 0;
  }
  
@@@ -3902,159 -3715,78 +3906,160 @@@ 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);
      }
 +    file_oformat= oc->oformat;
++    oc->interrupt_callback = int_cb;
  
 -    if (last_asked_format) {
 -        file_oformat = av_guess_format(last_asked_format, NULL, NULL);
 -        if (!file_oformat) {
 -            fprintf(stderr, "Requested output format '%s' is not a suitable output format\n", last_asked_format);
 +    if (!strcmp(file_oformat->name, "ffm") &&
 +        av_strstart(filename, "http:", NULL)) {
 +        int j;
 +        /* 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);
          }
 -        last_asked_format = NULL;
 +        for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
 +            ost = &output_streams[j];
 +            for (i = 0; i < nb_input_streams; i++) {
 +                ist = &input_streams[i];
 +                if(ist->st->codec->codec_type == ost->st->codec->codec_type){
 +                    ost->sync_ist= ist;
 +                    ost->source_index= i;
 +                    ist->discard = 0;
 +                    break;
 +                }
 +            }
 +        }
 +    } else if (!o->nb_stream_maps) {
 +        /* pick the "best" stream of each type */
 +#define NEW_STREAM(type, index)\
 +        if (index >= 0) {\
 +            ost = new_ ## type ## _stream(o, oc);\
 +            ost->source_index = index;\
 +            ost->sync_ist     = &input_streams[index];\
 +            input_streams[index].discard = 0;\
 +        }
 +
 +        /* video: highest resolution */
 +        if (!o->video_disable && oc->oformat->video_codec != CODEC_ID_NONE) {
 +            int area = 0, idx = -1;
 +            for (i = 0; i < nb_input_streams; i++) {
 +                ist = &input_streams[i];
 +                if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
 +                    ist->st->codec->width * ist->st->codec->height > area) {
 +                    area = ist->st->codec->width * ist->st->codec->height;
 +                    idx = i;
 +                }
 +            }
 +            NEW_STREAM(video, idx);
 +        }
 +
 +        /* audio: most channels */
 +        if (!o->audio_disable && oc->oformat->audio_codec != CODEC_ID_NONE) {
 +            int channels = 0, idx = -1;
 +            for (i = 0; i < nb_input_streams; i++) {
 +                ist = &input_streams[i];
 +                if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
 +                    ist->st->codec->channels > channels) {
 +                    channels = ist->st->codec->channels;
 +                    idx = i;
 +                }
 +            }
 +            NEW_STREAM(audio, idx);
 +        }
 +
 +        /* subtitles: pick first */
 +        if (!o->subtitle_disable && (oc->oformat->subtitle_codec != CODEC_ID_NONE || subtitle_codec_name)) {
 +            for (i = 0; i < nb_input_streams; i++)
 +                if (input_streams[i].st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
 +                    NEW_STREAM(subtitle, i);
 +                    break;
 +                }
 +        }
 +        /* do something with data? */
      } else {
 -        file_oformat = av_guess_format(NULL, filename, NULL);
 -        if (!file_oformat) {
 -            fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
 -                    filename);
 -            exit_program(1);
 +        for (i = 0; i < o->nb_stream_maps; i++) {
 +            StreamMap *map = &o->stream_maps[i];
 +
 +            if (map->disabled)
 +                continue;
 +
 +            ist = &input_streams[input_files[map->file_index].ist_index + map->stream_index];
 +            if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
 +                continue;
 +            if(o->   audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 +                continue;
 +            if(o->   video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 +                continue;
 +
 +            switch (ist->st->codec->codec_type) {
 +            case AVMEDIA_TYPE_VIDEO:    ost = new_video_stream(o, oc);    break;
 +            case AVMEDIA_TYPE_AUDIO:    ost = new_audio_stream(o, oc);    break;
 +            case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break;
 +            case AVMEDIA_TYPE_DATA:     ost = new_data_stream(o, oc);     break;
 +            case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc); break;
 +            default:
 +                av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n",
 +                       map->file_index, map->stream_index);
 +                exit_program(1);
 +            }
 +
 +            ost->source_index = input_files[map->file_index].ist_index + map->stream_index;
 +            ost->sync_ist = &input_streams[input_files[map->sync_file_index].ist_index +
 +                                           map->sync_stream_index];
 +            ist->discard = 0;
          }
      }
  
 -    oc->oformat = file_oformat;
 -    av_strlcpy(oc->filename, filename, sizeof(oc->filename));
 +    /* handle attached files */
 +    for (i = 0; i < o->nb_attachments; i++) {
 +        AVIOContext *pb;
 +        uint8_t *attachment;
 +        const char *p;
 +        int64_t len;
  
-         if ((err = avio_open(&pb, o->attachments[i], AVIO_FLAG_READ)) < 0) {
 -    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(oc, filename);
 -        if (err < 0) {
 -            print_error(filename, err);
++        if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) {
 +            av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n",
 +                   o->attachments[i]);
              exit_program(1);
          }
 -    } else {
 -        use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
 -        use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
 -        use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
 -        use_data = data_stream_copy ||  data_codec_name; /* XXX once generic data codec will be available add a ->data_codec reference and use it here */
 -
 -        /* disable if no corresponding type found */
 -        check_inputs(&input_has_video,
 -                     &input_has_audio,
 -                     &input_has_subtitle,
 -                     &input_has_data);
 -
 -        if (!input_has_video)
 -            use_video = 0;
 -        if (!input_has_audio)
 -            use_audio = 0;
 -        if (!input_has_subtitle)
 -            use_subtitle = 0;
 -        if (!input_has_data)
 -            use_data = 0;
 -
 -        /* manual disable */
 -        if (audio_disable)    use_audio    = 0;
 -        if (video_disable)    use_video    = 0;
 -        if (subtitle_disable) use_subtitle = 0;
 -        if (data_disable)     use_data     = 0;
 -
 -        if (use_video)    new_video_stream(oc, nb_output_files);
 -        if (use_audio)    new_audio_stream(oc, nb_output_files);
 -        if (use_subtitle) new_subtitle_stream(oc, nb_output_files);
 -        if (use_data)     new_data_stream(oc, nb_output_files);
 -
 -        av_dict_copy(&oc->metadata, metadata, 0);
 -        av_dict_free(&metadata);
 -    }
 -
 -    av_dict_copy(&output_opts[nb_output_files], format_opts, 0);
 -    output_files[nb_output_files++] = oc;
 +        if ((len = avio_size(pb)) <= 0) {
 +            av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n",
 +                   o->attachments[i]);
 +            exit_program(1);
 +        }
 +        if (!(attachment = av_malloc(len))) {
 +            av_log(NULL, AV_LOG_FATAL, "Attachment %s too large to fit into memory.\n",
 +                   o->attachments[i]);
 +            exit_program(1);
 +        }
 +        avio_read(pb, attachment, len);
 +
 +        ost = new_attachment_stream(o, oc);
 +        ost->stream_copy               = 0;
 +        ost->source_index              = -1;
 +        ost->attachment_filename       = o->attachments[i];
 +        ost->st->codec->extradata      = attachment;
 +        ost->st->codec->extradata_size = len;
 +
 +        p = strrchr(o->attachments[i], '/');
 +        av_dict_set(&ost->st->metadata, "filename", (p && *p) ? p + 1 : o->attachments[i], AV_DICT_DONT_OVERWRITE);
 +        avio_close(pb);
 +    }
 +
 +    output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1);
 +    output_files[nb_output_files - 1].ctx       = oc;
 +    output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams;
 +    output_files[nb_output_files - 1].recording_time = o->recording_time;
 +    output_files[nb_output_files - 1].start_time     = o->start_time;
 +    output_files[nb_output_files - 1].limit_filesize = o->limit_filesize;
 +    av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0);
  
      /* check filename in case of an image number is expected */
      if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
  
      if (!(oc->oformat->flags & AVFMT_NOFILE)) {
          /* test if it already exists to avoid loosing precious files */
 -        if (!file_overwrite &&
 -            (strchr(filename, ':') == NULL ||
 -             filename[1] == ':' ||
 -             av_strstart(filename, "file:", NULL))) {
 -            if (avio_check(filename, 0) == 0) {
 -                if (!using_stdin) {
 -                    fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
 -                    fflush(stderr);
 -                    if (!read_yesno()) {
 -                        fprintf(stderr, "Not overwriting - exiting\n");
 -                        exit_program(1);
 -                    }
 -                }
 -                else {
 -                    fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
 -                    exit_program(1);
 -                }
 -            }
 -        }
 +        assert_file_overwrite(filename);
  
          /* open the file */
--        if ((err = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE)) < 0) {
++        if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
++                              &oc->interrupt_callback,
++                              &output_files[nb_output_files - 1].opts)) < 0) {
              print_error(filename, err);
              exit_program(1);
          }
@@@ -4725,17 -4370,18 +4732,11 @@@ int main(int argc, char **argv
      av_register_all();
      avformat_network_init();
  
- #if HAVE_ISATTY
-     if(isatty(STDIN_FILENO))
-         avio_set_interrupt_cb(decode_interrupt_cb);
- #endif
-     show_banner();
 -    avio_set_interrupt_cb(decode_interrupt_cb);
  
 -    init_opts();
 -
 -    show_banner();
 -
 -    av_log(NULL, AV_LOG_WARNING, "This program is not developed anymore and is only "
 -                                 "provided for compatibility. Use avconv instead "
 -                                 "(see Changelog for the list of incompatible changes).\n");
 +    term_init();
  
      /* parse options */
 -    parse_options(NULL, argc, argv, options, opt_output_file);
 +    parse_options(&o, argc, argv, options, opt_output_file);
  
      if(nb_output_files <= 0 && nb_input_files == 0) {
          show_usage();
diff --cc ffplay.c
Simple merge
index fe6552487070c83e0dac588ee6ebf0ee6c3caa64,9cf38edb8e56bdb7386bea3af4103dbc0bf6ae61..ebdbb5eaecec21fe9d1b4ea925f132248ba9de46
@@@ -359,11 -359,9 +359,11 @@@ static int cinepak_decode (CinepakConte
  
      num_strips = FFMIN(num_strips, MAX_STRIPS);
  
 +    s->frame.key_frame = 0;
 +
      for (i=0; i < num_strips; i++) {
          if ((s->data + 12) > eod)
-             return -1;
+             return AVERROR_INVALIDDATA;
  
          s->strips[i].id = s->data[0];
          s->strips[i].y1 = y0;
          s->strips[i].y2 = y0 + AV_RB16 (&s->data[8]);
          s->strips[i].x2 = s->avctx->width;
  
 +        if (s->strips[i].id == 0x10)
 +            s->frame.key_frame = 1;
 +
          strip_size = AV_RB24 (&s->data[1]) - 12;
-         if(strip_size < 0)
-             return -1;
+         if (strip_size < 0)
+             return AVERROR_INVALIDDATA;
          s->data   += 12;
          strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size;
  
@@@ -433,12 -427,12 +433,12 @@@ static int cinepak_decode_frame(AVCodec
      s->data = buf;
      s->size = buf_size;
  
 -    s->frame.reference = 1;
 +    s->frame.reference = 3;
      s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
                              FF_BUFFER_HINTS_REUSABLE;
-     if (avctx->reget_buffer(avctx, &s->frame)) {
+     if ((ret = avctx->reget_buffer(avctx, &s->frame))) {
          av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
-         return -1;
+         return ret;
      }
  
      if (s->palette_video) {
Simple merge
index 7c41d9893c5433dde9e94a280041dd7304a1f290,366d8327ff5880d61eaf5357a85c1c26d4b47ac1..1694096d9ba11ac5c3c3af24a77b69bc908d3817
@@@ -644,11 -644,11 +644,12 @@@ static int applehttp_read_seek(AVFormat
      for (i = 0; i < c->n_variants; i++) {
          /* Reset reading */
          struct variant *var = c->variants[i];
-         int64_t pos = av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ?
+         int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 :
 -                      av_rescale_rnd(c->first_timestamp, 1,
 -                          stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE,
 -                          flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
 -        if (var->input) {
++                      av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ?
 +                               s->streams[stream_index]->time_base.den :
 +                               AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
 +                               AV_ROUND_DOWN : AV_ROUND_UP);
 +         if (var->input) {
              ffurl_close(var->input);
              var->input = NULL;
          }
index 879844aefc4ca390ddc0998c017bb45fc7c9b456,4750a9d54441146a406f2545df7b09d083e6c0ef..b2b39b32d76f83f51bb4ce759b1a569bee65951d
@@@ -83,10 -83,13 +83,12 @@@ const AVClass ffurl_context_class = 
  };
  /*@}*/
  
- static int default_interrupt_cb(void);
  
+ #if FF_API_OLD_INTERRUPT_CB
+ static int default_interrupt_cb(void);
  int (*url_interrupt_cb)(void) = default_interrupt_cb;
+ #endif
  
 -#if FF_API_OLD_AVIO
  URLProtocol *av_protocol_next(URLProtocol *p)
  {
      return ffurl_protocol_next(p);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 954d87a88e3f6e9c1109eedadba4b7118d5afbe9,d56bdb7c87e4a01ec80cef20e822d2ca8e714ba6..5c7ed6863e06039f2f9a8c6476e62281b5690d78
@@@ -24,7 -24,7 +24,7 @@@
  #include "libavutil/avutil.h"
  
  #define LIBAVFORMAT_VERSION_MAJOR 53
- #define LIBAVFORMAT_VERSION_MINOR 20
 -#define LIBAVFORMAT_VERSION_MINOR 15
++#define LIBAVFORMAT_VERSION_MINOR 21
  #define LIBAVFORMAT_VERSION_MICRO  0
  
  #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
index 292845d4e459e4840aabd2807d88d592b97f52cd,4a72e0ac1c43dc360d29349d07af6bbbefd9ea5e..1c579060cc4085f1691c51c58d34074b958ee9c1
@@@ -71,7 -71,7 +71,7 @@@ do_lavf mxf_d10 "-ar 48000 -ac 2 -r 25 
  fi
  
  if [ -n "$do_ts" ] ; then
- do_lavf ts "-ab 64k"
 -do_lavf ts "-mpegts_transport_stream_id 42"
++do_lavf ts "-ab 64k -mpegts_transport_stream_id 42"
  fi
  
  if [ -n "$do_swf" ] ; then
index 3b2dad1b5e0a394e7dabad26baf007c77a9e7fe5,ebe6a77566c8c1e657c48e43f478badbd5465e19..018d61813a3337c00faca19cc475c68aa294a821
@@@ -1,3 -1,3 +1,3 @@@
- 151774afed45b19da9b7e83613a1e72b *./tests/data/lavf/lavf.ts
 -293142d7286db15e5f4d7d1ca0d9c97c *./tests/data/lavf/lavf.ts
++024f0cdd4c51a158b2a38b901d2ed2e5 *./tests/data/lavf/lavf.ts
  406644 ./tests/data/lavf/lavf.ts
  ./tests/data/lavf/lavf.ts CRC=0x133216c1