Skip to content
Snippets Groups Projects
ffmpeg.c 116 KiB
Newer Older
  • Learn to ignore specific revisions
  •                 ist->file_index, ist->st->index, buf);
            if (exit_on_error)
    
        }
    
    discard_packet:
        av_free_packet(&pkt);
    
        return 0;
    }
    
    
    /**
     * Perform a step of transcoding for the specified filter graph.
     *
     * @param[in]  graph     filter graph to consider
     * @param[out] best_ist  input stream where a frame would allow to continue
     * @return  0 for success, <0 for error
     */
    static int transcode_from_filter(FilterGraph *graph, InputStream **best_ist)
    {
        int i, ret;
        int nb_requests, nb_requests_max = 0;
        InputFilter *ifilter;
        InputStream *ist;
    
        *best_ist = NULL;
        ret = avfilter_graph_request_oldest(graph->graph);
        if (ret >= 0)
            return reap_filters();
    
        if (ret == AVERROR_EOF) {
            ret = reap_filters();
            for (i = 0; i < graph->nb_outputs; i++)
                close_output_stream(graph->outputs[i]->ost);
            return ret;
        }
        if (ret != AVERROR(EAGAIN))
            return ret;
    
        for (i = 0; i < graph->nb_inputs; i++) {
            ifilter = graph->inputs[i];
            ist = ifilter->ist;
            if (input_files[ist->file_index]->eagain ||
                input_files[ist->file_index]->eof_reached)
                continue;
            nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter);
            if (nb_requests > nb_requests_max) {
                nb_requests_max = nb_requests;
                *best_ist = ist;
            }
        }
    
        if (!*best_ist)
            for (i = 0; i < graph->nb_outputs; i++)
                graph->outputs[i]->ost->unavailable = 1;
    
        return 0;
    }
    
    /**
     * Run a single step of transcoding.
     *
     * @return  0 for success, <0 for error
     */
    static int transcode_step(void)
    {
        OutputStream *ost;
        InputStream  *ist;
        int ret;
    
        ost = choose_output();
        if (!ost) {
            if (got_eagain()) {
                reset_eagain();
                av_usleep(10000);
                return 0;
            }
            av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n");
            return AVERROR_EOF;
        }
    
        if (ost->filter) {
            if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0)
                return ret;
            if (!ist)
                return 0;
        } else {
            av_assert0(ost->source_index >= 0);
            ist = input_streams[ost->source_index];
        }
    
        ret = process_input(ist->file_index);
        if (ret == AVERROR(EAGAIN)) {
            if (input_files[ist->file_index]->eagain)
                ost->unavailable = 1;
            return 0;
        }
        if (ret < 0)
            return ret == AVERROR_EOF ? 0 : ret;
    
        return reap_filters();
    }
    
    
    /*
     * The following code is the main loop of the file converter
     */
    
    static int transcode(void)
    
        AVFormatContext *os;
    
        OutputStream *ost;
    
        InputStream *ist;
        int64_t timer_start;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (stdin_interaction) {
            av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
    
        timer_start = av_gettime();
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    #if HAVE_PTHREADS
    
        if ((ret = init_input_threads()) < 0)
            goto fail;
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    Anton Khirnov's avatar
    Anton Khirnov committed
        while (!received_sigterm) {
    
            int64_t cur_time= av_gettime();
    
            /* if 'q' pressed, exits */
            if (stdin_interaction)
                if (check_keyboard_interaction(cur_time) < 0)
                    break;
    
            /* check if there's any stream where output is still needed */
    
            if (!need_output()) {
                av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n");
    
                if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
    
                av_log(NULL, AV_LOG_ERROR, "Error while filtering.\n");
                break;
    
    
            /* dump report by using the output first video and audio streams */
    
            print_report(0, timer_start, cur_time);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    #if HAVE_PTHREADS
    
        free_input_threads();
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* at the end of stream, we must flush the decoder buffers */
        for (i = 0; i < nb_input_streams; i++) {
    
            if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* write the trailer if needed and close file */
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
        for (i = 0; i < nb_output_files; i++) {
    
            av_write_trailer(os);
    
        /* dump report by using the first video and audio streams */
    
        print_report(1, timer_start, av_gettime());
    
        /* close each encoder */
    
        for (i = 0; i < nb_output_streams; i++) {
    
            if (ost->encoding_needed) {
                av_freep(&ost->st->codec->stats_in);
                avcodec_close(ost->st->codec);
    
        /* close each decoder */
        for (i = 0; i < nb_input_streams; i++) {
    
            if (ist->decoding_needed) {
                avcodec_close(ist->st->codec);
    
    #if HAVE_PTHREADS
    
        free_input_threads();
    #endif
    
        if (output_streams) {
            for (i = 0; i < nb_output_streams; i++) {
    
                    if (ost->stream_copy)
    
                        av_freep(&ost->st->codec->extradata);
                    if (ost->logfile) {
                        fclose(ost->logfile);
                        ost->logfile = NULL;
    
                    av_freep(&ost->st->codec->subtitle_header);
                    av_free(ost->forced_kf_pts);
                    av_dict_free(&ost->opts);
    
                    av_dict_free(&ost->resample_opts);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    }
    
    
    static int64_t getutime(void)
    
    #if HAVE_GETRUSAGE
        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
        return av_gettime();
    #endif
    
    static int64_t getmaxrss(void)
    {
    #if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
        struct rusage rusage;
        getrusage(RUSAGE_SELF, &rusage);
        return (int64_t)rusage.ru_maxrss * 1024;
    #elif HAVE_GETPROCESSMEMORYINFO
        HANDLE proc;
        PROCESS_MEMORY_COUNTERS memcounters;
        proc = GetCurrentProcess();
        memcounters.cb = sizeof(memcounters);
        GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters));
        return memcounters.PeakPagefileUsage;
    #else
        return 0;
    #endif
    }
    
    
    static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
    
    int main(int argc, char **argv)
    {
    
        int ret;
    
        setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
    
    
        av_log_set_flags(AV_LOG_SKIP_REPEATED);
    
        parse_loglevel(argc, argv, options);
    
        if(argc>1 && !strcmp(argv[1], "-d")){
    
            av_log_set_callback(log_callback_null);
            argc--;
            argv++;
        }
    
    
    Luca Abeni's avatar
    Luca Abeni committed
        avcodec_register_all();
    
    Luca Abeni's avatar
    Luca Abeni committed
        avdevice_register_all();
    
    #endif
        avfilter_register_all();
    
        av_register_all();
    
        avformat_network_init();
    
        show_banner(argc, argv, options);
    
        /* parse options and open all input/output files */
    
        ret = ffmpeg_parse_options(argc, argv);
    
        if (ret < 0)
            exit(1);
    
        if (nb_output_files <= 0 && nb_input_files == 0) {
    
            av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
    
        /* file converter / grab */
        if (nb_output_files <= 0) {
    
            av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
    
    //     if (nb_input_files == 0) {
    //         av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
    
        current_time = ti = getutime();
    
        ti = getutime() - ti;
        if (do_benchmark) {
    
            int maxrss = getmaxrss() / 1024;
            printf("bench: utime=%0.3fs maxrss=%ikB\n", ti / 1000000.0, maxrss);
    
        exit(received_nb_signals ? 255 : 0);