Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
1c43713e
Commit
1c43713e
authored
Oct 02, 2011
by
Stefano Sabatini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ffprobe: add compact writer
parent
0491a2a0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
281 additions
and
1 deletion
+281
-1
Changelog
Changelog
+1
-0
ffprobe.texi
doc/ffprobe.texi
+52
-0
ffprobe.c
ffprobe.c
+228
-1
No files found.
Changelog
View file @
1c43713e
...
...
@@ -121,6 +121,7 @@ easier to use. The changes are:
- Discworld II BMV decoding support
- VBLE Decoder
- OS X Video Decoder Acceleration (VDA) support
- compact output in ffprobe
version 0.8:
...
...
doc/ffprobe.texi
View file @
1c43713e
...
...
@@ -147,6 +147,58 @@ keyN=valN
Metadata tags are printed as a line in the corresponding FORMAT or
STREAM section, and are prefixed by the string "TAG:".
@section compact
Compact format.
Each section is printed on a single line.
If no option is specifid, the output has the form:
@example
section|key1=val1| ... |keyN=valN
@end example
Metadata tags are printed in the corresponding "format" or "stream"
section. A metadata tag key, if printed, is prefixed by the string
"tag:".
This writer accepts options as a list of @var
{
key
}
=@var
{
value
}
pairs,
separated by ":".
The description of the accepted options follows.
@table @option
@item item
_
sep, s
Specify the character to use for separating fields in the output line.
It must be a single printable character, it is "|" by default.
@item nokey, nk
If set to 1 specify not to print the key of each field. Its default
value is 0.
@item escape, e
Set the escape mode to use, default to "c".
It can assume one of the following values:
@table @option
@item c
Perform C-like escaping. Strings containing a newline ('
\n
') or
carriage return ('
\r
'), the escaping character ('
\'
) or the item
separator character @var
{
SEP
}
are escaped using C-like fashioned
escaping, so that a newline is converted to the sequence "
\n
", a
carriage return to "
\r
", '
\'
to "
\\
" and the separator @var
{
SEP
}
is
converted to "
\@
var
{
SEP
}
".
@item csv
Perform CSV-like escaping, as described in RFC4180. Strings
containing a newline ('
\n
'), a carriage return ('
\r
'), a double quote
('"'), or @var
{
SEP
}
are enclosed in double-quotes.
@item none
Perform no escaping.
@end table
@end table
@section json
JSON based format.
...
...
ffprobe.c
View file @
1c43713e
...
...
@@ -462,6 +462,232 @@ static Writer default_writer = {
.
flags
=
WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS
,
};
/* Compact output */
/**
* Escape \n, \r, \\ and sep characters contained in s, and print the
* resulting string.
*/
static
const
char
*
c_escape_str
(
char
**
dst
,
size_t
*
dst_size
,
const
char
*
src
,
const
char
sep
,
void
*
log_ctx
)
{
const
char
*
p
;
char
*
q
;
size_t
size
=
1
;
/* precompute size */
for
(
p
=
src
;
*
p
;
p
++
,
size
++
)
{
ESCAPE_CHECK_SIZE
(
src
,
size
,
SIZE_MAX
-
2
);
if
(
*
p
==
'\n'
||
*
p
==
'\r'
||
*
p
==
'\\'
)
size
++
;
}
ESCAPE_REALLOC_BUF
(
dst_size
,
dst
,
src
,
size
);
q
=
*
dst
;
for
(
p
=
src
;
*
p
;
p
++
)
{
switch
(
*
src
)
{
case
'\n'
:
*
q
++
=
'\\'
;
*
q
++
=
'n'
;
break
;
case
'\r'
:
*
q
++
=
'\\'
;
*
q
++
=
'r'
;
break
;
case
'\\'
:
*
q
++
=
'\\'
;
*
q
++
=
'\\'
;
break
;
default:
if
(
*
p
==
sep
)
*
q
++
=
'\\'
;
*
q
++
=
*
p
;
}
}
*
q
=
0
;
return
*
dst
;
}
/**
* Quote fields containing special characters, check RFC4180.
*/
static
const
char
*
csv_escape_str
(
char
**
dst
,
size_t
*
dst_size
,
const
char
*
src
,
const
char
sep
,
void
*
log_ctx
)
{
const
char
*
p
;
char
*
q
;
size_t
size
=
1
;
int
quote
=
0
;
/* precompute size */
for
(
p
=
src
;
*
p
;
p
++
,
size
++
)
{
ESCAPE_CHECK_SIZE
(
src
,
size
,
SIZE_MAX
-
4
);
if
(
*
p
==
'"'
||
*
p
==
sep
||
*
p
==
'\n'
||
*
p
==
'\r'
)
if
(
!
quote
)
{
quote
=
1
;
size
+=
2
;
}
if
(
*
p
==
'"'
)
size
++
;
}
ESCAPE_REALLOC_BUF
(
dst_size
,
dst
,
src
,
size
);
q
=
*
dst
;
p
=
src
;
if
(
quote
)
*
q
++
=
'\"'
;
while
(
*
p
)
{
if
(
*
p
==
'"'
)
*
q
++
=
'\"'
;
*
q
++
=
*
p
++
;
}
if
(
quote
)
*
q
++
=
'\"'
;
*
q
=
0
;
return
*
dst
;
}
static
const
char
*
none_escape_str
(
char
**
dst
,
size_t
*
dst_size
,
const
char
*
src
,
const
char
sep
,
void
*
log_ctx
)
{
return
src
;
}
typedef
struct
CompactContext
{
const
AVClass
*
class
;
char
*
item_sep_str
;
char
item_sep
;
int
nokey
;
char
*
buf
;
size_t
buf_size
;
char
*
escape_mode_str
;
const
char
*
(
*
escape_str
)(
char
**
dst
,
size_t
*
dst_size
,
const
char
*
src
,
const
char
sep
,
void
*
log_ctx
);
}
CompactContext
;
#define OFFSET(x) offsetof(CompactContext, x)
static
const
AVOption
compact_options
[]
=
{
{
"item_sep"
,
"set item separator"
,
OFFSET
(
item_sep_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"|"
},
CHAR_MIN
,
CHAR_MAX
},
{
"s"
,
"set item separator"
,
OFFSET
(
item_sep_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"|"
},
CHAR_MIN
,
CHAR_MAX
},
{
"nokey"
,
"force no key printing"
,
OFFSET
(
nokey
),
AV_OPT_TYPE_INT
,
{.
dbl
=
0
},
0
,
1
},
{
"nk"
,
"force no key printing"
,
OFFSET
(
nokey
),
AV_OPT_TYPE_INT
,
{.
dbl
=
0
},
0
,
1
},
{
"escape"
,
"set escape mode"
,
OFFSET
(
escape_mode_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"c"
},
CHAR_MIN
,
CHAR_MAX
},
{
"e"
,
"set escape mode"
,
OFFSET
(
escape_mode_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"c"
},
CHAR_MIN
,
CHAR_MAX
},
{
NULL
},
};
static
const
char
*
compact_get_name
(
void
*
ctx
)
{
return
"compact"
;
}
static
const
AVClass
compact_class
=
{
"CompactContext"
,
compact_get_name
,
compact_options
};
static
av_cold
int
compact_init
(
WriterContext
*
wctx
,
const
char
*
args
,
void
*
opaque
)
{
CompactContext
*
compact
=
wctx
->
priv
;
int
err
;
compact
->
class
=
&
compact_class
;
av_opt_set_defaults
(
compact
);
if
(
args
&&
(
err
=
(
av_set_options_string
(
compact
,
args
,
"="
,
":"
)))
<
0
)
{
av_log
(
wctx
,
AV_LOG_ERROR
,
"Error parsing options string: '%s'
\n
"
,
args
);
return
err
;
}
if
(
strlen
(
compact
->
item_sep_str
)
!=
1
)
{
av_log
(
wctx
,
AV_LOG_ERROR
,
"Item separator '%s' specified, but must contain a single character
\n
"
,
compact
->
item_sep_str
);
return
AVERROR
(
EINVAL
);
}
compact
->
item_sep
=
compact
->
item_sep_str
[
0
];
compact
->
buf_size
=
ESCAPE_INIT_BUF_SIZE
;
if
(
!
(
compact
->
buf
=
av_malloc
(
compact
->
buf_size
)))
return
AVERROR
(
ENOMEM
);
if
(
!
strcmp
(
compact
->
escape_mode_str
,
"none"
))
compact
->
escape_str
=
none_escape_str
;
else
if
(
!
strcmp
(
compact
->
escape_mode_str
,
"c"
))
compact
->
escape_str
=
c_escape_str
;
else
if
(
!
strcmp
(
compact
->
escape_mode_str
,
"csv"
))
compact
->
escape_str
=
csv_escape_str
;
else
{
av_log
(
wctx
,
AV_LOG_ERROR
,
"Unknown escape mode '%s'
\n
"
,
compact
->
escape_mode_str
);
return
AVERROR
(
EINVAL
);
}
return
0
;
}
static
av_cold
void
compact_uninit
(
WriterContext
*
wctx
)
{
CompactContext
*
compact
=
wctx
->
priv
;
av_freep
(
&
compact
->
item_sep_str
);
av_freep
(
&
compact
->
buf
);
av_freep
(
&
compact
->
escape_mode_str
);
}
static
void
compact_print_section_header
(
WriterContext
*
wctx
,
const
char
*
section
)
{
CompactContext
*
compact
=
wctx
->
priv
;
printf
(
"%s%c"
,
section
,
compact
->
item_sep
);
}
static
void
compact_print_section_footer
(
WriterContext
*
wctx
,
const
char
*
section
)
{
printf
(
"
\n
"
);
}
static
void
compact_print_str
(
WriterContext
*
wctx
,
const
char
*
key
,
const
char
*
value
)
{
CompactContext
*
compact
=
wctx
->
priv
;
if
(
wctx
->
nb_item
)
printf
(
"%c"
,
compact
->
item_sep
);
if
(
!
compact
->
nokey
)
printf
(
"%s="
,
key
);
printf
(
"%s"
,
compact
->
escape_str
(
&
compact
->
buf
,
&
compact
->
buf_size
,
value
,
compact
->
item_sep
,
wctx
));
}
static
void
compact_print_int
(
WriterContext
*
wctx
,
const
char
*
key
,
int
value
)
{
CompactContext
*
compact
=
wctx
->
priv
;
if
(
wctx
->
nb_item
)
printf
(
"%c"
,
compact
->
item_sep
);
if
(
!
compact
->
nokey
)
printf
(
"%s="
,
key
);
printf
(
"%d"
,
value
);
}
static
void
compact_show_tags
(
WriterContext
*
wctx
,
AVDictionary
*
dict
)
{
CompactContext
*
compact
=
wctx
->
priv
;
AVDictionaryEntry
*
tag
=
NULL
;
while
((
tag
=
av_dict_get
(
dict
,
""
,
tag
,
AV_DICT_IGNORE_SUFFIX
)))
{
if
(
wctx
->
nb_item
)
printf
(
"%c"
,
compact
->
item_sep
);
if
(
!
compact
->
nokey
)
printf
(
"tag:%s="
,
compact
->
escape_str
(
&
compact
->
buf
,
&
compact
->
buf_size
,
tag
->
key
,
compact
->
item_sep
,
wctx
));
printf
(
"%s"
,
compact
->
escape_str
(
&
compact
->
buf
,
&
compact
->
buf_size
,
tag
->
value
,
compact
->
item_sep
,
wctx
));
}
}
static
Writer
compact_writer
=
{
.
name
=
"compact"
,
.
priv_size
=
sizeof
(
CompactContext
),
.
init
=
compact_init
,
.
uninit
=
compact_uninit
,
.
print_section_header
=
compact_print_section_header
,
.
print_section_footer
=
compact_print_section_footer
,
.
print_integer
=
compact_print_int
,
.
print_string
=
compact_print_str
,
.
show_tags
=
compact_show_tags
,
.
flags
=
WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS
};
/* JSON output */
typedef
struct
{
...
...
@@ -630,6 +856,7 @@ static void writer_register_all(void)
initialized
=
1
;
writer_register
(
&
default_writer
);
writer_register
(
&
compact_writer
);
writer_register
(
&
json_writer
);
}
...
...
@@ -976,7 +1203,7 @@ static const OptionDef options[] = {
"use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units"
},
{
"pretty"
,
0
,
{(
void
*
)
&
opt_pretty
},
"prettify the format of displayed values, make it more human readable"
},
{
"print_format"
,
OPT_STRING
|
HAS_ARG
,
{(
void
*
)
&
print_format
},
"set the output printing format (available formats are: default, json)"
,
"format"
},
{
"print_format"
,
OPT_STRING
|
HAS_ARG
,
{(
void
*
)
&
print_format
},
"set the output printing format (available formats are: default,
compact,
json)"
,
"format"
},
{
"show_format"
,
OPT_BOOL
,
{(
void
*
)
&
do_show_format
}
,
"show format/container info"
},
{
"show_packets"
,
OPT_BOOL
,
{(
void
*
)
&
do_show_packets
},
"show packets info"
},
{
"show_streams"
,
OPT_BOOL
,
{(
void
*
)
&
do_show_streams
},
"show streams info"
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment