栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Linux onvif协议实现二(C语言客户端)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux onvif协议实现二(C语言客户端)

创作人QQ:851301776,邮箱:lfr890207@163.com,欢迎大家一起技术交流,本博客主要是自己学习的心得体会,只为每天进步一点点!

个人座右铭:
1.没有横空出世,只要厚积一定发。
2.你可以学历不高,你可以不上学,但你不能不学习

一、介绍

        这里主要是以测试实现功能为准则,并没有进一步的整理和优化,测试完成功能后,后期项目进行整理。

        ONVIF网上介绍的很多,还有很多对实现进行介绍的,这里不做介绍,网上很多的获取设备能力、获取音视频数据等都有,这里主要贴云台控制。

二、绝对移动 1.或者云台地址

ONVIF_GetCapabilities(DeviceXAddr, ptzXAddr);

2.获取配置文件token

ONVIF_GetProfiles(ptzXAddr, profilesToken); 

3.绝对移动(切记使用动态分配)

int ONVIF_PTZAbsoluteMove(const char *ptzXAddr, const char *ProfileToken)

{

    int result = 0;
    struct soap *soap = NULL;
    struct _tptz__AbsoluteMove           absoluteMove;
    struct _tptz__AbsoluteMoveResponse   absoluteMoveResponse;

    SOAP_ASSERT(ptzXAddr != NULL);
    SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));


    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    absoluteMove.ProfileToken = (char *)soap_malloc(soap, 128);
    memcpy(absoluteMove.ProfileToken, "MediaProfile00000", strlen("MediaProfile00000"));    
    printf("absoluteMove.ProfileToken = %sn", absoluteMove.ProfileToken);

    absoluteMove.Position = soap_new_tt__PTZVector(soap,sizeof(struct tt__PTZVector));
    absoluteMove.Position->PanTilt = soap_new_tt__Vector2D(soap, sizeof(struct tt__Vector2D));
    absoluteMove.Position->Zoom = soap_new_tt__Vector1D(soap, sizeof(struct tt__Vector1D));
    absoluteMove.Speed = soap_new_tt__PTZSpeed(soap, sizeof(struct tt__PTZSpeed));
    absoluteMove.Speed->PanTilt = soap_new_tt__Vector2D(soap, sizeof(struct tt__Vector2D));
    absoluteMove.Speed->Zoom = soap_new_tt__Vector1D(soap, sizeof(struct tt__Vector1D));


    absoluteMove.Position->PanTilt->x = 0;  // p
    absoluteMove.Position->PanTilt->y = 0;   // t
    absoluteMove.Position->Zoom->x = -1;   // z

     // x 和y的绝对值越接近1,表示云台的速度越快
    absoluteMove.Speed->PanTilt->x = 0;
    absoluteMove.Speed->PanTilt->y = 0;
    absoluteMove.Speed->Zoom->x = 1;
    result = soap_call___tptz__AbsoluteMove(soap,ptzXAddr, NULL,&absoluteMove,&absoluteMoveResponse);
    SOAP_CHECK_ERROR(result, soap, "ONVIF_PTZAbsoluteMove");
    
    printf("%s result = %d n", __func__);

EXIT:
    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }
    return 0;

}

4.相对移动

void ONVIF_PTZMoveStep(const char *ptzXAddr, char *ProfileToken, enum ptz_common cmd, float move_step)
{
    SOAP_ASSERT(NULL != ptzXAddr);
    SOAP_ASSERT(NULL != ProfileToken);

    float MoveStep = 0;
    if(move_step >= 1)
        MoveStep = 0.9;
    else{
        MoveStep = move_step;
    }

    struct soap *soap = NULL;
    SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    
    
    struct _tptz__RelativeMove RelativeMove;
    struct _tptz__RelativeMoveResponse RelativeMoveResponse;

    RelativeMove.ProfileToken = ProfileToken;
    printf("tptz__RelativeMove.ProfileToken:%sn", RelativeMove.ProfileToken);
    struct tt__PTZVector* Translation = soap_new_tt__PTZVector(soap, -1);
    RelativeMove.Translation = Translation;    
    struct tt__Vector2D* panTilt = soap_new_tt__Vector2D(soap, -1);
    RelativeMove.Translation->PanTilt = panTilt;
    //RelativeMove.Translation->PanTilt->space = "http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace";
    struct tt__Vector1D* zoom = soap_new_tt__Vector1D(soap, -1);
    RelativeMove.Translation->Zoom = zoom;
    
    switch (cmd)
    {
        case PTZ_LEFT:
            RelativeMove.Translation->PanTilt->x = MoveStep;
            break;
        case PTZ_RIGHT:
            RelativeMove.Translation->PanTilt->x = -MoveStep;
            break;
        case PTZ_UP:
            RelativeMove.Translation->PanTilt->y = -MoveStep;
            break;
        case PTZ_DOWN:
            RelativeMove.Translation->PanTilt->y = move_step;
            break;
        case PTZ_LEFTUP:
            RelativeMove.Translation->PanTilt->x = MoveStep;
            RelativeMove.Translation->PanTilt->y = -MoveStep;
            break;
        case PTZ_LEFTDOWN:
            RelativeMove.Translation->PanTilt->x = MoveStep;
            RelativeMove.Translation->PanTilt->y = MoveStep;
            break;
        case PTZ_RIGHTUP:
            RelativeMove.Translation->PanTilt->x = -MoveStep;
            RelativeMove.Translation->PanTilt->y = -move_step;
            break;
        case PTZ_RIGHTDOWN:
            RelativeMove.Translation->PanTilt->x = -MoveStep;
            RelativeMove.Translation->PanTilt->y = MoveStep;
            break;
        case PTZ_ZOOMIN:
            RelativeMove.Translation->Zoom->x = MoveStep;
            break;
        case PTZ_ZOOMOUT:
            RelativeMove.Translation->Zoom->x = -MoveStep;
            break;
        default:
            break;
    }

    int result = soap_call___tptz__RelativeMove(soap, ptzXAddr, NULL, &RelativeMove, &RelativeMoveResponse);
    SOAP_CHECK_ERROR(result, soap, "soap_call___tptz__RelativeMove");
    printf("result:%dn", result);
    
    
 EXIT:
    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }
    return result;    
    
}


5.持续移动

int ONVIF_PTZContinuousMove(const char *ptzXAddr, char *ProfileToken, enum PTZCMD cmd, float speed)

{      

   int result = 0;
    struct soap *soap = NULL;
    struct _tptz__ContinuousMove continuousMove;
    struct _tptz__ContinuousMoveResponse continuousMoveResponse;

    SOAP_ASSERT(NULL != ptzXAddr);
    SOAP_ASSERT(NULL != ProfileToken);
   SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
    //SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(5)));

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    continuousMove.ProfileToken = ProfileToken;
    printf("continuousMove.ProfileToken:%sn", continuousMove.ProfileToken);

   struct tt__PTZSpeed* velocity = soap_new_tt__PTZSpeed(soap, -1);
    continuousMove.Velocity = velocity;
    struct tt__Vector2D* panTilt = soap_new_tt__Vector2D(soap, -1);
    continuousMove.Velocity->PanTilt = panTilt;
    continuousMove.Velocity->PanTilt->space = "http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace";
    struct tt__Vector1D* zoom = soap_new_tt__Vector1D(soap, -1);
    continuousMove.Velocity->Zoom = zoom;

    

switch (cmd)
    {
        case  PTZ_CMD_LEFT:
            continuousMove.Velocity->PanTilt->x = -speed;
            continuousMove.Velocity->PanTilt->y = 0;
            break;
        case  PTZ_CMD_RIGHT:
            continuousMove.Velocity->PanTilt->x = speed;
            continuousMove.Velocity->PanTilt->y = 0;
            break;
        case  PTZ_CMD_UP:
            continuousMove.Velocity->PanTilt->x = 0;
            continuousMove.Velocity->PanTilt->y = speed;
            break;
        case  PTZ_CMD_DOWN:
            continuousMove.Velocity->PanTilt->x = 0;
            continuousMove.Velocity->PanTilt->y = -speed;
            break;
        case  PTZ_CMD_LEFTUP:
            continuousMove.Velocity->PanTilt->x = -speed;
            continuousMove.Velocity->PanTilt->y = speed;
            break;
        case PTZ_CMD_LEFTDOWN:
            continuousMove.Velocity->PanTilt->x = -speed;
            continuousMove.Velocity->PanTilt->y = -speed;
            break;
        case  PTZ_CMD_RIGHTUP:
            continuousMove.Velocity->PanTilt->x = speed;
            continuousMove.Velocity->PanTilt->y = speed;
            break;
        case PTZ_CMD_RIGHTDOWN:
            continuousMove.Velocity->PanTilt->x = speed;
            continuousMove.Velocity->PanTilt->y = -speed;
            break;
        case  PTZ_CMD_ZOOM_IN:
            continuousMove.Velocity->PanTilt->x = 1;
            continuousMove.Velocity->PanTilt->y = 1;
            continuousMove.Velocity->Zoom->x = speed;
            break;
        case  PTZ_CMD_ZOOM_OUT:
            continuousMove.Velocity->PanTilt->x = 0;
            continuousMove.Velocity->PanTilt->y = 0;
            continuousMove.Velocity->Zoom->x = -speed;
            break;
        default:
            break;
    }
    

    result = soap_call___tptz__ContinuousMove(soap,ptzXAddr, NULL,&continuousMove,&continuousMoveResponse);
    SOAP_CHECK_ERROR(result, soap, "soap_call___tptz__ContinuousMove");
    printf("soap_call___tptz__ContinuousMove :result = %dn", result);

   EXIT:
    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }
    return result;    

}

6.停止移动

int ONVIF_PTZStopMove(const char* ptzXAddr, const char* ProfileToken){
    int result = 0;
    struct soap *soap = NULL;
    struct _tptz__Stop tptzStop;
    struct _tptz__StopResponse tptzStopResponse;

    SOAP_ASSERT((ptzXAddr != NULL) && (ProfileToken != NULL));
    SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    tptzStop.ProfileToken = ProfileToken;
    result = soap_call___tptz__Stop(soap, ptzXAddr, NULL, &tptzStop, &tptzStopResponse);
    SOAP_CHECK_ERROR(result, soap, "ONVIF_PTZStopMove");
    printf("%s result=%dn", __func__);
    EXIT:
    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }
    return result;
}

7.获取云台状态

这个需要根据摄像头了,我这边已经实现,但是获取回来的状态有问题

8.提取音视频数据

    (1)安装库

    

 

void open_rtsp(char *rtsp)
{
    unsigned int    i;
    int             ret;
    int             video_st_index = -1;
    int             audio_st_index = -1;
    AVFormatContext *ifmt_ctx = NULL;
    AVPacket        pkt;
    AVStream        *st = NULL;
    char            errbuf[64];

    av_register_all();                                                          
    avformat_network_init();                                                    

    if ((ret = avformat_open_input(&ifmt_ctx, rtsp, 0, NULL)) < 0) {            
        printf("avformat_open_input errorn");
        goto EXIT;
    }

    if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {         
        printf("avformat_find_stream_info errorn");
        goto EXIT;
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++) {                                // dump information
        av_dump_format(ifmt_ctx, i, rtsp, 0);
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++) {                                // find video stream index
        st = ifmt_ctx->streams[i];
        switch(st->codec->codec_type) {
        case AVMEDIA_TYPE_AUDIO: audio_st_index = i; break;
        case AVMEDIA_TYPE_VIDEO: video_st_index = i; break;
        default: break;
        }
    }
    if (-1 == video_st_index) {
        printf("No H.264 video stream in the input filen");
        goto EXIT;
    }

    av_init_packet(&pkt);                                                       // initialize packet.
    pkt.data = NULL;
    pkt.size = 0;

    while (1)
    {

        do {
            ret = av_read_frame(ifmt_ctx, &pkt);                                // read frames
        } while (ret == AVERROR(EAGAIN));

        if (ret < 0) {
          
            printf("av_read_frame errorn");
            break;
        }
        
        if (pkt.stream_index == video_st_index) {                               // video frame
            printf("Video Packet size = %dn", pkt.size);
            printf("pkt.data:");
            int i = 0;
            for(i=0;i             {
                printf("%02x ", pkt.data[i]);
            }
            printf("n");
            sleep(1);
        } else if(pkt.stream_index == audio_st_index) {                         // audio frame
            printf("Audio Packet size = %dn", pkt.size);
        } else {
            printf("Unknow Packet size = %dn", pkt.size);
        }

        av_packet_unref(&pkt);
    }

EXIT:

    if (NULL != ifmt_ctx) {
        avformat_close_input(&ifmt_ctx);
        ifmt_ctx = NULL;
    }

    return ;
}

int ONVIF_GetStreamUri(const char *MediaXAddr, char *ProfileToken, char *uri, unsigned int sizeuri)
{
    int result = 0;
    struct soap *soap = NULL;
    struct tt__StreamSetup              ttStreamSetup;
    struct tt__Transport                ttTransport;
    struct _trt__GetStreamUri           req;
    struct _trt__GetStreamUriResponse   rep;

    SOAP_ASSERT(NULL != MediaXAddr);
    SOAP_ASSERT(NULL != uri);
    memset(uri, 0x00, sizeuri);

    SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));

    memset(&req, 0x00, sizeof(req));
    memset(&rep, 0x00, sizeof(rep));
    memset(&ttStreamSetup, 0x00, sizeof(ttStreamSetup));
    memset(&ttTransport, 0x00, sizeof(ttTransport));
    ttStreamSetup.Stream                = tt__StreamType__RTP_Unicast;
    ttStreamSetup.Transport             = &ttTransport;
    ttStreamSetup.Transport->Protocol   = tt__TransportProtocol__RTSP;
    ttStreamSetup.Transport->Tunnel     = NULL;
    req.StreamSetup                     = &ttStreamSetup;
    req.ProfileToken                    = ProfileToken;

    ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);
    result = soap_call___trt__GetStreamUri(soap, MediaXAddr, NULL, &req, &rep);
    SOAP_CHECK_ERROR(result, soap, "GetServices");

    dump_trt__GetStreamUriResponse(&rep);

    result = -1;
    if (NULL != rep.MediaUri) {
        if (NULL != rep.MediaUri->Uri) {
            if (sizeuri > strlen(rep.MediaUri->Uri)) {
                strcpy(uri, rep.MediaUri->Uri);
                result = 0;
            } else {
                SOAP_DBGERR("Not enough cache!n");
            }
        }
    }

EXIT:

    if (NULL != soap) {
        ONVIF_soap_delete(soap);
    }

    return result;
}

void cb_discovery(char *DeviceXAddr)
{
    int stmno = 0;                                                              // 码流序号,0为主码流,1为辅码流
    int profile_cnt = 0;                                                        // 设备配置文件个数
    struct tagProfile *profiles = NULL;                                         // 设备配置文件列表
    struct tagCapabilities capa;                                                // 设备能力信息

    char uri[ONVIF_ADDRESS_SIZE] = {0};                                         // 不带认证信息的URI地址
    char uri_auth[ONVIF_ADDRESS_SIZE + 50] = {0};                // 带有认证信息的URI地址

    ONVIF_GetCapabilities(DeviceXAddr, &capa);        // 获取设备能力信息(获取媒体服务地址)

    profile_cnt = ONVIF_GetProfiles(capa.MediaXAddr, &profiles);    // 获取媒体配置信息(主/辅码流配置信息)

    if (profile_cnt > stmno) {
        ONVIF_GetStreamUri(capa.MediaXAddr, profiles[stmno].token, uri, sizeof(uri)); // 获取RTSP地址

        make_uri_withauth(uri, USERNAME, PASSWORD, uri_auth, sizeof(uri_auth)); // 生成带认证信息的URI(有的IPC要求认证)

        open_rtsp(uri_auth);                                                    // 读取主码流的音视频数据
    }

    if (NULL != profiles) {
        free(profiles);
        profiles = NULL;
    }
}
 

9.其他

 其他的没什么难度了,比如获取时间之类的 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/511387.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号