Blog
dranbleiben!
Marcelo Emmerich

libVLC Entwicklungsumgebung als Docker Container ohne Qt4

Entwickler komplexer Projekte müssen oft Open-Source Bibliotheken einbinden. Insbesondere in der nativen Entwicklung können diese Bibliotheken eine hohe Anzahl an Abhängigkeiten haben. Diese Abhängigkeiten können sowohl in Form von weiteren Bibliotheken, Tools oder sogar ganze Programmiersprachen auftreten. Ein gutes Beispiel hierfür ist libVLC. libVLC ist die Bibliothek, auf die der populäre VLC Player aufgebaut ist. Als Entwickler kann man libVLC nutzen, um Audio und Video in eigenen Anwendungen abzuspielen.

Wichtig! Die folgenden Ausführungen setzen ein voll funktionsfähiges Linux mit X-Server und aktueller Docker (v1.9.1) Installation voraus.

In einem aktuellen Projekt hatten wir die Aufgabe, eine reproduzierbare Entwicklungsumgebung zu schaffen, auf deren Basis wir eine komplexe Qt5 Anwendung unter Linux implementieren wollten, die unter anderem Videos abspielen sollte. Das stellte uns vor zwei Herausforderungen:

  • wie können wir eine reproduzierbare Entwicklungsumgebung mit einer definierten Version von libVLC schaffen, und trotzdem den Entwicklern die Freiheit lassen, mit ihren bevorzugten Tools und Editoren zu arbeiten?
  • libVLC bindet Qt4 ein. Wir nutzen Qt5. Es ist bekannt, dass sich Qt4 und Qt5 im selben Projekt nicht nebeneinander ausführen lassen, ohne dass es Probleme zur Laufzeit gibt. Wie können wir also eine libVLC Version ohne Qt4 bauen?

Für die erste Herausforderung war eine Lösung relativ schnell gefunden. Wir haben ein Docker Image erstellt, das eine Basis Ubuntu Distribution mit der zu diesem Zeitpunkt aktuellen Version 2.2.1 von libVLC und allen nötigen Tools und Abhängigkeiten enthält. Die Idee ist, dass man als Entwickler den entsprechenden Container lokal ausführt und über einen Volume Mount sein Sourcecode mit dem Container teilt und baut. Somit kann das Editieren des Codes und das Arbeiten mit git und anderen Tools wie gewohnt auf dem lokalen Rechner statt finden. Nur zum Bauen muss der Container bemüht werden.

Das Qt4 Problem haben wir gelöst, indem wir einen Patch in libVLC während der Erstellung des Docker Images eingebaut haben, der zu einer Version von libVLC ohne Qt4 führt. Entgegen anfänglicher Bedenken ist das unproblematisch, weil Qt4 hauptsächlich für Benutzeroberflächen von Plugin-Einstellungen und ähnliches verwendet wird. Da wir libVLC lediglich einbinden und unsere eigene UI entwickelt haben, ist es für uns kein Problem, auf diese Funktionen zu verzichten.

Im Folgenden werde ich zeigen, wie man ein minimales C Programm, das eine Mediendatei mit libVLC wiedergibt, mit dem Image kompilieren und linken kann.

Das Image befindet sich auf unserem öffentlichen Repository, von dort können wir es erst einmal mittels pull auf unserem lokalen Rechner ziehen:

docker pull pulsarsolutions/libvlc_no_qt:2.2.1

Und dann interaktiv ausführen:

docker run --rm -it pulsarsolutions/libvlc_no_qt:2.2.1 bash

Nach dem o.g. Befehl sollte man sich in einer bash Shell im Container befinden. Damit kann man allerdings noch nicht viel anfangen, da es gar keinen Sourcecode zum kompilieren gibt. Das ändern wir jetzt. Wir gehen wieder aus dem laufendem Container indem wir

exit

eingeben. Als nächstes legen wir ein neues Verzeichnis an

mkdir /home/marcelo/projects/vlc_minimal_sample

und erzeugen dort eine neue C-Quelldatei test.c mit folgendem Inhalt:

#include <stdio.h>
#include <stdlib.h>

#include <vlc/vlc.h>

int main(int argc, char **argv)
{
    libvlc_instance_t *inst;
    libvlc_media_player_t *mp;
    libvlc_media_t *m;

    // load the vlc engine
    inst = libvlc_new(0, NULL);

    // create a new item
    m = libvlc_media_new_location(inst, "http://www.sample-videos.com/video/mp4/360/big_buck_bunny_360p_5mb.mp4");

    // create a media play playing environment
    mp = libvlc_media_player_new_from_media(m);

    // no need to keep the media now
    libvlc_media_release(m);

    // play the media_player
    libvlc_media_player_play(mp);

    getchar();

    // stop playing
    libvlc_media_player_stop(mp);

    // free the media_player
    libvlc_media_player_release(mp);

    libvlc_release(inst);


    return 0;
}

Das Programm ist eine minimalistische Implementierung einer Videowiedergabe mit libVLC. Das Video wird direkt aus dem Internet abgespielt, daher sollte der Host, also die Maschine auf der der Container gestartet wird, auch mit dem Internet verbunden sein.

Unser Ziel ist es, diese Datei nun im laufenden Container zu kompilieren und zu linken, denn nur im Container sind die dafür nötigen Tools, Bibliotheken und Abhängigkeiten installiert. Um die Datei dem Container bereitzustellen verwenden wir einen sog. Volume Mount. Das bedeutet, dass ein lokales Verzeichnis (Volume) in ein Verzeichnis im Container gemounted wird. Damit sieht unser docker Aufruf jetzt so aus:

docker run --rm -it -v /home/marcelo/projects/vlc_minimal_sample/:/home/developer/src pulsarsolutions/libvlc_no_qt:2.2.1

Damit wird das lokale Verzeichnis /home/marcelo/projects/vlcminimalsample auf das Verzeichnis /home/developer/src im Container gemounted. An dieser Stelle sei darauf hingewiesen, dass der Container einen Default-Benutzer namens developer anlegt. Dieser Benutzer hat die id 1000 und gehört einer Gruppe die ebenfalls die id 1000 hat. Wenn der lokale Benutzer auf dem Host eine andere Kombination von uid:gid hat, kann es zu einem Rechteproblem kommen. In einem zukünftigen Artikel werde ich beschreiben, wie man damit umgehen kann.

Nachdem wir den o.g. Befehl ausgeführt haben, können wir cd src im Container in das Verzeichnis wechseln, in das unsere Quelldatei liegt. Nun können wir diese wie folgt übersetzen:

gcc $(pkg-config --cflags libvlc) -c test.c -o test.o
gcc test.o -o test $(pkg-config --libs libvlc)

Im Anschluss daran sollte eine ausführbare Datei test im aktuellen Verzeichnis liegen. Mit

./test

kann die Datei ausgeführt werden. Da wir uns in der Kommandozeile befinden werden wir aber nicht viel zu sehen bekommen, die Shell wird höchstens versuchen, das Video im Text-Modus zu rendern. Als letzten Schritt in diesem Artikel werden wir nun die Ausgabe des Containers auf den lokalen X-Server im Host umleiten, so dass wir das Video-Fenster auch sehen können.

Das geschieht mit einem weiteren Volume Mount und der Übergabe der DISPLAY Umgebungsvariable und sieht dann so aus:

docker run --rm \
  -v --net=host \
  -e DISPLAY -v \ /home/marcelo/projects/vlc_minimal_sample/:/home/developer/src \
  -it pulsarsolutions/libvlc_no_qt:2.2.1 bash

ndem wir die DISPLAY Umgebungsvariable sowie die Option --net=host verwenden, kann der Docker Container auf den X Server und somit auf das Display zugreifen.

Die Option --net=host stellt auf Produktivsystemen ein Sicherheitsrisiko dar, da es im Grunde das Netzwerk des Containers nicht kapselt. Daher sollte diese Option nur für lokale Umgebungen verwendet werden, die man selber kontrolliert.

Wenn wir nun

./test

ausführen, sollte das Video in einem neuen Fenster im Host abgespielt werden.

Das war nur ein kurzer Einblick in die Möglichkeiten die Docker bietet, um reproduzierbare Entwicklungsumgebungen bereit zu stellen. Aus Platzgründen sind hier viele Themen nicht erwähnt worden, wie z.B. Audio oder IDEs. Das wird dann Gegenstand zukünftiger Artikel sein.

none
Conventic Icon
Standort Bonn
Burgstraße 69
53177 Bonn
Deutschland
+49 228 76 37 69 70
Standort Braunschweig
Westbahnhof 11
38118 Braunschweig
Deutschland
+49 228 76 37 69 70
Wir sind Mitglied bei
Grouplink Icon
Newsletter abonnieren
Impressum, Haftungsausschluss, Datenschutzerklärung und
© 2024 conventic GmbH · Alle Rechte vorbehalten.