Hallo! Dieser Artikel ist eine Fortsetzung
meines FFmpeg-Artikels, der mit Visual Studio beginnt. Hier kommen wir zur Hardware-Decodierung des FULL HD RTSP-Streams. Ich werde im Voraus sagen, dass sogar der Intel ATOM Z8350 diese Aufgabe problemlos bewältigen kann.
Aufgabe: Hardware-Decodierung und Aufzeichnung von bis zu 4 Frames im RAM für die anschließende Parallelverarbeitung (vier Prozessorkerne) von einer RTSP h.264 IP-Kamera. Ich zeige die verarbeiteten Frames mit den WinAPI-Funktionen an. Als Ergebnis erhalten wir ein Hochgeschwindigkeitssystem für die Computerverarbeitung des RTSP-Streams im Parallelmodus. Als Nächstes können Sie die
Computer-Vision- Algorithmen für die Verarbeitung von
Echtzeit- Frames verbinden.
Eintrag
Warum brauche ich Hardware-Dekodierung? Sie möchten Echtzeitvideos mit einem schwachen und billigen Prozessor dekodieren oder den Prozessor so weit wie möglich entladen, dann ist es Zeit, sich mit der Hardware-Dekodierung vertraut zu machen.
DirectX Video Acceleration (DXVA) ist eine API zur Verwendung der Hardwarebeschleunigung zur Beschleunigung der Videoverarbeitung mit GPUs. Mit DXVA 2.0 können Sie mehr Vorgänge auf die GPU umleiten, einschließlich Videoerfassungs- und Videoverarbeitungsvorgänge.
Nachdem ich den vorherigen Artikel geschrieben hatte, wurden mir einige Fragen gestellt: "Warum wird FFmpeg verwendet?" Ich werde mit den Problemen beginnen. Die Hauptschwierigkeit der Hardware-Decodierung besteht darin, den decodierten Rahmen in den RAM zu schreiben. Für Full HD sind dies 1920 x 1080 x 3 = 6.220.800 Byte. Selbst unter Berücksichtigung der Tatsache, dass der Frame im NV12-Format gespeichert ist, sind dies auch viele 1920 x 1080 x 1,5 = 3 110 400 Bytes. Das Überschreiben von 75 MB pro Sekunde ist eine ernsthafte Aufgabe für jeden Prozessor. Um dieses Problem zu lösen, hat Intel SSE 4-Befehle hinzugefügt, mit denen Sie Daten ohne Prozessor neu schreiben können. Leider haben dies nicht alle Bibliotheken implementiert. Ich habe folgende Bibliotheken getestet:
- Ffmpeg
- VLC
- Opencv
VLC - funktioniert mit IP-Kameras durch Hardware-Decodierung (sehr geringe Prozessorlast). Ein primitiver RTSP-Stream-Player kann in nur 10 Codezeilen erstellt werden, aber das Empfangen decodierter Frames im RAM benötigt zu viel Prozessorzeit.
OpenCV - RTSP verwendet FFmpeg, um mit dem Stream zu arbeiten, daher wurde beschlossen, ohne Zwischenhändler zu arbeiten, d. H. Verwenden Sie die FFmpeg-Bibliothek. Darüber hinaus wird FFmpeg, das standardmäßig installiert ist, in OpenCV ohne Hardware-Dekodierung erstellt.
FFmpeg - zeigte gute, meiner Meinung nach Ergebnisse, es funktioniert stabil. Der einzige Nachteil ist, dass die Arbeit mit WEB-Kameras für Version X86 (X64 scheint Ihnen das Arbeiten zu ermöglichen) unter Windows nicht implementiert ist.
Hardware-Videodecodierung ist einfach
Tatsächlich ist die Hardware-Dekodierung mit der FFmpeg-Bibliothek nicht komplizierter als mit Software. Die Projekteinstellungen sind die gleichen wie für die Software-Implementierung, das Blockschaltbild blieb unverändert.
Sie können eine Liste der von FFmpeg unterstützten Hardware-Dekodierungsmethoden anzeigen.
fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
Als erstes müssen wir FFmpeg mitteilen, mit welchem Hardware-Decoder Sie das Video decodieren möchten. In meinem Fall lässt Windows 10 + Intel Atom Z8350 nur DXVA2:
type = av_hwdevice_find_type_by_name("dxva2");
Sie können CUDA, D3D11VA, QSV oder VAAPI (nur Linux) als Hardware-Decoder auswählen. Dementsprechend sollten Sie über diese Hardwarelösung verfügen und FFmpeg sollte mit seiner Unterstützung erstellt werden.
Öffnen Sie den Videostream:
avformat_open_input(&input_ctx, filename, NULL, NULL;
Wir erhalten Informationen über den Videostream:
av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
Speicher zuweisen:
frame = av_frame_alloc();
Diese Funktion überschreibt die decodierte Datei im RAM:
av_hwframe_transfer_data(sw_frame, frame, 0);
Ein bisschen über das NV12-Format
Wir haben also einen Frame in der sw_frame-Struktur. Der empfangene Frame wird im NV12-Format gespeichert. Dieses Format wurde von Microsoft erfunden. Sie können Pixelinformationen in 12 Bit speichern. Wobei 8 Bit die Intensität ist und 4 Bit die Farbe beschreiben (oder besser gesagt, die Farbe wird sofort für 4 benachbarte 2 × 2 Pixel beschrieben). Darüber hinaus wird sw_frame.data [0] - die Intensität und in sw_frame.data [1] - die Farbe gespeichert. Um von NV-12 nach RGB zu konvertieren, können Sie die folgende Funktion verwenden:
C ++ - Übersetzung von NV12 nach RGB void SaveFrame(uint8_t * f1, uint8_t * f2, int iFrame) { FILE *pFile; char szFilename[32]; int x, i, j;
Obwohl Sie mit NV12 arbeiten, können Sie die Implementierung von Verfahren wie Unschärfe, Retinex und das Abrufen von Bildern in Graustufen beschleunigen (indem Sie einfach die Farbe verwerfen). Bei meinen Aufgaben übersetze ich das NV12-Format nicht in RGB, da dies zusätzliche Zeit in Anspruch nimmt.
Und so haben wir gelernt, wie man Videodateien in Hardware dekodiert und in einem Fenster anzeigt. Wir haben uns im NV12-Format kennengelernt und erfahren, wie man es in vertrautes RGB konvertiert.
DLL-Hardware-Dekodierung
FFmpeg gibt Frames nach 40 ms aus (bei 25 Frames pro Sekunde). Die Verarbeitung eines Full HD-Frames dauert in der Regel erheblich länger. Dies erfordert Multithreading, um die Last aller 4 Prozessorkerne zu maximieren. In der Praxis starte ich 6 Threads einmal und entferne sie nicht mehr, was die Arbeit erheblich vereinfacht und die Zuverlässigkeit des Programms erhöht. Das Betriebsschema ist in Fig. 2 gezeigt. 1
Abb. 1 Schema zum Erstellen eines Multithread-Programms mit FFmpegIch habe meinen Decoder als
* .dll (FFmpegD.DLL) geschrieben, um ihn in meine Projekte aufzunehmen. Auf diese Weise können Sie den Code des Projekts reduzieren, wodurch das Verständnis des Codes verbessert und in eine beliebige Programmiersprache aufgenommen wird, bis hin zu Assembler (verifiziert :)). Damit schreiben wir unseren RTSP-Stream-Player von der IP-Kamera.
Um mit einer DLL zu arbeiten, müssen Sie einen Zeiger auf ein int [13] -Array, einen HANDLE eines neuen Frame-Ankunftsereignisses, einen HANDLE zum Starten der Verarbeitung eines neuen Datenpakets von der Kamera und ein Array-Zeichen der Kamera übergeben.
Die Array-Struktur ist in Tabelle 1 angegeben.

Vor dem Anruf müssen Sie die Rahmennummern 1-4 zurücksetzen.
Die DLL führt alle erforderlichen Schritte aus, um FFmpeg zu initialisieren, und zeichnet Zeiger und Rahmennummern auf. Nachdem es das Ereignis "New Frame Arrival" gesetzt hat. Es ist nur erforderlich, die eingehenden Frames zu verarbeiten und 0 anstelle der Frame-Nummer zu schreiben (dies bedeutet, dass der Frame verarbeitet wurde und nicht mehr verwendet wird).
Unten finden Sie einen Beispiel-Player mit Quellcode. Das Beispiel ist ShowDib3 Charles Petzold.
→
Mit dem Projekt archivieren→
FFmpegD.dll-ArchivERGEBNISSE: FFmpeg-Hardware-Bewegungsmelder dekodiert sogar auf Intel Atom Z8350 h264 Full HD in Echtzeit mit bis zu 20% Prozessorlast mit angeschlossenem Bewegungsmelder.
Beispiel für den Betrieb des Bewegungsmelders unter Intel ATOM Z8350. Die ersten 30 Sekunden sind die Berechnung des Hintergrunds. Danach arbeitet der Bewegungsmelder nach der Methode des Subtrahierens des Hintergrunds.PS Sie können auch Videodateien dekodieren (komprimiert h.264) !!!
Referenzen:
- Verschiedene nützliche Informationen zu FFmpeg
- Informationen zur Verwendung der verschiedenen von FFmpeg bereitgestellten Bibliotheken
- Informationen zu Formaten und zur Konvertierung in RGB