es_out_id_t *p_es;
bool b_pts;
+
+ deque<VLCMediaSample> samples_queue;
} dshow_stream_t;
/*****************************************************************************
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;
+ int i_stream;
+ int i_found_samples;
+ i_found_samples = 0;
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 )
+ while ( !i_found_samples )
{
+ /* Try to grab samples from all streams */
for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
{
- p_stream = p_sys->pp_streams[i_stream];
+ dshow_stream_t *p_stream = p_sys->pp_streams[i_stream];
if( p_stream->p_capture_filter &&
p_stream->p_capture_filter->CustomGetPin()
- ->CustomGetSample( &sample ) == S_OK )
+ ->CustomGetSamples( p_stream->samples_queue ) == S_OK )
{
- break;
+ i_found_samples = 1;
}
}
+
+ if ( !i_found_samples)
+ {
+ /* Didn't find any audio nor video sample, just wait till the
+ * dshow thread pushes some samples */
+ vlc_cond_wait( &p_sys->wait, &p_sys->lock );
+ /* Some DShow thread pushed data, or the OS broke the wait all
+ * by itself. In all cases, it's *strongly* advised to test the
+ * condition again, so let the loop do the test again */
+ }
}
vlc_mutex_unlock( &p_sys->lock );
- if( i_stream == p_sys->i_streams )
+ for ( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
{
- /* Sleep so we do not consume all the cpu, 10ms seems
- * like a good value (100fps) */
- msleep( 10000 );
- return 1;
- }
+ int i_samples;
+ dshow_stream_t *p_stream = p_sys->pp_streams[i_stream];
- /*
- * We got our sample
- */
- i_data_size = sample.p_sample->GetActualDataLength();
- sample.p_sample->GetPointer( &p_data );
+ i_samples = p_stream->samples_queue.size();
+ while ( i_samples > 0 )
+ {
+ int i_data_size;
+ uint8_t *p_data;
+ block_t *p_block;
+ VLCMediaSample sample;
- 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;
+ sample = p_stream->samples_queue.front();
+ p_stream->samples_queue.pop_front();
- 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 = true;
- }
- }
+ i_data_size = sample.p_sample->GetActualDataLength();
+ sample.p_sample->GetPointer( &p_data );
- i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */
+ 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 = true;
+ }
+ }
+
+ i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */
#if 0
- msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: %"PRId64,
- i_stream, i_data_size, i_pts );
+ msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: %"PRId64,
+ i_stream, i_data_size, i_pts );
#endif
- p_block = block_New( p_demux, i_data_size );
- vlc_memcpy( p_block->p_buffer, p_data, i_data_size );
- p_block->i_pts = p_block->i_dts = i_pts;
- sample.p_sample->Release();
+ p_block = block_New( p_demux, i_data_size );
+ vlc_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 );
+ 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 );
+
+ i_samples--;
+ }
+ }
return 1;
}
FreeMediaType(cx_media_type);
}
+/**
+ * Returns the complete queue of samples that have been received so far.
+ * Lock the p_sys->lock before calling this function.
+ * @param samples_queue [out] Empty queue that will get all elements from
+ * the pin queue.
+ * @return S_OK if a sample was available, S_FALSE if no sample was
+ * available
+ */
+HRESULT CapturePin::CustomGetSamples( deque<VLCMediaSample> &external_queue )
+{
+#if 0 //def DEBUG_DSHOW
+ msg_Dbg( p_input, "CapturePin::CustomGetSamples: %d samples in the queue", samples_queue.size());
+#endif
+
+ if( !samples_queue.empty() )
+ {
+ external_queue.swap(samples_queue);
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+/**
+ * Returns a sample from its sample queue. Proper locking must be done prior
+ * to this call. Current dshow code protects the access to any sample queue
+ * (audio and video) with the p_sys->lock
+ * @param vlc_sample [out] Address of a sample if sucessfull. Undefined
+ * otherwise.
+ * @return S_OK if a sample was available, S_FALSE if no sample was
+ * available
+ */
HRESULT CapturePin::CustomGetSample( VLCMediaSample *vlc_sample )
{
#if 0 //def DEBUG_DSHOW
msg_Dbg( p_input, "CapturePin::CustomGetSample" );
#endif
- vlc_mutex_lock( &p_sys->lock );
if( samples_queue.size() )
{
*vlc_sample = samples_queue.back();
samples_queue.pop_back();
- vlc_mutex_unlock( &p_sys->lock );
return S_OK;
}
- vlc_mutex_unlock( &p_sys->lock );
return S_FALSE;
}