一、概述
DVR多通道实作流程与普通IPCamera逻辑一致,核心为「先建立IOTC连线创建主通道 → 同步指令创建剩余通道」,全程涉及通道分配、指令收发、线程优化等关键环节。具体基础流程可参考:
主通道建立后,需完成剩余通道的指令同步、创建与销毁,保障多通道数据收发的稳定性与效率。
二、主要流程
1. APP端
(1)APP发送指令IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_REQ查询DVR当前的通道数;
(2)获取通道数及对应IOTC通道后,创建线程并调用avClientStartEx创建剩余通道;
(3)在各独立通道完成数据收发操作。
2. 设备端
(1)设备端接收指令IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_REQ,回复当前支持的通道数及对应IOTC通道;
(2)创建线程并调用avServStartEx创建剩余通道;
(3)在各独立通道完成数据收发操作。
三、通道分配说明
以16位DVR为例,通道分配遵循「索引与IOTC通道号一一对应」原则,具体分配如下:
| 通道索引 | IOTC通道号(预分配) | avClientStartEx所用通道 (inconfig.iotc_channel_id) | avServStartEx所用通道 (inconfig.iotc_channel_id) |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 2 |
| ... | ... | ... | ... |
| 15 | 15 | 15 | 15 |
四、线程优化
1. avRecvIOCtrl 轮询优化
多通道场景下,可将avRecvIOCtrl指令接收逻辑集中至单个线程轮询,减少线程资源占用,核心实现如下:
while(!isRequestBreak){
// 轮询多个通道的指令
foreach(auto avIndex,avIndexList){
int ret = avRecvIOCtrl(avIndex,ioctrl,buffer,timeout=10ms);
if(ret == AV_ER_TIMEOUT){
continue;
}
else if(ret < 0){
// 主通道异常直接中断轮询
if(isMainChannel(avIndex)){
break;
}
else{
// 移除异常通道并尝试重建
removeAvIndexFromList(avIndex);
reConstructThisChannel(avIndex);
continue;
}
}
// 指令处理避免耗时操作,防止阻塞其他通道
handleCommandRequest(avIndex,ioctrl,buffer);
}
}
说明:轮询超时时间建议设为10ms,指令处理逻辑需轻量化,避免影响其他通道的指令接收效率。
2. avSendIOCtrl 队列优化
针对avSendIOCtrl指令发送,建议为每个avIndex单独创建发送队列,由专属线程按序处理,核心实现如下:
void commandSendWorker(void* arg){
while(!isRequestBreak){
// 从队列中获取IO数据并按序发送
ioData* data = dequeue(ioQueue);
if(data){
int ret = avSendIOCtrl(avIndex,data.ioctrl,data.ioBuffer,data.size);
free(data);
continue;
}
else{
usleep(10*1000);
}
}
}
说明:队列化发送可避免指令乱序,usleep休眠10ms减少空轮询功耗,适配嵌入式设备低功耗需求。
五、注意事项
核心约束
1. 通道重建机制:非主通道异常时建议自动重建,但需限制重建次数(如3次),避免无限循环占用资源;
2. 线程安全:多通道指令收发需保证线程安全,避免同一avIndex被多个线程同时操作;
3. 超时配置:avRecvIOCtrl超时时间不宜过长(建议5-10ms),否则会导致指令响应延迟;
4. 资源释放:通道销毁时需同步释放线程、队列等资源,避免内存泄漏;
5. 兼容性:不同型号DVR的最大通道数不同,APP需动态适配,避免硬编码通道数量。
DVR 多通道实作流程 | TUTK P2P SDK 开发手册 | 最后更新:2025年
