16

Silverlight 4 の新しい Web カメラ機能は、非常にクールです。ブラシとして公開することで、Flash が持つものをはるかに超えたシナリオが可能になります。

同時に、ウェブカメラにローカルでアクセスすることは、話の半分に過ぎないように思えます。自分の写真を撮って面白い顔を作るために Web カメラを購入する人はいません。彼らは、結果のビデオ ストリームを他の人に見てもらいたい、つまり、そのビデオをインターネット、一般の Skype、または他の数十のビデオ チャット サイト/アプリケーションのいずれかにストリーミングしたいので、Web カメラを購入します。そして、これまでのところ、私はそれを行う方法を理解していません

hereに示されているように、生の (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) と 1 つのビデオ コーデック (Dirac) がありますが、Java と同様に、それぞれの形式のデコード部分のみを実装しているようです。それらが移植された実装。

Ogg Theora 用の C# コーデック (csTheora、http://www.wreckedgames.com/forum/index.php?topic=1053.0 ) を見つけましたが、ベースとなっている jheora コーデックと同様に、デコードのみです。

もちろん、C や C++ からコーデックを移植するよりも Java からコーデックを移植する方がおそらく簡単ですが、私が見つけた唯一の Java ビデオ コーデックはデコード専用 ( jheoraや jirac など) でした。

だから私はちょっと振り出しに戻っています。Silverlight を介して Web カメラ (またはマイク) をインターネットに接続するためのオプションは次のとおりです。

(1) Microsoft がこれに関するガイダンスを提供するのを待ちます。

(2) C または C++ コーデックの 1 つを Silverlight 互換の C# に移植することに脳のサイクルを費やします。

(3) 圧縮されていない未加工のバイトストリームをサーバーに送信し (または zlib などでわずかに圧縮)、サーバー側でエンコードします。また

(4) 私より賢い誰かがこれを理解し、解決策を提供するのを待ちます.

他の誰かがより良いガイダンスを持っていますか? 他の人には明らかな何かを見落としていませんか? (たとえば、Silverlight 4 には、これを処理する、私が見逃したクラスがいくつかありますか?)

4

5 に答える 5

3

興味のある人に、私が実際に取ったアプローチを知らせたいと思いました. 私は CSpeex を使用して音声をエンコードしていますが、ビデオをエンコードするために独自のブロックベースのビデオ コーデックを作成しました。各フレームを 16x16 ブロックに分割し、どのブロックが送信を保証するのに十分に変更されたかを判断し、大幅に変更されたバージョンの FJCore を使用して、変更されたブロックを Jpeg エンコードします。(FJCore は一般的によくできていますが、JFIF ヘッダーを書き込まないように変更する必要があり、さまざまなオブジェクトの初期化を高速化する必要がありました。) これらはすべて、大まかに に基づいた独自のプロトコルを使用して独自のメディア サーバーに渡されます。 RTP。

144x176 で 1 つのストリームがアップし、4 つのストリームがダウンするため、現在、合計 474 Kbps (~82 Kbps/ビデオ ストリーム + 32 Kbps/オーディオ) を使用して、1 秒あたり 5 フレームを取得し、約 30% の CPU を消費しています。開発ボックス。品質は良くありませんが、ほとんどのビデオ チャット アプリケーションでは許容範囲です。

最初の質問を投稿して以来、解決策を実装する試みがいくつかありました。おそらく、こちらの SocketCoder Web サイト(およびこちら) が最適です。

ただし、SocketCoder モーション JPEG スタイルのビデオ コーデックは、変更されたブロックだけでなく、すべてのフレーム全体を変換するため、ほとんどのアプリケーションでは CPU と帯域幅の要件が非常に高くなると思います。

残念ながら、私自身のソリューションは、当面の間、独自のものであり続ける必要があります :-(.

2010 年 7 月 3 日編集: 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();
    }

