请问onvif协议怎么样和live555配合啊!

 2 E币 
成为会员,免费下载资料
文件大小:12.53 KB 上传者:david 时间:2013-01-29 23:00:11 下载量:61
本帖最后由 david 于 2013-1-29 23:01 编辑

年底了要忙飞掉了。给你推荐个以前收藏的的博客,讲的很详细了。[url]http://blog.csdn.net/ghostyu[/url] 转载于此。
有了前几篇的基础,现在可以正式开始onvif的实现工作,其中一项非常重要的部分就是视频流的对接,即能够在符合onvif标准的监控客户端软件里接收到设备端NVT发来的RTSP视频流。这里,我所用的客户端软件是Onvif Device Manager v2.2
ONVIF Profile S Specification文档描述了Device或者说DVT和Client可以使用的一种Profile,Profile这个词在计算机领域非常常见,我们可以理解成一种方案、配置、框架等。

[attach]463[/attach]
文档里描述了如果实现VideoStream,device和client应该具备的条件,当然如果实现文档的所有条件,就可以说该设备符合Profile S

如果单纯实现VideoStream,只需完成下列命令。
1、GetProfiles
2、GetStreamUri
填充rtsp路径,例如:[url]rtsp://192.168.1.201/petrov.m4e[/url]
3、Media Streaming using RTSP
这里使用开源的live555,完成rtsp功能
4、GetVideoEncoderConfiguration
5、GetVideoEncoderConfigurationOptions
6、GetCapabilities
NVC为了获取DVT所支持的功能的命令[code]1、ONVIF Profile S Specification
描述ProfileS是什么样的一个东西,如何实现
2、Reference_of_ONVIF_Development_v1.01.02
Onvif DVT设计参考,指明了一条道路,但没有具体内容
3、ONVIF-Media-Service-Spec-v220
Onvif Media的说明介绍
4、http://www.onvif.org/onvif/ver20/util/operationIndex.html
onvif几乎全部命令的详细说明,非常重要。该文档告诉我们结构体成员的意义和如何填充。Onvif开发其实就是各种结构体的填充。[/code]一、产生onvif源码框架
1、从wsdl生成C头文件
wsdl2h -o onvif.h -c -s -t .\typemap.dat [url]http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/display.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/deviceio.wsdl[/url] [url]http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl[/url] [url]http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl[/url]  [url]http://www.onvif.org/onvif/ver10/receiver.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/recording.wsdl[/url]  [url]http://www.onvif.org/onvif/ver10/search.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/replay.wsdl[/url] [url]http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl[/url]  [url]http://www.onvif.org/onvif/ver10/schema/onvif.xsd[/url]  [url]http://www.onvif.org/ver10/actionengine.wsdl[/url]
跟前一篇discovery唯一不同的是,这里多了很多wsdl文件,这次创建完整的onvif代码框架
2、从头文件生成源码框架
soapcpp2 -c onvif.h -x -I /root/onvif/gsoap-2.8/gsoap/import -I /root/onvif/gsoap-2.8/gsoap/
产生的C文件比较庞大,最大的有十几兆,大部分的内容没有复用导致。

二、创建soap运行环境
int main(int argc, char **argv)  
{  
    int m, s;  
    struct soap add_soap;  
        int server_udp;

        server_udp = create_server_socket_udp();
        //bind_server_udp1(server_udp);
        pthread_t thrHello;
        pthread_t thrProbe;
        //pthread_create(&thrHello,NULL,main_Hello,server_udp);
        //sleep(2);
        pthread_create(&thrProbe,NULL,main_Probe,server_udp);

    soap_init(&add_soap);  
    soap_set_namespaces(&add_soap, namespaces);  


    if (argc < 0) {  
        printf("usage: %s \n", argv[0]);  
        exit(1);  
    } else {  
        m = soap_bind(&add_soap, NULL, 80, 100);  
        if (m < 0) {  
            soap_print_fault(&add_soap, stderr);  
            exit(-1);  
        }  
        fprintf(stderr, "Socket connection successful: master socket = %d\n", m);  
        for (;;) {  
            s = soap_accept(&add_soap);  
            if (s < 0) {  
                soap_print_fault(&add_soap, stderr);  
                exit(-1);  
            }  
            fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);  
            soap_serve(&add_soap);  
            soap_end(&add_soap);  
        }  
    }  
    return 0;  
}

注意,这里绑定了80端口,onvif使用的是http请求,然后附带xml,其实正常的是将onvif集成到web服务器中,普通的http请求有web服务器处理,onvif的http请求则有soap处理。我们这里的做法也可行,只不过onvif的访问web服务器的功能是无法使用的。

三、RTSP视频对接
1、实现GetCapabilities命令
客户端发送GetCapabilities命令来得到设备端的能力,然后依据GetCapabilities返回的结果再来进行下一步操作

在__tds__GetCapabilities函数中我们只需要填充Media部分和一些必要的即可[code]        //想要对接RTSP视频,必须设置Media
        tds__GetCapabilitiesResponse->Capabilities->Media = (struct tt__MediaCapabilities*)soap_malloc(soap, sizeof(struct tt__MediaCapabilities));
        tds__GetCapabilitiesResponse->Capabilities->Media->XAddr = (char *) soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
        strcpy(tds__GetCapabilitiesResponse->Capabilities->Media->XAddr, _IPv4Address);
        tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities = (struct tt__RealTimeStreamingCapabilities*)soap_malloc(soap, sizeof(struct tt__RealTimeStreamingCapabilities));
        tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = (int *)soap_malloc(soap, sizeof(int));       
        *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = _false;       
        tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = (int *)soap_malloc(soap, sizeof(int));
        *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = _true;       
        tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = (int *)soap_malloc(soap, sizeof(int));
        *tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = _true;       
        tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->Extension = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Media->Extension = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Media->__size = 0;
        tds__GetCapabilitiesResponse->Capabilities->Media->__any = 0;[/code]另外必要填充的还有[code]        //下面的重要,这里只实现视频流,需要设置VideoSources
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->VideoSources = TRUE;
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->VideoOutputs = FALSE;
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->AudioSources = FALSE;
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->AudioOutputs = FALSE;
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->RelayOutputs = FALSE;
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->__size = 0;
        tds__GetCapabilitiesResponse->Capabilities->Extension->DeviceIO->__any = NULL;
       
        tds__GetCapabilitiesResponse->Capabilities->Extension->Display = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->Recording = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->Search = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->Replay = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->Receiver = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->AnalyticsDevice = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->Extensions = NULL;
        tds__GetCapabilitiesResponse->Capabilities->Extension->__size = 0;
        tds__GetCapabilitiesResponse->Capabilities->Extension->__any = NULL;[/code]2、实现GetServices命令[code]int  __tds__GetServices(struct soap* soap, struct _tds__GetServices *tds__GetServices, struct _tds__GetServicesResponse *tds__GetServicesResponse)
{
        DBG("__tds__GetServices\n");
        /*该函数很必要*/
        char _IPAddr[INFO_LENGTH];
        int i = 0;
        sprintf(_IPAddr, "http://%03d.%03d.%03d.%03d/onvif/services", 192, 168, 1, 233);
        tds__GetServicesResponse->__sizeService = 1;

        tds__GetServicesResponse->Service = (struct tds__Service *)soap_malloc(soap, sizeof(struct tds__Service));
        tds__GetServicesResponse->Service[0].XAddr = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
        tds__GetServicesResponse->Service[0].Namespace = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
        strcpy(tds__GetServicesResponse->Service[0].Namespace, "http://www.onvif.org/ver10/events/wsdl");
        strcpy(tds__GetServicesResponse[0].Service->XAddr, _IPAddr);
        tds__GetServicesResponse->Service[0].Capabilities = NULL;
        tds__GetServicesResponse->Service[0].Version = (struct tt__OnvifVersion *)soap_malloc(soap, sizeof(struct tt__OnvifVersion));
        tds__GetServicesResponse->Service[0].Version->Major = 0;
        tds__GetServicesResponse->Service[0].Version->Minor = 3;
        tds__GetServicesResponse->Service[0].__any = (char **)soap_malloc(soap, sizeof(char *));
        tds__GetServicesResponse->Service[0].__any[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
        strcpy(tds__GetServicesResponse->Service[0].__any[0],"why1");
        tds__GetServicesResponse->Service[0].__any[1] = (char *)soap_malloc(soap,sizeof(char) * INFO_LENGTH);
        strcpy(tds__GetServicesResponse->Service[0].__any[1],"why2");
        tds__GetServicesResponse->Service[0].__size = NULL;
        tds__GetServicesResponse->Service[0].__anyAttribute = NULL;
        return SOAP_OK;
}[/code]3、实现GetVideoSources命令[code]int  __tmd__GetVideoSources(struct soap* soap, struct _trt__GetVideoSources *trt__GetVideoSources, struct _trt__GetVideoSourcesResponse *trt__GetVideoSourcesResponse)
{
        DBG("__tmd__GetVideoSources\n");

        int size1;
        size1 = 1;
        trt__GetVideoSourcesResponse->__sizeVideoSources = size1;
        trt__GetVideoSourcesResponse->VideoSources = (struct tt__VideoSource *)soap_malloc(soap, sizeof(struct tt__VideoSource) * size1);
        trt__GetVideoSourcesResponse->VideoSources[0].Framerate = 30;
        trt__GetVideoSourcesResponse->VideoSources[0].Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));
        trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Height = 720;
        trt__GetVideoSourcesResponse->VideoSources[0].Resolution->Width = 1280;
        trt__GetVideoSourcesResponse->VideoSources[0].token = (char *)soap_malloc(soap, sizeof(char)*INFO_LENGTH);
        strcpy(trt__GetVideoSourcesResponse->VideoSources[0].token,"GhostyuSource_token"); //注意这里需要和GetProfile中的sourcetoken相同

        trt__GetVideoSourcesResponse->VideoSources[0].Imaging =(struct tt__ImagingSettings*)soap_malloc(soap, sizeof(struct tt__ImagingSettings));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness = (float*)soap_malloc(soap,sizeof(float));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Brightness[0] = 128;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation = (float*)soap_malloc(soap,sizeof(float));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->ColorSaturation[0] = 128;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast = (float*)soap_malloc(soap,sizeof(float));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Contrast[0] = 128;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = (int *)soap_malloc(soap,sizeof(int));
        *trt__GetVideoSourcesResponse->VideoSources[0].Imaging->IrCutFilter = 0;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness = (float*)soap_malloc(soap,sizeof(float));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Sharpness[0] = 128;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation = (struct tt__BacklightCompensation*)soap_malloc(soap, sizeof(struct tt__BacklightCompensation));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Mode = 0;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->BacklightCompensation->Level = 20;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Exposure = NULL;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Focus = NULL;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange = (struct tt__WideDynamicRange*)soap_malloc(soap, sizeof(struct tt__WideDynamicRange));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Mode = 0;   
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WideDynamicRange->Level = 20;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance = (struct tt__WhiteBalance*)soap_malloc(soap, sizeof(struct tt__WhiteBalance));
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->Mode = 0;       
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CrGain = 0;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->WhiteBalance->CbGain = 0;
        trt__GetVideoSourcesResponse->VideoSources[0].Imaging->Extension = NULL;
        trt__GetVideoSourcesResponse->VideoSources[0].Extension = NULL;       
        return SOAP_OK;
}[/code]__tmd__GetVideoSources最重要的是token的填充,必须要和下面profile中的sourcetoken相同,需要匹配到这个视频源

4、实现GetProfiles命令[code]        size = 1;
        trt__GetProfilesResponse->Profiles =(struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile) * size);
        trt__GetProfilesResponse->__sizeProfiles = size;

        i=0;
        trt__GetProfilesResponse->Profiles.Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
        strcpy(trt__GetProfilesResponse->Profiles.Name,"my_profile");
        trt__GetProfilesResponse->Profiles.token= (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
        strcpy(trt__GetProfilesResponse->Profiles.token,"token_profile");
        trt__GetProfilesResponse->Profiles.fixed = _false;
        trt__GetProfilesResponse->Profiles.__anyAttribute = NULL;[/code]除了上面的基本信息,还需要填充两大项:VideoSourceConfiguration和VideoEncoderConfiguration,一个用于描述视频源的信息,另外一个描述视频的编码信息

先给VideoSourceConfiguration分配空间[code]        trt__GetProfilesResponse->Profiles.VideoSourceConfiguration = (struct tt__VideoSourceConfiguration *)soap_malloc(soap,sizeof(struct tt__VideoSourceConfiguration ));
        trt__GetProfilesResponse->Profiles.VideoSourceConfiguration->Name = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
        trt__GetProfilesResponse->Profiles.VideoSourceConfiguration->token = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
        trt__GetProfilesResponse->Profiles.VideoSourceConfiguration->SourceToken = (char *)soap_malloc(soap,sizeof(char)*MAX_PROF_TOKEN);
        trt__GetProfilesResponse->Profiles.VideoSourceConfiguration->Bounds = (struct tt__IntRectangle *)soap_malloc(soap,sizeof(struct tt__IntRectangle));[/code]
展开
折叠
791
评论
共 0 个
内容存在敏感词
    易百纳技术社区暂无数据
相关资料
关于作者
易百纳技术社区
david
贡献资料 233
易百纳技术社区 我上传的资料
登录查看
我赚取的积分
登录查看
我赚取的收益
登录查看
上传资料 赚取积分兑换E币
易百纳技术社区
删除原因
广告/SPAM
恶意灌水
违规内容
文不对题
重复发帖
置顶时间设置
结束时间
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-资料模块

审核失败

失败原因
备注
易百纳技术社区