From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <ffmpeg-devel-bounces@ffmpeg.org>
Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100])
	by master.gitmailbox.com (Postfix) with ESMTPS id 98CD548A2D
	for <ffmpegdev@gitmailbox.com>; Wed, 19 Feb 2025 20:08:23 +0000 (UTC)
Received: from [127.0.1.1] (localhost [127.0.0.1])
	by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 447E668C2A0;
	Wed, 19 Feb 2025 22:08:08 +0200 (EET)
Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com
 [209.85.214.175])
 by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7EC8A68C0E4
 for <ffmpeg-devel@ffmpeg.org>; Wed, 19 Feb 2025 22:08:00 +0200 (EET)
Received: by mail-pl1-f175.google.com with SMTP id
 d9443c01a7336-220e989edb6so3336035ad.1
 for <ffmpeg-devel@ffmpeg.org>; Wed, 19 Feb 2025 12:08:00 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=gmail.com; s=20230601; t=1739995679; x=1740600479; darn=ffmpeg.org;
 h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date
 :references:in-reply-to:message-id:from:from:to:cc:subject:date
 :message-id:reply-to;
 bh=nFpEZs8aOJFuX8gqqFZeS2/852y+YahcdSTq/FwFN7g=;
 b=OaouGtGyc1Wy35xjCmhY/85UhmLVzMDLhessrYPkZEjypDiY02ai5yKdrSZ1DjCtcN
 OigZMBK6/jqBhu1g1qPxSsLGyJXFs0hR/hVKAWkajz/Z1Go8G34TKAi56CTY3aaZSREE
 iZ05XnFXTyRuzLkPZCQSUXo1ZrX/O+T5BlaiQ4H1wA8nOy5MQK1AuZG1WBD0IskxS83X
 nWxY395QnLtw9BJZNdXtfnk20oKrx9KOazGnVMbQifAj7kkmC+BMUtUV9dpXi0xi3mds
 /RSLHfWOfEuMicFmCrK98x2LcFcmnrP/1JOMUTahgfHxus7w5PUqiNlacD8XisAuU/bD
 CcJA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1739995679; x=1740600479;
 h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date
 :references:in-reply-to:message-id:from:x-gm-message-state:from:to
 :cc:subject:date:message-id:reply-to;
 bh=nFpEZs8aOJFuX8gqqFZeS2/852y+YahcdSTq/FwFN7g=;
 b=H9A0lBQ/ZzyfF2OsS83s8EXcOgKE4iCjTy39VkFLuY4s77vAHO1KOP+lza1Dl4GVGu
 JW5nWKKP0Uj7f8SQD6QUId5QDSYOOTNpYSQsrWvm+sR9xOQQr25Ouel6ZAuaNjeIZuol
 4enLa9cUCIfTuYB5uGv/nsumZAzlg2kPpDnZnkXtUWqQvQPbL22P2qxAaciAc2wnfjRZ
 qRQmQyLeO63ioMfEbzm9dpKa4c/pxWiSLZRvmFc1vO3V90OL0RV86KR6vg8HwzyZaE0a
 qFKO6mrpB6xJMOFKzdpDFaYvf7BSeoCf6HrJu5I7VKh/Uy+FXDWI2xZII7B9wKeXkoH6
 2bGw==
X-Gm-Message-State: AOJu0YwZEI396VDcz0BseYizizWJWPToonER5g4eg3uyFGWFQ8lrbw80
 M1SPDjElb5D5NjnCizBt13vizyhz4k326spWq5jlbnZK9NxbOIqgmbeYBA==
X-Gm-Gg: ASbGncvNZQDJTW6PzPVRfGL1UIrMlXLEO+UJ6v0QWScWxUumArszrEmwNsl1C0U+2Y/
 DFqzLBN/FDHMeVYyGlQM0aOeqoVivxOdkkLprM8Dqxjf0qV+NABi5lhcZCA/V2djBla/nRooQ4l
 OY4bV6x8GUtehGo4wIZ6r9q4Kn6Wki/hnArxNnaBlj1vou6xRJINQ46xVcjJ7TZLl8YmhITeTCe
 SoYocCia6LQq4S/Gt05Y+n3z8ZO7ROEzQB1ZB7M9NT/BMjWNbNuDshawu7ZkQR7nYzHgTCiDKM1
 0tqEBCfD3X+JbAWrUUTyN6N6RVisyiwCBg==
