You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AOSP 13 i.MX8MM开发板NDK Camera2 AImageReader无帧接收问题

问题

在i.MX8MM Var-SOM开发板基于AOSP 13系统,使用NDK Camera2 API实现原生人脸检测,目标是通过AImageReader捕获帧并交给TensorFlow Lite处理。相机能成功打开,但AImageReader始终无法接收帧,持续出现以下日志:

W CameraDeviceSessionHwlImpl: map_frame_request still empty after 100000000 ns
W CameraDeviceSessionHwlImpl: HandleImage: mImageList still empty after 100000000 ns

已验证的操作:

  • ✅ 相机成功打开(CameraService::connect日志确认)
  • ✅ AImageReader已创建并设置监听器(日志确认)
  • ✅ 捕获会话成功启动(日志显示“Capture Session Active”)
  • ❌ 无帧传输至ImageReader(“Image Available Callback Triggered!”从未触发)
  • ✅ 相机服务日志(dumpsys media.camera)显示:相机设备已打开,但无帧被处理,提示“No input stream configured.”

相关代码实现:

AImageReader配置及图像回调

// Creating AImageReader
AImageReader_new(320, 240, AIMAGE_FORMAT_JPEG, 10, 
&imageReader);

AImageReader_ImageListener listener = {
    .context = nullptr, 
    .onImageAvailable = ImageCallback
};
AImageReader_setImageListener(imageReader, &listener);

图像回调函数

void ImageCallback(void* context, AImageReader* reader) {
    LOG("Image Available Callback Triggered!");

    AImage* image;
    media_status_t imgStatus = AImageReader_acquireLatestImage(reader, &image);
    if (imgStatus != AMEDIA_OK || !image) {
        LOGE("Failed to acquire image, status: %d", imgStatus);
        return;
    }

    int32_t width, height, format;
    AImage_getWidth(image, &width);
    AImage_getHeight(image, &height);
    AImage_getFormat(image, &format);
    LOG("Received Image: %dx%d, Format: %d", width, height, format);

    AImage_delete(image);
}

捕获请求配置

ACameraDevice_createCaptureRequest(cameraDevice, TEMPLATE_PREVIEW, &captureRequest);

// Attach ImageReader to Capture Request
ANativeWindow* nativeWindow;
AImageReader_getWindow(imageReader, &nativeWindow);
ACameraOutputTarget* imageReaderTarget;
ACameraOutputTarget_create(nativeWindow, &imageReaderTarget);
ACaptureRequest_addTarget(captureRequest, imageReaderTarget);

// Set Capture Request Parameters
ACaptureRequest_setEntry_i32(captureRequest, ACAMERA_SENSOR_SENSITIVITY, 1, (int32_t[]){400});
ACaptureRequest_setEntry_i32(captureRequest, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, 2, (int32_t[]){15, 30});
ACaptureRequest_setEntry_i32(captureRequest, ACAMERA_SCALER_CROP_REGION, 4, (int32_t[]){0, 0, 320, 240});

// Start Capture Session
camera_status_t cam_status = ACameraCaptureSession_setRepeatingRequest(
    captureSession, nullptr, 1, &captureRequest, nullptr);

if (cam_status != ACAMERA_OK) {
    LOGE("Failed to start capture session, status: %d", cam_status);
    return;
}
LOG("Camera Capture Started!");
解决方案
  1. 更换AImageReader的图像格式
    当前使用AIMAGE_FORMAT_JPEG作为预览格式,但多数Android相机硬件的预览流不支持直接输出JPEG格式(JPEG多用于静态拍照)。预览流优先使用标准YUV格式,比如AIMAGE_FORMAT_YUV_420_888,修改AImageReader_new参数:

    AImageReader_new(320, 240, AIMAGE_FORMAT_YUV_420_888, 10, &imageReader);
    
  2. 验证相机支持的流配置
    日志中的“No input stream configured.”说明当前设置的分辨率、格式组合不被硬件支持。需要先查询相机支持的输出配置:

    • 调用ACameraDevice_getCharacteristics获取相机特性
    • 从特性中提取ACAMERA_SCALER_STREAM_CONFIGURATION_MAP,枚举所有支持的分辨率和格式组合
    • 确保320x240和所选格式在支持列表内
  3. 修正捕获会话的创建流程
    必须在创建ACameraCaptureSession时就将AImageReader的NativeWindow作为输出目标传入,而非仅在捕获请求中添加。正确流程:

    • 创建AImageReader后,获取其NativeWindow
    • 将NativeWindow加入会话的输出目标列表
    • 调用ACameraDevice_createCaptureSession创建会话并传入该目标列表
    • 会话创建成功后,再创建捕获请求、添加目标并启动重复捕获
  4. 移除或验证自定义参数
    当前设置的ACAMERA_SCALER_CROP_REGION可能不符合硬件支持的裁剪规则,建议先移除该参数,测试基础流是否正常,再逐步添加其他参数。

  5. 确保资源正确释放
    使用完ACameraOutputTarget后需及时释放,避免资源泄漏导致流异常:

    ACaptureRequest_removeTarget(captureRequest, imageReaderTarget);
    ACameraOutputTarget_free(imageReaderTarget);
    

内容的提问来源于stack exchange,提问作者frostSi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:32:12