Videos per SinkWriter der MediaFoundation schreiben

Aktuell arbeite ich in Vorbereitung für ein kommendes (Hobby-)Projekt wieder verstärkt mit der Media Foundation von MS. Erster Schritt war nun, per SinkWriter Videos direkt aus der 3D-Ansicht von Seeing# heraus schreiben zu können. Der zweite Schritt, Videos auch wieder auszulesen, ist noch in Arbeit [1]. Der SinkWriter ist eine Klasse der Media Foundation, welche dazu verwendet werden kann, von der Anwendung generierte Bilder direkt in eine Videodatei zu schreiben. Soll ein Video also etwa 30 Frames pro Sekunde haben, so kann die Anwendung eben diese 30 Frames pro Sekunde erzeugen und an den SinkWriter übergeben. Mein aktueller Stand ist damit der, dass ich direkt aus dem 3D-Rendering heraus nebenbei ein Video schreiben lassen kann.

Im Wesentlichen habe ich mich bei der Umsetzung an diesem Tutorial von Microsoft orientiert [2]. Herausgekommen sind die Klassen SeeingSharpVideoWriter und die entsprechenden Ableitungen davon, wie z. B. der Mp4VideoWriter [3]. Probleme hatte ich bei der Umsetzung eher wenige, das Größte ist aktuell noch die Integration für WinRT, da scheinbar das Kopieren von Speicherblöcken dort etwas anders programmiert werden muss. Weiterhin war es nicht ganz einfach, eine funktionierende Kombination von Parametern für den SinkWriter zu finden. Stellt man etwa Bitrate, Auflösung und Framerate so ein, dass sie für das verwendete Format nicht zusammenpassen, so bekommt man entweder beim Anlegen des SinkWriters einen Fehler oder dann erst im Anschluss beim Schreiben der Frames.

Die Konfiguration des SinkWriters bez. des Input-Formats (=Format der Daten aus der eigenen Anwendung. Hier: RGB32) befindet sich in der Klasse MediaFoundationVideoWriter:

Die Konfiguration des Output-Formats (=Format des zu schreibenden Videos, hier MP4) befindet sich dann in der abgeleiteten Klasse Mp4VideoWriter. Diese verschiedenen Klassen sind deswegen entstanden, da ich pro Dateiformat evtl. auch weitere Zusatzeinstellungen etwas anders zu treffen habe. Hier der Code für das MP4 Format:

Wenn man genau hinschaut, sieht man, dass die Konfiguration des Output-Formats (zweiter Codeblock) direkt vor der Konfiguration des Input-Formats (erster Codeblock) aufgerufen wird. Wenn alles konfiguriert ist, ist nur noch der Aufruf von m_sinkWriter.BeginWriting() nötig.

Das Schreiben der Frames selbst ist unabhängig vom Output-Format und wie folgt kodiert.

Besonders anzumerken an diesem Code-Block ist die Abfrage if(this.FlipY) in der Mitte. Diese ist schlicht dadurch entstanden, weil WMV-Videos korrekt und MP4-Dateien spiegelverkehrt geschrieben wurden. Aus diesem Grund habe ich kurzerhand diese Abfrage eingebaut… ich möchte aber nicht ausschließen, dass es da auch irgendwo eine elegantere Lösung dafür gibt. Aber so reicht es mir erst einmal.

Die Integration in das 3D-Rendering habe ich dann so gelöst, dass man diesen VideoWriter direkt der RenderLoop Klasse übergeben kann. Folgende Testmethode zeigt das recht anschaulich.

 

Verweise
[1] http://www.mycsharp.de/wbb2/thread.php?threadid=114414
[2] https://msdn.microsoft.com/de-de/library/windows/desktop/ff819477(v=vs.85).aspx 
[3] https://github.com/RolandKoenig/SeeingSharp/tree/master/SeeingSharp.Multimedia/DrawingVideo

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.