简体中文

基于AVAPIs模块开发网络摄像机-APP端

星空无限传媒xk8027-高清全集免费看

一、相关头文件说明

头文件说明
AVFRAMEINFO.h帧信息结构体定义(FRAMEINFO_t)、帧类型枚举等
AVIOCTRLDEFs.hIO控制指令定义(标准指令如IOTYPE_USER_IPCAM_START)、指令结构体定义
TUTKGlobalAPIs.h全局配置API、日志控制、版本查询等全局功能接口
IOTCClient.h客户端专用接口:连接建立、会话管理、网络配置等
IOTCCommon.h通用定义:错误码、数据类型、默认参数、枚举类型等
IOTCDevice.h设备端专用接口(客户端开发可忽略)
AVClient.h客户端AV通道接口:通道创建、数据收发、状态查询等
AVCommon.hAV模块通用定义:错误码、安全模式、认证类型等
AVServer.h设备端AV通道接口(客户端开发可忽略)
VSaaS.h云存储相关接口:录像查询、回放控制、云存储配置等
DASA.h码流自适应接口:动态码率调整、网络状况检测等

二、相关demo路径

平台例子路径
AndroidSDK目录\Sample\Android\Sample_AVAPIs_Client
iOSSDK目录\Sample\iOS\Sample_AVAPIs
WindowsSDK目录\Sample\Windows\Sample_AVAPIs_Client
MacSDK目录\Sample\MAC\Sample_AVAPIs

三、常见的配网方式

可以参考:常见的配网方式

四、连线和数据传输

主要使用的API: IOTCAPIs+AVAPIs

流程图:

客户端连线和数据传输流程图

图:客户端连线和数据传输流程图

(一)连线

连线需先通过IOTC_Get_SessionID获取空闲会话ID(SID),再调用IOTC_Connect_ByUIDEx与设备建立连接。该接口支持密钥认证,同时兼容局域网和广域网连接场景。

// 获取空闲会话ID(用于后续建立连接) int tmpSID = IOTC_Get_SessionID(); if (tmpSID < 0) {    printf("[%s:%d]IOTC_Get_SessionID failed ret[%d]\n",           __FUNCTION__, __LINE__, tmpSID);    pthread_exit(0); } printf("[%s:%d]IOTC_Get_SessionID tmpSID[%d]\n",       __FUNCTION__, __LINE__, tmpSID); // 初始化连接配置参数结构体 IOTCConnectInput connect_input; memset(&connect_input, 0, sizeof(connect_input)); // 清空结构体避免脏数据 // 配置核心连接参数 connect_input.cb = sizeof(connect_input); // 结构体大小(固定赋值,确保版本兼容) connect_input.authentication_type = AUTHENTICATE_BY_KEY; // 采用密钥认证方式 connect_input.timeout = 20; // 连线超时时间(单位:秒) // 复制认证密钥(需与设备端配置一致) memcpy(connect_input.auth_key,       gDemoConfig.iotc_auth_key,       IOTC_AUTH_KEY_LENGTH); // 建立IOTC连接(通过设备UID连接,返回最终会话ID) int SID = IOTC_Connect_ByUIDEx(uid, tmpSID, &connect_input); // 连接结果判断 if (SID >= 0) {    printf("[%s:%d]IOTC_Connect_ByUIDEx success, SID[%d]\n",           __FUNCTION__, __LINE__, SID); } else {    printf("[%s:%d]IOTC_Connect_ByUIDEx failed ret[%d]\n",           __FUNCTION__, __LINE__, SID);    // 常见错误码处理:-90(密钥错误)、-42(网络不可达)、-19(连接超时)    PrintErrHandling(SID);    pthread_exit(0); }
其他参考API:
1. IOTC_Connect_Stop_BySID:主动终止指定SID的连接
2. IOTC_Session_Close:关闭会话并释放资源
(二)创建传输通道

IOTCAPIs提供的是不可靠传输通道,AVAPIs基于此封装了可靠传输通道,专门用于音视频数据和信令的稳定传输。通过avClientStartEx创建通道时,需配置认证方式、安全加密模式、重传策略等核心参数。

// 初始化AV客户端配置结构体(输入/输出) AVClientStartInConfig avClientInConfig; AVClientStartOutConfig avClientOutConfig; // 清空输入配置结构体,避免脏数据影响 memset(&avClientInConfig, 0, sizeof(avClientInConfig)); // -------------------------- 核心配置参数 -------------------------- avClientInConfig.cb = sizeof(AVClientStartInConfig); // 结构体大小(固定赋值) avClientInConfig.iotc_channel_id = 0; // IOTC通道ID(范围0-31,默认0为主通道) avClientInConfig.iotc_session_id = SID; // 关联的IOTC会话ID(上一步连线返回值) avClientInConfig.timeout_sec = 30; // 通道创建超时时间(单位:秒) avClientInConfig.resend = 1; // 重传模式(1=开启重传,0=关闭重传,建议开启) // -------------------------- 安全加密模式配置 -------------------------- #if ENABLE_DTLS // 启用DTLS加密(推荐,安全性更高,适用于敏感数据传输) avClientInConfig.security_mode = AV_SECURITY_DTLS; #else // 使用TUTK SIMPLE加密(兼容性优先,适用于普通场景) avClientInConfig.security_mode = AV_SECURITY_SIMPLE; #endif // -------------------------- 认证方式配置 -------------------------- #if AUTH_BY_TOKEN // Token认证(支持更长的验证数据,适用于复杂权限控制) avClientInConfig.account_or_identity = gDemoConfig.av_identity; // 客户端身份标识 avClientInConfig.password_or_token = gDemoConfig.av_token; // 认证Token avClientInConfig.auth_type = AV_AUTH_TOKEN; // 认证类型标记 #else // 密码认证(验证数据较短,适用于简单场景) avClientInConfig.account_or_identity = gDemoConfig.av_account; // 客户端账号 avClientInConfig.password_or_token = gDemoConfig.av_password; // 认证密码 avClientInConfig.auth_type = AV_AUTH_PASSWORD; // 认证类型标记 #endif // -------------------------- 输出参数配置 -------------------------- avClientOutConfig.cb = sizeof(AVClientStartOutConfig); // 结构体大小(固定赋值) // 创建AV传输通道(返回通道索引avIndex,后续数据操作基于此索引) int avIndex = avClientStartEx(&avClientInConfig, &avClientOutConfig); // 通道创建结果判断 if (avIndex < 0) {    printf("[%s:%d]avClientStartEx failed ret[%d]\n",           __FUNCTION__, __LINE__, avIndex);    IOTC_Session_Close(SID); // 通道创建失败,关闭对应的IOTC会话    pthread_exit(0); }
其他参考API:
1. avClientStop:关闭AV通道并释放资源
2. avClientExit:中止avClientStartEx
(三)数据传输

AVAPIs针对不同数据类型提供专用传输API对,确保数据传输的高效性和可靠性。IO控制指令支持自定义格式,也可参考公版IO Command定义

  • 图像数据:avSendFrameData(发送) / avRecvFrameData2(接收,支持帧信息解析)
  • 音频数据:avSendAudioData(发送) / avRecvAudioData(接收)
  • IO控制指令:avSendIOCtrl(发送) / avRecvIOCtrl(接收)
1. 接收视频

客户端需先发送视频启动指令(IOTYPE_USER_IPCAM_START),再创建独立线程接收视频数据。视频解码需从I帧开始,中途丢帧后需等待下一个I帧才能恢复正常显示。

// 发送视频流启动指令(通知设备开始推送视频) SMsgAVIoctrlAVStream ioMsg; memset(&ioMsg, 0, sizeof(SMsgAVIoctrlAVStream)); // 清空指令结构体 int ret = avSendIOCtrl(    avIndex,    IOTYPE_USER_IPCAM_START, // 视频启动指令(标准指令定义)    (char*)&ioMsg,    sizeof(SMsgAVIoctrlAVStream) ); if (ret < 0) {    printf("start_ipcam_stream failed[%d]\n", ret);    avClientStop(avIndex);    IOTC_Session_Close(SID);    return 0; }

视频接收伪代码代码(独立线程中执行):

// 初始化视频接收相关变量 unsigned int frmNo; // 帧序号 int outBufSize = 0; // 缓冲区实际使用大小 int outFrmSize = 0; // 帧数据实际大小 int outFrmInfoSize = 0; // 帧信息实际大小 bool need_key_frame = true; // 是否需要等待I帧(初始状态需等待I帧) const int VIDEO_BUF_SIZE = 1024 * 1024; // 视频缓冲区大小(1MB,根据实际分辨率调整) char* video_buf = new char[VIDEO_BUF_SIZE]; // 视频数据缓冲区 FRAMEINFO_t frameInfo; // 帧信息结构体(包含帧类型、分辨率等) // 循环接收视频数据(线程主循环) while (gProcessRun) {    // 接收视频帧数据(avRecvFrameData2支持解析帧信息,推荐使用)    int ret = avRecvFrameData2(        avIndex,        video_buf,        VIDEO_BUF_SIZE,        &outBufSize,        &outFrmSize,        (char*)&frameInfo,        sizeof(FRAMEINFO_t),        &outFrmInfoSize,        &frmNo    );    // 处理接收结果    if (ret <= 0) {        // 数据未准备好(正常情况,短暂等待后重试)        if (ret == AV_ER_DATA_NOREADY) {            usleep(5 * 1000); // 5ms延迟,降低CPU占用            continue;        }        // 帧丢失或帧数据不完整(需标记等待I帧)        else if (ret == AV_ER_LOSED_THIS_FRAME || ret == AV_ER_INCOMPLETE_FRAME) {            printf("Recv video, Lost video frame NO[%d]\n", frmNo);            need_key_frame = true; // 标记需要等待下一个I帧            continue;        }        // 缓冲区大小不足(需增大缓冲区)        else if (ret == AV_ER_BUFPARA_MAXSIZE_INSUFF) {            printf("Video buffer is too small to store frame[%d]\n", frmNo);            need_key_frame = true;            // 可选:动态调整缓冲区大小(需重新分配内存)            // resizeVideoBuffer(&video_buf, VIDEO_BUF_SIZE * 2);            continue;        }        // 其他错误(通道关闭或网络异常,退出循环)        else {            printf("Recv video error, code[%d], break loop\n", ret);            break;        }    }    // 检查是否需要等待I帧    if (need_key_frame) {        // 判断当前帧是否为I帧(IPC_FRAME_FLAG_IFRAME)        if (frameInfo.flags == IPC_FRAME_FLAG_IFRAME) {            need_key_frame = false; // 已收到I帧,解除等待标记            printf("Recv I-Frame, frame NO[%d]\n", frmNo);        } else {            continue; // 未收到I帧,跳过当前非I帧        }    }    // 视频数据处理(提交到解码队列,由解码线程处理)    // 注意:解码和显示需在独立线程中执行,避免阻塞接收线程    push_video_frame_to_decode_queue(video_buf, outFrmSize, &frameInfo); } // 释放资源 delete[] video_buf; video_buf = NULL; avClientStop(avIndex); IOTC_Session_Close(SID);
2. 接收音频

音频接收流程与视频类似:先发送音频启动指令,再创建独立线程接收音频数据。音频具有线性特性,少量丢帧可通过填充上一帧数据避免杂音。

// 发送音频流启动指令(通知设备开始推送音频) SMsgAVIoctrlAVStream ioMsg; memset(&ioMsg, 0, sizeof(SMsgAVIoctrlAVStream)); int ret = avSendIOCtrl(    avIndex,    IOTYPE_USER_IPCAM_AUDIOSTART, // 音频启动指令(标准指令定义)    (char*)&ioMsg,    sizeof(SMsgAVIoctrlAVStream) ); if (ret < 0) {    printf("start_ipcam_audio_stream failed[%d]\n", ret);    avClientStop(avIndex);    IOTC_Session_Close(SID);    return 0; }

音频接收伪代码(独立线程中执行):

// 初始化音频接收相关变量 const int AUDIO_BUF_SIZE = 4096; // 音频缓冲区大小(根据采样率调整) char audio_buf[AUDIO_BUF_SIZE]; // 音频数据缓冲区 char last_audio_frame[AUDIO_BUF_SIZE]; // 上一帧音频数据(用于填充丢帧) int last_audio_size = 0; // 上一帧音频数据大小 FRAMEINFO_t frameInfo; // 帧信息结构体 unsigned int frmNo; // 帧序号 // 循环接收音频数据(线程主循环) while (gProcessRun) {    // 接收音频帧数据    int ret = avRecvAudioData(        avIndex,        audio_buf,        AUDIO_BUF_SIZE,        (char*)&frameInfo,        sizeof(FRAMEINFO_t),        &frmNo    );    // 处理接收结果    if (ret <= 5="" if="" ret="=" else="" recv="" lost="" audio="" frame="" ifdef="" _enable_fill_last_frame_="" last_audio_size=""> 0) {                push_audio_frame_to_decode_queue(last_audio_frame, last_audio_size);            } #else            // 不启用填充,直接跳过丢帧            continue; #endif            continue;        }        // 其他错误(退出循环)        else {            printf("Recv audio error, code[%d], break loop\n", ret);            break;        }    }    // 保存当前帧数据(用于后续丢帧填充)    memcpy(last_audio_frame, audio_buf, ret);    last_audio_size = ret;    // 提交音频数据到解码队列(解码和播放在独立线程执行)    push_audio_frame_to_decode_queue(audio_buf, ret); } // 释放资源(音频缓冲区为栈内存,无需手动释放) avClientStop(avIndex); IOTC_Session_Close(SID);

重要提示

1. 视频和音频接收需分别在独立线程中执行,避免数据收发互相阻塞,影响实时性。

2. 接收线程仅负责数据接收和预处理,解码和播放需在另一独立线程中执行,防止解码耗时导致丢帧。

3. 视频解码必须从I帧开始,非I帧无法独立解码;中途丢帧后,需等待下一个I帧才能恢复正常显示。

4. 缓冲区大小需根据实际分辨率和码率调整,过小会导致帧丢失,过大会浪费内存(建议1080P视频缓冲区不小于2MB)。

(四)对讲

对讲功能基于全双工AV通道实现,支持音频双向实时传输。详细实现可参考:基于AVAPIs的对讲实现

即刻开启您的物联网之旅

联系解决方案专家
Kalay App
资讯安全白皮书
全球专利布局
解决方案
新闻动态
公司动态
行业资讯
媒体报道
永续发展
经营者的话
社会参与
环境永续
公司治理

+86 755 27702549

7×24小时服务热线

法律声明 隐私权条款

关注“TUTK”

TUTK服务尽在掌握

© 2022 星空无限传媒xk8027版权所有粤ICP备14023641号
在线咨询
扫一扫

TUTK服务尽在掌握

全国免费服务热线
+86 755 27702549

返回顶部