[{"id":34126,"web_url":"https://patchwork.libcamera.org/comment/34126/","msgid":"<aBYYWXB44JVPdugN@duo.ucw.cz>","date":"2025-05-03T13:21:29","subject":"Re: [PATCH] cam: Implement %x handling","submitter":{"id":49,"url":"https://patchwork.libcamera.org/api/people/49/","name":"Pavel Machek","email":"pavel@ucw.cz"},"content":"Hi!\n\n> With raw files, we have no good place to store the metadata, yet\n> timestamp, width / height and format is useful for further\n> processing. Implement %x so that timestamped frames etc are possible.\n>     \n> Signed-off-by: Pavel Machek <pavel@ucw.cz>\n\nAny feedback on this one?\n\n> diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp\n> index 65794a2f..22cdaaa2 100644\n> --- a/src/apps/cam/file_sink.cpp\n> +++ b/src/apps/cam/file_sink.cpp\n> @@ -16,6 +16,8 @@\n>  #include <string.h>\n>  #include <unistd.h>\n>  #include <utility>\n> +#include <chrono>\n> +#include <ctime>\n>  \n>  #include <libcamera/camera.h>\n>  \n> @@ -116,6 +118,44 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,\n>  \t\tfilename.replace(pos, 1, ss.str());\n>  \t}\n>  \n> +\tstd::ostringstream result;\n> +\tfor (size_t i = 0; i < filename.size(); ++i) {\n> +\t\tif (filename[i] == '%' && i + 1 < filename.size()) {\n> +\t\t\tchar specifier = filename[i + 1];\n> +\t\t\ti++; // Skip specifier character\n> +\t\t\tswitch (specifier) {\n> +\t\t\tcase 's':\n> +\t\t\t\tresult << std::setw(6) << std::setfill('0') << buffer->metadata().sequence;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 'w':\n> +\t\t\t\tresult << stream->configuration().size.width;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 'h':\n> +\t\t\t\tresult << stream->configuration().size.height;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 'f':\n> +\t\t\t\tresult << stream->configuration().pixelFormat;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 't': {\n> +\t\t\t\tauto now = std::chrono::system_clock::now();\n> +\t\t\t\tauto micros = std::chrono::duration_cast<std::chrono::microseconds>(\n> +\t\t\t\t\tnow.time_since_epoch()).count();\n> +\t\t\t\tresult << micros;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t\tcase '%':\n> +\t\t\t\tresult << '%' << specifier;\n> +\t\t\t\tbreak;\n> +\t\t\tdefault:\n> +\t\t\t\tresult << \"%BAD%\";\n> +\t\t\t}\n> +\t\t} else {\n> +\t\t\tresult << filename[i];\n> +\t\t}\n> +\t}\n> +\t\n> +\tfilename =  result.str();\n> +\t\n>  \tImage *image = mappedBuffers_[buffer].get();\n>  \n>  #ifdef HAVE_TIFF\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 036A7C3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat,  3 May 2025 13:21:32 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 269D968B25;\n\tSat,  3 May 2025 15:21:32 +0200 (CEST)","from jabberwock.ucw.cz (jabberwock.ucw.cz [46.255.230.98])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4C825617CB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  3 May 2025 15:21:30 +0200 (CEST)","by jabberwock.ucw.cz (Postfix, from userid 1017)\n\tid C630B1C0082; Sat,  3 May 2025 15:21:29 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ucw.cz header.i=@ucw.cz header.b=\"V4Ws1E2y\";\n\tdkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=ucw.cz; s=gen1;\n\tt=1746278489;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=CZpzD9Rl48sXBguT34bqpcrabUiiydq5347FV0hKQOw=;\n\tb=V4Ws1E2y4cAKsEhK+Dlu3rj1DIAmc4w8Q4mrXVkQNnH77iDV4lky00jkMCeO4EU5rXhaau\n\tLvjXuarqMW/VEGPNgku4vCKxTotTSNI1rb6j9nr5KHD7RGUHICrcdX8cwqTPjoD57Jfljo\n\tl6J6lMP2rPiP5D3V+HgmjIHoL232yyk=","Date":"Sat, 3 May 2025 15:21:29 +0200","From":"Pavel Machek <pavel@ucw.cz>","To":"laurent.pinchart@ideasonboard.com, libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] cam: Implement %x handling","Message-ID":"<aBYYWXB44JVPdugN@duo.ucw.cz>","References":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha1;\n\tprotocol=\"application/pgp-signature\"; boundary=\"8+SNIo5sgZ7AZYuB\"","Content-Disposition":"inline","In-Reply-To":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":34131,"web_url":"https://patchwork.libcamera.org/comment/34131/","msgid":"<174645552667.770767.3429597190785954891@ping.linuxembedded.co.uk>","date":"2025-05-05T14:32:06","subject":"Re: [PATCH] cam: Implement %x handling","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Pavel Machek (2025-05-03 14:21:29)\n> Hi!\n> \n> > With raw files, we have no good place to store the metadata, yet\n> > timestamp, width / height and format is useful for further\n> > processing. Implement %x so that timestamped frames etc are possible.\n> >     \n> > Signed-off-by: Pavel Machek <pavel@ucw.cz>\n> \n> Any feedback on this one?\n\nI think this is helpful. I'd probably think using some defined\ncombination as a default would be helpful too, and some how using the\nsame definitions across cam, qcam and camshark to make sure the output\nfilename formats are consistent across the toolings would help.\n\nPerhaps we should make some header only helpers in libcamera-base to\nhave something optionally/commonly re-usable?\n\n\n> > diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp\n> > index 65794a2f..22cdaaa2 100644\n> > --- a/src/apps/cam/file_sink.cpp\n> > +++ b/src/apps/cam/file_sink.cpp\n> > @@ -16,6 +16,8 @@\n> >  #include <string.h>\n> >  #include <unistd.h>\n> >  #include <utility>\n> > +#include <chrono>\n> > +#include <ctime>\n> >  \n> >  #include <libcamera/camera.h>\n> >  \n> > @@ -116,6 +118,44 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,\n> >               filename.replace(pos, 1, ss.str());\n> >       }\n> >  \n> > +     std::ostringstream result;\n> > +     for (size_t i = 0; i < filename.size(); ++i) {\n> > +             if (filename[i] == '%' && i + 1 < filename.size()) {\n> > +                     char specifier = filename[i + 1];\n> > +                     i++; // Skip specifier character\n> > +                     switch (specifier) {\n> > +                     case 's':\n> > +                             result << std::setw(6) << std::setfill('0') << buffer->metadata().sequence;\n> > +                             break;\n> > +                     case 'w':\n> > +                             result << stream->configuration().size.width;\n> > +                             break;\n> > +                     case 'h':\n> > +                             result << stream->configuration().size.height;\n> > +                             break;\n\nWhat about a %s for size to automatically output %wx%h (which is already\npossible with just \n\t\t\t\t result << stream->configuration().size;\n\nI think ...\n\nBut you've already proposed s for sequence ;-s\n\n\nAre there any use cases where someone would want to split the width and\nheight separately in the output file name ? (Perhaps customisability\nwould make sense sometime there)\n\n> > +                     case 'f':\n> > +                             result << stream->configuration().pixelFormat;\n> > +                             break;\n\nseems reasonable.\n\nI do wonder if we extended this to have multiple chars we could copy the\nkernel and use \n\t%4cc ..\n\n(The kernel has %p4cc)\n\n> > +                     case 't': {\n> > +                             auto now = std::chrono::system_clock::now();\n> > +                             auto micros = std::chrono::duration_cast<std::chrono::microseconds>(\n> > +                                     now.time_since_epoch()).count();\n\nShouldn't this come from the request completion/sensor timestamp\ninformation instead ?\n\n\n> > +                             result << micros;\n> > +                             break;\n> > +                     }\n> > +                     case '%':\n> > +                             result << '%' << specifier;\n> > +                             break;\n> > +                     default:\n> > +                             result << \"%BAD%\";\n> > +                     }\n> > +             } else {\n> > +                     result << filename[i];\n> > +             }\n> > +     }\n> > +     \n> > +     filename =  result.str();\n> > +     \n> >       Image *image = mappedBuffers_[buffer].get();\n> >  \n> >  #ifdef HAVE_TIFF\n> > \n> \n> \n> \n> -- \n> I don't work for Nazis and criminals, and neither should you.\n> Boycott Putin, Trump, and Musk!","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 06C5BC3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  5 May 2025 14:32:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1A4AF68B25;\n\tMon,  5 May 2025 16:32:11 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 96A4368ADE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  5 May 2025 16:32:09 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8D3FD289;\n\tMon,  5 May 2025 16:31:59 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ifdDvTjf\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1746455519;\n\tbh=WXR8sYqtCHSCK0PLjZO2t+GeD8rARw86jN6YatSnAmA=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=ifdDvTjfYqoShSjVFlE0HFpTtuGm5VJzVRuEOOiIkMpiQ5oPhD6WAGXSRuyJgIjTc\n\t23tRJwFcJ+YOV4JH64TgasEEYNaN9gvV2U7LX9NL8g8DEEcIVcDqKczdld7LSOXU1N\n\tAfOVH83HW95zz1uMMifDJUN6nsMvqecqbBI6HthI=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<aBYYWXB44JVPdugN@duo.ucw.cz>","References":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz> <aBYYWXB44JVPdugN@duo.ucw.cz>","Subject":"Re: [PATCH] cam: Implement %x handling","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"Pavel Machek <pavel@ucw.cz>, laurent.pinchart@ideasonboard.com,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 05 May 2025 15:32:06 +0100","Message-ID":"<174645552667.770767.3429597190785954891@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":34164,"web_url":"https://patchwork.libcamera.org/comment/34164/","msgid":"<600f8a63-dde2-4e1a-bd95-d4c791998464@ideasonboard.com>","date":"2025-05-09T10:44:03","subject":"Re: [PATCH] cam: Implement %x handling","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"Hi\n\n2025. 04. 13. 10:22 keltezéssel, Pavel Machek írta:\n> With raw files, we have no good place to store the metadata, yet\n> timestamp, width / height and format is useful for further\n> processing. Implement %x so that timestamped frames etc are possible.\n>      \n> Signed-off-by: Pavel Machek <pavel@ucw.cz>\n> \n> diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp\n> index 65794a2f..22cdaaa2 100644\n> --- a/src/apps/cam/file_sink.cpp\n> +++ b/src/apps/cam/file_sink.cpp\n> @@ -16,6 +16,8 @@\n>   #include <string.h>\n>   #include <unistd.h>\n>   #include <utility>\n> +#include <chrono>\n> +#include <ctime>\n>   \n>   #include <libcamera/camera.h>\n>   \n> @@ -116,6 +118,44 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,\n>   \t\tfilename.replace(pos, 1, ss.str());\n>   \t}\n>   \n> +\tstd::ostringstream result;\n> +\tfor (size_t i = 0; i < filename.size(); ++i) {\n> +\t\tif (filename[i] == '%' && i + 1 < filename.size()) {\n> +\t\t\tchar specifier = filename[i + 1];\n> +\t\t\ti++; // Skip specifier character\n> +\t\t\tswitch (specifier) {\n> +\t\t\tcase 's':\n> +\t\t\t\tresult << std::setw(6) << std::setfill('0') << buffer->metadata().sequence;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 'w':\n> +\t\t\t\tresult << stream->configuration().size.width;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 'h':\n> +\t\t\t\tresult << stream->configuration().size.height;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 'f':\n> +\t\t\t\tresult << stream->configuration().pixelFormat;\n> +\t\t\t\tbreak;\n> +\t\t\tcase 't': {\n> +\t\t\t\tauto now = std::chrono::system_clock::now();\n> +\t\t\t\tauto micros = std::chrono::duration_cast<std::chrono::microseconds>(\n> +\t\t\t\t\tnow.time_since_epoch()).count();\n> +\t\t\t\tresult << micros;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t\tcase '%':\n> +\t\t\t\tresult << '%' << specifier;\n> +\t\t\t\tbreak;\n> +\t\t\tdefault:\n> +\t\t\t\tresult << \"%BAD%\";\n\nI believe when an unknown specifier is encountered, it should be left as is;\nor if `setFilePattern()` has been extended to check the format string, then\nit could potentially abort.\n\n\nRegards,\nBarnabás Pőcze\n\n\n> +\t\t\t}\n> +\t\t} else {\n> +\t\t\tresult << filename[i];\n> +\t\t}\n> +\t}\n> +\t\n> +\tfilename =  result.str();\n> +\t\n>   \tImage *image = mappedBuffers_[buffer].get();\n>   \n>   #ifdef HAVE_TIFF\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 83674C3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri,  9 May 2025 10:44:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D3B0C68B42;\n\tFri,  9 May 2025 12:44:10 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7BF3068B25\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  9 May 2025 12:44:09 +0200 (CEST)","from [192.168.33.12] (185.221.140.100.nat.pool.zt.hu\n\t[185.221.140.100])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4CC608DB;\n\tFri,  9 May 2025 12:43:54 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"vr8vXL0F\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1746787436;\n\tbh=TkoKFiswUGu0pB3cfCHk/J02837WWz6en5tegL01UVM=;\n\th=Date:Subject:To:References:From:Cc:In-Reply-To:From;\n\tb=vr8vXL0FwyRoheLVGjknysTvsplxrKej6XfsusaLyqlHhHTX3Rc2fuc4HuvEntGAo\n\tZafG8bT/euIzFKtSkFW3Yl776IOYO/YpCNNZfgCOGDrHsmlV/2Y+49hiJv/f9S3a4y\n\tw5zQTCZobs5WipIQodumOHEW+BbOBbCOK2clSoas=","Message-ID":"<600f8a63-dde2-4e1a-bd95-d4c791998464@ideasonboard.com>","Date":"Fri, 9 May 2025 12:44:03 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] cam: Implement %x handling","To":"Pavel Machek <pavel@ucw.cz>","References":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","Cc":"laurent.pinchart@ideasonboard.com, libcamera-devel@lists.libcamera.org","In-Reply-To":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":35640,"web_url":"https://patchwork.libcamera.org/comment/35640/","msgid":"<175655016524.1721288.10069759150197894991@ping.linuxembedded.co.uk>","date":"2025-08-30T10:36:05","subject":"Re: [PATCH] cam: Implement %x handling","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Pavel,\n\nQuoting Kieran Bingham (2025-05-05 15:32:06)\n> Quoting Pavel Machek (2025-05-03 14:21:29)\n> > Hi!\n> > \n> > > With raw files, we have no good place to store the metadata, yet\n> > > timestamp, width / height and format is useful for further\n> > > processing. Implement %x so that timestamped frames etc are possible.\n> > >     \n> > > Signed-off-by: Pavel Machek <pavel@ucw.cz>\n> > \n> > Any feedback on this one?\n\nDo you plan to submit an updated patch? Adding more detail to the file\noutput would be convenient I think.\n\n--\nKieran\n\n> \n> I think this is helpful. I'd probably think using some defined\n> combination as a default would be helpful too, and some how using the\n> same definitions across cam, qcam and camshark to make sure the output\n> filename formats are consistent across the toolings would help.\n> \n> Perhaps we should make some header only helpers in libcamera-base to\n> have something optionally/commonly re-usable?\n> \n> \n> > > diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp\n> > > index 65794a2f..22cdaaa2 100644\n> > > --- a/src/apps/cam/file_sink.cpp\n> > > +++ b/src/apps/cam/file_sink.cpp\n> > > @@ -16,6 +16,8 @@\n> > >  #include <string.h>\n> > >  #include <unistd.h>\n> > >  #include <utility>\n> > > +#include <chrono>\n> > > +#include <ctime>\n> > >  \n> > >  #include <libcamera/camera.h>\n> > >  \n> > > @@ -116,6 +118,44 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,\n> > >               filename.replace(pos, 1, ss.str());\n> > >       }\n> > >  \n> > > +     std::ostringstream result;\n> > > +     for (size_t i = 0; i < filename.size(); ++i) {\n> > > +             if (filename[i] == '%' && i + 1 < filename.size()) {\n> > > +                     char specifier = filename[i + 1];\n> > > +                     i++; // Skip specifier character\n> > > +                     switch (specifier) {\n> > > +                     case 's':\n> > > +                             result << std::setw(6) << std::setfill('0') << buffer->metadata().sequence;\n> > > +                             break;\n> > > +                     case 'w':\n> > > +                             result << stream->configuration().size.width;\n> > > +                             break;\n> > > +                     case 'h':\n> > > +                             result << stream->configuration().size.height;\n> > > +                             break;\n> \n> What about a %s for size to automatically output %wx%h (which is already\n> possible with just \n>                                  result << stream->configuration().size;\n> \n> I think ...\n> \n> But you've already proposed s for sequence ;-s\n> \n> \n> Are there any use cases where someone would want to split the width and\n> height separately in the output file name ? (Perhaps customisability\n> would make sense sometime there)\n> \n> > > +                     case 'f':\n> > > +                             result << stream->configuration().pixelFormat;\n> > > +                             break;\n> \n> seems reasonable.\n> \n> I do wonder if we extended this to have multiple chars we could copy the\n> kernel and use \n>         %4cc ..\n> \n> (The kernel has %p4cc)\n> \n> > > +                     case 't': {\n> > > +                             auto now = std::chrono::system_clock::now();\n> > > +                             auto micros = std::chrono::duration_cast<std::chrono::microseconds>(\n> > > +                                     now.time_since_epoch()).count();\n> \n> Shouldn't this come from the request completion/sensor timestamp\n> information instead ?\n> \n> \n> > > +                             result << micros;\n> > > +                             break;\n> > > +                     }\n> > > +                     case '%':\n> > > +                             result << '%' << specifier;\n> > > +                             break;\n> > > +                     default:\n> > > +                             result << \"%BAD%\";\n> > > +                     }\n> > > +             } else {\n> > > +                     result << filename[i];\n> > > +             }\n> > > +     }\n> > > +     \n> > > +     filename =  result.str();\n> > > +     \n> > >       Image *image = mappedBuffers_[buffer].get();\n> > >  \n> > >  #ifdef HAVE_TIFF\n> > > \n> > \n> > \n> > \n> > -- \n> > I don't work for Nazis and criminals, and neither should you.\n> > Boycott Putin, Trump, and Musk!","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 55BB5BD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 30 Aug 2025 10:36:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C3C4C69322;\n\tSat, 30 Aug 2025 12:36:09 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CA937613AF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 30 Aug 2025 12:36:08 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E3FC91666;\n\tSat, 30 Aug 2025 12:35:02 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"DnPVRwAm\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1756550103;\n\tbh=ND29uNaLxNoh/rFWqR0BBPG86zWsXycI6/DUYzcr2ZU=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=DnPVRwAmcgpY7GrMLmITlmVEypD/DeJWP/ZFc4TaxdQzB6V2DUKV369XfNOl2mRV5\n\tE06gm0HpOi0wekJFQuykuxWO/862t1xIBLid+oR7Xk7eKQjnFy5QgnoyigB0g/2PPv\n\tQBTG7QHoT9Wur85pJk3AId0EWDJ53V+NHsYz8NVE=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<174645552667.770767.3429597190785954891@ping.linuxembedded.co.uk>","References":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz> <aBYYWXB44JVPdugN@duo.ucw.cz>\n\t<174645552667.770767.3429597190785954891@ping.linuxembedded.co.uk>","Subject":"Re: [PATCH] cam: Implement %x handling","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"Pavel Machek <pavel@ucw.cz>, laurent.pinchart@ideasonboard.com,\n\tlibcamera-devel@lists.libcamera.org","Date":"Sat, 30 Aug 2025 11:36:05 +0100","Message-ID":"<175655016524.1721288.10069759150197894991@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":35650,"web_url":"https://patchwork.libcamera.org/comment/35650/","msgid":"<aLSnbS6QB/kt/gVW@duo.ucw.cz>","date":"2025-08-31T19:50:05","subject":"Re: [PATCH] cam: Implement %x handling","submitter":{"id":49,"url":"https://patchwork.libcamera.org/api/people/49/","name":"Pavel Machek","email":"pavel@ucw.cz"},"content":"On Sat 2025-08-30 11:36:05, Kieran Bingham wrote:\n> Hi Pavel,\n> \n> Quoting Kieran Bingham (2025-05-05 15:32:06)\n> > Quoting Pavel Machek (2025-05-03 14:21:29)\n> > > Hi!\n> > > \n> > > > With raw files, we have no good place to store the metadata, yet\n> > > > timestamp, width / height and format is useful for further\n> > > > processing. Implement %x so that timestamped frames etc are possible.\n> > > >     \n> > > > Signed-off-by: Pavel Machek <pavel@ucw.cz>\n> > > \n> > > Any feedback on this one?\n> \n> Do you plan to submit an updated patch? Adding more detail to the file\n> output would be convenient I think.\n\nI'm now hacking on clicks machine. I'll likely return to libcamera\nwhen GPU ISP / autofocus is merged. If someone can pick this up, that\nwould be great.\n\nBest regards,\n\t\t\t\t\t\t\t\tPavel","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 9B246BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 31 Aug 2025 19:50:08 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 50A6269322;\n\tSun, 31 Aug 2025 21:50:07 +0200 (CEST)","from jabberwock.ucw.cz (jabberwock.ucw.cz [46.255.230.98])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 2E062613AD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 31 Aug 2025 21:50:06 +0200 (CEST)","by jabberwock.ucw.cz (Postfix, from userid 1017)\n\tid 8E0711C01BD; Sun, 31 Aug 2025 21:50:05 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ucw.cz header.i=@ucw.cz header.b=\"TNmgsfm/\";\n\tdkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=ucw.cz; s=gen1;\n\tt=1756669805;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=hA/PQs5KffC/o5wf+D/N1lSPAYWmIj3aCmwdDcMwiTw=;\n\tb=TNmgsfm/VHAAWI9X+W5OZ3lPMjFIkG0YJb5XnDnSS1BwsGD8kdUom9oL0mB7moJlaucIDP\n\tQMDxGo/nMrTCtZCPHdXsKyXoVjs7H0+elRMDGsTpNpzGCwgMt6+CkNPSewbOfI7SopHWPI\n\typ7RTRQn8bAJystA+2AY24BfFegJwEs=","Date":"Sun, 31 Aug 2025 21:50:05 +0200","From":"Pavel Machek <pavel@ucw.cz>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"laurent.pinchart@ideasonboard.com, libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] cam: Implement %x handling","Message-ID":"<aLSnbS6QB/kt/gVW@duo.ucw.cz>","References":"<Z/t0OSQynbJ0BhEX@duo.ucw.cz> <aBYYWXB44JVPdugN@duo.ucw.cz>\n\t<174645552667.770767.3429597190785954891@ping.linuxembedded.co.uk>\n\t<175655016524.1721288.10069759150197894991@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha1;\n\tprotocol=\"application/pgp-signature\"; boundary=\"rQFshT/d+GJsONcg\"","Content-Disposition":"inline","In-Reply-To":"<175655016524.1721288.10069759150197894991@ping.linuxembedded.co.uk>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]