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
48 changes: 39 additions & 9 deletions libcam/libcam_v4l2core/v4l2_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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; // 是否找到首选分辨率
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
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);
}

/*
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
10 changes: 10 additions & 0 deletions src/assets/org.deepin.camera.encode.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
12 changes: 12 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
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.

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

View workflow job for this annotation

GitHub Actions / static-check / static-check

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

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

Expand Down Expand Up @@ -103,6 +107,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()
{
if (m_dataManager == nullptr) {
Expand All @@ -121,5 +167,6 @@
m_encodeEnv = GStreamer_Env;
m_devStatus = DeviceStatus::NOCAM;
m_H264EncoderExists = false;
m_preferredResolution = QSize(0, 0);
}

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.

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

View workflow job for this annotation

GitHub Actions / static-check / static-check

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.

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

View workflow job for this annotation

GitHub Actions / static-check / static-check

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.

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

View workflow job for this annotation

GitHub Actions / static-check / static-check

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
Loading