0001-Make-libcamera-hello-run-normally.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. From 2982813d58c13077c06d1c3c44cd60b0b93d1f4e Mon Sep 17 00:00:00 2001
  2. From: "zejian.su" <zejian.su@starfivetech.com>
  3. Date: Thu, 12 Oct 2023 11:54:09 +0800
  4. Subject: [PATCH 1/4] Make libcamera-hello run normally
  5. ---
  6. core/libcamera_app.cpp | 53 ++++++++++++++------------
  7. preview/drm_preview.cpp | 84 +++++++++++++++++++++++++++++++++++------
  8. 2 files changed, 100 insertions(+), 37 deletions(-)
  9. diff --git a/core/libcamera_app.cpp b/core/libcamera_app.cpp
  10. index d3a6b63..cc76e9b 100644
  11. --- a/core/libcamera_app.cpp
  12. +++ b/core/libcamera_app.cpp
  13. @@ -247,23 +247,24 @@ void LibcameraApp::ConfigureViewfinder()
  14. if (!configuration_)
  15. throw std::runtime_error("failed to generate viewfinder configuration");
  16. - Size size(1280, 960);
  17. - auto area = camera_->properties().get(properties::PixelArrayActiveAreas);
  18. + //Size size(1280, 960);
  19. + Size size = configuration_->at(0).size;
  20. + //auto area = camera_->properties().get(properties::PixelArrayActiveAreas);
  21. if (options_->viewfinder_width && options_->viewfinder_height)
  22. size = Size(options_->viewfinder_width, options_->viewfinder_height);
  23. - else if (area)
  24. - {
  25. - // The idea here is that most sensors will have a 2x2 binned mode that
  26. - // we can pick up. If it doesn't, well, you can always specify the size
  27. - // you want exactly with the viewfinder_width/height options_->
  28. - size = (*area)[0].size() / 2;
  29. - // If width and height were given, we might be switching to capture
  30. - // afterwards - so try to match the field of view.
  31. - if (options_->width && options_->height)
  32. - size = size.boundedToAspectRatio(Size(options_->width, options_->height));
  33. - size.alignDownTo(2, 2); // YUV420 will want to be even
  34. - LOG(2, "Viewfinder size chosen is " << size.toString());
  35. - }
  36. + //else if (area)
  37. + //{
  38. + // // The idea here is that most sensors will have a 2x2 binned mode that
  39. + // // we can pick up. If it doesn't, well, you can always specify the size
  40. + // // you want exactly with the viewfinder_width/height options_->
  41. + // size = (*area)[0].size() / 2;
  42. + // // If width and height were given, we might be switching to capture
  43. + // // afterwards - so try to match the field of view.
  44. + // if (options_->width && options_->height)
  45. + // size = size.boundedToAspectRatio(Size(options_->width, options_->height));
  46. + // size.alignDownTo(2, 2); // YUV420 will want to be even
  47. + // LOG(2, "Viewfinder size chosen is " << size.toString());
  48. + //}
  49. // Finally trim the image size to the largest that the preview can handle.
  50. Size max_size;
  51. @@ -275,7 +276,7 @@ void LibcameraApp::ConfigureViewfinder()
  52. }
  53. // Now we get to override any of the default settings from the options_->
  54. - configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  55. + //configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  56. configuration_->at(0).size = size;
  57. if (options_->viewfinder_buffer_count > 0)
  58. configuration_->at(0).bufferCount = options_->viewfinder_buffer_count;
  59. @@ -286,7 +287,7 @@ void LibcameraApp::ConfigureViewfinder()
  60. lores_size.alignDownTo(2, 2);
  61. if (lores_size.width > size.width || lores_size.height > size.height)
  62. throw std::runtime_error("Low res image larger than viewfinder");
  63. - configuration_->at(lores_stream_num).pixelFormat = libcamera::formats::YUV420;
  64. + //configuration_->at(lores_stream_num).pixelFormat = libcamera::formats::YUV420;
  65. configuration_->at(lores_stream_num).size = lores_size;
  66. configuration_->at(lores_stream_num).bufferCount = configuration_->at(0).bufferCount;
  67. }
  68. @@ -297,7 +298,7 @@ void LibcameraApp::ConfigureViewfinder()
  69. if (have_raw_stream)
  70. {
  71. configuration_->at(raw_stream_num).size = options_->viewfinder_mode.Size();
  72. - configuration_->at(raw_stream_num).pixelFormat = mode_to_pixel_format(options_->viewfinder_mode);
  73. + //configuration_->at(raw_stream_num).pixelFormat = mode_to_pixel_format(options_->viewfinder_mode);
  74. configuration_->at(raw_stream_num).bufferCount = configuration_->at(0).bufferCount;
  75. }
  76. @@ -335,8 +336,9 @@ void LibcameraApp::ConfigureStill(unsigned int flags)
  77. configuration_->at(0).pixelFormat = libcamera::formats::BGR888;
  78. else if (flags & FLAG_STILL_RGB)
  79. configuration_->at(0).pixelFormat = libcamera::formats::RGB888;
  80. - else
  81. - configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  82. + else {
  83. + //configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
  84. + }
  85. if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_DOUBLE_BUFFER)
  86. configuration_->at(0).bufferCount = 2;
  87. else if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_TRIPLE_BUFFER)
  88. @@ -358,8 +360,8 @@ void LibcameraApp::ConfigureStill(unsigned int flags)
  89. configuration_->at(1).pixelFormat = mode_to_pixel_format(options_->mode);
  90. }
  91. configuration_->at(1).bufferCount = configuration_->at(0).bufferCount;
  92. -
  93. configureDenoise(options_->denoise == "auto" ? "cdn_hq" : options_->denoise);
  94. +
  95. setupCapture();
  96. streams_["still"] = configuration_->at(0).stream();
  97. @@ -392,7 +394,7 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
  98. // Now we get to override any of the default settings from the options_->
  99. StreamConfiguration &cfg = configuration_->at(0);
  100. - cfg.pixelFormat = libcamera::formats::YUV420;
  101. + //cfg.pixelFormat = libcamera::formats::YUV420;
  102. cfg.bufferCount = 6; // 6 buffers is better than 4
  103. if (options_->buffer_count > 0)
  104. cfg.bufferCount = options_->buffer_count;
  105. @@ -431,7 +433,7 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
  106. if (lores_size.width > configuration_->at(0).size.width ||
  107. lores_size.height > configuration_->at(0).size.height)
  108. throw std::runtime_error("Low res image larger than video");
  109. - configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
  110. + //configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
  111. configuration_->at(lores_index).size = lores_size;
  112. configuration_->at(lores_index).bufferCount = configuration_->at(0).bufferCount;
  113. }
  114. @@ -959,8 +961,9 @@ void LibcameraApp::previewThread()
  115. preview_cond_var_.wait(lock);
  116. }
  117. - if (item.stream->configuration().pixelFormat != libcamera::formats::YUV420)
  118. - throw std::runtime_error("Preview windows only support YUV420");
  119. + if (item.stream->configuration().pixelFormat != libcamera::formats::YUV420 &&
  120. + item.stream->configuration().pixelFormat != libcamera::formats::NV12)
  121. + throw std::runtime_error("Preview windows only support YUV420 and NV12");
  122. StreamInfo info = GetStreamInfo(item.stream);
  123. FrameBuffer *buffer = item.completed_request->buffers[item.stream];
  124. diff --git a/preview/drm_preview.cpp b/preview/drm_preview.cpp
  125. index 4d6cf0d..38fc6a2 100644
  126. --- a/preview/drm_preview.cpp
  127. +++ b/preview/drm_preview.cpp
  128. @@ -10,6 +10,8 @@
  129. #include <drm_mode.h>
  130. #include <xf86drm.h>
  131. #include <xf86drmMode.h>
  132. +#include <fcntl.h>
  133. +#include <libcamera/formats.h>
  134. #include "core/options.hpp"
  135. @@ -48,6 +50,7 @@ private:
  136. void findPlane();
  137. int drmfd_;
  138. int conId_;
  139. + drmModeConnector *con_;
  140. uint32_t crtcId_;
  141. int crtcIdx_;
  142. uint32_t planeId_;
  143. @@ -93,10 +96,21 @@ void DrmPreview::findCrtc()
  144. if (con->encoder_id)
  145. {
  146. enc = drmModeGetEncoder(drmfd_, con->encoder_id);
  147. - if (enc->crtc_id)
  148. - {
  149. - crtc = drmModeGetCrtc(drmfd_, enc->crtc_id);
  150. - }
  151. + //if (enc->crtc_id)
  152. + //{
  153. + // crtc = drmModeGetCrtc(drmfd_, enc->crtc_id);
  154. + //}
  155. + } else
  156. + {
  157. + enc = drmModeGetEncoder(drmfd_, con->encoders[0]);
  158. + }
  159. +
  160. + if (enc->crtc_id)
  161. + {
  162. + crtc = drmModeGetCrtc(drmfd_, enc->crtc_id);
  163. + } else
  164. + {
  165. + crtc = drmModeGetCrtc(drmfd_, res->crtcs[0]);
  166. }
  167. if (!conId_ && crtc)
  168. @@ -158,6 +172,8 @@ void DrmPreview::findCrtc()
  169. throw std::runtime_error("connector supports no mode");
  170. }
  171. + con_ = c;
  172. +
  173. if (options_->fullscreen || width_ == 0 || height_ == 0)
  174. {
  175. drmModeCrtc *crtc = drmModeGetCrtc(drmfd_, crtcId_);
  176. @@ -225,10 +241,13 @@ void DrmPreview::findPlane()
  177. DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1), first_time_(true)
  178. {
  179. - drmfd_ = drmOpen("vc4", NULL);
  180. + //drmfd_ = drmOpen("vc4", NULL);
  181. + drmfd_ = drmOpen("starfive", NULL);
  182. if (drmfd_ < 0)
  183. throw std::runtime_error("drmOpen failed: " + std::string(ERRSTR));
  184. + drmSetClientCap(drmfd_, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
  185. +
  186. x_ = options_->preview_x;
  187. y_ = options_->preview_y;
  188. width_ = options_->preview_width;
  189. @@ -243,7 +262,8 @@ DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1),
  190. conId_ = 0;
  191. findCrtc();
  192. - out_fourcc_ = DRM_FORMAT_YUV420;
  193. + //out_fourcc_ = DRM_FORMAT_YUV420;
  194. + out_fourcc_ = DRM_FORMAT_NV12;
  195. findPlane();
  196. }
  197. catch (std::exception const &e)
  198. @@ -347,6 +367,7 @@ static void setup_colour_space(int fd, int plane_id, std::optional<libcamera::Co
  199. void DrmPreview::makeBuffer(int fd, size_t size, StreamInfo const &info, Buffer &buffer)
  200. {
  201. + unsigned int width = info.width, height = info.height, stride = info.stride;
  202. if (first_time_)
  203. {
  204. first_time_ = false;
  205. @@ -361,13 +382,52 @@ void DrmPreview::makeBuffer(int fd, size_t size, StreamInfo const &info, Buffer
  206. if (drmPrimeFDToHandle(drmfd_, fd, &buffer.bo_handle))
  207. throw std::runtime_error("drmPrimeFDToHandle failed for fd " + std::to_string(fd));
  208. - uint32_t offsets[4] =
  209. - { 0, info.stride * info.height, info.stride * info.height + (info.stride / 2) * (info.height / 2) };
  210. - uint32_t pitches[4] = { info.stride, info.stride / 2, info.stride / 2 };
  211. - uint32_t bo_handles[4] = { buffer.bo_handle, buffer.bo_handle, buffer.bo_handle };
  212. -
  213. - if (drmModeAddFB2(drmfd_, info.width, info.height, out_fourcc_, bo_handles, pitches, offsets, &buffer.fb_handle, 0))
  214. + if (out_fourcc_ == DRM_FORMAT_YUV420) {
  215. + uint32_t offsets[4] = { 0, stride * height, stride * height + (stride / 2) * (height / 2) };
  216. + uint32_t pitches[4] = { stride, stride / 2, stride / 2 };
  217. + uint32_t bo_handles[4] = { buffer.bo_handle, buffer.bo_handle, buffer.bo_handle };
  218. +
  219. + if (drmModeAddFB2(drmfd_, width, height, out_fourcc_, bo_handles, pitches, offsets, &buffer.fb_handle, 0))
  220. + throw std::runtime_error("YUV420 drmModeAddFB2 failed: " + std::string(ERRSTR));
  221. + } else if (out_fourcc_ == DRM_FORMAT_NV12 || out_fourcc_ == DRM_FORMAT_NV21) {
  222. + uint32_t offsets[4] = { 0, stride * height};
  223. + uint32_t pitches[4] = { stride, stride};
  224. + uint32_t bo_handles[4] = { buffer.bo_handle, buffer.bo_handle};
  225. +
  226. + if (drmModeAddFB2(drmfd_, width, height, out_fourcc_, bo_handles, pitches, offsets, &buffer.fb_handle, 0))
  227. + throw std::runtime_error("NV12/21 drmModeAddFB2 failed: " + std::string(ERRSTR));
  228. + } else
  229. throw std::runtime_error("drmModeAddFB2 failed: " + std::string(ERRSTR));
  230. +
  231. + /* find preferred mode */
  232. + drmModeModeInfo *modeptr = NULL, *preferred = NULL;
  233. + for (int m = 0; m < con_->count_modes; m++) {
  234. + modeptr = &con_->modes[m];
  235. + if (modeptr->hdisplay == width && modeptr->vdisplay == height) {
  236. + preferred = modeptr;
  237. + std::cout << "find the matched mode, modes index= "
  238. + << m << ", " << width << "x" << height << std::endl;
  239. + break;
  240. + }
  241. + if (modeptr->type & DRM_MODE_TYPE_PREFERRED) {
  242. + preferred = modeptr;
  243. + std::cout << "find perferred mode, modes index= " << m << std::endl;
  244. + }
  245. + }
  246. +
  247. + if (!preferred)
  248. + preferred = &con_->modes[0];
  249. +
  250. + // set default
  251. + if (drmModeSetCrtc(drmfd_, crtcId_, buffer.fb_handle, 0, 0,
  252. + (uint32_t *)&conId_, 1, preferred)) {
  253. + throw std::runtime_error("drmModeSetCrtc() failed");
  254. + }
  255. +
  256. + screen_width_ = preferred->hdisplay;
  257. + screen_height_ = preferred->vdisplay;
  258. + width_ = width;
  259. + height_ = height;
  260. }
  261. void DrmPreview::Show(int fd, libcamera::Span<uint8_t> span, StreamInfo const &info)
  262. --
  263. 2.34.1