GB28181上级平台接入下级平台

最近在搞gb28181平台接入,记录下吧,github找的demo,看了下流程,发现下级平台注册和ipc注册是一样的,不过就是catalog 不一样

外部库

使用了mxml 读取body,sip协议库,等等

流程demo

别的不说,直接代码吧,注释只是简单的写写流程

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <eXosip2/eXosip.h>
#include "cJSON.h"
#include "mxml.h"
#include "HTTPDigest.h"
#include "mediaServer.h"
#include "pstream.h"liveVideoStreamParams g_liveVideoParams;
//注册回复200
static void RegisterSuccess(struct eXosip_t * peCtx,eXosip_event_t *je)
{int iReturnCode = 0 ;osip_message_t * pSRegister = NULL;iReturnCode = eXosip_message_build_answer (peCtx,je->tid,200,&pSRegister);if ( iReturnCode == 0 && pSRegister != NULL ){eXosip_lock(peCtx);eXosip_message_send_answer (peCtx,je->tid,200,pSRegister);eXosip_unlock(peCtx);//osip_message_free(pSRegister);}
}
//注册失败
void RegisterFailed(struct eXosip_t * peCtx,eXosip_event_t *je) {int iReturnCode = 0 ;osip_message_t * pSRegister = NULL;iReturnCode = eXosip_message_build_answer (peCtx,je->tid,401,&pSRegister);if ( iReturnCode == 0 && pSRegister != NULL ){eXosip_lock(peCtx);eXosip_message_send_answer (peCtx,je->tid,401,pSRegister);eXosip_unlock(peCtx);}
}
//配置文件解析
static int doParaseJson(char *buf) {int i;cJSON * root = cJSON_Parse(buf);if(root != NULL) {cJSON * pSubRoot = cJSON_GetObjectItem(root, "gb28181");if(pSubRoot != NULL) {cJSON * pSub = cJSON_GetObjectItem(pSubRoot, "platform_id");if(pSub != NULL) {APP_DEBUG("platform_id:%s", pSub->valuestring);strncpy(g_liveVideoParams.gb28181Param.platformSipId, pSub->valuestring, 256);}pSub = cJSON_GetObjectItem(pSubRoot, "platform_port");if(pSub != NULL) {APP_DEBUG("platform_port:%d", pSub->valueint);g_liveVideoParams.gb28181Param.platformSipPort = pSub->valueint;}pSub = cJSON_GetObjectItem(pSubRoot, "platform_ip");if(pSub != NULL) {APP_DEBUG("platform_ip:%s", pSub->valuestring);strncpy(g_liveVideoParams.gb28181Param.platformIpAddr, pSub->valuestring, 128);}pSub = cJSON_GetObjectItem(pSubRoot, "local_id");if(pSub != NULL) {APP_DEBUG("local_id:%s", pSub->valuestring);strncpy(g_liveVideoParams.gb28181Param.localSipId, pSub->valuestring, 256);}pSub = cJSON_GetObjectItem(pSubRoot, "local_port");if(pSub != NULL) {APP_DEBUG("local_port:%d", pSub->valueint);g_liveVideoParams.gb28181Param.localSipPort = pSub->valueint;}pSub = cJSON_GetObjectItem(pSubRoot, "local_ip");if(pSub != NULL) {APP_DEBUG("local_ip:%s", pSub->valuestring);strncpy(g_liveVideoParams.gb28181Param.localIpAddr, pSub->valuestring, 128);}}else {APP_ERR("err");}cJSON *pSub = cJSON_GetObjectItem(root, "camera_num");if(pSub != NULL) {APP_DEBUG("camera_num:%d", pSub->valueint);g_liveVideoParams.cameraNum = pSub->valueint;if(g_liveVideoParams.cameraNum > 0 && g_liveVideoParams.cameraNum < CAMERA_SUPPORT_MAX) {g_liveVideoParams.pCameraParams = (CameraParams *)malloc(sizeof(CameraParams)*g_liveVideoParams.cameraNum);if(g_liveVideoParams.pCameraParams == NULL) {APP_ERR("malloc failed");return -1;}memset(g_liveVideoParams.pCameraParams, 0, sizeof(CameraParams)*g_liveVideoParams.cameraNum);CameraParams *p;char cameraName[32];for(i = 0; i < g_liveVideoParams.cameraNum; i ++) {p = g_liveVideoParams.pCameraParams + i;snprintf(cameraName, 32, "camera%d_sip_id", i + 1);pSub = cJSON_GetObjectItem(root, cameraName);if(pSub != NULL) {APP_DEBUG("%s:%s", cameraName, pSub->valuestring);strncpy(p->sipId, pSub->valuestring, 256);}else {APP_WARRING("get json failed, %s", cameraName);}snprintf(cameraName, 32, "camera%d_recv_port", i + 1);pSub = cJSON_GetObjectItem(root, cameraName);if(pSub != NULL) {APP_DEBUG("%s:%d", cameraName, pSub->valueint);p->recvPort = pSub->valueint;}else {APP_WARRING("get json failed, %s", cameraName);}}}else {APP_WARRING("err cameraNum : %d", g_liveVideoParams.cameraNum);}}cJSON_Delete(root);}else {APP_ERR("err, buf:%s", buf);}return 0;
}static int initParams(char *jsonCfgFile) {char *buf = NULL;memset(&g_liveVideoParams, 0, sizeof(g_liveVideoParams));FILE *fp = fopen(jsonCfgFile, "rb");if(fp != NULL) {fseek(fp, 0L, SEEK_END);int cfgSie = ftell(fp);fseek(fp, 0L, SEEK_SET);buf = (char *)malloc(cfgSie/1024*1024 + 1024);if(buf == NULL) {APP_ERR("malloc failed");goto err;}if(fread(buf, 1, cfgSie, fp)) {}doParaseJson(buf);}else {APP_ERR("fopen %s failed", jsonCfgFile);}g_liveVideoParams.gb28181Param.SN = 1;g_liveVideoParams.gb28181Param.call_id = -1;g_liveVideoParams.gb28181Param.dialog_id = -1;g_liveVideoParams.gb28181Param.registerOk = 0;err:if(buf != NULL) {free(buf);}if(fp != NULL) {fclose(fp);}return 0;
}static void *MainProcess(gb28181Params *p28181Params, void * pvSClientGB) {char *p;int keepAliveFlag = 0;struct eXosip_t * peCtx = (struct eXosip_t *)pvSClientGB;while(p28181Params->running) {eXosip_event_t *je = NULL;je = eXosip_event_wait (peCtx, 0, 4);if (je == NULL) {osip_usleep(100000);continue;}switch (je->type) {case EXOSIP_MESSAGE_NEW:{//printf("new msg method:%s\n", je->request->sip_method);if(MSG_IS_REGISTER(je->request)) {APP_DEBUG("recv Register");g_liveVideoParams.gb28181Param.registerOk = 1;}else if(MSG_IS_MESSAGE(je->request)){osip_body_t *body = NULL;osip_message_get_body(je->request, 0, &body);if(body != NULL) {p = strstr(body->body, "Keepalive");if(p != NULL) {if(keepAliveFlag == 0) {printf("msg body:%s\n", body->body);keepAliveFlag = 1;g_liveVideoParams.gb28181Param.registerOk = 1;}}else {printf("msg body:%s\n", body->body);}}else {APP_ERR("get body failed");}}else if(strncmp(je->request->sip_method, "BYE", 4) != 0){APP_WARRING("unsupport new msg method : %s", je->request->sip_method);}RegisterSuccess(peCtx, je);}break;case EXOSIP_MESSAGE_ANSWERED:{printf("answered method:%s\n", je->request->sip_method);RegisterSuccess(peCtx, je);}break;case EXOSIP_CALL_ANSWERED:{osip_message_t *ack=NULL;p28181Params->call_id = je->cid;p28181Params->dialog_id = je->did;printf("call answered method:%s, call_id:%d, dialog_id:%d\n", je->request->sip_method, p28181Params->call_id, p28181Params->dialog_id);eXosip_call_build_ack(peCtx, je->did, &ack);eXosip_lock(peCtx);eXosip_call_send_ack(peCtx, je->did, ack);eXosip_unlock(peCtx);}break;case EXOSIP_CALL_PROCEEDING:{printf("recv EXOSIP_CALL_PROCEEDING\n");RegisterSuccess(peCtx, je);}break;case EXOSIP_CALL_REQUESTFAILURE:{printf("recv EXOSIP_CALL_REQUESTFAILURE\n");RegisterSuccess(peCtx, je);}break;case EXOSIP_CALL_MESSAGE_ANSWERED:{printf("recv EXOSIP_CALL_MESSAGE_ANSWERED\n");RegisterSuccess(peCtx, je);}break;case EXOSIP_CALL_RELEASED:{printf("recv EXOSIP_CALL_RELEASED\n");RegisterSuccess(peCtx, je);}break;case EXOSIP_CALL_CLOSED:{printf("recv EXOSIP_CALL_CLOSED\n");RegisterSuccess(peCtx, je);}break;case EXOSIP_CALL_MESSAGE_NEW:{printf("recv EXOSIP_CALL_MESSAGE_NEW\n");RegisterSuccess(peCtx, je);}break;default:{printf("##test,%s:%d, unsupport type:%d\n", __FILE__, __LINE__, je->type);RegisterSuccess(peCtx, je);}break;}eXosip_event_free(je);}return NULL;
}
//接收下级平台 stream init
int init_udpsocket(int port, struct sockaddr_in *servaddr, char *mcast_addr) {int err = -1;int socket_fd;                                      socket_fd = socket(AF_INET, SOCK_DGRAM, 0);    if (socket_fd < 0 ) {APP_ERR("socket failed, port:%d", port);return -1;}  memset(servaddr, 0, sizeof(struct sockaddr_in));servaddr->sin_family     = AF_INET;servaddr->sin_addr.s_addr  = htonl(INADDR_ANY);servaddr->sin_port         = htons(port);err = bind(socket_fd,(struct sockaddr*)servaddr, sizeof(struct sockaddr_in)) ;if(err < 0) {APP_ERR("bind failed, port:%d", port);return -2;}/*set enable MULTICAST LOOP */                                       int loop = 1;err = setsockopt(socket_fd,IPPROTO_IP, IP_MULTICAST_LOOP,&loop, sizeof(loop));if(err < 0) {APP_ERR("setsockopt IP_MULTICAST_LOOP failed, port:%d", port);return -3;}return socket_fd;
}void release_udpsocket(int socket_fd, char *mcast_addr) {close(socket_fd);
}int inline ProgramStreamPackHeader(char* Pack, int length, char **NextPack, int *leftlength) {//printf("[%s]%x %x %x %x\n", __FUNCTION__, Pack[0], Pack[1], Pack[2], Pack[3]);//通过 00 00 01 ba头的第14个字节的最后3位来确定头部填充了多少字节program_stream_pack_header *PsHead = (program_stream_pack_header *)Pack;unsigned char pack_stuffing_length = PsHead->stuffinglen & '\x07';*leftlength = length - sizeof(program_stream_pack_header) - pack_stuffing_length;//减去头和填充的字节*NextPack = Pack+sizeof(program_stream_pack_header) + pack_stuffing_length;if(*leftlength<4) return 0;return *leftlength;
}inline int ProgramStreamMap(char* Pack, int length, char **NextPack, int *leftlength, char **PayloadData, int *PayloadDataLen)
{program_stream_map* PSMPack = (program_stream_map*)Pack;//no payload*PayloadData = 0;*PayloadDataLen = 0;if((unsigned int)length < sizeof(program_stream_map)) return 0;littel_endian_size psm_length;psm_length.byte[0] = PSMPack->PackLength.byte[1];psm_length.byte[1] = PSMPack->PackLength.byte[0];*leftlength = length - psm_length.length - sizeof(program_stream_map);if(*leftlength<=0) return 0;*NextPack = Pack + psm_length.length + sizeof(program_stream_map);return *leftlength;
}inline int ProgramShHead(char* Pack, int length, char **NextPack, int *leftlength, char **PayloadData, int *PayloadDataLen) {program_stream_map* PSMPack = (program_stream_map*)Pack;//no payload*PayloadData = 0;*PayloadDataLen = 0;if((unsigned int)length < sizeof(program_stream_map)) return 0;littel_endian_size psm_length;psm_length.byte[0] = PSMPack->PackLength.byte[1];psm_length.byte[1] = PSMPack->PackLength.byte[0];*leftlength = length - psm_length.length - sizeof(program_stream_map);if(*leftlength<=0) return 0;*NextPack = Pack + psm_length.length + sizeof(program_stream_map);return *leftlength;
}inline int Pes(char* Pack, int length, char **NextPack, int *leftlength, char **PayloadData, int *PayloadDataLen)
{program_stream_e* PSEPack = (program_stream_e*)Pack;*PayloadData = 0;*PayloadDataLen = 0;if((unsigned int)length < sizeof(program_stream_e)) return 0;littel_endian_size pse_length;pse_length.byte[0] = PSEPack->PackLength.byte[1];pse_length.byte[1] = PSEPack->PackLength.byte[0];*PayloadDataLen = pse_length.length - 2 - 1 - PSEPack->stuffing_length;if(*PayloadDataLen>0) *PayloadData = Pack + sizeof(program_stream_e) + PSEPack->stuffing_length;*leftlength = length - pse_length.length - sizeof(pack_start_code) - sizeof(littel_endian_size);if(*leftlength<=0) return 0;*NextPack = Pack + sizeof(pack_start_code) + sizeof(littel_endian_size) + pse_length.length;return *leftlength;
}int inline GetH246FromPs(char* buffer,int length, char *h264Buffer, int *h264length, char *sipId) {int leftlength = 0;char *NextPack = 0;*h264length = 0;if(ProgramStreamPackHeader(buffer, length, &NextPack, &leftlength)==0)return 0;char *PayloadData=NULL; int PayloadDataLen=0;while((unsigned int)leftlength >= sizeof(pack_start_code)) {PayloadData=NULL;PayloadDataLen=0;if(NextPack && NextPack[0]=='\x00' && NextPack[1]=='\x00' && NextPack[2]=='\x01' && NextPack[3]=='\xE0') {//接着就是流包,说明是非i帧if(Pes(NextPack, leftlength, &NextPack, &leftlength, &PayloadData, &PayloadDataLen)) {if(PayloadDataLen) {if(PayloadDataLen + *h264length < H264_FRAME_SIZE_MAX) {memcpy(h264Buffer, PayloadData, PayloadDataLen);h264Buffer += PayloadDataLen;*h264length += PayloadDataLen;}else {APP_WARRING("h264 frame size exception!! %d:%d", PayloadDataLen, *h264length);}}}else {if(PayloadDataLen) {if(PayloadDataLen + *h264length < H264_FRAME_SIZE_MAX) {memcpy(h264Buffer, PayloadData, PayloadDataLen);h264Buffer += PayloadDataLen;*h264length += PayloadDataLen;}else {APP_WARRING("h264 frame size exception!! %d:%d", PayloadDataLen, *h264length);}}break;}}else if(NextPack && NextPack[0]=='\x00' && NextPack[1]=='\x00'&& NextPack[2]=='\x01'&& NextPack[3]=='\xBB') {if(ProgramShHead(NextPack, leftlength, &NextPack, &leftlength, &PayloadData, &PayloadDataLen)==0)break;}else if(NextPack && NextPack[0]=='\x00' && NextPack[1]=='\x00'&& NextPack[2]=='\x01'&& NextPack[3]=='\xBC') {if(ProgramStreamMap(NextPack, leftlength, &NextPack, &leftlength, &PayloadData, &PayloadDataLen)==0)break;}else if(NextPack && NextPack[0]=='\x00' && NextPack[1]=='\x00'&& NextPack[2]=='\x01'&& (NextPack[3]=='\xC0' || NextPack[3]=='\xBD')) {//printf("audio ps frame, skip it\n");break;}else {printf("[%s]no know %x %x %x %x\n", sipId, NextPack[0], NextPack[1], NextPack[2], NextPack[3]);break;}}return *h264length;
}static void *rtp_recv_thread(void *arg) {int socket_fd;CameraParams *p = (CameraParams *)arg;int rtp_port = p->recvPort;struct sockaddr_in servaddr;socket_fd = init_udpsocket(rtp_port, &servaddr, NULL);if(socket_fd >= 0) {//printf("start socket port %d success\n", rtp_port);}unsigned char *buf = (unsigned char *)malloc(RTP_MAXBUF);if(buf == NULL) {APP_ERR("malloc failed buf");return NULL;}unsigned char *psBuf = (unsigned char *)malloc(PS_BUF_SIZE);if(psBuf == NULL) {APP_ERR("malloc failed");return NULL;}char *h264buf = (char *)malloc(H264_FRAME_SIZE_MAX);if(h264buf == NULL) {APP_ERR("malloc failed");return NULL;}int recvLen;int addr_len = sizeof(struct sockaddr_in);                                                        int rtpHeadLen = sizeof(RTP_header_t);char filename[128];snprintf(filename, 128, "%s.264", p->sipId);p->fpH264 = fopen(filename, "wb");if(p->fpH264 == NULL) {APP_ERR("fopen %s failed", filename);return NULL;}APP_DEBUG("%s:%d starting ...", p->sipId, p->recvPort);int cnt = 0;int rtpPsLen, h264length, psLen = 0;unsigned char *ptr;memset(buf, 0, RTP_MAXBUF); while(p->running) {recvLen = recvfrom(socket_fd, buf, RTP_MAXBUF, 0, (struct sockaddr*)&servaddr, (socklen_t*)&addr_len);if(recvLen > rtpHeadLen) {ptr = psBuf + psLen;rtpPsLen = recvLen - rtpHeadLen;if(psLen + rtpPsLen < PS_BUF_SIZE) {memcpy(ptr, buf + rtpHeadLen, rtpPsLen);}else {APP_WARRING("psBuf memory overflow, %d\n", psLen + rtpPsLen);psLen = 0;continue;}if(ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x01 && ptr[3] == 0xBA && psLen > 0) {if(cnt % 10000 == 0) {printf("rtpRecvPort:%d, cnt:%d, pssize:%d\n", rtp_port, cnt ++, psLen);}if(cnt % 25 == 0) {p->status = 1;}GetH246FromPs((char *)psBuf, psLen, h264buf, &h264length, p->sipId);if(h264length > 0) {fwrite(h264buf, 1, h264length, p->fpH264);}memcpy(psBuf, ptr, rtpPsLen);psLen = 0;cnt ++;}psLen += rtpPsLen;}else {perror("recvfrom()");}if(recvLen > 1500) {printf("udp frame exception, %d\n", recvLen);}}release_udpsocket(socket_fd, NULL);  if(buf != NULL) {free(buf);}if(psBuf != NULL) {free(psBuf);}if(h264buf != NULL) {free(h264buf);}if(p->fpH264 != NULL) {fclose(p->fpH264);p->fpH264 = NULL;}APP_DEBUG("%s:%d run over", p->sipId, p->recvPort);return NULL;
}static void *stream_keep_alive_thread(void *arg) {int socket_fd;CameraParams *p = (CameraParams *)arg;int rtcp_port = p->recvPort + 1;struct sockaddr_in servaddr;struct timeval tv;socket_fd = init_udpsocket(rtcp_port, &servaddr, NULL);if(socket_fd >= 0) {//printf("start socket port %d success\n", rtcp_port);}unsigned char *buf = (unsigned char *)malloc(1024);if(buf == NULL) {APP_ERR("malloc failed buf");return NULL;}int recvLen;int addr_len = sizeof(struct sockaddr_in);                                                        APP_DEBUG("%s:%d starting ...", p->sipId, rtcp_port);memset(buf, 0, 1024); while(p->running) {recvLen = recvfrom(socket_fd, buf, 1024, 0, (struct sockaddr*)&servaddr, (socklen_t*)&addr_len);if(recvLen > 0) {//printf("stream_keep_alive_thread, rtcp_port %d, recv %d bytes\n", rtcp_port, recvLen);recvLen = sendto(socket_fd, buf, recvLen, 0, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in));if(recvLen <= 0) {APP_ERR("sendto %d failed", rtcp_port);}}else {perror("recvfrom()");}gettimeofday(&tv, NULL);}release_udpsocket(socket_fd, NULL);   if(buf != NULL) {free(buf);}APP_DEBUG("%s:%d run over", p->sipId, rtcp_port);return NULL;
}static int startStreamRecv(liveVideoStreamParams *pliveVideoParams) {int i;pthread_t pid;CameraParams *p;for(i = 0; i < pliveVideoParams->cameraNum; i ++) {p = pliveVideoParams->pCameraParams + i;p->statusErrCnt = 0;p->running = 1;if(pthread_create(&pid, NULL, rtp_recv_thread, p) != 0) {APP_ERR("pthread_create rtp_recv_thread err, %s:%d", p->sipId, p->recvPort);}else {pthread_detach(pid);}if(pthread_create(&pid, NULL, stream_keep_alive_thread, p) != 0) {APP_ERR("pthread_create stream_keep_alive_thread err, %s:%d", p->sipId, p->recvPort + 1);}else {pthread_detach(pid);}}return 0;
}static void *gb28181ServerThread(void *arg) {int iReturnCode = 0;struct eXosip_t *eCtx;gb28181Params *p28181Params = (gb28181Params *)(arg);eCtx = eXosip_malloc();iReturnCode = eXosip_init (eCtx);if (iReturnCode != OSIP_SUCCESS ) {APP_ERR("Can't initialize eXosip!");return NULL;}else {printf("eXosip_init successfully!\n");}iReturnCode = eXosip_listen_addr (eCtx, IPPROTO_UDP, NULL, p28181Params->localSipPort, AF_INET, 0);if(iReturnCode !=  OSIP_SUCCESS) {APP_ERR("eXosip_listen_addr error!");return NULL;}p28181Params->eCtx = eCtx;MainProcess(p28181Params, eCtx);eXosip_quit(eCtx);osip_free(eCtx);eCtx = NULL;p28181Params->eCtx = NULL;APP_DEBUG("%s run over", __func__);return 0;
}static int sendInvitePlay(char *playSipId, int rtp_recv_port, gb28181Params *p28181Params) {char dest_call[256], source_call[256], subject[128];osip_message_t *invite=NULL;int ret;struct eXosip_t *peCtx = p28181Params->eCtx;snprintf(dest_call, 256, "sip:%s@%s:%d", playSipId, p28181Params->platformIpAddr, p28181Params->platformSipPort);snprintf(source_call, 256, "sip:%s@%s", p28181Params->localSipId, p28181Params->localIpAddr);snprintf(subject, 128, "%s:0,%s:0", playSipId, p28181Params->localSipId);ret = eXosip_call_build_initial_invite(peCtx, &invite, dest_call, source_call, NULL, subject);if(ret != 0) {APP_ERR("eXosip_call_build_initial_invite failed, %s,%s,%s", dest_call, source_call, subject);return -1;}char body[2048];int bodyLen = snprintf(body, 2048, "v=0\r\n""o=%s 0 0 IN IP4 %s\r\n""s=Play\r\n""c=IN IP4 %s\r\n""t=0 0\r\n""m=video %d RTP/AVP 96 97 98\r\n""a=rtpmap:96 PS/90000\r\n""a=rtpmap:97 MPEG4/90000\r\n""a=rtpmap:98 H264/90000\r\n""a=recvonly\r\n", playSipId, p28181Params->localIpAddr,p28181Params->localIpAddr, rtp_recv_port);osip_message_set_body(invite, body, bodyLen);// invite 我选择的zl,这个demo的ps 保存文件h264部分写的有问题,业务没用到我也没修改osip_message_set_content_type(invite, "APPLICATION/SDP");eXosip_lock(peCtx);eXosip_call_send_initial_invite(peCtx, invite);eXosip_unlock(peCtx);return 0;
}static int sendPlayBye(gb28181Params *p28181Params) {struct eXosip_t *peCtx = p28181Params->eCtx;eXosip_lock(peCtx);eXosip_call_terminate(peCtx, p28181Params->call_id, p28181Params->dialog_id);eXosip_unlock(peCtx);return 0;
}static int startCameraRealStream(liveVideoStreamParams *pliveVideoParams) {int i;CameraParams *p;for(i = 0; i < pliveVideoParams->cameraNum; i ++) {p = pliveVideoParams->pCameraParams + i;sendInvitePlay(p->sipId, p->recvPort, &(pliveVideoParams->gb28181Param));}return 0;
}//TODO : save call_id and dialog_id for play bye?
static int stopCameraRealStream(liveVideoStreamParams *pliveVideoParams) {int i, tryCnt;CameraParams *p;gb28181Params *p28181Params = &(pliveVideoParams->gb28181Param);for(i = 0; i < pliveVideoParams->cameraNum; i ++) {p = pliveVideoParams->pCameraParams + i;p28181Params->call_id = -1;sendInvitePlay(p->sipId, p->recvPort, p28181Params);tryCnt = 10;while(tryCnt-- > 0) {if(p28181Params->call_id != -1) {break;}usleep(100000);}if(p28181Params->call_id == -1) {APP_WARRING("exception wait call_id:%d, %s", p28181Params->call_id, p->sipId);}sendPlayBye(p28181Params);p->running = 0;}return 0;
}static int checkCameraStatus(liveVideoStreamParams *pliveVideoParams) {int i;CameraParams *p;gb28181Params *p28181Params = &(pliveVideoParams->gb28181Param);for(i = 0; i < pliveVideoParams->cameraNum; i ++) {p = pliveVideoParams->pCameraParams + i;if(p->status == 0) {p->statusErrCnt ++;if(p->statusErrCnt % 10 == 0) {APP_WARRING("camera %s is exception, restart it", p->sipId);p28181Params->call_id = -1;sendInvitePlay(p->sipId, p->recvPort, p28181Params);p->statusErrCnt = 0;}}else {p->statusErrCnt = 0;p->status = 0;}}return 0;
}static int stopStreamRecv(liveVideoStreamParams *pliveVideoParams) {int i;CameraParams *p;for(i = 0; i < pliveVideoParams->cameraNum; i ++) {p = pliveVideoParams->pCameraParams + i;p->running = 0;}return 0;
}const char *whitespace_cb(mxml_node_t *node, int where) {return NULL;
}static int sendQueryCatalog(gb28181Params *p28181Params) {char sn[32];int ret;mxml_node_t *tree, *query, *node;struct eXosip_t *peCtx = p28181Params->eCtx;char *deviceId = p28181Params->platformSipId;tree = mxmlNewXML("1.0");if(tree != NULL) {query = mxmlNewElement(tree, "Query");if(query != NULL) {char buf[256] = {0};char dest_call[256], source_call[256];node = mxmlNewElement(query, "CmdType");mxmlNewText(node, 0, "Catalog");node = mxmlNewElement(query, "SN");snprintf(sn, 32, "%d", p28181Params->SN++);mxmlNewText(node, 0, sn);node = mxmlNewElement(query, "DeviceID");mxmlNewText(node, 0, deviceId);mxmlSaveString(tree, buf, 256, whitespace_cb);//printf("send query catalog:%s\n", buf);osip_message_t *message = NULL;snprintf(dest_call, 256, "sip:%s@%s:%d", p28181Params->platformSipId, p28181Params->platformIpAddr, p28181Params->platformSipPort);snprintf(source_call, 256, "sip:%s@%s", p28181Params->localSipId, p28181Params->localIpAddr);ret = eXosip_message_build_request(peCtx, &message, "MESSAGE", dest_call, source_call, NULL);if(ret == 0 && message != NULL) {osip_message_set_body(message, buf, strlen(buf));osip_message_set_content_type(message,"Application/MANSCDP+xml");eXosip_lock(peCtx);eXosip_message_send_request(peCtx, message);eXosip_unlock(peCtx);APP_DEBUG("xml:%s, dest_call:%s, source_call:%s, ok", buf, dest_call, source_call);}else {APP_ERR("eXosip_message_build_request failed");}}else {APP_ERR("mxmlNewElement Query failed");}mxmlDelete(tree);}else {APP_ERR("mxmlNewXML failed");}return 0;
}int main(int argc, char *argv[]) {pthread_t pid;APP_DEBUG("Built: %s %s, liveVideoStream starting ...", __TIME__, __DATE__);initParams((char *)GB28181_CFG_FILE);//配置文件读取g_liveVideoParams.running = 1;g_liveVideoParams.gb28181Param.running = 1;if(pthread_create(&pid, NULL, gb28181ServerThread, &(g_liveVideoParams.gb28181Param)) != 0) {APP_ERR("pthread_create gb28181ServerThread err");}else {pthread_detach(pid);}int tmpCnt = 20;while((!g_liveVideoParams.gb28181Param.registerOk) && (tmpCnt > 0)) {printf("waiting register %d...\n", tmpCnt --);sleep(1);}sendQueryCatalog(&(g_liveVideoParams.gb28181Param));//获取下级平台所有设备startStreamRecv(&g_liveVideoParams);sleep(1);startCameraRealStream(&g_liveVideoParams);while(g_liveVideoParams.running) {checkCameraStatus(&g_liveVideoParams);sleep(2);}g_liveVideoParams.running = 0;stopCameraRealStream(&g_liveVideoParams);usleep(300000);stopStreamRecv(&g_liveVideoParams);g_liveVideoParams.gb28181Param.running = 0;sleep(1);APP_DEBUG("liveVideoStream run over");return 0;
}

这是资源我只是简单的修改了一下,还是推荐自己解一下ps 流,或者使用srs 或zl

添加链接描述

GB28181上级平台接入下级平台相关推荐

  1. 阿里开放平台接入——开放平台注册与API调用

    文章目录 1.背景 2.注册账户 3.获取key 4.能力列表 5.开发文档 6.获取SDK 7.注意事项 8.实在搞不定了点我 1.背景 目前对于大部分使用开放平台提供的技术开发应用的开发者而言,开 ...

  2. EasyCVR视频融合共享平台作为国标上级平台接入紫光华智云平台的流程解析

    当前,新基建的时代浪潮之下,人类社会正加速迈入一个数字化.智能化的崭新时代,转型升级的号角吹向百行百业,正在成为时代主旋律.对于银行机构而言,人工智能.5G通信.云计算.区块链等前沿技术的发展,将成为 ...

  3. GB28181 下级平台(设备)实现

    GB28181 下级平台(设备)实现 本文主要介绍GB28181 下级平台(设备)实现的基本内容,适合初入门同学,老司机可略过. 首先需要知道GB28181 上.下级关系,比如两个平台A和B,如B需要 ...

  4. LiveGBS国标GB/T28181流媒体平台接入GB28181设备作为下级支持级联到共享到海康大华宇视等第三方国标平台支持对接政务公安内网国标视频平台

    LiveGBS国标GB/T28181流媒体平台接入GB28181设备作为下级支持级联到共享到海康大华宇视等第三方国标平台支持对接政务公安内网国标视频平台 1.什么是GB/T28181级联 2.搭建GB ...

  5. LiveGBS流媒体平台GB/T28181功能-作为上级平台对接海康大华华为宇视等下级平台监控摄像机NVR硬件执法仪等GB28181设备

    LiveGBS作为上级平台对接海康大华华为宇视等下级平台监控摄像机NVR硬件执法仪等GB28181设备 1.背景说明 2.部署国标平台 2.1.安装使用说明 2.2.服务器网络环境 2.3.信令服务配 ...

  6. LiveGBS流媒体平台国标GB/T28181功能-国标流媒体服务平台作为上级接入海康大华华为宇视等下级平台及摄像头

    LiveGBS国标流媒体服务平台作为上级接入海康大华华为宇视等下级平台及摄像头 1.背景说明 2.部署国标平台 2.1.安装使用说明 2.2.服务器网络环境 2.3.信令服务配置 3.监控摄像头设备接 ...

  7. LiveGBS流媒体平台国标GB/T28181作为上级平台对接海康大华华为宇视等下级平台硬件NVR监控摄像机

    LiveGBS流媒体平台国标GB/T28181作为上级平台对接海康.大华.华为.宇视等下级平台NVR硬件监控摄像机 1.背景说明 2.部署国标平台 2.1.安装使用说明 2.2.服务器网络环境 2.3 ...

  8. 下级平台科达录像机级联接入EasyCVR出现字段报错是什么原因?

    安防市场的不断高清化.智能化,推动了视频监控技术与监控平台的升级.智能化设备产生的海量数据,也促使平台朝着综合化.网格化.集成化方向的发展.EasyCVR具备较强的视频能力,可支持海量设备接入.汇聚与 ...

  9. 城市消防项目采用宇视平台接入国标GB28181协议国标视频平台EasyGBS设备过多时应如何解决?

    目前我们TSINGSEE青犀视频团队和很多城市的消防平台都又对接项目,大部分的消防平台都是国标GB28181协议的前端设备,因此很多项目使用的是我们的EasyGBS视频平台. TSINGSEE青犀视频 ...

最新文章

  1. a类不确定度计算器_统统帮您搞定:LIMS系统,换版、内审、期间核查、不确定度、数据分析…………...
  2. docker 外部连接_使用外部网络连接Docker容器
  3. JavaScript 开发进阶:理解 JavaScript 作用域和作用域链(上)
  4. win11 wsl及ubuntu设置为wsl 2
  5. springboot读取json文件_SpringBoot:配置文件属性读取
  6. gps有几个轨道面_嫦五“一脚刹车”,进了环月轨道
  7. URL 路径长度限制(错误:指定的文件或文件夹名称太长)
  8. 郫都区计算机学校,成都郫县好升学的计算机学校有哪些
  9. 私藏的开发过程中的那些基类
  10. [Android 新特性] 有史来最大改变 Android 5.0十大新特性
  11. Jmeter远程启动负载机
  12. HCIE-RS面试--STP选举原理,状态机和接口角色
  13. cad2016批量修改相关字体,统一文字样式
  14. CorelDRAW2022下载附带序列号安装教程
  15. Allegro PCB多层板中负片热风焊盘的制作以及flash的添加
  16. 北京政协:电子垃圾回收是亟待破解的难题
  17. Java求解N皇后问题
  18. 利用APPium获取自动浏览获取喵币
  19. 计算机经常无法打印机,为什么我电脑连接打印机老是出现这种情况~重启也不行...
  20. 【网络安全】网络安全的重要性你知道吗?

热门文章

  1. 非全日制大专怎么考全日制本科
  2. 计算机冷知识科普,【科普冷知识】有趣的8个科学冷知识,让你大吃一惊
  3. Re: 什么是OO思想
  4. 话题情感混合模型(JST)
  5. ICN(Information centric networking)体系结构和技术实现
  6. 橘色超漂亮滑动二级导航菜单
  7. vps mysql卸载_MySQL数据库卸载的完整步骤
  8. Web前端期末大作业-生鲜商城平台公司网站网页设计(HTML+CSS+JS)
  9. Spring AOP中定义切点PointCut详解
  10. 名词解释第七十讲:基金会