From patchwork Thu Mar 31 13:06:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Curtin X-Patchwork-Id: 15588 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 0956BC3256 for ; Thu, 31 Mar 2022 13:06:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1FB6865633; Thu, 31 Mar 2022 15:06:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648731981; bh=2TM5Vk49OXW5l2z9xfsqGxHXNJdHXOjsStiXnCsCcdg=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=nLA7vu1THrzzb4HH8S5jJAdcLW3kQi5YKRRb9ZfzlrU+uL1dIBvTjs7FqUC0J7q9/ xGtouNRwxVpPCoVOsFbRMHSQWSJrwiejQjkxnPf85v6fdiVZGtgwfvx1Ku2yGBbpPZ s7wzCjDC9vyHi5e4kqnKZL2R14381IkoFih2uJE1w30J9KY+Gk/KkLBrTxpOkv5aq6 4ODyNRTO+bT09W5hVeFs/AJwWZKHfSPHtIdOW61XhIeYe3p7LBPWfv3v5MQpkmyp1u 7rqQwuA60E2H/C8OO0m6xW1MlYBP1d63umzvwExyN+WiRW2cwvds4jU02CfTW+GwTo knn0hJu4rw9KA== Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 402FB6559A for ; Thu, 31 Mar 2022 15:06:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="FFEwaCU4"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1648731978; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=njOd/QAKLUz3tpGCKgY0dHCom4OZou35qaNmd70Vtdk=; b=FFEwaCU4WJVGMOtLb2AMd0lUBMCFOcUUcWQ8xU0ByexyjI+4/lb6DnKr+LXbbv9T6dHgJ1 gQPmM1N7b0BICa5ejnNE7YT+1Bn1zEO+oiDsYXgKGSsOwAHTEMihqZyPNp+N9A1wXYajnU NXAFn6pYnfiH2bKF0P4bHgO4iq3AzBU= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-224-dXWnQGnTPF-H-DzLw0qT7g-1; Thu, 31 Mar 2022 09:06:16 -0400 X-MC-Unique: dXWnQGnTPF-H-DzLw0qT7g-1 Received: by mail-wm1-f72.google.com with SMTP id 2-20020a1c0202000000b0038c71e8c49cso1395786wmc.1 for ; Thu, 31 Mar 2022 06:06:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=njOd/QAKLUz3tpGCKgY0dHCom4OZou35qaNmd70Vtdk=; b=Qa/7+6PWjPTYhVjZyycx/JOCk/2/A9qPiR63toL0/Jd5YGSFuxPmWYtJZGCAMPtClS 5GmeB0E5W67Yd5v3DGcK5fb8eZgDIv+G1YCmUX94yw6YvTW7xNrCE+BBfvG3GdWzTivR ujBxt1cEwtz1h/l2K+mFgeAexWorHqRZPokSnjwLXoa9SrgRHKkwJ0jfw7VK5eb8nfS/ oKPZhK0aId5h1dh9B9WheJ9DIezbpBCWsHbiDNaOT8u/fMk2UYK/hzkspicCyZ23hKdK A/xpi/7HT0oSq8u49zM6abreJlvtGGeQC/NgiTTO2wQYadaOBu5NFxeMQLm7CDGaplGz z6ng== X-Gm-Message-State: AOAM5302SWGJWKRnnf+1hhGWwv3vc6o5PCkx6/8bK4Za0Qgx0GGRUqj0 0u/pGh8dIY+1mV60ER3XqUsjfOkBquHnYW3hZ2cLDGX7yswA3fy1HeRDFutPaPDc3jeJxTzJDUA zmIxLhneCPWLVbPAiMm7qZ53QHVM6n2ShkRQ8BNar/eTY+7WqQaIrtKYqdDHSEj4fB+EavOPDln lgh1wu5uws X-Received: by 2002:a1c:7519:0:b0:383:d29b:257 with SMTP id o25-20020a1c7519000000b00383d29b0257mr4743545wmc.172.1648731974791; Thu, 31 Mar 2022 06:06:14 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxvSJEbOWf+ahubDG9Um2KhXpDx0LM70OfsETycwuOk8kT0iMAyxb3cJPpKS3NarOOAJ5KCHw== X-Received: by 2002:a1c:7519:0:b0:383:d29b:257 with SMTP id o25-20020a1c7519000000b00383d29b0257mr4743522wmc.172.1648731974389; Thu, 31 Mar 2022 06:06:14 -0700 (PDT) Received: from p1.Home ([2001:8a0:6724:4500:a69c:e66f:828e:b340]) by smtp.gmail.com with ESMTPSA id 7-20020a05600c028700b0038cc9bfe6a4sm6883538wmk.37.2022.03.31.06.06.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Mar 2022 06:06:13 -0700 (PDT) To: libcamera-devel@lists.libcamera.org Date: Thu, 31 Mar 2022 14:06:09 +0100 Message-Id: <20220331130610.31806-1-ecurtin@redhat.com> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=ecurtin@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v5 1/2] cam: sdl_sink: Add SDL sink 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: , X-Patchwork-Original-From: Eric Curtin via libcamera-devel From: Eric Curtin Reply-To: Eric Curtin Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This adds more portability to existing cam sinks. You can pass a YUYV camera buffer for example and SDL will handle the pixel buffer conversion, although SDL does not support decompression for pixelformats like MJPEG. This allows cam reference implementation to display images on VMs, Mac M1, Raspberry Pi, etc. This also enables cam reference implementation, to run as a desktop application in wayland or x11. SDL also has support for Android and ChromeOS which I have not tested. Also tested on simpledrm raspberry pi 4 framebuffer successfully where existing kms sink did not work. Can also be used as kmsdrm sink. Only supports one camera stream at present. Signed-off-by: Eric Curtin --- src/cam/camera_session.cpp | 8 ++ src/cam/main.cpp | 5 + src/cam/main.h | 1 + src/cam/meson.build | 10 ++ src/cam/sdl_sink.cpp | 198 +++++++++++++++++++++++++++++++++++++ src/cam/sdl_sink.h | 46 +++++++++ 6 files changed, 268 insertions(+) create mode 100644 src/cam/sdl_sink.cpp create mode 100644 src/cam/sdl_sink.h diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp index 0428b538..30162dbd 100644 --- a/src/cam/camera_session.cpp +++ b/src/cam/camera_session.cpp @@ -19,6 +19,9 @@ #ifdef HAVE_KMS #include "kms_sink.h" #endif +#ifdef HAVE_SDL +#include "sdl_sink.h" +#endif #include "main.h" #include "stream_options.h" @@ -187,6 +190,11 @@ int CameraSession::start() sink_ = std::make_unique(options_[OptDisplay].toString()); #endif +#ifdef HAVE_SDL + if (options_.isSet(OptSDL)) + sink_ = std::make_unique(); +#endif + if (options_.isSet(OptFile)) { if (!options_[OptFile].toString().empty()) sink_ = std::make_unique(streamNames_, diff --git a/src/cam/main.cpp b/src/cam/main.cpp index c7f664b9..1d62a64a 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -137,6 +137,11 @@ int CamApp::parseOptions(int argc, char *argv[]) "Display viewfinder through DRM/KMS on specified connector", "display", ArgumentOptional, "connector", false, OptCamera); +#endif +#ifdef HAVE_SDL + parser.addOption(OptSDL, OptionNone, + "Display viewfinder through SDL", + "sdl", ArgumentNone, "", false, OptCamera); #endif parser.addOption(OptFile, OptionString, "Write captured frames to disk\n" diff --git a/src/cam/main.h b/src/cam/main.h index 62f7bbc9..2b285808 100644 --- a/src/cam/main.h +++ b/src/cam/main.h @@ -18,6 +18,7 @@ enum { OptListProperties = 'p', OptMonitor = 'm', OptStream = 's', + OptSDL = 'S', OptListControls = 256, OptStrictFormats = 257, OptMetadata = 258, diff --git a/src/cam/meson.build b/src/cam/meson.build index e8e2ae57..f2249296 100644 --- a/src/cam/meson.build +++ b/src/cam/meson.build @@ -32,11 +32,21 @@ cam_sources += files([ ]) endif +libsdl2 = dependency('SDL2', required : false) + +if libsdl2.found() + cam_cpp_args += ['-DHAVE_SDL'] + cam_sources += files([ + 'sdl_sink.cpp' + ]) +endif + cam = executable('cam', cam_sources, dependencies : [ libatomic, libcamera_public, libdrm, + libsdl2, libevent, ], cpp_args : cam_cpp_args, diff --git a/src/cam/sdl_sink.cpp b/src/cam/sdl_sink.cpp new file mode 100644 index 00000000..28e59cbb --- /dev/null +++ b/src/cam/sdl_sink.cpp @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * sdl_sink.cpp - SDL Sink + */ + +#include "sdl_sink.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "event_loop.h" +#include "image.h" + +using namespace libcamera; + +SDLSink::SDLSink() + : sdlWindow_(nullptr), sdlRenderer_(nullptr), sdlTexture_(nullptr), sdlRect_({}), sdlInit_(false) +{ +} + +SDLSink::~SDLSink() +{ + stop(); +} + +int SDLSink::configure(const libcamera::CameraConfiguration &cfg) +{ + int ret = FrameSink::configure(cfg); + if (ret < 0) + return ret; + + if (cfg.size() > 1) { + std::cerr << "SDL sink only supports one camera stream at present, streaming first camera stream" + << std::endl; + } else if (cfg.empty()) { + std::cerr << "Require at least one camera stream to process" << std::endl; + return -EINVAL; + } + + const libcamera::StreamConfiguration &sCfg = cfg.at(0); + sdlRect_.w = sCfg.size.width; + sdlRect_.h = sCfg.size.height; + switch (sCfg.pixelFormat) { + case libcamera::formats::YUYV: + pixelFormat_ = SDL_PIXELFORMAT_YUY2; + pitch_ = 4 * ((sdlRect_.w + 1) / 2); + break; + + /* From here down the fourcc values are identical between SDL, drm, libcamera */ + case libcamera::formats::NV21: + pixelFormat_ = SDL_PIXELFORMAT_NV21; + pitch_ = sdlRect_.w; + break; + case libcamera::formats::NV12: + pixelFormat_ = SDL_PIXELFORMAT_NV12; + pitch_ = sdlRect_.w; + break; + case libcamera::formats::YVU420: + pixelFormat_ = SDL_PIXELFORMAT_YV12; + pitch_ = sdlRect_.w; + break; + case libcamera::formats::YVYU: + pixelFormat_ = SDL_PIXELFORMAT_YVYU; + pitch_ = 4 * ((sdlRect_.w + 1) / 2); + break; + case libcamera::formats::UYVY: + pixelFormat_ = SDL_PIXELFORMAT_UYVY; + pitch_ = 4 * ((sdlRect_.w + 1) / 2); + break; + default: + std::cerr << sCfg.pixelFormat.toString() << " not present in libcamera <-> SDL map" + << std::endl; + return -EINVAL; + }; + + return 0; +} + +int SDLSink::start() +{ + int ret = SDL_Init(SDL_INIT_VIDEO); + if (ret) { + std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl; + return ret; + } + + sdlInit_ = true; + sdlWindow_ = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, sdlRect_.w, sdlRect_.h, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + if (!sdlWindow_) { + std::cerr << "Failed to create SDL window: " << SDL_GetError() << std::endl; + return -EINVAL; + } + + sdlRenderer_ = SDL_CreateRenderer(sdlWindow_, -1, 0); + if (!sdlRenderer_) { + std::cerr << "Failed to create SDL renderer: " << SDL_GetError() << std::endl; + return -EINVAL; + } + + ret = SDL_RenderSetLogicalSize(sdlRenderer_, sdlRect_.w, sdlRect_.h); + if (ret) { /* Not critical to set, don't return in this case, set for scaling purposes */ + std::cerr << "Failed to set SDL render logical size: " << SDL_GetError() << std::endl; + } + + sdlTexture_ = SDL_CreateTexture(sdlRenderer_, pixelFormat_, SDL_TEXTUREACCESS_STREAMING, sdlRect_.w, sdlRect_.h); + if (!sdlTexture_) { + std::cerr << "Failed to create SDL texture: " << SDL_GetError() << std::endl; + return -EINVAL; + } + + EventLoop::instance()->addEvent(-1, EventLoop::Read, std::bind(&SDLSink::processSDLEvents, this)); + + return 0; +} + +int SDLSink::stop() +{ + if (sdlTexture_) { + SDL_DestroyTexture(sdlTexture_); + sdlTexture_ = nullptr; + } + + if (sdlRenderer_) { + SDL_DestroyRenderer(sdlRenderer_); + sdlRenderer_ = nullptr; + } + + if (sdlWindow_) { + SDL_DestroyWindow(sdlWindow_); + sdlWindow_ = nullptr; + } + + if (sdlInit_) { + SDL_Quit(); + sdlInit_ = false; + } + + return FrameSink::stop(); +} + +void SDLSink::mapBuffer(FrameBuffer *buffer) +{ + std::unique_ptr image = Image::fromFrameBuffer(buffer, Image::MapMode::ReadOnly); + assert(image != nullptr); + + mappedBuffers_[buffer] = std::move(image); +} + +bool SDLSink::processRequest(Request *request) +{ + for (auto [stream, buffer] : request->buffers()) { + renderBuffer(buffer); + break; /* to be expanded to launch SDL window per buffer */ + } + + return true; +} + +/* + * Process SDL events, required for things like window resize and quit button + */ +void SDLSink::processSDLEvents() +{ + for (SDL_Event e; SDL_PollEvent(&e);) { + if (e.type == SDL_QUIT) { /* click close icon then quit */ + EventLoop::instance()->exit(0); + } + } +} + +void SDLSink::renderBuffer(FrameBuffer *buffer) +{ + Image *image = mappedBuffers_[buffer].get(); + + for (unsigned int i = 0; i < buffer->planes().size(); ++i) { + const FrameMetadata::Plane &meta = buffer->metadata().planes()[i]; + + Span data = image->data(i); + if (meta.bytesused > data.size()) + std::cerr << "payload size " << meta.bytesused + << " larger than plane size " << data.size() + << std::endl; + + SDL_UpdateTexture(sdlTexture_, &sdlRect_, data.data(), pitch_); + SDL_RenderClear(sdlRenderer_); + SDL_RenderCopy(sdlRenderer_, sdlTexture_, nullptr, nullptr); + SDL_RenderPresent(sdlRenderer_); + } +} diff --git a/src/cam/sdl_sink.h b/src/cam/sdl_sink.h new file mode 100644 index 00000000..c9b0ab8e --- /dev/null +++ b/src/cam/sdl_sink.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * sdl_sink.h - SDL Sink + */ + +#pragma once + +#include +#include +#include + +#include + +#include + +#include "frame_sink.h" + +class Image; + +class SDLSink : public FrameSink +{ +public: + SDLSink(); + ~SDLSink(); + + int configure(const libcamera::CameraConfiguration &cfg) override; + int start() override; + int stop() override; + void mapBuffer(libcamera::FrameBuffer *buffer) override; + + bool processRequest(libcamera::Request *request) override; + +private: + void renderBuffer(libcamera::FrameBuffer *buffer); + void processSDLEvents(); + + std::map> mappedBuffers_; + + SDL_Window *sdlWindow_; + SDL_Renderer *sdlRenderer_; + SDL_Texture *sdlTexture_; + SDL_Rect sdlRect_; + SDL_PixelFormatEnum pixelFormat_; + bool sdlInit_; + int pitch_; +}; From patchwork Thu Mar 31 13:06:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Curtin X-Patchwork-Id: 15589 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 EF220C3256 for ; Thu, 31 Mar 2022 13:06:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9F4F065638; Thu, 31 Mar 2022 15:06:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1648731983; bh=zMLvytW4CG/cfsO6Ief/dhTrEb4NA6qGozArrJJWFbM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=yGFg4MI/xabfROBUFI8xxf8DW4jRfxVQYJCQoEGsId7HYvpeJ9PRK3kMcSzQpbtWu h+ymTakKmxcdYfqGYIWQWxR3YgZ/M9nT6mmoynU2jHJRnbNE7oFl4Zy7U5tKHcDAhs eHXFseM4S0M6y9d5bOSTczupFCE3ZDAO4hoOXU7V93Uz4P/3jW5ZL1SVshUj2Y3+aU A3ahg9dd8HkYA3c2SjWnrXUcJlEjFB3eTT9t+dhsoTbmMQ1tbbQ2/A5k7bCqo9mtsj HiU6oKsuL06r35tVysNiCxC0uhaIa22tByc0pLLiSIV66Lihtad7fn43V7+j/6tBs6 xW4Ro8xzkknCw== Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3999A6559A for ; Thu, 31 Mar 2022 15:06:21 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Vq3JAZOa"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1648731980; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=95sP7rPZv50sCVWcj2ajITKn/riJ4Z8qvWBgJqLAoBY=; b=Vq3JAZOaKmMvQfB3fjZ2e0CWyfbdqFZ6xeoUP/YbJxhcA6/yIomyCowhIT0M/pHqGHcw54 +DWGdpKoeCyKgRyK5rSx0/J4Gq2R0+9wfknyef790XEKEKKzA2UTvEAslS85LzfFW9jSwu UHKsudUDaFmMM27xJFpm6CUJdHnmYP8= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-107-7GxvI2_GONS6_U4b9IS73Q-1; Thu, 31 Mar 2022 09:06:19 -0400 X-MC-Unique: 7GxvI2_GONS6_U4b9IS73Q-1 Received: by mail-wm1-f71.google.com with SMTP id 2-20020a1c0202000000b0038c71e8c49cso1395830wmc.1 for ; Thu, 31 Mar 2022 06:06:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=95sP7rPZv50sCVWcj2ajITKn/riJ4Z8qvWBgJqLAoBY=; b=MqbW9mNlq8ciPkJ5S52Wp9rbkVQKPmhhSp3YFx89JxhYArTzWvonMLT6yWm68yYk2W rnj2q6AnddxnRvy1Gvv03l4rS0362GK49eJQBsGFYMOcxRuMph+Slpp7VZIqr9eMqojG xkrS5YA+2b5PUcYUWh/rze643veAVXGPIMnEHSQhPbnUk25xwTYTTQ5YBQxHVgmUdqCu z4W5lKR1saL46RDtlF1HHZbR828a2WtwCXK7ZbngjzKxm1jITPui7RoIXzEKmyG5rvby WwfljC6/YbFdS/JY7wSSrXH1Z6ZMVmcpVYm8xegT1P8DOl7prSRm9fMNGQY25NiH+XVX DFpw== X-Gm-Message-State: AOAM530vYtVV4ViKzShal2jWsVuXwBtaDAroMZDCdxyVEXXWnwNwflxc lDY/39qEEXGs2gIXqSCowBHU/1XQSDKzogqc3FbAuPaM+L3npbiKqP2cRhTXpH7PQKxRaabZGbX 9gMCYsnK5ok9WNvdKUuWjMGcjwrAQPBZdb6siAiV3i3geV9mERNFjvVfI88pFOwdR0y5VNWKZhi EHg5rcDu7L X-Received: by 2002:adf:ee87:0:b0:203:de0b:b236 with SMTP id b7-20020adfee87000000b00203de0bb236mr4003112wro.337.1648731977269; Thu, 31 Mar 2022 06:06:17 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxnl6RQhKRhp2JWzdcdglIhwERUO8vK3XCOyBXvx+uznWBGrNftvKMPbnlyrrV4wAIsPfoSdA== X-Received: by 2002:adf:ee87:0:b0:203:de0b:b236 with SMTP id b7-20020adfee87000000b00203de0bb236mr4003090wro.337.1648731976969; Thu, 31 Mar 2022 06:06:16 -0700 (PDT) Received: from p1.Home ([2001:8a0:6724:4500:a69c:e66f:828e:b340]) by smtp.gmail.com with ESMTPSA id 7-20020a05600c028700b0038cc9bfe6a4sm6883538wmk.37.2022.03.31.06.06.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Mar 2022 06:06:16 -0700 (PDT) To: libcamera-devel@lists.libcamera.org Date: Thu, 31 Mar 2022 14:06:10 +0100 Message-Id: <20220331130610.31806-2-ecurtin@redhat.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220331130610.31806-1-ecurtin@redhat.com> References: <20220331130610.31806-1-ecurtin@redhat.com> MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=ecurtin@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v5 2/2] cam: event_loop: Add timed events to event loop 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: , X-Patchwork-Original-From: Eric Curtin via libcamera-devel From: Eric Curtin Reply-To: Eric Curtin Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If you add an event with EventLoop::Default, that event will be executed every 10ms or at a rate of 100fps. Used to handle resize of windows and quit events in SDL. Signed-off-by: Eric Curtin --- src/cam/event_loop.cpp | 10 +++++++++- src/cam/event_loop.h | 1 + src/cam/sdl_sink.cpp | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index e25784c0..7a5ed4da 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -75,7 +75,15 @@ void EventLoop::addEvent(int fd, EventType type, return; } - int ret = event_add(event->event_, nullptr); + struct timeval *tp = nullptr; + struct timeval tv; + if (events == EV_PERSIST) { /* EventType = Default */ + tp = &tv; + tv.tv_sec = 0; + tv.tv_usec = 10000; /* every 10 ms */ + } + + int ret = event_add(event->event_, tp); if (ret < 0) { std::cerr << "Failed to add event for fd " << fd << std::endl; return; diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index a4613eb2..8fd9bd20 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -20,6 +20,7 @@ class EventLoop { public: enum EventType { + Default = 0, /* the event can be triggered only by a timeout or by manual activation */ Read = 1, Write = 2, }; diff --git a/src/cam/sdl_sink.cpp b/src/cam/sdl_sink.cpp index 28e59cbb..97a550b5 100644 --- a/src/cam/sdl_sink.cpp +++ b/src/cam/sdl_sink.cpp @@ -117,7 +117,7 @@ int SDLSink::start() return -EINVAL; } - EventLoop::instance()->addEvent(-1, EventLoop::Read, std::bind(&SDLSink::processSDLEvents, this)); + EventLoop::instance()->addEvent(-1, EventLoop::Default, std::bind(&SDLSink::processSDLEvents, this)); return 0; }