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

时间:2017-10-09 20:30:25

标签: c++ qt qmediaplayer qvideoframe

我有一个简单的用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成员?或者我应该将包含QWidget

  2. VideoSurface子类化
  3. 在这两种情况下,我该如何显示此框架?我应该首先将其转换为QImage然后显示(这对我来说是可信的,因为我的检测系统正在使用QImage,但它会有效吗?)我知道我不能在绘画事件之外画画,所以我无法在present函数中绘画,所以这个绘画函数到底应该在哪里以及如何调用它?

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

1 个答案:

答案 0 :(得分:0)

  1. 这取决于您并且取决于您希望如何构建类。我希望有一个单独的小部件,它包含一个指向VideoSurface的指针,并绘制VideoSurface的某个成员函数返回的数据(取决于你在2中的解决方案。)

  2. a)QImage对于某些目的而言足够有效,如果您已经在检测代码中使用它,那么您已经拥有内存中的所有内容并且可以使用它。与所有与性能相关的担忧:测试并查看性能是否足够好。如果不是,您可能还需要考虑以不同的方式进行检测。我参与了一个项目,在这个项目中我们处理了从移动设备上的相机流上的类似VideoSurface转换的QImages(对于相对低分辨率的图像),并且性能足够好,我们还没有打算使用其他技术。该项目中的VideoSurface类的源代码(Neuronify)is hosted here。 b)您的present()函数可以发出一个信号,您可以从其他对象连接到从VideoSurface获取最新数据的信号,并保持它直到调用其paint函数。或者您可以将数据直接应用于接受图像数据的某个窗口小部件。有关此示例,请参阅Use of QAbstractVideoSurface

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

    < / LI>