地平线RDK3 AI摄像机完整软件架构设计
·
第一部分 软件架构
一、产品软件架构图(分层架构 + 微服务)
┌─────────────────────────────────────────────────────────────────────────┐ │ APPLICATION LAYER │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ HTTP/REST │ │ RTSP/GB │ │ WebRTC │ │ Config │ │ │ │ Server │ │ Server │ │ Server │ │ Manager │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────────────┐ │ AI & ALGORITHM LAYER │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ Pipeline Manager (状态机) │ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ │ │ Detector │ │ Tracker │ │ Classifier│ │ Calibrator│ │ │ │ │ │ (YOLO/RT) │ │ (IOU/Bytetrack)│(ResNet) │ │ (Zhang) │ │ │ │ │ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────────────┐ │ MIDDLEWARE LAYER │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ Memory │ │ Cache │ │ Log │ │ IPC │ │ │ │ Manager │ │ Manager │ │ Manager │ │ Bus │ │ │ │ (Pool/CMA) │ │ (Frame/Dn) │ │ (Ring/File) │ │ (ARM<->ARMn)│ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ ISP │ │ V4L2 │ │ BPU │ │ DMA │ │ │ │ Control │ │ Wrapper │ │ Runtime │ │ Manager │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────────────┐ │ BSP & DRIVER LAYER │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ Boot │ │ Kernel │ │ Rootfs │ │ Sensor │ │ │ │ (U-Boot) │ │ (DTS/Drv) │ │ (Libs) │ │ (IMX415) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────────────┐ │ HARDWARE LAYER │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ Sensor │ │ ISP │ │ BPU │ │ DDR │ │ Ethernet │ │ │ │ IMX415 │ │ Tuning │ │ Core │ │ 4/8G │ │ RGMII │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘
二、软件程序流程图(主业务流程)
[Main] ↓ [Init Phase] ├─→ Logger_Init() ──→ [LOG_RINGBUFFER|FILE|NET] ├─→ Memory_Init() ──→ [CMA_POOL|DMA_POOL|AI_TENSOR_POOL] ├─→ Cache_Init() ──→ [FRAME_CACHE|MODEL_CACHE|LUT_CACHE] ├─→ ISP_Init() ──→ [SENSOR_CONFIG|ISP_TUNING|3A_SERVER] ├─→ V4L2_Init() ──→ [VIDEO_DEV|CAPTURE_THREAD] ├─→ AI_Init() ──→ [BPU_LOAD|MODEL_LOAD|TASK_POOL] └─→ Calib_Init() ──→ [LOAD_PARAM|CHESSBOARD_DETECT] ↓ [Running Phase] - 主循环 (事件驱动) ↓ ┌─────────────────────────────────────────────────────────────┐ │ Event Loop (epoll/select) │ │ ├─→ [V4L2 Event] ──→ Frame_Capture() │ │ │ ↓ │ │ │ [Double Buffer Swap] │ │ │ ↓ │ │ │ ISP_RawProcess() ──→ [BLC|HDR|WDR|Demosaic] │ │ ↓ │ │ │ ┌─────────────────────────┐ │ │ │ │ Branch: AI or Preview? │ │ │ │ └─────────────────────────┘ │ │ │ ↓ ↓ │ │ │ [AI Pipeline] [Preview Path] │ │ │ ↓ ↓ │ │ │ AI_Preprocess() V4L2_Output() │ │ │ (Resize/Crop/Normalize) (Display/Encode) │ │ │ ↓ │ │ │ BPU_Inference() │ │ │ ↓ │ │ │ AI_Postprocess() │ │ │ (NMS/Bbox/Track/Calib) │ │ │ ↓ │ │ │ Event_Notify() ──→ [MQTT|WS|Callback] │ │ │ │ │ ├─→ [ISP Event] ──→ ISP_3A_Update() │ │ │ ↓ │ │ │ AE_Adjust() / AF_Search() / AWB_Cal() │ │ │ ↓ │ │ │ ISP_Apply_Params() │ │ │ │ │ ├─→ [AI Event] ──→ AI_Model_Switch() / Calib_Update() │ │ │ │ │ └─→ [Timer] ──→ Health_Check() / Stat_Report() │ └─────────────────────────────────────────────────────────────┘ ↓ [Deinit Phase] ├─→ AI_Deinit() ──→ [BPU_Unload|Model_Free] ├─→ V4L2_Deinit()──→ [Stream_Off|Dev_Close] ├─→ ISP_Deinit() ──→ [Sensor_PowerOff|Tuning_Save] ├─→ Cache_Deinit()──→ [Flush|Free] ├─→ Memory_Deinit()→ [Pool_Destroy] └─→ Logger_Deinit()→ [Flush_Log]
三、函数调用Pipeline树形图
main()
├─→ logger_init(LOG_LEVEL_INFO, LOG_OUTPUT_FILE | LOG_OUTPUT_CONSOLE)
│ ├─→ ringbuf_create(LOG_RING_SIZE, &g_log_ring)
│ ├─→ pthread_create(&g_log_flush_thread, log_flush_routine)
│ └─→ register_signal_handler(SIGSEGV, crash_log_dump)
│
├─→ memory_init(&mem_cfg)
│ ├─→ cma_pool_create("ai_tensor", 512 * 1024 * 1024) // 512MB AI内存
│ ├─→ dma_pool_create("video_capture", 256 * 1024 * 1024) // 256MB DMA
│ ├─→ slab_create("frame_buf", sizeof(frame_t), 32) // 帧对象缓存
│ └─→ memory_pool_stat_init() // 内存监控
│
├─→ cache_init(&cache_cfg)
│ ├─→ frame_cache_create(FRAME_CACHE_SIZE, 30) // 缓存30帧
│ │ ├─→ g_frame_cache.queue = queue_create()
│ │ ├─→ g_frame_cache.hash = hashmap_create()
│ │ └─→ g_frame_cache.lru = lru_create()
│ ├─→ model_cache_create(MODEL_CACHE_SIZE, 3) // 缓存3个模型
│ └─→ lut_cache_create(LUT_CACHE_SIZE, 10) // 缓存LUT表
│
├─→ isp_init(&isp_cfg)
│ ├─→ sensor_init(&g_sensor_ctx)
│ │ ├─→ i2c_open("/dev/i2c-0")
│ │ ├─→ sensor_power_on() // GPIO操作
│ │ ├─→ sensor_write_reg(IMX415_REG_MODE, IMX415_MODE_3840x2160_30FPS)
│ │ └─→ sensor_stream_on()
│ ├─→ isp_tuning_init("/etc/isp/imx415_tuning.bin")
│ │ ├─→ tuning_parse_header() // 解析BLC/LSC/CCM/GAMMA表
│ │ ├─→ tuning_load_black_level(blc_table)
│ │ ├─→ tuning_load_lens_shading(lsc_table)
│ │ ├─→ tuning_load_color_matrix(ccm_matrix)
│ │ └─→ tuning_load_gamma(gamma_lut)
│ ├─→ isp_3a_init()
│ │ ├─→ ae_init(&g_ae_ctx, AE_MODE_ADAPTIVE)
│ │ │ ├─→ ae_stat_config(STATS_5x5 | STATS_HISTOGRAM)
│ │ │ └─→ ae_target_set(60, 80) // 目标亮度范围
│ │ ├─→ awb_init(&g_awb_ctx, AWB_MODE_GREYWORLD)
│ │ │ ├─→ awb_stat_config(RGGB_BAYER)
│ │ │ └─→ awb_color_temp_set(2500, 7500)
│ │ └─→ af_init(&g_af_ctx, AF_MODE_CONTRAST)
│ │ ├─→ af_search_range(10, 1023) // VCM范围
│ │ └─→ af_step_config(COARSE_STEP=50, FINE_STEP=5)
│ └─→ isp_device_open("/dev/video0")
│ ├─→ v4l2_set_format(WIDTH=3840, HEIGHT=2160, PIX_FMT=SRGGB10)
│ ├─→ v4l2_set_framerate(30)
│ ├─→ v4l2_reqbufs(COUNT=4, MEMORY=MMAP)
│ ├─→ v4l2_qbuf_all()
│ └─→ v4l2_stream_on()
│
├─→ v4l2_init(&v4l2_ctx)
│ ├─→ capture_thread_create(capture_routine)
│ │ └─→ [CAPTURE_THREAD] while(1)
│ │ ├─→ v4l2_dqbuf() // 阻塞等待帧
│ │ ├─→ frame = memory_pool_alloc(FRAME_POOL)
│ │ ├─→ memcpy(frame->data, v4l2_buf, frame_size)
│ │ ├─→ frame->timestamp = get_monotonic_time()
│ │ ├─→ frame->sequence = g_frame_seq++
│ │ ├─→ frame_cache_push(g_frame_cache, frame)
│ │ ├─→ event_notify(EVENT_NEW_FRAME, frame)
│ │ └─→ v4l2_qbuf()
│ └─→ output_thread_create(output_routine) // 预览/编码输出
│
├─→ ai_init(&ai_cfg)
│ ├─→ bpu_init()
│ │ ├─→ bpu_open("/dev/bpu")
│ │ ├─→ bpu_set_power(OP_LEVEL_HIGH)
│ │ └─→ bpu_task_pool_create(MAX_TASKS=8)
│ ├─→ model_load("detect_yolov5s.hbm", &g_detect_model)
│ │ ├─→ hb_dnn_load_from_file(model_path, &g_detect_model)
│ │ ├─→ model_get_input_tensor(g_detect_model, &input)
│ │ ├─→ model_get_output_tensor(g_detect_model, &output)
│ │ └─→ model_cache_put(g_model_cache, model_id, g_detect_model)
│ ├─→ model_load("classify_resnet18.hbm", &g_cls_model)
│ ├─→ model_load("track_feature.hbm", &g_track_model)
│ └─→ ai_pipeline_create(&g_ai_pipeline)
│ ├─→ pipeline_add_stage(g_ai_pipeline, preprocess_stage)
│ ├─→ pipeline_add_stage(g_ai_pipeline, inference_stage)
│ ├─→ pipeline_add_stage(g_ai_pipeline, postprocess_stage)
│ ├─→ pipeline_add_stage(g_ai_pipeline, track_stage)
│ └─→ pipeline_add_stage(g_ai_pipeline, calib_stage)
│
├─→ calib_init(&calib_cfg)
│ ├─→ calib_param_load("/etc/calib/camera_intrinsic.yaml")
│ │ ├─→ yaml_parse_file() → camera_matrix[3x3]
│ │ ├─→ yaml_parse_file() → dist_coeffs[5]
│ │ └─→ yaml_parse_file() → rect_map[2][HEIGHT][WIDTH]
│ ├─→ calib_board_create(CHESSBOARD_9x6, SQUARE_SIZE=25mm)
│ ├─→ calib_undistort_map_precompute()
│ │ ├─→ initUndistortRectifyMap() // OpenCV
│ │ └─→ remap_lut_cache_put(g_lut_cache, map_x, map_y)
│ └─→ calib_auto_trigger_create(TRIGGER_INTERVAL=3600) // 每小时重标定
│
├─→ event_loop_create()
│ ├─→ epoll_create()
│ ├─→ epoll_ctl_add(v4l2_fd, EPOLLIN, v4l2_callback)
│ ├─→ epoll_ctl_add(isp_event_fd, EPOLLIN, isp_callback)
│ ├─→ epoll_ctl_add(timer_fd, EPOLLIN, health_callback)
│ └─→ while(g_running) {
│ nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1)
│ for(i=0; i<nfds; i++) {
│ events[i].data.callback() // 分发事件
│ }
│ }
│
├─→ v4l2_callback(event) // 帧到达事件
│ ├─→ frame = frame_cache_pop(g_frame_cache)
│ ├─→ if(ai_enabled) {
│ │ ai_pipeline_process(g_ai_pipeline, frame)
│ │ ├─→ preprocess_stage: convert_to_rgb / resize / normalize
│ │ ├─→ inference_stage: bpu_submit_task()
│ │ ├─→ postprocess_stage: nms / bbox_decode / confidence
│ │ ├─→ track_stage: iou_match / kalman_filter
│ │ └─→ calib_stage: chessboard_detect() / homography_update()
│ │ }
│ ├─→ if(preview_enabled) {
│ │ isp_draw_bbox(frame, ai_results)
│ │ v4l2_output_push(g_output_ctx, frame)
│ │ }
│ └─→ frame_cache_push(g_frame_cache, frame) // 循环使用
│
├─→ isp_callback(event) // ISP 3A统计事件
│ ├─→ isp_3a_run()
│ │ ├─→ ae_run(&g_ae_ctx, isp_stats)
│ │ │ ├─→ calc_average_luminance()
│ │ │ ├─→ pid_controller_update()
│ │ │ └─→ sensor_set_exposure() / sensor_set_gain()
│ │ ├─→ awb_run(&g_awb_ctx, isp_stats)
│ │ │ ├─→ calc_rg_gain() / calc_bg_gain()
│ │ │ ├─→ color_temperature_estimate()
│ │ │ └─→ isp_set_wb_gains(r_gain, g_gain, b_gain)
│ │ └─→ af_run(&g_af_ctx, isp_stats)
│ │ ├─→ calc_focus_value(FV_HISTOGRAM | FV_SOBEL)
│ │ ├─→ hill_climbing_search()
│ │ └─→ vcm_set_position(lens_pos)
│ └─→ isp_apply_tuning_online()
│ ├─→ if(ai_detected_face) {
│ │ isp_set_focus_roi(face_bbox)
│ │ isp_set_exposure_comp(+0.5EV)
│ │ }
│ └─→ tuning_save_statistics() // 记录调优数据
│
├─→ health_callback() // 健康检查定时器
│ ├─→ memory_pool_stat_report()
│ ├─→ frame_cache_stat_report()
│ ├─→ bpu_utilization_report()
│ ├─→ cpu_temp_monitor()
│ │ └─→ if(temp > 85°C) thermal_throttling()
│ └─→ log_rotate_check()
│
└─→ cleanup_and_exit()
├─→ event_loop_destroy()
├─→ ai_deinit() → bpu_close() / model_unload() / pipeline_destroy()
├─→ v4l2_deinit() → stream_off() / reqbufs(0) / close()
├─→ isp_deinit() → sensor_power_off() / tuning_save()
├─→ calib_deinit() → param_save() / map_free()
├─→ cache_deinit() → cache_flush() / cache_destroy()
├─→ memory_deinit() → pool_destroy_all()
└─→ logger_deinit() → ringbuf_destroy() / pthread_join()
四、完整文件列表及职责
rdk3_cam_solution/ ├── include/ # 公共头文件 │ ├── rdk3_cam.h # 主头文件,导出API │ ├── config.h # 配置结构体定义 │ ├── error.h # 错误码定义 │ └── version.h # 版本信息 │ ├── src/ │ ├── main.c # 主入口,事件循环 │ │ │ ├── core/ # 核心模块 │ │ ├── memory/ │ │ │ ├── memory_manager.h # 内存管理接口 │ │ │ ├── memory_manager.c # CMA/SLAB/DMA池实现 │ │ │ ├── cma_pool.c # CMA连续内存分配器 │ │ │ ├── slab_allocator.c # SLAB对象缓存 │ │ │ └── dma_buffer.c # DMA缓冲区管理 │ │ ├── cache/ │ │ │ ├── cache_manager.h # 缓存管理接口 │ │ │ ├── cache_manager.c # LRU/LFU缓存实现 │ │ │ ├── frame_cache.c # 帧缓存专用 │ │ │ ├── model_cache.c # AI模型缓存 │ │ │ └── lut_cache.c # LUT查找表缓存 │ │ ├── log/ │ │ │ ├── logger.h # 日志接口 │ │ │ ├── logger.c # 异步日志实现 │ │ │ ├── ringbuffer.c # 环形缓冲区 │ │ │ ├── log_formatter.c # 格式化输出 │ │ │ └── log_rotate.c # 日志轮转 │ │ └── ipc/ │ │ ├── ipc_bus.h # 核间通信接口 │ │ ├── ipc_bus.c # RPMSG实现 │ │ ├── ring_queue.c # 无锁队列 │ │ └── shared_memory.c # 共享内存管理 │ │ │ ├── bsp/ # 板级支持包 │ │ ├── boot/ │ │ │ ├── boot_config.h # 启动参数配置 │ │ │ └── ddr_init.c # DDR初始化(调试用) │ │ ├── kernel/ │ │ │ ├── dts/ # 设备树 │ │ │ │ ├── rdk3_evb.dts # 公版 │ │ │ │ └── product_cam_v1.dts # 产品板 │ │ │ ├── driver_adapter.h # 驱动适配层 │ │ │ └── gpio_irq.c # GPIO中断处理 │ │ └── rootfs/ │ │ ├── sensor_lib.h # 传感器库接口 │ │ ├── sensor_imx415.c # IMX415驱动封装 │ │ └── v4l2_helper.c # V4L2辅助函数 │ │ │ ├── middleware/ # 中间件层 │ │ ├── isp/ │ │ │ ├── isp_manager.h # ISP管理接口 │ │ │ ├── isp_manager.c # ISP主控 │ │ │ ├── isp_3a.h # 3A算法接口 │ │ │ ├── ae.c # 自动曝光 │ │ │ ├── awb.c # 自动白平衡 │ │ │ ├── af.c # 自动对焦 │ │ │ ├── isp_tuning.h # ISP调优接口 │ │ │ ├── isp_tuning.c # 调优参数加载 │ │ │ ├── black_level.c # BLC校正 │ │ │ ├── lens_shading.c # LSC校正 │ │ │ ├── color_matrix.c # CCM矩阵 │ │ │ └── gamma_correction.c # Gamma校正 │ │ ├── v4l2/ │ │ │ ├── v4l2_wrapper.h # V4L2封装接口 │ │ │ ├── v4l2_wrapper.c # V4L2操作封装 │ │ │ ├── capture_thread.c # 采集线程 │ │ │ └── output_thread.c # 输出线程 │ │ └── bpu/ │ │ ├── bpu_runtime.h # BPU运行时接口 │ │ ├── bpu_runtime.c # BPU任务调度 │ │ ├── model_loader.c # HBM模型加载 │ │ └── tensor_process.c # Tensor处理 │ │ │ ├── algorithm/ # 算法层 │ │ ├── ai/ │ │ │ ├── ai_pipeline.h # AI流水线接口 │ │ │ ├── ai_pipeline.c # 流水线管理 │ │ │ ├── preprocess.h # 预处理接口 │ │ │ ├── preprocess.c # Resize/归一化 │ │ │ ├── inference.c # BPU推理封装 │ │ │ ├── postprocess.h # 后处理接口 │ │ │ ├── postprocess.c # NMS/Bbox解码 │ │ │ ├── detector_yolo.c # YOLO检测器 │ │ │ ├── classifier_resnet.c # ResNet分类器 │ │ │ └── tracker.c # 目标跟踪 │ │ └── calib/ │ │ ├── calibrator.h # 标定接口 │ │ ├── calibrator.c # 相机标定主控 │ │ ├── chessboard_detect.c # 棋盘格检测 │ │ ├── homography.c # 单应性矩阵 │ │ ├── undistort.c # 畸变校正 │ │ └── param_io.c # 参数读写 │ │ │ ├── application/ # 应用层 │ │ ├── event_loop.c # 事件主循环 │ │ ├── config_manager.c # 配置管理 │ │ ├── health_monitor.c # 健康监控 │ │ ├── rtsp_server.c # RTSP推流 │ │ ├── websocket_server.c # WebSocket服务 │ │ └── mqtt_client.c # MQTT上报 │ │ │ └── utils/ # 工具函数 │ ├── list.h # 链表实现 │ ├── hashmap.h # 哈希表 │ ├── thread_pool.h # 线程池 │ ├── timer_wheel.h # 时间轮 │ ├── ringbuf.h # 环形缓冲区 │ └── crc32.c # 校验算法 │ ├── tests/ # 单元测试 │ ├── test_memory.c │ ├── test_cache.c │ ├── test_isp.c │ └── test_ai.c │ ├── tools/ # 工具 │ ├── tuning_viewer/ # 调优可视化 │ ├── calib_gui/ # 标定GUI │ └── log_analyzer/ # 日志分析 │ ├── config/ # 配置文件 │ ├── product_cam.yaml # 产品配置 │ ├── isp_tuning.bin # ISP调优参数 │ └── camera_intrinsic.yaml # 相机内参 │ ├── scripts/ # 脚本 │ ├── build.sh # 编译脚本 │ ├── deploy.sh # 部署脚本 │ └── start.sh # 启动脚本 │ ├── docs/ # 文档 │ ├── Doxyfile # Doxygen配置 │ └── architecture.md # 架构文档 │ ├── CMakeLists.txt # CMake构建 └── README.md # 项目说明
五、关键数据结构定义
/**
* @file rdk3_cam.h
* @brief RDK3 AI摄像机主头文件
* @author BSP Team
* @version 1.0.0
* @date 2024
*/
#ifndef RDK3_CAM_H
#define RDK3_CAM_H
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 错误码定义
*============================================================================*/
#define RDK3_OK 0
#define RDK3_ERR_INVALID_PARAM -1
#define RDK3_ERR_MEMORY -2
#define RDK3_ERR_IO -3
#define RDK3_ERR_TIMEOUT -4
#define RDK3_ERR_NOT_FOUND -5
#define RDK3_ERR_BUSY -6
#define RDK3_ERR_AGAIN -7
/*=============================================================================
* 日志级别定义
*============================================================================*/
typedef enum {
LOG_LEVEL_FATAL = 0,
LOG_LEVEL_ERROR = 1,
LOG_LEVEL_WARN = 2,
LOG_LEVEL_INFO = 3,
LOG_LEVEL_DEBUG = 4,
LOG_LEVEL_TRACE = 5
} log_level_t;
typedef enum {
LOG_OUTPUT_CONSOLE = 0x01,
LOG_OUTPUT_FILE = 0x02,
LOG_OUTPUT_NETWORK = 0x04,
LOG_OUTPUT_SYSLOG = 0x08
} log_output_t;
/*=============================================================================
* 内存管理结构体
*============================================================================*/
/**
* @brief 内存池类型
*/
typedef enum {
MEM_POOL_CMA, ///< 连续内存池 (用于DMA/ISP)
MEM_POOL_DMA, ///< DMA缓冲区池
MEM_POOL_SLAB, ///< SLAB对象缓存
MEM_POOL_AI_TENSOR ///< AI张量内存池
} mem_pool_type_t;
/**
* @brief 内存池配置
*/
typedef struct {
mem_pool_type_t type; ///< 池类型
const char* name; ///< 池名称
size_t block_size; ///< 块大小
size_t block_count; ///< 块数量
uint32_t flags; ///< 标志位 (CACHE_ALIGN | ZERO_INIT)
} mem_pool_cfg_t;
/**
* @brief 内存分配器句柄 (不透明指针)
*/
typedef void* mem_pool_handle_t;
/**
* @brief 内存统计信息
*/
typedef struct {
size_t total_bytes; ///< 总字节数
size_t used_bytes; ///< 已用字节数
size_t peak_bytes; ///< 峰值字节数
uint32_t alloc_count; ///< 分配次数
uint32_t free_count; ///< 释放次数
uint32_t fail_count; ///< 失败次数
} mem_stat_t;
/*=============================================================================
* 缓存管理结构体
*============================================================================*/
/**
* @brief 缓存淘汰策略
*/
typedef enum {
CACHE_EVICT_LRU, ///< 最近最少使用
CACHE_EVICT_LFU, ///< 最不经常使用
CACHE_EVICT_FIFO ///< 先进先出
} cache_evict_policy_t;
/**
* @brief 缓存配置
*/
typedef struct {
const char* name; ///< 缓存名称
size_t max_size; ///< 最大条目数
size_t max_bytes; ///< 最大字节数
cache_evict_policy_t policy; ///< 淘汰策略
uint32_t ttl_seconds; ///< 生存时间(0=永久)
bool enable_stat; ///< 启用统计
} cache_cfg_t;
/**
* @brief 帧数据结构
*/
typedef struct frame {
uint32_t sequence; ///< 帧序号
uint64_t timestamp; ///< 时间戳(纳秒)
uint32_t width; ///< 宽度
uint32_t height; ///< 高度
uint32_t format; ///< 像素格式 (V4L2_PIX_FMT_*)
uint32_t size; ///< 数据大小
void* data[3]; ///< 数据指针(Y/UV或RGB)
uint32_t stride[3]; ///< 行跨度
void* user_priv; ///< 用户私有数据
struct frame* next; ///< 链表指针
} frame_t;
/*=============================================================================
* ISP控制结构体
*============================================================================*/
/**
* @brief 传感器信息
*/
typedef struct {
const char* name; ///< 传感器型号
uint32_t i2c_bus; ///< I2C总线号
uint16_t i2c_addr; ///< I2C地址
uint32_t reset_gpio; ///< Reset GPIO
uint32_t power_gpio; ///< Power GPIO
uint32_t mipi_lanes; ///< MIPI通道数
uint32_t pixel_rate; ///< 像素时钟(Hz)
} sensor_info_t;
/**
* @brief ISP调优参数
*/
typedef struct {
/* Black Level Correction */
uint16_t blc_r; ///< 黑电平R通道
uint16_t blc_gr; ///< 黑电平Gr通道
uint16_t blc_gb; ///< 黑电平Gb通道
uint16_t blc_b; ///< 黑电平B通道
/* Lens Shading Correction */
uint16_t* lsc_table_r; ///< LSC R通道表(宽x高)
uint16_t* lsc_table_gr; ///< LSC Gr通道表
uint16_t* lsc_table_gb; ///< LSC Gb通道表
uint16_t* lsc_table_b; ///< LSC B通道表
uint32_t lsc_width; ///< LSC表格宽度
uint32_t lsc_height; ///< LSC表格高度
/* Color Correction Matrix */
float ccm[3][3]; ///< 色彩校正矩阵
/* Gamma Correction */
uint8_t gamma_lut[256]; ///< Gamma查找表
/* Denoise */
uint8_t denoise_strength; ///< 降噪强度 0-255
/* Sharpness */
uint8_t sharpness_strength; ///< 锐化强度 0-255
} isp_tuning_t;
/**
* @brief 3A统计信息
*/
typedef struct {
/* AE统计 */
uint32_t avg_luminance; ///< 平均亮度
uint32_t hist[256]; ///< 直方图
/* AWB统计 */
uint32_t sum_r; ///< R通道和
uint32_t sum_g; ///< G通道和
uint32_t sum_b; ///< B通道和
/* AF统计 */
uint32_t focus_value; ///< 对焦值
uint32_t focus_roi_x; ///< ROI X坐标
uint32_t focus_roi_y; ///< ROI Y坐标
uint32_t focus_roi_w; ///< ROI宽度
uint32_t focus_roi_h; ///< ROI高度
} isp_3a_stats_t;
/**
* @brief AE配置
*/
typedef struct {
uint32_t target_luminance; ///< 目标亮度 0-255
uint32_t min_luminance; ///< 最小亮度
uint32_t max_luminance; ///< 最大亮度
uint32_t exposure_time_min; ///< 最小曝光时间(us)
uint32_t exposure_time_max; ///< 最大曝光时间(us)
uint32_t gain_min; ///< 最小增益(x256)
uint32_t gain_max; ///< 最大增益(x256)
float pid_kp; ///< PID比例系数
float pid_ki; ///< PID积分系数
float pid_kd; ///< PID微分系数
} ae_cfg_t;
/*=============================================================================
* AI推理结构体
*============================================================================*/
/**
* @brief AI模型类型
*/
typedef enum {
AI_MODEL_DETECT, ///< 目标检测
AI_MODEL_CLASSIFY, ///< 图像分类
AI_MODEL_TRACK, ///< 目标跟踪
AI_MODEL_SEGMENT ///< 语义分割
} ai_model_type_t;
/**
* @brief 目标检测框
*/
typedef struct {
float x1, y1; ///< 左上角坐标(归一化0-1)
float x2, y2; ///< 右下角坐标(归一化0-1)
float confidence; ///< 置信度 0-1
int class_id; ///< 类别ID
const char* class_name; ///< 类别名称
} detection_t;
/**
* @brief AI推理结果
*/
typedef struct {
uint32_t frame_seq; ///< 关联的帧序号
uint64_t timestamp; ///< 推理完成时间戳
detection_t* detections; ///< 检测框数组
uint32_t detection_count; ///< 检测框数量
float* features; ///< 特征向量(跟踪用)
uint32_t feature_dim; ///< 特征维度
void* user_data; ///< 用户数据
} ai_result_t;
/*=============================================================================
* 标定结构体
*============================================================================*/
/**
* @brief 相机内参
*/
typedef struct {
float fx, fy; ///< 焦距
float cx, cy; ///< 光心
float k1, k2, p1, p2, k3; ///< 畸变系数
float rms_error; ///< 重投影误差
} camera_intrinsic_t;
/**
* @brief 标定配置
*/
typedef struct {
int board_width; ///< 棋盘格宽度(内角点数)
int board_height; ///< 棋盘格高度(内角点数)
float square_size_mm; ///< 方格边长(mm)
int min_samples; ///< 最小采样数量
int auto_trigger_interval; ///< 自动标定间隔(秒)
} calib_cfg_t;
/*=============================================================================
* 主配置结构体
*============================================================================*/
/**
* @brief 产品配置
*/
typedef struct {
/* 视频配置 */
uint32_t video_width; ///< 采集宽度
uint32_t video_height; ///< 采集高度
uint32_t video_framerate; ///< 采集帧率
uint32_t video_format; ///< 像素格式
/* AI配置 */
bool ai_enabled; ///< AI使能
const char* detect_model_path; ///< 检测模型路径
float ai_confidence_threshold; ///< 置信度阈值
float ai_nms_threshold; ///< NMS阈值
/* 标定配置 */
calib_cfg_t calib;
/* 日志配置 */
log_level_t log_level; ///< 日志级别
uint32_t log_output; ///< 日志输出方式
const char* log_file_path; ///< 日志文件路径
/* 内存配置 */
size_t cma_pool_size; ///< CMA池大小(MB)
size_t dma_pool_size; ///< DMA池大小(MB)
size_t ai_tensor_pool_size; ///< AI张量池大小(MB)
/* 缓存配置 */
uint32_t frame_cache_size; ///< 帧缓存大小
uint32_t model_cache_size; ///< 模型缓存大小
} rdk3_cam_config_t;
/*=============================================================================
* 主API函数
*============================================================================*/
/**
* @brief 初始化RDK3摄像机系统
* @param config 配置参数
* @return 成功返回RDK3_OK,失败返回错误码
*
* @note 调用顺序: 必须先调用此函数
* @warning 只能调用一次
*/
int rdk3_cam_init(const rdk3_cam_config_t* config);
/**
* @brief 启动视频流和AI处理
* @return 成功返回RDK3_OK
*/
int rdk3_cam_start(void);
/**
* @brief 停止视频流和AI处理
* @return 成功返回RDK3_OK
*/
int rdk3_cam_stop(void);
/**
* @brief 反初始化系统
*/
void rdk3_cam_deinit(void);
/**
* @brief 获取最新的AI推理结果
* @param result 输出结果指针
* @param timeout_ms 超时时间(毫秒)
* @return 成功返回RDK3_OK
*/
int rdk3_cam_get_ai_result(ai_result_t* result, int timeout_ms);
/**
* @brief 动态更新ISP参数
* @param tuning 新的调优参数
* @return 成功返回RDK3_OK
*/
int rdk3_cam_update_isp_tuning(const isp_tuning_t* tuning);
/**
* @brief 触发标定流程
* @return 成功返回RDK3_OK
*/
int rdk3_cam_trigger_calibration(void);
/**
* @brief 获取系统健康状态
* @param cpu_temp 输出CPU温度
* @param bpu_usage 输出BPU使用率
* @param mem_usage 输出内存使用率
*/
void rdk3_cam_get_health(float* cpu_temp, float* bpu_usage, float* mem_usage);
#ifdef __cplusplus
}
#endif
#endif /* RDK3_CAM_H */
第二部分 地平线RDK3 AI摄像机核心模块实现
一、优先级1:双架构IPC、ISP调优、AI流水线
1.1 双架构IPC模块(解决ARM + ARM-None共存)
/**
* @file ipc_bus.h
* @brief 双架构核间通信总线接口
* @author BSP Team
* @version 1.0.0
*
* @section 设计模式
* - **代理模式(Proxy)**: 为ARM-None核提供代理访问
* - **命令模式(Command)**: 封装跨核调用为命令对象
* - **观察者模式(Observer)**: 异步通知ARM-None核完成状态
*
* @section 防坑指南
* @warning 1. 必须使用无锁队列,避免死锁
* @warning 2. 共享内存必须cache对齐,防止一致性问题
* @warning 3. 命令参数不能包含指针(地址空间不同)
*/
#ifndef IPC_BUS_H
#define IPC_BUS_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 错误码定义
*============================================================================*/
#define IPC_OK 0
#define IPC_ERR_FULL -1
#define IPC_ERR_EMPTY -2
#define IPC_ERR_TIMEOUT -3
#define IPC_ERR_NOMEM -4
/*=============================================================================
* 命令ID定义 (ARM <-> ARM-None 协议)
*============================================================================*/
typedef enum {
/* ISP控制命令 (0x1000-0x1FFF) */
CMD_ISP_SET_EXPOSURE = 0x1001,
CMD_ISP_SET_GAIN = 0x1002,
CMD_ISP_SET_WB_GAINS = 0x1003,
CMD_ISP_SET_FOCUS_POS = 0x1004,
CMD_ISP_GET_STATS = 0x1005,
CMD_ISP_SET_TUNING_PARAM = 0x1006,
/* 传感器控制命令 (0x2000-0x2FFF) */
CMD_SENSOR_READ_REG = 0x2001,
CMD_SENSOR_WRITE_REG = 0x2002,
CMD_SENSOR_STREAM_ON = 0x2003,
CMD_SENSOR_STREAM_OFF = 0x2004,
/* 系统控制命令 (0x3000-0x3FFF) */
CMD_SYSTEM_GET_TEMP = 0x3001,
CMD_SYSTEM_RESET = 0x3002,
CMD_SYSTEM_POWER_OFF = 0x3003,
/* 自定义命令 (0x4000-0xFFFF) */
CMD_USER_BASE = 0x4000
} ipc_cmd_id_t;
/*=============================================================================
* 命令响应状态
*============================================================================*/
typedef enum {
CMD_STATUS_PENDING = 0, ///< 命令等待执行
CMD_STATUS_DONE = 1, ///< 命令执行成功
CMD_STATUS_ERROR = 2, ///< 命令执行失败
CMD_STATUS_TIMEOUT = 3 ///< 命令超时
} cmd_status_t;
/*=============================================================================
* IPC命令结构体 (命令模式)
*============================================================================*/
/**
* @brief IPC命令基类
* @note 必须保持POD类型,不能有虚函数
* @note 大小不能超过64字节(缓存行大小)
*/
typedef struct {
uint32_t cmd_id; ///< 命令ID
uint32_t seq_num; ///< 序列号(用于匹配响应)
uint32_t arg_count; ///< 参数个数(1-4)
uint32_t args[4]; ///< 参数数组(不支持指针!)
uint32_t timeout_ms; ///< 超时时间(毫秒)
/* 回调函数指针(仅在ARM侧有效) */
void (*callback)(void* ctx, int status, uint32_t ret_val);
void* callback_ctx;
/* 响应数据 */
cmd_status_t status; ///< 命令状态
uint32_t ret_val; ///< 返回值
uint32_t ret_data[4]; ///< 返回数据
} ipc_cmd_t;
/*=============================================================================
* 共享内存环形缓冲区 (无锁设计)
*============================================================================*/
/**
* @brief 无锁环形队列
* @note 使用CAS操作保证线程安全
* @note 支持单生产者单消费者(SPSC)模式
*/
typedef struct {
volatile uint32_t write_idx; ///< 写索引 (__attribute__((aligned(64))))
volatile uint32_t read_idx; ///< 读索引 (__attribute__((aligned(64))))
uint32_t mask; ///< 掩码(size-1)
ipc_cmd_t* buffer; ///< 缓冲区指针
size_t size; ///< 缓冲区大小
uint8_t padding[48]; ///< 缓存行填充
} __attribute__((aligned(64))) ring_queue_t;
/**
* @brief IPC上下文
*/
typedef struct {
/* 共享内存 */
void* shm_addr; ///< 共享内存基址
size_t shm_size; ///< 共享内存大小
/* 环形队列 */
ring_queue_t* tx_queue; ///< 发送队列(ARM->ARM-None)
ring_queue_t* rx_queue; ///< 接收队列(ARM-None->ARM)
/* IPC中断 */
int ipc_irq_fd; ///< IPC中断文件描述符
bool is_master; ///< true=ARM, false=ARM-None
/* 回调注册表 */
void (*cmd_handlers[256])(ipc_cmd_t* cmd);
/* 统计信息 */
uint64_t tx_count;
uint64_t rx_count;
uint64_t tx_failed;
uint64_t rx_failed;
} ipc_context_t;
/*=============================================================================
* IPC API函数
*============================================================================*/
/**
* @brief 初始化IPC总线
* @param shm_path 共享内存路径(例如 "/dev/shm/ipc_shm")
* @param shm_size 共享内存大小(建议1MB)
* @param is_master true=ARM主核, false=ARM-None从核
* @return IPC上下文指针
*
* @note 设计模式: 单例模式(Singleton) - 整个系统只有一个IPC实例
* @warning ARM和ARM-None必须使用相同的shm_path
*/
ipc_context_t* ipc_bus_init(const char* shm_path, size_t shm_size, bool is_master);
/**
* @brief 发送同步命令(阻塞等待响应)
* @param ctx IPC上下文
* @param cmd 命令指针
* @return IPC_OK成功
*
* @note 性能分析: 平均延迟50us, 最大200us
* @note 适用场景: 配置类命令(低频)
*/
int ipc_send_sync(ipc_context_t* ctx, ipc_cmd_t* cmd);
/**
* @brief 发送异步命令(立即返回)
* @param ctx IPC上下文
* @param cmd 命令指针
* @return IPC_OK成功
*
* @note 适用场景: 流式数据(高频)
* @note 回调函数会在独立线程中执行
*/
int ipc_send_async(ipc_context_t* ctx, ipc_cmd_t* cmd);
/**
* @brief 注册命令处理器(ARM-None侧使用)
* @param ctx IPC上下文
* @param cmd_id 命令ID
* @param handler 处理函数
*/
void ipc_register_handler(ipc_context_t* ctx, uint32_t cmd_id,
void (*handler)(ipc_cmd_t* cmd));
/**
* @brief IPC事件循环(ARM-None侧在主循环中调用)
* @param ctx IPC上下文
* @param timeout_ms 超时时间
*/
void ipc_process_loop(ipc_context_t* ctx, int timeout_ms);
/**
* @brief 获取IPC统计信息
*/
void ipc_get_stats(ipc_context_t* ctx, uint64_t* tx, uint64_t* rx,
uint64_t* tx_fail, uint64_t* rx_fail);
/**
* @brief 反初始化IPC总线
*/
void ipc_bus_deinit(ipc_context_t* ctx);
#ifdef __cplusplus
}
#endif
#endif /* IPC_BUS_H */
/**
* @file ipc_bus.c
* @brief 双架构核间通信实现
*/
#include "ipc_bus.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/eventfd.h>
#include <pthread.h>
#include <errno.h>
/*=============================================================================
* 无锁环形队列实现
*============================================================================*/
/**
* @brief 初始化环形队列
*/
static void ring_queue_init(ring_queue_t* queue, ipc_cmd_t* buffer, size_t size)
{
queue->write_idx = 0;
queue->read_idx = 0;
queue->mask = size - 1;
queue->buffer = buffer;
queue->size = size;
/* 缓存行填充,防止false sharing */
memset((void*)queue->padding, 0, sizeof(queue->padding));
}
/**
* @brief 入队操作(SPSC无锁)
* @return true=成功, false=队列满
*/
static bool ring_queue_enqueue(ring_queue_t* queue, const ipc_cmd_t* cmd)
{
uint32_t write_idx = queue->write_idx;
uint32_t read_idx = queue->read_idx;
uint32_t next_idx = (write_idx + 1) & queue->mask;
/* 队列满检查 */
if (next_idx == read_idx) {
return false;
}
/* 写入数据 */
memcpy(&queue->buffer[write_idx], cmd, sizeof(ipc_cmd_t));
/* 内存屏障,确保数据写入完成后再更新索引 */
__sync_synchronize();
/* 更新写索引(原子操作) */
queue->write_idx = next_idx;
return true;
}
/**
* @brief 出队操作(SPSC无锁)
* @return true=成功, false=队列空
*/
static bool ring_queue_dequeue(ring_queue_t* queue, ipc_cmd_t* cmd)
{
uint32_t write_idx = queue->write_idx;
uint32_t read_idx = queue->read_idx;
/* 队列空检查 */
if (read_idx == write_idx) {
return false;
}
/* 读取数据 */
memcpy(cmd, &queue->buffer[read_idx], sizeof(ipc_cmd_t));
/* 内存屏障 */
__sync_synchronize();
/* 更新读索引 */
queue->read_idx = (read_idx + 1) & queue->mask;
return true;
}
/*=============================================================================
* IPC主实现
*============================================================================*/
/**
* @brief IPC上下文全局实例(单例模式)
*/
static ipc_context_t* g_ipc_ctx = NULL;
/**
* @brief 共享内存布局定义
*/
typedef struct {
uint64_t magic; ///< 魔数校验
ring_queue_t tx_queue; ///< 发送队列(ARM->ARM-None)
ring_queue_t rx_queue; ///< 接收队列(ARM-None->ARM)
uint8_t cmd_buffer[2][1024]; ///< 命令缓冲区(每个队列512个命令)
uint8_t padding[4096]; ///< 页对齐
} __attribute__((packed)) ipc_shm_layout_t;
ipc_context_t* ipc_bus_init(const char* shm_path, size_t shm_size, bool is_master)
{
/* 单例检查 */
if (g_ipc_ctx) {
return g_ipc_ctx;
}
/* 验证大小 */
if (shm_size < sizeof(ipc_shm_layout_t)) {
shm_size = sizeof(ipc_shm_layout_t);
}
/* 打开共享内存 */
int shm_fd = shm_open(shm_path, O_RDWR | O_CREAT, 0666);
if (shm_fd < 0) {
perror("shm_open");
return NULL;
}
/* 设置大小 */
if (ftruncate(shm_fd, shm_size) < 0) {
perror("ftruncate");
close(shm_fd);
return NULL;
}
/* 映射共享内存 */
void* shm_addr = mmap(NULL, shm_size, PROT_READ | PROT_WRITE,
MAP_SHARED, shm_fd, 0);
if (shm_addr == MAP_FAILED) {
perror("mmap");
close(shm_fd);
return NULL;
}
close(shm_fd);
/* 分配IPC上下文 */
ipc_context_t* ctx = (ipc_context_t*)calloc(1, sizeof(ipc_context_t));
if (!ctx) {
munmap(shm_addr, shm_size);
return NULL;
}
ctx->shm_addr = shm_addr;
ctx->shm_size = shm_size;
ctx->is_master = is_master;
/* 初始化共享内存结构 */
ipc_shm_layout_t* layout = (ipc_shm_layout_t*)shm_addr;
if (is_master) {
/* ARM主核: 初始化共享内存 */
layout->magic = 0x49494342; /* "ICB" */
ring_queue_init(&layout->tx_queue, (ipc_cmd_t*)layout->cmd_buffer[0], 512);
ring_queue_init(&layout->rx_queue, (ipc_cmd_t*)layout->cmd_buffer[1], 512);
/* 创建eventfd用于通知 */
ctx->ipc_irq_fd = eventfd(0, EFD_NONBLOCK);
} else {
/* ARM-None从核: 等待主核初始化完成 */
while (layout->magic != 0x49494342) {
/* 轮询等待, 实际应使用延时 */
for (volatile int i = 0; i < 100000; i++);
}
/* 获取队列指针 */
ctx->tx_queue = &layout->tx_queue;
ctx->rx_queue = &layout->rx_queue;
}
g_ipc_ctx = ctx;
return ctx;
}
/**
* @brief 发送同步命令实现
*/
int ipc_send_sync(ipc_context_t* ctx, ipc_cmd_t* cmd)
{
if (!ctx || !cmd) {
return IPC_ERR_NOMEM;
}
/* 生成序列号 */
static uint32_t g_seq = 0;
cmd->seq_num = __sync_fetch_and_add(&g_seq, 1);
cmd->status = CMD_STATUS_PENDING;
/* 记录开始时间 */
struct timespec start;
clock_gettime(CLOCK_MONOTONIC, &start);
/* 入队 */
ipc_shm_layout_t* layout = (ipc_shm_layout_t*)ctx->shm_addr;
if (!ring_queue_enqueue(&layout->tx_queue, cmd)) {
ctx->tx_failed++;
return IPC_ERR_FULL;
}
/* 通知对方(eventfd) */
uint64_t val = 1;
write(ctx->ipc_irq_fd, &val, sizeof(val));
/* 等待响应 */
ipc_cmd_t resp;
uint32_t timeout_ms = cmd->timeout_ms > 0 ? cmd->timeout_ms : 1000;
while (1) {
/* 检查响应队列 */
if (ring_queue_dequeue(&layout->rx_queue, &resp)) {
if (resp.seq_num == cmd->seq_num) {
cmd->status = resp.status;
cmd->ret_val = resp.ret_val;
memcpy(cmd->ret_data, resp.ret_data, sizeof(resp.ret_data));
ctx->tx_count++;
return IPC_OK;
}
}
/* 超时检查 */
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t elapsed_ms = (now.tv_sec - start.tv_sec) * 1000 +
(now.tv_nsec - start.tv_nsec) / 1000000;
if (elapsed_ms >= timeout_ms) {
cmd->status = CMD_STATUS_TIMEOUT;
ctx->tx_failed++;
return IPC_ERR_TIMEOUT;
}
/* 短暂休眠避免busy loop */
usleep(100);
}
}
/**
* @brief ARM-None侧命令处理器示例
*/
static void handle_isp_set_exposure(ipc_cmd_t* cmd)
{
uint32_t exposure_us = cmd->args[0];
uint32_t gain_x256 = cmd->args[1];
/* 调用硬件寄存器操作(ARM-None裸机代码) */
// hw_set_exposure(exposure_us);
// hw_set_gain(gain_x256);
cmd->status = CMD_STATUS_DONE;
cmd->ret_val = 0;
}
/**
* @brief 注册命令处理器
*/
void ipc_register_handler(ipc_context_t* ctx, uint32_t cmd_id,
void (*handler)(ipc_cmd_t* cmd))
{
if (ctx && cmd_id < 256) {
ctx->cmd_handlers[cmd_id] = handler;
}
}
/**
* @brief IPC事件处理循环
*/
void ipc_process_loop(ipc_context_t* ctx, int timeout_ms)
{
if (!ctx || ctx->is_master) {
return;
}
ipc_shm_layout_t* layout = (ipc_shm_layout_t*)ctx->shm_addr;
ipc_cmd_t cmd;
/* 处理接收到的命令 */
while (ring_queue_dequeue(&layout->tx_queue, &cmd)) {
/* 查找并执行处理器 */
if (cmd.cmd_id < 256 && ctx->cmd_handlers[cmd.cmd_id]) {
ctx->cmd_handlers[cmd.cmd_id](&cmd);
} else {
/* 默认处理器 */
cmd.status = CMD_STATUS_ERROR;
cmd.ret_val = -1;
}
/* 发送响应 */
ring_queue_enqueue(&layout->rx_queue, &cmd);
ctx->rx_count++;
}
}
1.2 ISP调优模块
/**
* @file isp_tuning.h
* @brief ISP图像调优模块
* @author ISP Tuning Team
*
* @section 设计模式
* - **策略模式(Strategy)**: 动态切换不同的调优算法
* - **建造者模式(Builder)**: 逐步构建ISP参数配置
* - **模板方法(Template Method)**: 固定的调优流程框架
*/
#ifndef ISP_TUNING_H
#define ISP_TUNING_H
#include <stdint.h>
#include <stdbool.h>
#include "ipc_bus.h"
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* ISP模块类型定义
*============================================================================*/
/**
* @brief 黑电平校正策略
*/
typedef enum {
BLC_STRATEGY_FIXED, ///< 固定值校正
BLC_STRATEGY_DYNAMIC, ///< 动态校正(根据温度)
BLC_STRATEGY_ADAPTIVE ///< 自适应校正(根据亮度)
} blc_strategy_t;
/**
* @brief 镜头阴影校正策略
*/
typedef enum {
LSC_STRATEGY_PRELOAD, ///< 预加载固定表
LSC_STRATEGY_ONLINE, ///< 在线计算
LSC_STRATEGY_HYBRID ///< 混合模式
} lsc_strategy_t;
/**
* @brief 去噪策略
*/
typedef enum {
DENOISE_STRATEGY_BILATERAL, ///< 双边滤波
DENOISE_STRATEGY_BM3D, ///< BM3D去噪
DENOISE_STRATEGY_AI ///< AI去噪(BPU加速)
} denoise_strategy_t;
/*=============================================================================
* ISP参数配置结构体
*============================================================================*/
/**
* @brief 黑电平校正参数
*/
typedef struct {
blc_strategy_t strategy; ///< 策略选择
uint16_t fixed_r; ///< 固定R通道黑电平
uint16_t fixed_gr; ///< 固定Gr通道黑电平
uint16_t fixed_gb; ///< 固定Gb通道黑电平
uint16_t fixed_b; ///< 固定B通道黑电平
/* 动态校正参数 */
int16_t temp_coeff_r; ///< 温度系数R (LSB/°C)
int16_t temp_coeff_gr; ///< 温度系数Gr
int16_t temp_coeff_gb; ///< 温度系数Gb
int16_t temp_coeff_b; ///< 温度系数B
/* 自适应参数 */
uint16_t dark_threshold; ///< 暗区阈值
uint16_t bright_threshold; ///< 亮区阈值
} blc_params_t;
/**
* @brief 镜头阴影校正参数
*/
typedef struct {
lsc_strategy_t strategy; ///< 策略选择
uint16_t* lut_r; ///< R通道LUT(动态分配)
uint16_t* lut_gr; ///< Gr通道LUT
uint16_t* lut_gb; ///< Gb通道LUT
uint16_t* lut_b; ///< B通道LUT
uint32_t lut_width; ///< LUT宽度
uint32_t lut_height; ///< LUT高度
/* 多项式拟合系数(在线计算用) */
float poly_coeff_r[6]; ///< 6阶多项式系数
float poly_coeff_gr[6];
float poly_coeff_gb[6];
float poly_coeff_b[6];
} lsc_params_t;
/**
* @brief 色彩校正矩阵
*/
typedef struct {
float matrix[3][3]; ///< 3x3色彩校正矩阵
float offset[3]; ///< RGB偏移量
float saturation; ///< 饱和度因子(0-2)
float hue_rotation; ///< 色调旋转(度)
} ccm_params_t;
/**
* @brief Gamma校正参数
*/
typedef struct {
uint16_t gamma_curve[256]; ///< Gamma曲线(0-4095)
float gamma_value; ///< Gamma值(2.2标准)
bool enable_dither; ///< 使能抖动
} gamma_params_t;
/**
* @brief 去噪参数
*/
typedef struct {
denoise_strategy_t strategy; ///< 策略选择
uint8_t spatial_strength; ///< 空域降噪强度(0-255)
uint8_t temporal_strength; ///< 时域降噪强度(0-255)
uint8_t chroma_strength; ///< 彩色降噪强度(0-255)
bool enable_3d_nr; ///< 使能3D降噪
} denoise_params_t;
/**
* @brief 锐化参数
*/
typedef struct {
uint8_t sharp_strength; ///< 锐化强度(0-255)
uint8_t edge_threshold; ///< 边缘阈值(0-255)
bool unsharp_mask; ///< USM锐化
float usm_amount; ///< USM强度
uint8_t usm_radius; ///< USM半径
} sharpen_params_t;
/**
* @brief 完整的ISP调优参数集合
*/
typedef struct {
blc_params_t blc; ///< 黑电平校正
lsc_params_t lsc; ///< 镜头阴影校正
ccm_params_t ccm; ///< 色彩校正
gamma_params_t gamma; ///< Gamma校正
denoise_params_t denoise; ///< 去噪
sharpen_params_t sharpen; ///< 锐化
/* 场景识别参数 */
uint8_t scene_id; ///< 场景ID(0=自动,1=室内,2=室外,3=夜景)
float auto_adapt_speed; ///< 自适应速度(0-1)
/* 调优元数据 */
char version[32]; ///< 调优版本
uint32_t timestamp; ///< 时间戳
uint32_t crc32; ///< 校验和
} isp_tuning_params_t;
/*=============================================================================
* ISP调优API
*============================================================================*/
/**
* @brief 初始化ISP调优模块
* @param tuning_file_path 调优参数文件路径
* @return 成功返回RDK3_OK
*
* @note 设计模式: 建造者模式 - 逐步解析文件构建参数
*/
int isp_tuning_init(const char* tuning_file_path);
/**
* @brief 加载调优参数文件
* @param params 输出参数结构体
* @param file_path 文件路径
* @return 成功返回RDK3_OK
*/
int isp_tuning_load(isp_tuning_params_t* params, const char* file_path);
/**
* @brief 保存调优参数到文件
* @param params 参数结构体
* @param file_path 文件路径
* @return 成功返回RDK3_OK
*/
int isp_tuning_save(const isp_tuning_params_t* params, const char* file_path);
/**
* @brief 应用调优参数到ISP硬件
* @param params 参数结构体
* @return 成功返回RDK3_OK
*
* @note 会通过IPC将参数发送到ARM-None核
*/
int isp_tuning_apply(const isp_tuning_params_t* params);
/**
* @brief 根据场景自动调整参数(策略模式核心)
* @param scene_type 场景类型(0=室内,1=室外,2=夜景)
* @param lux 当前照度(Lux)
* @param color_temp 色温(K)
* @return 调整后的参数
*
* @note 设计模式: 策略模式 - 不同场景使用不同调优策略
*/
isp_tuning_params_t isp_tuning_auto_adapt(int scene_type, float lux, uint16_t color_temp);
/**
* @brief 动态更新ISP参数(在线调优)
* @param params 新参数
* @param smooth_time_ms 平滑过渡时间(毫秒)
* @return 成功返回RDK3_OK
*
* @note 支持参数平滑变化,避免画面闪烁
*/
int isp_tuning_update_smooth(const isp_tuning_params_t* params, uint32_t smooth_time_ms);
/**
* @brief 获取当前生效的调优参数
* @return 参数指针(只读)
*/
const isp_tuning_params_t* isp_tuning_get_current(void);
/**
* @brief 注册场景变化回调(观察者模式)
* @param callback 回调函数
* @param ctx 上下文
*/
void isp_tuning_register_scene_callback(void (*callback)(int scene_id, void* ctx), void* ctx);
#ifdef __cplusplus
}
#endif
#endif /* ISP_TUNING_H */
/**
* @file isp_tuning.c
* @brief ISP调优实现
*/
#include "isp_tuning.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <zlib.h> /* for CRC32 */
/* 全局当前参数 */
static isp_tuning_params_t g_current_params;
static bool g_tuning_initialized = false;
/* 观察者列表 */
typedef struct observer {
void (*callback)(int scene_id, void* ctx);
void* ctx;
struct observer* next;
} observer_t;
static observer_t* g_scene_observers = NULL;
/*=============================================================================
* 策略模式实现: 场景自适应算法
*============================================================================*/
/**
* @brief 室内场景调优策略
*/
static void strategy_indoor(isp_tuning_params_t* params, float lux, uint16_t color_temp)
{
/* 室内光线偏暖,色温3000-4000K */
params->ccm.matrix[0][0] = 1.2f; params->ccm.matrix[0][1] = -0.1f; params->ccm.matrix[0][2] = -0.1f;
params->ccm.matrix[1][0] = -0.05f; params->ccm.matrix[1][1] = 1.15f; params->ccm.matrix[1][2] = -0.1f;
params->ccm.matrix[2][0] = -0.05f; params->ccm.matrix[2][1] = -0.1f; params->ccm.matrix[2][2] = 1.15f;
/* 室内光线较暗,降噪加强 */
params->denoise.spatial_strength = 180;
params->denoise.temporal_strength = 150;
params->denoise.enable_3d_nr = true;
/* 锐化适度 */
params->sharpen.sharp_strength = 120;
/* Gamma值2.2标准 */
params->gamma.gamma_value = 2.2f;
}
/**
* @brief 室外场景调优策略
*/
static void strategy_outdoor(isp_tuning_params_t* params, float lux, uint16_t color_temp)
{
/* 室外光线偏冷,色温5500-6500K */
params->ccm.matrix[0][0] = 1.05f; params->ccm.matrix[0][1] = -0.02f; params->ccm.matrix[0][2] = -0.03f;
params->ccm.matrix[1][0] = -0.02f; params->ccm.matrix[1][1] = 1.08f; params->ccm.matrix[1][2] = -0.06f;
params->ccm.matrix[2][0] = -0.01f; params->ccm.matrix[2][1] = -0.05f; params->ccm.matrix[2][2] = 1.06f;
/* 室外光线充足,降噪减弱 */
params->denoise.spatial_strength = 80;
params->denoise.temporal_strength = 60;
params->denoise.enable_3d_nr = false;
/* 锐化加强 */
params->sharpen.sharp_strength = 200;
params->sharpen.unsharp_mask = true;
params->sharpen.usm_amount = 1.5f;
/* Gamma值1.8更通透 */
params->gamma.gamma_value = 1.8f;
}
/**
* @brief 夜景场景调优策略
*/
static void strategy_night(isp_tuning_params_t* params, float lux, uint16_t color_temp)
{
/* 夜景色彩增强 */
params->ccm.saturation = 1.3f;
params->ccm.matrix[0][0] = 1.3f; params->ccm.matrix[0][1] = -0.15f; params->ccm.matrix[0][2] = -0.15f;
params->ccm.matrix[1][0] = -0.1f; params->ccm.matrix[1][1] = 1.25f; params->ccm.matrix[1][2] = -0.15f;
params->ccm.matrix[2][0] = -0.1f; params->ccm.matrix[2][1] = -0.15f; params->ccm.matrix[2][2] = 1.25f;
/* 夜景降噪开到最大 */
params->denoise.spatial_strength = 255;
params->denoise.temporal_strength = 255;
params->denoise.chroma_strength = 200;
params->denoise.enable_3d_nr = true;
/* 锐化减弱,避免放大噪点 */
params->sharpen.sharp_strength = 50;
params->sharpen.edge_threshold = 100;
/* Gamma值2.5增强暗部 */
params->gamma.gamma_value = 2.5f;
/* 动态黑电平校正 */
params->blc.strategy = BLC_STRATEGY_ADAPTIVE;
params->blc.dark_threshold = 50;
}
/**
* @brief 场景自适应主函数(策略模式)
*/
isp_tuning_params_t isp_tuning_auto_adapt(int scene_type, float lux, uint16_t color_temp)
{
isp_tuning_params_t params;
/* 复制当前参数作为基础 */
memcpy(¶ms, &g_current_params, sizeof(isp_tuning_params_t));
/* 策略选择 */
switch (scene_type) {
case 0: /* 室内 */
strategy_indoor(¶ms, lux, color_temp);
params.scene_id = 0;
break;
case 1: /* 室外 */
strategy_outdoor(¶ms, lux, color_temp);
params.scene_id = 1;
break;
case 2: /* 夜景 */
strategy_night(¶ms, lux, color_temp);
params.scene_id = 2;
break;
default:
break;
}
/* 根据照度微调 */
if (lux < 10) {
/* 极暗环境,额外增益 */
params.denoise.spatial_strength = 255;
params.sharp.sharp_strength = 30;
} else if (lux > 10000) {
/* 强光环境,降低增益防止过曝 */
params.denoise.spatial_strength = 50;
params.sharp.sharp_strength = 150;
}
/* 根据色温微调白平衡偏移 */
if (color_temp < 3500) {
/* 暖光,增加蓝色分量 */
params.ccm.offset[2] += 0.05f;
} else if (color_temp > 6500) {
/* 冷光,增加红色分量 */
params.ccm.offset[0] += 0.05f;
}
return params;
}
/*=============================================================================
* 参数平滑过渡(线性插值)
*============================================================================*/
/**
* @brief 线性插值函数
*/
static float lerp(float a, float b, float t)
{
return a + (b - a) * t;
}
/**
* @brief 平滑更新参数(模板方法模式)
*/
static void smooth_update_params(const isp_tuning_params_t* target, float progress)
{
isp_tuning_params_t current;
memcpy(¤t, &g_current_params, sizeof(isp_tuning_params_t));
/* 对每个参数进行线性插值 */
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
current.ccm.matrix[i][j] = lerp(current.ccm.matrix[i][j],
target->ccm.matrix[i][j], progress);
}
current.ccm.offset[i] = lerp(current.ccm.offset[i], target->ccm.offset[i], progress);
}
current.denoise.spatial_strength = (uint8_t)lerp(current.denoise.spatial_strength,
target->denoise.spatial_strength, progress);
current.denoise.temporal_strength = (uint8_t)lerp(current.denoise.temporal_strength,
target->denoise.temporal_strength, progress);
current.sharpen.sharp_strength = (uint8_t)lerp(current.sharpen.sharp_strength,
target->sharpen.sharp_strength, progress);
/* Gamma曲线重新计算 */
if (fabs(current.gamma.gamma_value - target->gamma.gamma_value) > 0.01f) {
float gamma_val = lerp(current.gamma.gamma_value, target->gamma.gamma_value, progress);
for (int i = 0; i < 256; i++) {
float normalized = i / 255.0f;
float corrected = powf(normalized, 1.0f / gamma_val);
current.gamma.gamma_curve[i] = (uint16_t)(corrected * 4095);
}
}
/* 应用插值后的参数 */
isp_tuning_apply(¤t);
}
/**
* @brief 平滑更新ISP参数
*/
int isp_tuning_update_smooth(const isp_tuning_params_t* params, uint32_t smooth_time_ms)
{
if (!params || smooth_time_ms == 0) {
return isp_tuning_apply(params);
}
/* 平滑过渡实现(模板方法) */
uint32_t steps = 20; /* 20步完成平滑 */
uint32_t step_ms = smooth_time_ms / steps;
for (uint32_t step = 1; step <= steps; step++) {
float progress = (float)step / steps;
smooth_update_params(params, progress);
usleep(step_ms * 1000);
}
/* 最终应用目标参数 */
return isp_tuning_apply(params);
}
/*=============================================================================
* 文件IO和校验
*============================================================================*/
/**
* @brief 加载调优参数文件
*/
int isp_tuning_load(isp_tuning_params_t* params, const char* file_path)
{
FILE* fp = fopen(file_path, "rb");
if (!fp) {
return -1;
}
/* 读取参数 */
size_t read_size = fread(params, 1, sizeof(isp_tuning_params_t), fp);
fclose(fp);
if (read_size != sizeof(isp_tuning_params_t)) {
return -2;
}
/* CRC32校验 */
uint32_t crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, (const Bytef*)params, sizeof(isp_tuning_params_t) - sizeof(uint32_t));
if (crc != params->crc32) {
return -3; /* 校验失败 */
}
return 0;
}
/**
* @brief 保存调优参数文件
*/
int isp_tuning_save(const isp_tuning_params_t* params, const char* file_path)
{
isp_tuning_params_t copy;
memcpy(©, params, sizeof(isp_tuning_params_t));
/* 计算CRC32 */
copy.crc32 = crc32(0L, Z_NULL, 0);
copy.crc32 = crc32(copy.crc32, (const Bytef*)©, sizeof(isp_tuning_params_t) - sizeof(uint32_t));
FILE* fp = fopen(file_path, "wb");
if (!fp) {
return -1;
}
size_t written = fwrite(©, 1, sizeof(isp_tuning_params_t), fp);
fclose(fp);
return (written == sizeof(isp_tuning_params_t)) ? 0 : -2;
}
/**
* @brief 应用参数到硬件(通过IPC)
*/
int isp_tuning_apply(const isp_tuning_params_t* params)
{
if (!params) return -1;
/* 更新全局当前参数 */
memcpy(&g_current_params, params, sizeof(isp_tuning_params_t));
/* 通过IPC发送到ARM-None核 */
ipc_cmd_t cmd = {
.cmd_id = CMD_ISP_SET_TUNING_PARAM,
.arg_count = 2,
.timeout_ms = 100
};
/* 将参数通过共享内存传递(简化处理) */
cmd.args[0] = (uint32_t)(uintptr_t)params;
cmd.args[1] = sizeof(isp_tuning_params_t);
ipc_context_t* ipc = /* 获取全局IPC上下文 */ NULL;
if (ipc) {
return ipc_send_sync(ipc, &cmd);
}
return 0;
}
/**
* @brief 注册场景变化回调
*/
void isp_tuning_register_scene_callback(void (*callback)(int scene_id, void* ctx), void* ctx)
{
observer_t* obs = (observer_t*)malloc(sizeof(observer_t));
if (!obs) return;
obs->callback = callback;
obs->ctx = ctx;
obs->next = g_scene_observers;
g_scene_observers = obs;
}
/**
* @brief 通知场景变化(内部调用)
*/
static void notify_scene_change(int scene_id)
{
observer_t* obs = g_scene_observers;
while (obs) {
if (obs->callback) {
obs->callback(scene_id, obs->ctx);
}
obs = obs->next;
}
}
1.3 AI流水线模块(Pipeline模式 + 责任链模式)
/**
* @file ai_pipeline.h
* @brief AI推理流水线模块
* @author AI Algorithm Team
*
* @section 设计模式
* - **管道模式(Pipeline)**: 顺序处理AI任务各阶段
* - **责任链模式(Chain of Responsibility)**: 每个处理节点可独立处理或传递
* - **对象池模式(Object Pool)**: 复用AI任务对象和Tensor缓冲区
* - **策略模式(Strategy)**: 动态切换检测/分类/跟踪算法
*/
#ifndef AI_PIPELINE_H
#define AI_PIPELINE_H
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 前向声明
*============================================================================*/
typedef struct ai_pipeline ai_pipeline_t;
typedef struct ai_stage ai_stage_t;
typedef struct ai_task ai_task_t;
/*=============================================================================
* AI张量结构体
*============================================================================*/
/**
* @brief AI张量形状
*/
typedef struct {
uint32_t n; ///< 批次大小
uint32_t c; ///< 通道数
uint32_t h; ///< 高度
uint32_t w; ///< 宽度
} tensor_shape_t;
/**
* @brief AI张量数据格式
*/
typedef enum {
TENSOR_FORMAT_NCHW, ///< NCHW格式
TENSOR_FORMAT_NHWC, ///< NHWC格式
TENSOR_FORMAT_RGB, ///< RGB平面格式
TENSOR_FORMAT_BGR, ///< BGR平面格式
TENSOR_FORMAT_YUV420 ///< YUV420格式
} tensor_format_t;
/**
* @brief AI张量数据类型
*/
typedef enum {
TENSOR_TYPE_FP32, ///< 单精度浮点
TENSOR_TYPE_FP16, ///< 半精度浮点
TENSOR_TYPE_UINT8, ///< 8位无符号整型
TENSOR_TYPE_INT8 ///< 8位有符号整型
} tensor_dtype_t;
/**
* @brief AI张量结构体
*/
typedef struct {
tensor_shape_t shape; ///< 张量形状
tensor_format_t format; ///< 数据格式
tensor_dtype_t dtype; ///< 数据类型
void* data; ///< 数据指针
size_t size; ///< 数据大小(字节)
uint32_t sequence; ///< 关联帧序号
uint64_t timestamp; ///< 时间戳
struct ai_tensor* next; ///< 链表指针
} ai_tensor_t;
/*=============================================================================
* AI检测结果结构体
*============================================================================*/
/**
* @brief 边界框
*/
typedef struct {
float x1, y1; ///< 左上角(归一化0-1)
float x2, y2; ///< 右下角(归一化0-1)
float confidence; ///< 置信度
} bbox_t;
/**
* @brief 检测目标
*/
typedef struct {
bbox_t bbox; ///< 边界框
int class_id; ///< 类别ID
const char* class_name; ///< 类别名称
float* features; ///< 特征向量(用于跟踪)
uint32_t feature_dim; ///< 特征维度
uint32_t track_id; ///< 跟踪ID
} detection_object_t;
/**
* @brief 检测结果
*/
typedef struct {
detection_object_t* objects; ///< 目标数组
uint32_t object_count; ///< 目标数量
uint32_t max_objects; ///< 最大目标数
uint32_t frame_seq; ///< 帧序号
uint64_t inference_time_us; ///< 推理耗时(微秒)
} detection_result_t;
/*=============================================================================
* AI流水线配置
*============================================================================*/
/**
* @brief 预处理配置
*/
typedef struct {
uint32_t target_width; ///< 目标宽度(模型输入)
uint32_t target_height; ///< 目标高度
tensor_format_t target_format; ///< 目标格式
bool keep_aspect_ratio; ///< 保持宽高比(letterbox)
uint8_t pad_value; ///< 填充值(默认114)
float mean[3]; ///< 归一化均值
float std[3]; ///< 归一化标准差
bool convert_to_rgb; ///< 转换为RGB
} preprocess_config_t;
/**
* @brief 后处理配置
*/
typedef struct {
float confidence_threshold; ///< 置信度阈值
float nms_threshold; ///< NMS阈值(IOU)
int max_detections; ///< 最大检测数
bool enable_feature_extract; ///< 使能特征提取
uint32_t feature_dim; ///< 特征维度(默认512)
} postprocess_config_t;
/**
* @brief YOLO模型配置
*/
typedef struct {
int num_classes; ///< 类别数
int num_anchors; ///< Anchor数量
float anchors[3][2]; ///< Anchor尺寸
int stride[3]; ///< 输出步长(8,16,32)
int input_width; ///< 输入宽度
int input_height; ///< 输入高度
} yolo_config_t;
/**
* @brief 跟踪器配置
*/
typedef struct {
int max_tracked_objects; ///< 最大跟踪目标数
int max_lost_frames; ///< 最大丢失帧数
float iou_threshold; ///< IOU匹配阈值
float feature_threshold; ///< 特征匹配阈值
bool use_kalman; ///< 使用卡尔曼滤波
} tracker_config_t;
/**
* @brief AI流水线配置
*/
typedef struct {
/* 模型路径 */
const char* detect_model_path; ///< 检测模型路径
const char* classify_model_path; ///< 分类模型路径
const char* track_model_path; ///< 跟踪模型路径
/* 各阶段配置 */
preprocess_config_t preprocess;
postprocess_config_t postprocess;
yolo_config_t yolo;
tracker_config_t tracker;
/* 流水线配置 */
uint32_t max_pending_tasks; ///< 最大待处理任务数
bool enable_async; ///< 异步模式
uint32_t worker_threads; ///< 工作线程数(默认2)
} ai_pipeline_config_t;
/*=============================================================================
* AI流水线API
*============================================================================*/
/**
* @brief 创建AI流水线(建造者模式)
* @param config 流水线配置
* @return 流水线句柄
*
* @note 设计模式: 建造者模式 - 逐步构建流水线各阶段
*/
ai_pipeline_t* ai_pipeline_create(const ai_pipeline_config_t* config);
/**
* @brief 销毁AI流水线
* @param pipeline 流水线句柄
*/
void ai_pipeline_destroy(ai_pipeline_t* pipeline);
/**
* @brief 处理单帧图像(同步模式)
* @param pipeline 流水线句柄
* @param frame 输入帧(YUV/RGB格式)
* @param result 输出检测结果
* @return 成功返回RDK3_OK
*
* @note 完整流程: 预处理 -> BPU推理 -> 后处理 -> 跟踪
*/
int ai_pipeline_process_sync(ai_pipeline_t* pipeline, const frame_t* frame,
detection_result_t* result);
/**
* @brief 提交异步任务(异步模式)
* @param pipeline 流水线句柄
* @param frame 输入帧
* @param callback 完成回调
* @param user_data 用户数据
* @return 任务ID(负数为错误)
*
* @note 设计模式: 命令模式 - 任务封装为命令对象
*/
int ai_pipeline_submit_async(ai_pipeline_t* pipeline, const frame_t* frame,
void (*callback)(detection_result_t* result, void* user_data),
void* user_data);
/**
* @brief 等待异步任务完成
* @param pipeline 流水线句柄
* @param task_id 任务ID
* @param timeout_ms 超时时间
* @return 成功返回RDK3_OK
*/
int ai_pipeline_wait_task(ai_pipeline_t* pipeline, int task_id, int timeout_ms);
/**
* @brief 动态切换检测模型(策略模式)
* @param pipeline 流水线句柄
* @param model_path 新模型路径
* @return 成功返回RDK3_OK
*/
int ai_pipeline_switch_model(ai_pipeline_t* pipeline, const char* model_path);
/**
* @brief 获取流水线统计信息
* @param pipeline 流水线句柄
* @param fps 输出FPS
* @param avg_latency_us 输出平均延迟
* @param queue_depth 输出队列深度
*/
void ai_pipeline_get_stats(ai_pipeline_t* pipeline, float* fps,
uint32_t* avg_latency_us, uint32_t* queue_depth);
#ifdef __cplusplus
}
#endif
#endif /* AI_PIPELINE_H */
/**
* @file ai_pipeline.c
* @brief AI推理流水线实现
*/
#include "ai_pipeline.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <sys/time.h>
/*=============================================================================
* 内部数据结构
*============================================================================*/
/**
* @brief AI处理阶段类型(责任链模式)
*/
typedef enum {
STAGE_PREPROCESS, ///< 预处理阶段
STAGE_INFERENCE, ///< BPU推理阶段
STAGE_POSTPROCESS, ///< 后处理阶段
STAGE_TRACKING ///< 目标跟踪阶段
} stage_type_t;
/**
* @brief AI处理阶段接口(责任链节点)
*/
struct ai_stage {
stage_type_t type; ///< 阶段类型
const char* name; ///< 阶段名称
/* 处理函数(责任链的核心) */
int (*process)(struct ai_stage* stage, ai_task_t* task);
/* 初始化/销毁函数 */
int (*init)(struct ai_stage* stage, void* config);
void (*deinit)(struct ai_stage* stage);
/* 下一阶段 */
struct ai_stage* next;
/* 私有数据 */
void* priv;
};
/**
* @brief AI任务结构体(命令模式)
*/
struct ai_task {
uint32_t task_id; ///< 任务ID
uint32_t frame_seq; ///< 帧序号
uint64_t submit_time_us; ///< 提交时间
/* 输入输出 */
frame_t* input_frame; ///< 输入帧
ai_tensor_t* input_tensor; ///< 预处理后的张量
detection_result_t output; ///< 输出结果
/* 回调函数 */
void (*callback)(detection_result_t* result, void* user_data);
void* user_data;
/* 状态 */
volatile int stage_index; ///< 当前阶段索引
volatile bool completed; ///< 是否完成
/* 链表 */
struct ai_task* next;
};
/**
* @brief AI流水线主结构
*/
struct ai_pipeline {
ai_pipeline_config_t config; ///< 配置
/* 责任链头节点 */
ai_stage_t* first_stage;
ai_stage_t* last_stage;
/* 任务队列(对象池) */
ai_task_t* task_pool; ///< 任务对象池
ai_task_t* pending_queue; ///< 待处理队列
ai_task_t* completed_queue; ///< 完成队列
pthread_mutex_t queue_mutex; ///< 队列锁
pthread_cond_t queue_cond; ///< 队列条件变量
/* 工作线程 */
pthread_t* worker_threads;
uint32_t worker_count;
volatile bool running;
/* BPU句柄 */
void* bpu_handle;
void* detect_model;
void* classify_model;
/* 统计信息 */
uint64_t total_frames;
uint64_t total_latency_us;
uint32_t max_latency_us;
uint32_t min_latency_us;
uint32_t pending_count;
/* 跟踪器状态 */
void* tracker_handle;
};
/*=============================================================================
* 工具函数
*============================================================================*/
/**
* @brief 获取微秒级时间戳
*/
static inline uint64_t get_time_us(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
/**
* @brief 计算YUV转RGB(简化版)
*/
static void yuv_to_rgb(uint8_t* yuv, uint8_t* rgb, uint32_t width, uint32_t height)
{
/* 实际应使用查表法优化 */
for (uint32_t i = 0; i < width * height; i++) {
uint8_t y = yuv[i];
uint8_t u = yuv[width * height + (i / 2) * 2];
uint8_t v = yuv[width * height + (i / 2) * 2 + 1];
int r = y + 1.402f * (v - 128);
int g = y - 0.344f * (u - 128) - 0.714f * (v - 128);
int b = y + 1.772f * (u - 128);
rgb[i * 3] = r < 0 ? 0 : (r > 255 ? 255 : r);
rgb[i * 3 + 1] = g < 0 ? 0 : (g > 255 ? 255 : g);
rgb[i * 3 + 2] = b < 0 ? 0 : (b > 255 ? 255 : b);
}
}
/*=============================================================================
* 阶段1: 预处理(责任链节点)
*============================================================================*/
/**
* @brief 预处理阶段处理函数
*/
static int preprocess_stage_process(ai_stage_t* stage, ai_task_t* task)
{
preprocess_config_t* cfg = (preprocess_config_t*)stage->priv;
frame_t* frame = task->input_frame;
if (!frame || !frame->data[0]) {
return -1;
}
uint64_t start_us = get_time_us();
/* 1. 分配输入张量 */
ai_tensor_t* tensor = (ai_tensor_t*)calloc(1, sizeof(ai_tensor_t));
if (!tensor) return -2;
tensor->shape.n = 1;
tensor->shape.c = 3; /* RGB 3通道 */
tensor->shape.h = cfg->target_height;
tensor->shape.w = cfg->target_width;
tensor->format = TENSOR_FORMAT_RGB;
tensor->dtype = TENSOR_TYPE_UINT8;
tensor->size = tensor->shape.n * tensor->shape.c *
tensor->shape.h * tensor->shape.w;
tensor->data = malloc(tensor->size);
tensor->sequence = frame->sequence;
tensor->timestamp = frame->timestamp;
if (!tensor->data) {
free(tensor);
return -3;
}
/* 2. 格式转换(YUV -> RGB) */
uint8_t* rgb_buffer = (uint8_t*)malloc(frame->width * frame->height * 3);
yuv_to_rgb(frame->data[0], rgb_buffer, frame->width, frame->height);
/* 3. Letterbox缩放(保持宽高比) */
float scale_w = (float)cfg->target_width / frame->width;
float scale_h = (float)cfg->target_height / frame->height;
float scale = cfg->keep_aspect_ratio ? fminf(scale_w, scale_h) : scale_w;
uint32_t scaled_w = (uint32_t)(frame->width * scale);
uint32_t scaled_h = (uint32_t)(frame->height * scale);
/* 简化的最近邻缩放(实际应使用双线性插值) */
uint8_t* scaled_rgb = (uint8_t*)malloc(scaled_w * scaled_h * 3);
for (uint32_t y = 0; y < scaled_h; y++) {
uint32_t src_y = (y * frame->height) / scaled_h;
for (uint32_t x = 0; x < scaled_w; x++) {
uint32_t src_x = (x * frame->width) / scaled_w;
memcpy(&scaled_rgb[(y * scaled_w + x) * 3],
&rgb_buffer[(src_y * frame->width + src_x) * 3], 3);
}
}
/* 4. Padding到目标尺寸(letterbox) */
uint32_t pad_x = (cfg->target_width - scaled_w) / 2;
uint32_t pad_y = (cfg->target_height - scaled_h) / 2;
memset(tensor->data, cfg->pad_value, tensor->size);
for (uint32_t y = 0; y < scaled_h; y++) {
memcpy((uint8_t*)tensor->data + ((pad_y + y) * cfg->target_width + pad_x) * 3,
&scaled_rgb[y * scaled_w * 3], scaled_w * 3);
}
/* 5. 归一化(可选) */
if (cfg->mean[0] != 0 || cfg->std[0] != 1) {
uint8_t* data = (uint8_t*)tensor->data;
for (uint32_t i = 0; i < tensor->size; i++) {
float normalized = (data[i] - cfg->mean[i % 3]) / cfg->std[i % 3];
data[i] = (uint8_t)(normalized * 255);
}
}
free(rgb_buffer);
free(scaled_rgb);
task->input_tensor = tensor;
uint64_t elapsed_us = get_time_us() - start_us;
/* 调试日志 */
// printf("[Preprocess] frame=%u, size=%ux%u->%ux%u, time=%lluus\n",
// task->frame_seq, frame->width, frame->height,
// cfg->target_width, cfg->target_height, elapsed_us);
return 0;
}
/**
* @brief 预处理阶段初始化
*/
static int preprocess_stage_init(ai_stage_t* stage, void* config)
{
stage->priv = malloc(sizeof(preprocess_config_t));
if (!stage->priv) return -1;
memcpy(stage->priv, config, sizeof(preprocess_config_t));
return 0;
}
/**
* @brief 预处理阶段销毁
*/
static void preprocess_stage_deinit(ai_stage_t* stage)
{
if (stage->priv) {
free(stage->priv);
stage->priv = NULL;
}
}
/*=============================================================================
* 阶段2: BPU推理(策略模式核心)
*============================================================================*/
/**
* @brief BPU推理接口(简化实现)
*
* @note 实际应调用地平线BPU SDK: hb_bpu_task_submit()
*/
static int bpu_inference(void* model, ai_tensor_t* input, ai_tensor_t** output)
{
/* 模拟BPU推理延迟(实际约5-15ms) */
usleep(8000); /* 8ms模拟 */
/* 分配输出张量(简化) */
*output = (ai_tensor_t*)calloc(1, sizeof(ai_tensor_t));
if (!*output) return -1;
(*output)->shape.n = 1;
(*output)->shape.c = 84; /* YOLO: 80类 + 4坐标 */
(*output)->shape.h = 8400; /* 输出候选框数量 */
(*output)->shape.w = 1;
(*output)->size = 84 * 8400 * sizeof(float);
(*output)->data = malloc((*output)->size);
/* 模拟随机检测结果(实际应为模型输出) */
float* out_data = (float*)(*output)->data;
for (int i = 0; i < 8400 * 84; i++) {
out_data[i] = (float)rand() / RAND_MAX;
}
return 0;
}
/**
* @brief 推理阶段处理函数
*/
static int inference_stage_process(ai_stage_t* stage, ai_task_t* task)
{
ai_pipeline_t* pipeline = (ai_pipeline_t*)stage->priv;
ai_tensor_t* output_tensor = NULL;
if (!task->input_tensor) {
return -1;
}
uint64_t start_us = get_time_us();
/* 执行BPU推理 */
int ret = bpu_inference(pipeline->detect_model, task->input_tensor, &output_tensor);
if (ret == 0 && output_tensor) {
/* 将输出附加到任务 */
task->output.inference_time_us = get_time_us() - start_us;
/* 输出张量会在后处理阶段使用 */
}
/* 释放输入张量(不再需要) */
if (task->input_tensor) {
if (task->input_tensor->data) free(task->input_tensor->data);
free(task->input_tensor);
task->input_tensor = NULL;
}
return ret;
}
/*=============================================================================
* 阶段3: 后处理(NMS + 解码)
*============================================================================*/
/**
* @brief 计算IOU(交并比)
*/
static float compute_iou(const bbox_t* a, const bbox_t* b)
{
float ix1 = fmaxf(a->x1, b->x1);
float iy1 = fmaxf(a->y1, b->y1);
float ix2 = fminf(a->x2, b->x2);
float iy2 = fminf(a->y2, b->y2);
float iw = fmaxf(0, ix2 - ix1);
float ih = fmaxf(0, iy2 - iy1);
float inter = iw * ih;
float area_a = (a->x2 - a->x1) * (a->y2 - a->y1);
float area_b = (b->x2 - b->x1) * (b->y2 - b->y1);
float union_area = area_a + area_b - inter;
return inter / union_area;
}
/**
* @brief NMS(非极大值抑制)
*/
static void nms(detection_object_t* objects, uint32_t* count, float nms_threshold)
{
if (*count == 0) return;
/* 按置信度降序排序 */
for (uint32_t i = 0; i < *count - 1; i++) {
for (uint32_t j = i + 1; j < *count; j++) {
if (objects[i].bbox.confidence < objects[j].bbox.confidence) {
detection_object_t tmp = objects[i];
objects[i] = objects[j];
objects[j] = tmp;
}
}
}
/* NMS过滤 */
uint32_t keep_count = 0;
bool* suppressed = (bool*)calloc(*count, sizeof(bool));
for (uint32_t i = 0; i < *count; i++) {
if (suppressed[i]) continue;
keep_count++;
for (uint32_t j = i + 1; j < *count; j++) {
if (!suppressed[j] && compute_iou(&objects[i].bbox, &objects[j].bbox) > nms_threshold) {
suppressed[j] = true;
}
}
}
/* 压缩数组 */
uint32_t idx = 0;
for (uint32_t i = 0; i < *count && idx < keep_count; i++) {
if (!suppressed[i]) {
if (idx != i) {
objects[idx] = objects[i];
}
idx++;
}
}
*count = keep_count;
free(suppressed);
}
/**
* @brief 解码YOLO输出(简化版)
*/
static void decode_yolo_output(float* output, uint32_t output_size,
detection_object_t* objects, uint32_t* count,
float conf_threshold, int num_classes)
{
/* YOLO输出格式: [batch, 84, 8400] */
*count = 0;
for (int i = 0; i < 8400; i++) {
float* pred = &output[i * 84];
/* 获取类别置信度 */
float max_conf = 0;
int max_class = 0;
for (int c = 0; c < num_classes; c++) {
if (pred[4 + c] > max_conf) {
max_conf = pred[4 + c];
max_class = c;
}
}
/* 目标置信度 = 对象置信度 * 类别置信度 */
float obj_conf = pred[4]; /* 对象存在概率 */
float conf = obj_conf * max_conf;
if (conf > conf_threshold && *count < 100) {
/* 解码边界框(中心点+宽高 -> 左上角+右下角) */
float cx = pred[0];
float cy = pred[1];
float w = pred[2];
float h = pred[3];
detection_object_t* obj = &objects[*count];
obj->bbox.x1 = cx - w / 2;
obj->bbox.y1 = cy - h / 2;
obj->bbox.x2 = cx + w / 2;
obj->bbox.y2 = cy + h / 2;
obj->bbox.confidence = conf;
obj->class_id = max_class;
obj->class_name = "object"; /* 实际应从映射表获取 */
obj->track_id = 0;
(*count)++;
}
}
}
/**
* @brief 后处理阶段处理函数
*/
static int postprocess_stage_process(ai_stage_t* stage, ai_task_t* task)
{
postprocess_config_t* cfg = (postprocess_config_t*)stage->priv;
uint64_t start_us = get_time_us();
/* 分配结果存储 */
task->output.objects = (detection_object_t*)calloc(
cfg->max_detections, sizeof(detection_object_t));
task->output.max_objects = cfg->max_detections;
task->output.frame_seq = task->frame_seq;
/* 简化: 模拟检测结果 */
/* 实际应从推理输出解码 */
/* 模拟随机检测 */
task->output.object_count = 0;
for (int i = 0; i < 3; i++) {
if (rand() % 100 > 50) {
detection_object_t* obj = &task->output.objects[task->output.object_count++];
obj->bbox.x1 = 0.2f + (rand() % 60) / 100.0f;
obj->bbox.y1 = 0.3f + (rand() % 50) / 100.0f;
obj->bbox.x2 = obj->bbox.x1 + 0.2f + (rand() % 30) / 100.0f;
obj->bbox.y2 = obj->bbox.y1 + 0.3f + (rand() % 40) / 100.0f;
obj->bbox.confidence = 0.7f + (rand() % 28) / 100.0f;
obj->class_id = i;
obj->track_id = 0;
}
}
/* NMS */
if (task->output.object_count > 0) {
nms(task->output.objects, &task->output.object_count, cfg->nms_threshold);
}
task->output.inference_time_us = get_time_us() - start_us;
return 0;
}
/**
* @brief 后处理阶段初始化
*/
static int postprocess_stage_init(ai_stage_t* stage, void* config)
{
stage->priv = malloc(sizeof(postprocess_config_t));
if (!stage->priv) return -1;
memcpy(stage->priv, config, sizeof(postprocess_config_t));
return 0;
}
static void postprocess_stage_deinit(ai_stage_t* stage)
{
if (stage->priv) {
free(stage->priv);
stage->priv = NULL;
}
}
/*=============================================================================
* 阶段4: 目标跟踪(IOU + Kalman滤波)
*============================================================================*/
/**
* @brief 跟踪目标结构体
*/
typedef struct {
uint32_t track_id; ///< 跟踪ID
bbox_t bbox; ///< 当前边界框
bbox_t predicted_bbox; ///< 预测边界框(Kalman)
float* features; ///< 特征向量
uint32_t feature_dim; ///< 特征维度
int lost_count; ///< 丢失计数
int hit_count; ///< 命中计数
bool confirmed; ///< 是否确认
} tracked_object_t;
/**
* @brief 跟踪器上下文
*/
typedef struct {
tracked_object_t* tracks; ///< 跟踪列表
uint32_t track_count; ///< 当前跟踪数
uint32_t max_tracks; ///< 最大跟踪数
uint32_t next_track_id; ///< 下一个ID
tracker_config_t config; ///< 配置
} tracker_ctx_t;
/**
* @brief IOU匹配
*/
static void iou_match(tracker_ctx_t* tracker, detection_object_t* detections,
uint32_t det_count, bool* matched_det, bool* matched_track)
{
/* 构建代价矩阵 */
float* iou_matrix = (float*)malloc(tracker->track_count * det_count * sizeof(float));
for (uint32_t i = 0; i < tracker->track_count; i++) {
for (uint32_t j = 0; j < det_count; j++) {
iou_matrix[i * det_count + j] = compute_iou(
&tracker->tracks[i].bbox, &detections[j].bbox);
}
}
/* 贪心匹配(简化) */
for (uint32_t j = 0; j < det_count; j++) {
int best_track = -1;
float best_iou = 0;
for (uint32_t i = 0; i < tracker->track_count; i++) {
if (!matched_track[i] && iou_matrix[i * det_count + j] > best_iou) {
best_iou = iou_matrix[i * det_count + j];
best_track = i;
}
}
if (best_track >= 0 && best_iou > tracker->config.iou_threshold) {
matched_det[j] = true;
matched_track[best_track] = true;
/* 更新跟踪目标 */
tracker->tracks[best_track].bbox = detections[j].bbox;
tracker->tracks[best_track].hit_count++;
tracker->tracks[best_track].lost_count = 0;
detections[j].track_id = tracker->tracks[best_track].track_id;
}
}
free(iou_matrix);
}
/**
* @brief 跟踪阶段处理函数
*/
static int tracking_stage_process(ai_stage_t* stage, ai_task_t* task)
{
tracker_ctx_t* tracker = (tracker_ctx_t*)stage->priv;
detection_result_t* result = &task->output;
if (result->object_count == 0) {
return 0;
}
uint64_t start_us = get_time_us();
bool* matched_det = (bool*)calloc(result->object_count, sizeof(bool));
bool* matched_track = (bool*)calloc(tracker->track_count, sizeof(bool));
/* 1. IOU匹配 */
iou_match(tracker, result->objects, result->object_count, matched_det, matched_track);
/* 2. 创建新跟踪目标(未匹配的检测) */
for (uint32_t i = 0; i < result->object_count; i++) {
if (!matched_det[i] && tracker->track_count < tracker->max_tracks) {
tracked_object_t* new_track = &tracker->tracks[tracker->track_count];
new_track->track_id = tracker->next_track_id++;
new_track->bbox = result->objects[i].bbox;
new_track->lost_count = 0;
new_track->hit_count = 1;
new_track->confirmed = false;
result->objects[i].track_id = new_track->track_id;
tracker->track_count++;
}
}
/* 3. 更新未匹配的跟踪目标(lost计数增加) */
for (uint32_t i = 0; i < tracker->track_count; i++) {
if (!matched_track[i]) {
tracker->tracks[i].lost_count++;
/* 丢失超过阈值则删除 */
if (tracker->tracks[i].lost_count > tracker->config.max_lost_frames) {
/* 删除跟踪目标(将最后一个移到当前位置) */
if (i < tracker->track_count - 1) {
tracker->tracks[i] = tracker->tracks[tracker->track_count - 1];
}
tracker->track_count--;
i--; /* 重新检查当前位置 */
}
}
/* 更新检测结果的track_id */
for (uint32_t j = 0; j < result->object_count; j++) {
if (compute_iou(&result->objects[j].bbox, &tracker->tracks[i].bbox) > 0.5) {
result->objects[j].track_id = tracker->tracks[i].track_id;
}
}
}
free(matched_det);
free(matched_track);
task->output.inference_time_us += (get_time_us() - start_us);
return 0;
}
/**
* @brief 跟踪阶段初始化
*/
static int tracking_stage_init(ai_stage_t* stage, void* config)
{
tracker_config_t* cfg = (tracker_config_t*)config;
tracker_ctx_t* tracker = (tracker_ctx_t*)calloc(1, sizeof(tracker_ctx_t));
if (!tracker) return -1;
tracker->max_tracks = cfg->max_tracked_objects;
tracker->tracks = (tracked_object_t*)calloc(tracker->max_tracks, sizeof(tracked_object_t));
tracker->config = *cfg;
stage->priv = tracker;
return tracker->tracks ? 0 : -2;
}
static void tracking_stage_deinit(ai_stage_t* stage)
{
if (stage->priv) {
tracker_ctx_t* tracker = (tracker_ctx_t*)stage->priv;
if (tracker->tracks) free(tracker->tracks);
free(tracker);
stage->priv = NULL;
}
}
/*=============================================================================
* AI流水线主实现
*============================================================================*/
/**
* @brief 创建AI流水线(建造者模式)
*/
ai_pipeline_t* ai_pipeline_create(const ai_pipeline_config_t* config)
{
ai_pipeline_t* pipeline = (ai_pipeline_t*)calloc(1, sizeof(ai_pipeline_t));
if (!pipeline) return NULL;
memcpy(&pipeline->config, config, sizeof(ai_pipeline_config_t));
/* 构建责任链 */
ai_stage_t* stage = NULL;
/* 1. 预处理阶段 */
stage = (ai_stage_t*)calloc(1, sizeof(ai_stage_t));
stage->type = STAGE_PREPROCESS;
stage->name = "preprocess";
stage->process = preprocess_stage_process;
stage->init = preprocess_stage_init;
stage->deinit = preprocess_stage_deinit;
stage->init(stage, (void*)&config->preprocess);
pipeline->first_stage = stage;
pipeline->last_stage = stage;
/* 2. 推理阶段 */
stage = (ai_stage_t*)calloc(1, sizeof(ai_stage_t));
stage->type = STAGE_INFERENCE;
stage->name = "inference";
stage->process = inference_stage_process;
stage->priv = pipeline;
pipeline->last_stage->next = stage;
pipeline->last_stage = stage;
/* 3. 后处理阶段 */
stage = (ai_stage_t*)calloc(1, sizeof(ai_stage_t));
stage->type = STAGE_POSTPROCESS;
stage->name = "postprocess";
stage->process = postprocess_stage_process;
stage->init = postprocess_stage_init;
stage->deinit = postprocess_stage_deinit;
stage->init(stage, (void*)&config->postprocess);
pipeline->last_stage->next = stage;
pipeline->last_stage = stage;
/* 4. 跟踪阶段 */
stage = (ai_stage_t*)calloc(1, sizeof(ai_stage_t));
stage->type = STAGE_TRACKING;
stage->name = "tracking";
stage->process = tracking_stage_process;
stage->init = tracking_stage_init;
stage->deinit = tracking_stage_deinit;
stage->init(stage, (void*)&config->tracker);
pipeline->last_stage->next = stage;
pipeline->last_stage = stage;
/* 初始化任务对象池 */
pipeline->task_pool = (ai_task_t*)calloc(config->max_pending_tasks, sizeof(ai_task_t));
/* 初始化锁 */
pthread_mutex_init(&pipeline->queue_mutex, NULL);
pthread_cond_init(&pipeline->queue_cond, NULL);
/* 初始化统计 */
pipeline->min_latency_us = 0xFFFFFFFF;
/* 加载模型(简化) */
pipeline->detect_model = (void*)0x1000; /* 模拟句柄 */
return pipeline;
}
/**
* @brief 销毁AI流水线
*/
void ai_pipeline_destroy(ai_pipeline_t* pipeline)
{
if (!pipeline) return;
/* 停止工作线程 */
pipeline->running = false;
/* 销毁责任链 */
ai_stage_t* stage = pipeline->first_stage;
while (stage) {
ai_stage_t* next = stage->next;
if (stage->deinit) stage->deinit(stage);
free(stage);
stage = next;
}
/* 销毁对象池 */
if (pipeline->task_pool) {
free(pipeline->task_pool);
}
pthread_mutex_destroy(&pipeline->queue_mutex);
pthread_cond_destroy(&pipeline->queue_cond);
free(pipeline);
}
/**
* @brief 同步处理
*/
int ai_pipeline_process_sync(ai_pipeline_t* pipeline, const frame_t* frame,
detection_result_t* result)
{
if (!pipeline || !frame) return -1;
uint64_t start_us = get_time_us();
/* 创建任务 */
ai_task_t task;
memset(&task, 0, sizeof(ai_task_t));
task.input_frame = (frame_t*)frame;
task.frame_seq = frame->sequence;
task.submit_time_us = start_us;
/* 执行责任链 */
int ret = 0;
ai_stage_t* stage = pipeline->first_stage;
while (stage && ret == 0) {
ret = stage->process(stage, &task);
stage = stage->next;
}
if (ret == 0 && result) {
*result = task.output;
result->inference_time_us = get_time_us() - start_us;
/* 更新统计 */
pipeline->total_frames++;
pipeline->total_latency_us += result->inference_time_us;
if (result->inference_time_us > pipeline->max_latency_us) {
pipeline->max_latency_us = result->inference_time_us;
}
if (result->inference_time_us < pipeline->min_latency_us) {
pipeline->min_latency_us = result->inference_time_us;
}
}
/* 清理任务资源 */
if (task.output.objects) {
free(task.output.objects);
}
return ret;
}
/**
* @brief 获取流水线统计
*/
void ai_pipeline_get_stats(ai_pipeline_t* pipeline, float* fps,
uint32_t* avg_latency_us, uint32_t* queue_depth)
{
if (!pipeline) return;
if (fps) {
/* 简化FPS计算 */
*fps = pipeline->total_frames > 0 ? 1000000.0f / (pipeline->total_latency_us / pipeline->total_frames) : 0;
}
if (avg_latency_us) {
*avg_latency_us = pipeline->total_frames > 0 ?
pipeline->total_latency_us / pipeline->total_frames : 0;
}
if (queue_depth) {
*queue_depth = pipeline->pending_count;
}
}
二、3A策略模式应用(AE/AWB/AF)
/**
* @file isp_3a.h
* @brief ISP 3A算法模块(策略模式)
* @author ISP Algorithm Team
*
* @section 设计模式
* - **策略模式(Strategy)**: AE/AWB/AF可动态切换不同算法
* - **状态模式(State)**: 对焦状态机(搜索/锁定/重试)
* - **模板方法(Template Method)**: 3A处理流程框架
*/
#ifndef ISP_3A_H
#define ISP_3A_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 策略接口定义
*============================================================================*/
/**
* @brief AE策略接口
*/
typedef struct ae_strategy {
const char* name;
/* 策略方法 */
void (*init)(void* ctx);
void (*update)(void* ctx, const isp_3a_stats_t* stats, ae_cfg_t* cfg);
void (*deinit)(void* ctx);
/* 私有数据 */
void* priv;
} ae_strategy_t;
/**
* @brief AWB策略接口
*/
typedef struct awb_strategy {
const char* name;
void (*init)(void* ctx);
void (*update)(void* ctx, const isp_3a_stats_t* stats, awb_cfg_t* cfg);
void (*deinit)(void* ctx);
void* priv;
} awb_strategy_t;
/**
* @brief AF策略接口
*/
typedef struct af_strategy {
const char* name;
void (*init)(void* ctx);
void (*update)(void* ctx, const isp_3a_stats_t* stats, af_cfg_t* cfg);
void (*deinit)(void* ctx);
void* priv;
} af_strategy_t;
/*=============================================================================
* AE策略实现
*============================================================================*/
/**
* @brief PID控制策略(AE)
*/
typedef struct {
float integral; ///< 积分项
float prev_error; ///< 上次误差
uint32_t last_update; ///< 上次更新时间
} pid_ctx_t;
static void pid_ae_init(void* ctx)
{
pid_ctx_t* pid = (pid_ctx_t*)ctx;
memset(pid, 0, sizeof(pid_ctx_t));
}
static void pid_ae_update(void* ctx, const isp_3a_stats_t* stats, ae_cfg_t* cfg)
{
pid_ctx_t* pid = (pid_ctx_t*)ctx;
/* 计算亮度误差 */
int32_t error = (int32_t)cfg->target_luminance - (int32_t)stats->avg_luminance;
/* PID计算 */
float p_term = cfg->pid_kp * error;
pid->integral += error;
float i_term = cfg->pid_ki * pid->integral;
float d_term = cfg->pid_kd * (error - pid->prev_error);
float output = p_term + i_term + d_term;
pid->prev_error = error;
/* 限制输出范围 */
if (output > 0) {
/* 增加曝光/增益 */
uint32_t new_exp = cfg->exposure_time_min + (uint32_t)output;
if (new_exp > cfg->exposure_time_max) new_exp = cfg->exposure_time_max;
/* 应用曝光值 */
} else {
/* 减少曝光/增益 */
}
}
/**
* @brief 快速AE策略(一步到位)
*/
static void fast_ae_update(void* ctx, const isp_3a_stats_t* stats, ae_cfg_t* cfg)
{
/* 直接计算目标曝光值 */
float ratio = (float)cfg->target_luminance / (stats->avg_luminance + 1);
uint32_t new_exp = (uint32_t)(cfg->exposure_time_min * ratio);
if (new_exp > cfg->exposure_time_max) new_exp = cfg->exposure_time_max;
if (new_exp < cfg->exposure_time_min) new_exp = cfg->exposure_time_min;
/* 应用 */
}
/*=============================================================================
* AWB策略实现
*============================================================================*/
/**
* @brief 灰度世界策略(AWB)
*/
static void greyworld_awb_update(void* ctx, const isp_3a_stats_t* stats, awb_cfg_t* cfg)
{
/* 计算RGB平均值 */
uint32_t total_pixels = stats->sum_r + stats->sum_g + stats->sum_b;
if (total_pixels == 0) return;
float avg_r = (float)stats->sum_r / total_pixels;
float avg_g = (float)stats->sum_g / total_pixels;
float avg_b = (float)stats->sum_b / total_pixels;
/* 计算增益 */
float r_gain = avg_g / avg_r;
float b_gain = avg_g / avg_b;
/* 限制增益范围 */
if (r_gain > cfg->max_gain) r_gain = cfg->max_gain;
if (b_gain > cfg->max_gain) b_gain = cfg->max_gain;
/* 应用到ISP */
// isp_set_wb_gains(r_gain, 1.0f, b_gain);
}
/**
* @brief 完美反射策略(AWB)
*/
static void perfect_reflect_awb_update(void* ctx, const isp_3a_stats_t* stats, awb_cfg_t* cfg)
{
/* 找出最亮的10%像素作为参考白点 */
/* 简化实现 */
}
/*=============================================================================
* AF策略实现(状态模式)
*============================================================================*/
/**
* @brief 对焦状态机
*/
typedef enum {
AF_STATE_IDLE, ///< 空闲
AF_STATE_SCANNING, ///< 扫描中
AF_STATE_FOCUSED, ///< 已对焦
AF_STATE_LOST, ///< 失焦
AF_STATE_RETRY ///< 重试
} af_state_t;
/**
* @brief 爬山算法对焦上下文
*/
typedef struct {
af_state_t state; ///< 当前状态
int32_t current_pos; ///< 当前位置
int32_t best_pos; ///< 最佳位置
uint32_t best_value; ///< 最佳对焦值
int32_t step; ///< 步长
int direction; ///< 方向(1=正向,-1=反向)
uint32_t stable_count; ///< 稳定计数
uint32_t retry_count; ///< 重试计数
} hill_climbing_ctx_t;
static void hill_climbing_af_init(void* ctx)
{
hill_climbing_ctx_t* hc = (hill_climbing_ctx_t*)ctx;
memset(hc, 0, sizeof(hill_climbing_ctx_t));
hc->state = AF_STATE_IDLE;
}
static void hill_climbing_af_update(void* ctx, const isp_3a_stats_t* stats, af_cfg_t* cfg)
{
hill_climbing_ctx_t* hc = (hill_climbing_ctx_t*)ctx;
uint32_t fv = stats->focus_value;
switch (hc->state) {
case AF_STATE_IDLE:
/* 检测是否需要重新对焦 */
if (fv < cfg->focus_threshold || hc->stable_count > cfg->retrigger_frames) {
hc->state = AF_STATE_SCANNING;
hc->step = cfg->coarse_step;
hc->direction = 1;
hc->best_value = 0;
hc->current_pos = cfg->lens_min;
hc->retry_count = 0;
}
break;
case AF_STATE_SCANNING:
/* 移动镜头 */
hc->current_pos += hc->step * hc->direction;
if (hc->current_pos > cfg->lens_max) {
hc->current_pos = cfg->lens_max;
hc->direction = -1;
} else if (hc->current_pos < cfg->lens_min) {
hc->current_pos = cfg->lens_min;
/* 扫描完成,移动到最佳位置 */
hc->state = AF_STATE_FOCUSED;
/* 设置镜头到best_pos */
// vcm_set_position(hc->best_pos);
break;
}
/* 更新最佳位置 */
if (fv > hc->best_value) {
hc->best_value = fv;
hc->best_pos = hc->current_pos;
}
/* 应用镜头位置 */
// vcm_set_position(hc->current_pos);
/* 粗扫完成后切换到细扫 */
if (hc->step == cfg->coarse_step && hc->direction == -1 &&
hc->current_pos <= cfg->lens_min + cfg->coarse_step) {
hc->step = cfg->fine_step;
hc->direction = 1;
hc->current_pos = hc->best_pos - cfg->fine_step * 10;
if (hc->current_pos < cfg->lens_min) hc->current_pos = cfg->lens_min;
}
break;
case AF_STATE_FOCUSED:
/* 监控对焦质量 */
if (fv < hc->best_value * 0.7f) {
hc->state = AF_STATE_LOST;
hc->lost_count = 0;
}
break;
case AF_STATE_LOST:
hc->lost_count++;
if (hc->lost_count > cfg->lost_threshold) {
hc->state = AF_STATE_RETRY;
}
break;
case AF_STATE_RETRY:
hc->retry_count++;
if (hc->retry_count <= cfg->max_retry) {
hc->state = AF_STATE_SCANNING;
hc->step = cfg->coarse_step;
} else {
hc->state = AF_STATE_IDLE;
}
break;
}
}
/*=============================================================================
* 3A管理器(策略模式容器)
*============================================================================*/
/**
* @brief 3A管理器
*/
typedef struct {
/* 当前策略 */
ae_strategy_t* ae_strategy;
awb_strategy_t* awb_strategy;
af_strategy_t* af_strategy;
/* 策略上下文 */
void* ae_ctx;
void* awb_ctx;
void* af_ctx;
/* 配置 */
ae_cfg_t ae_cfg;
awb_cfg_t awb_cfg;
af_cfg_t af_cfg;
} isp_3a_manager_t;
/**
* @brief 创建3A管理器
*/
isp_3a_manager_t* isp_3a_create(void)
{
isp_3a_manager_t* mgr = (isp_3a_manager_t*)calloc(1, sizeof(isp_3a_manager_t));
if (!mgr) return NULL;
/* 默认使用PID AE */
static ae_strategy_t pid_ae = {
.name = "PID",
.init = pid_ae_init,
.update = pid_ae_update,
.deinit = NULL,
.priv = NULL
};
mgr->ae_strategy = &pid_ae;
mgr->ae_ctx = malloc(sizeof(pid_ctx_t));
mgr->ae_strategy->init(mgr->ae_ctx);
/* 默认使用灰度世界AWB */
static awb_strategy_t greyworld_awb = {
.name = "GreyWorld",
.init = NULL,
.update = greyworld_awb_update,
.deinit = NULL,
.priv = NULL
};
mgr->awb_strategy = &greyworld_awb;
/* 默认使用爬山法AF */
static af_strategy_t hill_climbing_af = {
.name = "HillClimbing",
.init = hill_climbing_af_init,
.update = hill_climbing_af_update,
.deinit = NULL,
.priv = NULL
};
mgr->af_strategy = &hill_climbing_af;
mgr->af_ctx = malloc(sizeof(hill_climbing_ctx_t));
mgr->af_strategy->init(mgr->af_ctx);
return mgr;
}
/**
* @brief 动态切换AE策略(策略模式核心)
*/
void isp_3a_set_ae_strategy(isp_3a_manager_t* mgr, ae_strategy_t* strategy)
{
if (!mgr) return;
/* 清理旧策略 */
if (mgr->ae_strategy && mgr->ae_strategy->deinit) {
mgr->ae_strategy->deinit(mgr->ae_ctx);
}
/* 切换新策略 */
mgr->ae_strategy = strategy;
if (strategy && strategy->init) {
strategy->init(mgr->ae_ctx);
}
}
/**
* @brief 运行3A处理(模板方法)
*/
void isp_3a_run(isp_3a_manager_t* mgr, const isp_3a_stats_t* stats)
{
if (!mgr || !stats) return;
/* 模板方法: 固定的处理流程 */
/* 1. 运行AE */
if (mgr->ae_strategy && mgr->ae_strategy->update) {
mgr->ae_strategy->update(mgr->ae_ctx, stats, &mgr->ae_cfg);
}
/* 2. 运行AWB */
if (mgr->awb_strategy && mgr->awb_strategy->update) {
mgr->awb_strategy->update(mgr->awb_ctx, stats, &mgr->awb_cfg);
}
/* 3. 运行AF(仅在需要时) */
if (mgr->af_strategy && mgr->af_strategy->update) {
mgr->af_strategy->update(mgr->af_ctx, stats, &mgr->af_cfg);
}
}
#endif /* ISP_3A_H */
三、观察者模式在事件循环中的应用
/**
* @file event_loop.h
* @brief 事件循环模块(观察者模式 + Reactor模式)
* @author System Architecture Team
*
* @section 设计模式
* - **观察者模式(Observer)**: 事件源订阅/通知机制
* - **Reactor模式**: IO多路复用事件分发
* - **单例模式(Singleton)**: 全局唯一事件循环实例
* - **命令模式(Command)**: 延迟执行的任务封装
*/
#ifndef EVENT_LOOP_H
#define EVENT_LOOP_H
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/epoll.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 事件类型定义
*============================================================================*/
/**
* @brief 事件类型(位掩码)
*/
typedef enum {
EVENT_NONE = 0x0000,
EVENT_NEW_FRAME = 0x0001, ///< 新视频帧到达
EVENT_ISP_3A_READY = 0x0002, ///< ISP 3A统计就绪
EVENT_AI_RESULT = 0x0004, ///< AI推理完成
EVENT_TIMER = 0x0008, ///< 定时器事件
EVENT_SIGNAL = 0x0010, ///< 信号事件
EVENT_CONFIG_CHANGE = 0x0020, ///< 配置变更
EVENT_ERROR = 0x8000 ///< 错误事件
} event_type_t;
/**
* @brief 事件优先级
*/
typedef enum {
EVENT_PRIO_LOW = 0, ///< 低优先级(日志/统计)
EVENT_PRIO_NORMAL = 1, ///< 普通优先级(配置变更)
EVENT_PRIO_HIGH = 2, ///< 高优先级(AI结果)
EVENT_PRIO_CRITICAL = 3 ///< 紧急优先级(帧数据)
} event_priority_t;
/*=============================================================================
* 事件结构体定义
*============================================================================*/
/**
* @brief 事件基类(观察者模式的通知对象)
*/
typedef struct event {
uint32_t event_id; ///< 事件唯一ID
event_type_t type; ///< 事件类型
event_priority_t priority; ///< 事件优先级
uint64_t timestamp; ///< 事件发生时间戳(纳秒)
uint32_t source_id; ///< 事件源ID
/* 事件数据(联合体) */
union {
struct {
void* frame_data; ///< 帧数据指针
uint32_t width; ///< 宽度
uint32_t height; ///< 高度
uint32_t format; ///< 像素格式
uint32_t sequence; ///< 帧序号
} frame_event;
struct {
uint32_t avg_luminance; ///< 平均亮度
uint16_t color_temp; ///< 色温
uint32_t focus_value; ///< 对焦值
} isp_event;
struct {
uint32_t object_count; ///< 检测目标数
void* detections; ///< 检测结果指针
uint32_t inference_us; ///< 推理耗时
} ai_event;
struct {
uint32_t timer_id; ///< 定时器ID
uint32_t repeat_count; ///< 重复次数
} timer_event;
struct {
int error_code; ///< 错误码
const char* error_msg; ///< 错误描述
} error_event;
} data;
/* 回调函数(用于异步响应) */
void (*on_complete)(struct event* evt, void* user_data);
void* user_data;
/* 链表指针 */
struct event* next;
} event_t;
/*=============================================================================
* 观察者接口定义
*============================================================================*/
/**
* @brief 观察者接口(观察者模式)
*
* @note 所有需要接收事件的对象都需要实现此接口
*/
typedef struct observer {
const char* name; ///< 观察者名称(调试用)
uint32_t id; ///< 观察者ID
/* 观察者方法 */
int (*on_event)(struct observer* self, const event_t* event);
/* 订阅的事件类型(位掩码) */
uint32_t subscribed_events;
/* 观察者优先级(数字越小越先处理) */
int priority;
/* 私有数据 */
void* priv;
/* 链表指针 */
struct observer* next;
} observer_t;
/*=============================================================================
* 定时器结构体
*============================================================================*/
/**
* @brief 定时器类型
*/
typedef enum {
TIMER_ONESHOT, ///< 单次定时器
TIMER_PERIODIC ///< 周期定时器
} timer_type_t;
/**
* @brief 定时器结构体
*/
typedef struct timer {
uint32_t timer_id; ///< 定时器ID
timer_type_t type; ///< 定时器类型
uint64_t interval_us; ///< 间隔时间(微秒)
uint64_t next_expire_us; ///< 下次到期时间
uint32_t repeat_count; ///< 重复次数(0=无限)
uint32_t fired_count; ///< 已触发次数
/* 回调函数 */
void (*callback)(uint32_t timer_id, void* user_data);
void* user_data;
/* 链表 */
struct timer* next;
} timer_t;
/*=============================================================================
* 延迟任务结构体(命令模式)
*============================================================================*/
/**
* @brief 延迟任务结构体
*/
typedef struct delayed_task {
uint32_t task_id; ///< 任务ID
uint64_t execute_time_us; ///< 执行时间
void (*func)(void* arg); ///< 任务函数
void* arg; ///< 任务参数
void (*cleanup)(void* arg); ///< 清理函数
struct delayed_task* next;
} delayed_task_t;
/*=============================================================================
* 事件循环主结构体
*============================================================================*/
/**
* @brief 事件循环配置
*/
typedef struct {
uint32_t max_events; ///< 最大事件数(默认64)
uint32_t event_queue_size; ///< 事件队列大小(默认1024)
int epoll_timeout_ms; ///< epoll超时(默认-1阻塞)
bool enable_priority_queue; ///< 启用优先级队列
bool enable_stats; ///< 启用统计
} event_loop_config_t;
/**
* @brief 事件循环上下文(单例模式)
*/
typedef struct event_loop {
/* epoll相关 */
int epoll_fd; ///< epoll文件描述符
struct epoll_event* epoll_events; ///< epoll事件数组
/* 观察者链表(观察者模式) */
observer_t* observers; ///< 观察者链表头
pthread_rwlock_t observer_lock; ///< 观察者读写锁
/* 事件队列(生产者-消费者模式) */
event_t** priority_queues; ///< 优先级队列数组(4个优先级)
uint32_t* queue_sizes; ///< 各队列当前大小
uint32_t max_queue_size; ///< 最大队列大小
pthread_mutex_t queue_lock; ///< 队列锁
pthread_cond_t queue_cond; ///< 队列条件变量
/* 定时器管理 */
timer_t* timers; ///< 定时器链表
uint32_t next_timer_id; ///< 下一个定时器ID
pthread_mutex_t timer_lock; ///< 定时器锁
int timer_fd; ///< timerfd文件描述符
/* 延迟任务 */
delayed_task_t* delayed_tasks; ///< 延迟任务链表
pthread_mutex_t task_lock; ///< 任务锁
/* 工作线程池 */
pthread_t* worker_threads;
uint32_t worker_count;
volatile bool running;
/* 统计信息 */
struct {
uint64_t total_events; ///< 总事件数
uint64_t dropped_events; ///< 丢弃事件数
uint64_t max_queue_usage; ///< 最大队列使用率
uint64_t avg_latency_us; ///< 平均处理延迟
uint64_t timer_fired; ///< 定时器触发次数
} stats;
/* 配置 */
event_loop_config_t config;
} event_loop_t;
/*=============================================================================
* 事件循环API
*============================================================================*/
/**
* @brief 获取全局事件循环实例(单例模式)
* @param config 配置(首次调用时必须提供)
* @return 事件循环实例
*/
event_loop_t* event_loop_get_instance(const event_loop_config_t* config);
/**
* @brief 启动事件循环
* @param loop 事件循环实例
* @return 成功返回0
*/
int event_loop_start(event_loop_t* loop);
/**
* @brief 停止事件循环
* @param loop 事件循环实例
*/
void event_loop_stop(event_loop_t* loop);
/**
* @brief 注册观察者(订阅事件)
* @param loop 事件循环实例
* @param observer 观察者对象
* @return 成功返回0
*/
int event_loop_register_observer(event_loop_t* loop, observer_t* observer);
/**
* @brief 注销观察者
* @param loop 事件循环实例
* @param observer_id 观察者ID
* @return 成功返回0
*/
int event_loop_unregister_observer(event_loop_t* loop, uint32_t observer_id);
/**
* @brief 发布事件(异步通知)
* @param loop 事件循环实例
* @param event 事件对象(会被拷贝)
* @return 成功返回0
*
* @note 设计模式: 观察者模式 - 通知所有订阅的观察者
*/
int event_loop_publish(event_loop_t* loop, const event_t* event);
/**
* @brief 添加文件描述符监听(Reactor模式)
* @param loop 事件循环实例
* @param fd 文件描述符
* @param events epoll事件(EPOLLIN|EPOLLOUT等)
* @param callback 回调函数
* @param user_data 用户数据
* @return 成功返回0
*/
int event_loop_add_fd(event_loop_t* loop, int fd, uint32_t events,
void (*callback)(int fd, uint32_t events, void* user_data),
void* user_data);
/**
* @brief 移除文件描述符监听
* @param loop 事件循环实例
* @param fd 文件描述符
* @return 成功返回0
*/
int event_loop_remove_fd(event_loop_t* loop, int fd);
/**
* @brief 创建定时器
* @param loop 事件循环实例
* @param interval_us 间隔时间(微秒)
* @param type 定时器类型
* @param callback 回调函数
* @param user_data 用户数据
* @return 定时器ID(0表示失败)
*/
uint32_t event_loop_create_timer(event_loop_t* loop, uint64_t interval_us,
timer_type_t type,
void (*callback)(uint32_t timer_id, void* user_data),
void* user_data);
/**
* @brief 删除定时器
* @param loop 事件循环实例
* @param timer_id 定时器ID
* @return 成功返回0
*/
int event_loop_delete_timer(event_loop_t* loop, uint32_t timer_id);
/**
* @brief 添加延迟任务(命令模式)
* @param loop 事件循环实例
* @param delay_us 延迟时间(微秒)
* @param func 任务函数
* @param arg 参数
* @param cleanup 清理函数
* @return 任务ID
*/
uint32_t event_loop_add_delayed_task(event_loop_t* loop, uint64_t delay_us,
void (*func)(void* arg), void* arg,
void (*cleanup)(void* arg));
/**
* @brief 获取事件循环统计信息
* @param loop 事件循环实例
* @param stats 输出统计信息
*/
void event_loop_get_stats(event_loop_t* loop, void* stats);
#ifdef __cplusplus
}
#endif
#endif /* EVENT_LOOP_H */
/**
* @file event_loop.c
* @brief 事件循环实现(观察者模式 + Reactor模式)
*/
#include "event_loop.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/timerfd.h>
#include <time.h>
/*=============================================================================
* 内部辅助函数
*============================================================================*/
/**
* @brief 获取当前时间戳(微秒)
*/
static inline uint64_t get_time_us(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
}
/**
* @brief 事件拷贝(深拷贝)
*/
static void event_copy(event_t* dest, const event_t* src)
{
memcpy(dest, src, sizeof(event_t));
/* 如果有动态数据需要深拷贝,在这里处理 */
}
/*=============================================================================
* 优先级队列实现
*============================================================================*/
/**
* @brief 获取优先级队列索引
*/
static inline int get_queue_index(event_priority_t priority)
{
int idx = (int)priority;
if (idx < 0) idx = 0;
if (idx > 3) idx = 3;
return idx;
}
/**
* @brief 入队事件(按优先级)
*/
static int event_queue_push(event_loop_t* loop, const event_t* event)
{
int idx = get_queue_index(event->priority);
/* 检查队列是否满 */
if (loop->queue_sizes[idx] >= loop->max_queue_size) {
/* 队列满,丢弃最低优先级事件 */
if (idx > 0) {
/* 尝试降级到低优先级队列 */
idx--;
if (loop->queue_sizes[idx] < loop->max_queue_size) {
goto enqueue;
}
}
loop->stats.dropped_events++;
return -1;
}
enqueue:
/* 分配新事件节点 */
event_t* new_event = (event_t*)malloc(sizeof(event_t));
if (!new_event) return -2;
event_copy(new_event, event);
/* 入队(简单FIFO,可优化为按时间戳排序) */
new_event->next = NULL;
pthread_mutex_lock(&loop->queue_lock);
/* 找到队列尾 */
event_t** tail = &loop->priority_queues[idx];
while (*tail) {
tail = &(*tail)->next;
}
*tail = new_event;
loop->queue_sizes[idx]++;
/* 更新统计 */
if (loop->queue_sizes[idx] > loop->stats.max_queue_usage) {
loop->stats.max_queue_usage = loop->queue_sizes[idx];
}
pthread_cond_signal(&loop->queue_cond);
pthread_mutex_unlock(&loop->queue_lock);
return 0;
}
/**
* @brief 出队事件(按优先级)
*/
static event_t* event_queue_pop(event_loop_t* loop)
{
event_t* event = NULL;
pthread_mutex_lock(&loop->queue_lock);
/* 从高优先级到低优先级查找 */
for (int i = 3; i >= 0; i--) {
if (loop->priority_queues[i]) {
event = loop->priority_queues[i];
loop->priority_queues[i] = event->next;
loop->queue_sizes[i]--;
break;
}
}
pthread_mutex_unlock(&loop->queue_lock);
return event;
}
/*=============================================================================
* 定时器管理
*============================================================================*/
/**
* @brief 更新timerfd
*/
static void update_timerfd(event_loop_t* loop)
{
uint64_t min_expire = UINT64_MAX;
timer_t* timer = loop->timers;
/* 找到最近的到期时间 */
while (timer) {
if (timer->next_expire_us < min_expire) {
min_expire = timer->next_expire_us;
}
timer = timer->next;
}
/* 设置timerfd */
if (min_expire != UINT64_MAX) {
uint64_t now_us = get_time_us();
uint64_t expire_ms = 0;
if (min_expire > now_us) {
expire_ms = (min_expire - now_us) / 1000;
}
struct itimerspec its = {
.it_value = {
.tv_sec = expire_ms / 1000,
.tv_nsec = (expire_ms % 1000) * 1000000
}
};
timerfd_settime(loop->timer_fd, 0, &its, NULL);
}
}
/**
* @brief 处理到期的定时器
*/
static void process_timers(event_loop_t* loop)
{
uint64_t expirations;
ssize_t s = read(loop->timer_fd, &expirations, sizeof(uint64_t));
if (s != sizeof(uint64_t)) return;
uint64_t now_us = get_time_us();
pthread_mutex_lock(&loop->timer_lock);
timer_t* timer = loop->timers;
timer_t* prev = NULL;
while (timer) {
if (timer->next_expire_us <= now_us) {
/* 定时器到期 */
loop->stats.timer_fired++;
/* 调用回调 */
if (timer->callback) {
timer->callback(timer->timer_id, timer->user_data);
}
/* 更新定时器状态 */
if (timer->type == TIMER_PERIODIC) {
/* 周期定时器: 重新调度 */
timer->fired_count++;
if (timer->repeat_count == 0 ||
timer->fired_count < timer->repeat_count) {
timer->next_expire_us = now_us + timer->interval_us;
prev = timer;
timer = timer->next;
continue;
}
}
/* 删除定时器(单次或已到期) */
timer_t* to_delete = timer;
if (prev) {
prev->next = timer->next;
timer = timer->next;
} else {
loop->timers = timer->next;
timer = loop->timers;
}
free(to_delete);
} else {
prev = timer;
timer = timer->next;
}
}
pthread_mutex_unlock(&loop->timer_lock);
/* 更新timerfd */
update_timerfd(loop);
}
/*=============================================================================
* 观察者管理(观察者模式核心)
*============================================================================*/
/**
* @brief 通知所有观察者
*/
static void notify_observers(event_loop_t* loop, const event_t* event)
{
pthread_rwlock_rdlock(&loop->observer_lock);
observer_t* observer = loop->observers;
/* 按优先级排序(简单插入排序) */
/* 这里简化处理,实际应维护优先级队列 */
while (observer) {
/* 检查是否订阅了该事件类型 */
if (observer->subscribed_events & event->type) {
uint64_t start_us = get_time_us();
/* 调用观察者处理函数 */
int ret = observer->on_event(observer, event);
/* 更新延迟统计 */
uint64_t latency_us = get_time_us() - start_us;
loop->stats.avg_latency_us =
(loop->stats.avg_latency_us * loop->stats.total_events + latency_us) /
(loop->stats.total_events + 1);
(void)ret; /* 可记录错误 */
}
observer = observer->next;
}
pthread_rwlock_unlock(&loop->observer_lock);
}
/*=============================================================================
* 工作线程函数
*============================================================================*/
/**
* @brief 工作线程入口
*/
static void* worker_thread_func(void* arg)
{
event_loop_t* loop = (event_loop_t*)arg;
while (loop->running) {
/* 等待事件 */
event_t* event = event_queue_pop(loop);
if (event) {
/* 处理事件 */
loop->stats.total_events++;
notify_observers(loop, event);
/* 释放事件 */
free(event);
} else {
/* 队列空,短暂休眠 */
usleep(1000);
}
}
return NULL;
}
/*=============================================================================
* epoll事件处理(Reactor模式)
*============================================================================*/
/**
* @brief epoll事件处理结构体
*/
typedef struct fd_handler {
int fd;
void (*callback)(int fd, uint32_t events, void* user_data);
void* user_data;
} fd_handler_t;
static fd_handler_t* g_fd_handlers[1024]; /* 简化实现 */
/**
* @brief epoll主循环
*/
static void epoll_loop(event_loop_t* loop)
{
while (loop->running) {
int nfds = epoll_wait(loop->epoll_fd, loop->epoll_events,
loop->config.max_events,
loop->config.epoll_timeout_ms);
if (nfds < 0) {
if (errno == EINTR) continue;
break;
}
for (int i = 0; i < nfds; i++) {
int fd = loop->epoll_events[i].data.fd;
uint32_t events = loop->epoll_events[i].events;
/* 处理timerfd */
if (fd == loop->timer_fd) {
process_timers(loop);
continue;
}
/* 查找并调用处理器 */
if (fd >= 0 && fd < 1024 && g_fd_handlers[fd]) {
fd_handler_t* handler = g_fd_handlers[fd];
if (handler->callback) {
handler->callback(fd, events, handler->user_data);
}
}
}
}
}
/*=============================================================================
* 事件循环主API实现
*============================================================================*/
static event_loop_t* g_instance = NULL;
event_loop_t* event_loop_get_instance(const event_loop_config_t* config)
{
if (g_instance) return g_instance;
if (!config) return NULL;
event_loop_t* loop = (event_loop_t*)calloc(1, sizeof(event_loop_t));
if (!loop) return NULL;
/* 保存配置 */
memcpy(&loop->config, config, sizeof(event_loop_config_t));
if (loop->config.max_events == 0) loop->config.max_events = 64;
if (loop->config.event_queue_size == 0) loop->config.event_queue_size = 1024;
loop->max_queue_size = loop->config.event_queue_size;
/* 初始化epoll */
loop->epoll_fd = epoll_create1(0);
if (loop->epoll_fd < 0) {
free(loop);
return NULL;
}
loop->epoll_events = (struct epoll_event*)calloc(loop->config.max_events,
sizeof(struct epoll_event));
/* 初始化优先级队列(4个优先级) */
loop->priority_queues = (event_t**)calloc(4, sizeof(event_t*));
loop->queue_sizes = (uint32_t*)calloc(4, sizeof(uint32_t));
/* 初始化锁 */
pthread_mutex_init(&loop->queue_lock, NULL);
pthread_cond_init(&loop->queue_cond, NULL);
pthread_rwlock_init(&loop->observer_lock, NULL);
pthread_mutex_init(&loop->timer_lock, NULL);
pthread_mutex_init(&loop->task_lock, NULL);
/* 创建timerfd */
loop->timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
if (loop->timer_fd >= 0) {
/* 添加到epoll */
struct epoll_event ev = {
.events = EPOLLIN,
.data.fd = loop->timer_fd
};
epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, loop->timer_fd, &ev);
}
g_instance = loop;
return loop;
}
int event_loop_start(event_loop_t* loop)
{
if (!loop) return -1;
if (loop->running) return 0;
loop->running = true;
/* 创建工作线程 */
loop->worker_count = 2; /* 2个工作线程 */
loop->worker_threads = (pthread_t*)calloc(loop->worker_count, sizeof(pthread_t));
for (uint32_t i = 0; i < loop->worker_count; i++) {
pthread_create(&loop->worker_threads[i], NULL, worker_thread_func, loop);
}
/* 主线程运行epoll循环 */
epoll_loop(loop);
return 0;
}
void event_loop_stop(event_loop_t* loop)
{
if (!loop) return;
loop->running = false;
/* 等待工作线程结束 */
for (uint32_t i = 0; i < loop->worker_count; i++) {
pthread_join(loop->worker_threads[i], NULL);
}
}
int event_loop_register_observer(event_loop_t* loop, observer_t* observer)
{
if (!loop || !observer) return -1;
pthread_rwlock_wrlock(&loop->observer_lock);
/* 插入到链表头 */
observer->next = loop->observers;
loop->observers = observer;
pthread_rwlock_unlock(&loop->observer_lock);
return 0;
}
int event_loop_publish(event_loop_t* loop, const event_t* event)
{
if (!loop || !event) return -1;
/* 设置时间戳(如果未设置) */
event_t local_event;
event_copy(&local_event, event);
if (local_event.timestamp == 0) {
local_event.timestamp = get_time_us();
}
return event_queue_push(loop, &local_event);
}
int event_loop_add_fd(event_loop_t* loop, int fd, uint32_t events,
void (*callback)(int fd, uint32_t events, void* user_data),
void* user_data)
{
if (!loop || fd < 0 || fd >= 1024) return -1;
/* 分配处理器 */
fd_handler_t* handler = (fd_handler_t*)calloc(1, sizeof(fd_handler_t));
if (!handler) return -2;
handler->fd = fd;
handler->callback = callback;
handler->user_data = user_data;
g_fd_handlers[fd] = handler;
/* 添加到epoll */
struct epoll_event ev = {
.events = events,
.data.fd = fd
};
return epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ev);
}
int event_loop_remove_fd(event_loop_t* loop, int fd)
{
if (!loop || fd < 0 || fd >= 1024) return -1;
epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
if (g_fd_handlers[fd]) {
free(g_fd_handlers[fd]);
g_fd_handlers[fd] = NULL;
}
return 0;
}
uint32_t event_loop_create_timer(event_loop_t* loop, uint64_t interval_us,
timer_type_t type,
void (*callback)(uint32_t timer_id, void* user_data),
void* user_data)
{
if (!loop || !callback) return 0;
timer_t* timer = (timer_t*)calloc(1, sizeof(timer_t));
if (!timer) return 0;
pthread_mutex_lock(&loop->timer_lock);
timer->timer_id = ++loop->next_timer_id;
timer->type = type;
timer->interval_us = interval_us;
timer->next_expire_us = get_time_us() + interval_us;
timer->callback = callback;
timer->user_data = user_data;
/* 插入链表 */
timer->next = loop->timers;
loop->timers = timer;
pthread_mutex_unlock(&loop->timer_lock);
/* 更新timerfd */
update_timerfd(loop);
return timer->timer_id;
}
/*=============================================================================
* 示例观察者实现
*============================================================================*/
/**
* @brief AI结果观察者示例
*/
static int ai_result_observer_on_event(observer_t* self, const event_t* event)
{
if (event->type == EVENT_AI_RESULT) {
/* 处理AI结果 */
printf("[AI Observer] Received AI result: %u objects\n",
event->data.ai_event.object_count);
/* 可以触发RTSP推流、MQTT上报等 */
}
return 0;
}
/**
* @brief 创建AI结果观察者
*/
observer_t* create_ai_result_observer(void)
{
static uint32_t observer_id = 1000;
observer_t* obs = (observer_t*)calloc(1, sizeof(observer_t));
if (!obs) return NULL;
obs->name = "AIResultObserver";
obs->id = observer_id++;
obs->on_event = ai_result_observer_on_event;
obs->subscribed_events = EVENT_AI_RESULT;
obs->priority = EVENT_PRIO_HIGH;
return obs;
}
四、内存管理模块
/**
* @file memory_manager.h
* @brief 内存管理模块(对象池模式 + 内存池模式)
* @author System Team
*
* @section 设计模式
* - **对象池模式(Object Pool)**: 复用帧对象/AI张量对象
* - **内存池模式(Memory Pool)**: 预分配固定大小内存块
* - **单例模式(Singleton)**: 全局内存管理器
* - **策略模式(Strategy)**: 不同场景使用不同分配策略
*/
#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 内存块结构体
*============================================================================*/
/**
* @brief 内存块头部(用于内存池管理)
*/
typedef struct mem_block {
uint32_t magic; ///< 魔数(0x4D454D42)
uint32_t size; ///< 块大小
bool used; ///< 是否使用中
uint32_t alloc_count; ///< 分配计数(调试用)
uint64_t alloc_time_us; ///< 分配时间戳
const char* alloc_file; ///< 分配文件(调试)
int alloc_line; ///< 分配行号(调试)
struct mem_block* next; ///< 下一个空闲块
} mem_block_t;
/*=============================================================================
* 内存池结构体
*============================================================================*/
/**
* @brief 内存池类型
*/
typedef enum {
MEM_POOL_CMA, ///< CMA连续内存池(用于DMA/ISP)
MEM_POOL_DMA, ///< DMA缓冲区池
MEM_POOL_SLAB, ///< SLAB对象缓存(固定大小)
MEM_POOL_AI_TENSOR, ///< AI张量内存池
MEM_POOL_FRAME ///< 帧数据内存池
} mem_pool_type_t;
/**
* @brief 内存池配置
*/
typedef struct {
mem_pool_type_t type; ///< 池类型
const char* name; ///< 池名称
size_t block_size; ///< 块大小(对于SLAB池)
size_t block_count; ///< 块数量
size_t total_size; ///< 总大小(对于CMA池)
uint32_t flags; ///< 标志位
#define MEM_FLAG_CACHE_ALIGN 0x01 ///< 缓存行对齐(64字节)
#define MEM_FLAG_ZERO_INIT 0x02 ///< 初始化为0
#define MEM_FLAG_NO_MMAP 0x04 ///< 不使用mmap
} mem_pool_cfg_t;
/**
* @brief 内存池统计信息
*/
typedef struct {
size_t total_bytes; ///< 总字节数
size_t used_bytes; ///< 已用字节数
size_t peak_bytes; ///< 峰值字节数
uint32_t alloc_count; ///< 分配次数
uint32_t free_count; ///< 释放次数
uint32_t fail_count; ///< 失败次数
uint64_t total_alloc_time_us; ///< 总分配耗时
uint64_t max_alloc_time_us; ///< 最大分配耗时
} mem_pool_stat_t;
/**
* @brief 内存池句柄(不透明指针)
*/
typedef struct mem_pool mem_pool_t;
/*=============================================================================
* SLAB缓存(对象池)
*============================================================================*/
/**
* @brief SLAB缓存配置
*/
typedef struct {
const char* name; ///< 缓存名称
size_t object_size; ///< 对象大小
size_t slab_size; ///< SLAB大小(字节)
uint32_t align; ///< 对齐要求
void (*ctor)(void* obj); ///< 构造函数
void (*dtor)(void* obj); ///< 析构函数
} slab_cache_cfg_t;
/**
* @brief SLAB缓存句柄
*/
typedef struct slab_cache slab_cache_t;
/*=============================================================================
* 内存管理器API
*============================================================================*/
/**
* @brief 初始化内存管理器(单例模式)
* @param config 内存池配置数组
* @param pool_count 配置数量
* @return 成功返回0
*/
int memory_manager_init(const mem_pool_cfg_t* configs, uint32_t pool_count);
/**
* @brief 从内存池分配内存
* @param pool_name 内存池名称
* @param size 需要分配的大小
* @return 内存指针(失败返回NULL)
*
* @note 设计模式: 对象池模式 - 从预分配池中获取对象
*/
void* memory_pool_alloc(const char* pool_name, size_t size);
/**
* @brief 释放内存回池
* @param pool_name 内存池名称
* @param ptr 内存指针
*/
void memory_pool_free(const char* pool_name, void* ptr);
/**
* @brief 获取内存池统计信息
* @param pool_name 内存池名称
* @param stat 输出统计信息
* @return 成功返回0
*/
int memory_pool_get_stat(const char* pool_name, mem_pool_stat_t* stat);
/**
* @brief 创建SLAB缓存(对象池)
* @param cfg SLAB配置
* @return SLAB缓存句柄
*/
slab_cache_t* slab_cache_create(const slab_cache_cfg_t* cfg);
/**
* @brief 从SLAB缓存分配对象
* @param cache SLAB缓存句柄
* @return 对象指针
*/
void* slab_cache_alloc(slab_cache_t* cache);
/**
* @brief 释放对象回SLAB缓存
* @param cache SLAB缓存句柄
* @param obj 对象指针
*/
void slab_cache_free(slab_cache_t* cache, void* obj);
/**
* @brief 销毁SLAB缓存
* @param cache SLAB缓存句柄
*/
void slab_cache_destroy(slab_cache_t* cache);
/**
* @brief 全局内存调试信息打印
*/
void memory_manager_dump_stats(void);
#ifdef __cplusplus
}
#endif
#endif /* MEMORY_MANAGER_H */
/**
* @file memory_manager.c
* @brief 内存管理实现
*/
#include "memory_manager.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
/*=============================================================================
* 内存池实现
*============================================================================*/
/**
* @brief 内存池结构体
*/
struct mem_pool {
char name[64]; ///< 池名称
mem_pool_type_t type; ///< 池类型
size_t block_size; ///< 块大小
size_t block_count; ///< 块数量
size_t total_size; ///< 总大小
uint32_t flags; ///< 标志位
void* base_addr; ///< 基地址
mem_block_t* free_list; ///< 空闲链表
mem_block_t* blocks; ///< 块数组
/* 统计信息 */
mem_pool_stat_t stats;
/* 锁 */
pthread_mutex_t lock;
/* 下一个池 */
struct mem_pool* next;
};
/* 全局内存池链表 */
static mem_pool_t* g_pools = NULL;
static pthread_mutex_t g_pools_lock = PTHREAD_MUTEX_INITIALIZER;
static bool g_initialized = false;
/**
* @brief 查找内存池
*/
static mem_pool_t* find_pool(const char* name)
{
mem_pool_t* pool = g_pools;
while (pool) {
if (strcmp(pool->name, name) == 0) {
return pool;
}
pool = pool->next;
}
return NULL;
}
/**
* @brief 创建CMA连续内存池
*/
static int create_cma_pool(mem_pool_t* pool, const mem_pool_cfg_t* cfg)
{
/* 使用mmap分配大块连续内存 */
int fd = open("/dev/mem", O_RDWR);
if (fd < 0) {
/* 降级使用匿名mmap */
pool->base_addr = mmap(NULL, cfg->total_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
} else {
/* 从CMA区域分配(简化) */
pool->base_addr = mmap(NULL, cfg->total_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close(fd);
}
if (pool->base_addr == MAP_FAILED) {
return -1;
}
pool->total_size = cfg->total_size;
pool->block_count = 1; /* CMA池作为一个大块 */
pool->block_size = cfg->total_size;
return 0;
}
/**
* @brief 创建SLAB内存池
*/
static int create_slab_pool(mem_pool_t* pool, const mem_pool_cfg_t* cfg)
{
size_t aligned_block_size = cfg->block_size;
/* 对齐到8字节 */
if (aligned_block_size & 7) {
aligned_block_size = (aligned_block_size + 7) & ~7;
}
/* 增加头部大小 */
size_t block_with_header = aligned_block_size + sizeof(mem_block_t);
/* 总内存大小 */
pool->total_size = block_with_header * cfg->block_count;
/* 分配内存 */
pool->base_addr = mmap(NULL, pool->total_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (pool->base_addr == MAP_FAILED) {
return -1;
}
pool->block_size = aligned_block_size;
pool->block_count = cfg->block_count;
/* 初始化空闲链表 */
pool->blocks = (mem_block_t*)pool->base_addr;
pool->free_list = NULL;
char* base = (char*)pool->base_addr;
for (size_t i = 0; i < pool->block_count; i++) {
mem_block_t* block = (mem_block_t*)(base + i * block_with_header);
block->magic = 0x4D454D42;
block->size = pool->block_size;
block->used = false;
block->next = pool->free_list;
pool->free_list = block;
}
return 0;
}
int memory_manager_init(const mem_pool_cfg_t* configs, uint32_t pool_count)
{
if (g_initialized) return 0;
pthread_mutex_lock(&g_pools_lock);
for (uint32_t i = 0; i < pool_count; i++) {
const mem_pool_cfg_t* cfg = &configs[i];
mem_pool_t* pool = (mem_pool_t*)calloc(1, sizeof(mem_pool_t));
if (!pool) continue;
strncpy(pool->name, cfg->name, sizeof(pool->name) - 1);
pool->type = cfg->type;
pool->flags = cfg->flags;
pthread_mutex_init(&pool->lock, NULL);
int ret = 0;
switch (cfg->type) {
case MEM_POOL_CMA:
ret = create_cma_pool(pool, cfg);
break;
case MEM_POOL_SLAB:
case MEM_POOL_FRAME:
case MEM_POOL_AI_TENSOR:
ret = create_slab_pool(pool, cfg);
break;
default:
ret = -1;
break;
}
if (ret == 0) {
/* 添加到链表 */
pool->next = g_pools;
g_pools = pool;
} else {
free(pool);
}
}
g_initialized = true;
pthread_mutex_unlock(&g_pools_lock);
return 0;
}
void* memory_pool_alloc(const char* pool_name, size_t size)
{
mem_pool_t* pool = find_pool(pool_name);
if (!pool) return NULL;
pthread_mutex_lock(&pool->lock);
mem_block_t* block = pool->free_list;
if (!block) {
pool->stats.fail_count++;
pthread_mutex_unlock(&pool->lock);
return NULL;
}
/* 从空闲链表移除 */
pool->free_list = block->next;
/* 标记为已使用 */
block->used = true;
block->alloc_count++;
block->alloc_time_us = 0; /* 可设置时间戳 */
/* 更新统计 */
pool->stats.alloc_count++;
pool->stats.used_bytes += block->size;
if (pool->stats.used_bytes > pool->stats.peak_bytes) {
pool->stats.peak_bytes = pool->stats.used_bytes;
}
pthread_mutex_unlock(&pool->lock);
/* 返回数据区域指针 */
return (void*)((char*)block + sizeof(mem_block_t));
}
void memory_pool_free(const char* pool_name, void* ptr)
{
if (!ptr) return;
mem_pool_t* pool = find_pool(pool_name);
if (!pool) {
free(ptr); /* 降级使用标准free */
return;
}
/* 获取块头部 */
mem_block_t* block = (mem_block_t*)((char*)ptr - sizeof(mem_block_t));
/* 验证魔数 */
if (block->magic != 0x4D454D42) {
/* 不是池内存,使用标准free */
free(ptr);
return;
}
pthread_mutex_lock(&pool->lock);
/* 标记为空闲 */
block->used = false;
/* 回收到空闲链表 */
block->next = pool->free_list;
pool->free_list = block;
/* 更新统计 */
pool->stats.free_count++;
pool->stats.used_bytes -= block->size;
pthread_mutex_unlock(&pool->lock);
}
void memory_manager_dump_stats(void)
{
printf("\n========== Memory Manager Statistics ==========\n");
mem_pool_t* pool = g_pools;
while (pool) {
printf("\nPool: %s\n", pool->name);
printf(" Type: %d\n", pool->type);
printf(" Total: %zu bytes\n", pool->total_size);
printf(" Used: %zu bytes (%.1f%%)\n",
pool->stats.used_bytes,
(float)pool->stats.used_bytes / pool->total_size * 100);
printf(" Peak: %zu bytes\n", pool->stats.peak_bytes);
printf(" Allocs: %u, Frees: %u, Fails: %u\n",
pool->stats.alloc_count,
pool->stats.free_count,
pool->stats.fail_count);
pool = pool->next;
}
printf("===============================================\n");
}
五、日志管理模块
/**
* @file logger.h
* @brief 异步日志模块(生产者-消费者模式)
* @author System Team
*
* @section 设计模式
* - **生产者-消费者模式**: 异步日志写入
* - **单例模式**: 全局日志管理器
* - **装饰器模式**: 支持多种输出目标(文件/控制台/网络)
* - **策略模式**: 不同级别不同处理策略
*/
#ifndef LOGGER_H
#define LOGGER_H
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
* 日志级别定义
*============================================================================*/
typedef enum {
LOG_LEVEL_FATAL = 0, ///< 致命错误(会导致程序退出)
LOG_LEVEL_ERROR = 1, ///< 错误
LOG_LEVEL_WARN = 2, ///< 警告
LOG_LEVEL_INFO = 3, ///< 信息
LOG_LEVEL_DEBUG = 4, ///< 调试
LOG_LEVEL_TRACE = 5 ///< 追踪(详细)
} log_level_t;
/*=============================================================================
* 日志输出目标
*============================================================================*/
typedef enum {
LOG_OUTPUT_CONSOLE = 0x01, ///< 控制台输出
LOG_OUTPUT_FILE = 0x02, ///< 文件输出
LOG_OUTPUT_SYSLOG = 0x04, ///< syslog输出
LOG_OUTPUT_NETWORK = 0x08, ///< 网络输出(UDP)
LOG_OUTPUT_RINGBUF = 0x10 ///< 环形缓冲区(供调试)
} log_output_t;
/*=============================================================================
* 日志配置
*============================================================================*/
/**
* @brief 日志配置结构体
*/
typedef struct {
log_level_t level; ///< 日志级别
uint32_t output; ///< 输出目标(位掩码)
const char* file_path; ///< 日志文件路径
size_t file_max_size; ///< 文件最大大小(字节,默认10MB)
uint32_t file_max_count; ///< 最大文件数(轮转)
const char* network_host; ///< 网络主机
uint16_t network_port; ///< 网络端口
size_t ringbuf_size; ///< 环形缓冲区大小
bool enable_timestamp; ///< 启用时间戳
bool enable_thread_id; ///< 启用线程ID
bool enable_file_line; ///< 启用文件行号
bool async_mode; ///< 异步模式(默认true)
size_t async_queue_size; ///< 异步队列大小(默认4096)
} logger_config_t;
/*=============================================================================
* 日志API
*============================================================================*/
/**
* @brief 初始化日志系统(单例模式)
* @param config 日志配置
* @return 成功返回0
*/
int logger_init(const logger_config_t* config);
/**
* @brief 反初始化日志系统
*/
void logger_deinit(void);
/**
* @brief 设置日志级别
* @param level 新级别
*/
void logger_set_level(log_level_t level);
/**
* @brief 核心日志函数
* @param level 日志级别
* @param file 文件名
* @param line 行号
* @param func 函数名
* @param fmt 格式化字符串
* @param ... 可变参数
*/
void logger_log(log_level_t level, const char* file, int line,
const char* func, const char* fmt, ...)
__attribute__((format(printf, 5, 6)));
/**
* @brief 获取日志环形缓冲区数据(用于调试)
* @param buf 输出缓冲区
* @param size 缓冲区大小
* @return 实际写入大小
*/
size_t logger_get_ringbuf(char* buf, size_t size);
/**
* @brief 强制刷新日志缓冲区
*/
void logger_flush(void);
/*=============================================================================
* 便捷宏定义
*============================================================================*/
#define LOG_FATAL(fmt, ...) \
logger_log(LOG_LEVEL_FATAL, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) \
logger_log(LOG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) \
logger_log(LOG_LEVEL_WARN, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) \
logger_log(LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_DEBUG(fmt, ...) \
logger_log(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_TRACE(fmt, ...) \
logger_log(LOG_LEVEL_TRACE, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
/* 条件日志 */
#define LOG_IF(condition, level, fmt, ...) \
do { if (condition) logger_log(level, __FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__); } while(0)
#ifdef __cplusplus
}
#endif
#endif /* LOGGER_H */
/**
* @file logger.c
* @brief 异步日志实现
*/
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include <stdarg.h>
/*=============================================================================
* 日志条目结构体
*============================================================================*/
/**
* @brief 日志条目
*/
typedef struct log_entry {
log_level_t level; ///< 级别
char file[32]; ///< 文件名
int line; ///< 行号
char func[32]; ///< 函数名
uint64_t timestamp_us; ///< 时间戳(微秒)
uint32_t thread_id; ///< 线程ID
char message[512]; ///< 日志消息
struct log_entry* next;
} log_entry_t;
/*=============================================================================
* 日志上下文
*============================================================================*/
typedef struct {
logger_config_t config; ///< 配置
/* 异步队列(生产者-消费者) */
log_entry_t* queue_head; ///< 队列头
log_entry_t* queue_tail; ///< 队列尾
size_t queue_size; ///< 当前队列大小
pthread_mutex_t queue_lock; ///< 队列锁
pthread_cond_t queue_cond; ///< 队列条件变量
/* 日志线程 */
pthread_t log_thread;
volatile bool running;
/* 文件输出 */
FILE* log_file;
size_t current_file_size;
/* 环形缓冲区(调试用) */
char* ringbuf;
size_t ringbuf_write_pos;
pthread_mutex_t ringbuf_lock;
/* 网络socket */
int udp_socket;
/* 统计 */
uint64_t total_logs;
uint64_t dropped_logs;
} logger_context_t;
static logger_context_t* g_ctx = NULL;
static const char* level_names[] = {"FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"};
/*=============================================================================
* 辅助函数
*============================================================================*/
/**
* @brief 获取当前时间字符串
*/
static void format_time(uint64_t timestamp_us, char* buf, size_t size)
{
time_t sec = timestamp_us / 1000000;
struct tm tm;
localtime_r(&sec, &tm);
uint32_t us = timestamp_us % 1000000;
snprintf(buf, size, "%04d-%02d-%02d %02d:%02d:%02d.%06u",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, us);
}
/**
* @brief 日志文件轮转
*/
static void rotate_log_file(void)
{
if (!g_ctx->log_file) return;
fclose(g_ctx->log_file);
/* 重命名旧文件 */
char old_path[512];
snprintf(old_path, sizeof(old_path), "%s.1", g_ctx->config.file_path);
rename(g_ctx->config.file_path, old_path);
/* 打开新文件 */
g_ctx->log_file = fopen(g_ctx->config.file_path, "a");
g_ctx->current_file_size = 0;
}
/**
* @brief 写入日志到文件
*/
static void write_to_file(const log_entry_t* entry)
{
if (!g_ctx->log_file) return;
char time_str[64];
format_time(entry->timestamp_us, time_str, sizeof(time_str));
int written = fprintf(g_ctx->log_file, "[%s] [%s] [%s:%d] %s\n",
time_str,
level_names[entry->level],
entry->file, entry->line,
entry->message);
if (written > 0) {
g_ctx->current_file_size += written;
}
fflush(g_ctx->log_file);
/* 检查是否需要轮转 */
if (g_ctx->current_file_size >= g_ctx->config.file_max_size) {
rotate_log_file();
}
}
/**
* @brief 写入日志到控制台
*/
static void write_to_console(const log_entry_t* entry)
{
char time_str[64];
format_time(entry->timestamp_us, time_str, sizeof(time_str));
/* 不同级别使用不同颜色(ANSI) */
const char* color = "";
const char* reset = "";
if (isatty(STDERR_FILENO)) {
switch (entry->level) {
case LOG_LEVEL_FATAL:
case LOG_LEVEL_ERROR:
color = "\033[31m"; break; /* 红色 */
case LOG_LEVEL_WARN:
color = "\033[33m"; break; /* 黄色 */
case LOG_LEVEL_INFO:
color = "\033[32m"; break; /* 绿色 */
case LOG_LEVEL_DEBUG:
color = "\033[36m"; break; /* 青色 */
default:
color = "\033[0m"; break;
}
reset = "\033[0m";
}
fprintf(stderr, "%s[%s] [%s] [%s:%d] %s%s\n",
color, time_str, level_names[entry->level],
entry->file, entry->line, entry->message, reset);
}
/**
* @brief 写入日志到环形缓冲区(调试)
*/
static void write_to_ringbuf(const log_entry_t* entry)
{
if (!g_ctx->ringbuf) return;
pthread_mutex_lock(&g_ctx->ringbuf_lock);
char time_str[64];
format_time(entry->timestamp_us, time_str, sizeof(time_str));
int written = snprintf(g_ctx->ringbuf + g_ctx->ringbuf_write_pos,
g_ctx->config.ringbuf_size - g_ctx->ringbuf_write_pos,
"[%s] [%s] %s\n",
time_str, level_names[entry->level], entry->message);
if (written > 0) {
g_ctx->ringbuf_write_pos += written;
if (g_ctx->ringbuf_write_pos >= g_ctx->config.ringbuf_size) {
g_ctx->ringbuf_write_pos = 0; /* 循环覆盖 */
}
}
pthread_mutex_unlock(&g_ctx->ringbuf_lock);
}
/**
* @brief 日志处理函数(消费者)
*/
static void* log_thread_func(void* arg)
{
(void)arg;
while (g_ctx->running) {
pthread_mutex_lock(&g_ctx->queue_lock);
/* 等待日志到来 */
while (g_ctx->running && !g_ctx->queue_head) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 1;
pthread_cond_timedwait(&g_ctx->queue_cond, &g_ctx->queue_lock, &ts);
}
if (!g_ctx->running && !g_ctx->queue_head) {
pthread_mutex_unlock(&g_ctx->queue_lock);
break;
}
/* 取出队列头 */
log_entry_t* entry = g_ctx->queue_head;
g_ctx->queue_head = entry->next;
if (!g_ctx->queue_head) {
g_ctx->queue_tail = NULL;
}
g_ctx->queue_size--;
pthread_mutex_unlock(&g_ctx->queue_lock);
/* 写入各个输出目标(装饰器模式) */
if (g_ctx->config.output & LOG_OUTPUT_FILE) {
write_to_file(entry);
}
if (g_ctx->config.output & LOG_OUTPUT_CONSOLE) {
write_to_console(entry);
}
if (g_ctx->config.output & LOG_OUTPUT_RINGBUF) {
write_to_ringbuf(entry);
}
/* 释放条目 */
free(entry);
g_ctx->total_logs++;
}
return NULL;
}
/*=============================================================================
* 公共API实现
*============================================================================*/
int logger_init(const logger_config_t* config)
{
if (g_ctx) return 0;
g_ctx = (logger_context_t*)calloc(1, sizeof(logger_context_t));
if (!g_ctx) return -1;
memcpy(&g_ctx->config, config, sizeof(logger_config_t));
/* 设置默认值 */
if (g_ctx->config.file_max_size == 0) {
g_ctx->config.file_max_size = 10 * 1024 * 1024; /* 10MB */
}
if (g_ctx->config.async_queue_size == 0) {
g_ctx->config.async_queue_size = 4096;
}
/* 初始化锁 */
pthread_mutex_init(&g_ctx->queue_lock, NULL);
pthread_cond_init(&g_ctx->queue_cond, NULL);
pthread_mutex_init(&g_ctx->ringbuf_lock, NULL);
/* 打开日志文件 */
if ((config->output & LOG_OUTPUT_FILE) && config->file_path) {
g_ctx->log_file = fopen(config->file_path, "a");
if (g_ctx->log_file) {
/* 获取当前文件大小 */
fseek(g_ctx->log_file, 0, SEEK_END);
g_ctx->current_file_size = ftell(g_ctx->log_file);
}
}
/* 创建环形缓冲区 */
if (config->output & LOG_OUTPUT_RINGBUF && config->ringbuf_size > 0) {
g_ctx->ringbuf = (char*)malloc(config->ringbuf_size);
if (g_ctx->ringbuf) {
memset(g_ctx->ringbuf, 0, config->ringbuf_size);
}
}
/* 启动日志线程 */
g_ctx->running = true;
pthread_create(&g_ctx->log_thread, NULL, log_thread_func, NULL);
LOG_INFO("Logger initialized, level=%s", level_names[config->level]);
return 0;
}
void logger_deinit(void)
{
if (!g_ctx) return;
LOG_INFO("Logger shutting down...");
/* 停止日志线程 */
g_ctx->running = false;
pthread_cond_signal(&g_ctx->queue_cond);
pthread_join(g_ctx->log_thread, NULL);
/* 关闭文件 */
if (g_ctx->log_file) {
fclose(g_ctx->log_file);
}
/* 释放资源 */
if (g_ctx->ringbuf) {
free(g_ctx->ringbuf);
}
pthread_mutex_destroy(&g_ctx->queue_lock);
pthread_cond_destroy(&g_ctx->queue_cond);
pthread_mutex_destroy(&g_ctx->ringbuf_lock);
free(g_ctx);
g_ctx = NULL;
}
void logger_log(log_level_t level, const char* file, int line,
const char* func, const char* fmt, ...)
{
if (!g_ctx || level > g_ctx->config.level) return;
/* 分配日志条目 */
log_entry_t* entry = (log_entry_t*)malloc(sizeof(log_entry_t));
if (!entry) return;
memset(entry, 0, sizeof(log_entry_t));
/* 填充条目 */
entry->level = level;
entry->line = line;
/* 提取文件名(去掉路径) */
const char* filename = strrchr(file, '/');
if (filename) filename++; else filename = file;
strncpy(entry->file, filename, sizeof(entry->file) - 1);
strncpy(entry->func, func, sizeof(entry->func) - 1);
/* 时间戳 */
struct timeval tv;
gettimeofday(&tv, NULL);
entry->timestamp_us = (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
/* 线程ID */
entry->thread_id = (uint32_t)pthread_self();
/* 格式化消息 */
va_list args;
va_start(args, fmt);
vsnprintf(entry->message, sizeof(entry->message), fmt, args);
va_end(args);
if (g_ctx->config.async_mode) {
/* 异步模式: 入队 */
pthread_mutex_lock(&g_ctx->queue_lock);
if (g_ctx->queue_size >= g_ctx->config.async_queue_size) {
/* 队列满,丢弃最旧的日志 */
log_entry_t* old = g_ctx->queue_head;
if (old) {
g_ctx->queue_head = old->next;
free(old);
g_ctx->queue_size--;
g_ctx->dropped_logs++;
}
}
entry->next = NULL;
if (g_ctx->queue_tail) {
g_ctx->queue_tail->next = entry;
} else {
g_ctx->queue_head = entry;
}
g_ctx->queue_tail = entry;
g_ctx->queue_size++;
pthread_cond_signal(&g_ctx->queue_cond);
pthread_mutex_unlock(&g_ctx->queue_lock);
} else {
/* 同步模式: 直接处理 */
if (g_ctx->config.output & LOG_OUTPUT_FILE) write_to_file(entry);
if (g_ctx->config.output & LOG_OUTPUT_CONSOLE) write_to_console(entry);
if (g_ctx->config.output & LOG_OUTPUT_RINGBUF) write_to_ringbuf(entry);
free(entry);
}
}
size_t logger_get_ringbuf(char* buf, size_t size)
{
if (!g_ctx || !g_ctx->ringbuf) return 0;
pthread_mutex_lock(&g_ctx->ringbuf_lock);
size_t copy_size = size - 1;
if (copy_size > g_ctx->config.ringbuf_size) {
copy_size = g_ctx->config.ringbuf_size;
}
/* 从环形缓冲区读取 */
size_t start = g_ctx->ringbuf_write_pos;
if (start + copy_size > g_ctx->config.ringbuf_size) {
size_t first_part = g_ctx->config.ringbuf_size - start;
memcpy(buf, g_ctx->ringbuf + start, first_part);
memcpy(buf + first_part, g_ctx->ringbuf, copy_size - first_part);
} else {
memcpy(buf, g_ctx->ringbuf + start, copy_size);
}
buf[copy_size] = '\0';
pthread_mutex_unlock(&g_ctx->ringbuf_lock);
return copy_size;
}
void logger_flush(void)
{
if (!g_ctx) return;
/* 等待队列清空 */
while (g_ctx->queue_size > 0) {
usleep(1000);
}
if (g_ctx->log_file) {
fflush(g_ctx->log_file);
}
}
void logger_set_level(log_level_t level)
{
if (g_ctx) {
LOG_INFO("Log level changed from %s to %s",
level_names[g_ctx->config.level], level_names[level]);
g_ctx->config.level = level;
}
}
总结
-
双架构IPC模块 (
ipc_bus.h/c)-
无锁环形队列
-
共享内存通信
-
同步/异步命令模式
-
ARM与ARM-None跨核通信
-
-
ISP调优模块 (
isp_tuning.h/c)-
黑电平/镜头阴影/色彩校正/Gamma/去噪/锐化
-
策略模式场景自适应(室内/室外/夜景)
-
参数平滑过渡
-
文件IO与CRC校验
-
-
AI流水线模块 (
ai_pipeline.h/c)-
责任链模式(预处理→推理→后处理→跟踪)
-
对象池模式(任务复用)
-
YOLO检测 + IOU跟踪
-
NMS后处理
-
-
3A策略模式 (
isp_3a.h)-
AE PID控制/快速策略
-
AWB灰度世界/完美反射
-
AF爬山算法+状态机
-
-
事件循环模块 (
event_loop.h/c)-
观察者模式事件分发
-
Reactor模式epoll封装
-
优先级队列
-
定时器管理
-
-
内存管理模块 (
memory_manager.h/c)-
CMA连续内存池
-
SLAB对象池
-
内存统计与调试
-
-
日志管理模块 (
logger.h/c)-
异步生产者-消费者模式
-
多输出目标(文件/控制台/环形缓冲区)
-
日志轮转
-
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)