static void rtsp_parse_thread(void *rtsp_handle2) { SDP_Info* sdp_info=NULL; RTSP_HANDLE *rtsp_handle = (RTSP_HANDLE *)rtsp_handle2; // char url[1024] = {0}; char buff[512] = {0}; rtsp_client_t *handle = rtsp_handle->client; int ret = 0; int x = 0; if(handle == NULL) { PRINTF("rtsp_parse_thread:ERROR,the rtsp handle is NULL\n"); goto MSG_EXIT; } ret = reach_rtsp_connect(handle, rtsp_handle->rtsp_url,"User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)" ); if(ret != 0) { PRINTF("rtsp_parse_thread:ERROR!!!!!!!!! reach_rtsp_connect\n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:*** rtsp_request_describe ***\n"); rtsp_schedule_field( handle, "Accept: application/sdp"); ret = rtsp_request_describe(handle,NULL); if(ret != 200) { PRINTF("rtsp_parse_thread:rtsp_request_describe ERROR!\n"); goto MSG_EXIT; } PRINTF("\nrtsp_parse_thread:*** rtsp_recv_sdp_info ***\n"); ret =rtsp_recv_sdp_info(handle,rtsp_handle->sdp_info,sizeof(rtsp_handle->sdp_info)); if(ret != 0) { PRINTF("rtsp_parse_thread:rtsp_request_describe ERROR! \n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:sdp_info=#%s#",rtsp_handle->sdp_info); /** sdp info **/ sdp_info = parse_sdp(rtsp_handle->sdp_info,strlen(rtsp_handle->sdp_info)); if(sdp_info==NULL){ PRINTF("rtsp_parse_thread:parse_sdp ERROR\n"); goto MSG_EXIT; ; } if( sdp_info->video_port == 0 ) sdp_info->video_port = 8436; if(sdp_info->audio_port == 0 ) sdp_info->audio_port = sdp_info->video_port+2; PRINTF("rtsp_parse_thread:*** rtsp_request_setup ***\n"); sprintf(buff,"Transport: RTP/AVP;unicast;client_port=%d-%d", sdp_info->video_port,sdp_info->video_port+1); rtsp_schedule_field( handle, buff); memset(buff,0,sizeof(buff)); sprintf(buff,"rtsp://%s:554/trackID=1",sdp_info->IP); ret = rtsp_request_setup(handle,buff); //"rtsp://192.168.4.161:554/trackID=1"); if(ret != 200) { PRINTF("rtsp_parse_thread:rtsp_request_setup ERROR! \n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:*** rtsp_request_setup ***\n"); memset(buff,0,sizeof(buff)); sprintf(buff,"Transport: RTP/AVP;unicast;client_port=%d-%d", sdp_info->audio_port,sdp_info->audio_port+1); rtsp_schedule_field( handle,buff);// "Transport: RTP/AVP;unicast;client_port=8502-8503"); memset(buff,0,sizeof(buff)); sprintf(buff,"rtsp://%s:554/trackID=2",sdp_info->IP); ret = rtsp_request_setup(handle, buff);//"rtsp://192.168.4.161:554/trackID=2"); if(ret != 200) { PRINTF("rtsp_parse_thread: rtsp_request_setup ERROR!\n"); goto MSG_EXIT; } PRINTF("rtsp_parse_thread:*** rtsp_request_play ***\n"); rtsp_schedule_field( handle, "Range: npt=0.000-"); ret = rtsp_request_play(handle, NULL); if(ret != 200) { PRINTF("rtsp_parse_thread:rtsp_request_play ERROR! \n"); goto MSG_EXIT; } //add rtp handle ret = rtsp_rtp_recv_start(rtsp_handle); if( ret < 0){ PRINTF("rtsp_parse_thread:rtsp_rtp_recv_start ERROR! \n"); goto MSG_EXIT; } while(1) { //if need stop if(rtsp_handle ->status == 1 || rtsp_handle->video_handle == NULL || rtsp_handle->audio_handle == NULL) { rtsp_rtp_recv_stop(rtsp_handle); Sleep(1000); rtsp_request_tearoff(handle, ""); Sleep(1000); break; } Sleep(3000); if(x++ != DEFAULT_HEARTBIT_TIME/3) continue; x =0; #if 0 ret = rtsp_request_getparameter(handle, NULL); PRINTF("rtsp_request_play ret =%d\n",ret); if(ret != 200) { PRINTF("ERROR! rtsp_request_play\n"); rtsp_rtp_recv_stop( rtsp_handle); break; } #endif } EXIT: if(handle) rtsp_close(handle ); if(rtsp_handle) { rtsp_handle->fCCEvent=NULL; rtsp_handle->fGetAudioEs=NULL; rtsp_handle->fGetVideoEs=NULL; free(rtsp_handle); rtsp_handle = NULL; } return; MSG_EXIT: if(rtsp_handle != NULL && rtsp_handle->fCCEvent) rtsp_handle->fCCEvent(RTSP_STREAM,MSG_RECV_FAIL); if(handle) rtsp_close(handle ); if(rtsp_handle) { rtsp_handle->fCCEvent=NULL; rtsp_handle->fGetAudioEs=NULL; rtsp_handle->fGetVideoEs=NULL; free(rtsp_handle); rtsp_handle = NULL; } return; }
int rtsp_connect(struct rtsp_client * rtsp, const char * host, unsigned int port, const char * mrl) { struct tcp_pcb * tp; in_addr_t host_addr; if (!inet_aton(host, (struct in_addr *)&host_addr)) { return -1; } if ((tp = tcp_alloc()) == NULL) { ERR("can't allocate socket!"); return -1; } if (port == 0) { port = rtsp->port; if (port == 0) port = 554; } INF("RTSP://%s:%d/%s", host, port, mrl); if (tcp_connect(tp, host_addr, htons(port)) < 0) { ERR("can't connect to host!"); tcp_close(tp); return -1; } rtsp->tcp = tp; rtsp->port = port; rtsp->host_addr = host_addr; rtsp->rtp.faddr = host_addr; rtsp->cseq = 1; strcpy(rtsp->host_name, host); strcpy(rtsp->media_name, mrl); if (rtsp_request_options(rtsp) < 0) { ERR("rtsp_request_options() failed!"); return -1; } if (rtsp_request_describe(rtsp) < 0) { ERR("rtsp_request_describe() failed!"); return -1; } if (rtsp_sdp_decode(rtsp) < 0) { ERR("rtsp_sdp_decode() failed!"); return -1; } INF("Track:\"%s\"", rtsp->track_name); if (rtsp_request_setup(rtsp) < 0) { ERR("rtsp_request_setup() failed!"); return -1; } if (rtsp_request_play(rtsp) < 0) { ERR("rtsp_request_play() failed!"); return -1; } return 0; }
rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth, char *username, char *password) { char *description=NULL; char *session_id=NULL; rmff_header_t *h = NULL; char *challenge1 = NULL; char challenge2[41]; char checksum[9]; char *subscribe = NULL; char *buf = xbuffer_init(256); char *mrl=rtsp_get_mrl(rtsp_session); unsigned int size; int status; uint32_t maxbandwidth = bandwidth; char* authfield = NULL; int i; /* get challenge */ challenge1=rtsp_search_answers(rtsp_session,"RealChallenge1"); if (!challenge1) goto out; challenge1=strdup(challenge1); #ifdef LOG printf("real: Challenge1: %s\n", challenge1); #endif /* set a reasonable default to get the best stream, unless bandwidth given */ if (!bandwidth) bandwidth = 10485800; /* request stream description */ rtsp_send_describe: rtsp_schedule_field(rtsp_session, "Accept: application/sdp"); sprintf(buf, "Bandwidth: %u", bandwidth); rtsp_schedule_field(rtsp_session, buf); rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000"); rtsp_schedule_field(rtsp_session, "RegionData: 0"); rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586"); rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1"); rtsp_schedule_field(rtsp_session, "Language: en-US"); rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup"); if(authfield) rtsp_schedule_field(rtsp_session, authfield); status=rtsp_request_describe(rtsp_session,NULL); if (status == 401) { int authlen, b64_authlen; char *authreq; char* authstr = NULL; if (authfield) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: authorization failed, check your credentials\n"); goto autherr; } if (!(authreq = rtsp_search_answers(rtsp_session,"WWW-Authenticate"))) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: 401 but no auth request, aborting\n"); goto autherr; } if (!username) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: auth required but no username supplied\n"); goto autherr; } if (!strstr(authreq, "Basic")) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: authenticator not supported (%s)\n", authreq); goto autherr; } authlen = strlen(username) + (password ? strlen(password) : 0) + 2; authstr = malloc(authlen); sprintf(authstr, "%s:%s", username, password ? password : ""); authfield = malloc(authlen*2+22); strcpy(authfield, "Authorization: Basic "); b64_authlen = base64_encode(authstr, authlen, authfield+21, authlen*2); free(authstr); if (b64_authlen < 0) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: base64 output overflow, this should never happen\n"); goto autherr; } authfield[b64_authlen+21] = 0; goto rtsp_send_describe; } autherr: if (authfield) free(authfield); if ( status<200 || status>299 ) { char *alert=rtsp_search_answers(rtsp_session,"Alert"); if (alert) { mp_msg(MSGT_STREAM, MSGL_WARN, "realrtsp: got message from server:\n%s\n", alert); } rtsp_send_ok(rtsp_session); goto out; } /* receive description */ size=0; if (!rtsp_search_answers(rtsp_session,"Content-length")) mp_msg(MSGT_STREAM, MSGL_WARN, "real: got no Content-length!\n"); else size=atoi(rtsp_search_answers(rtsp_session,"Content-length")); // as size is unsigned this also catches the case (size < 0) if (size > MAX_DESC_BUF) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: Content-length for description too big (> %uMB)!\n", MAX_DESC_BUF/(1024*1024) ); goto out; } if (!rtsp_search_answers(rtsp_session,"ETag")) mp_msg(MSGT_STREAM, MSGL_WARN, "realrtsp: got no ETag!\n"); else session_id=strdup(rtsp_search_answers(rtsp_session,"ETag")); #ifdef LOG printf("real: Stream description size: %u\n", size); #endif description=malloc(size+1); if( rtsp_read_data(rtsp_session, description, size) <= 0) { goto out; } description[size]=0; /* parse sdp (sdpplin) and create a header and a subscribe string */ subscribe = xbuffer_init(256); strcpy(subscribe, "Subscribe: "); h=real_parse_sdp(description, &subscribe, bandwidth); if (!h) { goto out; } rmff_fix_header(h); #ifdef LOG printf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n", h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams); #endif /* setup our streams */ real_calc_response_and_checksum (challenge2, checksum, challenge1); buf = xbuffer_ensure_size(buf, strlen(challenge2) + strlen(checksum) + 32); sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum); rtsp_schedule_field(rtsp_session, buf); buf = xbuffer_ensure_size(buf, strlen(session_id) + 32); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); buf = xbuffer_ensure_size(buf, strlen(mrl) + 32); sprintf(buf, "%s/streamid=0", mrl); rtsp_request_setup(rtsp_session,buf,NULL); /* Do setup for all the other streams we subscribed to */ for (i = 1; i < h->prop->num_streams; i++) { rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); buf = xbuffer_ensure_size(buf, strlen(session_id) + 32); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); buf = xbuffer_ensure_size(buf, strlen(mrl) + 32); sprintf(buf, "%s/streamid=%d", mrl, i); rtsp_request_setup(rtsp_session,buf,NULL); } /* set stream parameter (bandwidth) with our subscribe string */ rtsp_schedule_field(rtsp_session, subscribe); rtsp_request_setparameter(rtsp_session,NULL); /* set delivery bandwidth */ if (maxbandwidth) { sprintf(buf, "SetDeliveryBandwidth: Bandwidth=%u;BackOff=0", maxbandwidth); rtsp_schedule_field(rtsp_session, buf); rtsp_request_setparameter(rtsp_session,NULL); } { int s_ss = 0, s_ms = 0, e_ss = 0, e_ms = 0; char *str; if ((str = rtsp_get_param(rtsp_session, "start"))) { convert_timestamp(str, &s_ss, &s_ms); free(str); } if ((str = rtsp_get_param(rtsp_session, "end"))) { convert_timestamp(str, &e_ss, &e_ms); free(str); } str = buf + sprintf(buf, s_ms ? "%s%d.%d-" : "%s%d-", "Range: npt=", s_ss, s_ms); if (e_ss || e_ms) sprintf(str, e_ms ? "%d.%d" : "%d", e_ss, e_ms); } rtsp_schedule_field(rtsp_session, buf); /* and finally send a play request */ rtsp_request_play(rtsp_session,NULL); out: subscribe = xbuffer_free(subscribe); buf = xbuffer_free(buf); free(description); free(session_id); free(challenge1); return h; }
/* * send PLAY request * return value ... what rtsp_recv_header returned */ static int real_rtsp_play(struct stream_t *stream) { struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl; struct rtsp_header_t *rtsp_hdr = NULL; char *field = NULL; int ret = 0; /* * Sending part */ rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl); if(stream->dlopts->resume_download) { real_prepare_resuming(stream); } if(stream->dlopts->bandwidth) { /* when user specified bandwidth */ char *buffer = (char *)xmalloc(BUFSIZE_1K); snprintf(buffer,BUFSIZE_1K - 1, "Bandwidth: %d",stream->dlopts->bandwidth); rtsp_set_field(rtsp_hdr,buffer); free(buffer); } rtsp_set_range_field(rtsp_hdr,stream->dlopts->range); rtsp_set_speed_field(rtsp_hdr,stream->dlopts->speed); rtsp_request_play(rtsp_hdr,rtsp_ctrl->mrl); rtsp_send_request_and_free(stream,rtsp_hdr); /* * Receiving part */ /* receive message for PLAY request */ rtsp_hdr = new_rtsp_header(); ret = rtsp_recv_header(stream,rtsp_hdr); if(!is_rtsp_response_ok(rtsp_hdr->status_code)) { display(MSDL_ERR,"PLAY request returned: %d (%s)\n", rtsp_hdr->status_code,rtsp_hdr->reason_phrase); field = rtsp_get_field(rtsp_hdr,"Alert"); if(field) { while(*field == ' ') field++; display(MSDL_ERR,"message from server --> %s\n",field); } free_rtsp_header(rtsp_hdr); goto failed; } /* display real speed (might differ from user requested) */ if((field = rtsp_get_field(rtsp_hdr,"Speed")) != NULL) { if(stream->dlopts->speed) { while(*field == ' ') field++; display(MSDL_NOR,"Speed: %s\n",field); } } if((field = rtsp_get_field(rtsp_hdr,"Range")) != NULL) { if(stream->dlopts->range) { while(*field == ' ') field++; display(MSDL_NOR,"Range: %s\n",field); } } /* skip content-length bytes from network */ rtsp_ignore_data_after_header(stream,rtsp_hdr); free_rtsp_header(rtsp_hdr); return ret; failed: return -1; }