原生Camera2中CameraMetadata用法和代码流程详解

发布时间:2024年01月11日

1,CameraMetadata介绍

CameraMetadata在Android的Camera2 API中起到了关键的作用。它提供了一种机制,使应用程序能够获取关于相机硬件和其当前状态的元数据。这些元数据包括各种信息,例如相机传感器的状态、镜头的朝向、闪光灯的充电状态、自动曝光和自动对焦模式等。

通过使用CameraMetadata,应用程序可以更好地理解相机的工作状态,并根据这些信息做出决策。例如,应用程序可以根据传感器的灵敏度范围来选择合适的ISO值,或者根据镜头的状态来决定是否触发闪光灯。此外,应用程序还可以利用元数据来优化图像捕获过程,提高拍照效果和用户体验。

总而言之,CameraMetadata的作用是提供关于相机硬件和状态的元数据,使应用程序能够更好地控制相机行为并优化图像捕获过程。

2,CameraMetadata如何获取相机的元数据?

要获取相机的元数据,您需要使用Camera2 API的CameraMetadata类。以下是一些基本步骤:

获取CameraManager:首先,您需要获取CameraManager实例,这可以通过调用Context.getSystemService(Context.CAMERA_SERVICE)实现。
获取CameraId:使用CameraManager的getCameraIdList()方法获取所有可用相机的列表。您可以选择其中一个相机来获取其元数据。
打开Camera:使用CameraManager的openCamera()方法打开选定的相机。这将返回一个CameraDevice对象,您需要使用这个对象来获取相机的元数据。
创建CameraMetadata:使用CameraDevice.createCaptureRequest()方法创建一个CaptureRequest对象,该对象将包含您要查询的元数据。然后,您可以使用CaptureRequest.getMetadata()方法获取CameraMetadata对象。
查询元数据:使用CameraMetadata的get()方法查询特定的元数据字段。这些字段包括传感器信息、镜头状态、闪光灯状态等。
关闭Camera:完成元数据查询后,记得关闭相机。

请注意,上述步骤是一个基本的概述,实际操作可能因Android版本和设备而异。此外,确保您的应用程序具有必要的权限(如CAMERA权限)才能访问相机硬件。

3,CameraMetadata获取相机的元数据代码示例

以下是一个简单的示例代码,演示如何使用Camera2 API中的CameraMetadata来获取相机的元数据:

// 获取CameraManager  
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);  
  
// 获取相机列表  
List<String> cameraIdList = cameraManager.getCameraIdList();  
  
// 打开相机  
String cameraId = cameraIdList.get(0); // 假设使用第一个相机  
CameraDevice cameraDevice = cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {  
    @Override  
    public void onOpened(CameraDevice camera) {  
        // 创建CaptureRequest  
        CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);  
        captureRequestBuilder.addTarget(previewSurface); // 将预览Surface添加到CaptureRequest中  
        captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 设置自动对焦模式  
        captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); // 设置自动曝光模式  
        CaptureRequest captureRequest = captureRequestBuilder.build();  
  
        // 创建CameraMetadata  
        CameraMetadata cameraMetadata = captureRequest.getMetadata();  
  
        // 查询元数据  
        int sensorInfoTimestampSource = cameraMetadata.get(CaptureResult.SENSOR_INFO_TIMESTAMP_SOURCE);  
        long sensorTimestamp = cameraMetadata.getLong(CaptureResult.SENSOR_TIMESTAMP);  
        int sensitivityRange = cameraMetadata.getIntArray(CaptureResult.SENSOR_INFO_SENSITIVITY_RANGE)[0];  
        int lensFacing = cameraMetadata.getInt(CaptureResult.LENS_FACING);  
        int flashInfoChargingStage = cameraMetadata.getInt(CaptureResult.FLASH_INFO_CHARING_STAGE);  
        int aeTargetFpsRange = cameraMetadata.getIntArray(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE)[0];  
        int aeMode = cameraMetadata.getInt(CaptureResult.CONTROL_AE_MODE);  
        int afMode = cameraMetadata.getInt(CaptureResult.CONTROL_AF_MODE);  
        int afState = cameraMetadata.getInt(CaptureResult.CONTROL_AF_STATE);  
        int awbMode = cameraMetadata.getInt(CaptureResult.CONTROL_AWB_MODE);  
  
        // 处理元数据...  
    }  
    @Override  
    public void onDisconnected(CameraDevice camera) {  
        // 关闭相机设备  
        cameraDevice.close();  
    }  
    @Override  
    public void onError(CameraDevice camera, int error) {  
        // 处理错误...  
    }  
});

请注意,这只是一个简单的示例,仅展示了如何创建CaptureRequest、获取CameraMetadata并查询一些元数据字段。在实际应用中,您可能需要处理更复杂的场景,包括错误处理、权限检查和相机设备的生命周期管理。

4,原生Camera2 app中如何获取CameraMetadata?

在Camera open过程中会创建封装一个类中,路径packages\apps\Camera2\src\com\android\camera\one\v2\OneCameraCharacteristicsImpl.java,在这个类中可看到获取了CameraMetadata的接口操作,如下:

 public boolean isExposureCompensationSupported() {
        // Turn off exposure compensation for Nexus 6 on L (API level 21)
        // because the bug in framework b/19219128.
        if (ApiHelper.IS_NEXUS_6 && ApiHelper.isLollipop()) {
            return false;
        }
        Range<Integer> compensationRange =
                mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
        return compensationRange.getLower() != 0 || compensationRange.getUpper() != 0;
    }

这里通过TagID就可以获取到metadata的数据。

5,原生Camera2 app中如何设置metadata到底层?

这里可以看对焦的时候设置request到cameraservice的例子,如下:

private RequestBuilder createAFTriggerRequest(AFTriggerResult afScanResult) throws
            CameraAccessException {
        RequestBuilder triggerBuilder = mBuilderFactory.create(mTemplateType);
        triggerBuilder.addResponseListener(forPartialMetadata(afScanResult));
        triggerBuilder.setParam(CaptureRequest.CONTROL_MODE, CaptureRequest
                .CONTROL_MODE_AUTO);
        triggerBuilder.setParam(CaptureRequest.CONTROL_AF_MODE, CaptureRequest
                .CONTROL_AF_MODE_AUTO);
        triggerBuilder.setParam(CaptureRequest.CONTROL_AF_TRIGGER,
                CaptureRequest.CONTROL_AF_TRIGGER_START);
        return triggerBuilder;
    }

这里就是通过设置tagid的value来设置request。然后传到cameraservice中,如下:

RequestBuilder triggerBuilder = createAFTriggerRequest(afScanResult);
            session.submitRequest(Arrays.asList(triggerBuilder.build()),
                    FrameServer.RequestType.NON_REPEATING);

这段参考代码路径:packages\apps\Camera2\src\com\android\camera\one\v2\autofocus\FullAFScanCommand.java.通过这个例子可以添加自己的tagid到request中就可以实现自己的逻辑需求。

6,在CameraMetadata中添加vendortag的步骤和代码示例?

在Camera2中,要添加vendortag,需要使用CameraCharacteristics和CaptureRequest.Builder。以下是具体步骤:

获取CameraManager实例。
通过CameraManager获取相机列表。
遍历相机列表,找到目标相机。
获取目标相机的CameraCharacteristics。
从CameraCharacteristics中获取可用的VendorTags。
使用CaptureRequest.Builder创建CaptureRequest,并添加VendorTag。

以下是一个示例代码:

import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.os.Build;
import android.util.Log;

public class VendorTagHelper {
    private static final String TAG = "VendorTagHelper";

    public static void addVendorTag(Context context, int cameraId, int tagId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
            try {
                String cameraIdStr = String.valueOf(cameraId);
                CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraIdStr);
                int[] availableVendorTags = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_VENDOR_TAG_LIST);
                if (availableVendorTags != null && availableVendorTags.length > 0) {
                    int[] newVendorTags = new int[availableVendorTags.length + 1];
                    newVendorTags[0] = tagId;
                    System.arraycopy(availableVendorTags, 0, newVendorTags, 1, availableVendorTags.length);
                    characteristics.set(CameraCharacteristics.REQUEST_AVAILABLE_VENDOR_TAG_LIST, newVendorTags);
                    Log.d(TAG, "Added vendor tag: " + tagId + " to camera: " + cameraIdStr);
                } else {
                    Log.w(TAG, "No available vendor tags for camera: " + cameraIdStr);
                }
            } catch (CameraAccessException e) {
                Log.e(TAG, "Failed to access camera: " + cameraIdStr, e);
            }
        } else {
            Log.w(TAG, "Device does not support adding vendor tags");
        }
    }
}

使用方法:

// 添加一个名为"MyTag"的vendortag到第一个相机上,tag值为10001
VendorTagHelper.addVendorTag(context, 0, 10001);

你的鼓励将是我创作的最大动力:
在这里插入图片描述

文章来源:https://blog.csdn.net/jiangchaobing_2017/article/details/135510647
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。