Skip to content
Snippets Groups Projects
ffmpeg.c 156 KiB
Newer Older
  • Learn to ignore specific revisions
  •     if (pkt.dts != AV_NOPTS_VALUE)
            ifile->last_ts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
    
    
            av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n",
    
                   ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type),
    
                   av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base),
                   av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base),
                   av_ts2str(input_files[ist->file_index]->ts_offset),
                   av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q));
    
        sub2video_heartbeat(ist, pkt.pts);
    
    
        process_input_packet(ist, &pkt, 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(0);
    
            ret = reap_filters(1);
    
            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(0);
    
    /*
     * 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;
    
        int64_t total_packets_written = 0;
    
    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_relative();
    
    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_relative();
    
            /* 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 < 0 && ret != AVERROR_EOF) {
    
                char errbuf[128];
                av_strerror(ret, errbuf, sizeof(errbuf));
    
                av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
                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) {
    
                process_input_packet(ist, NULL, 0);
    
    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++) {
    
            if ((ret = av_write_trailer(os)) < 0) {
                av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s", os->filename, av_err2str(ret));
    
        /* dump report by using the first video and audio streams */
    
        print_report(1, timer_start, av_gettime_relative());
    
        /* close each encoder */
    
        for (i = 0; i < nb_output_streams; i++) {
    
            if (ost->encoding_needed) {
    
                av_freep(&ost->enc_ctx->stats_in);
    
            total_packets_written += ost->packets_written;
        }
    
        if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) {
            av_log(NULL, AV_LOG_FATAL, "Empty output\n");
            exit_program(1);
    
        /* close each decoder */
        for (i = 0; i < nb_input_streams; i++) {
    
            if (ist->decoding_needed) {
    
                avcodec_close(ist->dec_ctx);
    
                if (ist->hwaccel_uninit)
    
                    ist->hwaccel_uninit(ist->dec_ctx);
    
        av_buffer_unref(&hw_device_ctx);
    
    
    #if HAVE_PTHREADS
    
        free_input_threads();
    #endif
    
        if (output_streams) {
            for (i = 0; i < nb_output_streams; i++) {
    
                if (ost) {
                    if (ost->logfile) {
    
                        if (fclose(ost->logfile))
                            av_log(NULL, AV_LOG_ERROR,
                                   "Error closing logfile, loss of information possible: %s\n",
                                   av_err2str(AVERROR(errno)));
    
                        ost->logfile = NULL;
    
                    av_freep(&ost->forced_kf_pts);
    
                    av_dict_free(&ost->encoder_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_relative();
    
    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;
    
        register_exit(ffmpeg_cleanup);
    
        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_program(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);
    
            exit_program(1);
    
        /* file converter / grab */
        if (nb_output_files <= 0) {
    
            av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
    
            exit_program(1);
    
    //     if (nb_input_files == 0) {
    //         av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
    
        current_time = ti = getutime();
    
            exit_program(1);
    
        ti = getutime() - ti;
        if (do_benchmark) {
    
            av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
    
        av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
               decode_error_stat[0], decode_error_stat[1]);
    
        if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
    
            exit_program(69);
    
        exit_program(received_nb_signals ? 255 : main_return_code);
        return main_return_code;