]> git.sesse.net Git - ffmpeg/blobdiff - ffmpeg.c
typo fixes: tempBlured --> tempBlurred
[ffmpeg] / ffmpeg.c
index 880f3794c2136ecdaab3dde7fbb27ba11974d777..7c8ff4910ed3aaeeb883af2afe437777c8d0f32d 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
 #undef NDEBUG
 #include <assert.h>
 
-#if !defined(INFINITY) && defined(HUGE_VAL)
-#define INFINITY HUGE_VAL
-#endif
-
 #undef exit
 
 static const char program_name[] = "FFmpeg";
@@ -115,7 +111,7 @@ static int frame_bottomBand = 0;
 static int frame_leftBand  = 0;
 static int frame_rightBand = 0;
 static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};
-static AVRational frame_rate = (AVRational) {25,1};
+static AVRational frame_rate = (AVRational) {0,0};
 static float video_qscale = 0;
 static int video_qdiff = 3;
 static uint16_t *intra_matrix = NULL;
@@ -125,8 +121,7 @@ static float video_rc_qsquish=1.0;
 static float video_rc_qmod_amp=0;
 static int video_rc_qmod_freq=0;
 #endif
-static char *video_rc_override_string=NULL;
-static char *video_rc_eq="tex^qComp";
+static const char *video_rc_override_string=NULL;
 static int video_disable = 0;
 static int video_discard = 0;
 static char *video_codec_name = NULL;
@@ -167,6 +162,7 @@ static char *str_title = NULL;
 static char *str_author = NULL;
 static char *str_copyright = NULL;
 static char *str_comment = NULL;
+static char *str_genre = NULL;
 static char *str_album = NULL;
 static int do_benchmark = 0;
 static int do_hex_dump = 0;
@@ -210,7 +206,7 @@ static uint64_t limit_filesize = 0; //
 static int pgmyuv_compatibility_hack=0;
 static float dts_delta_threshold = 10;
 
-static int sws_flags = SWS_BICUBIC;
+static unsigned int sws_flags = SWS_BICUBIC;
 
 static const char **opt_names;
 static int opt_name_count;
@@ -221,6 +217,7 @@ static int64_t timer_start;
 
 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];
 
 #define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
@@ -415,9 +412,14 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx
                                           &new_pkt.data, &new_pkt.size,
                                           pkt->data, pkt->size,
                                           pkt->flags & PKT_FLAG_KEY);
-        if(a){
+        if(a>0){
             av_free_packet(pkt);
             new_pkt.destruct= av_destruct_packet;
+        } else if(a<0){
+            fprintf(stderr, "%s failed for stream %d, codec %s",
+                    bsfc->filter->name, pkt->stream_index,
+                    avctx->codec ? avctx->codec->name : "copy");
+            print_error("", a);
         }
         *pkt= new_pkt;
 
@@ -445,6 +447,7 @@ static void do_audio_out(AVFormatContext *s,
 
     int size_out, frame_bytes, ret;
     AVCodecContext *enc= ost->st->codec;
+    AVCodecContext *dec= ist->st->codec;
 
     /* SC: dynamic allocation of buffers */
     if (!audio_buf)
@@ -454,6 +457,20 @@ static void do_audio_out(AVFormatContext *s,
     if (!audio_buf || !audio_out)
         return;               /* Should signal an error ! */
 
+    if (enc->channels != dec->channels)
+        ost->audio_resample = 1;
+
+    if (ost->audio_resample && !ost->resample) {
+        ost->resample = audio_resample_init(enc->channels,    dec->channels,
+                                            enc->sample_rate, dec->sample_rate);
+        if (!ost->resample) {
+            fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n",
+                    dec->channels, dec->sample_rate,
+                    enc->channels, enc->sample_rate);
+            exit(1);
+        }
+    }
+
     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);
@@ -515,6 +532,7 @@ static void do_audio_out(AVFormatContext *s,
     /* now encode as many frames as possible */
     if (enc->frame_size > 1) {
         /* output resampled raw samples */
+        av_fifo_realloc(&ost->fifo, av_fifo_size(&ost->fifo) + size_out + 1);
         av_fifo_write(&ost->fifo, buftmp, size_out);
 
         frame_bytes = enc->frame_size * 2 * enc->channels;
@@ -523,6 +541,8 @@ static void do_audio_out(AVFormatContext *s,
             AVPacket pkt;
             av_init_packet(&pkt);
 
+            //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
+
             ret = avcodec_encode_audio(enc, audio_out, audio_out_size,
                                        (short *)audio_buf);
             audio_size += ret;
@@ -567,6 +587,7 @@ static void do_audio_out(AVFormatContext *s,
             size_out = size_out >> 1;
             break;
         }
+        //FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
         ret = avcodec_encode_audio(enc, audio_out, size_out,
                                    (short *)buftmp);
         audio_size += ret;
@@ -712,6 +733,8 @@ static void do_video_out(AVFormatContext *s,
         //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
         if (vdelta < -1.1)
             nb_frames = 0;
+        else if (video_sync_method == 2)
+            ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
         else if (vdelta > 1.1)
             nb_frames = lrintf(vdelta);
 //fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, ost->sync_ipts, nb_frames);
@@ -782,10 +805,8 @@ static void do_video_out(AVFormatContext *s,
             enc->coded_frame = dec->coded_frame; //FIXME/XXX remove this hack
             pkt.data= (uint8_t *)final_picture;
             pkt.size=  sizeof(AVPicture);
-            if(dec->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);
-            if(dec->coded_frame && dec->coded_frame->key_frame)
-                pkt.flags |= PKT_FLAG_KEY;
+            pkt.pts= av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);
+            pkt.flags |= PKT_FLAG_KEY;
 
             write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
             enc->coded_frame = old_frame;
@@ -851,7 +872,6 @@ static void do_video_out(AVFormatContext *s,
 }
 
 static double psnr(double d){
-    if(d==0) return INFINITY;
     return -10.0*log(d)/log(10.0);
 }
 
@@ -935,7 +955,8 @@ static void print_report(AVFormatContext **output_files,
         enc = ost->st->codec;
         if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {
             snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",
-                    enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+                     enc->coded_frame && !ost->st->stream_copy ?
+                     enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
         }
         if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
             float t = (av_gettime()-timer_start) / 1000000.0;
@@ -943,7 +964,8 @@ static void print_report(AVFormatContext **output_files,
             frame_number = ost->frame_number;
             snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
                      frame_number, (t>1)?(int)(frame_number/t+0.5) : 0,
-                     enc->coded_frame ? enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
+                     enc->coded_frame && !ost->st->stream_copy ?
+                     enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1);
             if(is_last_report)
                 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
             if(qp_hist && enc->coded_frame){
@@ -1032,13 +1054,8 @@ static int output_packet(AVInputStream *ist, int ist_index,
     AVSubtitle subtitle, *subtitle_to_free;
     int got_subtitle;
 
-    if(!pkt){
-        ist->pts= ist->next_pts; // needed for last packet if vsync=0
-    } else if (pkt->dts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too
-        ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
-    } else {
-//        assert(ist->pts == ist->next_pts);
-    }
+    if(ist->next_pts == AV_NOPTS_VALUE)
+        ist->next_pts= ist->pts;
 
     if (pkt == NULL) {
         /* EOF handling */
@@ -1047,10 +1064,18 @@ static int output_packet(AVInputStream *ist, int ist_index,
         goto handle_eof;
     }
 
+    if(pkt->dts != AV_NOPTS_VALUE)
+        ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
+
     len = pkt->size;
     ptr = pkt->data;
     while (len > 0) {
     handle_eof:
+        ist->pts= ist->next_pts;
+
+        if(len && len != pkt->size && verbose>0)
+            fprintf(stderr, "Multiple frames in a packet from stream %d\n", pkt->stream_index);
+
         /* decode the packet if needed */
         data_buf = NULL; /* fail safe */
         data_size = 0;
@@ -1118,7 +1143,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
             switch(ist->st->codec->codec_type) {
             case CODEC_TYPE_AUDIO:
                 ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
-                    (ist->st->codec->sample_rate * ist->st->codec->channels);
+                    ist->st->codec->sample_rate;
                 break;
             case CODEC_TYPE_VIDEO:
                 if (ist->st->codec->time_base.num != 0) {
@@ -1254,7 +1279,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
                         if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY))
                             opkt.destruct= av_destruct_packet;
 
-                        write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][pkt->stream_index]);
+                        write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][opkt.stream_index]);
                         ost->st->codec->frame_number++;
                         ost->frame_number++;
                         av_free_packet(&opkt);
@@ -1399,7 +1424,7 @@ static int av_encode(AVFormatContext **output_files,
     int key;
     int want_sdp = 1;
 
-    file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile));
+    file_table= av_mallocz(nb_input_files * sizeof(AVInputFile));
     if (!file_table)
         goto fail;
 
@@ -1567,6 +1592,8 @@ static int av_encode(AVFormatContext **output_files,
             av_strlcpy(ost->st->language, ist->st->language,
                        sizeof(ost->st->language));
 
+        ost->st->disposition = ist->st->disposition;
+
         if (ost->st->stream_copy) {
             /* if stream_copy is selected, no need to decode or encode */
             codec->codec_id = icodec->codec_id;
@@ -1613,40 +1640,10 @@ static int av_encode(AVFormatContext **output_files,
         } else {
             switch(codec->codec_type) {
             case CODEC_TYPE_AUDIO:
-                if (av_fifo_init(&ost->fifo, 2 * MAX_AUDIO_PACKET_SIZE))
+                if (av_fifo_init(&ost->fifo, 1024))
                     goto fail;
-
-                if (codec->channels == icodec->channels &&
-                    codec->sample_rate == icodec->sample_rate) {
-                    ost->audio_resample = 0;
-                } else {
-                    if (codec->channels != icodec->channels &&
-                        (icodec->codec_id == CODEC_ID_AC3 ||
-                         icodec->codec_id == CODEC_ID_DTS)) {
-                        /* Special case for 5:1 AC3 and DTS input */
-                        /* and mono or stereo output      */
-                        /* Request specific number of channels */
-                        icodec->channels = codec->channels;
-                        if (codec->sample_rate == icodec->sample_rate)
-                            ost->audio_resample = 0;
-                        else {
-                            ost->audio_resample = 1;
-                        }
-                    } else {
-                        ost->audio_resample = 1;
-                    }
-                }
-                if(audio_sync_method>1)
-                    ost->audio_resample = 1;
-
-                if(ost->audio_resample){
-                    ost->resample = audio_resample_init(codec->channels, icodec->channels,
-                                                    codec->sample_rate, icodec->sample_rate);
-                    if(!ost->resample){
-                        printf("Can't resample.  Aborting.\n");
-                        abort();
-                    }
-                }
+                ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
+                icodec->request_channels = codec->channels;
                 ist->decoding_needed = 1;
                 ost->encoding_needed = 1;
                 break;
@@ -1830,10 +1827,7 @@ static int av_encode(AVFormatContext **output_files,
         ist = ist_table[i];
         is = input_files[ist->file_index];
         ist->pts = 0;
-        ist->next_pts=0;
-        if(   input_files_ts_offset[ist->file_index] != -is->start_time
-           && !(is->start_time == AV_NOPTS_VALUE && input_files_ts_offset[ist->file_index]==0))
-            ist->next_pts= AV_NOPTS_VALUE;
+        ist->next_pts = AV_NOPTS_VALUE;
         ist->is_start = 1;
     }
 
@@ -2075,7 +2069,7 @@ static int av_encode(AVFormatContext **output_files,
                 av_free(ost->pict_tmp.data[0]);
                 if (ost->video_resample)
                     sws_freeContext(ost->img_resample_ctx);
-                if (ost->audio_resample)
+                if (ost->resample)
                     audio_resample_close(ost->resample);
                 av_free(ost);
             }
@@ -2128,9 +2122,7 @@ static void opt_format(const char *arg)
     }
 }
 
-#if defined(CONFIG_FFM_DEMUXER) || defined(CONFIG_FFM_MUXER)
 extern int ffm_nopts;
-#endif
 
 static int opt_default(const char *opt, const char *arg){
     int type;
@@ -2170,16 +2162,11 @@ static int opt_default(const char *opt, const char *arg){
 #endif
 
     if(avctx_opts[0]->debug)
-        av_log_level = AV_LOG_DEBUG;
+        av_log_set_level(AV_LOG_DEBUG);
     return 0;
 }
 
-static void opt_video_rc_eq(char *arg)
-{
-    video_rc_eq = arg;
-}
-
-static void opt_video_rc_override_string(char *arg)
+static void opt_video_rc_override_string(const char *arg)
 {
     video_rc_override_string = arg;
 }
@@ -2192,7 +2179,7 @@ static void opt_me_threshold(const char *arg)
 static void opt_verbose(const char *arg)
 {
     verbose = atoi(arg);
-    av_log_level = atoi(arg);
+    av_log_set_level(verbose);
 }
 
 static void opt_frame_rate(const char *arg)
@@ -2203,7 +2190,7 @@ static void opt_frame_rate(const char *arg)
     }
 }
 
-static void opt_bitrate(const char *opt, const char *arg)
+static int opt_bitrate(const char *opt, const char *arg)
 {
     int codec_type = opt[0]=='a' ? CODEC_TYPE_AUDIO : CODEC_TYPE_VIDEO;
 
@@ -2211,6 +2198,8 @@ static void opt_bitrate(const char *opt, const char *arg)
 
     if (av_get_int(avctx_opts[codec_type], "b", NULL) < 1000)
         fprintf(stderr, "WARNING: The bitrate parameter is set too low. It takes bits/s as argument, not kbits/s\n");
+
+    return 0;
 }
 
 static void opt_frame_crop_top(const char *arg)
@@ -2408,16 +2397,17 @@ static void opt_frame_aspect_ratio(const char *arg)
     int x = 0, y = 0;
     double ar = 0;
     const char *p;
+    char *end;
 
     p = strchr(arg, ':');
     if (p) {
-        x = strtol(arg, (char **)&arg, 10);
-        if (arg == p)
-            y = strtol(arg+1, (char **)&arg, 10);
+        x = strtol(arg, &end, 10);
+        if (end == p)
+            y = strtol(end+1, &end, 10);
         if (x > 0 && y > 0)
             ar = (double)x / (double)y;
     } else
-        ar = strtod(arg, (char **)&arg);
+        ar = strtod(arg, NULL);
 
     if (!ar) {
         fprintf(stderr, "Incorrect aspect ratio specification.\n");
@@ -2555,22 +2545,21 @@ static void opt_subtitle_codec(const char *arg)
 static void opt_map(const char *arg)
 {
     AVStreamMap *m;
-    const char *p;
+    char *p;
 
-    p = arg;
     m = &stream_maps[nb_stream_maps++];
 
-    m->file_index = strtol(arg, (char **)&p, 0);
+    m->file_index = strtol(arg, &p, 0);
     if (*p)
         p++;
 
-    m->stream_index = strtol(p, (char **)&p, 0);
+    m->stream_index = strtol(p, &p, 0);
     if (*p) {
         p++;
-        m->sync_file_index = strtol(p, (char **)&p, 0);
+        m->sync_file_index = strtol(p, &p, 0);
         if (*p)
             p++;
-        m->sync_stream_index = strtol(p, (char **)&p, 0);
+        m->sync_stream_index = strtol(p, &p, 0);
     } else {
         m->sync_file_index = m->file_index;
         m->sync_stream_index = m->stream_index;
@@ -2580,52 +2569,55 @@ static void opt_map(const char *arg)
 static void opt_map_meta_data(const char *arg)
 {
     AVMetaDataMap *m;
-    const char *p;
+    char *p;
 
-    p = arg;
     m = &meta_data_maps[nb_meta_data_maps++];
 
-    m->out_file = strtol(arg, (char **)&p, 0);
+    m->out_file = strtol(arg, &p, 0);
     if (*p)
         p++;
 
-    m->in_file = strtol(p, (char **)&p, 0);
+    m->in_file = strtol(p, &p, 0);
 }
 
-static int64_t parse_time_or_die(const char *timestr, int is_duration)
+static int64_t parse_time_or_die(const char *context, const char *timestr, int is_duration)
 {
     int64_t us = parse_date(timestr, is_duration);
     if (us == INT64_MIN) {
-        fprintf(stderr, "Invalid %s specification: %s\n",
-                is_duration ? "duration" : "date", timestr);
+        fprintf(stderr, "Invalid %s specification for %s: %s\n",
+                is_duration ? "duration" : "date", context, timestr);
         exit(1);
     }
     return us;
 }
 
-static void opt_recording_time(const char *arg)
+static int opt_recording_time(const char *opt, const char *arg)
 {
-    recording_time = parse_time_or_die(arg, 1);
+    recording_time = parse_time_or_die(opt, arg, 1);
+    return 0;
 }
 
-static void opt_start_time(const char *arg)
+static int opt_start_time(const char *opt, const char *arg)
 {
-    start_time = parse_time_or_die(arg, 1);
+    start_time = parse_time_or_die(opt, arg, 1);
+    return 0;
 }
 
-static void opt_rec_timestamp(const char *arg)
+static int opt_rec_timestamp(const char *opt, const char *arg)
 {
-    rec_timestamp = parse_time_or_die(arg, 0) / 1000000;
+    rec_timestamp = parse_time_or_die(opt, arg, 0) / 1000000;
+    return 0;
 }
 
-static void opt_input_ts_offset(const char *arg)
+static int opt_input_ts_offset(const char *opt, const char *arg)
 {
-    input_ts_offset = parse_time_or_die(arg, 1);
+    input_ts_offset = parse_time_or_die(opt, arg, 1);
+    return 0;
 }
 
 static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
 {
-    char *codec_string = encoder ? "encoder" : "decoder";
+    const char *codec_string = encoder ? "encoder" : "decoder";
     AVCodec *codec;
 
     if(!name)
@@ -2677,11 +2669,17 @@ static void opt_input_file(const char *filename)
         ap->video_codec_id= CODEC_ID_PGMYUV;
 
     for(i=0; i<opt_name_count; i++){
+        char buf[256];
         const AVOption *opt;
-        double d= av_get_double(avformat_opts, opt_names[i], &opt);
-        if(!isnan(d) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
-            av_set_double(ic, opt_names[i], d);
+        const char *str= av_get_string(avformat_opts, opt_names[i], &opt, buf, sizeof(buf));
+        if(str && (opt->flags & AV_OPT_FLAG_DECODING_PARAM))
+            av_set_string(ic, opt_names[i], str);
     }
+
+    ic->video_codec_id   = find_codec_or_die(video_codec_name   , CODEC_TYPE_VIDEO   , 0);
+    ic->audio_codec_id   = find_codec_or_die(audio_codec_name   , CODEC_TYPE_AUDIO   , 0);
+    ic->subtitle_codec_id= find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 0);
+
     /* open the input file with generic libav function */
     err = av_open_input_file(&ic, filename, file_iformat, 0, ap);
     if (err < 0) {
@@ -2731,10 +2729,11 @@ static void opt_input_file(const char *filename)
         switch(enc->codec_type) {
         case CODEC_TYPE_AUDIO:
             for(j=0; j<opt_name_count; j++){
+                char buf[256];
                 const AVOption *opt;
-                double d= av_get_double(avctx_opts[CODEC_TYPE_AUDIO], opt_names[j], &opt);
-                if(!isnan(d) && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
-                    av_set_double(enc, opt_names[j], d);
+                const char *str= av_get_string(avctx_opts[CODEC_TYPE_AUDIO], opt_names[j], &opt, buf, sizeof(buf));
+                if(str && (opt->flags & AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags & AV_OPT_FLAG_DECODING_PARAM))
+                    av_set_string(enc, opt_names[j], str);
             }
             //fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
             audio_channels = enc->channels;
@@ -2744,10 +2743,11 @@ static void opt_input_file(const char *filename)
             break;
         case CODEC_TYPE_VIDEO:
             for(j=0; j<opt_name_count; j++){
+                char buf[256];
                 const AVOption *opt;
-                double d= av_get_double(avctx_opts[CODEC_TYPE_VIDEO], opt_names[j], &opt);
-                if(!isnan(d) && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
-                    av_set_double(enc, opt_names[j], d);
+                const char *str= av_get_string(avctx_opts[CODEC_TYPE_VIDEO], opt_names[j], &opt, buf, sizeof(buf));
+                if(str && (opt->flags & AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags & AV_OPT_FLAG_DECODING_PARAM))
+                    av_set_string(enc, opt_names[j], str);
             }
             frame_height = enc->height;
             frame_width = enc->width;
@@ -2783,6 +2783,7 @@ static void opt_input_file(const char *filename)
             if(subtitle_disable)
                 ic->streams[i]->discard = AVDISCARD_ALL;
             break;
+        case CODEC_TYPE_ATTACHMENT:
         case CODEC_TYPE_UNKNOWN:
             break;
         default:
@@ -2803,6 +2804,9 @@ static void opt_input_file(const char *filename)
     video_channel = 0;
 
     rate_emu = 0;
+    av_freep(&video_codec_name);
+    av_freep(&audio_codec_name);
+    av_freep(&subtitle_codec_name);
 }
 
 static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
@@ -2829,6 +2833,7 @@ static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
                 has_subtitle = 1;
                 break;
             case CODEC_TYPE_DATA:
+            case CODEC_TYPE_ATTACHMENT:
             case CODEC_TYPE_UNKNOWN:
                 break;
             default:
@@ -2878,9 +2883,10 @@ static void new_video_stream(AVFormatContext *oc)
         st->stream_copy = 1;
         video_enc->codec_type = CODEC_TYPE_VIDEO;
     } else {
-        char *p;
+        const char *p;
         int i;
         AVCodec *codec;
+        AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1};
 
         codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
         if (video_codec_name)
@@ -2890,21 +2896,21 @@ static void new_video_stream(AVFormatContext *oc)
         codec = avcodec_find_encoder(codec_id);
 
         for(i=0; i<opt_name_count; i++){
-             const AVOption *opt;
-             double d= av_get_double(avctx_opts[CODEC_TYPE_VIDEO], opt_names[i], &opt);
-             if(!isnan(d) && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
-                 av_set_double(video_enc, opt_names[i], d);
+            char buf[256];
+            const AVOption *opt;
+            const char *str= av_get_string(avctx_opts[CODEC_TYPE_VIDEO], opt_names[i], &opt, buf, sizeof(buf));
+            if(str && (opt->flags & AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM))
+                av_set_string(video_enc, opt_names[i], str);
         }
 
-        video_enc->time_base.den = frame_rate.num;
-        video_enc->time_base.num = frame_rate.den;
+        video_enc->time_base.den = fps.num;
+        video_enc->time_base.num = fps.den;
         if(codec && codec->supported_framerates){
             const AVRational *p= codec->supported_framerates;
-            AVRational req= (AVRational){frame_rate.num, frame_rate.den};
             const AVRational *best=NULL;
             AVRational best_error= (AVRational){INT_MAX, 1};
             for(; p->den!=0; p++){
-                AVRational error= av_sub_q(req, *p);
+                AVRational error= av_sub_q(fps, *p);
                 if(error.num <0) error.num *= -1;
                 if(av_cmp_q(error, best_error) < 0){
                     best_error= error;
@@ -2944,7 +2950,6 @@ static void new_video_stream(AVFormatContext *oc)
             video_enc->inter_matrix = inter_matrix;
 
         video_enc->max_qdiff = video_qdiff;
-        video_enc->rc_eq = video_rc_eq;
         video_enc->thread_count = thread_count;
         p= video_rc_override_string;
         for(i=0; p; i++){
@@ -3033,10 +3038,11 @@ static void new_audio_stream(AVFormatContext *oc)
         codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_AUDIO);
 
         for(i=0; i<opt_name_count; i++){
+            char buf[256];
             const AVOption *opt;
-            double d= av_get_double(avctx_opts[CODEC_TYPE_AUDIO], opt_names[i], &opt);
-            if(!isnan(d) && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
-                av_set_double(audio_enc, opt_names[i], d);
+            const char *str= av_get_string(avctx_opts[CODEC_TYPE_AUDIO], opt_names[i], &opt, buf, sizeof(buf));
+            if(str && (opt->flags & AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM))
+                av_set_string(audio_enc, opt_names[i], str);
         }
 
         if (audio_codec_name)
@@ -3077,16 +3083,20 @@ static void new_subtitle_stream(AVFormatContext *oc)
     }
     avcodec_get_context_defaults2(st->codec, CODEC_TYPE_SUBTITLE);
 
+    bitstream_filters[nb_output_files][oc->nb_streams - 1]= subtitle_bitstream_filters;
+    subtitle_bitstream_filters= NULL;
+
     subtitle_enc = st->codec;
     subtitle_enc->codec_type = CODEC_TYPE_SUBTITLE;
     if (subtitle_stream_copy) {
         st->stream_copy = 1;
     } else {
         for(i=0; i<opt_name_count; i++){
-             const AVOption *opt;
-             double d= av_get_double(avctx_opts[CODEC_TYPE_SUBTITLE], opt_names[i], &opt);
-             if(!isnan(d) && (opt->flags&AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
-                 av_set_double(subtitle_enc, opt_names[i], d);
+            char buf[256];
+            const AVOption *opt;
+            const char *str= av_get_string(avctx_opts[CODEC_TYPE_SUBTITLE], opt_names[i], &opt, buf, sizeof(buf));
+            if(str && (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM))
+                av_set_string(subtitle_enc, opt_names[i], str);
         }
         subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 1);
     }
@@ -3220,6 +3230,8 @@ static void opt_output_file(const char *filename)
             av_strlcpy(oc->comment, str_comment, sizeof(oc->comment));
         if (str_album)
             av_strlcpy(oc->album, str_album, sizeof(oc->album));
+        if (str_genre)
+            av_strlcpy(oc->genre, str_genre, sizeof(oc->genre));
     }
 
     output_files[nb_output_files++] = oc;
@@ -3236,6 +3248,7 @@ static void opt_output_file(const char *filename)
         /* test if it already exists to avoid loosing precious files */
         if (!file_overwrite &&
             (strchr(filename, ':') == NULL ||
+             filename[1] == ':' ||
              av_strstart(filename, "file:", NULL))) {
             if (url_exist(filename)) {
                 int c;
@@ -3275,10 +3288,11 @@ static void opt_output_file(const char *filename)
     oc->loop_output = loop_output;
 
     for(i=0; i<opt_name_count; i++){
+        char buf[256];
         const AVOption *opt;
-        double d = av_get_double(avformat_opts, opt_names[i], &opt);
-        if(!isnan(d) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
-            av_set_double(oc, opt_names[i], d);
+        const char *str= av_get_string(avformat_opts, opt_names[i], &opt, buf, sizeof(buf));
+        if(str && (opt->flags & AV_OPT_FLAG_ENCODING_PARAM))
+            av_set_string(oc, opt_names[i], str);
     }
 
     /* reset some options */
@@ -3318,10 +3332,11 @@ static int64_t getutime(void)
 
 static void opt_show_formats(void)
 {
-    AVInputFormat *ifmt;
-    AVOutputFormat *ofmt;
-    URLProtocol *up;
-    AVCodec *p, *p2;
+    AVInputFormat *ifmt=NULL;
+    AVOutputFormat *ofmt=NULL;
+    URLProtocol *up=NULL;
+    AVCodec *p=NULL, *p2;
+    AVBitStreamFilter *bsf=NULL;
     const char *last_name;
 
     printf("File formats:\n");
@@ -3332,7 +3347,7 @@ static void opt_show_formats(void)
         const char *name=NULL;
         const char *long_name=NULL;
 
-        for(ofmt = first_oformat; ofmt != NULL; ofmt = ofmt->next) {
+        while((ofmt= av_oformat_next(ofmt))) {
             if((name == NULL || strcmp(ofmt->name, name)<0) &&
                 strcmp(ofmt->name, last_name)>0){
                 name= ofmt->name;
@@ -3340,7 +3355,7 @@ static void opt_show_formats(void)
                 encode=1;
             }
         }
-        for(ifmt = first_iformat; ifmt != NULL; ifmt = ifmt->next) {
+        while((ifmt= av_iformat_next(ifmt))) {
             if((name == NULL || strcmp(ifmt->name, name)<0) &&
                 strcmp(ifmt->name, last_name)>0){
                 name= ifmt->name;
@@ -3372,7 +3387,7 @@ static void opt_show_formats(void)
         const char *type_str;
 
         p2=NULL;
-        for(p = first_avcodec; p != NULL; p = p->next) {
+        while((p= av_codec_next(p))) {
             if((p2==NULL || strcmp(p->name, p2->name)<0) &&
                 strcmp(p->name, last_name)>0){
                 p2= p;
@@ -3417,8 +3432,13 @@ static void opt_show_formats(void)
     }
     printf("\n");
 
+    printf("Bitstream filters:\n");
+    while((bsf = av_bitstream_filter_next(bsf)))
+        printf(" %s", bsf->name);
+    printf("\n");
+
     printf("Supported file protocols:\n");
-    for(up = first_protocol; up != NULL; up = up->next)
+    while((up = av_protocol_next(up)))
         printf(" %s:", up->name);
     printf("\n");
 
@@ -3673,7 +3693,7 @@ static void opt_vstats (void)
     opt_vstats_file(filename);
 }
 
-static void opt_bsf(const char *opt, const char *arg)
+static int opt_bsf(const char *opt, const char *arg)
 {
     AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
     AVBitStreamFilterContext **bsfp;
@@ -3683,11 +3703,15 @@ static void opt_bsf(const char *opt, const char *arg)
         exit(1);
     }
 
-    bsfp= *opt == 'v' ? &video_bitstream_filters : &audio_bitstream_filters;
+    bsfp= *opt == 'v' ? &video_bitstream_filters :
+          *opt == 'a' ? &audio_bitstream_filters :
+                        &subtitle_bitstream_filters;
     while(*bsfp)
         bsfp= &(*bsfp)->next;
 
     *bsfp= bsfc;
+
+    return 0;
 }
 
 static void opt_show_license(void)
@@ -3713,15 +3737,16 @@ const OptionDef options[] = {
     { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
     { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
     { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
-    { "t", HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" },
+    { "t", OPT_FUNC2 | HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" },
     { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, //
-    { "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
-    { "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" },
+    { "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
+    { "itsoffset", OPT_FUNC2 | HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" },
     { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" },
-    { "timestamp", HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp", "time" },
+    { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp", "time" },
     { "author", HAS_ARG | OPT_STRING, {(void*)&str_author}, "set the author", "string" },
     { "copyright", HAS_ARG | OPT_STRING, {(void*)&str_copyright}, "set the copyright", "string" },
     { "comment", HAS_ARG | OPT_STRING, {(void*)&str_comment}, "set the comment", "string" },
+    { "genre", HAS_ARG | OPT_STRING, {(void*)&str_genre}, "set the genre", "string" },
     { "album", HAS_ARG | OPT_STRING, {(void*)&str_album}, "set the album", "string" },
     { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
       "add timings for benchmarking" },
@@ -3732,7 +3757,7 @@ const OptionDef options[] = {
     { "re", OPT_BOOL | OPT_EXPERT, {(void*)&rate_emu}, "read input at native frame rate", "" },
     { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "loop (current only works with images)" },
     { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "number of times to loop output in formats that support looping (0 loops forever)", "" },
-    { "v", HAS_ARG, {(void*)opt_verbose}, "control amount of logging", "verbose" },
+    { "v", HAS_ARG, {(void*)opt_verbose}, "set the logging verbosity level", "number" },
     { "target", HAS_ARG, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
     { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
     { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
@@ -3767,7 +3792,6 @@ const OptionDef options[] = {
     { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
     { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" },
     { "qdiff", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qdiff}, "max difference between the quantizer scale (VBR)", "q" },
-    { "rc_eq", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_eq}, "set rate control equation", "equation" },
     { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" },
     { "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
     { "me_threshold", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold",  "" },
@@ -3822,6 +3846,7 @@ const OptionDef options[] = {
 
     { "absf", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream filter" },
     { "vbsf", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream filter" },
+    { "sbsf", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_bsf}, "", "bitstream filter" },
 
     { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
     { NULL, },