2009-08-06 9 views
29

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

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

libswscaleで必要なビデオスケーリングや色空間変換を行っていますので、すべての処理が完了した後に画像データを表示する方が効率的な方法を知っているかどうかを知りたいと思います。

ありがとうございました。

答えて

26

答えをいただきありがとうございますが、最終的にこの問題を再訪し、優れたパフォーマンスを提供する簡単なソリューションを思いつきました。 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); 
} 

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

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

私の以前の方法では、私のプロセッサをディスプレイ上にペグしていました(デコードは別のスレッドで行っていました)。私のディスプレイスレッドはフルスクリーンの1920x1200 30fps再生のためにコアの約8-9%しか使用しません。 YUVデータをビデオカードにまっすぐ送ることができれば、おそらくもっと良くなるかもしれないと確信していますが、これは十分です。

+0

私はデコーダのスレッドでswfaleでyuvパケットをrgbに変換し、あなたの方法を使用しました。完璧に走っている。 – baci

+0

'p.SetRenderHint(QPainter :: SmoothPixmapTransform、1);' - setRenderHintは小文字でなければなりません。ありがとう、@ottoshmidt。 – ottoshmidt

+0

一定。 –

3

私はgtkmm(gtk + C++ラッピング)と同じ問題があります。 SDLオーバーレイを使用する以外にも、ウィジェットのイメージバッファを直接更新し、再描画を要求することが最善の方法でした。それはQtので実現可能である場合しかし、私はあなたにテクスチャをマッピングし、テクスチャにビデオフレームをコピーしようとすることができます...あなたのOpenGL /シェーディングのスキルに応じて、

私の2セント

3

を知りません四角形(または何か他のもの)を押して、OpenGLシーンに表示します。最も直接的なアプローチではなく、高速です(SDLのようなグラフィックメモリに直接書き込むため)。このフォーマットは圧縮されているので(色、Y =フルCb、Crはフレームの1/4です)、フレームを表示するために必要なメモリとコピーが少なくて済むので、YCbCRを使用することをお勧めします。私は直接Qts GLを使用していませんが、間接的にGLをQt(OSG)で使用しており、リアルタイムで約7-11フルHD(1440 x 1080)のビデオを表示できます。

関連する問題