嘉楠科技
直播中

张霞

8年用户 1102经验值
私信 关注
[问答]

K230在同时使用H265编码与yolo进行检测时出现错误怎么解决?

1、单独使用H265编码时或者yolo检测没有问题
2.一旦将二者结合,因为H265编码时YUV格式,所以我另外开了一个RGB平面格式来运行yolo推理
3.报错信息显示:两者的空间会冲突然后导致程序失败,我在想是不是因为H265编码是硬件编码而在硬件编码期间,使用软件yolo运行占用其空间导致冲突进而报错,有什么解决方案?

回帖(1)

秋风宜人

2025-7-17 17:45:55

针对K230在同时使用H265硬件编码和YOLO检测时出现的空间冲突问题,结合您的描述和报错信息,以下是根本原因分析和解决方案:




问题根源




  1. 内存访问冲突



    • H265硬件编码器直接访问物理内存(DMA缓冲区),而YOLO在CPU端运行需要虚拟内存访问权限。

    • 当硬件编码器(如K230的NPU/VPU)持续操作YUV数据的内存区域时,YOLO从同一块物理内存的副本(您创建的RGB缓冲区)进行读/写操作,触发并发访问冲突。




  2. 缓存一致性失效



    • 硬件编码器可能通过直接内存访问(DMA)操作内存,绕过了CPU缓存。

    • YOLO修改RGB数据后,若未同步到硬件编码器可见的物理内存,可能导致数据不一致,引发崩溃。






解决方案


1. 双缓冲机制(推荐)



  • 原理:隔离两个模块的内存区域,避免同时访问同一块物理内存。

  • 步骤

    1. 分配独立的两个缓冲区:buffer_yuv(供H265编码器使用)和buffer_rgb(供YOLO使用)。

    2. 视频帧流处理流程:

      • Step 1: 原始帧存入 buffer_yuv(硬件编码器锁定此内存)。

      • Step 2: 异步拷贝 buffer_yuvbuffer_rgb(需确保拷贝完成前编码器不使用此帧)。

      • Step 3: YOLO处理 buffer_rgb

      • Step 4: 下一帧覆盖 buffer_yuv,循环处理。




  • 关键代码示例(伪代码):


     import cv2
    import numpy as np

    # 初始化双缓冲区
    buffer_yuv = np.zeros((height, width), dtype=np.uint8)  # YUV格式,硬件编码器使用
    buffer_rgb = np.zeros((height, width, 3), dtype=np.uint8)  # RGB格式,YOLO使用

    while True:
         # 捕获一帧
         ret, frame = camera.read()  # frame为YUV格式
         if not ret:
             break

         # 复制到硬件编码缓冲区
         np.copyto(buffer_yuv, frame)

         # 启动硬件编码(异步,非阻塞)
         h265_encoder.async_encode(buffer_yuv)

         # 转换为RGB并复制到YOLO缓冲区
         rgb_frame = cv2.cvtColor(frame, cv2.COLOR_YUV2RGB_I420)
         np.copyto(buffer_rgb, rgb_frame)

         # YOLO推理
         yolo.detect(buffer_rgb)

         # 等待编码器完成(避免缓冲区覆盖)
         h265_encoder.wait_for_encode()



2. 内存映射同步



  • 使用mmap或硬件厂商提供的同步API确保缓存一致性(如ARM平台的Cache Flush操作):

    • 在YOLO修改RGB数据后,主动刷新CPU缓存,通知硬件编码器内存已更新。

    • K230相关API(示例):
      #include 
      void flush_cache(void *addr, size_t size) {
         __clear_cache(addr, (char*)addr + size);  // ARM架构缓存刷新
      }

    • 在复制数据到RGB缓冲区后调用:
      # 假设buffer_rgb是共享内存地址
      flush_cache(buffer_rgb.ctypes.data, buffer_rgb.nbytes)



3. 零拷贝优化(高性能方案)



  • 使用硬件支持的共享内存池(如K230的ION内存分配器):
     #include 
    int alloc_shared_buffer(size_t size, void **ptr) {
         ion_user_handle_t handle;
         ion_alloc_fd(size, &handle);  // ION分配物理连续内存
         return ion_map(handle, ptr);   // 映射到用户空间
    }

  • 优势:YUV和RGB使用同一块物理内存(避免复制),但通过虚拟地址隔离访问权限。

  • 注意:需严格同步(如使用互斥锁)确保H265编码器完成DMA后再允许YOLO读取。


4. 硬件流水线控制



  • 关键调整:强制硬件编码器在释放当前帧内存前发出完成信号。

  • 伪代码逻辑:
     1. 帧N进入编码器
    2. 编码器完成帧N → 发送中断/回调信号
    3. 收到信号后,帧N的内存才允许被YOLO或下一帧使用

  • 通过厂商SDK实现(如嘉楠K230的kdev_encoder_set_callback())。




调试建议



  1. 验证内存独立性

    • 打印buffer_yuvbuffer_rgb的物理地址(通过/proc/mapsion_mmap),确认无重叠。


  2. 最小化测试

    • 移除YOLO推理,只保留YUV→RGB转换,观察是否崩溃。


  3. 性能监控

    • 使用tophtop监控CPU占用,确认内存拷贝是否成为瓶颈(若存在则优先采用零拷贝方案)。





通过双缓冲或零拷贝技术,可彻底解决H265硬件编码与YOLO的内存空间冲突。推荐优先实现双缓冲方案,稳定后再优化为零拷贝。请根据K230的具体SDK调整示例代码。

举报

更多回帖

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