Qt5.15.2+WebRTC学习笔记(六)打开本机摄像头并显示(win10+vs2019)

前记:

上一篇记录了第一次使用Qt调WebRTC的库,但仅仅输出了梧桐摄像头的名字,本次展示一个简单的示例,展示如何从本地摄像头获取数据,并显示在Qt的界面上

 一、编写源码

1.编辑工程文件(*.pro)

在qtcreator中,新建一下VS2019的工程,打开工程文件,添加如下代码

(1)添加webRTC静态库

#请将{webrtcdir}替换为自己的实际目录
win32:CONFIG(release, debug|release): LIBS += -L{webrtcdir}/src/out/Release_qt/obj/ -lwebrtc
else:win32:CONFIG(debug, debug|release): LIBS += -L{webrtcdir}/src/out/Default_qt/obj/ -lwebrtc

INCLUDEPATH += {webrtcdir}/src
DEPENDPATH += {webrtcdir}/src

win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += {webrtcdir}/src/out/Release_qt/obj/libwebrtc.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += {webrtcdir}/src/out/Default_qt/obj/libwebrtc.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += {webrtcdir}/src/out/Release_qt/obj/webrtc.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += {webrtcdir}/src/out/Default_qt/obj/webrtc.lib

(2)修改VS运行时

QMAKE_CXXFLAGS_RELEASE += /MT
QMAKE_CFLAGS_RELEASE += /MT
QMAKE_CXXFLAGS_DEBUG += /MTd
QMAKE_CFLAGS_DEBUG += /MTd

(3)添加需要链接的静态库

LIBS += -lstrmiids -lOle32 -lOleAut32 -lwinmm -luser32

(4)添加第三方库

#请将{webrtcdir}替换为自己的实际目录
INCLUDEPATH += {webrtcdir}/src/third_party/abseil-cpp
DEPENDPATH += {webrtcdir}/src/third_party/abseil-cpp

INCLUDEPATH += {webrtcdir}/src/third_party/libyuv/include
DEPENDPATH += {webrtcdir}/src/third_party/libyuv/include

(5)增加宏定义

DEFINES += WEBRTC_WIN

2.编写处理数据帧的类CaptureObserver

(1)头文件

关键代码:

增加头文件的引用

#include "modules/video_capture/video_capture_factory.h"
#include "rtc_base/synchronization/mutex.h"
#include "third_party/libyuv/include/libyuv/convert_argb.h"

 类CaptureObserver是从VideoSinkInterface公有继承的

class CaptureObserver : public rtc::VideoSinkInterface<webrtc::VideoFrame>

重载帧处理的函数

//处理接收到的帧
void OnFrame(const webrtc::VideoFrame& videoFrame) override;

(2)源文件

关键代码:

重新实现帧处理的函数

    webrtc::MutexLock lock(&capture_lock_);
    int height = videoFrame.height();
    int width = videoFrame.width();

    incoming_frames_++;

    qDebug()<<"width"<<width<<"height"<<height<<"incoming_frames_"<<incoming_frames_;

//将收到的数据帧转换下格式
    rtc::scoped_refptr<webrtc::I420BufferInterface> buffer(
        videoFrame.video_frame_buffer()->ToI420());

//开辟一段存放BGR数据的空间
    const int length =buffer->width()* buffer->height()*3;
    qDebug()<<"buffer->width()"<<buffer->width()<<"buffer->height()"<<buffer->height();
    uchar *imageBuffer=new uchar[length];

//使用libyuvy库转换一帧数据到BGR
    libyuv::I420ToRGB24(buffer->DataY(), buffer->StrideY(), buffer->DataU(),
                       buffer->StrideU(), buffer->DataV(), buffer->StrideV(),
                       imageBuffer,
                       buffer->width()*3,
                       buffer->width(), buffer->height());
//将得到的数据放入QImage中
    QImage image(imageBuffer,buffer->width(), buffer->height(), QImage::Format_BGR888);
    qDebug()<<image;
    m_lastImage=image.copy();
    delete imageBuffer;

2.修改类MainWindow

(1)修改UI

如下图所示,设计器中加入以下窗口部件

(2)修改头文件

//增加需要的引用
#include "modules/video_capture/video_capture.h"
#include "modules/video_capture/video_capture_factory.h"
#include "captureobserver.h"

#include <QMainWindow>
#include <QDebug>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
//处理点击事件,打开或关闭摄像头
    void on_pushButton_clicked();

private:
//初始化界面上的设备列表
    void getDeviceList();

    Ui::MainWindow *ui;
    QTimer m_timer;

    rtc::scoped_refptr<webrtc::VideoCaptureModule> m_module;
    CaptureObserver m_captureObserver;
    webrtc::VideoCaptureCapability m_capability;
};

(3)修改源文件

关键代码:

//处理点击事件,打开或关闭摄像头
void MainWindow::on_pushButton_clicked()
{
    static bool flag=true;
    if(flag)
    {

        webrtc::VideoCaptureModule::DeviceInfo             
        *device_info_=webrtc::VideoCaptureFactory::CreateDeviceInfo();

        char device_name[256];
        char unique_name[256];

        if(device_info_->GetDeviceName(ui->comboBox->currentIndex(), device_name, 256,
                                       unique_name, 256) !=0)
        {
            qDebug()<<"info->GetDeviceName error";
            return ;
        }

        m_module =
           webrtc::VideoCaptureFactory::Create(unique_name);
        if (m_module.get() == NULL)
        {
            qDebug()<<"webrtc::VideoCaptureFactory::Create error";
            return ;
        }

        m_module->RegisterCaptureDataCallback(&m_captureObserver);

        device_info_->GetCapability(m_module->CurrentDeviceName(), 0, m_capability);


        //开始捕捉
        if(m_module->StartCapture(m_capability)!=0)
        {
            qDebug()<<"m_module->StartCapture failed";
            return;
        }


        if(m_module->CaptureStarted())
        {
            qDebug()<<"Capture is running";
        }

        m_timer.start(40);
        ui->pushButton->setText(tr("关闭"));
    }
    else
    {
        ui->pushButton->setText(tr("打开"));
        m_timer.stop();
        //重复连接会报错,需要先断开,才能再次连接
        m_module->StopCapture();
        if(!m_module->CaptureStarted())
        {
            qDebug()<<"Capture is stoped";
        }
        ui->label->clear();
    }
    flag=!flag;
}
//初始化界面上的设备列表
void MainWindow::getDeviceList()
{
    webrtc::VideoCaptureModule::DeviceInfo 
    *info=webrtc::VideoCaptureFactory::CreateDeviceInfo();
    int deviceNum=info->NumberOfDevices();

    for (int i = 0; i < deviceNum; ++i)
    {
        const uint32_t kSize = 256;
        char name[kSize] = {0};
        char id[kSize] = {0};
        if (info->GetDeviceName(i, name, kSize, id, kSize) != -1)
        {
            ui->comboBox->addItem(QString(name));
        }
    }

    if(deviceNum==0)
    {
        ui->pushButton->setEnabled(false);
    }
}

二、运行结果

若正常运行,并打开摄像头,会显示如下,这是同事送的点心和饮料(PS.其实是太凉了,我喝不下)

注:

笔者在测试时发现,若是关闭摄像头后,立即打开,可能会打开失败,所以请读者自行处理

后记:

 谢谢同事的关心,但也希望对方放松下,不用一天两次的关照(项目)

本次记录的是摄像头相关的,下次计划研究下本地音频相关的

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

꧁白杨树下꧂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值