📄 rtsp.c
字号:
memcpy( &cmd, p_block_cmd->p_buffer, sizeof(cmd) ); block_Release( p_block_cmd ); if( cmd.i_type == RTSP_CMD_TYPE_NONE ) break; /* */ vlc_mutex_lock( &p_sys->lock_media ); for( i = 0; i < p_sys->i_media; i++ ) { if( p_sys->media[i]->id == cmd.i_media_id ) break; } if( i >= p_sys->i_media ) goto next; p_media = p_sys->media[i]; switch( cmd.i_type ) { case RTSP_CMD_TYPE_PLAY: vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_PLAY, cmd.psz_arg ); break; case RTSP_CMD_TYPE_PAUSE: vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_PAUSE ); break; case RTSP_CMD_TYPE_STOP: vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_STOP ); break; case RTSP_CMD_TYPE_SEEK: vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_SEEK, cmd.f_arg ); break; case RTSP_CMD_TYPE_REWIND: vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_REWIND, cmd.f_arg ); break; case RTSP_CMD_TYPE_FORWARD: vod_MediaControl( p_vod, p_media, cmd.psz_session, VOD_MEDIA_FORWARD, cmd.f_arg ); break; default: break; } next: vlc_mutex_unlock( &p_sys->lock_media ); free( cmd.psz_session ); free( cmd.psz_arg ); } return NULL;}/**************************************************************************** * RTSP server implementation ****************************************************************************/static rtsp_client_t *RtspClientNew( vod_media_t *p_media, char *psz_session ){ rtsp_client_t *p_rtsp = malloc( sizeof(rtsp_client_t) ); if( !p_rtsp ) return NULL; memset( p_rtsp, 0, sizeof(rtsp_client_t) ); p_rtsp->es = 0; p_rtsp->psz_session = psz_session; TAB_APPEND( p_media->i_rtsp, p_media->rtsp, p_rtsp ); p_media->p_vod->p_sys->i_connections++; msg_Dbg( p_media->p_vod, "new session: %s, connections: %d", psz_session, p_media->p_vod->p_sys->i_throttle_users ); return p_rtsp;}static rtsp_client_t *RtspClientGet( vod_media_t *p_media, const char *psz_session ){ int i; for( i = 0; psz_session && i < p_media->i_rtsp; i++ ) { if( !strcmp( p_media->rtsp[i]->psz_session, psz_session ) ) return p_media->rtsp[i]; } return NULL;}static void RtspClientDel( vod_media_t *p_media, rtsp_client_t *p_rtsp ){ p_media->p_vod->p_sys->i_connections--; msg_Dbg( p_media->p_vod, "closing session: %s, connections: %d", p_rtsp->psz_session, p_media->p_vod->p_sys->i_throttle_users ); while( p_rtsp->i_es-- ) { free( p_rtsp->es[p_rtsp->i_es]->psz_ip ); free( p_rtsp->es[p_rtsp->i_es] ); if( !p_rtsp->i_es ) free( p_rtsp->es ); } TAB_REMOVE( p_media->i_rtsp, p_media->rtsp, p_rtsp ); free( p_rtsp->psz_session ); free( p_rtsp );}static float ParseNPT (const char *str){ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t oldloc = uselocale (loc); unsigned hour, min; float sec; if (sscanf (str, "%u:%u:%f", &hour, &min, &sec) == 3) sec += ((hour * 60) + min) * 60; else if (sscanf (str, "%f", &sec) != 1) sec = 0.; if (loc != (locale_t)0) { uselocale (oldloc); freelocale (loc); } return sec;}static int RtspCallback( httpd_callback_sys_t *p_args, httpd_client_t *cl, httpd_message_t *answer, const httpd_message_t *query ){ vod_media_t *p_media = (vod_media_t*)p_args; vod_t *p_vod = p_media->p_vod; const char *psz_transport = NULL; const char *psz_playnow = NULL; /* support option: x-playNow */ const char *psz_session = NULL; const char *psz_cseq = NULL; rtsp_client_t *p_rtsp; int i_port = 0; int i_cseq = 0; if( answer == NULL || query == NULL ) return VLC_SUCCESS; msg_Dbg( p_vod, "RtspCallback query: type=%d", query->i_type ); answer->i_proto = HTTPD_PROTO_RTSP; answer->i_version = query->i_version; answer->i_type = HTTPD_MSG_ANSWER; answer->i_body = 0; answer->p_body = NULL; switch( query->i_type ) { case HTTPD_MSG_SETUP: { psz_playnow = httpd_MsgGet( query, "x-playNow" ); psz_transport = httpd_MsgGet( query, "Transport" ); if( psz_transport == NULL ) { answer->i_status = 400; break; } msg_Dbg( p_vod, "HTTPD_MSG_SETUP: transport=%s", psz_transport ); if( strstr( psz_transport, "unicast" ) && strstr( psz_transport, "client_port=" ) ) { rtsp_client_t *p_rtsp = NULL; char ip[NI_MAXNUMERICHOST]; i_port = atoi( strstr( psz_transport, "client_port=" ) + strlen("client_port=") ); if( strstr( psz_transport, "MP2T/H2221/UDP" ) || strstr( psz_transport, "RAW/RAW/UDP" ) ) { free( p_media->psz_mux ); p_media->psz_mux = NULL; p_media->psz_mux = strdup( p_vod->p_sys->psz_raw_mux ); p_media->b_raw = true; } if( httpd_ClientIP( cl, ip ) == NULL ) { answer->i_status = 500; answer->i_body = 0; answer->p_body = NULL; break; } msg_Dbg( p_vod, "HTTPD_MSG_SETUP: unicast ip=%s port=%d", ip, i_port ); psz_session = httpd_MsgGet( query, "Session" ); if( !psz_session || !*psz_session ) { char *psz_new; if( ( p_vod->p_sys->i_throttle_users > 0 ) && ( p_vod->p_sys->i_connections >= p_vod->p_sys->i_throttle_users ) ) { answer->i_status = 503; answer->i_body = 0; answer->p_body = NULL; break; } if( asprintf( &psz_new, "%d", rand() ) < 0 ) return VLC_ENOMEM; psz_session = psz_new; p_rtsp = RtspClientNew( p_media, psz_new ); if( !p_rtsp ) { answer->i_status = 454; answer->i_body = 0; answer->p_body = NULL; break; } } else { p_rtsp = RtspClientGet( p_media, psz_session ); if( !p_rtsp ) { answer->i_status = 454; answer->i_body = 0; answer->p_body = NULL; break; } } answer->i_status = 200; answer->i_body = 0; answer->p_body = NULL; if( p_media->b_raw ) { if( strstr( psz_transport, "MP2T/H2221/UDP" ) ) { httpd_MsgAdd( answer, "Transport", "MP2T/H2221/UDP;unicast;client_port=%d-%d", i_port, i_port + 1 ); } else if( strstr( psz_transport, "RAW/RAW/UDP" ) ) { httpd_MsgAdd( answer, "Transport", "RAW/RAW/UDP;unicast;client_port=%d-%d", i_port, i_port + 1 ); } } else httpd_MsgAdd( answer, "Transport", "RTP/AVP/UDP;unicast;client_port=%d-%d", i_port, i_port + 1 ); } else /* TODO strstr( psz_transport, "interleaved" ) ) */ { answer->i_status = 461; answer->i_body = 0; answer->p_body = NULL; } /* Intentional fall-through on x-playNow option in RTSP request */ if( !psz_playnow ) break; } case HTTPD_MSG_PLAY: { char *psz_output, ip[NI_MAXNUMERICHOST]; int i, i_port_audio = 0, i_port_video = 0; /* for now only multicast so easy */ if( !psz_playnow ) { answer->i_status = 200; answer->i_body = 0; answer->p_body = NULL; } if( !psz_session ) psz_session = httpd_MsgGet( query, "Session" ); msg_Dbg( p_vod, "HTTPD_MSG_PLAY for session: %s", psz_session ); p_rtsp = RtspClientGet( p_media, psz_session ); if( !p_rtsp ) { answer->i_status = 500; answer->i_body = 0; answer->p_body = NULL; break; } if( p_rtsp->b_playing ) { const char *psz_position = httpd_MsgGet( query, "Range" ); const char *psz_scale = httpd_MsgGet( query, "Scale" ); if( psz_position ) psz_position = strstr( psz_position, "npt=" ); if( psz_position && !psz_scale ) { double f_pos = ParseNPT (psz_position + 4); msg_Dbg( p_vod, "seeking request: %s", psz_position ); f_pos /= ((double)(p_media->i_length))/1000 /1000 / 100; CommandPush( p_vod, RTSP_CMD_TYPE_SEEK, p_media, psz_session, f_pos, NULL ); break; } if( psz_scale ) { double f_scale = 0.0; char *end; f_scale = us_strtod( psz_scale, &end ); if( end > psz_scale ) { f_scale = (f_scale * 30.0); if( psz_scale[0] == '-' ) /* rewind */ { msg_Dbg( p_vod, "rewind request: %s", psz_scale ); CommandPush( p_vod, RTSP_CMD_TYPE_REWIND, p_media, psz_session, f_scale, NULL ); } else if(psz_scale[0] != '1' ) /* fast-forward */ { msg_Dbg( p_vod, "fastforward request: %s", psz_scale ); CommandPush( p_vod, RTSP_CMD_TYPE_FORWARD, p_media, psz_session, f_scale, NULL ); } if( p_rtsp->b_paused == true ) { p_rtsp->b_paused = false; CommandPush( p_vod, RTSP_CMD_TYPE_PAUSE, p_media, psz_session, 0, NULL ); } } break; } } if( p_rtsp->b_playing && p_rtsp->b_paused ) { CommandPush( p_vod, RTSP_CMD_TYPE_PAUSE, p_media, psz_session, 0, NULL ); p_rtsp->b_paused = false; break; } else if( p_rtsp->b_playing ) break; if( httpd_ClientIP( cl, ip ) == NULL ) break; p_rtsp->b_playing = true; /* FIXME for != 1 video and 1 audio */ for( i = 0; i < p_rtsp->i_es; i++ ) { if( p_rtsp->es[i]->p_media_es->fmt.i_cat == AUDIO_ES ) i_port_audio = p_rtsp->es[i]->i_port; if( p_rtsp->es[i]->p_media_es->fmt.i_cat == VIDEO_ES ) i_port_video = p_rtsp->es[i]->i_port; } if( p_media->psz_mux ) { if( p_media->b_raw ) { if( asprintf( &psz_output, "std{access=udp,dst=%s:%i,mux=%s}", ip, i_port, p_media->psz_mux ) < 0 ) return VLC_ENOMEM; } else { if( asprintf( &psz_output, "rtp{dst=%s,port=%i,mux=%s}", ip, i_port_video, p_media->psz_mux ) < 0 ) return VLC_ENOMEM; } } else { if( asprintf( &psz_output, "rtp{dst=%s,port-video=%i,port-audio=%i}", ip, i_port_video, i_port_audio ) < 0 ) return VLC_ENOMEM; } CommandPush( p_vod, RTSP_CMD_TYPE_PLAY, p_media, psz_session, 0, psz_output ); free( psz_output ); break; } case HTTPD_MSG_DESCRIBE: { char *psz_sdp = SDPGenerate( p_media, cl ); if( psz_sdp != NULL ) { answer->i_status = 200; httpd_MsgAdd( answer, "Content-type", "%s", "application/sdp" ); answer->p_body = (uint8_t *)psz_sdp; answer->i_body = strlen( psz_sdp );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -