144
151
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
145
152
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
146
153
[SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
147
[SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, -1 } },
154
[SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
148
155
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, -1 } },
149
156
[SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
150
157
[SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
167
174
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } },
168
175
[SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
169
176
[SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
177
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
172
180
static const OptionDef *options;
306
325
return wctx->writer->name;
328
#define OFFSET(x) offsetof(WriterContext, x)
330
static const AVOption writer_options[] = {
331
{ "string_validation", "set string validation mode",
332
OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
333
{ "sv", "set string validation mode",
334
OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
335
{ "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
336
{ "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
337
{ "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
338
{ "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
339
{ "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
343
static void *writer_child_next(void *obj, void *prev)
345
WriterContext *ctx = obj;
346
if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
309
351
static const AVClass writer_class = {
313
LIBAVUTIL_VERSION_INT,
352
.class_name = "Writer",
353
.item_name = writer_get_name,
354
.option = writer_options,
355
.version = LIBAVUTIL_VERSION_INT,
356
.child_next = writer_child_next,
316
359
static void writer_close(WriterContext **wctx)
327
370
if ((*wctx)->writer->priv_class)
328
371
av_opt_free((*wctx)->priv);
329
372
av_freep(&((*wctx)->priv));
377
static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
380
av_bprintf(bp, "0X");
381
for (i = 0; i < ubuf_size; i++)
382
av_bprintf(bp, "%02X", ubuf[i]);
333
386
static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
334
387
const struct section *sections, int nb_sections)
351
404
(*wctx)->sections = sections;
352
405
(*wctx)->nb_sections = nb_sections;
407
av_opt_set_defaults(*wctx);
354
409
if (writer->priv_class) {
355
410
void *priv_ctx = (*wctx)->priv;
356
411
*((const AVClass **)priv_ctx) = writer->priv_class;
357
412
av_opt_set_defaults(priv_ctx);
360
(ret = av_set_options_string(priv_ctx, args, "=", ":")) < 0)
415
/* convert options to dictionary */
417
AVDictionary *opts = NULL;
418
AVDictionaryEntry *opt = NULL;
420
if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
421
av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
426
while ((opt = av_dict_get(opts, "", opt, AV_DICT_IGNORE_SUFFIX))) {
427
if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
428
av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
429
opt->key, opt->value);
438
/* validate replace string */
440
const uint8_t *p = (*wctx)->string_validation_replacement;
441
const uint8_t *endp = p + strlen(p);
443
const uint8_t *p0 = p;
445
ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
448
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
449
bprint_bytes(&bp, p0, p-p0),
450
av_log(wctx, AV_LOG_ERROR,
451
"Invalid UTF8 sequence %s found in string validation replace '%s'\n",
452
bp.str, (*wctx)->string_validation_replacement);
364
458
for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
431
static inline void writer_print_string(WriterContext *wctx,
432
const char *key, const char *val, int opt)
525
static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
527
const uint8_t *p, *endp;
529
int invalid_chars_nb = 0, ret = 0;
531
av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
533
endp = src + strlen(src);
534
for (p = (uint8_t *)src; *p;) {
537
const uint8_t *p0 = p;
539
if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
541
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
542
bprint_bytes(&bp, p0, p-p0);
543
av_log(wctx, AV_LOG_DEBUG,
544
"Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
551
switch (wctx->string_validation) {
552
case WRITER_STRING_VALIDATION_FAIL:
553
av_log(wctx, AV_LOG_ERROR,
554
"Invalid UTF-8 sequence found in string '%s'\n", src);
555
ret = AVERROR_INVALIDDATA;
559
case WRITER_STRING_VALIDATION_REPLACE:
560
av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
565
if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
566
av_bprint_append_data(&dstbuf, p0, p-p0);
569
if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
570
av_log(wctx, AV_LOG_WARNING,
571
"%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
572
invalid_chars_nb, src, wctx->string_validation_replacement);
576
av_bprint_finalize(&dstbuf, dstp);
580
#define PRINT_STRING_OPT 1
581
#define PRINT_STRING_VALIDATE 2
583
static inline int writer_print_string(WriterContext *wctx,
584
const char *key, const char *val, int flags)
434
586
const struct section *section = wctx->section[wctx->level];
436
if (opt && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS))
589
if ((flags & PRINT_STRING_OPT)
590
&& !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS))
439
593
if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
440
wctx->writer->print_string(wctx, key, val);
594
if (flags & PRINT_STRING_VALIDATE) {
595
char *key1 = NULL, *val1 = NULL;
596
ret = validate_string(wctx, &key1, key);
597
if (ret < 0) goto end;
598
ret = validate_string(wctx, &val1, val);
599
if (ret < 0) goto end;
600
wctx->writer->print_string(wctx, key1, val1);
603
av_log(wctx, AV_LOG_ERROR,
604
"Invalid key=value string combination %s=%s in section %s\n",
605
key, val, section->unique_name);
610
wctx->writer->print_string(wctx, key, val);
441
613
wctx->nb_item[wctx->level]++;
445
619
static inline void writer_print_rational(WriterContext *wctx,
1440
1615
#define print_int(k, v) writer_print_integer(w, k, v)
1441
1616
#define print_q(k, v, s) writer_print_rational(w, k, v, s)
1442
1617
#define print_str(k, v) writer_print_string(w, k, v, 0)
1443
#define print_str_opt(k, v) writer_print_string(w, k, v, 1)
1618
#define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
1619
#define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
1444
1620
#define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
1445
1621
#define print_ts(k, v) writer_print_ts(w, k, v, 0)
1446
1622
#define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
1455
1631
#define print_section_header(s) writer_print_section_header(w, s)
1456
1632
#define print_section_footer(s) writer_print_section_footer(w, s)
1458
static inline void show_tags(WriterContext *wctx, AVDictionary *tags, int section_id)
1634
static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
1460
1636
AVDictionaryEntry *tag = NULL;
1464
writer_print_section_header(wctx, section_id);
1465
while ((tag = av_dict_get(tags, "", tag, AV_DICT_IGNORE_SUFFIX)))
1466
writer_print_string(wctx, tag->key, tag->value, 0);
1467
writer_print_section_footer(wctx);
1641
writer_print_section_header(w, section_id);
1643
while ((tag = av_dict_get(tags, "", tag, AV_DICT_IGNORE_SUFFIX))) {
1644
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
1647
writer_print_section_footer(w);
1470
1652
static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pkt, int packet_idx)
1502
1684
fflush(stdout);
1687
static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
1688
AVFormatContext *fmt_ctx)
1692
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
1694
writer_print_section_header(w, SECTION_ID_SUBTITLE);
1696
print_str ("media_type", "subtitle");
1697
print_ts ("pts", sub->pts);
1698
print_time("pts_time", sub->pts, &AV_TIME_BASE_Q);
1699
print_int ("format", sub->format);
1700
print_int ("start_display_time", sub->start_display_time);
1701
print_int ("end_display_time", sub->end_display_time);
1702
print_int ("num_rects", sub->num_rects);
1704
writer_print_section_footer(w);
1706
av_bprint_finalize(&pbuf, NULL);
1505
1710
static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
1506
1711
AVFormatContext *fmt_ctx)
1520
1725
print_time("pkt_pts_time", frame->pkt_pts, &stream->time_base);
1521
1726
print_ts ("pkt_dts", frame->pkt_dts);
1522
1727
print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base);
1728
print_ts ("best_effort_timestamp", av_frame_get_best_effort_timestamp(frame));
1729
print_time("best_effort_timestamp_time", av_frame_get_best_effort_timestamp(frame), &stream->time_base);
1523
1730
print_duration_ts ("pkt_duration", av_frame_get_pkt_duration(frame));
1524
1731
print_duration_time("pkt_duration_time", av_frame_get_pkt_duration(frame), &stream->time_base);
1525
1732
if (av_frame_get_pkt_pos (frame) != -1) print_fmt ("pkt_pos", "%"PRId64, av_frame_get_pkt_pos(frame));
1903
2130
writer_print_section_footer(w);
1906
show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
2133
if (do_show_stream_tags)
2134
ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
1908
2136
writer_print_section_footer(w);
1909
2137
av_bprint_finalize(&pbuf, NULL);
1910
2138
fflush(stdout);
1913
static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
2143
static int show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
1916
2147
writer_print_section_header(w, SECTION_ID_STREAMS);
1917
2148
for (i = 0; i < fmt_ctx->nb_streams; i++)
1918
if (selected_streams[i])
1919
show_stream(w, fmt_ctx, i, 0);
2149
if (selected_streams[i]) {
2150
ret = show_stream(w, fmt_ctx, i, 0);
1920
2154
writer_print_section_footer(w);
1923
static void show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program)
2159
static int show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program)
1927
2163
writer_print_section_header(w, SECTION_ID_PROGRAM);
1928
2164
print_int("program_id", program->id);
1934
2170
print_time("start_time", program->start_time, &AV_TIME_BASE_Q);
1935
2171
print_ts("end_pts", program->end_time);
1936
2172
print_time("end_time", program->end_time, &AV_TIME_BASE_Q);
1937
show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
2173
if (do_show_program_tags)
2174
ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
1939
2178
writer_print_section_header(w, SECTION_ID_PROGRAM_STREAMS);
1940
2179
for (i = 0; i < program->nb_stream_indexes; i++) {
1941
if (selected_streams[program->stream_index[i]])
1942
show_stream(w, fmt_ctx, program->stream_index[i], 1);
2180
if (selected_streams[program->stream_index[i]]) {
2181
ret = show_stream(w, fmt_ctx, program->stream_index[i], 1);
1944
2186
writer_print_section_footer(w);
1946
2189
writer_print_section_footer(w);
1949
static void show_programs(WriterContext *w, AVFormatContext *fmt_ctx)
2193
static int show_programs(WriterContext *w, AVFormatContext *fmt_ctx)
1953
2197
writer_print_section_header(w, SECTION_ID_PROGRAMS);
1954
2198
for (i = 0; i < fmt_ctx->nb_programs; i++) {
1955
2199
AVProgram *program = fmt_ctx->programs[i];
1958
show_program(w, fmt_ctx, program);
2202
ret = show_program(w, fmt_ctx, program);
1960
2206
writer_print_section_footer(w);
1963
static void show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
2210
static int show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
1967
2214
writer_print_section_header(w, SECTION_ID_CHAPTERS);
1968
2215
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
1975
2222
print_time("start_time", chapter->start, &chapter->time_base);
1976
2223
print_int("end", chapter->end);
1977
2224
print_time("end_time", chapter->end, &chapter->time_base);
1978
show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
2225
if (do_show_chapter_tags)
2226
ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
1979
2227
writer_print_section_footer(w);
1981
2229
writer_print_section_footer(w);
1984
static void show_format(WriterContext *w, AVFormatContext *fmt_ctx)
2234
static int show_format(WriterContext *w, AVFormatContext *fmt_ctx)
1986
2236
char val_str[128];
1987
2237
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
1989
2240
writer_print_section_header(w, SECTION_ID_FORMAT);
1990
print_str("filename", fmt_ctx->filename);
2241
print_str_validate("filename", fmt_ctx->filename);
1991
2242
print_int("nb_streams", fmt_ctx->nb_streams);
1992
2243
print_int("nb_programs", fmt_ctx->nb_programs);
1993
2244
print_str("format_name", fmt_ctx->iformat->name);
2002
2253
if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
2003
2254
else print_str_opt("bit_rate", "N/A");
2004
2255
print_int("probe_score", av_format_get_probe_score(fmt_ctx));
2005
show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
2256
if (do_show_format_tags)
2257
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
2007
2259
writer_print_section_footer(w);
2008
2260
fflush(stdout);
2011
2264
static void show_error(WriterContext *w, int err)
2140
2394
section_id = SECTION_ID_FRAMES;
2141
2395
if (do_show_frames || do_show_packets)
2142
2396
writer_print_section_header(wctx, section_id);
2143
read_packets(wctx, fmt_ctx);
2397
ret = read_packets(wctx, fmt_ctx);
2144
2398
if (do_show_frames || do_show_packets)
2145
2399
writer_print_section_footer(wctx);
2147
if (do_show_programs)
2148
show_programs(wctx, fmt_ctx);
2149
if (do_show_streams)
2150
show_streams(wctx, fmt_ctx);
2151
if (do_show_chapters)
2152
show_chapters(wctx, fmt_ctx);
2154
show_format(wctx, fmt_ctx);
2403
if (do_show_programs) {
2404
ret = show_programs(wctx, fmt_ctx);
2408
if (do_show_streams) {
2409
ret = show_streams(wctx, fmt_ctx);
2412
if (do_show_chapters) {
2413
ret = show_chapters(wctx, fmt_ctx);
2416
if (do_show_format) {
2417
ret = show_format(wctx, fmt_ctx);
2157
2422
close_input_file(&fmt_ctx);
2177
2442
writer_print_section_header(w, SECTION_ID_PROGRAM_VERSION);
2178
2443
print_str("version", FFMPEG_VERSION);
2179
2444
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
2180
program_birth_year, this_year);
2445
program_birth_year, CONFIG_THIS_YEAR);
2181
2446
print_str("build_date", __DATE__);
2182
2447
print_str("build_time", __TIME__);
2183
2448
print_str("compiler_ident", CC_IDENT);
2646
2913
SET_DO_SHOW(STREAM_DISPOSITION, stream_disposition);
2647
2914
SET_DO_SHOW(PROGRAM_STREAM_DISPOSITION, stream_disposition);
2916
SET_DO_SHOW(CHAPTER_TAGS, chapter_tags);
2917
SET_DO_SHOW(FORMAT_TAGS, format_tags);
2918
SET_DO_SHOW(FRAME_TAGS, frame_tags);
2919
SET_DO_SHOW(PROGRAM_TAGS, program_tags);
2920
SET_DO_SHOW(STREAM_TAGS, stream_tags);
2649
2922
if (do_bitexact && (do_show_program_version || do_show_library_versions)) {
2650
2923
av_log(NULL, AV_LOG_ERROR,
2651
2924
"-bitexact and -show_program_version or -show_library_versions "