From patchwork Wed Jul 20 13:03:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16702 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 1ED70BD1F1 for ; Wed, 20 Jul 2022 13:04:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 581CD63311; Wed, 20 Jul 2022 15:04:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1658322269; bh=sI4UlJbLvGIZhicBLEjHbefgyOesG1ClvDSiJl0g0kg=; 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=3vy9RYit1AJxAEK3XV9EOMTqaNG8+4pHdMD20YhA25fgSCAulOeBY6ZBvSjKhLIlu jFRMkeN7CxQivlNrwX/mQG/TZDydwPZJm2o41ofmB/M6HInbJRs6/hr0aI2DA48wpc 2kx5xvHIaNzGY7ypGAzdIxfV9QbL/5bRsfRsqaBgsjY74hYjXa6yKaswp4K992iGhs gM0f1gp7SFsmj9NOl3/ZD7cC+LGEGZE9eGeiRrGhOUjGT/wK0zpr37GwnKMUGdkudB smfz57vDdOQsHO3uEnLCUcKBKMGch8OUD+P7RncFnQCVXOjt3gRxGJ0cyX04oFMFcf KvSkGCePPWg7A== 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 C31A860489 for ; Wed, 20 Jul 2022 15:04:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="QjvvZb1Z"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 61F7488F; Wed, 20 Jul 2022 15:04:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1658322266; bh=sI4UlJbLvGIZhicBLEjHbefgyOesG1ClvDSiJl0g0kg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QjvvZb1ZpIy3mus6DmhG7hyteMK+fALcj7EHo2we7GgdMsCmizKKAKGp5GsxuTrFc y3H9c2MYDgU4GKWZ4jTAacfgyNeW3+ZVO4fm0RjYSgyZwvdJgMeF2PQ+Oy0jwNdWwn qwlEwM6fC61tInM7H5HtKt76Uy+JqQz7sLhEdcrs= To: libcamera-devel@lists.libcamera.org Date: Wed, 20 Jul 2022 16:03:47 +0300 Message-Id: <20220720130348.1337-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220720130348.1337-1-laurent.pinchart@ideasonboard.com> References: <20220720130348.1337-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 1/2] cam: sdl_sink: Use libjpeg over SDL2_image 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: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Eric Curtin We were using the libjpeg functionality of SDL2_image only, instead just use libjpeg directly to reduce our dependancy count, it is a more commonly available library. Signed-off-by: Eric Curtin Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- Changes since v4: - Move JpegErrorManager to sdl_texture_mjpg.cpp - Make JpegErrorManager inherit from jpeg_error_mgr - Define errorExit and outputMessage as member functions --- README.rst | 2 +- src/cam/meson.build | 8 ++--- src/cam/sdl_sink.cpp | 4 +-- src/cam/sdl_texture_mjpg.cpp | 70 ++++++++++++++++++++++++++++++++---- src/cam/sdl_texture_mjpg.h | 6 ++++ 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/README.rst b/README.rst index b9e72d81b90c..47b914f02260 100644 --- a/README.rst +++ b/README.rst @@ -92,8 +92,8 @@ for cam: [optional] tool: - libdrm-dev: Enables the KMS sink + - libjpeg-dev: Enables MJPEG on the SDL sink - libsdl2-dev: Enables the SDL sink - - libsdl2-image-dev: Supports MJPEG on the SDL sink for qcam: [optional] qtbase5-dev libqt5core5a libqt5gui5 libqt5widgets5 qttools5-dev-tools libtiff-dev diff --git a/src/cam/meson.build b/src/cam/meson.build index 5957ce140391..4dfa7b22aea9 100644 --- a/src/cam/meson.build +++ b/src/cam/meson.build @@ -24,8 +24,8 @@ cam_sources = files([ cam_cpp_args = [] libdrm = dependency('libdrm', required : false) +libjpeg = dependency('libjpeg', required : false) libsdl2 = dependency('SDL2', required : false) -libsdl2_image = dependency('SDL2_image', required : false) if libdrm.found() cam_cpp_args += [ '-DHAVE_KMS' ] @@ -43,8 +43,8 @@ if libsdl2.found() 'sdl_texture_yuyv.cpp' ]) - if libsdl2_image.found() - cam_cpp_args += ['-DHAVE_SDL_IMAGE'] + if libjpeg.found() + cam_cpp_args += ['-DHAVE_LIBJPEG'] cam_sources += files([ 'sdl_texture_mjpg.cpp' ]) @@ -57,8 +57,8 @@ cam = executable('cam', cam_sources, libcamera_public, libdrm, libevent, + libjpeg, libsdl2, - libsdl2_image, libyaml, ], cpp_args : cam_cpp_args, diff --git a/src/cam/sdl_sink.cpp b/src/cam/sdl_sink.cpp index f8e3e95dd392..19fdfd6dced5 100644 --- a/src/cam/sdl_sink.cpp +++ b/src/cam/sdl_sink.cpp @@ -21,7 +21,7 @@ #include "event_loop.h" #include "image.h" -#ifdef HAVE_SDL_IMAGE +#ifdef HAVE_LIBJPEG #include "sdl_texture_mjpg.h" #endif #include "sdl_texture_yuyv.h" @@ -62,7 +62,7 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config) rect_.h = cfg.size.height; switch (cfg.pixelFormat) { -#ifdef HAVE_SDL_IMAGE +#ifdef HAVE_LIBJPEG case libcamera::formats::MJPEG: texture_ = std::make_unique(rect_); break; diff --git a/src/cam/sdl_texture_mjpg.cpp b/src/cam/sdl_texture_mjpg.cpp index 69e99ad35219..7eddc00cd210 100644 --- a/src/cam/sdl_texture_mjpg.cpp +++ b/src/cam/sdl_texture_mjpg.cpp @@ -7,19 +7,77 @@ #include "sdl_texture_mjpg.h" -#include +#include +#include +#include + +#include using namespace libcamera; +struct JpegErrorManager : public jpeg_error_mgr { + JpegErrorManager() + { + jpeg_std_error(this); + error_exit = errorExit; + output_message = outputMessage; + } + + static void errorExit(j_common_ptr cinfo) + { + JpegErrorManager *self = + static_cast(cinfo->err); + longjmp(self->escape_, 1); + } + + static void outputMessage([[maybe_unused]] j_common_ptr cinfo) + { + } + + jmp_buf escape_; +}; + SDLTextureMJPG::SDLTextureMJPG(const SDL_Rect &rect) - : SDLTexture(rect, SDL_PIXELFORMAT_RGB24, 0) + : SDLTexture(rect, SDL_PIXELFORMAT_RGB24, rect.w * 3), + rgb_(std::make_unique(pitch_ * rect.h)) { } +int SDLTextureMJPG::decompress(const Span &data) +{ + struct jpeg_decompress_struct cinfo; + + JpegErrorManager errorManager; + if (setjmp(errorManager.escape_)) { + /* libjpeg found an error */ + jpeg_destroy_decompress(&cinfo); + std::cerr << "JPEG decompression error" << std::endl; + return -EINVAL; + } + + cinfo.err = &errorManager; + jpeg_create_decompress(&cinfo); + + jpeg_mem_src(&cinfo, data.data(), data.size()); + + jpeg_read_header(&cinfo, TRUE); + + jpeg_start_decompress(&cinfo); + + for (int i = 0; cinfo.output_scanline < cinfo.output_height; ++i) { + JSAMPROW rowptr = rgb_.get() + i * pitch_; + jpeg_read_scanlines(&cinfo, &rowptr, 1); + } + + jpeg_finish_decompress(&cinfo); + + jpeg_destroy_decompress(&cinfo); + + return 0; +} + void SDLTextureMJPG::update(const Span &data) { - SDL_RWops *bufferStream = SDL_RWFromMem(data.data(), data.size()); - SDL_Surface *frame = IMG_Load_RW(bufferStream, 0); - SDL_UpdateTexture(ptr_, nullptr, frame->pixels, frame->pitch); - SDL_FreeSurface(frame); + decompress(data); + SDL_UpdateTexture(ptr_, nullptr, rgb_.get(), pitch_); } diff --git a/src/cam/sdl_texture_mjpg.h b/src/cam/sdl_texture_mjpg.h index b103f801176d..328c45a913c5 100644 --- a/src/cam/sdl_texture_mjpg.h +++ b/src/cam/sdl_texture_mjpg.h @@ -13,5 +13,11 @@ class SDLTextureMJPG : public SDLTexture { public: SDLTextureMJPG(const SDL_Rect &rect); + void update(const libcamera::Span &data) override; + +private: + int decompress(const libcamera::Span &data); + + std::unique_ptr rgb_; }; From patchwork Wed Jul 20 13:03:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16703 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 13310BD1F1 for ; Wed, 20 Jul 2022 13:04:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CA71C63318; Wed, 20 Jul 2022 15:04:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1658322271; bh=dZwyTDWTzsRQ1vjmq/2l08kflkIlUmxOA188SbNDlRY=; 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=nMGzQ1+xZlGPA/9548eN5Y4pfaYrqSdStHq1qInpz5VW9CojQUlAue0RbQX1eyJsK 0bCoQeSV/kdC4+YZnAsYtoJiJiD/Y/xgM1YtrbvoN6MRdLU7dDcfhGk5pP1J3+axU2 G23B0YEL+QUBY+xjTU5037NRwtz/UmflN0n2q6NNklvhCWLovWms/VvMRDkrdUrLK1 5HHKVIuvvic2BVs2cq1j7x3/As1sqM52vp92ej+/7ktNEndera/G6L3QBj5kM9jjC6 Ya/w4A3z4aKckOMx2PaT2/JOjtC4Uw0sxcVCuu3CibAJOj+tCTb9eKFtUaeu/ayRsb dDh8YXKasgl3A== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 34BD060489 for ; Wed, 20 Jul 2022 15:04:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Rnr5FBNA"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BD450D02; Wed, 20 Jul 2022 15:04:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1658322267; bh=dZwyTDWTzsRQ1vjmq/2l08kflkIlUmxOA188SbNDlRY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Rnr5FBNA+GQz8nz68jValTMRErQNEWlB1EYmdlWSDm5RYz/+LEYxmyCYA185iteGn w0rJ/76rTm6FWRbFhyS1LXa/ws+iIyPOOHG52GE0UdzNqXyC3skwDhd6QXHAuhrSFy BoeO6Nlo7DOLD0mreJXEOE5tLUhOdGoavMWHNOJA= To: libcamera-devel@lists.libcamera.org Date: Wed, 20 Jul 2022 16:03:48 +0300 Message-Id: <20220720130348.1337-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220720130348.1337-1-laurent.pinchart@ideasonboard.com> References: <20220720130348.1337-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 2/2] cam: sdl_sink: Pass a Span to SDLTexture::update() 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: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The SDLTexture::update() function isn't meant to modify the data it receives. Make the Span type const to ensure this at compile time. While at it, pass the Span by value instead of reference, as a Span is only a pointer and size, which will fit in registers and will avoid pointer dereferences in the callee. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/cam/sdl_texture.h | 2 +- src/cam/sdl_texture_mjpg.cpp | 4 ++-- src/cam/sdl_texture_mjpg.h | 4 ++-- src/cam/sdl_texture_yuyv.cpp | 2 +- src/cam/sdl_texture_yuyv.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cam/sdl_texture.h b/src/cam/sdl_texture.h index 1d8b09288d50..f523fa5ebf51 100644 --- a/src/cam/sdl_texture.h +++ b/src/cam/sdl_texture.h @@ -17,7 +17,7 @@ public: SDLTexture(const SDL_Rect &rect, uint32_t pixelFormat, const int pitch); virtual ~SDLTexture(); int create(SDL_Renderer *renderer); - virtual void update(const libcamera::Span &data) = 0; + virtual void update(libcamera::Span data) = 0; SDL_Texture *get() const { return ptr_; } protected: diff --git a/src/cam/sdl_texture_mjpg.cpp b/src/cam/sdl_texture_mjpg.cpp index 7eddc00cd210..7542efd75d96 100644 --- a/src/cam/sdl_texture_mjpg.cpp +++ b/src/cam/sdl_texture_mjpg.cpp @@ -43,7 +43,7 @@ SDLTextureMJPG::SDLTextureMJPG(const SDL_Rect &rect) { } -int SDLTextureMJPG::decompress(const Span &data) +int SDLTextureMJPG::decompress(Span data) { struct jpeg_decompress_struct cinfo; @@ -76,7 +76,7 @@ int SDLTextureMJPG::decompress(const Span &data) return 0; } -void SDLTextureMJPG::update(const Span &data) +void SDLTextureMJPG::update(Span data) { decompress(data); SDL_UpdateTexture(ptr_, nullptr, rgb_.get(), pitch_); diff --git a/src/cam/sdl_texture_mjpg.h b/src/cam/sdl_texture_mjpg.h index 328c45a913c5..5141ed73bf70 100644 --- a/src/cam/sdl_texture_mjpg.h +++ b/src/cam/sdl_texture_mjpg.h @@ -14,10 +14,10 @@ class SDLTextureMJPG : public SDLTexture public: SDLTextureMJPG(const SDL_Rect &rect); - void update(const libcamera::Span &data) override; + void update(libcamera::Span data) override; private: - int decompress(const libcamera::Span &data); + int decompress(libcamera::Span data); std::unique_ptr rgb_; }; diff --git a/src/cam/sdl_texture_yuyv.cpp b/src/cam/sdl_texture_yuyv.cpp index cc161b2cfa79..637c0900edff 100644 --- a/src/cam/sdl_texture_yuyv.cpp +++ b/src/cam/sdl_texture_yuyv.cpp @@ -14,7 +14,7 @@ SDLTextureYUYV::SDLTextureYUYV(const SDL_Rect &rect) { } -void SDLTextureYUYV::update(const Span &data) +void SDLTextureYUYV::update(Span data) { SDL_UpdateTexture(ptr_, &rect_, data.data(), pitch_); } diff --git a/src/cam/sdl_texture_yuyv.h b/src/cam/sdl_texture_yuyv.h index 9f7c72f09db2..529a72d6a40e 100644 --- a/src/cam/sdl_texture_yuyv.h +++ b/src/cam/sdl_texture_yuyv.h @@ -13,5 +13,5 @@ class SDLTextureYUYV : public SDLTexture { public: SDLTextureYUYV(const SDL_Rect &rect); - void update(const libcamera::Span &data) override; + void update(libcamera::Span data) override; };