GUI in Russisch oder VKS-Terminal selbst machen

Erfahrung in der Entwicklung einer C ++ - GUI für das russische Videokonferenzsystem (VKS). Die Synthese moderner Technologie- und Zertifizierungsanforderungen. Der Haupt- "Rechen" der Entwicklung und Wege, um sie zu umgehen. Was haben die GUI und das russische Ballett gemeinsam?

Das erste, was der Benutzer des Videokonferenzsystems sieht, ist die Schnittstelle. In den meisten Fällen beurteilen sie das System anhand seines Erscheinungsbilds und seiner Funktionalität. Eine unbequeme oder weitläufige Benutzeroberfläche ermöglicht es nicht, die hohe Systemleistung oder die breite Funktionalität zu bewerten. Technisch gesehen sollte ein „schönes“ System in eine attraktive und stabile Arbeitsschale eingewickelt werden. Daher wurde zu Beginn der Entwicklung des inländischen VKS-Systems dieser Moment sofort berücksichtigt.

Bild

Wer wird der Benutzer des russischen Videokonferenzsystems sein?


Seit dem Frühjahr 2020 ist die Antwort auf die Frage nach der Zweckmäßigkeit der Entwicklung eines vollwertigen VKS-Systems offensichtlich geworden. Beamte, Handelsunternehmen, Krankenhäuser und Schulen benötigen moderne Kommunikationsmittel mit einem gewissen Maß an Produktivität und Sicherheit. Sie können in Zoom sprechen, aber lohnt es sich, es für ernsthafte Handelsverhandlungen oder ein operatives Treffen von Managern zu verwenden?

Für verschiedene Aufgaben russischer Unternehmen wurde es notwendig, ein inländisches Videokonferenzsystem zu schaffen. Darüber hinaus besteht ein System nicht nur aus einer Softwarekomponente, sondern auch aus einer vollwertigen Hardware. Unter den weltberühmten Anbietern bieten mindestens 5 Unternehmen multifunktionale Videokonferenzsysteme an. In Russland beginnt das Konzept der Importsubstitution jedoch allmählich zu funktionieren. Außerdem sind Sicherheitsprobleme für viele wichtiger geworden als das Herkunftsland des Produkts, und der Preis zu aktuellen Wechselkursen steht nicht an letzter Stelle. Und die "Schönheit" der Benutzeroberfläche erwies sich als ziemlich realistisch, um sie von Grund auf neu zu entwickeln.

GUI beim Start


Die Hauptanforderungen an moderne Schnittstellen sind die schnelle Implementierung, das aktuelle Erscheinungsbild und die vollständige Benutzerfreundlichkeit. Daher war die erste Aufgabe der Entwickler der grafischen Benutzeroberfläche (GUI) eine klare Definition der Softwarefunktionalität für die Videokonferenzen.

Aus Sicht der GUI wurden folgende Anforderungen formuliert:

  • Ausgehende Video- / Audioanrufe tätigen;
  • Eingehende Anrufe annehmen / ablehnen;
  • Automatische Beantwortung eines eingehenden Anrufs in einem benutzerdefinierten Zeitintervall;
  • Wechseln Sie während und außerhalb des Anrufs zwischen zwei Audiogeräten (Headset / Freisprecheinrichtung).
  • Schalten Sie das Mikrofon und die Kamera sowohl während als auch außerhalb des Anrufs ein / aus.
  • DTMF-Wahl während eines Anrufs;
  • Konferenztreffen am Terminal;
  • Verwaltung von PTZ-Kameras, Speichern von PTZ-Voreinstellungen und deren Anwendung;
  • Die Möglichkeit, Videos in verschiedenen Fenstern auszugeben;
  • Steuermaus, Tastatur, Fernbedienung;
  • Die Möglichkeit, das Terminal über die Webschnittstelle fernzusteuern.

Mit dieser Liste von Funktionen können Sie das Problem der Entwicklung einer Schnittstelle auf verschiedene Arten lösen. Darüber hinaus wurde die Auswahl eines bestimmten Implementierungstyps durch Einschränkungen der Art der Programmiersprachen (z. B. war Java aus Zertifizierungsgründen, CSS / HTML - je nach Funktionalität - kategorisch nicht geeignet), die Spezialisierung der Entwickler und das Timing beeinflusst. Insgesamt wurde die Wahl zugunsten von C ++ und der Verwendung des Qt5-Frameworks getroffen, da beispielsweise die modernere QML-Technologie das Rendern von Videos in einem beliebigen OpenGL-Kontext nicht zulässt, was laut ToR für VKS-Terminals erforderlich war.

