diff options
Diffstat (limited to 'src/apps/cam')
-rw-r--r-- | src/apps/cam/camera_session.cpp | 110 | ||||
-rw-r--r-- | src/apps/cam/camera_session.h | 2 | ||||
-rw-r--r-- | src/apps/cam/capture_script.cpp | 42 | ||||
-rw-r--r-- | src/apps/cam/capture_script.h | 2 | ||||
-rw-r--r-- | src/apps/cam/drm.cpp | 2 | ||||
-rw-r--r-- | src/apps/cam/drm.h | 2 | ||||
-rw-r--r-- | src/apps/cam/file_sink.cpp | 66 | ||||
-rw-r--r-- | src/apps/cam/file_sink.h | 21 | ||||
-rw-r--r-- | src/apps/cam/frame_sink.cpp | 2 | ||||
-rw-r--r-- | src/apps/cam/frame_sink.h | 2 | ||||
-rw-r--r-- | src/apps/cam/kms_sink.cpp | 2 | ||||
-rw-r--r-- | src/apps/cam/kms_sink.h | 2 | ||||
-rw-r--r-- | src/apps/cam/main.cpp | 9 | ||||
-rw-r--r-- | src/apps/cam/main.h | 2 | ||||
-rw-r--r-- | src/apps/cam/meson.build | 1 | ||||
-rw-r--r-- | src/apps/cam/sdl_sink.cpp | 63 | ||||
-rw-r--r-- | src/apps/cam/sdl_sink.h | 2 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture.cpp | 2 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture.h | 6 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture_1plane.cpp | 17 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture_1plane.h | 18 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture_mjpg.cpp | 4 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture_mjpg.h | 4 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture_yuv.cpp | 16 | ||||
-rw-r--r-- | src/apps/cam/sdl_texture_yuv.h | 11 |
25 files changed, 280 insertions, 130 deletions
diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 8447f932..f63fcb22 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -2,12 +2,15 @@ /* * Copyright (C) 2019, Google Inc. * - * camera_session.cpp - Camera capture session + * Camera capture session */ +#include "camera_session.h" + #include <iomanip> #include <iostream> #include <limits.h> +#include <optional> #include <sstream> #include <libcamera/control_ids.h> @@ -16,7 +19,6 @@ #include "../common/event_loop.h" #include "../common/stream_options.h" -#include "camera_session.h" #include "capture_script.h" #include "file_sink.h" #ifdef HAVE_KMS @@ -39,9 +41,14 @@ CameraSession::CameraSession(CameraManager *cm, { char *endptr; unsigned long index = strtoul(cameraId.c_str(), &endptr, 10); - if (*endptr == '\0' && index > 0 && index <= cm->cameras().size()) - camera_ = cm->cameras()[index - 1]; - else + + if (*endptr == '\0' && index > 0) { + auto cameras = cm->cameras(); + if (index <= cameras.size()) + camera_ = cameras[index - 1]; + } + + if (!camera_) camera_ = cm->get(cameraId); if (!camera_) { @@ -55,11 +62,32 @@ CameraSession::CameraSession(CameraManager *cm, return; } - std::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]); + std::vector<StreamRole> roles = + StreamKeyValueParser::roles(options_[OptStream]); + std::vector<std::vector<StreamRole>> tryRoles; + if (!roles.empty()) { + /* + * If the roles are explicitly specified then there's no need + * to try other roles + */ + tryRoles.push_back(roles); + } else { + tryRoles.push_back({ StreamRole::Viewfinder }); + tryRoles.push_back({ StreamRole::Raw }); + } + + std::unique_ptr<CameraConfiguration> config; + bool valid = false; + for (std::vector<StreamRole> &rolesIt : tryRoles) { + config = camera_->generateConfiguration(rolesIt); + if (config && config->size() == rolesIt.size()) { + roles = rolesIt; + valid = true; + break; + } + } - std::unique_ptr<CameraConfiguration> config = - camera_->generateConfiguration(roles); - if (!config || config->size() != roles.size()) { + if (!valid) { std::cerr << "Failed to get default stream configuration" << std::endl; return; @@ -154,8 +182,51 @@ CameraSession::~CameraSession() void CameraSession::listControls() const { for (const auto &[id, info] : camera_->controls()) { - std::cout << "Control: " << id->name() << ": " - << info.toString() << std::endl; + std::stringstream io; + io << "[" + << (id->isInput() ? "in" : " ") + << (id->isOutput() ? "out" : " ") + << "] "; + + if (info.values().empty()) { + std::cout << "Control: " << io.str() + << id->vendor() << "::" << id->name() << ": " + << info.toString() << std::endl; + } else { + std::cout << "Control: " << io.str() + << id->vendor() << "::" << id->name() << ":" + << std::endl; + + std::optional<int32_t> def; + if (!info.def().isNone()) + def = info.def().get<int32_t>(); + + for (const auto &value : info.values()) { + int32_t val = value.get<int32_t>(); + const auto &it = id->enumerators().find(val); + + std::cout << " - "; + if (it == id->enumerators().end()) + std::cout << "UNKNOWN"; + else + std::cout << it->second; + + std::cout << " (" << val << ")" + << (val == def ? " [default]" : "") + << std::endl; + } + } + + if (id->isArray()) { + std::size_t size = id->size(); + + std::cout << " Size: "; + if (size == std::numeric_limits<std::size_t>::max()) + std::cout << "n"; + else + std::cout << std::to_string(size); + std::cout << std::endl; + } } } @@ -225,11 +296,16 @@ int CameraSession::start() #endif if (options_.isSet(OptFile)) { - if (!options_[OptFile].toString().empty()) - sink_ = std::make_unique<FileSink>(camera_.get(), streamNames_, - options_[OptFile]); - else - sink_ = std::make_unique<FileSink>(camera_.get(), streamNames_); + std::unique_ptr<FileSink> sink = + std::make_unique<FileSink>(camera_.get(), streamNames_); + + if (!options_[OptFile].toString().empty()) { + ret = sink->setFilePattern(options_[OptFile]); + if (ret) + return ret; + } + + sink_ = std::move(sink); } if (sink_) { @@ -377,7 +453,7 @@ void CameraSession::requestComplete(Request *request) * Defer processing of the completed request to the event loop, to avoid * blocking the camera manager thread. */ - EventLoop::instance()->callLater([=]() { processRequest(request); }); + EventLoop::instance()->callLater([this, request]() { processRequest(request); }); } void CameraSession::processRequest(Request *request) diff --git a/src/apps/cam/camera_session.h b/src/apps/cam/camera_session.h index 0bab519f..4442fd9b 100644 --- a/src/apps/cam/camera_session.h +++ b/src/apps/cam/camera_session.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * camera_session.h - Camera capture session + * Camera capture session */ #pragma once diff --git a/src/apps/cam/capture_script.cpp b/src/apps/cam/capture_script.cpp index 1215713f..fdf82efc 100644 --- a/src/apps/cam/capture_script.cpp +++ b/src/apps/cam/capture_script.cpp @@ -2,12 +2,13 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * capture_script.cpp - Capture session configuration script + * Capture session configuration script */ #include "capture_script.h" #include <iostream> +#include <memory> #include <stdio.h> #include <stdlib.h> @@ -521,45 +522,22 @@ ControlValue CaptureScript::parseArrayControl(const ControlId *id, case ControlTypeNone: break; case ControlTypeBool: { - /* - * This is unpleasant, but we cannot use an std::vector<> as its - * boolean type overload does not allow to access the raw data, - * as boolean values are stored in a bitmask for efficiency. - * - * As we need a contiguous memory region to wrap in a Span<>, - * use an array instead but be strict about not overflowing it - * by limiting the number of controls we can store. - * - * Be loud but do not fail, as the issue would present at - * runtime and it's not fatal. - */ - static constexpr unsigned int kMaxNumBooleanControls = 1024; - std::array<bool, kMaxNumBooleanControls> values; - unsigned int idx = 0; + auto values = std::make_unique<bool[]>(repr.size()); - for (const std::string &s : repr) { - bool val; + for (std::size_t i = 0; i < repr.size(); i++) { + const auto &s = repr[i]; if (s == "true") { - val = true; + values[i] = true; } else if (s == "false") { - val = false; + values[i] = false; } else { unpackFailure(id, s); return value; } - - if (idx == kMaxNumBooleanControls) { - std::cerr << "Cannot parse more than " - << kMaxNumBooleanControls - << " boolean controls" << std::endl; - break; - } - - values[idx++] = val; } - value = Span<bool>(values.data(), idx); + value = Span<bool>(values.get(), repr.size()); break; } case ControlTypeByte: { @@ -600,10 +578,6 @@ ControlValue CaptureScript::parseArrayControl(const ControlId *id, value = Span<const float>(values.data(), values.size()); break; } - case ControlTypeString: { - value = Span<const std::string>(repr.data(), repr.size()); - break; - } default: std::cerr << "Unsupported control type" << std::endl; break; diff --git a/src/apps/cam/capture_script.h b/src/apps/cam/capture_script.h index 40042c03..294b9203 100644 --- a/src/apps/cam/capture_script.h +++ b/src/apps/cam/capture_script.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * capture_script.h - Capture session configuration script + * Capture session configuration script */ #pragma once diff --git a/src/apps/cam/drm.cpp b/src/apps/cam/drm.cpp index 8779a713..47bbb6b0 100644 --- a/src/apps/cam/drm.cpp +++ b/src/apps/cam/drm.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * drm.cpp - DRM/KMS Helpers + * DRM/KMS Helpers */ #include "drm.h" diff --git a/src/apps/cam/drm.h b/src/apps/cam/drm.h index ebaea04d..1ba83b6e 100644 --- a/src/apps/cam/drm.h +++ b/src/apps/cam/drm.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * drm.h - DRM/KMS Helpers + * DRM/KMS Helpers */ #pragma once diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp index 906b50e6..65794a2f 100644 --- a/src/apps/cam/file_sink.cpp +++ b/src/apps/cam/file_sink.cpp @@ -2,9 +2,12 @@ /* * Copyright (C) 2019, Google Inc. * - * file_sink.cpp - File Sink + * File Sink */ +#include "file_sink.h" + +#include <array> #include <assert.h> #include <fcntl.h> #include <iomanip> @@ -12,6 +15,7 @@ #include <sstream> #include <string.h> #include <unistd.h> +#include <utility> #include <libcamera/camera.h> @@ -19,18 +23,16 @@ #include "../common/image.h" #include "../common/ppm_writer.h" -#include "file_sink.h" - using namespace libcamera; FileSink::FileSink([[maybe_unused]] const libcamera::Camera *camera, - const std::map<const libcamera::Stream *, std::string> &streamNames, - const std::string &pattern) + const std::map<const libcamera::Stream *, std::string> &streamNames) : #ifdef HAVE_TIFF camera_(camera), #endif - streamNames_(streamNames), pattern_(pattern) + pattern_(kDefaultFilePattern), fileType_(FileType::Binary), + streamNames_(streamNames) { } @@ -38,6 +40,41 @@ FileSink::~FileSink() { } +int FileSink::setFilePattern(const std::string &pattern) +{ + static const std::array<std::pair<std::string, FileType>, 2> types{{ + { ".dng", FileType::Dng }, + { ".ppm", FileType::Ppm }, + }}; + + pattern_ = pattern; + + if (pattern_.empty() || pattern_.back() == '/') + pattern_ += kDefaultFilePattern; + + fileType_ = FileType::Binary; + + for (const auto &type : types) { + if (pattern_.size() < type.first.size()) + continue; + + if (pattern_.find(type.first, pattern_.size() - type.first.size()) != + std::string::npos) { + fileType_ = type.second; + break; + } + } + +#ifndef HAVE_TIFF + if (fileType_ == FileType::Dng) { + std::cerr << "DNG support not available" << std::endl; + return -EINVAL; + } +#endif /* HAVE_TIFF */ + + return 0; +} + int FileSink::configure(const libcamera::CameraConfiguration &config) { int ret = FrameSink::configure(config); @@ -67,21 +104,10 @@ bool FileSink::processRequest(Request *request) void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer, [[maybe_unused]] const ControlList &metadata) { - std::string filename; + std::string filename = pattern_; size_t pos; int fd, ret = 0; - if (!pattern_.empty()) - filename = pattern_; - -#ifdef HAVE_TIFF - bool dng = filename.find(".dng", filename.size() - 4) != std::string::npos; -#endif /* HAVE_TIFF */ - bool ppm = filename.find(".ppm", filename.size() - 4) != std::string::npos; - - if (filename.empty() || filename.back() == '/') - filename += "frame-#.bin"; - pos = filename.find_first_of('#'); if (pos != std::string::npos) { std::stringstream ss; @@ -93,7 +119,7 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer, Image *image = mappedBuffers_[buffer].get(); #ifdef HAVE_TIFF - if (dng) { + if (fileType_ == FileType::Dng) { ret = DNGWriter::write(filename.c_str(), camera_, stream->configuration(), metadata, buffer, image->data(0).data()); @@ -104,7 +130,7 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer, return; } #endif /* HAVE_TIFF */ - if (ppm) { + if (fileType_ == FileType::Ppm) { ret = PPMWriter::write(filename.c_str(), stream->configuration(), image->data(0)); if (ret < 0) diff --git a/src/apps/cam/file_sink.h b/src/apps/cam/file_sink.h index 300edf8d..26cd61b3 100644 --- a/src/apps/cam/file_sink.h +++ b/src/apps/cam/file_sink.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * file_sink.h - File Sink + * File Sink */ #pragma once @@ -11,6 +11,7 @@ #include <memory> #include <string> +#include <libcamera/controls.h> #include <libcamera/stream.h> #include "frame_sink.h" @@ -21,10 +22,11 @@ class FileSink : public FrameSink { public: FileSink(const libcamera::Camera *camera, - const std::map<const libcamera::Stream *, std::string> &streamNames, - const std::string &pattern = ""); + const std::map<const libcamera::Stream *, std::string> &streamNames); ~FileSink(); + int setFilePattern(const std::string &pattern); + int configure(const libcamera::CameraConfiguration &config) override; void mapBuffer(libcamera::FrameBuffer *buffer) override; @@ -32,6 +34,14 @@ public: bool processRequest(libcamera::Request *request) override; private: + static constexpr const char *kDefaultFilePattern = "frame-#.bin"; + + enum class FileType { + Binary, + Dng, + Ppm, + }; + void writeBuffer(const libcamera::Stream *stream, libcamera::FrameBuffer *buffer, const libcamera::ControlList &metadata); @@ -39,7 +49,10 @@ private: #ifdef HAVE_TIFF const libcamera::Camera *camera_; #endif - std::map<const libcamera::Stream *, std::string> streamNames_; + std::string pattern_; + FileType fileType_; + + std::map<const libcamera::Stream *, std::string> streamNames_; std::map<libcamera::FrameBuffer *, std::unique_ptr<Image>> mappedBuffers_; }; diff --git a/src/apps/cam/frame_sink.cpp b/src/apps/cam/frame_sink.cpp index af21d575..68d6f2c1 100644 --- a/src/apps/cam/frame_sink.cpp +++ b/src/apps/cam/frame_sink.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * frame_sink.cpp - Base Frame Sink Class + * Base Frame Sink Class */ #include "frame_sink.h" diff --git a/src/apps/cam/frame_sink.h b/src/apps/cam/frame_sink.h index ca4347cb..11105c6c 100644 --- a/src/apps/cam/frame_sink.h +++ b/src/apps/cam/frame_sink.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * frame_sink.h - Base Frame Sink Class + * Base Frame Sink Class */ #pragma once diff --git a/src/apps/cam/kms_sink.cpp b/src/apps/cam/kms_sink.cpp index 6991c3fa..672c985a 100644 --- a/src/apps/cam/kms_sink.cpp +++ b/src/apps/cam/kms_sink.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * kms_sink.cpp - KMS Sink + * KMS Sink */ #include "kms_sink.h" diff --git a/src/apps/cam/kms_sink.h b/src/apps/cam/kms_sink.h index e2c618a1..4b7b4c26 100644 --- a/src/apps/cam/kms_sink.h +++ b/src/apps/cam/kms_sink.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * kms_sink.h - KMS Sink + * KMS Sink */ #pragma once diff --git a/src/apps/cam/main.cpp b/src/apps/cam/main.cpp index 1aabee01..fa266eca 100644 --- a/src/apps/cam/main.cpp +++ b/src/apps/cam/main.cpp @@ -2,9 +2,11 @@ /* * Copyright (C) 2019, Google Inc. * - * main.cpp - cam - The libcamera swiss army knife + * cam - The libcamera swiss army knife */ +#include "main.h" + #include <atomic> #include <iomanip> #include <iostream> @@ -19,7 +21,6 @@ #include "../common/stream_options.h" #include "camera_session.h" -#include "main.h" using namespace libcamera; @@ -344,12 +345,16 @@ std::string CamApp::cameraName(const Camera *camera) return name; } +namespace { + void signalHandler([[maybe_unused]] int signal) { std::cout << "Exiting" << std::endl; CamApp::instance()->quit(); } +} /* namespace */ + int main(int argc, char **argv) { CamApp app; diff --git a/src/apps/cam/main.h b/src/apps/cam/main.h index 4aa959b3..64e6a20e 100644 --- a/src/apps/cam/main.h +++ b/src/apps/cam/main.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * main.h - Cam application + * Cam application */ #pragma once diff --git a/src/apps/cam/meson.build b/src/apps/cam/meson.build index c70ca3cd..2833c86e 100644 --- a/src/apps/cam/meson.build +++ b/src/apps/cam/meson.build @@ -34,6 +34,7 @@ if libsdl2.found() cam_sources += files([ 'sdl_sink.cpp', 'sdl_texture.cpp', + 'sdl_texture_1plane.cpp', 'sdl_texture_yuv.cpp', ]) diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp index a2f4abc1..30cfdf0a 100644 --- a/src/apps/cam/sdl_sink.cpp +++ b/src/apps/cam/sdl_sink.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_sink.h - SDL Sink + * SDL Sink */ #include "sdl_sink.h" @@ -11,6 +11,7 @@ #include <fcntl.h> #include <iomanip> #include <iostream> +#include <optional> #include <signal.h> #include <sstream> #include <string.h> @@ -22,6 +23,7 @@ #include "../common/event_loop.h" #include "../common/image.h" +#include "sdl_texture_1plane.h" #ifdef HAVE_LIBJPEG #include "sdl_texture_mjpg.h" #endif @@ -31,6 +33,46 @@ using namespace libcamera; using namespace std::chrono_literals; +namespace { + +std::optional<SDL_PixelFormatEnum> singlePlaneFormatToSDL(const libcamera::PixelFormat &f) +{ + switch (f) { + case libcamera::formats::RGB888: + return SDL_PIXELFORMAT_BGR24; + case libcamera::formats::BGR888: + return SDL_PIXELFORMAT_RGB24; + case libcamera::formats::RGBA8888: + return SDL_PIXELFORMAT_ABGR32; + case libcamera::formats::ARGB8888: + return SDL_PIXELFORMAT_BGRA32; + case libcamera::formats::BGRA8888: + return SDL_PIXELFORMAT_ARGB32; + case libcamera::formats::ABGR8888: + return SDL_PIXELFORMAT_RGBA32; +#if SDL_VERSION_ATLEAST(2, 29, 1) + case libcamera::formats::RGBX8888: + return SDL_PIXELFORMAT_XBGR32; + case libcamera::formats::XRGB8888: + return SDL_PIXELFORMAT_BGRX32; + case libcamera::formats::BGRX8888: + return SDL_PIXELFORMAT_XRGB32; + case libcamera::formats::XBGR8888: + return SDL_PIXELFORMAT_RGBX32; +#endif + case libcamera::formats::YUYV: + return SDL_PIXELFORMAT_YUY2; + case libcamera::formats::UYVY: + return SDL_PIXELFORMAT_UYVY; + case libcamera::formats::YVYU: + return SDL_PIXELFORMAT_YVYU; + } + + return {}; +} + +} /* namespace */ + SDLSink::SDLSink() : window_(nullptr), renderer_(nullptr), rect_({}), init_(false) @@ -62,25 +104,20 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config) rect_.w = cfg.size.width; rect_.h = cfg.size.height; - switch (cfg.pixelFormat) { + if (auto sdlFormat = singlePlaneFormatToSDL(cfg.pixelFormat)) + texture_ = std::make_unique<SDLTexture1Plane>(rect_, *sdlFormat, cfg.stride); #ifdef HAVE_LIBJPEG - case libcamera::formats::MJPEG: + else if (cfg.pixelFormat == libcamera::formats::MJPEG) texture_ = std::make_unique<SDLTextureMJPG>(rect_); - break; #endif #if SDL_VERSION_ATLEAST(2, 0, 16) - case libcamera::formats::NV12: + else if (cfg.pixelFormat == libcamera::formats::NV12) texture_ = std::make_unique<SDLTextureNV12>(rect_, cfg.stride); - break; #endif - case libcamera::formats::YUYV: - texture_ = std::make_unique<SDLTextureYUYV>(rect_, cfg.stride); - break; - default: - std::cerr << "Unsupported pixel format " - << cfg.pixelFormat.toString() << std::endl; + else { + std::cerr << "Unsupported pixel format " << cfg.pixelFormat << std::endl; return -EINVAL; - }; + } return 0; } diff --git a/src/apps/cam/sdl_sink.h b/src/apps/cam/sdl_sink.h index 6c19c663..18ec7fbe 100644 --- a/src/apps/cam/sdl_sink.h +++ b/src/apps/cam/sdl_sink.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_sink.h - SDL Sink + * SDL Sink */ #pragma once diff --git a/src/apps/cam/sdl_texture.cpp b/src/apps/cam/sdl_texture.cpp index e9040bc5..e52c4a3a 100644 --- a/src/apps/cam/sdl_texture.cpp +++ b/src/apps/cam/sdl_texture.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_texture.cpp - SDL Texture + * SDL Texture */ #include "sdl_texture.h" diff --git a/src/apps/cam/sdl_texture.h b/src/apps/cam/sdl_texture.h index 3993dd46..39e1c7b3 100644 --- a/src/apps/cam/sdl_texture.h +++ b/src/apps/cam/sdl_texture.h @@ -2,12 +2,12 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_texture.h - SDL Texture + * SDL Texture */ #pragma once -#include <vector> +#include <libcamera/base/span.h> #include <SDL2/SDL.h> @@ -19,7 +19,7 @@ public: SDLTexture(const SDL_Rect &rect, uint32_t pixelFormat, const int stride); virtual ~SDLTexture(); int create(SDL_Renderer *renderer); - virtual void update(const std::vector<libcamera::Span<const uint8_t>> &data) = 0; + virtual void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) = 0; SDL_Texture *get() const { return ptr_; } protected: diff --git a/src/apps/cam/sdl_texture_1plane.cpp b/src/apps/cam/sdl_texture_1plane.cpp new file mode 100644 index 00000000..b97015bc --- /dev/null +++ b/src/apps/cam/sdl_texture_1plane.cpp @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2025, Ideas on Board Oy + * + * SDL single plane textures + */ + +#include "sdl_texture_1plane.h" + +#include <assert.h> + +void SDLTexture1Plane::update(libcamera::Span<const libcamera::Span<const uint8_t>> data) +{ + assert(data.size() == 1); + assert(data[0].size_bytes() == std::size_t(rect_.h) * std::size_t(stride_)); + SDL_UpdateTexture(ptr_, nullptr, data[0].data(), stride_); +} diff --git a/src/apps/cam/sdl_texture_1plane.h b/src/apps/cam/sdl_texture_1plane.h new file mode 100644 index 00000000..795e1fa4 --- /dev/null +++ b/src/apps/cam/sdl_texture_1plane.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2025, Ideas on Board Oy + * + * SDL single plane textures + */ + +#pragma once + +#include "sdl_texture.h" + +class SDLTexture1Plane final : public SDLTexture +{ +public: + using SDLTexture::SDLTexture; + + void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) override; +}; diff --git a/src/apps/cam/sdl_texture_mjpg.cpp b/src/apps/cam/sdl_texture_mjpg.cpp index da958e03..ca49a114 100644 --- a/src/apps/cam/sdl_texture_mjpg.cpp +++ b/src/apps/cam/sdl_texture_mjpg.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_texture_mjpg.cpp - SDL Texture MJPG + * SDL Texture MJPG */ #include "sdl_texture_mjpg.h" @@ -76,7 +76,7 @@ int SDLTextureMJPG::decompress(Span<const uint8_t> data) return 0; } -void SDLTextureMJPG::update(const std::vector<libcamera::Span<const uint8_t>> &data) +void SDLTextureMJPG::update(libcamera::Span<const libcamera::Span<const uint8_t>> data) { decompress(data[0]); SDL_UpdateTexture(ptr_, nullptr, rgb_.get(), stride_); diff --git a/src/apps/cam/sdl_texture_mjpg.h b/src/apps/cam/sdl_texture_mjpg.h index 814ca79a..be8a55fe 100644 --- a/src/apps/cam/sdl_texture_mjpg.h +++ b/src/apps/cam/sdl_texture_mjpg.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_texture_mjpg.h - SDL Texture MJPG + * SDL Texture MJPG */ #pragma once @@ -14,7 +14,7 @@ class SDLTextureMJPG : public SDLTexture public: SDLTextureMJPG(const SDL_Rect &rect); - void update(const std::vector<libcamera::Span<const uint8_t>> &data) override; + void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) override; private: int decompress(libcamera::Span<const uint8_t> data); diff --git a/src/apps/cam/sdl_texture_yuv.cpp b/src/apps/cam/sdl_texture_yuv.cpp index b29c3b93..bed297d2 100644 --- a/src/apps/cam/sdl_texture_yuv.cpp +++ b/src/apps/cam/sdl_texture_yuv.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_texture_yuv.cpp - SDL YUV Textures + * SDL YUV Textures */ #include "sdl_texture_yuv.h" @@ -15,19 +15,9 @@ SDLTextureNV12::SDLTextureNV12(const SDL_Rect &rect, unsigned int stride) { } -void SDLTextureNV12::update(const std::vector<libcamera::Span<const uint8_t>> &data) +void SDLTextureNV12::update(libcamera::Span<const libcamera::Span<const uint8_t>> data) { - SDL_UpdateNVTexture(ptr_, &rect_, data[0].data(), stride_, + SDL_UpdateNVTexture(ptr_, nullptr, data[0].data(), stride_, data[1].data(), stride_); } #endif - -SDLTextureYUYV::SDLTextureYUYV(const SDL_Rect &rect, unsigned int stride) - : SDLTexture(rect, SDL_PIXELFORMAT_YUY2, stride) -{ -} - -void SDLTextureYUYV::update(const std::vector<libcamera::Span<const uint8_t>> &data) -{ - SDL_UpdateTexture(ptr_, &rect_, data[0].data(), stride_); -} diff --git a/src/apps/cam/sdl_texture_yuv.h b/src/apps/cam/sdl_texture_yuv.h index 310e4e50..c271f901 100644 --- a/src/apps/cam/sdl_texture_yuv.h +++ b/src/apps/cam/sdl_texture_yuv.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2022, Ideas on Board Oy * - * sdl_texture_yuv.h - SDL YUV Textures + * SDL YUV Textures */ #pragma once @@ -14,13 +14,6 @@ class SDLTextureNV12 : public SDLTexture { public: SDLTextureNV12(const SDL_Rect &rect, unsigned int stride); - void update(const std::vector<libcamera::Span<const uint8_t>> &data) override; + void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) override; }; #endif - -class SDLTextureYUYV : public SDLTexture -{ -public: - SDLTextureYUYV(const SDL_Rect &rect, unsigned int stride); - void update(const std::vector<libcamera::Span<const uint8_t>> &data) override; -}; |