27 #include "libavutil/ffversion.h"
70 # ifdef pthread_mutex_lock
71 # undef pthread_mutex_lock
73 # define pthread_mutex_lock(a) do{}while(0)
74 # ifdef pthread_mutex_unlock
75 # undef pthread_mutex_unlock
77 # define pthread_mutex_unlock(a) do{}while(0)
130 #define SHOW_OPTIONAL_FIELDS_AUTO -1
131 #define SHOW_OPTIONAL_FIELDS_NEVER 0
132 #define SHOW_OPTIONAL_FIELDS_ALWAYS 1
154 #define SECTION_MAX_NB_CHILDREN 10
160 #define SECTION_FLAG_IS_WRAPPER 1
161 #define SECTION_FLAG_IS_ARRAY 2
162 #define SECTION_FLAG_HAS_VARIABLE_FIELDS 4
288 static const struct {
294 { 1.0, 1.0,
"",
"" },
295 { 1.024e3, 1e3,
"Ki",
"K" },
296 { 1.048576e6, 1e6,
"Mi",
"M" },
297 { 1.073741824e9, 1e9,
"Gi",
"G" },
298 { 1.099511627776e12, 1e12,
"Ti",
"T" },
299 { 1.125899906842624e15, 1e15,
"Pi",
"P" },
332 static int print_prefix = 1;
333 void *new_log_buffer;
344 if (new_log_buffer) {
357 for (
i=strlen(msg) - 1;
i>=0 && msg[
i] ==
'\n';
i--) {
363 if (parent && *parent) {
366 (*parent)->get_category ? (*parent)->get_category(parent) :(*parent)->category;
388 union {
double d;
long long int i; }
val;
402 vald = vali = uv.
val.
i;
409 mins = (
int)secs / 60;
410 secs = secs - mins * 60;
413 snprintf(buf, buf_size,
"%d:%02d:%09.6f", hours, mins, secs);
415 const char *prefix_string =
"";
426 index = (
long long int) (log10(vald)) / 3;
435 snprintf(buf, buf_size,
"%f", vald);
437 snprintf(buf, buf_size,
"%lld", vali);
449 #define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
450 #define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
475 #define SECTION_MAX_NB_LEVELS 10
517 #define OFFSET(x) offsetof(WriterContext, x)
520 {
"string_validation",
"set string validation mode",
522 {
"sv",
"set string validation mode",
527 {
"string_validation_replacement",
"set string validation replacement string",
OFFSET(string_validation_replacement),
AV_OPT_TYPE_STRING, {.str=
""}},
528 {
"svr",
"set string validation replacement string",
OFFSET(string_validation_replacement),
AV_OPT_TYPE_STRING, {.str=
"\xEF\xBF\xBD"}},
535 if (!prev &&
ctx->writer &&
ctx->writer->priv_class &&
ctx->priv)
556 if ((*wctx)->writer->uninit)
557 (*wctx)->writer->uninit(*wctx);
560 if ((*wctx)->writer->priv_class)
572 static void bprint_bytes(AVBPrint *bp,
const uint8_t *ubuf,
size_t ubuf_size)
576 for (
i = 0;
i < ubuf_size;
i++)
634 (*wctx)->writer = writer;
637 (*wctx)->nb_sections = nb_sections;
642 void *priv_ctx = (*wctx)->priv;
653 av_log(*wctx,
AV_LOG_ERROR,
"Failed to parse option string '%s' provided to writer context\n", args);
660 av_log(*wctx,
AV_LOG_ERROR,
"Failed to set option '%s' with value '%s' provided to writer context\n",
672 const uint8_t *p = (*wctx)->string_validation_replacement;
673 const uint8_t *endp = p + strlen(p);
675 const uint8_t *p0 = p;
683 "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
684 bp.str, (*wctx)->string_validation_replacement);
708 if ((*wctx)->writer->init)
709 ret = (*wctx)->writer->init(*wctx);
723 int parent_section_id;
726 parent_section_id = wctx->
level ?
747 int parent_section_id = wctx->
level ?
762 const char *
key,
long long int val)
774 const uint8_t *p, *endp;
776 int invalid_chars_nb = 0,
ret = 0;
781 for (p = (uint8_t *)
src; *p;) {
784 const uint8_t *p0 = p;
791 "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str,
src);
801 "Invalid UTF-8 sequence found in string '%s'\n",
src);
818 "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
827 #define PRINT_STRING_OPT 1
828 #define PRINT_STRING_VALIDATE 2
846 if (
ret < 0)
goto end;
848 if (
ret < 0)
goto end;
853 "Invalid key=value string combination %s=%s in section %s\n",
878 int64_t ts,
const AVRational *time_base,
int is_duration)
882 if ((!is_duration && ts ==
AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
885 double d = ts *
av_q2d(*time_base);
896 if ((!is_duration && ts ==
AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
914 for (
i = 0;
i < l;
i++) {
920 for (
i = 0;
i < l;
i++)
941 p = buf + strlen(buf);
948 int columns,
int bytes,
int offset_add)
958 for (
i = 0;
i < l;
i++) {
972 #define writer_w8(wctx_, b_) (wctx_)->writer_w8(wctx_, b_)
973 #define writer_put_str(wctx_, str_) (wctx_)->writer_put_str(wctx_, str_)
974 #define writer_printf(wctx_, fmt_, ...) (wctx_)->writer_printf(wctx_, fmt_, __VA_ARGS__)
976 #define MAX_REGISTERED_WRITERS_NB 64
982 static int next_registered_writer_idx = 0;
1005 #define DEFINE_WRITER_CLASS(name) \
1006 static const char *name##_get_name(void *ctx) \
1010 static const AVClass name##_class = { \
1011 .class_name = #name, \
1012 .item_name = name##_get_name, \
1013 .option = name##_options \
1026 #define OFFSET(x) offsetof(DefaultContext, x)
1029 {
"noprint_wrappers",
"do not print headers and footers",
OFFSET(noprint_wrappers),
AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1030 {
"nw",
"do not print headers and footers",
OFFSET(noprint_wrappers),
AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1042 for (
i = 0;
src[
i] &&
i < dst_size-1;
i++)
1057 if (parent_section &&
1112 .priv_class = &default_class,
1120 static const char *
c_escape_str(AVBPrint *dst,
const char *
src,
const char sep,
void *log_ctx)
1124 for (p =
src; *p; p++) {
1126 case '\b':
av_bprintf(dst,
"%s",
"\\b");
break;
1127 case '\f':
av_bprintf(dst,
"%s",
"\\f");
break;
1128 case '\n':
av_bprintf(dst,
"%s",
"\\n");
break;
1129 case '\r':
av_bprintf(dst,
"%s",
"\\r");
break;
1130 case '\\':
av_bprintf(dst,
"%s",
"\\\\");
break;
1145 char meta_chars[] = { sep,
'"',
'\n',
'\r',
'\0' };
1146 int needs_quoting = !!
src[strcspn(
src, meta_chars)];
1173 const char * (*escape_str)(AVBPrint *dst,
const char *
src,
const char sep,
void *log_ctx);
1180 #define OFFSET(x) offsetof(CompactContext, x)
1201 av_log(wctx,
AV_LOG_ERROR,
"Item separator '%s' specified, but must contain a single character\n",
1266 if (!compact->
nokey)
1278 if (!compact->
nokey)
1292 .priv_class = &compact_class,
1298 #define OFFSET(x) offsetof(CompactContext, x)
1323 .priv_class = &csv_class,
1336 #define OFFSET(x) offsetof(FlatContext, x)
1341 {
"hierarchical",
"specify if the section specification should be hierarchical",
OFFSET(hierarchical),
AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1342 {
"h",
"specify if the section specification should be hierarchical",
OFFSET(hierarchical),
AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1352 if (strlen(
flat->sep_str) != 1) {
1353 av_log(wctx,
AV_LOG_ERROR,
"Item separator '%s' specified, but must contain a single character\n",
1366 for (p =
src; *p; p++) {
1367 if (!((*p >=
'0' && *p <=
'9') ||
1368 (*p >=
'a' && *p <=
'z') ||
1369 (*p >=
'A' && *p <=
'Z')))
1381 for (p =
src; *p; p++) {
1383 case '\n':
av_bprintf(dst,
"%s",
"\\n");
break;
1384 case '\r':
av_bprintf(dst,
"%s",
"\\r");
break;
1385 case '\\':
av_bprintf(dst,
"%s",
"\\\\");
break;
1386 case '"':
av_bprintf(dst,
"%s",
"\\\"");
break;
1387 case '`':
av_bprintf(dst,
"%s",
"\\`");
break;
1388 case '$':
av_bprintf(dst,
"%s",
"\\$");
break;
1405 if (!parent_section)
1409 if (
flat->hierarchical ||
1447 .priv_class = &flat_class,
1458 #define OFFSET(x) offsetof(INIContext, x)
1461 {
"hierarchical",
"specify if the section specification should be hierarchical",
OFFSET(hierarchical),
AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1462 {
"h",
"specify if the section specification should be hierarchical",
OFFSET(hierarchical),
AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1473 while (
c =
src[
i++]) {
1475 case '\b':
av_bprintf(dst,
"%s",
"\\b");
break;
1476 case '\f':
av_bprintf(dst,
"%s",
"\\f");
break;
1477 case '\n':
av_bprintf(dst,
"%s",
"\\n");
break;
1478 case '\r':
av_bprintf(dst,
"%s",
"\\r");
break;
1479 case '\t':
av_bprintf(dst,
"%s",
"\\t");
break;
1485 if ((
unsigned char)
c < 32)
1504 if (!parent_section) {
1551 .priv_class = &ini_class,
1564 #define OFFSET(x) offsetof(JSONContext, x)
1586 static const char json_escape[] = {
'"',
'\\',
'\b',
'\f',
'\n',
'\r',
'\t', 0};
1587 static const char json_subst[] = {
'"',
'\\',
'b',
'f',
'n',
'r',
't', 0};
1590 for (p =
src; *p; p++) {
1591 char *
s = strchr(json_escape, *p);
1595 }
else if ((
unsigned char)*p < 32) {
1604 #define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
1650 if (wctx->
level == 0) {
1668 const char *
key,
const char *
value)
1718 .priv_class = &json_class,
1732 #define OFFSET(x) offsetof(XMLContext, x)
1735 {
"fully_qualified",
"specify if the output should be fully qualified",
OFFSET(fully_qualified),
AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1736 {
"q",
"specify if the output should be fully qualified",
OFFSET(fully_qualified),
AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1737 {
"xsd_strict",
"ensure that the output is XSD compliant",
OFFSET(xsd_strict),
AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1750 #define CHECK_COMPLIANCE(opt, opt_name) \
1752 av_log(wctx, AV_LOG_ERROR, \
1753 "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
1754 "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
1755 return AVERROR(EINVAL); \
1765 #define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
1774 if (wctx->
level == 0) {
1775 const char *qual =
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
1776 "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
1777 "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
1779 writer_put_str(wctx,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1812 if (wctx->
level == 0) {
1873 .priv_class = &xml_class,
1893 #define print_fmt(k, f, ...) do { \
1894 av_bprint_clear(&pbuf); \
1895 av_bprintf(&pbuf, f, __VA_ARGS__); \
1896 writer_print_string(w, k, pbuf.str, 0); \
1899 #define print_list_fmt(k, f, n, ...) do { \
1900 av_bprint_clear(&pbuf); \
1901 for (int idx = 0; idx < n; idx++) { \
1903 av_bprint_chars(&pbuf, ' ', 1); \
1904 av_bprintf(&pbuf, f, __VA_ARGS__); \
1906 writer_print_string(w, k, pbuf.str, 0); \
1909 #define print_int(k, v) writer_print_integer(w, k, v)
1910 #define print_q(k, v, s) writer_print_rational(w, k, v, s)
1911 #define print_str(k, v) writer_print_string(w, k, v, 0)
1912 #define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
1913 #define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
1914 #define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
1915 #define print_ts(k, v) writer_print_ts(w, k, v, 0)
1916 #define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
1917 #define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
1918 #define print_val(k, v, u) do { \
1919 struct unit_value uv; \
1922 writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
1925 #define print_section_header(s) writer_print_section_header(w, s)
1926 #define print_section_footer(s) writer_print_section_footer(w, s)
1928 #define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
1930 ret = av_reallocp_array(&(ptr), (new_n), sizeof(*(ptr))); \
1933 memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
1972 print_int(
"chroma_resampling_explicit_filter_flag",
1981 print_int(
"spatial_resampling_filter_flag",
1983 print_int(
"el_spatial_resampling_filter_flag",
1996 print_str(
"nlq_method_idc_name",
"none");
1999 print_str(
"nlq_method_idc_name",
"linear_dz");
2002 print_str(
"nlq_method_idc_name",
"unknown");
2011 for (
int c = 0;
c < 3;
c++) {
2024 print_str(
"mapping_idc_name",
"polynomial");
2039 print_str(
"mapping_idc_name",
"unknown");
2075 color->ycc_to_rgb_matrix[idx].num,
2076 color->ycc_to_rgb_matrix[idx].den);
2079 color->ycc_to_rgb_offset[idx].num,
2080 color->ycc_to_rgb_offset[idx].den);
2083 color->rgb_to_lms_matrix[idx].num,
2084 color->rgb_to_lms_matrix[idx].den);
2092 print_int(
"signal_full_range_flag",
color->signal_full_range_flag);
2109 print_q(
"window_upper_left_corner_x",
2111 print_q(
"window_upper_left_corner_y",
2113 print_q(
"window_lower_right_corner_x",
2115 print_q(
"window_lower_right_corner_y",
2117 print_q(
"window_upper_left_corner_x",
2119 print_q(
"window_upper_left_corner_y",
2127 print_int(
"semimajor_axis_internal_ellipse",
2129 print_int(
"semimajor_axis_external_ellipse",
2131 print_int(
"semiminor_axis_external_ellipse",
2136 print_q(
"targeted_system_display_maximum_luminance",
2139 print_int(
"num_rows_targeted_system_display_actual_peak_luminance",
2141 print_int(
"num_cols_targeted_system_display_actual_peak_luminance",
2145 print_q(
"targeted_system_display_actual_peak_luminance",
2152 for (
int i = 0;
i < 3;
i++) {
2157 print_int(
"num_distribution_maxrgb_percentiles",
2160 print_int(
"distribution_maxrgb_percentage",
2162 print_q(
"distribution_maxrgb_percentile",
2165 print_q(
"fraction_bright_pixels",
2169 print_int(
"num_rows_mastering_display_actual_peak_luminance",
2171 print_int(
"num_cols_mastering_display_actual_peak_luminance",
2175 print_q(
"mastering_display_actual_peak_luminance",
2189 print_q(
"bezier_curve_anchors",
2194 print_q(
"color_saturation_weight",
2225 print_q(
"targeted_system_display_maximum_luminance",
2238 print_int(
"base_param_Delta_enable_mode",
2278 for (
i = 0;
i < nb_side_data;
i++) {
2503 const uint8_t *side_metadata;
2540 print_int (
"start_display_time",
sub->start_display_time);
2571 print_ts (
"best_effort_timestamp",
frame->best_effort_timestamp);
2573 #if LIBAVUTIL_VERSION_MAJOR < 58
2597 print_q(
"sample_aspect_ratio", sar,
':');
2603 print_int(
"display_picture_number",
frame->display_picture_number);
2632 if (
frame->nb_side_data) {
2634 for (
i = 0;
i <
frame->nb_side_data;
i++) {
2651 uint32_t *
tc = (uint32_t*)sd->
data;
2654 for (
int j = 1; j <= m ; j++) {
2719 int ret = 0, got_frame = 0;
2770 return got_frame || *packet_new;
2775 av_log(log_ctx, log_level,
"id:%d", interval->
id);
2781 av_log(log_ctx, log_level,
" start:N/A");
2787 av_log(log_ctx, log_level,
"#%"PRId64, interval->
end);
2791 av_log(log_ctx, log_level,
" end:N/A");
2794 av_log(log_ctx, log_level,
"\n");
2803 int ret = 0,
i = 0, frame_count = 0;
2804 int64_t start = -INT64_MAX, end = interval->
end;
2815 "Could not seek to relative position since current "
2816 "timestamp is not defined\n");
2820 target = *cur_ts + interval->
start;
2822 target = interval->
start;
2863 end = start + interval->
end;
2868 if (frame_count >= interval->
end)
2870 }
else if (has_end && *cur_ts !=
AV_NOPTS_VALUE && *cur_ts >= end) {
2893 if (
ifile->streams[
i].dec_ctx)
2966 char profile_num[12];
2994 print_q(
"sample_aspect_ratio", sar,
':');
2999 print_q(
"display_aspect_ratio", dar,
':');
3016 print_str(
"field_order",
"progressive");
3107 #define PRINT_DISPOSITION(flagname, name) do { \
3108 print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \
3155 for (
i = 0;
i <
ifile->nb_streams;
i++)
3183 for (
i = 0;
i <
program->nb_stream_indexes;
i++) {
3274 const char *errbuf_ptr = errbuf;
3286 const char *print_filename)
3291 int scan_all_pmts_set = 0;
3301 scan_all_pmts_set = 1;
3308 if (print_filename) {
3313 if (scan_all_pmts_set)
3324 for (
i = 0;
i < orig_nb_streams;
i++)
3337 if (!
ifile->streams)
3351 "Failed to probe codec for input stream %d\n",
3359 "Unsupported codec with id %d for input stream %d\n",
3407 for (
i = 0;
i <
ifile->nb_streams;
i++)
3411 ifile->nb_streams = 0;
3417 const char *print_filename)
3430 #define CHECK_END if (ret < 0) goto end
3437 for (
i = 0;
i <
ifile.fmt_ctx->nb_streams;
i++) {
3440 ifile.fmt_ctx->streams[
i],
3511 print_fmt(
"copyright",
"Copyright (c) %d-%d the FFmpeg developers",
3514 print_str(
"configuration", FFMPEG_CONFIGURATION);
3520 #define SHOW_LIB_VERSION(libname, LIBNAME) \
3522 if (CONFIG_##LIBNAME) { \
3523 unsigned int version = libname##_version(); \
3524 writer_print_section_header(w, SECTION_ID_LIBRARY_VERSION); \
3525 print_str("name", "lib" #libname); \
3526 print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
3527 print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
3528 print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
3529 print_int("version", version); \
3530 print_str("ident", LIB##LIBNAME##_IDENT); \
3531 writer_print_section_footer(w); \
3549 #define PRINT_PIX_FMT_FLAG(flagname, name) \
3551 print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
3646 "'%s' matches section with unique name '%s'\n", section_name,
3657 const char *p =
arg;
3665 if (!section_name) {
3667 "Missing section name for option '%s'\n", opt);
3673 while (*p && *p !=
':') {
3678 "Adding '%s' to the entries to show in section '%s'\n",
3679 entry, section_name);
3709 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3713 if (!strcmp(
arg,
"-"))
3728 "Argument '%s' provided as output filename, but '%s' was already specified.\n",
3732 if (!strcmp(
arg,
"-"))
3769 char *next, *p, *spec =
av_strdup(interval_spec);
3780 next = strchr(spec,
'%');
3822 lli = strtoll(p, &tail, 10);
3823 if (*tail || lli < 0) {
3825 "Invalid or negative value '%s' for duration number of frames\n", p);
3828 interval->
end = lli;
3850 char *p, *spec =
av_strdup(intervals_spec);
3855 for (n = 0, p = spec; *p; p++)
3869 for (
i = 0; p;
i++) {
3873 next = strchr(p,
',');
3929 "W.. = Section is a wrapper (contains other sections, no local entries)\n"
3930 ".A. = Section contains an array of elements of the same type\n"
3931 "..V = Section may contain a variable number of fields with variable keys\n"
3932 "FLAGS NAME/UNIQUE_NAME\n"
3945 #define DEFINE_OPT_SHOW_SECTION(section, target_section_id) \
3946 static int opt_show_##section(void *optctx, const char *opt, const char *arg) \
3948 mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \
3969 "use binary prefixes for byte units" },
3971 "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
3973 "prettify the format of displayed values, make it more human readable" },
3975 "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)",
"format" },
3978 {
"sections",
OPT_EXIT, {.func_arg =
opt_sections},
"print sections structure and section information, and exit" },
3981 {
"show_error", 0, { .func_arg = &opt_show_error },
"show probing error" },
3982 {
"show_format", 0, { .func_arg = &opt_show_format },
"show format/container info" },
3983 {
"show_frames", 0, { .func_arg = &opt_show_frames },
"show frames info" },
3985 "show a set of specified entries",
"entry_list" },
3989 {
"show_packets", 0, { .func_arg = &opt_show_packets },
"show packets info" },
3990 {
"show_programs", 0, { .func_arg = &opt_show_programs },
"show programs info" },
3991 {
"show_streams", 0, { .func_arg = &opt_show_streams },
"show streams info" },
3992 {
"show_chapters", 0, { .func_arg = &opt_show_chapters },
"show chapters info" },
3995 {
"show_program_version", 0, { .func_arg = &opt_show_program_version },
"show ffprobe version" },
3996 {
"show_library_versions", 0, { .func_arg = &opt_show_library_versions },
"show library versions" },
3997 {
"show_versions", 0, { .func_arg = &
opt_show_versions },
"show program and library versions" },
3998 {
"show_pixel_formats", 0, { .func_arg = &opt_show_pixel_formats },
"show pixel format descriptions" },
4008 "read and decode the streams to fill missing information with heuristics" },