0002-Make-libcamera-jpeg-run-normally.patch 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. From d02d3b3a6c0abdfd8a89ee92447df7d8d48639d5 Mon Sep 17 00:00:00 2001
  2. From: "zejian.su" <zejian.su@starfivetech.com>
  3. Date: Thu, 12 Oct 2023 11:55:47 +0800
  4. Subject: [PATCH 2/4] Make libcamera-jpeg run normally
  5. ---
  6. apps/libcamera_jpeg.cpp | 28 +++++----
  7. core/CMakeLists.txt | 2 +-
  8. core/cvt_color_format.cpp | 119 ++++++++++++++++++++++++++++++++++++++
  9. image/jpeg.cpp | 1 +
  10. 4 files changed, 134 insertions(+), 16 deletions(-)
  11. create mode 100755 core/cvt_color_format.cpp
  12. diff --git a/apps/libcamera_jpeg.cpp b/apps/libcamera_jpeg.cpp
  13. index 05a632b..b791960 100644
  14. --- a/apps/libcamera_jpeg.cpp
  15. +++ b/apps/libcamera_jpeg.cpp
  16. @@ -15,6 +15,8 @@
  17. using namespace std::placeholders;
  18. using libcamera::Stream;
  19. +void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &yuv420, StreamInfo &info);
  20. +
  21. class LibcameraJpegApp : public LibcameraApp
  22. {
  23. public:
  24. @@ -61,10 +63,19 @@ static void event_loop(LibcameraJpegApp &app)
  25. auto now = std::chrono::high_resolution_clock::now();
  26. if (options->timeout && now - start_time > std::chrono::milliseconds(options->timeout))
  27. {
  28. + Stream *stream = app.ViewfinderStream();
  29. + StreamInfo info = app.GetStreamInfo(stream);
  30. + CompletedRequestPtr &payload = std::get<CompletedRequestPtr>(msg.payload);
  31. + const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
  32. + std::vector<libcamera::Span<uint8_t>> yuv420;
  33. +
  34. + NV12ToYUV420(mem[0], yuv420, info);
  35. app.StopCamera();
  36. app.Teardown();
  37. - app.ConfigureStill();
  38. - app.StartCamera();
  39. +
  40. + jpeg_save(yuv420, info, payload->metadata, options->output, app.CameraModel(), options);
  41. + delete[] yuv420[0].data();
  42. + return;
  43. }
  44. else
  45. {
  46. @@ -72,19 +83,6 @@ static void event_loop(LibcameraJpegApp &app)
  47. app.ShowPreview(completed_request, app.ViewfinderStream());
  48. }
  49. }
  50. - // In still capture mode, save a jpeg and quit.
  51. - else if (app.StillStream())
  52. - {
  53. - app.StopCamera();
  54. - LOG(1, "Still capture image received");
  55. -
  56. - Stream *stream = app.StillStream();
  57. - StreamInfo info = app.GetStreamInfo(stream);
  58. - CompletedRequestPtr &payload = std::get<CompletedRequestPtr>(msg.payload);
  59. - const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
  60. - jpeg_save(mem, info, payload->metadata, options->output, app.CameraModel(), options);
  61. - return;
  62. - }
  63. }
  64. }
  65. diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
  66. index b601538..5d9ee30 100644
  67. --- a/core/CMakeLists.txt
  68. +++ b/core/CMakeLists.txt
  69. @@ -7,7 +7,7 @@ find_package(Boost REQUIRED COMPONENTS program_options)
  70. add_custom_target(VersionCpp ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${CMAKE_CURRENT_LIST_DIR}/version.cmake)
  71. set_source_files_properties(version.cpp PROPERTIES GENERATED 1)
  72. -add_library(libcamera_app libcamera_app.cpp post_processor.cpp version.cpp options.cpp)
  73. +add_library(libcamera_app libcamera_app.cpp post_processor.cpp version.cpp options.cpp cvt_color_format.cpp)
  74. add_dependencies(libcamera_app VersionCpp)
  75. set_target_properties(libcamera_app PROPERTIES PREFIX "" IMPORT_PREFIX "" VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
  76. diff --git a/core/cvt_color_format.cpp b/core/cvt_color_format.cpp
  77. new file mode 100755
  78. index 0000000..9ff2b6b
  79. --- /dev/null
  80. +++ b/core/cvt_color_format.cpp
  81. @@ -0,0 +1,119 @@
  82. +/* SPDX-License-Identifier: BSD-2-Clause */
  83. +/*
  84. + * Copyright (C) 2023, Starfive Technology Co., Ltd.
  85. + *
  86. + * cvt_color_format.cpp - convert other format to yuv420.
  87. + */
  88. +
  89. +#include <stdio.h>
  90. +#include <unistd.h>
  91. +#include <sys/types.h>
  92. +#include "core/still_options.hpp"
  93. +
  94. +void NV12ToYUV420(const uint8_t *mem, uint8_t *dst, const StreamInfo &info)
  95. +{
  96. + const uint8_t *src = mem;
  97. + uint32_t width = info.width, height = info.height, stride = info.stride;
  98. + uint8_t *u = dst + height * stride;
  99. + uint8_t *v = u + ((height * width) >> 2);
  100. + uint32_t i;
  101. +
  102. + memcpy(dst, src, height * stride);
  103. +
  104. + src += height * stride;
  105. + for(i = 0; i < (height * width) >> 2; i++, src += 2)
  106. + u[i] = src[0], v[i] = src[1];
  107. +}
  108. +
  109. +void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, uint8_t *dst, const StreamInfo &info)
  110. +{
  111. + NV12ToYUV420((const uint8_t *)(mem.data()), dst, info);
  112. +/*
  113. + const uint8_t *src = mem.data();
  114. + uint32_t width = info.width, height = info.height, stride = info.stride;
  115. + uint8_t *u = dst + height * stride;
  116. + uint8_t *v = u + ((height * width) >> 2);
  117. + uint32_t i;
  118. +
  119. + memcpy(dst, src, height * stride);
  120. +
  121. + src += height * stride;
  122. + for(i = 0; i < (height * width) >> 2; i++, src += 2)
  123. + u[i] = src[0], v[i] = src[1];
  124. +*/
  125. +}
  126. +
  127. +void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &yuv420, StreamInfo &info)
  128. +{
  129. + uint32_t imgBufSize = info.height * info.stride + ((info.height * info.width) >> 1);
  130. + uint8_t * yuv420Buf = new uint8_t[imgBufSize];
  131. +
  132. + if(!yuv420Buf)
  133. + throw std::runtime_error("fail to apply memory");
  134. +
  135. + yuv420.push_back(libcamera::Span<uint8_t>(yuv420Buf, imgBufSize));
  136. +
  137. + NV12ToYUV420(mem, yuv420Buf, info);
  138. + info.pixel_format = libcamera::formats::YUV420;
  139. +}
  140. +
  141. +template<int R>
  142. +void NV12ToRGB888(const libcamera::Span<uint8_t> &mem, uint8_t *dst, const StreamInfo &info)
  143. +{
  144. + uint32_t width = info.width, height = info.height, stride = info.stride;
  145. + const uint8_t *yRow = mem.data();
  146. + const uint8_t *uv = yRow + height * stride;
  147. + int ri = R ? 2 : 0;
  148. +
  149. + for(uint32_t i = 0; i < height; i++, yRow += stride, dst += 3 * width)
  150. + {
  151. + const uint8_t * curUV = uv;
  152. + uint8_t * curDst = dst;
  153. + for(uint32_t j = 0; j < width; j++, curDst += 3)
  154. + {
  155. + int32_t y = (int32_t)yRow[j] - 16;
  156. + int32_t u = (int32_t)curUV[0] - 128;
  157. + int32_t v = (int32_t)curUV[1] - 128;
  158. + int32_t val;
  159. +
  160. + val = (1192 * y + 2066 * u - v) >> 10;
  161. + curDst[ri] = val < 0 ? 0 : (val > 255 ? 255 : (uint8_t)val);
  162. + val = (1192 * y - 401 * u - 833 * v) >> 10;
  163. + curDst[1] = val < 0 ? 0 : (val > 255 ? 255 : (uint8_t)val);
  164. + val = (1192 * y - 2 * u + 1634 * v) >> 10;
  165. + curDst[2 - ri] = val < 0 ? 0 : (val > 255 ? 255 : (uint8_t)val);
  166. +
  167. + if(j & 1)
  168. + curUV += 2;
  169. + }
  170. + if(i & 1)
  171. + uv += width;
  172. + }
  173. +}
  174. +
  175. +template<int R>
  176. +void RGB888FromNV12(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info)
  177. +{
  178. + uint32_t imgBufSize = info.height * info.width * 3;
  179. + uint8_t * rgb888Buf = new uint8_t[imgBufSize];
  180. +
  181. + if(!rgb888Buf)
  182. + throw std::runtime_error("fail to apply memory");
  183. +
  184. + rgb888.push_back(libcamera::Span<uint8_t>(rgb888Buf, imgBufSize));
  185. +
  186. + NV12ToRGB888<R>(mem, rgb888Buf, info);
  187. + info.stride = 3 * info.width;
  188. +}
  189. +
  190. +void NV12ToRGB888(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info)
  191. +{
  192. + RGB888FromNV12<0>(mem, rgb888, info);
  193. + info.pixel_format = libcamera::formats::RGB888;
  194. +}
  195. +
  196. +void NV12ToBGR888(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info)
  197. +{
  198. + RGB888FromNV12<2>(mem, rgb888, info);
  199. + info.pixel_format = libcamera::formats::BGR888;
  200. +}
  201. \ No newline at end of file
  202. diff --git a/image/jpeg.cpp b/image/jpeg.cpp
  203. index e3516ef..872f5c6 100644
  204. --- a/image/jpeg.cpp
  205. +++ b/image/jpeg.cpp
  206. @@ -447,6 +447,7 @@ static void create_exif_data(std::vector<libcamera::Span<uint8_t>> const &mem, S
  207. exif = exif_data_new();
  208. if (!exif)
  209. throw std::runtime_error("failed to allocate EXIF data");
  210. +
  211. exif_data_set_byte_order(exif, exif_byte_order);
  212. // First add some fixed EXIF tags.
  213. --
  214. 2.34.1