]> git.sesse.net Git - vlc/blobdiff - modules/access/sdi.cpp
Set i_pts to frame end instead of frame start, to avoid i_pts=0.
[vlc] / modules / access / sdi.cpp
index 8b405ee3d71eb665a4325826dea18287d1f64618..201af4ac17f03b522f600251c7059c82aa6ea541 100644 (file)
@@ -53,6 +53,10 @@ struct demux_sys_t
     IDeckLinkInput *p_input;
     DeckLinkCaptureDelegate *p_delegate;
     es_out_id_t  *p_es;
+
+    vlc_mutex_t frame_lock;
+    block_t *p_frame;  // protected by <frame_lock>
+    vlc_cond_t has_frame;  // related to <frame_lock>
 };
 
 class DeckLinkCaptureDelegate : public IDeckLinkInputCallback
@@ -80,7 +84,38 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged(BMDVideoInputFormatChan
 
 HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrame, IDeckLinkAudioInputPacket* audioFrame)
 {
-    msg_Dbg( p_demux_, "Received a frame" );
+    demux_sys_t *p_sys = p_demux_->p_sys;
+
+    if(videoFrame)
+    {
+        if(videoFrame->GetFlags() & bmdFrameHasNoInputSource)
+        {
+            msg_Warn( p_demux_, "No input signal detected" );
+            return S_OK;
+        }
+
+        block_t *p_frame;
+        p_frame = block_New( p_demux_, 720 * 576 * 3 );
+        if( !p_frame )
+        {
+            msg_Err( p_demux_, "Could not allocate memory for frame" );
+            return S_OK;
+        }
+
+        void *frame_bytes;
+        videoFrame->GetBytes( &frame_bytes );
+        memcpy( p_frame->p_buffer, frame_bytes, 720 * 576 * 3 );
+
+        BMDTimeValue stream_time, frame_duration;
+        videoFrame->GetStreamTime( &stream_time, &frame_duration, 1000000 );
+        p_frame->i_pts = stream_time + frame_duration;  // FIXME: hack to avoid i_pts=0?
+
+        vlc_mutex_lock( &p_sys->frame_lock );
+        p_sys->p_frame = p_frame;  // FIXME: leak
+        vlc_cond_signal( &p_sys->has_frame );
+        vlc_mutex_unlock( &p_sys->frame_lock );
+    }
+
     return S_OK;
 }
 
@@ -103,10 +138,13 @@ static int Open( vlc_object_t *p_this )
     if( !p_sys )
         return VLC_ENOMEM;
 
-    msg_Dbg( p_demux, "hello world" );
+    vlc_mutex_init( &p_sys->frame_lock );
+    vlc_cond_init( &p_sys->has_frame );
+    p_sys->p_frame = NULL;
 
     IDeckLinkIterator *decklink_iterator = CreateDeckLinkIteratorInstance();
-    if ( !decklink_iterator ) {
+    if( !decklink_iterator )
+    {
         msg_Err( p_demux, "DeckLink drivers not found." );
         // FIXME: Leak here and several other error paths.
         return VLC_EGENERIC;
@@ -115,12 +153,14 @@ static int Open( vlc_object_t *p_this )
     HRESULT result;
     result = decklink_iterator->Next( &p_sys->p_card );
 
-    if ( result != S_OK ) {
+    if( result != S_OK )
+    {
         msg_Err( p_demux, "No DeckLink PCI cards found" );
         return VLC_EGENERIC;
     }
 
-    if ( p_sys->p_card->QueryInterface(IID_IDeckLinkInput, (void**)&p_sys->p_input) != S_OK ) {
+    if( p_sys->p_card->QueryInterface(IID_IDeckLinkInput, (void**)&p_sys->p_input) != S_OK )
+    {
         msg_Err( p_demux, "Card has no inputs" );
         return VLC_EGENERIC;
     }
@@ -129,25 +169,29 @@ static int Open( vlc_object_t *p_this )
     p_sys->p_input->SetCallback( p_sys->p_delegate );
 
     result = p_sys->p_input->EnableVideoInput(bmdModePAL, bmdFormat8BitYUV, 0);
-    if ( result != S_OK ) {
+    if( result != S_OK )
+    {
         msg_Err( p_demux, "Failed to enable video input" );
         return VLC_EGENERIC;
     }
 
     // FIXME: add audio
     result = p_sys->p_input->StartStreams();
-    if ( result != S_OK ) {
+    if( result != S_OK )
+    {
         msg_Err( p_demux, "Failed to start streams" );
         return VLC_EGENERIC;
     }
 
     /*eDeclare elementary streams */
     es_format_t fmt;
-    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_YUYV );
+    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_UYVY );
     fmt.video.i_width = 720;
     fmt.video.i_height = 576;
-    fmt.video.i_sar_num = 1;
-    fmt.video.i_sar_den = 1;
+    fmt.video.i_sar_num = 16 * fmt.video.i_height;
+    fmt.video.i_sar_den = 9 * fmt.video.i_width;
+    fmt.video.i_frame_rate = 25;
+    fmt.video.i_frame_rate_base = 1;
 
     msg_Dbg( p_demux, "added new video es %4.4s %dx%d",
              (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
@@ -203,8 +247,20 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 static int Demux( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
+    block_t *p_block;
+
+    vlc_mutex_lock( &p_sys->frame_lock );
+
+    while( !p_sys->p_frame )
+        vlc_cond_wait( &p_sys->has_frame, &p_sys->frame_lock );
+
+    p_block = p_sys->p_frame;
+    p_sys->p_frame = NULL;
+
+    vlc_mutex_unlock( &p_sys->frame_lock );
 
-    // FIXME
+    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
+    es_out_Send( p_demux->out, p_sys->p_es, p_block );
 
     return 1;
 }