修改和显示在QAbstractVideoSurface中获得的QVideoFrames

Modifing and displaying QVideoFrames obtained in QAbstractVideoSurface

本文关键字:QVideoFrames QAbstractVideoSurface 显示 修改      更新时间:2023-10-16

我有一个用QT编写的简单应用程序,我想在其中使用QMediaPlayer显示电影,但在显示任何帧之前,我想检测一些对象,并在上面画一个矩形来标记它们。

我读过http://doc.qt.io/qt-5/videooverview.html我可以通过对QAbstractVideoSurface进行子类化来访问每个帧,因此我对其进行编辑

class VideoSurface : public QAbstractVideoSurface {
Q_OBJECT
bool present(const QVideoFrame &frame) override {
if (surfaceFormat().pixelFormat() != frame.pixelFormat()
|| surfaceFormat().frameSize() != frame.size()) {
setError(IncorrectFormatError);
stop();
return false;
} else {
currentFrame = frame;
return true;
}
}
...
}

现在,我在这个成员功能框中收到了我想修改的框,在我检测到对象的地方画矩形,然后我想在屏幕上显示它们(最好是在一些小部件上)。

我该怎么做?

  1. 我的VideoSurface类是否应该包含QWidget作为成员?或者我应该将包含VideoSurfaceQWidget子类化?

  2. 在这两种情况下,如何显示此框架?我应该先将其转换为QImage,然后显示(这对我来说很方便,因为我的检测系统使用QImage,但它会有效吗)?我知道我不能在绘画事件之外绘画,所以我不能在present函数中绘画,那么这个绘画函数到底应该在哪里,我该如何调用它?

  3. 我应该在哪里检测这些对象并修改帧?在present函数中,还是在绘图函数中?

  1. 这取决于您喜欢如何构建类。我更喜欢有一个单独的小部件,它可以保存指向VideoSurface的指针,并绘制VideoSurface的某个成员函数返回的数据(取决于您在2中的解决方案)

  2. a) QImage对于某些目的来说已经足够有效了,如果你已经在检测代码中使用它,那么你已经在内存中拥有了一切,并且可以进行处理。与所有与性能相关的担忧一样:测试性能是否足够好。如果不是,您可能还必须考虑以不同的方式进行检测。我曾参与过一个项目,我们在移动设备上的相机流上处理从类似VideoSurface转换而来的QImages(用于相对低分辨率的图像),性能足够好,我们还没有费心使用其他技术。该项目(Neuronify)中VideoSurface类的源代码位于此处。b) 您的present()函数可能会发出一个信号,您可以从其他从VideoSurface获取最新数据的对象连接到该信号,并将其保留到调用其绘制函数为止。或者,您可以将数据直接应用于接受图像数据的某个小部件。请参见QAbstractVideoSurface的使用以获取相关示例。

  3. 同样,这取决于您:)但是,如果您需要在某个时刻提高性能,您可能希望在不同的线程上进行这项工作,以防止您的GUI在处理数据时被锁定。如果你这样做,你需要决定是必须处理每一帧,还是有些帧可以跳过处理来提高播放的FPS。在后一种情况下,您可能不应该在present()函数中执行此操作,因为这可能会使媒体播放器在处理旧帧时无法向您提供更多帧。