diff --git a/.omo/run-continuation/ses_07c60f6efffewjubKjvUAK1JPM.json b/.omo/run-continuation/ses_07c60f6efffewjubKjvUAK1JPM.json new file mode 100644 index 00000000..96e2325d --- /dev/null +++ b/.omo/run-continuation/ses_07c60f6efffewjubKjvUAK1JPM.json @@ -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" + } + } +} \ No newline at end of file diff --git a/libcam/libcam_v4l2core/v4l2_core.c b/libcam/libcam_v4l2core/v4l2_core.c index bcb1830f..3af06a4c 100644 --- a/libcam/libcam_v4l2core/v4l2_core.c +++ b/libcam/libcam_v4l2core/v4l2_core.c @@ -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) { + 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); } /* 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 dfb5897e..b81583ca 100644 --- a/src/assets/org.deepin.camera.encode.json +++ b/src/assets/org.deepin.camera.encode.json @@ -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" } } } diff --git a/src/main.cpp b/src/main.cpp index 5050ff3f..49b8c818 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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()); } diff --git a/src/src/basepub/datamanager.cpp b/src/src/basepub/datamanager.cpp index 44d0fe97..8d33eed6 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" @@ -112,6 +116,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() { // qDebug() << "Function started: instance"; @@ -134,6 +180,7 @@ DataManager::DataManager() m_encodeEnv = GStreamer_Env; m_devStatus = DeviceStatus::NOCAM; m_H264EncoderExists = false; + m_preferredResolution = QSize(0, 0); // qDebug() << "Function completed: DataManager constructor"; } diff --git a/src/src/basepub/datamanager.h b/src/src/basepub/datamanager.h index 1b9d3204..48463a1d 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 diff --git a/src/src/globalutils.cpp b/src/src/globalutils.cpp index 7bc71704..72d9621d 100644 --- a/src/src/globalutils.cpp +++ b/src/src/globalutils.cpp @@ -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 @@ -15,11 +15,17 @@ DCORE_USE_NAMESPACE +#ifdef DTKCORE_CLASS_DConfigFile +#include +#include +#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; @@ -34,6 +40,7 @@ struct DMIInfo { QString sysSerialNumber; QString sysUUID; }; + Q_DECLARE_METATYPE(DMIInfo) // Marshall the MyStructure data into a D-Bus argument @@ -63,6 +70,12 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, DMIInfo &mystruct bool GlobalUtils::isLowPerformanceBoard() { // qDebug() << "Checking for low performance board"; +#ifdef DTKCORE_CLASS_DConfigFile + if (m_IsLowPerformanceDevice) { + return true; + } +#endif + qDBusRegisterMetaType(); QString systemInfoService = "com.deepin.system.SystemInfo"; @@ -115,5 +128,14 @@ void GlobalUtils::loadCameraConf() qWarning() << "No low performance boards configuration found in" << CAMERA_CONF_PATH; m_LowPerformanceBoards = QStringList(); } + +#ifdef DTKCORE_CLASS_DConfigFile + m_IsLowPerformanceDevice = false; + std::unique_ptr 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"; } diff --git a/src/src/globalutils.h b/src/src/globalutils.h index 51e021d4..dfbaf95d 100644 --- a/src/src/globalutils.h +++ b/src/src/globalutils.h @@ -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 @@ -19,6 +19,7 @@ class GlobalUtils private: static QStringList m_LowPerformanceBoards; + static bool m_IsLowPerformanceDevice; }; #endif // GLOBALUTILS_H