]> git.sesse.net Git - ffmpeg/blobdiff - ffmpeg.c
xdcam hd422 720p24 fourcc in mov
[ffmpeg] / ffmpeg.c
index 104d57e5b82ae595db9a826e0b4d0c1a09a97b4d..6309acf5831874e22f5447967ffa1fc284e718aa 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -79,8 +79,7 @@
 
 #include "cmdutils.h"
 
-#undef NDEBUG
-#include <assert.h>
+#include "libavutil/avassert.h"
 
 const char program_name[] = "FFmpeg";
 const int program_birth_year = 2000;
@@ -93,7 +92,9 @@ typedef struct AVStreamMap {
     int sync_stream_index;
 } AVStreamMap;
 
-/** select an input file for an output file */
+/**
+ * select an input file for an output file
+ */
 typedef struct AVMetaDataMap {
     int out_file;
     int in_file;
@@ -102,28 +103,33 @@ typedef struct AVMetaDataMap {
 static const OptionDef options[];
 
 #define MAX_FILES 100
+#if !FF_API_MAX_STREAMS
+#define MAX_STREAMS 1024    /* arbitrary sanity check value */
+#endif
 
 static const char *last_asked_format = NULL;
 static AVFormatContext *input_files[MAX_FILES];
 static int64_t input_files_ts_offset[MAX_FILES];
-static double input_files_ts_scale[MAX_FILES][MAX_STREAMS];
-static AVCodec *input_codecs[MAX_FILES*MAX_STREAMS];
+static double *input_files_ts_scale[MAX_FILES] = {NULL};
+static AVCodec **input_codecs = NULL;
 static int nb_input_files = 0;
-static int nb_icodecs;
+static int nb_input_codecs = 0;
+static int nb_input_files_ts_scale[MAX_FILES] = {0};
 
 static AVFormatContext *output_files[MAX_FILES];
-static AVCodec *output_codecs[MAX_FILES*MAX_STREAMS];
+static AVCodec **output_codecs = NULL;
 static int nb_output_files = 0;
-static int nb_ocodecs;
+static int nb_output_codecs = 0;
 
-static AVStreamMap stream_maps[MAX_FILES*MAX_STREAMS];
+static AVStreamMap *stream_maps = NULL;
 static int nb_stream_maps;
 
 static AVMetaDataMap meta_data_maps[MAX_FILES];
 static int nb_meta_data_maps;
 
 /* indexed by output file stream index */
-static int streamid_map[MAX_STREAMS];
+static int *streamid_map = NULL;
+static int nb_streamid_map = 0;
 
 static int frame_width  = 0;
 static int frame_height = 0;
@@ -241,7 +247,8 @@ static short *samples;
 static AVBitStreamFilterContext *video_bitstream_filters=NULL;
 static AVBitStreamFilterContext *audio_bitstream_filters=NULL;
 static AVBitStreamFilterContext *subtitle_bitstream_filters=NULL;
-static AVBitStreamFilterContext *bitstream_filters[MAX_FILES][MAX_STREAMS];
+static AVBitStreamFilterContext **bitstream_filters[MAX_FILES] = {NULL};
+static int nb_bitstream_filters[MAX_FILES] = {0};
 
 #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
 
@@ -309,7 +316,7 @@ typedef struct AVInputStream {
     int showed_multi_packet_warning;
     int is_past_recording_time;
 #if CONFIG_AVFILTER
-    AVFilterContext *out_video_filter;
+    AVFilterContext *output_video_filter;
     AVFilterContext *input_video_filter;
     AVFrame *filter_frame;
     int has_filter_frame;
@@ -368,17 +375,17 @@ static int get_filtered_video_pic(AVFilterContext *ctx,
 
     if(avfilter_request_frame(ctx->inputs[0]))
         return -1;
-    if(!(pic = ctx->inputs[0]->cur_pic))
+    if(!(pic = ctx->inputs[0]->cur_buf))
         return -1;
     *picref = pic;
-    ctx->inputs[0]->cur_pic = NULL;
+    ctx->inputs[0]->cur_buf = NULL;
 
     *pts          = pic->pts;
 
     memcpy(pic2->data,     pic->data,     sizeof(pic->data));
     memcpy(pic2->linesize, pic->linesize, sizeof(pic->linesize));
-    pic2->interlaced_frame = pic->interlaced;
-    pic2->top_field_first  = pic->top_field_first;
+    pic2->interlaced_frame = pic->video->interlaced;
+    pic2->top_field_first  = pic->video->top_field_first;
 
     return 1;
 }
@@ -407,38 +414,38 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
     AVCodecContext *codec = ost->st->codec;
     AVCodecContext *icodec = ist->st->codec;
     char args[255];
+    int ret;
 
     graph = av_mallocz(sizeof(AVFilterGraph));
 
-    if (!(ist->input_video_filter = avfilter_open(avfilter_get_by_name("buffer"), "src")))
-        return -1;
-    if (!(ist->out_video_filter = avfilter_open(&output_filter, "out")))
-        return -1;
+    if ((ret = avfilter_open(&ist->input_video_filter, avfilter_get_by_name("buffer"), "src")) < 0)
+        return ret;
+    if ((ret = avfilter_open(&ist->output_video_filter, &output_filter, "out")) < 0)
+        return ret;
 
     snprintf(args, 255, "%d:%d:%d", ist->st->codec->width,
              ist->st->codec->height, ist->st->codec->pix_fmt);
-    if (avfilter_init_filter(ist->input_video_filter, args, NULL))
-        return -1;
-    if (avfilter_init_filter(ist->out_video_filter, NULL, &codec->pix_fmt))
-        return -1;
+    if ((ret = avfilter_init_filter(ist->input_video_filter, args, NULL)) < 0)
+        return ret;
+    if ((ret = avfilter_init_filter(ist->output_video_filter, NULL, &codec->pix_fmt)) < 0)
+        return ret;
 
     /* add input and output filters to the overall graph */
     avfilter_graph_add_filter(graph, ist->input_video_filter);
-    avfilter_graph_add_filter(graph, ist->out_video_filter);
+    avfilter_graph_add_filter(graph, ist->output_video_filter);
 
     last_filter = ist->input_video_filter;
 
     if (ost->video_crop) {
-        snprintf(args, 255, "%d:%d:%d:%d", ost->leftBand, ost->topBand,
-                 codec->width,
-                 codec->height);
-        filter = avfilter_open(avfilter_get_by_name("crop"), NULL);
-        if (!filter)
-            return -1;
-        if (avfilter_init_filter(filter, args, NULL))
-            return -1;
-        if (avfilter_link(last_filter, 0, filter, 0))
-            return -1;
+        snprintf(args, 255, "%d:%d:%d:%d",
+                 codec->width, codec->height,
+                 ost->leftBand, ost->topBand);
+        if ((ret = avfilter_open(&filter, avfilter_get_by_name("crop"), NULL)) < 0)
+            return ret;
+        if ((ret = avfilter_init_filter(filter, args, NULL)) < 0)
+            return ret;
+        if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
+            return ret;
         last_filter = filter;
         avfilter_graph_add_filter(graph, last_filter);
     }
@@ -450,13 +457,12 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
                  codec->width,
                  codec->height,
                  (int)av_get_int(sws_opts, "sws_flags", NULL));
-        filter = avfilter_open(avfilter_get_by_name("scale"), NULL);
-        if (!filter)
-            return -1;
-        if (avfilter_init_filter(filter, args, NULL))
-            return -1;
-        if (avfilter_link(last_filter, 0, filter, 0))
-            return -1;
+        if ((ret = avfilter_open(&filter, avfilter_get_by_name("scale"), NULL)) < 0)
+            return ret;
+        if ((ret = avfilter_init_filter(filter, args, NULL)) < 0)
+            return ret;
+        if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
+            return ret;
         last_filter = filter;
         avfilter_graph_add_filter(graph, last_filter);
     }
@@ -474,28 +480,28 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
         outputs->next    = NULL;
 
         inputs->name    = av_strdup("out");
-        inputs->filter  = ist->out_video_filter;
+        inputs->filter  = ist->output_video_filter;
         inputs->pad_idx = 0;
         inputs->next    = NULL;
 
-        if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
-            return -1;
+        if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
+            return ret;
         av_freep(&vfilters);
     } else {
-        if (avfilter_link(last_filter, 0, ist->out_video_filter, 0) < 0)
-            return -1;
+        if ((ret = avfilter_link(last_filter, 0, ist->output_video_filter, 0)) < 0)
+            return ret;
     }
 
     /* configure all the filter links */
-    if (avfilter_graph_check_validity(graph, NULL))
-        return -1;
-    if (avfilter_graph_config_formats(graph, NULL))
-        return -1;
-    if (avfilter_graph_config_links(graph, NULL))
-        return -1;
+    if ((ret = avfilter_graph_check_validity(graph, NULL)) < 0)
+        return ret;
+    if ((ret = avfilter_graph_config_formats(graph, NULL)) < 0)
+        return ret;
+    if ((ret = avfilter_graph_config_links(graph, NULL)) < 0)
+        return ret;
 
-    codec->width = ist->out_video_filter->inputs[0]->w;
-    codec->height = ist->out_video_filter->inputs[0]->h;
+    codec->width  = ist->output_video_filter->inputs[0]->w;
+    codec->height = ist->output_video_filter->inputs[0]->h;
 
     return 0;
 }
@@ -503,6 +509,7 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
 
 static void term_exit(void)
 {
+    av_log(NULL, AV_LOG_QUIET, "");
 #if HAVE_TERMIOS_H
     tcsetattr (0, TCSANOW, &oldtty);
 #endif
@@ -603,9 +610,12 @@ static int ffmpeg_exit(int ret)
         }
         av_metadata_free(&s->metadata);
         av_free(s);
+        av_free(bitstream_filters[i]);
     }
