⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp.c

📁 一个简单的RTSP客户端实现源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********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 + -