私の変更のほとんどは、2 つの新しいクラス JpegFrameEncoder (JpegEncoder の代わり) と JpegFrameDecoder (JpegDecoder の代わり) に関するものです。基本的に、JpegFrameEncoder は、JFIF ヘッダーなしでエンコードされたフレームを書き込み、JpegFrameDecoder は、JFIF ヘッダーが使用する値を伝えることを期待せずにフレームをデコードします (他の帯域外の方法で値を共有することを前提としています)。 )。また、必要なオブジェクトを一度だけ (「静的」として) インスタンス化するため、最小限のオーバーヘッドで JpegFrameEncoder と JpegFrameDecoder をすばやくインスタンス化できます。既存の JpegEncoder および JpegDecoder クラスは、これまでとほとんど同じように動作するはずですが、それを確認するためにごくわずかなテストしか行っていません。

改善したい点はたくさんあります (静的オブジェクトは好きではありません。インスタンス化して個別に渡す必要があります) が、現時点では十分に機能します。うまくいけば、それは他の誰かに役立ちます。コード/ドキュメント/サンプル コード/その他を改善できるかどうかを確認します。時間があれば。

于 2010-03-09T22:05:07.487 に答える
3

私のブログで Jason Clary から次のような回答を受け取りました。


Silverlight 4 ベータ版の VideoSink/AudioSink に関する Mike Taulty のブログの投稿をご覧ください。

VideoSink の OnSample は、WritableBitmap に直接コピーできる圧縮されていない 32bpp ARGB フレームを 1 つ提供することを指摘しておきます。

それを手に入れて、C# の jpeg コーデックである FJCore を取得し、JFIF ヘッダーを出力しないように変更します。次に、それらを次々に書き出すだけで、Motion JPEG コーデックを手に入れることができます。RFC2435 は、RTSP ストリーミングのためにそれを RTP パケットに詰め込む方法を説明しています。

PCM オーディオを ADPCM に圧縮するのもかなり簡単ですが、既製の実装はまだ見つかっていません。RFC3551 は、PCM または ADPCM を RTP パケットに入れる方法を説明しています。

MJPEG と PCM または ADPCM を AVI ファイルに詰め込むのもかなり簡単です。MS には AVI の修正 RIFF 形式に関する適切なドキュメントがいくつかあり、MJPEG と ADPCM の両方が広くサポートされているコーデックです。

とにかくスタートです。

もちろん、これらの問題をすべて解決したら、次のベータ版では、圧縮と WMS へのストリーミングをネイティブでサポートし、より優れた WMV コーデックを使用できるようになるでしょう。


投稿しようと思いました。今まで見た中で最高の提案です。

于 2009-11-23T06:10:22.590 に答える
0

ストップギャップ?

Silverlightが提供する生のビデオの圧縮方法としてWindowsMediaエンコーダーを使用することは可能でしょうか?ISOストレージにキャプチャした後、 WMEを使用してエンコードし、 WebClientを介してサーバーに送信します。2つの大きな問題は次のとおりです。

  • ユーザーがエンコーダーをインストールする必要があります
  • WMEはサポートされなくなります

何か良いことが起こるまで、それは一時的な解決策かもしれないようです。私はこれまでWMEを使って仕事をしたことがないので、これがどれほど実現可能かはわかりません。考え?

于 2010-06-15T16:05:31.877 に答える
0

もう1つコメントを追加します。今日、Microsoftの連絡先から、MicrosoftがSilverlightにアップストリームオーディオおよびビデオエンコーディング/ストリーミングのサポートを追加する予定はないことを聞いたので、少なくとも現時点では、オプション#1はテーブルから外れているようです。私の推測では、これに対するサポートを見つけることは、コミュニティの責任、つまりあなたと私次第だと思います。

于 2009-12-03T21:58:47.180 に答える
-4

新しい Expression 4 エンコーダーを試しましたか?

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

于 2010-06-20T17:15:01.200 に答える