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

📄 rtsp.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    do { /* get rtsp reply */	rtsp_hdr->buffer_len += BUFSIZE_1K;	rtsp_hdr->buffer = (char *)xrealloc(rtsp_hdr->buffer,					    rtsp_hdr->buffer_len + 1);	i = recv_data(stream,rtsp_hdr->buffer + total,BUFSIZE_1K);	if(i <= 0) {	    display(MSDL_ERR,"rtsp_recv_header error: recv_data() returned %d\n",i);	    goto failed;	}	total += i;    	rtsp_hdr->buffer[total] = '\0'; /* for rtsp_is_entire_header */    } while(!rtsp_is_entire_header(rtsp_hdr));        /* rtsp_hdr->buffer_size is length in buffer, not the malloc()ed size.  */    rtsp_hdr->buffer_len = total;    rtsp_hdr->buffer[total] = '\0';      ret = rtsp_response_parse(rtsp_hdr);    if(ret < 0) {	display(MSDL_ERR,"response RTSP header parse failed\n");	goto failed;    }    /* push body back !!! */    if(rtsp_hdr->body_len) {	stream_data_push_back(stream,rtsp_hdr->body,rtsp_hdr->body_len);    }      /* rtsp_hdr->buffer *ONLY* contains header, no body follows */    memset(rtsp_hdr->body,0,rtsp_hdr->body_len);    /* dbg */    display(MSDL_DBG,"rtsp header===========\n"	    "%s\n"	    "==(%d bytes)====================\n",	    rtsp_hdr->buffer,strlen(rtsp_hdr->buffer));      /* success */    return rtsp_hdr->status_code;    failed:    if(rtsp_hdr->buffer) free(rtsp_hdr->buffer);    rtsp_hdr->buffer = NULL;    return -1;}/* * set fields which are common in all rtsp packet.  * CSeq and Session field should be present in * every rtsp packet. */int rtsp_set_standard_fields(struct rtsp_ctrl_t *rtsp_ctrl,			     struct rtsp_header_t *rtsp_hdr){    char buf[20];    snprintf(buf,20,"Cseq: %u",rtsp_ctrl->cseq);    rtsp_set_field(rtsp_hdr,buf);      if(rtsp_ctrl->session) {	char *buf2;	buf2 = (char *)xmalloc(strlen(rtsp_ctrl->session) + 15);	sprintf(buf2,"Session: %s",rtsp_ctrl->session);	rtsp_set_field(rtsp_hdr,buf2);	free(buf2);    }    return 0;}/* * send rtsp header (rtsp_hdr->buffer) */int rtsp_send_request(struct stream_t *stream,		      struct rtsp_header_t *rtsp_hdr){    int ret;      /* dbg */    display(MSDL_DBG,"SEND rtsp header ------------>\n"	    "%s\n--(%d bytes)---------------<\n",	    rtsp_hdr->buffer,(int)rtsp_hdr->buffer_len);        ret = xsend(stream->netsock->sock,rtsp_hdr->buffer,rtsp_hdr->buffer_len);      /* OK change stream->stream_ctrl->rtsp_ctrl->cseq!! */    stream->stream_ctrl->rtsp_ctrl->cseq++;      return ret;}/* * set basic stuff and send OPTIONS request. * this can be used to determine  which protocol to use, * depending on its server. *              return value    sock : success *                                -1 : failure */int rtsp_connect(struct stream_t *stream){    int sock;    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct rtsp_ctrl_t *rtsp_ctrl = stream_ctrl->rtsp_ctrl;    struct url_t *url = stream->url;            set_serverinfo(stream->serverinfo,url->hostname,url->port,NULL,0,RTSP_PORT);      rtsp_ctrl->server = NULL;    rtsp_ctrl->cseq = 1;    rtsp_ctrl->server_state = 0;    rtsp_ctrl->server_caps  = 0;    rtsp_ctrl->session = NULL;    rtsp_ctrl->get_media_packet = NULL;    /* make mrl */    rtsp_make_mrl(rtsp_ctrl,stream->serverinfo->host,stream->serverinfo->port,url->filepath);    sock = server_connect(stream->serverinfo->connect_host,stream->serverinfo->connect_port);    if(sock < 0) { /* couldn't connect for some reason. (port closed maybe) */	goto failed;    }        stream->netsock->sock = sock; /* save socket id */    return sock;  failed:    return -1;}/* * make mrl from url and set to rtsp_ctrl->mrl * mrl is "rtsp://server.com:port/path/to/file.foo" * --IMPORTANT-- * request URI must be complete according to RFC */int rtsp_make_mrl(struct rtsp_ctrl_t *rtsp_ctrl,char *host,int port,char *filepath){    int len = 0;    len = strlen(host) + strlen(filepath) + 32; /* 32 is enough */      rtsp_ctrl->mrl = (char *)xmalloc(len);    snprintf(rtsp_ctrl->mrl,len,"rtsp://%s:%i%s",	     host,port,filepath);    return 1;}/* * parse rtsp response * return value:   1 ... success *                -1 ... parse error */int rtsp_parse_response(struct rtsp_ctrl_t *rtsp_ctrl,			struct rtsp_header_t *rtsp_hdr){    char *field;    int answer_cseq;    if((field = rtsp_get_field(rtsp_hdr,"Alert")) != NULL) {	display(MSDL_ERR,"*** Alert ***\n%s\n",field);    }      if((field = rtsp_get_field(rtsp_hdr,"Cseq")) != NULL) {	sscanf(field,"%d",&answer_cseq);	if(answer_cseq != rtsp_ctrl->cseq - 1) {	    /* -1 because cseq is incremented in build_request */	    display(MSDL_DBG,"warning: Cseq mismatch, got %u, expected %u\n",		    answer_cseq,rtsp_ctrl->cseq - 1);	}    }      if((field = rtsp_get_field(rtsp_hdr,"Server")) != NULL) {	while(*field == ' ') field++;	if(rtsp_ctrl->server) { /* already has it */	    if(strcmp(rtsp_ctrl->server,field)) { /* different server */		display(MSDL_DBG,"warning: got different server\n"			"    old: %s\n"			"    new: %s\n",rtsp_ctrl->server,field);		free(rtsp_ctrl->server);		rtsp_ctrl->server = strdup(field);	    }	}	else { /* not set yet */	    rtsp_ctrl->server = strdup(field);	}    }      if((field = rtsp_get_field(rtsp_hdr,"Session")) != NULL) {	while(*field == ' ') field++;	if(rtsp_ctrl->session) {	    if(strcmp(rtsp_ctrl->session,field)) { /* different session */		display(MSDL_DBG,"warning: got different session\n"			"    old: [%s]\n"			"    new: [%s]\n",rtsp_ctrl->session,field);		free(rtsp_ctrl->session);		rtsp_ctrl->session = strdup(field);	    }	}	else {	    rtsp_ctrl->session = strdup(field);	}    }      /* real only, ignore in other protocol... */    if((field = rtsp_get_field(rtsp_hdr,"RealChallenge1")) != NULL) {	while(*field == ' ') field++;	if(rtsp_ctrl->challenge) {	    if(strcmp(rtsp_ctrl->challenge,field)) { /* different server */		display(MSDL_DBG,"warning: got different client challenge\n"			"    old: %s\n"			"    new: %s\n",rtsp_ctrl->challenge,field);		free(rtsp_ctrl->challenge);		rtsp_ctrl->challenge = strdup(field);	    }	}	else {	    rtsp_ctrl->challenge = strdup(field);	}    }        return 1;}/* * rtsp_response_parse :  parse rtsp response header  * make rtsp_hdr from raw data in rtsp_hdr->buffer * *    return value :        -1 ... ERROR *                           0 ... already parsed. *                           1 ... success. */int rtsp_response_parse(struct rtsp_header_t *rtsp_hdr){      char *hdr_ptr, *ptr;    char *field = NULL;      int pos_hdr_sep, hdr_sep_len;    size_t len;      if(rtsp_hdr == NULL) return -1;    if(rtsp_hdr->is_parsed) return 0; /* already parsed. */        /* get first word  */    hdr_ptr = strstr(rtsp_hdr->buffer, " ");    if(hdr_ptr == NULL) {	display(MSDL_ERR,"Malformed answer : No %20 separator\n");	return -1;    }      len = hdr_ptr - rtsp_hdr->buffer;    rtsp_hdr->protocol = xmalloc(len + 1);    strncpy(rtsp_hdr->protocol,rtsp_hdr->buffer,len);    rtsp_hdr->protocol[len] = '\0';      /* 1. set method */    rtsp_hdr->method = strdup(rtsp_hdr->protocol);      if(!strncasecmp(rtsp_hdr->protocol,"RTSP",4)) { /* RTSP message*/    	/* 2. get RTSP status code */	if(sscanf(++hdr_ptr,"%d",&(rtsp_hdr->status_code)) != 1) {	    display(MSDL_ERR,"Malformed answer : No rtsp status code!!\n");	    return -1;	}     	hdr_ptr += 4; /* "[0-9][0-9][0-9] " */    	/* 3. get reason phrase */	ptr = strstr(hdr_ptr,"\n");	if(ptr == NULL) {	    display(MSDL_ERR,"Malformed answer : unable to get reason_phrase\n");	    return -1;	}	len = ptr - hdr_ptr; // len of reason phrase.	rtsp_hdr->reason_phrase = xmalloc(len + 1);	strncpy(rtsp_hdr->reason_phrase,hdr_ptr,len);	if(rtsp_hdr->reason_phrase[len - 1] == '\r') { // M$ style newline!	    len --; // we don't need \r.	}	rtsp_hdr->reason_phrase[len] = '\0'; // terminate string    }     else if(!strncasecmp(rtsp_hdr->protocol,"SET_PARAMETER",strlen("SET_PARAMETER"))) {	rtsp_hdr->status_code = RTSP_STATUS_SET_PARAMETER;    }    else if(!strncasecmp(rtsp_hdr->protocol,"OPTIONS",strlen("OPTIONS"))) {	rtsp_hdr->status_code = RTSP_STATUS_OPTIONS;    }    else if(!strncasecmp(rtsp_hdr->protocol,"ANNOUNCE",strlen("ANNOUNCE"))) {	rtsp_hdr->status_code = RTSP_STATUS_ANNOUNCE;    }    else {  /* NOT RTSP ---> abort */	display(MSDL_ERR,"Protocol not RTSP, server says '%s'",rtsp_hdr->protocol);	return -1;    }        hdr_sep_len = 4; /* header separator length */    ptr = strstr(rtsp_hdr->buffer,"\r\n\r\n");    if(!ptr) {	ptr = strstr(rtsp_hdr->buffer,"\n\n");	if(!ptr) {	    display(MSDL_ERR,"Header may be incomplete!\n");	    return -1;	}	hdr_sep_len = 2;    }    pos_hdr_sep = ptr - rtsp_hdr->buffer;      /* points to first line after method line. */    hdr_ptr = strstr(rtsp_hdr->buffer,"\n") + 1;    /* parse of first line [DONE] */        /* get all fields. they are separated by '\n' */    do {	ptr = hdr_ptr;	while(*ptr != '\r' && *ptr != '\n') ptr++;	len  = ptr - hdr_ptr;	if(len == 0) break; /* met \n\n --> end of header! */    	field = (char *)xrealloc(field,len + 1); // +1 for '\0'	strncpy(field,hdr_ptr,len);	field[len] = '\0';        	rtsp_set_field(rtsp_hdr,field);	hdr_ptr = ptr + ((*ptr == '\r') ? 2 : 1); /* points to next line */    } while(hdr_ptr < (rtsp_hdr->buffer + pos_hdr_sep));      if(field) {	free(field);    }    /*      rtsp_hdr->buffer_len is length of header total data received    */    if(pos_hdr_sep + hdr_sep_len < rtsp_hdr->buffer_len) {	rtsp_hdr->body = rtsp_hdr->buffer + (pos_hdr_sep + hdr_sep_len);	rtsp_hdr->body_len = rtsp_hdr->buffer_len - (pos_hdr_sep + hdr_sep_len);    }      /* mark parsed */    rtsp_hdr->is_parsed = 1;          return 1;}/* * start rtsp streaming. *  *    return value :   negative or 0  ... error *                                 1  ... success */int rtsp_streaming_start(struct stream_t *stream){        struct rtsp_header_t *rtsp_answer = NULL;    int header_size;      char *answer = NULL; /* temporary pointer */    char *server = NULL;    char *redirected = NULL;    stream->stream_ctrl->status = STREAMING_HANDSHAKING;    if(stream->dlopts->dl_protocol == RTSP_WMS) {	server = strdup("WMServer");    }    else { /* still don't know which rtsp protocol, or REAL specified (need challenge) */		stream->netsock->sock = rtsp_connect(stream);	if(stream->netsock->sock < 0) {	    display(MSDL_ERR,"cannot establish rtsp connection\n");	    goto failed;	}		real_rtsp_options(stream,&rtsp_answer);	if(rtsp_answer == NULL) {	    display(MSDL_ERR,"rtsp connection failed\n");	    goto failed;	}		/* get server name */	if((answer = rtsp_get_field(rtsp_answer,"Server")) != NULL) {	    while(*answer == ' ') answer++;  /* skip space */	    server = strdup(answer);	}	else {	    if((rtsp_get_field(rtsp_answer,"RealChallenge1")) != NULL) {		server = strdup("Real");	    }	    else {		server = strdup("Unknown Server");	    }	}    }      /* real or helix server (supported) */    if(strstr(server,"Real") || strstr(server,"Helix")) {		/* real-rtsp */	struct rmff_header_t *rmff_header = NULL;		int ret = 0;	/* connection is already setup, by real_rtsp_options called above */	/* this is the function to do almost all setup process */	ret = real_setup_and_get_header(stream,&rmff_header);		if((!rmff_header) || (ret <= 0)) { /*  NOT OK  */	    if((answer = rtsp_get_field(rtsp_answer,"Location")) != NULL) {		/* redirected */		while(*answer == ' ') answer++;				redirected = strdup(answer);		display(MSDL_NOR,"redirected to %s\n",redirected);		/*		  TODO redirection support		  and I have never seen example...		*/		goto failed;	    }	    else {		display(MSDL_ERR,"real/helix connection not established\n");		goto failed;	    }	}    	/* OK, connection established */		header_size = rmff_dump_header(rmff_header,				       stream->stream_ctrl->write_buffer);	stream->stream_ctrl->write_data_len = header_size;    	display(MSDL_VER,"rmff_header_size = %d\n",header_size);		/* All Green */	stream->stream_ctrl->rtsp_ctrl->rmff_header = rmff_header;	stream->stream_ctrl->file_size     = rmff_header->data->size;	stream->stream_ctrl->total_packets = rmff_header->data->num_packets;	stream->stream_ctrl->rtsp_ctrl->get_media_packet = real_rdt_get_media_packet;	/* to distinguish which rtsp */	stream->stream_ctrl->rtsp_ctrl->rtsp_protocol = RTSP_REAL_PROTOCOL;	/* for msdl function to know protocol */	stream->stream_ctrl->protocol = RTSP_REAL;    }    else if(strstr(server,"WMServer")) {		/* try rtsp-wms */	struct asf_headerinfo_t *asf_headerinfo = NULL;	int ret = 0;		/*	 * Clean up first.	 */	if(stream->netsock->sock) {	    close(stream->netsock->sock);	}		/* free rtsp_ctrl_t */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -