Dienstag, 9. Juni 2009

RTMPDump unter Windows mit MinGW compilieren

RTMPDump compilieren

Um RTMPDump compilieren zu können ist zunächst unter Windows MinGW aufzusetzen, dann OpenSSL zu compilieren und dann RTMPDump zu compilieren (benötigt die OpenSSL-Bibliotheken).


0. Compile-Umgebung

MinGW-Umgebung herunterladen (http://www.mingw.org/) und aufsetzen (inkl. Perl).

"bin"-Verzeichnis von mingw muss im Pfad sein.

MSYS-Bash über Batch starten.

msys.bat

Anmerkung: Eine Anleitung zum Aufsetzen von MinGW ist NICHT Gegenstand dieser Anleitung.


1. OpenSSL compilieren

OpenSSL-Sourcen herunterladen (http://www.openssl.org/source/) und in temporäres Verzeichnis unterhalb von mingw entpacken (z.B. "temp/rtmpdump/openssl-1.0.0-beta2").

Hinweis:
openssl-0.9.8k läßt sich NICHT richtig compilieren
openssl-1.0.0-beta2 *GEHT prima*

OpenSSL-Build für mingw-Win32-Platform konfigurieren:

./Configure mingw --prefix=`pwd`/win32libs -DL_ENDIAN -DOPENSSL_NO_HW

Compilieren:

make -k

Hinweis: i) Der Build dauert etwas. Ruhig mal 'ne Zigarette rauchen gehen. :-) ii) Der Parameter "-k" ist wichtig, sonst bricht Build beim 1. Fehler ab. Fehler kommen bei den Tests bei denen in manche C-Dateien nur "link: dummytest.c" geschrieben wurde. Das compiliert natürlich nicht, macht aber auch im weiteren Verlauf nichts aus. Mit dem Parameter "-k" ignoriert make brav diese einzelne Fehler und der Build läuft durch.

Win32-Anwendungspaket erstellen:

make install_sw

Anschließend finden sich die Win32-Files (und vor allem die im folgenden benötigten Bibliotheken zum Verlinken) im Unterverzeichnis "win32libs".


2. RTMPDump compilieren

RTMPDump-Sourcen herunterladen (http://lkcl.net/rtmp/) und in temporäres Verzeichnis unterhalb von mingw entpacken (z.B. "temp/rtmpdump").

Anpassen des OpenSSL-Verzeichnisses im "MakefileWIN32" je nach verwendeter Version:

CXXFLAGS=-Wall -I openssl-VERSION/include/
LDFLAGS=-Wall -L openssl-VERSION/win32libs/lib/


RTMPDump compilieren

make -f MakefileWIN32 rtmpdump

Danach befindet sich "rtmpdump_win32.exe" im Verzeichnis.

Fertig!

Mittwoch, 3. Juni 2009

USB-Probleme - Verschwundener CardReader und Fehler in der Hotplug.dll

USB-Geräte haben bei mir bisher unter Windows XP noch nie irgendein Problem verursacht... bis eben... und dann auch noch gleich zwei Probleme auf einmal. :-) Meine Lösung möchte ich teilen, damit andere ggf. schneller zum Ziel kommen.

Probleme

1. Beim Schreiben einer größeren Datenmenge auf eine SD-Karte in meinem _internen_ USB-CardReader meldete Windows Datenverlust. Anschließend war der CardReader verschwunden. Auch ein mehrmaliger Neustart des Rechners brachte den CardReader nicht zurück.

2. Bei einem Klick mit der rechten Maustaste auf das "Hardware sicher entfernen"-Tray-Icon und Auswahl von "Hardware sicher entfernen" erschien statt des erwarteten Dialogs lediglich die Meldung:

Beim Ausführen von "shell32.dll,Control_RunDLL hotplug.dll" ist eine Ausnahme aufgetreten.

Lösung 1: CardReader reaktivieren

Die Lösung ist relativ unspektakulär:

1. Rechner herunterfahren.

2. Netzteil ausschalten, oder falls kein Schalter vorhanden, Netzstecker ziehen.

3. Power-Knopf für einige Sekunden gedrückt lassen um Spannung aus Netzteil zu ziehen.

4. Netzteil einschalten, bzw. Netzstecker wieder einstecken.

5. Rechner starten -> der CardReader wird wieder erkannt.

Wer den Rechner offen hat, oder den Rechner nicht herunterfahren kann/will (Server?) einfach Gehäuse öffnen, Stecker des CardReaders vom Mainboard ziehen und wieder einstecken.

Hintergrund:

Dieser CardReader (VID 07CC, PID 0301, REV 0005) hängt sich gerne mal beim Schreiben großer Datenmengen auf. Das ist ein Problem des Geräts und nicht von Windows, da dieser Fehler auch auf anderen Rechnern unter Linux auftritt (siehe Beitrag von Thomas Thanner hier). Da USB-Geräte selbst bei ausgeschaltetem Rechner mit Strom versorgt werden, verbleibt das Gerät nun ewig im abgestürztem Zustand. Über den USB-Bus kann man es auch nicht mehr ansprechen, da es mit diesem nicht mehr kommuniziert. Einen externen CardReader hätte man jetzt schnell vom USB-Port abgezogen (Strom weg) und wieder angesteckt (Gerät startet neu), was aber bei internen Geräten ohne das Öffnen des Gehäuses nicht möglich ist. Zudem ist es unmöglich USB-Controller, die in handelsüblichen Rechnern verbaut werden, dazu zu bekommen die Stromzufuhr zu USB-Geräten zu unterbrechen. Das ist zwar in der EHCI-Spezifikation (USB 2.0) vorgesehen, aber selbst die EHCI-Controller der neusten Intel ICH-Familie unterstützen dieses Feature nicht (siehe z.B. im Datasheet den Kommentar zu Bit 12 der PORTSC-Struktur). Wer Glück hat, der hat ein Mainboard dessen BIOS es zumindest erlaubt die Stromzufuhr bei ausgeschaltetem Rechner abzustellen.

Zusammenfassend ergibt sich:

  • Kommandos am USB-Port (ein-/ausschalten, Reset, o.ä.) nimmt das Gerät nicht an, da es abgestürzt ist und gar nicht mehr mit dem USB-Port kommuniziert.

  • Es ist NICHT möglich die Stromzufuhr zum Gerät per Software zu unterbrechen (z.B. über den USB-Hub).

  • Auch bei ausgeschaltetem Rechner werden USB-Ports mit Strom versorgt.

  • Es existiert meist keine BIOS-Option um die Stromversorgung der USB-Ports bei ausgeschaltetem Rechner abzustellen.

  • => Um ein abgestürztes, internes USB-Gerät wieder in Betrieb zu nehmen, muss der Rechner "hart" vom Strom getrennt werden (Netzteil aus!).


Eine ganz andere Situation ergibt sich, wenn das Gerät gar nicht abgestürzt ist, sondern z.B. aus Versehen über "Hardware sicher entfernen" entfernt wurde. Hier genügt es den USB-Hub zu deaktivieren und anschließend wieder zu aktivieren. Hierbei fordert der Hub die Geräte beim Deaktivieren auf sich auszuschalten, bzw. in Standby zu gehen. Beim Reaktivieren sender der Hub an alle Geräte Kommandos damit diese wieder erwachen und sich neu anmelden. Ist das Gerät nicht abgestürzt, so ragiert es auf die Kommandos und erscheint wieder neu (im Falle von Massenspeichern inkl. aller Laufwerke). Das ganze lässt sich bequem über die Kommandozeile mit dem Tool Devcon von Microsoft erledigen:

>devcon disable @USB\ROOT_HUB*
>devcon enable @USB\ROOT_HUB*
>devcon rescan


Wer sich alle Geräte anschauen möchte die jemals am Rechner über USB angeschlossen waren:

>devcon findall @USB\*

Eine schöne Übersicht über all diese Geräte gibt auch das Tool USBDeview. Eine Auflösung der VendorID und ProductID von USB-Geräten ist z.B. über die USB-ID-Liste von Stephen J. Gowdy möglich.

Wer sich mit der Programmierung rund um USB beschäftigen möchte findet z.B. hier Einstiegsmöglichkeiten / Bibliotheken:

Lösung 2: Hotplug.dll-Fehler beheben

Dieser Fehler wird aller Wahrscheinlichkeit nach durch "Standardvolumes" mit falsch hinterlegtem Treiber verursacht. Um dies zu beheben folgendermaßen vorgehen:

  • Im Gerätemanager aus dem Menü "Ansicht" wählen und auf "Ausgeblendete Geräte anzeigen" klicken.

  • Jetzt auf das "+" bei "Speichervolumes" klicken um die Baumansicht zu öffnen.

  • Ziel sind nun alle Geräte namens "Standartvolume" (auch falls hinter Standardvolume noch irgendwelche zusätzliche Zeichen stehen).

  • Die Standardvolumes durchgehen und über das Kontextmenü (rechte Maustaste) die Treiber aktualisieren.

  • Bei einigen (nicht allen) wird der Treiber aktualisiert werden.


Das hat bei mir gereicht um das Problem zu behben.

Sollte das nicht ausreichen um das Problem zu beheben, kann man zusätzlich versuchen die USB-Controller neu zu installieren:

  • Alle USB-Controller-Treiber im Gerätemanager deinstallieren, d.h. alle Geräte unterhalb von "USB-Controller" im Gerätemanagerbaum.

  • Neu Booten. Nach dem Neustart werden die Treiber der USB-Controller automatisch neu installiert.


An dieser Stelle herzlichen Dank an Johannes, der diesen Fix in seinem Blog beschreibt und damit nicht nur mir, sondern auch vielen anderen bereits damit geholfen hat.

Ansonsten empfiehlt sich bei kleineren USB-Problemen durchaus mal ein schneller Blick in die diversen USB-FAQs der Consumer-Seiten, wie z.B. diesen hier.

Montag, 1. Juni 2009

XVID-Windows-Compilierung - Teil 2: DirectShow-Treiber compilieren

Im vorherigen Post haben wir die XVID-Core-Bibliothek und den VFW-Treiber compiliert. Dieser Beitrag schließt die XVID-Compilierung unter Windows mit Visual Studio mit der Compilierung des DirectShow-Treibers ab.

DirectShow-Basisklassen compilieren

Um den DirectShow-Treiber compilieren zu können, benötigt man die DirectShow-Basisklassen. Diese waren vor einigen Jahren noch als Beispiele im DirectX SDK enthalten, sind dann aber in das Plattform SDK verlagert worden und schliesslich in das Windows SDK. Da das Windows SDK ein ziemlicher Brocken ist, greifen wir auf das DirectX SDK vom Sommer 2004 zurück:

http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=fd044a42-9912-42a3-9a9e-d857199f888e


Nach dem Aufruf der heruntergeladenen EXE wird das SDK zunächst in ein beliebiges Verzeichnis entpackt. Dies sei im Folgenden als %SDK% bezeichnet. Anschließend wird ein Installationsprogramm gestartet, welches abgebrochen werden kann. Wir benötigen nur die Dateien und die haben wir bereits nach dem Entpacken.

Nun öffnen wir das Projekt zum Compilieren der Basisklassen von DirektShow:
%SDK%\Samples\C++\DirectShow\BaseClasses\baseclasses.sln

Wir stellen wieder von "Debug" auf "Release" um.

Nun ergänzen wir die Pfade zu den Includes und Bibliotheken des DirectX-SDKs:
- Tools > Options... > Projects and Solutions > VC++ Directories
- Include Path ergänzen: %SDK%\Include
- Library Path ergänzen: %SDK%\Lib

Nun starten wir den Build. Beim Compilieren werden zunächst einige Fehler auftreten, die durch eine mangelnde Typisierung von Variablen verursacht werden. Hier genügen 4 kleine Fixes bei den Variablendeklarationen um den Build fehlerfrei zu bekommen. (Diese werden u.a. auch auf folgender Seite beschrieben).

In den Basisklassen werden folgende Änderungen vorgenommen:

ctlutil.h (278):
(LONG) operator=(LONG);

wxdebug.cpp (564):
static DWORD g_dwLastRefresh = 0;

winutil.cpp (2092):
UINT Count;
for (Count = 0;Count <>

outputq.cpp (635):
long iDone = 0;
for (iDone = 0;


Nun läuft der Build durch. Das Ergebnis der Mühen ist die Bibliothek der Basisklassen "%SDK%\Samples\C++\DirectShow\BaseClasses\Release\STRMBASE.lib" gegen den der XVID DirectShow-Filter gelinkt werden kann.

XVID-DirectShow-Treiber compilieren

Wir schließen den Workspace und öffnen das Projekt "%XVID%\dshow\dshow.dsp".

Nun ergänzen wir die Pfade zu der soben erstellten Bibliothek der DirectShow-Basisklassen.
- Tools > Options... > Projects and Solutions > VC++ Directories
- Include Path ergänzen: %SDK%\Samples\C++\DirectShow\BaseClasses
- Library Path ergänzen: %SDK%\Samples\C++\DirectShow\BaseClasses\Release

Nun den Build des Projekts "dshow" anstoßen. Er sollte problemlos durchlaufen.

XVID-DirectShow-Treiber installieren

Nach der Compilierung liegt der DirectShow-Filter im bin-Verzeichnis des dshow-Projekts:

%XVID%\dshow\bin\xvid.ax

Zum Installieren des Filters, die Datei in das Unterverzeichnis "systems32" von Windows kopieren und registrieren.

Registrieren des DirectShow-Filters am System:

regsvr32 \system32\xvid.ax

Will man den Filter wieder entfernen, dann mit folgender Kommandozeile deregistrieren und anschließend löschen:

regsvr32 /u \system32\xvid.ax

XVID-DirectShow-Treiber testen

Die Funktion des DirectShow-Filters kann man mit GraphEdit aus den SDK-Utilities überprüfen, indem man einen Verarbeitungsgraph für eine XVID-Datei aufbaut, der explizit den XVID-DirectShow-Filter beinhaltet. Zu empfehlen ist auch GraphStudio, eine Open-Source-Software, die GraphEdit erweitert:

http://blog.monogram.sk/janos/tools/monogram-graphstudio/

Ein geeigneter Graph zum Testen wäre:

[ File Source (async.) ] -> [ AVI Splitter ] -> [ XVID MPEG-4 Video Decoder ] -> [ Overlay Mixer2 ] -> [ Video Renderer ]

Mit Hilfe von GSpot (http://www.headbands.com/gspot) läßt sich zudem überprüfen, welche Graphen für Video-Dateien vom System tatsächlich verwendet werden um diese abzuspielen.

Weitere Informationen zu DirectShow findet man z.B. hier:
- Programmierung: http://tmhare.mvps.org/help.htm
- Generell: http://en.wikipedia.org/wiki/DirectShow