qt6 多媒体开发代码分析(五、录像与拍照)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include    <QtMultimedia>

#include    <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE


class MainWindow : public QMainWindow
{
    Q_OBJECT

private:
    QMediaCaptureSession  *session;      //抓取管理器
    QCamera     *camera;                //摄像头

    QImageCapture   *imageCapture;      //抓图器
    QSoundEffect    *soundEffect;       //用于拍照时播放快门音效

    QMediaRecorder  *recorder;          //录像

    QLabel   *labDuration;  //用于状态栏显示信息
    QLabel   *labInfo;
    QLabel   *labFormatInfo;
    bool    m_isWorking=false;  //是否已开启摄像头

//    void    iniCamera();//初始化
//    void    iniImageCapture();//初始化静态画图
//    void    iniVideoRecorder();//初始化视频录制

    void    showCameraDeviceInfo(QCameraDevice *device);
    void    showCameraSupportFeatures(QCamera *aCamera);
    void    closeEvent(QCloseEvent *event);
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void do_camera_changed(int index);  //与摄像头下拉列表框的信号关联

//与QCamera的信号关联
    void do_camera_activeChanged(bool active);

//与QImageCapture的信号关联
    void do_image_readyForCapture(bool ready);
    void do_image_captured(int id, const QImage &preview);
    void do_image_saved(int id, const QString &fileName);

//与QMediaRecorder的信号关联
    void do_recorder_duration(qint64 duration);
    void do_recorder_stateChanged(QMediaRecorder::RecorderState state);
    void do_recorder_error(QMediaRecorder::Error error, const QString &errorString);


    void on_actStartCamera_triggered();

    void on_actStopCamera_triggered();

    void on_actCapture_triggered();

    void on_actVideoRecord_triggered();

    void on_actVideoStop_triggered();

    void on_btnVideoFile_clicked();


private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

该代码是一个使用Qt框架的主窗口类MainWindow的头文件。主要实现了摄像头的初始化、抓图、录像等功能。

在头文件中,定义了以下私有成员变量:

  • session:抓取管理器
  • camera:摄像头
  • imageCapture:抓图器
  • soundEffect:用于拍照时播放快门音效
  • recorder:录像
  • labDuration:用于状态栏显示信息的标签
  • labInfo:显示摄像头设备信息的标签
  • labFormatInfo:显示摄像头支持的特性信息的标签
  • m_isWorking:判断是否已开启摄像头的标志位

此外,还声明了一些私有函数和私有槽函数,包括:

  • showCameraDeviceInfo:显示摄像头设备信息
  • showCameraSupportFeatures:显示摄像头支持的特性信息
  • do_camera_changed:与摄像头下拉列表框的信号关联的槽函数
  • do_camera_activeChanged:与QCamera的信号activeChanged关联的槽函数
  • do_image_readyForCapture:与QImageCapture的信号readyForCapture关联的槽函数
  • do_image_captured:与QImageCapture的信号imageCaptured关联的槽函数
  • do_image_saved:与QImageCapture的信号imageSaved关联的槽函数
  • do_recorder_duration:与QMediaRecorder的信号durationChanged关联的槽函数
  • do_recorder_stateChanged:与QMediaRecorder的信号stateChanged关联的槽函数
  • do_recorder_error:与QMediaRecorder的信号error关联的槽函数

最后声明了MainWindow类本身,继承自QMainWindow类,并定义了构造函数和析构函数。

在头文件中还存在一些注释掉的函数,可能是用于初始化摄像头、抓图、录像等功能的函数,可以根据需要进行调整或使用。

#include    "mainwindow.h"
#include    "ui_mainwindow.h"

#include    <QFileDialog>
#include    <QMessageBox>
#include    <QSoundEffect>

//void MainWindow::iniCamera()
//{//  创建  QCamera对象
//}

//void MainWindow::iniImageCapture()
//{//创建 QCameraImageCapture对象
//}

//void MainWindow::iniVideoRecorder()
//{//创建QMediaRecorder对象
//}

void MainWindow::showCameraDeviceInfo(QCameraDevice *device)
{//显示摄像头设备信息
    ui->comboCam_Position->setCurrentIndex(device->position()); //摄像头位置

    ui->comboCam_PhotoRes->clear();     //支持的拍照分辨率
    ui->comboImage_Resolution->clear(); //拍照使用的分辨率
    foreach(QSize size, device->photoResolutions())
    {
        QString str=QString::asprintf("%d X %d",size.width(),size.height());
        ui->comboCam_PhotoRes->addItem(str);            //支持的拍照分辨率
        ui->comboImage_Resolution->addItem(str,size);   //拍照使用的分辨率,添加QSize用户数据
    }

    ui->comboCam_VideoRes->clear();     //支持的视频分辨率
    ui->comboCam_FrameRate->clear();    //支持的帧率范围
    ui->comboVideo_Resolution->clear(); //录像用的分辨率
    foreach(QCameraFormat format, device->videoFormats())
    {
        QSize size=format.resolution();
        QString str=QString::asprintf("%d X %d",size.width(),size.height());
        ui->comboCam_VideoRes->addItem(str);
        ui->comboVideo_Resolution->addItem(str,size);   //添加QSize用户数据

        str=QString::asprintf("%.1f ~ %.1f",format.minFrameRate(),format.maxFrameRate());
        ui->comboCam_FrameRate->addItem(str);
    }
}

void MainWindow::showCameraSupportFeatures(QCamera *aCamera)
{//显示摄像头支持的特性
    QCamera::Features features= aCamera->supportedFeatures();

    bool    supported=features.testFlag(QCamera::Feature::ColorTemperature);
    ui->chkBoxCam_Color->setChecked(supported);

    supported=features.testFlag(QCamera::Feature::ExposureCompensation);
    ui->chkBoxCam_Exposure->setChecked(supported);

    supported=features.testFlag(QCamera::Feature::IsoSensitivity);
    ui->chkBoxCam_Iso->setChecked(supported);

    supported=features.testFlag(QCamera::Feature::CustomFocusPoint);
    ui->chkBoxCam_Custom->setChecked(supported);

    supported=features.testFlag(QCamera::Feature::ManualExposureTime);
    ui->chkBoxCam_Manual->setChecked(supported);

    supported=features.testFlag(QCamera::Feature::FocusDistance);
    ui->chkBoxCam_Focus->setChecked(supported);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (m_isWorking)
    {
        if(recorder->recorderState() == QMediaRecorder::RecordingState) //正在录制视频
            recorder->stop();   //停止录制视频
        camera->stop();         //关闭摄像头
    }
    event->accept();
}

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    labDuration=new QLabel("录制时间: ");
    labDuration->setMinimumWidth(120);
    ui->statusBar->addWidget(labDuration);

    labFormatInfo=new QLabel("图片分辨率: ");
    labFormatInfo->setMinimumWidth(150);
    ui->statusBar->addWidget(labFormatInfo);

    labInfo=new QLabel("信息");
    ui->statusBar->addPermanentWidget(labInfo);

//1. 发现摄像头
    QCameraDevice  defaultCameraDevice= QMediaDevices::defaultVideoInput();
    if (defaultCameraDevice.isNull())
    {
        QMessageBox::critical(this,"提示","没有发现摄像头");
        return;
    }
    QByteArray defaultCameraID=defaultCameraDevice.id();
    ui->actStartCamera->setEnabled(true);

//    disconnect(ui->comboCam_List);  //解除与comboCam_List连接的所有槽函数
    int index=0;
    for(int i=0; i<QMediaDevices::videoInputs().size(); i++)
    {
        QCameraDevice device=QMediaDevices::videoInputs().at(i);
        if (device.id() == defaultCameraID)
        {
            ui->comboCam_List->addItem(device.description()+"(默认)",QVariant::fromValue(device));
            index=i;
        }
        else
            ui->comboCam_List->addItem(device.description(),QVariant::fromValue(device));
    }

