[{"id":24211,"web_url":"https://patchwork.libcamera.org/comment/24211/","msgid":"<20220728081157.kkwjsmyk2zmvzunl@uno.localdomain>","date":"2022-07-28T08:11:57","subject":"Re: [libcamera-devel] [PATCH v5 1/2] cam: sdl_sink: Use libjpeg\n\tover SDL2_image","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Not knowing that much about libjpeg, I can only comment that the\nplumbing seems right\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n   j\n\nOn Wed, Jul 20, 2022 at 04:03:47PM +0300, Laurent Pinchart via libcamera-devel wrote:\n> From: Eric Curtin <ecurtin@redhat.com>\n>\n> We were using the libjpeg functionality of SDL2_image only, instead just\n> use libjpeg directly to reduce our dependancy count, it is a more\n> commonly available library.\n>\n> Signed-off-by: Eric Curtin <ecurtin@redhat.com>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n> Changes since v4:\n>\n> - Move JpegErrorManager to sdl_texture_mjpg.cpp\n> - Make JpegErrorManager inherit from jpeg_error_mgr\n> - Define errorExit and outputMessage as member functions\n> ---\n>  README.rst                   |  2 +-\n>  src/cam/meson.build          |  8 ++---\n>  src/cam/sdl_sink.cpp         |  4 +--\n>  src/cam/sdl_texture_mjpg.cpp | 70 ++++++++++++++++++++++++++++++++----\n>  src/cam/sdl_texture_mjpg.h   |  6 ++++\n>  5 files changed, 77 insertions(+), 13 deletions(-)\n>\n> diff --git a/README.rst b/README.rst\n> index b9e72d81b90c..47b914f02260 100644\n> --- a/README.rst\n> +++ b/README.rst\n> @@ -92,8 +92,8 @@ for cam: [optional]\n>          tool:\n>\n>          - libdrm-dev: Enables the KMS sink\n> +        - libjpeg-dev: Enables MJPEG on the SDL sink\n>          - libsdl2-dev: Enables the SDL sink\n> -        - libsdl2-image-dev: Supports MJPEG on the SDL sink\n>\n>  for qcam: [optional]\n>          qtbase5-dev libqt5core5a libqt5gui5 libqt5widgets5 qttools5-dev-tools libtiff-dev\n> diff --git a/src/cam/meson.build b/src/cam/meson.build\n> index 5957ce140391..4dfa7b22aea9 100644\n> --- a/src/cam/meson.build\n> +++ b/src/cam/meson.build\n> @@ -24,8 +24,8 @@ cam_sources = files([\n>  cam_cpp_args = []\n>\n>  libdrm = dependency('libdrm', required : false)\n> +libjpeg = dependency('libjpeg', required : false)\n>  libsdl2 = dependency('SDL2', required : false)\n> -libsdl2_image = dependency('SDL2_image', required : false)\n>\n>  if libdrm.found()\n>      cam_cpp_args += [ '-DHAVE_KMS' ]\n> @@ -43,8 +43,8 @@ if libsdl2.found()\n>          'sdl_texture_yuyv.cpp'\n>      ])\n>\n> -    if libsdl2_image.found()\n> -        cam_cpp_args += ['-DHAVE_SDL_IMAGE']\n> +    if libjpeg.found()\n> +        cam_cpp_args += ['-DHAVE_LIBJPEG']\n>          cam_sources += files([\n>              'sdl_texture_mjpg.cpp'\n>          ])\n> @@ -57,8 +57,8 @@ cam  = executable('cam', cam_sources,\n>                        libcamera_public,\n>                        libdrm,\n>                        libevent,\n> +                      libjpeg,\n>                        libsdl2,\n> -                      libsdl2_image,\n>                        libyaml,\n>                    ],\n>                    cpp_args : cam_cpp_args,\n> diff --git a/src/cam/sdl_sink.cpp b/src/cam/sdl_sink.cpp\n> index f8e3e95dd392..19fdfd6dced5 100644\n> --- a/src/cam/sdl_sink.cpp\n> +++ b/src/cam/sdl_sink.cpp\n> @@ -21,7 +21,7 @@\n>\n>  #include \"event_loop.h\"\n>  #include \"image.h\"\n> -#ifdef HAVE_SDL_IMAGE\n> +#ifdef HAVE_LIBJPEG\n>  #include \"sdl_texture_mjpg.h\"\n>  #endif\n>  #include \"sdl_texture_yuyv.h\"\n> @@ -62,7 +62,7 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config)\n>  \trect_.h = cfg.size.height;\n>\n>  \tswitch (cfg.pixelFormat) {\n> -#ifdef HAVE_SDL_IMAGE\n> +#ifdef HAVE_LIBJPEG\n>  \tcase libcamera::formats::MJPEG:\n>  \t\ttexture_ = std::make_unique<SDLTextureMJPG>(rect_);\n>  \t\tbreak;\n> diff --git a/src/cam/sdl_texture_mjpg.cpp b/src/cam/sdl_texture_mjpg.cpp\n> index 69e99ad35219..7eddc00cd210 100644\n> --- a/src/cam/sdl_texture_mjpg.cpp\n> +++ b/src/cam/sdl_texture_mjpg.cpp\n> @@ -7,19 +7,77 @@\n>\n>  #include \"sdl_texture_mjpg.h\"\n>\n> -#include <SDL2/SDL_image.h>\n> +#include <iostream>\n> +#include <setjmp.h>\n> +#include <stdio.h>\n> +\n> +#include <jpeglib.h>\n>\n>  using namespace libcamera;\n>\n> +struct JpegErrorManager : public jpeg_error_mgr {\n> +\tJpegErrorManager()\n> +\t{\n> +\t\tjpeg_std_error(this);\n> +\t\terror_exit = errorExit;\n> +\t\toutput_message = outputMessage;\n> +\t}\n> +\n> +\tstatic void errorExit(j_common_ptr cinfo)\n> +\t{\n> +\t\tJpegErrorManager *self =\n> +\t\t\tstatic_cast<JpegErrorManager *>(cinfo->err);\n> +\t\tlongjmp(self->escape_, 1);\n> +\t}\n> +\n> +\tstatic void outputMessage([[maybe_unused]] j_common_ptr cinfo)\n> +\t{\n> +\t}\n> +\n> +\tjmp_buf escape_;\n> +};\n> +\n>  SDLTextureMJPG::SDLTextureMJPG(const SDL_Rect &rect)\n> -\t: SDLTexture(rect, SDL_PIXELFORMAT_RGB24, 0)\n> +\t: SDLTexture(rect, SDL_PIXELFORMAT_RGB24, rect.w * 3),\n> +\t  rgb_(std::make_unique<unsigned char[]>(pitch_ * rect.h))\n>  {\n>  }\n>\n> +int SDLTextureMJPG::decompress(const Span<uint8_t> &data)\n> +{\n> +\tstruct jpeg_decompress_struct cinfo;\n> +\n> +\tJpegErrorManager errorManager;\n> +\tif (setjmp(errorManager.escape_)) {\n> +\t\t/* libjpeg found an error */\n> +\t\tjpeg_destroy_decompress(&cinfo);\n> +\t\tstd::cerr << \"JPEG decompression error\" << std::endl;\n> +\t\treturn -EINVAL;\n> +\t}\n> +\n> +\tcinfo.err = &errorManager;\n> +\tjpeg_create_decompress(&cinfo);\n> +\n> +\tjpeg_mem_src(&cinfo, data.data(), data.size());\n> +\n> +\tjpeg_read_header(&cinfo, TRUE);\n> +\n> +\tjpeg_start_decompress(&cinfo);\n> +\n> +\tfor (int i = 0; cinfo.output_scanline < cinfo.output_height; ++i) {\n> +\t\tJSAMPROW rowptr = rgb_.get() + i * pitch_;\n> +\t\tjpeg_read_scanlines(&cinfo, &rowptr, 1);\n> +\t}\n> +\n> +\tjpeg_finish_decompress(&cinfo);\n> +\n> +\tjpeg_destroy_decompress(&cinfo);\n> +\n> +\treturn 0;\n> +}\n> +\n>  void SDLTextureMJPG::update(const Span<uint8_t> &data)\n>  {\n> -\tSDL_RWops *bufferStream = SDL_RWFromMem(data.data(), data.size());\n> -\tSDL_Surface *frame = IMG_Load_RW(bufferStream, 0);\n> -\tSDL_UpdateTexture(ptr_, nullptr, frame->pixels, frame->pitch);\n> -\tSDL_FreeSurface(frame);\n> +\tdecompress(data);\n> +\tSDL_UpdateTexture(ptr_, nullptr, rgb_.get(), pitch_);\n>  }\n> diff --git a/src/cam/sdl_texture_mjpg.h b/src/cam/sdl_texture_mjpg.h\n> index b103f801176d..328c45a913c5 100644\n> --- a/src/cam/sdl_texture_mjpg.h\n> +++ b/src/cam/sdl_texture_mjpg.h\n> @@ -13,5 +13,11 @@ class SDLTextureMJPG : public SDLTexture\n>  {\n>  public:\n>  \tSDLTextureMJPG(const SDL_Rect &rect);\n> +\n>  \tvoid update(const libcamera::Span<uint8_t> &data) override;\n> +\n> +private:\n> +\tint decompress(const libcamera::Span<uint8_t> &data);\n> +\n> +\tstd::unique_ptr<unsigned char[]> rgb_;\n>  };\n> --\n> Regards,\n>\n> Laurent Pinchart\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E2030BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 28 Jul 2022 08:12:02 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 14C4463311;\n\tThu, 28 Jul 2022 10:12:02 +0200 (CEST)","from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net\n\t[IPv6:2001:4b98:dc4:8::222])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 42F68603EB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 28 Jul 2022 10:12:00 +0200 (CEST)","(Authenticated sender: jacopo@jmondi.org)\n\tby mail.gandi.net (Postfix) with ESMTPSA id 334A940002;\n\tThu, 28 Jul 2022 08:11:58 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1658995922;\n\tbh=eyelvBe5oSCwyCZVqwoMrFCRiFBt5WIWeh4nWqjK7jw=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=AQEaipBjhIM1h3r1Fy/w+usa/eLnLac4BElmQVEv6+JIxxPTuYUPqXjSTY9VVMYiM\n\t4Z4QhXoWVTcTvvd//FUDLMQfm21XHtoLWtJrm4fkf4ub8+GbMvqEgpGQ5jY4Z4yCFm\n\t1bZxsZiTVzpG4aaRlSmcJ5zN4+ic8QwVZxR63+lm0uUD//FPDExcucwcQ/1nDWXQGe\n\taavh+c47D30KvFEgdkKc07rIAwyotg0LPlO691hFzJZGTpbgXJDbMuwEfKKeikoTtK\n\tUyvDNAq5ugXPUojtDMeltthE6GvKTmzQjoS61MW/CjDIvUIg+nW3LNUDa1QLNpPrSv\n\t14wACKY18dcUg==","Date":"Thu, 28 Jul 2022 10:11:57 +0200","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20220728081157.kkwjsmyk2zmvzunl@uno.localdomain>","References":"<20220720130348.1337-1-laurent.pinchart@ideasonboard.com>\n\t<20220720130348.1337-2-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220720130348.1337-2-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v5 1/2] cam: sdl_sink: Use libjpeg\n\tover SDL2_image","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]