2009-11-20 40 views
16

Silverlight 4中的新攝像頭內容令人沉醉。通過將其公開爲畫筆,它可以實現超出Flash所具有的任何形式。從Silverlight 4(Beta)流式傳輸攝像頭

與此同時,在本地訪問攝像頭看起來只是故事的一半。沒有人會購買攝像頭,以便他們可以拍攝自己的照片,並製作出有趣的照片。他們購買網絡攝像頭是因爲他們希望其他人看到最終的視頻流,即他們想要將該視頻流式傳輸到互聯網,Skype或任何其他幾十個視頻聊天站點/應用程序。到目前爲止,我還沒有想出如何做到這一點

事實證明,這是非常簡單的得到一個原始(Format32bppArgb格式化)字節流的保持,如演示here。但是,除非我們想將原始字節流傳輸到服務器(這會消耗太多的帶寬),否則我們需要以某種方式對其進行編碼。而這更復雜。 MS已經在Silverlight中實現了多個編解碼器,但據我所知,他們都專注於解碼視頻流,而不是首先對其進行編碼。除此之外,我無法弄清如何直接訪問H.264編解碼器。

有大量的開源編解碼器(例如,在ffmpeg項目here),但它們都用C語言編寫,並且它們看起來不容易移植到C#。除非翻譯10000+行的代碼看起來像這是你:-)樂趣所在

const int b_xy= h->mb2b_xy[left_xy[i]] + 3; 
const int b8_xy= h->mb2b8_xy[left_xy[i]] + 1; 
*(uint32_t*)h->mv_cache[list][cache_idx ]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[0+i*2]]; 
*(uint32_t*)h->mv_cache[list][cache_idx+8]= *(uint32_t*)s->current_picture.motion_val[list][b_xy + h->b_stride*left_block[1+i*2]]; 
h->ref_cache[list][cache_idx ]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[0+i*2]>>1)]; 
h->ref_cache[list][cache_idx+8]= s->current_picture.ref_index[list][b8_xy + h->b8_stride*(left_block[1+i*2]>>1)]; 

Mono項目(here)內的mooncodecs文件夾在C#幾個音頻編解碼器(ADPCM和Ogg Vorbis),和一個視頻編解碼器(Dirac),但它們似乎都只實現了各自格式的解碼部分,就像它們所移植的Java實現一樣。

我發現了Ogg Theora的C#編解碼器(csTheora,http://www.wreckedgames.com/forum/index.php?topic=1053.0),但它只是解碼,就像它所基於的jheora編解碼器一樣。當然,它可能比從C或C++更容易移植來自Java的編解碼器,但是我發現的唯一的Java視頻編解碼器只是解碼(例如jheora或jirac)。

所以我有點回到原點。它看起來像我們通過Silverlight將互聯網攝像頭(或麥克風)連接到互聯網的選項是:

(1)等待Microsoft爲此提供一些指導; (2)花大腦循環將C或C++編解碼器之一移植到Silverlight兼容的C#中; (3)將未壓縮的原始未壓縮字節流發送到服務器(或者稍微用類似zlib的方式壓縮),然後對服務器端進行編碼;或

(4)等一個比我聰明的人解決這個問題並提供一個解決方案。

其他人有沒有更好的指導?我錯過了對其他人顯而易見的事情嗎? (例如,Silverlight 4的某個地方是否有一些我錯過了的類來處理這個問題?)

回答

3

我以爲我會讓感興趣的人知道我實際採取的方法。我使用CSpeex編碼語音,但是我編寫了自己的基於塊的視頻編解碼器來編碼視頻。它將每個幀分成16x16塊,確定哪些塊已足夠改變以保證傳輸,然後使用大量修改版本的FJCore對改變後的塊進行Jpeg編碼。 (FJCore一般都做得很好,但需要修改它以避免寫入JFIF頭文件,並加速各種對象的初始化。)所有這些都通過專有協議傳遞到專有媒體服務器,這些協議大致基於RTP。我現在使用總共474 Kbps(〜82 Kbps /視頻流+ 32 Kbps /音頻),每秒獲得5幀,並且咀嚼大約30個%我的開發箱上的CPU。質量不是很好,但對大多數視頻聊天應用程序來說是可以接受的。

由於我發佈我的原始問題,有幾次嘗試實施解決方案。可能最好的是在SocketCoder網站here(和here)。但是,由於SocketCoder運動JPEG風格的視頻編解碼器轉換了每個幀的整體而不僅僅是已經改變的塊,我的假設是,CPU和帶寬要求對於大多數應用程序來說將是禁止的。

不幸的是,我自己的解決方案將不得不爲可預見的未來仍然具有專利:-(

編輯10年7月3日:我剛剛得到的權限來分享我的修改到FJCore庫我VE張貼的項目(不加任何示例代碼,不幸)在這裏:

http://www.alanta.com/Alanta.Client.Media.Jpeg.zip

A(很粗糙)如何使用它例如:

public void EncodeAsJpeg() 
    { 
     byte[][,] raster = GetSubsampledRaster(); 
     var image = new Alanta.Client.Media.Jpeg.Image(colorModel, raster); 
     EncodedStream = new MemoryStream(); 
     var encoder = new JpegFrameEncoder(image, MediaConstants.JpegQuality, EncodedStream); 
     encoder.Encode(); 
    } 


    public void DecodeFromJpeg() 
    { 
     EncodedStream.Seek(0, SeekOrigin.Begin); 
     var decoder = new JpegFrameDecoder(EncodedStream, height, width, MediaConstants.JpegQuality); 
     var raster = decoder.Decode(); 
    } 

我的大部分更改都圍繞着兩個新類JpegFrameEncoder(而不是JpegEncoder)和JpegFrameDecoder(而不是JpegDecoder)。基本上,JpegFrameEncoder編寫沒有任何JFIF頭的編碼幀,並且JpegFrameDecoder對幀進行解碼而不期望任何JFIF頭告訴它使用什麼值(它假設您將以某種其他帶外方式共享這些值)。它還可以實例化一次它需要的任何對象(如「靜態」),以便可以以最小的開銷快速實例化JpegFrameEncoder和JpegFrameDecoder。預先存在的JpegEncoder和JpegDecoder類應該和以往一樣工作,儘管我只做了一點測試來確認。

有很多的事情,我想改善一下(我不喜歡靜態的對象 - 他們應該在單獨被實例化,並通過),但目前的工作不夠好,我們的目的。希望對別人有幫助。我會看看我是否可以改進代碼/文檔/示例代碼/等。如果我有時間。

+0

謝謝你的例子,肯。我有一個silverlight應用程序,我願意允許上傳用戶創建的視頻到Facebook。但是,儘管我使用了m-jpeg編碼,但這不是通過FB支持的編解碼器。 GRRRR。這是一個恥辱MS不幫我們在這裏。 – tyshock 2010-07-15 20:02:28

3

我剛剛接到了來自傑森克拉裏這種反應在我的博客:


看到你在Silverlight 4 beta中邁克Taulty的約VideoSink/AudioSink博客文章。

我想我會指出VideoSink的OnSample爲您提供了一個單獨的未壓縮的32bpp ARGB幀,它可以直接複製到WritableBitmap中。

用手抓住C#中的jpeg編解碼器FJCore,並修改它以不輸出JFIF頭。然後把它們一個接一個寫出來,然後你就得到了一個Motion JPEG編解碼器。 RFC2435解釋瞭如何將其填充到用於RTSP流的RTP數據包中。

將PCM音頻壓縮到ADPCM也很容易,但我還沒有找到現成的實現。 RFC3551解釋瞭如何將PCM或ADPCM放入RTP數據包。

將MJPEG和PCM或ADPCM填充到AVI文件中也應該是相當容易的。 MS在AVI的修改後的RIFF格式上有一些體面的文檔,MJPEG和ADPCM都廣泛支持編解碼器。

無論如何這是一個開始。

當然,一旦你經歷了所有這些麻煩,下一個測試版本可能會提供原生支持,通過更好的WMV編解碼器對WMS進行壓縮和流式傳輸。


想我會張貼它。這是迄今爲止我見過的最好的建議。

0

我會添加一個其他評論。我今天剛剛從微軟的一位聯繫人那裏得知,微軟的而不是計劃爲Silverlight添加對上游音頻和視頻編碼/流的任何支持,所以選項#1似乎脫離了桌面,至少目前如此。我的猜測是,找出對此的支持將是社區的責任,即取決於你和我。

0

停止差距?

是否有可能使用Windows Media編碼器作爲Silverlight提供的原始視頻的壓縮方法?在捕獲到ISO存儲,編碼w/WME並通過WebClient發送到服務器。兩大問題是:

  • 要求用戶安裝編碼器
  • WME將不再支持

好像直到更好的東西可能是一個權宜之計沿。我沒有工作w/WME之前,但我不知道這將是多麼可行。思考?

+0

除了需要用戶安裝Windows Media Encoder之外,除非應用程序運行在瀏覽器外並處於完全信任模式,否則Silverlight將無法與WME通話:此時,它不再完全清楚爲什麼我們需要在Silverlight中做到這一點:-)。 – 2010-06-15 18:49:51

-4

您是否嘗試了新的Expression 4 Encoders?

http://www.microsoft.com/expression/products/EncoderPro_Overview.aspx

+0

除非我錯過了很多東西,否則WME不是Silverlight客戶端實時編碼的解決方案。 – 2010-06-21 10:44:05

+0

你錯過了什麼。這不是WME。因爲它確實是QuickTime,H.264,AAC-LC,目前在Windows Media Encoder下都不支持。它也可以用於AVI,MPEG-2等。不太確定你的問題,但這是Microsoft Expressions Endcoder工具的核心,它是一種客戶端應用程序,並且不僅支持Windows Media格式。 – 2010-06-29 02:36:19

+0

尼克,肯的重點不是「WME」,而是「實時」。 – 2010-12-12 11:59:57

相關問題