Bild

Schnell und effizient


Der erste GUI-Prototyp wurde für das Softphone von Qt erstellt und verwendete viele Open-Source-Bibliotheken. Beispielsweise wurden für das SIP-Protokoll eXosip / oSIP-Bibliotheken zum Codieren / Decodieren von Video und Audio - ffmpeg - zum Arbeiten mit Audiogeräten - PortAudio - verwendet. Dieses Softphone funktionierte unter Linux, Windows, MacOS und war ein Technologiedemonstrator und kein echtes Gerät.

Später wurde ein abstraktes Softphone in ein echtes Bildtelefonprojekt umgewandelt, und die erste Version der Software dafür sollte 2 Monate nach dem Start erstellt worden sein. Um dieses Problem in so kurzer Zeit zu lösen, wurde die Telefonsoftware in Module unterteilt und entsprechend den Kompetenzen auf mehrere Entwicklergruppen verteilt. Eine solche Organisation des Prozesses trug dazu bei, das Bildtelefonprojekt schnell und effizient zu entwickeln.

Kern und Front


Zur Vereinheitlichung und zur Möglichkeit, vorhandene GUI-Entwicklungen in anderen Geräten aus einem vorhandenen Projekt zu verwenden, befindet sich die gemeinsame Codebasis in einem separaten Modul - dem GUI-Backend oder dem GUI-Kernmodul. Und direkte Darstellungen, die für verschiedene Geräte unterschiedlich sind, werden in separaten GUI-Frontmodulen implementiert.

Diese Architektur der GUI-Module erwies sich als vorteilhaft und führte zum gewünschten Ergebnis: Die Entwicklung von Schnittstellen für die neuen Komponenten des VKS-Systems selbst ist relativ schnell und qualitativ hochwertig geworden. Schließlich mussten die Schnittstellen für VKS-Terminals jetzt nicht mehr von Grund auf neu geschrieben werden.

Qual und Sieg


Auf dem Weg zur Erstellung von Software gibt es natürlich Schwierigkeiten und Probleme. Das Erstellen einer GUI für die Videokonferenzen war keine Ausnahme. Unabhängig vom spezifischen Zweck des Systems können sie in jedem Befehl wiederholt werden. Schwierigkeiten und Siege auf dem Entwicklungspfad sind für Kollegen interessant und führen möglicherweise zu effektiven Lösungen ohne unseren „Rechen“.

Für immer Konsistenz


Historisch gesehen war das allererste interessante Problem, das während der Entwicklung der GUI für verschiedene Arten von VKS-Terminals auftrat, das Problem der Konsistenz, dh des koordinierten Zustands aller Module. Während des Betriebs interagiert die GUI mit mehreren anderen Modulen: einem Modul für die Interaktion mit Hardware, einem Anrufverwaltungssubsystem, einem Medienverarbeitungsmodul (MCU) und einem Benutzerinteraktionssubsystem.

Bild

Anfänglich arbeitete die GUI mit all diesen Modulen als unabhängig, dh sie konnte gleichzeitig Anforderungen an zwei verschiedene Module senden. Dies stellte sich als falsch heraus und führte manchmal zu Problemen, da diese Module selbst nicht unabhängig waren und aktiv miteinander interagierten. Die Lösung des Problems war die Erstellung eines speziellen Arbeitsschemas, das eine streng sequentielle Ausführung der Anforderungen in allen Modulen sicherstellte.

Es gab zwei Schwierigkeiten beim Hinzufügen: Erstens erfordern einige (aber nicht alle) Anforderungen eine Antwort, in deren Erwartung sich das Terminal tatsächlich in einem inkonsistenten Zustand befindet, sodass andere Anforderungen nicht ausgeführt werden können. Es ist jedoch auch unerwünscht, die Benutzeroberfläche zu blockieren, während auf Antworten gewartet wird. Zweitens kommen Antworten auf GUI-Anforderungen von Modulen sowie Anforderungen von Modulen an die GUI in ihren eigenen Threads, die sich von der GUI unterscheiden. Die GUI muss jedoch alle Änderungen in ihrem Status in ihrem Thread implementieren (Qt erfordert dies für einige Aktionen, jedoch in In einigen Fällen werden dadurch unnötige Schwierigkeiten bei der Gewährleistung der Thread-Synchronisation vermieden.

Die Lösung wurde gefunden und bestand aus zwei Teilen. Zunächst wurden alle Anforderungen / Antworten von anderen Modulen mithilfe des Qt-Signalschlitzmechanismus in Verbindung mit QueuedConnection, dh mithilfe der globalen QApplication-Ereignisschleife, an den GUI-Stream umgeleitet. Um eine konsistente Verarbeitung aller Anforderungen zu gewährleisten, wurde ein Transitions-System mit einer eigenen Warteschlange und einem eigenen Verarbeitungszyklus (TransitionLoop) entwickelt.

Wenn der Benutzer eine Aktionstaste in der GUI drückt (z. B. die Anruftaste), wird ein entsprechender Übergang erstellt, der in die Übergangswarteschlange gestellt wird. Danach wird ein Signal für den Übergangsverarbeitungszyklus erzeugt. TransitionLoop prüft beim Empfang eines Signals, ob gerade ein Übergang stattfindet. Wenn dies der Fall ist, wird das Warten auf den Abschluss des aktuellen Übergangs fortgesetzt. Wenn nicht, wird der nächste Übergang aus der Übergangswarteschlange abgerufen und gestartet. Wenn eine Antwort von einem anderen TransitionLoop-Modul mit demselben Signal empfangen wird, wird der Abschluss des aktuellen Übergangs benachrichtigt und TransitionLoop kann den nächsten Übergang aus der Warteschlange starten.

Wichtig hierbei ist, dass die gesamte Übergangsverarbeitung in einem GUI-Thread erfolgt. Dies wird durch die Verwendung des Qt-Signalschlitzmechanismus in der QueuedConnection-Variante sichergestellt, bei dem für jedes Signal ein Ereignis generiert und in der Hauptereignisschleife der Anwendung platziert wird.

OpenGL-Rendering auf stromsparender Hardware


Eine weitere Schwierigkeit, mit der wir uns befassen mussten, war das Problem beim Rendern von Videos. Qt ermöglicht das OpenGL-Rendern einer speziellen QOpenGLWidget-Klasse und verwandter Hilfsklassen, die ursprünglich zum Rendern von Videos verwendet wurden. Die Daten zum Rendern (decodierte Videobilder) selbst werden vom Medienverarbeitungsmodul (MCU) bereitgestellt, das unter anderem die Hardware-Decodierung des Videostreams (auf der GPU) implementiert. Bei Prozessoren mit geringem Stromverbrauch wurde eine "Verlangsamung" des Renderns von FullHD-Videos festgestellt. Die direkte Lösung bestand darin, den Prozessor auszutauschen. Dies würde jedoch eine ernsthafte Verarbeitung der bereits fertigen Komponenten des Videokonferenzsystems erfordern und die Kosten für die Geräte selbst erhöhen. Daher wurde der gesamte Renderprozess sorgfältig analysiert, um bessere Möglichkeiten zur Lösung des Problems zu finden.

Beim Standard-OpenGL-Rendering und der Hardware-Decodierung geschieht Folgendes: Daten mit codiertem Video stammen aus dem Netzwerk, werden im RAM gespeichert, und diese Daten aus dem RAM werden in den Videospeicher der GPU übertragen, wo sie decodiert werden. Dann werden decodierte Daten mit einem wesentlich größeren Volumen als codierte Daten erneut in den RAM übertragen. Als nächstes kommt ein Rendering-Code ins Spiel, der diese Daten vom RAM direkt zum Rendern zurück zur GPU überträgt. Somit werden ziemlich große Datenmengen durch den Speicherbus hin und her gepumpt, und der Bus kann dies einfach nicht.

In modernen Versionen von OpenGL gibt es spezielle Erweiterungen, mit denen Sie festlegen können, dass Daten gerendert werden sollen, die sich bereits im GPU-Speicher befinden, und nicht wie üblich Daten im Haupt-RAM. Dieser Mechanismus schloss das Verschieben von Daten von Hardware-decodierten Frames von der GPU in den RAM und dann zurück aus. Damit war das Problem des Renderns auf Prozessoren mit geringem Stromverbrauch nahezu gelöst.

Bild

Ein weiteres großes Problem waren die in Qt unterstützten OpenGL-Kontexte. Sie können die erforderliche OpenGL-Erweiterung nicht verwenden, dh Sie können QOpenGLWidget mit dieser Option nicht verwenden. Die Lösung bestand darin, ein reguläres QWidget zu verwenden, die Qt-Rendering-Pipeline jedoch auszuschalten. Eine solche Möglichkeit besteht in Qt. Hier stellte sich jedoch eine Frage, da bei dieser Option die GUI für das gesamte Rendern im Bereich dieses Widgets voll verantwortlich ist. Qt hilft uns nicht. Dies ist normal für die Anzeige von Videos. Für die Verwendung von Widgets über Videos können jedoch keine regulären Qt-Tools verwendet werden, da beispielsweise über dem Video ein zusätzliches Popup-Menü angezeigt werden muss.

Dieses Problem wurde wie folgt gelöst: Aus dem vorhandenen Widget wird das Bild abgerufen (QWidget verfügt hierfür über eine grab () -Methode), das resultierende Bild wird in eine OpenGL-Textur konvertiert und letztere mit OpenGL-Tools über dem Video gerendert. Durch Hinzufügen der entsprechenden Umgebung wurde ein universeller Mechanismus implementiert, mit dem alle Standard-Widgets über dem Video auf eine nicht standardmäßige Weise angezeigt werden können.

Kioske und Widgets


Die Verwaltung von Anzeigen und die Verteilung von Fragmenten der Benutzeroberfläche im Kiosk-Modus war nicht einfach. Das VKS-Terminal kann in zwei Modi betrieben werden: Fenstermodus, dh wie jede andere Fensteranwendung in der Desktop-Umgebung des Betriebssystems, und „Kiosk-Modus“ (dh das Betriebssystem führt nur eine Anwendung mit einer grafischen Oberfläche aus - VKST - und es gibt keine Umgebung Desktop).

Im Fenstermodus ist alles relativ einfach: Das Fenster wird vom Fenstermanager der Desktop-Umgebung gesteuert, die Anwendung erstellt bei Bedarf ein zweites Fenster und der Benutzer verteilt die Fenster auf den Displays nach Bedarf. Im „Kiosk“ -Modus ist jedoch alles viel komplizierter, da das System keinen Fenstermanager hat und es nur ein Fenster geben kann und der Benutzer nicht in der Lage ist, es zu verschieben. Daher erschien die Aufgabe, ein Ereignis automatisch zu erkennen, beispielsweise eine Anzeige zu verbinden / zu trennen. Bei diesem Ereignis mussten die Anzeigen automatisch konfiguriert und Fragmente der Benutzeroberfläche korrekt darauf platziert werden.

Bild

Die Antwort kam von der LINUX Xrandr OS-Systembibliothek, die für die Arbeit mit Displays verantwortlich ist. Da es im Internet nur sehr wenige Dokumentationen gibt, wurde die Implementierung anhand von Beispielen aus dem Internet durchgeführt, einschließlich von Habr. Darüber hinaus war es notwendig, einen Algorithmus zum Verteilen von Schnittstellenfragmenten auf Displays zu entwickeln und zwei verschiedene Fenster in ein einziges zu integrieren. Letzteres wurde wie folgt implementiert: Was sind Fenster im Fenstermodus, im "Kiosk" -Modus sind Widgets in einem großen Fenster, das sich über 2 Anzeigen erstreckt (wenn es 2 davon gibt). In diesem Fall müssen Sie die Positionen der Anzeigen so konfigurieren, dass ein kontinuierlicher virtueller Raum erstellt wird (dies erfolgt mithilfe der XRandr-Bibliothek), und dann die Geometrie der internen Widgets in einem einzelnen globalen Fenster festlegendamit jeder auf sein Display kommt.

Wir schaffen Russisch


Die gesamte Art der Erstellung des russischen Videokonferenzsystems bestand aus vielen Phasen, und die grafische Benutzeroberfläche ist nur die Spitze des Eisbergs. Das Auffälligste und nicht das Schwierigste. Die Komplexität der Lösung, die Kombination von Software und Hardware sowie Softwarekomponenten und der Wunsch, ein technisch und ästhetisch „schönes“ System zu schaffen, verursachten jedoch viele Schwierigkeiten. Neue Aufgaben führten zu nicht standardmäßigen Lösungen und trugen dazu bei, ein Produkt zu schaffen, das sich nicht schämt, nicht nur in Russland, sondern auch im Ausland zu zeigen.

Russische Entwicklungen haben sich seit langem bewährt, und das in einer schönen Hülle und Wettbewerbsfähigkeit. Unsere Life-Hacks werden für alle nützlich sein, die ernsthaft an der Entwicklung von GUI beteiligt sind, und wir hoffen, dass sie anderen Entwicklern helfen werden, den Prozess der Erstellung moderner Shells für neue russische Softwareprodukte zu beschleunigen und zu vereinfachen. Wir glauben, dass russische Entscheidungen in der Welt nicht weniger geschätzt werden als russisches Ballett oder schwarzer Kaviar.

All Articles