]> git.sesse.net Git - ffmpeg/blobdiff - ffmpeg.c
ffplay: consider estimated time of filter in early frame drop
[ffmpeg] / ffmpeg.c
index b7964cf79ad069a2d26f9a02b8675668374ec87e..347c324a9d37a9d149e4727f55768db6ce7471ad 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -146,7 +146,7 @@ static int audio_volume = 256;
 static int exit_on_error = 0;
 static int using_stdin = 0;
 static int run_as_daemon  = 0;
-static volatile int q_pressed = 0;
+static volatile int received_nb_signals = 0;
 static int64_t video_size = 0;
 static int64_t audio_size = 0;
 static int64_t extra_size = 0;
@@ -156,6 +156,8 @@ static int input_sync;
 
 static float dts_delta_threshold = 10;
 
+static int print_stats = 1;
+
 static uint8_t *audio_buf;
 static uint8_t *audio_out;
 static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
@@ -185,10 +187,10 @@ typedef struct InputStream {
 typedef struct InputFile {
     AVFormatContext *ctx;
     int eof_reached;      /* true if eof reached */
-    int ist_index;        /* index of first stream in ist_table */
+    int ist_index;        /* index of first stream in input_streams */
     int buffer_size;      /* current total buffer size */
     int64_t ts_offset;
-    int nb_streams;       /* number of stream that avconv is aware of; may be different
+    int nb_streams;       /* number of stream that ffmpeg is aware of; may be different
                              from ctx.nb_streams if new streams appear during av_read_frame() */
     int rate_emu;
 } InputFile;
@@ -245,7 +247,7 @@ typedef struct OutputStream {
     AVFilterGraph *graph;
 #endif
 
-   int sws_flags;
+   int64_t sws_flags;
    AVDictionary *opts;
    int is_past_recording_time;
 } OutputStream;
@@ -353,6 +355,8 @@ typedef struct OptionsContext {
     int        nb_inter_matrices;
     SpecifierOpt *top_field_first;
     int        nb_top_field_first;
+    SpecifierOpt *presets;
+    int        nb_presets;
 #if CONFIG_AVFILTER
     SpecifierOpt *filters;
     int        nb_filters;
@@ -458,7 +462,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
         snprintf(args, 255, "%d:%d:flags=0x%X",
                  codec->width,
                  codec->height,
-                 ost->sws_flags);
+                 (unsigned)ost->sws_flags);
         if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
                                                 NULL, args, NULL, ost->graph)) < 0)
             return ret;
@@ -467,7 +471,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
         last_filter = filter;
     }
 
-    snprintf(args, sizeof(args), "flags=0x%X", ost->sws_flags);
+    snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
     ost->graph->scale_sws_opts = av_strdup(args);
 
     if (ost->avfilter) {
@@ -520,7 +524,7 @@ static volatile int received_sigterm = 0;
 static void sigterm_handler(int sig)
 {
     received_sigterm = sig;
-    q_pressed++;
+    received_nb_signals++;
     term_exit();
 }
 
@@ -564,9 +568,6 @@ static int read_key(void)
     struct timeval tv;
     fd_set rfds;
 
-    if(run_as_daemon)
-        return -1;
-
     FD_ZERO(&rfds);
     FD_SET(0, &rfds);
     tv.tv_sec = 0;
@@ -612,21 +613,9 @@ static int read_key(void)
     return -1;
 }
 
-static int read_yn(void)
-{
-    int c;
-#if HAVE_TERMIOS_H || HAVE_KBHIT
-    while((c=read_key()) < 0);
-#else
-    c= getchar();
-#endif
-
-    return (toupper(c) == 'Y');
-}
-
 static int decode_interrupt_cb(void)
 {
-    return q_pressed > 1;
+    return received_nb_signals > 1;
 }
 
 void exit_program(int ret)
@@ -1381,7 +1370,7 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost,
 
 static void print_report(OutputFile *output_files,
                          OutputStream *ost_table, int nb_ostreams,
-                         int is_last_report, int64_t timer_start)
+                         int is_last_report, int64_t timer_start, int64_t cur_time)
 {
     char buf[1024];
     OutputStream *ost;
@@ -1395,10 +1384,10 @@ static void print_report(OutputFile *output_files,
     static int qp_histogram[52];
     int hours, mins, secs, us;
 
+    if (!print_stats && !is_last_report)
+        return;
+
     if (!is_last_report) {
-        int64_t cur_time;
-        /* display the report every 0.5 seconds */
-        cur_time = av_gettime();
         if (last_time == -1) {
             last_time = cur_time;
             return;
@@ -1427,7 +1416,7 @@ static void print_report(OutputFile *output_files,
             snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
         }
         if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
-            float t = (av_gettime()-timer_start) / 1000000.0;
+            float t = (cur_time-timer_start) / 1000000.0;
 
             frame_number = ost->frame_number;
             snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
@@ -1491,7 +1480,7 @@ static void print_report(OutputFile *output_files,
         snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
                 nb_frames_dup, nb_frames_drop);
 
-    av_log(NULL, is_last_report ? AV_LOG_WARNING : AV_LOG_INFO, "%s    \r", buf);
+    av_log(NULL, AV_LOG_INFO, "%s    \r", buf);
 
     fflush(stderr);
 
@@ -1689,7 +1678,6 @@ static int output_packet(InputStream *ist, int ist_index,
                     (ist->st->codec->sample_rate * ist->st->codec->channels);
                 break;}
             case AVMEDIA_TYPE_VIDEO:
-                    decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
                     if (!(decoded_frame = avcodec_alloc_frame()))
                         return AVERROR(ENOMEM);
                     avpkt.pts = pkt_pts;
@@ -2161,6 +2149,8 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
         } else {
             if (!ost->enc)
                 ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
+            ist->decoding_needed = 1;
+            ost->encoding_needed = 1;
             switch(codec->codec_type) {
             case AVMEDIA_TYPE_AUDIO:
                 ost->fifo= av_fifo_alloc(1024);
@@ -2185,8 +2175,6 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
                 ost->audio_resample |=    codec->sample_fmt     != icodec->sample_fmt
                                        || codec->channel_layout != icodec->channel_layout;
                 icodec->request_channels = codec->channels;
-                ist->decoding_needed = 1;
-                ost->encoding_needed = 1;
                 ost->resample_sample_fmt  = icodec->sample_fmt;
                 ost->resample_sample_rate = icodec->sample_rate;
                 ost->resample_channels    = icodec->channels;
@@ -2216,8 +2204,6 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
                 ost->resample_height = icodec->height;
                 ost->resample_width  = icodec->width;
                 ost->resample_pix_fmt= icodec->pix_fmt;
-                ost->encoding_needed = 1;
-                ist->decoding_needed = 1;
 
                 if (!ost->frame_rate.num)
                     ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25,1};
@@ -2244,15 +2230,13 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
 #endif
                 break;
             case AVMEDIA_TYPE_SUBTITLE:
-                ost->encoding_needed = 1;
-                ist->decoding_needed = 1;
                 break;
             default:
                 abort();
                 break;
             }
             /* two pass mode */
-            if (ost->encoding_needed && codec->codec_id != CODEC_ID_H264 &&
+            if (codec->codec_id != CODEC_ID_H264 &&
                 (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
                 char logfilename[1024];
                 FILE *f;
@@ -2326,7 +2310,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
             assert_avoptions(ost->opts);
             if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000)
                 av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
-                                             "It takes bits/s as argument, not kbits/s\n");
+                                             " It takes bits/s as argument, not kbits/s\n");
             extra_size += ost->st->codec->extradata_size;
 
             if (ost->st->codec->me_threshold)
@@ -2444,15 +2428,21 @@ static int transcode(OutputFile *output_files, int nb_output_files,
         AVPacket pkt;
         int64_t ipts_min;
         double opts_min;
+        int64_t cur_time= av_gettime();
 
         ipts_min= INT64_MAX;
         opts_min= 1e100;
         /* if 'q' pressed, exits */
         if (!using_stdin) {
-            if (q_pressed)
+            static int64_t last_time;
+            if (received_nb_signals)
                 break;
             /* read_key() returns 0 on EOF */
-            key = read_key();
+            if(cur_time - last_time >= 100000 && !run_as_daemon){
+                key =  read_key();
+                last_time = cur_time;
+            }else
+                key = -1;
             if (key == 'q')
                 break;
             if (key == '+') av_log_set_level(av_log_get_level()+10);
@@ -2653,7 +2643,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
         av_free_packet(&pkt);
 
         /* dump report by using the output first video and audio streams */
-        print_report(output_files, output_streams, nb_output_streams, 0, timer_start);
+        print_report(output_files, output_streams, nb_output_streams, 0, timer_start, cur_time);
     }
 
     /* at the end of stream, we must flush the decoder buffers */
@@ -2674,7 +2664,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
     }
 
     /* dump report by using the first video and audio streams */
-    print_report(output_files, output_streams, nb_output_streams, 1, timer_start);
+    print_report(output_files, output_streams, nb_output_streams, 1, timer_start, av_gettime());
 
     /* close each encoder */
     for (i = 0; i < nb_output_streams; i++) {
@@ -2728,12 +2718,6 @@ static int transcode(OutputFile *output_files, int nb_output_files,
     return ret;
 }
 
-static int opt_verbose(const char *opt, const char *arg)
-{
-    av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -loglevel\n", opt);
-    return 0;
-}
-
 static int opt_frame_crop(const char *opt, const char *arg)
 {
     av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the crop filter instead\n", opt);
@@ -3006,6 +2990,7 @@ static AVCodec *choose_codec(OptionsContext *o, AVFormatContext *s, AVStream *st
 static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
 {
     int i, rfps, rfps_base;
+    char *next, *codec_tag = NULL;
 
     for (i = 0; i < ic->nb_streams; i++) {
         AVStream *st = ic->streams[i];
@@ -3023,6 +3008,14 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
         MATCH_PER_STREAM_OPT(ts_scale, dbl, scale, ic, st);
         ist->ts_scale = scale;
 
+        MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
+        if (codec_tag) {
+            uint32_t tag = strtol(codec_tag, &next, 0);
+            if (*next)
+                tag = AV_RL32(codec_tag);
+            st->codec->codec_tag = tag;
+        }
+
         ist->dec = choose_codec(o, ic, st, dec->codec_type);
         if (!ist->dec)
             ist->dec = avcodec_find_decoder(dec->codec_id);
@@ -3118,6 +3111,12 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena
     if (o->nb_frame_pix_fmts)
         av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
 
+    ic->video_codec_id   =
+        find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0);
+    ic->audio_codec_id   =
+        find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0);
+    ic->subtitle_codec_id=
+        find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
     ic->flags |= AVFMT_FLAG_NONBLOCK;
 
     if (loop_input) {
@@ -3205,21 +3204,71 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost)
     }
 }
 
+static uint8_t *get_line(AVIOContext *s)
+{
+    AVIOContext *line;
+    uint8_t *buf;
+    char c;
+
+    if (avio_open_dyn_buf(&line) < 0) {
+        av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n");
+        exit_program(1);
+    }
+
+    while ((c = avio_r8(s)) && c != '\n')
+        avio_w8(line, c);
+    avio_w8(line, 0);
+    avio_close_dyn_buf(line, &buf);
+
+    return buf;
+}
+
+static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s)
+{
+    int i, ret = 1;
+    char filename[1000];
+    const char *base[3] = { getenv("AVCONV_DATADIR"),
+                            getenv("HOME"),
+                            AVCONV_DATADIR,
+                            };
+
+    for (i = 0; i < FF_ARRAY_ELEMS(base) && ret; i++) {
+        if (!base[i])
+            continue;
+        if (codec_name) {
+            snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i],
+                     i != 1 ? "" : "/.avconv", codec_name, preset_name);
+            ret = avio_open(s, filename, AVIO_FLAG_READ);
+        }
+        if (ret) {
+            snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
+                     i != 1 ? "" : "/.avconv", preset_name);
+            ret = avio_open(s, filename, AVIO_FLAG_READ);
+        }
+    }
+    return ret;
+}
+
 static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type)
 {
     OutputStream *ost;
-    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;
+    AVStream *st = avformat_new_stream(oc, NULL);
+    int idx      = oc->nb_streams - 1, ret = 0;
     int64_t max_frames = INT64_MAX;
     char *bsf = NULL, *next, *codec_tag = NULL;
     AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL;
     double qscale = -1;
+    char *buf = NULL, *arg = NULL, *preset = NULL;
+    AVIOContext *s = NULL;
 
     if (!st) {
         av_log(NULL, AV_LOG_FATAL, "Could not alloc stream.\n");
         exit_program(1);
     }
 
+    if (oc->nb_streams - 1 < o->nb_streamid_map)
+        st->id = o->streamid_map[oc->nb_streams - 1];
+
     output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams,
                                 nb_output_streams + 1);
     ost = &output_streams[nb_output_streams - 1];
@@ -3235,6 +3284,31 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     avcodec_get_context_defaults3(st->codec, ost->enc);
     st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
 
+    MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
+    if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) {
+        do  {
+            buf = get_line(s);
+            if (!buf[0] || buf[0] == '#') {
+                av_free(buf);
+                continue;
+            }
+            if (!(arg = strchr(buf, '='))) {
+                av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
+                exit_program(1);
+            }
+            *arg++ = 0;
+            av_dict_set(&ost->opts, buf, arg, AV_DICT_DONT_OVERWRITE);
+            av_free(buf);
+        } while (!s->eof_reached);
+        avio_close(s);
+    }
+    if (ret) {
+        av_log(NULL, AV_LOG_FATAL,
+               "Preset %s specified for stream %d:%d, but could not be opened.\n",
+               preset, ost->file_index, ost->index);
+        exit_program(1);
+    }
+
     MATCH_PER_STREAM_OPT(max_frames, i64, max_frames, oc, st);
     ost->max_frames = max_frames;
 
@@ -3272,7 +3346,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
         st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
 
-    ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
+    av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags);
     return ost;
 }
 
@@ -3710,11 +3784,12 @@ static void opt_output_file(void *optctx, const char *filename)
                 if (!using_stdin) {
                     fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
                     fflush(stderr);
-                    if (!read_yn()) {
-                        av_log(0, AV_LOG_FATAL, "\nNot overwriting - exiting\n");
+                    term_exit();
+                    if (!read_yesno()) {
+                        av_log(0, AV_LOG_FATAL, "Not overwriting - exiting\n");
                         exit_program(1);
                     }
-                    fprintf(stderr,"\n");
+                    term_init();
                 }
                 else {
                     av_log(0, AV_LOG_FATAL,"File '%s' already exists. Exiting.\n", filename);
@@ -3918,11 +3993,7 @@ static void show_usage(void)
 
 static int opt_help(const char *opt, const char *arg)
 {
-    AVCodec *c;
-    AVOutputFormat *oformat = NULL;
-    AVInputFormat  *iformat = NULL;
-    const AVClass *class;
-
+    int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
     av_log_set_callback(log_callback_help);
     show_usage();
     show_help_options(options, "Main options:\n",
@@ -3949,41 +4020,10 @@ static int opt_help(const char *opt, const char *arg)
                       OPT_GRAB,
                       OPT_GRAB);
     printf("\n");
-    class = avcodec_get_class();
-    av_opt_show2(&class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
-    printf("\n");
-
-    /* individual codec options */
-    c = NULL;
-    while ((c = av_codec_next(c))) {
-        if (c->priv_class) {
-            av_opt_show2(&c->priv_class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
-            printf("\n");
-        }
-    }
-
-    class = avformat_get_class();
-    av_opt_show2(&class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
-    printf("\n");
-
-    /* individual muxer options */
-    while ((oformat = av_oformat_next(oformat))) {
-        if (oformat->priv_class) {
-            av_opt_show2(&oformat->priv_class, NULL, AV_OPT_FLAG_ENCODING_PARAM, 0);
-            printf("\n");
-        }
-    }
-
-    /* individual demuxer options */
-    while ((iformat = av_iformat_next(iformat))) {
-        if (iformat->priv_class) {
-            av_opt_show2(&iformat->priv_class, NULL, AV_OPT_FLAG_DECODING_PARAM, 0);
-            printf("\n");
-        }
-    }
+    show_help_children(avcodec_get_class(), flags);
+    show_help_children(avformat_get_class(), flags);
+    show_help_children(sws_get_class(), flags);
 
-    class = sws_get_class();
-    av_opt_show2(&class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
     return 0;
 }
 
@@ -4246,6 +4286,7 @@ static const OptionDef options[] = {
     { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
     { "c", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
     { "codec", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
+    { "pre", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(presets)}, "preset name", "preset" },
     { "map", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map}, "set input stream mapping", "file.stream[:syncfile.syncstream]" },
     { "map_meta_data", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map_meta_data}, "DEPRECATED set meta data information of outfile from infile",
       "outfile[,metadata]:infile[,metadata]" },
@@ -4270,7 +4311,6 @@ static const OptionDef options[] = {
     { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" },
     { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "deprecated, use -loop" },
     { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "deprecated, use -loop", "" },
-    { "v", HAS_ARG, {(void*)opt_verbose}, "deprecated, use -loglevel instead", "number" },
     { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
     { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
     { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
@@ -4288,6 +4328,7 @@ static const OptionDef options[] = {
 #if CONFIG_AVFILTER
     { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
 #endif
+    { "stats", OPT_BOOL, {&print_stats}, "print progress report during encoding", },
 
     /* video options */
     { "vframes", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_frames}, "set the number of video frames to record", "number" },