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; }
/***************************************************************************** * Open: open the rtsp connection *****************************************************************************/ static int Open( vlc_object_t *p_this ) { access_t *p_access = (access_t *)p_this; access_sys_t *p_sys; char* psz_server = NULL; int i_result; if( !p_access->psz_access || ( strncmp( p_access->psz_access, "rtsp", 4 ) && strncmp( p_access->psz_access, "pnm", 3 ) && strncmp( p_access->psz_access, "realrtsp", 8 ) )) { return VLC_EGENERIC; } p_access->pf_read = NULL; p_access->pf_block = BlockRead; p_access->pf_seek = Seek; p_access->pf_control = Control; p_access->info.i_pos = 0; p_access->info.b_eof = false; p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_sys->p_rtsp = malloc( sizeof( rtsp_client_t) ); if( !p_sys->p_rtsp ) { free( p_sys ); return VLC_ENOMEM; } p_sys->p_header = NULL; p_sys->p_rtsp->p_userdata = p_access; p_sys->p_rtsp->pf_connect = RtspConnect; p_sys->p_rtsp->pf_disconnect = RtspDisconnect; p_sys->p_rtsp->pf_read = RtspRead; p_sys->p_rtsp->pf_read_line = RtspReadLine; p_sys->p_rtsp->pf_write = RtspWrite; i_result = rtsp_connect( p_sys->p_rtsp, p_access->psz_location, 0 ); if( i_result ) { msg_Dbg( p_access, "could not connect to: %s", p_access->psz_location ); free( p_sys->p_rtsp ); p_sys->p_rtsp = NULL; goto error; } msg_Dbg( p_access, "rtsp connected" ); /* looking for server type */ if( rtsp_search_answers( p_sys->p_rtsp, "Server" ) ) psz_server = strdup( rtsp_search_answers( p_sys->p_rtsp, "Server" ) ); else { if( rtsp_search_answers( p_sys->p_rtsp, "RealChallenge1" ) ) psz_server = strdup("Real"); else psz_server = strdup("unknown"); } if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" ) ) { uint32_t bandwidth = 10485800; rmff_header_t *h; msg_Dbg( p_access, "found a real/helix rtsp server" ); if( !(h = real_setup_and_get_header( p_sys->p_rtsp, bandwidth )) ) { /* Check if we got a redirect */ if( rtsp_search_answers( p_sys->p_rtsp, "Location" ) ) { msg_Dbg( p_access, "redirect: %s", rtsp_search_answers(p_sys->p_rtsp, "Location") ); msg_Warn( p_access, "redirect not supported" ); goto error; } msg_Err( p_access, "rtsp session can not be established" ); dialog_Fatal( p_access, _("Session failed"), "%s", _("The requested RTSP session could not be established.") ); goto error; } p_sys->p_header = block_Alloc( 4096 ); p_sys->p_header->i_buffer = rmff_dump_header( h, (char *)p_sys->p_header->p_buffer, 1024 ); rmff_free_header( h ); } else { msg_Warn( p_access, "only real/helix rtsp servers supported for now" ); goto error; } free( psz_server ); return VLC_SUCCESS; error: free( psz_server ); Close( p_this ); return VLC_EGENERIC; }
/* * 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 */ 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"); 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; }