/* * Copyright (c) The FFmpeg developers * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "avtextformat.h" #include "libavutil/bprint.h" #include "libavutil/opt.h" #define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) #define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) #define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) #define DEFINE_FORMATTER_CLASS(name) \ static const char *name##_get_name(void *ctx) \ { \ return #name ; \ } \ static const AVClass name##_class = { \ .class_name = #name, \ .item_name = name##_get_name, \ .option = name##_options \ } /* Default output */ typedef struct DefaultContext { const AVClass *class; int nokey; int noprint_wrappers; int nested_section[SECTION_MAX_NB_LEVELS]; } DefaultContext; #undef OFFSET #define OFFSET(x) offsetof(DefaultContext, x) static const AVOption default_options[] = { { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 }, { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 }, { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 }, { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 }, {NULL}, }; DEFINE_FORMATTER_CLASS(default); /* lame uppercasing routine, assumes the string is lower case ASCII */ static inline char *upcase_string(char *dst, size_t dst_size, const char *src) { int i; for (i = 0; src[i] && i < dst_size-1; i++) dst[i] = av_toupper(src[i]); dst[i] = 0; return dst; } static void default_print_section_header(AVTextFormatContext *wctx, const void *data) { DefaultContext *def = wctx->priv; char buf[32]; const struct AVTextFormatSection *section = wctx->section[wctx->level]; const struct AVTextFormatSection *parent_section = wctx->level ? wctx->section[wctx->level-1] : NULL; av_bprint_clear(&wctx->section_pbuf[wctx->level]); if (parent_section && !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) { def->nested_section[wctx->level] = 1; av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:", wctx->section_pbuf[wctx->level-1].str, upcase_string(buf, sizeof(buf), av_x_if_null(section->element_name, section->name))); } if (def->noprint_wrappers || def->nested_section[wctx->level]) return; if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name)); } static void default_print_section_footer(AVTextFormatContext *wctx) { DefaultContext *def = wctx->priv; const struct AVTextFormatSection *section = wctx->section[wctx->level]; char buf[32]; if (def->noprint_wrappers || def->nested_section[wctx->level]) return; if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name)); } static void default_print_str(AVTextFormatContext *wctx, const char *key, const char *value) { DefaultContext *def = wctx->priv; if (!def->nokey) writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key); writer_printf(wctx, "%s\n", value); } static void default_print_int(AVTextFormatContext *wctx, const char *key, int64_t value) { DefaultContext *def = wctx->priv; if (!def->nokey) writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key); writer_printf(wctx, "%"PRId64"\n", value); } const AVTextFormatter avtextformatter_default = { .name = "default", .priv_size = sizeof(DefaultContext), .print_section_header = default_print_section_header, .print_section_footer = default_print_section_footer, .print_integer = default_print_int, .print_string = default_print_str, .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS, .priv_class = &default_class, };