📄 rtp.c
字号:
msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type ); for( i_offset = 1; i_offset+3 < i_buffer ; i_offset++) { if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 0 && p_buffer[i_offset+3] == 1 ) { /* we found another startcode */ i_startcode = i_offset; break; } } i_size = i_startcode ? i_startcode : i_buffer; if( i_nal_type == 7 ) { p_64_sps = (char *)malloc( ap_base64encode_len( i_size - 4) ); i_encoded = ap_base64encode_binary( p_64_sps, &p_buffer[4], i_size - 4 ); p_64_sps[i_encoded] = '\0'; sprintf_hexa( hexa, &p_buffer[5], 3 ); hexa[6] = '\0'; } if( i_nal_type == 8 ) { p_64_pps = (char *)malloc( ap_base64encode_len( i_size - 4) ); i_encoded = ap_base64encode_binary( p_64_pps, &p_buffer[4], i_size - 4 ); p_64_pps[i_encoded] = '\0'; } i_buffer -= i_size; p_buffer += i_size; } /* FIXME: All this is a bit unsafe */ asprintf( &id->psz_fmtp, "packetization-mode=1;profile-level-id=%s;sprop-parameter-sets=%s,%s;", hexa, p_64_sps, p_64_pps ); free( p_64_sps ); free( p_64_pps ); } else id->psz_fmtp = strdup( "packetization-mode=1" ); 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' ): { id->i_payload_type = p_sys->i_payload_type++; id->i_clock_rate = p_fmt->audio.i_rate; if(!p_sys->b_latm) { char hexa[2*p_fmt->i_extra +1]; 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 ); } 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; asprintf( &id->psz_rtpmap, "MP4A-LATM/%d/%d", p_fmt->audio.i_rate, p_fmt->audio.i_channels ); id->pf_packetize = rtp_packetize_mp4a_latm; sprintf_hexa( hexa, config, 6 ); asprintf( &id->psz_fmtp, "profile-level-id=15; " "object=2; cpresent=0; config=%s", hexa ); } break; } case VLC_FOURCC( 's', 'a', 'm', 'r' ): id->i_payload_type = p_sys->i_payload_type++; id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ? "AMR/8000/2" : "AMR/8000" ); id->psz_fmtp = strdup( "octet-align=1" ); id->i_clock_rate = p_fmt->audio.i_rate; id->pf_packetize = rtp_packetize_amr; break; case VLC_FOURCC( 's', 'a', 'w', 'b' ): id->i_payload_type = p_sys->i_payload_type++; id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ? "AMR-WB/16000/2" : "AMR-WB/16000" ); id->psz_fmtp = strdup( "octet-align=1" ); id->i_clock_rate = p_fmt->audio.i_rate; id->pf_packetize = rtp_packetize_amr; 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_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */ id->i_mtu = config_GetInt( p_stream, "mtu" ); /* XXX beuk */ if( id->i_mtu <= 16 + MTU_REDUCE ) { /* better than nothing */ id->i_mtu = 1500; } id->i_mtu -= MTU_REDUCE; msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", 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 ); msg_Dbg( p_stream, "rtsp: adding %s\n", psz_urlc ); id->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, 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++; msg_Dbg( p_stream, "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 && !p_sys->p_mux ) 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; unsigned 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; p_sys->packet->p_buffer[ 5] = ( i_timestamp >> 16 )&0xff; p_sys->packet->p_buffer[ 6] = ( i_timestamp >> 8 )&0xff; p_sys->packet->p_buffer[ 7] = ( i_timestamp )&0xff; p_sys->packet->p_buffer[ 8] = p_sys->ssrc[0]; p_sys->packet->p_buffer[ 9] = p_sys->ssrc[1]; p_sys->packet->p_buffer[10] = p_sys->ssrc[2]; p_sys->packet->p_buffer[11] = p_sys->ssrc[3]; p_sys->packet->i_buffer = 12; p_sys->packet->i_dts = i_dts; p_sys->packet->i_length = p_buffer->i_length / i_packet; i_dts += p_sys->packet->i_length; p_sys->i_sequence++; } i_size = __MIN( i_data, (unsigned)(p_sys->i_mtu - p_sys->packet->i_buffer) ); memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer], p_data, i_size ); p_sys->packet->i_buffer += i_size; p_data += i_size; i_data -= i_size; } return VLC_SUCCESS;}static int AccessOutGrabberWrite( sout_access_out_t *p_access, block_t *p_buffer ){ sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys; //fprintf( stderr, "received buffer size=%d\n", p_buffer->i_buffer ); // while( p_buffer ) { block_t *p_next; AccessOutGrabberWriteBuffer( p_stream, p_buffer ); p_next = p_buffer->p_next; block_Release( p_buffer ); p_buffer = p_next; } return VLC_SUCCESS;}/**************************************************************************** * SAP: ****************************************************************************/static int SapSetup( sout_stream_t *p_stream ){ sout_stream_sys_t *p_sys = p_stream->p_sys; sout_instance_t *p_sout = p_stream->p_sout; announce_method_t *p_method = sout_AnnounceMethodCreate( METHOD_TYPE_SAP ); /* Remove the previous session */ if( p_sys->p_session != NULL) { sout_AnnounceUnRegister( p_sout, p_sys->p_session); sout_AnnounceSessionDestroy( p_sys->p_session ); p_sys->p_session = NULL; } if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp ) { p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, p_sys->psz_sdp, p_sys->psz_destination, p_method ); } free( p_method ); return VLC_SUCCESS;}/***************************************************************************** File:****************************************************************************/static int FileSetup( sout_stream_t *p_stream ){ sout_stream_sys_t *p_sys = p_stream->p_sys; FILE *f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -