脳汁portal

アメリカ在住(だった)新米エンジニアがその日学んだIT知識を書き綴るブログ

mjpg-streamerでraspberryPiのカメラからストリーミングをする方法

以下のサイトを参考にさせて頂いてraspberryPiのカメラでストリーミングを行えるようにしました
neuralassemblyのメモ: Raspberry Pi用カメラモジュールおよび赤外線カメラPi NoIRの映像をandroidで表示してみた

1. カメラの接続

まずは何はともあれカメラを接続します。
場所は基盤に「CAMERA」と書いてあるのですぐわかると思います。
f:id:portaltan:20161129184618p:plain

2. cameraの有効化

カメラは接続しただけでは有効化されていないので、raspi-configから有効化します

sudo raspi-config

以下のような設定用の画面が出てくるので、6の[Enable Camera]を選択します
f:id:portaltan:20161129182803p:plain

カメラを有効化するかどうか聞かれるのでYesを選択します
f:id:portaltan:20161129182856p:plain

無事有効化できたら確認の画面が出た後に、再起動するか聞かれるので一応再起動しておきましょう

3. mjpg-streamerのinstall

streamingソフトのmjpg-streamerをinstallします

### download
$ cd ~
$ git clone https://github.com/jacksonliam/mjpg-streamer.git mjpg-streamer

### install
$ cd mjpg-streamer/mjpg-streamer-experimental
$ sudo apt-get install libjpeg8-dev cmake
$ make
$ cd ../../
$ sudo mv mjpg-streamer/mjpg-streamer-experimental /opt/mjpg-streamer

### 起動
$ LD_LIBRARY_PATH=/opt/mjpg-streamer/ /opt/mjpg-streamer/mjpg_streamer -i "input_raspicam.so" -o "output_http.so -p 9000 -w /opt/mjpg-streamer/www"

以上でストリーミングがはじまります。

http://${IP}:9000にアクセスすると以下のようにmjpg-streamerのroot pageが表示されます
f:id:portaltan:20161129184138p:plain
左にあるタブを選択することで、Staticでその画像、Streamでストリーミング映像が表示されます

4. オプションの設定

input_raspicam.soにオプションを指定することで色々と条件を変更することができます

### for input_raspicam.so option
-fps  # FPS
-q    # set JPEG quality 0-100, default 85
-x    # width of frame capture, default 640
-y    # height of frame capture, default 480
-br   # Set image brightness (0 to 100)
-ex   # Set exposure mode (see raspistill notes)
-mm   # Set metering mode (see raspistill note)

RaspberryPi3 初期設定

RaspberryPi3にraspbianをinstallして初期設定を行う方法です

1. SDカードをいれて、ケーブル等をつなぐ

SDカードにraspbianのimageをいれて、SDスロットにさし、電源ケーブルに繋ぎます
この時点でraspberryPiの装備は

  • raspberry Pi3
  • SDカード(raspbian image)
  • LANケーブル
  • USBキーボード
  • USBマウス
  • HDMIケーブル(to ディスプレイ)

2. 電源を入れる

電源をいれるのは簡単で、基盤の「PWR IN」というところにmicroUSBの電源ケーブルをさせば電源が入ります
あとは自動でinstallや設定が行われて、以下のようなraspbianのGUIが表示されます
f:id:portaltan:20161129154428j:plain

3. ネットワークの確認

GUIからコンソールを開いてネットワークを確認します

割り振られたIPの確認
pi@raspberrypi:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr b8:27:eb:c2:b2:c8
          inet addr:192.168.11.22  Bcast:192.168.11.255  Mask:255.255.255.0
          inet6 addr: aa80::bb65:cc31:dd5:20/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:13522 errors:0 dropped:8 overruns:0 frame:0
          TX packets:3058 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:16528566 (15.7 MiB)  TX bytes:274511 (268.0 KiB)

lo        Link encap:Local Loopback
          .
          .
          .

wlan0     Link encap:Ethernet  HWaddr a8:b7:cb:d7:e7:fd
          .
          .
          .

上記のeth0のipアドレスを利用することで、同じネットワーク内のPCからraspberryPiへアクセスすることができます
(上記では192.168.11.22)

アクセスできない場合はeth0の設定を見てみる
pi@raspberrypi:~$ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

iface eth0 inet manual   ### staticとかになってないか確認

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

