Wie zum codieren eines video aus mehreren Bildern generiert, die in einem C++ - Programm ohne separaten Rahmen, Bilder auf die Festplatte?

Ich Schreibe ein C++ - code, in dem eine Sequenz von N verschiedenen frames generiert wird, nach der Durchführung einige Operationen implementiert darin. Nach jedem frame abgeschlossen ist, Schreibe ich es auf die Festplatte als IMG_%d....png, und schließlich ich encodieren Sie ein video durch ffmpeg mit dem x264 codec.

Den pseudocode zusammengefasst der wichtigste Teil des Programms ist das folgende:

std::vector<int> B(width*height*3);
for (i=0; i<N; i++)
{
  //void generateframe(std::vector<int> &, int)
  generateframe(B, i); //Returns different images for different i values.
  sprintf(s, "IMG_%d.png", i+1);
  WriteToDisk(B, s); //void WriteToDisk(std::vector<int>, char[])
}

Das problem dieser Implementierung ist, dass die Nummer des gewünschten frames, N, ist in der Regel hoch (N~100000) sowie die Auflösung der Bilder (1920 x 1080), was in einer überlastung der Festplatte, Herstellung von schreib-Zyklen von Dutzenden von GB nach jeder Ausführung.

Um dies zu vermeiden, habe ich versucht zu finden-Dokumentation über die Analyse direkt jedes Bild gespeichert, im Vektor B an einen encoder wie x264 (ohne zu schreiben, die intermediate-image-Dateien auf der Festplatte). Obgleich einige interessante Themen gefunden wurden, keiner von Ihnen gelöst konkret, was ich genau will, wie viele von Ihnen betreffen die Ausführung der encoder mit den bestehenden Bilder-Dateien auf der Festplatte, während andere Lösungen für andere Programmiersprachen wie z.B. Python (hier finden Sie eine voll befriedigende Lösung für diese Plattform).

Den pseudocode von dem, was ich möchte, zu erhalten, ist etwas ähnlich wie diese:

std::vector<int> B(width*height*3);
video_file=open_video("Generated_Video.mp4", ...[encoder options]...);
for (i=0; i<N; i++)
{
  generateframe(B, i+1);
  add_frame(video_file, B);
}
video_file.close();

Je nach dem was ich gelesen habe, auf Verwandte Themen, die x264-C++ - API in der Lage sein könnte, dies zu tun, aber, wie oben gesagt, ich habe nicht gefunden, eine befriedigende Antwort für meine spezielle Frage. Ich habe versucht, zu lernen und direkt mit dem ffmpeg-Quellcode, aber sowohl seine geringe Benutzerfreundlichkeit und Zusammenstellung der Themen hat mich gezwungen Sie zu verwerfen, diese Möglichkeit als eine bloße nicht-Profi-Programmierer bin ich (ich nehme es als nur ein hobby und leider kann ich nicht Abfälle, die viele Zeit, etwas zu lernen so anspruchsvoll).

Andere mögliche Lösung, die mir in den Sinn gekommen ist einen Weg zu finden, rufen Sie die ffmpeg-binary Datei in den C++ - code, und es irgendwie schaffen, zur übertragung der Bild Daten jeder iteration (gespeichert in B) auf den encoder, so dass der Zusatz von jedem frame (das heißt, nicht "schließen" die video-Datei zu schreiben), bis Sie den letzten frame, so dass frames können Hinzugefügt werden, bis das erreichen der N-TEN ein, wo Sie die video-Datei wird "geschlossen". In anderen Worten, rufen Sie ffmpeg.exe durch das C++ - Programm zu schreiben, das erste Bild zu einem video, aber das machen die encoder "warten" für mehr frames. Dann wieder anrufen, ffmpeg, um das zweite Bild und das encoder "warten" wieder für mehr frames und so weiter, bis Sie den letzten frame, wo das video fertig sein wird. Allerdings, ich weiß nicht, wie es weitergehen soll oder ob es eigentlich möglich ist.

Edit 1:

Wie vorgeschlagen-in die Antworten, ich habe bereits dokumentiert über named pipes und versucht, Sie in meinem code. Zuerst von allen, es sollte angemerkt werden, dass ich arbeite mit Cygwin, so dass meine named pipes werden erzeugt, wie Sie entstehen würden, unter Linux. Die geänderten pseudocode I verwendet werden (einschließlich der entsprechenden system-Bibliotheken) ist die folgende:

FILE *fd;
mkfifo("myfifo", 0666);

for (i=0; i<N; i++)
{
  fd=fopen("myfifo", "wb");
  generateframe(B, i+1);
  WriteToPipe(B, fd); //void WriteToPipe(std::vector<int>, FILE *&fd)
  fflush(fd);
  fd=fclose("myfifo");
}
unlink("myfifo");

WriteToPipe ist eine leichte Modifikation der früheren WriteToFile-Funktion, wo ich sicher, dass der schreib-Puffer zum senden der Bilddaten ist klein genug, um das Rohr Pufferung Einschränkungen.

Ich dann kompilieren und schreiben Sie den folgenden Befehl in die Cygwin-terminal:

./myprogram | ffmpeg -i pipe:myfifo -c:v libx264 -preset slow -crf 20 Video.mp4

Jedoch, bleibt Sie fest an der Schleife, wenn i=0 an die "fopen" - Zeile (also die erste fopen-Aufruf). Hätte ich nicht angerufen ffmpeg wäre es natürlich, wenn die server (mein Programm) auf Sie wartet ein client-Programm eine Verbindung zu der "anderen Seite" der Leitung, aber es ist nicht der Fall. Es sieht aus wie Sie können nicht angeschlossen werden, durch die Leitung irgendwie, aber ich habe nicht in der Lage zu finden, eine weitere Dokumentation, um zu überwinden dieses Problem. Jede Anregung?

  • Haben Sie versucht, verwendet named pipe? Für FFMPEG kann es akzeptieren, named pipes als input-i pipe:von pipe_name Beispiel auf der msdn-Website.microsoft
  • Danke für die Anregung. Ich lernte über named pipes und versuchte zu gehen auf diesem Weg. Die neuen Themen, die erschien nach dem Versuch diese Methode ausgesetzt sind, in meinem neuen zu Bearbeiten.
InformationsquelleAutor ksb496 | 2015-12-29
Schreibe einen Kommentar