]> git.sesse.net Git - ffmpeg/blobdiff - avconv.c
pcmdec: use unique classes for all pcm demuxers.
[ffmpeg] / avconv.c
index d81a118f75d54b6fdf8117427567a4a6c8b0e6ac..74120c8c5e1e3ffe7382f60f924e6e768523dbee 100644 (file)
--- a/avconv.c
+++ b/avconv.c
@@ -97,28 +97,16 @@ typedef struct MetadataMap {
 
 static const OptionDef options[];
 
-/* indexed by output file stream index */
-static int *streamid_map = NULL;
-static int nb_streamid_map = 0;
-
-static uint16_t *intra_matrix = NULL;
-static uint16_t *inter_matrix = NULL;
 static int video_discard = 0;
 static int same_quant = 0;
 static int do_deinterlace = 0;
-static int top_field_first = -1;
-static int me_threshold = 0;
 static int intra_dc_precision = 8;
 static int qp_hist = 0;
-#if CONFIG_AVFILTER
-static char *vfilters = NULL;
-#endif
 
 static int file_overwrite = 0;
 static int do_benchmark = 0;
 static int do_hex_dump = 0;
 static int do_pkt_dump = 0;
-static int do_psnr = 0;
 static int do_pass = 0;
 static char *pass_logfilename_prefix = NULL;
 static int video_sync_method= -1;
@@ -207,6 +195,7 @@ typedef struct OutputStream {
     int resample_pix_fmt;
     AVRational frame_rate;
     int force_fps;
+    int top_field_first;
 
     float frame_aspect_ratio;
 
@@ -306,6 +295,10 @@ typedef struct OptionsContext {
     int subtitle_disable;
     int data_disable;
 
+    /* indexed by output file stream index */
+    int   *streamid_map;
+    int nb_streamid_map;
+
     SpecifierOpt *metadata;
     int        nb_metadata;
     SpecifierOpt *max_frames;
@@ -326,6 +319,16 @@ typedef struct OptionsContext {
     int        nb_frame_aspect_ratios;
     SpecifierOpt *rc_overrides;
     int        nb_rc_overrides;
+    SpecifierOpt *intra_matrices;
+    int        nb_intra_matrices;
+    SpecifierOpt *inter_matrices;
+    int        nb_inter_matrices;
+    SpecifierOpt *top_field_first;
+    int        nb_top_field_first;
+#if CONFIG_AVFILTER
+    SpecifierOpt *filters;
+    int        nb_filters;
+#endif
 } OptionsContext;
 
 #define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
@@ -365,6 +368,7 @@ static void reset_options(OptionsContext *o)
 
     av_freep(&o->stream_maps);
     av_freep(&o->meta_data_maps);
+    av_freep(&o->streamid_map);
 
     memset(o, 0, sizeof(*o));
 
@@ -512,9 +516,6 @@ void exit_program(int ret)
     for (i = 0; i < nb_input_streams; i++)
         av_dict_free(&input_streams[i].opts);
 
-    av_free(intra_matrix);
-    av_free(inter_matrix);
-
     if (vstats_file)
         fclose(vstats_file);
     av_free(vstats_filename);
@@ -1208,16 +1209,16 @@ static void do_video_out(AVFormatContext *s,
                settings */
             big_picture.interlaced_frame = in_picture->interlaced_frame;
             if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) {
-                if(top_field_first == -1)
+                if (ost->top_field_first == -1)
                     big_picture.top_field_first = in_picture->top_field_first;
                 else
-                    big_picture.top_field_first = top_field_first;
+                    big_picture.top_field_first = !!ost->top_field_first;
             }
 
             /* handles same_quant here. This is not correct because it may
                not be a global option */
             big_picture.quality = quality;
-            if(!me_threshold)
+            if (!enc->me_threshold)
                 big_picture.pict_type = 0;
 //            big_picture.pts = AV_NOPTS_VALUE;
             big_picture.pts= ost->sync_opts;
@@ -2187,6 +2188,9 @@ static int transcode_init(OutputFile *output_files,
                 av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
                                              "It takes bits/s as argument, not kbits/s\n");
             extra_size += ost->st->codec->extradata_size;
+
+            if (ost->st->codec->me_threshold)
+                input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV;
         }
     }
 
@@ -2502,12 +2506,6 @@ static int transcode(OutputFile *output_files,
     return ret;
 }
 
-static int opt_me_threshold(const char *opt, const char *arg)
-{
-    me_threshold = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
-    return 0;
-}
-
 static int opt_verbose(const char *opt, const char *arg)
 {
     verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10);
@@ -2538,12 +2536,6 @@ static double parse_frame_aspect_ratio(const char *arg)
     return ar;
 }
 
-static int opt_top_field_first(const char *opt, const char *arg)
-{
-    top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1);
-    return 0;
-}
-
 static int opt_audio_codec(OptionsContext *o, const char *opt, const char *arg)
 {
     return parse_option(o, "codec:a", arg, options);
@@ -2779,8 +2771,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
                 dec->height >>= dec->lowres;
                 dec->width  >>= dec->lowres;
             }
-            if(me_threshold)
-                dec->debug |= FF_DEBUG_MV;
 
             if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) {
 
@@ -2945,7 +2935,7 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
 static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type)
 {
     OutputStream *ost;
-    AVStream *st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
+    AVStream *st = av_new_stream(oc, oc->nb_streams < o->nb_streamid_map ? o->streamid_map[oc->nb_streams] : 0);
     int idx      = oc->nb_streams - 1;
     int64_t max_frames = INT64_MAX;
     char *bsf = NULL, *next, *codec_tag = NULL;
@@ -3010,6 +3000,23 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     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) {
+            fprintf(stderr, "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;
@@ -3018,13 +3025,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
 
     ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO);
     st  = ost->st;
-    if (!st->stream_copy) {
-#if CONFIG_AVFILTER
-        ost->avfilter= vfilters;
-        vfilters = NULL;
-#endif
-    }
-
     video_enc = st->codec;
 
     if(oc->oformat->flags & AVFMT_GLOBALHEADER) {
@@ -3035,7 +3035,8 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
         const char *p = NULL;
         char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL;
         char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
-        int i, force_fps = 0;
+        char *intra_matrix = NULL, *inter_matrix = NULL, *filters = NULL;
+        int i, force_fps = 0, top_field_first = -1;
 
         MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
         if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) {
@@ -3060,10 +3061,22 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
         }
         st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
 
-        if(intra_matrix)
-            video_enc->intra_matrix = intra_matrix;
-        if(inter_matrix)
-            video_enc->inter_matrix = inter_matrix;
+        MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st);
+        if (intra_matrix) {
+            if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) {
+                av_log(NULL, AV_LOG_ERROR, "Could not allocate memory for intra matrix.\n");
+                exit_program(1);
+            }
+            parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix);
+        }
+        MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st);
+        if (inter_matrix) {
+            if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) {
+                av_log(NULL, AV_LOG_ERROR, "Could not allocate memory for inter matrix.\n");
+                exit_program(1);
+            }
+            parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix);
+        }
 
         MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st);
         for(i=0; p; i++){
@@ -3092,12 +3105,8 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
         video_enc->rc_override_count=i;
         if (!video_enc->rc_initial_buffer_occupancy)
             video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4;
-        video_enc->me_threshold= me_threshold;
         video_enc->intra_dc_precision= intra_dc_precision - 8;
 
-        if (do_psnr)
-            video_enc->flags|= CODEC_FLAG_PSNR;
-
         /* two pass mode */
         if (do_pass) {
             if (do_pass == 1) {
@@ -3113,6 +3122,15 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
 
         MATCH_PER_STREAM_OPT(force_fps, i, force_fps, oc, st);
         ost->force_fps = force_fps;
+
+        MATCH_PER_STREAM_OPT(top_field_first, i, top_field_first, oc, st);
+        ost->top_field_first = top_field_first;
+
+#if CONFIG_AVFILTER
+        MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
+        if (filters)
+            ost->avfilter = av_strdup(filters);
+#endif
     }
 
     return ost;
@@ -3192,7 +3210,7 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc)
 }
 
 /* arg format is "output-stream-index:streamid-value". */
-static int opt_streamid(const char *opt, const char *arg)
+static int opt_streamid(OptionsContext *o, const char *opt, const char *arg)
 {
     int idx;
     char *p;
@@ -3208,8 +3226,8 @@ static int opt_streamid(const char *opt, const char *arg)
     }
     *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);
+    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;
 }
 
@@ -3471,7 +3489,7 @@ static void opt_output_file(void *optctx, const char *filename)
     }
     if (o->chapters_input_file >= 0)
         copy_chapters(&input_files[o->chapters_input_file], &output_files[nb_output_files - 1],
-                      o->metadata_chapters_manual);
+                      !o->metadata_chapters_manual);
 
     /* copy metadata */
     for (i = 0; i < o->nb_meta_data_maps; i++) {
@@ -3553,14 +3571,14 @@ static void opt_output_file(void *optctx, const char *filename)
                 av_log(NULL, AV_LOG_ERROR, "Invalid stream index %d in metadata specifier.\n", index);
                 exit_program(1);
             }
-            m = &oc->streams[i]->metadata;
+            m = &oc->streams[index]->metadata;
             break;
         case 'c':
             if (index < 0 || index >= oc->nb_chapters) {
                 av_log(NULL, AV_LOG_ERROR, "Invalid chapter index %d in metadata specifier.\n", index);
                 exit_program(1);
             }
-            m = &oc->chapters[i]->metadata;
+            m = &oc->chapters[index]->metadata;
             break;
         default:
             av_log(NULL, AV_LOG_ERROR, "Invalid metadata specifier %s.\n", o->metadata[i].specifier);
@@ -3570,9 +3588,6 @@ static void opt_output_file(void *optctx, const char *filename)
         av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0);
     }
 
-    av_freep(&streamid_map);
-    nb_streamid_map = 0;
-
     reset_options(o);
 }
 
@@ -3619,35 +3634,6 @@ static int64_t getmaxrss(void)
 #endif
 }
 
-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) {
-            fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i);
-            exit_program(1);
-        }
-        p++;
-    }
-}
-
-static void opt_inter_matrix(const char *arg)
-{
-    inter_matrix = av_mallocz(sizeof(uint16_t) * 64);
-    parse_matrix_coeffs(inter_matrix, arg);
-}
-
-static void opt_intra_matrix(const char *arg)
-{
-    intra_matrix = av_mallocz(sizeof(uint16_t) * 64);
-    parse_matrix_coeffs(intra_matrix, arg);
-}
-
 static int opt_audio_qscale(OptionsContext *o, const char *opt, const char *arg)
 {
     return parse_option(o, "q:a", arg, options);
@@ -3914,6 +3900,11 @@ static int opt_subtitle_tag(OptionsContext *o, const char *opt, const char *arg)
     return parse_option(o, "tag:s", arg, options);
 }
 
+static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg)
+{
+    return parse_option(o, "filter:v", arg, options);
+}
+
 #define OFFSET(x) offsetof(OptionsContext, x)
 static const OptionDef options[] = {
     /* main options */
@@ -3957,6 +3948,9 @@ static const OptionDef options[] = {
     { "tag",   OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" },
     { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" },
     { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" },
+#if CONFIG_AVFILTER
+    { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
+#endif
 
     /* video options */
     { "vframes", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_frames}, "set the number of video frames to record", "number" },
@@ -3968,27 +3962,25 @@ static const OptionDef options[] = {
     { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
     { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(rc_overrides)}, "rate control override for specific intervals", "override" },
     { "vcodec", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(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 estimation threshold",  "threshold" },
     { "same_quant", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant},
       "use same quantizer as source (implies VBR)" },
     { "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" },
     { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" },
     { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace},
       "deinterlace pictures" },
-    { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
     { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
     { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
 #if CONFIG_AVFILTER
-    { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
+    { "vf", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_filters}, "video filters", "filter list" },
 #endif
-    { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
-    { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
-    { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
+    { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(intra_matrices)}, "specify intra matrix coeffs", "matrix" },
+    { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(inter_matrices)}, "specify inter matrix coeffs", "matrix" },
+    { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_INT| OPT_SPEC, {.off = OFFSET(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 | OPT_FUNC2, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
     { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
     { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO | OPT_SPEC, {.off = OFFSET(force_fps)}, "force the selected framerate, disable the best supported framerate selection" },
-    { "streamid", HAS_ARG | OPT_EXPERT, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" },
+    { "streamid", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" },
     { "force_key_frames", OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_SPEC, {.off = OFFSET(forced_key_frames)}, "force key frames at specified timestamps", "timestamps" },
 
     /* audio options */