QMLビデオの例

ビデオやカメラのビューファインダーのコンテンツを変換する。

QML Videoでは、QMLVideoOutputCamera タイプに適用できるさまざまな変換(移動、サイズ変更、回転、アスペクト比の変更)を紹介しています。

また、ネイティブコードとQMLを組み合わせることで、より高度な機能を実装できることも示しています。この例では、C++コードを使ってQMLのフレームレートを計算しています。QMLのフレームレートは、映像の上に半透明のアイテムとして表示されます。

次の画像は、アプリケーションがビデオオーバーレイシーンを実行しているところです。ダミーのオーバーレイアイテム(半透明のRectangle )が作成され、VideoOutput アイテムを横切って移動します。

例の実行

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。

アプリケーションの構造

Main.qml ファイルは、以下の項目を含む UI を作成します:

  • 2 つのButton インスタンス。各インスタンスはファイル名を表示し、FileDialog を起動するために使用できます。
  • 終了Button
  • 利用可能なシーンを表示するフリック可能なリストであるSceneSelectionPanel
  • 左下にはQMLの再描画レートを表示する項目があり、上の数字は瞬時のフレームレート、下の数字は過去1秒間の平均です。

例えば、video-basicシーン(画面中央に静的なVideoOutput )は、VideoBasic.qml 。コードからわかるように、これは一種の継承を利用しています。VideoBasic アイテム ...

SceneBasic {
    contentType: "video"
}

... はSceneBasic... 型である。

import QtQuick
import QtQuick.Controls

Scene {
    id: root
    property string contentType
    ...
    Content {
        id: content
    ...
    }

    Label {
        anchors {
            horizontalCenter: parent.horizontalCenter
            bottom: parent.bottom
            margins: 20
        }
        text: content.started ? qsTr("Tap the screen to stop content")
                              : qsTr("Tap the screen to start content")
        z: 2.0
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            if (content.started)
                content.stop()
            else
                content.start()
        }
    }

    Component.onCompleted: root.content = content
}

それ自体がScene

import QtQuick
import QtQuick.Controls

Rectangle {
    id: root
    ...
    property QtObject content
    ...
    Button {
        id: closeButton
        anchors {
            top: parent.top
            right: parent.right
            margins: root.margins
        }
        z: 2.0
        text: qsTr("Back")
        onClicked: root.close()
    }
}

SceneBasic は、シーンの構造と動作を記述しますが、表示されるコンテンツのタイプについては不可知です - これは、 によって抽象化されます。Content

このパターンによって、特定のユースケース(この場合、単に静的なコンテンツを表示する)を定義し、そのユースケースをビデオ・コンテンツ(VideoBasic )とカメラ・コンテンツ(({CameraBasic}) )の両方でインスタンス化することができます。このアプローチは、他の多くのシーンを実装するために使用される。例えば、「コンテンツを左から右へ繰り返しスライドさせる」はSceneMove によって実装され、VideoMoveCameraMove がベースになっている。

トップレベルのシーンインスタンスのcontentTypeプロパティの値によって、埋め込まれたContent アイテムは、MediaPlayer またはCamera アイテムを作成します。

QMLペインティング率の計算と表示

FrequencyMonitorクラスは、(notify()スロットを介して受信した)イベントのストリームを、瞬間的な頻度と平均化された頻度に変換します:

class FrequencyMonitor : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal instantaneousFrequency READ instantaneousFrequency NOTIFY
                       instantaneousFrequencyChanged)
    Q_PROPERTY(qreal averageFrequency READ averageFrequency NOTIFY averageFrequencyChanged)

public:
    ...
    static void qmlRegisterType();

public slots:
    Q_INVOKABLE void notify();
};

FrequencyMonitorクラスは次のようにQMLに公開されます。

void FrequencyMonitor::qmlRegisterType()
{
    ::qmlRegisterType<FrequencyMonitor>("FrequencyMonitor", 1, 0, "FrequencyMonitor");
}

FrequencyMonitorクラスは次のようにQMLに公開され、FrequencyItemというQMLアイテムを定義することでデータを表示します:

import FrequencyMonitor 1.0

Rectangle {
    id: root
    ...
    function notify() {
        monitor.notify()
    }

    FrequencyMonitor {
        id: monitor
        onAverageFrequencyChanged: {
            averageFrequencyText.text = monitor.averageFrequency.toFixed(2)
        }
    }

    Text {
        id: labelText
        anchors {
            left: parent.left
            top: parent.top
            margins: 10
        }
        color: root.textColor
        font.pixelSize: 0.6 * root.textSize
        text: root.label
        width: root.width - 2*anchors.margins
        elide: Text.ElideRight
    }

    Text {
        id: averageFrequencyText
        anchors {
            right: parent.right
            bottom: parent.bottom
            margins: 10
        }
        color: root.textColor
        font.pixelSize: root.textSize
    }
}

結果は次のようになる:

あとは、QQuickView オブジェクトのafterRendering()シグナルをJavaScript関数に接続し、最終的にfrequencyItem.notify() を呼び出すだけです:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    ...
    QQuickView viewer;
    ...
    QQuickItem *rootObject = viewer.rootObject();
    ...
    QObject::connect(&viewer, SIGNAL(afterRendering()), rootObject, SLOT(qmlFramePainted()));

プロジェクト例 @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。