aboutsummaryrefslogtreecommitdiff
path: root/ffprobe.c
diff options
context:
space:
mode:
authorStefano Sabatini2011-10-24 01:23:22 +0200
committerStefano Sabatini2011-11-16 00:30:35 +0100
commit0491a2a07a44f6e5e6f34081835e402c07025fd2 (patch)
tree880ae11629c80894a6d14be4d84f18a8eede1086 /ffprobe.c
parent7776091b9f8af51750b27bacd5a50e35fa3930ea (diff)
ffprobe: force display of missing fields, depending on writer.flags
Add flags field to Writer, and define the WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS flag which forces the display of optional fields, for example non-available or invalid fields. Also set the flag in the default writer. This change is required as for some writers it is preferable to show all fields (for example for avoiding a variable number of fields in CSV output), while for other formats (e.g. JSON, XML) it is better to leave invalid/unavailable fields unspecified and thus simplify the parsing stage on the deserializer side.
Diffstat (limited to 'ffprobe.c')
-rw-r--r--ffprobe.c125
1 files changed, 77 insertions, 48 deletions
diff --git a/ffprobe.c b/ffprobe.c
index e512f00d1b..a8c2ff0c9c 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -121,33 +121,12 @@ static char *value_string(char *buf, int buf_size, struct unit_value uv)
return buf;
}
-static char *time_value_string(char *buf, int buf_size, int64_t val, const AVRational *time_base)
-{
- if (val == AV_NOPTS_VALUE) {
- snprintf(buf, buf_size, "N/A");
- } else {
- double d = val * av_q2d(*time_base);
- value_string(buf, buf_size, (struct unit_value){.val.d=d, .unit=unit_second_str});
- }
-
- return buf;
-}
-
-static char *ts_value_string (char *buf, int buf_size, int64_t ts)
-{
- if (ts == AV_NOPTS_VALUE) {
- snprintf(buf, buf_size, "N/A");
- } else {
- snprintf(buf, buf_size, "%"PRId64, ts);
- }
-
- return buf;
-}
-
/* WRITERS API */
typedef struct WriterContext WriterContext;
+#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
+
typedef struct Writer {
int priv_size; ///< private size for the writer context
const char *name;
@@ -165,6 +144,7 @@ typedef struct Writer {
void (*print_integer) (WriterContext *wctx, const char *, int);
void (*print_string) (WriterContext *wctx, const char *, const char *);
void (*show_tags) (WriterContext *wctx, AVDictionary *dict);
+ int flags; ///< a combination or WRITER_FLAG_*
} Writer;
struct WriterContext {
@@ -281,12 +261,40 @@ static inline void writer_print_integer(WriterContext *wctx,
}
static inline void writer_print_string(WriterContext *wctx,
- const char *key, const char *val)
+ const char *key, const char *val, int opt)
{
+ if (opt && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS))
+ return;
wctx->writer->print_string(wctx, key, val);
wctx->nb_item++;
}
+static void writer_print_time(WriterContext *wctx, const char *key,
+ int64_t ts, const AVRational *time_base)
+{
+ char buf[128];
+
+ if (ts == AV_NOPTS_VALUE) {
+ writer_print_string(wctx, key, "N/A", 1);
+ } else {
+ double d = ts * av_q2d(*time_base);
+ value_string(buf, sizeof(buf), (struct unit_value){.val.d=d, .unit=unit_second_str});
+ writer_print_string(wctx, key, buf, 0);
+ }
+}
+
+static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts)
+{
+ char buf[128];
+
+ if (ts == AV_NOPTS_VALUE) {
+ writer_print_string(wctx, key, "N/A", 1);
+ } else {
+ snprintf(buf, sizeof(buf), "%"PRId64, ts);
+ writer_print_string(wctx, key, buf, 0);
+ }
+}
+
static inline void writer_show_tags(WriterContext *wctx, AVDictionary *dict)
{
wctx->writer->show_tags(wctx, dict);
@@ -438,7 +446,7 @@ static void default_show_tags(WriterContext *wctx, AVDictionary *dict)
AVDictionaryEntry *tag = NULL;
while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
printf("TAG:");
- writer_print_string(wctx, tag->key, tag->value);
+ writer_print_string(wctx, tag->key, tag->value, 0);
}
}
@@ -450,7 +458,8 @@ static Writer default_writer = {
.print_section_footer = default_print_section_footer,
.print_integer = default_print_int,
.print_string = default_print_str,
- .show_tags = default_show_tags
+ .show_tags = default_show_tags,
+ .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
};
/* JSON output */
@@ -626,15 +635,21 @@ static void writer_register_all(void)
#define print_fmt(k, f, ...) do { \
if (fast_asprintf(&pbuf, f, __VA_ARGS__)) \
- writer_print_string(w, k, pbuf.s); \
+ writer_print_string(w, k, pbuf.s, 0); \
+} while (0)
+
+#define print_fmt_opt(k, f, ...) do { \
+ if (fast_asprintf(&pbuf, f, __VA_ARGS__)) \
+ writer_print_string(w, k, pbuf.s, 1); \
} while (0)
#define print_int(k, v) writer_print_integer(w, k, v)
-#define print_str(k, v) writer_print_string(w, k, v)
-#define print_ts(k, v) writer_print_string(w, k, ts_value_string (val_str, sizeof(val_str), v))
-#define print_time(k, v, tb) writer_print_string(w, k, time_value_string(val_str, sizeof(val_str), v, tb))
-#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}))
+#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}), 1)
#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)
@@ -644,9 +659,12 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
char val_str[128];
AVStream *st = fmt_ctx->streams[pkt->stream_index];
struct print_buf pbuf = {.s = NULL};
+ const char *s;
print_section_header("packet");
- print_str("codec_type", av_x_if_null(av_get_media_type_string(st->codec->codec_type), "unknown"));
+ 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);
@@ -655,7 +673,8 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
print_ts ("duration", pkt->duration);
print_time("duration_time", pkt->duration, &st->time_base);
print_val("size", pkt->size, unit_byte_str);
- print_fmt("pos", "%"PRId64, pkt->pos);
+ 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");
@@ -680,6 +699,7 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
AVCodecContext *dec_ctx;
AVCodec *dec;
char val_str[128];
+ const char *s;
AVRational display_aspect_ratio;
struct print_buf pbuf = {.s = NULL};
@@ -692,10 +712,13 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
print_str("codec_name", dec->name);
print_str("codec_long_name", dec->long_name);
} else {
- print_str("codec_name", "unknown");
+ print_str_opt("codec_name", "unknown");
+ print_str_opt("codec_long_name", "unknown");
}
- print_str("codec_type", av_x_if_null(av_get_media_type_string(dec_ctx->codec_type), "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);
/* print AVI/FourCC tag */
@@ -719,21 +742,27 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
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");
}
- print_str("pix_fmt", av_x_if_null(av_get_pix_fmt_name(dec_ctx->pix_fmt), "unknown"));
+ 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);
break;
case AVMEDIA_TYPE_AUDIO:
- print_str("sample_fmt",
- av_x_if_null(av_get_sample_fmt_name(dec_ctx->sample_fmt), "unknown"));
+ 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));
break;
}
} else {
- print_str("codec_type", "unknown");
+ print_str_opt("codec_type", "unknown");
}
if (dec_ctx->codec && dec_ctx->codec->priv_class) {
const AVOption *opt = NULL;
@@ -747,16 +776,15 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
}
}
- if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS)
- print_fmt("id", "0x%x", stream->id);
+ 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 (stream->nb_frames)
- print_fmt("nb_frames", "%"PRId64, stream->nb_frames);
-
+ if (stream->nb_frames) print_fmt ("nb_frames", "%"PRId64, stream->nb_frames);
+ else print_str_opt("nb_frames", "N/A");
show_tags(stream->metadata);
print_section_footer("stream");
@@ -784,9 +812,10 @@ static void show_format(WriterContext *w, AVFormatContext *fmt_ctx)
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);
- print_val("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
+ 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");
av_free(pbuf.s);