Make 5 libcamera-apps work. They are libcamera-hello, libcamera-jpeg, libcamera-still, libcamera-raw, libcamera-vid

Signed-off-by: zejian.su <zejian.su@starfivetech.com>
This commit is contained in:
zejian.su
2023-11-01 17:58:58 +08:00
parent 53780ad297
commit e50c6c1b2b
11 changed files with 9232 additions and 991 deletions
@@ -0,0 +1,284 @@
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
@@ -1,489 +0,0 @@
From 6abadc7414f0fdfea160374326cea32bd2b40d7d Mon Sep 17 00:00:00 2001
From: sw.multimedia <sw.multimedia@starfivetech.com>
Date: Fri, 15 Oct 2021 10:55:01 +0800
Subject: [PATCH] add starfive support
---
CMakeLists.txt | 2 +-
core/CMakeLists.txt | 2 +-
core/libcamera_app.cpp | 38 ++++--
core/options.hpp | 3 +
preview/CMakeLists.txt | 9 ++
preview/fb_preview.cpp | 289 +++++++++++++++++++++++++++++++++++++++++
preview/preview.cpp | 7 +-
7 files changed, 338 insertions(+), 12 deletions(-)
create mode 100644 preview/fb_preview.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2293211..253ec8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,7 +12,7 @@ endif()
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic -Wno-unused-parameter -faligned-new")
-add_definitions(-Werror)
+# add_definitions(-Werror)
add_definitions(-Wfatal-errors)
add_definitions(-D_FILE_OFFSET_BITS=64)
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 1618541..84316b2 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -11,6 +11,6 @@ add_library(libcamera_app libcamera_app.cpp post_processor.cpp version.cpp)
add_dependencies(libcamera_app VersionCpp)
set_target_properties(libcamera_app PROPERTIES PREFIX "" IMPORT_PREFIX "")
-target_link_libraries(libcamera_app pthread preview ${LIBCAMERA_LINK_LIBRARIES} ${Boost_LIBRARIES} post_processing_stages)
+target_link_libraries(libcamera_app pthread preview ${LIBCAMERA_LIBRARIES} ${Boost_LIBRARIES} post_processing_stages)
install(TARGETS libcamera_app LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/core/libcamera_app.cpp b/core/libcamera_app.cpp
index 7d4e28f..3c4d862 100644
--- a/core/libcamera_app.cpp
+++ b/core/libcamera_app.cpp
@@ -134,7 +134,12 @@ void LibcameraApp::ConfigureViewfinder()
}
// Now we get to override any of the default settings from the options_->
- configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
+ std::cout << "viewfinder pixelformat: " << options_->pixelformat << std::endl;
+ if (options_->pixelformat.length())
+ configuration_->at(0).pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+ else
+ configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
configuration_->at(0).size = size;
if (have_lores_stream)
@@ -143,7 +148,11 @@ 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(1).pixelFormat = libcamera::formats::YUV420;
+ if (options_->pixelformat.length())
+ configuration_->at(0).pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+ else
+ configuration_->at(1).pixelFormat = libcamera::formats::YUV420;
configuration_->at(1).size = lores_size;
configuration_->at(1).bufferCount = configuration_->at(0).bufferCount;
}
@@ -186,8 +195,13 @@ 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 {
+ if (options_->pixelformat.length())
+ configuration_->at(0).pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+ 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)
@@ -241,7 +255,11 @@ void LibcameraApp::ConfigureVideo(unsigned int flags)
throw std::runtime_error("failed to generate video configuration");
// Now we get to override any of the default settings from the options_->
- configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
+ if (options_->pixelformat.length())
+ configuration_->at(0).pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+ else
+ configuration_->at(0).pixelFormat = libcamera::formats::YUV420;
configuration_->at(0).bufferCount = 6; // 6 buffers is better than 4
if (options_->width)
configuration_->at(0).size.width = options_->width;
@@ -267,7 +285,11 @@ 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;
+ if (options_->pixelformat.length())
+ configuration_->at(0).pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+ else
+ configuration_->at(lores_index).pixelFormat = libcamera::formats::YUV420;
configuration_->at(lores_index).size = lores_size;
configuration_->at(lores_index).bufferCount = configuration_->at(0).bufferCount;
}
@@ -713,8 +735,8 @@ 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)
+ // throw std::runtime_error("Preview windows only support YUV420");
unsigned int w, h, stride;
StreamDimensions(item.stream, &w, &h, &stride);
diff --git a/core/options.hpp b/core/options.hpp
index 447983f..5c68088 100644
--- a/core/options.hpp
+++ b/core/options.hpp
@@ -43,6 +43,8 @@ struct Options
"Set the output image width (0 = use default value)")
("height", value<unsigned int>(&height)->default_value(0),
"Set the output image height (0 = use default value)")
+ ("pixelformat", value<std::string>(&pixelformat),
+ "Set the pixelformat name")
("timeout,t", value<uint64_t>(&timeout)->default_value(5000),
"Time (in ms) for which program runs")
("output,o", value<std::string>(&output),
@@ -119,6 +121,7 @@ struct Options
std::string post_process_file;
unsigned int width;
unsigned int height;
+ std::string pixelformat;
bool rawfull;
bool nopreview;
std::string preview;
diff --git a/preview/CMakeLists.txt b/preview/CMakeLists.txt
index 1a7481f..a772e14 100644
--- a/preview/CMakeLists.txt
+++ b/preview/CMakeLists.txt
@@ -63,6 +63,15 @@ else()
message(STATUS "QT display mode will be unavailable!")
endif()
+set(ENABLE_FB 1)
+if (ENABLE_FB)
+ set(SRC ${SRC} fb_preview.cpp)
+ set(FB_FOUND 1)
+ message(STATUS "FB display mode enabled")
+else()
+ message(STATUS "FB display mode will be unavailable!")
+endif()
+
add_library(preview null_preview.cpp ${SRC})
target_link_libraries(preview ${TARGET_LIBS})
diff --git a/preview/fb_preview.cpp b/preview/fb_preview.cpp
new file mode 100644
index 0000000..1a88b79
--- /dev/null
+++ b/preview/fb_preview.cpp
@@ -0,0 +1,289 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2021, Raspberry Pi (Trading) Ltd.
+ *
+ * null_preview.cpp - dummy "show nothing" preview window.
+ */
+
+#include <iostream>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <string.h>
+#include <malloc.h>
+#include <linux/videodev2.h>
+#include <libcamera/formats.h>
+#include <chrono>
+
+#include "core/options.hpp"
+
+#include "preview.hpp"
+
+#define FBIOPAN_GET_PP_MODE 0x4609
+#define FBIOPAN_SET_PP_MODE 0x460a
+
+enum COLOR_FORMAT {
+ COLOR_YUV422_UYVY = 0, // 00={Y1,V0,Y0,U0}
+ COLOR_YUV422_VYUY = 1, // 01={Y1,U0,Y0,V0}
+ COLOR_YUV422_YUYV = 2, // 10={V0,Y1,U0,Y0}
+ COLOR_YUV422_YVYU = 3, // 11={U0,Y1,V0,Y0}
+
+ COLOR_YUV420P, // 4
+ COLOR_YUV420_NV21, // 5
+ COLOR_YUV420_NV12, // 6
+
+ COLOR_RGB888_ARGB, // 7
+ COLOR_RGB888_ABGR, // 8
+ COLOR_RGB888_RGBA, // 9
+ COLOR_RGB888_BGRA, // 10
+ COLOR_RGB565, // 11
+};
+
+struct pp_video_mode {
+ enum COLOR_FORMAT format;
+ unsigned int height;
+ unsigned int width;
+ unsigned int addr;
+};
+
+struct pp_mode {
+ char pp_id;
+ bool bus_out; /*out to ddr*/
+ bool fifo_out; /*out to lcdc*/
+ bool inited;
+ struct pp_video_mode src;
+ struct pp_video_mode dst;
+};
+
+class FbPreview : public Preview
+{
+public:
+ FbPreview(Options const *options);
+ ~FbPreview();
+ void SetInfoText(const std::string &text) override
+ {
+ std::cout << "Camera fps: " << text << std::endl;
+ }
+ // Display the buffer. You get given the fd back in the BufferDoneCallback
+ // once its available for re-use.
+ virtual void Show(int fd, libcamera::Span<uint8_t> span, int width, int height, int stride) override;
+ // Reset the preview window, clearing the current buffers and being ready to
+ // show new ones.
+ void Reset() override {}
+ // Return the maximum image size allowed. Zeroes mean "no limit".
+ virtual void MaxImageSize(unsigned int &w, unsigned int &h) const override { w = h = 0; }
+
+private:
+ int NVResize(unsigned char *inBuf,
+ unsigned char *outBuf, int imgWidth, int imgHeight);
+ int g_fb_fd;
+ int g_stfbc_fd;
+ struct fb_var_screeninfo g_vinfo;
+ struct fb_fix_screeninfo g_finfo;
+ unsigned char *g_fb_buf;
+ unsigned char *tmpBuf;
+ unsigned int g_screensize;
+ enum COLOR_FORMAT pixformat;
+};
+
+static enum COLOR_FORMAT v4l2fmt_to_fbfmt(unsigned int format)
+{
+ enum COLOR_FORMAT pixformat = COLOR_RGB565;
+
+ switch (format) {
+ case V4L2_PIX_FMT_RGB565:
+ pixformat = COLOR_RGB565;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ pixformat = COLOR_RGB888_ARGB;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ pixformat = COLOR_YUV420P;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ pixformat = COLOR_YUV422_YUYV;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ pixformat = COLOR_YUV420_NV21;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ pixformat = COLOR_YUV420_NV12;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ pixformat = COLOR_YUV422_YVYU;
+ break;
+ default:
+ pixformat = COLOR_RGB565;
+ break;
+ }
+
+ return pixformat;
+}
+
+FbPreview::FbPreview(Options const *options) : Preview(options)
+{
+ g_fb_fd = open("/dev/fb0", O_RDWR);
+ if (g_fb_fd == -1)
+ throw std::runtime_error("Couldn't open fb display");
+ g_stfbc_fd = open("/dev/stfbcdev", O_RDWR);
+ if (g_stfbc_fd == -1)
+ throw std::runtime_error("Couldn't open stfbcdev display");
+
+ struct pp_mode pp_info[3];
+ libcamera::PixelFormat pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+
+ if (pixelFormat.fourcc() != V4L2_PIX_FMT_NV12)
+ throw std::runtime_error("FB onlu support NV12 display");
+
+ pixformat = v4l2fmt_to_fbfmt(pixelFormat.fourcc());
+ if (-1 == ioctl(g_stfbc_fd, FBIOPAN_GET_PP_MODE, &pp_info[0]))
+ throw std::runtime_error("Error reading variable information.");
+
+ std::cout << "get pp format : "
+ << pp_info[1].src.format
+ << std::endl;
+
+ pp_info[1].src.format = pixformat;
+
+ if (-1 == ioctl(g_stfbc_fd, FBIOPAN_SET_PP_MODE, &pp_info[0]))
+ throw std::runtime_error("Error reading variable information.");
+
+ if (-1 == ioctl(g_stfbc_fd, FBIOPAN_GET_PP_MODE, &pp_info[0]))
+ throw std::runtime_error("Error reading variable information.");
+
+ std::cout << "get pp format : "
+ << pp_info[1].src.format
+ << std::endl;
+
+ pixformat = pp_info[1].src.format;
+
+ // Get fixed screen information
+ if (-1 == ioctl(g_fb_fd, FBIOGET_FSCREENINFO, &g_finfo))
+ throw std::runtime_error("Error reading fixed information.");
+
+ // Get variable screen information
+ if (-1 == ioctl(g_fb_fd, FBIOGET_VSCREENINFO, &g_vinfo))
+ throw std::runtime_error("Error reading variable information.");
+
+ std::cout << "g_vinfo.xres = " << g_vinfo.xres
+ << ", g_vinfo.yres = " << g_vinfo.yres
+ << ", grayscale = " << g_vinfo.grayscale
+ << std::endl;
+ std::cout << "g_vinfo.xoffset = " << g_vinfo.xoffset
+ << ", g_vinfo.yoffset = " << g_vinfo.yoffset
+ << std::endl;
+ std::cout << "g_vinfo.bits_per_pixel = " << g_vinfo.bits_per_pixel
+ << ", g_finfo.line_length = " << g_finfo.line_length
+ << std::endl;
+
+ g_screensize = g_vinfo.xres * g_vinfo.yres * g_vinfo.bits_per_pixel / 8;
+ g_fb_buf = (unsigned char *)mmap(NULL, g_screensize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fb_fd, 0);
+ if (g_fb_buf == (void *)(-1))
+ throw std::runtime_error("Error: failed to map framebuffer device to memory.");
+
+ memset(g_fb_buf, 0x00, g_screensize);
+ tmpBuf = static_cast<unsigned char *>(malloc(g_screensize));
+ if (!tmpBuf)
+ throw std::runtime_error("Error: failed to malloc memory.");
+ memset(tmpBuf, 0x00, g_screensize);
+
+ if (options->verbose)
+ std::cout << "Running fb preview window" << std::endl;
+}
+
+FbPreview::~FbPreview()
+{
+ free(tmpBuf);
+ munmap((void *)g_fb_buf, g_screensize);
+ close(g_fb_fd);
+ close(g_stfbc_fd);
+ std::cout << "fb preview window ~FbPreview" << std::endl;
+}
+
+int FbPreview::NVResize(unsigned char *inBuf,
+ unsigned char *outBuf, int imgWidth, int imgHeight)
+{
+ int rows, cols;
+ unsigned char *OutNVdata, *InNVdata;
+ int Ypos, Upos, Vpos;
+ int fb_Ypos, fb_Upos, fb_Vpos;
+ int width, height;
+ int x_offset, y_offset;
+ unsigned int start_timems;
+ unsigned int end_timems;
+ struct timeval ts_start, ts_end;
+
+ width = imgWidth > g_vinfo.xres ? g_vinfo.xres : imgWidth;
+ height = imgHeight > g_vinfo.yres ? g_vinfo.yres : imgHeight;
+ x_offset = (g_vinfo.xres - width) / 2;
+ y_offset = (g_vinfo.yres - height) / 2;
+
+ InNVdata = inBuf;
+ OutNVdata = tmpBuf;
+
+ if (imgWidth == g_vinfo.xres) {
+ fb_Ypos = y_offset * g_vinfo.xres + x_offset;
+ fb_Upos = (y_offset / 2 * g_vinfo.xres / 2 + x_offset / 2) * 2;
+ fb_Upos = g_vinfo.xres * g_vinfo.yres + fb_Upos;
+ Upos = imgWidth * imgHeight;
+ memcpy(&tmpBuf[fb_Ypos], inBuf, imgWidth * height);
+ memcpy(&tmpBuf[fb_Upos], &inBuf[Upos], imgWidth * height / 2);
+ memcpy(&outBuf[fb_Ypos], &tmpBuf[fb_Ypos], imgWidth * height * 2);
+ memcpy(&outBuf[fb_Upos], &tmpBuf[fb_Upos], imgWidth * height / 2);
+ return 0;
+ }
+
+ /* two bytes for every pixels */
+ for(rows = 0; rows < height; rows+=2)
+ {
+ // g_vinfo.xres, g_vinfo.yres g_vinfo.bits_per_pixel
+ fb_Ypos = ((rows + y_offset) * g_vinfo.xres + x_offset);
+ fb_Upos = ((rows + y_offset) / 2 * g_vinfo.xres / 2 + x_offset / 2) * 2;
+ fb_Upos = g_vinfo.xres * g_vinfo.yres + fb_Upos;
+ fb_Vpos = fb_Upos + 1;
+
+ Ypos = rows * imgWidth;
+ Upos = imgWidth * imgHeight + Ypos / 2;
+ Vpos = Upos + 1;
+ memcpy(&OutNVdata[fb_Ypos], &InNVdata[Ypos], width);
+ memcpy(&OutNVdata[fb_Ypos+g_vinfo.xres], &InNVdata[Ypos+imgWidth], width);
+
+ memcpy(&OutNVdata[fb_Upos], &InNVdata[Upos], width);
+ }
+
+ memcpy(outBuf, tmpBuf, g_screensize);
+
+ return 0;
+}
+
+void FbPreview::Show(int fd, libcamera::Span<uint8_t> span, int width, int height, int stride)
+{
+ int imgsize = stride * height + stride * height / 2;
+ auto startTime = std::chrono::high_resolution_clock::now();
+
+ if (pixformat == COLOR_YUV420_NV21 || pixformat == COLOR_YUV420_NV12)
+ NVResize(span.data(), g_fb_buf, width, height);
+ else
+ std::cout << "FbPreview unsupport pixformat: " << pixformat << std::endl;
+
+ auto endTime = std::chrono::high_resolution_clock::now();
+
+ std::chrono::duration<double,std::ratio<1,1000000>> duration_mcs =
+ std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1,1000000>>>(endTime-startTime);
+ std::cout << "FbPreview copy fps " << 1000000 / duration_mcs.count() << "." << std::endl;
+
+ done_callback_(fd);
+}
+
+Preview *make_fb_preview(Options const *options)
+{
+ return new FbPreview(options);
+}
diff --git a/preview/preview.cpp b/preview/preview.cpp
index 68d193a..0086d83 100644
--- a/preview/preview.cpp
+++ b/preview/preview.cpp
@@ -13,6 +13,7 @@ Preview *make_null_preview(Options const *options);
Preview *make_egl_preview(Options const *options);
Preview *make_drm_preview(Options const *options);
Preview *make_qt_preview(Options const *options);
+Preview *make_fb_preview(Options const *options);
Preview *make_preview(Options const *options)
{
@@ -48,8 +49,10 @@ Preview *make_preview(Options const *options)
}
catch (std::exception const &e)
{
- std::cout << "Preview window unavailable" << std::endl;
- return make_null_preview(options);
+ std::cout << "FB Preview window." << std::endl;
+ return make_fb_preview(options);
+ // std::cout << "Preview window unavailable" << std::endl;
+ // return make_null_preview(options);
}
}
}
--
2.17.1
@@ -0,0 +1,222 @@
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
@@ -1,92 +0,0 @@
From aec56c70bdc7f037a88deaa4cc84854ec2c961e9 Mon Sep 17 00:00:00 2001
From: sw.multimedia <sw.multimedia@starfivetech.com>
Date: Mon, 22 Nov 2021 10:16:15 +0800
Subject: [PATCH] add select camera options
---
core/libcamera_app.cpp | 29 +++++++++++++++++++++--------
core/options.hpp | 5 +++++
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/core/libcamera_app.cpp b/core/libcamera_app.cpp
index 3c4d862..22896a7 100644
--- a/core/libcamera_app.cpp
+++ b/core/libcamera_app.cpp
@@ -58,17 +58,30 @@ void LibcameraApp::OpenCamera()
if (camera_manager_->cameras().size() == 0)
throw std::runtime_error("no cameras available");
- std::string const &cam_id = camera_manager_->cameras()[0]->id();
- camera_ = camera_manager_->get(cam_id);
- if (!camera_)
- throw std::runtime_error("failed to find camera " + cam_id);
-
- if (camera_->acquire())
- throw std::runtime_error("failed to acquire camera " + cam_id);
+ if (options_->camera_name.length()) {
+ char *endptr;
+ unsigned long index = strtoul(options_->camera_name.c_str(), &endptr, 10);
+ std::cout << "Acquired camera name: " << options_->camera_name << std::endl;
+ if (*endptr == '\0' && index > 0 && index <= camera_manager_->cameras().size())
+ camera_ = camera_manager_->cameras()[index - 1];
+ else
+ camera_ = camera_manager_->get(options_->camera_name);
+ if (!camera_)
+ throw std::runtime_error("failed to find camera " + options_->camera_name);
+ if (camera_->acquire())
+ throw std::runtime_error("failed to acquire camera " + options_->camera_name);
+ } else {
+ std::string const &cam_id = camera_manager_->cameras()[0]->id();
+ camera_ = camera_manager_->get(cam_id);
+ if (!camera_)
+ throw std::runtime_error("failed to find camera " + cam_id);
+ if (camera_->acquire())
+ throw std::runtime_error("failed to acquire camera " + cam_id);
+ }
camera_acquired_ = true;
if (options_->verbose)
- std::cout << "Acquired camera " << cam_id << std::endl;
+ std::cout << "Acquired camera " << camera_->id() << std::endl;
if (!options_->post_process_file.empty())
post_processor_.Read(options_->post_process_file);
diff --git a/core/options.hpp b/core/options.hpp
index 5c68088..de49beb 100644
--- a/core/options.hpp
+++ b/core/options.hpp
@@ -30,6 +30,8 @@ struct Options
"Displays the build version number")
("verbose,v", value<bool>(&verbose)->default_value(false)->implicit_value(true),
"Output extra debug and diagnostics")
+ ("camera", value<std::string>(&camera_name),
+ "Specify which camera to operate on, by id or by index")
("config,c", value<std::string>(&config_file)->implicit_value("config.txt"),
"Read the options from a file. If no filename is specified, default to config.txt. "
"In case of duplicate options, the ones provided on the command line will be used. "
@@ -115,6 +117,7 @@ struct Options
bool help;
bool version;
bool verbose;
+ std::string camera_name;
uint64_t timeout; // in ms
std::string config_file;
std::string output;
@@ -259,12 +262,14 @@ struct Options
{
std::cout << "Options:" << std::endl;
std::cout << " verbose: " << verbose << std::endl;
+ std::cout << " camera_name: " << camera_name << std::endl;
if (!config_file.empty())
std::cout << " config file: " << config_file << std::endl;
std::cout << " info_text:" << info_text << std::endl;
std::cout << " timeout: " << timeout << std::endl;
std::cout << " width: " << width << std::endl;
std::cout << " height: " << height << std::endl;
+ std::cout << " pixelformat: " << pixelformat << std::endl;
std::cout << " output: " << output << std::endl;
std::cout << " post_process_file: " << post_process_file << std::endl;
std::cout << " rawfull: " << rawfull << std::endl;
--
2.17.1
@@ -0,0 +1,204 @@
From f79f0914c3f8e740cf653da0dd14e5664760188d Mon Sep 17 00:00:00 2001
From: "zejian.su" <zejian.su@starfivetech.com>
Date: Thu, 12 Oct 2023 11:56:48 +0800
Subject: [PATCH 3/4] Make libcamera-still run normally
---
apps/libcamera_still.cpp | 137 +++++++++++++++++++++++++--------------
image/dng.cpp | 1 -
2 files changed, 88 insertions(+), 50 deletions(-)
diff --git a/apps/libcamera_still.cpp b/apps/libcamera_still.cpp
index 856f1be..bd44818 100644
--- a/apps/libcamera_still.cpp
+++ b/apps/libcamera_still.cpp
@@ -74,22 +74,79 @@ static void update_latest_link(std::string const &filename, StillOptions const *
}
}
+void cvtRawData(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &packRaw, StreamInfo &info)
+{
+ const uint8_t *src = (uint8_t *)mem.data();
+ uint32_t width = info.width, height = info.height;
+ uint32_t bufSize = (width * height) + ((width * height) >> 1);
+ uint8_t * dstBuf = new uint8_t[bufSize];
+ uint8_t * dst = dstBuf;
+ uint32_t srcStride = ((width * 12 / 8 + 8 * 16 - 1) / (8 * 16)) * 128;
+
+ if(!dst)
+ throw std::runtime_error("fail to apply memory");
+
+ for(uint32_t i = 0; i < height; i++, src += srcStride, dst += (3 * width) >> 1) {
+ const uint8_t *srcRow = src;
+ uint8_t * dstRow = dst;
+ for(uint32_t j = 0; j < width; j += 2, srcRow += 3, dstRow += 3) {
+ dstRow[0] = ((srcRow[1] & 0xf) << 4) | (srcRow[0] >> 4);
+ dstRow[1] = srcRow[2];
+ dstRow[2] = (srcRow[1] & 0xf0) | (srcRow[0] & 0xf);
+ }
+ }
+
+ packRaw.push_back(libcamera::Span<uint8_t>(dstBuf, bufSize));
+
+ if(libcamera::formats::SRGGB12 == info.pixel_format)
+ info.pixel_format = libcamera::formats::SRGGB12_CSI2P;
+ else if(libcamera::formats::SGRBG12 == info.pixel_format)
+ info.pixel_format = libcamera::formats::SGRBG12_CSI2P;
+ else if(libcamera::formats::SBGGR12 == info.pixel_format)
+ info.pixel_format = libcamera::formats::SBGGR12_CSI2P;
+ else if(libcamera::formats::SGBRG12 == info.pixel_format)
+ info.pixel_format = libcamera::formats::SGBRG12_CSI2P;
+ else
+ throw std::runtime_error("unsupported Bayer format");
+ info.stride = (3 * width) >> 1;
+}
+
+void NV12ToYUV420(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &yuv420, StreamInfo &info);
+void NV12ToRGB888(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info);
+void NV12ToBGR888(const libcamera::Span<uint8_t> &mem, std::vector<libcamera::Span<uint8_t>> &rgb888, StreamInfo &info);
+
static void save_image(LibcameraStillApp &app, CompletedRequestPtr &payload, Stream *stream,
std::string const &filename)
{
StillOptions const *options = app.GetOptions();
StreamInfo info = app.GetStreamInfo(stream);
const std::vector<libcamera::Span<uint8_t>> mem = app.Mmap(payload->buffers[stream]);
- if (stream == app.RawStream())
- dng_save(mem, info, payload->metadata, filename, app.CameraModel(), options);
- else if (options->encoding == "jpg")
- jpeg_save(mem, info, payload->metadata, filename, app.CameraModel(), options);
- else if (options->encoding == "png")
- png_save(mem, info, filename, options);
- else if (options->encoding == "bmp")
- bmp_save(mem, info, filename, options);
- else
- yuv_save(mem, info, filename, options);
+ if (stream == app.RawStream()) {
+ std::vector<libcamera::Span<uint8_t>> packRaw;
+ cvtRawData(mem[0], packRaw, info);
+ dng_save(packRaw, info, payload->metadata, filename, app.CameraModel(), options);
+ delete[] packRaw[0].data();
+ } else if (options->encoding == "jpg") {
+ std::vector<libcamera::Span<uint8_t>> yuv420;
+ NV12ToYUV420(mem[0], yuv420, info);
+ jpeg_save(yuv420, info, payload->metadata, filename, app.CameraModel(), options);
+ delete[] yuv420[0].data();
+ } else if (options->encoding == "png") {
+ std::vector<libcamera::Span<uint8_t>> rgb888;
+ NV12ToBGR888(mem[0], rgb888, info);
+ png_save(rgb888, info, filename, options);
+ delete[] rgb888[0].data();
+ } else if (options->encoding == "bmp") {
+ std::vector<libcamera::Span<uint8_t>> rgb888;
+ NV12ToRGB888(mem[0], rgb888, info);
+ bmp_save(rgb888, info, filename, options);
+ delete[] rgb888[0].data();
+ } else {
+ std::vector<libcamera::Span<uint8_t>> yuv420;
+ NV12ToYUV420(mem[0], yuv420, info);
+ yuv_save(yuv420, info, filename, options);
+ delete[] yuv420[0].data();
+ }
LOG(2, "Saved image " << info.width << " x " << info.height << " to file " << filename);
}
@@ -193,7 +250,7 @@ static void event_loop(LibcameraStillApp &app)
}
}
else
- app.ConfigureViewfinder();
+ app.ConfigureStill();
app.StartCamera();
auto start_time = std::chrono::high_resolution_clock::now();
auto timelapse_time = start_time;
@@ -234,7 +291,7 @@ static void event_loop(LibcameraStillApp &app)
// In viewfinder mode, run until the timeout or keypress. When that happens,
// if the "--autofocus-on-capture" option was set, trigger an AF scan and wait
// for it to complete. Then switch to capture mode if an output was requested.
- if (app.ViewfinderStream())
+ if (app.StillStream())
{
LOG(2, "Viewfinder frame " << count);
timelapse_frames++;
@@ -280,47 +337,29 @@ static void event_loop(LibcameraStillApp &app)
keypressed = false;
af_wait_state = AF_WAIT_NONE;
timelapse_time = std::chrono::high_resolution_clock::now();
+
+ save_images(app, completed_request);
+ if (!options->metadata.empty())
+ save_metadata(options, completed_request->metadata);
+
app.StopCamera();
app.Teardown();
- app.ConfigureStill(still_flags);
- if (options->af_on_capture)
- {
- libcamera::ControlList cl;
- cl.set(libcamera::controls::AfMode, libcamera::controls::AfModeAuto);
- cl.set(libcamera::controls::AfTrigger, libcamera::controls::AfTriggerCancel);
- app.SetControls(cl);
- }
- app.StartCamera();
- }
- else
- app.ShowPreview(completed_request, app.ViewfinderStream());
- }
- // In still capture mode, save a jpeg. Go back to viewfinder if in timelapse mode,
- // otherwise quit.
- else if (app.StillStream())
- {
- app.StopCamera();
- LOG(1, "Still capture image received");
- save_images(app, completed_request);
- if (!options->metadata.empty())
- save_metadata(options, completed_request->metadata);
- timelapse_frames = 0;
- if (!options->immediate && (options->timelapse || options->signal || options->keypress))
- {
- app.Teardown();
- app.ConfigureViewfinder();
- if (options->af_on_capture && options->afMode_index == -1)
- {
- libcamera::ControlList cl;
- cl.set(libcamera::controls::AfMode, libcamera::controls::AfModeAuto);
- cl.set(libcamera::controls::AfTrigger, libcamera::controls::AfTriggerCancel);
- app.SetControls(cl);
- }
- app.StartCamera();
- af_wait_state = AF_WAIT_NONE;
+ if (!options->immediate && (options->timelapse || options->signal || options->keypress)){
+ app.ConfigureStill(still_flags);
+ if (options->af_on_capture)
+ {
+ libcamera::ControlList cl;
+ cl.set(libcamera::controls::AfMode, libcamera::controls::AfModeAuto);
+ cl.set(libcamera::controls::AfTrigger, libcamera::controls::AfTriggerCancel);
+ app.SetControls(cl);
+ }
+ app.StartCamera();
+ }
+ else
+ return;
}
else
- return;
+ app.ShowPreview(completed_request, app.StillStream());
}
}
}
diff --git a/image/dng.cpp b/image/dng.cpp
index fbc02bb..98cb5e7 100644
--- a/image/dng.cpp
+++ b/image/dng.cpp
@@ -151,7 +151,6 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamInfo const
std::string const &filename, std::string const &cam_model, StillOptions const *options)
{
// Check the Bayer format and unpack it to u16.
-
auto it = bayer_formats.find(info.pixel_format);
if (it == bayer_formats.end())
throw std::runtime_error("unsupported Bayer format");
--
2.34.1
@@ -1,224 +0,0 @@
From 4fd0d73ae92f4e0f49c9d0f9f7e559e55e4fe2a8 Mon Sep 17 00:00:00 2001
From: sw.multimedia <sw.multimedia@starfivetech.com>
Date: Mon, 22 Nov 2021 15:28:17 +0800
Subject: [PATCH] add FbPreview support YUYV/YVYU display
---
preview/fb_preview.cpp | 123 +++++++++++++++++++++++++++++++++++------
preview/preview.cpp | 15 +++--
2 files changed, 118 insertions(+), 20 deletions(-)
diff --git a/preview/fb_preview.cpp b/preview/fb_preview.cpp
index 1a88b79..0b42ad1 100644
--- a/preview/fb_preview.cpp
+++ b/preview/fb_preview.cpp
@@ -44,6 +44,7 @@ enum COLOR_FORMAT {
COLOR_RGB888_RGBA, // 9
COLOR_RGB888_BGRA, // 10
COLOR_RGB565, // 11
+ COLOR_UNKOWN, // unkown
};
struct pp_video_mode {
@@ -83,6 +84,10 @@ public:
private:
int NVResize(unsigned char *inBuf,
unsigned char *outBuf, int imgWidth, int imgHeight);
+ int YUYVResize(unsigned char *inBuf,
+ unsigned char *outBuf, int imgWidth, int imgHeight);
+ void setPixformat(unsigned int format);
+ unsigned int getPixformat(void);
int g_fb_fd;
int g_stfbc_fd;
struct fb_var_screeninfo g_vinfo;
@@ -93,10 +98,8 @@ private:
enum COLOR_FORMAT pixformat;
};
-static enum COLOR_FORMAT v4l2fmt_to_fbfmt(unsigned int format)
+void FbPreview::setPixformat(unsigned int format)
{
- enum COLOR_FORMAT pixformat = COLOR_RGB565;
-
switch (format) {
case V4L2_PIX_FMT_RGB565:
pixformat = COLOR_RGB565;
@@ -120,11 +123,43 @@ static enum COLOR_FORMAT v4l2fmt_to_fbfmt(unsigned int format)
pixformat = COLOR_YUV422_YVYU;
break;
default:
- pixformat = COLOR_RGB565;
+ pixformat = COLOR_UNKOWN;
break;
}
+}
- return pixformat;
+unsigned int FbPreview::getPixformat(void)
+{
+ unsigned int format;
+
+ switch (pixformat) {
+ case COLOR_RGB565:
+ format = V4L2_PIX_FMT_RGB565;
+ break;
+ case COLOR_RGB888_ARGB:
+ format = V4L2_PIX_FMT_RGB24;
+ break;
+ case COLOR_YUV420P:
+ format = V4L2_PIX_FMT_YUV420;
+ break;
+ case COLOR_YUV422_YUYV:
+ format = V4L2_PIX_FMT_YUYV;
+ break;
+ case COLOR_YUV420_NV21:
+ format = V4L2_PIX_FMT_NV21;
+ break;
+ case COLOR_YUV420_NV12:
+ format = V4L2_PIX_FMT_NV12;
+ break;
+ case COLOR_YUV422_YVYU:
+ format = V4L2_PIX_FMT_YVYU;
+ break;
+ default:
+ format = 0;
+ break;
+ }
+
+ return format;
}
FbPreview::FbPreview(Options const *options) : Preview(options)
@@ -140,10 +175,10 @@ FbPreview::FbPreview(Options const *options) : Preview(options)
libcamera::PixelFormat pixelFormat =
libcamera::PixelFormat::fromString(options_->pixelformat);
- if (pixelFormat.fourcc() != V4L2_PIX_FMT_NV12)
- throw std::runtime_error("FB onlu support NV12 display");
+ setPixformat(pixelFormat.fourcc());
+ if (pixformat == COLOR_UNKOWN)
+ throw std::runtime_error("FB unsupport format display.");
- pixformat = v4l2fmt_to_fbfmt(pixelFormat.fourcc());
if (-1 == ioctl(g_stfbc_fd, FBIOPAN_GET_PP_MODE, &pp_info[0]))
throw std::runtime_error("Error reading variable information.");
@@ -217,9 +252,6 @@ int FbPreview::NVResize(unsigned char *inBuf,
int fb_Ypos, fb_Upos, fb_Vpos;
int width, height;
int x_offset, y_offset;
- unsigned int start_timems;
- unsigned int end_timems;
- struct timeval ts_start, ts_end;
width = imgWidth > g_vinfo.xres ? g_vinfo.xres : imgWidth;
height = imgHeight > g_vinfo.yres ? g_vinfo.yres : imgHeight;
@@ -264,15 +296,74 @@ int FbPreview::NVResize(unsigned char *inBuf,
return 0;
}
+int FbPreview::YUYVResize(unsigned char *inBuf,
+ unsigned char *outBuf, int imgWidth, int imgHeight)
+{
+ int rows, cols;
+ unsigned char *OutNVdata, *InNVdata;
+ int Ypos, fb_Ypos;
+ int width, height;
+ int x_offset, y_offset;
+
+ width = imgWidth > g_vinfo.xres ? g_vinfo.xres : imgWidth;
+ height = imgHeight > g_vinfo.yres ? g_vinfo.yres : imgHeight;
+ x_offset = (g_vinfo.xres - width) / 2;
+ y_offset = (g_vinfo.yres - height) / 2;
+ x_offset &= ~0x1;
+
+ InNVdata = inBuf;
+ OutNVdata = tmpBuf;
+
+ if (imgWidth == g_vinfo.xres) {
+ fb_Ypos = y_offset * g_vinfo.xres + x_offset;
+ memcpy(&tmpBuf[fb_Ypos], inBuf, imgWidth * height * 2);
+ memcpy(&outBuf[fb_Ypos], &tmpBuf[fb_Ypos], imgWidth * height * 2);
+ return 0;
+ }
+
+ /* two bytes for every pixels */
+ for(rows = 0; rows < height; rows++)
+ {
+ // g_vinfo.xres, g_vinfo.yres g_vinfo.bits_per_pixel
+ fb_Ypos = ((rows + y_offset) * g_vinfo.xres + x_offset) * 2;
+ Ypos = rows * imgWidth * 2;
+ memcpy(&OutNVdata[fb_Ypos], &InNVdata[Ypos], width * 2);
+ }
+
+ memcpy(outBuf, tmpBuf, g_screensize);
+
+ return 0;
+}
+
void FbPreview::Show(int fd, libcamera::Span<uint8_t> span, int width, int height, int stride)
{
- int imgsize = stride * height + stride * height / 2;
auto startTime = std::chrono::high_resolution_clock::now();
+ int size_valid = 0;
+ int imgsize;
+
+ if (pixformat == COLOR_YUV420_NV21 || pixformat == COLOR_YUV420_NV12) {
+ imgsize = stride * height + stride * height / 2;
+ if (imgsize == span.size()) {
+ size_valid = 1;
+ NVResize(span.data(), g_fb_buf, width, height);
+ }
+ } else if (pixformat == COLOR_YUV422_YVYU || pixformat == COLOR_YUV422_YUYV) {
+ imgsize = stride * height;
+ if (imgsize == span.size()) {
+ size_valid = 1;
+ YUYVResize(span.data(), g_fb_buf, width, height);
+ }
+ }
- if (pixformat == COLOR_YUV420_NV21 || pixformat == COLOR_YUV420_NV12)
- NVResize(span.data(), g_fb_buf, width, height);
- else
- std::cout << "FbPreview unsupport pixformat: " << pixformat << std::endl;
+ if (!size_valid) {
+ std::cout << "FbPreview unsupport pixformat: " << pixformat
+ << " fb need size: " << imgsize
+ << " width: " << width
+ << " height: " << height
+ << " stride: " << stride
+ << " size: " << span.size() << std::endl;
+ throw std::runtime_error("Error FbPreview unsupport pixformat.");
+ }
auto endTime = std::chrono::high_resolution_clock::now();
diff --git a/preview/preview.cpp b/preview/preview.cpp
index 0086d83..17118d4 100644
--- a/preview/preview.cpp
+++ b/preview/preview.cpp
@@ -49,10 +49,17 @@ Preview *make_preview(Options const *options)
}
catch (std::exception const &e)
{
- std::cout << "FB Preview window." << std::endl;
- return make_fb_preview(options);
- // std::cout << "Preview window unavailable" << std::endl;
- // return make_null_preview(options);
+ try {
+ std::cout << "FB Preview window." << std::endl;
+ return make_fb_preview(options);
+ if (options->verbose)
+ std::cout << "Made FB Preview window." << std::endl;
+ }
+ catch (std::exception const &e)
+ {
+ std::cout << "Preview window unavailable" << std::endl;
+ return make_null_preview(options);
+ }
}
}
}
--
2.17.1
File diff suppressed because it is too large Load Diff
@@ -1,153 +0,0 @@
From 30ce74f6cc34ddb310cee72280d9e1e00aa4e459 Mon Sep 17 00:00:00 2001
From: sw.multimedia <sw.multimedia@starfivetech.com>
Date: Thu, 25 Nov 2021 14:57:09 +0800
Subject: [PATCH] add DrmPreview support NV12 display
---
preview/drm_preview.cpp | 84 +++++++++++++++++++++++++++++++++++------
1 file changed, 73 insertions(+), 11 deletions(-)
diff --git a/preview/drm_preview.cpp b/preview/drm_preview.cpp
index c444918..a969358 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"
@@ -50,6 +52,7 @@ private:
void findPlane();
int drmfd_;
int conId_;
+ drmModeConnector *con_;
uint32_t crtcId_;
int crtcIdx_;
uint32_t planeId_;
@@ -95,10 +98,19 @@ void DrmPreview::findCrtc()
if (con->encoder_id)
{
enc = drmModeGetEncoder(drmfd_, con->encoder_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)
@@ -161,6 +173,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_);
@@ -227,10 +241,13 @@ void DrmPreview::findPlane()
DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1)
{
- drmfd_ = drmOpen("vc4", NULL);
+ // drmfd_ = drmOpen("vc4", NULL);
+ drmfd_ = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
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;
@@ -245,7 +262,12 @@ DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1)
conId_ = 0;
findCrtc();
- out_fourcc_ = DRM_FORMAT_YUV420;
+ if (options_->pixelformat.length()) {
+ libcamera::PixelFormat pixelFormat =
+ libcamera::PixelFormat::fromString(options_->pixelformat);
+ out_fourcc_ = pixelFormat.fourcc();
+ } else
+ out_fourcc_ = DRM_FORMAT_YUV420;
findPlane();
}
catch (std::exception const &e)
@@ -281,12 +303,52 @@ void DrmPreview::makeBuffer(int fd, size_t size, unsigned int width, unsigned in
if (drmPrimeFDToHandle(drmfd_, fd, &buffer.bo_handle))
throw std::runtime_error("drmPrimeFDToHandle failed for fd " + std::to_string(fd));
- 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))
+ 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, int width, int height, int stride)
--
2.17.1
@@ -1,28 +0,0 @@
From 5021e32ddc68459c1d96a5ddb8c4225e82023130 Mon Sep 17 00:00:00 2001
From: "Kevin.xie" <kevin.xie@starfivetech.com>
Date: Thu, 4 Aug 2022 13:55:56 +0800
Subject: [PATCH] libcamera-apps: Open drm device by module name 'starfive'
Signed-off-by: Kevin.xie <kevin.xie@starfivetech.com>
---
preview/drm_preview.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/preview/drm_preview.cpp b/preview/drm_preview.cpp
index a969358..df6bfb5 100644
--- a/preview/drm_preview.cpp
+++ b/preview/drm_preview.cpp
@@ -241,8 +241,8 @@ void DrmPreview::findPlane()
DrmPreview::DrmPreview(Options const *options) : Preview(options), last_fd_(-1)
{
- // drmfd_ = drmOpen("vc4", NULL);
- drmfd_ = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
+ drmfd_ = drmOpen("starfive", NULL);
+ // drmfd_ = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
if (drmfd_ < 0)
throw std::runtime_error("drmOpen failed: " + std::string(ERRSTR));
--
2.17.1
@@ -1,3 +1 @@
sha256 5600c4289457c03a5062001f5942c77fabe4fcef8877b67cfaeed5bae5672756 libcamera-apps-main.tar.gz
sha256 3fe6e9e343f268c518652a00260791c55f18cd5902fd5de578005b9c6ec9785b libcamera-apps-87f807f4eacf7d62021e3b4061348e64b2ecadc3.tar.gz
sha256 09a169037dfba889bc9f449aaefc18c210fdf4eb7ea02cffd4a36c383b71583c libcamera-apps-87f807f4eacf7d62021e3b4061348e64b2ecadc3-br1.tar.gz
sha256 add2d80450f3b61de275c6505689b0984d29c9dde94f0cf381c4209620c96263 libcamera-apps-54a781dffdd101954dcfa6acd0bd80006f67da83-br1.tar.gz
@@ -5,10 +5,10 @@
################################################################################
LIBCAMERA_APPS_SITE = https://github.com/raspberrypi/libcamera-apps.git
LIBCAMERA_APPS_VERSION = 87f807f4eacf7d62021e3b4061348e64b2ecadc3
LIBCAMERA_APPS_VERSION = 54a781dffdd101954dcfa6acd0bd80006f67da83
LIBCAMERA_APPS_SITE_METHOD = git
LIBCAMERA_APPS_INSTALL_STAGING = YES
LIBCAMERA_APPS_DEPENDENCIES = libcamera libexif tiff boost host-pkgconf
LIBCAMERA_APPS_DEPENDENCIES = libcamera libexif tiff boost host-pkgconf jpeg libpng sf-omx-il
$(eval $(cmake-package))