From patchwork Fri Jan 30 08:09:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 26049 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id E1AE1C3226 for ; Fri, 30 Jan 2026 08:09:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3FBD261FC9; Fri, 30 Jan 2026 09:09:49 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Cr/Yc1KX"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E1C361FA0 for ; Fri, 30 Jan 2026 09:09:48 +0100 (CET) Received: from neptunite.hamster-moth.ts.net (unknown [IPv6:2404:7a81:160:2100:ec11:5e0c:deb8:1e2d]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D45B355C; Fri, 30 Jan 2026 09:09:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1769760550; bh=ZWVV3TbQRtqx5IiHZ/snuWignbbkoqLQ+LoXWUonhYw=; h=From:To:Cc:Subject:Date:From; b=Cr/Yc1KXS7fArhHWWA2ctYTAcUpUCLuclE74k9pR/cCSE6KsEZxYCCzGcEvuO98Tu XKRKCreI7Cx2J8v5fBfGxUXOBW7FYb2FXdR2pRb/+qqFLL0AnYp2Vfj9vqb3hh9j78 r28gvltb6wtcWfTAbbaiCv1i94XOoMUZuelrkUZM= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder , david.plowman@raspberrypi.com, naush@raspberrypi.com, kieran.bingham@ideasonboard.com, stefan.klug@ideasonboard.com Subject: [PATCH v2 0/4] Add Sync Layer Date: Fri, 30 Jan 2026 17:09:31 +0900 Message-ID: <20260130080935.2569621-1-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This series depends on: - v6 of "Add Layers support" [0] (and optionally "libcamera: layer_manager: Add support for global configuration" [1]) There is a branch available at [2]. There is another version of the branch available at [3], which is the same branch rebased on top of Raspberry Pi's next [4] branch with an additional patch [5] on top to make Raspberry Pi use the Sync Layer instead of RPiSync. This patch series adds a layer implementation of the Sync algorithm, where any number of cameras can synchronize the timing of their captures. This allows any camera to use the Sync algorithm, as long as it implements the SyncAdjustment control and SensorTimestamp. I tested this on a pi5 (with an imx219 and imx708) and a Debix SOM (with an imx335 and imx283) with the following capture scripts, running the client first before running the server in separate terminals: $ cat cscript-sync-client.yaml frames: - 1: FrameDurationLimits: [33333, 33333] SyncMode: 2 $ cat cscript-sync-server.yaml frames: - 1: FrameDurationLimits: [33333, 33333] SyncMode: 1 The below information is also available in the PR at [6] for ease of access. I ran: - pi5 with pure rpi/next (RPiSync) [7] - pi5 with this branch (epaul/dev/sync on top of rpi/next) (SyncLayer) [8] - som with pure epaul/dev/sync (SyncLayer) [9] And I logged the correction time over a single run each of about 10 minutes at 30fps (aiming for 800 corrections). Here are the descriptive statistics for the correction values (all in microseconds): - pi5 with RPiSync Min. 1st Qu. Median Mean 3rd Qu. Max. 238.0 247.0 252.0 251.9 257.0 263.0 - pi5 with SyncLayer Min. 1st Qu. Median Mean 3rd Qu. Max. 239.0 247.0 252.0 251.9 257.0 263.0 - som with SyncLayer Min. 1st Qu. Median Mean 3rd Qu. Max. -16661 1273 7705 4386 11616 16643 I have graphs of these runs here [10]. The som could use some optimization, but we can see that on the pi5 the correction times between RPiSync and SyncLayer are nearly identical. [0] https://patchwork.libcamera.org/project/libcamera/list/?series=5753 [1] https://patchwork.libcamera.org/project/libcamera/list/?series=5758 [2] https://git.ideasonboard.com/epaul/libcamera/src/branch/epaul/dev/sync [3] https://git.ideasonboard.com/epaul/libcamera/src/branch/epaul/dev/sync-pi5 [4] https://github.com/raspberrypi/libcamera/tree/next [5] https://git.ideasonboard.com/epaul/libcamera/commit/4c480e1ec43ec3d698a19f444c8994f03b3ed5d6 [6] https://git.ideasonboard.com/epaul/libcamera/pulls/2 [7] https://git.ideasonboard.com/epaul/libcamera/commit/f0e40f1c [8] https://git.ideasonboard.com/epaul/libcamera/commit/4c480e1e [9] https://git.ideasonboard.com/epaul/libcamera/commit/0427d359 [10] https://git.ideasonboard.com/epaul/libcamera/pulls/2#issuecomment-26463 Paul Elder (4): controls: Add SyncAdjustment and SyncInterface controls layer: Add layer that implements the sync algorithm libipa: Add SyncHelper ipa: rkisp1: agc: Add support for sync src/ipa/libipa/meson.build | 2 + src/ipa/libipa/sync_helper.cpp | 88 ++++++ src/ipa/libipa/sync_helper.h | 43 +++ src/ipa/rkisp1/algorithms/agc.cpp | 22 +- src/ipa/rkisp1/algorithms/agc.h | 3 + src/ipa/rkisp1/ipa_context.h | 1 + src/layer/meson.build | 1 + src/layer/sync/meson.build | 15 + src/layer/sync/sync.cpp | 463 ++++++++++++++++++++++++++++ src/layer/sync/sync.h | 98 ++++++ src/libcamera/control_ids_core.yaml | 23 ++ 11 files changed, 758 insertions(+), 1 deletion(-) create mode 100644 src/ipa/libipa/sync_helper.cpp create mode 100644 src/ipa/libipa/sync_helper.h create mode 100644 src/layer/sync/meson.build create mode 100644 src/layer/sync/sync.cpp create mode 100644 src/layer/sync/sync.h