Newer
Older
}
static void json_print_section_header(WriterContext *wctx, const char *section)
{
JSONContext *json = wctx->priv;
if (wctx->nb_section)
printf(",\n");
JSON_INDENT();
if (!wctx->multiple_sections)
printf("\"%s\": ", section);
printf("{%s", json->item_start_end);
json->indent_level++;
/* this is required so the parser can distinguish between packets and frames */
if (wctx->is_packets_and_frames) {
if (!json->compact)
JSON_INDENT();
printf("\"type\": \"%s\"%s", section, json->item_sep);
}
static void json_print_section_footer(WriterContext *wctx, const char *section)
{
JSONContext *json = wctx->priv;
printf("%s", json->item_start_end);
json->indent_level--;
if (!json->compact)
JSON_INDENT();
printf("}");
}
static inline void json_print_item_str(WriterContext *wctx,
const char *key, const char *value)
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
printf("\"%s\":", json_escape_str(&buf, key, wctx));
printf(" \"%s\"", json_escape_str(&buf, value, wctx));
av_bprint_finalize(&buf, NULL);
}
static void json_print_str(WriterContext *wctx, const char *key, const char *value)
{
JSONContext *json = wctx->priv;
if (wctx->nb_item) printf("%s", json->item_sep);
if (!json->compact)
JSON_INDENT();
json_print_item_str(wctx, key, value);
}
static void json_print_int(WriterContext *wctx, const char *key, long long int value)
JSONContext *json = wctx->priv;
if (wctx->nb_item) printf("%s", json->item_sep);
if (!json->compact)
JSON_INDENT();
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
av_bprint_finalize(&buf, NULL);
static void json_show_tags(WriterContext *wctx, AVDictionary *dict)
{
JSONContext *json = wctx->priv;
AVDictionaryEntry *tag = NULL;
int is_first = 1;
if (!dict)
return;
printf("%s", json->item_sep);
if (!json->compact)
JSON_INDENT();
printf("\"tags\": {%s", json->item_start_end);
json->indent_level++;
while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
if (is_first) is_first = 0;
else printf("%s", json->item_sep);
if (!json->compact)
JSON_INDENT();
json_print_item_str(wctx, tag->key, tag->value);
json->indent_level--;
printf("%s", json->item_start_end);
if (!json->compact)
JSON_INDENT();
printf("}");
}
.name = "json",
.priv_size = sizeof(JSONContext),
.init = json_init,
.print_header = json_print_header,
.print_footer = json_print_footer,
.print_chapter_header = json_print_chapter_header,
.print_chapter_footer = json_print_chapter_footer,
.print_section_header = json_print_section_header,
.print_section_footer = json_print_section_footer,
.print_integer = json_print_int,
.print_string = json_print_str,
.show_tags = json_show_tags,
.flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
};
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
/* XML output */
typedef struct {
const AVClass *class;
int within_tag;
int indent_level;
int fully_qualified;
int xsd_strict;
} XMLContext;
#undef OFFSET
#define OFFSET(x) offsetof(XMLContext, x)
static const AVOption xml_options[] = {
{"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
{"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
{"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
{"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
{NULL},
};
static const char *xml_get_name(void *ctx)
{
return "xml";
}
static const AVClass xml_class = {
"XMLContext",
xml_get_name,
xml_options
};
static av_cold int xml_init(WriterContext *wctx, const char *args, void *opaque)
{
XMLContext *xml = wctx->priv;
int err;
xml->class = &xml_class;
av_opt_set_defaults(xml);
if (args &&
(err = (av_set_options_string(xml, args, "=", ":"))) < 0) {
av_log(wctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
return err;
}
if (xml->xsd_strict) {
xml->fully_qualified = 1;
#define CHECK_COMPLIANCE(opt, opt_name) \
if (opt) { \
av_log(wctx, AV_LOG_ERROR, \
"XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
"You need to disable such option with '-no%s'\n", opt_name, opt_name); \
Stefano Sabatini
committed
return AVERROR(EINVAL); \
}
CHECK_COMPLIANCE(show_private_data, "private");
CHECK_COMPLIANCE(show_value_unit, "unit");
CHECK_COMPLIANCE(use_value_prefix, "prefix");
if (do_show_frames && do_show_packets) {
av_log(wctx, AV_LOG_ERROR,
"Interleaved frames and packets are not allowed in XSD. "
"Select only one between the -show_frames and the -show_packets options.\n");
return AVERROR(EINVAL);
}
static const char *xml_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
case '&' : av_bprintf(dst, "%s", "&"); break;
case '<' : av_bprintf(dst, "%s", "<"); break;
case '>' : av_bprintf(dst, "%s", ">"); break;
case '\"': av_bprintf(dst, "%s", """); break;
case '\'': av_bprintf(dst, "%s", "'"); break;
default: av_bprint_chars(dst, *p, 1);
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
}
static void xml_print_header(WriterContext *wctx)
{
XMLContext *xml = wctx->priv;
const char *qual = " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
"xmlns:ffprobe='http://www.ffmpeg.org/schema/ffprobe' "
"xsi:schemaLocation='http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd'";
printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
printf("<%sffprobe%s>\n",
xml->fully_qualified ? "ffprobe:" : "",
xml->fully_qualified ? qual : "");
xml->indent_level++;
}
static void xml_print_footer(WriterContext *wctx)
{
XMLContext *xml = wctx->priv;
xml->indent_level--;
printf("</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
}
#define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ')
static void xml_print_chapter_header(WriterContext *wctx, const char *chapter)
{
XMLContext *xml = wctx->priv;
if (wctx->nb_chapter)
printf("\n");
Clément Bœsch
committed
if (wctx->multiple_sections) {
XML_INDENT(); printf("<%s>\n", chapter);
xml->indent_level++;
}
}
static void xml_print_chapter_footer(WriterContext *wctx, const char *chapter)
{
XMLContext *xml = wctx->priv;
Clément Bœsch
committed
if (wctx->multiple_sections) {
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
xml->indent_level--;
XML_INDENT(); printf("</%s>\n", chapter);
}
}
static void xml_print_section_header(WriterContext *wctx, const char *section)
{
XMLContext *xml = wctx->priv;
XML_INDENT(); printf("<%s ", section);
xml->within_tag = 1;
}
static void xml_print_section_footer(WriterContext *wctx, const char *section)
{
XMLContext *xml = wctx->priv;
if (xml->within_tag)
printf("/>\n");
else {
XML_INDENT(); printf("</%s>\n", section);
}
}
static void xml_print_str(WriterContext *wctx, const char *key, const char *value)
{
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
printf("%s=\"%s\"", key, xml_escape_str(&buf, value, wctx));
av_bprint_finalize(&buf, NULL);
}
static void xml_print_int(WriterContext *wctx, const char *key, long long int value)
{
if (wctx->nb_item)
printf(" ");
printf("%s=\"%lld\"", key, value);
}
static void xml_show_tags(WriterContext *wctx, AVDictionary *dict)
{
XMLContext *xml = wctx->priv;
AVDictionaryEntry *tag = NULL;
int is_first = 1;
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
xml->indent_level++;
while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
if (is_first) {
/* close section tag */
printf(">\n");
xml->within_tag = 0;
is_first = 0;
}
XML_INDENT();
printf("<tag key=\"%s\"", xml_escape_str(&buf, tag->key, wctx));
printf(" value=\"%s\"/>\n", xml_escape_str(&buf, tag->value, wctx));
av_bprint_finalize(&buf, NULL);
xml->indent_level--;
}
static Writer xml_writer = {
.name = "xml",
.priv_size = sizeof(XMLContext),
.init = xml_init,
.print_header = xml_print_header,
.print_footer = xml_print_footer,
.print_chapter_header = xml_print_chapter_header,
.print_chapter_footer = xml_print_chapter_footer,
.print_section_header = xml_print_section_header,
.print_section_footer = xml_print_section_footer,
.print_integer = xml_print_int,
.print_string = xml_print_str,
.show_tags = xml_show_tags,
.flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
static void writer_register_all(void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
writer_register(&default_writer);
writer_register(&json_writer);
}
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
writer_print_string(w, k, pbuf.str, 0); \
} while (0)
#define print_int(k, v) writer_print_integer(w, k, v)
#define print_str(k, v) writer_print_string(w, k, v, 0)
#define print_str_opt(k, v) writer_print_string(w, k, v, 1)
#define print_time(k, v, tb) writer_print_time(w, k, v, tb)
#define print_ts(k, v) writer_print_ts(w, k, v)
#define print_val(k, v, u) writer_print_string(w, k, \
value_string(val_str, sizeof(val_str), (struct unit_value){.val.i = v, .unit=u}), 0)
#define print_section_header(s) writer_print_section_header(w, s)
#define print_section_footer(s) writer_print_section_footer(w, s)
#define show_tags(metadata) writer_show_tags(w, metadata)
static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pkt, int packet_idx)
{
char val_str[128];
AVStream *st = fmt_ctx->streams[pkt->stream_index];
const char *s;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
print_section_header("packet");
s = av_get_media_type_string(st->codec->codec_type);
if (s) print_str ("codec_type", s);
else print_str_opt("codec_type", "unknown");
print_int("stream_index", pkt->stream_index);
print_ts ("pts", pkt->pts);
print_time("pts_time", pkt->pts, &st->time_base);
print_ts ("dts", pkt->dts);
print_time("dts_time", pkt->dts, &st->time_base);
print_ts ("duration", pkt->duration);
print_time("duration_time", pkt->duration, &st->time_base);
print_val("size", pkt->size, unit_byte_str);
if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos);
else print_str_opt("pos", "N/A");
print_fmt("flags", "%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_');
print_section_footer("packet");
av_bprint_finalize(&pbuf, NULL);
static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream)
{
const char *s;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
print_section_header("frame");
s = av_get_media_type_string(stream->codec->codec_type);
if (s) print_str ("media_type", s);
else print_str_opt("media_type", "unknown");
print_int("key_frame", frame->key_frame);
print_ts ("pkt_pts", frame->pkt_pts);
print_time("pkt_pts_time", frame->pkt_pts, &stream->time_base);
print_ts ("pkt_dts", frame->pkt_dts);
print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base);
if (frame->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, frame->pkt_pos);
else print_str_opt("pkt_pos", "N/A");
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
print_int("width", frame->width);
print_int("height", frame->height);
s = av_get_pix_fmt_name(frame->format);
if (s) print_str ("pix_fmt", s);
else print_str_opt("pix_fmt", "unknown");
if (frame->sample_aspect_ratio.num) {
print_fmt("sample_aspect_ratio", "%d:%d",
frame->sample_aspect_ratio.num,
frame->sample_aspect_ratio.den);
} else {
print_str_opt("sample_aspect_ratio", "N/A");
}
print_fmt("pict_type", "%c", av_get_picture_type_char(frame->pict_type));
print_int("coded_picture_number", frame->coded_picture_number);
print_int("display_picture_number", frame->display_picture_number);
print_int("interlaced_frame", frame->interlaced_frame);
print_int("top_field_first", frame->top_field_first);
print_int("repeat_pict", frame->repeat_pict);
print_int("reference", frame->reference);
break;
case AVMEDIA_TYPE_AUDIO:
s = av_get_sample_fmt_name(frame->format);
if (s) print_str ("sample_fmt", s);
else print_str_opt("sample_fmt", "unknown");
print_int("nb_samples", frame->nb_samples);
break;
}
print_section_footer("frame");
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
static av_always_inline int get_decoded_frame(AVFormatContext *fmt_ctx,
AVFrame *frame, int *got_frame,
AVPacket *pkt)
{
AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
int ret = 0;
*got_frame = 0;
switch (dec_ctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_decode_video2(dec_ctx, frame, got_frame, pkt);
break;
case AVMEDIA_TYPE_AUDIO:
ret = avcodec_decode_audio4(dec_ctx, frame, got_frame, pkt);
break;
}
return ret;
static void read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
AVPacket pkt, pkt1;
AVFrame frame;
int i = 0, ret, got_frame;
while (!av_read_frame(fmt_ctx, &pkt)) {
if (do_read_packets) {
if (do_show_packets)
show_packet(w, fmt_ctx, &pkt, i++);
nb_streams_packets[pkt.stream_index]++;
}
if (do_read_frames) {
pkt1 = pkt;
avcodec_get_frame_defaults(&frame);
ret = get_decoded_frame(fmt_ctx, &frame, &got_frame, &pkt1);
if (ret < 0 || !got_frame)
break;
if (do_show_frames)
show_frame(w, &frame, fmt_ctx->streams[pkt.stream_index]);
pkt1.data += ret;
pkt1.size -= ret;
nb_streams_frames[pkt.stream_index]++;
}
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
//Flush remaining frames that are cached in the decoder
for (i = 0; i < fmt_ctx->nb_streams; i++) {
pkt.stream_index = i;
while (get_decoded_frame(fmt_ctx, &frame, &got_frame, &pkt) >= 0 && got_frame) {
if (do_read_frames) {
if (do_show_frames)
show_frame(w, &frame, fmt_ctx->streams[pkt.stream_index]);
nb_streams_frames[pkt.stream_index]++;
}
}
static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx)
{
AVStream *stream = fmt_ctx->streams[stream_idx];
AVCodecContext *dec_ctx;
AVCodec *dec;
char val_str[128];
const char *s;
AVRational display_aspect_ratio;
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
print_section_header("stream");
print_int("index", stream->index);
const char *profile = NULL;
print_str("codec_name", dec->name);
print_str("codec_long_name", dec->long_name);
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_fmt("codec_time_base", "%d/%d", dec_ctx->time_base.num, dec_ctx->time_base.den);
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);
if (dec_ctx->sample_aspect_ratio.num) {
print_fmt("sample_aspect_ratio", "%d:%d",
dec_ctx->sample_aspect_ratio.num,
dec_ctx->sample_aspect_ratio.den);
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
dec_ctx->width * dec_ctx->sample_aspect_ratio.num,
dec_ctx->height * dec_ctx->sample_aspect_ratio.den,
1024*1024);
print_fmt("display_aspect_ratio", "%d:%d",
display_aspect_ratio.num,
display_aspect_ratio.den);
} 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->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);
print_int("bits_per_sample", av_get_bits_per_sample(dec_ctx->codec_id));
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_fmt("r_frame_rate", "%d/%d", stream->r_frame_rate.num, stream->r_frame_rate.den);
print_fmt("avg_frame_rate", "%d/%d", stream->avg_frame_rate.num, stream->avg_frame_rate.den);
print_fmt("time_base", "%d/%d", stream->time_base.num, stream->time_base.den);
print_time("start_time", stream->start_time, &stream->time_base);
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 (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");
show_tags(stream->metadata);
print_section_footer("stream");
av_bprint_finalize(&pbuf, NULL);
static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
{
int i;
for (i = 0; i < fmt_ctx->nb_streams; i++)
show_stream(w, fmt_ctx, i);
}
static void show_format(WriterContext *w, AVFormatContext *fmt_ctx)
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
print_section_header("format");
print_str("filename", fmt_ctx->filename);
print_int("nb_streams", fmt_ctx->nb_streams);
print_str("format_name", fmt_ctx->iformat->name);
print_str("format_long_name", fmt_ctx->iformat->long_name);
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");
show_tags(fmt_ctx->metadata);
print_section_footer("format");
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_chapter_header(w, "error");
print_section_header("error");
print_int("code", err);
print_str("string", errbuf_ptr);
print_section_footer("error");
writer_print_chapter_footer(w, "error");
}
static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
{
int err, i;
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;
}
if ((err = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
print_error(filename, err);
return err;
}
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 (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
av_log(NULL, AV_LOG_ERROR,
"Unsupported codec with id %d for input stream %d\n",
stream->codec->codec_id, stream->index);
} else if (avcodec_open2(stream->codec, codec, NULL) < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while opening codec for input stream %d\n",
stream->index);
}
}
*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 != CODEC_ID_NONE)
avcodec_close(fmt_ctx->streams[i]->codec);
avformat_close_input(ctx_ptr);
}
#define PRINT_CHAPTER(name) do { \
if (do_show_ ## name) { \
writer_print_chapter_header(wctx, #name); \
show_ ## name (wctx, fmt_ctx); \
writer_print_chapter_footer(wctx, #name); \
} \
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) {
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));
if (do_read_frames || do_read_packets) {
const char *chapter;
if (do_show_frames && do_show_packets &&
wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
chapter = "packets_and_frames";
else if (do_show_packets && !do_show_frames)
chapter = "packets";
else // (!do_show_packets && do_show_frames)
chapter = "frames";
if (do_show_frames || do_show_packets)
writer_print_chapter_header(wctx, chapter);
read_packets(wctx, fmt_ctx);
if (do_show_frames || do_show_packets)
writer_print_chapter_footer(wctx, chapter);
PRINT_CHAPTER(streams);
PRINT_CHAPTER(format);
close_input_file(&fmt_ctx);
av_freep(&nb_streams_frames);
av_freep(&nb_streams_packets);
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_chapter_header(w, "program_version");
print_section_header("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_type", CC_TYPE);
print_str("compiler_version", CC_VERSION);
print_str("configuration", FFMPEG_CONFIGURATION);
print_section_footer("program_version");
writer_print_chapter_footer(w, "program_version");
av_bprint_finalize(&pbuf, NULL);
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
}
#define SHOW_LIB_VERSION(libname, LIBNAME) \
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
print_section_header("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_section_footer("library_version"); \
} \
} while (0)
static void ffprobe_show_library_versions(WriterContext *w)
{
writer_print_chapter_header(w, "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_chapter_footer(w, "library_versions");
}
static int opt_format(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);
}
}
static int opt_show_format_entry(const char *opt, const char *arg)
{
do_show_format = 1;
av_dict_set(&fmt_entries_to_show, arg, "", 0);
return 0;
}
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);
if (!strcmp(arg, "-"))
arg = "pipe:";
input_filename = arg;
Jeff Downs
committed
static int opt_help(const char *opt, const char *arg)
av_log_set_callback(log_callback_help);
show_usage();
show_help_options(options, "Main options:\n", 0, 0);
printf("\n");
show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
Jeff Downs
committed
return 0;
static int opt_pretty(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;
static int opt_show_versions(const char *opt, const char *arg)
{
do_show_program_version = 1;
do_show_library_versions = 1;
return 0;
}
static const OptionDef options[] = {
#include "cmdutils_common_opts.h"
{ "f", HAS_ARG, {(void*)opt_format}, "force format", "format" },
{ "unit", OPT_BOOL, {(void*)&show_value_unit}, "show unit of the displayed values" },
{ "prefix", OPT_BOOL, {(void*)&use_value_prefix}, "use SI prefixes for the displayed values" },
{ "byte_binary_prefix", OPT_BOOL, {(void*)&use_byte_value_binary_prefix},
"use binary prefixes for byte units" },
{ "sexagesimal", OPT_BOOL, {(void*)&use_value_sexagesimal_format},
"use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
{ "pretty", 0, {(void*)&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, ini, json, xml)", "format" },
{ "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" },
{ "show_error", OPT_BOOL, {(void*)&do_show_error} , "show probing error" },
{ "show_format", OPT_BOOL, {(void*)&do_show_format} , "show format/container info" },
{ "show_frames", OPT_BOOL, {(void*)&do_show_frames} , "show frames info" },
{ "show_format_entry", HAS_ARG, {(void*)opt_show_format_entry},
"show a particular entry from the format/container info", "entry" },
{ "show_packets", OPT_BOOL, {(void*)&do_show_packets}, "show packets info" },
{ "show_streams", OPT_BOOL, {(void*)&do_show_streams}, "show streams 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", OPT_BOOL, {(void*)&do_show_program_version}, "show ffprobe version" },
{ "show_library_versions", OPT_BOOL, {(void*)&do_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" },
{ "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
{ "i", HAS_ARG, {(void *)opt_input_file}, "read specified file", "input_file"},
{ NULL, },
};
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);
parse_loglevel(argc, argv, options);
avformat_network_init();
#if CONFIG_AVDEVICE
avdevice_register_all();
#endif
show_banner(argc, argv, options);
parse_options(NULL, argc, argv, options, opt_input_file);
writer_register_all();
if (!print_format)
print_format = av_strdup("default");
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, NULL)) >= 0) {
writer_print_header(wctx);
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_streams || 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);
} else if (input_filename) {
ret = probe_file(wctx, input_filename);
if (ret < 0 && do_show_error)
show_error(wctx, ret);
}
writer_print_footer(wctx);
writer_close(&wctx);
}
end:
av_freep(&print_format);
uninit_opts();
av_dict_free(&fmt_entries_to_show);
avformat_network_deinit();