e50c6c1b2b
Signed-off-by: zejian.su <zejian.su@starfivetech.com>
223 lines
7.4 KiB
Diff
223 lines
7.4 KiB
Diff
From d02d3b3a6c0abdfd8a89ee92447df7d8d48639d5 Mon Sep 17 00:00:00 2001
|
|
From: "zejian.su" <zejian.su@starfivetech.com>
|
|
Date: Thu, 12 Oct 2023 11:55:47 +0800
|
|
Subject: [PATCH 2/4] Make libcamera-jpeg run normally
|
|
|
|
---
|
|
apps/libcamera_jpeg.cpp | 28 +++++----
|
|
core/CMakeLists.txt | 2 +-
|
|
core/cvt_color_format.cpp | 119 ++++++++++++++++++++++++++++++++++++++
|
|
image/jpeg.cpp | 1 +
|
|
4 files changed, 134 insertions(+), 16 deletions(-)
|
|
create mode 100755 core/cvt_color_format.cpp
|
|
|
|
diff --git a/apps/libcamera_jpeg.cpp b/apps/libcamera_jpeg.cpp
|
|
index 05a632b..b791960 100644
|
|
--- a/apps/libcamera_jpeg.cpp
|
|
+++ b/apps/libcamera_jpeg.cpp
|
|
@@ -15,6 +15,8 @@
|
|
using namespace std::placeholders;
|
|
using libcamera::Stream;
|
|
|
|
+void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &yuv420, StreamInfo &info);
|
|
+
|
|
class LibcameraJpegApp : public LibcameraApp
|
|
{
|
|
public:
|
|
@@ -61,10 +63,19 @@ static void event_loop(LibcameraJpegApp &app)
|
|
auto now = std::chrono::high_resolution_clock::now();
|
|
if (options->timeout && now - start_time > std::chrono::milliseconds(options->timeout))
|
|
{
|
|
+ Stream *stream = app.ViewfinderStream();
|
|
+ StreamInfo info = app.GetStreamInfo(stream);
|
|
+ CompletedRequestPtr &payload = std::get<CompletedRequestPtr>(msg.payload);
|
|
+ const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
|
|
+ std::vector<libcamera::Span<uint8_t>> yuv420;
|
|
+
|
|
+ NV12ToYUV420(mem[0], yuv420, info);
|
|
app.StopCamera();
|
|
app.Teardown();
|
|
- app.ConfigureStill();
|
|
- app.StartCamera();
|
|
+
|
|
+ jpeg_save(yuv420, info, payload->metadata, options->output, app.CameraModel(), options);
|
|
+ delete[] yuv420[0].data();
|
|
+ return;
|
|
}
|
|
else
|
|
{
|
|
@@ -72,19 +83,6 @@ static void event_loop(LibcameraJpegApp &app)
|
|
app.ShowPreview(completed_request, app.ViewfinderStream());
|
|
}
|
|
}
|
|
- // In still capture mode, save a jpeg and quit.
|
|
- else if (app.StillStream())
|
|
- {
|
|
- app.StopCamera();
|
|
- LOG(1, "Still capture image received");
|
|
-
|
|
- Stream *stream = app.StillStream();
|
|
- StreamInfo info = app.GetStreamInfo(stream);
|
|
- CompletedRequestPtr &payload = std::get<CompletedRequestPtr>(msg.payload);
|
|
- const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
|
|
- jpeg_save(mem, info, payload->metadata, options->output, app.CameraModel(), options);
|
|
- return;
|
|
- }
|
|
}
|
|
}
|
|
|
|
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
|
|
index b601538..5d9ee30 100644
|
|
--- a/core/CMakeLists.txt
|
|
+++ b/core/CMakeLists.txt
|
|
@@ -7,7 +7,7 @@ find_package(Boost REQUIRED COMPONENTS program_options)
|
|
add_custom_target(VersionCpp ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${CMAKE_CURRENT_LIST_DIR}/version.cmake)
|
|
set_source_files_properties(version.cpp PROPERTIES GENERATED 1)
|
|
|
|
-add_library(libcamera_app libcamera_app.cpp post_processor.cpp version.cpp options.cpp)
|
|
+add_library(libcamera_app libcamera_app.cpp post_processor.cpp version.cpp options.cpp cvt_color_format.cpp)
|
|
add_dependencies(libcamera_app VersionCpp)
|
|
|
|
set_target_properties(libcamera_app PROPERTIES PREFIX "" IMPORT_PREFIX "" VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
|
|
diff --git a/core/cvt_color_format.cpp b/core/cvt_color_format.cpp
|
|
new file mode 100755
|
|
index 0000000..9ff2b6b
|
|
--- /dev/null
|
|
+++ b/core/cvt_color_format.cpp
|
|
@@ -0,0 +1,119 @@
|
|
+/* SPDX-License-Identifier: BSD-2-Clause */
|
|
+/*
|
|
+ * Copyright (C) 2023, Starfive Technology Co., Ltd.
|
|
+ *
|
|
+ * cvt_color_format.cpp - convert other format to yuv420.
|
|
+ */
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <unistd.h>
|
|
+#include <sys/types.h>
|
|
+#include "core/still_options.hpp"
|
|
+
|
|
+void NV12ToYUV420(const uint8_t *mem, uint8_t *dst, const StreamInfo &info)
|
|
+{
|
|
+ const uint8_t *src = mem;
|
|
+ uint32_t width = info.width, height = info.height, stride = info.stride;
|
|
+ uint8_t *u = dst + height * stride;
|
|
+ uint8_t *v = u + ((height * width) >> 2);
|
|
+ uint32_t i;
|
|
+
|
|
+ memcpy(dst, src, height * stride);
|
|
+
|
|
+ src += height * stride;
|
|
+ for(i = 0; i < (height * width) >> 2; i++, src += 2)
|
|
+ u[i] = src[0], v[i] = src[1];
|
|
+}
|
|
+
|
|
+void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, uint8_t *dst, const StreamInfo &info)
|
|
+{
|
|
+ NV12ToYUV420((const uint8_t *)(mem.data()), dst, info);
|
|
+/*
|
|
+ const uint8_t *src = mem.data();
|
|
+ uint32_t width = info.width, height = info.height, stride = info.stride;
|
|
+ uint8_t *u = dst + height * stride;
|
|
+ uint8_t *v = u + ((height * width) >> 2);
|
|
+ uint32_t i;
|
|
+
|
|
+ memcpy(dst, src, height * stride);
|
|
+
|
|
+ src += height * stride;
|
|
+ for(i = 0; i < (height * width) >> 2; i++, src += 2)
|
|
+ u[i] = src[0], v[i] = src[1];
|
|
+*/
|
|
+}
|
|
+
|
|
+void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &yuv420, StreamInfo &info)
|
|
+{
|
|
+ uint32_t imgBufSize = info.height * info.stride + ((info.height * info.width) >> 1);
|
|
+ uint8_t * yuv420Buf = new uint8_t[imgBufSize];
|
|
+
|
|
+ if(!yuv420Buf)
|
|
+ throw std::runtime_error("fail to apply memory");
|
|
+
|
|
+ yuv420.push_back(libcamera::Span<uint8_t>(yuv420Buf, imgBufSize));
|
|
+
|
|
+ NV12ToYUV420(mem, yuv420Buf, info);
|
|
+ info.pixel_format = libcamera::formats::YUV420;
|
|
+}
|
|
+
|
|
+template<int R>
|
|
+void NV12ToRGB888(const libcamera::Span<uint8_t> &mem, uint8_t *dst, const StreamInfo &info)
|
|
+{
|
|
+ uint32_t width = info.width, height = info.height, stride = info.stride;
|
|
+ const uint8_t *yRow = mem.data();
|
|
+ const uint8_t *uv = yRow + height * stride;
|
|
+ int ri = R ? 2 : 0;
|
|
+
|
|
+ for(uint32_t i = 0; i < height; i++, yRow += stride, dst += 3 * width)
|
|
+ {
|
|
+ const uint8_t * curUV = uv;
|
|
+ uint8_t * curDst = dst;
|
|
+ for(uint32_t j = 0; j < width; j++, curDst += 3)
|
|
+ {
|
|
+ int32_t y = (int32_t)yRow[j] - 16;
|
|
+ int32_t u = (int32_t)curUV[0] - 128;
|
|
+ int32_t v = (int32_t)curUV[1] - 128;
|
|
+ int32_t val;
|
|
+
|
|
+ val = (1192 * y + 2066 * u - v) >> 10;
|
|
+ curDst[ri] = val < 0 ? 0 : (val > 255 ? 255 : (uint8_t)val);
|
|
+ val = (1192 * y - 401 * u - 833 * v) >> 10;
|
|
+ curDst[1] = val < 0 ? 0 : (val > 255 ? 255 : (uint8_t)val);
|
|
+ val = (1192 * y - 2 * u + 1634 * v) >> 10;
|
|
+ curDst[2 - ri] = val < 0 ? 0 : (val > 255 ? 255 : (uint8_t)val);
|
|
+
|
|
+ if(j & 1)
|
|
+ curUV += 2;
|
|
+ }
|
|
+ if(i & 1)
|
|
+ uv += width;
|
|
+ }
|
|
+}
|
|
+
|
|
+template<int R>
|
|
+void RGB888FromNV12(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info)
|
|
+{
|
|
+ uint32_t imgBufSize = info.height * info.width * 3;
|
|
+ uint8_t * rgb888Buf = new uint8_t[imgBufSize];
|
|
+
|
|
+ if(!rgb888Buf)
|
|
+ throw std::runtime_error("fail to apply memory");
|
|
+
|
|
+ rgb888.push_back(libcamera::Span<uint8_t>(rgb888Buf, imgBufSize));
|
|
+
|
|
+ NV12ToRGB888<R>(mem, rgb888Buf, info);
|
|
+ info.stride = 3 * info.width;
|
|
+}
|
|
+
|
|
+void NV12ToRGB888(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info)
|
|
+{
|
|
+ RGB888FromNV12<0>(mem, rgb888, info);
|
|
+ info.pixel_format = libcamera::formats::RGB888;
|
|
+}
|
|
+
|
|
+void NV12ToBGR888(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info)
|
|
+{
|
|
+ RGB888FromNV12<2>(mem, rgb888, info);
|
|
+ info.pixel_format = libcamera::formats::BGR888;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/image/jpeg.cpp b/image/jpeg.cpp
|
|
index e3516ef..872f5c6 100644
|
|
--- a/image/jpeg.cpp
|
|
+++ b/image/jpeg.cpp
|
|
@@ -447,6 +447,7 @@ static void create_exif_data(std::vector<libcamera::Span<uint8_t>> const &mem, S
|
|
exif = exif_data_new();
|
|
if (!exif)
|
|
throw std::runtime_error("failed to allocate EXIF data");
|
|
+
|
|
exif_data_set_byte_order(exif, exif_byte_order);
|
|
|
|
// First add some fixed EXIF tags.
|
|
--
|
|
2.34.1
|
|
|