📄 rtsp.c
字号:
free_rtsp_ctrl_t(stream->stream_ctrl->rtsp_ctrl); stream->stream_ctrl->rtsp_ctrl = new_rtsp_ctrl_t(); /* free serverinfo_t */ free_serverinfo_t(stream->serverinfo); stream->serverinfo = new_serverinfo_t(); /* DO NOT MESS WITH * stream_t->netsock, * stream_t->url, * stream_t->dlopts, * stream_t->resumeinfo, * these are still valid (or just nothing (resumeinfo)) */ /* re-establish rtsp connection for WMServer */ stream->netsock->sock = rtsp_connect(stream); if(stream->netsock->sock < 0) { /* couldn't connect for some reason. (rtsp port probably closed) */ display(MSDL_ERR,"rtsp-wms connection not established\n"); display(MSDL_ERR,"server probably does not accept rtsp\n" "retry using mmst protocol\n",server); stream->stream_ctrl->status = STREAMING_OTHER_PROTOCOL; stream->stream_ctrl->retry_protocol = MMST; goto failed; } ret = wmserver_setup_and_get_header(stream,&asf_headerinfo); if(ret == 0) { /* retry */ /* probably non-wmserver */ display(MSDL_ERR,"server probably does not accept rtsp\n" "retry using mmst protocol\n",server); stream->stream_ctrl->status = STREAMING_OTHER_PROTOCOL; stream->stream_ctrl->retry_protocol = MMST; goto failed; } else if((!asf_headerinfo) || (ret < 0)) { /* no retry */ display(MSDL_ERR,"rtsp setup failed\n"); goto failed; } /* All Green */ stream->stream_ctrl->rtsp_ctrl->asf_headerinfo = asf_headerinfo; /* set infomation */ stream->stream_ctrl->packet_length = asf_headerinfo->fileh->max_packet_size; stream->stream_ctrl->file_size = asf_headerinfo->fileh->file_size; stream->stream_ctrl->total_packets = asf_headerinfo->fileh->num_packets; stream->stream_ctrl->rtsp_ctrl->get_media_packet = wmserver_rtp_get_media_packet; /* distinguish which rtsp */ stream->stream_ctrl->rtsp_ctrl->rtsp_protocol = RTSP_WMS_PROTOCOL; /* for msdl function to know protocol */ stream->stream_ctrl->protocol = RTSP_WMS; } else { /* unsupported servers */ display(MSDL_ERR,"server type [%s] not supported\n",server); stream->stream_ctrl->rtsp_ctrl->rtsp_protocol = RTSP_UNKNOWN_PROTOCOL; goto failed; } if(server) free(server); if(rtsp_answer) free_rtsp_header(rtsp_answer); if(redirected) free(redirected); stream->stream_ctrl->status = STREAMING_DOWNLOADING; return 1; /* success */ failed: if(server) free(server); if(rtsp_answer) free_rtsp_header(rtsp_answer); if(redirected) free(redirected); return -1;}/* * new_rtsp_header : create new RTSP header */struct rtsp_header_t *new_rtsp_header(void){ struct rtsp_header_t *hdr; hdr = (struct rtsp_header_t *)xmalloc(sizeof(struct rtsp_header_t)); return hdr;}/* * free RTSP header */void free_rtsp_header(struct rtsp_header_t *h){ struct rtsp_field_t *field, *prev; if(h == NULL) return; // rtsp_hdr is not malloc()ed yet. if(h->protocol) free(h->protocol); if(h->method) free(h->method); if(h->uri) free(h->uri); if(h->reason_phrase) free(h->reason_phrase); if(h->field_search) free(h->field_search); if(h->buffer) free(h->buffer); field = h->first_field; for(field = h->first_field; field ; ) { if(field->field_name) free(field->field_name); prev = field; field = field->next; free(prev); } free(h);}/* * returns first filed with 'field name'. * rtsp_get_next_field will get next field with 'filed_name' */char *rtsp_get_field(struct rtsp_header_t *rtsp_hdr, const char *field_name){ if(!rtsp_hdr || !field_name) return NULL; rtsp_hdr->field_search_pos = rtsp_hdr->first_field; rtsp_hdr->field_search = (char *)xrealloc(rtsp_hdr->field_search, strlen(field_name) + 1); /* copy field name first. */ strcpy(rtsp_hdr->field_search, field_name); /* get first field value with this field_name. */ return rtsp_get_next_field(rtsp_hdr);}/* * return field string after "rtsp_hdr->field_search". * NULL if not found. */char *rtsp_get_next_field(struct rtsp_header_t *rtsp_hdr){ char *ptr; struct rtsp_field_t *field; if(!rtsp_hdr) return NULL; field = rtsp_hdr->field_search_pos; while(field) { ptr = strstr(field->field_name,":"); if(ptr == NULL) return NULL; // the header is not valid... if(!strncasecmp(field->field_name,rtsp_hdr->field_search, ptr - field->field_name)) { // found field!!!! ptr++; // skip colon. while(*ptr == ' ') ptr++; // skip %20 rtsp_hdr->field_search_pos = field->next; // points to next field. return ptr; // return the string without filed name!! } field = field->next; } return NULL; // NOT FOUND}/* * rtsp_set_field : make new field and attach it to last_field->next. */void rtsp_set_field(struct rtsp_header_t *rtsp_hdr, const char *field_name){ struct rtsp_field_t *new_field; if(rtsp_hdr == NULL || field_name == NULL) return; new_field = xmalloc(sizeof(struct rtsp_field_t)); new_field->next = NULL; new_field->field_name = xmalloc(strlen(field_name) + 1); strcpy(new_field->field_name, field_name); if(rtsp_hdr->last_field == NULL) { rtsp_hdr->first_field = new_field; // this was first filed!! } else { rtsp_hdr->last_field->next = new_field; // attach to last. } rtsp_hdr->last_field = new_field; rtsp_hdr->field_nb++;}void rtsp_set_uri(struct rtsp_header_t *rtsp_hdr,const char *uri){ if(rtsp_hdr == NULL || uri == NULL) return; rtsp_hdr->uri = xmalloc(strlen(uri) + 1); strcpy(rtsp_hdr->uri,uri);}void rtsp_set_method(struct rtsp_header_t *rtsp_hdr, const char *method){ if(rtsp_hdr == NULL || method == NULL) return; rtsp_hdr->method = xmalloc(strlen(method) + 1); strcpy(rtsp_hdr->method,method);}/* * wrappers for each request */int rtsp_200ok(struct stream_t *stream,int cseq,char *session){ int ret; int buflen = 100 + strlen(rtsp_protocol_version) + strlen(session); char *buf = xmalloc(buflen + 1); snprintf(buf,buflen, "%s 200 OK\r\n" "Cseq: %u\r\n" "Session: %s\r\n" "\r\n", rtsp_protocol_version, cseq, session); ret = xsend(stream->netsock->sock,buf,strlen(buf)); display(MSDL_DBG,"=send 200 OK============\n%s\n=================\n",buf); free(buf); return ret;}/* OPTIONS */char *rtsp_request_options(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"OPTIONS"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* DESCRIBE */char *rtsp_request_describe(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"DESCRIBE"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* SETUP */char *rtsp_request_setup(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"SETUP"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* SET_PARAMETER */char *rtsp_request_set_parameter(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"SET_PARAMETER"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* GET_PARAMETER */char *rtsp_request_get_parameter(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"GET_PARAMETER"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* PLAY */char *rtsp_request_play(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"PLAY"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* TEARDOWN */char *rtsp_request_teardown(struct rtsp_header_t *rtsp_hdr,char *request_uri){ rtsp_set_method(rtsp_hdr,"TEARDOWN"); rtsp_set_uri(rtsp_hdr,request_uri); return (rtsp_build_request(rtsp_hdr));}/* * make complete rtsp_header_t. * firstline is first line, such as OPTIONS, DESCRIBE, etc... (see rtsp) * the request string goes to rtsp_hdr->buffer */char *rtsp_build_request(struct rtsp_header_t *rtsp_hdr){ char *ptr; int len = 0; struct rtsp_field_t *field; if(!rtsp_hdr) return NULL; if(!rtsp_hdr->method) return NULL; if(!rtsp_hdr->uri) return NULL; /* * culculate the request length. */ len = strlen(rtsp_hdr->method) + strlen(rtsp_hdr->uri) + strlen(rtsp_protocol_version) + 2 + 2 ; /* 3 is for spaces between*/ /* fields */ field = rtsp_hdr->first_field; while(field) { len += strlen(field->field_name) + 2; field = field->next; } /* CRLF at the end */ len += 2; /* request body */ if(rtsp_hdr->body) { len += rtsp_hdr->body_len; } if(rtsp_hdr->buffer) { free(rtsp_hdr->buffer); rtsp_hdr->buffer = NULL; } if(rtsp_hdr->body_len) len += rtsp_hdr->body_len; rtsp_hdr->buffer_len = len; rtsp_hdr->buffer = xmalloc(len + 1); /* 1 for '\0' */ /* * build the request */ ptr = rtsp_hdr->buffer; ptr += sprintf(ptr,"%s %s %s\r\n",rtsp_hdr->method,rtsp_hdr->uri, rtsp_protocol_version); field = rtsp_hdr->first_field; /* fields */ while(field != NULL) { ptr += sprintf(ptr,"%s\r\n",field->field_name); field = field->next; } ptr += sprintf(ptr,"\r\n"); if(rtsp_hdr->body != NULL) { memcpy(ptr,rtsp_hdr->body,rtsp_hdr->body_len); } return rtsp_hdr->buffer;}/* * judges if rtsp_hdr is complete RTSP header, or still needs some parts. * return value : 0 ... NOT complete * 1 ... COMPLETE!! */int rtsp_is_entire_header(struct rtsp_header_t *rtsp_hdr){ if(rtsp_hdr == NULL) return 0; /* unlikely, but error */ if(rtsp_hdr->buffer == NULL) return 0; /* nothing received. */ if(strstr(rtsp_hdr->buffer,"\r\n\r\n") || strstr(rtsp_hdr->buffer,"\n\n")) { return 1; } return 0;}static struct rtsp_ctrl_t *new_rtsp_ctrl_t(void){ struct rtsp_ctrl_t *ctrlt = (struct rtsp_ctrl_t *)xmalloc(sizeof(struct rtsp_ctrl_t)); /* allocate other protocol controllers in each protocol initiation functions, such as rmff_header or asf_headerinfo... */ ctrlt->prev_ts = -1; ctrlt->prev_stream_number = -1; ctrlt->rtsp_protocol = RTSP_UNKNOWN_PROTOCOL; /* off course unknown by default */ return ctrlt;}static void free_rtsp_ctrl_t(struct rtsp_ctrl_t *ctrlt){ if(ctrlt->rtsp_protocol == RTSP_REAL_PROTOCOL) { if(ctrlt->rmff_header) { free_rmff_header_t(ctrlt->rmff_header); } } else if(ctrlt->rtsp_protocol == RTSP_WMS_PROTOCOL) { if(ctrlt->asf_headerinfo) { free_asf_headerinfo_t(ctrlt->asf_headerinfo); } } if(ctrlt->mrl) free(ctrlt->mrl); if(ctrlt->server) free(ctrlt->server); if(ctrlt->session) free(ctrlt->session); if(ctrlt->etag) free(ctrlt->etag); if(ctrlt->challenge) free(ctrlt->challenge); free(ctrlt);}struct stream_t *rtsp_streaming_init(){ struct stream_t *stream = streaming_init_common(); stream->stream_ctrl->rtsp_ctrl = new_rtsp_ctrl_t(); stream->start = rtsp_streaming_start; stream->read = rtsp_streaming_read; stream->close = rtsp_streaming_close; return stream;}void rtsp_streaming_close(struct stream_t *stream){ if(stream == NULL) return; /* TEARDOWN */ if(stream->stream_ctrl->status == STREAMING_DOWNLOADING || stream->stream_ctrl->status == STREAMING_FINISHED) { struct rtsp_header_t *rtsp_hdr; int ret; /* send teardown request to make server happier. */ rtsp_hdr = new_rtsp_header_with_standard_fields(stream->stream_ctrl->rtsp_ctrl); rtsp_request_teardown(rtsp_hdr,stream->stream_ctrl->rtsp_ctrl->mrl); ret = rtsp_send_request_and_free(stream,rtsp_hdr); } if(stream->netsock->sock > 0) { /* valid socket --> close */ close(stream->netsock->sock); } free_rtsp_ctrl_t(stream->stream_ctrl->rtsp_ctrl); streaming_close_common(stream);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -