システムメンテナンスのお知らせ

TCPでデータを受け取ってそれを画像として連続表示する、いわゆるストリーミング動画再生ソフトを作ろうと思っています。
ソフトウェアプログラミングは疎く、TCPでのデータの受信プログラムの作成はできるのですが、PCへの負荷を最小限にして表示する方法がよくわからず困っております。

動画サイズは、1280*720のフルカラーで、60fpsで表示したいと考えています。
画像は非圧縮のベタデータで送られてきます。

VC++とDirectXを用いれば高速に表示できるかと思い(どちらも使用は初めてです)、この数日調べまわっていますが、まずベタデータを表示することすらままならず(ファイルを読み出してテクスチャを作成し、レンダリングするという情報は多いのですが。。)、それがなんとかできても今度はそのデータを変えてアニメーション表示しようとするとメモリーを山のように消費してまともに動かないプログラムが出来上がったりと、なんとも苦しんでおります。

当方使用できるプログラミング言語はC言語のみですが、必要であればC++も勉強して使用したいと思います。

どのような手法が最適で、どのような手順でやればいいのか、ヒントだけでも、教えていただければ助かります。

gooドクター

A 回答 (4件)

D3DXCreateTextureFromFileInMemoryEx が遅そうですね。


DirectXを使わずに、ビットマップをBitBltで描画する方法はどうでしょうか。

参考URL:
保存した100枚のビットマップ画像を連続表示 - 質問・相談ならMSN相談箱
http://questionbox.jp.msn.com/qa4477113.html
GDI/GDI+のビットマップ転送能力
http://lamoo.s53.xrea.com/develop/gdiplus/gdiplu …

また、YUV→RGB変換には、実数演算がふくまれているので、整数の処理に置き換えると良いかもしれません。

参考URL:
KnowledgeBase: RGB<-->YUV変換
http://tyre.gotdns.org/domino/web01/tecrep2.nsf/ …

この回答への補足

ありがとうございます。
BitBltを試してみましたが、圧倒的に早いですね。

ただ、LoadImageでbmpファイルから作ったビットマップの表示はできるのですが、
メモリー上にあるデータをビットマップ(DDB)にする方法がわからず四苦八苦しております。

CreateBitmapである程度できるようですが、カラーにはCreateCompatibleBitmapで作れとありCreateBitmapでカラーDDBを作るサンプルが見当たらず、CreateCompatibleBitmapで作ろうとすると、こいつは画像データのポインタを渡してくれないらしく、結局メモリー上のデータをDDBにすることができず。。。

このあたりなにかヒントがあれば、お教えいただければと思います。

補足日時:2010/10/25 20:45
    • good
    • 0
この回答へのお礼

BitBltの情報をいただけたおかげで、デモのほう完成いたしました。

結局DDBは直接触れないようで、DIBで作成しました。
YUV→RGB変換は、演算そのものよりピクセルごとにデータを書き込むのに時間がかかるようで(ライトバックキャッシュはどうなってるんでしょうか。。)、送信側でYUV→RGB変換して、ソケットの受信バッファに直接DIBの画像データポインタを指定することで表示させました。
そのため、32bitの転送となり、フレームレートは30fpsに下げざるを得なくなりましたが、DIBの表示自体も若干重かったので、ちょうどよかったのかなと考えています。

なんだか、Windowsプログラミングは、MicroSoftの手のひらで踊らされているようですね。

ともかく、ありがとうございました。

お礼日時:2010/10/27 15:12

非圧縮ということにこだわらないのであれば、1枚ずつJPEG圧縮をかけるのはどうでしょうか。

これでもサイズは数10分の1になります。

処理がフレーム単位で独立していますので、送信側、受信側とも苦労せずに対応可能だと思います。送信サイズが小さくなる分、無圧縮で送信するよりも負荷は小さく出来るでしょう。

ちなみに、初代Playstationは、この方法で動画を表示していました。規格的には「MotionJPEG」と呼ばれています。

この回答への補足

今回はTCP転送が高速にできますよというデモに使用しますので、圧縮して転送するのはNGとなります。

また、実際TCPデータの受信およびデータのチェックだけであれば、CPU使用率は20~30%にとどまっています。

今回、TCPの通信を行わない状態で、画像データをPCプログラム内でパターンを生成しているのみにもかかわらず、CPU使用率は50%を超え(Core duoなので、実質使用率は100%です)、60fpsの描画ができていない状況です。

一般的な動画とは違い、60fpsなので重いというのはわかってはいるのですが、WindowsではOpenGLよりDirectXのほうが軽いのではとの思いがあり、今回質問させていただいたしだいです。

DirectShowのレンダラーを使えばできそうな感じではあるのですが、DirectX以上にベタデータの表示に関する情報が少なく、困っております。

補足日時:2010/10/24 03:27
    • good
    • 0

>これで1280*720*60*16なので、885Mbpsになるかと考えています。



やっぱりギガビットイーサでも足りません。
「ギガビットイーサなら1000Mbpsだから足りるのでは?」
とか思っています?

規格上は1000Mbpsでも、その速度がフルで出るコトはありません。
またTCP/IPのヘッダが付与されたりしますから全部は使えません。
TCPは比較的重いです。
UDPなら多少は早くなりますが、エラー時の再送などはありませんしパケットの到着順も保証されません。
データ圧縮して転送するなりしないとどうにもならんでしょう。

この回答への補足

今回ハードワイヤードTCP/IPをFPGAで作成しまして、PCで受信して
データ比較も行って実測で900Mbps出ることを確認しています。
これはもちろんヘッダを除いた実データ部分の速度です。

以下は、実際のデータ転送の模様で、4GBの転送を35秒以内で完了しています。


ただデータが流れてるだけでは面白くないので、ハイビジョンカメラのデータを
イーサネット経由でPCで受信して表示するというデモを作成しようと思っております。

通信部分は今回問題としておりませんので、できれば、今回の質問そのものに
お答えいただけますと助かります。

DirectXで、
D3DXCreateTextureFromFileInMemoryEx→BeginScene→Begin→Draw→End→EndScene→Present→SAFE_RELEASE
をループさせることで表示させることはできましたが、負荷が高すぎて60fpsはまったく出ませんでした。(表示する画像はプログラム内で簡単なパターンを作成しています)
この方法があっているかどうかがわかっておりませんが。。

OpenGLも、試してみましたが少し厳しいようです。
(glutIdleFuncで画像パターンデータ生成と、glutPostRedisplayを回しております。)

そもそも画像データパターン生成だけでも重いようで(したがって、ソフトウェアでのYUV→RGB変換も重いと思われます)、そこから考えないといけないようではあるのですが。。

補足日時:2010/10/24 00:53
    • good
    • 0

ソフトの問題より通信速度的にギガビットイーサネットでも無理です

この回答への補足

すいません。相談する部分とは直接関係なかったので詳しくは書きませんでしたが、イーサネットで来るデータはYUVで、Yに8bit、UVにそれぞれ4bitを割り当てる予定です。これで1280*720*60*16なので、885Mbpsになるかと考えています。
表示するときにRGBに変換して24bitにしようかと考えています。

補足日時:2010/10/23 13:41
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

gooドクター

人気Q&Aランキング