diff options
author | Clément Bœsch <ubitux@gmail.com> | 2011-09-12 19:22:53 +0200 |
---|---|---|
committer | Clément Bœsch <ubitux@gmail.com> | 2011-09-13 22:41:08 +0200 |
commit | afbeb494565de2530d0dd288588434d9d2902cda (patch) | |
tree | 9275f1548a633460874604c02690897f1957d94a /ffprobe.c | |
parent | e29d6db55b96a642c5498794247742020697369a (diff) | |
download | ffmpeg-afbeb494565de2530d0dd288588434d9d2902cda.tar.gz |
ffprobe: replace fmt callback with str callback.
Having a string callback is much more simpler than a variable args
one for writers to deal with, especially when dealing with escaping.
This patch also introduces a local fast_asprintf() function which is
similar to av_asprintf() but avoids reallocating at each print (leading
to a performance issue).
Diffstat (limited to 'ffprobe.c')
-rw-r--r-- | ffprobe.c | 64 |
1 files changed, 54 insertions, 10 deletions
@@ -137,8 +137,8 @@ struct writer { const char *header, *footer; void (*print_header)(const char *); void (*print_footer)(const char *); - void (*print_fmt_f)(const char *, const char *, ...); void (*print_int_f)(const char *, int); + void (*print_str_f)(const char *, const char *); void (*show_tags)(struct writer *w, AVDictionary *dict); }; @@ -150,13 +150,9 @@ static void default_print_header(const char *section) printf("[%s]\n", section); } -static void default_print_fmt(const char *key, const char *fmt, ...) +static void default_print_str(const char *key, const char *value) { - va_list ap; - va_start(ap, fmt); - printf("%s=", key); - vprintf(fmt, ap); - va_end(ap); + printf("%s=%s", key, value); } static void default_print_int(const char *key, int value) @@ -172,11 +168,51 @@ static void default_print_footer(const char *section) /* Print helpers */ -#define print_fmt0(k, f, ...) w->print_fmt_f(k, f, __VA_ARGS__) +struct print_buf { + char *s; + int len; +}; + +static char *fast_asprintf(struct print_buf *pbuf, const char *fmt, ...) +{ + va_list va; + int len; + + va_start(va, fmt); + len = vsnprintf(NULL, 0, fmt, va); + va_end(va); + if (len < 0) + goto fail; + + if (pbuf->len < len) { + char *p = av_realloc(pbuf->s, len + 1); + if (!p) + goto fail; + pbuf->s = p; + pbuf->len = len; + } + + va_start(va, fmt); + len = vsnprintf(pbuf->s, len + 1, fmt, va); + va_end(va); + if (len < 0) + goto fail; + return pbuf->s; + +fail: + av_freep(&pbuf->s); + pbuf->len = 0; + return NULL; +} + +#define print_fmt0(k, f, ...) do { \ + if (fast_asprintf(&pbuf, f, __VA_ARGS__)) \ + w->print_str_f(k, pbuf.s); \ +} while (0) #define print_fmt( k, f, ...) do { \ if (w->item_sep) \ printf("%s", w->item_sep); \ - w->print_fmt_f(k, f, __VA_ARGS__); \ + print_fmt0(k, f, __VA_ARGS__); \ } while (0) #define print_int0(k, v) w->print_int_f(k, v) @@ -194,6 +230,7 @@ static void show_packet(struct writer *w, AVFormatContext *fmt_ctx, AVPacket *pk { char val_str[128]; AVStream *st = fmt_ctx->streams[pkt->stream_index]; + struct print_buf pbuf = {.s = NULL}; if (packet_idx) printf("%s", w->items_sep); @@ -210,6 +247,7 @@ static void show_packet(struct writer *w, AVFormatContext *fmt_ctx, AVPacket *pk print_fmt("pos", "%"PRId64, pkt->pos); print_fmt("flags", "%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_'); w->print_footer("PACKET"); + av_free(pbuf.s); fflush(stdout); } @@ -227,10 +265,12 @@ static void show_packets(struct writer *w, AVFormatContext *fmt_ctx) static void default_show_tags(struct writer *w, AVDictionary *dict) { AVDictionaryEntry *tag = NULL; + struct print_buf pbuf = {.s = NULL}; while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) { printf("\nTAG:"); print_str0(tag->key, tag->value); } + av_free(pbuf.s); } static void show_stream(struct writer *w, AVFormatContext *fmt_ctx, int stream_idx) @@ -240,6 +280,7 @@ static void show_stream(struct writer *w, AVFormatContext *fmt_ctx, int stream_i AVCodec *dec; char val_str[128]; AVRational display_aspect_ratio; + struct print_buf pbuf = {.s = NULL}; if (stream_idx) printf("%s", w->items_sep); @@ -307,6 +348,7 @@ static void show_stream(struct writer *w, AVFormatContext *fmt_ctx, int stream_i w->show_tags(w, stream->metadata); w->print_footer("STREAM"); + av_free(pbuf.s); fflush(stdout); } @@ -320,6 +362,7 @@ static void show_streams(struct writer *w, AVFormatContext *fmt_ctx) static void show_format(struct writer *w, AVFormatContext *fmt_ctx) { char val_str[128]; + struct print_buf pbuf = {.s = NULL}; w->print_header("FORMAT"); print_str0("filename", fmt_ctx->filename); @@ -332,6 +375,7 @@ static void show_format(struct writer *w, AVFormatContext *fmt_ctx) print_str("bit_rate", value_string(val_str, sizeof(val_str), fmt_ctx->bit_rate, unit_bit_per_second_str)); w->show_tags(w, fmt_ctx->metadata); w->print_footer("FORMAT"); + av_free(pbuf.s); fflush(stdout); } @@ -380,8 +424,8 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename) #define WRITER_FUNC(func) \ .print_header = func ## _print_header, \ .print_footer = func ## _print_footer, \ - .print_fmt_f = func ## _print_fmt, \ .print_int_f = func ## _print_int, \ + .print_str_f = func ## _print_str, \ .show_tags = func ## _show_tags static struct writer writers[] = {{ |