From 3ea431c5b5425806b7139025b6f233999563594d Mon Sep 17 00:00:00 2001 From: Julien Moutte Date: Wed, 13 Jan 2016 22:05:49 +0100 Subject: [PATCH] decklinkvideosrc: implement RGB capture support Combine mode and format to generate caps and support the flags from VideoChanged callback to support RGB capture. https://bugzilla.gnome.org/show_bug.cgi?id=760594 --- sys/decklink/gstdecklink.cpp | 63 ++++++++++++++++++++------- sys/decklink/gstdecklink.h | 3 +- sys/decklink/gstdecklinkvideosink.cpp | 2 +- sys/decklink/gstdecklinkvideosrc.cpp | 17 +++++--- sys/decklink/gstdecklinkvideosrc.h | 1 + 5 files changed, 63 insertions(+), 23 deletions(-) diff --git a/sys/decklink/gstdecklink.cpp b/sys/decklink/gstdecklink.cpp index c0d1128b05..64637f1d9f 100644 --- a/sys/decklink/gstdecklink.cpp +++ b/sys/decklink/gstdecklink.cpp @@ -316,28 +316,53 @@ gst_decklink_get_connection (GstDecklinkConnectionEnum e) } static GstStructure * -gst_decklink_mode_get_structure (GstDecklinkModeEnum e) +gst_decklink_mode_get_structure (GstDecklinkModeEnum e, BMDPixelFormat f) { const GstDecklinkMode *mode = &modes[e]; - - return gst_structure_new ("video/x-raw", - "format", G_TYPE_STRING, "UYVY", + GstStructure *s = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, mode->width, "height", G_TYPE_INT, mode->height, - "framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d, - "interlace-mode", G_TYPE_STRING, - mode->interlaced ? "interleaved" : "progressive", "pixel-aspect-ratio", - GST_TYPE_FRACTION, mode->par_n, mode->par_d, "colorimetry", G_TYPE_STRING, - mode->colorimetry, "chroma-site", G_TYPE_STRING, "mpeg2", NULL); + "pixel-aspect-ratio", GST_TYPE_FRACTION, mode->par_n, mode->par_d, + "interlace-mode", G_TYPE_STRING, mode->interlaced ? "interleaved" : "progressive", + "framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d, NULL); + + switch (f) { + case bmdFormat8BitYUV: /* '2vuy' */ + gst_structure_set (s, "format", G_TYPE_STRING, "UYVY", + "colorimetry", G_TYPE_STRING, mode->colorimetry, + "chroma-site", G_TYPE_STRING, "mpeg2", NULL); + break; + case bmdFormat10BitYUV: /* 'v210' */ + gst_structure_set (s, "format", G_TYPE_STRING, "v210", NULL); + break; + case bmdFormat8BitARGB: /* 'ARGB' */ + gst_structure_set (s, "format", G_TYPE_STRING, "ARGB", NULL); + break; + case bmdFormat8BitBGRA: /* 'BGRA' */ + gst_structure_set (s, "format", G_TYPE_STRING, "BGRA", NULL); + break; + case bmdFormat10BitRGB: /* 'r210' Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10 */ + case bmdFormat12BitRGB: /* 'R12B' Big-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component */ + case bmdFormat12BitRGBLE: /* 'R12L' Little-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component */ + case bmdFormat10BitRGBXLE: /* 'R10l' Little-endian 10-bit RGB with SMPTE video levels (64-940) */ + case bmdFormat10BitRGBX: /* 'R10b' Big-endian 10-bit RGB with SMPTE video levels (64-940) */ + default: + GST_WARNING ("format not supported %d", f); + gst_structure_free (s); + s = NULL; + break; + } + + return s; } GstCaps * -gst_decklink_mode_get_caps (GstDecklinkModeEnum e) +gst_decklink_mode_get_caps (GstDecklinkModeEnum e, BMDPixelFormat f) { GstCaps *caps; caps = gst_caps_new_empty (); - gst_caps_append_structure (caps, gst_decklink_mode_get_structure (e)); + gst_caps_append_structure (caps, gst_decklink_mode_get_structure (e, f)); return caps; } @@ -351,7 +376,9 @@ gst_decklink_mode_get_template_caps (void) caps = gst_caps_new_empty (); for (i = 1; i < (int) G_N_ELEMENTS (modes); i++) { - s = gst_decklink_mode_get_structure ((GstDecklinkModeEnum) i); + s = gst_decklink_mode_get_structure ((GstDecklinkModeEnum) i, bmdFormat8BitYUV); + gst_caps_append_structure (caps, s); + s = gst_decklink_mode_get_structure ((GstDecklinkModeEnum) i, bmdFormat8BitARGB); gst_caps_append_structure (caps, s); } @@ -365,7 +392,7 @@ gst_decklink_find_mode_for_caps (GstCaps * caps) GstCaps *mode_caps; for (i = 1; i < (int) G_N_ELEMENTS (modes); i++) { - mode_caps = gst_decklink_mode_get_caps ((GstDecklinkModeEnum) i); + mode_caps = gst_decklink_mode_get_caps ((GstDecklinkModeEnum) i, bmdFormat8BitYUV); if (gst_caps_can_intersect (caps, mode_caps)) { gst_caps_unref (mode_caps); return gst_decklink_get_mode ((GstDecklinkModeEnum) i); @@ -470,19 +497,25 @@ public: virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged (BMDVideoInputFormatChangedEvents, - IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags) + IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags formatFlags) { + BMDPixelFormat pixelFormat = bmdFormat8BitYUV; + GST_INFO ("Video input format changed"); + if (formatFlags & bmdDetectedVideoInputRGB444) + pixelFormat = bmdFormat8BitARGB; + g_mutex_lock (&m_input->lock); m_input->input->PauseStreams (); m_input->input->EnableVideoInput (mode->GetDisplayMode (), - bmdFormat8BitYUV, bmdVideoInputEnableFormatDetection); + pixelFormat, bmdVideoInputEnableFormatDetection); m_input->input->FlushStreams (); m_input->input->StartStreams (); m_input->mode = gst_decklink_get_mode (gst_decklink_get_mode_enum_from_bmd (mode->GetDisplayMode ())); + m_input->format = pixelFormat; g_mutex_unlock (&m_input->lock); return S_OK; diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h index 493b48e5c2..6c32feef6c 100644 --- a/sys/decklink/gstdecklink.h +++ b/sys/decklink/gstdecklink.h @@ -126,7 +126,7 @@ struct _GstDecklinkMode { const GstDecklinkMode * gst_decklink_get_mode (GstDecklinkModeEnum e); const GstDecklinkModeEnum gst_decklink_get_mode_enum_from_bmd (BMDDisplayMode mode); const BMDVideoConnection gst_decklink_get_connection (GstDecklinkConnectionEnum e); -GstCaps * gst_decklink_mode_get_caps (GstDecklinkModeEnum e); +GstCaps * gst_decklink_mode_get_caps (GstDecklinkModeEnum e, BMDPixelFormat f); GstCaps * gst_decklink_mode_get_template_caps (void); typedef struct _GstDecklinkOutput GstDecklinkOutput; @@ -172,6 +172,7 @@ struct _GstDecklinkInput { void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime capture_duration); /* Configured mode or NULL */ const GstDecklinkMode *mode; + BMDPixelFormat format; /* Set by the audio source */ void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time); diff --git a/sys/decklink/gstdecklinkvideosink.cpp b/sys/decklink/gstdecklinkvideosink.cpp index 7111cb1c55..eebeff3287 100644 --- a/sys/decklink/gstdecklinkvideosink.cpp +++ b/sys/decklink/gstdecklinkvideosink.cpp @@ -330,7 +330,7 @@ gst_decklink_video_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) if (self->mode == GST_DECKLINK_MODE_AUTO) mode_caps = gst_decklink_mode_get_template_caps (); else - mode_caps = gst_decklink_mode_get_caps (self->mode); + mode_caps = gst_decklink_mode_get_caps (self->mode, bmdFormat8BitYUV); mode_caps = gst_caps_make_writable (mode_caps); /* For output we support any framerate and only really care about timestamps */ gst_caps_map_in_place (mode_caps, reset_framerate, NULL); diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp index 915393eaf3..2b304f9123 100644 --- a/sys/decklink/gstdecklinkvideosrc.cpp +++ b/sys/decklink/gstdecklinkvideosrc.cpp @@ -47,6 +47,7 @@ typedef struct IDeckLinkVideoInputFrame *frame; GstClockTime capture_time, capture_duration; GstDecklinkModeEnum mode; + BMDPixelFormat format; } CaptureFrame; static void @@ -178,6 +179,7 @@ gst_decklink_video_src_init (GstDecklinkVideoSrc * self) { self->mode = DEFAULT_MODE; self->caps_mode = GST_DECKLINK_MODE_AUTO; + self->caps_format = bmdFormat8BitYUV; self->connection = DEFAULT_CONNECTION; self->device_number = 0; self->buffer_size = DEFAULT_BUFFER_SIZE; @@ -352,9 +354,9 @@ gst_decklink_video_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter) g_mutex_lock (&self->lock); if (self->caps_mode != GST_DECKLINK_MODE_AUTO) - mode_caps = gst_decklink_mode_get_caps (self->caps_mode); + mode_caps = gst_decklink_mode_get_caps (self->caps_mode, self->caps_format); else - mode_caps = gst_decklink_mode_get_caps (self->mode); + mode_caps = gst_decklink_mode_get_caps (self->mode, self->caps_format); g_mutex_unlock (&self->lock); if (filter) { @@ -481,6 +483,7 @@ gst_decklink_video_src_got_frame (GstElement * element, f->capture_time = capture_time; f->capture_duration = capture_duration; f->mode = mode; + f->format = frame->GetPixelFormat (); frame->AddRef (); g_queue_push_tail (&self->current_frames, f); g_cond_signal (&self->cond); @@ -515,12 +518,14 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) } g_mutex_lock (&self->lock); - if (self->mode == GST_DECKLINK_MODE_AUTO && self->caps_mode != f->mode) { - GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode, - f->mode); + if (self->mode == GST_DECKLINK_MODE_AUTO && + (self->caps_mode != f->mode || self->caps_format != f->format)) { + GST_DEBUG_OBJECT (self, "Mode/Format changed from %d/%d to %d/%d", + self->caps_mode, self->caps_format, f->mode, f->format); self->caps_mode = f->mode; + self->caps_format = f->format; g_mutex_unlock (&self->lock); - caps = gst_decklink_mode_get_caps (f->mode); + caps = gst_decklink_mode_get_caps (f->mode, f->format); gst_video_info_from_caps (&self->info, caps); gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps); gst_element_post_message (GST_ELEMENT_CAST (self), diff --git a/sys/decklink/gstdecklinkvideosrc.h b/sys/decklink/gstdecklinkvideosrc.h index 6cb5bb9d34..b83495f0ca 100644 --- a/sys/decklink/gstdecklinkvideosrc.h +++ b/sys/decklink/gstdecklinkvideosrc.h @@ -52,6 +52,7 @@ struct _GstDecklinkVideoSrc GstDecklinkModeEnum mode; GstDecklinkModeEnum caps_mode; + BMDPixelFormat caps_format; GstDecklinkConnectionEnum connection; gint device_number;