嘉楠科技
直播中

djfldsthtr

9年用户 1021经验值
擅长:光电显示
私信 关注
[问答]

启用了同一个摄像头的3个vicap通道和3个venc通道遇到的疑问求解

我启用了同一个摄像头的3个vicap通道和3个venc通道
他们一一进行了系统绑定
CSI2 -- vicap0 -- venc0 h264编码 网络推流使用
CSI2 -- vicap1 -- venc1 h264编码 本地录像使用
CSI2 -- vicap2 -- venc2 jpg编码  本地拍照使用
现在的问题是
由于拍照需要保持实时响应 用户按键一按下就需要立即捕捉图像 所以在开机后就需要立即调用kd_mpi_vicap_start_stream和kd_mpi_venc_start_chn来让图像捕捉和编码一直保持运行
但我发现当我不去将所有venc的缓冲区数据都读走 那么venc和vicap会一直阻塞住! 直到venc的所有缓冲区的数据都被取走才会产生新数据!
这个有什么办法解决么? 就是说 不管我应用层读不读缓冲区 都可以让他一直自动的产生新数据
        你好。
当缓冲区满时,将停止填充新数据。以下是两种优化的解决方案:

  • 启动一个独立线程,实时读取编码后的数据,提取所需内容并丢弃无用数据,以确保缓冲区始终保持最新状态。
  • 在抓拍图像时,动态绑定 VI 到 VENC;抓拍完成后,及时解除绑定。
        

回帖(1)

张玉兰

2025-5-6 16:56:59

针对你的问题,可以尝试以下解决方案:




  1. 非阻塞模式设置


    // 设置VENC通道为非阻塞模式
    KD_VENC_CHN_ATTR_S stVencChnAttr;
    kd_mpi_venc_get_chn_attr(vencChn, &stVencChnAttr);
    stVencChnAttr.stVencAttr.enVencMode = VENC_WORK_MODE_NONBLOCK; // 非阻塞模式
    stVencChnAttr.stVencAttr.u32BufCacheCnt = 1; // 仅保留1帧缓存
    kd_mpi_venc_set_chn_attr(vencChn, &stVencChnAttr);



  2. 动态启停策略



    // 平时保持VICAP运行但VENC停止
    kd_mpi_venc_stop_chn(vencChn2);



// 当拍照按键触发时
void capture_image() {
kd_mpi_venc_start_chn(vencChn2);  // 快速启动编码通道
usleep(10000);  // 等待10ms确保数据流通
kd_mpi_venc_get_stream(vencChn2, &stStream, -1); // 阻塞获取单帧
save_jpeg(stStream.pstPack);
kd_mpi_venc_stop_chn(vencChn2);  // 立即停止编码通道
}



3. **主动缓冲区清理**
```c
// 创建独立线程处理VENC2缓冲区
void* venc2_buffer_thread(void* arg) {
    while (1) {
        if (need_capture) {
            kd_mpi_venc_get_stream(vencChn2, &stStream, 0); // 非阻塞获取
            if (stStream.u32PackCount > 0) {
                save_jpeg(stStream.pstPack);
                kd_mpi_venc_release_stream(vencChn2, &stStream);
            }
        } else {
            // 非拍照时段主动丢弃帧
            kd_mpi_venc_clear_chn_buffer(vencChn2);
        }
        usleep(5000);  // 5ms轮询间隔
    }
    return NULL;
}


  1. 编码参数优化
    // 设置关键参数
    KD_VENC_JPEG_PARAM_S stJpegParam;
    kd_mpi_venc_get_jpeg_param(vencChn2, &stJpegParam);
    stJpegParam.u32Qfactor = 80;  // 降低质量提升编码速度
    stJpegParam.bByFrame = KD_TRUE;  // 按帧获取模式
    stJpegParam.enDropMode = VENC_DROP_MODE_REF;  // 允许丢帧
    kd_mpi_venc_set_jpeg_param(vencChn2, &stJpegParam);


关键建议:



  1. 对VENC2通道采用非阻塞模式 + 单缓冲区组合,确保新帧覆盖旧帧

  2. 当不需要拍照时,定期调用kd_mpi_venc_clear_chn_buffer()主动清空缓冲区

  3. 使用独立高优先级线程处理VENC2的数据获取

  4. 通过kd_mpi_sys_set_regions()设置VIPCAP的ROI区域,减少无效数据处理

  5. 在VICAP层面对通道2设置最低优先级:
    KD_VICAP_CHN_ATTR_S stChnAttr;
    stChnAttr.u32Priority = 3;  // 0-最高,3-最低
    kd_mpi_vicap_set_chn_attr(vicapChn2, &stChnAttr);


注意事项:



  1. 不同VENC通道的码率控制需要独立设置,避免互相干扰

  2. 监控系统带宽使用情况(CSI2、DDR带宽),必要时降低其他通道的分辨率

  3. JPEG编码建议使用硬件DMA传输,减少CPU参与

  4. 在按键响应中断服务中直接触发硬件抓帧事件:
    void capture_isr() {
    kd_mpi_vicap_send_event(VICAP_EVENT_SNAPSHOT);  // 硬件级抓帧
    }


通过上述方法,可以在保证实时响应的同时,避免因缓冲区堆积导致的系统阻塞。实际应用中建议将VENC2的帧率设置为略高于实际需求(如30->33fps),为丢帧策略留出余量。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分