e50c6c1b2b
Signed-off-by: zejian.su <zejian.su@starfivetech.com>
285 lines
11 KiB
Diff
285 lines
11 KiB
Diff
From 2982813d58c13077c06d1c3c44cd60b0b93d1f4e Mon Sep 17 00:00:00 2001
|
|
From: "zejian.su" <zejian.su@starfivetech.com>
|
|
Date: Thu, 12 Oct 2023 11:54:09 +0800
|
|
Subject: [PATCH 1/4] Make libcamera-hello run normally
|
|
|
|
---
|
|
core/libcamera_app.cpp | 53 ++++++++++++++------------
|
|
preview/drm_preview.cpp | 84 +++++++++++++++++++++++++++++++++++------
|
|
2 files changed, 100 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/core/libcamera_app.cpp b/core/libcamera_app.cpp
|
|
index d3a6b63..cc76e9b 100644
|
|
--- a/core/libcamera_app.cpp
|
|
+++ b/core/libcamera_app.cpp
|
|
@@ -247,23 +247,24 @@ void LibcameraApp::ConfigureViewfinder()
|
|
if (!configuration_)
|
|
throw std::runtime_error("failed to generate viewfinder configuration");
|
|
|
|
- Size size(1280, 960);
|
|
- auto area = camera_->properties().get(properties::PixelArrayActiveAreas);
|
|
+ //Size size(1280, 960);
|
|
+ Size size = configuration_->at(0).size;
|
|
+ //auto area = camera_->properties().get(properties::PixelArrayActiveAreas);
|
|
if (options_->viewfinder_width && options_->viewfinder_height)
|
|
size = Size(options_->viewfinder_width, options_->viewfinder_height);
|
|
- else if (area)
|
|
- {
|
|
- // The idea here is that most sensors will have a 2x2 binned mode that
|
|
- // we can pick up. If it doesn't, well, you can always specify the size
|
|
- // you want exactly with the viewfinder_width/height options_->
|
|
- size = (*area)[0].size() / 2;
|
|
- // If width and height were given, we might be switching to capture
|
|
- // afterwards - so try to match the field of view.
|
|
- if (options_->width && options_->height)
|
|
- size = size.boundedToAspectRatio(Size(options_->width, options_->height));
|
|
- size.alignDownTo(2, 2); // YUV420 will want to be even
|
|
- LOG(2, "Viewfinder size chosen is " << size.toString());
|
|
- }
|
|
+ //else if (area)
|
|
+ //{
|
|
+ // // The idea here is that most sensors will have a 2x2 binned mode that
|
|
+ // // we can pick up. If it doesn't, well, you can always specify the size
|
|
+ // // you want exactly with the viewfinder_width/height options_->
|
|
+ // size = (*area)[0].size() / 2;
|
|
+ // // If width and height were given, we might be switching to capture
|
|
+ // // afterwards - so try to match the field of view.
|
|
+ // if (options_->width && options_->height)
|
|
+ // size = size.boundedToAspectRatio(Size(options_->width, options_->height));
|
|
+ // size.alignDownTo(2, 2); // YUV420 will want to be even
|
|
+ // LOG(2, "Viewfinder size chosen is " << size.toString());
|
|
+ //}
|
|
|
|
// Finally trim the image size to the largest that the preview can handle.
|
|
Size max_size;
|
|
@@ -275,7 +276,7 @@ void LibcameraApp::ConfigureViewfinder()
|
|
}
|
|
|
|
// Now we get to override any of the default settings from the options_->
|
|
- configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
|
|
+ //configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
|
|
configuration_->at(0).size = size;
|
|
if (options_->viewfinder_buffer_count > 0)
|
|
configuration_->at(0).bufferCount = options_->viewfinder_buffer_count;
|
|
@@ -286,7 +287,7 @@ void LibcameraApp::ConfigureViewfinder()
|
|
lores_size.alignDownTo(2, 2);
|
|
if (lores_size.width > size.width || lores_size.height > size.height)
|
|
throw std::runtime_error("Low res image larger than viewfinder");
|
|
- configuration_->at(lores_stream_num).pixelFormat = libcamera::formats::YUV420;
|
|
+ //configuration_->at(lores_stream_num).pixelFormat = libcamera::formats::YUV420;
|
|
configuration_->at(lores_stream_num).size = lores_size;
|
|
configuration_->at(lores_stream_num).bufferCount = configuration_->at(0).bufferCount;
|
|
}
|
|
@@ -297,7 +298,7 @@ void LibcameraApp::ConfigureViewfinder()
|
|
if (have_raw_stream)
|
|
{
|
|
configuration_->at(raw_stream_num).size = options_->viewfinder_mode.Size();
|
|
- configuration_->at(raw_stream_num).pixelFormat = mode_to_pixel_format(options_->viewfinder_mode);
|
|
+ //configuration_->at(raw_stream_num).pixelFormat = mode_to_pixel_format(options_->viewfinder_mode);
|
|
configuration_->at(raw_stream_num).bufferCount = configuration_->at(0).bufferCount;
|
|
}
|
|
|
|
@@ -335,8 +336,9 @@ void LibcameraApp::ConfigureStill(unsigned int flags)
|
|
configuration_->at(0).pixelFormat = libcamera::formats::BGR888;
|
|
else if (flags & FLAG_STILL_RGB)
|
|
configuration_->at(0).pixelFormat = libcamera::formats::RGB888;
|
|
- else
|
|
- configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
|
|
+ else {
|
|
+ //configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
|
|
+ }
|
|
if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_DOUBLE_BUFFER)
|
|
configuration_->at(0).bufferCount = 2;
|
|
else if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_TRIPLE_BUFFER)
|
|
@@ -358,8 +360,8 @@ void LibcameraApp::ConfigureStill(unsigned int flags)
|
|
configuration_->at(1).pixelFormat = mode_to_pixel_format(options_->mode);
|
|
}
|
|
configuration_->at(1).bufferCount = configuration_->at(0).bufferCount;
|
|
-
|
|
configureDenoise(options_->denoise == "auto" ? "cdn_hq" : options_->denoise);
|
|
+
|
|
setupCapture();
|
|
|
|
streams_["still"] = configuration_->at(0).stream();
|
|
@@ -392,7 +394,7 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
|
|
|
|
// Now we get to override any of the default settings from the options_->
|
|
StreamConfiguration &cfg = configuration_->at(0);
|
|
- cfg.pixelFormat = libcamera::formats::YUV420;
|
|
+ //cfg.pixelFormat = libcamera::formats::YUV420;
|
|
cfg.bufferCount = 6; // 6 buffers is better than 4
|
|
if (options_->buffer_count > 0)
|
|
cfg.bufferCount = options_->buffer_count;
|
|
@@ -431,7 +433,7 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
|
|
if (lores_size.width > configuration_->at(0).size.width ||
|
|
lores_size.height > configuration_->at(0).size.height)
|
|
throw std::runtime_error("Low res image larger than video");
|
|
- configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
|
|
+ //configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
|
|
configuration_->at(lores_index).size = lores_size;
|
|
configuration_->at(lores_index).bufferCount = configuration_->at(0).bufferCount;
|
|
}
|
|
@@ -959,8 +961,9 @@ void LibcameraApp::previewThread()
|
|
preview_cond_var_.wait(lock);
|
|
}
|
|
|
|
- if (item.stream->configuration().pixelFormat != libcamera::formats::YUV420)
|
|
- throw std::runtime_error("Preview windows only support YUV420");
|
|
+ if (item.stream->configuration().pixelFormat != libcamera::formats::YUV420 &&
|
|
+ item.stream->configuration().pixelFormat != libcamera::formats::NV12)
|
|
+ throw std::runtime_error("Preview windows only support YUV420 and NV12");
|
|
|
|
StreamInfo info = GetStreamInfo(item.stream);
|
|
FrameBuffer *buffer = item.completed_request->buffers[item.stream];
|
|
diff --git a/preview/drm_preview.cpp b/preview/drm_preview.cpp
|
|
index 4d6cf0d..38fc6a2 100644
|
|
--- a/preview/drm_preview.cpp
|
|
+++ b/preview/drm_preview.cpp
|
|
@@ -10,6 +10,8 @@
|
|
#include <drm_mode.h>
|
|
#include <xf86drm.h>
|
|
#include <xf86drmMode.h>
|
|
+#include <fcntl.h>
|
|
+#include <libcamera/formats.h>
|
|
|
|
#include "core/options.hpp"
|
|
|
|
@@ -48,6 +50,7 @@ private:
|
|
void findPlane();
|
|
int drmfd_;
|
|
int conId_;
|
|
+ drmModeConnector *con_;
|
|
uint32_t crtcId_;
|
|
int crtcIdx_;
|
|
uint32_t planeId_;
|
|
@@ -93,10 +96,21 @@ void DrmPreview::findCrtc()
|
|
if (con->encoder_id)
|
|
{
|
|
enc = drmModeGetEncoder(drmfd_, con->encoder_id);
|
|
- if (enc->crtc_id)
|
|
- {
|
|
- crtc = drmModeGetCrtc(drmfd_, enc->crtc_id);
|
|
- }
|
|
+ //if (enc->crtc_id)
|
|
+ //{
|
|
+ // crtc = drmModeGetCrtc(drmfd_, enc->crtc_id);
|
|
+ //}
|
|
+ } else
|
|
+ {
|
|
+ enc = drmModeGetEncoder(drmfd_, con->encoders[0]);
|
|
+ }
|
|
+
|
|
+ if (enc->crtc_id)
|
|
+ {
|
|
+ crtc = drmModeGetCrtc(drmfd_, enc->crtc_id);
|
|
+ } else
|
|
+ {
|
|
+ crtc = drmModeGetCrtc(drmfd_, res->crtcs[0]);
|
|
}
|
|
|
|
if (!conId_ && crtc)
|
|
@@ -158,6 +172,8 @@ void DrmPreview::findCrtc()
|
|
throw std::runtime_error("connector supports no mode");
|
|
}
|
|
|
|
+ con_ = c;
|
|
+
|
|
if (options_->fullscreen || width_ == 0 || height_ == 0)
|
|
{
|
|
drmModeCrtc *crtc = drmModeGetCrtc(drmfd_, crtcId_);
|
|
@@ -225,10 +241,13 @@ void DrmPreview::findPlane()
|
|
|
|
DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1), first_time_(true)
|
|
{
|
|
- drmfd_ = drmOpen("vc4", NULL);
|
|
+ //drmfd_ = drmOpen("vc4", NULL);
|
|
+ drmfd_ = drmOpen("starfive", NULL);
|
|
if (drmfd_ < 0)
|
|
throw std::runtime_error("drmOpen failed: " + std::string(ERRSTR));
|
|
|
|
+ drmSetClientCap(drmfd_, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
|
+
|
|
x_ = options_->preview_x;
|
|
y_ = options_->preview_y;
|
|
width_ = options_->preview_width;
|
|
@@ -243,7 +262,8 @@ DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1),
|
|
|
|
conId_ = 0;
|
|
findCrtc();
|
|
- out_fourcc_ = DRM_FORMAT_YUV420;
|
|
+ //out_fourcc_ = DRM_FORMAT_YUV420;
|
|
+ out_fourcc_ = DRM_FORMAT_NV12;
|
|
findPlane();
|
|
}
|
|
catch (std::exception const &e)
|
|
@@ -347,6 +367,7 @@ static void setup_colour_space(int fd, int plane_id, std::optional<libcamera::Co
|
|
|
|
void DrmPreview::makeBuffer(int fd, size_t size, StreamInfo const &info, Buffer &buffer)
|
|
{
|
|
+ unsigned int width = info.width, height = info.height, stride = info.stride;
|
|
if (first_time_)
|
|
{
|
|
first_time_ = false;
|
|
@@ -361,13 +382,52 @@ void DrmPreview::makeBuffer(int fd, size_t size, StreamInfo const &info, Buffer
|
|
if (drmPrimeFDToHandle(drmfd_, fd, &buffer.bo_handle))
|
|
throw std::runtime_error("drmPrimeFDToHandle failed for fd " + std::to_string(fd));
|
|
|
|
- uint32_t offsets[4] =
|
|
- { 0, info.stride * info.height, info.stride * info.height + (info.stride / 2) * (info.height / 2) };
|
|
- uint32_t pitches[4] = { info.stride, info.stride / 2, info.stride / 2 };
|
|
- uint32_t bo_handles[4] = { buffer.bo_handle, buffer.bo_handle, buffer.bo_handle };
|
|
-
|
|
- if (drmModeAddFB2(drmfd_, info.width, info.height, out_fourcc_, bo_handles, pitches, offsets, &buffer.fb_handle, 0))
|
|
+ if (out_fourcc_ == DRM_FORMAT_YUV420) {
|
|
+ uint32_t offsets[4] = { 0, stride * height, stride * height + (stride / 2) * (height / 2) };
|
|
+ uint32_t pitches[4] = { stride, stride / 2, stride / 2 };
|
|
+ uint32_t bo_handles[4] = { buffer.bo_handle, buffer.bo_handle, buffer.bo_handle };
|
|
+
|
|
+ if (drmModeAddFB2(drmfd_, width, height, out_fourcc_, bo_handles, pitches, offsets, &buffer.fb_handle, 0))
|
|
+ throw std::runtime_error("YUV420 drmModeAddFB2 failed: " + std::string(ERRSTR));
|
|
+ } else if (out_fourcc_ == DRM_FORMAT_NV12 || out_fourcc_ == DRM_FORMAT_NV21) {
|
|
+ uint32_t offsets[4] = { 0, stride * height};
|
|
+ uint32_t pitches[4] = { stride, stride};
|
|
+ uint32_t bo_handles[4] = { buffer.bo_handle, buffer.bo_handle};
|
|
+
|
|
+ if (drmModeAddFB2(drmfd_, width, height, out_fourcc_, bo_handles, pitches, offsets, &buffer.fb_handle, 0))
|
|
+ throw std::runtime_error("NV12/21 drmModeAddFB2 failed: " + std::string(ERRSTR));
|
|
+ } else
|
|
throw std::runtime_error("drmModeAddFB2 failed: " + std::string(ERRSTR));
|
|
+
|
|
+ /* find preferred mode */
|
|
+ drmModeModeInfo *modeptr = NULL, *preferred = NULL;
|
|
+ for (int m = 0; m < con_->count_modes; m++) {
|
|
+ modeptr = &con_->modes[m];
|
|
+ if (modeptr->hdisplay == width && modeptr->vdisplay == height) {
|
|
+ preferred = modeptr;
|
|
+ std::cout << "find the matched mode, modes index= "
|
|
+ << m << ", " << width << "x" << height << std::endl;
|
|
+ break;
|
|
+ }
|
|
+ if (modeptr->type & DRM_MODE_TYPE_PREFERRED) {
|
|
+ preferred = modeptr;
|
|
+ std::cout << "find perferred mode, modes index= " << m << std::endl;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!preferred)
|
|
+ preferred = &con_->modes[0];
|
|
+
|
|
+ // set default
|
|
+ if (drmModeSetCrtc(drmfd_, crtcId_, buffer.fb_handle, 0, 0,
|
|
+ (uint32_t *)&conId_, 1, preferred)) {
|
|
+ throw std::runtime_error("drmModeSetCrtc() failed");
|
|
+ }
|
|
+
|
|
+ screen_width_ = preferred->hdisplay;
|
|
+ screen_height_ = preferred->vdisplay;
|
|
+ width_ = width;
|
|
+ height_ = height;
|
|
}
|
|
|
|
void DrmPreview::Show(int fd, libcamera::Span<uint8_t> span, StreamInfo const &info)
|
|
--
|
|
2.34.1
|
|
|