📄 rtsp.c
字号:
int bytesRead = 0; // because we've already read the first byte unsigned bytesReadNow = 0; fSocketNum = socketNum; if (responseBufferSize == 0) return 0; // just in case... *(responseBuffer) = '\0'; while (bytesRead < (int)responseBufferSize) { lastToCheck = NULL; if(blockUntilReadable(fSocketNum)<=0) { fprintf(stderr,"socket is unreadable\n"); break; } bytesReadNow = recv(fSocketNum,(unsigned char*)(responseBuffer+bytesRead),1, 0); if (bytesReadNow != 1) { fprintf(stderr,"RTSP response was truncated\n"); break; } bytesRead++; lastToCheck = responseBuffer+bytesRead-4; if (lastToCheck < responseBuffer) continue; p = lastToCheck; if (*p == '\r' && *(p+1) == '\n' && *(p+2) == '\r' && *(p+3) == '\n') { *(responseBuffer+bytesRead)= '\0'; // Before returning, trim any \r or \n from the start: while (*responseBuffer == '\r' || *responseBuffer == '\n'||*responseBuffer!=0x52) { ++responseBuffer; --bytesRead; } if(*responseBuffer == 0x52)//&&responseBuffer[1]=='T'&&responseBuffer[2]=='S'&&responseBuffer[3]=='P') return bytesRead; } } return bytesRead;}/////////////////////char* parseSDPLine(char* inputLine){ char *ptr; for (ptr = inputLine; *ptr != '\0'; ++ptr) { if (*ptr == '\r' || *ptr == '\n') { ++ptr; while (*ptr == '\r' || *ptr == '\n') ++ptr; if (ptr[0] == '\0') ptr = NULL; // special case for end break; } } if (inputLine[0] == '\r' || inputLine[0] == '\n') return ptr; if (strlen(inputLine) < 2 || inputLine[1] != '=' || inputLine[0] < 'a' || inputLine[0] > 'z') { fprintf(stderr,"Invalid SDP line \n"); return NULL; } return ptr;}char * parseSDPAttribute_rtpmap(char* sdpLine,unsigned* rtpTimestampFrequency,unsigned *fnumChannels) { unsigned rtpmapPayloadFormat; unsigned numChannels = 1; char* codecName = strDupSize(sdpLine); // ensures we have enough space if (sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u/%u", &rtpmapPayloadFormat, codecName, rtpTimestampFrequency, &numChannels) == 4 || sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u", &rtpmapPayloadFormat, codecName, rtpTimestampFrequency) == 3 || sscanf(sdpLine, "a=rtpmap: %u %s", &rtpmapPayloadFormat, codecName) == 2) { *fnumChannels = numChannels; return strDup(codecName); } free(codecName); return NULL;}char * parseSDPAttribute_control(char* sdpLine) { char* controlPath = strDupSize(sdpLine); // ensures we have enough space if (sscanf(sdpLine, "a=control:%s", controlPath) == 1) { return strDup(controlPath); } free(controlPath); return NULL;}int parseSDPAttribute_range(char* sdpLine) { int parseSuccess = -1; char playEndTime[32]; char temp[32]; int index = 0; int j = 0; unsigned long endtime = 0; char *endstr; int k; int i,num; if (sscanf(sdpLine, "a=range:npt=0- %s", playEndTime)==1) { parseSuccess = 0; for(index = 0;index<strlen(playEndTime);index++) { if(playEndTime[index]!='.') { temp[j] = playEndTime[index]; j++; } else { for(k=index+1;k<strlen(playEndTime);k++) { temp[j] = playEndTime[k]; j++; PotPos++; } break; } } temp[j] = '\0'; endtime = strtoul(temp,&endstr,10); if (endtime > fMaxPlayEndTime) { if(PotPos>=3) { num = 1; for(i = 0;i<PotPos-3;i++) { num = 10*num; } fMaxPlayEndTime = endtime/num; } else { num = 1; for(i = 0;i<3-PotPos;i++) { num = 10*num; } fMaxPlayEndTime = endtime*num; } PotPos = 1000; } fprintf(stderr,"fMaxPlayEndTime is %lu\n",fMaxPlayEndTime); } return parseSuccess;}char * parseSDPAttribute_fmtp(char* sdpLine) { char* lineCopy; char* line; char* valueStr; char* c; do { if (strncmp(sdpLine, "a=fmtp:", 7) != 0) break; sdpLine += 7; while (isdigit(*sdpLine)) ++sdpLine; lineCopy = strDup(sdpLine); line = lineCopy; for (c = line; *c != '\0'; ++c) *c = tolower(*c); while (*line != '\0' && *line != '\r' && *line != '\n') { valueStr = strDupSize(line); if (sscanf(line, " config = %[^; \t\r\n]", valueStr) == 1) { free(lineCopy); return strDup(valueStr); } free(valueStr); while (*line != '\0' && *line != '\r' && *line != '\n'&& *line != ';') ++line; while (*line == ';') ++line; } free(lineCopy); } while (0); return NULL;}struct MediaAttribute * GetMediaAttrbute(struct MediaAttribute *Attribute,struct MediaSubsession * subsession,int subsessionNum){ struct MediaSubsession *mediasub; int len = 0; mediasub = subsession; while(subsessionNum>0) { if(strcmp(mediasub->fCodecName,"MP4V-ES") == 0) { Attribute->fVideoFrequency = mediasub->frtpTimestampFrequency; Attribute->fVideoPayloadFormat = mediasub->fRTPPayloadFormat; len = strlen(mediasub->fConfig); memcpy(Attribute->fConfigAsc,mediasub->fConfig,len); a_hex(mediasub->fConfig,Attribute->fConfigHex,len); Attribute->fConfigHexLen = len/2; parse_vovod(Attribute->fConfigHex,Attribute->fConfigHexLen,&(Attribute->fVideoFrameRate),&(Attribute->fTimeIncBits),&(Attribute->fVideoWidth),&(Attribute->fVideoHeight)); Attribute->fixed_vop_rate = fixed_vop_rate; VFrameRate = Attribute->fVideoFrameRate; } else if(strcmp(mediasub->fCodecName,"MPA") == 0||strcmp(mediasub->fCodecName,"mpeg4-generic") == 0) { Attribute->fAudioFrequency = mediasub->frtpTimestampFrequency; Attribute->fAudioPayloadFormat = mediasub->fRTPPayloadFormat; Attribute->fTrackNum = mediasub->fNumChannels; } mediasub = mediasub->fNext; subsessionNum--; } return Attribute;}struct MediaSubsession * initializeWithSDP(char* sdpDescription,int *SubsessionNum){ int Num = 0; char* sdpLine = sdpDescription; char* nextSDPLine = NULL; struct MediaSubsession *fSubsessionsHead; struct MediaSubsession *fSubsessionsTail; struct MediaSubsession* subsession; char* mediumName; char * CodecName; char * ControlPath; char *Config; unsigned payloadFormat; if (sdpDescription == NULL) return NULL; fSubsessionsHead = fSubsessionsTail = NULL; while (1) { if ((nextSDPLine = parseSDPLine(sdpLine)) == NULL) { return NULL; } if (sdpLine[0] == 'm') { Num++; break; } sdpLine = nextSDPLine; if (sdpLine == NULL) break; // there are no m= lines at all if (!parseSDPAttribute_range(sdpLine)) continue;//check a=range:npt= } while (sdpLine != NULL) { subsession = (struct MediaSubsession*)malloc(sizeof(struct MediaSubsession)); if (subsession == NULL) { fprintf(stderr,"Unable to create new MediaSubsession\n"); return NULL; } if (fSubsessionsTail == NULL) { fSubsessionsHead = fSubsessionsTail = subsession; } else { fSubsessionsTail->fNext = subsession; subsession->fNext = NULL; fSubsessionsTail = subsession; } mediumName = strDupSize(sdpLine); if (sscanf(sdpLine, "m=%s %hu RTP/AVP %u",mediumName, &subsession->fClientPortNum, &payloadFormat) != 3 || payloadFormat > 127) { fprintf(stderr,"Bad SDP line\n"); free(mediumName); return NULL; } subsession->fMediumName = strDup(mediumName); free(mediumName); subsession->fRTPPayloadFormat = payloadFormat; while (1) { sdpLine = nextSDPLine;//a=rtpmap... if (sdpLine == NULL) break; // we've reached the end if ((nextSDPLine = parseSDPLine(sdpLine)) == NULL) { *SubsessionNum = Num; return fSubsessionsHead; //下移一行 } if (sdpLine[0] == 'm') { Num ++; break; // we've reached the next subsession } // Check for various special SDP lines that we understand: CodecName = strDupSize(sdpLine); if ((CodecName = parseSDPAttribute_rtpmap(sdpLine,&(subsession->frtpTimestampFrequency),&(subsession->fNumChannels)))!=NULL) { subsession->fCodecName = strDup(CodecName); if(strcmp(CodecName,"MP4V-ES") == 0) { VTimestampFrequency = subsession->frtpTimestampFrequency; VPayloadType = subsession->fRTPPayloadFormat; } else if(strcmp(CodecName,"MPA") == 0||strcmp(CodecName,"mpeg4-generic") == 0) { ATimestampFrequency = subsession->frtpTimestampFrequency; APayloadType = subsession->fRTPPayloadFormat; } free(CodecName); continue; } ControlPath = strDupSize(sdpLine); if ((ControlPath = parseSDPAttribute_control(sdpLine))!=NULL) { subsession->fControlPath = strDup(ControlPath); free(ControlPath); continue; } Config = strDupSize(sdpLine); if ((Config = parseSDPAttribute_fmtp(sdpLine))!=NULL) { subsession->fConfig = strDup(Config); free(Config); continue; } } } *SubsessionNum = Num; return fSubsessionsHead; }int blockUntilwriteable(int socket)//, struct timeval* timeout){ int result = -1; static unsigned numFds; fd_set wd_set; do { FD_ZERO(&wd_set); if (socket < 0) break; FD_SET((unsigned) socket, &wd_set); numFds = socket+1; result = select(numFds, NULL, &wd_set, NULL,0);// timeout); if (result == 0) { break; // this is OK - timeout occurred } else if(result <= 0) { fprintf(stderr, "select() error\n "); break; } if (!FD_ISSET(socket, &wd_set)) { fprintf(stderr, "select() error - !FD_ISSET\n"); break; } } while (0); return result;};int blockUntilReadable(int socket)//, struct timeval* timeout) { fd_set rd_set; int result = -1; static unsigned numFds; do { FD_ZERO(&rd_set); if (socket < 0) break; FD_SET((unsigned) socket, &rd_set); numFds = socket+1; result = select(numFds, &rd_set, NULL, NULL,0); if (result == 0) { break; // this is OK - timeout occurred } else if (result <= 0) { fprintf(stderr, "select() error\n "); break; } if (!FD_ISSET(socket, &rd_set)) { fprintf(stderr, "select() error - !FD_ISSET\n"); break; } } while (0); return result;}int getSDPDescriptionFromURL(int socketNum,char* url,char* Description){ int fSocketNum; char *readBuffer;//[MAX_READBUFSIZE+1]; char* readBuf; int bytesRead; char* cmdFmt ="DESCRIBE %s RTSP/1.0\r\nCSeq: %d\r\nAccept: application/sdp\r\n%s\r\n"; unsigned cmdSize = 0; char* cmd = NULL; char* firstLine; char* nextLineStart; unsigned responseCode; int contentLength = -1; char* lineStart; unsigned numExtraBytesNeeded; char* ptr; int bytesRead2; readBuffer = (char *)malloc((MAX_READBUFSIZE+1)*sizeof(char)); if(readBuffer == NULL) { fprintf(stderr,"failed to alloc the memory\n"); return -1; } memset(readBuffer,0,MAX_READBUFSIZE+1); readBuf =readBuffer; //fprintf(stderr,"start alloc cmd\n"); cmdSize = strlen(cmdFmt) + strlen(url) + 20 /* max int len */+ strlen(UserAgentHeaderStr); cmd = (char *)malloc((cmdSize+1)*sizeof(char)); if(cmd ==NULL) { fprintf(stderr,"failed to alloc the memory\n"); free(readBuffer); return -1; } //fprintf(stderr,"alloc cmd successful\n"); memset(cmd,0,cmdSize+1); fSocketNum = socketNum; do { // Send the DESCRIBE command: //fprintf(stderr,"Send the DESCRIBE command\n"); sprintf(cmd, cmdFmt,url,++fCSeq,UserAgentHeaderStr); //发送description 请求 //fprintf(stderr,"start blockUntilwriteable\n"); if(blockUntilwriteable(fSocketNum)<=0) { fprintf(stderr,"socket is unwriteable\n"); break; } //fprintf(stderr,"start send\n"); if (send(fSocketNum, cmd, strlen(cmd), 0)<0) { fprintf(stderr,"DESCRIBE send() failed\n "); break; } //fprintf(stderr,"DESCRIBE send() successful\n"); // Get the response from the server: //fprintf(stderr,"Get the response from the server\n"); bytesRead = getResponse(fSocketNum,readBuf, MAX_READBUFSIZE); if (bytesRead <= 0) break; //fprintf(stderr,"DESCRIBE response-%d:\n%s\n",fCSeq,readBuf); //Received DESCRIBE response // Inspect the first line to check whether it's a result code that // we can handle. firstLine = readBuf; nextLineStart = getLine(firstLine); if (sscanf(firstLine, "%*s%u", &responseCode) != 1) { fprintf(stderr,"no response code in line\n"); break; } if (responseCode != 200) { fprintf(stderr,"cannot handle DESCRIBE response\n"); break; } // Skip every subsequent header line, until we see a blank line // The remaining data is assumed to be the SDP descriptor that we want. // We should really do some checking on the headers here - e.g., to // check for "Content-type: application/sdp", "Content-base", // "Content-location", "CSeq", etc. ##### //fprintf(stderr,"start get Content-Length\n"); while (1) { lineStart = nextLineStart; if (lineStart == NULL||lineStart[0] == '\0') break; nextLineStart = getLine(lineStart); if (sscanf(lineStart, "Content-Length: %d", &contentLength) == 1 || sscanf(lineStart, "Content-length: %d", &contentLength) == 1) if(contentLength>0) { if (contentLength < 0) { fprintf(stderr,"Bad Content-length\n"); break; } // Use the remaining data as the SDP descr, but first, check // the "Content-length:" header (if any) that we saw. We may need to // read more data, or we may have extraneous data in the buffer. //bodyStart = nextLineStart; // We saw a "Content-length:" header //numBodyBytes = &readBuf[bytesRead] - bodyStart; //if (contentLength > (int)numBodyBytes) //{ // We need to read more data. First, make sure we have enough // space for it: numExtraBytesNeeded = contentLength;// - numBodyBytes; // Keep reading more data until we have enough: bytesRead = 0; //fprintf(stderr,"start recv %d\n",contentLength); while (numExtraBytesNeeded > 0) { if(blockUntilReadable(fSocketNum)<=0) { fprintf(stderr,"socket is unreadable\n"); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -