2009-11-20 39 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

相关问题