-    for(i=0;i<nb_input_files;i++)
+    for(i=0;i<nb_input_files;i++) {
         av_close_input_file(input_files[i]);
+        av_free(input_files_ts_scale[i]);
+    }
 
     av_free(intra_matrix);
     av_free(inter_matrix);
@@ -615,6 +625,10 @@ static int ffmpeg_exit(int ret)
     av_free(vstats_filename);
 
     av_free(opt_names);
+    av_free(streamid_map);
+    av_free(input_codecs);
+    av_free(output_codecs);
+    av_free(stream_maps);
 
     av_free(video_codec_name);
     av_free(audio_codec_name);
@@ -622,10 +636,7 @@ static int ffmpeg_exit(int ret)
 
     av_free(video_standard);
 
-    for (i=0;i<AVMEDIA_TYPE_NB;i++)
-        av_free(avcodec_opts[i]);
-    av_free(avformat_opts);
-    av_free(sws_opts);
+    uninit_opts();
     av_free(audio_buf);
     av_free(audio_out);
     allocated_audio_buf_size= allocated_audio_out_size= 0;
@@ -646,6 +657,26 @@ static int ffmpeg_exit(int ret)
     return ret;
 }
 
+/* similar to ff_dynarray_add() and av_fast_realloc() */
+static void *grow_array(void *array, int elem_size, int *size, int new_size)
+{
+    if (new_size >= INT_MAX / elem_size) {
+        fprintf(stderr, "Array too big.\n");
+        ffmpeg_exit(1);
+    }
+    if (*size < new_size) {
+        uint8_t *tmp = av_realloc(array, new_size*elem_size);
+        if (!tmp) {
+            fprintf(stderr, "Could not alloc buffer.\n");
+            ffmpeg_exit(1);
+        }
+        memset(tmp + *size*elem_size, 0, (new_size-*size) * elem_size);
+        *size = new_size;
+        return tmp;
+    }
+    return array;
+}
+
 static void choose_sample_fmt(AVStream *st, AVCodec *codec)
 {
     if(codec && codec->sample_fmts){
@@ -868,9 +899,9 @@ need_realloc:
 
     if(audio_sync_method){
         double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
-                - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2);
-        double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate;
-        int byte_delta= ((int)idelta)*2*ist->st->codec->channels;
+                - av_fifo_size(ost->fifo)/(enc->channels * 2);
+        double idelta= delta*dec->sample_rate / enc->sample_rate;
+        int byte_delta= ((int)idelta)*2*dec->channels;
 
         //FIXME resample delay
         if(fabs(delta) > 50){
@@ -903,7 +934,7 @@ need_realloc:
                 }
             }else if(audio_sync_method>1){
                 int comp= av_clip(delta, -audio_sync_method, audio_sync_method);
-                assert(ost->audio_resample);
+                av_assert0(ost->audio_resample);
                 if(verbose > 2)
                     fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate);
 //                fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
@@ -912,13 +943,13 @@ need_realloc:
         }
     }else
         ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
-                        - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong
+                        - av_fifo_size(ost->fifo)/(enc->channels * 2); //FIXME wrong
 
     if (ost->audio_resample) {
         buftmp = audio_buf;
         size_out = audio_resample(ost->resample,
                                   (short *)buftmp, (short *)buf,
-                                  size / (ist->st->codec->channels * isize));
+                                  size / (dec->channels * isize));
         size_out = size_out * enc->channels * osize;
     } else {
         buftmp = buf;
@@ -973,7 +1004,7 @@ need_realloc:
             if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
                 pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
             pkt.flags |= AV_PKT_FLAG_KEY;
-            write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+            write_frame(s, &pkt, enc, bitstream_filters[ost->file_index][pkt.stream_index]);
 
             ost->sync_opts += enc->frame_size;
         }
@@ -1008,7 +1039,7 @@ need_realloc:
         if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
             pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
         pkt.flags |= AV_PKT_FLAG_KEY;
-        write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
+        write_frame(s, &pkt, enc, bitstream_filters[ost->file_index][pkt.stream_index]);
     }
 }
 
