📄 rtsp.c
字号:
p_es->psz_rtpmap = strdup( "MPV/90000" ); break; case VLC_FOURCC( 'a', '5', '2', ' ' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( "ac3/90000" ); break; case VLC_FOURCC( 'H', '2', '6', '3' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( "H263-1998/90000" ); break; case VLC_FOURCC( 'h', '2', '6', '4' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( "H264/90000" ); p_es->psz_fmtp = strdup( "packetization-mode=1" ); break; case VLC_FOURCC( 'm', 'p', '4', 'v' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( "MP4V-ES/90000" ); if( p_fmt->i_extra > 0 ) { char *p_hexa = malloc( 2 * p_fmt->i_extra + 1 ); p_es->psz_fmtp = malloc( 100 + 2 * p_fmt->i_extra ); sprintf_hexa( p_hexa, p_fmt->p_extra, p_fmt->i_extra ); sprintf( p_es->psz_fmtp, "profile-level-id=3; config=%s;", p_hexa ); free( p_hexa ); } break; case VLC_FOURCC( 'm', 'p', '4', 'a' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = malloc( strlen( "mpeg4-generic/" ) + 12 ); sprintf( p_es->psz_rtpmap, "mpeg4-generic/%d", p_fmt->audio.i_rate ); if( p_fmt->i_extra > 0 ) { char *p_hexa = malloc( 2 * p_fmt->i_extra + 1 ); p_es->psz_fmtp = malloc( 200 + 2 * p_fmt->i_extra ); sprintf_hexa( p_hexa, p_fmt->p_extra, p_fmt->i_extra ); sprintf( p_es->psz_fmtp, "streamtype=5; profile-level-id=15; mode=AAC-hbr; " "config=%s; SizeLength=13;IndexLength=3; " "IndexDeltaLength=3; Profile=1;", p_hexa ); free( p_hexa ); } break; case VLC_FOURCC( 'm', 'p', '2', 't' ): p_media->psz_mux = "ts"; p_es->i_payload_type = 33; p_es->psz_rtpmap = strdup( "MP2T/90000" ); break; case VLC_FOURCC( 'm', 'p', '2', 'p' ): p_media->psz_mux = "ps"; p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( "MP2P/90000" ); break; case VLC_FOURCC( 's', 'a', 'm', 'r' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ? "AMR/8000/2" : "AMR/8000" ); p_es->psz_fmtp = strdup( "octet-align=1" ); break; case VLC_FOURCC( 's', 'a', 'w', 'b' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ? "AMR-WB/16000/2" : "AMR-WB/16000" ); p_es->psz_fmtp = strdup( "octet-align=1" ); break; default: msg_Err( p_vod, "cannot add this stream (unsupported " "codec: %4.4s)", (char*)&p_fmt->i_codec ); free( p_es ); return VLC_EGENERIC; } p_es->p_rtsp_url = httpd_UrlNewUnique( p_vod->p_sys->p_rtsp_host, psz_urlc, NULL, NULL, NULL ); if( !p_es->p_rtsp_url ) { msg_Err( p_vod, "cannot create RTSP url (%s)", psz_urlc ); free( psz_urlc ); free( p_es ); return VLC_EGENERIC; } free( psz_urlc ); httpd_UrlCatch( p_es->p_rtsp_url, HTTPD_MSG_SETUP, RtspCallbackES, (void*)p_es ); httpd_UrlCatch( p_es->p_rtsp_url, HTTPD_MSG_TEARDOWN, RtspCallbackES, (void*)p_es ); httpd_UrlCatch( p_es->p_rtsp_url, HTTPD_MSG_PLAY, RtspCallbackES, (void*)p_es ); httpd_UrlCatch( p_es->p_rtsp_url, HTTPD_MSG_PAUSE, RtspCallbackES, (void*)p_es ); es_format_Copy( &p_es->fmt, p_fmt ); p_es->p_vod = p_vod; p_es->p_media = p_media;#if 0 /* Choose the port */ if( p_fmt->i_cat == AUDIO_ES && p_media->i_port_audio > 0 ) { p_es->i_port = p_media->i_port_audio; p_media->i_port_audio = 0; } else if( p_fmt->i_cat == VIDEO_ES && p_media->i_port_video > 0 ) { p_es->i_port = p_media->i_port_video; p_media->i_port_video = 0; } while( !p_es->i_port ) { if( p_media->i_port != p_media->i_port_audio && p_media->i_port != p_media->i_port_video ) { p_es->i_port = p_media->i_port; p_media->i_port += 2; break; } p_media->i_port += 2; }#else p_es->i_port = 0;#endif vlc_mutex_lock( &p_media->lock ); TAB_APPEND( p_media->i_es, p_media->es, p_es ); vlc_mutex_unlock( &p_media->lock ); p_media->i_sdp_version++; return VLC_SUCCESS;}static void MediaDelES( vod_t *p_vod, vod_media_t *p_media, es_format_t *p_fmt){ media_es_t *p_es = 0; int i; /* Find the ES */ for( i = 0; i < p_media->i_es; i++ ) { if( p_media->es[i]->fmt.i_cat == p_fmt->i_cat && p_media->es[i]->fmt.i_codec == p_fmt->i_codec && p_media->es[i]->fmt.i_id == p_fmt->i_id ) { p_es = p_media->es[i]; } } if( !p_es ) return; msg_Dbg( p_vod, " - Removing ES %4.4s", (char *)&p_fmt->i_codec ); vlc_mutex_lock( &p_media->lock ); TAB_REMOVE( p_media->i_es, p_media->es, p_es ); vlc_mutex_unlock( &p_media->lock ); if( p_es->psz_rtpmap ) free( p_es->psz_rtpmap ); if( p_es->psz_fmtp ) free( p_es->psz_fmtp ); p_media->i_sdp_version++; if( p_es->p_rtsp_url ) httpd_UrlDelete( p_es->p_rtsp_url ); es_format_Clean( &p_es->fmt );}/**************************************************************************** * 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, 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-- ) { if( p_rtsp->es[p_rtsp->i_es]->psz_ip ) 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 int RtspCallback( httpd_callback_sys_t *p_args, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){ vod_media_t *p_media = (vod_media_t*)p_args; vod_t *p_vod = p_media->p_vod; char *psz_transport = NULL; char *psz_playnow = NULL; /* support option: x-playNow */ char *psz_session = NULL; 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" ); 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; 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" ) ) { p_media->b_raw = VLC_TRUE; } if( httpd_ClientIP( cl, ip ) == NULL ) { answer->i_status = 500; answer->psz_status = strdup( "Internal server error" ); 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 ) { 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->psz_status = strdup( "Too many connections" ); answer->i_body = 0; answer->p_body = NULL; break; } asprintf( &psz_session, "%d", rand() ); p_rtsp = RtspClientNew( p_media, psz_session ); } else { p_rtsp = RtspClientGet( p_media, psz_session ); if( !p_rtsp ) { answer->i_status = 454; answer->psz_status = strdup( "Unknown session id" ); answer->i_body = 0; answer->p_body = NULL; break; } } answer->i_status = 200; answer->psz_status = strdup( "OK" ); 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;client_port=%d-%d", i_port, i_port + 1 ); } else if( strstr( psz_transport, "RAW/RAW/UDP" ) ) { httpd_MsgAdd( answer, "Transport", "RAW/RAW/UDP;client_port=%d-%d", i_port, i_port + 1 ); } } else httpd_MsgAdd( answer, "Transport", "RTP/AVP/UDP;client_port=%d-%d", i_port, i_port + 1 ); } else /* TODO strstr( psz_transport, "interleaved" ) ) */ { answer->i_status = 461; answer->psz_status = strdup( "Unsupported Transport" ); 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->psz_status = strdup( "OK" ); 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 ) break; if( p_rtsp->b_playing ) { char *psz_position = httpd_MsgGet( query, "Range" ); if( psz_position ) psz_position = strstr( psz_position, "npt=" ); if( psz_position ) { double f_pos; char *end; msg_Dbg( p_vod, "seeking request: %s", psz_position ); psz_position += 4; /* FIXME: npt= is not necessarily formatted as a float */ f_pos = us_strtod( psz_position, &end ); if( end > psz_position ) { f_pos /= ((double)(p_media->i_length))/1000 /1000 / 100; vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_SEEK, f_pos ); } break; } } if( p_rtsp->b_playing && p_rtsp->b_paused ) { vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_PAUSE ); p_rtsp->b_paused = VLC_FALSE; break; } else if( p_rtsp->b_playing ) break; if( httpd_ClientIP( cl, ip ) == NULL ) break; p_rtsp->b_playing = VLC_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 ) { asprintf( &psz_output, "std{access=udp,dst=%s:%i,mux=%s}", ip, i_port, p_media->psz_mux ); } else { asprintf( &psz_output, "rtp{dst=%s,port=%i,mux=%s}", ip, i_port_video, p_media->psz_mux ); } } else { asprintf( &psz_output, "rtp{dst=%s,port-video=%i,"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -