欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > Android11 Camera HAL Interface规范:Flush该如何实现

Android11 Camera HAL Interface规范:Flush该如何实现

2025/2/28 9:44:40 来源:https://blog.csdn.net/hongyeying/article/details/145827511  浏览:    关键词:Android11 Camera HAL Interface规范:Flush该如何实现

 背景描述:

Android11 Camera HAL层需要实现框架定义的一组HIDL Interface。以Google Demo为例子,HAL层接口实现如下:

namespace default_camera_hal {
...
const camera3_device_ops_t Camera::sOps = {.initialize = default_camera_hal::initialize,.configure_streams = default_camera_hal::configure_streams,.register_stream_buffers = nullptr,.construct_default_request_settings =default_camera_hal::construct_default_request_settings,.process_capture_request = default_camera_hal::process_capture_request,.get_metadata_vendor_tag_ops = nullptr,.dump = default_camera_hal::dump,.flush = default_camera_hal::flush,.reserved = {0},
};}

    HAL层该如何实现flush处理呢?接口该如何实现,

    • 可以参考官方的设计说明文档
    • 可以看接口定义
    • 可以参考Demo实现

    先思考一下:相机工作(这里指request&result处理)有哪些线程,这些线程是如何工作的。

    Android11 Camera HAL Demo中request&result处理

    Camera HAL在相机初始化阶段会创建两个线程:

    • 一个负责从缓存队列中取框架下发的request进行处理,对应执行函数enqueueRequestBuffers。
    • 一个负责将处理结果通过result回调回框架,对应执行函数dequeueRequestBuffers。

    request&result正常处理过程如下图,

    从框架下来的有效request先缓存到request_queue_队列中,然后process_capture_request()接口返回。enqueueRequestBuffes线程从request_queue_队列中一帧一帧的取request,送设备节点进行处理(HAL Demo V4L2节点是1个Buffer, 这里可以根据自己需要调大, 上图假设是5个buffer)。dequeueRequestBuffers线程不断查询设备节点是不是处理完一帧,如果有帧输出则取出图像数据,处理后回调result给框架。

    从上图观察request是有转移的,框架下来的一个request可能在两个位置:

    • request_queue_队列,等待被送往设备
    • 从request_queue_队列出来了,已经送到设备了,这时候在buffers_里关联着。

    有没有一个统一的位置可以跟踪一个框架下来的request,直到它返回框架?有的,就是mInFlightTracker。一个有效的request被添加到request_queue_队列的同时会加到mInFlightTracker跟踪队列,直到回调回框架。

    Android11 Camera HAL Demo中的mInFlightTracker

    mInFlightTracker(RequestTracker类的实例)是Camera类中用来跟踪框架request的跟踪器。从RequestTracker可以观察到一个request从进入HAL层到出HAL层的整个时间。接下来分析RequestTracker是如何跟踪一个request的。

    RequestTracker是通过一个map表(std::map<uint32_t, std::shared_ptr<CaptureRequest>>)实现对request跟踪管理。

    mInFlightTracker对request的跟踪涉及四个操作:

    • mInFlightTracker->Remove(request)  取消对一个request的跟踪。
    • mInFlightTracker->Clear(&requests)   取出跟踪的所有request
    • mInFlightTracker->CanAddRequest(*request)  检查是不是能添加对这个request的跟踪。
    • mInFlightTracker->Add(request) 添加一个request到跟踪队列。

    Camera HAL Demo中跟踪事务流如下图:

    注:notify和sendResult都是向框架回调的接口,这里为了强调"notify回调->result回调"图中只画了sendResult向外箭头。

    如上图可以看出mInFlightTracker跟踪request涉及:

    • 一个"入":框架调process capture request处理流程,如果mInFlightTracker容量有余,并且是有效request,工作状态的HAL将"接收"这个request。
    • 三个"出":
      • 正常输出:dequeueRequestBuffers线程对于正常处理的一帧结果回调
      • 异常输出:enqueueRequestBuffers线程对于异常处理的一帧回调和flush流程将HAL层未返回的请求立即回调。

    Android11 Camera HAL Demo中flush处理

    对于上图四个线程同时执行调度,Demo HAL实现逻辑是这样的:

    • request处理过程中,如果flush先被调到,mInFlightTrackerLock将mInFlightTracker锁住,这时flush线程将所有未返回的request立即返回。process capture request在flush执行期间被调到,由于mInFlightTrackerLock锁被获取,需要等flush执行完之后获取mInFlightTrackerLock再执行。
    • request处理过程中,如果process capture request先被调到,mInFlightTrackerLock被获取。flush在process capture request执行期间被调用,由于mInFlightTrackerLock锁被获取,需要等process capture request执行完后获取mInFlightTrackerLock再执行。

    flush和processCaptureRequest实现中有如下注释:

    int Camera::processCaptureRequest(camera3_capture_request_t *temp_request)
    {// TODO(b/32917568): A capture request submitted or ongoing during a flush// should be returned with an error; for now they are mutually exclusive.android::Mutex::Autolock tl(mInFlightTrackerLock);...
    }int Camera::flush()
    {// TODO(b/32917568): Synchronization. Behave "appropriately"// (i.e. according to camera3.h) if process_capture_request()// is called concurrently with this (in eigher order).// Since the callback to completeRequest also may happen on a separate// thread, this function should behavae nicely concurrently with that too.android::Mutex::Autolock tl(mInFlightTrackerLock);...
    }

     说明flush期间的request应尽快以error状态返回框架。

    回看当前flush()和processCaptureRequest() mInFlightTrackerLock锁的使用会导致两个结果:

    1. flush和processCaptureRequest不能并发执行,如果processCaptureRequest先获取到锁,flush不能被立即处理,不能达到最佳加速冲刷效果。
    2. flush和processCaptureRequest不能并发执行,如果flush先获取到锁,processCaptureRequest在处理期间下来的request被识别为有效的request。我们知道框架request和flush是异步并发的,flush被调用是为了将HAL层遗留的request尽快清空。
    3. 如果flush和processCaptureRequest并发执行,flush开始执行一段时间这时processCaptureRequest输入一个request,这个request该如何处理?立即返回。(确保flush执行后HAL层无request待返回)。
    4. 如果flush和processCaptureRequest并发执行,processCaptureRequest先执行一段时间这时flush被调用,最近输入的这个request应立即返回。(确保flush执行后HAL层无request待返回)。

    所以flush和processCaptureRequest改如何协调,关键是为了达到一个效果,即flush执行完HAL无request要返回。

    Android11 Camera HAL Demo flush处理的优化

    版权声明:

    本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

    我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

    热搜词