📄 rtp.c
字号:
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; } id->p_stream = p_stream; id->i_sequence = rand()&0xffff; id->i_payload_type = p_sys->i_payload_type; id->ssrc[0] = rand()&0xff; id->ssrc[1] = rand()&0xff; id->ssrc[2] = rand()&0xff; id->ssrc[3] = rand()&0xff; id->psz_enc = NULL; id->psz_fmtp = NULL; id->i_clock_rate = 90000; /* most common case for video */ id->i_channels = 0; id->i_port = i_port; if( p_fmt != NULL ) { id->i_cat = p_fmt->i_cat; if( p_fmt->i_cat == AUDIO_ES ) { id->i_clock_rate = p_fmt->audio.i_rate; id->i_channels = p_fmt->audio.i_channels; } id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */ } else { id->i_cat = VIDEO_ES; id->i_bitrate = 0; } id->i_mtu = config_GetInt( p_stream, "mtu" ); if( id->i_mtu <= 12 + 16 ) id->i_mtu = 576 - 20 - 8; /* pessimistic */ msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu ); id->srtp = NULL; id->pf_packetize = NULL; char *key = var_CreateGetNonEmptyString (p_stream, SOUT_CFG_PREFIX"key"); if (key) { id->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10, SRTP_PRF_AES_CM, SRTP_RCC_MODE1); if (id->srtp == NULL) { free (key); goto error; } char *salt = var_CreateGetNonEmptyString (p_stream, SOUT_CFG_PREFIX"salt"); errno = srtp_setkeystring (id->srtp, key, salt ? salt : ""); free (salt); free (key); if (errno) { msg_Err (p_stream, "bad SRTP key/salt combination (%m)"); goto error; } id->i_sequence = 0; /* FIXME: awful hack for libvlc_srtp */ } vlc_mutex_init( &id->lock_sink ); id->sinkc = 0; id->sinkv = NULL; id->rtsp_id = NULL; id->p_fifo = NULL; id->listen_fd = NULL; id->i_caching = (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching"); if( p_sys->psz_destination != NULL ) switch( p_sys->proto ) { case IPPROTO_DCCP: { const char *code; switch (id->i_cat) { case VIDEO_ES: code = "RTPV"; break; case AUDIO_ES: code = "RTPARTPV"; break; case SPU_ES: code = "RTPTRPTV"; break; default: code = "RTPORTPV"; break; } var_SetString (p_stream, "dccp-service", code); } /* fall through */ case IPPROTO_TCP: id->listen_fd = net_Listen( VLC_OBJECT(p_stream), p_sys->psz_destination, i_port, p_sys->proto ); if( id->listen_fd == NULL ) { msg_Err( p_stream, "passive COMEDIA RTP socket failed" ); goto error; } break; default: { int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1; int fd = net_ConnectDgram( p_stream, p_sys->psz_destination, i_port, ttl, p_sys->proto ); if( fd == -1 ) { msg_Err( p_stream, "cannot create RTP socket" ); goto error; } rtp_add_sink( id, fd, p_sys->rtcp_mux ); } } if( p_fmt == NULL ) { char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" ); if( psz == NULL ) /* Uho! */ ; else if( strncmp( psz, "ts", 2 ) == 0 ) { id->i_payload_type = 33; id->psz_enc = "MP2T"; } else { id->psz_enc = "MP2P"; } free( psz ); } else switch( p_fmt->i_codec ) { case VLC_FOURCC( 'u', 'l', 'a', 'w' ): if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 ) id->i_payload_type = 0; id->psz_enc = "PCMU"; id->pf_packetize = rtp_packetize_split; rtp_set_ptime (id, 20, 1); break; case VLC_FOURCC( 'a', 'l', 'a', 'w' ): if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 ) id->i_payload_type = 8; id->psz_enc = "PCMA"; id->pf_packetize = rtp_packetize_split; rtp_set_ptime (id, 20, 1); break; 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; } id->psz_enc = "L16"; id->pf_packetize = rtp_packetize_split; rtp_set_ptime (id, 20, 2); break; case VLC_FOURCC( 'u', '8', ' ', ' ' ): id->psz_enc = "L8"; id->pf_packetize = rtp_packetize_split; rtp_set_ptime (id, 20, 1); break; case VLC_FOURCC( 'm', 'p', 'g', 'a' ): case VLC_FOURCC( 'm', 'p', '3', ' ' ): id->i_payload_type = 14; id->psz_enc = "MPA"; id->i_clock_rate = 90000; /* not 44100 */ id->pf_packetize = rtp_packetize_mpa; break; case VLC_FOURCC( 'm', 'p', 'g', 'v' ): id->i_payload_type = 32; id->psz_enc = "MPV"; id->pf_packetize = rtp_packetize_mpv; break; case VLC_FOURCC( 'a', '5', '2', ' ' ): id->psz_enc = "ac3"; id->pf_packetize = rtp_packetize_ac3; break; case VLC_FOURCC( 'H', '2', '6', '3' ): id->psz_enc = "H263-1998"; id->pf_packetize = rtp_packetize_h263; break; case VLC_FOURCC( 'h', '2', '6', '4' ): id->psz_enc = "H264"; id->pf_packetize = rtp_packetize_h264; id->psz_fmtp = NULL; if( p_fmt->i_extra > 0 ) { uint8_t *p_buffer = p_fmt->p_extra; int i_buffer = p_fmt->i_extra; char *p_64_sps = NULL; char *p_64_pps = NULL; char hexa[6+1]; while( i_buffer > 4 && p_buffer[0] == 0 && p_buffer[1] == 0 && p_buffer[2] == 0 && p_buffer[3] == 1 ) { const int i_nal_type = p_buffer[4]&0x1f; int i_offset; int i_size = 0; msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type ); i_size = i_buffer; for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++) { if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) ) { /* we found another startcode */ i_size = i_offset; break; } } if( i_nal_type == 7 ) { p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 ); sprintf_hexa( hexa, &p_buffer[5], 3 ); } else if( i_nal_type == 8 ) { p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 ); } i_buffer -= i_size; p_buffer += i_size; } /* */ if( p_64_sps && p_64_pps && ( asprintf( &id->psz_fmtp, "packetization-mode=1;profile-level-id=%s;" "sprop-parameter-sets=%s,%s;", hexa, p_64_sps, p_64_pps ) == -1 ) ) id->psz_fmtp = NULL; free( p_64_sps ); free( p_64_pps ); } if( !id->psz_fmtp ) id->psz_fmtp = strdup( "packetization-mode=1" ); break; case VLC_FOURCC( 'm', 'p', '4', 'v' ): { char hexa[2*p_fmt->i_extra +1]; id->psz_enc = "MP4V-ES"; id->pf_packetize = rtp_packetize_split; if( p_fmt->i_extra > 0 ) { sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra ); if( asprintf( &id->psz_fmtp, "profile-level-id=3; config=%s;", hexa ) == -1 ) id->psz_fmtp = NULL; } break; } case VLC_FOURCC( 'm', 'p', '4', 'a' ): { if(!p_sys->b_latm) { char hexa[2*p_fmt->i_extra +1]; id->psz_enc = "mpeg4-generic"; id->pf_packetize = rtp_packetize_mp4a; sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra ); if( asprintf( &id->psz_fmtp, "streamtype=5; profile-level-id=15; " "mode=AAC-hbr; config=%s; SizeLength=13; " "IndexLength=3; IndexDeltaLength=3; Profile=1;", hexa ) == -1 ) id->psz_fmtp = NULL; } else { char hexa[13]; int i; unsigned char config[6]; unsigned int aacsrates[15] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0 }; for( i = 0; i < 15; i++ ) if( p_fmt->audio.i_rate == aacsrates[i] ) break; config[0]=0x40; config[1]=0; config[2]=0x20|i; config[3]=p_fmt->audio.i_channels<<4; config[4]=0x3f; config[5]=0xc0; id->psz_enc = "MP4A-LATM"; id->pf_packetize = rtp_packetize_mp4a_latm; sprintf_hexa( hexa, config, 6 ); if( asprintf( &id->psz_fmtp, "profile-level-id=15; " "object=2; cpresent=0; config=%s", hexa ) == -1 ) id->psz_fmtp = NULL; } break; } case VLC_FOURCC( 's', 'a', 'm', 'r' ): id->psz_enc = "AMR"; id->psz_fmtp = strdup( "octet-align=1" ); id->pf_packetize = rtp_packetize_amr; break; case VLC_FOURCC( 's', 'a', 'w', 'b' ): id->psz_enc = "AMR-WB"; id->psz_fmtp = strdup( "octet-align=1" ); id->pf_packetize = rtp_packetize_amr; break; case VLC_FOURCC( 's', 'p', 'x', ' ' ): id->i_payload_type = p_sys->i_payload_type++; id->psz_enc = "SPEEX"; id->pf_packetize = rtp_packetize_spx; break; case VLC_FOURCC( 't', '1', '4', '0' ): id->psz_enc = "t140" ; id->i_clock_rate = 1000; id->pf_packetize = rtp_packetize_t140; break; default: msg_Err( p_stream, "cannot add this stream (unsupported " "codec:%4.4s)", (char*)&p_fmt->i_codec ); goto error; } if( cscov != -1 ) cscov += 8 /* UDP */ + 12 /* RTP */; if( id->sinkc > 0 ) net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 ); if( id->i_payload_type == p_sys->i_payload_type ) p_sys->i_payload_type++; if( p_sys->rtsp != NULL ) id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es, GetDWBE( id->ssrc ), p_sys->psz_destination, p_sys->i_ttl, id->i_port, id->i_port + 1 ); id->p_fifo = block_FifoNew(); if( vlc_thread_create( id, "RTP send thread", ThreadSend, VLC_THREAD_PRIORITY_HIGHEST, false ) ) goto error; /* 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, NULL ); 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 ); msg_Dbg( p_stream, "sdp=\n%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;error: Del( p_stream, id ); return NULL;}static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ){ sout_stream_sys_t *p_sys = p_stream->p_sys; if( id->p_fifo != NULL ) { vlc_object_kill( id ); block_FifoWake( id->p_fifo ); vlc_thread_join( id ); block_FifoRelease( id->p_fifo ); } 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 == var_GetInteger( p_stream, "port-audio" ) ) p_sys->i_port_audio = id->i_port; if( id->i_port == var_GetInteger( p_stream, "port-video" ) ) p_sys->i_port_video = id->i_port; free( id->psz_fmtp ); if( id->rtsp_id ) RtspDelId( p_sys->rtsp, id->rtsp_id ); if( id->sinkc > 0 ) rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */ if( id->listen_fd != NULL ) net_ListenClose( id->listen_fd ); if( id->srtp != NULL ) srtp_destroy( id->srtp ); vlc_mutex_destroy( &id->lock_sink ); /* Update SDP (sap/file) */ if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream ); if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -