Mastodon

Hello zusammen!

In der letzten Woche habe ich Fortschritte mit der QML-Rendering-Bibliothek erzielt (siehe den Code hier).

Es tut, was es tun soll – es rendert eine Input-QML-Datei als output Frames eines bestimmten Formats, und rendert so schnell wie möglich (mit QQuickRenderControl). Wenn Sie es testen möchten gibt es einen CLI-Zugriff über eine ausführbare Datei (was eines der Dinge ist, an denen ich in der letzten Woche gearbeitet habe) für die Bibliothek im Testverzeichnis hier (stellen Sie sicher, dass Sie die READMEs lesen!)

Versuchen wir also zu verstehen, was wirklich im Kern der Bibliothek passiert; im Rendering-Teil.

Um QML zu rendern, ist es naheliegend, “Screenshots” jedes Frames mit einer grab () – Methode zu erstellen, die alle Pixel zu jedem Zeitpunkt erfasst und dann rendert – dies ist nicht nur sehr langsam und aufwändig, sondern auf diese Weise kann auch nicht mit einer benutzerdefinierten Bildrate gerendert werden.

Hier kommt QQuickRenderControl ins Spiel. QQuickRenderControl wird verwendet, um Qt Quick-Inhalte (Lese-QML) sehr kontrolliert auf irgendetwas zu rendern. Wenn Sie die offizielle Dokumentation lesen, ist ‘irgendetwas’ ein ‘Offscreen-Rendering-Ziel’ – Betonung auf ‘Offscreen’ -, was bedeutet, dass wir unser Dummy-Fenster oder unsere Oberfläche anweisen können, unser QML auf irgendetwas anderes zu rendern (ein QOpenGLFramebufferObject, um genau zu sein) und das in einem sehr schnellen Prozess!

Das war die Beschreibung in Worten, jetzt wollen wir etwas Code sehen – ich möchte Sie nicht (weiter) verwirren, aber dies ist wesentlich, weil der Kern der neuen Bibliothek das beschriebene Rendering ist.

Bevor wir mit dem Rendern beginnen, müssen wir QQuickRenderControl einrichten:

1) Einstellen des Formats der Oberfläche, auf der das Rendering ausgeführt werden soll.

QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);

2) Einrichten des OpenGL-Kontext

m_context = std::make_unique<QOpenGLContext>();
m_context->setFormat(format);
m_context->create();

3) Einrichten der Oberfläche (Dummy)

m_offscreenSurface = std::make_unique<QOffscreenSurface>();
m_offscreenSurface->setFormat(m_context->format());
m_offscreenSurface->create();

4) Einrichten von RenderControl und Zielfenster (Dummy)

m_renderControl = std::make_unique<QQuickRenderControl>(this);
m_quickWindow = std::make_unique<QQuickWindow>(m_renderControl.get());
m_context->makeCurrent(m_offscreenSurface.get());
m_renderControl->initialize(m_context.get());

5) Erstellen des Bildpufferobjekts und Anweisung an QuickWindow dieses Objekt zu rendern

m_fbo = std::make_unique<QOpenGLFramebufferObject>(m_size * m_dpr, QOpenGLFramebufferObject::CombinedDepthStencil);
m_quickWindow->setRenderTarget(m_fbo.get());

Und damit können wir anfangen zu rendern, aber es gibt einen Haken – wir können noch nicht mit einer benutzerdefinierten Framerate rendern, wie ich bereits sagte (und genau das versuchte der Blog, den ich zuvor erwähnt hatte, in erster Linie zu adressieren). Um dies zu erreichen, müssen wir den Animationstreiber optimieren – wir erstellen unseren eigenen Animationstreiber damit Frames in der gewünschten Framerate erzeugt werden:

void advance() override
{
m_elapsed += m_step;
advanceAnimation();
}

Damit und mit den nächsten 4 Zeilen (natürlich in einer ereignisgesteuerten Schleife)

m_renderControl->polishItems();
m_renderControl->sync();
m_renderControl->render();
m_context->functions()->glFlush();

Rendern wir Frames! (Wenn Sie diesen Code in der Praxis sehen möchten, schauen Sie sich bitte root/QmlRenderer/src/ an.)

So funktioniert es – in meiner bisherigen Arbeit habe ich den oben genannten Code fast serienreif gemacht.

Für die nächste Woche habe ich bereits angefangen, Komponententests zu schreiben, um sicherzustellen, dass die Bibliothek in Zukunft jederzeit einwandfrei funktioniert. Und danach werde ich anfangen MLT zu flicken und einen MLT-Produzenten zu schreiben.

Und jetzt werden Sie vielleicht Fragen: Warum diese Bibliothek als unabhängige Bibliothek entwickeln? Warum nicht einfach direkt in MLT integrieren?

Weil
a) Modularität: Es ist einfacher einen unabhängigen Code zu testen und sicherzustellen, dass er funktioniert.
b) Einfache Integration: Es ist einfacher ein Modul in ein Framework zu integrieren – da über die Zukunft von MLT in Kdenlive diskutiert wird.

Das wars für diese Woche, lass uns auf das Beste hoffen!

Übersetzung des Artikels von