2012年12月17日月曜日

AndroidでWifiカメラからのMJPEGストリームを表示する

最近ひとりぶろぐさんのエントリ
でも紹介されていましたが、Ai-BallのようにMJPEGストリームを送信できるカメラが楽しいです。

ここではその映像をandroidで受信する方法について紹介します。利用形態は左図のようなイメージです。

サンプルコードはstack overflowの「Android ICS and MJPEG using AsyncTask」で既に紹介されています。しかし、このコードを用いると
  • メモリ使用量が多くGarbage Collectionが一秒間に多数回実行される
  • 端末によっては映像の遅れが1秒以上起こる
となり、少し性能が物足りないです。

MJPEGを表示するアプリケーションでGoogle Playでダウンロードできるものとしては「MJpeg Viewer」がありますが、これも同様の問題を抱えています。

この問題を解決するため、その高速版として「SimpleMjpegView」を作成して公開しました。
(ソースだけではなく、ビルド済みアプリもGoogle Playからダウンロードできるようにしました。2013.4.29)


メモリ使用量を削減し、jpegのデコードにJNI経由でlibjpegを利用しているのが主な変更点です。上記の問題に対しては下記のように解決されています。
  • Garbage Collection は1秒に1回以下(端末依存、後述)
  • 映像の遅れは1秒より大幅に短い(<< 1秒)
このコードをベースに作成したのが下記の、WifiカメラAi-Ballを搭載したプラレールです。


このプラレールを2012年10月20日(土)に仙台にて行われたICT ERA + ABC 2012 東北や2012年12月1日(土)、2日(日)に日本未来科学館で行われたMaker Faire Tokyo 2012にて展示させて頂きました。

ここでは、そこでの体験なども含め、MJPEGストリームをAndroidで表示する方法についてまとめてみたいと思います。

利用形態

(1)Wifiカメラ+スマホ

Trek Ai-Ballが用いている方式で、カメラ自体がアクセスポイントになります。メリットはとにかく小型であることです。

Planexからも多数のネットワークカメラが発売されていますが、それらで動作するかは試していません。

URLはデフォルトでは
http://192.168.2.1:80/?action=stream
となります。


(2)スマホ+Wifiルーター+スマホ

カメラデータ送信用スマートフォンにIP WebcamというフリーソフトをインストールしてWifiカメラ化し、そこからの映像をWifiルーター経由で受信するという方式です。(1)よりも無線が安定するのではないかと導入してみました。

URLはデフォルトでは
http://192.168.x.y:8080/videofeed
となります。

(3)スマホ(テザリング)+スマホ

(2)と同じですが、Wifiルーターの代わりにスマートフォンのテザリング機能を用いるものです。

部品点数が減るのがメリットですが、送信側のスマートフォンの電池持ちが悪くなるのがデメリットです。


(4)PC+Wifiルーター+スマホ

LinuxなどのUnix系PCにmjpeg streamerというソフトウェアを導入して、UVC対応のUSBカメラの映像をルーター経由で送信します。

様々なカメラを用いることができるのがメリットですが、PCとカメラを有線接続する必要があるため、規模が大きくなるのがデメリットです。

こちらの方法を(ノートPCなどでなく)Raspberry Piで使っている方々がいらっしゃいます。

(5)Raspberry Pi+カメラモジュール

(4)と少し似ていますが、こちらはUSBカメラではなく、Raspberry Pi専用のカメラモジュールを用いる方法です。画質も良いのでお勧めの方法です。下記で解説しています。



性能

stack overflowで公開されているサンプルと、性能改善したSimpleMjpegViewとで性能を比較したのが下記の表です。カメラは「利用形態」の(1)で紹介したTrek Ai-Ballを用いました。解像度640x480、30fpsの映像が送られてきます。

なお、たまたま手元にあった端末が全てカスタムOSが載ったものだったのですが、結果は公式OSでも変わりません。また、OSのバージョンにもあまり依存しないようです。

まず、オリジナルのサンプルから。

stack overflow のサンプル
端末 フレーム数 (fps) 1秒あたりのGC回数 時間遅れ (s)
Nexus 7
OS: 4.2.1, JCROM
15 25 << 1
Galaxy S3 (docomo)
OS: 4.1.2, cm10-based JCROM
17 4 << 1
Galaxy Nexus
OS: 4.2.1, JCROM
16 26 > 1
Xperia Arc
OS: 4.1.2, CM10-based JCROM
17 18 << 1
Nexus S
OS: 4.2.1, JCROM
11 30 > 1

ここで見るべきポイントは以下の通りです。
  • どの端末も、1秒間に多数回のGarbage Collection (GC)が実行される
  • フレーム数はそれほど悪くないが、1秒以上の映像の時間遅れがある端末がある
  • 新しい端末の方が性能が良いとは限らない。最新機種のGalaxy S3の性能が良い一方で、古い端末であるXperia Arcの性能も良い
一方、性能改善したアプリでは下記のようになります。

性能改善したSimpleMjpegView
端末 フレーム数 (fps) 1秒あたりのGC回数 時間遅れ (s)
Nexus 7
OS: 4.2.1, JCROM
17 1 << 1
Galaxy S3 (docomo)
OS: 4.1.2, cm10-based JCROM
17 およそ1/10 << 1
Galaxy Nexus
OS: 4.2.1, JCROM
17 1 << 1
Xperia Arc
OS: 4.1.2, CM10-based JCROM
17 1/4 << 1
Nexus S
OS: 4.2.1, JCROM
17 1 << 1

見るべきポイントは下記の通りです。
  • どの端末もGCの回数は秒間1回以下に改善(性能が良いのはやはりGalaxy S3とXperia Arc)
  • 時間遅れはどの端末でも1秒以下に改善された

端末による性能差

上の表で見た通り、映像表示の性能には端末による差があり、なおかつ新しい端末の方が性能が良いとは限らない、という現象が見られます。

性能改善したSimpleMjpegViewを用いる場合、映像表示するだけならそれほど差は見られませんが、上のプラレールの動画のように、画像処理に基づいて制御を行う場合、微妙な性能差が結果に影響を及ぼすことがあるので注意が必要です。

下記の端末で特に性能が悪かったのが印象的です。
  • Galaxy Nexus
  • Nexus S
上記のプラレールの動画でXperia Arcを用いているのは、古い端末で安価に入手できるにも関わらず映像表示の性能が良いためです。今後、Galaxy S3の価格が下がって入手しやすくなればそちらに乗り換えるかもしれません。

なお、この端末による性能差の原因はわかっていませんが、ハードウェアの違いやkernelのドライバに起因する問題ではないかと現在のところは考えています。

Wifiの干渉についての体験記

このようなWifiカメラの利用法の一つとして、自作のロボットなどに搭載して遊ぶ、というものが考えられます。個人で遊ぶぶんには何の問題もないのですが、大勢の人が集まる展示会でデモしようとすると、Wifiの干渉により映像が遅れるなどして、期待の動作をしないということがあります。

この現象は個人で再現することがなかなか難しく、有効な対策ができない場合が多いのですが、ここでは私が展示会で体験した経験をいくつか紹介したいと思います。

結論から先に述べると、「利用形態」の(3)で紹介した「スマホ(テザリング)+スマホ」が、Wifiの干渉に最も強い組み合わせでした。

2012年10月20日(土)ICT ERA + ABC 2012 東北(Trek Ai-Ball + Xperia Arc, 802.11g)

動画で紹介したプラレールを展示した初めての展示会でしたが、「利用形態」(1)で紹介したWifiカメラ(Trek Ai-Ball)で送信した映像をXperia Arcで受信しました。

この場合、映像が3~5秒くらい遅れて届いたため、画像処理に基づく制御はあきらめ、Bluetooth経由での手動制御を中心に紹介しました。なお、Trek Ai-BallはWifiのチャンネルを手動で変更する機能がついているのですが、それを行っても焼け石に水という感じでした。

2012年12月1日(土)Maker Faire Tokyo 2012 (Xperia Ray + Router + Xperia Arc, 802.11n)

ABC2012東北の約1か月後に行われたMaker Faire Tokyo 2012の初日です。Trek Ai-Ballでの展示はあきらめ、「利用形態」(2)で紹介した「スマホ+ルーター+スマホ」の組み合わせで行いました。

カメラはXperia RayにIP Webcamを入れてWifiカメラ化し、プラレールに搭載します(左図)。ルーターはNECのAtermWR8370N、受信はいつも通りXperia Arcです。

結果はボチボチ、といったところでした。カメラの映像は基本的にはスムーズに届き、画像処理に基づく制御もうまく機能しました。ただしやや不安定で、1~2分おきに映像が届かなくなる現象が起こりました。そんなときはルーターとスマホの位置関係を変えると突然映像が復帰することが多かったので、そのまま展示を続けることができました。

不安定ではありましたが、少なくとも昼から17時までの展示はなんとか乗り切ることができました。

2012年12月2日(日)Maker Faire Tokyo 2012 (Xperia Ray + Xperia Arc, 802.11g)

Maker Faire Tokyo 2012の2日目です。前日と同様に「スマホ+ルーター+スマホ」の組み合わせで行こうとしたのですが、前日と異なり映像が頻繁に途切れてうまく流れません。

想像ですが、恐らく会場では私と同様に2.4GHz帯の無線を使って何かデモをしようとした方が大勢いらっしゃったと思います。初日に無線の干渉の問題でデモに失敗した方が、2日目にリベンジとして別の無線機器を持ち込んだ、ということがあったかもしれません。

いずれにせよ前日の組み合わせではうまくいかなかったので、「利用形態」の(3)で紹介した「スマホ(テザリング)+スマホ」の組み合わせを試してみたところ、(何故か)非常に安定して映像が送受信でき、終日それで乗り切りました。1日目のルーターを噛ませる場合に比べて安定性はかなり上でした。

テザリングを行ったスマホはXperia Rayで、この上でIP Webcamも動作させました。テザリングはdocomoの公式OSでもカスタムOSでも問題なくできます(SIMは刺さずにデモしました)。ただし、当然電池の持ちは悪いので予備バッテリーは必須です。10:00~17:00の展示で、Rayの電池は2回交換したと思います。

Wifi干渉についてのまとめ

以上、展示会3日分の体験を紹介しました。少なくともこの3日間の体験から判断するなら、安定性は「スマホ(テザリング)+スマホ」で決まり、なのですが、もう少し検証をしたい気もします。展示会ほど無線が飛び交う状況をなかなか作れないので、新たに展示会に出展することでしか検証は難しいのですが。

あと、この3日間で用いた無線の規格は802.11gか11nのどちらかです。802.11aを用いたらどうなるだろう、という興味もありますが、この場合、映像の送信側も受信側も802.11aに対応している必要があります。個人的にはXperia SXが小型で11aに対応しているので送信側に適してそうな気がしています。

おしまい

以上、私自身の体験も交えてWifiカメラからのMJPEGストリームをandroidで表示する方法についてまとめてみました。

気が向いたら、画像処理の方法(ピクセルを直接いじる方法、OpenCVを用いる方法)や複数個のカメラからの映像を一つの端末で受信する方法などについても書いてみたいと思います。

こちらもどうぞ

6 件のコメント:

  1. はじめまして。
    私は、無線LANでのリアルタイムで画像を送信する技術に興味があり、上のリンクからダウンロードさせていただき、Eclipseでインポートしてみました。
    そのアプリにボタンを付けたいのですが、activity_main.xmlを使ったことしかないのでやり方がわかりません。

    素人の突然の質問で大変申し訳ないのですが、少しでもヒントをいただけましたら幸いです。
    どうぞよろしくお願いします。

    返信削除
    返信
    1. せっかくなのでレイアウトにxmlを用いる方式に変更してみました。再ダウンロードして試してみてください

      削除
    2. ありがとうございます!
      早速試してみます!

      削除
  2. はじめまして。Raspberry Pi で gstreamer を走らせて Web cam のストリーミングを実験しています。Androidへストリーミングするさいに、SimpleMjpegViewerを改造して利用させていただきました。ありがとうございます。m(__)m
    改造したソースコードを以下にて公開いたしましたが、もし問題がありましたら削除いたします。
    https://bitbucket.org/coisme/simplemjpegview_gst/wiki/Home

    返信削除
  3. 連絡ありがとうございます。ご自由にお使いください。gstreamerは使ったことがなかったのですが、修正が必要なのですね

    返信削除
    返信
    1. ありがとうございます!
      gstreamer から http で配信するには、ひと工夫いるみたいで、それだったらいっそ http を使わなければいいかな、と思って改造した次第です。

      削除