4. 他のPCからログイン

teratermとかからログインしてみる
デフォルトのログイン情報は

  • id: pi
  • pass: raspberry

5. 個人環境の設定

vimとかtimezoneとかaliasとか設定する

以上でRaspberryPiのinstall完了
f:id:portaltan:20161129160715j:plain

AVPro Videoで映像の再生ができなくなった時の調査したことまとめ

何もしてないのにこわれた!!()

ということでOculus Rift向けの動画アプリをUnityで作っていたのですが、急に動かなくなりました。
具体的には音声は聞こえるものの、映像は白一色で何も見えません。
Unityのシミュレータだけではなく、以前ビルドしたアプリも同様に見えなくなっていました。

環境

Unity: 5.3.6p1
Oculus Utilities: v1.7.0
asset: AVPro Video(Windows)
decoder: LAV Filters
movie format: H.264(mp4)
resolution: 4K

調査

わかってしまってからだから言える事ですが、大分遠回りしています

1から作り直してみた

create projectから作成しなおしてみた
f:id:portaltan:20161101160740j:plain

  • シミュレータでは動くようになったが、今度はRiftではずっとloading中で確認すらできなくなった
  • 再起動するとRiftから確認が出来るようになったが、前と同じく白一色で映像は表示されず

しかし一点気になったのはAVProVideo(Windows)がまさに今日11/1にupdateしている点
AVProVideo側に問題があるのか・・・?

AVProVideo側からアプローチしてみた

hardware decoringのチェックを外してみた

 動いた!けど当然高解像度の動画を再生するとガックガクになった
f:id:portaltan:20161101160740j:plain

AVProVideoの無料試用版を使ってみた

 動いた!けど当然WaterMarkが出現した
f:id:portaltan:20161101160740j:plain
 

  • この無料試用版はAsset Storeではなく、HPから直接unitypackageファイルをダウンロードしてきて、それをcustom importで取り込む形
  • ちゃんと見てないけどたぶんこれはversion upに対応していちいちupdateはされていないんじゃなかろうか?

過去のavpro videoが動くということは、最新のavpro videoのUnityやutiliesに対する依存性に変更があったのかも・・・?

Unityのversionをあげてみた

現在の安定版最新のv5.4.2で試してみた

f:id:portaltan:20161101160740j:plain

5.3系最新パッチのv5.3.6p8で試してみた

f:id:portaltan:20161101160740j:plain

Utilityのversionをあげてみた

1.7.0から最新の1.8.0にあげてみた

 f:id:portaltan:20161101160740j:plain

decorderを変更してみた

f:id:portaltan:20161102165817p:plain

LAV Filter

f:id:portaltan:20161101160740j:plain

default

f:id:portaltan:20161101160740j:plain

Oculus appをdowngradeしてみた(かった)

色々見ていると、Oculus Appの最新version(1.9.0)が2016/10/19にリリースされておいることに気づいた
現在更新の設定がデフォルト(自動update)になっていたため既に1.9.0になっていた

以前確認して、完全に動いているのを確認したのは2週間前くらい・・・怪しい・・・

とりあえずは1.8.0にダウングレード
  • しようとしたけど方法がわからない
    • PC SDKがそれにあてはまると思っていたのだがどうも違うっぽい。
    • Oculus AppはSetupツール上でダウンロードするんだけど、それだと最新版がダウンロードされてしまう。
    • 古いversionのsetupツールも提供されていない
    • どっかのconfigファイルとかで指定できるんだろうか・・・

f:id:portaltan:20161101160931j:plain

そういやOculus appだけじゃなくてWindows Updateも走ってたな・・・

Windows Updateの履歴を確認してみた

つい最近Updateされていることを確認

他のしばらく起動していないPCで確認してみた

動いた!
f:id:portaltan:20161101161214j:plain

Windows Updateが原因なのか・・・

再度AVProVideoの設定をいじってみる

前回Hardware Decordingのチェックを外したら動くことまでは確認したが、今回はdecorderの選択をDirectShowに変更してみた
f:id:portaltan:20161102102805p:plain

動いた・・・

ちなみに以前の設定はこちら
f:id:portaltan:20161102102835p:plain

  • 前はこの設定で動いていたのだが、設定としては今回の設定の方が正しい気がする

(なんで黄色くなったの?ねぇなんで?)

