1. 初始化8K HDR Camera会话

任务目标

在Qualcomm平台(如SM8550/SM8650)上,通过Camera HAL3接口配置并启动一个支持8K分辨率(7680×4320)与HDR(10-bit)输出的相机会话,并验证基本预览通路是否正常建立。本案例聚焦于会话初始化与预览流配置,不涉及拍照或录像。

环境依赖

  • 硬件:Qualcomm 8K HDR平台设备(如SM8550 MTP/QRD)
  • 系统:Android 13+(Camera HAL3已启用)
  • NDK:android.hardware.camera2 NDK API(android.hardware.camera2包)
  • 权限:CAMERA权限已在AndroidManifest中声明

关键实现

以下代码使用Camera2 NDK API创建8K HDR预览会话。核心步骤包括:查询8K HDR能力、配置输出流、创建会话并启动预览请求。代码通过ACameraManager获取相机实例,使用ACaptureSessionOutputContainer管理输出流,并设置10-bit HDR像素格式。

// camera_8k_hdr_session.cpp
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraCaptureSession.h>
#include <camera/NdkCameraMetadata.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <android/hardware_buffer.h>
#include <vector>
#include <cstring>

// 8K HDR会话初始化类
class Camera8KHdrSession {
public:
    bool initialize(ANativeWindow* previewWindow) {
        // 1. 获取相机管理器
        camera_manager_ = ACameraManager_create();
        if (!camera_manager_) return false;

        // 2. 选择后置相机(ID "0")
        const char* camera_id = "0";
        ACameraMetadata* metadata = nullptr;
        if (ACameraManager_getCameraCharacteristics(camera_manager_, camera_id, &metadata) != ACAMERA_OK) {
            return false;
        }

        // 3. 验证8K HDR能力
        if (!check8KHdrCapability(metadata)) {
            ACameraMetadata_free(metadata);
            return false;
        }
        ACameraMetadata_free(metadata);

        // 4. 打开相机设备
        ACameraDevice_StateCallbacks device_callbacks = {};
        device_callbacks.onDisconnected = [](void*, ACameraDevice*) {};
        device_callbacks.onError = [](void*, ACameraDevice*, int) {};
        if (ACameraManager_openCamera(camera_manager_, camera_id, &device_callbacks, &camera_device_) != ACAMERA_OK) {
            return false;
        }

        // 5. 配置8K HDR输出流
        if (!configureStreams(previewWindow)) {
            return false;
        }

        // 6. 创建捕获会话
        if (!createCaptureSession()) {
            return false;
        }

        // 7. 启动预览请求
        return startPreview();
    }

    void destroy() {
        if (capture_session_) {
            ACameraCaptureSession_stopRepeating(capture_session_);
            ACameraCaptureSession_close(capture_session_);
        }
        if (camera_device_) {
            ACameraDevice_close(camera_device_);
        }
        if (camera_manager_) {
            ACameraManager_delete(camera_manager_);
        }
    }

private:
    ACameraManager* camera_manager_ = nullptr;
    ACameraDevice* camera_device_ = nullptr;
    ACameraCaptureSession* capture_session_ = nullptr;
    ACaptureSessionOutputContainer* output_container_ = nullptr;
    ACaptureSessionOutput* session_output_ = nullptr;
    ACameraOutputTarget* output_target_ = nullptr;
    ANativeWindow* preview_window_ = nullptr;
    AImageReader* image_reader_ = nullptr;

    // 检查是否支持8K HDR(10-bit)输出
    bool check8KHdrCapability(ACameraMetadata* metadata) {
        // 查询流配置能力
        ACameraMetadata_const_entry entry;
        if (ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry) != ACAMERA_OK) {
            return false;
        }

        bool has_8k_hdr = false;
        for (int i = 0; i < entry.count; i += 4) {
            int32_t format = entry.data.i32[i];
            int32_t width = entry.data.i32[i + 1];
            int32_t height = entry.data.i32[i + 2];
            int32_t direction = entry.data.i32[i + 3];

            // 检查输出方向(1=输出)且为8K分辨率
            if (direction == 1 && width == 7680 && height == 4320) {
                // 检查是否为10-bit HDR格式(HAL_PIXEL_FORMAT_RGBA_1010102 = 43)
                if (format == 43) {  // RGBA_1010102
                    has_8k_hdr = true;
                    break;
                }
            }
        }
        return has_8k_hdr;
    }

    // 配置8K HDR输出流
    bool configureStreams(ANativeWindow* previewWindow) {
        preview_window_ = previewWindow;

        // 创建ImageReader用于8K HDR帧获取(可选,用于验证)
        media_status_t status = AImageReader_new(7680, 4320, AIMAGE_FORMAT_RGBA_1010102, 1, &image_reader_);
        if (status != AMEDIA_OK) return false;

        // 获取ImageReader的NativeWindow
        ANativeWindow* reader_window = nullptr;
        AImageReader_getWindow(image_reader_, &reader_window);

        // 创建输出容器
        if (ACaptureSessionOutputContainer_create(&output_container_) != ACAMERA_OK) {
            return false;
        }

        // 添加预览窗口输出
        if (ACaptureSessionOutput_create(preview_window_, &session_output_) != ACAMERA_OK) {
            return false;
        }
        if (ACaptureSessionOutputContainer_add(output_container_, session_output_) != ACAMERA_OK) {
            return false;
        }

        // 创建输出目标
        if (ACameraOutputTarget_create(preview_window_, &output_target_) != ACAMERA_OK) {
            return false;
        }

        return true;
    }

    // 创建捕获会话
    bool createCaptureSession() {
        ACameraCaptureSession_stateCallbacks session_callbacks = {};
        session_callbacks.onReady = [](void*, ACameraCaptureSession*) {};
        session_callbacks.onActive = [](void*, ACameraCaptureSession*) {};

        // 创建会话
        camera_status_t status = ACameraDevice_createCaptureSession(camera_device_, output_container_, &session_callbacks, &capture_session_);
        return status == ACAMERA_OK;
    }

    // 启动预览请求
    bool startPreview() {
        // 创建捕获请求
        ACameraCaptureRequest* request = nullptr;
        if (ACameraDevice_createCaptureRequest(camera_device_, TEMPLATE_PREVIEW, &request) != ACAMERA_OK) {
            return false;
        }

        // 添加输出目标
        if (ACameraCaptureRequest_addTarget(request, output_target_) != ACAMERA_OK) {
            ACameraCaptureRequest_free(request);
            return false;
        }

        // 设置HDR相关参数(10-bit色调映射)
        // 注意:实际HDR参数需根据具体传感器能力设置
        // 此处设置基础参数确保会话可用
        uint8_t tonemap_mode = ACAMERA_TONEMAP_MODE_HDR;
        ACameraCaptureRequest_setEntryU8(request, ACAMERA_TONEMAP_MODE, &tonemap_mode, 1);

        // 设置重复请求
        int32_t sequence_id = 0;
        camera_status_t status = ACameraCaptureSession_setRepeatingRequest(capture_session_, nullptr, 1, &request, &sequence_id);
        ACameraCaptureRequest_free(request);
        return status == ACAMERA_OK;
    }
};

调用与验证

在Android应用层通过JNI调用上述类,传入SurfaceView的NativeWindow。验证步骤如下:

  1. 初始化调用:在onSurfaceCreated回调中调用initialize(),传入Surface的NativeWindow。
  2. 观察预览:若会话成功,SurfaceView应显示实时相机预览画面。
  3. 日志验证:在onReady回调中打印日志,确认会话状态为ACAMERA_CAPTURE_SESSION_READY。
  4. 分辨率确认:通过adb shell dumpsys media.camera查看当前活跃会话的输出流配置,确认分辨率为7680×4320且格式为RGBA_1010102。

通过条件:预览画面正常显示且无错误回调;dumpsys输出显示8K HDR流已激活。

常见问题

  • 会话创建失败:确认设备支持8K HDR输出,且SurfaceView尺寸与8K匹配(需在布局中设置固定尺寸)。
  • 预览黑屏:检查是否设置了正确的HDR像素格式,部分设备需要显式设置ACAMERA_CONTROL_ENABLE_ZSL为false。
  • 性能不足:8K预览需要较高带宽,建议在真机测试而非模拟器。