FFmpeg
tf_xml.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) The FFmpeg developers
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <limits.h>
22 #include <stdarg.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include "avtextformat.h"
28 #include <libavutil/mem.h>
29 #include <libavutil/avassert.h>
30 #include <libavutil/bprint.h>
31 #include <libavutil/error.h>
32 #include <libavutil/macros.h>
33 #include <libavutil/opt.h>
34 
35 #define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
36 #define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
37 #define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
38 
39 #define DEFINE_FORMATTER_CLASS(name) \
40 static const char *name##_get_name(void *ctx) \
41 { \
42  return #name ; \
43 } \
44 static const AVClass name##_class = { \
45  .class_name = #name, \
46  .item_name = name##_get_name, \
47  .option = name##_options \
48 }
49 
50 /* XML output */
51 
52 typedef struct XMLContext {
53  const AVClass *class;
58 } XMLContext;
59 
60 #undef OFFSET
61 #define OFFSET(x) offsetof(XMLContext, x)
62 
63 static const AVOption xml_options[] = {
64  {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
65  {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
66  {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
67  {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
68  {NULL},
69 };
70 
72 
74 {
75  XMLContext *xml = wctx->priv;
76 
77  if (xml->xsd_strict) {
78  xml->fully_qualified = 1;
79 #define CHECK_COMPLIANCE(opt, opt_name) \
80  if (opt) { \
81  av_log(wctx, AV_LOG_ERROR, \
82  "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
83  "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
84  return AVERROR(EINVAL); \
85  }
86  ////CHECK_COMPLIANCE(show_private_data, "private");
87  CHECK_COMPLIANCE(wctx->show_value_unit, "unit");
88  CHECK_COMPLIANCE(wctx->use_value_prefix, "prefix");
89  }
90 
91  return 0;
92 }
93 
94 #define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
95 
96 static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
97 {
98  XMLContext *xml = wctx->priv;
99  const struct AVTextFormatSection *section = wctx->section[wctx->level];
100  const struct AVTextFormatSection *parent_section = wctx->level ?
101  wctx->section[wctx->level-1] : NULL;
102 
103  if (wctx->level == 0) {
104  const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
105  "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
106  "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
107 
108  writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
109  writer_printf(wctx, "<%sffprobe%s>\n",
110  xml->fully_qualified ? "ffprobe:" : "",
111  xml->fully_qualified ? qual : "");
112  return;
113  }
114 
115  if (xml->within_tag) {
116  xml->within_tag = 0;
117  writer_put_str(wctx, ">\n");
118  }
119 
120  if (parent_section && (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) &&
121  wctx->level && wctx->nb_item[wctx->level-1])
122  writer_w8(wctx, '\n');
123  xml->indent_level++;
124 
126  XML_INDENT(); writer_printf(wctx, "<%s", section->name);
127 
129  AVBPrint buf;
131  av_bprint_escape(&buf, section->get_type(data), NULL,
133  writer_printf(wctx, " type=\"%s\"", buf.str);
134  }
135  writer_printf(wctx, ">\n", section->name);
136  } else {
137  XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
138  xml->within_tag = 1;
139  }
140 }
141 
143 {
144  XMLContext *xml = wctx->priv;
145  const struct AVTextFormatSection *section = wctx->section[wctx->level];
146 
147  if (wctx->level == 0) {
148  writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
149  } else if (xml->within_tag) {
150  xml->within_tag = 0;
151  writer_put_str(wctx, "/>\n");
152  xml->indent_level--;
153  } else {
154  XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
155  xml->indent_level--;
156  }
157 }
158 
159 static void xml_print_value(AVTextFormatContext *wctx, const char *key,
160  const char *str, int64_t num, const int is_int)
161 {
162  AVBPrint buf;
163  XMLContext *xml = wctx->priv;
164  const struct AVTextFormatSection *section = wctx->section[wctx->level];
165 
167 
169  xml->indent_level++;
170  XML_INDENT();
171  av_bprint_escape(&buf, key, NULL,
173  writer_printf(wctx, "<%s key=\"%s\"",
174  section->element_name, buf.str);
175  av_bprint_clear(&buf);
176 
177  if (is_int) {
178  writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
179  } else {
180  av_bprint_escape(&buf, str, NULL,
182  writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
183  }
184  xml->indent_level--;
185  } else {
186  if (wctx->nb_item[wctx->level])
187  writer_w8(wctx, ' ');
188 
189  if (is_int) {
190  writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
191  } else {
192  av_bprint_escape(&buf, str, NULL,
194  writer_printf(wctx, "%s=\"%s\"", key, buf.str);
195  }
196  }
197 
198  av_bprint_finalize(&buf, NULL);
199 }
200 
201 static inline void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value) {
202  xml_print_value(wctx, key, value, 0, 0);
203 }
204 
205 static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
206 {
207  xml_print_value(wctx, key, NULL, value, 1);
208 }
209 
211  .name = "xml",
212  .priv_size = sizeof(XMLContext),
213  .init = xml_init,
214  .print_section_header = xml_print_section_header,
215  .print_section_footer = xml_print_section_footer,
216  .print_integer = xml_print_int,
217  .print_string = xml_print_str,
219  .priv_class = &xml_class,
220 };
221 
flags
const SwsFlags flags[]
Definition: swscale.c:61
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
opt.h
AVTextFormatContext::section
const struct AVTextFormatSection * section[SECTION_MAX_NB_LEVELS]
section per each level
Definition: avtextformat.h:106
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
avtextformatter_xml
const AVTextFormatter avtextformatter_xml
Definition: tf_xml.c:210
int64_t
long long int64_t
Definition: coverity.c:34
AVOption
AVOption.
Definition: opt.h:429
data
const char data[16]
Definition: mxf.c:149
AVTextFormatContext::show_value_unit
int show_value_unit
Definition: avtextformat.h:111
avtextformat.h
AVTextFormatContext
Definition: avtextformat.h:88
XMLContext::within_tag
int within_tag
Definition: tf_xml.c:54
AVTextFormatContext::level
int level
current level, starting from 0
Definition: avtextformat.h:99
AVTextFormatSection::name
const char * name
Definition: avtextformat.h:39
macros.h
xml_print_section_header
static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
Definition: tf_xml.c:96
AVTextFormatSection::flags
int flags
Definition: avtextformat.h:48
avassert.h
av_cold
#define av_cold
Definition: attributes.h:90
AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES
#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES
Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double quoted attributes.
Definition: avstring.h:348
AVTextFormatSection::element_name
const char * element_name
name of the contained element, if provided
Definition: avtextformat.h:50
AVTextFormatter
Definition: avtextformat.h:69
writer_w8
#define writer_w8(wctx_, b_)
Definition: tf_xml.c:35
AVTextFormatSection
Definition: avtextformat.h:37
limits.h
AVTextFormatContext::priv
void * priv
private data for use by the filter
Definition: avtextformat.h:94
key
const char * key
Definition: hwcontext_opencl.c:189
AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE
#define AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE
For these sections the element_name field is mandatory.
Definition: avtextformat.h:45
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
av_bprint_escape
void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars, enum AVEscapeMode mode, int flags)
Escape the content in src and append it to dstbuf.
Definition: bprint.c:268
xml_print_value
static void xml_print_value(AVTextFormatContext *wctx, const char *key, const char *str, int64_t num, const int is_int)
Definition: tf_xml.c:159
writer_printf
#define writer_printf(wctx_, fmt_,...)
Definition: tf_xml.c:37
XML_INDENT
#define XML_INDENT()
Definition: tf_xml.c:94
xml_options
static const AVOption xml_options[]
Definition: tf_xml.c:63
error.h
xml_print_int
static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
Definition: tf_xml.c:205
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
AVTextFormatter::name
const char * name
Definition: avtextformat.h:72
XMLContext::fully_qualified
int fully_qualified
Definition: tf_xml.c:56
AV_ESCAPE_MODE_XML
@ AV_ESCAPE_MODE_XML
Use XML non-markup character data escaping.
Definition: avstring.h:318
AVTextFormatSection::get_type
const char *(* get_type)(const void *data)
function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
Definition: avtextformat.h:53
xml_init
static av_cold int xml_init(AVTextFormatContext *wctx)
Definition: tf_xml.c:73
bprint.h
xml_print_str
static void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
Definition: tf_xml.c:201
AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS
#define AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS
the section may contain a variable number of fields with variable keys.
Definition: avtextformat.h:43
XMLContext::xsd_strict
int xsd_strict
Definition: tf_xml.c:57
xml_print_section_footer
static void xml_print_section_footer(AVTextFormatContext *wctx)
Definition: tf_xml.c:142
CHECK_COMPLIANCE
#define CHECK_COMPLIANCE(opt, opt_name)
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
writer_put_str
#define writer_put_str(wctx_, str_)
Definition: tf_xml.c:36
AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT
#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT
Definition: avtextformat.h:60
AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER
#define AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER
the section only contains other sections, but has no data at its own level
Definition: avtextformat.h:41
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:232
AVTextFormatContext::use_value_prefix
int use_value_prefix
Definition: avtextformat.h:112
XMLContext
Definition: tf_xml.c:52
mem.h
AVTextFormatContext::nb_item
unsigned int nb_item[SECTION_MAX_NB_LEVELS]
number of the item printed in the given section, starting from 0
Definition: avtextformat.h:102
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
XMLContext::indent_level
int indent_level
Definition: tf_xml.c:55
OFFSET
#define OFFSET(x)
Definition: tf_xml.c:61
AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY
#define AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY
the section contains an array of elements of the same type
Definition: avtextformat.h:42
DEFINE_FORMATTER_CLASS
#define DEFINE_FORMATTER_CLASS(name)
Definition: tf_xml.c:39