Onvif服务端开发

embedded/2024/12/22 23:12:57/

实现了Onvif服务端的设备搜索和RTSP流的功能。用 ONVIF Device Manager 测试工具可以成功搜索到设备和获取到RTSP流,有的路由器可能不支持239.255.255.250组播,我一开始用的电信的那种光猫路由器二合一的,一直搜不到设备,后面用Socket调试工具发现根本收不到组播消息,换了个小米的路由器就可以了🥲。RTSP服务端我是直接用的 live555, 完整代码我已上传,不需要积分就能下载。主要是看onvif_server.c 和 onvif_server_interface.c 文件,onvif_server.c 主要是创建socket服务,onvif_server_interface.c 主要是实现相关的onvif服务接口。相关代码如下:

onvif_server.c:

#include <pthread.h>
#include "soapH.h"
#include "macro.h"void *onvif_discovered_server(void *arg)
{struct soap soap_udp;int socked_fd;// 初始化 SOAP 服务器对象soap_init1(&soap_udp, SOAP_IO_UDP | SOAP_XML_IGNORENS);soap_udp.bind_flags = SO_REUSEADDR; // 允许重复绑定soap_udp.port = 3702;soap_set_namespaces(&soap_udp, namespaces);// 绑定端口socked_fd = soap_bind(&soap_udp, NULL, soap_udp.port, 10);if (socked_fd < 0){printf("%d soap_bind failed\n", __LINE__);soap_print_fault(&soap_udp, stderr);goto end;}// 加入组播struct ip_mreq mreqcon;mreqcon.imr_multiaddr.s_addr = inet_addr("239.255.255.250");mreqcon.imr_interface.s_addr = htonl(INADDR_ANY);if (setsockopt(soap_udp.master, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreqcon, sizeof(mreqcon)) < 0){printf("setsockopt error, error message: %s\n", strerror(errno));goto end;}while (1){socked_fd = soap_serve(&soap_udp);if (socked_fd != SOAP_OK){printf("%d soap_serve failed\n", __LINE__);soap_print_fault(&soap_udp, stderr);}soap_destroy(&soap_udp);soap_end(&soap_udp);}end:soap_done(&soap_udp);return NULL;
}int http_get(struct soap *soap)
{FILE *fd = NULL;static char buf[1024 * 5] = {0};fd = fopen(PATH_HTML, "rb");if (!fd)return 404;if (soap_response(soap, SOAP_HTML) == SOAP_OK) // HTTP response header with text/html{size_t r = fread(buf, 1, sizeof(buf), fd);if (r > 0)soap_send(soap, buf);}soap_end_send(soap);fclose(fd);return SOAP_OK;
}void *onvif_http_server(void *arg)
{struct soap soap_tcp;int socked_fd;fd_set readfds;struct timeval timeout;timeout.tv_sec = 1;timeout.tv_usec = 0;soap_init1(&soap_tcp, SOAP_XML_INDENT);soap_tcp.port = DEVICE_PORT;soap_tcp.bind_flags = SO_REUSEADDR;soap_tcp.send_timeout = 3; // send timeout is 3ssoap_tcp.recv_timeout = 3; // receive timeout is 3ssoap_tcp.fget = http_get;soap_set_namespaces(&soap_tcp, namespaces);socked_fd = soap_bind(&soap_tcp, DEVICE_IP, soap_tcp.port, 10);if (socked_fd < 0){printf("%d soap_bind failed\n", __LINE__);soap_print_fault(&soap_tcp, stderr);goto end;}int socked_fd_new = -1;while (1){socked_fd_new = soap_accept(&soap_tcp);if (!soap_valid_socket(socked_fd_new)){printf("soap_accept failed\n");soap_print_fault(&soap_tcp, stderr);goto end;}FD_ZERO(&readfds);FD_SET(socked_fd_new, &readfds);int activity = select(socked_fd_new + 1, &readfds, NULL, NULL, &timeout);if (activity < 0){printf("select error\n");goto end;}if (FD_ISSET(socked_fd_new, &readfds)){if (soap_serve(&soap_tcp) != SOAP_OK){printf("%d soap_serve failed, error: %d\n", __LINE__, soap_tcp.error);soap_print_fault(&soap_tcp, stderr);}}soap_destroy(&soap_tcp);soap_end(&soap_tcp);}end:soap_done(&soap_tcp);return NULL;
}int create_onvif_server()
{pthread_t thread1, thread2;pthread_attr_t attr1, attr2;pthread_attr_init(&attr1);pthread_attr_init(&attr2);pthread_attr_setdetachstate(&attr1, PTHREAD_CREATE_DETACHED);pthread_attr_setdetachstate(&attr2, PTHREAD_CREATE_DETACHED);if (pthread_create(&thread1, &attr1, onvif_discovered_server, NULL) != 0)return -1;if (pthread_create(&thread2, &attr2, onvif_http_server, NULL) != 0)return -1;pthread_attr_destroy(&attr1);pthread_attr_destroy(&attr2);return 0;
}

 onvif_server_interface.c,这里只写出已经实现了的接口函数:

