📄 live555.cpp
字号:
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->sub->rtpSource() && tk->sub->rtpSource()->hasBeenSynchronizedUsingRTCP() ) { msg_Dbg( p_demux, "tk->rtpSource->hasBeenSynchronizedUsingRTCP()" ); es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); tk->b_rtcp_sync = true; /* reset PCR */ tk->i_pts = 0; tk->i_npt = 0; p_sys->i_pcr = 0; p_sys->i_npt = 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 ) ) { bool b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ) || var_GetBool( p_demux, "rtsp-http" ); 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; } return 1; } msg_Err( p_demux, "no data received in 10s, aborting" ); return 0; } else if( !p_sys->b_multicast && 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, i64; double *pf, f; bool *pb, *pb2, b_bool; int *pi_int; switch( i_query ) { case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->i_npt > 0 ) { *pi64 = p_sys->i_npt; return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->i_npt_length > 0 ) { *pi64 = p_sys->i_npt_length; return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_POSITION: pf = (double*)va_arg( args, double* ); if( p_sys->i_npt_length > 0 && p_sys->i_npt > 0) { *pf = ( (double)p_sys->i_npt / (double)p_sys->i_npt_length ); return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_SET_POSITION: case DEMUX_SET_TIME: if( p_sys->rtsp && p_sys->i_npt_length > 0 ) { int i; float time; if( i_query == DEMUX_SET_TIME && p_sys->i_npt ) { i64 = (int64_t)va_arg( args, int64_t ); time = (float)((double)i64 / (double)1000000.0); /* in second */ } else if( i_query == DEMUX_SET_TIME ) return VLC_EGENERIC; else { f = (double)va_arg( args, double ); time = f * (double)p_sys->i_npt_length / (double)1000000.0; /* in second */ } if( !p_sys->rtsp->playMediaSession( *p_sys->ms, time, -1, 1 ) ) { msg_Err( p_demux, "PLAY failed %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); p_sys->i_pcr = 0; /* Retrieve RTP-Info values */ for( i = 0; i < p_sys->i_track; i++ ) { p_sys->track[i]->b_rtcp_sync = false; p_sys->track[i]->i_pts = 0; } /* Retrieve the starttime if possible */ p_sys->i_npt_start = (int64_t)( p_sys->ms->playStartTime() * (double)1000000.0 ); if( p_sys->i_npt_start < 0 ) p_sys->i_npt_start = -1; else p_sys->i_npt = p_sys->i_npt_start; /* Retrieve the duration if possible */ p_sys->i_npt_length = (int64_t)( p_sys->ms->playEndTime() * (double)1000000.0 ); if( p_sys->i_npt_length < 0 ) p_sys->i_npt_length = -1; msg_Dbg( p_demux, "seek start: %lld stop:%lld", p_sys->i_npt_start, p_sys->i_npt_length ); return VLC_SUCCESS; } return VLC_EGENERIC; /* Special for access_demux */ case DEMUX_CAN_PAUSE: case DEMUX_CAN_SEEK: pb = (bool*)va_arg( args, bool * ); if( p_sys->rtsp && p_sys->i_npt_length ) /* Not always true, but will be handled in SET_PAUSE_STATE */ *pb = true; else *pb = false; return VLC_SUCCESS; case DEMUX_CAN_CONTROL_PACE: pb = (bool*)va_arg( args, bool * );#if 1 /* Disable for now until we have a clock synchro algo * which works with something else than MPEG over UDP */ *pb = false;#else *pb = true;#endif return VLC_SUCCESS;#if 0 case DEMUX_CAN_CONTROL_RATE: pb = (bool*)va_arg( args, bool * ); pb2 = (bool*)va_arg( args, bool * ); *pb = p_sys->rtsp != NULL && p_sys->i_npt_length > 0 && !var_GetBool( p_demux, "rtsp-kasenna" ); *pb2 = false; return VLC_SUCCESS; case DEMUX_SET_RATE: { double f_scale; if( !p_sys->rtsp || p_sys->i_npt_length <= 0 || var_GetBool( p_demux, "rtsp-kasenna" ) ) return VLC_EGENERIC; /* TODO we might want to ensure that the new rate is different from * old rate after playMediaSession... * I have no idea how the server map the requested rate to the * ones it supports. * ex: * current is x2 we request x1.5 if the server return x2 we will * never succeed to return to x1. * In this case we should retry with a lower rate until we have * one (even x1). */ pi_int = (int*)va_arg( args, int * ); f_scale = (double)INPUT_RATE_DEFAULT / (*p_int); /* Passing -1 for the start and end time will mean liveMedia won't * create a Range: section for the RTSP message. The server should * pick up from the current position */ if( !p_sys->rtsp->playMediaSession( *p_sys->ms, -1, -1, f_scale ) ) { msg_Err( p_demux, "PLAY with Scale %0.2f failed %s", f_scale, p_sys->env->getResultMsg() ); return VLC_EGENERIC; } /* ReSync the stream */ p_sys->i_npt_start = 0; p_sys->i_pcr = 0; p_sys->i_npt = 0; es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); *pi_int = (int)( INPUT_RATE_DEFAULT / p_sys->ms->scale() + 0.5 ); return VLC_SUCCESS; }#endif case DEMUX_SET_PAUSE_STATE: { int i; b_bool = (bool)va_arg( args, int ); if( p_sys->rtsp == NULL ) return VLC_EGENERIC; /* FIXME */ if( ( b_bool && !p_sys->rtsp->pauseMediaSession( *p_sys->ms ) ) || ( !b_bool && !p_sys->rtsp->playMediaSession( *p_sys->ms, -1 ) ) ) { msg_Err( p_demux, "PLAY or PAUSE failed %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } /* When we Pause, we'll need the TimeoutPrevention thread to * handle sending the "Keep Alive" message to the server. * Unfortunately Live555 isn't thread safe and so can't * do this normally while the main Demux thread is handling * a live stream. We end up with the Timeout thread blocking * waiting for a response from the server. So when we PAUSE * we set a flag that the TimeoutPrevention function will check * and if it's set, it will trigger the GET_PARAMETER message */ if( b_bool && p_sys->p_timeout != NULL ) p_sys->p_timeout->b_handle_keep_alive = true; else if( !b_bool && p_sys->p_timeout != NULL ) p_sys->p_timeout->b_handle_keep_alive = false; for( i = 0; !b_bool && i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; tk->b_rtcp_sync = false; tk->i_pts = 0; p_sys->i_pcr = 0; es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); } /* Retrieve the starttime if possible */ p_sys->i_npt_start = (int64_t)( p_sys->ms->playStartTime() * (double)1000000.0 ); if( p_sys->i_npt_start < 0 ) p_sys->i_npt_start = -1; else p_sys->i_npt = p_sys->i_npt_start; /* Retrieve the duration if possible */ p_sys->i_npt_length = (int64_t)( p_sys->ms->playEndTime() * (double)1000000.0 ); if( p_sys->i_npt_length < 0 ) p_sys->i_npt_length = -1; msg_Dbg( p_demux, "pause start: %lld stop:%lld", p_sys->i_npt_start, p_sys->i_npt_length ); 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() * This should REALLY be fixed *****************************************************************************/static int RollOverTcp( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; int i, i_return; var_SetBool( p_demux, "rtsp-tcp", true ); /* We close the old RTSP session */ for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; if( tk->b_muxed ) stream_DemuxDelete( tk->p_out_muxed ); if( tk->p_es ) es_out_Del( p_demux->out, tk->p_es ); es_format_Clean( &tk->fmt ); free( tk->p_buffer ); free( tk ); } if( p_sys->i_track ) free( p_sys->track ); if( p_sys->p_out_asf ) stream_DemuxDelete( p_sys->p_out_asf ); 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; p_sys->track = NULL; p_sys->i_track = 0; /* 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; } if( ( i_return = SessionsSetup( p_demux ) ) != VLC_SUCCESS ) { msg_Err( p_demux, "Nothing to play for rtsp://%s", p_sys->psz_path ); goto error; } if( ( i_return = Play( p_demux ) ) != VLC_SUCCESS ) goto error; return VLC_SUCCESS;error: return VLC_EGENERIC;}/***************************************************************************** * *****************************************************************************/static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int duration ){ live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -