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/bprint.h"
29 #include "libavutil/error.h"
30 #include "libavutil/opt.h"
31 
32 #define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
33 #define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
34 #define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
35 
36 #define DEFINE_FORMATTER_CLASS(name) \
37 static const char *name##_get_name(void *ctx) \
38 { \
39  return #name ; \
40 } \
41 static const AVClass name##_class = { \
42  .class_name = #name, \
43  .item_name = name##_get_name, \
44  .option = name##_options \
45 }
46 
47 /* XML output */
48 
49 typedef struct XMLContext {
50  const AVClass *class;
55 } XMLContext;
56 
57 #undef OFFSET
58 #define OFFSET(x) offsetof(XMLContext, x)
59 
60 static const AVOption xml_options[] = {
61  {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
62  {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
63  {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
64  {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
65  {NULL},
66 };
67 
69 
71 {
72  XMLContext *xml = wctx->priv;
73 
74  if (xml->xsd_strict) {
75  xml->fully_qualified = 1;
76 #define CHECK_COMPLIANCE(opt, opt_name) \
77  if (opt) { \
78  av_log(wctx, AV_LOG_ERROR, \
79  "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
80  "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
81  return AVERROR(EINVAL); \
82  }
83  ////CHECK_COMPLIANCE(show_private_data, "private");
84  CHECK_COMPLIANCE(wctx->show_value_unit, "unit");
85  CHECK_COMPLIANCE(wctx->use_value_prefix, "prefix");
86  }
87 
88  return 0;
89 }
90 
91 #define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
92 
93 static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
94 {
95  XMLContext *xml = wctx->priv;
96  const struct AVTextFormatSection *section = wctx->section[wctx->level];
97  const struct AVTextFormatSection *parent_section = wctx->level ?
98  wctx->section[wctx->level-1] : NULL;
99 
100  if (wctx->level == 0) {
101  const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
102  "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
103  "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
104 
105  writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
106  writer_printf(wctx, "<%sffprobe%s>\n",
107  xml->fully_qualified ? "ffprobe:" : "",
108  xml->fully_qualified ? qual : "");
109  return;
110  }
111 
112  if (xml->within_tag) {
113  xml->within_tag = 0;
114  writer_put_str(wctx, ">\n");
115  }
116 
117  if (parent_section && (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) &&
118  wctx->level && wctx->nb_item[wctx->level-1])
119  writer_w8(wctx, '\n');
120  xml->indent_level++;
121 
123  XML_INDENT(); writer_printf(wctx, "<%s", section->name);
124 
126  AVBPrint buf;
128  av_bprint_escape(&buf, section->get_type(data), NULL,
130  writer_printf(wctx, " type=\"%s\"", buf.str);
131  }
132  writer_printf(wctx, ">\n", section->name);
133  } else {
134  XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
135  xml->within_tag = 1;
136  }
137 }
138 
140 {
141  XMLContext *xml = wctx->priv;
142  const struct AVTextFormatSection *section = wctx->section[wctx->level];
143 
144  if (wctx->level == 0) {
145  writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
146  } else if (xml->within_tag) {
147  xml->within_tag = 0;
148  writer_put_str(wctx, "/>\n");
149  xml->indent_level--;
150  } else {
151  XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
152  xml->indent_level--;
153  }
154 }
155 
156 static void xml_print_value(AVTextFormatContext *wctx, const char *key,
157  const char *str, int64_t num, const int is_int)
158 {
159  AVBPrint buf;
160  XMLContext *xml = wctx->priv;
161  const struct AVTextFormatSection *section = wctx->section[wctx->level];
162 
164 
166  xml->indent_level++;
167  XML_INDENT();
168  av_bprint_escape(&buf, key, NULL,
170  writer_printf(wctx, "<%s key=\"%s\"",
171  section->element_name, buf.str);
172  av_bprint_clear(&buf);
173 
174  if (is_int) {
175  writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
176  } else {
177  av_bprint_escape(&buf, str, NULL,
179  writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
180  }
181  xml->indent_level--;
182  } else {
183  if (wctx->nb_item[wctx->level])
184  writer_w8(wctx, ' ');
185 
186  if (is_int) {
187  writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
188  } else {
189  av_bprint_escape(&buf, str, NULL,
191  writer_printf(wctx, "%s=\"%s\"", key, buf.str);
192  }
193  }
194 
195  av_bprint_finalize(&buf, NULL);
196 }
197 
198 static inline void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value) {
199  xml_print_value(wctx, key, value, 0, 0);
200 }
201 
202 static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
203 {
204  xml_print_value(wctx, key, NULL, value, 1);
205 }
206 
208  .name = "xml",
209  .priv_size = sizeof(XMLContext),
210  .init = xml_init,
211  .print_section_header = xml_print_section_header,
212  .print_section_footer = xml_print_section_footer,
213  .print_integer = xml_print_int,
214  .print_string = xml_print_str,
216  .priv_class = &xml_class,
217 };
218 
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:207
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:51
AVTextFormatContext::level
int level
current level, starting from 0
Definition: avtextformat.h:99
AVTextFormatSection::name
const char * name
Definition: avtextformat.h:39
xml_print_section_header
static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
Definition: tf_xml.c:93
AVTextFormatSection::flags
int flags
Definition: avtextformat.h:48
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:32
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:156
writer_printf
#define writer_printf(wctx_, fmt_,...)
Definition: tf_xml.c:34
XML_INDENT
#define XML_INDENT()
Definition: tf_xml.c:91
xml_options
static const AVOption xml_options[]
Definition: tf_xml.c:60
error.h
xml_print_int
static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
Definition: tf_xml.c:202
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:53
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:70
bprint.h
xml_print_str
static void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
Definition: tf_xml.c:198
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:54
xml_print_section_footer
static void xml_print_section_footer(AVTextFormatContext *wctx)
Definition: tf_xml.c:139
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:33
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:49
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:52
OFFSET
#define OFFSET(x)
Definition: tf_xml.c:58
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:36