2013年10月20日日曜日

android(SimpleMjpegView)でwebcamからのストリーミングを見たときのメモ

休日2日(18時間程度)つぶしてどうにかウェブカメラ映像をタブレット上で見れるようになってのでその際のメモ、公開されているライブラリを取り込んだだけだが・・・

一応ライブラリ(SimpleMjpegView)のライセンスに基づく告知

This software is based in part on the work of the Independent JPEG Group.
Moreover, for decoding MJPEG, some codes in OpenCV are utilized.
Therefore, before downloading, you have to agree to the following license.
//////////////////////////////////////////////////////////////////////////////////
IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
By downloading, copying, installing or using the software you agree to this license.
If you do not agree to this license, do not download, install,
copy or use the software.
                    Intel License Agreement

            For Open Source Computer Vision Library
Copyright (C) 2000, Intel Corporation, all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
  • Redistribution's of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
  • Redistribution's in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
  • The name of Intel Corporation may not be used to endorse or promote products
    derived from this software without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall the Intel Corporation or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.

 ライセンス告知ここまで


参考文献:
1、 neuralassemblyのメモ 様:
http://neuralassembly.blogspot.jp/2012/12/androidwifimjpeg.html
今回はTakashi Kanamaru 氏が公開されているありがたいライブラリ「SimpleMjpegView」を自分のプロジェクトに使う。
 
2、yahoo知恵袋 Android NDKを使った開発環境の構築
http://note.chiebukuro.yahoo.co.jp/detail/n136598
今回の話は実質的にNDKに関するものなので重要。


・今回の目的 : 自作androidアプリに(ゲームボーイ的な感じで)ウェブカメラからのリアルタイム映像を映す

・手法 : 数日粘ったが自分の手には負えそうも無かったので参考文献1のライブラリを利用させて頂くことに

・利用させて頂き方 : 
※事前にNDKが使える状態になっていること

1、 https://bitbucket.org/neuralassembly/simplemjpegview からライブラリをダウンロード、展開→eclipseへプロジェクトをインポート

2、インポートしたプロジェクトが正常に動く(ウェブカメラのストリーミングが見られること)ことを確認する


3、問題なければMjpegView.java と MjpegInputStream.javaを自分のプロジェクトのsrcにコピー。jniフォルダもコピー(自分は他にndkを使っていなかったから問題なかったが自作ndkがある場合はmakeファイル内容などを上手くマージしたりする必要があるかもしれない)

4、 コマンドプロンプトで自分のプロジェクトのフォルダに移動(cd (プロジェクトフォルダパス))して「C:\\android_ndk\\android-ndk\\ndk-build.cmd(筆者の場合)」を実行。要はjniフォルダ内のcファイルをビルドする。旧バージョンだとcygwinからやらないといけないようだが参考文献1のリンクなどを参照のこと

※重要 : ここで半日詰まった。参考文献2にもあるがjniフォルダ内のcファイルとヘッダファイル内の一部を自分のプロジェクト名に(規則にのっとって)改名する必要がある。↓
「JavaとC/C++(或いはその他の言語)によるプログラムの間で相互に連携をするためには、JNI(Java Native Interface)という仕様に沿う必要があります。この仕様では、C/C++側の関数名は頭にJava_を付け、その後ろにパッケージ名、クラス名、 メソッド名を並べ、ドットをアンダーバーに置き換えた名前にします。」(参考文献2より引用)

コピーしてきた時点でcファイルとヘッダファイル内の関数名はインポートしたSimpleMjpegViewプロジェクトのパッケージになっているので自分のパッケージ名にすべて変更する。これをしないとリンクエラーが発生する(そんなnativeメソッド無いよ。というエラーが発生する)。まとめて変更するための情報が参考文献2にあるが今回は手動で変換した

5、インポートしたプロジェクト内のMjpegActivity.javaのソースを参考に必要な部分を自分のライブラリに書き足す。最低限以下の部分をコピペすれば動作はする(ポーズなどで落ちるが)
5-1 onCreate内
     mv =(MjpegView) findViewById(R.id.mjpegView1);
         if(mv != null){
                mv.setResolution(640,480);
            }
            new DoRead().execute(URL);

 5-2 activityクラス内、onCreateなどと並列に
    public class DoRead extends AsyncTask<String, Void, MjpegInputStream> {
        protected MjpegInputStream doInBackground(String... url) {
            //TODO: if camera has authentication deal with it and don't just not work
            HttpResponse res = null;
            DefaultHttpClient httpclient = new DefaultHttpClient();
            HttpParams httpParams = httpclient.getParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, 5*1000);
            Log.d(TAG, "1. Sending http request");
            try {
                res = httpclient.execute(new HttpGet(URI.create(url[0])));
                Log.d(TAG, "2. Request finished, status = " + res.getStatusLine().getStatusCode());
                if(res.getStatusLine().getStatusCode()==401){
                    //You must turn off camera User Access Control before this will work
                    return null;
                }
                return new MjpegInputStream(res.getEntity().getContent());
            } catch (ClientProtocolException e) {
                e.printStackTrace();
                Log.d(TAG, "Request failed-ClientProtocolException", e);
                //Error connecting to camera
            } catch (IOException e) {
                e.printStackTrace();
                Log.d(TAG, "Request failed-IOException", e);
                //Error connecting to camera
            }
            return null;
        }

        protected void onPostExecute(MjpegInputStream result) {
            mv.setSource(result);
            if(result!=null) result.setSkip(1);
            mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
            mv.showFps(false);
        }
    }


結果:
そりゃあ所詮無線のカメラなので若干のラグはあるがかなりスムーズ。Takashi Kanamaru 氏は間違いなく神



以上。結局NDKの基本的なところが全くわかっていなかったのが時間をとった原因だったり・・・



0 件のコメント:

コメントを投稿