    if (ui->comboCam_List->currentIndex() != index)
        ui->comboCam_List->setCurrentIndex(index);

//    foreach(QCameraDevice device, QMediaDevices::videoInputs())
//    {
//        if (device.isDefault())         //是默认设备
//            ui->comboCam_List->addItem(device.description()+"(默认)",QVariant::fromValue(device));
//        else
//            ui->comboCam_List->addItem(device.description(),QVariant::fromValue(device));
//    }

//    ui->comboCam_List->addItem(cameraDevice.description());
//    showCameraDeviceInfo(&cameraDevice);

//    ui->comboCam_List->addItem(cameraDevice.description());

//2. 创建抓取管理器session和各个设备
    session = new QMediaCaptureSession(this);       //抓取管理器
    session->setVideoOutput(ui->videoPreview);      //设置视频输出组件,用于视频预览
//2.1 创建QAudioInput对象,用用音频输入
    QAudioInput  *audioInput=new QAudioInput(this);
    audioInput->setDevice(QMediaDevices::defaultAudioInput());
    session->setAudioInput(audioInput);     //设置音频输入设备

//2.2 创建QCamera对象,用于控制摄像头
    camera = new QCamera(this);        //摄像头
    camera->setCameraDevice(defaultCameraDevice);   //
    session->setCamera(camera);        //为session设置摄像头
    connect(camera, &QCamera::activeChanged,this, &MainWindow::do_camera_activeChanged);
    connect(ui->comboCam_List,&QComboBox::currentIndexChanged,
            this, &MainWindow::do_camera_changed);
    do_camera_changed(ui->comboCam_List->currentIndex());

//2.3 创建QImageCapture对象,用于拍照
    imageCapture = new QImageCapture(this);     //抓图器
    imageCapture->setQuality(QImageCapture::VeryHighQuality);
    session->setImageCapture(imageCapture);     //为session设置抓图器
    connect(imageCapture,&QImageCapture::readyForCaptureChanged,
            this, &MainWindow::do_image_readyForCapture);
    connect(imageCapture,&QImageCapture::imageCaptured,
            this,&MainWindow::do_image_captured);
    connect(imageCapture, &QImageCapture::imageSaved,
            this, &MainWindow::do_image_saved);

    soundEffect =new QSoundEffect(this);     //用于播放音效,拍照时的快门声音
    QString filename=":/sound/images/shutter.wav";
    soundEffect->setSource(QUrl::fromLocalFile(filename));

//2.4 创建QMediaRecorder对象,用于录制视频
    recorder = new QMediaRecorder(this);  //创建recorder
    session->setRecorder(recorder);       //为session设置recorder
    connect(recorder, &QMediaRecorder::durationChanged,
            this, &MainWindow::do_recorder_duration);
    connect(recorder, &QMediaRecorder::recorderStateChanged,
            this, &MainWindow::do_recorder_stateChanged);
    connect(recorder, &QMediaRecorder::errorOccurred,
            this, &MainWindow::do_recorder_error);

//3. 视频编码和文件格式,添加到录像设置的下拉列表框里,用于选择
    QMediaFormat format;
    foreach(QMediaFormat::VideoCodec codec, format.supportedVideoCodecs(QMediaFormat::Encode))
        ui->comboVideo_Codec->addItem(QMediaFormat::videoCodecDescription(codec),
                                      QVariant::fromValue(codec));
    foreach(QMediaFormat::FileFormat fileFormat, format.supportedFileFormats(QMediaFormat::Encode))
        ui->comboVideo_FileFormat->addItem(QMediaFormat::fileFormatDescription(fileFormat),
                                      QVariant::fromValue(fileFormat));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::do_camera_activeChanged(bool active)
{//摄像头状态变化
    ui->actStartCamera->setEnabled(!active);
    ui->actStopCamera->setEnabled(active);

    ui->actVideoRecord->setEnabled(active);
    ui->comboCam_List->setEnabled(!active);

    m_isWorking = active;
}

void MainWindow::do_image_readyForCapture(bool ready)
{//与 readyForCaptureChanged()信号关联
    ui->actCapture->setEnabled(ready);
}

void MainWindow::do_image_captured(int id, const QImage &preview)
{//与 imageCaptured()信号关联
    Q_UNUSED(id);

//    QSize size=imageCapture->resolution();   //被设置了,但是不起作用, Qt  6.2.2的 bug
//    QString str=QString::asprintf("实际图片分辨率= %d X %d",size.width(),size.height());
    QString str=QString::asprintf("实际图片分辨率= %d X %d",preview.width(),preview.height());
    labFormatInfo->setText(str);

    QImage scaledImage = preview.scaledToWidth(ui->scrollArea->width()-30);
    ui->labImage->setPixmap(QPixmap::fromImage(scaledImage));

    if(! ui->chkBox_SaveToFile->isChecked())
        labInfo->setText("图片未保存为文件");
}

void MainWindow::do_image_saved(int id, const QString &fileName)
{//与 imageSaved()信号关联
    Q_UNUSED(id);
    labInfo->setText("图片保存为文件: "+fileName);
}

void MainWindow::do_recorder_duration(qint64 duration)
{//与  durationChanged()信号关联
    labDuration->setText(QString::asprintf("录制时间:%.1f 秒 ",duration/1000.0));
}

void MainWindow::do_recorder_stateChanged(QMediaRecorder::RecorderState state)
{//与 recorderStateChanged()信号关联
    ui->actVideoRecord->setEnabled(state == QMediaRecorder::StoppedState);
    ui->actVideoStop->setEnabled(state == QMediaRecorder::RecordingState);
}

void MainWindow::do_recorder_error(QMediaRecorder::Error error, const QString &errorString)
{//与 errorOccurred()信号关联
    Q_UNUSED(error);
    labInfo->setText(errorString);
}

void MainWindow::on_actStartCamera_triggered()
{//开启摄像头
   camera->start();
}

void MainWindow::on_actStopCamera_triggered()
{//关闭摄像头
    if (recorder->recorderState() == QMediaRecorder::RecordingState)
        recorder->stop(); //停止录像
    camera->stop();
}

void MainWindow::on_actCapture_triggered()
{//"拍照" 按钮
    int index=ui->comboImage_Quality->currentIndex();
    imageCapture->setQuality(QImageCapture::Quality(index));  //图片文件编码品质

    index=ui->comboImage_Resolution->currentIndex();
    QVariant var=ui->comboImage_Resolution->itemData(index);    //用户数据
    imageCapture->setResolution(var.toSize());      //设置分辨率

    //    imageCapture->setResolution(640, 480);  //直接设置也不起作用,是Qt 6.2.2中的bug
    if (ui->chkBox_SaveToFile->isChecked())
        imageCapture->captureToFile();  //拍照并保存到文件
    else
        imageCapture->capture();        //拍照
    if (ui->chkBox_Sound->isChecked())
        soundEffect->play();    //播放快门音效
    ui->tabWidget->setCurrentIndex(0);
}

void MainWindow::on_actVideoRecord_triggered()
{//"开始录像"按钮
    QString selectedFile=ui->editVideo_OutputFile->text().trimmed();
    if (selectedFile.isEmpty())
    {
        QMessageBox::critical(this,"错误","请先设置录像输出文件");
        return;
    }

    if (QFile::exists(selectedFile))
        if (!QFile::remove(selectedFile))
        {
            QMessageBox::critical(this,"错误","所设置录像输出文件被占用,无法删除");
            return;
        }

    recorder->setEncodingMode(QMediaRecorder::ConstantQualityEncoding);   //按固定品质编码
    int index =ui->comboViedo_Quality->currentIndex();
    recorder->setQuality(QMediaRecorder::Quality(index));  //编码品质

    //设置媒介格式
    QMediaFormat mediaFormat;
    index=ui->comboVideo_Codec->currentIndex();
    QVariant var= ui->comboVideo_Codec->itemData(index);    //获取用户数据
    QMediaFormat::VideoCodec codec=var.value<QMediaFormat::VideoCodec>();
    mediaFormat.setVideoCodec(codec);       //设置视频编码

    index=ui->comboVideo_FileFormat->currentIndex();
    var=ui->comboVideo_FileFormat->itemData(index);
    QMediaFormat::FileFormat fileFormat=var.value<QMediaFormat::FileFormat>();
    mediaFormat.setFileFormat(fileFormat);  //设置文件格式

    recorder->setMediaFormat(mediaFormat);  //设置媒介格式

    index=ui->comboVideo_Resolution->currentIndex();
    var=ui->comboVideo_Resolution->itemData(index); //获取用户数据
    recorder->setVideoResolution(var.toSize());     //设置视频分辨率

    labInfo->clear();
    recorder->setOutputLocation(QUrl::fromLocalFile(selectedFile)); //设置输出文件
    recorder->record();
}

void MainWindow::on_actVideoStop_triggered()
{//停止录像
    recorder->stop();
}

void MainWindow::on_btnVideoFile_clicked()
{
    QString curPath=QDir::homePath();
    QString dlgTitle="选择保存文件";
    QString filter="MP4视频文件(*.mp4);;WMV视频文件(*.wmv);;所有文件(*.*)";
    QString selectedFile=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
    if (!selectedFile.isEmpty())
        ui->editVideo_OutputFile->setText(selectedFile);
}

void MainWindow::do_camera_changed(int index)
{
    QVariant var=ui->comboCam_List->itemData(index);
    QCameraDevice device = var.value<QCameraDevice>();
    showCameraDeviceInfo(&device);      //显示摄像头设备信息

    camera->setCameraDevice(device);    //重新设置摄像头设备
    showCameraSupportFeatures(camera);  //显示摄像头支持的特性
}

这段代码是一个基于Qt框架的摄像头应用程序的主窗口类的实现。主要功能包括显示摄像头设备信息、显示摄像头支持的特性、开启和关闭摄像头、拍照和录制视频等。

在构造函数中,进行了以下操作:

  1. 发现摄像头:使用QMediaDevices::defaultVideoInput()获取默认摄像头设备,如果没有找到摄像头则提示用户没有发现摄像头。

  2. 创建抓取管理器session和各个设备:

    • 创建QAudioInput对象用于音频输入,并设置音频输入设备。
    • 创建QCamera对象用于控制摄像头,并设置默认摄像头设备为当前选择的摄像头设备。连接camera的activeChanged信号与槽函数do_camera_activeChanged。
    • 创建QImageCapture对象用于拍照,并设置抓图质量为VeryHighQuality。连接imageCapture的readyForCaptureChanged、imageCaptured和imageSaved信号与相应的槽函数。
    • 创建QMediaRecorder对象用于录制视频,并设置录像相关的信号和槽函数。
  3. 视频编码和文件格式:将支持的视频编码和文件格式添加到录像设置的下拉列表框中,供用户选择。

在析构函数中,释放UI资源。

其他成员函数包括:

  • showCameraDeviceInfo:显示摄像头设备信息,包括位置、支持的拍照分辨率和视频分辨率等。
  • showCameraSupportFeatures:显示摄像头支持的特性,包括颜色温度、曝光补偿、ISO感光度等。
  • closeEvent:处理窗口关闭事件,停止录制视频并关闭摄像头。
  • do_camera_activeChanged:处理摄像头状态变化,更新界面按钮状态。
  • do_image_readyForCapture:处理readyForCaptureChanged信号,更新界面按钮状态。
  • do_image_captured:处理imageCaptured信号,显示拍照的图片和实际图片分辨率。
  • do_image_saved:处理imageSaved信号,显示图片保存的文件名。
  • do_recorder_duration:处理durationChanged信号,更新录制时间显示。
  • do_recorder_stateChanged:处理recorderStateChanged信号,更新录制按钮的状态。
  • do_recorder_error:处理errorOccurred信号,显示错误信息。
  • 槽函数:

    • do_camera_activeChanged:摄像头状态变化时更新界面元素的可用性。
    • do_image_readyForCapture:在可以进行拍照时启用拍照按钮。
    • do_image_captured:拍照后显示预览图片和分辨率信息。
    • do_image_saved:保存图片后显示保存文件的信息。
    • do_recorder_duration:更新录制时间显示。
    • do_recorder_stateChanged:根据录制器状态更新界面元素的可用性。
    • do_recorder_error:处理录制器错误并显示错误信息。
  • 其他函数:

    • on_actStartCamera_triggered:启动摄像头。
    • on_actStopCamera_triggered:停止摄像头,如果正在录制视频,则同时停止录制。
    • on_actCapture_triggered:拍照,根据用户选择设置图片质量和分辨率。
    • on_actVideoRecord_triggered:开始录制视频,根据用户选择设置视频质量、编码格式和分辨率。
    • on_actVideoStop_triggered:停止录制视频。
    • on_btnVideoFile_clicked:选择视频保存文件的路径。
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值