📄 dshow.cpp
字号:
p_sys->p_capture_graph_builder2 = NULL; p_sys->p_control = NULL; vlc_mutex_init( p_this, &p_sys->lock ); vlc_cond_init( p_this, &p_sys->wait ); /* Build directshow graph */ CreateDirectShowGraph( p_sys ); if( OpenDevice( p_this, p_sys, vdevname, 0 ) != VLC_SUCCESS ) { msg_Err( p_this, "can't open video"); } else { /* Check if we can handle the demuxing ourselves or need to spawn * a demuxer module */ dshow_stream_t *p_stream = p_sys->pp_streams[p_sys->i_streams-1]; if( p_stream->mt.majortype == MEDIATYPE_Video ) { if( /* Raw DV stream */ p_stream->i_fourcc == VLC_FOURCC('d','v','s','l') || p_stream->i_fourcc == VLC_FOURCC('d','v','s','d') || p_stream->i_fourcc == VLC_FOURCC('d','v','h','d') || /* Raw MPEG video stream */ p_stream->i_fourcc == VLC_FOURCC('m','p','2','v') ) { b_audio = VLC_FALSE; if( b_access_demux ) { /* Let the access (only) take care of that */ return VLC_EGENERIC; } } } if( p_stream->mt.majortype == MEDIATYPE_Stream ) { b_audio = VLC_FALSE; if( b_access_demux ) { /* Let the access (only) take care of that */ return VLC_EGENERIC; } var_Get( p_this, "dshow-tuner", &val ); if( val.b_bool ) { /* FIXME: we do MEDIATYPE_Stream here so we don't do * it twice. */ ShowTunerProperties( p_this, p_sys->p_capture_graph_builder2, p_stream->p_device_filter, 0 ); } } } if( b_audio && OpenDevice( p_this, p_sys, adevname, 1 ) != VLC_SUCCESS ) { msg_Err( p_this, "can't open audio"); } for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) { IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar; LONG VideoInputIndex = p_sys->crossbar_routes[i].VideoInputIndex; LONG VideoOutputIndex = p_sys->crossbar_routes[i].VideoOutputIndex; LONG AudioInputIndex = p_sys->crossbar_routes[i].AudioInputIndex; LONG AudioOutputIndex = p_sys->crossbar_routes[i].AudioOutputIndex; if( SUCCEEDED(pXbar->Route(VideoOutputIndex, VideoInputIndex)) ) { msg_Dbg( p_this, "Crossbar at depth %d, Routed video " "ouput %ld to video input %ld", i, VideoOutputIndex, VideoInputIndex ); if( AudioOutputIndex != -1 && AudioInputIndex != -1 ) { if( SUCCEEDED( pXbar->Route(AudioOutputIndex, AudioInputIndex)) ) { msg_Dbg(p_this, "Crossbar at depth %d, Routed audio " "ouput %ld to audio input %ld", i, AudioOutputIndex, AudioInputIndex ); } } } } /* ** Show properties pages from other filters in graph */ var_Get( p_this, "dshow-config", &val ); if( val.b_bool ) { for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) { IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar; IBaseFilter *p_XF; if( SUCCEEDED( pXbar->QueryInterface( IID_IBaseFilter, (void **)&p_XF ) ) ) { ShowPropertyPage( p_XF ); p_XF->Release(); } } } /* Initialize some data */ p_sys->i_current_stream = 0; if( !p_sys->i_streams ) return VLC_EGENERIC; return VLC_SUCCESS;}/***************************************************************************** * DemuxOpen: open direct show device as an access_demux module *****************************************************************************/static int DemuxOpen( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t *)p_this; access_sys_t *p_sys; int i; p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) ); memset( p_sys, 0, sizeof( access_sys_t ) ); p_demux->p_sys = (demux_sys_t *)p_sys; if( CommonOpen( p_this, p_sys, VLC_TRUE ) != VLC_SUCCESS ) { CommonClose( p_this, p_sys ); return VLC_EGENERIC; } /* Everything is ready. Let's rock baby */ msg_Dbg( p_this, "Playing..."); p_sys->p_control->Run(); p_demux->pf_demux = Demux; p_demux->pf_control = DemuxControl; p_demux->info.i_update = 0; p_demux->info.i_title = 0; p_demux->info.i_seekpoint = 0; for( i = 0; i < p_sys->i_streams; i++ ) { dshow_stream_t *p_stream = p_sys->pp_streams[i]; es_format_t fmt; if( p_stream->mt.majortype == MEDIATYPE_Video ) { es_format_Init( &fmt, VIDEO_ES, p_stream->i_fourcc ); fmt.video.i_width = p_stream->header.video.bmiHeader.biWidth; fmt.video.i_height = p_stream->header.video.bmiHeader.biHeight; fmt.video.i_aspect = 4 * VOUT_ASPECT_FACTOR / 3; if( !p_stream->header.video.bmiHeader.biCompression ) { /* RGB DIB are coded from bottom to top */ fmt.video.i_height = (unsigned int)(-(int)fmt.video.i_height); } /* Setup rgb mask for RGB formats */ if( p_stream->i_fourcc == VLC_FOURCC('R','V','2','4') ) { /* This is in BGR format */ fmt.video.i_bmask = 0x00ff0000; fmt.video.i_gmask = 0x0000ff00; fmt.video.i_rmask = 0x000000ff; } if( p_stream->header.video.AvgTimePerFrame ) { fmt.video.i_frame_rate = 10000000; fmt.video.i_frame_rate_base = p_stream->header.video.AvgTimePerFrame; } } else if( p_stream->mt.majortype == MEDIATYPE_Audio ) { es_format_Init( &fmt, AUDIO_ES, p_stream->i_fourcc ); fmt.audio.i_channels = p_stream->header.audio.nChannels; fmt.audio.i_rate = p_stream->header.audio.nSamplesPerSec; fmt.audio.i_bitspersample = p_stream->header.audio.wBitsPerSample; fmt.audio.i_blockalign = fmt.audio.i_channels * fmt.audio.i_bitspersample / 8; fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate * fmt.audio.i_bitspersample; } p_stream->p_es = es_out_Add( p_demux->out, &fmt ); } return VLC_SUCCESS;}/***************************************************************************** * AccessOpen: open direct show device as an access module *****************************************************************************/static int AccessOpen( vlc_object_t *p_this ){ access_t *p_access = (access_t*)p_this; access_sys_t *p_sys; p_access->p_sys = p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) ); memset( p_sys, 0, sizeof( access_sys_t ) ); if( CommonOpen( p_this, p_sys, VLC_FALSE ) != VLC_SUCCESS ) { CommonClose( p_this, p_sys ); return VLC_EGENERIC; } dshow_stream_t *p_stream = p_sys->pp_streams[0]; /* Check if we need to force demuxers */ if( !p_access->psz_demux || !*p_access->psz_demux ) { if( p_stream->i_fourcc == VLC_FOURCC('d','v','s','l') || p_stream->i_fourcc == VLC_FOURCC('d','v','s','d') || p_stream->i_fourcc == VLC_FOURCC('d','v','h','d') ) { p_access->psz_demux = strdup( "rawdv" ); } else if( p_stream->i_fourcc == VLC_FOURCC('m','p','2','v') ) { p_access->psz_demux = "mpgv"; } } /* Setup Access */ p_access->pf_read = NULL; p_access->pf_block = ReadCompressed; p_access->pf_control = AccessControl; p_access->pf_seek = NULL; p_access->info.i_update = 0; p_access->info.i_size = 0; p_access->info.i_pos = 0; p_access->info.b_eof = VLC_FALSE; p_access->info.i_title = 0; p_access->info.i_seekpoint = 0; p_access->p_sys = p_sys; /* Everything is ready. Let's rock baby */ msg_Dbg( p_this, "Playing..."); p_sys->p_control->Run(); return VLC_SUCCESS;}/***************************************************************************** * CommonClose: close device *****************************************************************************/static void CommonClose( vlc_object_t *p_this, access_sys_t *p_sys ){ msg_Dbg( p_this, "Releasing DirectShow"); DeleteDirectShowGraph( p_sys ); /* Uninitialize OLE/COM */ CoUninitialize(); for( int i = 0; i < p_sys->i_streams; i++ ) delete p_sys->pp_streams[i]; if( p_sys->i_streams ) free( p_sys->pp_streams ); vlc_mutex_destroy( &p_sys->lock ); vlc_cond_destroy( &p_sys->wait ); free( p_sys );}/***************************************************************************** * AccessClose: close device *****************************************************************************/static void AccessClose( vlc_object_t *p_this ){ access_t *p_access = (access_t *)p_this; access_sys_t *p_sys = p_access->p_sys; /* Stop capturing stuff */ p_sys->p_control->Stop(); CommonClose( p_this, p_sys );}/***************************************************************************** * DemuxClose: close device *****************************************************************************/static void DemuxClose( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t *)p_this; access_sys_t *p_sys = (access_sys_t *)p_demux->p_sys; /* Stop capturing stuff */ p_sys->p_control->Stop(); CommonClose( p_this, p_sys );}/**************************************************************************** * ConnectFilters ****************************************************************************/static bool ConnectFilters( vlc_object_t *p_this, access_sys_t *p_sys, IBaseFilter *p_filter, CaptureFilter *p_capture_filter ){ CapturePin *p_input_pin = p_capture_filter->CustomGetPin(); AM_MEDIA_TYPE mediaType = p_input_pin->CustomGetMediaType(); if( p_sys->p_capture_graph_builder2 ) { if( FAILED(p_sys->p_capture_graph_builder2-> RenderStream( &PIN_CATEGORY_CAPTURE, &mediaType.majortype, p_filter, 0, (IBaseFilter *)p_capture_filter )) ) { return false; } // Sort out all the possible video inputs // The class needs to be given the capture filters ANALOGVIDEO input pin IEnumPins *pins = 0; if( ( mediaType.majortype == MEDIATYPE_Video || mediaType.majortype == MEDIATYPE_Stream ) && SUCCEEDED(p_filter->EnumPins(&pins)) ) { IPin *pP = 0; ULONG n; PIN_INFO pinInfo; BOOL Found = FALSE; IKsPropertySet *pKs=0; GUID guid; DWORD dw; while( !Found && ( S_OK == pins->Next(1, &pP, &n) ) ) { if( S_OK == pP->QueryPinInfo(&pinInfo) ) { // is this pin an ANALOGVIDEOIN input pin? if( pinInfo.dir == PINDIR_INPUT && pP->QueryInterface( IID_IKsPropertySet, (void **)&pKs ) == S_OK ) { if( pKs->Get( AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, &guid, sizeof(GUID), &dw ) == S_OK ) { if( guid == PIN_CATEGORY_ANALOGVIDEOIN ) { // recursively search crossbar routes FindCrossbarRoutes( p_this, p_sys, pP, 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -