第一次使用华为的网络摄像头并进行二次开发,网上关于QT对华为网络摄像头的二次开发的文章很少,基于项目的需求做了一些工作,特此记录。

目标:

1、实时预览

2、手动控制录制视频

3、监听告警信号

4、实时获取元数据中的划定区域内的人数

摄像头型号如下:

夜莺监控二次开发 监控摄像头二次开发_错误信息

准备工作:

在购买摄像头后,应当在官网下载对应的开发资料,如果需要权限,则联系华为的技术支持人员。下载资料如下:

夜莺监控二次开发 监控摄像头二次开发_华为网络摄像头二次开发_02

SDC Development Kit Demo 8.0.T9 SDK DEMO下载地址:https://bbs.huaweicloud.com/forum/thread-76061-1-1.html

SDC Development Kit 8.0.RC3 下载地址:https://bbs.huaweicloud.com/forum/thread-76255-1-1.html

智能摄像机SDK相关FAQ集:https://bbs.huaweicloud.com/forum/thread-28015-1-1.html?mobile=2Q57

夜莺监控二次开发 监控摄像头二次开发_夜莺监控二次开发_03

在sdk目录下有对应的开发指南,根据开发指南进行环境搭建、流程搭建、函数查找等

代码分析:
/*********************告警回调函数,此处用于监听人数超限告警***********************/
long CALLBACK fGetAlarmInfoCallBack(LPPU_ALARM_REPORT_S pstAlarmReport , void *pUsrData)
{
    PU_ITGT_CROWD_DENSITY_DETECT_PARAM_S *crowdDensityWarning;
    //选择人群密度告警
    switch(pstAlarmReport-> enAlarmType)
    {
        case PU_ALARM_TYPE_CROWD_DENSITY_DETECT:
            //crowdDensityWarning = qobject_cast<PU_ITGT_CROWD_DENSITY_DETECT_PARAM_S *>(pUsrData);
            break;
        default:
            break;
    }

    printf("Device Id:%d\tAlarm type:%d\ttime:%s-%s-%s % s:%s:%s\tAlarm happen:%d\n", pstAlarmReport->ulDeviceId, pstAlarmReport-> enAlarmType,
    pstAlarmReport->stTime.szYear, pstAlarmReport->stTime.szMonth, pstAlarmReport->stTime.szDay, pstAlarmReport->stTime.szHour,
    pstAlarmReport->stTime.szMinute,  pstAlarmReport->stTime.szSecond, pstAlarmReport->enAction);

    return 0;
}
/*****************回调函数,此处用于获取元数据中划定区域的人数*********************/
void CALLBACK fRealDataCallBack(CHAR *szBuffer, LONG lSize, VOID *pUsrData)
{
    BOOL bRet = PU_FALSE;
    //第二层元数据TYPE : TARGET //目标(车、人、人脸等)
    PU_META_DATA *pstMetaTargetData = NULL;
    bRet = IVS_User_GetMetaData(szBuffer,lSize,TARGET, &pstMetaTargetData);
    if ((PU_TRUE == bRet) && (NULL != pstMetaTargetData))
    {
        procMetaData(pstMetaTargetData);
        IVS_User_FreeMetaData(&pstMetaTargetData);
    }
    return;
}
//初始化SDK
void camerawidget::InitSDK()
{
    bool isInit = IVS_PU_Init(3 , NULL , 5050);
    if(!isInit)
    {
        long RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "提示" , QString("错误码是%1,错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        return;
    }
}

//注册设备
void camerawidget::DeviceLogin()
{
    QString m_IP = "192.168.0.14";
    ULONG strPort = 6060;
    QString strUser = "admin";
    QString strPwd = "HuaWei123";

    m_lUserID = IVS_PU_Login(m_IP.toLatin1().data() , strPort , strUser.toLatin1().data() , strPwd.toLatin1().data());
    if(PU_FALSE == m_lUserID)
    {
        long RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "提示" , QString("错误码是%1,错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        return;
    }

    //设置断网重连
    if(PU_FALSE == IVS_PU_SetAutoReconnect(1))
    {
        long RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "提示" , QString("错误码是%1,错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        return;
    }
}

 

/********************Part1: 实时获取区域人数****************/
void camerawidget::startPreview_callbackPeoploNum()
{
    PU_REAL_PLAY_INFO_S stRealPlayInfo = {0};
    stRealPlayInfo.ulChannelId = 101;               //通道号
    stRealPlayInfo.bKeepLive = TRUE;            //是否报活
    stRealPlayInfo.enStreamType = PU_VIDEO_MAIN_STREAM;             //码流类型
    stRealPlayInfo.enVideoType = PU_VIDEO_TYPE_META;      //流类型
    stRealPlayInfo.enProtocolType = PU_PROTOCOL_TYPE_TCP;           //传输协议类型
    stRealPlayInfo.enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE_META_FRAME;
    stRealPlayInfo.enMediaCryptoType = PU_MEDIA_CRYPTO_NONE;    //不加密
    stRealPlayInfo.szReserved[22] = 1;
    stRealPlayInfo.hPlayWnd = NULL;

    m_ReculVideoPlayhandle = IVS_PU_RealPlay(m_lUserID, &stRealPlayInfo, fRealDataCallBack , NULL);
    if(PU_FALSE == m_ReculVideoPlayhandle)
    {
        ULONG RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "提示" , QString("错误码是%1 , 错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        //如果错误,则定时重连
        callbackPeoploNumConnectFlag = false;
        return;
    }
    else
    {
        callbackPeoploNumConnectFlag = true;
    }

    //告警
 /*   if(PU_FALSE == IVS_PU_AlarmInfoStatesCallBack(m_lUserID,  fGetAlarmInfoCallBack , NULL))
    {
        long RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "提示" , QString("错误码是%1,错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        return;
    }*/
}
/*********************Part2 :录像部分*********************/
void camerawidget::startPreview_saveRealData()       //预览,并用于录像
{
    PU_REAL_PLAY_INFO_S stRealPlayInfo = {0};

    stRealPlayInfo.ulChannelId = 101;               //通道号
    stRealPlayInfo.bKeepLive = TRUE;            //是否报活
    stRealPlayInfo.enStreamType = PU_VIDEO_MAIN_STREAM;             //码流类型
    stRealPlayInfo.enVideoType = PU_VIDEO_TYPE_VIDEO;      //流类型
    stRealPlayInfo.enProtocolType = PU_PROTOCOL_TYPE_TCP;           //传输协议类型
    stRealPlayInfo.enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE_RTP;
    stRealPlayInfo.enMediaCryptoType = PU_MEDIA_CRYPTO_NONE;    //不加密
    stRealPlayInfo.hPlayWnd =  (HWND)ui->label->winId();

    if(NULL == stRealPlayInfo.hPlayWnd)
    {
        QMessageBox::about(NULL , "提示" , "获取句柄失败");
        return;
    }

    m_recordingPreviewHandle = IVS_PU_RealPlay(m_lUserID, &stRealPlayInfo, NULL , NULL);
    if(PU_FALSE == m_recordingPreviewHandle)
    {
        ULONG RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "提示" , QString("错误码是%1 , 错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        saveRealDataConnectFlag = false;
        return;
    }
    else
    {
        saveRealDataConnectFlag = true;
    }
}
//开始保存录像数据
void camerawidget::startSaveRealData(QString path)
{
    //保存实况数据
    PU_SAVE_REALDATA_INFO_S saveRealDataInfo = {0};
    //memset(saveRealDataInfo, 0, sizeof(LPPU_SAVE_REALDATA_INFO_S));
    saveRealDataInfo.enSaveType = PU_SAVE_REALDATA_TYPE_TIME;
    strcpy(saveRealDataInfo.szFilePath , path.toLatin1().data());
    saveRealDataInfo.ulSaveSize = 1440;          //最大大小,才能正常播放(时间单位:分钟,大小单位:Mb),此处设置为一天

    if(PU_FALSE == IVS_PU_SaveRealData(m_lUserID , m_recordingPreviewHandle, &saveRealDataInfo))
    {
        ULONG RetErro=IVS_PU_GetLastError();
        QMessageBox::about(NULL , "开始录像" , QString("错误码是%1 , 错误信息是%2").arg(RetErro).arg(IVS_PU_GetErrorMsg(RetErro)));
        return;
    }
}
注意事项:

1、windows下64位sdk加载有问题,请参考:

夜莺监控二次开发 监控摄像头二次开发_错误码_04

2、网页登录摄像头与通过SDK登录摄像头的密码是独立的;SDK固定的账户名和密码:admin/HuaWei123,固定端口是6060

3、视频显示和码流回调不能同时进行,需两次调用接口即可

4、录像时,开始录像函数与停止录像函数必须成对使用,否则视频会无法渲染