/***************************************************************************** * Close: close the target *****************************************************************************/ static void Close( vlc_object_t * p_this ) { access_t *p_access = (access_t*)p_this; access_sys_t *p_sys = p_access->p_sys; if( p_sys->p_rtsp ) rtsp_close( p_sys->p_rtsp ); free( p_sys->p_rtsp ); free( p_sys ); }
static void demux_close_rtp(demuxer_t* demuxer) { Nemesi_DemuxerStreamData * ndsd = demuxer->priv; rtsp_ctrl * ctl = ndsd->rtsp; RTSP_Error err; mp_msg(MSGT_DEMUX, MSGL_INFO, "Closing libNemesi RTSP Stream...\n"); if (ndsd == NULL) return; free(ndsd); if (rtsp_close(ctl)) { err = rtsp_wait(ctl); if (err.got_error) mp_msg(MSGT_DEMUX, MSGL_ERR, "Error Closing Stream: %s\n", err.message.reply_str); } rtsp_uninit(ctl); }
int rtsp_connect( rtsp_client_t *rtsp, const char *psz_mrl, const char *psz_user_agent ) { rtsp_t *s; char *mrl_ptr; char *slash, *colon; unsigned int hostend, pathbegin, i; if( !psz_mrl ) return -1; s = xmalloc( sizeof(rtsp_t) ); rtsp->p_private = s; if( !strncmp( psz_mrl, "rtsp://", 7 ) ) psz_mrl += 7; mrl_ptr = strdup( psz_mrl ); for( i=0; i<MAX_FIELDS; i++ ) { s->answers[i]=NULL; s->scheduled[i]=NULL; } s->host = NULL; s->port = 554; /* rtsp standard port */ s->path = NULL; s->mrl = strdup(psz_mrl); s->server = NULL; s->server_state = 0; s->server_caps = 0; s->cseq = 0; s->session = NULL; if( psz_user_agent ) s->user_agent = strdup( psz_user_agent ); else s->user_agent = strdup( "User-Agent: RealMedia Player Version " "6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)" ); slash = strchr( mrl_ptr, '/' ); colon = strchr( mrl_ptr, ':' ); if( !slash ) slash = mrl_ptr + strlen(mrl_ptr) + 1; if( !colon ) colon = slash; if( colon > slash ) colon = slash; pathbegin = slash - mrl_ptr; hostend = colon - mrl_ptr; s->host = xmalloc(hostend+1); strncpy( s->host, mrl_ptr, hostend ); s->host[hostend] = 0; if( pathbegin < strlen(mrl_ptr) ) s->path = strdup(mrl_ptr+pathbegin+1); if( colon != slash ) { char buffer[pathbegin-hostend]; strncpy( buffer, mrl_ptr+hostend+1, pathbegin-hostend-1 ); buffer[pathbegin-hostend-1] = 0; s->port = atoi(buffer); if( s->port < 0 || s->port > 65535 ) s->port = 554; } free( mrl_ptr ); //fprintf( stderr, "got mrl: %s %i %s\n", s->host, s->port, s->path ); s->s = rtsp->pf_connect( rtsp->p_userdata, s->host, s->port ); if( s->s < 0 ) { //fprintf(stderr, "rtsp: failed to connect to '%s'\n", s->host); rtsp_close( rtsp ); return -1; } s->server_state = RTSP_CONNECTED; /* now lets send an options request. */ rtsp_schedule_field( rtsp, "CSeq: 1"); rtsp_schedule_field( rtsp, s->user_agent); rtsp_schedule_field( rtsp, "ClientChallenge: " "9e26d33f2984236010ef6253fb1887f7"); rtsp_schedule_field( rtsp, "PlayerStarttime: [28/03/2003:22:50:23 00:00]"); rtsp_schedule_field( rtsp, "CompanyID: KnKV4M4I/B2FjJ1TToLycw==" ); rtsp_schedule_field( rtsp, "GUID: 00000000-0000-0000-0000-000000000000" ); rtsp_schedule_field( rtsp, "RegionData: 0" ); rtsp_schedule_field( rtsp, "ClientID: " "Linux_2.4_6.0.9.1235_play32_RN01_EN_586" ); /*rtsp_schedule_field( rtsp, "Pragma: initiate-session" );*/ rtsp_request_options( rtsp, NULL ); return 0; }
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 main(int argc, char **argv) { int opt; char *url, *out = "nemesi.dump"; FILE *outfile = NULL; rtsp_ctrl *ctl; rtsp_session *sess; rtsp_medium *med; nms_rtsp_hints rtsp_hints = { -1 }; sdp_attr *attr; RTSP_Error reply; if (argc < 2) { fprintf(stderr, "\tPlease specify at least an url.\n"); fprintf(stderr, "\tUsage: %s [-f outputfile ] [-p rtp_port] [-t url\n", argv[0]); exit(1); } #ifndef WIN32 while ((opt = getopt(argc, argv, "df:p:v:")) != -1) { switch (opt) { /* Set output file */ case 'f': out = strdup(optarg); break; /* Set rtp port */ case 'p': rtsp_hints.first_rtp_port = atoi(optarg); break; /* Set verbosity */ case 'v': nms_verbosity_set(atoi(optarg)); break; /* Unknown option */ case '?': fprintf(stderr, "\n Unknown option `-%c'.\n", optopt); fprintf(stderr, "\tUsage: %s [-f outputfile ] [-d] url\n\n", argv[0]); return 1; } } #endif outfile = fopen(out, "rb"); if (outfile == NULL) outfile = stderr; url = argv[argc - 1]; fprintf(stderr, "URL %s.\n", url); /* initialize the rtsp state machine, starts the rtsp and the rtp threads * the hints available are just one: * - the first port to use (instead of picking one at random) */ if ((ctl = rtsp_init(&rtsp_hints)) == NULL) { fprintf(stderr, "Cannot init rtsp.\n"); return 1; } if (rtsp_open(ctl, url)) { fprintf(stderr, "rtsp_open failed.\n"); // die return 1; } // you must call rtsp_wait after issuing any command reply = rtsp_wait(ctl); printf("OPEN: Received reply from server: %s\n", reply.message.reply_str); // Get the session information sess = ctl->rtsp_queue; if (!sess) { fprintf(stderr, "No session available.\n"); return 1; } while (sess) { // foreach session... fprintf(outfile, "\tSession %s\n", sess->pathname); fprintf(outfile, "\tSession Duration %s\n", sess->info->t); for (attr = sess->info->attr_list; attr; attr = attr->next) { fprintf(outfile, "\t* %s %s\n", attr->name, attr->value); } med = sess->media_queue; while (med) { //... foreach medium switch (med->medium_info->media_type) { // Just care about audio and video case 'A': case 'V': fprintf(outfile, "\tTransport %s\n", med->medium_info->transport); fprintf(outfile, "\tMedia Type %s\n", (med->medium_info->media_type == 'A'? "Audio" : "Video")); fprintf(outfile, "\tMedia format %s\n", med->medium_info->fmts); break; default: //do nothing break; } // attributes are already parsed, get them from the list for (attr = med->medium_info->attr_list; attr; attr = attr->next) { fprintf(outfile, "\t* %s %s\n", attr->name, attr->value); } med = med->next; } sess = sess->next; } /* * Close the rtsp connection, we are polite */ rtsp_close(ctl); reply = rtsp_wait(ctl); printf("CLOSE: Received reply from server: %s\n", reply.message.reply_str); /* * Kill the threads, dealloc everything. */ rtsp_uninit(ctl); return 0; }
rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl) { rtsp_session_t *rtsp_session = calloc(1, sizeof(rtsp_session_t)); xine_t *xine = stream->xine; char *server; char *mrl_line=strdup(mrl); rmff_header_t *h; int bandwidth_id; uint32_t bandwidth; bandwidth_id = xine->config->register_enum(xine->config, "media.network.bandwidth", 10, rtsp_bandwidth_strs, _("network bandwidth"), _("Specify the bandwidth of your internet connection here. " "This will be used when streaming servers offer different versions " "with different bandwidth requirements of the same stream."), 0, NULL, NULL); bandwidth = rtsp_bandwidths[bandwidth_id]; rtsp_session->recv = xine_buffer_init(BUF_SIZE); connect: /* connect to server */ rtsp_session->s=rtsp_connect(stream, mrl_line, NULL); if (!rtsp_session->s) { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: failed to connect to server %s\n"), mrl_line); xine_buffer_free(rtsp_session->recv); free(rtsp_session); return NULL; } /* looking for server type */ if (rtsp_search_answers(rtsp_session->s,"Server")) server=strdup(rtsp_search_answers(rtsp_session->s,"Server")); else { if (rtsp_search_answers(rtsp_session->s,"RealChallenge1")) server=strdup("Real"); else server=strdup("unknown"); } if (strstr(server,"Real") || strstr(server,"Helix")) { /* we are talking to a real server ... */ h=real_setup_and_get_header(rtsp_session->s, bandwidth); if (!h) { /* got an redirect? */ if (rtsp_search_answers(rtsp_session->s, "Location")) { free(mrl_line); mrl_line=strdup(rtsp_search_answers(rtsp_session->s, "Location")); xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "rtsp_session: redirected to %s\n", mrl_line); rtsp_close(rtsp_session->s); free(server); goto connect; /* *shudder* i made a design mistake somewhere */ } else { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: session can not be established.\n")); rtsp_close(rtsp_session->s); xine_buffer_free(rtsp_session->recv); free(rtsp_session); return NULL; } } rtsp_session->header_left = rtsp_session->header_len = rmff_dump_header(h,rtsp_session->header,HEADER_SIZE); if (rtsp_session->header_len < 0) { xprintf (stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: rtsp server returned overly-large headers, session can not be established.\n")); goto session_abort; } xine_buffer_copyin(rtsp_session->recv, 0, rtsp_session->header, rtsp_session->header_len); rtsp_session->recv_size = rtsp_session->header_len; rtsp_session->recv_read = 0; } else { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: rtsp server type '%s' not supported yet. sorry.\n"), server); session_abort: rtsp_close(rtsp_session->s); free(server); xine_buffer_free(rtsp_session->recv); free(rtsp_session); return NULL; } free(server); return rtsp_session; }
rtsp_t *rtsp_connect(xine_stream_t *stream, const char *mrl, const char *user_agent) { rtsp_t *s = malloc(sizeof(rtsp_t)); char *mrl_ptr=strdup(mrl); char *slash, *colon, *amp; int hostend, i; size_t pathbegin; if (strncmp(mrl,"rtsp://",7)) { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp: bad mrl: %s\n"), mrl); free(s); return NULL; } mrl_ptr+=7; for (i=0; i<MAX_FIELDS; i++) { s->answers[i]=NULL; s->scheduled[i]=NULL; } s->stream=stream; s->host=NULL; s->port=554; /* rtsp standard port */ s->path=NULL; s->mrl=NULL; s->mrl=strdup(mrl); s->server=NULL; s->server_state=0; s->server_caps=0; s->cseq=0; s->session=NULL; if (user_agent) s->user_agent=strdup(user_agent); else s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)"); amp =strchr(mrl_ptr,'@'); slash=strchr(mrl_ptr,'/'); colon=strchr(mrl_ptr,':'); if (amp && (!slash || amp < slash)) { char *username = NULL, *password = NULL; /* xxx@host:port/ */ if (colon && colon < amp) { /* xxx:yyy@host:port/ */ username = strndup(mrl_ptr, colon - mrl_ptr); password = strndup(colon + 1, amp - colon - 1); } else { username = strndup(mrl_ptr, amp - mrl_ptr); } mrl_ptr = amp + 1; slash = strchr(mrl_ptr, '/'); colon = strchr(mrl_ptr, ':'); if (username) { char *auth; rtsp_basicauth(username, password, &auth); s->auth = _x_asprintf("Authorization: Basic %s", auth); free(auth); } free(username); free(password); } if(!slash) slash=mrl_ptr+strlen(mrl_ptr)+1; if(!colon) colon=slash; if(colon > slash) colon=slash; pathbegin=slash-mrl_ptr; hostend=colon-mrl_ptr; s->host = strndup(mrl_ptr, hostend); if (pathbegin < strlen(mrl_ptr)) s->path=strdup(mrl_ptr+pathbegin+1); if (colon != slash) { char buffer[pathbegin-hostend]; strncpy(buffer,mrl_ptr+hostend+1, pathbegin-hostend-1); buffer[pathbegin-hostend-1]=0; s->port=atoi(buffer); if (s->port < 0 || s->port > 65535) s->port = 554; /* rtsp standard port */ } lprintf("got mrl: %s %i %s\n",s->host,s->port,s->path); s->s = _x_io_tcp_connect (stream, s->host, s->port); if (s->s < 0) { xprintf (stream->xine, XINE_VERBOSITY_LOG, _("rtsp: failed to connect to '%s'\n"), s->host); rtsp_close(s); return NULL; } s->server_state=RTSP_CONNECTED; /* now lets send an options request. */ rtsp_schedule_field(s, "CSeq: 1"); rtsp_schedule_field(s, s->user_agent); rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7"); rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]"); rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw=="); rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000"); rtsp_schedule_field(s, "RegionData: 0"); rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586"); /*rtsp_schedule_field(s, "Pragma: initiate-session");*/ rtsp_request_options(s, NULL); return s; }