From dfe5563f80041b9dcd62e8f03054919e3e844d5f Mon Sep 17 00:00:00 2001 From: lichaofan Date: Thu, 19 Mar 2026 15:09:53 +0800 Subject: [PATCH] feat: enable the configuration for the preferred resolution. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the DConfig mechanism to enable the configuration for the preferred resolution. 使用DConfig机制,开放首选分辨率的配置功能。 Task: https://pms.uniontech.com/task-view-387315.html --- libcam/libcam_v4l2core/v4l2_core.c | 48 +++++++++++++++++---- libcam/libcam_v4l2core/v4l2_formats.c | 55 ++++++++++++++++++++++++ libcam/libcam_v4l2core/v4l2_formats.h | 37 ++++++++++++++++ src/assets/org.deepin.camera.encode.json | 10 +++++ src/main.cpp | 12 ++++++ src/src/basepub/datamanager.cpp | 47 ++++++++++++++++++++ src/src/basepub/datamanager.h | 14 ++++++ 7 files changed, 214 insertions(+), 9 deletions(-) diff --git a/libcam/libcam_v4l2core/v4l2_core.c b/libcam/libcam_v4l2core/v4l2_core.c index bcb1830f..4da187c3 100644 --- a/libcam/libcam_v4l2core/v4l2_core.c +++ b/libcam/libcam_v4l2core/v4l2_core.c @@ -1696,20 +1696,50 @@ 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)) + { + // 找出首选分辨率 + printf("V4L2_CORE: check valid resolution, width: %d, height: %d, preferred width: %d, preferred height: %d\n", + w, h, pref_w, pref_h); + if (!found_preferred && pref_w != 0 && pref_h != 0 && w == pref_w && h == pref_h) { + printf("V4L2_CORE: preferred resolution found, width: %d, height: %d\n", w, h); + found_preferred = 1; + } + + // 找出最大分辨率 + if (w > max_width || (w == max_width && h > max_height)) { + max_width = w; + max_height = h; + } + } + } + printf("V4L2_CORE: max resolution found, width: %d, height: %d\n", max_width, max_height); + if (found_preferred) { + // 有首选分辨率,使用首选分辨率 + printf("V4L2_CORE: use preferred resolution, width: %d, height: %d\n", pref_w, pref_h); + my_width = pref_w; + my_height = pref_h; + } else { + // 没有首选分辨率,使用最大分辨率 + printf("V4L2_CORE: use max resolution, width: %d, height: %d\n", max_width, max_height); + my_width = max_width; + my_height = max_height; + // 极端情况,没有可用分辨率,发出错误提示 + if (max_width == 0 || max_height == 0) { + printf("V4L2_CORE: ERROR: no valid resolution found!\n"); } } - printf("V4L2_CORE: select resolution(%dx%d)\n", my_width, my_height); } /* diff --git a/libcam/libcam_v4l2core/v4l2_formats.c b/libcam/libcam_v4l2core/v4l2_formats.c index a3d1a8df..9e705e90 100644 --- a/libcam/libcam_v4l2core/v4l2_formats.c +++ b/libcam/libcam_v4l2core/v4l2_formats.c @@ -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 @@ -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; +} diff --git a/libcam/libcam_v4l2core/v4l2_formats.h b/libcam/libcam_v4l2core/v4l2_formats.h index ab50576c..0ce1a362 100644 --- a/libcam/libcam_v4l2core/v4l2_formats.h +++ b/libcam/libcam_v4l2core/v4l2_formats.h @@ -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 diff --git a/src/assets/org.deepin.camera.encode.json b/src/assets/org.deepin.camera.encode.json index 18e14441..a8bfab9a 100644 --- a/src/assets/org.deepin.camera.encode.json +++ b/src/assets/org.deepin.camera.encode.json @@ -101,6 +101,16 @@ "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" } } } diff --git a/src/main.cpp b/src/main.cpp index 4481f2dc..99bef41a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -205,6 +205,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()); } diff --git a/src/src/basepub/datamanager.cpp b/src/src/basepub/datamanager.cpp index 3c0f5448..8c290718 100644 --- a/src/src/basepub/datamanager.cpp +++ b/src/src/basepub/datamanager.cpp @@ -3,6 +3,10 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +extern "C" { +#include "v4l2_formats.h" +} + #include "datamanager.h" #include "../capplication.h" @@ -103,6 +107,48 @@ bool DataManager::isDeviceValid(const QString &vid, const QString &pid, const QS 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() { if (m_dataManager == nullptr) { @@ -121,5 +167,6 @@ DataManager::DataManager() m_encodeEnv = GStreamer_Env; m_devStatus = DeviceStatus::NOCAM; m_H264EncoderExists = false; + m_preferredResolution = QSize(0, 0); } diff --git a/src/src/basepub/datamanager.h b/src/src/basepub/datamanager.h index 97fe125b..729c3b75 100644 --- a/src/src/basepub/datamanager.h +++ b/src/src/basepub/datamanager.h @@ -8,6 +8,7 @@ #include #include +#include enum GridType { @@ -198,6 +199,18 @@ class DataManager: public QObject * @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; @@ -212,5 +225,6 @@ class DataManager: public QObject bool m_enableUsbGroup = false; // 是否启用USB摄像头分组 bool m_enable8kPreview = false; // 是否启用8K预览 QSet m_deviceBlacklistSet; // 设备黑名单 + QSize m_preferredResolution; // 首选分辨率 }; #endif // DATAMANAGER_H