修改并显示QAbstractVideoSurface中获取的QVideoFrame
Modifing and displaying QVideoFrames obtained in QAbstractVideoSurface
我有一个用 QT 编写的非常简单的应用程序,我想在其中使用 QMediaPlayer
显示电影,但在显示任何帧之前,我想在其上检测一些对象并标记它们在上面画一个矩形。
我在 http://doc.qt.io/qt-5/videooverview.html 中读到我可以通过 subclassing 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;
}
}
...
}
现在,我收到这个成员函数框架,我想通过在我检测到对象的地方绘制矩形来修改它,然后我想将它们显示在屏幕上(最好是在某些小部件上)。
我该怎么做?
我的 VideoSurface
class 是否应该包含 QWidget
作为成员?或者我应该 subclass QWidget
包含 VideoSurface
?
在这两种情况下,如何显示此帧?我应该先将它转换为 QImage
然后再显示吗(这对我来说很方便,因为我的检测系统正在使用 QImage
,但它是否有效)?我知道我不能从绘画事件外部绘画,所以我不能在 present
函数中绘画,那么这个绘画函数到底应该在哪里,我该如何调用它?
我应该在哪里检测那些对象并修改框架?在present
函数中,还是在绘图函数中?
这取决于您,取决于您喜欢如何构建 classes。我更愿意有一个单独的小部件,它包含一个指向您的 VideoSurface 的指针,并绘制由 VideoSurface 的某些成员函数返回的数据(取决于您在 2 中的解决方案。)
a) QImage 对于某些用途来说足够高效,如果您已经在检测代码中使用它,那么您已经在内存中拥有了所有内容并且可以对其进行处理。与所有与性能相关的担忧一样:测试并查看性能是否足够好。如果不是,您可能还必须考虑以不同的方式进行检测。我参与了一个项目,在该项目中,我们处理了从移动设备上的相机流上的类似 VideoSurface 转换而来的 QImage(对于分辨率相对较低的图像),并且性能足够好,我们还没有费心使用其他技术。该项目 (Neuronify) is hosted here 中 VideoSurface class 的源代码。
b) 您的 present()
函数可以发出一个信号,您可以从其他对象连接到该信号,这些对象从 VideoSurface 获取最新数据并保留它直到调用它们的绘制函数。或者您可以将数据直接应用到某些接受图像数据的小部件。有关示例,请参阅 Use of QAbstractVideoSurface。
同样,这取决于您 :) 但是,如果您需要在某个时候提高性能,您可能希望在不同的线程上进行这项工作,以防止 GUI 在您执行操作时锁定正在处理数据。如果这样做,您需要决定是否必须处理每一帧,或者某些帧是否可以跳过处理以提高播放的 FPS。在后一种情况下,您可能不应该在 present()
函数中执行此操作,因为这可能会使媒体播放器无法在您处理旧帧时为您提供更多帧。
我有一个用 QT 编写的非常简单的应用程序,我想在其中使用 QMediaPlayer
显示电影,但在显示任何帧之前,我想在其上检测一些对象并标记它们在上面画一个矩形。
我在 http://doc.qt.io/qt-5/videooverview.html 中读到我可以通过 subclassing 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;
}
}
...
}
现在,我收到这个成员函数框架,我想通过在我检测到对象的地方绘制矩形来修改它,然后我想将它们显示在屏幕上(最好是在某些小部件上)。
我该怎么做?
我的
VideoSurface
class 是否应该包含QWidget
作为成员?或者我应该 subclassQWidget
包含VideoSurface
?在这两种情况下,如何显示此帧?我应该先将它转换为
QImage
然后再显示吗(这对我来说很方便,因为我的检测系统正在使用QImage
,但它是否有效)?我知道我不能从绘画事件外部绘画,所以我不能在present
函数中绘画,那么这个绘画函数到底应该在哪里,我该如何调用它?我应该在哪里检测那些对象并修改框架?在
present
函数中,还是在绘图函数中?
这取决于您,取决于您喜欢如何构建 classes。我更愿意有一个单独的小部件,它包含一个指向您的 VideoSurface 的指针,并绘制由 VideoSurface 的某些成员函数返回的数据(取决于您在 2 中的解决方案。)
a) QImage 对于某些用途来说足够高效,如果您已经在检测代码中使用它,那么您已经在内存中拥有了所有内容并且可以对其进行处理。与所有与性能相关的担忧一样:测试并查看性能是否足够好。如果不是,您可能还必须考虑以不同的方式进行检测。我参与了一个项目,在该项目中,我们处理了从移动设备上的相机流上的类似 VideoSurface 转换而来的 QImage(对于分辨率相对较低的图像),并且性能足够好,我们还没有费心使用其他技术。该项目 (Neuronify) is hosted here 中 VideoSurface class 的源代码。 b) 您的
present()
函数可以发出一个信号,您可以从其他对象连接到该信号,这些对象从 VideoSurface 获取最新数据并保留它直到调用它们的绘制函数。或者您可以将数据直接应用到某些接受图像数据的小部件。有关示例,请参阅 Use of QAbstractVideoSurface。同样,这取决于您 :) 但是,如果您需要在某个时候提高性能,您可能希望在不同的线程上进行这项工作,以防止 GUI 在您执行操作时锁定正在处理数据。如果这样做,您需要决定是否必须处理每一帧,或者某些帧是否可以跳过处理以提高播放的 FPS。在后一种情况下,您可能不应该在
present()
函数中执行此操作,因为这可能会使媒体播放器无法在您处理旧帧时为您提供更多帧。