@@ -1221,10 +1252,10 @@ static void do_video_out(AVFormatContext *s,
             rightBand  = ((int64_t)ist->st->codec->width  * ost->original_rightBand  / ost->original_width)  & ~1;
 
             /* sanity check to ensure no bad band sizes sneak in */
-            assert(topBand    <= INT_MAX && topBand    >= 0);
-            assert(bottomBand <= INT_MAX && bottomBand >= 0);
-            assert(leftBand   <= INT_MAX && leftBand   >= 0);
-            assert(rightBand  <= INT_MAX && rightBand  >= 0);
+            av_assert0(topBand    <= INT_MAX && topBand    >= 0);
+            av_assert0(bottomBand <= INT_MAX && bottomBand >= 0);
+            av_assert0(leftBand   <= INT_MAX && leftBand   >= 0);
+            av_assert0(rightBand  <= INT_MAX && rightBand  >= 0);
 
             ost->topBand    = topBand;
             ost->bottomBand = bottomBand;
@@ -1673,15 +1704,15 @@ static int output_packet(AVInputStream *ist, int ist_index,
         }
 #if CONFIG_AVFILTER
         frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
-            !ist->out_video_filter || avfilter_poll_frame(ist->out_video_filter->inputs[0]);
+            !ist->output_video_filter || avfilter_poll_frame(ist->output_video_filter->inputs[0]);
 #endif
         /* if output time reached then transcode raw format,
            encode packets and output them */
         if (start_time == 0 || ist->pts >= start_time)
 #if CONFIG_AVFILTER
         while (frame_available) {
-            if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->out_video_filter)
-                get_filtered_video_pic(ist->out_video_filter, &ist->picref, &picture, &ist->pts);
+            if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->output_video_filter)
+                get_filtered_video_pic(ist->output_video_filter, &ist->picref, &picture, &ist->pts);
 #endif
             for(i=0;i<nb_ostreams;i++) {
                 int frame_size;
@@ -1694,14 +1725,15 @@ static int output_packet(AVInputStream *ist, int ist_index,
                     //ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE;
 
                     if (ost->encoding_needed) {
-                        assert(ist->decoding_needed);
+                        av_assert0(ist->decoding_needed);
                         switch(ost->st->codec->codec_type) {
                         case AVMEDIA_TYPE_AUDIO:
                             do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size);
                             break;
                         case AVMEDIA_TYPE_VIDEO:
 #if CONFIG_AVFILTER
-                            ost->st->codec->sample_aspect_ratio = ist->picref->pixel_aspect;
+                            if (ist->picref->video)
+                                ost->st->codec->sample_aspect_ratio = ist->picref->video->pixel_aspect;
 #endif
                             do_video_out(os, ost, ist, &picture, &frame_size);
                             if (vstats_filename && frame_size)
@@ -1775,7 +1807,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
 
 #if CONFIG_AVFILTER
             frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
-                              ist->out_video_filter && avfilter_poll_frame(ist->out_video_filter->inputs[0]);
+                              ist->output_video_filter && avfilter_poll_frame(ist->output_video_filter->inputs[0]);
             if(ist->picref)
                 avfilter_unref_buffer(ist->picref);
         }
@@ -2072,33 +2104,33 @@ static int transcode(AVFormatContext **output_files,
 
             } else {
                 int best_nb_frames=-1;
-                    /* get corresponding input stream index : we select the first one with the right type */
-                    found = 0;
-                    for(j=0;j<nb_istreams;j++) {
-                        int skip=0;
-                        ist = ist_table[j];
-                        if(opt_programid){
-                            int pi,si;
-                            AVFormatContext *f= input_files[ ist->file_index ];
-                            skip=1;
-                            for(pi=0; pi<f->nb_programs; pi++){
-                                AVProgram *p= f->programs[pi];
-                                if(p->id == opt_programid)
-                                    for(si=0; si<p->nb_stream_indexes; si++){
-                                        if(f->streams[ p->stream_index[si] ] == ist->st)
-                                            skip=0;
-                                    }
-                            }
+                /* get corresponding input stream index : we select the first one with the right type */
+                found = 0;
+                for(j=0;j<nb_istreams;j++) {
+                    int skip=0;
+                    ist = ist_table[j];
+                    if(opt_programid){
+                        int pi,si;
+                        AVFormatContext *f= input_files[ ist->file_index ];
+                        skip=1;
+                        for(pi=0; pi<f->nb_programs; pi++){
+                            AVProgram *p= f->programs[pi];
+                            if(p->id == opt_programid)
+                                for(si=0; si<p->nb_stream_indexes; si++){
+                                    if(f->streams[ p->stream_index[si] ] == ist->st)
+                                        skip=0;
+                                }
                         }
-                        if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip &&
-                            ist->st->codec->codec_type == ost->st->codec->codec_type) {
-                            if(best_nb_frames < ist->st->codec_info_nb_frames){
-                                best_nb_frames= ist->st->codec_info_nb_frames;
-                                ost->source_index = j;
-                                found = 1;
-                            }
+                    }
+                    if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip &&
+                        ist->st->codec->codec_type == ost->st->codec->codec_type) {
+                        if(best_nb_frames < ist->st->codec_info_nb_frames){
+                            best_nb_frames= ist->st->codec_info_nb_frames;
+                            ost->source_index = j;
+                            found = 1;
                         }
                     }
+                }
 
                 if (!found) {
                     if(! opt_programid) {
@@ -2329,7 +2361,7 @@ static int transcode(AVFormatContext **output_files,
     for(i=0;i<nb_ostreams;i++) {
         ost = ost_table[i];
         if (ost->encoding_needed) {
-            AVCodec *codec = output_codecs[i];
+            AVCodec *codec = i < nb_output_codecs ? output_codecs[i] : NULL;
             if (!codec)
                 codec = avcodec_find_encoder(ost->st->codec->codec_id);
             if (!codec) {
@@ -2352,7 +2384,7 @@ static int transcode(AVFormatContext **output_files,
     for(i=0;i<nb_istreams;i++) {
         ist = ist_table[i];
         if (ist->decoding_needed) {
-            AVCodec *codec = input_codecs[i];
+            AVCodec *codec = i < nb_input_codecs ? input_codecs[i] : NULL;
             if (!codec)
                 codec = avcodec_find_decoder(ist->st->codec->codec_id);
             if (!codec) {
@@ -2537,7 +2569,7 @@ static int transcode(AVFormatContext **output_files,
         }
 
         /* finish if limit size exhausted */
-        if (limit_filesize != 0 && limit_filesize < url_ftell(output_files[0]->pb))
+        if (limit_filesize != 0 && limit_filesize <= url_ftell(output_files[0]->pb))
             break;
 
         /* read a frame from it and output it in the fifo */
@@ -2576,7 +2608,8 @@ static int transcode(AVFormatContext **output_files,
         if (pkt.pts != AV_NOPTS_VALUE)
             pkt.pts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
 
-        if(input_files_ts_scale[file_index][pkt.stream_index]){
+        if (pkt.stream_index < nb_input_files_ts_scale[file_index]
+            && input_files_ts_scale[file_index][pkt.stream_index]){
             if(pkt.pts != AV_NOPTS_VALUE)
                 pkt.pts *= input_files_ts_scale[file_index][pkt.stream_index];
             if(pkt.dts != AV_NOPTS_VALUE)
@@ -3002,7 +3035,8 @@ static void opt_map(const char *arg)
     AVStreamMap *m;
     char *p;
 
-    m = &stream_maps[nb_stream_maps++];
+    stream_maps = grow_array(stream_maps, sizeof(*stream_maps), &nb_stream_maps, nb_stream_maps + 1);
+    m = &stream_maps[nb_stream_maps-1];
 
     m->file_index = strtol(arg, &p, 0);
     if (*p)
@@ -3049,6 +3083,7 @@ static void opt_input_ts_scale(const char *arg)
     if(stream >= MAX_STREAMS)
         ffmpeg_exit(1);
 
+    input_files_ts_scale[nb_input_files] = grow_array(input_files_ts_scale[nb_input_files], sizeof(*input_files_ts_scale[nb_input_files]), &nb_input_files_ts_scale[nb_input_files], stream + 1);
     input_files_ts_scale[nb_input_files][stream]= scale;
 }
 
@@ -3152,7 +3187,7 @@ static void opt_input_file(const char *filename)
     ap->channel = video_channel;
     ap->standard = video_standard;
 
-    set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM);
+    set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL);
 
     ic->video_codec_id   =
         find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0,
@@ -3230,20 +3265,27 @@ static void opt_input_file(const char *filename)
         AVStream *st = ic->streams[i];
         AVCodecContext *dec = st->codec;
         avcodec_thread_init(dec, thread_count);
+        input_codecs = grow_array(input_codecs, sizeof(*input_codecs), &nb_input_codecs, nb_input_codecs + 1);
         switch (dec->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
-            set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM);
+            input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(audio_codec_name);
+            set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
             //fprintf(stderr, "\nInput Audio channels: %d", dec->channels);
             channel_layout    = dec->channel_layout;
             audio_channels    = dec->channels;
             audio_sample_rate = dec->sample_rate;
             audio_sample_fmt  = dec->sample_fmt;
-            input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(audio_codec_name);
             if(audio_disable)
                 st->discard= AVDISCARD_ALL;
+            /* Note that av_find_stream_info can add more streams, and we
+             * currently have no chance of setting up lowres decoding
+             * early enough for them. */
+            if (dec->lowres)
+                audio_sample_rate >>= dec->lowres;
             break;
         case AVMEDIA_TYPE_VIDEO:
-            set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM);
+            input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(video_codec_name);
+            set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]);
             frame_height = dec->height;
             frame_width  = dec->width;
             if(ic->streams[i]->sample_aspect_ratio.num)
@@ -3274,7 +3316,6 @@ static void opt_input_file(const char *filename)
             frame_rate.num = rfps;
             frame_rate.den = rfps_base;
 
-            input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(video_codec_name);
             if(video_disable)
                 st->discard= AVDISCARD_ALL;
             else if(video_discard)
@@ -3283,13 +3324,12 @@ static void opt_input_file(const char *filename)
         case AVMEDIA_TYPE_DATA:
             break;
         case AVMEDIA_TYPE_SUBTITLE:
-            input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(subtitle_codec_name);
+            input_codecs[nb_input_codecs-1] = avcodec_find_decoder_by_name(subtitle_codec_name);
             if(subtitle_disable)
                 st->discard = AVDISCARD_ALL;
             break;
         case AVMEDIA_TYPE_ATTACHMENT:
         case AVMEDIA_TYPE_UNKNOWN:
-            nb_icodecs++;
             break;
         default:
             abort();
@@ -3353,13 +3393,29 @@ static void new_video_stream(AVFormatContext *oc)
     AVStream *st;
     AVCodecContext *video_enc;
     enum CodecID codec_id;
+    AVCodec *codec= NULL;
 
-    st = av_new_stream(oc, streamid_map[oc->nb_streams]);
+    st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
     if (!st) {
         fprintf(stderr, "Could not alloc stream\n");
         ffmpeg_exit(1);
     }
-    avcodec_get_context_defaults2(st->codec, AVMEDIA_TYPE_VIDEO);
+
+    output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
+    if(!video_stream_copy){
+        if (video_codec_name) {
+            codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1,
+                                         avcodec_opts[AVMEDIA_TYPE_VIDEO]->strict_std_compliance);
+            codec = avcodec_find_encoder_by_name(video_codec_name);
+            output_codecs[nb_output_codecs-1] = codec;
+        } else {
+            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
+            codec = avcodec_find_encoder(codec_id);
+        }
+    }
+
+    avcodec_get_context_defaults3(st->codec, codec);
+    bitstream_filters[nb_output_files] = grow_array(bitstream_filters[nb_output_files], sizeof(*bitstream_filters[nb_output_files]), &nb_bitstream_filters[nb_output_files], oc->nb_streams);
     bitstream_filters[nb_output_files][oc->nb_streams - 1]= video_bitstream_filters;
     video_bitstream_filters= NULL;
 
@@ -3388,22 +3444,10 @@ static void new_video_stream(AVFormatContext *oc)
     } else {
         const char *p;
         int i;
-        AVCodec *codec;
         AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1};
 
-        if (video_codec_name) {
-            codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1,
-                                         video_enc->strict_std_compliance);
-            codec = avcodec_find_encoder_by_name(video_codec_name);
-            output_codecs[nb_ocodecs] = codec;
-        } else {
-            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
-            codec = avcodec_find_encoder(codec_id);
-        }
-
         video_enc->codec_id = codec_id;
-
-        set_context_opts(video_enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
+        set_context_opts(video_enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
 
         if (codec && codec->supported_framerates && !force_fps)
             fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)];
@@ -3473,7 +3517,6 @@ static void new_video_stream(AVFormatContext *oc)
             }
         }
     }
-    nb_ocodecs++;
     if (video_language) {
         av_metadata_set2(&st->metadata, "language", video_language, 0);
         av_freep(&video_language);
@@ -3489,16 +3532,32 @@ static void new_video_stream(AVFormatContext *oc)
 static void new_audio_stream(AVFormatContext *oc)
 {
     AVStream *st;
+    AVCodec *codec= NULL;
     AVCodecContext *audio_enc;
     enum CodecID codec_id;
 
-    st = av_new_stream(oc, streamid_map[oc->nb_streams]);
+    st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
     if (!st) {
         fprintf(stderr, "Could not alloc stream\n");
         ffmpeg_exit(1);
     }
-    avcodec_get_context_defaults2(st->codec, AVMEDIA_TYPE_AUDIO);
 
+    output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
+    if(!audio_stream_copy){
+        if (audio_codec_name) {
+            codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1,
+                                         avcodec_opts[AVMEDIA_TYPE_AUDIO]->strict_std_compliance);
+            codec = avcodec_find_encoder_by_name(audio_codec_name);
+            output_codecs[nb_output_codecs-1] = codec;
+        } else {
+            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
+            codec = avcodec_find_encoder(codec_id);
+        }
+    }
+
+    avcodec_get_context_defaults3(st->codec, codec);
+
+    bitstream_filters[nb_output_files] = grow_array(bitstream_filters[nb_output_files], sizeof(*bitstream_filters[nb_output_files]), &nb_bitstream_filters[nb_output_files], oc->nb_streams);
     bitstream_filters[nb_output_files][oc->nb_streams - 1]= audio_bitstream_filters;
     audio_bitstream_filters= NULL;
 
@@ -3519,20 +3578,8 @@ static void new_audio_stream(AVFormatContext *oc)
         audio_enc->channels = audio_channels;
         audio_enc->sample_rate = audio_sample_rate;
     } else {
-        AVCodec *codec;
-
-        set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
-
-        if (audio_codec_name) {
-            codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1,
-                                         audio_enc->strict_std_compliance);
-            codec = avcodec_find_encoder_by_name(audio_codec_name);
-            output_codecs[nb_ocodecs] = codec;
-        } else {
-            codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO);
-            codec = avcodec_find_encoder(codec_id);
-        }
         audio_enc->codec_id = codec_id;
+        set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
 
         if (audio_qscale > QSCALE_NONE) {
             audio_enc->flags |= CODEC_FLAG_QSCALE;
@@ -3547,7 +3594,6 @@ static void new_audio_stream(AVFormatContext *oc)
         choose_sample_fmt(st, codec);
         choose_sample_rate(st, codec);
     }
-    nb_ocodecs++;
     audio_enc->time_base= (AVRational){1, audio_sample_rate};
     if (audio_language) {
         av_metadata_set2(&st->metadata, "language", audio_language, 0);
@@ -3563,19 +3609,30 @@ static void new_audio_stream(AVFormatContext *oc)
 static void new_subtitle_stream(AVFormatContext *oc)
 {
     AVStream *st;
+    AVCodec *codec=NULL;
     AVCodecContext *subtitle_enc;
 
-    st = av_new_stream(oc, streamid_map[oc->nb_streams]);
+    st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
     if (!st) {
         fprintf(stderr, "Could not alloc stream\n");
         ffmpeg_exit(1);
     }
-    avcodec_get_context_defaults2(st->codec, AVMEDIA_TYPE_SUBTITLE);
+    subtitle_enc = st->codec;
+    output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
+    if(!subtitle_stream_copy){
+        subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1,
+                                                   avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance);
+        codec= output_codecs[nb_output_codecs-1] = avcodec_find_encoder_by_name(subtitle_codec_name);
+    }
+    avcodec_get_context_defaults3(st->codec, codec);
 
+    bitstream_filters[nb_output_files] =
+        grow_array(bitstream_filters[nb_output_files],
+                   sizeof(*bitstream_filters[nb_output_files]),
+                   &nb_bitstream_filters[nb_output_files], oc->nb_streams);
     bitstream_filters[nb_output_files][oc->nb_streams - 1]= subtitle_bitstream_filters;
     subtitle_bitstream_filters= NULL;
 
-    subtitle_enc = st->codec;
     subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
 
     if(subtitle_codec_tag)
@@ -3584,12 +3641,8 @@ static void new_subtitle_stream(AVFormatContext *oc)
     if (subtitle_stream_copy) {
         st->stream_copy = 1;
     } else {
-        set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
-        subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1,
-                                                   subtitle_enc->strict_std_compliance);
-        output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name);
+        set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec);
     }
-    nb_ocodecs++;
 
     if (subtitle_language) {
         av_metadata_set2(&st->metadata, "language", subtitle_language, 0);
@@ -3601,7 +3654,7 @@ static void new_subtitle_stream(AVFormatContext *oc)
     subtitle_stream_copy = 0;
 }
 
-static void opt_new_audio_stream(void)
+static void opt_new_stream(const char *opt, const char *arg)
 {
     AVFormatContext *oc;
     if (nb_output_files <= 0) {
@@ -3609,29 +3662,11 @@ static void opt_new_audio_stream(void)
         ffmpeg_exit(1);
     }
     oc = output_files[nb_output_files - 1];
-    new_audio_stream(oc);
-}
 
-static void opt_new_video_stream(void)
-{
-    AVFormatContext *oc;
-    if (nb_output_files <= 0) {
-        fprintf(stderr, "At least one output file must be specified\n");
-        ffmpeg_exit(1);
-    }
-    oc = output_files[nb_output_files - 1];
-    new_video_stream(oc);
-}
-
-static void opt_new_subtitle_stream(void)
-{
-    AVFormatContext *oc;
-    if (nb_output_files <= 0) {
-        fprintf(stderr, "At least one output file must be specified\n");
-        ffmpeg_exit(1);
-    }
-    oc = output_files[nb_output_files - 1];
-    new_subtitle_stream(oc);
+    if      (!strcmp(opt, "newvideo"   )) new_video_stream   (oc);
+    else if (!strcmp(opt, "newaudio"   )) new_audio_stream   (oc);
+    else if (!strcmp(opt, "newsubtitle")) new_subtitle_stream(oc);
+    else av_assert0(0);
 }
 
 /* arg format is "output-stream-index:streamid-value". */
@@ -3652,6 +3687,7 @@ static void opt_streamid(const char *opt, const char *arg)
     }
     *p++ = '\0';
     idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
+    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);
 }
 
