📄 dshow.cpp
字号:
mt[mt_count++] = *p_mt; /* Setup a few properties like the audio latency */ IAMBufferNegotiation *p_ambuf; if( SUCCEEDED( p_output_pin->QueryInterface( IID_IAMBufferNegotiation, (void **)&p_ambuf ) ) ) { ALLOCATOR_PROPERTIES AllocProp; AllocProp.cbAlign = -1; /* 100 ms of latency */ AllocProp.cbBuffer = i_current_channels * i_current_samplespersec * i_current_bitspersample / 8 / 10; AllocProp.cbPrefix = -1; AllocProp.cBuffers = -1; p_ambuf->SuggestAllocatorProperties( &AllocProp ); p_ambuf->Release(); } } else FreeMediaType( *p_mt ); } else if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Stream ) { msg_Dbg( p_this, "EnumDeviceCaps: input pin " "accepts stream format: %4.4s", (char *)&i_current_fourcc ); if( ( !i_fourcc || i_fourcc == i_current_fourcc ) && mt_count < mt_max ) { /* Pick match */ mt[mt_count++] = *p_mt; i_fourcc = i_current_fourcc; } else FreeMediaType( *p_mt ); } else { char *psz_type = "unknown"; if( p_mt->majortype == MEDIATYPE_Video ) psz_type = "video"; if( p_mt->majortype == MEDIATYPE_Audio ) psz_type = "audio"; if( p_mt->majortype == MEDIATYPE_Stream ) psz_type = "stream"; msg_Dbg( p_this, "EnumDeviceCaps: input pin media: unknown format " "(%s %4.4s)", psz_type, (char *)&p_mt->subtype ); FreeMediaType( *p_mt ); } CoTaskMemFree( (PVOID)p_mt ); } p_enummt->Release(); p_output_pin->Release(); } p_enumpins->Release(); return mt_count;}/***************************************************************************** * ReadCompressed: reads compressed (MPEG/DV) data from the device. ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, otherwise the number of * bytes. *****************************************************************************/static block_t *ReadCompressed( access_t *p_access ){ access_sys_t *p_sys = p_access->p_sys; dshow_stream_t *p_stream = NULL; VLCMediaSample sample; /* Read 1 DV/MPEG frame (they contain the video and audio data) */ /* There must be only 1 elementary stream to produce a valid stream * of MPEG or DV data */ p_stream = p_sys->pp_streams[0]; while( 1 ) { if( p_access->b_die || p_access->b_error ) return 0; /* Get new sample/frame from the elementary stream (blocking). */ vlc_mutex_lock( &p_sys->lock ); if( p_stream->p_capture_filter->CustomGetPin() ->CustomGetSample( &sample ) != S_OK ) { /* No data available. Wait until some data has arrived */ vlc_cond_wait( &p_sys->wait, &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock ); continue; } vlc_mutex_unlock( &p_sys->lock ); /* * We got our sample */ block_t *p_block; uint8_t *p_data; int i_data_size = sample.p_sample->GetActualDataLength(); if( !i_data_size || !(p_block = block_New( p_access, i_data_size )) ) { sample.p_sample->Release(); continue; } sample.p_sample->GetPointer( &p_data ); p_access->p_vlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size ); sample.p_sample->Release(); /* The caller got what he wanted */ return p_block; } return 0; /* never reached */}/**************************************************************************** * Demux: ****************************************************************************/static int Demux( demux_t *p_demux ){ access_sys_t *p_sys = (access_sys_t *)p_demux->p_sys; dshow_stream_t *p_stream = NULL; VLCMediaSample sample; int i_data_size, i_stream; uint8_t *p_data; block_t *p_block; vlc_mutex_lock( &p_sys->lock ); /* Try to grab an audio sample (audio has a higher priority) */ for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { p_stream = p_sys->pp_streams[i_stream]; if( p_stream->mt.majortype == MEDIATYPE_Audio && p_stream->p_capture_filter && p_stream->p_capture_filter->CustomGetPin() ->CustomGetSample( &sample ) == S_OK ) { break; } } /* Try to grab a video sample */ if( i_stream == p_sys->i_streams ) { for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { p_stream = p_sys->pp_streams[i_stream]; if( p_stream->p_capture_filter && p_stream->p_capture_filter->CustomGetPin() ->CustomGetSample( &sample ) == S_OK ) { break; } } } vlc_mutex_unlock( &p_sys->lock ); if( i_stream == p_sys->i_streams ) { /* Sleep so we do not consume all the cpu, 10ms seems * like a good value (100fps) */ msleep( 10000 ); return 1; } /* * We got our sample */ i_data_size = sample.p_sample->GetActualDataLength(); sample.p_sample->GetPointer( &p_data ); REFERENCE_TIME i_pts, i_end_date; HRESULT hr = sample.p_sample->GetTime( &i_pts, &i_end_date ); if( hr != VFW_S_NO_STOP_TIME && hr != S_OK ) i_pts = 0; if( !i_pts ) { if( p_stream->mt.majortype == MEDIATYPE_Video || !p_stream->b_pts ) { /* Use our data timestamp */ i_pts = sample.i_timestamp; p_stream->b_pts = VLC_TRUE; } } i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */#if 0 msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: "I64Fd, i_stream, i_data_size, i_pts );#endif p_block = block_New( p_demux, i_data_size ); p_demux->p_vlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size ); p_block->i_pts = p_block->i_dts = i_pts; sample.p_sample->Release(); es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pts > 0 ? i_pts : 0 ); es_out_Send( p_demux->out, p_stream->p_es, p_block ); return 1;}/***************************************************************************** * AccessControl: *****************************************************************************/static int AccessControl( access_t *p_access, int i_query, va_list args ){ vlc_bool_t *pb_bool; int *pi_int; int64_t *pi_64; switch( i_query ) { /* */ case ACCESS_CAN_SEEK: case ACCESS_CAN_FASTSEEK: case ACCESS_CAN_PAUSE: case ACCESS_CAN_CONTROL_PACE: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); *pb_bool = VLC_FALSE; break; /* */ case ACCESS_GET_MTU: pi_int = (int*)va_arg( args, int * ); *pi_int = 0; break; case ACCESS_GET_PTS_DELAY: pi_64 = (int64_t*)va_arg( args, int64_t * ); *pi_64 = (int64_t)var_GetInteger( p_access, "dshow-caching" ) * 1000; break; /* */ case ACCESS_SET_PAUSE_STATE: case ACCESS_GET_TITLE_INFO: case ACCESS_SET_TITLE: case ACCESS_SET_SEEKPOINT: case ACCESS_SET_PRIVATE_ID_STATE: return VLC_EGENERIC; default: msg_Warn( p_access, "unimplemented query in control" ); return VLC_EGENERIC; } return VLC_SUCCESS;}/**************************************************************************** * DemuxControl: ****************************************************************************/static int DemuxControl( demux_t *p_demux, int i_query, va_list args ){ vlc_bool_t *pb; int64_t *pi64; switch( i_query ) { /* Special for access_demux */ case DEMUX_CAN_PAUSE: case DEMUX_SET_PAUSE_STATE: case DEMUX_CAN_CONTROL_PACE: pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * ); *pb = VLC_FALSE; return VLC_SUCCESS; case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = (int64_t)var_GetInteger( p_demux, "dshow-caching" ) * 1000; return VLC_SUCCESS; case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = mdate(); return VLC_SUCCESS; /* TODO implement others */ default: return VLC_EGENERIC; } return VLC_EGENERIC;}/***************************************************************************** * config variable callback *****************************************************************************/static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name, vlc_value_t newval, vlc_value_t oldval, void * ){ module_config_t *p_item; vlc_bool_t b_audio = VLC_FALSE; int i; p_item = config_FindConfig( p_this, psz_name ); if( !p_item ) return VLC_SUCCESS; if( !strcmp( psz_name, "dshow-adev" ) ) b_audio = VLC_TRUE; /* Clear-up the current list */ if( p_item->i_list ) { /* Keep the 2 first entries */ for( i = 2; i < p_item->i_list; i++ ) { free( p_item->ppsz_list[i] ); free( p_item->ppsz_list_text[i] ); } /* TODO: Remove when no more needed */ p_item->ppsz_list[i] = NULL; p_item->ppsz_list_text[i] = NULL; } p_item->i_list = 2; /* Find list of devices */ list<string> list_devices; /* Initialize OLE/COM */ CoInitialize( 0 ); FindCaptureDevice( p_this, NULL, &list_devices, b_audio ); /* Uninitialize OLE/COM */ CoUninitialize(); if( !list_devices.size() ) return VLC_SUCCESS; p_item->ppsz_list = (char **)realloc( p_item->ppsz_list, (list_devices.size()+3) * sizeof(char *) ); p_item->ppsz_list_text = (char **)realloc( p_item->ppsz_list_text, (list_devices.size()+3) * sizeof(char *) ); list<string>::iterator iter; for( iter = list_devices.begin(), i = 2; iter != list_devices.end(); iter++, i++ ) { p_item->ppsz_list[i] = strdup( iter->c_str() ); p_item->ppsz_list_text[i] = NULL; p_item->i_list++; } p_item->ppsz_list[i] = NULL; p_item->ppsz_list_text[i] = NULL; /* Signal change to the interface */ p_i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -