ONVIF獲取265的rtsp地址,ptz控制記錄

1、獲取url、ptz或imaging的一般流程

在這裏插入圖片描述

《1》、注意

  GetCapabilities是向下兼容的接口只能獲取到設備支持的最基本功能。GetServices接口能獲取到設備支持的所有功能,H265格式的RTSP地址的獲取必須通過該接口獲得。
原文:
在這裏插入圖片描述

《2》、onvif test工具的對比

在這裏插入圖片描述
在這裏插入圖片描述

2、獲取profiles

  以獲取H265的爲例,需要onvif開發框架支持265,該環境搭建看參考6.1

void GetProfileUsedMedia2()
{
    char media_addr2[] = "http://172.16.41.64/onvif/Media2"; //GetServices得到的地址
    struct SOAP_ENV__Header header;  
    struct soap* soap = ONVIF_Initsoap(&header, NULL, NULL, 5);

    struct _tr2__GetProfiles tr2__GetProfiles;
    struct _tr2__GetProfilesResponse tr2__GetProfilesResponse;
    
    tr2__GetProfiles.__sizeType = 1;
    tr2__GetProfiles.Token = NULL;

    char* type[1] = {"VideoEncoder"};
    tr2__GetProfiles.Type = type;

    ONVIF_SetAuthInfo(soap,user_name,passwd);  //鑑權
    soap_call___tr2__GetProfiles(soap, media_addr2, NULL, &tr2__GetProfiles, &tr2__GetProfilesResponse); 
    if(soap->error)
    {
            cout << "soap_call___tr2__GetProfiles main soap error:"<< soap->error << *soap_faultcode(soap) <<
                        *soap_faultstring(soap) << endl;
    }
    else
    {
            if(tr2__GetProfilesResponse.Profiles == NULL)
            {
                ret = -2;
                
            }
            else
            {
                //循環輸出文件信息
                for(int i = 0;i < tr2__GetProfilesResponse.__sizeProfiles;i++,tr2__GetProfilesResponse.Profiles++)
                {

                    if(strstr(tr2__GetProfilesResponse.Profiles->Name,"test"))
                        continue;

                    string video_type =  tr2__GetProfilesResponse.Profiles->Configurations->VideoEncoder->Encoding;
                    transform(video_type.begin(), video_type.end(), video_type.begin(), ::tolower);
                    cout << "===== 265 profile name " << tr2__GetProfilesResponse.Profiles->Name << " token " << tr2__GetProfilesResponse.Profiles->token 
                    <<  " video type " << video_type << endl;
                
                }
            }

    }

    ONVIF_soap_delete(soap);
}

3、獲取rtsp地址

  以獲取H265的爲例,需要onvif開發框架支持265,該環境搭建看參考6.1, 同時也需要對應的IPC設備支持H265獲取RTSP,大概是2018年年底之後的IPC固件才支持,如果IPC不支持是獲取不到media2的

   char media_addr2[] = "http://172.16.41.64/onvif/Media2"; //GetServices得到的地址
    char taken[] = "Profile_1";   //get_profiles獲取
    struct SOAP_ENV__Header header;

    struct soap* soap = ONVIF_Initsoap(&header, NULL, NULL, 5);
    struct _tr2__GetStreamUri tr2__GetStreamUri;
    struct _tr2__GetStreamUriResponse tr2__GetStreamUriResponse;
    tr2__GetStreamUri.Protocol = (char *)soap_malloc(soap, 128*sizeof(char));
    if (NULL == tr2__GetStreamUri.Protocol)
    {
        printf("soap_malloc is error\n");
        ret = -1;
    }

    tr2__GetStreamUri.ProfileToken = (char *)soap_malloc(soap, 128*sizeof(char ));
    if (NULL == tr2__GetStreamUri.ProfileToken)
    {
        printf("soap_malloc is error\n");
        ret = -1;
    }

    strcpy(tr2__GetStreamUri.Protocol, "tcp");
    strcpy(tr2__GetStreamUri.ProfileToken, taken);
    ONVIF_SetAuthInfo(soap,user_name,passwd);  //鑑權
    soap_call___tr2__GetStreamUri(soap, media_addr2, NULL, &tr2__GetStreamUri, &tr2__GetStreamUriResponse);
    if(soap->error)
    {
            cout << "soap_call___tr2__GetStreamUri main soap error:"<< soap->error << *soap_faultcode(soap) <<
                        *soap_faultstring(soap) << endl;
    }
    else
    {
            cout << "media2 MediaUri->Uri=" <<  tr2__GetStreamUriResponse.Uri << endl;

    }

    ONVIF_soap_delete(soap);

4、PTZ持續移動

void ptzContinueMove(int cmd , int speed)
{
    if(ptzurl.empty())
    {
        printf("ptzContinueMove ptzurl is empty \n");
        return;
    }
    
    struct SOAP_ENV__Header header;
    struct soap* soap = ONVIF_Initsoap(&header, NULL, NULL, 5);
    const int RECV_MAX_TIME = 2;
    soap->recv_timeout = RECV_MAX_TIME;
    soap->send_timeout = RECV_MAX_TIME;
    soap->connect_timeout = RECV_MAX_TIME;

    int speed_x=0;
    int speed_y=0;
    int speed_z=0;

    struct _tptz__ContinuousMove                continuousMove;
    struct _tptz__ContinuousMoveResponse        continuousMoveresponse;

    LONG64 timeout = 2;
    continuousMove.Timeout = &timeout;
    char ProfileToken[32] = {0};
    strncpy(ProfileToken, "MainProfileToken", sizeof(ProfileToken));
    continuousMove.ProfileToken = ProfileToken;

    struct tt__PTZSpeed* velocity = (struct tt__PTZSpeed*)soap_malloc(soap, sizeof(struct tt__PTZSpeed));
    continuousMove.Velocity = velocity;

    struct tt__Vector2D* panTilt = (struct tt__Vector2D*)soap_malloc(soap, sizeof(struct tt__Vector2D));
    continuousMove.Velocity->PanTilt = panTilt;

    continuousMove.Velocity->PanTilt->space = NULL;

    if(cmd >= PTZ_CMD_ZOOM_NEAR)
    {
        struct tt__Vector1D* zoom = (struct tt__Vector1D*)soap_malloc(soap, sizeof(struct tt__Vector1D));
        continuousMove.Velocity->Zoom = zoom;
        continuousMove.Velocity->PanTilt->x = (float)speed_x / 100;
        continuousMove.Velocity->PanTilt->y = (float) speed_y / 100;
        continuousMove.Velocity->Zoom->x = (float)speed_z / 100;

        continuousMove.Velocity->Zoom->space = NULL;
    }

    switch (cmd)
    {
        case PTZ_CMD_LEFT:
            continuousMove.Velocity->PanTilt->x = -((float)speed / 100);
            break;

        case PTZ_CMD_RIGHT:
            continuousMove.Velocity->PanTilt->x = (float)speed / 100;
            //continuousMove.Velocity->PanTilt->y = 0;
            break;
        case PTZ_CMD_UP:
            //continuousMove.Velocity->PanTilt->x = 0;
            continuousMove.Velocity->PanTilt->y = (float)speed / 100;
            break;

        case PTZ_CMD_DOWN:
            //continuousMove.Velocity->PanTilt->x = 0;
            continuousMove.Velocity->PanTilt->y = -((float)speed / 100);
            break;
        
            // 縮小
        case PTZ_CMD_ZOOM_NEAR:
            continuousMove.Velocity->Zoom->x = -((float)speed / 100);
            break;

        // 放大
        case PTZ_CMD_ZOOM_FAR:
            continuousMove.Velocity->Zoom->x = (float)speed / 100;
            break;

        default:
            break;
    }

    char soap_endpoint[64] = {0};
    sprintf(soap_endpoint, "%s", ptzurl.c_str());
    printf("ptz_url: %s \n", soap_endpoint);

    ONVIF_SetAuthInfo(soap, user_name, passwd);  //鑑權
    if(soap_call___tptz__ContinuousMove(soap, soap_endpoint, NULL, &continuousMove, &continuousMoveresponse) == SOAP_OK)
    {
        printf("======SetPTZcontinuous_move is success!!!=======\n");
    }
    else
    {
        printf("======SetPTZcontinuous_move is faile!!!=======\n");
        printf("soap_call___tptz__ContinuousMove soap error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
    }

    ONVIF_soap_delete(soap);

}

5、完整demo

6、參考

《1》、Linux下onvi支持h264、h265環境的的搭建:gsoap的安裝及生產.c .h文件
《2》、Linux下onvif客戶端獲取h265 IPC攝像頭的RTSP地址
《3》、ONVIF Core Specification

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章