1. 程式人生 > >(一)Android camera2 實現相機預覽及獲取預覽幀資料流

(一)Android camera2 實現相機預覽及獲取預覽幀資料流

一、本文重點說明

  1. 本文基於 android camera2 實現視訊預覽,暫未相容 camera1 API,基礎實現可以參考 googlesample Camera2 例子 android-Camera2Basic ,本文以工具類形式實現一步呼叫。
  2. 谷歌例子中沒有具體指明預覽幀的獲取,即 camera1 setPreviewCallback 類似功能實現,具體是通過 ImageReader 中的 OnImageAvailableListener 來實現的,重點來了,獲取幀資料不能用 ImageFormat.JPEG 格式,否則你會發現預覽非常卡的,因為渲染 JPEG 資料量過大,導致掉幀,所以預覽幀請使用其他編碼格式
    。簡單程式碼如下:
public void init(){
	ImageReader imageReader = ImageReader.newInstance(width, height, ImageFormat.YV12, 1);//預覽資料流最好用非JPEG
	imageReader.setOnImageAvailableListener(new OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
        	Image image =
reader.acquireLatestImage();//最後一幀 //do something int len = image.getPlanes().length; byte[][] bytes = new byte[len][]; int count = 0; for (int i = 0; i < len; i++) { ByteBuffer buffer = image.getPlanes()[i].getBuffer(); int remaining =
buffer.remaining(); byte[] data = new byte[remaining]; byte[] _data = new byte[remaining]; buffer.get(data); System.arraycopy(data, 0, _data, 0, remaining); bytes[i] = _data; count += remaining; } //資料流都在 bytes[][] 中,關於有幾個plane,可以看檢視 ImageUtils.getNumPlanesForFormat(int format); // ... image.close();//一定要關閉 } }, handler); }

到這裡,重點已講完,下面僅僅是我對 Camera2 的封裝,如不需要,可以暫停往下閱讀,節省您的時間。

二、預覽資料流說明

不同編碼的資料通道數不同,具體可以通過 ImageUtils.getNumPlanesForFormat(int format) 檢視,一通道的話一般是包含所有資料,可以通過 Bitmap 直接儲存出一幀的資料,三通道輸出是 YUV 資料,如果要輸出圖片,需要轉碼為 RGB 格式。

三、camera2 API 簡單說明

  1. 說明
    Camera1 區別較大,主要建立會話機制,通過 Session 完成對相機請求操作,更具體的原理說明請使用 csdn 的搜尋功能。流程說明:
    openCamera() -> CameraDevice.StateCallback 中建立 CameraCaptureSession -> CameraCaptureSession.StateCallback 中發起請求。
  2. 工具類使用 CameraUtil,呼叫示例
private CameraUtil cameraUtil;
//初始化,傳入你預覽的控制元件,目前支援 TextureView 暫未支援到 SurfaceView
//如不需要預覽可以傳null
protected void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     TextureView textureView = findViewById(R.id.textureView);
     //自行判斷是否有相機許可權
     //前預覽,後預覽,可共用一個,不需預覽可傳 null
     cameraUtil = new CameraUtil(this, textureView, null);
     //預覽幀獲取
    cameraUtil.setPreviewFrameCallback(new CameraUtil.OnPreviewFrameCallback() {
                @Override
                public void onCameraFront(byte[][] bytes, int orientation) {
                    //前預覽回撥
                }

                @Override
                public void onCameraBack(byte[][] bytes, int orientation) {
					//後預覽回撥
                }

                @Override
                public void onCameraFront(byte[] bytes, int orientation) {
                	//前預覽回撥
                }

                @Override
                public void onCameraBack(byte[] bytes, int orientation) {
                	//後預覽回撥
                }
            });
 }
@Override
protected void onResume() {
    super.onResume();
    //啟動預覽
    cameraUtil.startPreview(this);
}
//在 onPause 或者 onDestroy 中釋放資源
//建議在 onPause 中,因為 onDestroy 中系統已先斷開與相機的連線
@Override
protected void onPause() {
    if (cameraUtil != null) {
        cameraUtil.release();
    }
    super.onPause();
}

介面說明:
這裡的預覽幀回撥主要是兩個,一個前置,一個後置,其中每一個回撥都分兩種,一個是把所有資料用一個byte陣列返回,另一個是各通道區分返回,主要用於 YUV 編碼型別。

四、效果示意圖:

  1. 兩個攝像頭使用同一個 TextureView 顯示
    共用預覽控制元件
  2. 兩個攝像頭使用不同的 TextureView 顯示
    分開預覽
  3. 沒有預覽畫面,通過預覽回撥顯示
    沒有預覽

----對比
TextureView 預覽 + 回撥預覽 GLSurefaceView 直接將 YUV 顯示出來,這裡回撥資料流需要更加感測器方向做旋轉,暫未做完,待 libyuv 庫寫完再更新。這裡的資料回撥顯示,用的是 opneGLGLSurdfaceView直接繪製 YUV 資料,使用的是 李狗蛋52635 的Android上使用OpenGLES2.0顯示YUV資料 可以在這裡檢視
對比

結語

到此本文已結束,目前僅適用 camera2 API,但不夠好,後續會新增更基礎的功能,如拍照、相容 camera1、資料幀方向處理等操作。本文僅僅是做一個總結,希望都對您有所幫助。
下面貼上我的 CameraUtil 類地址,因為還沒完善,所以沒有剝離,暫放在我的 github測試專案中,專案地址 >> 戳我

camera2 >> com.zhou.android.camera2 地址
opengl >> com.zhou.android.opengl 地址

示例 Activity 在 main 包中 CameraUtilTestActivity

說明 包 Package 類Class
相機工具類 com.zhou.android.camera2 CameraUtil
相機配置 com.zhou.android.camera2 CameraConfig
資料回撥介面 com.zhou.android.camera2 OnImageAvailableListener
GL 渲染器 com.zhou.android.opengl GLFrameRenderer
yuv 轉換器 com.zhou.android.opengl GLProgram

不會從github下的話,從 CSDN camera2 這裡下載
opengl 這裡下載

未完,待續