📄 rtsp.c
字号:
static int MediaAddES( vod_t *p_vod, vod_media_t *p_media, es_format_t *p_fmt ){ media_es_t *p_es = malloc( sizeof(media_es_t) ); char *psz_urlc; memset( p_es, 0, sizeof(media_es_t) ); p_media->psz_mux = NULL; /* TODO: update SDP, etc... */ asprintf( &psz_urlc, "%s/trackid=%d", p_media->psz_rtsp_path, p_media->i_es ); msg_Dbg( p_vod, " - ES %4.4s (%s)", (char *)&p_fmt->i_codec, psz_urlc ); switch( p_fmt->i_codec ) { case VLC_FOURCC( 's', '1', '6', 'b' ): if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 ) { p_es->i_payload_type = 11; } else if( p_fmt->audio.i_channels == 2 && p_fmt->audio.i_rate == 44100 ) { p_es->i_payload_type = 10; } else { p_es->i_payload_type = p_media->i_payload_type++; } p_es->psz_rtpmap = malloc( strlen( "L16/*/*" ) + 20+1 ); sprintf( p_es->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate, p_fmt->audio.i_channels ); break; case VLC_FOURCC( 'u', '8', ' ', ' ' ): p_es->i_payload_type = p_media->i_payload_type++; p_es->psz_rtpmap = malloc( strlen( "L8/*/*" ) + 20+1 ); sprintf( p_es->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate, p_fmt->audio.i_channels ); break; case VLC_FOURCC( 'm', 'p', 'g', 'a' ): p_es->i_payload_type = 14; p_es->psz_rtpmap = strdup( "MPA/90000" ); break; case VLC_FOURCC( 'm', 'p', 'g', 'v' ): p_es->i_payload_type = 32; 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( '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; 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, 0, 0 ); if( !p_es->p_rtsp_url ) { msg_Err( p_vod, "cannot create http 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) ); 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 ); msg_Dbg( p_media->p_vod, "new session: %s", psz_session ); 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 ){ msg_Dbg( p_media->p_vod, "closing session: %s", p_rtsp->psz_session ); 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_destination = p_media->psz_destination; char *psz_session = NULL; rtsp_client_t *p_rtsp; if( answer == NULL || query == NULL ) return VLC_SUCCESS; fprintf( stderr, "RtspCallback query: type=%d\n", query->i_type ); answer->i_proto = HTTPD_PROTO_RTSP; answer->i_version = query->i_version; answer->i_type = HTTPD_MSG_ANSWER; switch( query->i_type ) { case HTTPD_MSG_DESCRIBE: { char *psz_sdp = SDPGenerate( p_media, psz_destination ? psz_destination : "0.0.0.0" ); answer->i_status = 200; answer->psz_status = strdup( "OK" ); httpd_MsgAdd( answer, "Content-type", "%s", "application/sdp" ); answer->p_body = psz_sdp; answer->i_body = strlen( psz_sdp ); break; } case HTTPD_MSG_PLAY: { char *psz_output, *ip; int i, i_port_audio = 0, i_port_video = 0; /* for now only multicast so easy */ answer->i_status = 200; answer->psz_status = strdup( "OK" ); answer->i_body = 0; answer->p_body = NULL; 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 && 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( !(ip = httpd_ClientIP( cl )) ) 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 ) { 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," "port-audio=%i}", ip, i_port_video, i_port_audio ); } vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_PLAY, psz_output ); free( psz_output ); free( ip ); break; } case HTTPD_MSG_PAUSE: psz_session = httpd_MsgGet( query, "Session" ); msg_Dbg( p_vod, "HTTPD_MSG_PAUSE for session: %s", psz_session ); p_rtsp = RtspClientGet( p_media, psz_session ); if( !p_rtsp ) break; vod_MediaControl( p_vod, p_media, psz_session, VOD_MEDIA_PAUSE ); p_rtsp->b_paused = VLC_TRUE; answer->i_status = 200; answer->psz_status = strdup( "OK" ); answer->i_body = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -