📄 rtp.c
字号:
if( b_rtsp ) { p += sprintf( p, "a=control:%s/trackid=%d\r\n", p_sys->psz_rtsp_control, i ); } } return psz_sdp;}/***************************************************************************** * *****************************************************************************/static int rtp_packetize_l16 ( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_l8 ( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_mpa ( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_mpv ( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_ac3 ( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );static void sprintf_hexa( char *s, uint8_t *p_data, int i_data ){ static const char hex[16] = "0123456789abcdef"; int i; for( i = 0; i < i_data; i++ ) { s[2*i+0] = hex[(p_data[i]>>4)&0xf]; s[2*i+1] = hex[(p_data[i] )&0xf]; } s[2*i_data] = '\0';}static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ){ sout_instance_t *p_sout = p_stream->p_sout; sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_id_t *id; sout_access_out_t *p_access = NULL; int i_port; char *psz_sdp; if( p_sys->p_mux != NULL ) { sout_input_t *p_input = NULL; if( ( p_input = sout_MuxAddStream( p_sys->p_mux, p_fmt ) ) == NULL ) { msg_Err( p_stream, "cannot add this stream to the muxer" ); return NULL; } id = malloc( sizeof( sout_stream_id_t ) ); memset( id, 0, sizeof( sout_stream_id_t ) ); id->p_access = NULL; id->p_input = p_input; id->pf_packetize= NULL; id->p_rtsp_url = NULL; id->i_port = 0; return id; } /* Choose the port */ i_port = 0; if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 ) { i_port = p_sys->i_port_audio; p_sys->i_port_audio = 0; } else if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 ) { i_port = p_sys->i_port_video; p_sys->i_port_video = 0; } while( i_port == 0 ) { if( p_sys->i_port != p_sys->i_port_audio && p_sys->i_port != p_sys->i_port_video ) { i_port = p_sys->i_port; p_sys->i_port += 2; break; } p_sys->i_port += 2; } if( p_sys->psz_destination ) { char access[100]; char url[strlen( p_sys->psz_destination ) + 1 + 12 + 1]; /* first try to create the access out */ if( p_sys->i_ttl > 0 ) { sprintf( access, "udp{raw,ttl=%d}", p_sys->i_ttl ); } else { sprintf( access, "udp{raw}" ); } sprintf( url, "%s:%d", p_sys->psz_destination, i_port ); if( ( p_access = sout_AccessOutNew( p_sout, access, url ) ) == NULL ) { msg_Err( p_stream, "cannot create the access out for %s://%s", access, url ); return NULL; } msg_Dbg( p_stream, "access out %s:%s", access, url ); } /* not create the rtp specific stuff */ id = malloc( sizeof( sout_stream_id_t ) ); memset( id, 0, sizeof( sout_stream_id_t ) ); id->p_stream = p_stream; id->p_access = p_access; id->p_input = NULL; id->psz_rtpmap = NULL; id->psz_fmtp = NULL; id->psz_destination = p_sys->psz_destination ? strdup( p_sys->psz_destination ) : NULL; id->i_port = i_port; id->p_rtsp_url = NULL; vlc_mutex_init( p_stream, &id->lock_rtsp ); id->i_rtsp_access = 0; id->rtsp_access = NULL; 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 ) { id->i_payload_type = 11; } else if( p_fmt->audio.i_channels == 2 && p_fmt->audio.i_rate == 44100 ) { id->i_payload_type = 10; } else { id->i_payload_type = p_sys->i_payload_type++; } id->psz_rtpmap = malloc( strlen( "L16/*/*" ) + 20+1 ); sprintf( id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate, p_fmt->audio.i_channels ); id->i_clock_rate = p_fmt->audio.i_rate; id->pf_packetize = rtp_packetize_l16; break; case VLC_FOURCC( 'u', '8', ' ', ' ' ): id->i_payload_type = p_sys->i_payload_type++; id->psz_rtpmap = malloc( strlen( "L8/*/*" ) + 20+1 ); sprintf( id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate, p_fmt->audio.i_channels ); id->i_clock_rate = p_fmt->audio.i_rate; id->pf_packetize = rtp_packetize_l8; break; case VLC_FOURCC( 'm', 'p', 'g', 'a' ): id->i_payload_type = 14; id->i_clock_rate = 90000; id->psz_rtpmap = strdup( "MPA/90000" ); id->pf_packetize = rtp_packetize_mpa; break; case VLC_FOURCC( 'm', 'p', 'g', 'v' ): id->i_payload_type = 32; id->i_clock_rate = 90000; id->psz_rtpmap = strdup( "MPV/90000" ); id->pf_packetize = rtp_packetize_mpv; break; case VLC_FOURCC( 'a', '5', '2', ' ' ): id->i_payload_type = p_sys->i_payload_type++; id->i_clock_rate = 90000; id->psz_rtpmap = strdup( "ac3/90000" ); id->pf_packetize = rtp_packetize_ac3; break; case VLC_FOURCC( 'H', '2', '6', '3' ): id->i_payload_type = p_sys->i_payload_type++; id->i_clock_rate = 90000; id->psz_rtpmap = strdup( "H263-1998/90000" ); id->pf_packetize = rtp_packetize_h263; break; case VLC_FOURCC( 'm', 'p', '4', 'v' ): { char hexa[2*p_fmt->i_extra +1]; id->i_payload_type = p_sys->i_payload_type++; id->i_clock_rate = 90000; id->psz_rtpmap = strdup( "MP4V-ES/90000" ); id->pf_packetize = rtp_packetize_split; if( p_fmt->i_extra > 0 ) { id->psz_fmtp = malloc( 100 + 2 * p_fmt->i_extra ); sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra ); sprintf( id->psz_fmtp, "profile-level-id=3; config=%s;", hexa ); } break; } case VLC_FOURCC( 'm', 'p', '4', 'a' ): { char hexa[2*p_fmt->i_extra +1]; id->i_payload_type = p_sys->i_payload_type++; id->i_clock_rate = p_fmt->audio.i_rate; id->psz_rtpmap = malloc( strlen( "mpeg4-generic/" ) + 12 ); sprintf( id->psz_rtpmap, "mpeg4-generic/%d", p_fmt->audio.i_rate ); id->pf_packetize = rtp_packetize_mp4a; id->psz_fmtp = malloc( 200 + 2 * p_fmt->i_extra ); sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra ); sprintf( id->psz_fmtp, "streamtype=5; profile-level-id=15; mode=AAC-hbr; " "config=%s; SizeLength=13;IndexLength=3; " "IndexDeltaLength=3; Profile=1;", hexa ); break; } default: msg_Err( p_stream, "cannot add this stream (unsupported " "codec:%4.4s)", (char*)&p_fmt->i_codec ); if( p_access ) { sout_AccessOutDelete( p_access ); } free( id ); return NULL; } id->i_cat = p_fmt->i_cat; id->ssrc[0] = rand()&0xff; id->ssrc[1] = rand()&0xff; id->ssrc[2] = rand()&0xff; id->ssrc[3] = rand()&0xff; id->i_sequence = rand()&0xffff; id->i_timestamp_start = rand()&0xffffffff; id->i_mtu = config_GetInt( p_stream, "mtu" ); /* XXX beuk */ if( id->i_mtu <= 16 ) { /* better than nothing */ id->i_mtu = 1500; } msg_Dbg( p_stream, "using mtu=%d", id->i_mtu ); if( p_sys->p_rtsp_url ) { char psz_urlc[strlen( p_sys->psz_rtsp_control ) + 1 + 10]; sprintf( psz_urlc, "%s/trackid=%d", p_sys->psz_rtsp_path, p_sys->i_es ); fprintf( stderr, "rtsp: adding %s\n", psz_urlc ); id->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, NULL ); if( id->p_rtsp_url ) { httpd_UrlCatch( id->p_rtsp_url, HTTPD_MSG_SETUP, RtspCallbackId, (void*)id ); //httpd_UrlCatch( id->p_rtsp_url, HTTPD_MSG_PLAY, RtspCallback, (void*)p_stream ); //httpd_UrlCatch( id->p_rtsp_url, HTTPD_MSG_PAUSE, RtspCallback, (void*)p_stream ); } } /* Update p_sys context */ vlc_mutex_lock( &p_sys->lock_es ); TAB_APPEND( p_sys->i_es, p_sys->es, id ); vlc_mutex_unlock( &p_sys->lock_es ); psz_sdp = SDPGenerate( p_stream, p_sys->psz_destination, VLC_FALSE ); vlc_mutex_lock( &p_sys->lock_sdp ); free( p_sys->psz_sdp ); p_sys->psz_sdp = psz_sdp; vlc_mutex_unlock( &p_sys->lock_sdp ); p_sys->i_sdp_version++; fprintf( stderr, "sdp=%s", p_sys->psz_sdp ); /* Update SDP (sap/file) */ if( p_sys->b_export_sap ) SapSetup( p_stream ); if( p_sys->b_export_sdp_file ) FileSetup( p_stream ); return id;}static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ){ sout_stream_sys_t *p_sys = p_stream->p_sys; vlc_mutex_lock( &p_sys->lock_es ); TAB_REMOVE( p_sys->i_es, p_sys->es, id ); vlc_mutex_unlock( &p_sys->lock_es ); /* Release port */ if( id->i_port > 0 ) { if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 ) p_sys->i_port_audio = id->i_port; else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 ) p_sys->i_port_video = id->i_port; } if( id->p_access ) { if( id->psz_rtpmap ) { free( id->psz_rtpmap ); } if( id->psz_fmtp ) { free( id->psz_fmtp ); } if( id->psz_destination ) free( id->psz_destination ); sout_AccessOutDelete( id->p_access ); } else if( id->p_input ) { sout_MuxDeleteStream( p_sys->p_mux, id->p_input ); } if( id->p_rtsp_url ) { httpd_UrlDelete( id->p_rtsp_url ); } vlc_mutex_destroy( &id->lock_rtsp ); if( id->rtsp_access ) free( id->rtsp_access ); /* Update SDP (sap/file) */ if( p_sys->b_export_sap ) SapSetup( p_stream ); if( p_sys->b_export_sdp_file ) FileSetup( p_stream ); free( id ); return VLC_SUCCESS;}static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *p_buffer ){ block_t *p_next; if( p_stream->p_sys->p_mux ) { sout_MuxSendBuffer( p_stream->p_sys->p_mux, id->p_input, p_buffer ); } else { while( p_buffer ) { p_next = p_buffer->p_next; if( id->pf_packetize( p_stream, id, p_buffer ) ) { break; } block_Release( p_buffer ); p_buffer = p_next; } } return VLC_SUCCESS;}static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream, block_t *p_buffer ){ sout_stream_sys_t *p_sys = p_stream->p_sys; int64_t i_dts = p_buffer->i_dts; uint32_t i_timestamp = i_dts * 9 / 100; uint8_t *p_data = p_buffer->p_buffer; unsigned int i_data = p_buffer->i_buffer; unsigned int i_max = p_sys->i_mtu - 12; int i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max; while( i_data > 0 ) { unsigned int i_size; /* output complete packet */ if( p_sys->packet && p_sys->packet->i_buffer + i_data > i_max ) { sout_AccessOutWrite( p_sys->p_access, p_sys->packet ); p_sys->packet = NULL; } if( p_sys->packet == NULL ) { /* allocate a new packet */ p_sys->packet = block_New( p_stream, p_sys->i_mtu ); p_sys->packet->p_buffer[ 0] = 0x80; p_sys->packet->p_buffer[ 1] = 0x80|p_sys->i_payload_type; p_sys->packet->p_buffer[ 2] = ( p_sys->i_sequence >> 8)&0xff; p_sys->packet->p_buffer[ 3] = ( p_sys->i_sequence )&0xff; p_sys->packet->p_buffer[ 4] = ( i_timestamp >> 24 )&0xff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -