Linux下RTSPServer程序--HI3516实测通过
源代码是CSDN上一位前辈那里下的[http://download.csdn.net/detail/showmove/6570893],用法和前辈的一样,最大的改动是把所有关于RTSP的代码独立出来,使用者直接调用即可。另外,对程序做了优化,目前在HI3516上测试下来,四个客户端连上,播D1视频,延时约2s。
代码分为两个文件,sample_comm_rtsp.c、rtsp_server.h。用法流程如下:
1.InitRtspServer();
2.udpfd = socket(AF_INET,SOCK_DGRAM,0);//UDP
3.SAMPLE_COMM_VENC_Sentjin(&stStream);
/****************************************************************************** 文件名:sample_comm_rtsp.c 源作者:http://download.csdn.net/detail/showmove/6570893 时间:2015.06 ******************************************************************************/ #ifdef __cplusplus #if __cplusplus extern "C"{ #endif #endif /* End of #ifdef __cplusplus */ #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <netdb.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <fcntl.h> #include <pthread.h> #include <sys/ipc.h> #include <sys/msg.h> #include <netinet/if_ether.h> #include <net/if.h> #include <linux/if_ether.h> #include <linux/sockios.h> #include <netinet/in.h> #include <arpa/inet.h> #include "rtsp_server.h" #include "sample_comm.h" #define nalu_sent_len 14000 #define RTP_H264 96 #define MAX_CHAN 8 #define RTP_AUDIO 97 #define MAX_RTSP_CLIENT 6 #define RTSP_SERVER_PORT 554 #define RTSP_RECV_SIZE 1024 #define RTSP_MAX_VID (640*1024) #define RTSP_MAX_AUD (15*1024) #define AU_HEADER_SIZE 4 #define PARAM_STRING_MAX 100 //static SAMPLE_VENC_GETSTREAM_PARA_S gs_stPara; //static pthread_t gs_VencPid; typedef unsigned short u_int16_t; typedef unsigned char u_int8_t; typedef u_int16_t portNumBits; typedef u_int32_t netAddressBits; typedef long long _int64; #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #define AUDIO_RATE 8000 //#define PACKET_BUFFER_END (unsigned int)0x00000000 typedef struct { int startblock;//代表开始文件块号 int endblock;//代表结束文件块号 int BlockFileNum;//代表录像段数 }IDXFILEHEAD_INFO;//.IDX文件的头信息 typedef struct { _int64 starttime;//代表开始shijian _int64 endtime;//代表结束shijian int startblock;//代表开始文件块号 int endblock;//代表结束文件块号 int stampnum;//代表时间戳数量 }IDXFILEBLOCK_INFO;//.IDX文件段信息 typedef struct { int blockindex;//代表所在文件块号 int pos;//代表该时间戳在文件块的位置 _int64 time;//代表时间戳时间戳的时间点 }IDXSTAMP_INFO;//.IDX文件的时间戳信息 typedef struct { char filename[150];//代表所在文件块号 int pos;//代表该时间戳在文件块的位置 _int64 time;//代表时间戳时间戳的时间点 }FILESTAMP_INFO;//.IDX文件的时间戳信息 typedef struct { char channelid[9]; _int64 starttime;//代表开始shijian _int64 endtime;//代表结束shijian _int64 session; int type; //类型 int encodetype;//编码格式; }FIND_INFO;//.IDX文件的时间戳信息 typedef enum { RTP_UDP, RTP_TCP, RAW_UDP }StreamingMode; typedef enum { RTSP_IDLE = 0, RTSP_CONNECTED = 1, RTSP_SENDING = 2, }RTSP_STATUS; typedef struct { int nVidLen; int nAudLen; int bIsIFrm; int bWaitIFrm; int bIsFree; char vidBuf[RTSP_MAX_VID]; char audBuf[RTSP_MAX_AUD]; }RTSP_PACK; typedef struct { int index; int socket; int reqchn; int seqnum; int seqnum2; unsigned int tsvid; unsigned int tsaud; int status; int sessionid; int rtpport[2]; int rtcpport; char IP[20]; char urlPre[PARAM_STRING_MAX]; }RTSP_CLIENT; typedef struct { int vidLen; int audLen; int nFrameID; char vidBuf[RTSP_MAX_VID]; char audBuf[RTSP_MAX_AUD]; }FRAME_PACK; typedef struct { int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested) unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU) unsigned max_size; //! Nal Unit Buffer size int forbidden_bit; //! should be always FALSE int nal_reference_idc; //! NALU_PRIORITY_xxxx int nal_unit_type; //! NALU_TYPE_xxxx char *buf; //! contains the first byte followed by the EBSP unsigned short lost_packets; //! true, if packet loss is detected } NALU_t; //static bool flag = true; RTP_FIXED_HEADER *rtp_hdr; NALU_HEADER *nalu_hdr; FU_INDICATOR *fu_ind; FU_HEADER *fu_hdr; FRAME_PACK g_FrmPack[MAX_CHAN]; RTSP_PACK g_rtpPack[MAX_CHAN]; RTSP_CLIENT g_rtspClients[MAX_RTSP_CLIENT]; int g_nSendDataChn = -1; pthread_mutex_t g_mutex; pthread_cond_t g_cond; pthread_mutex_t g_sendmutex; pthread_t g_SendDataThreadId = 0; char g_rtp_playload[20]; int g_audio_rate = 8000; int g_nframerate; int exitok = 0; #if 1 static char const* dateHeader() { static char buf[200]; #if !defined(_WIN32_WCE) time_t tt = time(NULL); strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt)); #endif return buf; } #endif static char* GetLocalIP(int sock) { struct ifreq ifreq; struct sockaddr_in *sin; char * LocalIP = malloc(20); strcpy(ifreq.ifr_name,"eth0"); if (!(ioctl (sock, SIOCGIFADDR,&ifreq))) { sin = (struct sockaddr_in *)&ifreq.ifr_addr; sin->sin_family = AF_INET; strcpy(LocalIP,inet_ntoa(sin->sin_addr)); //inet_ntop(AF_INET, &sin->sin_addr,LocalIP, 16); } //printf("--------------------------------------------%s\n",LocalIP); return LocalIP; } char* strDupSize(char const* str) { if (str == NULL) return NULL; size_t len = strlen(str) + 1; char* copy = malloc(len); return copy; } int ParseRequestString( char const* reqStr, unsigned reqStrSize, char* resultCmdName, unsigned resultCmdNameMaxSize, char* resultURLPreSuffix, unsigned resultURLPreSuffixMaxSize, char* resultURLSuffix, unsigned resultURLSuffixMaxSize, char* resultCSeq, unsigned resultCSeqMaxSize) { // Read everything up to the first space as the command name: int parseSucceeded = FALSE; unsigned i; for (i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) { char c = reqStr[i]; if (c == ' ' || c == '\t') { parseSucceeded = TRUE; break; } resultCmdName[i] = c; } resultCmdName[i] = '\0'; if (!parseSucceeded) return FALSE; // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows: unsigned j = i+1; while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white space //rtsp://192.168.1.5:554 for (j = i+1; j < reqStrSize-8; ++j) { if ((reqStr[j] == 'r' || reqStr[j] == 'R') && (reqStr[j+1] == 't' || reqStr[j+1] == 'T') && (reqStr[j+2] == 's' || reqStr[j+2] == 'S') && (reqStr[j+3] == 'p' || reqStr[j+3] == 'P') && reqStr[j+4] == ':' && reqStr[j+5] == '/') { j += 6; //printf("reqStr:%s__\n",&reqStr[j]); if (reqStr[j] == '/') { // This is a "rtsp://" URL; skip over the host:port part that follows: ++j; while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j; } else { // This is a "rtsp:/" URL; back up to the "/": --j; } i = j; break; } } // Look for the URL suffix (before the following "RTSP/"): parseSucceeded = FALSE; unsigned k; for (k = i+1; k < reqStrSize-5; ++k) { if (reqStr[k] == 'R' && \ reqStr[k+1] == 'T' && \ reqStr[k+2] == 'S' && \ reqStr[k+3] == 'P' && \ reqStr[k+4] == '/') { while (--k >= i && reqStr[k] == ' '); // go back over all spaces before "RTSP/" unsigned k1 = k; while (k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1; // the URL suffix comes from [k1+1,k] // Copy "resultURLSuffix": if (k - k1 + 1 > resultURLSuffixMaxSize) return FALSE; // there's no room unsigned n = 0, k2 = k1+1; while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++]; resultURLSuffix[n] = '\0'; // Also look for the URL 'pre-suffix' before this: unsigned k3 = --k1; while (k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3; // the URL pre-suffix comes from [k3+1,k1] // Copy "resultURLPreSuffix": if (k1 - k3 + 1 > resultURLPreSuffixMaxSize) return FALSE; // there's no room n = 0; k2 = k3+1; while (k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++]; resultURLPreSuffix[n] = '\0'; i = k + 7; // to go past " RTSP/" parseSucceeded = TRUE; break; } } if (!parseSucceeded) return FALSE; #if 1 // Look for "CSeq:", skip whitespace, // then read everything up to the next \r or \n as 'CSeq': parseSucceeded = FALSE; for (j = i; j < reqStrSize-5; ++j) { if (reqStr[j] == 'C' && reqStr[j+1] == 'S' && reqStr[j+2] == 'e' && reqStr[j+3] == 'q' && reqStr[j+4] == ':') { j += 5; unsigned n; while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) { char c = reqStr[j]; if (c == '\r' || c == '\n') { parseSucceeded = TRUE; break; } resultCSeq[n] = c; } resultCSeq[n] = '\0'; break; } } if (!parseSucceeded) return FALSE; #endif return parseSucceeded; } int OptionAnswer(char *cseq, int sock) { if (sock != 0) { char buf[1024]; memset(buf,0,1024); char *pTemp = buf; pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n", cseq,dateHeader(),"OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN"); int reg = send(sock, buf,strlen(buf),0); if(reg <= 0) { return FALSE; } else { printf(">>>>>%s\n",buf); } return TRUE; } return FALSE; } int DescribeAnswer(char *cseq,int sock,char * urlSuffix,char* recvbuf) { if (sock != 0) { char sdpMsg[1024]; char buf[2048]; memset(buf,0,2048); memset(sdpMsg,0,1024); char*localip; localip = GetLocalIP(sock); char *pTemp = buf; pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n",cseq); pTemp += sprintf(pTemp,"%s",dateHeader()); pTemp += sprintf(pTemp,"Content-Type: application/sdp\r\n"); //TODO °ÑһЩ¹Ì¶šÖµžÄΪ¶¯Ì¬Öµ char *pTemp2 = sdpMsg; pTemp2 += sprintf(pTemp2,"v=0\r\n"); pTemp2 += sprintf(pTemp2,"o=StreamingServer 3331435948 1116907222000 IN IP4 %s\r\n",localip); pTemp2 += sprintf(pTemp2,"s=H.264\r\n"); pTemp2 += sprintf(pTemp2,"c=IN IP4 0.0.0.0\r\n"); pTemp2 += sprintf(pTemp2,"t=0 0\r\n"); pTemp2 += sprintf(pTemp2,"a=control:*\r\n"); /*ÊÓƵÜÌåÃèÊö*/ /*H264 TrackID=0 RTP_PT 96*/ pTemp2 += sprintf(pTemp2,"m=video 0 RTP/AVP 96\r\n"); pTemp2 += sprintf(pTemp2,"a=control:trackID=0\r\n"); pTemp2 += sprintf(pTemp2,"a=rtpmap:96 H264/90000\r\n"); pTemp2 += sprintf(pTemp2,"a=fmtp:96 packetization-mode=1; sprop-parameter-sets=%s\r\n", "AAABBCCC"); #if 1 /*ÒôƵÜÌåÃèÊö*/ /*G726*/ /*TODO ÒôƵ*/ pTemp2 += sprintf(pTemp2,"m=audio 0 RTP/AVP 97\r\n"); pTemp2 += sprintf(pTemp2,"a=control:trackID=1\r\n"); if(strcmp(g_rtp_playload,"AAC")==0) { pTemp2 += sprintf(pTemp2,"a=rtpmap:97 MPEG4-GENERIC/%d/2\r\n",16000); pTemp2 += sprintf(pTemp2,"a=fmtp:97 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1410\r\n"); } else { pTemp2 += sprintf(pTemp2,"a=rtpmap:97 G726-32/%d/1\r\n",8000); pTemp2 += sprintf(pTemp2,"a=fmtp:97 packetization-mode=1\r\n"); } #endif pTemp += sprintf(pTemp,"Content-length: %d\r\n", strlen(sdpMsg)); pTemp += sprintf(pTemp,"Content-Base: rtsp://%s/%s/\r\n\r\n",localip,urlSuffix); //printf("mem ready\n"); strcat(pTemp, sdpMsg); free(localip); //printf("Describe ready sent\n"); int re = send(sock, buf, strlen(buf),0); if(re <= 0) { return FALSE; } else { printf(">>>>>%s\n",buf); } } return TRUE; } void ParseTransportHeader(char const* buf, StreamingMode* streamingMode, char**streamingModeString, char**destinationAddressStr, u_int8_t* destinationTTL, portNumBits* clientRTPPortNum, // if UDP portNumBits* clientRTCPPortNum, // if UDP unsigned char* rtpChannelId, // if TCP unsigned char* rtcpChannelId // if TCP ) { // Initialize the result parameters to default values: *streamingMode = RTP_UDP; *streamingModeString = NULL; *destinationAddressStr = NULL; *destinationTTL = 255; *clientRTPPortNum = 0; *clientRTCPPortNum = 1; *rtpChannelId = *rtcpChannelId = 0xFF; portNumBits p1, p2; unsigned ttl, rtpCid, rtcpCid; // First, find "Transport:" while (1) { if (*buf == '\0') return; // not found if (strncasecmp(buf, "Transport: ", 11) == 0) break; ++buf; } // Then, run through each of the fields, looking for ones we handle: char const* fields = buf + 11; char* field = strDupSize(fields); while (sscanf(fields, "%[^;]", field) == 1) { if (strcmp(field, "RTP/AVP/TCP") == 0) { *streamingMode = RTP_TCP; } else if (strcmp(field, "RAW/RAW/UDP") == 0 || strcmp(field, "MP2T/H2221/UDP") == 0) { *streamingMode = RAW_UDP; } else if (strncasecmp(field, "destination=", 12) == 0) { free(destinationAddressStr); } else if (sscanf(field, "ttl%u", &ttl) == 1) { destinationTTL = (u_int8_t)ttl; } else if (sscanf(field, "client_port=%hu-%hu", &p1, &p2) == 2) { *clientRTPPortNum = p1; *clientRTCPPortNum = p2; } else if (sscanf(field, "client_port=%hu", &p1) == 1) { *clientRTPPortNum = p1; *clientRTCPPortNum = streamingMode == RAW_UDP ? 0 : p1 + 1; } else if (sscanf(field, "interleaved=%u-%u", &rtpCid, &rtcpCid) == 2) { *rtpChannelId = (unsigned char)rtpCid; *rtcpChannelId = (unsigned char)rtcpCid; } fields += strlen(field); while (*fields == ';') ++fields; // skip over separating ';' chars if (*fields == '\0' || *fields == '\r' || *fields == '\n') break; } free(field); } int SetupAnswer(char *cseq,int sock,int SessionId,char * urlSuffix,char* recvbuf,int* rtpport, int* rtcpport) { if (sock != 0) { char buf[1024]; memset(buf,0,1024); StreamingMode streamingMode; char* streamingModeString; // set when RAW_UDP streaming is specified char* clientsDestinationAddressStr; u_int8_t clientsDestinationTTL; portNumBits clientRTPPortNum, clientRTCPPortNum; unsigned char rtpChannelId, rtcpChannelId; ParseTransportHeader(recvbuf,&streamingMode, &streamingModeString, &clientsDestinationAddressStr, &clientsDestinationTTL, &clientRTPPortNum, &clientRTCPPortNum, &rtpChannelId, &rtcpChannelId); *rtpport = clientRTPPortNum; *rtcpport = clientRTCPPortNum; char *pTemp = buf; char*localip; localip = GetLocalIP(sock); pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sTransport: RTP/AVP;unicast;destination=%s;client_port=%d-%d;server_port=%d-%d\r\nSession: %d\r\n\r\n", cseq,dateHeader(),localip, ntohs(htons(clientRTPPortNum)), ntohs(htons(clientRTCPPortNum)), ntohs(2000), ntohs(2001), SessionId); free(localip); int reg = send(sock, buf,strlen(buf),0); if(reg <= 0) { return FALSE; } else { printf(">>>>>%s",buf); } return TRUE; } return FALSE; } int PlayAnswer(char *cseq, int sock,int SessionId,char* urlPre,char* recvbuf) { if (sock != 0) { char buf[1024]; memset(buf,0,1024); char *pTemp = buf; char*localip; localip = GetLocalIP(sock); pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sRange: npt=0.000-\r\nSession: %d\r\nRTP-Info: url=rtsp://%s/%s;seq=0\r\n\r\n", cseq,dateHeader(),SessionId,localip,urlPre); free(localip); int reg = send(sock, buf,strlen(buf),0); if(reg <= 0) { return FALSE; } else { printf(">>>>>%s",buf); } return TRUE; } return FALSE; } int PauseAnswer(char *cseq,int sock,char *recvbuf) { if (sock != 0) { char buf[1024]; memset(buf,0,1024); char *pTemp = buf; pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%s\r\n\r\n", cseq,dateHeader()); int reg = send(sock, buf,strlen(buf),0); if(reg <= 0) { return FALSE; } else { printf(">>>>>%s",buf); } return TRUE; } return FALSE; } int TeardownAnswer(char *cseq,int sock,int SessionId,char *recvbuf) { if (sock != 0) { char buf[1024]; memset(buf,0,1024); char *pTemp = buf; pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sSession: %d\r\n\r\n", cseq,dateHeader(),SessionId); int reg = send(sock, buf,strlen(buf),0); if(reg <= 0) { return FALSE; } else { printf(">>>>>%s",buf); } return TRUE; } return FALSE; } void * RtspClientMsg(void*pParam) { pthread_detach(pthread_self()); char strIp[255]; //192.168.001.001 int srcIP[4]; int strPort; char strOther[255]; int nRes,Ret; char pRecvBuf[RTSP_RECV_SIZE]; RTSP_CLIENT * pClient = (RTSP_CLIENT*)pParam; memset(pRecvBuf,0,sizeof(pRecvBuf)); printf("RTSP:-----Create Client %s\n",pClient->IP); while(pClient->status != RTSP_IDLE) { nRes = recv(pClient->socket, pRecvBuf, RTSP_RECV_SIZE,0); if(nRes < 1) { printf("RTSP:Recv Error--- %d\n",nRes); g_rtspClients[pClient->index].status = RTSP_IDLE; g_rtspClients[pClient->index].seqnum = 0; g_rtspClients[pClient->index].tsvid = 0; g_rtspClients[pClient->index].tsaud = 0; close(pClient->socket); break; } { sscanf(pRecvBuf, "%*[^:]://%[^:]:%d/%s", strIp, &strPort, strOther); sscanf(strIp,"%d.%d.%d.%d",&srcIP[0],&srcIP[1],&srcIP[2],&srcIP[3]); printf("%d\t%d\t%d\t%d\t\n",srcIP[0],srcIP[1],srcIP[2],srcIP[3]); printf("%s\t%d\t%s\t\n",strIp,strPort,strOther); } char cmdName[PARAM_STRING_MAX]; char urlPreSuffix[PARAM_STRING_MAX]; char urlSuffix[PARAM_STRING_MAX]; char cseq[PARAM_STRING_MAX]; Ret = ParseRequestString(pRecvBuf,nRes,cmdName,sizeof(cmdName),urlPreSuffix,sizeof(urlPreSuffix), urlSuffix,sizeof(urlSuffix),cseq,sizeof(cseq)); if(Ret==FALSE) { printf("ParseRequestString error[%s]\n",pRecvBuf); break; } char *p = pRecvBuf; printf("<<<<<%s\n",p); if(strstr(cmdName, "OPTIONS")) { OptionAnswer(cseq,pClient->socket); } else if(strstr(cmdName, "DESCRIBE")) { DescribeAnswer(cseq,pClient->socket,urlSuffix,p); } else if(strstr(cmdName, "SETUP")) { int rtpport,rtcpport; int trackID=0; SetupAnswer(cseq,pClient->socket,pClient->sessionid,urlPreSuffix,p,&rtpport,&rtcpport); sscanf(urlSuffix, "trackID=%u", &trackID); if(trackID<0 || trackID>=2) trackID=0; g_rtspClients[pClient->index].rtpport[trackID] = rtpport; g_rtspClients[pClient->index].rtcpport= rtcpport; g_rtspClients[pClient->index].reqchn = atoi(urlPreSuffix); if(strlen(urlPreSuffix)<100) strcpy(g_rtspClients[pClient->index].urlPre,urlPreSuffix); } else if(strstr(cmdName, "PLAY")) { PlayAnswer(cseq,pClient->socket,pClient->sessionid,g_rtspClients[pClient->index].urlPre,p); g_rtspClients[pClient->index].status = RTSP_SENDING; } else if(strstr(cmdName, "PAUSE")) { PauseAnswer(cseq,pClient->socket,p); } else if(strstr(cmdName, "TEARDOWN")) { TeardownAnswer(cseq,pClient->socket,pClient->sessionid,p); g_rtspClients[pClient->index].status = RTSP_IDLE; g_rtspClients[pClient->index].seqnum = 0; g_rtspClients[pClient->index].tsvid = 0; g_rtspClients[pClient->index].tsaud = 0; close(pClient->socket); } if(exitok) { exitok++; return NULL; } } printf("RTSP:-----Exit Client %s\n",pClient->IP); return NULL; } void * RtspServerListen(void*pParam) { int s32Socket; struct sockaddr_in servaddr; int s32CSocket; int s32Rtn; int s32Socket_opt_value = 1; int nAddrLen; struct sockaddr_in addrAccept; //int bResult; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(RTSP_SERVER_PORT); s32Socket = socket(AF_INET, SOCK_STREAM, 0); if (setsockopt(s32Socket ,SOL_SOCKET,SO_REUSEADDR,&s32Socket_opt_value,sizeof(int)) == -1) { return (void *)(-1); } s32Rtn = bind(s32Socket, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)); if(s32Rtn < 0) { return (void *)(-2); } s32Rtn = listen(s32Socket, 50); /*50,×îŽóµÄÁ¬œÓÊý*/ if(s32Rtn < 0) { return (void *)(-2); } nAddrLen = sizeof(struct sockaddr_in); int nSessionId = 1000; while ((s32CSocket = accept(s32Socket,(struct sockaddr*)&addrAccept,(socklen_t *)&nAddrLen)) >= 0) { printf("<<<<RTSP Client %s Connected...\n", inet_ntoa(addrAccept.sin_addr)); int nMaxBuf = 10 * 1024; // ϵͳœ«»á·ÖÅä 2 x nMaxBuf µÄ»º³åŽóС if(setsockopt(s32CSocket, SOL_SOCKET, SO_SNDBUF, (char*)&nMaxBuf, sizeof(nMaxBuf)) == -1) printf("RTSP:!!!!!! Enalarge socket sending buffer error !!!!!!\n"); int i; int bAdd=FALSE; for(i=0;i<MAX_RTSP_CLIENT;i++) { if(g_rtspClients[i].status == RTSP_IDLE) { memset(&g_rtspClients[i],0,sizeof(RTSP_CLIENT)); g_rtspClients[i].index = i; g_rtspClients[i].socket = s32CSocket; g_rtspClients[i].status = RTSP_CONNECTED ;//RTSP_SENDING; g_rtspClients[i].sessionid = nSessionId++; strcpy(g_rtspClients[i].IP,inet_ntoa(addrAccept.sin_addr)); pthread_t threadIdlsn = 0; struct sched_param sched; sched.sched_priority = 1; //to return ACKecho pthread_create(&threadIdlsn, NULL, RtspClientMsg, &g_rtspClients[i]); pthread_setschedparam(threadIdlsn,SCHED_RR,&sched); bAdd = TRUE; break; } } if(bAdd==FALSE) { memset(&g_rtspClients[0],0,sizeof(RTSP_CLIENT)); g_rtspClients[0].index = 0; g_rtspClients[0].socket = s32CSocket; g_rtspClients[0].status = RTSP_CONNECTED ;//RTSP_SENDING; g_rtspClients[0].sessionid = nSessionId++; strcpy(g_rtspClients[0].IP,inet_ntoa(addrAccept.sin_addr)); pthread_t threadIdlsn = 0; struct sched_param sched; sched.sched_priority = 1; //to return ACKecho pthread_create(&threadIdlsn, NULL, RtspClientMsg, &g_rtspClients[0]); pthread_setschedparam(threadIdlsn,SCHED_RR,&sched); bAdd = TRUE; } if(exitok) { exitok++; return NULL; } } printf("----- INIT_RTSP_Listen() Exit !! \n"); return NULL; } HI_S32 framenum=0; HI_S32 VENC_Sent(char *buffer,int buflen) { //HI_S32 i; VIDEO_NORM_E gs_enNorm = VIDEO_ENCODING_MODE_NTSC;//30fps //-------------------------------------------------------- int is=0; int nChanNum=0; #if 0 FILE *fp; fp = fopen("test_rtsp.264", "ab"); if (!fp) { SAMPLE_PRT("open file failed!\n"); return 0; } #endif framenum++; for(is=0;is<MAX_RTSP_CLIENT;is++) { if(g_rtspClients[is].status!=RTSP_SENDING) { continue; } int heart = g_rtspClients[is].seqnum % 1000; if(heart==0 && g_rtspClients[is].seqnum!=0) { char buf[1024]; memset(buf,0,1024); char *pTemp = buf; pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: %s\r\n\r\n", \ "","OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN"); int reg = send(g_rtspClients[is].socket, buf,strlen(buf),0); if(reg <= 0) { //printf("RTSP:Send Error---- %d\n",reg); g_rtspClients[is].status = RTSP_IDLE; g_rtspClients[is].seqnum = 0; g_rtspClients[is].tsvid = 0; g_rtspClients[is].tsaud = 0; close(g_rtspClients[is].socket); continue; } else { unsigned char Time[20]; GetSysTime(Time); printf("%s\tHeart:%d----------------------------------\n",Time,reg); } } char* nalu_payload; int nAvFrmLen = 0; int nIsIFrm = 0; int nNaluType = 0; char sendbuf[320*1024+32]; nChanNum = g_rtspClients[is].reqchn; if(nChanNum<0 || nChanNum>=MAX_CHAN ) { continue; } nAvFrmLen = buflen; struct sockaddr_in server; server.sin_family=AF_INET; server.sin_port=htons(g_rtspClients[is].rtpport[0]); server.sin_addr.s_addr=inet_addr(g_rtspClients[is].IP); int bytes=0; unsigned int timestamp_increse=0; if(VIDEO_ENCODING_MODE_PAL == gs_enNorm) g_nframerate = 15; else if(VIDEO_ENCODING_MODE_NTSC == gs_enNorm) g_nframerate = 30; timestamp_increse=(unsigned int)(90000.0 / g_nframerate); rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; rtp_hdr->payload = RTP_H264; //¸ºÔØÀàÐͺţ¬ rtp_hdr->version = 2; //°æ±¾ºÅ£¬´Ë°æ±¾¹Ì¶¨Îª2 rtp_hdr->marker = 0; //±ê־룬ÓɾßÌåЭÒé¹æ¶¨ÆäÖµ¡£ rtp_hdr->ssrc = htonl(10); //Ëæ»úÖ¸¶¨Îª10£¬²¢ÇÒÔÚ±¾RTP»á»°ÖÐÈ«¾ÖΨһ s32RtspFrmRate++; if(nAvFrmLen<=nalu_sent_len) { //ÉèÖÃrtp M λ£» //printf("a"); rtp_hdr->marker=1; rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++); //ÐòÁкţ¬Ã¿·¢ËÍÒ»¸öRTP°üÔö1 nalu_hdr =(NALU_HEADER*)&sendbuf[12]; nalu_hdr->F=0; nalu_hdr->NRI= nIsIFrm; nalu_hdr->TYPE= nNaluType; nalu_payload=&sendbuf[13];//ͬÀí½«sendbuf[13]¸³¸ønalu_payload memcpy(nalu_payload,buffer,nAvFrmLen); //memcpy(nalu_payload,buffer+4,nAvFrmLen-4); g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse; rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid); bytes=nAvFrmLen+ 13 ; sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); //fwrite(nalu_payload,nAvFrmLen, 1, fp); //fwrite(sendbuf,bytes, 1, fp); } else if(nAvFrmLen>nalu_sent_len) { //printf("b"); //µÃµ½¸ÃnaluÐèÒªÓöàÉÙ³¤¶ÈΪ1400×Ö½ÚµÄRTP°üÀ´·¢ËÍ int k=0,l=0; k=nAvFrmLen/nalu_sent_len;//ÐèÒªk¸ö1400×Ö½ÚµÄRTP°ü l=nAvFrmLen%nalu_sent_len;//×îºóÒ»¸öRTP°üµÄÐèҪװÔصÄ×Ö½ÚÊý int t=0; //ÓÃÓÚָʾµ±Ç°·¢Ë͵ÄÊǵڼ¸¸ö·ÖƬRTP°ü g_rtspClients[is].tsvid = g_rtspClients[is].tsvid+timestamp_increse; //rtp_hdr->timestamp=htonl(g_rtspClients[is].tsvid); while(t<=k) { rtp_hdr->seq_no = htons(g_rtspClients[is].seqnum++); if(t==0) { //ÉèÖÃrtp M λ£» rtp_hdr->marker=0; fu_ind =(FU_INDICATOR*)&sendbuf[12]; fu_ind->F= 0; fu_ind->NRI= nIsIFrm; fu_ind->TYPE=28; //ÉèÖÃFU HEADER,²¢½«Õâ¸öHEADERÌîÈësendbuf[13] fu_hdr =(FU_HEADER*)&sendbuf[13]; fu_hdr->E=0; fu_hdr->R=0; fu_hdr->S=1; fu_hdr->TYPE=nNaluType; nalu_payload=&sendbuf[14]; memcpy(nalu_payload,buffer,nalu_sent_len); //memcpy(nalu_payload,buffer+4,nalu_sent_len); bytes=nalu_sent_len+14; sendto( udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); //fwrite(nalu_payload,nalu_sent_len, 1, fp); //fwrite(sendbuf,bytes, 1, fp); t++; } else if(k==t) { //ÉèÖÃrtp M λ£»µ±Ç°´«ÊäµÄÊÇ×îºóÒ»¸ö·ÖƬʱ¸ÃλÖÃ1 rtp_hdr->marker=1; fu_ind =(FU_INDICATOR*)&sendbuf[12]; fu_ind->F= 0 ; fu_ind->NRI= nIsIFrm ; fu_ind->TYPE=28; //ÉèÖÃFU HEADER,²¢½«Õâ¸öHEADERÌîÈësendbuf[13] fu_hdr =(FU_HEADER*)&sendbuf[13]; fu_hdr->R=0; fu_hdr->S=0; fu_hdr->TYPE= nNaluType; fu_hdr->E=1; nalu_payload=&sendbuf[14]; memcpy(nalu_payload,buffer+t*nalu_sent_len,l); //memcpy(nalu_payload,buffer+4+t*nalu_sent_len,l); bytes=l+14; sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); //fwrite(nalu_payload,l, 1, fp); //fwrite(sendbuf,bytes, 1, fp); t++; } else if(t<k && t!=0) { //ÉèÖÃrtp M λ£» rtp_hdr->marker=0; //ÉèÖÃFU INDICATOR,²¢½«Õâ¸öHEADERÌîÈësendbuf[12] fu_ind =(FU_INDICATOR*)&sendbuf[12]; fu_ind->F=0; fu_ind->NRI=nIsIFrm; fu_ind->TYPE=28; fu_hdr =(FU_HEADER*)&sendbuf[13]; //fu_hdr->E=0; fu_hdr->R=0; fu_hdr->S=0; fu_hdr->E=0; fu_hdr->TYPE=nNaluType; nalu_payload=&sendbuf[14]; memcpy(nalu_payload,buffer+t*nalu_sent_len,nalu_sent_len); //memcpy(nalu_payload,buffer+4+t*nalu_sent_len,nalu_sent_len); bytes=nalu_sent_len+14; sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server)); //fwrite(sendbuf,bytes, 1, fp); t++; } } } #if 0 { unsigned char testdat[20]; int i; memcpy(testdat,sendbuf,20); printf("[%d]--------------------------------------------------->\n",nAvFrmLen); for(i=0;i<14;i++) { printf("%#.2x\t",testdat[i]); if(i==11) printf("-->\n"); } printf("\n"); printf("<---------------------------------------------------\n\n"); } #endif { #if 0 FILE *fp; unsigned char filename[20]; sprintf(filename, "frame%d.264", framenum); fp = fopen(filename, "ab"); if (!fp) { SAMPLE_PRT("open file failed!\n"); return NULL; } fwrite(buffer,buflen, 1, fp); //fwrite(buffer,buflen, 1, fp); fclose(fp); #endif //fclose(fp); } } return 0; } /****************************************************************************** * funciton : sent H264 stream ******************************************************************************/ HI_S32 SAMPLE_COMM_VENC_Sentjin(VENC_STREAM_S *pstStream) { HI_S32 i,flag=0; for(i=0;i<MAX_RTSP_CLIENT;i++)//have atleast a connect { if(g_rtspClients[i].status == RTSP_SENDING) { flag = 1; break; } } if(flag) { //printf("a"); for (i = 0; i < pstStream->u32PackCount; i++) { HI_S32 lens=0; //HI_S32 j; //HI_S32 lastadd=0; //HI_S32 newadd=0; HI_S32 showflap=0; char sendbuf[320*1024]; //char tmp[640*1024]; lens = pstStream->pstPack[i].u32Len[0]; memcpy(&sendbuf[0],pstStream->pstPack[i].pu8Addr[0],lens); if (pstStream->pstPack[i].u32Len[1] > 0) { memcpy(&sendbuf[lens],pstStream->pstPack[i].pu8Addr[1],lens+pstStream->pstPack[i].u32Len[1]); lens = lens+pstStream->pstPack[i].u32Len[1]; showflap=1; } VENC_Sent(sendbuf,lens); lens = 0; } } return HI_SUCCESS; } void InitRtspServer(void) { int i; pthread_t threadId = 0; for(i=0;i<MAX_CHAN;i++) { memset(&g_rtpPack[i],0,sizeof(RTSP_PACK)); g_rtpPack[i].bIsFree = TRUE; memset(&g_FrmPack[i],0,sizeof(FRAME_PACK)); } memset(g_rtp_playload,0,sizeof(g_rtp_playload)); strcpy(g_rtp_playload,"G726-32"); g_audio_rate = 8000; pthread_mutex_init(&g_sendmutex,NULL); pthread_mutex_init(&g_mutex,NULL); pthread_cond_init(&g_cond,NULL); memset(g_rtspClients,0,sizeof(RTSP_CLIENT)*MAX_RTSP_CLIENT); struct sched_param thdsched; thdsched.sched_priority = 2; //to listen visiting pthread_create(&threadId, NULL, RtspServerListen, NULL); pthread_setschedparam(threadId,SCHED_RR,&thdsched); printf("RTSP:-----Init Rtsp server\n"); #if 0 HI_S32 s32Ret; s32Ret = SAMPLE_VENC_720P_CLASSIC(); //exit if (HI_SUCCESS == s32Ret) printf("program exit normally!\n"); else printf("program exit abnormally!\n"); exitok++; #endif } #ifdef __cplusplus #if __cplusplus } #endif #endif /* End of #ifdef __cplusplus */
/****************************************************************************** 文件名:rtsp_server.h 源作者:http://download.csdn.net/detail/showmove/6570893 时间:2015.06 ******************************************************************************/ #ifndef RTSP_SERVER_H #define RTSP_SERVER_H //#include "rtsp_cmd.h" #if !defined(WIN32) #define __PACKED__ __attribute__ ((__packed__)) #else #define __PACKED__ #endif typedef enum { RTSP_VIDEO=0, RTSP_VIDEOSUB=1, RTSP_AUDIO=2, RTSP_YUV422=3, RTSP_RGB=4, RTSP_VIDEOPS=5, RTSP_VIDEOSUBPS=6 }enRTSP_MonBlockType; struct _RTP_FIXED_HEADER { /**//* byte 0 */ unsigned char csrc_len:4; /**//* expect 0 */ unsigned char extension:1; /**//* expect 1, see RTP_OP below */ unsigned char padding:1; /**//* expect 0 */ unsigned char version:2; /**//* expect 2 */ /**//* byte 1 */ unsigned char payload:7; /**//* RTP_PAYLOAD_RTSP */ unsigned char marker:1; /**//* expect 1 */ /**//* bytes 2, 3 */ unsigned short seq_no; /**//* bytes 4-7 */ unsigned long timestamp; /**//* bytes 8-11 */ unsigned long ssrc; /**//* stream number is used here. */ } __PACKED__; typedef struct _RTP_FIXED_HEADER RTP_FIXED_HEADER; struct _NALU_HEADER { //byte 0 unsigned char TYPE:5; unsigned char NRI:2; unsigned char F:1; }__PACKED__; /**//* 1 BYTES */ typedef struct _NALU_HEADER NALU_HEADER; struct _FU_INDICATOR { //byte 0 unsigned char TYPE:5; unsigned char NRI:2; unsigned char F:1; }__PACKED__; /**//* 1 BYTES */ typedef struct _FU_INDICATOR FU_INDICATOR; struct _FU_HEADER { //byte 0 unsigned char TYPE:5; unsigned char R:1; unsigned char E:1; unsigned char S:1; } __PACKED__; /**//* 1 BYTES */ typedef struct _FU_HEADER FU_HEADER; struct _AU_HEADER { //byte 0, 1 unsigned short au_len; //byte 2,3 unsigned short frm_len:13; unsigned char au_index:3; } __PACKED__; /**//* 1 BYTES */ typedef struct _AU_HEADER AU_HEADER; #endif
凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!