Skip to content
Snippets Groups Projects
ffmpeg.c 139 KiB
Newer Older
  • Learn to ignore specific revisions
  •         st->stream_copy = 1;
            video_enc->codec_type = CODEC_TYPE_VIDEO;
    
            video_enc->sample_aspect_ratio =
    
            st->sample_aspect_ratio = av_d2q(frame_aspect_ratio*frame_height/frame_width, 255);
    
            const char *p;
    
            AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1};
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
            if (video_codec_name) {
    
                codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 1);
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
                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, CODEC_TYPE_VIDEO);
                codec = avcodec_find_encoder(codec_id);
            }
    
            set_context_opts(video_enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
    
            if (codec && codec->supported_framerates && !force_fps)
                fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)];
    
            video_enc->time_base.den = fps.num;
            video_enc->time_base.num = fps.den;
    
            video_enc->width = frame_width + frame_padright + frame_padleft;
            video_enc->height = frame_height + frame_padtop + frame_padbottom;
    
            video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255);
    
            st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
    
    
            if(codec && codec->pix_fmts){
                const enum PixelFormat *p= codec->pix_fmts;
                for(; *p!=-1; p++){
                    if(*p == video_enc->pix_fmt)
                        break;
                }
                if(*p == -1)
                    video_enc->pix_fmt = codec->pix_fmts[0];
            }
    
    
                video_enc->gop_size = 0;
            if (video_qscale || same_quality) {
                video_enc->flags |= CODEC_FLAG_QSCALE;
    
                video_enc->global_quality=
    
                    st->quality = FF_QP2LAMBDA * video_qscale;
            }
    
            if(intra_matrix)
                video_enc->intra_matrix = intra_matrix;
            if(inter_matrix)
                video_enc->inter_matrix = inter_matrix;
    
            video_enc->thread_count = thread_count;
            p= video_rc_override_string;
            for(i=0; p; i++){
                int start, end, q;
                int e=sscanf(p, "%d,%d,%d", &start, &end, &q);
                if(e!=3){
                    fprintf(stderr, "error parsing rc_override\n");
    
                video_enc->rc_override=
                    av_realloc(video_enc->rc_override,
    
                               sizeof(RcOverride)*(i+1));
                video_enc->rc_override[i].start_frame= start;
                video_enc->rc_override[i].end_frame  = end;
                if(q>0){
                    video_enc->rc_override[i].qscale= q;
                    video_enc->rc_override[i].quality_factor= 1.0;
                }
                else{
                    video_enc->rc_override[i].qscale= 0;
                    video_enc->rc_override[i].quality_factor= -q/100.0;
                }
                p= strchr(p, '/');
                if(p) p++;
            }
            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) {
                    video_enc->flags |= CODEC_FLAG_PASS1;
                } else {
                    video_enc->flags |= CODEC_FLAG_PASS2;
                }
            }
        }
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
        nb_ocodecs++;
    
    
        /* reset some key parameters */
        video_disable = 0;
    
        video_stream_copy = 0;
    }
    
    static void new_audio_stream(AVFormatContext *oc)
    {
        AVStream *st;
        AVCodecContext *audio_enc;
    
        int codec_id;
    
        st = av_new_stream(oc, oc->nb_streams);
        if (!st) {
            fprintf(stderr, "Could not alloc stream\n");
    
        avcodec_get_context_defaults2(st->codec, CODEC_TYPE_AUDIO);
    
    
        bitstream_filters[nb_output_files][oc->nb_streams - 1]= audio_bitstream_filters;
        audio_bitstream_filters= NULL;
    
    
            avcodec_thread_init(st->codec, thread_count);
    
        audio_enc->codec_type = CODEC_TYPE_AUDIO;
    
        if(audio_codec_tag)
            audio_enc->codec_tag= audio_codec_tag;
    
        if (oc->oformat->flags & AVFMT_GLOBALHEADER) {
    
            audio_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
    
            avctx_opts[CODEC_TYPE_AUDIO]->flags|= CODEC_FLAG_GLOBAL_HEADER;
    
        if (audio_stream_copy) {
            st->stream_copy = 1;
            audio_enc->channels = audio_channels;
        } else {
    
            set_context_opts(audio_enc, avctx_opts[CODEC_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
            if (audio_codec_name) {
    
                codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1);
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
                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, CODEC_TYPE_AUDIO);
                codec = avcodec_find_encoder(codec_id);
            }
    
            if (audio_qscale > QSCALE_NONE) {
                audio_enc->flags |= CODEC_FLAG_QSCALE;
                audio_enc->global_quality = st->quality = FF_QP2LAMBDA * audio_qscale;
            }
    
            audio_enc->thread_count = thread_count;
    
            audio_enc->channels = audio_channels;
    
            audio_enc->sample_fmt = audio_sample_fmt;
    
            audio_enc->channel_layout = channel_layout;
    
    
            if(codec && codec->sample_fmts){
                const enum SampleFormat *p= codec->sample_fmts;
                for(; *p!=-1; p++){
                    if(*p == audio_enc->sample_fmt)
                        break;
                }
                if(*p == -1)
                    audio_enc->sample_fmt = codec->sample_fmts[0];
            }
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
        nb_ocodecs++;
    
        audio_enc->sample_rate = audio_sample_rate;
    
        audio_enc->time_base= (AVRational){1, audio_sample_rate};
    
            av_strlcpy(st->language, audio_language, sizeof(st->language));
    
            av_free(audio_language);
            audio_language = NULL;
        }
    
        /* reset some key parameters */
        audio_disable = 0;
    
    static void new_subtitle_stream(AVFormatContext *oc)
    
        st = av_new_stream(oc, oc->nb_streams);
        if (!st) {
            fprintf(stderr, "Could not alloc stream\n");
    
        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->codec_type = CODEC_TYPE_SUBTITLE;
        if (subtitle_stream_copy) {
            st->stream_copy = 1;
        } else {
    
            set_context_opts(avctx_opts[CODEC_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, CODEC_TYPE_SUBTITLE, 1);
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
            output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name);
    
    Aurelien Jacobs's avatar
    Aurelien Jacobs committed
        nb_ocodecs++;
    
            av_strlcpy(st->language, subtitle_language, sizeof(st->language));
    
            av_free(subtitle_language);
            subtitle_language = NULL;
        }
    
    
        subtitle_stream_copy = 0;
    }
    
    static void opt_new_audio_stream(void)
    {
        AVFormatContext *oc;
        if (nb_output_files <= 0) {
            fprintf(stderr, "At least one output file must be specified\n");
    
        }
        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");
    
        }
        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");
    
        }
        oc = output_files[nb_output_files - 1];
        new_subtitle_stream(oc);
    }
    
    
    static void opt_output_file(const char *filename)
    {
        AVFormatContext *oc;
    
        int use_video, use_audio, use_subtitle;
    
        int input_has_video, input_has_audio, input_has_subtitle;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        if (!strcmp(filename, "-"))
            filename = "pipe:";
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (!file_oformat) {
            file_oformat = guess_format(NULL, filename, NULL);
            if (!file_oformat) {
    
                fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        av_strlcpy(oc->filename, filename, sizeof(oc->filename));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (!strcmp(file_oformat->name, "ffm") &&
    
            av_strstart(filename, "http:", NULL)) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* special case for files sent to ffserver: we get the stream
               parameters from ffserver */
    
            int err = read_ffserver_streams(oc, filename);
            if (err < 0) {
                print_error(filename, err);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        } else {
    
            use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
            use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
            use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
    
            /* disable if no corresponding type found and at least one
               input file */
            if (nb_input_files > 0) {
    
                check_audio_video_sub_inputs(&input_has_video, &input_has_audio,
                                             &input_has_subtitle);
    
                if (!input_has_video)
                    use_video = 0;
                if (!input_has_audio)
                    use_audio = 0;
    
                if (!input_has_subtitle)
                    use_subtitle = 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (audio_disable) {
                use_audio = 0;
            }
            if (video_disable) {
                use_video = 0;
            }
    
            if (subtitle_disable) {
                use_subtitle = 0;
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (use_video) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (use_audio) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
    
    
            if (use_subtitle) {
                new_subtitle_stream(oc);
            }
    
    
                av_strlcpy(oc->title, str_title, sizeof(oc->title));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (str_author)
    
                av_strlcpy(oc->author, str_author, sizeof(oc->author));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (str_copyright)
    
                av_strlcpy(oc->copyright, str_copyright, sizeof(oc->copyright));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            if (str_comment)
    
                av_strlcpy(oc->comment, str_comment, sizeof(oc->comment));
    
                av_strlcpy(oc->album, str_album, sizeof(oc->album));
    
            if (str_genre)
                av_strlcpy(oc->genre, str_genre, sizeof(oc->genre));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
        output_files[nb_output_files++] = oc;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* check filename in case of an image number is expected */
    
        if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
    
                print_error(oc->filename, AVERROR_NUMEXPECTED);
    
        if (!(oc->oformat->flags & AVFMT_NOFILE)) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* test if it already exists to avoid loosing precious files */
    
            if (!file_overwrite &&
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                (strchr(filename, ':') == NULL ||
    
                 av_strstart(filename, "file:", NULL))) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                if (url_exist(filename)) {
                    int c;
    
                        fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
                        fflush(stderr);
                        c = getchar();
                        if (toupper(c) != 'Y') {
                            fprintf(stderr, "Not overwriting - exiting\n");
    
                        fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                }
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            /* open the file */
            if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
                fprintf(stderr, "Could not open '%s'\n", filename);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            }
        }
    
    
        memset(ap, 0, sizeof(*ap));
        if (av_set_parameters(oc, ap) < 0) {
            fprintf(stderr, "%s: Invalid encoding parameters\n",
                    oc->filename);
    
        oc->preload= (int)(mux_preload*AV_TIME_BASE);
        oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
    
        oc->loop_output = loop_output;
    
        set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* reset some options */
    
        file_oformat = NULL;
        file_iformat = NULL;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    /* same option as mencoder */
    
    static void opt_pass(const char *pass_str)
    
    {
        int pass;
        pass = atoi(pass_str);
        if (pass != 1 && pass != 2) {
            fprintf(stderr, "pass number can be only 1 or 2\n");
    
    static int64_t getutime(void)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        struct rusage rusage;
    
        getrusage(RUSAGE_SELF, &rusage);
        return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
    
    #elif HAVE_GETPROCESSTIMES
    
        HANDLE proc;
        FILETIME c, e, k, u;
        proc = GetCurrentProcess();
        GetProcessTimes(proc, &c, &e, &k, &u);
        return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
    #else
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        return av_gettime();
    
    Ramiro Polla's avatar
    Ramiro Polla committed
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    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);
    
    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);
    }
    
    
    /**
     * 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_help(void)
    {
        av_log_set_callback(log_callback_help);
        printf("usage: ffmpeg [[infile options] -i infile]... {[outfile options] outfile}...\n"
               "Hyper fast Audio and Video encoder\n");
        printf("\n");
        show_help_options(options, "Main options:\n",
    
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, 0);
    
        show_help_options(options, "\nAdvanced options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB,
                          OPT_EXPERT);
    
        show_help_options(options, "\nVideo options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_VIDEO);
        show_help_options(options, "\nAdvanced Video options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_VIDEO | OPT_EXPERT);
        show_help_options(options, "\nAudio options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_AUDIO);
        show_help_options(options, "\nAdvanced Audio options:\n",
                          OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB,
                          OPT_AUDIO | OPT_EXPERT);
        show_help_options(options, "\nSubtitle options:\n",
                          OPT_SUBTITLE | OPT_GRAB,
                          OPT_SUBTITLE);
        show_help_options(options, "\nAudio/Video grab options:\n",
                          OPT_GRAB,
                          OPT_GRAB);
    
        av_opt_show(avctx_opts[0], NULL);
    
        av_opt_show(avformat_opts, NULL);
    
    static void opt_target(const char *arg)
    {
        int norm = -1;
    
        static const char *const frame_rates[] = {"25", "30000/1001", "24000/1001"};
    
    
        if(!strncmp(arg, "pal-", 4)) {
            norm = 0;
            arg += 4;
        } else if(!strncmp(arg, "ntsc-", 5)) {
            norm = 1;
            arg += 5;
    
        } else if(!strncmp(arg, "film-", 5)) {
            norm = 2;
            arg += 5;
    
        } else {
            int fr;
            /* Calculate FR via float to avoid int overflow */
    
            fr = (int)(frame_rate.num * 1000.0 / frame_rate.den);
    
            if(fr == 25000) {
                norm = 0;
            } else if((fr == 29970) || (fr == 23976)) {
                norm = 1;
            } else {
                /* Try to determine PAL/NTSC by peeking in the input files */
                if(nb_input_files) {
                    int i, j;
                    for(j = 0; j < nb_input_files; j++) {
                        for(i = 0; i < input_files[j]->nb_streams; i++) {
    
                            AVCodecContext *c = input_files[j]->streams[i]->codec;
    
                            if(c->codec_type != CODEC_TYPE_VIDEO)
                                continue;
    
                            fr = c->time_base.den * 1000 / c->time_base.num;
    
                            if(fr == 25000) {
                                norm = 0;
                                break;
                            } else if((fr == 29970) || (fr == 23976)) {
                                norm = 1;
                                break;
                            }
                        }
                        if(norm >= 0)
                            break;
                    }
                }
            }
            if(verbose && norm >= 0)
    
                fprintf(stderr, "Assuming %s for target.\n", norm ? "NTSC" : "PAL");
    
            fprintf(stderr, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n");
            fprintf(stderr, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n");
    
            fprintf(stderr, "or set a framerate with \"-r xxx\".\n");
    
        }
    
        if(!strcmp(arg, "vcd")) {
    
            opt_video_codec("mpeg1video");
            opt_audio_codec("mp2");
            opt_format("vcd");
    
            opt_frame_size(norm ? "352x240" : "352x288");
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
            opt_default("gop", norm ? "18" : "15");
    
            opt_default("maxrate", "1150000");
            opt_default("minrate", "1150000");
    
            opt_default("bufsize", "327680"); // 40*1024*8;
    
            audio_channels = 2;
    
            opt_default("packetsize", "2324");
    
            opt_default("muxrate", "1411200"); // 2352 * 75 * 8;
    
            /* We have to offset the PTS, so that it is consistent with the SCR.
               SCR starts at 36000, but the first two packs contain only padding
               and the first pack from the other stream, respectively, may also have
               been written before.
               So the real data starts at SCR 36000+3*1200. */
            mux_preload= (36000+3*1200) / 90000.0; //0.44
    
        } else if(!strcmp(arg, "svcd")) {
    
            opt_video_codec("mpeg2video");
            opt_audio_codec("mp2");
    
    
            opt_frame_size(norm ? "480x480" : "480x576");
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
            opt_default("gop", norm ? "18" : "15");
    
            opt_default("maxrate", "2516000");
            opt_default("minrate", "0"); //1145000;
    
            opt_default("bufsize", "1835008"); //224*1024*8;
    
            opt_default("flags", "+scan_offset");
    
            opt_default("packetsize", "2324");
    
        } else if(!strcmp(arg, "dvd")) {
    
            opt_video_codec("mpeg2video");
            opt_audio_codec("ac3");
    
    
            opt_frame_size(norm ? "720x480" : "720x576");
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
            opt_default("gop", norm ? "18" : "15");
    
            opt_default("maxrate", "9000000");
            opt_default("minrate", "0"); //1500000;
    
            opt_default("bufsize", "1835008"); //224*1024*8;
    
            opt_default("packetsize", "2048");  // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
    
            opt_default("muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
    
    
            opt_format("dv");
    
            opt_frame_size(norm ? "720x480" : "720x576");
    
            opt_frame_pix_fmt(!strncmp(arg, "dv50", 4) ? "yuv422p" :
                                                 (norm ? "yuv411p" : "yuv420p"));
    
            opt_frame_rate(NULL, frame_rates[norm]);
    
        } else {
            fprintf(stderr, "Unknown target: %s\n", arg);
    
    static void opt_vstats_file (const char *arg)
    {
        av_free (vstats_filename);
        vstats_filename=av_strdup (arg);
    }
    
    static void opt_vstats (void)
    {
        char filename[40];
        time_t today2 = time(NULL);
        struct tm *today = localtime(&today2);
    
        snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min,
                 today->tm_sec);
        opt_vstats_file(filename);
    }
    
    
    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;
    
        if(!bsfc){
    
    Alex Beregszaszi's avatar
    Alex Beregszaszi committed
            fprintf(stderr, "Unknown bitstream filter %s\n", arg);
    
        bsfp= *opt == 'v' ? &video_bitstream_filters :
              *opt == 'a' ? &audio_bitstream_filters :
                            &subtitle_bitstream_filters;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    static int opt_preset(const char *opt, const char *arg)
    {
    
        char filename[1000], tmp[1000], tmp2[1000], line[1000];
    
        const char *base[2]= { getenv("HOME"),
                               FFMPEG_DATADIR,
    
        for(i=!base[0]; i<2 && !f; i++){
            snprintf(filename, sizeof(filename), "%s%s/%s.ffpreset", base[i], i ? "" : "/.ffmpeg", arg);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            if(!f){
                char *codec_name= *opt == 'v' ? video_codec_name :
                                  *opt == 'a' ? audio_codec_name :
                                                subtitle_codec_name;
    
                snprintf(filename, sizeof(filename), "%s%s/%s-%s.ffpreset", base[i],  i ? "" : "/.ffmpeg", codec_name, arg);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            }
    
        if(!f && ((arg[0]=='.' && arg[1]=='/') || arg[0]=='/' ||
                  is_dos_path(arg))){
    
            snprintf(filename, sizeof(filename), arg);
            f= fopen(filename, "r");
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
        if(!f){
    
            fprintf(stderr, "File for preset '%s' not found\n", arg);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            av_exit(1);
        }
    
        while(!feof(f)){
    
            int e= fscanf(f, "%999[^\n]\n", line) - 1;
            if(line[0] == '#' && !e)
                continue;
            e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
            if(e){
    
                fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                av_exit(1);
            }
    
            if(!strcmp(tmp, "acodec")){
                opt_audio_codec(tmp2);
            }else if(!strcmp(tmp, "vcodec")){
                opt_video_codec(tmp2);
            }else if(!strcmp(tmp, "scodec")){
                opt_subtitle_codec(tmp2);
    
            }else if(opt_default(tmp, tmp2) < 0){
    
                fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
    
        /* main options */
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        { "L", OPT_EXIT, {(void*)show_license}, "show license" },
        { "h", OPT_EXIT, {(void*)show_help}, "show help" },
    
        { "version", OPT_EXIT, {(void*)show_version}, "show version" },
    
        { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
        { "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
        { "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", 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", 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" },
    
        { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { "title", HAS_ARG | OPT_STRING, {(void*)&str_title}, "set the title", "string" },
    
        { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)&opt_rec_timestamp}, "set the timestamp", "time" },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { "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" },
    
        { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[CODEC_TYPE_DATA]}, "set the number of data frames to record", "number" },
    
        { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
          "add timings for benchmarking" },
    
        { "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump},
    
          "dump each input packet" },
    
        { "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
    
          "when dumping packets, also dump the payload" },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { "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 | OPT_FUNC2, {(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", OPT_FUNC2 | 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", "" },
        { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
    
        { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" },
    
        { "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_global_header}, "video global header storage type", "" },
    
        { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" },
    
        { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
    
        { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" },
    
        { "programid", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&opt_programid}, "desired program number", "" },
    
        { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" },
    
        { "copyinkf", OPT_BOOL | OPT_EXPERT, {(void*)&copy_initial_nonkeyframes}, "copy initial non-keyframes" },
    
        { "b", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
        { "vb", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
    
        { "vframes", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&max_frames[CODEC_TYPE_VIDEO]}, "set the number of video frames to record", "number" },
    
        { "r", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_rate}, "set frame rate (Hz value, fraction or abbreviation)", "rate" },
    
        { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
        { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
    
        { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format, 'list' as argument shows all the pixel formats supported", "format" },
    
        { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_top}, "set top crop band size (in pixels)", "size" },
        { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" },
        { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" },
        { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" },
    
        { "padtop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_top}, "set top pad band size (in pixels)", "size" },
        { "padbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_bottom}, "set bottom pad band size (in pixels)", "size" },
        { "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_left}, "set left pad band size (in pixels)", "size" },
        { "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_right}, "set right pad band size (in pixels)", "size" },
        { "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad_color}, "set color of pad bands (Hex 000000 thru FFFFFF)", "color" },
    
        { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"},
        { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" },
    
    Måns Rullgård's avatar
    Måns Rullgård committed
        { "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" },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { "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_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold",  "threshold" },
    
        { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality},
    
          "use same video quality as source (implies VBR)" },
        { "pass", HAS_ARG | OPT_VIDEO, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" },
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
        { "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" },
    
        { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" },
    
        { "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", "" },
    
        { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" },
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        { "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" },
    
        { "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" },
    
        { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
    
        { "aframes", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&max_frames[CODEC_TYPE_AUDIO]}, "set the number of audio frames to record", "number" },
    
        { "aq", OPT_FLOAT | HAS_ARG | OPT_AUDIO, {(void*)&audio_qscale}, "set audio quality (codec-specific)", "quality", },
    
        { "ar", HAS_ARG | OPT_FUNC2 | OPT_AUDIO, {(void*)opt_audio_rate}, "set audio sampling rate (in Hz)", "rate" },
        { "ac", HAS_ARG | OPT_FUNC2 | OPT_AUDIO, {(void*)opt_audio_channels}, "set number of audio channels", "channels" },
    
        { "an", OPT_BOOL | OPT_AUDIO, {(void*)&audio_disable}, "disable audio" },
        { "acodec", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
        { "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" },
        { "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" },
    
        { "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" },
        { "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" },
    
        /* grab options */
        { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" },
        { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" },
    
        { "isync", OPT_BOOL | OPT_EXPERT | OPT_GRAB, {(void*)&input_sync}, "sync read on input", "" },
    
        { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_max_delay}, "set the maximum demux-decode delay", "seconds" },
        { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_preload}, "set the initial demux-decode delay", "seconds" },
    
        { "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" },
    
        { "apre", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_preset}, "set the audio options to the indicated preset", "preset" },
        { "vpre", OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_preset}, "set the video options to the indicated preset", "preset" },
        { "spre", OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT, {(void*)opt_preset}, "set the subtitle options to the indicated preset", "preset" },
    
        { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { NULL, },
    };
    
    
    int main(int argc, char **argv)
    {
        int i;
        int64_t ti;
    
    
    Luca Abeni's avatar
    Luca Abeni committed
        avcodec_register_all();
        avdevice_register_all();
    
        av_register_all();
    
    
        if(isatty(STDIN_FILENO))
            url_set_interrupt_cb(decode_interrupt_cb);
    
    
        for(i=0; i<CODEC_TYPE_NB; i++){
            avctx_opts[i]= avcodec_alloc_context2(i);
        }
        avformat_opts = av_alloc_format_context();
        sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
    
    
    
        /* parse options */
        parse_options(argc, argv, options, opt_output_file);
    
        /* file converter / grab */
        if (nb_output_files <= 0) {
    
            fprintf(stderr, "At least one output file must be specified\n");
    
        }
    
        if (nb_input_files == 0) {
    
            fprintf(stderr, "At least one input file must be specified\n");
    
        }
    
        ti = getutime();
    
        if (av_encode(output_files, nb_output_files, input_files, nb_input_files,
                      stream_maps, nb_stream_maps) < 0)
            av_exit(1);
    
        ti = getutime() - ti;
        if (do_benchmark) {
            printf("bench: utime=%0.3fs\n", ti / 1000000.0);
        }