Echtzeit-Videostreaming in C #

8

Ich entwickle eine Anwendung für Echtzeit-Streaming. Zwei Teile enthalten für das Streaming. Ich verwende eine Capture-Karte, um einige Live-Quellen zu erfassen und muss in Echtzeit streamen. Außerdem müssen Sie eine lokale Videodatei streamen.

Um lokale Videodateien in Echtzeit zu streamen, verwende ich emgu cv, um den Videorahmen als Bitmaps aufzunehmen. Um dies zu erreichen, erstelle ich die Bitmap-Liste und speichere die aufgezeichnete Bitmap mit einem Thread in diese Liste. und ich zeige diese Bilder auch in einer Bildbox. Bitmap-Liste kann 1 Sekunde Video speichern. wenn die Bildrate ist 30 speichert es 30 Videoframes. Nach dem Ausfüllen dieser Liste starte ich einen weiteren Thread, um diesen 1-Sekunden-Chunk zu codieren Video.

Zum Zweck der Verschlüsselung verwende ich ffmpeg wrapper namens nreco. Ich schreibe diese Videorahmen zu ffmpeg und starte die ffmpeg zum Verschlüsseln. Nach dem Beenden dieser Aufgabe kann ich codierte Daten als Byte-Array erhalten.

Dann sende ich diese Daten mit dem UDP-Protokoll über LAN.

Das funktioniert gut. Aber ich kann das flüssige Streaming nicht erreichen. Wenn ich Stream über VLC-Player empfangen habe, gibt es einige Millisekunden Verzögerung zwischen den Paketen und auch dort habe ich festgestellt, dass ein Frame verloren gegangen ist.

%Vor%

Dies ist der Prozess, den ich verwendet habe, um das Live-Streaming zu erreichen. Aber der Strom ist nicht glatt. Ich habe stattdessen versucht, eine Warteschlange zu verwenden der Liste, um die Latenz zu reduzieren, um die Liste zu füllen. Weil ich dachte, dass Latenz beim Kodieren von Thread-Kodierung auftritt und senden Sie 2 Sekunden Video sehr schnell. Aber wenn es diesen Kodierungsprozess der Bitmap-Liste nicht beendet komplett voll. Der Encoding-Thread stoppt also, bis das nächste 2-Sekunden-Video fertig ist.

Wenn mir jemand helfen kann, das herauszufinden, ist es sehr dankbar. Wenn die Art, wie ich das tue, falsch ist, korrigiere mich bitte. Danke!

    
Nuwan 19.07.2014, 10:50
quelle

2 Antworten

1

Es ist schwer, etwas über den Code zu sagen, da Ihre Fragmente keine Details für den gesamten Prozess bereitstellen.

Als Erstes können Sie den Rahmenpuffer (Liste der Bitmaps) überhaupt eliminieren. Erstellen Sie einfach einen Live-Stream-Encoding-Prozess (Erstellen eines neuen Prozesses für alle 2 Sekunden Chunk ist sehr schlechte Idee) und schieben Sie Bitmaps zu VideoConverter mit Write-Methode, wie sie kommen. Da Sie Frames vom Gerät in Echtzeit erhalten, müssen Sie auch keine manuellen Verzögerungen machen (Thread.Sleep ((int) (1000.5 / FrameRate))). Als Ergebnis sollten Sie ein flüssiges Video auf der VLC-Seite bekommen (eine gewisse Latenz - normalerweise etwa 200 - 500 ms - ist aufgrund der Kodierung und der Netzwerkübertragung unvermeidbar).

Wenn Sie Bilder von der Aufnahme des Geräts per "fits and starts" erhalten, können Sie die Option "-re" FFMpeg versuchen.

    
Vitaliy Fedorchenko 21.07.2014 07:59
quelle
0

Ich habe meinen Code jetzt geändert. Als der Bildspeicher voll war, habe ich den Thread gestartet, der den Videoframe codiert hat. Innerhalb dieses Threads kodiere ich Videoframes und ich speichere diese kodierten Daten in einer threadsicheren Warteschlange. Nachdem ich diese Warteschlange einigermaßen gefüllt habe, starte ich den Timer. Der Timer wird jedes 200-Millisekunden-Intervall auslösen und codierte Daten senden.

Das funktioniert sehr gut und ich habe den reibungslosen Stream auf der Empfängerseite bekommen. Ich habe das mit 720 Video getestet. Aber wenn ich versuche, 1080p Video zu streamen, stream es am Anfang sehr gut. Aber nach einiger Zeit wird der Stream Teil für Teil angezeigt. Ich habe festgestellt, dass dies passiert, wenn meine Streaming-Anwendung nicht sehr schnell Daten sendet. So wird der Player-Puffer für kleine Millisekunden leer. Ich denke, das passiert, weil emgu cv keine Frames in Echtzeit aufgenommen hat. Es wurde sehr schnell für Videos mit niedriger Auflösung aufgenommen. Wenn ich 1080p HD-Video aufnehme, wird die Aufnahme langsamer. Sogar beide haben die gleiche Bildrate. Jedes Mal, wenn das Ereignis "Application.Idle + = ProcessFrame;" ausgelöst wird, wird der Frame erfasst.

Ich habe eine Capture-Karte, mit der man Video in Echtzeit aufnehmen kann und wenn ich HDMI-Leitung habe. Ich weiß also nicht, wie man eine Videodatei mit einer Aufnahmekarte aufnimmt. Deshalb habe ich offenen Lebenslauf verwendet. Und ich habe auch den gesamten Thread entfernt, wie du gesagt hast.

    
Nuwan 22.07.2014 16:34
quelle

Tags und Links