FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
tf_mermaid.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 "tf_internal.h"
29 #include "tf_mermaid.h"
30 #include <libavutil/mem.h>
31 #include <libavutil/avassert.h>
32 #include <libavutil/bprint.h>
33 #include <libavutil/opt.h>
34 
35 
36 static const char *init_directive = ""
37  "%%{init: {"
38  "\"theme\": \"base\","
39  "\"curve\": \"monotoneX\","
40  "\"rankSpacing\": 10,"
41  "\"nodeSpacing\": 10,"
42  "\"themeCSS\": \"__###__\","
43  "\"fontFamily\": \"Roboto,Segoe UI,sans-serif\","
44  "\"themeVariables\": { "
45  "\"clusterBkg\": \"white\", "
46  "\"primaryBorderColor\": \"gray\", "
47  "\"lineColor\": \"gray\", "
48  "\"secondaryTextColor\": \"gray\", "
49  "\"tertiaryBorderColor\": \"gray\", "
50  "\"primaryTextColor\": \"#666\", "
51  "\"secondaryTextColor\": \"red\" "
52  "},"
53  "\"flowchart\": { "
54  "\"subGraphTitleMargin\": { \"top\": -15, \"bottom\": 20 }, "
55  "\"diagramPadding\": 20, "
56  "\"curve\": \"monotoneX\" "
57  "}"
58  " }}%%\n\n";
59 
60 static const char* init_directive_er = ""
61  "%%{init: {"
62  "\"theme\": \"base\","
63  "\"layout\": \"elk\","
64  "\"curve\": \"monotoneX\","
65  "\"rankSpacing\": 65,"
66  "\"nodeSpacing\": 60,"
67  "\"themeCSS\": \"__###__\","
68  "\"fontFamily\": \"Roboto,Segoe UI,sans-serif\","
69  "\"themeVariables\": { "
70  "\"clusterBkg\": \"white\", "
71  "\"primaryBorderColor\": \"gray\", "
72  "\"lineColor\": \"gray\", "
73  "\"secondaryTextColor\": \"gray\", "
74  "\"tertiaryBorderColor\": \"gray\", "
75  "\"primaryTextColor\": \"#666\", "
76  "\"secondaryTextColor\": \"red\" "
77  "},"
78  "\"er\": { "
79  "\"diagramPadding\": 12, "
80  "\"entityPadding\": 4, "
81  "\"minEntityWidth\": 150, "
82  "\"minEntityHeight\": 20, "
83  "\"curve\": \"monotoneX\" "
84  "}"
85  " }}%%\n\n";
86 
87 static const char *theme_css_er = ""
88 
89  // Variables
90  ".root { "
91  "--ff-colvideo: #6eaa7b; "
92  "--ff-colaudio: #477fb3; "
93  "--ff-colsubtitle: #ad76ab; "
94  "--ff-coltext: #666; "
95  "} "
96  " g.nodes g.node.default rect.basic.label-container, "
97  " g.nodes g.node.default path { "
98  " rx: 1; "
99  " ry: 1; "
100  " stroke-width: 1px !important; "
101  " stroke: #e9e9e9 !important; "
102  " fill: url(#ff-filtergradient) !important; "
103  " filter: drop-shadow(0px 0px 5.5px rgba(0, 0, 0, 0.05)); "
104  " fill: white !important; "
105  " } "
106  " "
107  " .relationshipLine { "
108  " stroke: gray; "
109  " stroke-width: 1; "
110  " fill: none; "
111  " filter: drop-shadow(0px 0px 3px rgba(0, 0, 0, 0.2)); "
112  " } "
113  " "
114  " g.node.default g.label.name foreignObject > div > span > p, "
115  " g.nodes g.node.default g.label:not(.attribute-name, .attribute-keys, .attribute-type, .attribute-comment) foreignObject > div > span > p { "
116  " font-size: 0.95rem; "
117  " font-weight: 500; "
118  " text-transform: uppercase; "
119  " min-width: 5.5rem; "
120  " margin-bottom: 0.5rem; "
121  " "
122  " } "
123  " "
124  " .edgePaths path { "
125  " marker-end: none; "
126  " marker-start: none; "
127  " "
128  "} ";
129 
130 
131 /* Mermaid Graph output */
132 
133 typedef struct MermaidContext {
134  const AVClass *class;
140 
141  // Options
142  int enable_link_colors; // Requires Mermaid 11.5
143 
144  struct section_data {
145  const char *section_id;
146  const char *section_type;
147  const char *src_id;
148  const char *dest_id;
154 
155  unsigned nb_link_captions[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
156  AVBPrint link_buf; ///< print buffer for writing diagram links
159 
160 #undef OFFSET
161 #define OFFSET(x) offsetof(MermaidContext, x)
162 
163 static const AVOption mermaid_options[] = {
164  { "link_coloring", "enable colored links (requires Mermaid >= 11.5)", OFFSET(enable_link_colors), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1 },
165  ////{"diagram_css", "CSS for the diagram", OFFSET(diagram_css), AV_OPT_TYPE_STRING, {.i64=0}, 0, 1 },
166  ////{"html_template", "Template HTML", OFFSET(html_template), AV_OPT_TYPE_STRING, {.i64=0}, 0, 1 },
167  { NULL },
168 };
169 
170 DEFINE_FORMATTER_CLASS(mermaid);
171 
173 {
174  MermaidContext *mmc = tfc->priv;
175  mmc->diagram_config = diagram_config;
176 }
177 
178 static av_cold int has_link_pair(const AVTextFormatContext *tfc, const char *src, const char *dest)
179 {
180  MermaidContext *mmc = tfc->priv;
181  AVBPrint buf;
182 
184  av_bprintf(&buf, "%s--%s", src, dest);
185 
186  if (mmc->link_dict && av_dict_get(mmc->link_dict, buf.str, NULL, 0))
187  return 1;
188 
189  av_dict_set(&mmc->link_dict, buf.str, buf.str, 0);
190 
191  return 0;
192 }
193 
195 {
196  MermaidContext *mmc = tfc->priv;
197 
199 
200  ////mmc->enable_link_colors = 1; // Requires Mermaid 11.5
201  return 0;
202 }
203 
205 {
206  MermaidContext *mmc = tfc->priv;
207 
208  int ret = mermaid_init(tfc);
209 
210  if (ret < 0)
211  return ret;
212 
213  mmc->create_html = 1;
214 
215  return 0;
216 }
217 
219 {
220  MermaidContext *mmc = tfc->priv;
221 
223  av_dict_free(&mmc->link_dict);
224 
225  for (unsigned i = 0; i < SECTION_MAX_NB_LEVELS; i++) {
226  av_freep(&mmc->section_data[i].dest_id);
228  av_freep(&mmc->section_data[i].src_id);
230  }
231 
232  return 0;
233 }
234 
235 static void set_str(const char **dst, const char *src)
236 {
237  if (*dst)
238  av_freep(dst);
239 
240  if (src)
241  *dst = av_strdup(src);
242 }
243 
244 #define MM_INDENT() writer_printf(tfc, "%*c", mmc->indent_level * 2, ' ')
245 
247 {
248  const AVTextFormatSection *section = tf_get_section(tfc, tfc->level);
249  const AVTextFormatSection *parent_section = tf_get_parent_section(tfc, tfc->level);
250 
251  if (!section)
252  return;
253  AVBPrint *buf = &tfc->section_pbuf[tfc->level];
254  MermaidContext *mmc = tfc->priv;
255  const AVTextFormatSectionContext *sec_ctx = data;
256 
257  if (tfc->level == 0) {
258  char *directive;
259  AVBPrint css_buf;
261  char *single_line_css = av_strireplace(mmc->diagram_config->diagram_css, "\n", " ");
262  (void)theme_css_er;
263  ////char *single_line_css = av_strireplace(theme_css_er, "\n", " ");
265  av_bprint_escape(&css_buf, single_line_css, "'\\", AV_ESCAPE_MODE_BACKSLASH, AV_ESCAPE_FLAG_STRICT);
266  av_freep(&single_line_css);
267 
268  directive = av_strireplace(diag_directive, "__###__", css_buf.str);
269  if (mmc->create_html) {
270  uint64_t length;
271  char *token_pos = av_stristr(mmc->diagram_config->html_template, "__###__");
272  if (!token_pos) {
273  av_log(tfc, AV_LOG_ERROR, "Unable to locate the required token (__###__) in the html template.");
274  return;
275  }
276 
277  length = token_pos - mmc->diagram_config->html_template;
278  for (uint64_t i = 0; i < length; i++)
280  }
281 
282  writer_put_str(tfc, directive);
283  switch (mmc->diagram_config->diagram_type) {
285  writer_put_str(tfc, "flowchart LR\n");
286  ////writer_put_str(tfc, " gradient_def@{ shape: text, label: \"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1\" height=\"1\"><defs><linearGradient id=\"ff-filtergradient\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\"><stop offset=\"0%\" style=\"stop-color:hsla(0, 0%, 30%, 0.02);\"/><stop offset=\"50%\" style=\"stop-color:hsla(0, 0%, 30%, 0);\"/><stop offset=\"100%\" style=\"stop-color:hsla(0, 0%, 30%, 0.05);\"/></linearGradient></defs></svg>\" }\n");
287  writer_put_str(tfc, " gradient_def@{ shape: text, label: \"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1\" height=\"1\"><defs><linearGradient id=\"ff-filtergradient\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\"><stop offset=\"0%\" style=\"stop-color:hsl(0, 0%, 98.6%); \"/><stop offset=\"50%\" style=\"stop-color:hsl(0, 0%, 100%); \"/><stop offset=\"100%\" style=\"stop-color:hsl(0, 0%, 96.5%); \"/></linearGradient><radialGradient id=\"ff-radgradient\" cx=\"50%\" cy=\"50%\" r=\"100%\" fx=\"45%\" fy=\"40%\"><stop offset=\"25%\" stop-color=\"hsl(0, 0%, 100%)\" /><stop offset=\"100%\" stop-color=\"hsl(0, 0%, 96%)\" /></radialGradient></defs></svg>\" }\n");
288  break;
290  writer_put_str(tfc, "erDiagram\n");
291  break;
292  }
293 
294  av_bprint_finalize(&css_buf, NULL);
295  av_freep(&directive);
296  return;
297  }
298 
299  if (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH) {
300 
301  struct section_data parent_sec_data = mmc->section_data[tfc->level - 1];
302  AVBPrint *parent_buf = &tfc->section_pbuf[tfc->level - 1];
303 
304  if (parent_sec_data.subgraph_start_incomplete) {
305 
306  if (parent_buf->len > 0)
307  writer_printf(tfc, "%s", parent_buf->str);
308 
309  writer_put_str(tfc, "</div>\"]\n");
310 
311  mmc->section_data[tfc->level - 1].subgraph_start_incomplete = 0;
312  }
313  }
314 
315  av_freep(&mmc->section_data[tfc->level].section_id);
317  av_freep(&mmc->section_data[tfc->level].src_id);
318  av_freep(&mmc->section_data[tfc->level].dest_id);
319  mmc->section_data[tfc->level].current_is_textblock = 0;
320  mmc->section_data[tfc->level].current_is_stadium = 0;
323 
324  // NOTE: av_strdup() allocations aren't checked
326 
327  av_bprint_clear(buf);
328  writer_put_str(tfc, "\n");
329 
330  mmc->indent_level++;
331 
332  if (sec_ctx->context_id) {
333  MM_INDENT();
334  writer_printf(tfc, "subgraph %s[\"<div class=\"ff-%s\">", sec_ctx->context_id, section->name);
335  } else {
336  av_log(tfc, AV_LOG_ERROR, "Unable to write subgraph start. Missing id field. Section: %s", section->name);
337  }
338 
340  set_str(&mmc->section_data[tfc->level].section_id, sec_ctx->context_id);
341  }
342 
344 
345  av_bprint_clear(buf);
346  writer_put_str(tfc, "\n");
347 
348  mmc->indent_level++;
349 
350  if (sec_ctx->context_id) {
351 
352  set_str(&mmc->section_data[tfc->level].section_id, sec_ctx->context_id);
353 
354  switch (mmc->diagram_config->diagram_type) {
356  if (sec_ctx->context_flags & 1) {
357 
358  MM_INDENT();
359  writer_printf(tfc, "%s@{ shape: text, label: \"", sec_ctx->context_id);
360  mmc->section_data[tfc->level].current_is_textblock = 1;
361  } else if (sec_ctx->context_flags & 2) {
362 
363  MM_INDENT();
364  writer_printf(tfc, "%s([\"", sec_ctx->context_id);
365  mmc->section_data[tfc->level].current_is_stadium = 1;
366  } else {
367  MM_INDENT();
368  writer_printf(tfc, "%s(\"", sec_ctx->context_id);
369  }
370 
371  break;
373  MM_INDENT();
374  writer_printf(tfc, "%s {\n", sec_ctx->context_id);
375  break;
376  }
377 
378  } else {
379  av_log(tfc, AV_LOG_ERROR, "Unable to write shape start. Missing id field. Section: %s", section->name);
380  }
381 
382  set_str(&mmc->section_data[tfc->level].section_id, sec_ctx->context_id);
383  }
384 
385 
386  if (section->flags & AV_TEXTFORMAT_SECTION_PRINT_TAGS) {
387 
388  if (sec_ctx && sec_ctx->context_type)
389  writer_printf(tfc, "<div class=\"ff-%s %s\">", section->name, sec_ctx->context_type);
390  else
391  writer_printf(tfc, "<div class=\"ff-%s\">", section->name);
392  }
393 
394 
396 
397  av_bprint_clear(buf);
398  mmc->nb_link_captions[tfc->level] = 0;
399 
400  if (sec_ctx && sec_ctx->context_type)
401  set_str(&mmc->section_data[tfc->level].section_type, sec_ctx->context_type);
402 
403  ////if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
404  //// AVBPrint buf;
405  //// av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
406  //// av_bprint_escape(&buf, section->get_type(data), NULL,
407  //// AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
408  //// writer_printf(tfc, " type=\"%s\"", buf.str);
409  }
410 }
411 
413 {
414  MermaidContext *mmc = tfc->priv;
415  const AVTextFormatSection *section = tf_get_section(tfc, tfc->level);
416 
417  if (!section)
418  return;
419  AVBPrint *buf = &tfc->section_pbuf[tfc->level];
420  struct section_data sec_data = mmc->section_data[tfc->level];
421 
423  writer_put_str(tfc, "</div>");
424 
426 
427  switch (mmc->diagram_config->diagram_type) {
429 
430  if (sec_data.current_is_textblock) {
431  writer_printf(tfc, "\"}\n", section->name);
432 
433  if (sec_data.section_id) {
434  MM_INDENT();
435  writer_put_str(tfc, "class ");
436  writer_put_str(tfc, sec_data.section_id);
437  writer_put_str(tfc, " ff-");
438  writer_put_str(tfc, section->name);
439  writer_put_str(tfc, "\n");
440  }
441  } else if (sec_data.current_is_stadium) {
442  writer_printf(tfc, "\"]):::ff-%s\n", section->name);
443  } else {
444  writer_printf(tfc, "\"):::ff-%s\n", section->name);
445  }
446 
447  break;
449  MM_INDENT();
450  writer_put_str(tfc, "}\n\n");
451  break;
452  }
453 
454  mmc->indent_level--;
455 
456  } else if ((section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH)) {
457 
458  MM_INDENT();
459  writer_put_str(tfc, "end\n");
460 
461  if (sec_data.section_id) {
462  MM_INDENT();
463  writer_put_str(tfc, "class ");
464  writer_put_str(tfc, sec_data.section_id);
465  writer_put_str(tfc, " ff-");
466  writer_put_str(tfc, section->name);
467  writer_put_str(tfc, "\n");
468  }
469 
470  mmc->indent_level--;
471  }
472 
474  if (sec_data.src_id && sec_data.dest_id
475  && !has_link_pair(tfc, sec_data.src_id, sec_data.dest_id))
476  switch (mmc->diagram_config->diagram_type) {
478 
479  if (sec_data.section_type && mmc->enable_link_colors)
480  av_bprintf(&mmc->link_buf, "\n %s %s-%s-%s@==", sec_data.src_id, sec_data.section_type, sec_data.src_id, sec_data.dest_id);
481  else
482  av_bprintf(&mmc->link_buf, "\n %s ==", sec_data.src_id);
483 
484  if (buf->len > 0) {
485  av_bprintf(&mmc->link_buf, " \"%s", buf->str);
486 
487  for (unsigned i = 0; i < mmc->nb_link_captions[tfc->level]; i++)
488  av_bprintf(&mmc->link_buf, "<br>&nbsp;");
489 
490  av_bprintf(&mmc->link_buf, "\" ==");
491  }
492 
493  av_bprintf(&mmc->link_buf, "> %s", sec_data.dest_id);
494 
495  break;
497 
498 
499  av_bprintf(&mmc->link_buf, "\n %s", sec_data.src_id);
500 
501  switch (sec_data.link_type) {
503  av_bprintf(&mmc->link_buf, "%s", " ||--o{ ");
504  break;
506  av_bprintf(&mmc->link_buf, "%s", " }o--|| ");
507  break;
509  av_bprintf(&mmc->link_buf, "%s", " ||--|| ");
510  break;
512  av_bprintf(&mmc->link_buf, "%s", " }o--o{ ");
513  break;
514  default:
515  av_bprintf(&mmc->link_buf, "%s", " ||--|| ");
516  break;
517  }
518 
519  av_bprintf(&mmc->link_buf, "%s : \"\"", sec_data.dest_id);
520 
521  break;
522  }
523 
524  if (tfc->level == 0) {
525 
526  writer_put_str(tfc, "\n");
527  if (mmc->create_html) {
528  char *token_pos = av_stristr(mmc->diagram_config->html_template, "__###__");
529  if (!token_pos) {
530  av_log(tfc, AV_LOG_ERROR, "Unable to locate the required token (__###__) in the html template.");
531  return;
532  }
533  token_pos += strlen("__###__");
534  writer_put_str(tfc, token_pos);
535  }
536  }
537 
538  if (tfc->level == 1) {
539 
540  if (mmc->link_buf.len > 0) {
541  writer_put_str(tfc, mmc->link_buf.str);
542  av_bprint_clear(&mmc->link_buf);
543  }
544 
545  writer_put_str(tfc, "\n");
546  }
547 }
548 
549 static void mermaid_print_value(AVTextFormatContext *tfc, const char *key,
550  const char *str, int64_t num, const int is_int)
551 {
552  MermaidContext *mmc = tfc->priv;
553  const AVTextFormatSection *section = tf_get_section(tfc, tfc->level);
554 
555  if (!section)
556  return;
557 
558  AVBPrint *buf = &tfc->section_pbuf[tfc->level];
559  struct section_data sec_data = mmc->section_data[tfc->level];
560  int exit = 0;
561 
562  if (section->id_key && !strcmp(section->id_key, key)) {
563  set_str(&mmc->section_data[tfc->level].section_id, str);
564  exit = 1;
565  }
566 
567  if (section->dest_id_key && !strcmp(section->dest_id_key, key)) {
568  set_str(&mmc->section_data[tfc->level].dest_id, str);
569  exit = 1;
570  }
571 
572  if (section->src_id_key && !strcmp(section->src_id_key, key)) {
573  set_str(&mmc->section_data[tfc->level].src_id, str);
574  exit = 1;
575  }
576 
577  if (section->linktype_key && !strcmp(section->linktype_key, key)) {
579  exit = 1;
580  }
581 
582  //if (exit)
583  // return;
584 
586  || (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH && sec_data.subgraph_start_incomplete)) {
587 
588  if (exit)
589  return;
590 
591  switch (mmc->diagram_config->diagram_type) {
593 
594  if (is_int) {
595  writer_printf(tfc, "<span class=\"%s\">%s: %"PRId64"</span>", key, key, num);
596  } else {
597  ////AVBPrint b;
598  ////av_bprint_init(&b, 0, AV_BPRINT_SIZE_UNLIMITED);
599  const char *tmp = av_strireplace(str, "\"", "'");
600  ////av_bprint_escape(&b, str, NULL, AV_ESCAPE_MODE_AUTO, AV_ESCAPE_FLAG_STRICT);
601  writer_printf(tfc, "<span class=\"%s\">%s</span>", key, tmp);
602  av_freep(&tmp);
603  }
604 
605  break;
607 
608  if (!is_int && str)
609  {
610  const char *col_type;
611 
612  if (key[0] == '_')
613  return;
614 
615  if (sec_data.section_id && !strcmp(str, sec_data.section_id))
616  col_type = "PK";
617  else if (sec_data.dest_id && !strcmp(str, sec_data.dest_id))
618  col_type = "FK";
619  else if (sec_data.src_id && !strcmp(str, sec_data.src_id))
620  col_type = "FK";
621  else
622  col_type = "";
623 
624  MM_INDENT();
625 
626  if (is_int)
627  writer_printf(tfc, " %s %"PRId64" %s\n", key, num, col_type);
628  else
629  writer_printf(tfc, " %s %s %s\n", key, str, col_type);
630  }
631  break;
632  }
633 
634  } else if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS) {
635 
636  if (exit)
637  return;
638 
639  if (buf->len > 0)
640  av_bprintf(buf, "%s", "<br>");
641 
642  av_bprintf(buf, "");
643  if (is_int)
644  av_bprintf(buf, "<span>%s: %"PRId64"</span>", key, num);
645  else
646  av_bprintf(buf, "<span>%s</span>", str);
647 
648  mmc->nb_link_captions[tfc->level]++;
649  }
650 }
651 
652 static inline void mermaid_print_str(AVTextFormatContext *tfc, const char *key, const char *value)
653 {
654  mermaid_print_value(tfc, key, value, 0, 0);
655 }
656 
657 static void mermaid_print_int(AVTextFormatContext *tfc, const char *key, int64_t value)
658 {
659  mermaid_print_value(tfc, key, NULL, value, 1);
660 }
661 
663  .name = "mermaid",
664  .priv_size = sizeof(MermaidContext),
665  .init = mermaid_init,
667  .print_section_header = mermaid_print_section_header,
668  .print_section_footer = mermaid_print_section_footer,
669  .print_integer = mermaid_print_int,
670  .print_string = mermaid_print_str,
672  .priv_class = &mermaid_class,
673 };
674 
675 
677  .name = "mermaidhtml",
678  .priv_size = sizeof(MermaidContext),
681  .print_section_header = mermaid_print_section_header,
682  .print_section_footer = mermaid_print_section_footer,
683  .print_integer = mermaid_print_int,
684  .print_string = mermaid_print_str,
686  .priv_class = &mermaid_class,
687 };
flags
const SwsFlags flags[]
Definition: swscale.c:61
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AV_TEXTFORMAT_SECTION_PRINT_TAGS
#define AV_TEXTFORMAT_SECTION_PRINT_TAGS
...
Definition: avtextformat.h:53
MermaidContext::link_buf
AVBPrint link_buf
print buffer for writing diagram links
Definition: tf_mermaid.c:156
AV_TEXTFORMAT_FLAG_IS_DIAGRAM_FORMATTER
#define AV_TEXTFORMAT_FLAG_IS_DIAGRAM_FORMATTER
Definition: avtextformat.h:73
opt.h
AV_TEXTFORMAT_LINKTYPE_SRCDEST
@ AV_TEXTFORMAT_LINKTYPE_SRCDEST
Definition: avtextformat.h:83
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
av_stristr
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition: avstring.c:58
has_link_pair
static av_cold int has_link_pair(const AVTextFormatContext *tfc, const char *src, const char *dest)
Definition: tf_mermaid.c:178
int64_t
long long int64_t
Definition: coverity.c:34
AVTextFormatSection::src_id_key
const char * src_id_key
name of the key to be used as the source id for diagram connections
Definition: avtextformat.h:64
AV_DIAGRAMTYPE_ENTITYRELATIONSHIP
@ AV_DIAGRAMTYPE_ENTITYRELATIONSHIP
Definition: tf_mermaid.h:26
AVTextFormatSectionContext::context_type
const char * context_type
Definition: avtextformat.h:36
AVDiagramConfig::diagram_css
const char * diagram_css
Definition: tf_mermaid.h:31
writer_printf
static void writer_printf(AVTextFormatContext *wctx, const char *fmt,...)
Definition: tf_internal.h:73
AVOption
AVOption.
Definition: opt.h:429
data
const char data[16]
Definition: mxf.c:149
AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH
#define AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH
...
Definition: avtextformat.h:54
avtextformat.h
AVTextFormatContext
Definition: avtextformat.h:112
AVDictionary
Definition: dict.c:32
AV_TEXTFORMAT_LINKTYPE_ONETOMANY
@ AV_TEXTFORMAT_LINKTYPE_ONETOMANY
Definition: avtextformat.h:88
mermaid_print_int
static void mermaid_print_int(AVTextFormatContext *tfc, const char *key, int64_t value)
Definition: tf_mermaid.c:657
DEFINE_FORMATTER_CLASS
DEFINE_FORMATTER_CLASS(mermaid)
init_directive
static const char * init_directive
Definition: tf_mermaid.c:36
AVTextFormatContext::level
int level
current level, starting from 0
Definition: avtextformat.h:123
AVTextFormatSection::name
const char * name
Definition: avtextformat.h:43
AVDiagramConfig
Definition: tf_mermaid.h:29
AV_ESCAPE_FLAG_STRICT
#define AV_ESCAPE_FLAG_STRICT
Escape only specified special characters.
Definition: avstring.h:336
AVTextFormatLinkType
AVTextFormatLinkType
Definition: avtextformat.h:82
MermaidContext::link_dict
AVDictionary * link_dict
Definition: tf_mermaid.c:157
AV_TEXTFORMAT_LINKTYPE_MANYTOONE
@ AV_TEXTFORMAT_LINKTYPE_MANYTOONE
Definition: avtextformat.h:89
avtextformatter_mermaid
const AVTextFormatter avtextformatter_mermaid
Definition: tf_mermaid.c:662
mermaid_print_str
static void mermaid_print_str(AVTextFormatContext *tfc, const char *key, const char *value)
Definition: tf_mermaid.c:652
AVTextFormatSectionContext
Definition: avtextformat.h:34
mermaid_init_html
static av_cold int mermaid_init_html(AVTextFormatContext *tfc)
Definition: tf_mermaid.c:204
AVTextFormatSection::flags
int flags
Definition: avtextformat.h:56
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:90
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:60
AVTextFormatter
Definition: avtextformat.h:94
AVTextFormatSection
Definition: avtextformat.h:41
limits.h
AVTextFormatContext::priv
void * priv
private data for use by the filter
Definition: avtextformat.h:118
key
const char * key
Definition: hwcontext_opencl.c:189
MermaidContext::section_data::subgraph_start_incomplete
int subgraph_start_incomplete
Definition: tf_mermaid.c:152
MermaidContext
Definition: tf_mermaid.c:133
AV_DIAGRAMTYPE_GRAPH
@ AV_DIAGRAMTYPE_GRAPH
Definition: tf_mermaid.h:25
MermaidContext::within_tag
int within_tag
Definition: tf_mermaid.c:137
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
NULL
#define NULL
Definition: coverity.c:32
writer_w8
static void writer_w8(AVTextFormatContext *wctx, int b)
Definition: tf_internal.h:63
MermaidContext::create_html
int create_html
Definition: tf_mermaid.c:139
tmp
static uint8_t tmp[20]
Definition: aes_ctr.c:47
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
tf_get_parent_section
static const AVTextFormatSection * tf_get_parent_section(AVTextFormatContext *tfc, int level)
Safely access the parent section.
Definition: tf_internal.h:55
OFFSET
#define OFFSET(x)
Definition: tf_mermaid.c:161
MermaidContext::section_data::current_is_textblock
int current_is_textblock
Definition: tf_mermaid.c:150
av_strireplace
char * av_strireplace(const char *str, const char *from, const char *to)
Locale-independent strings replace.
Definition: avstring.c:229
AV_TEXTFORMAT_LINKTYPE_MANYTOMANY
@ AV_TEXTFORMAT_LINKTYPE_MANYTOMANY
Definition: avtextformat.h:91
MermaidContext::section_data
Definition: tf_mermaid.c:144
MermaidContext::diagram_config
AVDiagramConfig * diagram_config
Definition: tf_mermaid.c:135
MermaidContext::subgraph_count
int subgraph_count
Definition: tf_mermaid.c:136
SECTION_MAX_NB_LEVELS
#define SECTION_MAX_NB_LEVELS
Definition: avtextformat.h:109
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
mermaid_print_section_footer
static void mermaid_print_section_footer(AVTextFormatContext *tfc)
Definition: tf_mermaid.c:412
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
MM_INDENT
#define MM_INDENT()
Definition: tf_mermaid.c:244
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
mermaid_print_value
static void mermaid_print_value(AVTextFormatContext *tfc, const char *key, const char *str, int64_t num, const int is_int)
Definition: tf_mermaid.c:549
AVTextFormatter::name
const char * name
Definition: avtextformat.h:97
MermaidContext::section_data::src_id
const char * src_id
Definition: tf_mermaid.c:147
AV_TEXTFORMAT_SECTION_FLAG_IS_SHAPE
#define AV_TEXTFORMAT_SECTION_FLAG_IS_SHAPE
...
Definition: avtextformat.h:51
MermaidContext::indent_level
int indent_level
Definition: tf_mermaid.c:138
AVTextFormatContext::section_pbuf
AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]
generic print buffer dedicated to each section, used by various formatters
Definition: avtextformat.h:131
theme_css_er
static const char * theme_css_er
Definition: tf_mermaid.c:87
avtextformatter_mermaidhtml
const AVTextFormatter avtextformatter_mermaidhtml
Definition: tf_mermaid.c:676
tf_internal.h
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:233
AVTextFormatSection::linktype_key
const char * linktype_key
name of the key to be used as the link type for diagram connections (AVTextFormatLinkType)
Definition: avtextformat.h:66
mermaid_print_section_header
static void mermaid_print_section_header(AVTextFormatContext *tfc, const void *data)
Definition: tf_mermaid.c:246
AVDiagramConfig::diagram_type
AVDiagramType diagram_type
Definition: tf_mermaid.h:30
MermaidContext::enable_link_colors
int enable_link_colors
Definition: tf_mermaid.c:142
writer_put_str
static void writer_put_str(AVTextFormatContext *wctx, const char *str)
Definition: tf_internal.h:68
uninit
static void uninit(AVBSFContext *ctx)
Definition: pcm_rechunk.c:68
bprint.h
AVTextFormatSectionContext::context_id
char * context_id
Definition: avtextformat.h:35
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
MermaidContext::nb_link_captions
unsigned nb_link_captions[SECTION_MAX_NB_LEVELS]
generic print buffer dedicated to each section,
Definition: tf_mermaid.c:155
set_str
static void set_str(const char **dst, const char *src)
Definition: tf_mermaid.c:235
mermaid_init
static av_cold int mermaid_init(AVTextFormatContext *tfc)
Definition: tf_mermaid.c:194
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
AVTextFormatSectionContext::context_flags
int context_flags
Definition: avtextformat.h:37
MermaidContext::section_data
struct MermaidContext::section_data section_data[SECTION_MAX_NB_LEVELS]
AV_TEXTFORMAT_LINKTYPE_ONETOONE
@ AV_TEXTFORMAT_LINKTYPE_ONETOONE
Definition: avtextformat.h:90
ret
ret
Definition: filter_design.txt:187
AVTextFormatSection::dest_id_key
const char * dest_id_key
name of the key to be used as the target id for diagram connections
Definition: avtextformat.h:65
MermaidContext::section_data::dest_id
const char * dest_id
Definition: tf_mermaid.c:148
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS
#define AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS
...
Definition: avtextformat.h:52
AVDiagramConfig::html_template
const char * html_template
Definition: tf_mermaid.h:32
MermaidContext::section_data::section_id
const char * section_id
Definition: tf_mermaid.c:145
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:232
mermaid_uninit
static av_cold int mermaid_uninit(AVTextFormatContext *tfc)
Definition: tf_mermaid.c:218
MermaidContext::section_data::current_is_stadium
int current_is_stadium
Definition: tf_mermaid.c:151
MermaidContext::section_data::section_type
const char * section_type
Definition: tf_mermaid.c:146
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
mem.h
AVTextFormatSection::id_key
const char * id_key
name of the key to be used as the id
Definition: avtextformat.h:63
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:86
AV_ESCAPE_MODE_BACKSLASH
@ AV_ESCAPE_MODE_BACKSLASH
Use backslash escaping.
Definition: avstring.h:316
tf_get_section
static const AVTextFormatSection * tf_get_section(AVTextFormatContext *tfc, int level)
Safely validate and access a section at a given level.
Definition: tf_internal.h:42
av_diagram_init
void av_diagram_init(AVTextFormatContext *tfc, AVDiagramConfig *diagram_config)
Definition: tf_mermaid.c:172
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
MermaidContext::section_data::link_type
AVTextFormatLinkType link_type
Definition: tf_mermaid.c:149
src
#define src
Definition: vp8dsp.c:248
mermaid_options
static const AVOption mermaid_options[]
Definition: tf_mermaid.c:163
init_directive_er
static const char * init_directive_er
Definition: tf_mermaid.c:60
tf_mermaid.h