Newer
Older
av_frame_free(&frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not read packets in interval ");
log_read_interval(interval, NULL, AV_LOG_ERROR);
}
return ret;
}
static int read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
{
int i, ret = 0;
int64_t cur_ts = fmt_ctx->start_time;
if (read_intervals_nb == 0) {
ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
ret = read_interval_packets(w, fmt_ctx, &interval, &cur_ts);
} else {
for (i = 0; i < read_intervals_nb; i++) {
ret = read_interval_packets(w, fmt_ctx, &read_intervals[i], &cur_ts);
if (ret < 0)
break;
}
}
static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, int in_program)
{
AVStream *stream = fmt_ctx->streams[stream_idx];
AVCodecContext *dec_ctx;
const char *s;
Stefano Sabatini
committed
AVRational sar, dar;
const AVCodecDescriptor *cd;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM : SECTION_ID_STREAM);
print_int("index", stream->index);
const char *profile = NULL;
dec = dec_ctx->codec;
if (dec) {
print_str("codec_name", dec->name);
if (!do_bitexact) {
if (dec->long_name) print_str ("codec_long_name", dec->long_name);
else print_str_opt("codec_long_name", "unknown");
} else if ((cd = avcodec_descriptor_get(stream->codec->codec_id))) {
print_str_opt("codec_name", cd->name);
if (!do_bitexact) {
print_str_opt("codec_long_name",
cd->long_name ? cd->long_name : "unknown");
}
print_str_opt("codec_name", "unknown");
print_str_opt("codec_long_name", "unknown");
if (dec && (profile = av_get_profile_name(dec, dec_ctx->profile)))
print_str("profile", profile);
else
print_str_opt("profile", "unknown");
s = av_get_media_type_string(dec_ctx->codec_type);
if (s) print_str ("codec_type", s);
else print_str_opt("codec_type", "unknown");
print_q("codec_time_base", dec_ctx->time_base, '/');
av_get_codec_tag_string(val_str, sizeof(val_str), dec_ctx->codec_tag);
print_str("codec_tag_string", val_str);
print_fmt("codec_tag", "0x%04x", dec_ctx->codec_tag);
case AVMEDIA_TYPE_VIDEO:
print_int("width", dec_ctx->width);
print_int("height", dec_ctx->height);
print_int("has_b_frames", dec_ctx->has_b_frames);
Stefano Sabatini
committed
sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
if (sar.den) {
print_q("sample_aspect_ratio", sar, ':');
av_reduce(&dar.num, &dar.den,
dec_ctx->width * sar.num,
dec_ctx->height * sar.den,
Stefano Sabatini
committed
print_q("display_aspect_ratio", dar, ':');
} else {
print_str_opt("sample_aspect_ratio", "N/A");
print_str_opt("display_aspect_ratio", "N/A");
}
s = av_get_pix_fmt_name(dec_ctx->pix_fmt);
if (s) print_str ("pix_fmt", s);
else print_str_opt("pix_fmt", "unknown");
print_int("level", dec_ctx->level);
if (dec_ctx->color_range != AVCOL_RANGE_UNSPECIFIED)
print_str ("color_range", dec_ctx->color_range == AVCOL_RANGE_MPEG ? "tv": "pc");
else
print_str_opt("color_range", "N/A");
s = av_get_colorspace_name(dec_ctx->colorspace);
if (s) print_str ("color_space", s);
else print_str_opt("color_space", "unknown");
if (dec_ctx->timecode_frame_start >= 0) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_mpeg_tc_string(tcbuf, dec_ctx->timecode_frame_start);
print_str("timecode", tcbuf);
} else {
print_str_opt("timecode", "N/A");
}
case AVMEDIA_TYPE_AUDIO:
s = av_get_sample_fmt_name(dec_ctx->sample_fmt);
if (s) print_str ("sample_fmt", s);
else print_str_opt("sample_fmt", "unknown");
print_val("sample_rate", dec_ctx->sample_rate, unit_hertz_str);
print_int("channels", dec_ctx->channels);
if (dec_ctx->channel_layout) {
av_bprint_clear(&pbuf);
av_bprint_channel_layout(&pbuf, dec_ctx->channels, dec_ctx->channel_layout);
print_str ("channel_layout", pbuf.str);
} else {
print_str_opt("channel_layout", "unknown");
}
print_int("bits_per_sample", av_get_bits_per_sample(dec_ctx->codec_id));
case AVMEDIA_TYPE_SUBTITLE:
if (dec_ctx->width)
print_int("width", dec_ctx->width);
else
print_str_opt("width", "N/A");
if (dec_ctx->height)
print_int("height", dec_ctx->height);
else
print_str_opt("height", "N/A");
break;
print_str_opt("codec_type", "unknown");
if (dec_ctx->codec && dec_ctx->codec->priv_class && show_private_data) {
while (opt = av_opt_next(dec_ctx->priv_data,opt)) {
uint8_t *str;
if (opt->flags) continue;
if (av_opt_get(dec_ctx->priv_data, opt->name, 0, &str) >= 0) {
print_str(opt->name, str);
av_free(str);
}
}
}
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
else print_str_opt("id", "N/A");
print_q("r_frame_rate", stream->r_frame_rate, '/');
print_q("avg_frame_rate", stream->avg_frame_rate, '/');
print_q("time_base", stream->time_base, '/');
print_ts ("start_pts", stream->start_time);
print_time("start_time", stream->start_time, &stream->time_base);
print_ts ("duration_ts", stream->duration);
print_time("duration", stream->duration, &stream->time_base);
if (dec_ctx->bit_rate > 0) print_val ("bit_rate", dec_ctx->bit_rate, unit_bit_per_second_str);
else print_str_opt("bit_rate", "N/A");
if (dec_ctx->rc_max_rate > 0) print_val ("max_bit_rate", dec_ctx->rc_max_rate, unit_bit_per_second_str);
else print_str_opt("max_bit_rate", "N/A");
if (dec_ctx->bits_per_raw_sample > 0) print_fmt("bits_per_raw_sample", "%d", dec_ctx->bits_per_raw_sample);
else print_str_opt("bits_per_raw_sample", "N/A");
if (stream->nb_frames) print_fmt ("nb_frames", "%"PRId64, stream->nb_frames);
else print_str_opt("nb_frames", "N/A");
if (nb_streams_frames[stream_idx]) print_fmt ("nb_read_frames", "%"PRIu64, nb_streams_frames[stream_idx]);
else print_str_opt("nb_read_frames", "N/A");
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
writer_print_data(w, "extradata", dec_ctx->extradata,
dec_ctx->extradata_size);
writer_print_data_hash(w, "extradata_hash", dec_ctx->extradata,
dec_ctx->extradata_size);
/* Print disposition information */
#define PRINT_DISPOSITION(flagname, name) do { \
print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \
} while (0)
Stefano Sabatini
committed
if (do_show_stream_disposition) {
writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM_DISPOSITION : SECTION_ID_STREAM_DISPOSITION);
PRINT_DISPOSITION(DEFAULT, "default");
PRINT_DISPOSITION(DUB, "dub");
PRINT_DISPOSITION(ORIGINAL, "original");
PRINT_DISPOSITION(COMMENT, "comment");
PRINT_DISPOSITION(LYRICS, "lyrics");
PRINT_DISPOSITION(KARAOKE, "karaoke");
PRINT_DISPOSITION(FORCED, "forced");
PRINT_DISPOSITION(HEARING_IMPAIRED, "hearing_impaired");
PRINT_DISPOSITION(VISUAL_IMPAIRED, "visual_impaired");
PRINT_DISPOSITION(CLEAN_EFFECTS, "clean_effects");
PRINT_DISPOSITION(ATTACHED_PIC, "attached_pic");
writer_print_section_footer(w);
Stefano Sabatini
committed
}
if (do_show_stream_tags)
ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
writer_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
static int show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
int i, ret = 0;
writer_print_section_header(w, SECTION_ID_STREAMS);
for (i = 0; i < fmt_ctx->nb_streams; i++)
if (selected_streams[i]) {
ret = show_stream(w, fmt_ctx, i, 0);
if (ret < 0)
break;
}
writer_print_section_footer(w);
static int show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program)
writer_print_section_header(w, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
print_int("pmt_pid", program->pmt_pid);
print_int("pcr_pid", program->pcr_pid);
print_ts("start_pts", program->start_time);
print_time("start_time", program->start_time, &AV_TIME_BASE_Q);
print_ts("end_pts", program->end_time);
print_time("end_time", program->end_time, &AV_TIME_BASE_Q);
if (do_show_program_tags)
ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
if (ret < 0)
goto end;
writer_print_section_header(w, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
ret = show_stream(w, fmt_ctx, program->stream_index[i], 1);
if (ret < 0)
break;
}
}
writer_print_section_footer(w);
writer_print_section_footer(w);
static int show_programs(WriterContext *w, AVFormatContext *fmt_ctx)
writer_print_section_header(w, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
continue;
ret = show_program(w, fmt_ctx, program);
if (ret < 0)
break;
writer_print_section_footer(w);
static int show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
writer_print_section_header(w, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
writer_print_section_header(w, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
print_time("start_time", chapter->start, &chapter->time_base);
print_int("end", chapter->end);
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
writer_print_section_footer(w);
}
writer_print_section_footer(w);
static int show_format(WriterContext *w, AVFormatContext *fmt_ctx)
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
writer_print_section_header(w, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->filename);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
print_str("format_name", fmt_ctx->iformat->name);
if (fmt_ctx->iformat->long_name) print_str ("format_long_name", fmt_ctx->iformat->long_name);
else print_str_opt("format_long_name", "unknown");
print_time("start_time", fmt_ctx->start_time, &AV_TIME_BASE_Q);
print_time("duration", fmt_ctx->duration, &AV_TIME_BASE_Q);
if (size >= 0) print_val ("size", size, unit_byte_str);
else print_str_opt("size", "N/A");
if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
else print_str_opt("bit_rate", "N/A");
print_int("probe_score", av_format_get_probe_score(fmt_ctx));
if (do_show_format_tags)
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
writer_print_section_footer(w);
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);
static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
{
AVFormatContext *fmt_ctx = NULL;
AVDictionaryEntry *t;
if ((err = avformat_open_input(&fmt_ctx, filename,
iformat, &format_opts)) < 0) {
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;
}
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) {
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);
/* 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) {
av_log(NULL, AV_LOG_WARNING,
"Failed to probe codec for input stream %d\n",
stream->index);
} else if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
av_log(NULL, AV_LOG_WARNING,
"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;
}
}
}
*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)
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);
if (ret < 0)
return ret;
#define CHECK_END if (ret < 0) goto end
nb_streams = fmt_ctx->nb_streams;
REALLOCZ_ARRAY_STREAM(nb_streams_frames,0,fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(nb_streams_packets,0,fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(selected_streams,0,fmt_ctx->nb_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);
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);
ret = read_packets(wctx, fmt_ctx);
if (do_show_frames || do_show_packets)
writer_print_section_footer(wctx);
if (do_show_programs) {
ret = show_programs(wctx, fmt_ctx);
CHECK_END;
}
if (do_show_streams) {
ret = show_streams(wctx, fmt_ctx);
CHECK_END;
}
if (do_show_chapters) {
ret = show_chapters(wctx, fmt_ctx);
CHECK_END;
}
if (do_show_format) {
ret = show_format(wctx, fmt_ctx);
CHECK_END;
}
end:
close_input_file(&fmt_ctx);
av_freep(&nb_streams_frames);
av_freep(&nb_streams_packets);
av_freep(&selected_streams);
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, CONFIG_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 void ffprobe_show_pixel_formats(WriterContext *w)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int n;
writer_print_section_header(w, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
writer_print_section_header(w, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
n = av_get_bits_per_pixel(pixdesc);
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
writer_print_section_footer(w);
}
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);
}
}
Stefano Sabatini
committed
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
static inline void mark_section_show_entries(SectionID section_id,
int show_all_entries, AVDictionary *entries)
{
struct section *section = §ions[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(§ion->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 = §ions[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);
Stefano Sabatini
committed
av_free(section_name);
if (ret <= 0)
break;
if (*p)
p++;
}
return ret;
}
static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
Stefano Sabatini
committed
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)
av_log(NULL, AV_LOG_ERROR,
"Argument '%s' provided as input filename, but '%s' was already specified.\n",
arg, input_filename);
exit_program(1);
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)
av_log_set_callback(log_callback_help);
show_help_options(options, "Main options:", 0, 0, 0);
show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
/**
* 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_array(n, sizeof(*read_intervals));
if (!read_intervals) {
ret = AVERROR(ENOMEM);
goto end;
}
read_intervals_nb = n;
/* parse intervals */
p = spec;
for (i = 0; p; i++) {
char *next;
av_assert0(i < read_intervals_nb);
next = strchr(p, ',');
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
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);
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)
{
show_value_unit = 1;
use_value_prefix = 1;
use_byte_value_binary_prefix = 1;
use_value_sexagesimal_format = 1;
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
static void print_section(SectionID id, int level)
{
const SectionID *pid;
const struct section *section = §ions[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)
{
Stefano Sabatini
committed
mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL);
mark_section_show_entries(SECTION_ID_LIBRARY_VERSION, 1, NULL);
return 0;
}
Stefano Sabatini
committed
#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);
Stefano Sabatini
committed
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(pixel_formats, PIXEL_FORMATS);
Stefano Sabatini
committed
DEFINE_OPT_SHOW_SECTION(program_version, PROGRAM_VERSION);
DEFINE_OPT_SHOW_SECTION(streams, STREAMS);
DEFINE_OPT_SHOW_SECTION(programs, PROGRAMS);
Stefano Sabatini
committed
static const OptionDef real_options[] = {
{ "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},
{ "sexagesimal", OPT_BOOL, {&use_value_sexagesimal_format},
"use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
{ "pretty", 0, {.func_arg = opt_pretty},
"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_data_hash", OPT_STRING | HAS_ARG, {(void*)&show_data_hash}, "show packets data hash" },
Stefano Sabatini
committed
{ "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" },
Stefano Sabatini
committed
{ "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" },
Stefano Sabatini
committed
{ "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" },
Stefano Sabatini
committed
{ "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_pixel_formats", 0, {(void*)&opt_show_pixel_formats}, "show pixel format descriptions" },
{ "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
committed
static inline int check_section_show_entries(int section_id)
{
int *id;
struct section *section = §ions[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)
const Writer *w;
WriterContext *wctx;
char *buf;
char *w_name = NULL, *w_args = NULL;
Stefano Sabatini
committed
int ret, i;
av_log_set_flags(AV_LOG_SKIP_REPEATED);
register_exit(ffprobe_cleanup);
options = real_options;
parse_loglevel(argc, argv, options);
avformat_network_init();
#if CONFIG_AVDEVICE
avdevice_register_all();