16

Silverlight 4 中的新网络摄像头非常酷。通过将其暴露为画笔,它可以实现超出 Flash 所拥有的任何场景。

同时,在本地访问网络摄像头似乎只是故事的一半。没有人会购买网络摄像头,这样他们就可以为自己拍照并做出有趣的表情。他们购买网络摄像头是因为他们希望其他人看到生成的视频流,即,他们希望将该视频流式传输到 Internet、外行 Skype 或其他数十个视频聊天站点/应用程序中的任何一个。到目前为止,我还没有想出如何做到这一点

事实证明,获取原始(Format32bppArgb 格式)字节流非常简单,如此处所示

但除非我们想将原始字节流传输到服务器(这会占用太多带宽),否则我们需要以某种方式对其进行编码。这更复杂。MS 已经在 Silverlight 中实现了几个编解码器,但据我所知,它们都专注于解码视频流,而不是首先对其进行编码。除此之外,我首先不知道如何直接访问 H.264 编解码器。

有大量的开源编解码器(例如,在此处的 ffmpeg 项目中),但它们都是用 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 项目中的 mooncodecs 文件夹(此处)有几个 C# 音频编解码器(ADPCM 和 Ogg Vorbis)和一个视频编解码器(Dirac),但它们似乎都实现了各自格式的解码部分,就像 java移植它们的实现。

我找到了一个用于 Ogg Theora 的 C# 编解码器(csTheora,http ://www.wreckedgames.com/forum/index.php?topic=1053.0 ),但同样,它只是解码,它所基于的 jheora 编解码器也是如此。

当然,从 Java 移植编解码器可能比从 C 或 C++ 移植编解码器更容易,但我发现的唯一 Java 视频编解码器是仅解码(例如jheora或 jirac)。

所以我有点回到第一方了。看起来我们通过 Silverlight 将网络摄像头(或麦克风)连接到 Internet 的选项是:

(1) 等待微软对此提供一些指导;

(2) 花费脑力将 C 或 C++ 编解码器之一移植到与 Silverlight 兼容的 C#;

(3) 将原始的、未压缩的字节流发送到服务器(或者可能用 zlib 之类的东西稍微压缩),然后在服务器端对其进行编码;或者

(4) 等待比我聪明的人解决这个问题并提供解决方案。

其他人有更好的指导吗?我是否错过了对其他人来说非常明显的东西?(例如,Silverlight 4 是否有一些我错过的课程可以解决这个问题?)

4

5 回答 5

3

我刚刚在我的博客上收到了 Jason Clary 的回复:


在 Mike Taulty 的博客上看到了您关于 Silverlight 4 beta 中 VideoSink/AudioSink 的帖子。

我想我会指出 VideoSink 的 OnSample 为您提供了一个未压缩的 32bpp ARGB 帧,可以直接将其复制到 WritableBitmap 中。

有了这个,抓取 FJCore,一个 C# 中的 jpeg 编解码器,并将其修改为不输出 JFIF 标头。然后把它们一个接一个地写出来,你就得到了一个 Motion JPEG 编解码器。RFC2435 解释了如何将其填充到 RTP 数据包中以进行 RTSP 流传输。

将 PCM 音频压缩为 ADPCM 也相当容易,但我还没有找到现成的实现。RFC3551 解释了如何将 PCM 或 ADPCM 放入 RTP 数据包。

将 MJPEG 和 PCM 或 ADPCM 填充到 AVI 文件中也应该相当容易。MS 有一些关于 AVI 修改后的 RIFF 格式的不错的文档,并且 MJPEG 和 ADPCM 都是广泛支持的编解码器。

无论如何,这是一个开始。

当然,一旦您解决了所有这些问题,下一个 Beta 版可能会提供对 WMS 压缩和流式传输的原生支持,并带有更好的 WMV 编解码器。


以为我会发布它。这是迄今为止我见过的最好的建议。

于 2009-11-23T06:10:22.590 回答
3

我想我会让感兴趣的人知道我实际采用的方法。我正在使用 CSpeex 对语音进行编码,但我编写了自己的基于块的视频编解码器来对视频进行编码。它将每一帧分成 16x16 块,确定哪些块已充分更改以保证传输,然后使用 FJCore 的大量修改版本对更改的块进行 Jpeg 编码。(FJCore 通常做得很好,但需要修改它以不写入 JFIF 标头,并加快各种对象的初始化。)所有这些都被传递到使用专有协议的专有媒体服务器,大致基于实时传输协议。

在 144x176 上一个流向上和四个流向下,我目前每秒获得 5 帧,总共使用 474 Kbps(~82 Kbps / 视频流 + 32 Kbps / 音频),我的 CPU 占用了大约 30%开发箱。质量不是很好,但对于大多数视频聊天应用程序来说是可以接受的。

自从我发布了我的原始问题以来,已经多次尝试实施解决方案。最好的可能是在这里(和这里)的 SocketCoder 网站。

但是,由于 SocketCoder 运动 JPEG 风格的视频编解码器会转换每一帧的全部内容,而不仅仅是已更改的块,我的假设是 CPU 和带宽要求对于大多数应用程序来说都是令人望而却步的。

不幸的是,在可预见的未来,我自己的解决方案将不得不保持专有性:-(。

编辑 7/3/10:我刚刚获得了分享我对 FJCore 库的修改的权限。我已经在此处发布了该项目(不幸的是,没有任何示例代码):

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

如何使用它的(非常粗略的)示例:

    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 类的工作方式应该与它们一直以来的工作方式几乎相同,尽管我只做了一点点测试来确认这一点。

有很多我想改进的地方(我不喜欢静态对象——它们应该被实例化并单独传递),但它目前对于我们的目的来说已经足够好了。希望它对其他人有帮助。我会看看我是否可以改进代码/文档/示例代码/等。如果我有时间。

于 2010-03-09T22:05:07.487 回答
0

我将添加另一条评论。我今天刚刚从 Microsoft 联系人那里听说,Microsoft打算向 Silverlight 添加任何对上游音频和视频编码/流式传输的支持,因此选项 #1 似乎不在讨论范围内,至少目前是这样。我的猜测是,找出对此的支持将是社区的责任,即取决于你和我。

于 2009-12-03T21:58:47.180 回答
0

权宜之计?

是否可以使用Windows Media Encoder作为 Silverlight 提供的原始视频的压缩方法?捕获到ISO 存储后,使用WME编码并通过WebClient发送到服务器。两个大问题是:

  • 需要用户安装编码器
  • WME将不再受支持

在出现更好的情况之前,这似乎是一个权宜之计。我之前没有与WME合作过,所以我不知道这有多可行。想法?

于 2010-06-15T16:05:31.877 回答
-4

您是否尝试过新的 Expression 4 编码器?

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

于 2010-06-20T17:15:01.200 回答