#include "cameracontroller.h"
#include <QMediaDevices>
#include <QVideoWidget>
#include <QDebug>
#include <QImageCapture>
#include <QTimer>
#include <QMediaFormat>
#ifdef Q_OS_ANDROID
#include <QCoreApplication>
#include <QJniObject>
#include <QJniEnvironment>
#endif
CameraController::CameraController(QObject *parent)
: QObject(parent)
, m_camera(nullptr)
, m_captureSession(nullptr)
, m_imageCapture(nullptr)
, m_hasCamera(false)
, m_videoOutput(nullptr)
{
qDebug() << "=== 初始化USB摄像头控制器(Android优化版)===";
//连接视频输出状态信号
//QTimer::singleShot(100, this, &CameraController::initializeCamera);
initializeCamera();
}
CameraController::~CameraController()
{
stopCamera();
delete m_imageCapture;
delete m_captureSession;
delete m_camera;
}
void CameraController::initializeCamera()
{
qDebug() << "=== 初始化摄像头硬件 ===";
auto cameras = QMediaDevices::videoInputs();
m_hasCamera = !cameras.isEmpty();
if (!m_hasCamera) {
qDebug() << "❌ 未找到任何摄像头";
emit errorOccurred("未检测到USB摄像头");
return;
}
//输出所有可用摄像头信息
for (const auto &camera : cameras) {
qDebug() << "可用摄像头:" << camera.description()
<< "ID:" << camera.id()
<< "位置:" << camera.position();
}
//优先选择USB摄像头 获取不到usb摄像头
QCameraDevice selectedCamera;
for (const auto &camera : cameras) {
if (isUSBCamera(camera)) {
selectedCamera = camera;
qDebug() << "✅ 找到USB摄像头:" << camera.description();
break;
}
//如果没有USB摄像头,选择第一个
if (selectedCamera.isNull()) {
selectedCamera = cameras.first();
}
}
m_cameraDevice = selectedCamera;
m_currentCameraDescription = selectedCamera.description();
qDebug() << "选择摄像头:" << m_currentCameraDescription
<< "ID:" << selectedCamera.id();
// 创建摄像头和会话
m_camera = new QCamera(selectedCamera);
m_captureSession = new QMediaCaptureSession();
m_imageCapture = new QImageCapture();
// 配置摄像头参数
if (!configureCamera()) {
qDebug() << "⚠️ 摄像头配置可能不理想,但继续尝试...";
}
// 设置会话
m_captureSession->setCamera(m_camera);
m_captureSession->setImageCapture(m_imageCapture);
// 连接信号
connect(m_camera, &QCamera::errorOccurred,
this, &CameraController::handleCameraError);
connect(m_camera, &QCamera::activeChanged,
this, &CameraController::onCameraActiveChanged);
qDebug() << "✅ 摄像头硬件初始化完成";
emit statusChanged("摄像头硬件准备就绪");
}
void CameraController::onVideoFrameChanged(const QVideoFrame &frame)
{
qDebug()<<"接受到帧数据";
static int frameCount = 0;
frameCount++;
if (frameCount % 30 == 0) { // 每30帧输出一次,避免日志过多
qDebug() << "📹 接收到视频帧 #" << frameCount
<< "尺寸:" << frame.size()
<< "格式:" << frame.pixelFormat()
<< "有效:" << frame.isValid();
}
}
bool CameraController::configureCamera()
{
//完全不配置
// qDebug() << "=== 使用系统自动摄像头配置 ===";
// // 不设置任何格式,让系统和摄像头硬件自动协商最佳配置
// // 这样可以完全避免 setParameters failed 错误
// qDebug() << "让系统自动选择摄像头格式";
// // 延迟检查系统选择的格式
// QTimer::singleShot(2000, this, [this]() {
// if (m_camera && m_camera->isActive()) {
// QCameraFormat actualFormat = m_camera->cameraFormat();
// qDebug() << "系统自动选择的摄像头格式:";
// qDebug() << " 分辨率:" << actualFormat.resolution();
// qDebug() << " 像素格式:" << actualFormat.pixelFormat();
// qDebug() << " 帧率范围:" << actualFormat.minFrameRate() << "-" << actualFormat.maxFrameRate();
// // 根据实际格式优化显示
// if (m_videoOutput) {
// QSize resolution = actualFormat.resolution();
// if (resolution.width() > 1280) {
// qDebug() << "高分辨率模式,优化显示性能";
// // 可以在这里进行高分辨率特定的优化
// }
// }
// }
// });
return true;
}
bool CameraController::isUSBCamera(const QCameraDevice &camera)
{
// USB摄像头通常有特定的描述或ID特征
QString description = camera.description().toLower();
QString id = camera.id().toLower();
// 检测USB摄像头的常见特征
bool isUSB = description.contains("usb") ||
id.contains("usb") ||
description.contains("external") ||
camera.position() == QCameraDevice::UnspecifiedPosition;
qDebug() << "摄像头检测 - 描述:" << description
<< "ID:" << id
<< "位置:" << camera.position()
<< "是USB摄像头:" << isUSB;
return isUSB;
}
bool CameraController::startCamera()
{
qDebug() << "=== 启动USB摄像头 ===";
if (!m_camera) {
qDebug() << "❌ 摄像头未初始化";
emit errorOccurred("USB摄像头未初始化");
return false;
}
if (m_camera->isActive()) {
qDebug() << "USB摄像头已在运行";
return true;
}
// Android平台:先检查权限
if (!checkAndroidCameraPermission()) {
qDebug() << "Android摄像头权限未授予";
emit errorOccurred("请授予摄像头权限后重试");
return false;
}
try {
// 启动摄像头
m_camera->start();
qDebug() << "USB摄像头启动命令已发送";
emit statusChanged("正在启动USB摄像头...");
return true;
} catch (const std::exception& e) {
qDebug() << "启动摄像头异常:" << e.what();
emit errorOccurred(QString("启动摄像头异常: %1").arg(e.what()));
return false;
}
}
bool CameraController::checkAndroidCameraPermission()
{
// 在Qt 6.2中,我们可以使用JNI来检查权限
QJniObject permission = QJniObject::fromString("android.permission.CAMERA");
QJniObject activity = QJniObject::callStaticObjectMethod(
"org/qtproject/qt/android/QtNative", "activity", "()Landroid/app/Activity;");
if (!activity.isValid()) {
qDebug() << "无法获取Android Activity";
return false;
}
jint result = activity.callMethod<jint>(
"checkSelfPermission",
"(Ljava/lang/String;)I",
permission.object<jstring>());
// PERMISSION_GRANTED = 0
if (result == 0) {
qDebug() << "Android摄像头权限已授予";
return true;
} else {
qDebug() << "Android摄像头权限未授予,需要请求权限";
// 请求权限
QJniObject::callStaticMethod<void>(
"org/qtproject/qt/android/QtNative",
"requestPermission",
"(Ljava/lang/String;)V",
permission.object<jstring>());
// 在真实应用中,您需要处理权限请求的回调
// 这里简化处理,假设权限会被授予
return false;
}
}
void CameraController::stopCamera()
{
qDebug() << "停止USB摄像头";
if (m_camera && m_camera->isActive()) {
m_camera->stop();
emit statusChanged("USB摄像头已停止");
qDebug() << "USB摄像头已停止";
}
}
void CameraController::handleCameraError(QCamera::Error error, const QString &errorString)
{
QString errorMsg;
switch (error) {
case QCamera::NoError:
return;
case QCamera::CameraError:
errorMsg = "摄像头错误: " + errorString;
break;
}
qDebug() << "❌ USB摄像头错误:" << errorMsg;
if (errorString.contains("Permission", Qt::CaseInsensitive) ||
errorString.contains("permission", Qt::CaseInsensitive)) {
errorMsg = "摄像头权限被拒绝,请重启应用并授予权限";
} else if (errorString.contains("format", Qt::CaseInsensitive) ||
errorString.contains("pixel", Qt::CaseInsensitive)) {
errorMsg = "视频格式不兼容,尝试使用基本模式";
}
emit errorOccurred(errorMsg);
}
void CameraController::onCameraActiveChanged(bool active)
{
if (active)
{
qDebug() << "✅ USB摄像头已激活";
qDebug() <<" 摄像头活动状态:"<<m_camera->isActive();
//qDebug() << "会话活动状态:" << m_captureSession->isActive();
qDebug() << "视频输出:" << m_captureSession->videoOutput();
emit statusChanged("USB摄像头运行中");
emit cameraReady();
// 摄像头激活后,强制刷新视频输出
if (m_videoOutput) {
qDebug() << "强制刷新视频输出控件";
m_videoOutput->setVisible(true);
m_videoOutput->update();
m_videoOutput->repaint();
// 多次刷新确保显示
QTimer::singleShot(100, [this]() {
if (m_videoOutput) {
m_videoOutput->update();
m_videoOutput->repaint();
}
});
}
} else {
qDebug() << "USB摄像头已停用";
emit statusChanged("USB摄像头已停止");
}
}
void CameraController::setVideoOutput(QVideoWidget* videoOutput)
{
if (!videoOutput) {
qDebug() << "❌ 视频输出为nullptr";
return;
}
m_videoOutput = videoOutput;
if (m_captureSession) {
qDebug() << "=== 设置视频输出 ===";
m_captureSession->setVideoOutput(videoOutput);
qDebug() << "✅ 视频输出设置为QVideoWidget";
// 获取 VideoSink 并连接帧信号
QVideoSink *sink = videoOutput->videoSink();
m_captureSession->setVideoSink(sink);
if (sink) {
connect(sink, &QVideoSink::videoFrameChanged,
this, &CameraController::onVideoFrameChanged);
qDebug() << "✅ 视频帧监听已连接";
} else {
qDebug() << "❌ 无法获取 VideoSink";
}
if (m_captureSession && videoOutput)
{
m_videoOutput = videoOutput;
m_captureSession->setVideoOutput(videoOutput);
qDebug() << "✅ 视频输出设置为QVideoWidget";
// 详细调试信息
qDebug() << "视频输出对象:" << videoOutput;
qDebug() << "会话视频输出:" << m_captureSession->videoOutput();
// 优化视频显示设置
videoOutput->setAspectRatioMode(Qt::KeepAspectRatio);
videoOutput->setAttribute(Qt::WA_AcceptTouchEvents, true);
videoOutput->setAttribute(Qt::WA_OpaquePaintEvent, true);
videoOutput->setAttribute(Qt::WA_NoSystemBackground, true);
// 设置黑色背景
videoOutput->setStyleSheet("QVideoWidget { background-color: black; }");
// 强制启用原生渲染
videoOutput->setAutoFillBackground(false);
// 连接视频输出的信号
// connect(videoOutput, &QVideoWidget::nativeObjectChanged, this, [this]() {
// qDebug() << "QVideoWidget native对象已改变";
// });
}
}
}
//QStringList CameraController::getCameraInfo() const
//{
// QStringList info;
// if (!m_camera) {
// info << "摄像头: 未初始化";
// return info;
// }
// info << "设备: " + m_currentCameraDescription;
// info << "状态: " + QString(m_camera->isActive() ? "运行中" : "已停止");
// info << "显示: QVideoWidget (Android优化版)";
// info << "QT版本: 6.2兼容";
// // 添加格式信息
// if (!m_cameraDevice.videoFormats().isEmpty()) {
// auto format = m_camera->cameraFormat();
// info << "分辨率: " + QString::number(format.resolution().width()) + "x" + QString::number(format.resolution().height());
// info << "帧率: " + QString::number(format.minFrameRate()) + "-" + QString::number(format.maxFrameRate());
// }
// return info;
//}
你帮我看看代码,这个视频帧不会触发,调试信息是这样的D USBCameraApp: UI初始化完成
D USBCameraApp: === 初始化摄像头控制器 ===
D USBCameraApp: === 初始化USB摄像头控制器(Android优化版)===
D USBCameraApp: === 初始化摄像头硬件 ===
D USBCameraApp: 可用摄像头: "Rear-facing camera" ID: "back" 位置: QCameraDevice::BackFace
D USBCameraApp: 摄像头检测 - 描述: "rear-facing camera" ID: "back" 位置: QCameraDevice::BackFace 是USB摄像头: false
D USBCameraApp: 选择摄像头: "Rear-facing camera" ID: "back"
D USBCameraApp: ✅ 摄像头硬件初始化完成
D USBCameraApp: MainWindow初始化完成
D mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, egl_color_buffer_format *, EGLBoolean) returns 0x3000
D : set stream to NULL
D : set stream to NULL
D : set stream to NULL
D : set stream to NULL
D USBCameraApp: === 设置视频输出 ===
D USBCameraApp: ✅ 视频输出设置为QVideoWidget
D USBCameraApp: ✅ 视频帧监听已连接
D USBCameraApp: ✅ 视频输出设置为QVideoWidget
D USBCameraApp: 视频输出对象: QVideoWidget(0xadbd0430, name="videoWidget")
D USBCameraApp: 会话视频输出: QVideoWidget(0xadbd0430, name = "videoWidget")
D USBCameraApp: ✅ 摄像头控制器初始化成功
W System.err: java.lang.RuntimeException: setParameters failed
W System.err: at android.hardware.Camera.native_setParameters(Native Method)
W System.err: at android.hardware.Camera.setParameters(Camera.java:2110)
D USBCameraApp: ✅ USB摄像头已激活
D USBCameraApp: 摄像头活动状态: true
D USBCameraApp: 视频输出: QVideoWidget(0xadbd0430, name = "videoWidget")
D USBCameraApp: USB摄像头状态: "USB摄像头运行中"
D USBCameraApp: 摄像头准备就绪,可以显示视频
D USBCameraApp: 强制刷新视频输出控件
W System.err: java.lang.RuntimeException: setParameters failed
W System.err: at android.hardware.Camera.native_setParameters(Native Method)
W System.err: at android.hardware.Camera.setParameters(Camera.java:2110)
I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080.
I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080.
I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080.
I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080.
I [Gralloc]: for nv12, w : 1920, h : 1080, pixel_stride : 1920, byte_stride : 1920, size : 4147200; internalHeight : 1080.
D USBCameraApp: 显示摄像头预览 - 视频控件可见性: true
D USBCameraApp: 视频控件尺寸: QSize(1301, 651)
D USBCameraApp: 视频控件实际尺寸: QSize(-1, -1)
D USBCameraApp: 显示摄像头预览 - 视频控件可见性: true
D USBCameraApp: 视频控件尺寸: QSize(1301, 651)
D USBCameraApp: 视频控件实际尺寸: QSize(-1, -1) 为什么显示不了视频画面呢
最新发布