RTSP服务器程序实现

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
在这里插入图片描述
RTSP服务器程序实现_第1张图片

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
在这里插入图片描述
在这里插入图片描述
RTSP服务器程序实现_第2张图片
RTSP服务器程序实现_第3张图片

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
RTSP服务器程序实现_第4张图片
RTSP服务器程序实现_第5张图片

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
RTSP服务器程序实现_第6张图片
RTSP服务器程序实现_第7张图片
SDP
RTSP服务器程序实现_第8张图片

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;
}

你可能感兴趣的:(rtsp)