天天看點

【Android】EasyClient與EasyCamera的移植學習EasyCameraEasyCilent

最近公司需求搞視訊監控視訊對講,但個人對視訊這塊基本全無了解。在網上翻了一圈之後,使用EasyDarwin家的源碼做了基礎嘗試。

EasyCamera

首先是移植EasyCamera。既然要移植,當然要分析源碼。

【Android】EasyClient與EasyCamera的移植學習EasyCameraEasyCilent

EasyCamera的主要UI在StreamActivity上,如果是隻是想抓一個視訊界面來用,隻要把這個Activity搬過去就好。不過我的需求是在我自己的項目的界面上進行顯示。是以還要拆分啊。

UI方面的暫且不提。

mMediaStream = new MediaStream(getApplicationContext(), surfaceView.getHolder());
mMediaStream.updateResolution(width, height);
mMediaStream.setDgree(getDgree());
           

以上是初始化一個流媒體

接下來我們看一下它的構造。

public MediaStream(Context context, SurfaceHolder holder) {
        mApplicationContext = context;
        mSurfaceHolderRef = new WeakReference(holder);
        mEasyPusher = new EasyPusher();
        audioStream = new AudioStream(mEasyPusher, null, EasyApplication.aio, EasyApplication.sMainBus);
        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.d(TAG, "kim onReceive: "+intent.getAction());
                mRequestSnapshot = true;
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(MediaStream.ACTION_SNAPSHOT_REQ);
        LocalBroadcastManager.getInstance(mApplicationContext).registerReceiver(mReceiver, filter);
    }
           

其中EasyPusher是直接對接jni方法。對于jni我也全無研究,今後要适當看點資料了。

而AudioStream内提供了一個編碼方法。

回到StreamActivity,再看下一步:

mPusherCallBack = new EasyPusher.OnInitPusherCallback() {
            @Override
            public void onCallback(int code) {
                switch (code) {
                    case CODE.EASY_ACTIVATE_INVALID_KEY:
                        sendMessage("無效Key");
                        break;
                    case CODE.EASY_ACTIVATE_SUCCESS:
                        sendMessage("激活成功");
                        break;
                    case CODE.EASY_PUSH_STATE_CONNECTING:
                        sendMessage("連接配接中");
           

這個功能是什麼就不用多說了吧。

之後注冊的一個廣播也是核心功能。

mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (CommandService.ACTION_START_STREAM.equals(intent.getAction())) {
                     } else if (CommandService.ACTION_STOP_STREAM.equals(intent.getAction())) {
                } else if (CommandService.ACTION_COMMOND_RESTART_THREAD.equals(intent.getAction())) {
            }
        };
           

其中ACTION_START_STREAM内便是開始啟動視訊對接。具體内容請去看源碼。

我需要的功能也很簡單,就是移植。是以把初始化内的内容照原樣搬過去就可以了。不過在搬過去的途中遇到了一個小坑,主要來自于移植所用的SurfaceView

<SurfaceView
        android:id="@+id/sv_surfaceview"
        android:keepScreenOn="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
           

這個SurfaceView在android測試中似乎必須顯示,移出視圖外也不行,若不顯示則在某些機子上會出現對面的Client可以聽見聲音,但是無法觀看視訊的現象。具體原因是什麼我也不知道,如果有知道的大牛希望可以不吝賜教。

EasyClient中的清單與EasyCamera配對的方式主要是通過Serial,是以如果有需求對指定使用者名進行比對的情況,就把這句修改就好了。

public String getDeviceSerial(){
    return InfoSharedPreference.getString(this , Config.device_serial_key);
}
           

EasyCilent

下一步是移植EasyClient。

移植EasyClient的途中沒遇上太多坑,還算是比較順利的。公司需求是點選使用者的監視按鈕,則對已開啟EasyCamera的使用者進行監視。

EasyClient中我主要使用的就是

【Android】EasyClient與EasyCamera的移植學習EasyCameraEasyCilent

EasyPlayerActivity這個activity。原樣搬過去基本就可以了,當然途中若修改了包名,則需要去官方申請一個key值。

  • 注意申請時填寫的必須是ApplicationID而不是包名。

key替換在這裡。

private void startRending(Surface surface) {
        mStreamRender = new EasyRTSPClient(this, "79393674363536526D3432413254315A7073496D4A655A76636D63755A57467A65575268636E64706269356C59584E35593278705A573530567778576F502B6C34456468646D6C754A6B4A68596D397A595541794D4445325257467A65555268636E6470626C526C5957316C59584E35", surface, mResultReceiver);
        Log.i("SpeedTalk" , "Url>>>" + mRTSPUrl + ",TCP>>" + RTSPClient.TRANSTYPE_TCP);
        mStreamRender.start(mRTSPUrl, RTSPClient.TRANSTYPE_TCP, RTSPClient.EASY_SDK_VIDEO_FRAME_FLAG | RTSPClient.EASY_SDK_AUDIO_FRAME_FLAG, "admin", "admin");
    }
           

在點選打開這個Activity之前,還需要對已開啟EasyCamera的使用者進行一個查詢。

查詢的代碼在CameraFragment中,首頁的三個碎片都是繼承自這個界面的,隻需要替換

protected String mType = "ARM_Linux";

就可以進行切換。

MyApplication.asyncGet(url, new CallbackWrapper<DeviceListBody>(DeviceListBody.class) {
            @Override
            public void onBefore(Request request) {
                mSwipeRefreshLayout.setRefreshing(false);
                activity.showWaitProgress("");
            }
            @Override
            public void onAfter() {
                activity.hideWaitProgress();
            }
            @Override
            public void onError(Call call, Exception e) {
                Toast.makeText(mContext, "onError:" + e.toString(), Toast.LENGTH_LONG).show();
            }
            @Override
            public void onResponse(DeviceListBody body) {
                List<DeviceListBody.Device> devices = body.getDevices();
                if (devices.size() == ) {
                    activity.showToadMessage("暫無直播資訊");
                    liveVOAdapter = new OnlineCameraAdapter(new ArrayList<DeviceListBody.Device>());
                } else {
                    liveVOAdapter = new OnlineCameraAdapter(devices);
                    int screenW = mContext.getResources().getDisplayMetrics().widthPixels;
                    int columnum = mGrid_live.getNumColumns();
                    int space = (int) (mContext.getResources().getDimension(R.dimen.gridview_horizontalspacing));
                    int itemWidth = (int) ((screenW - (columnum - ) * space) / columnum);
                    int itemHeight = getItemHeight(itemWidth);
                    liveVOAdapter.setmSnapshotWidth(itemWidth);
                    liveVOAdapter.setmSnapshotHeight(itemHeight);
                    //                    int screenW = mContext.getResources().getDisplayMetrics().widthPixels;
//                    int columnum = mGrid_live.getNumColumns();
//                    int space = (int)(mContext.getResources().getDimension(R.dimen.gridview_horizontalspacing));
//                    int itemWidth = (int)((screenW-(columnum-1)*space)/columnum);
//                    int itemHeight = (int) (itemWidth * 4 / 3.0 + 0.5f);
//                    liveVOAdapter.setmSnapshotWidth(itemWidth);
//                    liveVOAdapter.setmSnapshotHeight(itemHeight);
                }
                mGrid_live.setAdapter(liveVOAdapter);
            }
        });
           

上面的onResponse就是進行了直播清單查詢的相關方法。在使用時隻需要原樣替換就好。

移植兩邊之後,就可以進行正常的監視操作了。至于實作對講,還在繼續研究。至少這個案例當兩邊同時監聽的時候,Android端會崩潰。

EasyDarwin這個平台稍微有點不穩定,後續需要調整的部分估計有不少。

上個官網源碼。

https://github.com/EasyDarwin