Basic RTSP protocol support - advanced support is nog nodig, maar testen kan. Tip: gebruik vlc als test client, die lijkt goed te werken.
This commit is contained in:
		
							parent
							
								
									dff5e311df
								
							
						
					
					
						commit
						67cff04775
					
				
					 2 changed files with 156 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -13,6 +13,15 @@
 | 
			
		|||
#include <sys/types.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
 | 
			
		||||
unsigned int getNowMS(){
 | 
			
		||||
  timeval t;
 | 
			
		||||
  gettimeofday(&t, 0);
 | 
			
		||||
  return t.tv_sec + t.tv_usec/1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//for connection to server
 | 
			
		||||
#include "../sockets/SocketW.h"
 | 
			
		||||
bool ready4data = false;//set to true when streaming starts
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +30,7 @@ bool stopparsing = false;
 | 
			
		|||
timeval lastrec;
 | 
			
		||||
 | 
			
		||||
#include "../util/flv_sock.cpp" //FLV parsing with SocketW
 | 
			
		||||
#include "rtsp.cpp"
 | 
			
		||||
 | 
			
		||||
int main(){
 | 
			
		||||
  unsigned int ts;
 | 
			
		||||
| 
						 | 
				
			
			@ -34,18 +44,13 @@ int main(){
 | 
			
		|||
  FD_ZERO(&pollset);//clear the polling set
 | 
			
		||||
  FD_SET(0, &pollset);//add stdin to polling set
 | 
			
		||||
 | 
			
		||||
  //first timestamp set
 | 
			
		||||
  firsttime = getNowMS();
 | 
			
		||||
 | 
			
		||||
  DEBUG("Starting processing...\n");
 | 
			
		||||
  while (!feof(stdin)){
 | 
			
		||||
  while (!feof(stdin) && !stopparsing){
 | 
			
		||||
    //select(1, &pollset, 0, 0, &timeout);
 | 
			
		||||
    //only parse input from stdin if available or not yet init'ed
 | 
			
		||||
    //FD_ISSET(0, &pollset) || //NOTE: Polling does not work? WHY?!? WHY DAMN IT?!?
 | 
			
		||||
    if (!ready4data && !stopparsing){
 | 
			
		||||
      //JARON: verwerk rtsp data
 | 
			
		||||
    }
 | 
			
		||||
    if (ready4data){
 | 
			
		||||
    if (!ready4data && !stopparsing){ParseRTSPPacket();}
 | 
			
		||||
    if (ready4data && !stopparsing){
 | 
			
		||||
      if (!inited){
 | 
			
		||||
        //we are ready, connect the socket!
 | 
			
		||||
        if (!ss.connect("/tmp/shared_socket")){
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +60,8 @@ int main(){
 | 
			
		|||
        FLV_Readheader(ss);//read the header, we don't want it
 | 
			
		||||
        DEBUG("Header read, starting to send video data...\n");
 | 
			
		||||
        
 | 
			
		||||
        //ERIK: Connect de RTP lib hier. De poorten weet je nog niet, dus doe dit later pas, als mijn deel af is.
 | 
			
		||||
        //ERIK: Connect de RTP lib hier.
 | 
			
		||||
        //Poorten vind je in clientport en serverport, die worden gevuld door mijn deel.
 | 
			
		||||
        
 | 
			
		||||
        inited = true;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										141
									
								
								Connector_RTSP/rtsp.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								Connector_RTSP/rtsp.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,141 @@
 | 
			
		|||
#include <stdlib.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
int clientport = 0;
 | 
			
		||||
int serverport = 6256;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RTSPPack{
 | 
			
		||||
  public:
 | 
			
		||||
    std::map<std::string, std::string> params;
 | 
			
		||||
    std::string data;
 | 
			
		||||
};//RTSPPack
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RTSPPack GetRTSPPacket(){
 | 
			
		||||
  std::string tmp, a, b;
 | 
			
		||||
  RTSPPack ret;
 | 
			
		||||
  bool first = true;
 | 
			
		||||
  std::size_t f;
 | 
			
		||||
  do {
 | 
			
		||||
    std::getline(std::cin, tmp);
 | 
			
		||||
    if (first){
 | 
			
		||||
      f = tmp.find_first_of(' ');
 | 
			
		||||
      if (f != std::string::npos){
 | 
			
		||||
        a = tmp.substr(0, f);
 | 
			
		||||
        tmp = tmp.substr(f+1);
 | 
			
		||||
        f = tmp.find('\r');
 | 
			
		||||
        if (f != std::string::npos){tmp.erase(f);}
 | 
			
		||||
        ret.params["request"] = a;
 | 
			
		||||
        DEBUG("Request type %s\n", a.c_str());
 | 
			
		||||
        f = tmp.find_first_of(' ');
 | 
			
		||||
        if (f != std::string::npos){
 | 
			
		||||
          a = tmp.substr(0, f);
 | 
			
		||||
          ret.params["url"] = a;
 | 
			
		||||
          DEBUG("URL=%s\n", a.c_str());
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      first = false;
 | 
			
		||||
    }else{
 | 
			
		||||
      f = tmp.find_first_of(':');
 | 
			
		||||
      if (f != std::string::npos){
 | 
			
		||||
        a = tmp.substr(0, f);
 | 
			
		||||
        b = tmp.substr(f+2);
 | 
			
		||||
        f = b.find('\r');
 | 
			
		||||
        if (f != std::string::npos){b.erase(f);}
 | 
			
		||||
        ret.params[a] = b;
 | 
			
		||||
        DEBUG("Adding '%s' as '%s'\n", a.c_str(), b.c_str());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }while(tmp.length() > 2);
 | 
			
		||||
  DEBUG("End of request headers\n");
 | 
			
		||||
  int len = 0;
 | 
			
		||||
  if (ret.params["Content-Length"] != ""){
 | 
			
		||||
    len = atoi(ret.params["Content-Length"].c_str());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (len > 0){
 | 
			
		||||
    DEBUG("There is a length %i request body:\n", len);
 | 
			
		||||
    char * data = (char*)malloc(len);
 | 
			
		||||
    fread(&data, 1, len, stdin);
 | 
			
		||||
    ret.data = data;
 | 
			
		||||
    free(data);
 | 
			
		||||
    DEBUG("%s\nEnd of body data.\n", ret.data.c_str());
 | 
			
		||||
  }else{
 | 
			
		||||
    DEBUG("No request body.\n");
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}//GetRTSPPacket
 | 
			
		||||
 | 
			
		||||
void RTSPReply(RTSPPack & q, RTSPPack & a, std::string retval){
 | 
			
		||||
  if (q.params["CSeq"] != ""){a.params["CSeq"] = q.params["CSeq"];}
 | 
			
		||||
  if (q.params["Require"] != ""){a.params["Unsupported"] = q.params["Require"];}
 | 
			
		||||
  if (a.data != ""){
 | 
			
		||||
    char * len = (char*)malloc(10);
 | 
			
		||||
    sprintf(len, "%i", (int)a.data.length());
 | 
			
		||||
    a.params["Content-Length"] = len;
 | 
			
		||||
    free(len);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout << "RTSP/1.0 " << retval << "\r\n";
 | 
			
		||||
 | 
			
		||||
  std::map<std::string,std::string>::iterator it;
 | 
			
		||||
  for (it = a.params.begin(); it != a.params.end(); it++){
 | 
			
		||||
    std::cout << (*it).first << ": " << (*it).second << "\r\n";
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << "\r\n" << a.data;
 | 
			
		||||
  std::cout.flush();
 | 
			
		||||
}//RTSPReply
 | 
			
		||||
 | 
			
		||||
void ParseRTSPPacket(){
 | 
			
		||||
  RTSPPack q = GetRTSPPacket();
 | 
			
		||||
  RTSPPack a;
 | 
			
		||||
  
 | 
			
		||||
  //parse OPTIONS request
 | 
			
		||||
  if (q.params["request"] == "OPTIONS"){
 | 
			
		||||
    a.params["Public"] = "SETUP, TEARDOWN, OPTIONS, DESCRIBE, PLAY";
 | 
			
		||||
    RTSPReply(q, a, "200 OK");
 | 
			
		||||
    DEBUG("Sent OPTIONS reply\n");
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //parse DESCRIBE request
 | 
			
		||||
  if (q.params["request"] == "DESCRIBE"){
 | 
			
		||||
    a.params["Content-Type"] = "application/sdp";
 | 
			
		||||
    a.data = "v=0\r\no=- 0 0 IN IP4 ddvtech.com\r\ns=PLSServer\r\nc=IN IP4 0.0.0.0\r\na=recvonly\r\nt=0 0\r\nm=video 0 RTP/AVP 98\r\na=rtpmap:98 H264/90000\r\nm=audio 0 RTP/AVP 99\r\na=rtpmap:99 MPEG4-GENERIC/11025/1\r\n";
 | 
			
		||||
    RTSPReply(q, a, "200 OK");
 | 
			
		||||
    DEBUG("Sent DESCRIBE reply\n");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //parse SETUP request
 | 
			
		||||
  if (q.params["request"] == "SETUP"){
 | 
			
		||||
    size_t f, g;
 | 
			
		||||
    std::string s;
 | 
			
		||||
    f = q.params["Transport"].rfind('=')+1;
 | 
			
		||||
    g = q.params["Transport"].rfind('-');
 | 
			
		||||
    clientport = atoi(q.params["Transport"].substr(f, g-f).c_str());
 | 
			
		||||
    DEBUG("Requested client base port: %i\n", clientport);
 | 
			
		||||
    char * len = (char*)malloc(30);
 | 
			
		||||
    sprintf(len, ";server_port=%i-%i", serverport, serverport+1);
 | 
			
		||||
    a.params["Transport"] = len;
 | 
			
		||||
    a.params["Transport"] = q.params["Transport"] + a.params["Transport"];
 | 
			
		||||
    free(len);
 | 
			
		||||
    a.params["Session"] = "puddingbroodjes";
 | 
			
		||||
    RTSPReply(q, a, "200 OK");
 | 
			
		||||
    DEBUG("Sent SETUP reply\n");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //parse PLAY request
 | 
			
		||||
  if (q.params["request"] == "PLAY"){
 | 
			
		||||
    RTSPReply(q, a, "200 OK");
 | 
			
		||||
    ready4data = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //parse TEARDOWN request
 | 
			
		||||
  if (q.params["request"] == "TEARDOWN"){
 | 
			
		||||
    RTSPReply(q, a, "200 OK");
 | 
			
		||||
    stopparsing = true;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
}//ParseRTSPPacket
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue