Skip to content
Snippets Groups Projects
ffprobe.c 96 KiB
Newer Older
  • Learn to ignore specific revisions
  • static void show_error(WriterContext *w, int err)
    {
        char errbuf[128];
        const char *errbuf_ptr = errbuf;
    
        if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
            errbuf_ptr = strerror(AVUNERROR(err));
    
    
        writer_print_section_header(w, SECTION_ID_ERROR);
    
        print_int("code", err);
        print_str("string", errbuf_ptr);
    
        writer_print_section_footer(w);
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
    {
    
        int err, i, orig_nb_streams;
    
        AVFormatContext *fmt_ctx = NULL;
        AVDictionaryEntry *t;
    
        AVDictionary **opts;
    
        if ((err = avformat_open_input(&fmt_ctx, filename,
                                       iformat, &format_opts)) < 0) {
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
            print_error(filename, err);
            return err;
        }
    
        if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
            av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
            return AVERROR_OPTION_NOT_FOUND;
        }
    
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
        /* fill the streams in the format context */
    
        opts = setup_find_stream_info_opts(fmt_ctx, codec_opts);
        orig_nb_streams = fmt_ctx->nb_streams;
    
        if ((err = avformat_find_stream_info(fmt_ctx, opts)) < 0) {
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
            print_error(filename, err);
            return err;
        }
    
        for (i = 0; i < orig_nb_streams; i++)
            av_dict_free(&opts[i]);
        av_freep(&opts);
    
        av_dump_format(fmt_ctx, 0, filename, 0);
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    
        /* bind a decoder to each input stream */
        for (i = 0; i < fmt_ctx->nb_streams; i++) {
            AVStream *stream = fmt_ctx->streams[i];
            AVCodec *codec;
    
    
            if (stream->codec->codec_id == AV_CODEC_ID_PROBE) {
    
                       "Failed to probe codec for input stream %d\n",
                        stream->index);
            } else if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
    
                        "Unsupported codec with id %d for input stream %d\n",
                        stream->codec->codec_id, stream->index);
    
            } else {
                AVDictionary *opts = filter_codec_opts(codec_opts, stream->codec->codec_id,
                                                       fmt_ctx, stream, codec);
                if (avcodec_open2(stream->codec, codec, &opts) < 0) {
    
                    av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n",
    
                           stream->index);
                }
                if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
                    av_log(NULL, AV_LOG_ERROR, "Option %s for input stream %d not found\n",
                           t->key, stream->index);
                    return AVERROR_OPTION_NOT_FOUND;
                }
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
            }
        }
    
        *fmt_ctx_ptr = fmt_ctx;
        return 0;
    }
    
    
    static void close_input_file(AVFormatContext **ctx_ptr)
    {
        int i;
        AVFormatContext *fmt_ctx = *ctx_ptr;
    
        /* close decoder for each stream */
        for (i = 0; i < fmt_ctx->nb_streams; i++)
    
            if (fmt_ctx->streams[i]->codec->codec_id != AV_CODEC_ID_NONE)
    
                avcodec_close(fmt_ctx->streams[i]->codec);
    
        avformat_close_input(ctx_ptr);
    }
    
    
    static int probe_file(WriterContext *wctx, const char *filename)
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    {
        AVFormatContext *fmt_ctx;
    
        do_read_frames = do_show_frames || do_count_frames;
        do_read_packets = do_show_packets || do_count_packets;
    
    
        ret = open_input_file(&fmt_ctx, filename);
    
        nb_streams_frames  = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_frames));
        nb_streams_packets = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_packets));
        selected_streams   = av_calloc(fmt_ctx->nb_streams, sizeof(*selected_streams));
    
        for (i = 0; i < fmt_ctx->nb_streams; i++) {
            if (stream_specifier) {
                ret = avformat_match_stream_specifier(fmt_ctx,
                                                      fmt_ctx->streams[i],
                                                      stream_specifier);
                if (ret < 0)
                    goto end;
                else
                    selected_streams[i] = ret;
                ret = 0;
            } else {
                selected_streams[i] = 1;
    
        }
    
        if (do_read_frames || do_read_packets) {
            if (do_show_frames && do_show_packets &&
                wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
                section_id = SECTION_ID_PACKETS_AND_FRAMES;
            else if (do_show_packets && !do_show_frames)
                section_id = SECTION_ID_PACKETS;
            else // (!do_show_packets && do_show_frames)
                section_id = SECTION_ID_FRAMES;
            if (do_show_frames || do_show_packets)
                writer_print_section_header(wctx, section_id);
            read_packets(wctx, fmt_ctx);
            if (do_show_frames || do_show_packets)
                writer_print_section_footer(wctx);
        }
    
        if (do_show_programs)
            show_programs(wctx, fmt_ctx);
    
        if (do_show_streams)
            show_streams(wctx, fmt_ctx);
        if (do_show_chapters)
            show_chapters(wctx, fmt_ctx);
        if (do_show_format)
            show_format(wctx, fmt_ctx);
    
    end:
        close_input_file(&fmt_ctx);
        av_freep(&nb_streams_frames);
        av_freep(&nb_streams_packets);
        av_freep(&selected_streams);
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    }
    
    static void show_usage(void)
    {
    
        av_log(NULL, AV_LOG_INFO, "Simple multimedia streams analyzer\n");
        av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", program_name);
        av_log(NULL, AV_LOG_INFO, "\n");
    
    static void ffprobe_show_program_version(WriterContext *w)
    {
    
        AVBPrint pbuf;
        av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
    
        writer_print_section_header(w, SECTION_ID_PROGRAM_VERSION);
    
        print_str("version", FFMPEG_VERSION);
        print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
                  program_birth_year, this_year);
        print_str("build_date", __DATE__);
        print_str("build_time", __TIME__);
    
        print_str("compiler_ident", CC_IDENT);
    
        print_str("configuration", FFMPEG_CONFIGURATION);
    
        writer_print_section_footer(w);
    
        av_bprint_finalize(&pbuf, NULL);
    
    }
    
    #define SHOW_LIB_VERSION(libname, LIBNAME)                              \
        do {                                                                \
            if (CONFIG_##LIBNAME) {                                         \
                unsigned int version = libname##_version();                 \
    
                writer_print_section_header(w, SECTION_ID_LIBRARY_VERSION); \
    
                print_str("name",    "lib" #libname);                       \
                print_int("major",   LIB##LIBNAME##_VERSION_MAJOR);         \
                print_int("minor",   LIB##LIBNAME##_VERSION_MINOR);         \
                print_int("micro",   LIB##LIBNAME##_VERSION_MICRO);         \
                print_int("version", version);                              \
    
                print_str("ident",   LIB##LIBNAME##_IDENT);                 \
    
                writer_print_section_footer(w);                             \
    
            }                                                               \
        } while (0)
    
    static void ffprobe_show_library_versions(WriterContext *w)
    {
    
        writer_print_section_header(w, SECTION_ID_LIBRARY_VERSIONS);
    
        SHOW_LIB_VERSION(avutil,     AVUTIL);
        SHOW_LIB_VERSION(avcodec,    AVCODEC);
        SHOW_LIB_VERSION(avformat,   AVFORMAT);
        SHOW_LIB_VERSION(avdevice,   AVDEVICE);
        SHOW_LIB_VERSION(avfilter,   AVFILTER);
        SHOW_LIB_VERSION(swscale,    SWSCALE);
        SHOW_LIB_VERSION(swresample, SWRESAMPLE);
        SHOW_LIB_VERSION(postproc,   POSTPROC);
    
        writer_print_section_footer(w);
    
    static int opt_format(void *optctx, const char *opt, const char *arg)
    
    {
        iformat = av_find_input_format(arg);
        if (!iformat) {
    
            av_log(NULL, AV_LOG_ERROR, "Unknown input format: %s\n", arg);
    
            return AVERROR(EINVAL);
    
        return 0;
    
    static inline void mark_section_show_entries(SectionID section_id,
                                                 int show_all_entries, AVDictionary *entries)
    {
        struct section *section = &sections[section_id];
    
        section->show_all_entries = show_all_entries;
        if (show_all_entries) {
            SectionID *id;
            for (id = section->children_ids; *id != -1; id++)
                mark_section_show_entries(*id, show_all_entries, entries);
        } else {
            av_dict_copy(&section->entries_to_show, entries, 0);
        }
    }
    
    static int match_section(const char *section_name,
                             int show_all_entries, AVDictionary *entries)
    {
        int i, ret = 0;
    
        for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
            const struct section *section = &sections[i];
            if (!strcmp(section_name, section->name) ||
                (section->unique_name && !strcmp(section_name, section->unique_name))) {
                av_log(NULL, AV_LOG_DEBUG,
                       "'%s' matches section with unique name '%s'\n", section_name,
                       (char *)av_x_if_null(section->unique_name, section->name));
                ret++;
                mark_section_show_entries(section->id, show_all_entries, entries);
            }
        }
        return ret;
    }
    
    static int opt_show_entries(void *optctx, const char *opt, const char *arg)
    {
        const char *p = arg;
        int ret = 0;
    
        while (*p) {
            AVDictionary *entries = NULL;
            char *section_name = av_get_token(&p, "=:");
            int show_all_entries = 0;
    
            if (!section_name) {
                av_log(NULL, AV_LOG_ERROR,
                       "Missing section name for option '%s'\n", opt);
                return AVERROR(EINVAL);
            }
    
            if (*p == '=') {
                p++;
                while (*p && *p != ':') {
                    char *entry = av_get_token(&p, ",:");
                    if (!entry)
                        break;
                    av_log(NULL, AV_LOG_VERBOSE,
                           "Adding '%s' to the entries to show in section '%s'\n",
                           entry, section_name);
                    av_dict_set(&entries, entry, "", AV_DICT_DONT_STRDUP_KEY);
                    if (*p == ',')
                        p++;
                }
            } else {
                show_all_entries = 1;
            }
    
            ret = match_section(section_name, show_all_entries, entries);
            if (ret == 0) {
                av_log(NULL, AV_LOG_ERROR, "No match for section '%s'\n", section_name);
                ret = AVERROR(EINVAL);
            }
    
            av_dict_free(&entries);
    
    static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
    
        char *buf = av_asprintf("format=%s", arg);
        int ret;
    
        av_log(NULL, AV_LOG_WARNING,
               "Option '%s' is deprecated, use '-show_entries format=%s' instead\n",
               opt, arg);
        ret = opt_show_entries(optctx, opt, buf);
        av_free(buf);
        return ret;
    
    static void opt_input_file(void *optctx, const char *arg)
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    {
    
        if (input_filename) {
    
            av_log(NULL, AV_LOG_ERROR,
                    "Argument '%s' provided as input filename, but '%s' was already specified.\n",
                    arg, input_filename);
    
        if (!strcmp(arg, "-"))
            arg = "pipe:";
        input_filename = arg;
    
    static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
    {
        opt_input_file(optctx, arg);
        return 0;
    }
    
    
    void show_help_default(const char *opt, const char *arg)
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    {
    
        av_log_set_callback(log_callback_help);
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
        show_usage();
    
        show_help_options(options, "Main options:", 0, 0, 0);
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
        printf("\n");
    
    
        show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
    
    /**
     * Parse interval specification, according to the format:
     * INTERVAL ::= [START|+START_OFFSET][%[END|+END_OFFSET]]
     * INTERVALS ::= INTERVAL[,INTERVALS]
    */
    static int parse_read_interval(const char *interval_spec,
                                   ReadInterval *interval)
    {
        int ret = 0;
        char *next, *p, *spec = av_strdup(interval_spec);
        if (!spec)
            return AVERROR(ENOMEM);
    
        if (!*spec) {
            av_log(NULL, AV_LOG_ERROR, "Invalid empty interval specification\n");
            ret = AVERROR(EINVAL);
            goto end;
        }
    
        p = spec;
        next = strchr(spec, '%');
        if (next)
            *next++ = 0;
    
        /* parse first part */
        if (*p) {
            interval->has_start = 1;
    
            if (*p == '+') {
                interval->start_is_offset = 1;
                p++;
            } else {
                interval->start_is_offset = 0;
            }
    
            ret = av_parse_time(&interval->start, p, 1);
            if (ret < 0) {
                av_log(NULL, AV_LOG_ERROR, "Invalid interval start specification '%s'\n", p);
                goto end;
            }
        } else {
            interval->has_start = 0;
        }
    
        /* parse second part */
        p = next;
        if (p && *p) {
            int64_t us;
            interval->has_end = 1;
    
            if (*p == '+') {
                interval->end_is_offset = 1;
                p++;
            } else {
                interval->end_is_offset = 0;
            }
    
            if (interval->end_is_offset && *p == '#') {
                long long int lli;
                char *tail;
                interval->duration_frames = 1;
                p++;
                lli = strtoll(p, &tail, 10);
                if (*tail || lli < 0) {
                    av_log(NULL, AV_LOG_ERROR,
                           "Invalid or negative value '%s' for duration number of frames\n", p);
                    goto end;
                }
                interval->end = lli;
            } else {
                ret = av_parse_time(&us, p, 1);
                if (ret < 0) {
                    av_log(NULL, AV_LOG_ERROR, "Invalid interval end/duration specification '%s'\n", p);
                    goto end;
                }
                interval->end = us;
            }
        } else {
            interval->has_end = 0;
        }
    
    end:
        av_free(spec);
        return ret;
    }
    
    static int parse_read_intervals(const char *intervals_spec)
    {
        int ret, n, i;
        char *p, *spec = av_strdup(intervals_spec);
        if (!spec)
            return AVERROR(ENOMEM);
    
        /* preparse specification, get number of intervals */
        for (n = 0, p = spec; *p; p++)
            if (*p == ',')
                n++;
        n++;
    
        read_intervals = av_malloc(n * sizeof(*read_intervals));
        if (!read_intervals) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
        read_intervals_nb = n;
    
        /* parse intervals */
        p = spec;
        for (i = 0; i < n; i++) {
            char *next = strchr(p, ',');
            if (next)
                *next++ = 0;
    
            read_intervals[i].id = i;
            ret = parse_read_interval(p, &read_intervals[i]);
            if (ret < 0) {
                av_log(NULL, AV_LOG_ERROR, "Error parsing read interval #%d '%s'\n",
                       i, p);
                goto end;
            }
            av_log(NULL, AV_LOG_VERBOSE, "Parsed log interval ");
            log_read_interval(&read_intervals[i], NULL, AV_LOG_VERBOSE);
            p = next;
            av_assert0(i <= read_intervals_nb);
        }
        av_assert0(i == read_intervals_nb);
    
    end:
        av_free(spec);
        return ret;
    }
    
    static int opt_read_intervals(void *optctx, const char *opt, const char *arg)
    {
        return parse_read_intervals(arg);
    }
    
    
    static int opt_pretty(void *optctx, const char *opt, const char *arg)
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    {
        show_value_unit              = 1;
        use_value_prefix             = 1;
        use_byte_value_binary_prefix = 1;
        use_value_sexagesimal_format = 1;
    
    static void print_section(SectionID id, int level)
    {
        const SectionID *pid;
        const struct section *section = &sections[id];
        printf("%c%c%c",
               section->flags & SECTION_FLAG_IS_WRAPPER           ? 'W' : '.',
               section->flags & SECTION_FLAG_IS_ARRAY             ? 'A' : '.',
               section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS  ? 'V' : '.');
        printf("%*c  %s", level * 4, ' ', section->name);
        if (section->unique_name)
            printf("/%s", section->unique_name);
        printf("\n");
    
        for (pid = section->children_ids; *pid != -1; pid++)
            print_section(*pid, level+1);
    }
    
    static int opt_sections(void *optctx, const char *opt, const char *arg)
    {
        printf("Sections:\n"
               "W.. = Section is a wrapper (contains other sections, no local entries)\n"
               ".A. = Section contains an array of elements of the same type\n"
               "..V = Section may contain a variable number of fields with variable keys\n"
               "FLAGS NAME/UNIQUE_NAME\n"
               "---\n");
        print_section(SECTION_ID_ROOT, 0);
        return 0;
    }
    
    
    static int opt_show_versions(const char *opt, const char *arg)
    {
    
        mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL);
        mark_section_show_entries(SECTION_ID_LIBRARY_VERSION, 1, NULL);
    
    #define DEFINE_OPT_SHOW_SECTION(section, target_section_id)             \
        static int opt_show_##section(const char *opt, const char *arg)     \
        {                                                                   \
            mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \
            return 0;                                                       \
        }
    
    
    DEFINE_OPT_SHOW_SECTION(chapters,         CHAPTERS);
    
    DEFINE_OPT_SHOW_SECTION(error,            ERROR);
    DEFINE_OPT_SHOW_SECTION(format,           FORMAT);
    DEFINE_OPT_SHOW_SECTION(frames,           FRAMES);
    DEFINE_OPT_SHOW_SECTION(library_versions, LIBRARY_VERSIONS);
    DEFINE_OPT_SHOW_SECTION(packets,          PACKETS);
    DEFINE_OPT_SHOW_SECTION(program_version,  PROGRAM_VERSION);
    DEFINE_OPT_SHOW_SECTION(streams,          STREAMS);
    
    DEFINE_OPT_SHOW_SECTION(programs,         PROGRAMS);
    
    static const OptionDef real_options[] = {
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    #include "cmdutils_common_opts.h"
    
        { "f", HAS_ARG, {.func_arg = opt_format}, "force format", "format" },
        { "unit", OPT_BOOL, {&show_value_unit}, "show unit of the displayed values" },
        { "prefix", OPT_BOOL, {&use_value_prefix}, "use SI prefixes for the displayed values" },
        { "byte_binary_prefix", OPT_BOOL, {&use_byte_value_binary_prefix},
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
          "use binary prefixes for byte units" },
    
        { "sexagesimal", OPT_BOOL,  {&use_value_sexagesimal_format},
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
          "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
    
        { "pretty", 0, {.func_arg = opt_pretty},
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
          "prettify the format of displayed values, make it more human readable" },
    
        { "print_format", OPT_STRING | HAS_ARG, {(void*)&print_format},
    
          "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
    
        { "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" },
    
        { "select_streams", OPT_STRING | HAS_ARG, {(void*)&stream_specifier}, "select the specified streams", "stream_specifier" },
    
        { "sections", OPT_EXIT, {.func_arg = opt_sections}, "print sections structure and section information, and exit" },
    
        { "show_data",    OPT_BOOL, {(void*)&do_show_data}, "show packets data" },
    
        { "show_error",   0, {(void*)&opt_show_error},  "show probing error" },
        { "show_format",  0, {(void*)&opt_show_format}, "show format/container info" },
        { "show_frames",  0, {(void*)&opt_show_frames}, "show frames info" },
    
        { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry},
    
          "show a particular entry from the format/container info", "entry" },
    
        { "show_entries", HAS_ARG, {.func_arg = opt_show_entries},
          "show a set of specified entries", "entry_list" },
        { "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" },
    
        { "show_programs", 0, {(void*)&opt_show_programs}, "show programs info" },
    
        { "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" },
    
        { "show_chapters", 0, {(void*)&opt_show_chapters}, "show chapters info" },
    
        { "count_frames", OPT_BOOL, {(void*)&do_count_frames}, "count the number of frames per stream" },
        { "count_packets", OPT_BOOL, {(void*)&do_count_packets}, "count the number of packets per stream" },
    
        { "show_program_version",  0, {(void*)&opt_show_program_version},  "show ffprobe version" },
        { "show_library_versions", 0, {(void*)&opt_show_library_versions}, "show library versions" },
    
        { "show_versions",         0, {(void*)&opt_show_versions}, "show program and library versions" },
    
        { "show_private_data", OPT_BOOL, {(void*)&show_private_data}, "show private data" },
        { "private",           OPT_BOOL, {(void*)&show_private_data}, "same as show_private_data" },
    
        { "bitexact", OPT_BOOL, {&do_bitexact}, "force bitexact output" },
    
        { "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" },
    
        { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default}, "generic catch all option", "" },
    
        { "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"},
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
        { NULL, },
    };
    
    
    static inline int check_section_show_entries(int section_id)
    {
        int *id;
        struct section *section = &sections[section_id];
        if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
            return 1;
        for (id = section->children_ids; *id != -1; id++)
            if (check_section_show_entries(*id))
                return 1;
        return 0;
    }
    
    #define SET_DO_SHOW(id, varname) do {                                   \
            if (check_section_show_entries(SECTION_ID_##id))                \
                do_show_##varname = 1;                                      \
        } while (0)
    
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    int main(int argc, char **argv)
    {
    
        const Writer *w;
        WriterContext *wctx;
        char *buf;
        char *w_name = NULL, *w_args = NULL;
    
        av_log_set_flags(AV_LOG_SKIP_REPEATED);
    
        register_exit(ffprobe_cleanup);
    
        parse_loglevel(argc, argv, options);
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
        av_register_all();
    
        avformat_network_init();
    
        init_opts();
    
    #if CONFIG_AVDEVICE
        avdevice_register_all();
    #endif
    
        show_banner(argc, argv, options);
    
        parse_options(NULL, argc, argv, options, opt_input_file);
    
        /* mark things to show, based on -show_entries */
    
        SET_DO_SHOW(CHAPTERS, chapters);
    
        SET_DO_SHOW(ERROR, error);
        SET_DO_SHOW(FORMAT, format);
        SET_DO_SHOW(FRAMES, frames);
        SET_DO_SHOW(LIBRARY_VERSIONS, library_versions);
        SET_DO_SHOW(PACKETS, packets);
        SET_DO_SHOW(PROGRAM_VERSION, program_version);
    
        SET_DO_SHOW(PROGRAMS, programs);
    
        SET_DO_SHOW(STREAMS, streams);
        SET_DO_SHOW(STREAM_DISPOSITION, stream_disposition);
    
        SET_DO_SHOW(PROGRAM_STREAM_DISPOSITION, stream_disposition);
    
        if (do_bitexact && (do_show_program_version || do_show_library_versions)) {
            av_log(NULL, AV_LOG_ERROR,
                   "-bitexact and -show_program_version or -show_library_versions "
                   "options are incompatible\n");
            ret = AVERROR(EINVAL);
            goto end;
        }
    
    
        writer_register_all();
    
        if (!print_format)
            print_format = av_strdup("default");
    
        if (!print_format) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
    
        w_name = av_strtok(print_format, "=", &buf);
        w_args = buf;
    
        w = writer_get_by_name(w_name);
        if (!w) {
            av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
            ret = AVERROR(EINVAL);
            goto end;
    
        if ((ret = writer_open(&wctx, w, w_args,
                               sections, FF_ARRAY_ELEMS(sections))) >= 0) {
            writer_print_section_header(wctx, SECTION_ID_ROOT);
    
            if (do_show_program_version)
                ffprobe_show_program_version(wctx);
            if (do_show_library_versions)
                ffprobe_show_library_versions(wctx);
    
            if (!input_filename &&
    
                ((do_show_format || do_show_programs || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
    
                 (!do_show_program_version && !do_show_library_versions))) {
    
                show_usage();
                av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n");
                av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
                ret = AVERROR(EINVAL);
    
                ret = probe_file(wctx, input_filename);
    
                if (ret < 0 && do_show_error)
                    show_error(wctx, ret);
            }
    
            writer_print_section_footer(wctx);
    
        av_freep(&read_intervals);
    
        for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
            av_dict_free(&(sections[i].entries_to_show));
    
        avformat_network_deinit();
    
    
    Stefano Sabatini's avatar
    Stefano Sabatini committed
    }