Android Camera2 是 Android 系统中用于相机操作的一套高级应用程序接口(API),它取代了之前的 Camera API。以下是关于 Android Camera2 的一些主要信息:
Context.getSystemService(Context.CAMERA_SERVICE)
方法来获取 CameraManager。openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)
方法打开指定的摄像头。其中,cameraId
是要打开的摄像头的标识符,callback
用于监听摄像头的状态变化,handler
表示执行回调的线程。CameraDevice.createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)
方法创建 CameraCaptureSession。outputs
是一个包含所有需要从该摄像头获取图片的 Surface
的列表,callback
用于监听会话的创建过程,handler
表示执行回调的线程。CameraDevice.createCaptureRequest(int templateType)
方法创建 CaptureRequest.Builder
,其中 templateType
可以是 TEMPLATE_PREVIEW
(预览)、TEMPLATE_RECORD
(拍摄视频)、TEMPLATE_STILL_CAPTURE
(拍照)等。然后使用 CaptureRequest.Builder
设置拍照的各种参数。CameraCaptureSession.setRepeatingRequest()
方法开始预览,或调用 capture()
方法进行拍照。拍照的优先级比预览的优先级高,如果需要多次拍照,可以多次调用 capture()
方法。Android Camera2 与 Camera API 相比,具有以下优势:
Surface
中。这种架构使得开发者可以更方便地定制和扩展相机的功能,实现各种复杂的拍摄需求。CameraCharacteristics
类,Camera2 可以方便地检查设备相机的各种特性和功能,开发者可以根据设备的支持情况来动态地调整相机的设置和功能,提高了应用的适应性和稳定性。例如,在应用启动时,可以先检测设备是否支持手动对焦功能,如果支持则开启手动对焦选项,否则隐藏该选项,避免出现功能不可用的情况。要使用 Android Camera2 进行 RAW 图像捕获,你可以按照以下步骤进行操作:
Context.getSystemService(Context.CAMERA_SERVICE)
获取 CameraManager 实例123。openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)
方法打开相机设备。你需要指定要打开的相机 ID 以及相应的回调和处理程序123。ImageFormat.RAW_SENSOR
以指定捕获 RAW 图像1。createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)
方法创建一个 CameraCaptureSession。将包含 RAW 图像的 Surface 添加到输出列表中1。capture(CaptureRequest request, CameraCaptureSession.CaptureCallback callback, Handler handler)
方法开始捕获 RAW 图像。你可以指定相应的回调来处理捕获结果1。onCaptureCompleted
方法中,你将接收到包含 RAW 图像数据的 CaptureResult 对象。你可以从 CaptureResult 中获取图像数据,并进行相应的处理或保存。示例代码如下:
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;
public class RawImageCapture {
private CameraManager cameraManager;
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSession;
private CaptureRequest.Builder captureRequestBuilder;
public void startRawImageCapture(Context context) {
// 获取CameraManager
cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
// 获取相机设备ID
cameraId = cameraManager.getCameraIdList()[0];
// 打开相机设备
cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
cameraDevice = camera;
createCaptureSession();
}
@Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}
@Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCaptureSession() {
try {
// 创建CaptureRequest.Builder
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(new Surface(ImageFormat.RAW_SENSOR));
// 创建CameraCaptureSession
cameraDevice.createCaptureSession(Arrays.asList(new Surface(ImageFormat.RAW_SENSOR)), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
cameraCaptureSession = session;
startCapture();
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void startCapture() {
try {
cameraCaptureSession.capture(captureRequestBuilder.build(), new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
// 处理RAW图像数据
Log.d("RawImageCapture", "RAW image captured");
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
大牛直播SDK前几年在做Android平台RTMP推送和轻量级RTSP服务的时候,实际上就已经支持了Camera2的采集和数据投递,考虑到,目前5.0以下版本的设备越来越少,后面的GB28181设备接入模块,更是以Camera2的demo为准。
Camera2数据回调并投递到底层jni示例代码如下:
/*
* Camera2MainActivity.java
* Author:daniusdk.com
* WeChat: xinsheng120
*/
@Override
public void onCameraImageData(Image image) {
Image.Plane[] planes = image.getPlanes();
if (image.getFormat() != ImageFormat.YUV_420_888) {
Log.i(TAG, "image format is not YUV_420_888, format:" + image.getFormat());
return;
} else {
// Log.i(TAG, "image format is YUV_420_888, format:" + image.getFormat());
}
int w = image.getWidth(), h = image.getHeight();
int y_offset = 0, u_offset = 0, v_offset = 0;
Rect crop_rect = image.getCropRect();
if (crop_rect != null && !crop_rect.isEmpty()) {
w = crop_rect.width();
h = crop_rect.height();
y_offset += crop_rect.top * planes[0].getRowStride() + crop_rect.left * planes[0].getPixelStride();
u_offset += (crop_rect.top / 2) * planes[1].getRowStride() + (crop_rect.left / 2) * planes[1].getPixelStride();
v_offset += (crop_rect.top / 2) * planes[2].getRowStride() + (crop_rect.left / 2) * planes[2].getPixelStride();
;
// Log.i(TAG, "crop w:" + w + " h:" + h + " y_offset:"+ y_offset + " u_offset:" + u_offset + " v_offset:" + v_offset);
}
int scale_w = 0, scale_h = 0, scale_filter_mode = 0;
scale_filter_mode = 3;
int rotation_degree = cameraImageRotationDegree_;
if (rotation_degree < 0) {
Log.i(TAG, "onCameraImageData rotation_degree < 0, may need to set orientation_ to 0, 90, 180 or 270");
return;
}
for (LibPublisherWrapper i : publisher_array_)
i.PostLayerImageYUV420888ByteBuffer(0, 0, 0,
planes[0].getBuffer(), y_offset, planes[0].getRowStride(),
planes[1].getBuffer(), u_offset, planes[1].getRowStride(),
planes[2].getBuffer(), v_offset, planes[2].getRowStride(), planes[1].getPixelStride(),
w, h, 0, 0,
scale_w, scale_h, scale_filter_mode, rotation_degree);
}
Android Camera2 API 是从 Android 5.0(Lollipop)开始引入的,相对Camera API,优势非常明显,如果需要通过Android平台采集视频数据,在设备支持的前提下,建议尽可能用Camera2做数据采集。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。