一、概述
DVR多通道實作流程與普通IPCamera邏輯一致,核心為「先建立IOTC連線創(chuàng)建主通道 → 同步指令創(chuàng)建剩余通道」,全程涉及通道分配、指令收發(fā)、線程優(yōu)化等關(guān)鍵環(huán)節(jié)。具體基礎(chǔ)流程可參考:
主通道建立后,需完成剩余通道的指令同步、創(chuàng)建與銷毀,保障多通道數(shù)據(jù)收發(fā)的穩(wěn)定性與效率。
二、主要流程
1. APP端
(1)APP發(fā)送指令IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_REQ查詢DVR當(dāng)前的通道數(shù);
(2)獲取通道數(shù)及對應(yīng)IOTC通道后,創(chuàng)建線程并調(diào)用avClientStartEx創(chuàng)建剩余通道;
(3)在各獨立通道完成數(shù)據(jù)收發(fā)操作。
2. 設(shè)備端
(1)設(shè)備端接收指令IOTYPE_USER_IPCAM_GETSUPPORTSTREAM_REQ,回復(fù)當(dāng)前支持的通道數(shù)及對應(yīng)IOTC通道;
(2)創(chuàng)建線程并調(diào)用avServStartEx創(chuàng)建剩余通道;
(3)在各獨立通道完成數(shù)據(jù)收發(fā)操作。
三、通道分配說明
以16位DVR為例,通道分配遵循「索引與IOTC通道號一一對應(yīng)」原則,具體分配如下:
| 通道索引 | IOTC通道號(預(yù)分配) | 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 |
四、線程優(yōu)化
1. avRecvIOCtrl 輪詢優(yōu)化
多通道場景下,可將avRecvIOCtrl指令接收邏輯集中至單個線程輪詢,減少線程資源占用,核心實現(xiàn)如下:
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);
}
}
說明:輪詢超時時間建議設(shè)為10ms,指令處理邏輯需輕量化,避免影響其他通道的指令接收效率。
2. avSendIOCtrl 隊列優(yōu)化
針對avSendIOCtrl指令發(fā)送,建議為每個avIndex單獨創(chuàng)建發(fā)送隊列,由專屬線程按序處理,核心實現(xiàn)如下:
void commandSendWorker(void* arg){
while(!isRequestBreak){
// 從隊列中獲取IO數(shù)據(jù)并按序發(fā)送
ioData* data = dequeue(ioQueue);
if(data){
int ret = avSendIOCtrl(avIndex,data.ioctrl,data.ioBuffer,data.size);
free(data);
continue;
}
else{
usleep(10*1000);
}
}
}
說明:隊列化發(fā)送可避免指令亂序,usleep休眠10ms減少空輪詢功耗,適配嵌入式設(shè)備低功耗需求。