これで解決と思いきや

1からアプリを動画アプリを作成してcodecもdirectshowにした
f:id:portaltan:20161101160740j:plain

辛い・・・
 f:id:portaltan:20161101161120j:plain


とりあえず以前のアプリは動くようになったので一旦置いておこう・・・
検証十分じゃないし・・・
今日新versionでたばっかだし・・・

今は動いてるし・・・

まとめると・・・

推測ですが、

  • AVProVideo(無印)からAVProVideo(Windows)に変えた際にForceDirectShowのチェック項目がなかったので、Windows環境専用のこのassetではデフォルトでDirectShowが使用されていると思っていた
  • だけど実際はデフォルトではmediafoundationを利用していた。以前はこのAPI(decorder)でも偶然再生できたため、違いに気付かなかった
  • しかしWindows updateでcodecに変更が入り、AVPro経由ではmedia foundationで再生できなくなった
  • ここで設定を確認しなおすとDirectShowを利用する場合は明示的にVideoAPIの項目を変更しないといけないことに気づく
  • 変更したところAVPro Video(無印)のときと同じ再生フローになり、正常に再生されるようになった

f:id:portaltan:20161101161502j:plain

HMDスペックまとめ(Oculus Rift CV1/GearVR/HTC Vive/PSVR)

簡単に調べた各HMDのスペック表です。

Oculus Rift CV1 GearVR
(Galaxy S7 Edge)
HTC Vive PSVR
HMD解像度 2160×1200 2560×1440 2160×1200 1920×1080
端末再生可能解像度 PC依存 4k(3840 x 2160) PC依存 4k(PS4 Pro)
リフレッシュレート 90Hz 60(fps) 90Hz 120Hz
視野角 110度 96度 110度 100度
重量 475g(318g + 157g) 555g 610g
発売価格 $599 $99 $799 $399

GPGPU用語集てきなもの

備忘録

CNN

BLAS

ATLAS

  • Automatically Tuned Linear Algebra Software
  • 自動で最適化されたBLASライブラリを作成するオープンソースライブラリ

OpenBLAS

MKL

  • Intel製CPUに最適化されたライブラリ
  • ライセンス購入をする必要がある
  • Intel製のCPU環境ではATLASよりもパフォーマンスがいいらしい(Intel側のレポート)

OpenCV

  • Computer Visionのためのライブラリ
  • 画像の入出力や一部を切り抜く際などに利用されている

LevelDB

  • KVS
  • DB内部でよくアクセスされるデータを段階的に分けることでアクセス効率がよくなる
  • Caffeでは学習データおよび評価データをそれぞれ一つのDBにまとめてから、それを利用してモデルの学習を行う

LMDB

  • KVS
  • LevelDBでは内部のデータにアクセスする際にロックがかかる仕様になっているため、複数のCaffeプロセスが単一のDBにアクセスすることが出来ない
  • この問題を解決するために単一のDBへの同時アクセスできるLMDBが導入された

HDF5

  • 大量の数値データをほぞんすることに適したファイルフォーマットとそれを操作する機能を提供するライブラリ

Blob

  • Binary Large OBject

MPI

  • Message Passing Interface
  • 分散メモリ間のメッセージ通信APIの規格
  • 実装でメジャーなものとしてOpen MPI とmpichがある

GPUDirect

  • CUDAを使ってGPUと同じバスに繋がっている(他のGPUを含む)デバイスに対して、GPUから直接アクセスする技術
  • CPUを経由しない高速なデータ転送が実現でき、GPU間のデータ同期やネットワークデバイスを使った他のノードとの通信を効率的に行うことが出来る
  • この技術を使ったGPU間の直接データ転送をPeerアクセスと呼ぶ
  • Peerアクセスを使うことで、他のGPUで割り当てたデバイスメモリに対して、カーネルやcudaMemcpy系の関数で、直接アクセスすることができるようになる
  • teslaとQuadroのみのプレミアム機能(GeForceでは使えたという報告もあるが要確認)

RDMA

RDMAとは

Remote Direct Memory Access
DMA(Direct Memory Access)はCPUが介在することなくホストメモリへアクセスを行うデバイスの機能
RDMA(Remote DMA)はCPUが関与することなくネットワーク越しにリモート計算機上のメモリへアクセスする機能

RDMAをサポートするネットワークプロトコル
  • InfiniBand
    • はじめからRDMAをネイティブサポートする新世代ネットワークプロトコル
    • 対応のNIC(HCA: Host Channel Adapter)とスイッチが必要となる
  • RoCE
  • iWARP
RDMAを使うには?

LInuxの主要なDistributionでRDMAをサポートしている

NVIDIA GPUDirect RDMA

f:id:portaltan:20161014215950p:plain

GPU tip

Tesla and Quadro-class GPUSで使える

messaging system

open MPIとMVAPICH2がGPUDirectをサポートしている(CUDA-aware MPI経由で)

Environment

Infiniband

infinibandとは非常に高いRAS(信頼性・可用性・保守性)をもつI/Oバスアーキテクチャ及びインターコネクトのこと
f:id:portaltan:20161014220038j:plain

  • オープンスタンダードなインターコネクト・プロトコル
  • 広帯域・低レイテンシ・高RAS
  • HPC/エンタープライズデータセンタ/高い画像処理能力を必要とする医療機器や検査装置などで使用されている

確認方法

Unityのmetaファイルが持つguidを変更する

前提

  • Unityでは各ファイルに対してメタファイルが自動で生成される
  • このmetaファイルの中でguidというパラメータが設定されている
  • 他のオブジェクトとの相関性などは、ファイル名ではなくこのguidをもとにして行われている
fileFormatVersion: 2
guid: 14f9hogehogehogehogefugaugasdfd7fc21a  //<== これ
timeCreated: 1467869181
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 

問題

  • スクリプトリファクタリングをするときなど、適当な名前のファイルとしてコピーし、後で同名ファイルを削除して置き換えるというようなことをした場合、ファイル名は同じだが生成されたmetaファイルのguidが異なるので、他のオブジェクトとの関連性がリセットされてしまっている。
  • もう一つ問題として、パッケージをexportして別プロジェクトへimportする場合があるが、このとき同じguidが使われていると全く別のファイルにも関わらず同じguidのオブジェクトが上書きされてしまう

解決方法

  • 上の方の問題に関してはそもそも該当のファイルを直接編集すればいいが、下のimport問題が少しやっかいで、この場合ファイルのguidを変えてやる必要がある
guidの変更
  • 試しにmetaファイルを削除してUnityを起動してみたところ、新しく新規にmetaファイルが作成されたのでいけるかと思ったが、まさかの消したはずのguidと同じguidが再度生成されていた。
  • なので現在は少し強引ではあるが、Duplicateで同じファイルを作成し(この時点で違うguidをもつmetaファイルが生成される)、これをもとにパッケージをexportすることにしている。
  • もちろんmetaファイルを直接編集してもいいのだが、低い確率で他のファイルが既に利用しているguidにしてしまった場合、問題の発見が困難になってしまう
    • DuplicateだとUnityの機能で行うので、Unityが重複のないguidをアサインしてくれる

他にいい方法があるような気がしないでもない・・・

Android端末で初回起動時にStreamingAssetsからPersistentDataディレクトリにデータをコピーする方法

UnityでStreamingAssetsに配置したファイルはアプリコンパイル時にも圧縮されないため、必要な情報の保存に利用できる。
しかしこのStreamingAssetsはアプリ内にStreamingAssetsという名前のディレクトリが作成されるわけではなく、いわゆるシムリンク的なもので、デバイス毎にどこに保存されるかは異なる。
その中でもAndroidの場合が少し曲者で、AndroidのStreamingAssets上のファイルはReadはできるがWriteができない。
なので通常は初回起動時にStreamingAssetsからPersistentDataディレクトリへファイルをコピーし、二回目以降はそちらを読み書きして使う方法がメジャーとなっている。

void Start(){
    if (!File.Exists (Application.persistentDataPath + "/" + filename)) {
        FileCopyFromStreamingToPersistent();
    }
}
  • 目的のファイルがpersistentDataディレクトリにない場合は初回起動とみなしてファイルをコピーする
void FileCopyFromStreamingToPersistent(){
	string path = Application.streamingAssetsPath + "/" + filename;
	WWW www = new WWW (path);
	while (!www.isDone) {
	}
	string toPath = Application.persistentDataPath + "/" + filename;
	File.WriteAllBytes (toPath, www.bytes);
}
  • 実際にコピーをするメソッドはこちら