RK Android使用的是标准的 Camera HAL3框架,可以支持android下标准的摄像头编程方式,如camera2,这个摄像头默认被系统占用。
YY3588上有两组CSI接口,默认适配GC8034摄像头模组,接线如下
下面介绍如何使用Camera2框架实现视频预览。
在第一章节创建的app基础上,增加一个按钮和一个视频预览窗口textureView,进行画面预览。
在 onCreate 中添加按钮的逻辑,按下按钮执行 toggleCameraPreview 开启或停止摄像头预览
button4.setText("Start Preview");
button4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textDisplay.setText("start camera test... \n");
toggleCameraPreview();
}
});
下面代码中,使用 toggleCameraPreview ,在按钮按下时,开启或关闭摄像头预览。
其中 startCameraPreview 判断当前 textureView 是否可用,如果不可用时创建一个 Listener ,当可用时触发回调,回调中执行 openCamera 。可用时直接执行 openCamera
openCamera 中打开后置摄像头,并设置一个 stateCallback ,在回调中,摄像头打开完毕后,执行 createCameraPreview,将摄像头的画面更新到TextureView。其中这个更新是放到一个名为 CameraBackground 的线程中进行。在app的pause和resume时会停止和开启这个线程。
private void toggleCameraPreview() {
if (isPreviewing) {
stopCameraPreview();
button4.setText("Start Preview");
textureView.setVisibility(View.INVISIBLE);
} else {
startCameraPreview();
button4.setText("Stop Preview");
textureView.setVisibility(View.VISIBLE);
}
}
private void startCameraPreview() {
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(surfaceTextureListener);
}
}
private void stopCameraPreview() {
if (cameraCaptureSession != null) {
cameraCaptureSession.close();
cameraCaptureSession = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
isPreviewing = false;
}
private final TextureView.SurfaceTextureListener surfaceTextureListener =
new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// 处理纹理视图大小变化
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = manager.getCameraIdList()[0]; // 使用后置摄像头
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// 设置预览尺寸
previewSize = new Size(600, 300);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
isPreviewing = true;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
cameraDevice.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
private void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (cameraDevice == null) {
return;
}
cameraCaptureSession = session;
updatePreview();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(MainActivity.this, "Configuration failed",
Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if (cameraDevice == null) {
return;
}
try {
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,
CaptureRequest.CONTROL_MODE_AUTO);
cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(),
null, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
startCameraBackgroundThread();
}
@Override
protected void onPause() {
stopCameraPreview();
stopCameraBackgroundThread();
super.onPause();
}
private void startCameraBackgroundThread() {
backgroundThread = new HandlerThread("CameraBackground");
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
}
private void stopCameraBackgroundThread() {
if (backgroundThread != null) {
backgroundThread.quitSafely();
try {
backgroundThread.join();
backgroundThread = null;
backgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此外,要使用camera2的api,需要在 AndroidManifest.xml 中添加
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.any" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
此app运行效果如下,可以看到按下 Start Preview 按钮后 textureView 出现摄像头画面
按下 Stop Preview 摄像头画面消失