Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .omo/run-continuation/ses_07c60f6efffewjubKjvUAK1JPM.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"sessionID": "ses_07c60f6efffewjubKjvUAK1JPM",
"updatedAt": "2026-07-21T07:43:16.026Z",
"sources": {
"background-task": {
"state": "idle",
"updatedAt": "2026-07-21T07:43:16.026Z"
}
}
}
42 changes: 33 additions & 9 deletions libcam/libcam_v4l2core/v4l2_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1696,20 +1696,44 @@ void v4l2core_prepare_valid_resolution(v4l2_dev_t *vd)
}
}

// 查找可以支持的最大分辨率
// 由于上游guvcview项目在解码3840x2160分辨率以上时会出现异常(出现条纹、崩溃等),所以我们需要限制可用分辨率到3840x2160
printf("V4L2_CORE: valid resolution counts: %d\n", vd->list_stream_formats[format_index].numb_res);
for(int i=0; i < vd->list_stream_formats[format_index].numb_res; i++)
int found_preferred = 0; // 是否找到首选分辨率
int pref_w = get_preferred_resolution_width();
int pref_h = get_preferred_resolution_height();
// 最大分辨率
int max_width = 0;
int max_height = 0;
// 通过一次遍历,找出首选分辨率,同时找出最大分辨率。虽然最大分辨率可能用不到,但是便于调试分析
for (int i = 0; i < vd->list_stream_formats[format_index].numb_res; i++)
{
int w = vd->list_stream_formats[format_index].list_stream_cap[i].width;
int h = vd->list_stream_formats[format_index].list_stream_cap[i].height;
printf("V4L2_CORE: - valid resolution(%dx%d)\n", w, h);
if (my_width <= w && my_height <= h && is_valid_resolution(w, h)) {
my_width = w;
my_height = h;
if (is_valid_resolution(w, h))
{
// 找出首选分辨率
if (!found_preferred && pref_w != 0 && pref_h != 0 && w == pref_w && h == pref_h) {
Comment on lines +1706 to +1713

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Handle the case where no valid resolution is found more robustly.

Currently, if no valid resolution is found, max_width/max_height stay at 0, causing my_width/my_height to be set to 0 and only logging an error. If callers treat these as valid, this can result in invalid downstream configuration. Please either fall back to the previous my_width/my_height, return/propagate an error from this function, or ensure that a (0, 0) resolution is never used later in the pipeline.

found_preferred = 1;
}

// 找出最大分辨率
if (w > max_width || (w == max_width && h > max_height)) {
max_width = w;
max_height = h;
}
}
}
if (found_preferred) {
// 有首选分辨率,使用首选分辨率
my_width = pref_w;
my_height = pref_h;
} else {
// 没有首选分辨率,使用最大分辨率
my_width = max_width;
my_height = max_height;
// 极端情况,没有可用分辨率,发出错误提示
if (max_width == 0 || max_height == 0) {
fprintf(stderr, "V4L2_CORE: ERROR: no valid resolution found!\n");
}
}
printf("V4L2_CORE: select resolution(%dx%d)\n", my_width, my_height);
}

/*
Expand Down
55 changes: 55 additions & 0 deletions libcam/libcam_v4l2core/v4l2_formats.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ static uint32_t decoder_supported_formats[] =

// 是否开启8K预览
static int enable_8k_preview = 0;
// 首选分辨率
static int preferred_resolution_width = 0;
static int preferred_resolution_height = 0;

/* FIXME: doesn't support bigendian formats=> fourcc | (1 << 31)
* get pixelformat from fourcc
Expand Down Expand Up @@ -793,3 +796,55 @@ int is_enable_8k_preview()
{
return enable_8k_preview;
}

/**
* set preferred resolution
* args:
* width - preferred width
* height - preferred height
*
* asserts:
* none
*
* returns: void
*/
void set_preferred_resolution(int width, int height)
{
if (width <= 0 || height <= 0) {
printf("V4L2_CORE: Invalid preferred resolution: %dx%d\n", width, height);
return;
}

preferred_resolution_width = width;
preferred_resolution_height = height;
}

/**
* get preferred resolution width
* args:
* none
*
* asserts:
* none
*
* returns: preferred width
*/
int get_preferred_resolution_width()
{
return preferred_resolution_width;
}

/**
* get preferred resolution height
* args:
* none
*
* asserts:
* none
*
* returns: preferred height
*/
int get_preferred_resolution_height()
{
return preferred_resolution_height;
}
37 changes: 37 additions & 0 deletions libcam/libcam_v4l2core/v4l2_formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,41 @@ void set_enable_8k_preview(int enable);
*/
int is_enable_8k_preview();

/**
* set preferred resolution
* args:
* width - preferred width
* height - preferred height
*
* asserts:
* none
*
* returns: void
*/
void set_preferred_resolution(int width, int height);

/**
* get preferred resolution width
* args:
* none
*
* asserts:
* none
*
* returns: preferred width
*/
int get_preferred_resolution_width();

/**
* get preferred resolution height
* args:
* none
*
* asserts:
* none
*
* returns: preferred height
*/
int get_preferred_resolution_height();

#endif
20 changes: 20 additions & 0 deletions src/assets/org.deepin.camera.encode.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@
"description": "Set device blacklist, format: vid,pid,name",
"permissions": "readwrite",
"visibility": "private"
},
"preferredResolution": {
"value": "",
"serial": 0,
"flags": ["global"],
"name": "preferred resolution",
"name[zh_CN]": "首选分辨率",
"description": "Set preferred resolution",
"permissions": "readwrite",
"visibility": "private"
},
"isLowPerformanceDevice": {
"value": false,
"serial": 0,
"flags": ["global"],
"name": "is low performance device",
"name[zh_CN]": "是否是低性能设备",
"description": "Is low performance device",
"permissions": "readwrite",
"visibility": "private"
}
}
}
12 changes: 12 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,18 @@ int main(int argc, char *argv[])
DataManager::instance()->setDeviceBlacklist(deviceBlacklist);
}

if (dconfig && dconfig->isValid() && dconfig->keyList().contains("preferredResolution")) {
QString preferredResolution = dconfig->value("preferredResolution").toString();
qInfo() << "preferred resolution:" << preferredResolution;
if (!preferredResolution.isEmpty()) {
DataManager::instance()->setPreferredResolution(preferredResolution);
QSize size = DataManager::instance()->getPreferredResolution();
if (!size.isNull()) {
set_preferred_resolution(size.width(), size.height());
}
}
}

if (!libVaDriverName.isEmpty()) {
qputenv("LIBVA_DRIVER_NAME", libVaDriverName.toLocal8Bit());
}
Expand Down
47 changes: 47 additions & 0 deletions src/src/basepub/datamanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later

extern "C" {
#include "v4l2_formats.h"

Check warning on line 7 in src/src/basepub/datamanager.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "v4l2_formats.h" not found.
}

#include "datamanager.h"
#include "../capplication.h"

Expand Down Expand Up @@ -112,6 +116,48 @@
return !m_deviceBlacklistSet.contains(key);
}

void DataManager::setPreferredResolution(const QString &resolution)
{
if (resolution.isEmpty()) {
qInfo() << "Preferred resolution is empty";
return;
}

QStringList parts = resolution.split("x");
if (parts.size() != 2) {
qWarning() << "Invalid resolution format:" << resolution << "Expected format: WIDTHxHEIGHT";
return;
}

bool widthOk, heightOk;
int width = parts[0].toInt(&widthOk);
int height = parts[1].toInt(&heightOk);

if (!widthOk || !heightOk || width <= 0 || height <= 0) {
qWarning() << "Invalid resolution values:" << resolution;
return;
}

// 添加合理的上限检查,例如16K
static const int MAX_RESOLUTION = 16384;
if (width > MAX_RESOLUTION || height > MAX_RESOLUTION) {
qWarning() << "Resolution exceeds maximum limit:" << resolution;
return;
}

if (!is_valid_resolution(width, height)) {
qWarning() << "Resolution does not meet validation requirements:" << resolution;
return;
}

m_preferredResolution = QSize(width, height);
}

QSize DataManager::getPreferredResolution()
{
return m_preferredResolution;
}

DataManager *DataManager::instance()
{
// qDebug() << "Function started: instance";
Expand All @@ -134,6 +180,7 @@
m_encodeEnv = GStreamer_Env;
m_devStatus = DeviceStatus::NOCAM;
m_H264EncoderExists = false;
m_preferredResolution = QSize(0, 0);
// qDebug() << "Function completed: DataManager constructor";
}

14 changes: 14 additions & 0 deletions src/src/basepub/datamanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#ifndef DATAMANAGER_H
#define DATAMANAGER_H

#include <QObject>

Check warning on line 9 in src/src/basepub/datamanager.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QSet>

Check warning on line 10 in src/src/basepub/datamanager.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QSet> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QSize>

Check warning on line 11 in src/src/basepub/datamanager.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QSize> not found. Please note: Cppcheck does not need standard library headers to get proper results.

enum GridType
{
Expand Down Expand Up @@ -198,6 +199,18 @@
* @return
*/
bool isDeviceValid(const QString &vid, const QString &pid, const QString &name);

/**
* @brief 设置首选分辨率
* @param resolution 分辨率字符串,格式如 "1920x1080"
*/
void setPreferredResolution(const QString &resolution);

/**
* @brief 获取首选分辨率
* @return 分辨率
*/
QSize getPreferredResolution();
private:
DataManager();
static DataManager *m_dataManager;
Expand All @@ -212,5 +225,6 @@
bool m_enableUsbGroup = false; // 是否启用USB摄像头分组
bool m_enable8kPreview = false; // 是否启用8K预览
QSet<QString> m_deviceBlacklistSet; // 设备黑名单
QSize m_preferredResolution; // 首选分辨率
};
#endif // DATAMANAGER_H
26 changes: 24 additions & 2 deletions src/src/globalutils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
// Copyright (C) 2020 - 2026 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -15,11 +15,17 @@

DCORE_USE_NAMESPACE

#ifdef DTKCORE_CLASS_DConfigFile
#include <DConfig>

Check warning on line 19 in src/src/globalutils.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DConfig> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <memory>

Check warning on line 20 in src/src/globalutils.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <memory> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#endif

// 相机配置文件
const QString CAMERA_CONF_PATH = "/usr/share/deepin-camera/camera.conf";
#define LOW_PERFORMANCE_BOARD "LowPerformanceBoard"

QStringList GlobalUtils::m_LowPerformanceBoards = QStringList();
bool GlobalUtils::m_IsLowPerformanceDevice = false;

struct DMIInfo {
QString biosManufacturer;
Expand All @@ -34,6 +40,7 @@
QString sysSerialNumber;
QString sysUUID;
};

Q_DECLARE_METATYPE(DMIInfo)

// Marshall the MyStructure data into a D-Bus argument
Expand All @@ -60,9 +67,15 @@
return argument;
}

bool GlobalUtils::isLowPerformanceBoard()

Check warning on line 70 in src/src/globalutils.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'isLowPerformanceBoard' is never used.
{
// qDebug() << "Checking for low performance board";
#ifdef DTKCORE_CLASS_DConfigFile
if (m_IsLowPerformanceDevice) {
return true;
}
#endif

qDBusRegisterMetaType<DMIInfo>();

QString systemInfoService = "com.deepin.system.SystemInfo";
Expand Down Expand Up @@ -115,5 +128,14 @@
qWarning() << "No low performance boards configuration found in" << CAMERA_CONF_PATH;
m_LowPerformanceBoards = QStringList();
}

#ifdef DTKCORE_CLASS_DConfigFile
m_IsLowPerformanceDevice = false;
std::unique_ptr<DTK_CORE_NAMESPACE::DConfig> dconfig(
DTK_CORE_NAMESPACE::DConfig::create("org.deepin.camera", "org.deepin.camera.encode"));
if (dconfig && dconfig->isValid() && dconfig->keyList().contains("isLowPerformanceDevice")) {
m_IsLowPerformanceDevice = dconfig->value("isLowPerformanceDevice").toBool();
}
#endif
qDebug() << "Function completed: loadCameraConf";
}
5 changes: 3 additions & 2 deletions src/src/globalutils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
// Copyright (C) 2020 - 2026 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -19,6 +19,7 @@ class GlobalUtils

private:
static QStringList m_LowPerformanceBoards;
static bool m_IsLowPerformanceDevice;
};

#endif // GLOBALUTILS_H
Loading