1. 概述
QVideoFrame
是 Qt 中的一个类,属于 Qt Multimedia 模块,用于表示视频帧数据。它提供了访问视频数据的接口,可以与 QMediaPlayer
、QVideoWidget
等 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
并没有直接的信号机制,它通常与 QMediaPlayer
、QVideoWidget
或其他多媒体组件配合使用。通过信号槽机制来传递视频帧数据。例如,当视频播放时,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群:
觉得有帮助的话,打赏一下呗。。
需要商务合作(定制程序)的欢迎私信!!