由QImage对象

时间:2018-02-12 18:54:43

标签: c++ performance video qpainter qimage

一点背景:
我正在写一个媒体播放器,我必须在任何给定的视频上绘制一个大点云和一些更多的几何形状。复杂性还在于我们没有定义的视频格式,它可以采用任何格式。 (fps,决议)
一个限制是我们需要使用QT特定组件,如果QT中没有选项,任何外部库都将被讨论。

我确实实现了QAbstractVideoSurface来读取帧,然后使用动态数据对其进行编辑。我在后面提到的代码中遇到了两个具体问题:

  1. 图像加载到QPainter的点,根据图像的分辨率变得非常慢。在低分辨率下,性能与实时性一样好,但在高分辨率下则非常糟糕。
  2. 首先,我知道这是一个众所周知的问题并得到广泛讨论,但我找到的答案都不适合我,因为所有这些答案最终都会出现在特定情况下。

    1. 即使在我几乎实时绘制视频的情况下,我正在绘制的矩形在显示为视频时经常丢失边缘。纯粹的图像转储显示每个像素都已正确绘制。
    2. 我必须接受,在我完成这项任务之前,我对媒体处理一无所知,因为一切都是在飞行中发生的,我没有时间阅读大量文本。但是,如果你指出我正确的文件,我会从乞讨到结束。 :)

      现在,下面是我的QAbstractVideoSurface实施方法的代码:

      bool VideoFrameGrabber::present(const QVideoFrame &frame)
      {
          if (frame.isValid())
          {
              QVideoFrame cloneFrame(frame);
              cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
      
              qDebug()<<"1 "<<QTime::currentTime().msecsSinceStartOfDay(); 
              const QImage image(cloneFrame.bits(),
                                 cloneFrame.width(),
                                 cloneFrame.height(),
                                 QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat()));
              qDebug()<<"2 "<<QTime::currentTime().msecsSinceStartOfDay();
              imageEdited = image;
      
              qDebug()<<"3 "<<QTime::currentTime().msecsSinceStartOfDay();
              QPainter p(&imageEdited);
      
              qDebug()<<"4 "<<QTime::currentTime().msecsSinceStartOfDay();
              if(rectMetaData.count() > 0){
                  while(rectMetaData.at(rectSequence).frameNumber == frameSequence && rectSequence < rectCount-1)
                  {
                      if(rectMetaData.at(rectSequence).fillStatus){                        p.setBrush(QBrush(QColor(rectMetaData.at(rectSequence).color)));
                      } else {
                          p.setPen(rectMetaData.at(rectSequence).color);
                      }    
                      p.drawRect(rectMetaData.at(rectSequence).x1,
                                 rectMetaData.at(rectSequence).y1,
                                 rectMetaData.at(rectSequence).x2,
                                 rectMetaData.at(rectSequence).y2);
                      rectSequence++;
                  }
              }
              qDebug()<<"5 "<<QTime::currentTime().msecsSinceStartOfDay();
              if(circleMetaData.count() > 0){
                  while(circleMetaData.at(circleSequence).frameNumber == frameSequence && circleSequence < circleCount-1)
                  {
                      if(circleMetaData.at(circleSequence).fillStatus)
                      {
      p.setBrush(QBrush(QColor(circleMetaData.at(circleSequence).color)));
                      } else {
                          p.setPen(circleMetaData.at(circleSequence).color);
                      }
      
                      p.drawEllipse(circleMetaData.at(circleSequence).centerX,
                                    circleMetaData.at(circleSequence).centerY,
                                    circleMetaData.at(circleSequence).radiusX,
                                    circleMetaData.at(circleSequence).radiusY);
                      circleSequence++;
                  }
              }
              qDebug()<<"6 "<<QTime::currentTime().msecsSinceStartOfDay();
              p.end();
              //imageEdited.save(QString("frame"+QString::number(frameSequence)+".jpg"));
              frameSequence++;
              cloneFrame.unmap();
          }
      
          if (surfaceFormat().pixelFormat() != frame.pixelFormat()
                  || surfaceFormat().frameSize() != frame.size()) {
              setError(IncorrectFormatError);
              stop();
      
              return false;
          } else {
              currentFrame = QVideoFrame(imageEdited);
              // check by reconverting above to image if it is lost in this conversion
              // else it is a rendering problem
              widget->repaint(targetRect);
              return true;
          }
      }
      

      两种不同视频情况下的调试输出是:

      30 FPS, 1920*1080 pixels
      1  68862821
      2  68862822
      3  68862822
      4  68862892
      5  68862893
      6  68862893
      25 FPS, 1280*720 pixels
      1  69319622
      2  69319622
      3  69319623
      4  69319653
      5  69319654
      6  69319654
      

      请指出一些适合这两个问题的解决方案。

      使用Windows 10 64位/ Intel I5第二代2.3 Gig 2 Core / 8 gig RAM捕获以上性能有人想比较。

0 个答案:

没有答案