/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more 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;
}
i