qt QVideoFrame 详解

1. 概述

QVideoFrame 是 Qt 中的一个类,属于 Qt Multimedia 模块,用于表示视频帧数据。它提供了访问视频数据的接口,可以与 QMediaPlayerQVideoWidget 等 Qt 的多媒体组件一起使用。QVideoFrame 类封装了视频帧的内容、格式、尺寸等属性,并提供对视频帧内存的直接访问。

QVideoFrame 主要用于图像处理、视频播放和视频流的管理等场景,允许开发者直接操作视频帧的数据,适用于需要自定义视频渲染和处理的应用。

2. 重要方法

  • QVideoFrame() 构造函数,用于创建一个空的视频帧。

  • QVideoFrame(const QVideoFrame &other) 复制构造函数,用于从另一个 QVideoFrame 对象创建一个副本。

  • bool isValid() const 检查当前 QVideoFrame 是否有效。如果视频帧为空或未正确初始化,返回 false

  • QSize size() const 返回视频帧的尺寸,以像素为单位,格式为 QSize

  • QVideoFrame::PixelFormat pixelFormat() const 返回视频帧的像素格式,表示如何在内存中存储图像数据。

  • QImage toImage() const 将视频帧转换为 QImage 对象,以便进行图像处理或显示。转换可能会丢失一些信息,取决于视频帧的像素格式。

  • QVideoFrame::MapMode mapMode() const 返回当前帧的映射模式(只读、可写等)。这个方法可以帮助用户理解该视频帧的数据是否可以直接修改。

  • bool map(QVideoFrame::MapMode mode) 将视频帧的数据映射到内存中,允许用户直接访问和修改帧的数据。映射操作成功后,可以通过 bits()data() 方法访问帧的数据。

  • void unmap() 解映射操作,将内存中映射的帧数据释放。

  • uchar *bits() 返回指向视频帧数据的指针,用户可以通过该指针直接访问帧数据。只有在帧已被映射后才可以调用此方法。

  • int bytesPerLine(int plane = 0) const 返回每行像素所占的字节数,支持多平面的视频帧格式。比如对于 YUV 格式的视频帧,不同颜色平面的字节数可能不同。

  • QVideoFrame::FrameFlags frameFlags() const 返回当前视频帧的标记,用于描述该帧的特殊特性(例如关键帧)。

3. 重要信号

QVideoFrame 并没有直接的信号机制,它通常与 QMediaPlayerQVideoWidget 或其他多媒体组件配合使用。通过信号槽机制来传递视频帧数据。例如,当视频播放时,QMediaPlayer 会发出信号,例如 QMediaPlayer::videoFrameProbed(),并将视频帧传递给相应的处理函数。

常见的相关信号:

  • QMediaPlayer::videoFrameProbed(QVideoFrame frame) 在视频播放时,QMediaPlayer 会发出此信号,将一个 QVideoFrame 传递给接收者,用于进一步处理或显示。

  • QVideoWidget::paintEvent() 当需要在视频窗口中绘制内容时,会触发此事件,通过重写 paintEvent 可以将 QVideoFrame 渲染到 QWidget

4. 常用枚举类型

QVideoFrame 类中有一些常用的枚举类型,帮助开发者确定视频帧的属性和状态。

  • QVideoFrame::PixelFormat 枚举类型,用于定义视频帧的像素格式,常见的值有:

    • QVideoFrame::Format_Invalid:无效格式。
    • QVideoFrame::Format_RGB32:32位 RGB 格式。
    • QVideoFrame::Format_YUV420P:YUV 420P 格式。
    • QVideoFrame::Format_YUV422P:YUV 422P 格式。
    • QVideoFrame::Format_YUV444P:YUV 444P 格式。
  • QVideoFrame::MapMode 枚举类型,表示视频帧数据的映射模式,常见的值有:

    • QVideoFrame::ReadOnly:只读模式。
    • QVideoFrame::WriteOnly:只写模式。
    • QVideoFrame::ReadWrite:读写模式。
  • QVideoFrame::FrameFlags 枚举类型,表示视频帧的标记,常见的值有:

    • QVideoFrame::FrameIsKeyFrame:表示该帧是关键帧。
    • QVideoFrame::FrameIsInvalid:表示该帧无效。
class CameraWidget : public QWidget {
    Q_OBJECT

public:
    CameraWidget(QWidget *parent = nullptr) : QWidget(parent) {
        QVBoxLayout *layout = new QVBoxLayout(this);
        QLabel *label = new QLabel(this);
        layout->addWidget(label);

        QCamera *camera = new QCamera(QCameraInfo::availableCameras().first(), this);
        QVideoProbe *probe = new QVideoProbe(this);

        connect(probe, &QVideoProbe::videoFrameProbed, this, [this, label](const QVideoFrame &frame) {
            this->processFrame(frame, label);
        });

        probe->setSource(camera);
        camera->setViewfinder(new QCameraViewfinder(this));
        camera->start();
    }

private slots:
    void processFrame(const QVideoFrame &frame, QLabel *label) {
        if (!frame.isValid()) {
            qDebug() << "Invalid frame";
            return;
        }

        QVideoFrame cloneFrame(frame);

        // 将视频帧映射到内存中
        if (cloneFrame.map(QAbstractVideoBuffer::ReadOnly)) {
            // 获取帧数据指针和帧的宽度、高度以及每行字节数
            const uchar *data = cloneFrame.bits();
            int width = cloneFrame.width();
            int height = cloneFrame.height();
            int bytesPerLine = cloneFrame.bytesPerLine();

            // 处理帧数据,例如可以将帧数据转换为 QImage 进行显示或处理
            QImage image(data, width, height, bytesPerLine, QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat()));

            label->setPixmap(QPixmap::fromImage(image));

            // 解映射帧
            cloneFrame.unmap();
        }

    }
};

技术交流qq群:

觉得有帮助的话,打赏一下呗。。

           

需要商务合作(定制程序)的欢迎私信!! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值