#include "wsaapi.h"
#include "soapH.h"
#include "soapStub.h"
#include "macro.h"
#include "wsseapi.h"// 该函数从 soapClient.c 文件中拷贝过来的
SOAP_FMAC5 int SOAP_FMAC6 soap_send___wsdd__ProbeMatches(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{struct __wsdd__ProbeMatches soap_tmp___wsdd__ProbeMatches;if (soap_action == NULL)soap_action = "http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/ProbeMatches";soap_tmp___wsdd__ProbeMatches.wsdd__ProbeMatches = wsdd__ProbeMatches;soap_begin(soap);soap_set_version(soap, 2);  /* use SOAP1.2 */soap->encodingStyle = NULL; /* use SOAP literal style */soap_serializeheader(soap);soap_serialize___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches);if (soap_begin_count(soap))return soap->error;if ((soap->mode & SOAP_IO_LENGTH)){if (soap_envelope_begin_out(soap) || soap_putheader(soap) || soap_body_begin_out(soap) || soap_put___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches, "-wsdd:ProbeMatches", "") || soap_body_end_out(soap) || soap_envelope_end_out(soap))return soap->error;}if (soap_end_count(soap))return soap->error;if (soap_connect(soap, soap_endpoint, soap_action) || soap_envelope_begin_out(soap) || soap_putheader(soap) || soap_body_begin_out(soap) || soap_put___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches, "-wsdd:ProbeMatches", "") || soap_body_end_out(soap) || soap_envelope_end_out(soap) || soap_end_send(soap))return soap_closesock(soap);return SOAP_OK;
}// 鉴权
int onvif_access_control(struct soap *soap){const char *username = soap_wsse_get_Username(soap);if (!username){soap_wsse_delete_Security(soap); // remove old security headers before returning!return soap->error;              // no username: return FailedAuthentication (from soap_wsse_get_Username)}if (strcmp(username, USERNAME) != 0){printf("username error\n");soap_wsse_delete_Security(soap);return 401;}if (soap_wsse_verify_Password(soap, PASSWORD)){soap_wsse_delete_Security(soap); // remove old security headers before returning!return soap->error;              // no username: return FailedAuthentication (from soap_wsse_verify_Password)}return 0;
}// 实现 __wsdd__Probe 函数,用于处理 WS-Discovery Probe 请求
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Probe(struct soap *soap, struct wsdd__ProbeType *wsdd__Probe)
{printf("-------- %s --------\n", __func__);// 定义一个 ProbeMatches 结构,用于存储多个 ProbeMatch 条目struct wsdd__ProbeMatchesType ProbeMatches;// 假设设备仅有一个匹配项 (一个服务)int MatchSize = 1;// 初始化 ProbeMatches 结构,清零内存memset(&ProbeMatches, 0, sizeof(ProbeMatches));// 分配内存给 ProbeMatch 数组// 使用 soap_malloc 分配内存,这样 gSOAP 可以自动管理其生命周期ProbeMatches.ProbeMatch = (struct wsdd__ProbeMatchType *)soap_malloc(soap, sizeof(struct wsdd__ProbeMatchType) * MatchSize);if (!ProbeMatches.ProbeMatch)return SOAP_FAULT; // 内存分配失败,返回 SOAP Fault// 初始化 ProbeMatches.ProbeMatchsoap_default_wsdd__ProbeMatchType(soap, ProbeMatches.ProbeMatch);// 设置实际的 ProbeMatch 数量ProbeMatches.__sizeProbeMatch = MatchSize;// 获取第一个(也是唯一一个) ProbeMatch 条目struct wsdd__ProbeMatchType *ProbeMatch = &ProbeMatches.ProbeMatch[0];// ----------------------------// 填充 EndpointReference 信息// ----------------------------/** EndpointReference 用于标识设备的唯一地址 (URI)。* 通常使用设备的 UUID 来生成一个 URN 格式的地址。*/ProbeMatch->wsa__EndpointReference.Address = (char *)soap_malloc(soap, 256);if (!ProbeMatch->wsa__EndpointReference.Address)return SOAP_FAULT;// 格式化地址为 "urn:uuid:device_uuid"snprintf(ProbeMatch->wsa__EndpointReference.Address, 256, "urn:uuid:%s", "12345678-1234-1234-1234-1234567890ab");// -------------------// 填充 Types 信息// -------------------/** Types 用于描述设备的类型,根据 ONVIF 规范,通常包括设备提供的服务类型。* 例如,"tdn:NetworkVideoTransmitter" 表示设备是一个网络视频传输器。*/ProbeMatch->Types = (char *)soap_malloc(soap, 256);if (!ProbeMatch->Types)return SOAP_FAULT;strcpy(ProbeMatch->Types, "tdn:NetworkVideoTransmitter");// -------------------// 填充 Scopes 信息// -------------------/** Scopes 用于描述设备的作用域信息,提供更详细的设备分类和属性。* 例如,设备类型、制造商、型号、位置等。* 作用域以空格分隔的 URI 形式表示。*/ProbeMatch->Scopes = (struct wsdd__ScopesType *)soap_malloc(soap, sizeof(struct wsdd__ScopesType));if (!ProbeMatch->Scopes)return SOAP_FAULT;ProbeMatch->Scopes->__item = (char *)soap_malloc(soap, 512);if (!ProbeMatch->Scopes->__item)return SOAP_FAULT;// 示例作用域信息,根据实际情况调整snprintf(ProbeMatch->Scopes->__item, 512,"onvif://www.onvif.org/type/video_encoder ""onvif://www.onvif.org/type/audio_encoder ""onvif://www.onvif.org/hardware/%s ""onvif://www.onvif.org/name/%s","MyDeviceHardware", "MyONVIFDevice");// -------------------// 填充 XAddrs 信息// -------------------/** XAddrs 提供设备服务的访问地址 (URL),通常包括 HTTP 或 HTTPS 地址。* 该地址用于访问设备的 Onvif 服务,如设备管理、媒体服务等。*/ProbeMatch->XAddrs = (char *)soap_malloc(soap, 256);if (!ProbeMatch->XAddrs)return SOAP_FAULT;// 格式化服务访问地址snprintf(ProbeMatch->XAddrs, 256, "http://%s:%d/onvif/device_service", DEVICE_IP, DEVICE_PORT);// ---------------------------// 填充 MetadataVersion 信息// ---------------------------/** MetadataVersion 表示设备元数据的版本号,用于跟踪设备描述的变化。* 每当设备的元数据(如服务列表、配置等)发生变化时,应递增此版本号。*/ProbeMatch->MetadataVersion = 1;// Build SOAP Headersoap->header->wsa__RelatesTo = (struct wsa__Relationship *)soap_malloc(soap, sizeof(struct wsa__Relationship));if (!soap->header->wsa__RelatesTo)return SOAP_FAULT;// 初始化 soap->header->wsa__RelatesTosoap_default__wsa__RelatesTo(soap, soap->header->wsa__RelatesTo);soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;soap->header->wsa__Action = soap_strdup(soap, "http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches");soap->header->wsa__To = soap_strdup(soap, "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous");// 发送 ProbeMatches 响应return soap_send___wsdd__ProbeMatches(soap, "http://", NULL, &ProbeMatches);
}SOAP_FMAC5 int SOAP_FMAC6 __tds__GetCapabilities(struct soap *soap, struct _tds__GetCapabilities *tds__GetCapabilities, struct _tds__GetCapabilitiesResponse *tds__GetCapabilitiesResponse)
{printf("-------- %s --------\n", __func__);/*int ret = onvif_access_control(soap);if (ret != 0)return ret;*/tds__GetCapabilitiesResponse->Capabilities = (struct tt__Capabilities *)soap_malloc(soap, sizeof(struct tt__Capabilities));memset(tds__GetCapabilitiesResponse->Capabilities, 0, sizeof(struct tt__Capabilities));// Mediaif (tds__GetCapabilities->Category[0] == tt__CapabilityCategory__Media ||tds__GetCapabilities->Category[0] == tt__CapabilityCategory__All){tds__GetCapabilitiesResponse->Capabilities->Media = (struct tt__MediaCapabilities *)soap_malloc(soap, sizeof(struct tt__MediaCapabilities));memset(tds__GetCapabilitiesResponse->Capabilities->Media, 0, sizeof(struct tt__MediaCapabilities));tds__GetCapabilitiesResponse->Capabilities->Media->XAddr = (char *)soap_malloc(soap, sizeof(char) * 256);memset(tds__GetCapabilitiesResponse->Capabilities->Media->XAddr, 0, sizeof(char) * 256);sprintf(tds__GetCapabilitiesResponse->Capabilities->Media->XAddr, "http://%s:%d/onvif/media_service", DEVICE_IP, DEVICE_PORT);//<Media><StreamingCapabilities>tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities = (struct tt__RealTimeStreamingCapabilities *)soap_malloc(soap, sizeof(struct tt__RealTimeStreamingCapabilities));memset(tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities, 0, sizeof(struct tt__RealTimeStreamingCapabilities));tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast = (enum xsd__boolean *)soap_malloc(soap, sizeof(enum xsd__boolean));*(tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTPMulticast) = xsd__boolean__false_; // 表示设备不支持RTP的多播功能tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP = (enum xsd__boolean *)soap_malloc(soap, sizeof(enum xsd__boolean));*(tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP) = xsd__boolean__true_; // 表示设备支持通过RTSP的TCP传输方式tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP = (enum xsd__boolean *)soap_malloc(soap, sizeof(enum xsd__boolean));*(tds__GetCapabilitiesResponse->Capabilities->Media->StreamingCapabilities->RTP_USCORETCP) = xsd__boolean__true_; // 表示设备支持RTP协议的TCP传输方式}// 返回成功return SOAP_OK;
}SOAP_FMAC5 int SOAP_FMAC6 __trt__GetVideoSources(struct soap *soap, struct _trt__GetVideoSources *trt__GetVideoSources, struct _trt__GetVideoSourcesResponse *trt__GetVideoSourcesResponse)
{printf("-------- %s --------\n", __func__);int size = 1;trt__GetVideoSourcesResponse->__sizeVideoSources = size;trt__GetVideoSourcesResponse->VideoSources = (struct tt__VideoSource *)soap_malloc(soap, sizeof(struct tt__VideoSource) * size);memset(trt__GetVideoSourcesResponse->VideoSources, 0, sizeof(struct tt__VideoSource) * trt__GetVideoSourcesResponse->__sizeVideoSources);trt__GetVideoSourcesResponse->VideoSources->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetVideoSourcesResponse->VideoSources->token, 0, sizeof(char) * 32);strcpy(trt__GetVideoSourcesResponse->VideoSources->token, "vs_SourceToken");trt__GetVideoSourcesResponse->VideoSources->Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));memset(trt__GetVideoSourcesResponse->VideoSources->Resolution, 0, sizeof(struct tt__VideoResolution));trt__GetVideoSourcesResponse->VideoSources->Resolution->Width = VIDEO_WIDTH;trt__GetVideoSourcesResponse->VideoSources->Resolution->Height = VIDEO_HEIGHT;trt__GetVideoSourcesResponse->VideoSources->Framerate = FRAME_RATE;return SOAP_OK;
}SOAP_FMAC5 int SOAP_FMAC6 __trt__GetProfile(struct soap *soap, struct _trt__GetProfile *trt__GetProfile, struct _trt__GetProfileResponse *trt__GetProfileResponse)
{printf("-------- %s --------\n", __func__);trt__GetProfileResponse->Profile = (struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile));memset(trt__GetProfileResponse->Profile, 0, sizeof(struct tt__Profile));trt__GetProfileResponse->Profile->Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->Name, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->Name, "MyProfile");trt__GetProfileResponse->Profile->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->token, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->token, "ProfileToken");trt__GetProfileResponse->Profile->fixed = (enum xsd__boolean *)soap_malloc(soap, sizeof(enum xsd__boolean));*(trt__GetProfileResponse->Profile->fixed) = xsd__boolean__true_;// <VideoSourceConfiguration><name>和<VideoSourceConfiguration><token>trt__GetProfileResponse->Profile->VideoSourceConfiguration = (struct tt__VideoSourceConfiguration *)soap_malloc(soap, sizeof(struct tt__VideoSourceConfiguration));memset(trt__GetProfileResponse->Profile->VideoSourceConfiguration, 0, sizeof(struct tt__VideoSourceConfiguration));trt__GetProfileResponse->Profile->VideoSourceConfiguration->Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->VideoSourceConfiguration->Name, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->VideoSourceConfiguration->Name, "vs_name");trt__GetProfileResponse->Profile->VideoSourceConfiguration->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->VideoSourceConfiguration->token, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->VideoSourceConfiguration->token, "vs_token");trt__GetProfileResponse->Profile->VideoSourceConfiguration->SourceToken = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->VideoSourceConfiguration->SourceToken, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->VideoSourceConfiguration->SourceToken, "vs_SourceToken");trt__GetProfileResponse->Profile->VideoSourceConfiguration->UseCount = 1;// <VideoSourceConfiguration><Bounds>trt__GetProfileResponse->Profile->VideoSourceConfiguration->Bounds = (struct tt__IntRectangle *)soap_malloc(soap, sizeof(struct tt__IntRectangle));memset(trt__GetProfileResponse->Profile->VideoSourceConfiguration->Bounds, 0, sizeof(struct tt__IntRectangle));trt__GetProfileResponse->Profile->VideoSourceConfiguration->Bounds->x = 0;trt__GetProfileResponse->Profile->VideoSourceConfiguration->Bounds->y = 0;trt__GetProfileResponse->Profile->VideoSourceConfiguration->Bounds->width = VIDEO_WIDTH;trt__GetProfileResponse->Profile->VideoSourceConfiguration->Bounds->height = VIDEO_HEIGHT;// <VideoEncoderConfiguration>trt__GetProfileResponse->Profile->VideoEncoderConfiguration = (struct tt__VideoEncoderConfiguration *)soap_malloc(soap, sizeof(struct tt__VideoEncoderConfiguration));memset(trt__GetProfileResponse->Profile->VideoEncoderConfiguration, 0, sizeof(struct tt__VideoEncoderConfiguration));trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Name, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Name, "ve_name");trt__GetProfileResponse->Profile->VideoEncoderConfiguration->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->token, 0, sizeof(char) * 32);strcpy(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->token, "ve_token");trt__GetProfileResponse->Profile->VideoEncoderConfiguration->UseCount = 1;trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Encoding = tt__VideoEncoding__H264;// <VideoEncoderConfiguration><Resolution>、<RateControl>trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));memset(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Resolution, 0, sizeof(struct tt__VideoResolution));trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Resolution->Width = VIDEO_WIDTH;trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Resolution->Height = VIDEO_HEIGHT;trt__GetProfileResponse->Profile->VideoEncoderConfiguration->Quality = 10;// <VideoEncoderConfiguration><RateControl>trt__GetProfileResponse->Profile->VideoEncoderConfiguration->RateControl = (struct tt__VideoRateControl *)soap_malloc(soap, sizeof(struct tt__VideoRateControl));memset(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->RateControl, 0, sizeof(struct tt__VideoRateControl));trt__GetProfileResponse->Profile->VideoEncoderConfiguration->RateControl->FrameRateLimit = FRAME_RATE;trt__GetProfileResponse->Profile->VideoEncoderConfiguration->RateControl->EncodingInterval = 1;trt__GetProfileResponse->Profile->VideoEncoderConfiguration->RateControl->BitrateLimit = 6000;// <VideoEncoderConfiguration><H264>trt__GetProfileResponse->Profile->VideoEncoderConfiguration->H264 = (struct tt__H264Configuration *)soap_malloc(soap, sizeof(struct tt__H264Configuration));memset(trt__GetProfileResponse->Profile->VideoEncoderConfiguration->H264, 0, sizeof(struct tt__H264Configuration));trt__GetProfileResponse->Profile->VideoEncoderConfiguration->H264->GovLength = 120;trt__GetProfileResponse->Profile->VideoEncoderConfiguration->H264->H264Profile = tt__H264Profile__High;return SOAP_OK;
}SOAP_FMAC5 int SOAP_FMAC6 __trt__GetProfiles(struct soap *soap, struct _trt__GetProfiles *trt__GetProfiles, struct _trt__GetProfilesResponse *trt__GetProfilesResponse)
{printf("-------- %s --------\n", __func__);trt__GetProfilesResponse->__sizeProfiles = 1;trt__GetProfilesResponse->Profiles = (struct tt__Profile *)soap_malloc(soap, sizeof(struct tt__Profile) * trt__GetProfilesResponse->__sizeProfiles);memset(trt__GetProfilesResponse->Profiles, 0, sizeof(struct tt__Profile) * trt__GetProfilesResponse->__sizeProfiles);int i = 0;trt__GetProfilesResponse->Profiles[i].Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].Name, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].Name, "MyProfile");trt__GetProfilesResponse->Profiles[i].token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].token, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].token, "ProfileToken");// <VideoSourceConfiguration><name>trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration = (struct tt__VideoSourceConfiguration *)soap_malloc(soap, sizeof(struct tt__VideoSourceConfiguration));memset(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration, 0, sizeof(struct tt__VideoSourceConfiguration));trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Name, "vs_name");// <VideoSourceConfiguration><token>trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->token, "vs_token");trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->SourceToken, "vs_SourceToken");trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->UseCount = 1; // 表示该视频源配置的使用次数// <VideoSourceConfiguration><Bounds>trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds = (struct tt__IntRectangle *)soap_malloc(soap, sizeof(struct tt__IntRectangle));memset(trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds, 0, sizeof(struct tt__IntRectangle));trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->x = 0;trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->y = 0;trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->width = VIDEO_WIDTH;trt__GetProfilesResponse->Profiles[i].VideoSourceConfiguration->Bounds->height = VIDEO_HEIGHT;// <VideoEncoderConfiguration>trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration = (struct tt__VideoEncoderConfiguration *)soap_malloc(soap, sizeof(struct tt__VideoEncoderConfiguration));memset(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration, 0, sizeof(struct tt__VideoEncoderConfiguration));trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Name, "ve_name");trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token, 0, sizeof(char) * 32);strcpy(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->token, "ve_token");trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->UseCount = 1;                       // 表示视频编码配置的使用次数trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Encoding = tt__VideoEncoding__H264; // 视频编码格式// <VideoEncoderConfiguration><Resolution>trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution = (struct tt__VideoResolution *)soap_malloc(soap, sizeof(struct tt__VideoResolution));memset(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution, 0, sizeof(struct tt__VideoResolution));trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Width = VIDEO_WIDTH;trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Resolution->Height = VIDEO_HEIGHT;trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->Quality = 10; //  视频质量// <VideoEncoderConfiguration><RateControl>trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl = (struct tt__VideoRateControl *)soap_malloc(soap, sizeof(struct tt__VideoRateControl));memset(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl, 0, sizeof(struct tt__VideoRateControl));trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->FrameRateLimit = FRAME_RATE; // 帧率trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->EncodingInterval = 1;        // 编码间隔trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->RateControl->BitrateLimit = 3000;         // 比特率限制// <VideoEncoderConfiguration><H264>trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->H264 = (struct tt__H264Configuration *)soap_malloc(soap, sizeof(struct tt__H264Configuration));memset(trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->H264, 0, sizeof(struct tt__H264Configuration));trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->H264->GovLength = 120;                     // GOP长度trt__GetProfilesResponse->Profiles[i].VideoEncoderConfiguration->H264->H264Profile = tt__H264Profile__High; // H.264 Profilereturn SOAP_OK;
}SOAP_FMAC5 int SOAP_FMAC6 __trt__GetVideoSourceConfiguration(struct soap *soap, struct _trt__GetVideoSourceConfiguration *trt__GetVideoSourceConfiguration, struct _trt__GetVideoSourceConfigurationResponse *trt__GetVideoSourceConfigurationResponse)
{printf("-------- %s --------\n", __func__);trt__GetVideoSourceConfigurationResponse->Configuration = (struct tt__VideoSourceConfiguration *)soap_malloc(soap, sizeof(struct tt__VideoSourceConfiguration));memset(trt__GetVideoSourceConfigurationResponse->Configuration, 0, sizeof(struct tt__VideoSourceConfiguration));trt__GetVideoSourceConfigurationResponse->Configuration->UseCount = 1;trt__GetVideoSourceConfigurationResponse->Configuration->Name = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetVideoSourceConfigurationResponse->Configuration->Name, 0, sizeof(char) * 32);trt__GetVideoSourceConfigurationResponse->Configuration->token = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetVideoSourceConfigurationResponse->Configuration->token, 0, sizeof(char) * 32);strcpy(trt__GetVideoSourceConfigurationResponse->Configuration->Name, "vs_name");strcpy(trt__GetVideoSourceConfigurationResponse->Configuration->token, "vs_token");trt__GetVideoSourceConfigurationResponse->Configuration->SourceToken = (char *)soap_malloc(soap, sizeof(char) * 32);memset(trt__GetVideoSourceConfigurationResponse->Configuration->SourceToken, 0, sizeof(char) * 32);strcpy(trt__GetVideoSourceConfigurationResponse->Configuration->SourceToken, "vs_SourceToken");trt__GetVideoSourceConfigurationResponse->Configuration->Bounds = (struct tt__IntRectangle *)soap_malloc(soap, sizeof(struct tt__IntRectangle));memset(trt__GetVideoSourceConfigurationResponse->Configuration->Bounds, 0, sizeof(struct tt__IntRectangle));trt__GetVideoSourceConfigurationResponse->Configuration->Bounds->x = 0;trt__GetVideoSourceConfigurationResponse->Configuration->Bounds->y = 0;trt__GetVideoSourceConfigurationResponse->Configuration->Bounds->width = VIDEO_WIDTH;trt__GetVideoSourceConfigurationResponse->Configuration->Bounds->height = VIDEO_HEIGHT;return SOAP_OK;
}SOAP_FMAC5 int SOAP_FMAC6 __trt__GetStreamUri(struct soap *soap, struct _trt__GetStreamUri *trt__GetStreamUri, struct _trt__GetStreamUriResponse *trt__GetStreamUriResponse)
{printf("-------- %s --------\n", __func__);trt__GetStreamUriResponse->MediaUri = (struct tt__MediaUri *)soap_malloc(soap, sizeof(struct tt__MediaUri));memset(trt__GetStreamUriResponse->MediaUri, 0, sizeof(struct tt__MediaUri));trt__GetStreamUriResponse->MediaUri->Uri = (char *)soap_malloc(soap, sizeof(char) * 256);memset(trt__GetStreamUriResponse->MediaUri->Uri, 0, sizeof(char) * 256);sprintf(trt__GetStreamUriResponse->MediaUri->Uri, RTSP_URL);trt__GetStreamUriResponse->MediaUri->InvalidAfterConnect = xsd__boolean__true_;trt__GetStreamUriResponse->MediaUri->InvalidAfterReboot = xsd__boolean__true_;// 超时时间trt__GetStreamUriResponse->MediaUri->Timeout = 200;return 0;
}

参考了这个项目中的源码:onvif-server-with-rtsp

我的另一篇博客:Ubuntu 编译gSOAP库,并生成ONVIF代码框架_gsoap 生成-CSDN博客

相关资料:一个比较完善的Onvif服务端 ,不过源码要钱:happytimesoft

 


http://www.ppmy.cn/embedded/147927.html

相关文章

PyTorch实现的猫狗图像分类项

猫狗图像分类项目 这是一个使用PyTorch实现的猫狗图像分类项目。 项目结构 model.py: 定义了CNN模型结构train.py: 训练模型的脚本predict.py: 使用训练好的模型进行预测requirements.txt: 项目依赖 环境配置 创建虚拟环境&#xff08;推荐&#xff09; python -m venv v…

C# 6.0 连接elasticsearch数据库

在 C# 6.0 中连接 Elasticsearch 数据库,您可以使用官方的 Elasticsearch 客户端库 NEST。NEST 是一个高性能的 .NET 客户端,用于与 Elasticsearch 进行交互。以下是一个详细的步骤指南,帮助您在 C# 6.0 项目中连接和操作 Elasticsearch。 1. 安装 NEST 包 首先,您需要在您…

Fgui世界坐标转ui坐标的问题

在做玩家与3d物体交互的时候遇到一个问题&#xff0c;就是3d物体的世界坐标转换成Fgui的UI坐标&#xff0c;会有一点问题&#xff0c;在fgui的官方文档中是这么描述一个3d物体的世界坐标转换为fgui的ui坐标是这么描述的 这个应该是一个比较普遍的方案&#xff0c;在我的实际项目…

【线性代数】理解矩阵乘法的意义(点乘)

刚接触线性代数时&#xff0c;很不理解矩阵乘法的计算规则&#xff0c;为什么规则定义的看起来那么有规律却又莫名其妙&#xff0c;现在参考了一些资料&#xff0c;回过头重新总结下个人对矩阵乘法的理解&#xff08;严格来说是点乘&#xff09;。 理解矩阵和矩阵的乘法&#x…

siglip代码笔记

Github siglip-so400m-patch14-384 使用了SoViT-400m结构&#xff0c;SoViT &#xff1a;a shape-optimized vision transformer&#xff0c;结构参数经过试验测试得到。具体见 Getting ViT in Shape: Scaling Laws for Compute-Optimal Model Design We validate these predic…

MFC/C++学习系列之简单记录11——树控件的使用

MFC/C学习系列之简单记录11——树控件的使用 前言CTreectrl使用界面设置代码使用简单设计其他使用注意&#xff01; 总结 前言 在之前的界面设计中使用得很少&#xff0c;但是可以学习一下&#xff0c;以备不时之需&#xff01; CTreectrl使用 界面设置 在工具箱中选择Tree C…

数据结构—图

目录 一、图的定义 二、图的基本概念和术语 2.1有向图 2.2无向图 2.3简单图 2.4多重图 2.5完全图 2.6子图 2.7连通、连通图和连通分量 2.8强连通图、强联通分量 2.9生成树&#xff0c;生成森林 2.10顶点的度、入度和出度 2.11边的权和网 2.12稠密图、稀疏图 2.1…

【docker】容器编排之docker swarm

Docker Swarm容器编排详细讲解 Docker Swarm是Docker的原生容器编排工具&#xff0c;它通过将多个Docker引擎组合成一个集群来实现高效的容器部署和管理。 Swarm提供了服务发现、负载均衡、扩展、自动恢复等功能&#xff0c;能够让开发者和运维人员以更简便的方式管理容器化应…