2014-06-28 62 views
5

我有一個專用相機的Raspberry Pi板,僅在h264中記錄視頻。我正在尋找在c#windows窗體應用程序中實時流式傳輸和播放錄製視頻的最佳方法(比如,延遲小於1秒)。額外的要求是這樣的流可以在顯示之前被容易地處理,例如用於搜索圖像上的對象。在C#應用程序中播放樹莓派h264流

的東西,我試過:

- 上raspi和VLC控制在C#的形式應用 < VLC服務器 - 簡單的解決方案,RTSP,但有一個嚴重的缺陷,這是在圖像顯示的〜3秒的延遲。我無法buffor尺寸/期權等修復

- 創建與NC raspi插座,在C#中接收的原始數據H264並將它傳遞給mplayer的前端 < - 如果我只是開始raspivid | NC和筆記本電腦NC | mplayer,我得到了我想要的結果,我得到的視頻非常實時,但問題出現在我嘗試在c#中創建mplayer前端並模擬nc.exe時。也許我錯誤地傳遞了h264的數據(只需將它們寫入標準輸入)或者其他的東西。

- 使用https://github.com/cisco/openh264 < - 我編的一切,但我甚至不能解碼樣本vid.h264我記錄在raspi與h264dec.exe,不是在C#中使用它來提。

h264dec.exe vid.h264 out.yuv 

這產生0bytes out.yuv文件,而:

h264dec.exe vid.h264 

給我錯誤消息: 「在配置文件中指定無輸入文件」。

- ffmpeg的 < - 我實現ffplay.exe播放在C#應用程序,但由於缺乏簡單的方法,採取screencaps等鼓勵我進一步研究和開發。

我甚至不確定我是否正確地接近這個主題,所以我會非常感謝我能得到的每一條建議。

編輯 這裏是我的「工作」的解決方案,我想在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 - 

這裏的關鍵是FPS 100,監守然後mplayer的跳過落後並播放立即與正常接收視頻速度。 這裏的問題是我不知道如何通過C#將視頻數據從套接字傳遞到mplayer,因爲我猜這不是通過stdin(已經嘗試過)完成的。

回答

4

好了,其實我設法解決這個問題:

就像我剛纔所說-fps 120的選擇是有讓玩家跳過什麼在buffor並儘快收到它播放流。 PanelId是mplayer嵌套的面板的句柄。

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

從插座的背景工人閱讀的東西:

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

腳本在運行樹莓派。 Portnumber是端口銼刀正在監聽的編號。

#!/bin/bash 

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