diff options
Diffstat (limited to 'src/cam/sdl_sink.cpp')
-rw-r--r-- | src/cam/sdl_sink.cpp | 214 |
1 files changed, 0 insertions, 214 deletions
diff --git a/src/cam/sdl_sink.cpp b/src/cam/sdl_sink.cpp deleted file mode 100644 index ee177227..00000000 --- a/src/cam/sdl_sink.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2022, Ideas on Board Oy - * - * sdl_sink.h - SDL Sink - */ - -#include "sdl_sink.h" - -#include <assert.h> -#include <fcntl.h> -#include <iomanip> -#include <iostream> -#include <signal.h> -#include <sstream> -#include <string.h> -#include <unistd.h> - -#include <libcamera/camera.h> -#include <libcamera/formats.h> - -#include "event_loop.h" -#include "image.h" -#ifdef HAVE_LIBJPEG -#include "sdl_texture_mjpg.h" -#endif -#include "sdl_texture_yuv.h" - -using namespace libcamera; - -using namespace std::chrono_literals; - -SDLSink::SDLSink() - : window_(nullptr), renderer_(nullptr), rect_({}), - init_(false) -{ -} - -SDLSink::~SDLSink() -{ - stop(); -} - -int SDLSink::configure(const libcamera::CameraConfiguration &config) -{ - int ret = FrameSink::configure(config); - if (ret < 0) - return ret; - - if (config.size() > 1) { - std::cerr - << "SDL sink only supports one camera stream at present, streaming first camera stream" - << std::endl; - } else if (config.empty()) { - std::cerr << "Require at least one camera stream to process" - << std::endl; - return -EINVAL; - } - - const libcamera::StreamConfiguration &cfg = config.at(0); - rect_.w = cfg.size.width; - rect_.h = cfg.size.height; - - switch (cfg.pixelFormat) { -#ifdef HAVE_LIBJPEG - case libcamera::formats::MJPEG: - texture_ = std::make_unique<SDLTextureMJPG>(rect_); - break; -#endif -#if SDL_VERSION_ATLEAST(2, 0, 16) - case 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; - 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; - } - - init_ = true; - window_ = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, rect_.w, - rect_.h, - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); - if (!window_) { - std::cerr << "Failed to create SDL window: " << SDL_GetError() - << std::endl; - return -EINVAL; - } - - renderer_ = SDL_CreateRenderer(window_, -1, 0); - if (!renderer_) { - std::cerr << "Failed to create SDL renderer: " << SDL_GetError() - << std::endl; - return -EINVAL; - } - - /* - * Set for scaling purposes, not critical, don't return in case of - * error. - */ - ret = SDL_RenderSetLogicalSize(renderer_, rect_.w, rect_.h); - if (ret) - std::cerr << "Failed to set SDL render logical size: " - << SDL_GetError() << std::endl; - - ret = texture_->create(renderer_); - if (ret) { - return ret; - } - - /* \todo Make the event cancellable to support stop/start cycles. */ - EventLoop::instance()->addTimerEvent( - 10ms, std::bind(&SDLSink::processSDLEvents, this)); - - return 0; -} - -int SDLSink::stop() -{ - texture_.reset(); - - if (renderer_) { - SDL_DestroyRenderer(renderer_); - renderer_ = nullptr; - } - - if (window_) { - SDL_DestroyWindow(window_); - window_ = nullptr; - } - - if (init_) { - SDL_Quit(); - init_ = false; - } - - return FrameSink::stop(); -} - -void SDLSink::mapBuffer(FrameBuffer *buffer) -{ - std::unique_ptr<Image> 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(); - - std::vector<Span<const uint8_t>> planes; - unsigned int i = 0; - - planes.reserve(buffer->metadata().planes().size()); - - for (const FrameMetadata::Plane &meta : buffer->metadata().planes()) { - Span<uint8_t> data = image->data(i); - if (meta.bytesused > data.size()) - std::cerr << "payload size " << meta.bytesused - << " larger than plane size " << data.size() - << std::endl; - - planes.push_back(data); - i++; - } - - texture_->update(planes); - - SDL_RenderClear(renderer_); - SDL_RenderCopy(renderer_, texture_->get(), nullptr, nullptr); - SDL_RenderPresent(renderer_); -} |