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
This commit is contained in:
Julien Moutte 2016-01-13 22:05:49 +01:00
parent 8c57341241
commit 3ea431c5b5
5 changed files with 63 additions and 23 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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),

View file

@ -52,6 +52,7 @@ struct _GstDecklinkVideoSrc
GstDecklinkModeEnum mode;
GstDecklinkModeEnum caps_mode;
BMDPixelFormat caps_format;
GstDecklinkConnectionEnum connection;
gint device_number;