@@ -3801,9 +3837,9 @@ static void opt_output_file(const char *filename)
     oc->loop_output = loop_output;
     oc->flags |= AVFMT_FLAG_NONBLOCK;
 
-    set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM);
+    set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
 
-    memset(streamid_map, 0, sizeof(streamid_map));
+    nb_streamid_map = 0;
 }
 
 /* same option as mencoder */
@@ -3883,15 +3919,6 @@ static void opt_intra_matrix(const char *arg)
     parse_matrix_coeffs(intra_matrix, arg);
 }
 
-/**
- * Trivial log callback.
- * Only suitable for show_help and similar since it lacks prefix handling.
- */
-static void log_callback_help(void* ptr, int level, const char* fmt, va_list vl)
-{
-    vfprintf(stdout, fmt, vl);
-}
-
 static void show_usage(void)
 {
     printf("Hyper fast Audio and Video encoder\n");
@@ -3927,11 +3954,11 @@ static void show_help(void)
                       OPT_GRAB,
                       OPT_GRAB);
     printf("\n");
-    av_opt_show(avcodec_opts[0], NULL);
+    av_opt_show2(avcodec_opts[0], NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
     printf("\n");
-    av_opt_show(avformat_opts, NULL);
+    av_opt_show2(avformat_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
     printf("\n");
-    av_opt_show(sws_opts, NULL);
+    av_opt_show2(sws_opts, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
 }
 
 static void opt_target(const char *arg)
@@ -4258,7 +4285,7 @@ static const OptionDef options[] = {
     { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
     { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" },
     { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
-    { "newvideo", OPT_VIDEO, {(void*)opt_new_video_stream}, "add a new video stream to the current output stream" },
+    { "newvideo", OPT_VIDEO | OPT_FUNC2, {(void*)opt_new_stream}, "add a new video stream to the current output stream" },
     { "vlang", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void *)&video_language}, "set the ISO 639 language code (3 letters) of the current video stream" , "code" },
     { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
     { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&force_fps}, "force the selected framerate, disable the best supported framerate selection" },
@@ -4274,14 +4301,14 @@ static const OptionDef options[] = {
     { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
     { "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_tag}, "force audio tag/fourcc", "fourcc/tag" },
     { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
-    { "newaudio", OPT_AUDIO, {(void*)opt_new_audio_stream}, "add a new audio stream to the current output stream" },
+    { "newaudio", OPT_AUDIO | OPT_FUNC2, {(void*)opt_new_stream}, "add a new audio stream to the current output stream" },
     { "alang", HAS_ARG | OPT_STRING | OPT_AUDIO, {(void *)&audio_language}, "set the ISO 639 language code (3 letters) of the current audio stream" , "code" },
     { "sample_fmt", HAS_ARG | OPT_EXPERT | OPT_AUDIO, {(void*)opt_audio_sample_fmt}, "set sample format, 'list' as argument shows all the sample formats supported", "format" },
 
     /* subtitle options */
     { "sn", OPT_BOOL | OPT_SUBTITLE, {(void*)&subtitle_disable}, "disable subtitle" },
     { "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
-    { "newsubtitle", OPT_SUBTITLE, {(void*)opt_new_subtitle_stream}, "add a new subtitle stream to the current output stream" },
+    { "newsubtitle", OPT_SUBTITLE | OPT_FUNC2, {(void*)opt_new_stream}, "add a new subtitle stream to the current output stream" },
     { "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" },
     { "stag", HAS_ARG | OPT_EXPERT | OPT_SUBTITLE, {(void*)opt_subtitle_tag}, "force subtitle tag/fourcc", "fourcc/tag" },
 
@@ -4309,9 +4336,10 @@ static const OptionDef options[] = {
 
 int main(int argc, char **argv)
 {
-    int i;
     int64_t ti;
 
+    av_log_set_flags(AV_LOG_SKIP_REPEATED);
+
     avcodec_register_all();
 #if CONFIG_AVDEVICE
     avdevice_register_all();
@@ -4326,11 +4354,7 @@ int main(int argc, char **argv)
         url_set_interrupt_cb(decode_interrupt_cb);
 #endif
 
-    for(i=0; i<AVMEDIA_TYPE_NB; i++){
-        avcodec_opts[i]= avcodec_alloc_context2(i);
-    }
-    avformat_opts = avformat_alloc_context();
-    sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
+    init_opts();
 
     show_banner();