📄 livedotcom.cpp
字号:
} else if( !strcmp( sub->codecName(), "PCMA" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'a', 'l', 'a', 'w' ); } else if( !strcmp( sub->codecName(), "MP4A-LATM" ) ) { unsigned int i_extra; uint8_t *p_extra; tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' ); if( ( p_extra = parseStreamMuxConfigStr( sub->fmtp_config(), i_extra ) ) ) { tk->fmt.i_extra = i_extra; tk->fmt.p_extra = malloc( i_extra ); memcpy( tk->fmt.p_extra, p_extra, i_extra ); delete[] p_extra; } } else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) ) { unsigned int i_extra; uint8_t *p_extra; tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'a' ); if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(), i_extra ) ) ) { tk->fmt.i_extra = i_extra; tk->fmt.p_extra = malloc( i_extra ); memcpy( tk->fmt.p_extra, p_extra, i_extra ); delete[] p_extra; } } else if( !strcmp( sub->codecName(), "X-ASF-PF" ) ) { tk->b_asf = VLC_TRUE; if( p_sys->p_out_asf == NULL ) p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf", p_demux->out ); } } else if( !strcmp( sub->mediumName(), "video" ) ) { es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('u','n','d','f') ); if( !strcmp( sub->codecName(), "MPV" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' ); } else if( !strcmp( sub->codecName(), "H263" ) || !strcmp( sub->codecName(), "H263-1998" ) || !strcmp( sub->codecName(), "H263-2000" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '3' ); } else if( !strcmp( sub->codecName(), "H261" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'H', '2', '6', '1' ); } else if( !strcmp( sub->codecName(), "JPEG" ) ) { tk->fmt.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' ); } else if( !strcmp( sub->codecName(), "MP4V-ES" ) ) { unsigned int i_extra; uint8_t *p_extra; tk->fmt.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' ); if( ( p_extra = parseGeneralConfigStr( sub->fmtp_config(), i_extra ) ) ) { tk->fmt.i_extra = i_extra; tk->fmt.p_extra = malloc( i_extra ); memcpy( tk->fmt.p_extra, p_extra, i_extra ); delete[] p_extra; } } else if( !strcmp( sub->codecName(), "X-QT" ) || !strcmp( sub->codecName(), "X-QUICKTIME" ) || !strcmp( sub->codecName(), "X-QDM" ) || !strcmp( sub->codecName(), "X-SV3V-ES" ) || !strcmp( sub->codecName(), "X-SORENSONVIDEO" ) ) { tk->b_quicktime = VLC_TRUE; } else if( !strcmp( sub->codecName(), "MP2T" ) ) { tk->b_muxed = VLC_TRUE; tk->p_out_muxed = stream_DemuxNew( p_demux, "ts", p_demux->out ); } else if( !strcmp( sub->codecName(), "MP2P" ) || !strcmp( sub->codecName(), "MP1S" ) ) { tk->b_muxed = VLC_TRUE; tk->p_out_muxed = stream_DemuxNew( p_demux, "ps", p_demux->out ); } else if( !strcmp( sub->codecName(), "X-ASF-PF" ) ) { tk->b_asf = VLC_TRUE; if( p_sys->p_out_asf == NULL ) p_sys->p_out_asf = stream_DemuxNew( p_demux, "asf", p_demux->out );; } } if( tk->fmt.i_codec != VLC_FOURCC( 'u', 'n', 'd', 'f' ) ) { tk->p_es = es_out_Add( p_demux->out, &tk->fmt ); } if( sub->rtcpInstance() != NULL ) { sub->rtcpInstance()->setByeHandler( StreamClose, tk ); } if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf ) { tk->readSource = sub->readSource(); tk->rtpSource = sub->rtpSource(); /* Append */ p_sys->track = (live_track_t**)realloc( p_sys->track, sizeof( live_track_t ) * ( p_sys->i_track + 1 ) ); p_sys->track[p_sys->i_track++] = tk; } else { free( tk ); } } delete iter; if( p_sys->p_out_asf && ParseASF( p_demux ) ) { msg_Err( p_demux, "cannot find a usable asf header" ); /* TODO Clean tracks */ goto error; } p_sys->i_length = (mtime_t)(p_sys->ms->playEndTime() * 1000000.0); if( p_sys->i_length < 0 ) { p_sys->i_length = 0; } else if( p_sys->i_length > 0 ) { /* FIXME */ /* p_input->stream.p_selected_area->i_size = 1000;*/ /* needed for now */ } if( p_sys->i_track <= 0 ) { msg_Err( p_demux, "no codec supported, aborting" ); goto error; } return VLC_SUCCESS;error: if( p_sys->p_out_asf ) { stream_DemuxDelete( p_sys->p_out_asf ); } if( p_sys->ms ) { Medium::close( p_sys->ms ); } if( p_sys->rtsp ) { Medium::close( p_sys->rtsp ); } if( p_sys->env ) { RECLAIM_ENV(p_sys->env); } if( p_sys->scheduler ) { delete p_sys->scheduler; } if( p_sys->p_sdp ) { free( p_sys->p_sdp ); } if( ( p_sys->psz_path != NULL ) && ( p_sys->psz_path != p_demux->psz_path ) ) free( p_sys->psz_path ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * DemuxClose: *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; int i; 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 ); 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 ); if( p_sys->rtsp && p_sys->ms ) { /* TEARDOWN */ p_sys->rtsp->teardownMediaSession( *p_sys->ms ); } Medium::close( p_sys->ms ); if( p_sys->rtsp ) Medium::close( p_sys->rtsp ); if( p_sys->env ) RECLAIM_ENV(p_sys->env); if( p_sys->scheduler ) delete p_sys->scheduler; if( p_sys->p_sdp ) free( p_sys->p_sdp ); if( p_sys->psz_path != p_demux->psz_path ) free( p_sys->psz_path ); free( p_sys );}/***************************************************************************** * 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; mtime_t i_pcr = 0; int i; 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; } } /* First warm 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->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; } var_SetBool( p_demux, "rtsp-tcp", VLC_TRUE ); } 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; } return VLC_SUCCESS; case DEMUX_SET_POSITION: { float time; f = (double)va_arg( args, double ); time = f * (double)p_sys->i_length / 1000000.0; /* in second */ if( p_sys->rtsp && p_sys->i_length > 0 ) { MediaSubsessionIterator *iter = new MediaSubsessionIterator( *p_sys->ms ); MediaSubsession *sub; int i; while( ( sub = iter->next() ) != NULL ) { p_sys->rtsp->playMediaSubsession( *sub, time ); } delete iter; p_sys->i_start = (mtime_t)(f * (double)p_sys->i_length); p_sys->i_pcr_start = 0; p_sys->i_pcr = 0; for( i = 0; i < p_sys->i_track; i++ ) { p_sys->track[i]->i_pts = 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;#endif *pb = VLC_TRUE; return VLC_SUCCESS; case DEMUX_SET_PAUSE_STATE: double d_npt; MediaSubsessionIterator *iter; MediaSubsession *sub; d_npt = ( (double)( p_sys->i_pcr - p_sys->i_pcr_start +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -