Dieser Artikel wurde maschinell übersetzt.

Videocodierung

Speichern und Wiederverwenden von Einstellungen für die Videocodierung

ADI Shavit

Von entfernten Überwachungssysteme für die embedded-Roboter Plattformen Anwendungen, die automatisch oder autonom Video aufzeichnen bekommen immer mehr allgegenwärtig wie der Preis von Geräten wie Kameras und Speicherplatz fällt und Rechenleistung erhöht.Ist jedoch nicht konfigurieren solcher Systeme Remote oft eine Option, während Bereitstellung und Installation einfach und automatisch werden müssen.

Ich brauchte vor kurzem eine Möglichkeit, video-Aufnahme-Einstellungen auf einem remoten System vorkonfigurieren, so dass es würde automatisch laden und die gleichen Einstellungen beim Systemstart verwenden.Eine Suche im Internet brachte viele ähnliche Fragen in mehreren Foren mehr als ein Jahrzehnt zurück, aber nur teilweise und unbefriedigende Lösungen.

In diesem Artikel werde ich vorstellen eine einfache, aber allgemeine Möglichkeit Videoverarbeitung Anwendungen speichern Video mit konsistenten Komprimierungseinstellungen, so vermeiden müssend manuell die Codeceinstellungen jedes Mal angeben, wenn die Anwendung oder die Maschine gestartet wird.Ich werde zeigen, wie auf die internen Einstellung Puffer eines Codecs zugreifen, so dass sie leicht gespeichert, geladen und wiederverwertet werden können.Dies funktioniert für alle video-Codec auf dem Computer installiert, ohne den Gebrauch von Codec-spezifische APIs.

Video 101

Video Rohdaten ist riesig.Betrachten Sie eine bescheidene VGA-Kamera gehen zusammen mit einer bescheidenen Rate von 15 Frames pro Sekunde.Jeder Frame 3-Kanal 640 × 480 Pixel beträgt 900 KB und generiert eine Datenrate von 13MBps (das über 105Mbps)!Etwas möglicherweise weniger bescheiden Videogeräte, des Typs, die Sie auf einem Handy finden high-Definition (HD) Auflösungen, höhere Bildraten oder mehr als 8 Bit Farbtiefe.Ein 90-minütige HD Film verbraucht ca. 1 TB in unformatierter Form.Glücklicherweise, Videodaten enthält eine Menge von Redundanz und -Videokomprimierungs-Algorithmen können sehr effizient video-Dateien speichern.Der Typ der Komprimierungsalgorithmus ausgewählt hängt die jeweilige Anwendung, seiner Anforderungen und deren Einschränkungen.Mehrere Faktoren variiert stark zwischen den Komprimierungsmethoden, einschließlich Echtzeit Preise, Überlegungen zur Leistung und den Kompromiss zwischen Bildqualität und die resultierende Dateigröße.

Unter Windows werden video-Kompression von Codecs (COmpressor-DECompressor) angeboten.Ich konzentriere mich auf das Video für Windows (VfW) API zum Speichern von komprimierten AVI video-Dateien.Audio Video Interleave (AVI) ist ein multimedia-Container-Dateiformat, das kann mehrere Streams von audio und video enthalten und ermöglichen synchrone Audio mit Video-Wiedergabe von ausgewählten Streams.Ich werde zeigen, wie Kompression Codec-Einstellungen können manuell ausgewählt und werden in einer permanenten Weise gespeichert, so dass sie später wieder geladen und automatisch von der Anwendung auf einem Computer, auf dem der gleiche Codec installiert ist, wiederverwertet werden können.

Speichern von Video mit VfW

Obwohl es im Jahr 1992 eingeführt wurde, ist VfW eine dauerhafte API, heute immer noch weit verbreitet.Neue Codecs und Codec-Implementierungen, wie z. B. die Ffmpeg-Suite (ffmpeg.mplayerhq.hu), weiterhin eine VfW-Schnittstelle auf dem Microsoft Windows bereitstellen.

Der typische Ablauf für eine video-Aufnahme-Programm dauert in der Regel die Form die folgenden Schritte aus:

  1. Erstellen Sie eine neue AVI-Datei, erstellen Sie einen neuen unkomprimierten video Stream innerhalb es, wählen Sie die erforderliche Komprimierungseinstellungen erstellen Sie und einen neuen komprimierten Stream von der unkomprimierten.
  2. Fügen Sie neue Rahmen wie gewünscht.
  3. Wenn fertig, Freigeben von Ressourcen in umgekehrter Reihenfolge.

Mit VfW sieht es aus wie folgt:

  1. Öffnen Sie und Vorbereiten der video AVI-Datei mit dem folgenden:
    1. AVIFileInit: Initialisiert die AVIFile-Bibliothek.Muss aufgerufen werden, bevor Sie andere AVIFile-Funktionen verwenden.
    2. AVIFileOpen: Öffnet eine AVI-Datei.
    3. AVIFileCreateStream: Erstellt einen neuen video-Stream in die AVI-Datei.Eine AVI-Datei kann mehrere Streams (von verschiedenen Typen) enthalten.
    4. AVISaveOptions: Stellt ein Standarddialogfeld Komprimierungsoptionen (finden Sie unter Abbildung 1).Wenn der Benutzer beendet die Komprimierungsoptionen auswählen, werden die Optionen in einer AVICOMPRESSOPTIONS-Struktur zurückgegeben.
    5. AVIMakeCompressedStream: Erstellt einen komprimierten Stream von unkomprimierten Streams zurückgegeben von AVIFileCreateStream und der Komprimierungsfilter von AVISaveOptions zurückgegeben.
    6. AVIStreamSetFormat: Legt das Bildformat für den Stream fest.
  2. Fügen Sie Bilder in den video Stream:
    1. AVIStreamWrite: Fügen Sie einen einzelnen Frame in den video Stream.Rufen Sie immer wieder mit zusätzliche Frames wie gewünscht.
  3. Bereinigen und schließen:
    1. AVIStreamRelease: Schließt den komprimierten Stream (aus AVIMakeCompressedStream).
    2. AVIStreamRelease: Schließt den unkomprimierten Stream (aus AVIFileCreateStream).
    3. AVISaveOptionsFree: Gibt die von der AVISaveOptions-Funktion (Dies wird oft vergessen, was zu Speicherverlusten,) reservierten Ressourcen frei.
    4. AVIFileRelease: Schließt die AVI-Datei (von AVIFileOpen).
    5. AVIFileExit: Beenden der AVIFile-Bibliothek.

The Video Compression Dialog Box Opened by the AVISaveOptions Function
Abbildung 1 das Videokomprimierung Dialogfeld geöffnet von der AVISaveOptions-Funktion

Erklärt im Detail VfW für Aufnahmevideo veranschaulicht ist über den Rahmen dieses Artikels hinaus.Hier finden Sie viele Beispiele und Tutorien online.Ich werde mich hier nur auf Schritt 1.4 konzentrieren: die Kompressor-Auswahl und Codec-Einstellungen Teil.Der Quellcode zu diesem Artikel basiert auf die C++-Implementierung aus dem open-Source-Projekt OpenCV (opencv.willowgarage.com) und kann heruntergeladen werden von code.msdn.microsoft.com/mag201112Video.Allerdings sind die Techniken ich hier zeige für — leicht integriert — video Aufnahme-Anwendung, die die VfW API verwendet und ist nicht speziell auf eine bestimmte Implementierung oder Programmiersprache.

Gemeinsame Lösungen

Wie zuvor gezeigt, ist der gemeinsame Weg an die Komprimierungseinstellungen durch Aufrufen der Funktion AVISaveOptions, um das Dialogfeld Optionen anzuzeigen.Der Benutzer kann dann den gewünschten Codec manuell auswählen.Der gewählte Codec kann oder möglicherweise keinen Codec "Configure…" Option, die erlaubt es, Einstellungen für Codec-spezifischen Anpassungen.Natürlich ist in diesem Dialogfeld auf Systemen ohne eine aktive Nutzer oder sogar eine GUI, eine Option nicht.

Die gemeinsame Alternative zur manuellen Auswahl ist programmgesteuert auswählen einen bestimmten Codec mit dem Codec Fourcc (vier Zeichen bestehenden Code; Siehe fourcc.org) Bezeichner, und einige zusätzlichen, allgemeinen Einstellungen auf alle Codecs, wie Datenrate, Qualität und Keyframe-Rate gemeinsame festgelegt.Der größte Nachteil dieser Methode ist, dass es keine Codec-spezifischen Einstellungen festlegen.Darüber hinaus macht es den Codec verwenden, was auch immer die aktuellen internen Einstellungen sind.Diese können Standardwerte oder, schlimmer noch, Einstellungen willkürlich festgelegt von anderen Programmen.Darüber hinaus unterstützen nicht alle Fourcc-Codecs, die auf einem System die VfW API, die das komprimierte Stream erstellen Fehler verursachen kann.

Einige Codecs bieten spezielle Konfiguration, die erlauben, ihre internen Einstellungen extern zu ändern.Diese Tools können in Form einer GUI oder ein Befehlszeilenprogramm erfolgen.Allerdings bieten die meisten Codecs nicht solche Werkzeuge, und da jedes Tool für einen bestimmten Codec angepasst ist, müssten Sie seine bestimmte Syntax und Verwendung zu nutzen lernen.

Was ich wollte, war die Flexibilität von der manuellen Auswahlmodus mit automatisierten Auswahl von Codec und alle seine internen Einstellungen.

Das Beste aus beiden Welten

Bei der ersten Möglichkeit gibt der Aufruf AVISaveOptions ein AVICOMPRESSOPTIONS Objekt vollständig ausgefüllt.Der zweite Ansatz ist, im Wesentlichen einige Werte im AVICOMPRESSOPTIONS-Objekt von innerhalb des Codes Füllung ohne Verwendung von AVISaveOptions.

In der Tat ist es möglich, den volle, interne Codec Zustand nach einem Aufruf von AVISaveOptions speichern, so dass dieser Zustand später wiederhergestellt werden kann, ohne zu müssen, AVISaveOptions erneut aufzurufen.Das Geheimnis des internen Video-Kompressor-spezifische Daten und Format ist im undurchsichtigen Zeiger LpParms und LpFormat des AVICOMPRESSOPTIONS.Rückgabe von AVISaveOptions, enthalten diese zwei Zeiger alles, was die AVIMakeCompressedStream Funktion muss eine komprimierte Streams (Dies sind vermutlich die Ressourcen von AVISaveOptionsFree veröffentlicht).

Das Wesen der meine Technik spart dann opaken Daten von LpParms und LpFormat damit es wiederverwendet werden kann.Glücklicherweise ist dies einfach zu tun.Die AVICOMPRESSOPTIONS-Struktur enthält zwei hilfreiche ganzzahligen Member, CbParms und CbFormat, die die Größe der undurchsichtige binäre Puffer verwies auf LpParms und LpFormat, respektieren staatliche­drucksvoll.Diese Größen ändern sich je nach den bestimmten Codec ausgewählt.

Zusammenfassend gibt es drei binären "Blobs", die nach einem Aufruf von AVISaveOptions gespeichert werden müssen.Dies sind das AVICOMPRESSOPTIONS-Objekt selbst und die zwei binären Puffer verwies auf durch seine LpParms und LpFormat Mitglieder.Die Länge in Bytes der diese Puffer ist, bzw. CbParms und CbFormat zugesprochen.Wiederherstellen der Codeceinstellungen ist nur Umkehr des Prozesses: das AVICOMPRESSOPTIONS-Objekt aus der Datei und legen Sie ihre LpParms und LpFormat Mitglieder darauf an die jeweiligen binären Puffer lesen aus der Datei lesen.Die wiederhergestellte binäre Puffer werden zugeordnet und von der Anwendung selbst verwaltet.

Es gibt viele Möglichkeiten zum Speichern von binärer Daten.Siehe Abbildung 2, mein Beispielcode speichert die Daten im Binärformat.Alternativ, in Fällen, in denen nicht druckbare Zeichen (z. B. txt- oder XML-Dateien) vermieden werden sollte, ich habe erfolgreich verwendet Base-64-Codierung, um die Puffer zu speichern.

Abbildung 2 Beispiel zum Speichern und Wiederherstellen von Codec-Einstellungen

bool CvVideoWriter_VFW::writeCodecParams( char const* configFileName ) const
{
  using namespace std;   
  try
  { // Open config file
    ofstream cfgFile(configFileName, ios::out | ios::binary);          
    cfgFile.exceptions ( fstream::failbit | fstream::badbit );
    // Write AVICOMPRESSOPTIONS struct data
    cfgFile.write(reinterpret_cast<char const*>(&copts_), sizeof(copts_)); 
    if (copts_.cbParms != 0)// Write codec param buffer
      cfgFile.write(reinterpret_cast<char const*>(copts_.lpParms), copts_.cbParms);
    if (copts_.cbFormat != 0)// Write codec format buffer
      cfgFile.write(reinterpret_cast<char const*>(copts_.lpFormat),
        copts_.cbFormat);
  }
  catch (fstream::failure const&)
  { return false; } // Write failed
  return true;
}
bool CvVideoWriter_VFW::readCodecParams( char const* configFileName )
{ 
  using namespace std;
  try
  { // Open config file
    ifstream cfgFile(configFileName, ios::in | ios::binary);
    cfgFile.exceptions (
      fstream::failbit | fstream::badbit | fstream::eofbit );
    // Read AVICOMPRESSOPTIONS struct data
    cfgFile.read(reinterpret_cast<char*>(&copts_), sizeof(copts_));        
    if (copts_.cbParms != 0)
    { copts_Parms_.resize(copts_.cbParms,0);                // Allocate buffer
      cfgFile.read(&copts_Parms_[0], copts_Parms_.size());  // Read param buffer
      copts_.lpParms = &copts_Parms_[0];                    // Set lpParms to buffer
    }
    else
    { copts_Parms_.clear();
      copts_.lpParms = NULL;
    }
    if (copts_.cbFormat != 0)
    { copts_Format_.resize(copts_.cbFormat,0);              // Allocate buffer
      cfgFile.read(&copts_Format_[0], copts_Format_.size());// Read format buffer
      copts_.lpFormat = &copts_Format_[0];                  // Set lpFormat to buffer
    }
    else
    { copts_Format_.clear();
      copts_.lpFormat = NULL;
    }
  }
  catch (fstream::failure const&)
  { // A read failed, clean up
    ZeroMemory(&copts_,sizeof(AVICOMPRESSOPTIONS));
    copts_Parms_.clear();
    copts_Format_.clear();   
    return false; 
  }
  return true;
}

Beispiel Code Notes

Der Beispielcode Videodaten von einer Videokamera oder Webcam erfasst und speichert sie in eine AVI-Datei. Es verwendet die OpenCV VideoCapture Klasse den Zugriff auf die Kamera und die Videoaufnahme. Speichern das Video erfolgt mit einer Version der Klasse OpenCV CvVideoWriter_VFW, das ich abgeändert, unterstützen die Codeceinstellungen speichern. Ich habe versucht, die Änderungen an den ursprünglichen Code so gering wie möglich zu halten. Im Code wird das zweite Argument der CvVideoWriter_VFW::open ein Std:: String. Wenn diese Zeichenfolge vier Zeichen lange (wie in einem Fourcc ist), es wird angenommen, dass ein Fourcc werden und entsprechend dieser Fourcc Codec gewählt – Konvertieren von der vier 1-Byte-Zeichen in dem Fourcc ganzzahligen Code erfolgt häufig mit dem Makro MmioFOURCC wie in mmioFOURCC('D','I','V','X'); finden Sie unter tinyurl.com/mmioFOURCC für Details. Andernfalls wird die Zeichenfolge als den Namen der Datei ein Codec-Einstellungen übernommen. Wenn die Datei vorhanden ist, werden die Einstellungen aus der Datei gelesen und für die Videokomprimierung verwendet. Wenn es nicht vorhanden ist, dann das Dialogfeld Optionen wird geöffnet und ein Codec und dessen Einstellungen können manuell ausgewählt werden; die gewählten Einstellungen werden dann in die Datei mit den ausgewählten Namen das nächste Mal wieder verwendet werden, die, das die Anwendung ausgeführt wird, gespeichert. Hinweis: Sie müssen eine OpenCV-Installation zum Kompilieren und Ausführen des Beispielcodes.

Einige Vorteile

Die Lösung, die ich vorgestellt hat mehrere Vorteile. Ändern der Komprimierungseinstellungen für eine Anwendung ist nur eine Frage der Änderung eines ihrer Argumente. Es gibt keine Notwendigkeit, es erneut kompilieren oder sogar stoppen die laufende app. Die Methode ist Codec-unabhängigen und funktioniert für alle VfW Codecs. Einige Codecs erlauben sogar für zusätzliche kundenspezifische Bildverarbeitung z. B. Frame Größenänderung und deinterlacing. Alle diese Optionen werden automatisch innerhalb der Codec-Einstellungen-Datei erfasst.

Die Methode funktioniert genauso gut auf älteren Windows-Systemen (ab Windows 2000 und höher) und auch mit älteren Compiler wie z. B. Visual Studio 6.0. Außerdem kann es mit einer Vielzahl von Sprachen verwendet werden, die die VfW-Schnittstelle, z. B. Visual Basic und c# verfügbar. Es kann auf mehreren Computern unabhängig vom aktuellen internen Codec Status jeder Maschine eingesetzt werden.

Die wichtigste Einschränkung ist, dass diese Lösung garantiert funktionieren nur, wenn die genaue gleiche Version des Codecs verwendet wird. Wenn ein Codec auf einem bestimmten Computer fehlt oder eine andere Version der verwendet, um die Einstellungsdatei ist, möglicherweise die Ergebnisse unbestimmt. Natürlich kann NonVfW Codecs verwendet werden, da diese Lösung auf die VfW API basiert.

Mögliche Erweiterungen für diese Arbeit sind ebenso speichern audio Kompressor Einstellungen, die auf video-Kompressor Einstellungen identisch behandelt werden. Auch, da AVISaveOptions nativ AVIs mit mehreren Streams unterstützt, die gleiche Lösung funktioniert auch in diesen Fällen, und die Codeceinstellungen für jede der Streams in einer einzigen Datei geschrieben werden können.

Die anderen gemeinsame und modernere Video- und Verarbeitung-API in Windows ist DirectShow. Es sollte möglich sein, eine ähnliche Lösung für DirectShow sowie implementieren, aber das ist ein Thema für einen zukünftigen Artikel.

ADI Shavit ist ein Computer-Vision-Berater. Er arbeitet auf Bild und Video Verarbeitungssysteme für mehr als 15 Jahren, spezialisiert auf video-Analyse in Echtzeit. Er kann erreicht werden unter adishavit@gmail.com.

Dank der folgenden technischen Experten für die Überprüfung dieses Artikels: Dana Shavit und Matthew Wilson