2014-06-28 19 views
5

Ho una scheda Raspberry Pi con videocamera dedicata che registra solo video in h264. Sto cercando il metodo migliore per lo streaming e la riproduzione di video registrati in tempo reale (come in meno di 1 secondo di ritardo) nell'app di Windows Forms C#. Il requisito aggiuntivo è che tale flusso può essere facilmente elaborato prima di essere visualizzato, ad esempio per cercare oggetti nell'immagine.Riproduci stream Raspberry Pi h264 nell'app C#

Stuff ho provato:

- server di VLC su raspi e controllo VLC in C# forme app < - soluzione semplice, con RTSP, ma ha un grave difetto, che è un ~ ritardo 3sec in immagine visualizzata. Non riuscivo a risolvere il problema con buffor dimensioni/opzioni ecc

- la creazione di una presa Raspi con NC, la ricezione di dati grezzi H264 in C# e passarlo a mplayer frontend < - Se io semplicemente iniziare raspivid | nc e sul portatile nc | mplayer, ottengo esattamente i risultati che voglio, il video che ottengo è praticamente in tempo reale, ma il problema sorge quando provo a creare il frontend mplayer in C# e simulare il nc.exe. Forse sto passando male i dati dell'h264 (semplicemente li scrivo su stdin) o forse qualcos'altro.

- utilizzando https://github.com/cisco/openh264 < - Ho compilato tutto, ma non posso anche arrivare a decodificare campione vid.h264 ho registrato sul Raspi con h264dec.exe, per non parlare di usarlo in C#.

h264dec.exe vid.h264 out.yuv 

Questo produce file di 0bytes out.yuv, mentre:

h264dec.exe vid.h264 

Mi dà messaggio di errore: "Nessun file di input specificato nel file di configurazione"

- ffmpeg < - ho implementato la riproduzione ffplay.exe in C# app, ma la mancanza di metodo facile prendere screencaps ecc scoraggiato me di approfondire e sviluppare.

Non sono nemmeno sicuro se sto approcciando correttamente l'argomento, quindi sarei davvero grato per ogni consiglio che posso dare.

EDIT Ecco la mia soluzione 'di lavoro' Sto cercando di implementare 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 - 

La chiave qui è FPS 100, becuase poi salta mplayer GAL e riproduce il video che riceve immediatamente con normale velocità. Il problema qui è che non so come passare i dati video dal socket in mplayer tramite C#, perché suppongo che non sia stato fatto tramite stdin (già provato).

risposta

4

Ok, quindi in realtà sono riuscito a risolvere questo:

Come ho detto prima -fps 120 opzione è lì per rendere il lettore salta cosa c'è nel buffor e giocare flusso non appena riceve. PanelId è un handle di un pannello in cui mplayer è annidato.

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(); 
    } 
} 

Lo sfondo roba lettura lavoratore da presa:

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); 
     } 
    } 

Lo script in esecuzione sul Raspberry Pi. Il numero di porta è il numero di rasp della porta in ascolto.

#!/bin/bash 

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