[FFmpeg-devel] [PATCH] ffprobe: add INI writer

Clément Bœsch ubitux at gmail.com
Sun May 27 10:14:47 CEST 2012


On Sun, May 27, 2012 at 01:37:13AM +0200, Stefano Sabatini wrote:
> Liberally based on the work of Luca Barbato <lu_zero at gentoo.org>, done
> for libav/avprobe.
> ---
>  doc/ffprobe.texi |   24 +++++++++
>  ffprobe.c        |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 167 insertions(+), 1 deletions(-)
> 
> diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
> index ed96575..b6af5df 100644
> --- a/doc/ffprobe.texi
> +++ b/doc/ffprobe.texi
> @@ -269,6 +269,30 @@ CSV format.
>  This writer is equivalent to
>  @code{compact=item_sep=,:nokey=1:escape=csv}.
>  
> + at section ini
> +INI format output.
> +
> +Print output in an INI based format.
> +
> +The following convenctions are adopted:
> +

conventions?

> + at itemize
> + at item
> +all key and values are UTF8

UTF-8

> + at item
> +'.' is the subgroup separator
> + at item
> +newline, tab, form feed, and back space characters are escaped

I'd explicit the \n, \t, ...

> + at item
> +'\' is the escape character
> + at item
> +'#' is the comment indicator
> + at item
> +'=' is the key/value separators

separator?

> + at item
> +':' is not used but usually parsed as key/value separator
> + at end itemize
> +
>  @section json
>  JSON based format.
>  
> diff --git a/ffprobe.c b/ffprobe.c
> index 1375f14..54ab9cd 100644
> --- a/ffprobe.c
> +++ b/ffprobe.c
> @@ -715,6 +715,147 @@ static const Writer csv_writer = {
>      .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
>  };
>  
> +/*
> + * INI format output
> + *
> + * - all key and values are UTF8
> + * - '.' is the subgroup separator
> + * - newlines and the following characters are escaped
> + * - '\' is the escape character
> + * - '#' is the comment
> + * - '=' is the key/value separators
> + * - ':' is not used but usually parsed as key/value separator
> + */
> +

This is already in the documentation with the same typo errors, not sure
it's worth duplicating them.

> +typedef struct IniContext {

Note: do we really need to name these struct?

> +    AVBPrint section_name;
> +    int print_packets_and_frames;
> +    int nb_frame;
> +    int nb_packet;
> +} IniContext;
> +

nit: INIContext?

> +static av_cold int ini_init(WriterContext *wctx, const char *args, void *opaque)
> +{
> +    IniContext *ini = wctx->priv;
> +    av_bprint_init(&ini->section_name, 1, AV_BPRINT_SIZE_UNLIMITED);
> +    ini->nb_frame = ini->nb_packet = 0;
> +
> +    if (args) {
> +        av_log(wctx, AV_LOG_ERROR, "No options supported by the ini format writer: '%s'\n", args);

nit: "INI"? (we should change the strcmp to strcasecmp in the writers
selection).

> +        return AVERROR(EINVAL);
> +    }
> +
> +    return 0;
> +}
> +
> +static av_cold void ini_uninit(WriterContext *wctx)
> +{
> +    IniContext *ini = wctx->priv;
> +    av_bprint_finalize(&ini->section_name, NULL);
> +}
> +
> +static void ini_print_header(WriterContext *wctx)
> +{
> +    printf("# ffprobe output\n\n");
> +}
> +
> +static char *ini_escape_str(AVBPrint *dst, const char *src)
> +{
> +    int i = 0;
> +    char c = 0;
> +
> +    while (c = src[i++]) {
> +        switch (c) {
> +        case '\b': av_bprintf(dst, "%s", "\\b"); break;
> +        case '\f': av_bprintf(dst, "%s", "\\f"); break;
> +        case '\n': av_bprintf(dst, "%s", "\\n"); break;
> +        case '\r': av_bprintf(dst, "%s", "\\r"); break;
> +        case '\t': av_bprintf(dst, "%s", "\\t"); break;
> +        case '\\':
> +        case '#' :
> +        case '=' :
> +        case ':' : av_bprint_chars(dst, '\\', 1);
> +        default:
> +            if ((unsigned char)c < 32)
> +                av_bprintf(dst, "\\x00%02x", c & 0xff);
> +            else
> +                av_bprint_chars(dst, c, 1);
> +        break;

nit: align breaker

> +        }
> +    }
> +    return dst->str;
> +}
> +
> +static void ini_print_chapter_header(WriterContext *wctx, const char *chapter)
> +{
> +    IniContext *ini = wctx->priv;
> +    if (wctx->nb_chapter)
> +        printf("\n");
> +    ini->print_packets_and_frames = !strcmp("packets_and_frames", chapter);
> +}
> +
> +static void ini_print_section_header(WriterContext *wctx, const char *section)
> +{
> +    IniContext *ini = wctx->priv;
> +    int n;
> +    if (wctx->nb_section)
> +        printf("\n");
> +    av_bprint_clear(&ini->section_name);
> +    av_bprintf(&ini->section_name, "%s", section);
> +
> +   if (ini->print_packets_and_frames)

align

> +        n = !strcmp(section, "packet") ? ini->nb_packet++ : ini->nb_frame++;
> +    else
> +        n = wctx->nb_section;
> +    if (wctx->multiple_sections)
> +        av_bprintf(&ini->section_name, ".%d", n);
> +    printf("[%s]\n", ini->section_name.str);
> +}
> +
> +static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
> +{
> +    AVBPrint buf;
> +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
> +
> +    printf("%s=", ini_escape_str(&buf, key));
> +    av_bprint_clear(&buf);
> +    printf("%s\n", ini_escape_str(&buf, value));

I know this is meant to change, but using AV_BPRINT_SIZE_UNLIMITED needs a
finalize to avoid leaks in some cases.

Beside that, the rest LGTM, thanks.

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120527/6e30d1f3/attachment.asc>


More information about the ffmpeg-devel mailing list