GB28181 protocol -- real time video and audio on demand (Preview)

1. Basic requirements

According to the description of real-time video and audio on demand in Chapter 9 of GB/T 28181-2016, its contents are as follows:

  • SIP messages of real-time video and audio on demand shall be routed and forwarded through SIP servers in this domain or other domains, and the real-time video and audio stream of the target device shall be forwarded through media servers in this domain.
  • Real time video and audio on demand adopts the Invite method in SIP protocol (IETF RFC3261) to realize session connection, and adopts RTP/RTCP
    The protocol (IETF RFC3550) realizes media transmission.

2. Basic process

The real-time video and audio on demand process initiated by the client is shown in the figure below:

Among them, signaling 1, 8, 9, 10, 11 and 12 are the media stream signaling process between the media stream receiver and the media server through B2BUA proxy after the SIP server receives the call request from the client, and signaling 2-7 is the media stream signaling process between the media server and the media stream sender through three-party call control, Signaling 13 ~ 16 is the media stream signaling process for the media stream receiver to disconnect from the media server, and signaling 17 ~ 20 is the media stream signaling process for the SIP server to disconnect from the media server and the media stream sender.
The command flow is described as follows:

  • The media stream receiver sends an Invite message to the SIP server. The Subject field is carried in the message header field, indicating the video source ID, sender media stream serial number, media stream receiver ID, receiver media stream serial number and other parameters of on-demand. The s field in the SDP message body is "Play", which represents real-time on-demand.
  • After receiving the Invite request, the SIP server establishes the media connection between the media server and the media stream sender through the three-party call control. Send an Invite message to the media server. This message does not carry the SDP message body.
  • After receiving the Invite request from the SIP server, the media server replies with a 200 OK response, carrying the SDP message body, which describes the IP, port, media format and other contents of the media stream received by the media server.
  • After receiving the 200 OK response returned by the media server, the SIP server sends an Invite request to the media stream sender. The request carries the 200 OK response message body replied by the media server in message 3. The s field is "Play" for real-time on-demand, the y field is added to describe the SSRC value, and the f field describes the media parameters.
  • After receiving the Invite request from the SIP server, the media stream sender replies with a 200 OK response and carries the SDP message body, which describes the IP, port, media format, SSRC field and other contents of the media stream sent by the media stream sender.
  • After receiving the 200 OK response returned by the media stream sender, the SIP server sends an ACK request to the media server. The request carries the 200 OK response message body replied by the media stream sender in message 5 to complete the Invite session establishment process with the media server.
  • After receiving the 200 OK response returned by the media stream sender, the SIP server sends an ACK request to the media stream sender. The request does not carry a message body and completes the establishment of an Invite session with the media stream sender.
  • After completing the three-party call control, the SIP server establishes the media connection between the media stream receiver and the media server through B2BUA proxy. Increase the SSRC value in message 1 and forward it to the media server.
  • After receiving the Invite request, the media server replies with a 200 OK response, carrying the SDP message body, which describes the IP, port, media format, SSRC value and other contents of the media stream sent by the media server.
  • The SIP server forwards message 9 to the media stream recipient.
  • After receiving the 200 OK response, the media stream receiver replies to the ACK message and completes the Invite session establishment process with the SIP server.
  • The SIP server forwards the message 11 to the media server to complete the Invite session establishment process with the media server.
  • The media stream receiver sends a BYE message to the SIP server and disconnects the Invite session with the media stream receiver established by messages 1, 10 and 11.
  • After receiving the BYE message, the SIP server replies with a 200 OK response, and the session is disconnected.
  • After receiving the BYE message, the SIP server sends the BYE message to the media server and disconnects the Invite session with the media server established by messages 8, 9 and 12.
  • After receiving the BYE message, the media server replies with a 200 OK response, and the session is disconnected.
  • The SIP server sends a BYE message to the media server and disconnects the Invite session with the media server established by messages 2, 3 and 6.
  • After receiving the BYE message, the media server replies with a 200 OK response, and the session is disconnected.
  • The SIP server sends a BYE message to the media stream sender and disconnects the Invite session with the media stream sender established by messages 4, 5 and 7.
  • After receiving the BYE message, the media stream sender replies 200 OK response, and the session is disconnected.

3. Development of VOD based on SIP Library

  • sip signaling processing:
int SipEventProcess(GB28181Param_t *pGB28181Param)
{
	int ret = 0;
	eXosip_event_t *sipEvent = NULL;


	sipEvent = eXosip_event_wait( 0, 100);
	if (!sipEvent)
	{
		//GB_PrintError("sipEvent is null. \n");
		return -1;
	}
	eXosip_lock();
	eXosip_default_action(sipEvent);
	eXosip_automatic_refresh();
	eXosip_unlock();

	switch(sipEvent->type)
	{
		case EXOSIP_CALL_INVITE:/* INVITE Method to establish a session */
			ret = SipInviteProcess(pGB28181Param, sipEvent);
			break;
			
		case EXOSIP_CALL_ACK:
			ret = SipStartStreamProcess(pGB28181Param, sipEvent);
			break;

		case EXOSIP_CALL_CLOSED:
			ret = SipStopStreamProcess(pGB28181Param, sipEvent);
			break;
		default:
			break;
	}
	eXosip_event_free(sipEvent);
	return ret;
}
  • sip Invite processing
static int SipInviteProcess(GB28181Param_t *pGB28181Param, eXosip_event_t *sipEvent)
{
	int ret = -1;
	uint8_t iChn;
	char transMode[16] = "active";
	char *message = NULL;
	char sdpBody[2048] = {0,};
	osip_message_t *aswMsg = NULL;
	osip_message_t *cloneEvent = NULL;
	sdp_message_t *sdpMsg = NULL;

	if (!pGB28181Param)
	{
		return -1;
	}

	if(MSG_IS_INVITE(sipEvent->request))
	{
		eXosip_lock();
	 	ret = eXosip_call_build_answer( sipEvent->tid, 200, &aswMsg);
		if(ret != OSIP_SUCCESS)
		{
			eXosip_call_send_answer( sipEvent->tid, 603, NULL);
			eXosip_unlock();
			return -1;
		}
		eXosip_unlock();

		// Get device channel number
		if ((ret = osip_message_clone(sipEvent->request, &cloneEvent)) != OSIP_SUCCESS)
		{
			return -1;
		}
		if ((ret = osip_to_to_str(cloneEvent->to, &message)) != OSIP_SUCCESS)
		{
			return -1;
		}
		
		// Judge whether the channel number is valid
		iChn = GetChannelIdByMsg(message, pGB28181Param);
		if (!IS_ICHN_VALID(iChn))
		{
			return -1;
		}
		osip_message_free(cloneEvent);
		osip_free(message);
		
		sdpMsg = eXosip_get_remote_sdp(sipEvent->did); 
		if(NULL == sdpMsg)
		{
			return -1;
		}

		if (OSIP_SUCCESS == sdp_message_to_str(sdpMsg, &message))
		{
			char *str = NULL;
			char strTmp[16] = {0,};

			if ((str = strstr(message ,"a=setup:")))
			{
				strncpy(strTmp, str+strlen("a=setup:"), sizeof(strTmp));
			}

			if ((str = strstr(strTmp, "active")))
			{
				strncpy(transMode, "passive", strlen("passive"));
			}

			osip_free(message);
		}

		snprintf(sdpBody, sizeof(sdpBody),
			"v=0\r\n"
			"o=%s 0 0 IN IP4 %s\r\n"		/*Session source*//*User name / session ID / Version / network type / address type / address*/
			"s=Play\r\n"					/*Session name*/
			"c=IN IP4 %s\r\n" 				/*Connection information*//*Network type / address information / address of multipoint conference*/
			"t=0 0\n"						/*time*//*Start time / end time*/
			"m=video %s RTP/AVP %d\r\n"		/*Media / port / transport layer protocol / format list*/
			"a=setup:%s\r\n"
			"a=sendonly\r\n"				/*Transceiver mode*/
			"a=rtpmap:%d %s/%d\r\n"			/*Payload type / code name / clock rate*/
			"a=username:%s\r\n"
			"a=password:%s\r\n"
			"a=filesize:0\r\n"
			"y=%d\r\n",
			pGB28181Param->userParam.devSipID,
			pGB28181Param->userParam.devSipIP,
			pGB28181Param->userParam.devSipIP,
			pGB28181Param->userParam.devTcpActivePort[iChn],
			pGB28181Param->runParam.vedioPayload,
			transMode,
			pGB28181Param->runParam.vedioPayload,
			pGB28181Param->runParam.vedioPackType,
			pGB28181Param->runParam.vedioSample,
			pGB28181Param->userParam.devSipID,
			pGB28181Param->userParam.devSipPasswd,
			pGB28181Param->runParam.ssrc
		);
		
		eXosip_lock();
		osip_message_set_content_type(aswMsg, "application/sdp");
		osip_message_set_body(aswMsg, sdpBody, strlen(sdpBody));
		ret = eXosip_call_send_answer( sipEvent->tid, 200, aswMsg);
		eXosip_unlock();

		if (ret == OSIP_SUCCESS)
		{
			ret = 0;
		}
	}
	return ret;
}
  • Start on demand function
static int SipStartStreamProcess(GB28181Param_t *pGB28181Param, eXosip_event_t *sipEvent)
{
	int ret = 0;
	uint8_t iChn = 0;
	uint8_t transMode = TCP_PASSIVE;
	char *message = NULL;
	char *mediaSeverIP = NULL;
	char *mediaSeverPort = NULL;
	sdp_message_t *sdpMsg = NULL;
	osip_message_t *cloneEvent = NULL;

	if (!pGB28181Param)
	{
		return -1;
	}

	if ((ret = osip_message_clone(sipEvent->request, &cloneEvent)) != OSIP_SUCCESS)
	{
		return -1;
	}
	
	if ((ret = osip_to_to_str(cloneEvent->to, &message)) != OSIP_SUCCESS)
	{
		return -1;
	}
	
	/* Obtain the IP address and port of the media server from the o field, c field or m field of the INVITE request sent from the SIP server */
	iChn = GetChannelIdByMsg(message, pGB28181Param);
	// Determine whether the port is valid
	if (!IS_ICHN_VALID(iChn))
	{
		return -1;
	}
	osip_message_free(cloneEvent);
	osip_free(message);

	sdpMsg = eXosip_get_remote_sdp(sipEvent->did); 
	if(NULL == sdpMsg)
	{
		return -1;
	}
	mediaSeverIP = sdp_message_o_addr_get(sdpMsg);    		/*Media server IP address*/
	mediaSeverPort = sdp_message_m_port_get(sdpMsg, 0); 	/*Media server IP port*/
	if (OSIP_SUCCESS == sdp_message_to_str(sdpMsg, &message))
	{
		char *str = NULL;
		char strTmp[16] = {0,};

		if ((str = strstr(message ,"a=setup:")))
		{
			strncpy(strTmp, str+strlen("a=setup:"), sizeof(strTmp));
		}

		if ((str = strstr(strTmp, "active")))
		{
			transMode = TCP_ACTIVE;
		}
	
		osip_free(message);
	}

	ret = StartStreamByChannel(mediaSeverIP, mediaSeverPort, iChn, transMode, pGB28181Param);
	sdp_message_free(sdpMsg);
	return ret;
}

The above function will send relevant code stream data to the streaming media server according to the channel number.

reference material:
GBT 28181-2016 technical requirements for information transmission, exchange and control of public safety video surveillance networking system
Recommended reading:
GB28181 protocol - equipment registration and cancellation

Keywords: Operation & Maintenance network server image processing

Added by perfume on Mon, 24 Jan 2022 02:17:19 +0200