[Oculus]3D動画をストリーミング再生する方法 – 13 –

前回は、Socket.IOの速度改善についてご紹介しました。
今回は、現状のボトルネックを調査するためにクライアント・サーバーの処理時間を測定しました。

まず初めに、今のクライアント・サーバーの処理の流れを簡単に説明いたします。
詳細を知りたい方は、過去の記事でご紹介しているため、そちらをご覧下さい。

クライアント
1.カメラプレビューを使用してフレーム毎のデータを取得
2.取得したデータ(YUV形式)をRGB形式に変換
3.RGB形式データからBitmapを生成
4.BitmapをJPEG圧縮
5.BitmapをBase64データへエンコード
6.htmlのformにデータとして設定
7.サーバーへアップロード

サーバー
1.アップロードされた画像を保存
 ※一定量の画像が用意できるまで待機
2.一定量の画像が用意できたタイミングで、ffmpegを使用し動画を生成

上記工程が現在の構成の大まかなフローとなります。
この構成を使用して測定した結果が、次の表です。

■クライアント側処理

■サーバー側処理

使用した解像度は512×384と640×480の2種類で、両方ともアスペクト比は4:3になります。
数値化すると一目瞭然で、画像処理に時間がかかっていることがわかります。
その中でもBitmapの生成が一番処理が重いようです。

測定した中で一番負荷が軽い(解像度が低く、fpsが低い)ものでも、1秒分の画像を作成するのに、1秒以上の時間がかかっています。
現在のプログラムでは、記載した工程に含まれていない箇所で少し特殊な処理を行い、この数値でもある程度スムーズに表示することができていますが
それにも限界があるため、今の処理構成のままでは、品質・パフォーマンス向上は望めません。
また、現時点では未だ触れておりませんが、後に控える音声データの合成を考えると
さらに処理の負荷が上がるため、今以上のパフォーマンスが必要となってきます。

一般的に、アニメや映画等の映像データは24fps+音声データが共通規格となっているため、
そこを目標とした場合でも、前回達成した20fpsから更に+4fpsと音声処理分の負荷に耐える作りにする必要があります。

改善策として、今回ピクセルフォーマットはRGBA_8888を使用しているため
RGB_565やRGBA_4444に変更することで負荷軽減は見込むことができますが
画像品質が落ちてしまうため、いい選択肢とはいえません。
使用する画像圧縮形式も、動画作成が目的であり透過情報が必要ないことから
JPEGがベストな選択肢だと考えられます。

では、どのように改善するかということが問題になってきますが
この場合は、JNIを使用することで大幅な改善が期待できます。

過去の記事でもご紹介しましたが、JNIというのはJavaからネイティブ言語(※1)を扱う際に使用するものです。
スマートフォンアプリ業界では、HTMLやJavaScriptで作成されたWebアプリに対比する言葉として
Java/Objective-Cで作成しているアプリをネイティブアプリといいますが、本記事内に記述する「ネイティブ」は
IT業界内で昔から言われている「機械語プログラムを作成出来る言語」を指しています。
※1.今回使用する言語はC/C++

皆さんご存知かと思いますが、Java言語をビルドして出来上がるのは中間言語であり機械語ではないため
中間言語を解釈する仮想マシンのやりとりが発生する分、どうしても処理速度が遅くなってしまいます。
しかし、JNIを使用するとその先の処理はネイティブ言語で書かれたものであるため
すべての処理をJava言語で書いた場合に比べて、格段に速くなります。

多くの開発者がAndroidの画像処理をJNIを使用する方法に変更することで、速度向上を図っていることから
この問題点についてもネイティブ言語への処理移行をすることで、改善をしていこうと思います。

JNIを使用する形に変更した場合、記載したクライアント工程の内、ネイティブ言語へ移行する箇所は2~5で
Java側で必要となる処理は、プレビュー表示と通信処理となります。
前々回の記事でも同じことを書いていますが、通信処理自体もネイティブ言語へ移行することが出来ると
「Java→Web→サーバー」と行っている処理も「ネイティブ言語→サーバー」にすることができるため、更なる通信速度改善が見込めます。

先ほどから、パフォーマンスの向上ばかりをメリットとして書いてきましたが
ネイティブ言語を使用するメリットは他にもあります。
例えば、音声処理もネイティブ言語で行うことで
クライアントで必要となる処理のほとんどをネイティブに委託することができるため
iOS版のクライアントを作成しようとした際に、主要となる処理の全てが流用出来るということです。

他にも、openCVという画像・動画の処理を行うためのc++言語ライブラリも扱えるため
単純にリアルタイム配信をするというだけではなく、配信する動画にちょっとした加工を加える等のオプション機能もつけやすくなります。
openCVには、Java,Android用のライブラリも公開されていますが、iOSへのソースコード流用を考えるとc++を利用したほうがメリットが大きいです。

ただ、メリットがある分デメリットもあり主に以下のような点が考えられます。
・メモリ管理が必要
・プラットフォームに依存
・デバッグがしづらい

しかし、これらの問題は正しい環境構築や事前の設計を行うことで回避できるため、メリットのほうが大きいと私は思います。
メモリは、解放漏れがないように注意してコーディングを行うことはもちろんですが
解放漏れを忘れた場合を考慮して、あらかじめメモリ管理するしくみを設計することで、問題が発生する可能性を下げることができます。
プラットフォーム依存は、ターゲットを定めることで、それらのプラットフォームに合わせてコンパイルすれば良いですし
デバッグ環境も、事前に使用するIDEやプログラミング環境を構築しておけば、以降は通常のプログラミングと変わりません。

このようにネイティブ言語を使用することで起こるデメリットも初めに少し手間をかけて準備するだけで
なくすことができるため、パフォーマンス向上を目的とした場合は、十分に使用するメリットがあります。

JNIを使用したネイティブ言語化についてご紹介しましたが
外部のハードウェアと連携することでスマホ側の負荷を下げることができれば、それも十分なパフォーマンス改善であるため
今後は、ソフトによる改善のみではなく、いろいろな側面から改善を試みていきたいと思います。


弊社では全国各地の請負い(ご自宅)で作業協力頂ける、フリーランスエンジニアの方を常時探しております。
ご興味ある方は、お気軽にお問い合わせ下さい。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*