一、概述
IOTC通道是其他通道(AV或RDT通道)封装的基础,默认情况下,每个连接最多可以创建32个通道(如需更多通道,如DVR/NVR场景,需修改SDK限制)。在RDT及AV通道中,默认以
IOTC_Channel_ID=0为主通道,用于实时音视频观看、对讲等操作。部分功能(如事件回放、事件下载、文件上传/下载等)可能会需频繁或者快速地创建/销毁子通道,因此,通道的高效管理策略对功能体验至关重要。
二、IOTC空闲通道的获取
1. SDK API获取
IOTCAPIs已提供
IOTC_Session_Get_Free_Channel接口,用于获取指定SID的空闲通道,默认返回当前最小可用的通道,使用方式可以参考:// 获取指定SID的空闲通道
int channel = IOTC_Session_Get_Free_Channel(sid);
调用成功返回[0,31]范围内的通道号;获取失败时常见的错误码:
- -14:SID无效
- -18:无空闲通道
注意事项
高频次操作(如快速点击)场景下,可能出现通道被占用的情况。
2. 手动获取
IOTCAPIs支持上层自行指定空闲IOTC通道,通道号需遵循SDK默认范围[0,31]。推荐实现方式:从当前通道(首次从1开始)遍历至31号通道,找到未占用通道后标记为已使用。此逻辑的设计,使SDK在短期内不会拿到相同的IOTC通道,避免出现通道未来得及释放导致被占用的情形:
- 第一次:使用IOTC_Channel_ID=1(如已被占用,自动加1)
- 第二次:使用IOTC_Channel_ID=2(如已被占用,自动加1)
- 第三次:使用IOTC_Channel_ID=3(如已被占用,自动加1)
- ...
- 第三十二次:使用IOTC_Channel_ID=1(已超出31的范围,自动从1开始,如已被占用,自动加1)
实现示例
初始化
#define _USER_DEFINE_MAX_SESSION_NUMBER_ 8
typedef struct {
int currentChannelPosition;
unsigned int channelStatu;
pthread_mutex_t lock;
} stChannelStatuInSession;
static stChannelStatuInSession stChannelInfos[_USER_DEFINE_MAX_SESSION_NUMBER_];
static void initChannelStatus() {
// 初始化互斥锁(默认属性)
int ret = pthread_mutex_init(&stChannelInfos[sid].lock, NULL);
if (ret != 0) {
printf("init mutex failed:%d\n", ret);
return;
}
for (int i = 0; i < _USER_DEFINE_MAX_SESSION_NUMBER_; i++) {
stChannelInfos[i].channelStatu = 0U;
stChannelInfos[i].currentChannelPosition = 31;
}
}
获取空闲通道
static int getFreeChannelOfSession(unsigned int sid) {
// 校验位号有效性(仅支持0~31位)
if (sid >= _USER_DEFINE_MAX_SESSION_NUMBER_) {
return -1;
}
int ret = pthread_mutex_lock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_lock failed:%d\n", ret);
return -1;
}
int start = (stChannelInfos[sid].currentChannelPosition + 1) % 32; // 下次查找起始位置
for (int i = 0; i < 32; i++) {
int target_ch = (start + i) % 32; // 当前检查的通道号(循环查找)
// 检查通道是否空闲(对应位为0)
if (!(stChannelInfos[sid].channelStatu & (1U << target_ch))) {
// 标记通道为占用(对应位置1)
if (!target_ch) {
continue;
}
printf("get free channel:%d(last:%d -> current:%d)\n",
target_ch, stChannelInfos[sid].currentChannelPosition, target_ch);
stChannelInfos[sid].channelStatu |= (1U << target_ch);
stChannelInfos[sid].currentChannelPosition = target_ch; // 更新上次分配记录
ret = pthread_mutex_unlock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_unlock failed:%d\n", ret);
return -1;
}
return target_ch;
}
}
ret = pthread_mutex_unlock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_unlock failed:%d\n", ret);
return -1;
}
return -1;
}
释放通道
int freeChannelOfSession(unsigned int sid, int channel) {
// 校验位号有效性
if (channel <= 0="" channel=""> 31 || sid >= _USER_DEFINE_MAX_SESSION_NUMBER_) {
return -1;
}
int ret = pthread_mutex_lock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_lock failed:%d\n", ret);
return -1;
}
// 检查通道是否已占用(对应位为1)
if (stChannelInfos[sid].channelStatu & (1U << channel)) {
stChannelInfos[sid].channelStatu &= ~(1U << channel);
printf("free:%d\n", channel);
ret = pthread_mutex_unlock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_unlock failed:%d\n", ret);
return -1;
}
return 0;
}
ret = pthread_mutex_unlock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_unlock failed:%d\n", ret);
return -1;
}
printf("free failed\n", channel);
return -1;
}
通道状态打印
static void ChannelStatusPrintf(int sid) {
printf("\n===current status[sid=%d]===\n", sid);
printf("channel:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31\n");
printf("status :");
int ret = pthread_mutex_lock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_lock failed:%d\n", ret);
return;
}
for (int i = 0; i < 32; i++) {
if (stChannelInfos[sid].channelStatu & (1U << i)) {
printf("1 "); // 占用
} else {
printf("0 "); // 空闲
}
}
ret = pthread_mutex_unlock(&stChannelInfos[sid].lock);
if (ret != 0) {
printf("pthread_mutex_unlock failed:%d\n", ret);
return;
}
printf("\nstatus:1=used,0=free\n\n");
}
说明:示例中考虑嵌入式内存资源有限,仅用位来存储对应通道的状态,通过互斥锁保证通道操作的线程安全,使用位运算高效管理32个通道的占用状态,支持通道分配、释放及状态打印功能。
