web-dev-qa-db-ja.com

Qtでデコードされたビデオフレームを表示する最も効率的な方法は何ですか?

Qtウィジェットに画像を表示する最速の方法は何ですか? libavformatとlibavcodecを使用してビデオをデコードしたので、生のRGBまたはYCbCr 4:2:0フレームがすでにあります。現在、QGraphicsPixmapItemを含むQGraphicsSceneオブジェクトでQGraphicsViewを使用しています。現在、メモリバッファからQImageコンストラクタを使用してフレームデータをQPixmapに取得し、QPixmap :: fromImage()を使用してQPixmapに変換しています。

私はこの結果が好きで、比較的速いように見えますが、もっと効率的な方法があるはずだと思わずにはいられません。また、QImageからQPixmapへの変換にはコストがかかると聞きました。ウィジェットにSDLオーバーレイを使用するソリューションを実装しましたが、QGraphicsViewを使用してビデオディスプレイでのクリックやその他のユーザーインタラクションを簡単にキャプチャできるため、Qtだけを使用したいと思います。

Libswscaleを使用して必要なビデオスケーリングまたは色空間変換を行っているので、すべての処理が実行された後、画像データを表示するためのより効率的な方法があるかどうかを知りたいだけです。

ありがとう。

36
Jason B

答えてくれてありがとう、しかし私はついにこの問題を再考し、良いパフォーマンスを与えるかなり単純な解決策を思いついた。これには、QGLWidgetから派生し、paintEvent()関数をオーバーライドすることが含まれます。 paintEvent()関数内で、QPainter::drawImage(...)を呼び出すことができ、可能な場合はハードウェアを使用して、指定された長方形へのスケーリングを実行します。したがって、次のようになります。

_class QGLCanvas : public QGLWidget
{
public:
    QGLCanvas(QWidget* parent = NULL);
    void setImage(const QImage& image);
protected:
    void paintEvent(QPaintEvent*);
private:
    QImage img;
};

QGLCanvas::QGLCanvas(QWidget* parent)
    : QGLWidget(parent)
{
}

void QGLCanvas::setImage(const QImage& image)
{
    img = image;
}

void QGLCanvas::paintEvent(QPaintEvent*)
{
    QPainter p(this);

    //Set the Painter to use a smooth scaling algorithm.
    p.setRenderHint(QPainter::SmoothPixmapTransform, 1);

    p.drawImage(this->rect(), img);
}
_

これで、私はまだYUV 420PをRGB32に変換する必要がありますが、ffmpegはlibswscaleでその変換の非常に高速な実装を持っています。主なメリットは次の2つです。

  • ソフトウェアのスケーリングは必要ありません。スケーリングはビデオカードで行われます(利用可能な場合)
  • QPainter::drawImage()関数で発生するQImageからQPixmapへの変換は、アップスケールされたフルスクリーン解像度ではなく、元の画像解像度で実行されます。

以前の方法で、プロセッサをディスプレイだけに固定していました(デコードは別のスレッドで実行されていました)。現在、私のディスプレイスレッドは、フルスクリーン1920x1200 30fpsの再生にコアの約8〜9%しか使用していません。 YUVのデータを直接ビデオカードに送ることができれば、おそらくもっと良くなると思いますが、今のところこれで十分です。

34
Jason B

Gtkmm(gtk + C++ラッピング)でも同じ問題があります。 SDLオーバーレイを使用する以外の最善の解決策は、ウィジェットの画像バッファーを直接更新してから、再描画を要求することでした。しかし、それがQtで実現可能かどうかはわかりません...

私の2セント

3
neuro

OpenGL /シェーディングのスキルに応じて、ビデオフレームをテクスチャにコピーし、テクスチャを長方形(またはその他の楽しいもの)にマッピングして、OpenGLシーンに表示することができます。最も単純なアプローチではありませんが、グラフィックメモリ(SDLなど)に直接書き込んでいるため、高速です。また、このフォーマットは圧縮されているため(カラー、Y =フルCb、Crはフレームの1/4)、YCbCRのみを使用することをお勧めします。そのため、フレームを表示するために必要なメモリとコピーが少なくて済みます。私はQts GLを直接使用していませんが、Qt(vis OSG)でGLを使用して間接的に使用しており、約7-11フルHD(1440 x 1080)を表示できます)リアルタイムのビデオ。

3
count0