X-Google-Smtp-Source: AGHT+IEVCjDupl0DsiDdZ5aAvPz1y7WvjjVLuDzAmYWQAYM4uSOd3g1qmaeF/HJfzE+ibUE8teH1Ow==
X-Received: by 2002:a05:6a00:4f96:b0:730:9a55:d921 with SMTP id
 d2e1a72fcca58-732617e63acmr26965033b3a.14.1739995678674; 
 Wed, 19 Feb 2025 12:07:58 -0800 (PST)
Received: from [127.0.0.1] (master.gitmailbox.com. [34.83.118.50])
 by smtp.gmail.com with ESMTPSA id
 d2e1a72fcca58-7326b5ef448sm8278394b3a.173.2025.02.19.12.07.58
 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);
 Wed, 19 Feb 2025 12:07:58 -0800 (PST)
From: softworkz <ffmpegagent@gmail.com>
X-Google-Original-From: softworkz <softworkz@hotmail.com>
Message-Id: <494f07298ffed191891d3070a49d19e9a3cdc625.1739995676.git.ffmpegagent@gmail.com>
In-Reply-To: <pull.55.ffstaging.FFmpeg.1739995676.ffmpegagent@gmail.com>
References: <pull.55.ffstaging.FFmpeg.1739995676.ffmpegagent@gmail.com>
Date: Wed, 19 Feb 2025 20:07:55 +0000
Fcc: Sent
MIME-Version: 1.0
To: ffmpeg-devel@ffmpeg.org
Subject: [FFmpeg-devel] [PATCH 1/2] fftools/ffprobe: Add YAML output writer
X-BeenThere: ffmpeg-devel@ffmpeg.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: FFmpeg development discussions and patches <ffmpeg-devel.ffmpeg.org>
List-Unsubscribe: <https://ffmpeg.org/mailman/options/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=unsubscribe>
List-Archive: <https://ffmpeg.org/pipermail/ffmpeg-devel>
List-Post: <mailto:ffmpeg-devel@ffmpeg.org>
List-Help: <mailto:ffmpeg-devel-request@ffmpeg.org?subject=help>
List-Subscribe: <https://ffmpeg.org/mailman/listinfo/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=subscribe>
Reply-To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Cc: softworkz <softworkz@hotmail.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: ffmpeg-devel-bounces@ffmpeg.org
Sender: "ffmpeg-devel" <ffmpeg-devel-bounces@ffmpeg.org>
Archived-At: <https://master.gitmailbox.com/ffmpegdev/494f07298ffed191891d3070a49d19e9a3cdc625.1739995676.git.ffmpegagent@gmail.com/>
List-Archive: <https://master.gitmailbox.com/ffmpegdev/>
List-Post: <mailto:ffmpegdev@gitmailbox.com>

From: softworkz <softworkz@hotmail.com>

Signed-off-by: softworkz <softworkz@hotmail.com>
---
 fftools/ffprobe.c | 147 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 146 insertions(+), 1 deletion(-)

diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 0270878ead..843c8df7f3 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -1980,6 +1980,150 @@ static Writer xml_writer = {
     .priv_class           = &xml_class,
 };
 
+
+/* YAML output */
+
+typedef struct YMLContext {
+    const AVClass *class;
+    int indent_level;
+    int blank_lines;
+} YMLContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(YMLContext, x)
+
+static const AVOption yml_options[] = {
+    { "blank_lines", "print blank lines for better readability", OFFSET(blank_lines), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+    { NULL }
+};
+
+DEFINE_WRITER_CLASS(yml);
+
+static av_cold int yml_init(WriterContext *wctx)
+{
+    YMLContext *yml = wctx->priv;
+    yml->indent_level = 0;
+    return 0;
+}
+
+static int yml_is_plain(const char *s)
+{
+    if (!s || !*s)
+        return 0;
+    for (; *s; s++) {
+        if (!( (*s >= 'a' && *s <= 'z') ||
+               (*s >= 'A' && *s <= 'Z') ||
+               (*s >= '0' && *s <= '9') ||
+               *s == '_' || *s == '-' || *s == '.' ))
+            return 0;
+    }
+    return 1;
+}
+
+static void yml_print_quote_escape(WriterContext *wctx, const char *src)
+{
+    if (yml_is_plain(src)) {
+        writer_put_str(wctx, src);
+    } else {
+        writer_w8(wctx, '"');
+        for (const char *p = src; *p; p++) {
+            unsigned char c = *p;
+            if (c == '\\' || c == '"') {
+                writer_w8(wctx, '\\');
+                writer_w8(wctx, c);
+            } else if (c < 32 || c > 126) {
+                writer_printf(wctx, "\\u%04x", c);
+            } else {
+                writer_w8(wctx, c);
+            }
+        }
+        writer_w8(wctx, '"');
+    }
+}
+
+#define YML_INDENT() if (yml->indent_level > 0) writer_printf(wctx, "%*c", yml->indent_level * 2, ' ')
+#define YML_BLANKLINE() if (yml->blank_lines ) writer_put_str(wctx, "\n");
+
+/* At the top level, print yaml start marker '---'. If parent section is array,
+ * output a dash. If the section isn't merely a wrapper, its name as a mapping key.
+ * Otherwise, output the section name as a mapping key. */
+static void yml_print_section_header(WriterContext *wctx, const void *data)
+{
+    YMLContext *yml = wctx->priv;
+    const struct section *section = wctx->section[wctx->level];
+    const struct section *parent = (wctx->level > 0) ? wctx->section[wctx->level-1] : NULL;
+
+    if (wctx->level == 0) {
+        writer_put_str(wctx, "---\n");
+        return;
+    }
+
+    int parent_is_array = parent && (parent->flags & SECTION_FLAG_IS_ARRAY);
+    if (parent_is_array) {
+        YML_BLANKLINE();
+        writer_printf(wctx, "%*c- ", yml->indent_level * 2, ' ');
+        if (!(section->flags & SECTION_FLAG_IS_WRAPPER)) {
+            writer_printf(wctx, "%s:\n", section->name);
+        } else {
+            writer_put_str(wctx, "\n");
+        }
+        yml->indent_level++;
+        return;
+    }
+
+    YML_INDENT();
+    writer_put_str(wctx, section->name);
+    writer_put_str(wctx, ":\n");
+    yml->indent_level++;
+}
+
+static void yml_print_section_footer(WriterContext *wctx)
+{
+    YMLContext *yml = wctx->priv;
+    if (wctx->level == 0) {
+        writer_put_str(wctx, "...\n"); // yaml end document marker
+    } else {
+        if (wctx->level == 1)
+            YML_BLANKLINE();
+        yml->indent_level--;
+    }
+}
+
+static void yml_print_str(WriterContext *wctx, const char *key, const char *value)
+{
+    YMLContext *yml = wctx->priv;
+    YML_INDENT();
+
+    yml_print_quote_escape(wctx, key);
+    writer_put_str(wctx, ": ");
+
+    yml_print_quote_escape(wctx, value);
+    writer_put_str(wctx, "\n");
+}
+
+static void yml_print_int(WriterContext *wctx, const char *key, int64_t value)
+{
+    YMLContext *yml = wctx->priv;
+    YML_INDENT();
+
+    yml_print_quote_escape(wctx, key);
+    writer_put_str(wctx, ": ");
+
+    writer_printf(wctx, "%"PRId64"\n", value);
+}
+
+static const Writer yml_writer = {
+    .name                 = "yml",
+    .priv_size            = sizeof(YMLContext),
+    .init                 = yml_init,
+    .print_section_header = yml_print_section_header,
+    .print_section_footer = yml_print_section_footer,
+    .print_integer        = yml_print_int,
+    .print_string         = yml_print_str,
+    .flags                = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
+    .priv_class           = &yml_class,
+};
+
 static void writer_register_all(void)
 {
     static int initialized;
@@ -1995,6 +2139,7 @@ static void writer_register_all(void)
     writer_register(&ini_writer);
     writer_register(&json_writer);
     writer_register(&xml_writer);
+    writer_register(&yml_writer);
 }
 
 #define print_fmt(k, f, ...) do {              \
@@ -4597,7 +4742,7 @@ static const OptionDef real_options[] = {
     { "pretty",                OPT_TYPE_FUNC,        0, {.func_arg = opt_pretty},
       "prettify the format of displayed values, make it more human readable" },
     { "output_format",         OPT_TYPE_STRING,      0, { &output_format },
-      "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
+      "set the output printing format (available formats are: default, compact, csv, flat, ini, yml, json, xml)", "format" },
     { "print_format",          OPT_TYPE_STRING,      0, { &output_format }, "alias for -output_format (deprecated)" },
     { "of",                    OPT_TYPE_STRING,      0, { &output_format }, "alias for -output_format", "format" },
     { "select_streams",        OPT_TYPE_STRING,      0, { &stream_specifier }, "select the specified streams", "stream_specifier" },
-- 
ffmpeg-codebot

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".