[vlc-devel] [PATCH] access: decklink: Support rgb input modes

Julian Scheel julian at jusst.de
Mon Oct 16 12:45:54 CEST 2017


Check if the card reports yuv or rgb input and set the codec format
accordingly.

Signed-off-by: Julian Scheel <julian at jusst.de>
---
 modules/access/decklink.cpp | 68 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 16 deletions(-)

diff --git a/modules/access/decklink.cpp b/modules/access/decklink.cpp
index 4c5f826fbd..04f0b469f4 100644
--- a/modules/access/decklink.cpp
+++ b/modules/access/decklink.cpp
@@ -140,6 +140,7 @@ struct demux_sys_t
     bool autodetect;
 
     es_out_id_t *video_es;
+    es_format_t video_fmt;
     es_out_id_t *audio_es;
     es_out_id_t *cc_es;
 
@@ -172,7 +173,8 @@ static const char *GetFieldDominance(BMDFieldDominance dom, uint32_t *flags)
     }
 }
 
-static es_format_t GetModeSettings(demux_t *demux, IDeckLinkDisplayMode *m)
+static es_format_t GetModeSettings(demux_t *demux, IDeckLinkDisplayMode *m,
+        BMDDetectedVideoInputFormatFlags fmt_flags)
 {
     demux_sys_t *sys = demux->p_sys;
     uint32_t flags = 0;
@@ -185,7 +187,18 @@ static es_format_t GetModeSettings(demux_t *demux, IDeckLinkDisplayMode *m)
     }
 
     es_format_t video_fmt;
-    vlc_fourcc_t chroma = sys->tenbits ? VLC_CODEC_I422_10L : VLC_CODEC_UYVY;
+    vlc_fourcc_t chroma = 0;
+    switch (fmt_flags) {
+        case bmdDetectedVideoInputYCbCr422:
+            chroma = sys->tenbits ? VLC_CODEC_I422_10L : VLC_CODEC_UYVY;
+            break;
+        case bmdDetectedVideoInputRGB444:
+            chroma = VLC_CODEC_ARGB;
+            break;
+        default:
+            msg_Err(demux, "Unsupported input format");
+            break;
+    }
     es_format_Init(&video_fmt, VIDEO_ES, chroma);
 
     video_fmt.video.i_chroma = chroma;
@@ -232,7 +245,7 @@ public:
         return new_ref;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags)
+    virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags flags)
     {
         demux_sys_t *sys = demux_->p_sys;
 
@@ -249,11 +262,23 @@ public:
             return S_OK;
         }
 
+        BMDPixelFormat fmt = 0;
+        switch (flags) {
+            case bmdDetectedVideoInputYCbCr422:
+                fmt = sys->tenbits ? bmdFormat10BitYUV : bmdFormat8BitYUV;
+                break;
+            case bmdDetectedVideoInputRGB444:
+                fmt = bmdFormat8BitARGB;
+                break;
+            default:
+                msg_Err(demux_, "Unsupported input format");
+                return S_OK;
+        }
+
         es_out_Del(demux_->out, sys->video_es);
-        es_format_t video_fmt = GetModeSettings(demux_, mode);
-        sys->video_es = es_out_Add(demux_->out, &video_fmt);
+        sys->video_fmt = GetModeSettings(demux_, mode, flags);
+        sys->video_es = es_out_Add(demux_->out, &sys->video_fmt);
 
-        BMDPixelFormat fmt = sys->tenbits ? bmdFormat10BitYUV : bmdFormat8BitYUV;
         sys->input->PauseStreams();
         sys->input->EnableVideoInput( mode->GetDisplayMode(), fmt, bmdVideoInputEnableFormatDetection );
         sys->input->FlushStreams();
@@ -275,7 +300,8 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
 
     if (videoFrame) {
         if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) {
-            msg_Warn(demux_, "No input signal detected");
+            msg_Warn(demux_, "No input signal detected (%dx%d)",
+			    videoFrame->GetWidth(), videoFrame->GetHeight());
             return S_OK;
         }
 
@@ -283,7 +309,16 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
         const int height = videoFrame->GetHeight();
         const int stride = videoFrame->GetRowBytes();
 
-        int bpp = sys->tenbits ? 4 : 2;
+        int bpp = 0;
+        switch (sys->video_fmt.i_codec) {
+            case VLC_CODEC_I422_10L:
+            case VLC_CODEC_ARGB:
+                bpp = 4;
+                break;
+            case VLC_CODEC_UYVY:
+                bpp = 2;
+                break;
+        };
         block_t *video_frame = block_Alloc(width * height * bpp);
         if (!video_frame)
             return S_OK;
@@ -296,7 +331,7 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
         video_frame->i_flags = BLOCK_FLAG_TYPE_I | sys->dominance_flags;
         video_frame->i_pts = video_frame->i_dts = VLC_TS_0 + stream_time;
 
-        if (sys->tenbits) {
+        if (sys->video_fmt.i_codec == VLC_CODEC_I422_10L) {
             v210_convert((uint16_t*)video_frame->p_buffer, frame_bytes, width, height);
             IDeckLinkVideoFrameAncillary *vanc;
             if (videoFrame->GetAncillaryData(&vanc) == S_OK) {
@@ -329,12 +364,14 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame
                 }
                 vanc->Release();
             }
-        } else {
+        } else if (sys->video_fmt.i_codec == VLC_CODEC_UYVY) {
             for (int y = 0; y < height; ++y) {
                 const uint8_t *src = (const uint8_t *)frame_bytes + stride * y;
                 uint8_t *dst = video_frame->p_buffer + width * 2 * y;
                 memcpy(dst, src, width * 2);
             }
+        } else {
+                memcpy(video_frame->p_buffer, frame_bytes, width * height * bpp);
         }
 
         vlc_mutex_lock(&sys->pts_lock);
@@ -558,8 +595,7 @@ static int Open(vlc_object_t *p_this)
         free(mode);
     }
 
-    es_format_t video_fmt;
-    video_fmt.video.i_width = 0;
+    sys->video_fmt.video.i_width = 0;
 
     for (IDeckLinkDisplayMode *m;; m->Release()) {
         if ((mode_it->Next(&m) != S_OK) || !m)
@@ -584,14 +620,14 @@ static int Open(vlc_object_t *p_this)
                  double(time_scale) / frame_duration, field);
 
         if (u.id == id) {
-            video_fmt = GetModeSettings(demux, m);
+            sys->video_fmt = GetModeSettings(demux, m, bmdDetectedVideoInputYCbCr422);
             msg_Dbg(demux, "Using that mode");
         }
     }
 
     mode_it->Release();
 
-    if (video_fmt.video.i_width == 0) {
+    if (sys->video_fmt.video.i_width == 0) {
         msg_Err(demux, "Unknown video mode `%4.4s\' specified.", (char*)&u.id);
         goto finish;
     }
@@ -635,8 +671,8 @@ static int Open(vlc_object_t *p_this)
     }
 
     msg_Dbg(demux, "added new video es %4.4s %dx%d",
-             (char*)&video_fmt.i_codec, video_fmt.video.i_width, video_fmt.video.i_height);
-    sys->video_es = es_out_Add(demux->out, &video_fmt);
+             (char*)&sys->video_fmt.i_codec, sys->video_fmt.video.i_width, sys->video_fmt.video.i_height);
+    sys->video_es = es_out_Add(demux->out, &sys->video_fmt);
 
     es_format_t audio_fmt;
     es_format_Init(&audio_fmt, AUDIO_ES, VLC_CODEC_S16N);
-- 
2.14.2



More information about the vlc-devel mailing list