int play_cgi(struct httpctl * ctl) { strcpy(rtsp_host, http_query_lookup(ctl, "host")); strcpy(rtsp_media, http_query_lookup(ctl, "mrl")); rtsp_port = atoi(http_query_lookup(ctl, "port")); audio_level = atoi(http_query_lookup(ctl, "vol")); if (audio_level > 800) audio_level = 800; if (rtsp_connect(&rtsp, rtsp_host, rtsp_port, rtsp_media) < 0) { int code; WARN("RTSP connection failed!"); send_play_form(ctl); send_error(ctl, "RTSP playback failed"); if ((code = rtsp_response_code(&rtsp)) > 200) { http_send(ctl, rtsp_iframe_html, sizeof(rtsp_iframe_html) - 1); } } else { audio_gain_set(audio_level * Q15(1.0) / 100); send_stop_form(ctl); } return http_send(ctl, footer_html, sizeof(footer_html) - 1); }
int netcam_setup_rtsp(netcam_context_ptr netcam, struct url_t *url) { struct context *cnt = netcam->cnt; const char *ptr; netcam->caps.streaming = NCS_RTSP; netcam->rtsp = rtsp_new_context(); if (netcam->rtsp == NULL) { MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: unable to create rtsp context"); return -1; } /* * Allocate space for a working string to contain the path. * The extra 5 is for "://", ":" and string terminator. */ // force port to a sane value if (netcam->connect_port > 65536) { netcam->connect_port = 65536; } else if (netcam->connect_port < 0) { netcam->connect_port = 0; } ptr = mymalloc(strlen(url->service) + strlen(netcam->connect_host) + 5 + strlen(url->path) + 5); sprintf((char *)ptr, "%s://%s:%d%s", url->service, netcam->connect_host, netcam->connect_port, url->path); netcam->rtsp->path = (char *)ptr; if (cnt->conf.netcam_userpass != NULL) { ptr = cnt->conf.netcam_userpass; } else { ptr = url->userpass; /* Don't set this one NULL, gets freed. */ } if (ptr != NULL) { char *cptr; if ((cptr = strchr(ptr, ':')) == NULL) { netcam->rtsp->user = mystrdup(ptr); } else { netcam->rtsp->user = mymalloc((cptr - ptr)); memcpy(netcam->rtsp->user, ptr,(cptr - ptr)); netcam->rtsp->pass = mystrdup(cptr + 1); } } netcam_url_free(url); /* * The RTSP context should be all ready to attempt a connection with * the server, so we try .... */ rtsp_connect(netcam); netcam->get_image = netcam_read_rtsp_image; return 0; }
/***************************************************************************** * 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; }
static int netcam_read_rtsp_image(netcam_context_ptr netcam) { if (netcam->rtsp == NULL) { if (rtsp_connect(netcam) < 0) { return -1; } } AVCodecContext *cc = netcam->rtsp->codec_context; AVFormatContext *fc = netcam->rtsp->format_context; netcam_buff_ptr buffer; /* Point to our working buffer. */ buffer = netcam->receiving; buffer->used = 0; AVFrame *frame = avcodec_alloc_frame(); AVPacket packet; av_init_packet(&packet); packet.data = NULL; packet.size = 0; int size_decoded = 0; static int usual_size_decoded = 0; while (size_decoded == 0 && av_read_frame(fc, &packet) >= 0) { if(packet.stream_index != netcam->rtsp->video_stream_index) { // not our packet, skip continue; } size_decoded = decode_packet(&packet, buffer, frame, cc); } if (size_decoded == 0) { // something went wrong, end of stream? MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "%s: invalid frame!"); return -1; } if (size_decoded != usual_size_decoded) { MOTION_LOG(WRN, TYPE_NETCAM, SHOW_ERRNO, "%s: unusual frame size of %d!", size_decoded); usual_size_decoded = size_decoded; } // at this point, we are finished with the packet and frame, so free them. av_free_packet(&packet); av_free(frame); struct timeval curtime; if (gettimeofday(&curtime, NULL) < 0) { MOTION_LOG(WRN, TYPE_NETCAM, SHOW_ERRNO, "%s: gettimeofday"); } netcam->receiving->image_time = curtime; /* * Calculate our "running average" time for this netcam's * frame transmissions (except for the first time). * Note that the average frame time is held in microseconds. */ if (netcam->last_image.tv_sec) { netcam->av_frame_time = ((9.0 * netcam->av_frame_time) + 1000000.0 * (curtime.tv_sec - netcam->last_image.tv_sec) + (curtime.tv_usec- netcam->last_image.tv_usec)) / 10.0; MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO, "%s: Calculated frame time %f", netcam->av_frame_time); } netcam->last_image = curtime; netcam_buff *xchg; /* * read is complete - set the current 'receiving' buffer atomically * as 'latest', and make the buffer previously in 'latest' become * the new 'receiving'. */ pthread_mutex_lock(&netcam->mutex); xchg = netcam->latest; netcam->latest = netcam->receiving; netcam->receiving = xchg; netcam->imgcnt++; /* * We have a new frame ready. We send a signal so that * any thread (e.g. the motion main loop) waiting for the * next frame to become available may proceed. */ pthread_cond_signal(&netcam->pic_ready); pthread_mutex_unlock(&netcam->mutex); 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; }
/* * 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; }