📄 live555.cpp
字号:
if( i_buffer > 0 ) increaseReceiveBufferTo( *p_sys->env, fd, i_buffer ); /* Increase the RTP reorder timebuffer just a bit */ sub->rtpSource()->setPacketReorderingThresholdTime(thresh); } msg_Dbg( p_demux, "RTP subsession '%s/%s'", sub->mediumName(), sub->codecName() ); /* Issue the SETUP */ if( p_sys->rtsp ) { if( !( p_sys->rtsp->setupMediaSubsession( *sub, False, b_rtsp_tcp ? True : False ) ) ) { msg_Err( p_demux, "SETUP of'%s/%s' failed %s", sub->mediumName(), sub->codecName(), p_sys->env->getResultMsg() ); } else i_active_sessions++; } else i_active_sessions++; /* we don't really know, let's just hope it's there */ if( !p_sys->b_multicast ) { /* Check, because we need diff. rollover behaviour for multicast */ p_sys->b_multicast = IsMulticastAddress( sub->connectionEndpointAddress() ); } } } delete iter; if( i_active_sessions <= 0 ) i_return = VLC_EGENERIC; return i_return;}/***************************************************************************** * Play: starts the actual playback of the stream *****************************************************************************/static int Play( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; if( p_sys->rtsp ) { /* The PLAY */ if( !p_sys->rtsp->playMediaSession( *p_sys->ms ) ) { msg_Err( p_demux, "RTSP PLAY failed %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } /* Retrieve the timeout value and set up a timeout prevention thread */#if LIVEMEDIA_LIBRARY_VERSION_INT >= 1138089600 p_sys->i_timeout = p_sys->rtsp->sessionTimeoutParameter();#endif if( p_sys->i_timeout > 0 && !p_sys->p_timeout ) { msg_Dbg( p_demux, "We have a timeout of %d seconds", p_sys->i_timeout ); p_sys->p_timeout = (timeout_thread_t *)vlc_object_create( p_demux, sizeof(timeout_thread_t) ); p_sys->p_timeout->p_sys = p_demux->p_sys; /* lol, object recursion :D */ if( vlc_thread_create( p_sys->p_timeout, "liveMedia-timeout", TimeoutPrevention, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) ) { msg_Err( p_demux, "cannot spawn liveMedia timeout thread" ); vlc_object_destroy( p_sys->p_timeout ); } msg_Dbg( p_demux, "spawned timeout thread" ); vlc_object_attach( p_sys->p_timeout, p_demux ); } } return VLC_SUCCESS;}/***************************************************************************** * Demux: *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; TaskToken task; vlc_bool_t b_send_pcr = VLC_TRUE; int64_t i_pcr = 0; int i; /* Check if we need to send the server a Keep-A-Live signal */ if( p_sys->b_timeout_call && p_sys->rtsp && p_sys->ms ) {#if LIVEMEDIA_LIBRARY_VERSION_INT >= 1138089600 char *psz_bye = NULL; p_sys->rtsp->getMediaSessionParameter( *p_sys->ms, NULL, psz_bye );#endif p_sys->b_timeout_call = VLC_FALSE; } for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; if( tk->b_asf || tk->b_muxed ) b_send_pcr = VLC_FALSE; if( i_pcr == 0 ) { i_pcr = tk->i_pts; } else if( tk->i_pts != 0 && i_pcr > tk->i_pts ) { i_pcr = tk->i_pts ; } } if( i_pcr != p_sys->i_pcr && i_pcr > 0 ) { p_sys->i_pcr = i_pcr; if( b_send_pcr ) es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pcr ); if( p_sys->i_pcr_start <= 0 || p_sys->i_pcr_start > i_pcr || ( p_sys->i_length > 0 && i_pcr - p_sys->i_pcr_start > p_sys->i_length ) ) { p_sys->i_pcr_start = i_pcr; } }#if 0 /* Disabled because it's simply not reliable enough */ /* When a On Demand QT stream ends, the last frame keeps going with the same PCR/PTS value */ /* This tests for that, so we can later decide to end this session */ if( i_pcr > 0 && p_sys->i_pcr == p_sys->i_pcr_previous ) { if( p_sys->i_pcr_repeats == 0 ) p_sys->i_pcr_repeatdate = mdate(); p_sys->i_pcr_repeats++; } else { p_sys->i_pcr_previous = p_sys->i_pcr; p_sys->i_pcr_repeatdate = 0; p_sys->i_pcr_repeats = 0; } if( p_sys->i_pcr_repeats > 5 && mdate() > p_sys->i_pcr_repeatdate + 1000000 ) { /* We need at least 5 repeats over at least a second of time before we EOF */ msg_Dbg( p_demux, "suspect EOF due to end of VoD session" ); return 0; }#endif /* First warn we want to read data */ p_sys->event = 0; for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; if( tk->waiting == 0 ) { tk->waiting = 1; tk->readSource->getNextFrame( tk->p_buffer, tk->i_buffer, StreamRead, tk, StreamClose, tk ); } } /* Create a task that will be called if we wait more than 300ms */ task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterrupt, p_demux ); /* Do the read */ p_sys->scheduler->doEventLoop( &p_sys->event ); /* remove the task */ p_sys->scheduler->unscheduleDelayedTask( task ); /* Check for gap in pts value */ for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; if( !tk->b_muxed && !tk->b_rtcp_sync && tk->rtpSource && tk->rtpSource->hasBeenSynchronizedUsingRTCP() ) { msg_Dbg( p_demux, "tk->rtpSource->hasBeenSynchronizedUsingRTCP()" ); es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); tk->b_rtcp_sync = VLC_TRUE; /* reset PCR and PCR start, mmh won't work well for multi-stream I fear */ tk->i_pts = 0; p_sys->i_pcr_start = 0; p_sys->i_pcr = 0; i_pcr = 0; } } if( p_sys->b_multicast && p_sys->b_no_data && p_sys->i_no_data_ti > 120 ) { /* FIXME Make this configurable msg_Err( p_demux, "no multicast data received in 36s, aborting" ); return 0; */ } else if( !p_sys->b_multicast && p_sys->b_no_data && p_sys->i_no_data_ti > 34 ) { vlc_bool_t b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ); if( !b_rtsp_tcp && p_sys->rtsp && p_sys->ms ) { msg_Warn( p_demux, "no data received in 10s. Switching to TCP" ); if( RollOverTcp( p_demux ) ) { msg_Err( p_demux, "TCP rollover failed, aborting" ); return 0; } } else if( p_sys->i_no_data_ti > 34 ) { msg_Err( p_demux, "no data received in 10s, aborting" ); return 0; } } else if( !p_sys->b_multicast && p_sys->b_no_data && p_sys->i_no_data_ti > 34 ) { /* EOF ? */ msg_Warn( p_demux, "no data received in 10s, eof ?" ); return 0; } return p_demux->b_error ? 0 : 1;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){ demux_sys_t *p_sys = p_demux->p_sys; int64_t *pi64; double *pf, f; vlc_bool_t *pb, b_bool; switch( i_query ) { case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start; return VLC_SUCCESS; case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_length; return VLC_SUCCESS; case DEMUX_GET_POSITION: pf = (double*)va_arg( args, double* ); if( p_sys->i_length > 0 ) { *pf = (double)( p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start ) / (double)(p_sys->i_length); } else { *pf = 0.0; } return VLC_SUCCESS; case DEMUX_SET_POSITION: float time; f = (double)va_arg( args, double ); if( p_sys->rtsp && p_sys->i_length > 0 ) { time = f * (double)p_sys->i_length / 1000000.0; /* in second */ if( !p_sys->rtsp->playMediaSession( *p_sys->ms, time ) ) { msg_Err( p_demux, "PLAY failed %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } p_sys->i_start = (int64_t)(f * (double)p_sys->i_length); p_sys->i_pcr_start = 0; p_sys->i_pcr = 0; return VLC_SUCCESS; } return VLC_SUCCESS; /* Special for access_demux */ case DEMUX_CAN_PAUSE: pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * ); if( p_sys->rtsp && p_sys->i_length ) /* Not always true, but will be handled in SET_PAUSE_STATE */ *pb = VLC_TRUE; else *pb = VLC_FALSE; return VLC_SUCCESS; case DEMUX_CAN_CONTROL_PACE: pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );#if 0 /* Disable for now until we have a clock synchro algo * which works with something else than MPEG over UDP */ *pb = VLC_FALSE;#else *pb = VLC_TRUE;#endif return VLC_SUCCESS; case DEMUX_SET_PAUSE_STATE: double d_npt; d_npt = ( (double)( p_sys->i_pcr - p_sys->i_pcr_start + p_sys->i_start ) ) / 1000000.00; b_bool = (vlc_bool_t)va_arg( args, vlc_bool_t ); if( p_sys->rtsp == NULL ) return VLC_EGENERIC; if( ( b_bool && !p_sys->rtsp->pauseMediaSession( *p_sys->ms ) ) || ( !b_bool && !p_sys->rtsp->playMediaSession( *p_sys->ms, d_npt > 0 ? d_npt : -1 ) ) ) { msg_Err( p_demux, "PLAY or PAUSE failed %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; }#if 0 /* reset PCR and PCR start, mmh won't work well for multi-stream I fear */ for( i = 0; i < p_sys->i_track; i++ ) { p_sys->track[i]->i_pts = 0; } p_sys->i_pcr_start = 0; /* FIXME Wrong */ p_sys->i_pcr = 0;#endif return VLC_SUCCESS; case DEMUX_GET_TITLE_INFO: case DEMUX_SET_TITLE: case DEMUX_SET_SEEKPOINT: return VLC_EGENERIC; case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = (int64_t)var_GetInteger( p_demux, "rtsp-caching" ) * 1000; return VLC_SUCCESS; default: return VLC_EGENERIC; }}/***************************************************************************** * RollOverTcp: reopen the rtsp into TCP mode * XXX: ugly, a lot of code are duplicated from Open() *****************************************************************************/static int RollOverTcp( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; MediaSubsessionIterator *iter = 0; MediaSubsession *sub; int i_tk; int i_return; var_SetBool( p_demux, "rtsp-tcp", VLC_TRUE ); /* We close the old RTSP session */ p_sys->rtsp->teardownMediaSession( *p_sys->ms ); Medium::close( p_sys->ms ); RTSPClient::close( p_sys->rtsp ); p_sys->ms = NULL; p_sys->rtsp = NULL; /* Reopen rtsp client */ if( ( i_return = Connect( p_demux ) ) != VLC_SUCCESS ) { msg_Err( p_demux, "Failed to connect with rtsp://%s", p_sys->psz_path ); goto error; } if( p_sys->p_sdp == NULL ) { msg_Err( p_demux, "Failed to retrieve the RTSP Session Description" ); goto error; } /* Create the session from the SDP */ if( !( p_sys->ms = MediaSession::createNew( *p_sys->env, p_sys->p_sdp ) ) ) { msg_Err( p_demux, "Could not create the RTSP Session: %s", p_sys->env->getResultMsg() ); goto error; } if( ( i_return = SessionsSetup( p_demux ) ) != VLC_SUCCESS ) { msg_Err( p_demux, "Nothing to play for rtsp://%s", p_sys->psz_path ); goto error; } /* Retrieve the duration if possible */ p_sys->i_length = (int64_t)( p_sys->ms->playEndTime() * 1000000.0 ); if( p_sys->i_length < 0 ) p_sys->i_length = -1; if( ( i_return = Play( p_demux ) ) != VLC_SUCCESS ) goto error; /* Update all tracks */ iter = new MediaSubsessionIterator( *p_sys->ms ); i_tk = 0; while( ( sub = iter->next() ) != NULL ) { live_track_t *tk; if( sub->readSource() == NULL ) continue; if( i_tk >= p_sys->i_track )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -