📄 rtsp.c
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.**********/#include <string.h>#include <stdio.h>#include "rtsp.h"#include "bitstream.h"// Forward function definitions:unsigned fCSeq = 0;char const* const UserAgentHeaderStr = "User-Agent: simplertsp v20051123\r\n";unsigned const parseBufferSize = 100;char *fBaseURL=NULL;char *fLastSessionId = NULL;unsigned long fMaxPlayEndTime = 0;unsigned VTimestampFrequency = 0;unsigned ATimestampFrequency = 0;unsigned char VPayloadType = 0;unsigned char APayloadType = 0;int PotPos = 0;unsigned long VFrameRate = 0;uint32_t fixed_vop_rate = 0;unsigned long vloopNum = 0;int init_rtsp(char *url,struct MediaAttribute *Attribute){ char* sdpDescription = NULL; struct MediaSubsession *subsession = NULL; int subsessionNum = 0; int socketNum = -1; int result = -1; fBaseURL = strDup(url); fprintf(stderr,"start openConnectionFromURL %s\n",fBaseURL); socketNum = openConnectionFromURL(fBaseURL); fprintf(stderr,"socketNum is %d\n",socketNum); if(socketNum<0) { fprintf(stderr,"failed to open the URL\n"); return (-1); } sdpDescription = (char*)malloc(MAX_READBUFSIZE*sizeof(char)); if(sdpDescription == NULL) { fprintf(stderr,"failed to alloc the memory\n"); return (-1); } memset(sdpDescription,0,MAX_READBUFSIZE); fprintf(stderr,"start getSDPDescriptionFromURL \n"); result = getSDPDescriptionFromURL(socketNum,fBaseURL,sdpDescription); if (result<0) { fprintf(stderr,"Failed to get a SDP description from URL\n"); free(sdpDescription); close(socketNum); return (-1); } fprintf(stderr,"Opened URL %s Sreturning a SDP description:\n%s\n",fBaseURL,sdpDescription); fprintf(stderr,"start initializeWithSDP\n"); subsession = initializeWithSDP(sdpDescription,&subsessionNum); if(subsession == NULL) { fprintf(stderr,"Failed to initialize a SDP description\n"); free(sdpDescription); close(socketNum); return (-1); } GetMediaAttrbute(Attribute,subsession,subsessionNum); setupStreams(socketNum,subsession,subsessionNum); startPlayingStreams(socketNum,subsession,subsessionNum); free(sdpDescription); return socketNum;}int RTP_ReadHandler(int socketNum,struct ResultData* data){ unsigned char c; unsigned char streamChannelId; unsigned short size; unsigned fNextTCPReadSize; int result = 0; do { do { result = recv(socketNum, &c, 1, 0); if (result <=0) { // error reading TCP socket //fprintf(stderr,"vloopNum is : %lu\n",vloopNum); fprintf(stderr,"error reading TCP socket\n"); return 0; } } while (c != '$'); if (recv(socketNum, &streamChannelId, 1, 0)!= 1) break; if (recv(socketNum, (unsigned char*)&size, 2,0) != 2) break; fNextTCPReadSize = ntohs(size); return networkReadHandler(socketNum,&fNextTCPReadSize,data); } while (0); return -1;}void clearup(int socketNum){ //teardownMediaSession(socketNum); if(fBaseURL !=NULL) free(fBaseURL); if(fLastSessionId !=NULL) free(fLastSessionId); if(socketNum>=0) { close(socketNum); }}void startPlayingStreams(int socketNum,struct MediaSubsession *subsession,int subsessionNum){ if(playMediaSession(socketNum,0,-1)) { fprintf(stderr,"Play MediaSession failed\n"); exit(0); } fprintf(stderr,"Play MediaSession successful\n");}void setupStreams(int socketNum,struct MediaSubsession *subsession,int subsessionNum) { struct MediaSubsession *mediasub; mediasub = subsession; while(subsessionNum>0) { if(setupMediaSubsession(socketNum,mediasub)) { fprintf(stderr,"Setup MediaSubsession Failed\n"); exit(0); } mediasub = mediasub->fNext; subsessionNum--; } fprintf(stderr,"Setup Streams successful\n");}int handleRead(int socketNum,unsigned char* buffer,unsigned bufferMaxSize,unsigned *bytesRead,unsigned* NextTCPReadSize) { int readSuccess = -1; unsigned totBytesToRead; unsigned curBytesToRead; unsigned curBytesRead; if (socketNum < 0) { fprintf(stderr,"no socket active\n"); return -1; } else { // Read from the TCP connection: *bytesRead = 0; totBytesToRead = *NextTCPReadSize; *NextTCPReadSize = 0; if (totBytesToRead > bufferMaxSize) totBytesToRead = bufferMaxSize; curBytesToRead = totBytesToRead; while ((curBytesRead = recv(socketNum,&buffer[*bytesRead], curBytesToRead,0)) > 0) { (*bytesRead) += curBytesRead; if ((*bytesRead) >= totBytesToRead) break; curBytesToRead -= curBytesRead; } if (curBytesRead <= 0) { *bytesRead = 0; readSuccess = -1; } else { readSuccess = 0; } } return readSuccess;}unsigned char* skip(unsigned char * buffer,unsigned numBytes) { buffer = buffer + numBytes; return buffer;} int networkReadHandler(int socketNum,unsigned *NextTCPReadSize,struct ResultData* data){ unsigned bytesRead; unsigned datasize; unsigned rtpHdr; unsigned char *buffer; int rtpMarkerBit; unsigned long rtpTimestamp; static unsigned long LVrtpTimestamp = 0; static unsigned long LArtpTimestamp = 0; unsigned rtpSSRC; unsigned cc; unsigned char payloadType = 0; static unsigned long subTime = 0; static unsigned long MaxFrameNum = 0; //static unsigned long vloopNum = 0; static unsigned long aloopNum = 0; static unsigned long audioFirstTimestamp = 0; static unsigned long vedioFirstTimestamp = 0; unsigned extHdr; unsigned remExtSize; unsigned numPaddingBytes; unsigned short rtpSeqNo; static unsigned long time_inc; static unsigned subTimeFlag = 0; unsigned char *bufptr;//[MAX_PACKET_SIZE]; buffer = data->buffer; bufptr = (unsigned char *)malloc(MAX_PACKET_SIZE*sizeof(unsigned char)); if(bufptr == NULL) { fprintf(stderr,"alloc failed\n"); return -1; } memset(bufptr,0,MAX_PACKET_SIZE); do { if(handleRead(socketNum,buffer,MAX_PACKET_SIZE,&bytesRead,NextTCPReadSize)) break; memcpy(bufptr,buffer,bytesRead); datasize = bytesRead; // Check for the 12-byte RTP header: if (datasize < 12) break; rtpHdr = ntohl(*(unsigned*)(buffer)); buffer = skip(buffer,4); datasize -=4; rtpMarkerBit = (rtpHdr&0x00800000) >> 23; rtpTimestamp = ntohl(*(unsigned*)(buffer)); buffer = skip(buffer,4); datasize -=4; rtpSSRC = ntohl(*(unsigned*)(buffer)); buffer = skip(buffer,4); datasize -=4; if ((rtpHdr&0xC0000000) != 0x80000000) break; cc = (rtpHdr>>24)&0xF; if (datasize < cc) break; buffer = skip(buffer,cc); datasize-=cc; // Check for (& ignore) any RTP header extension if (rtpHdr&0x10000000) { fprintf(stderr,"1 datasize is %u\n",datasize); if (datasize < 4) break; extHdr = ntohl(*(unsigned*)(buffer)); buffer = skip(buffer,4); datasize -=4; remExtSize = 4*(extHdr&0xFFFF); if (datasize < remExtSize) break; buffer = skip(buffer,remExtSize); datasize -= remExtSize; fprintf(stderr,"2 datasize is %u\n",datasize); } // Discard any padding bytes: if (rtpHdr&0x20000000) { if (datasize == 0) break; numPaddingBytes = (unsigned)(buffer)[datasize-1]; if (datasize < numPaddingBytes) break; if (numPaddingBytes > datasize) numPaddingBytes = datasize; datasize -= numPaddingBytes; } // Check the Payload Type. payloadType = (unsigned char)((rtpHdr&0x007F0000)>>16); rtpSeqNo = (unsigned short)(rtpHdr&0xFFFF); if(payloadType == VPayloadType) { if(vloopNum == 0) { vedioFirstTimestamp = rtpTimestamp; LVrtpTimestamp = rtpTimestamp; } if(rtpTimestamp<LVrtpTimestamp) break; if(rtpTimestamp>=LVrtpTimestamp) { // fprintf(stderr,"LVrtpTimestamp is %lu;rtpTimestamp is %lu\n",LVrtpTimestamp,rtpTimestamp); LVrtpTimestamp = rtpTimestamp; } memcpy(data->buffer,buffer,datasize); data->len = datasize; data->fRTPPayloadFormat = payloadType; data->frtpTimestamp = rtpTimestamp; data->frtpMarkerBit = rtpMarkerBit; if(rtpTimestamp>vedioFirstTimestamp&&!subTimeFlag) { if(!fixed_vop_rate) { subTime = rtpTimestamp-vedioFirstTimestamp; time_inc = VTimestampFrequency/subTime; VFrameRate = VTimestampFrequency*1000/subTime; fprintf(stderr,"time_inc is %lu\n",time_inc); if(time_inc<24) { time_inc = 24; VFrameRate = 24000*1000/1001; } fprintf(stderr,"subTime is %lu\n",subTime); fprintf(stderr,"time_inc is %lu\n",time_inc); MaxFrameNum = fMaxPlayEndTime*(time_inc*10-3)+5000; } else { MaxFrameNum = fMaxPlayEndTime*VFrameRate*10; } subTimeFlag = 1; fprintf(stderr,"VFrameRate is %lu\n",VFrameRate); fprintf(stderr,"fixed_vop_rate is %d\n",fixed_vop_rate); } if(rtpMarkerBit) { vloopNum++; if(MaxFrameNum>0&&vloopNum*10000>=MaxFrameNum) { fprintf(stderr,"vloopNum is : %lu\n",vloopNum); fprintf(stderr,"MaxFrameNum is : %lu\n",MaxFrameNum); //fprintf(stderr,"(rtpTimestamp-vedioFirstTimestamp)/VTimestampFrequency is :%f\n",(double)(rtpTimestamp-vedioFirstTimestamp)/(double)VTimestampFrequency); teardownMediaSession(socketNum); free(bufptr); return 0; } } } else if(payloadType == APayloadType) { if(aloopNum == 0) { audioFirstTimestamp = rtpTimestamp; LArtpTimestamp = rtpTimestamp; } if(rtpTimestamp<LArtpTimestamp) break; if(rtpTimestamp>=LArtpTimestamp) { //fprintf(stderr,"LArtpTimestamp is %lu;rtpTimestamp is %lu\n",LArtpTimestamp,rtpTimestamp); LArtpTimestamp = rtpTimestamp; } datasize -=4; memcpy(buffer,buffer+4,datasize); memcpy(data->buffer,buffer,datasize); data->len = datasize; data->fRTPPayloadFormat = payloadType; data->frtpTimestamp = rtpTimestamp; data->frtpMarkerBit = rtpMarkerBit; if(rtpMarkerBit) aloopNum++; } } while (0); free(bufptr); return -1;}int parseResponseCode(char* line, unsigned int * responseCode) { if (sscanf(line, "%*s%u", responseCode) != 1) { fprintf(stderr,"no response code in line\n"); return -1; } return 0;}int setupMediaSubsession(int socketNum,struct MediaSubsession* subsession) { static int rtpNumber = 0; static int rtcpNumber = 0;// static char *fLastSessionId = NULL; int fSocketNum = socketNum; char* lineStart; char* cmd = NULL; unsigned int cmdSize; unsigned const readBufSize = 10000; char *readBuffer;//[readBufSize+1]; char* readBuf ; char cmdFmt[]= "SETUP %s/%s RTSP/1.0\r\n" "CSeq: %d\r\n" "Transport: RTP/AVP/TCP;unicast;interleaved=%d-%d\r\n" "%s\r\n"; char* firstLine; char* nextLineStart; unsigned responseCode; int bytesRead; char *SessionId; char *Sessionstr; readBuffer = (char *)malloc((readBufSize+1)*sizeof(char)); SessionId = (char *)malloc((readBufSize+1)*sizeof(char)); if(fSocketNum<0) return -1; if(readBuffer == NULL||SessionId == NULL) return -1; memset(readBuffer,0,readBufSize+1); readBuf = readBuffer; do { if (fLastSessionId != NULL) { Sessionstr = (char *)malloc((20+strlen(fLastSessionId))*sizeof(char)); if(Sessionstr == NULL) { fprintf(stderr,"Sessionstr failed to alloc the memory\n"); free(readBuffer); free(SessionId); return -1; } sprintf(Sessionstr, "Session: %s\r\n", fLastSessionId); } else { Sessionstr = ""; } rtcpNumber = rtpNumber + 1; cmdSize = strlen(cmdFmt) + strlen(fBaseURL) + strlen(subsession->fControlPath) + 20 /* max int len */ +2*5 /* max port len */ +strlen(Sessionstr) + strlen(UserAgentHeaderStr); cmd = (char *)malloc((cmdSize+1)*sizeof(char)); if(cmd == NULL) { fprintf(stderr,"cmd failed to alloc the memory\n"); if(Sessionstr[0]!='\0') free(Sessionstr); free(readBuffer); free(SessionId); return -1; } memset(cmd,0,cmdSize); sprintf(cmd, cmdFmt, fBaseURL, subsession->fControlPath, ++fCSeq, rtpNumber, rtcpNumber,Sessionstr,UserAgentHeaderStr); rtpNumber +=2; fprintf(stderr,"SETUP command-%d:\n%s\n",fCSeq,cmd); if (send(fSocketNum,cmd,strlen(cmd),0)<0) { fprintf(stderr,"SETUP send() failed\n"); break; } // Get the response from the server: bytesRead = getResponse(fSocketNum,readBuf, readBufSize); if (bytesRead <= 0) break; fprintf(stderr,"SETUP response-%d:\n%s\n",fCSeq,readBuf); // Inspect the first line to check whether it's a result code 200 firstLine = readBuf; nextLineStart = getLine(firstLine); if (parseResponseCode(firstLine, &responseCode)) break; if (responseCode != 200) { fprintf(stderr,"cannot handle SETUP response\n"); break; } while (1) { lineStart = nextLineStart; if (lineStart == NULL||lineStart[0] == '\0') break; nextLineStart = getLine(lineStart); if (sscanf(lineStart, "Session: %s",SessionId ) == 1) { subsession->fSessionId = strDup(SessionId); if(fLastSessionId!=NULL) free(fLastSessionId); fLastSessionId = strDup(SessionId); break; } //////////////// } if (subsession->fSessionId == NULL) { fprintf(stderr,"Session header is missing in the response\n"); break; } if(Sessionstr[0]!='\0') free(Sessionstr); free(SessionId); free(cmd); free(readBuffer); return 0; } while (0); if(Sessionstr[0]!='\0') free(Sessionstr); free(SessionId); free(cmd); free(readBuffer); return -1;}////////////////////////////int getResponse(int socketNum,char* responseBuffer,unsigned responseBufferSize) { int fSocketNum; char *lastToCheck=NULL; char* p = NULL;//responseBuffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -