feat: 链路控制、延迟校准与长测工具,补全文档
- 固件:新增 link_control / stream_control,覆盖运行中 Wi-Fi 断线恢复、取帧节拍、 温控与质量/帧率减载;UDP 发送增加有界重试预算与帧期限,PSRAM JPEG 直发减少拷贝。 - 协议:重组器严格校验分片布局,统计未收齐、超时与完全缺失的帧,处理帧号回绕与设备重启。 - 桌面端:视频改 latest-value 通道并前置帧时间标记,拒绝积压和慢解码的过期画面;新增 延迟标记页与 --latency-report 校准,完善录制、服务端与退出流程。 - 文档与脚本:新增硬件、开发、延迟、功耗、实时性、稳定性文档和改动记录,重写根 README; 新增构建、性能、延迟与串口长测脚本,以及长测客户端脚本。 - 构建:固定 esp-1.97.0.0 工具链,分区表随构建复制,更新 sdkconfig 与忽略规则。
This commit is contained in:
@@ -733,13 +733,14 @@ camera_fb_t *cam_take(TickType_t timeout)
|
||||
for (;;)
|
||||
{
|
||||
TickType_t elapsed = xTaskGetTickCount() - start; /* TickType_t is unsigned so rollover is safe */
|
||||
if (elapsed >= timeout) {
|
||||
if (timeout && elapsed >= timeout) {
|
||||
ESP_LOGW(TAG, "Failed to get frame: timeout");
|
||||
return NULL;
|
||||
}
|
||||
TickType_t remaining = timeout - elapsed;
|
||||
TickType_t remaining = timeout ? timeout - elapsed : 0;
|
||||
|
||||
if (xQueueReceive(cam_obj->frame_buffer_queue, (void *)&dma_buffer, remaining) == pdFALSE) {
|
||||
if (!timeout) return NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -750,6 +751,7 @@ camera_fb_t *cam_take(TickType_t timeout)
|
||||
if (dma_reset_counter < MAX_GDMA_RESETS) {
|
||||
ll_cam_dma_reset(cam_obj);
|
||||
dma_reset_counter++;
|
||||
if (!timeout) return NULL;
|
||||
continue; /* retry with queue timeout */
|
||||
}
|
||||
if (dma_reset_counter == MAX_GDMA_RESETS) {
|
||||
@@ -762,6 +764,7 @@ camera_fb_t *cam_take(TickType_t timeout)
|
||||
CAM_WARN_THROTTLE(warn_null_cnt,
|
||||
"Unexpected NULL frame on " CONFIG_IDF_TARGET);
|
||||
#endif
|
||||
if (!timeout) return NULL;
|
||||
vTaskDelay(1); /* immediate yield once resets are done */
|
||||
continue; /* go to top of loop */
|
||||
}
|
||||
@@ -802,6 +805,7 @@ skip_eoi_check:
|
||||
CAM_WARN_THROTTLE(warn_eoi_miss_cnt,
|
||||
"NO-EOI - JPEG end marker missing");
|
||||
cam_give(dma_buffer);
|
||||
if (!timeout) return NULL;
|
||||
continue; /* wait for another frame */
|
||||
} else if (cam_obj->psram_mode &&
|
||||
cam_obj->in_bytes_per_pixel != cam_obj->fb_bytes_per_pixel) {
|
||||
@@ -818,6 +822,24 @@ skip_eoi_check:
|
||||
}
|
||||
}
|
||||
|
||||
camera_fb_t *cam_take_latest(TickType_t timeout, uint32_t *skipped)
|
||||
{
|
||||
if (skipped) *skipped = 0;
|
||||
camera_fb_t *latest = cam_take(timeout);
|
||||
if (!latest) return NULL;
|
||||
/* A bounded drain, not availability-check + blocking get: the producer can
|
||||
* replace queued buffers on the other core. Retain the valid frame if a
|
||||
* newer candidate is invalid or a GDMA-reset sentinel is encountered. */
|
||||
for (size_t i = 1; i < cam_obj->frame_cnt; i++) {
|
||||
camera_fb_t *next = cam_take(0);
|
||||
if (!next) break;
|
||||
cam_give(latest);
|
||||
latest = next;
|
||||
if (skipped) (*skipped)++;
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
|
||||
void cam_give(camera_fb_t *dma_buffer)
|
||||
{
|
||||
for (int x = 0; x < cam_obj->frame_cnt; x++) {
|
||||
|
||||
Reference in New Issue
Block a user