创作人QQ:851301776,邮箱:lfr890207@163.com,欢迎大家一起技术交流,本博客主要是自己学习的心得体会,只为每天进步一点点!
个人座右铭:
1.没有横空出世,只要厚积一定发。
2.你可以学历不高,你可以不上学,但你不能不学习
这里主要是以测试实现功能为准则,并没有进一步的整理和优化,测试完成功能后,后期项目进行整理。
ONVIF网上介绍的很多,还有很多对实现进行介绍的,这里不做介绍,网上很多的获取设备能力、获取音视频数据等都有,这里主要贴云台控制。
二、绝对移动 1.或者云台地址ONVIF_GetCapabilities(DeviceXAddr, ptzXAddr);
2.获取配置文件tokenONVIF_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;
}
这个需要根据摄像头了,我这边已经实现,但是获取回来的状态有问题
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;
}
}
其他的没什么难度了,比如获取时间之类的



