camerad: improve IFE robustness to lags (#38548)

camerad: keep request IDs monotonic
This commit is contained in:
Adeeb Shihadeh
2026-08-10 22:36:54 -07:00
committed by GitHub
parent b1cdf387b5
commit 122a8ca00a
2 changed files with 17 additions and 13 deletions
+14 -11
View File
@@ -297,7 +297,7 @@ void SpectraCamera::camera_open(VisionIpcServer *v) {
LOGD("camera init %d", cc.camera_num);
buf.init(this, v, ife_buf_depth, cc.stream_type);
camera_map_bufs();
clearAndRequeue(1);
clearAndRequeue();
}
void SpectraCamera::sensors_start() {
@@ -942,7 +942,10 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
assert(ret == 0);
}
void SpectraCamera::enqueue_frame(uint64_t request_id) {
void SpectraCamera::enqueue_frame() {
// The kernel reports only requests newer than reported_req_id, which a flush does not reset.
// https://github.com/commaai/agnos-kernel-sdm845/blob/93ddd472ce522ab8669456b11bf3924ad32e9882/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c#L609-L613
uint64_t request_id = next_request_id++;
int i = request_id % ife_buf_depth;
assert(sync_objs_ife[i] == 0);
@@ -1428,14 +1431,14 @@ bool SpectraCamera::handle_camera_event(const cam_req_mgr_message *event_data) {
if (!waitForFrameReady(request_id)) {
// Reset queue on sync failure to prevent frame tearing
LOGE("camera %d sync failure %ld %ld ", cc.camera_num, request_id, ife_frame_id);
clearAndRequeue(request_id + 1);
clearAndRequeue();
return false;
}
int buf_idx = request_id % ife_buf_depth;
bool ret = processFrame(buf_idx, request_id, ife_frame_id, timestamp);
destroySyncObjectAt(buf_idx);
enqueue_frame(request_id + ife_buf_depth); // request next frame for this slot
enqueue_frame(); // request next frame for this slot
return ret;
}
@@ -1445,7 +1448,7 @@ bool SpectraCamera::validateEvent(uint64_t request_id, uint64_t ife_frame_id) {
if (request_id == 0) {
if (invalid_request_count++ > ife_buf_depth+2) {
LOGE("camera %d reset after half second of invalid requests", cc.camera_num);
clearAndRequeue(last_valid_request_id + 1);
clearAndRequeue();
invalid_request_count = 0;
}
return false;
@@ -1456,26 +1459,26 @@ bool SpectraCamera::validateEvent(uint64_t request_id, uint64_t ife_frame_id) {
if (!skip_expected) {
if (ife_frame_id != last_valid_ife_frame_id + 1) {
LOGE("camera %d frame ID skipped, %lu -> %lu", cc.camera_num, last_valid_ife_frame_id, ife_frame_id);
clearAndRequeue(request_id + 1);
clearAndRequeue();
return false;
}
if (request_id != last_valid_request_id + 1) {
LOGE("camera %d requests skipped %ld -> %ld", cc.camera_num, last_valid_request_id, request_id);
clearAndRequeue(request_id + 1);
clearAndRequeue();
return false;
}
}
return true;
}
void SpectraCamera::clearAndRequeue(uint64_t from_request_id) {
void SpectraCamera::clearAndRequeue() {
// clear everything, then queue up a fresh set of frames
LOGW("clearing and requeuing camera %d from %lu", cc.camera_num, from_request_id);
LOGW("clearing and requeuing camera %d from %lu", cc.camera_num, next_request_id);
clear_req_queue();
last_requeue_ts = nanos_since_boot();
for (uint64_t id = from_request_id; id < from_request_id + ife_buf_depth; ++id) {
enqueue_frame(id);
for (int i = 0; i < ife_buf_depth; ++i) {
enqueue_frame();
}
skip_expected = true;
}
+3 -2
View File
@@ -144,7 +144,7 @@ public:
void config_ife(int idx, int request_id, bool init=false);
int clear_req_queue();
void enqueue_frame(uint64_t request_id);
void enqueue_frame();
int sensors_init();
void sensors_start();
@@ -205,6 +205,7 @@ public:
int buf_handle_raw[MAX_IFE_BUFS] = {};
int sync_objs_ife[MAX_IFE_BUFS] = {};
int sync_objs_bps[MAX_IFE_BUFS] = {};
uint64_t next_request_id = 1;
uint64_t last_valid_request_id = 0;
uint64_t last_requeue_ts = 0;
uint64_t last_valid_ife_frame_id = 0;
@@ -215,7 +216,7 @@ public:
SpectraMaster *m;
private:
void clearAndRequeue(uint64_t from_request_id);
void clearAndRequeue();
bool validateEvent(uint64_t request_id, uint64_t ife_frame_id);
bool waitForFrameReady(uint64_t request_id);
bool processFrame(int buf_idx, uint64_t request_id, uint64_t ife_frame_id, uint64_t timestamp);