2014-06-28 4 views
5

Ich habe ein Raspberry Pi Board mit dedizierten Kamera, die Video nur in h264 aufzeichnet. Ich bin auf der Suche nach der besten Methode zum Streamen und Abspielen von Video in Echtzeit (wie in, weniger als 1 s Verzögerung) in C# Windows Forms App. Die zusätzliche Anforderung besteht darin, dass ein solcher Strom vor der Anzeige leicht verarbeitet werden kann, um zum Beispiel nach Objekten auf dem Bild zu suchen.Spielen Raspberry Pi h264 Stream in C# App

Stuff Ich habe versucht:

- VLC-Server auf Raspi und VLC-Control in C# Formen app < - einfache Lösung, mit RTSP, hat aber einen schwerwiegenden Fehler, die eine ~ 3 Sekunden Verzögerung in Bild angezeigt wird. Ich konnte es nicht reparieren es mit buffor Größe/Optionen usw.

- Erstellen einer Buchse auf Raspi mit nc, roh h264 Daten in C# zu empfangen und sie zu mplayer Frontend < vorbei - Wenn ich einfach raspivid Anfang | nc und auf dem Laptop nc | mplayer, ich bekomme genau die Ergebnisse, die ich möchte, das Video, das ich bekomme, ist ziemlich realtime, aber das Problem entsteht, wenn ich versuche, mplayer-Frontend in C# zu erstellen und die nc.exe zu simulieren. Vielleicht übergebe ich die h264-Daten falsch (schreibe sie einfach an stdin) oder vielleicht etwas anderes.

- mit https://github.com/cisco/openh264 < - ich alles zusammengestellt, aber ich kann vid.h264 nicht einmal Probe zu dekodieren bekommen i auf Raspi mit h264dec.exe aufgezeichnet, nicht verwenden es in C# zu erwähnen.

h264dec.exe vid.h264 out.yuv 

Dies erzeugt 0Bytes out.yuv Datei, während:

h264dec.exe vid.h264 

Nachricht gibt mir Fehler: "Keine Eingabedatei in der Konfigurationsdatei angegeben"

- ffmpeg < - I ffplay.exe Wiedergabe in C# -Anwendung implementiert, aber der Mangel an einfachen Methode Screencaps nehmen usw. entmutigt mich, weiter zu untersuchen und zu entwickeln.

Ich bin nicht einmal sicher, ob ich mich dem Thema richtig annähere, also wäre ich wirklich dankbar für jeden Rat, den ich bekommen kann.

EDIT Hier ist meine ‚Arbeit‘ Lösung, die ich in C#

raspivid --width 400 --height 300 -t 9999999 --framerate 25 --output - | nc -l 5884 

nc ip_addr 5884 | mplayer -nosound -fps 100 -demuxer +h264es -cache 1024 - 

Der Schlüssel hier ist FPS 100, becuase dann hinkt MPlayer überspringt umzusetzen versuchen und spielt das Video sofort mit normalen erhält Geschwindigkeit. Das Problem hier ist, dass ich nicht weiß, wie man Videodaten vom Sockel in mplayer über C# übergibt, weil ich denke, dass es nicht über stdin erfolgt ist (bereits versucht das).

Antwort

4

Ok, also eigentlich habe ich es geschafft, diese zu lösen:

Wie ich bereits sagte -fps 120 Option ist es dem Spieler zu machen überspringen, was in der buffor ist und spielen Strom, sobald er sie empfängt. PanelId ist ein Handle eines Panels, in dem mplayer verschachtelt ist.

class Mplayer 
{ 
    Process mplayer; 

    public Mplayer(string path, string pipeName, int panelId) 
    { 
     String args = ""; 
     mplayer = new Process(); 
     mplayer.StartInfo.UseShellExecute = false; 
     mplayer.StartInfo.RedirectStandardInput = true; 
     mplayer.StartInfo.FileName = path; 
     args = @"\\.\pipe\" + pipeName + " -demuxer +h264es -fps 120 -nosound -cache 512"; 
     args += " -nofs -noquiet -identify -slave "; 
     args += " -nomouseinput -sub-fuzziness 1 "; 
     args += " -vo direct3d, -ao dsound -wid "; 
     args += panelId; 
     mplayer.StartInfo.Arguments = args; 
    } 

    public void Start() 
    { 
     mplayer.Start(); 
    } 

    public void End() 
    { 
     mplayer.Kill(); 
    } 
} 

Der Hintergrund Arbeiter Lesestoff aus der Steckdose:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     try 
     { 
      pipeServ.WaitForConnection(); //opcjonalne? 
      StreamWriter sw = new StreamWriter(pipeServ); 
      sw.AutoFlush = true; 

      tcpCamera = new TcpClient(); 
      tcpCamera.Connect(ipAddress, camPort); 
      NetworkStream camStream = tcpCamera.GetStream(); 

      int read = 0; 
      byte[] bytes = new byte[tcpCamera.ReceiveBufferSize]; 
      while (tcpCamera.Connected) 
      { 
       read = camStream.Read(bytes, 0, tcpCamera.ReceiveBufferSize); 
       if (read > 0) 
        pipeServ.Write(bytes, 0, read); 
      } 
     } 
     catch (IOException ex) 
     { 
      //Broken pipe - result of Mplayer exit 
      //MessageBox.Show(ex.Message); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 

Das Skript auf dem Raspberry Pi läuft. Portnummer ist die Nummer des Port-Raspels.

#!/bin/bash 

raspivid --width 1280 --height 720 -t 9999999 --framerate 25 --output - | nc -l PORTNUMBER