点击 RTSP实时监控项目:项目索引,回到目录。
糅合RTSP协议实现
与RTP传输h264码流
/RTP传输aac码流
,即可实现一个传输h264码流的RTSP服务器。
基于RTSP与VLC的交互流程,在接收到PLAY请求时,使用rtp_play_h264传输视频码流,或使用rtp_play_aac传输音频码流。
①传输h264码流:do_client(client_sockfd, &client, rtp_fd, rtcp_fd, rtp_play_h264);
②传输aac码流:do_client(client_sockfd, &client, rtp_fd, rtcp_fd, rtp_play_aac);
do_client函数原型:
static void do_client(int clientSockfd, client_t *client,
int serverRtpSockfd, int serverRtcpSockfd, playfunc_t func)
职责:解析vlc客户端请求,响应并传输码流数据。
#define BUF_MAX_SIZE (1024*1024)
typedef int (*playfunc_t) (int, client_t *);
int rtp_play_null(int rtp_sockfd, client_t *client) {}
static void do_client(int clientSockfd, client_t *client,
int serverRtpSockfd, int serverRtcpSockfd, playfunc_t func)
{
char method[40], url[100], version[40];
char *bufPtr;
char* rbuf = malloc(BUF_MAX_SIZE);
char* sbuf = malloc(BUF_MAX_SIZE);
char line[400];
int cseq = 0, recvLen;
while(1)
{
recvLen = recv(clientSockfd, rbuf, BUF_MAX_SIZE, 0);
if(recvLen <= 0)
goto out;
rbuf[recvLen] = '\0';
printf("---------------C->S--------------\n");
printf("%s", rbuf);
/* 解析方法 */
bufPtr = getLineFromBuf(rbuf, line);
if(sscanf(line, "%s %s %s\r\n", method, url, version) != 3)
{
printf("parse err\n");
goto out;
}
/* 解析序列号 */
bufPtr = getLineFromBuf(bufPtr, line);
if(sscanf(line, "CSeq: %d\r\n", &cseq) != 1)
{
printf("parse err\n");
goto out;
}
/* 如果是SETUP,那么就再解析client_port */
if (!strcmp(method, "SETUP")) {
while(1) {
bufPtr = getLineFromBuf(bufPtr, line);
if (!strncmp(line, "Transport:", strlen("Transport:"))) {
sscanf(line, "Transport: RTP/AVP;unicast;client_port=%d-%d\r\n",
&client->rtp_port, &client->rtcp_port);
break;
}
}
}
if (!strcmp(method, "OPTIONS"))
loadptk_OPTIONS(sbuf, cseq);
else if (!strcmp(method, "DESCRIBE"))
loadptk_DESCRIBE(sbuf, cseq, url);
else if (!strcmp(method, "SETUP"))
loadptk_SETUP(sbuf, cseq, client->rtp_port);
else if (!strcmp(method, "PLAY")) {
loadptk_PLAY(sbuf, cseq);
}
else
goto out;
printf("---------------S->C--------------\n");
printf("%s", sbuf);
send(clientSockfd, sbuf, strlen(sbuf), 0);
// 响应完成后,再发码流数据
if (!strcmp(method, "PLAY")) {
printf("start play\n");
func(serverRtpSockfd, client);
printf("play finish.\n");
}
}
out:
close_socket(clientSockfd);
free(rbuf);
free(sbuf);
}
运行测试: