- 締切済み
ネットワークカメラの動画保存をコマ落ちせずに取得するには
・目的は、 ネットワークカメラBB-HCM311 http://panasonic.biz/netsys/netwkcam/lineup/hcm311.html http://panasonic.biz/netsys/netwkcam/support/download/technical/cgi_cmnd_ver2.1.pdf(CGI) から流れてくるMotionJpegをパソコンのファイルに格納すると言うものです。 ・現状としては、MotionJpegのJpegを切り出して保存することが出来ています。 ・未解決の問題は、カメラから配信されているデータを100%取得できていないと言う所です。なぜならば、下のソースに示すように、Read()でバッファに格納しもう一度Read()を行うまでにf()を実行するために、f()の実行中にカメラからの配信が進んでしまうためです。 通常のファイルをサーバーから取得する場合は順次読み込めば問題ないと思うのですが、このようなストリーム配信の場合、何か参考になるものをご存じないですか? よろしくお願いします。 開発環境 VC6.0, OS WinXP Pro
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- taka_tetsu
- ベストアンサー率65% (1020/1553)
>スレッド中でRead()だけを繰り返し処理した場合に、Read()が終わって次のRead()を呼ぶ間に必ず遅延が起こると思っているからです。 よーく考えてみてくださいね。 これがちゃんと出来なきゃ何にもできませんよねぇ(^^;;; 無限大のバッファなんて準備できないんですから。 >OSがWindowsXPですから、リアルタイム性は保証して無いだろうと思っているわけです。 うーん、ネットワーク、TCP/IPという時点で、リアルタイム性はそこまで意味は無いかと・・・ あくまでも受信データの取りこぼしが無ければいいのですから。十分なサイズのバッファと、単位時間に送られてくるデータ量以上の速さでデータをOSのバッファから自分の準備した領域に取り出せればいいんですよね。OS側のバッファがあふれる前に。 あと、 >あとマルチスレッドなら、取りこぼし防ぐために受信スレッドの方をプライオリティをあげておいたほうがいいでしょう。 確かに受信スレッドのプライオリティあげるべきですけど、それによってファイル書き込みが間に合わなくなると本末転倒ですのでバランスが肝心です。
- terra5
- ベストアンサー率34% (574/1662)
ダブルバッファでは足らないこともあるように思えますので、 さらに多くのバッファを用意して、 既に回答があるようにファイル書き込みを別スレッドで行うか、 非同期I/O(オーバーラップ I/O)を使うかでしょうね。 あとマルチスレッドなら、取りこぼし防ぐために受信スレッドの方をプライオリティをあげておいたほうがいいでしょう。
お礼
ありがとうございます。今のネットワーク環境の転送速度のせいか、取りこぼしを考慮して1秒間に8枚程度しかデータが流れてきていないようです。ということで、ダブルバッファリングを使ってもうちょっときっちりやってみます。 taka_tetsuさんterra5さん、また後日報告いたします。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
>ダブルバッファリング+(スレッドで2回線つないで交互に取り込む)も考えましたが、どうも接続数を増やすとパフォーマンスが落ちてあまり速度が得られないようです。 なぜ接続数を増やすんですか? Read()を連続しておこないたいんですよね? 別スレッド内で処理を行えばいいのはf()なんですから。 Read()をしてるメインスレッド内のループはバッファに書き込むだけ、f()の内部処理を行うスレッドのループは1つのバッファが満杯になったかチェックし、なってたらファイル格納を行うようにするのが普通かと。
お礼
ありがとうございます。 接続数を増やし2回線で冗長に取り込もうと思った理由について→スレッド中でRead()だけを繰り返し処理した場合に、Read()が終わって次のRead()を呼ぶ間に必ず遅延が起こると思っているからです。 OSがWindowsXPですから、リアルタイム性は保証して無いだろうと思っているわけです。 ちょっと詳しく実験してみます。 スレッドはあまり詳しくないので、まずf()で何もせずにRead()を繰り返してみました。その時つなぎ目が怪しかったので、私のプログラムにどこかにバグがあるかもしれません。少しお時間をください。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
一般的にはダブルバッファリングでしょう。 バッファを2つ以上準備し、1つのバッファが満杯になったら別スレッドで保存を行い、データの受信は残りのバッファで行えばいいかと。
お礼
お返事ありがとうございます。 私もそう思いますが、カメラ(HTTPサーバー)より送られてくる信号は、ソース中のRead()を間髪いれずに実行し続けなければ連続データを取り込むことができないようなのです。なぜかというと、Webカメラの画像をリアルタイムで配信する特性上、受け取らなかったデータは捨てて、常に新しいデータを配信する必要性があるからです。 ダブルバッファリング+(スレッドで2回線つないで交互に取り込む)も考えましたが、どうも接続数を増やすとパフォーマンスが落ちてあまり速度が得られないようです。 むしろ、リングバッファのようなイメージで、途切れず取り込みながら保存していく方法って無いかと模索中です。
補足
ソースを補足します。 const int max_2len=一度に取得するデータの大きさ; UINT nRead=0; CInternetSession session; CHttpConnection* pConnection = session.GetHttpConnection( "IPアドレス" , ポート番号 , "ID" , "パスワード"); CHttpFile* pFile[2]; pFile[0]= pConnection->OpenRequest ( CHttpConnection::HTTP_VERB_GET , "/nphMotionJpeg?Resolution=640x480&Quality=Motion HTTP/1.0\r\n" ); pFile[0]->SendRequest(); DWORD dwRet; pFile[0]->QueryInfoStatusCode( dwRet ); if( dwRet == HTTP_STATUS_OK ) { BYTE* m_cambuf[2]; // カメラからのデータを格納 m_cambuf[0] =new BYTE[max_2len]; int gflag[2]={0}; while( 1 ) { nRead = pFile[0]->Read( m_cambuf[0], max_2len ); // カメラからデータ取得 f(); // カメラからのデータをファイルに保存等 } delete[] m_buf; delete[] m_cambuf[0]; } delete pFile[0]; delete pConnection; session.Close();
お礼
いやー。 たのしいっすねここ。 まわりにこういうネタについてきてくれる人がいなくて(汗) 所詮私も含めて開発系には弱いということでしょうか・・・。 よーく考えてやってみます。