OPTION
int UnitTest_rtspCmdOptions(rtsp_session_t *sessp)
{
char resp_buf[1024] = {0};
char *p = resp_buf;
/* Send response message. */
sprintf(p, RTSP_VERSION" %d %s\r\n", 200, UnitTest_rtspUtilGetPhraseStatus(200));
p += strlen(p);
sprintf(p, "Cseq: %d\r\n", sessp->cseq);
p += strlen(p);
sprintf(p, "%s", UnitTest_rtspCmdPackDateHeader());
p += strlen(p);
sprintf(p, "Public: %s\r\n", g_Supported_methods);
p += strlen(p);
sprintf(p, "\r\n");
p += strlen(p);
if (p - resp_buf >= sizeof(resp_buf)) {
RTSPSERVERDEBUG("Response message is too long.\n");
return -1;
}
UnitTest_rtspUtilSendData(sessp->rtsp_sock, resp_buf, p - resp_buf);
return 0;
}
DESCRIBE
sprintf(p, RTSP_VERSION" %d %s\r\n", 200, UnitTest_rtspUtilGetPhraseStatus(200));
p += strlen(p);
sprintf(p, "Cseq: %d\r\n", sessp->cseq);
p += strlen(p);
t = time(NULL);
strftime(p, sizeof(resp_buf), "Date: %a, %b %d %Y %H:%M:%S HIK_GMT\r\n",
gmtime(&t));
p += strlen(p);
sprintf(p, "Content-Type: application/sdp\r\n");
p += strlen(p);
sprintf(p, "Content-Length: %d\r\n", sdp_len);
p += strlen(p);
sprintf(p, "\r\n");
p += strlen(p);
/* Make sure the rest size in resp_buf is
* long enough for sdp description. */
if (sizeof(resp_buf) - (p - resp_buf) < sdp_len) {
RTSPSERVERDEBUG("Buffer size[%d] used for response message isn't enough.\n",
sizeof(resp_buf));
return -1;
} else {
memcpy(p, sdp_buf, sdp_len);
}
p += strlen(p);
RTSPSERVERDEBUG("%s\r\n", resp_buf);
UnitTest_rtspUtilSendData(sessp->rtsp_sock, resp_buf, strlen(resp_buf));
SETUP
UnitTest_rtspCmdRtpHeaderInit(&sessp->rtp[media_type].rtp_hdr, media_type);
if (sessp->rtp_tp_type == RTP_TP_TYPE_TCP) {
UnitTest_rtspCmdRtpTcpInit(sessp, media_type);
} else if (sessp->rtp_tp_type == RTP_TP_TYPE_UDP) {
UnitTest_rtspCmdRtpUdpInit(sessp, media_type);
/* Get socket port of server & client. */
if (getsockname(sessp->rtp[media_type].tp.udp.rtp_sock,
(struct sockaddr *)&serv_sa, &serv_salen) < 0 ) {
perror("Getsockname server UDP socket error");
return -1;
}
serv_rtp_port = ntohs(serv_sa.sin_port);
if (getsockname(sessp->rtp[media_type].tp.udp.rtcp_sock,
(struct sockaddr *)&serv_sa, &serv_salen) < 0 ) {
perror("Getsockname server UDP socket error");
return -1;
}
serv_rtcp_port = ntohs(serv_sa.sin_port);
tmp_sap = (struct sockaddr_in *)&sessp->rtp[media_type].tp.udp.rtp_sa;
cli_rtp_port = ntohs(tmp_sap->sin_port);
tmp_sap = (struct sockaddr_in *)&sessp->rtp[media_type].tp.udp.rtcp_sa;
cli_rtcp_port = ntohs(tmp_sap->sin_port);
}
/* Send response message. */
sprintf(p, RTSP_VERSION" %d %s\r\n", 200, UnitTest_rtspUtilGetPhraseStatus(200));
p += strlen(p);
sprintf(p, "Cseq: %d\r\n", sessp->cseq);
p += strlen(p);
sprintf(p, "%s", UnitTest_rtspCmdPackDateHeader());
p += strlen(p);
sprintf(p, "Session: %llu\r\n", sessp->session_id);
p += strlen(p);
if (sessp->rtp_tp_type == RTP_TP_TYPE_TCP) {
sprintf(p, "Transport: RTP/AVP/TCP;unicast;"
"interleaved=%hhd-%hhd\r\n",
sessp->rtp[media_type].tp.tcp.rtp_chn,
sessp->rtp[media_type].tp.tcp.rtcp_chn);
} else if (sessp->rtp_tp_type == RTP_TP_TYPE_UDP) {
sprintf(p, "Transport: RTP/AVP;unicast;"
"client_port=%hu-%hu;server_port=%hu-%hu\r\n",
cli_rtp_port, cli_rtcp_port,
serv_rtp_port, serv_rtcp_port);
}
p += strlen(p);
sprintf(p, "\r\n");
p += strlen(p);
UnitTest_rtspUtilSendData(sessp->rtsp_sock, resp_buf, strlen(resp_buf));
PLAY
int UnitTest_rtspCmdPlay(rtsp_session_t *sessp)
{
char resp_buf[2048] = {0};
char *p = resp_buf;
/* Send response message. */
sprintf(p, RTSP_VERSION" %d %s\r\n", 200, UnitTest_rtspUtilGetPhraseStatus(200));
p += strlen(p);
sprintf(p, "Cseq: %d\r\n", sessp->cseq);
p += strlen(p);
sprintf(p, "%s", UnitTest_rtspCmdPackDateHeader());
p += strlen(p);
sprintf(p, "Session: %llu\r\n", sessp->session_id);
p += strlen(p);
sprintf(p, "\r\n");
p += strlen(p);
UnitTest_rtspUtilSendData(sessp->rtsp_sock, resp_buf, strlen(resp_buf));
return 0;
}
GET_PARMETER
SDP
static int UnitTest_rtspCmdPackSdpDescription(rtsp_session_t *sessp, char *buf, int size)
{
char *p = NULL;
RTSPSERVERDEBUG("make sdp description Begin \r\n");
int rtp_pt_video = 0;
char videType[10];
char audioType[10];
char *ip = NULL;
ip = UnitTest_rtspCmdGetServerIpAdder(ETH0_INTERFACE_NAME);
if(ip == NULL)
{
ip = "127.0.0.1";
}
p = buf;
sprintf(p, "v=0\r\n");
p += strlen(p);
sprintf(p, "o=- %ld %ld IN IP4 %s\r\n", time(NULL), time(NULL) + 1,ip);
p += strlen(p);
sprintf(p, "s=streamed by the RTSP server\r\n");
p += strlen(p);
sprintf(p, "t=0 0\r\n");
rtp_pt_video = RTP_PT_VIDEO_H264;
sprintf(videType,"H264");
if (2 == sessp->vido_type)
{
rtp_pt_video = RTP_PT_VIDEO_H265;
sprintf(videType,"H265");
}
p += strlen(p);
sprintf(p, "m=video 0 RTP/AVP %d\r\n", rtp_pt_video);
p += strlen(p);
sprintf(p, "a=rtpmap:%d %s/90000\r\n", rtp_pt_video,videType);
p += strlen(p);
sprintf(p, "a=control:track%d\r\n", MEDIA_TYPE_VIDEO);
p += strlen(p);
#if 1 // 音频部分SDP信息
int rtp_pt_audio = 0;
rtp_pt_audio = RTP_PT_AUDIO_PCMU;
if (4 == sessp->aud_type)
{
rtp_pt_audio = RTP_PT_AUDIO_PCMA;
}
sprintf(p, "m=audio 0 RTP/AVP %d\r\n", 0);
p += strlen(p);
sprintf(p, "a=rtpmap:%d %s/8000/1\r\n", rtp_pt_audio,
(rtp_pt_audio == RTP_PT_AUDIO_PCMA) ? "PCMA" : "PCMU");
p += strlen(p);
sprintf(p, "a=control:track%d\r\n", MEDIA_TYPE_AUDIO);
p += strlen(p);
sprintf(p, "a=range:npt=0-\r\n");
p += strlen(p);
#endif
sprintf(p, "a=fmtp:%d packetization-mode=1;profile-level-id=%s;sprop-parameter-sets=%s\r\n",RTP_PT_VIDEO_H264, "64001F", "Z0IAH5WoFAFuQA==,aM48gA==");
p += strlen(p);
sprintf(p, "\r\n");
p += strlen(p);
RTSPSERVERDEBUG("make sdp description end \r\n");
return (p - buf); /* Return length of sdp description. */
}
static int UnitTest_rtspCmdRtpHeaderInit(rtp_hdr_t *hdrp, int media_type)
{
if (hdrp == NULL) {
return -1;
}
hdrp->v = 2;
hdrp->p = 0;
hdrp->x = 0;
hdrp->cc = 0;
hdrp->m = 0;
hdrp->pt = (media_type == MEDIA_TYPE_VIDEO) ? RTP_PT_VIDEO_H264 : RTP_PT_AUDIO_PCMU;
// hdrp->seq = random();
// hdrp->ts = random();
// hdrp->ssrc = random();
hdrp->seq = htons(1);
hdrp->ts = 1000;
hdrp->ssrc = 0x88776655;
return 0;
}
static int UnitTest_rtspCmdRtpTcpInit(rtsp_session_t *sessp, int media)
{
/* Initialize interleaved header. */
intlvd_t intlvd = {
.dollar = '$',
.chn = 0,
.size = 0,
};
memcpy(sessp->send_buf, &intlvd, sizeof(intlvd_t));
return 0;
}
static int UnitTest_rtspCmdRtpUdpInit(rtsp_session_t *sessp, int media)
{
if (sessp == NULL) {
return -1;
}
int first_sock = -1;
int second_sock = -1;
unsigned short first_port = 0;
unsigned short second_port = 0;
struct sockaddr_in sa; /* Use for creating RTP & RTCP socket. */
struct sockaddr_in *tmp_sap = NULL;
struct sockaddr_in rtsp_sa;
socklen_t sa_len = sizeof(sa);
sessp->rtp[media].tp.udp.rtp_sock = -1;
sessp->rtp[media].tp.udp.rtcp_sock = -1;
bzero(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl(INADDR_ANY);
/* Create first socket. */
if ((first_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Create first UDP socket for RTP error");
goto err_rtn;
}
if (bind(first_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("Bind first UDP sockaddr error");
goto err_rtn;
}
/* Get first port. */
if (getsockname(first_sock, (struct sockaddr *)&sa, &sa_len) < 0) {
perror("Getsockname first UDP socket error");
goto err_rtn;
}
first_port = ntohs(sa.sin_port);
second_port = (first_port % 2 == 0) ? (first_port + 1) : (first_port - 1);
/* Create second socket. */
sa.sin_port = htons(second_port);
if ((second_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Create second UDP socket for RTP error");
goto err_rtn;
}
if (bind(second_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
if (errno == EADDRINUSE) { /* Address already in use. */
sa.sin_port = 0;
if (bind(second_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("Bind second UDP sockaddr error");
goto err_rtn;
}
} else {
perror("Bind second UDP sockaddr error");
goto err_rtn;
}
}
/* Get second port. */
if (getsockname(second_sock, (struct sockaddr *)&sa, &sa_len) < 0 ) {
perror("Getsockname second UDP socket error");
goto err_rtn;
}
second_port = ntohs(sa.sin_port);
if (first_port % 2 == 0) { /* Even port. */
sessp->rtp[media].tp.udp.rtp_sock = first_sock;
sessp->rtp[media].tp.udp.rtcp_sock = second_sock;
} else { /* Odd port. */
sessp->rtp[media].tp.udp.rtp_sock = second_sock;
sessp->rtp[media].tp.udp.rtcp_sock = first_sock;
}
if (getpeername(sessp->rtsp_sock, (struct sockaddr *)&rtsp_sa, &sa_len) < 0) {
perror("Getpeername cli_sock");
return -1;
}
tmp_sap = (struct sockaddr_in *)&sessp->rtp[media].tp.udp.rtp_sa;
tmp_sap->sin_family = rtsp_sa.sin_family;
tmp_sap->sin_addr = rtsp_sa.sin_addr;
tmp_sap = (struct sockaddr_in *)&sessp->rtp[media].tp.udp.rtcp_sa;
tmp_sap->sin_family = rtsp_sa.sin_family;
tmp_sap->sin_addr = rtsp_sa.sin_addr;
return 0;
err_rtn:
shutdown(first_sock, SHUT_RDWR);
shutdown(second_sock, SHUT_RDWR);
close(first_sock);
close(second_sock);
return -1;
}