创建qml自定义视频源(Qt6.3.1+取景器帧)

前言

笔者之前记录的是Qt5.15的,当前Qt6系列无法使用

笔者本次记录下Qt6中,如何创建qml自定义视频源

一、获取视频帧

这个笔者在之前的文档中记录过,本次算是重复了

1.通过videoSink获取

关键代码如下

    Camera {
        id: camera
    }

    CaptureSession {
        id: captureSession
        camera: camera
        videoOutput: page.videoOutput
    }

    Connections {
        target: videoOutput.videoSink
        function onVideoFrameChanged(frame) {
            //设置并处理已获取视频帧
        }
    }

笔者翻看源码时发现,QMediaCaptureSession中有关于QVideoSink的方法,但没有作为属性导出,不明白官方是什么用意。应该是可以在C++中正常使用的,笔者未测试,感兴趣的小伙伴可以试试

代码很好理解,videoSink的onVideoFrameChanged会将视频帧直接扔出来

2.通过imageCapture获取

正确地说,这是获取静态图片了,关键代码如下

    Camera {
        id: camera
    }

    ImageCapture {
        id: imageCapture
    }

    CaptureSession {
        id: captureSession
        camera: camera
        imageCapture: imageCapture
        videoOutput: page.videoOutput
    }

    Timer {
        id: timer
        interval: 500; running: true; repeat: true
        onTriggered: imageCapture.capture()
    }

    Connections {
        target: imageCapture
        function onErrorOccurred(requestId, error, message) {//发生错误
            console.debug("imageCapture onErrorOccurred",requestId, error, message)
        }
        function onImageCaptured(requestId, previewImage) {//已经捕获到QImage
            console.debug("imageCapture onImageCaptured",requestId, previewImage,imageCapture.preview)

            //imageCapture.preview可以直接作为Image的source,以显示图片
            //previewImage是QImage对象,可以交给C++处理

        }

        }
    }

 代码也很好理解,就是使用定时器,定时获取一个QImage

二、创建视频源

VideoOutput类型的videoSink属性中,有一个setVideoFrame()方法,可以添加新的视频帧,但此方法未注册到qml中,因此需要在C++中实现。笔者定义了一个工具类来实现,关键代码如下

class Tool : public QObject
{
    Q_OBJECT

public:
    explicit Tool(QObject *parent = nullptr);

    //设置并处理已获取视频帧
    Q_INVOKABLE void setVideoFrame(const QVideoFrame frame);
    Q_INVOKABLE void setVideoImage(const QImage image);

    //设置QVideoSink对象实例
    Q_INVOKABLE void setVideoSink(QVideoSink *newVideoSink);

signals:

private:
    QVideoSink *m_videoSink = nullptr;
};

 将此工具类直接注册到qml中,设置好QVideoSink对象实例,然后把已有的视频帧放入就可以了

实现的关键代码如下

/*!
 * \brief Tool::setVideoFrame 设置并处理已获取视频帧
 * \param frame 已获取视频帧
 */
void Tool::setVideoFrame(const QVideoFrame frame)
{
    qDebug()<<Q_FUNC_INFO<<__LINE__<<frame;

    if(m_videoSink != nullptr)
        m_videoSink->setVideoFrame(frame);
}

void Tool::setVideoImage(const QImage image)
{
    qDebug()<<Q_FUNC_INFO<<__LINE__<<image;

    QVideoFrameFormat frameFormat(image.size(), QVideoFrameFormat::Format_BGRA8888);
    QVideoFrame f(frameFormat);

    if (f.map(QVideoFrame::WriteOnly)) {
        memcpy(f.bits(0), image.bits(), image.sizeInBytes());

        f.setStartTime(0);
        f.unmap();
        if(m_videoSink != nullptr)
            m_videoSink->setVideoFrame(f);
    }
}

void Tool::setVideoSink(QVideoSink *newVideoSink)
{
    if (m_videoSink == newVideoSink)
        return;
    m_videoSink = newVideoSink;
}

 实现代码也不复杂,但笔者有点疑问,QImage明明显示是RGB32的颜色空间,但在生成QVideoFrame时,却要使用BGRA8888的颜色空间????

三、运行测试

代码不难理解,只是这个运行结果,有空让人难受

1.在win10下测试时,videoSink获取的QVideoFrame是Format_NV12,与Qt5下的完全不同。

若是需要QImage,可以通过QVideoFrame::toImage()方法直接得到

2.在鸿蒙系统下测试时,videoSink获取的QVideoFrame是Format_SamplerExternalOES,与Qt5下的完全不同。

若是需要QImage,无法通过QVideoFrame::toImage()方法得到,而且一用到这个方法,程序就会卡住,界面没响应

3.在win10下,通过imageCapture可是正常获取到QImage的图像,但在鸿蒙系统下获取会很慢

运行结果就不放图片了,笔者建议还是再等等官方修复吧

笔者测试使用的源码

后记

与之前的版本相关,新版本Qt6.3.1中的多媒体模块,已经修复了不少问题。已经可以使用mingw编译器,qml中可以获取正常的Image source。但目前仍然存在很多问题,如设置分辨率无效等。

笔者听说多媒体模块计划使用ffmpeg实现,笔者很期待

接下来,因项目需要,笔者计划暂时使用openCV获取视频帧,并使用VideoOutput显示

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

꧁白杨树下꧂

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

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

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

打赏作者

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

抵扣说明:

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

余额充值