mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
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:
parent
8c57341241
commit
3ea431c5b5
5 changed files with 63 additions and 23 deletions
|
@ -316,28 +316,53 @@ gst_decklink_get_connection (GstDecklinkConnectionEnum e)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStructure *
|
static GstStructure *
|
||||||
gst_decklink_mode_get_structure (GstDecklinkModeEnum e)
|
gst_decklink_mode_get_structure (GstDecklinkModeEnum e, BMDPixelFormat f)
|
||||||
{
|
{
|
||||||
const GstDecklinkMode *mode = &modes[e];
|
const GstDecklinkMode *mode = &modes[e];
|
||||||
|
GstStructure *s = gst_structure_new ("video/x-raw",
|
||||||
return gst_structure_new ("video/x-raw",
|
|
||||||
"format", G_TYPE_STRING, "UYVY",
|
|
||||||
"width", G_TYPE_INT, mode->width,
|
"width", G_TYPE_INT, mode->width,
|
||||||
"height", G_TYPE_INT, mode->height,
|
"height", G_TYPE_INT, mode->height,
|
||||||
"framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d,
|
"pixel-aspect-ratio", GST_TYPE_FRACTION, mode->par_n, mode->par_d,
|
||||||
"interlace-mode", G_TYPE_STRING,
|
"interlace-mode", G_TYPE_STRING, mode->interlaced ? "interleaved" : "progressive",
|
||||||
mode->interlaced ? "interleaved" : "progressive", "pixel-aspect-ratio",
|
"framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d, NULL);
|
||||||
GST_TYPE_FRACTION, mode->par_n, mode->par_d, "colorimetry", G_TYPE_STRING,
|
|
||||||
mode->colorimetry, "chroma-site", G_TYPE_STRING, "mpeg2", 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 *
|
GstCaps *
|
||||||
gst_decklink_mode_get_caps (GstDecklinkModeEnum e)
|
gst_decklink_mode_get_caps (GstDecklinkModeEnum e, BMDPixelFormat f)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
caps = gst_caps_new_empty ();
|
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;
|
return caps;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +376,9 @@ gst_decklink_mode_get_template_caps (void)
|
||||||
|
|
||||||
caps = gst_caps_new_empty ();
|
caps = gst_caps_new_empty ();
|
||||||
for (i = 1; i < (int) G_N_ELEMENTS (modes); i++) {
|
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);
|
gst_caps_append_structure (caps, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +392,7 @@ gst_decklink_find_mode_for_caps (GstCaps * caps)
|
||||||
GstCaps *mode_caps;
|
GstCaps *mode_caps;
|
||||||
|
|
||||||
for (i = 1; i < (int) G_N_ELEMENTS (modes); i++) {
|
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)) {
|
if (gst_caps_can_intersect (caps, mode_caps)) {
|
||||||
gst_caps_unref (mode_caps);
|
gst_caps_unref (mode_caps);
|
||||||
return gst_decklink_get_mode ((GstDecklinkModeEnum) i);
|
return gst_decklink_get_mode ((GstDecklinkModeEnum) i);
|
||||||
|
@ -470,19 +497,25 @@ public:
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE
|
virtual HRESULT STDMETHODCALLTYPE
|
||||||
VideoInputFormatChanged (BMDVideoInputFormatChangedEvents,
|
VideoInputFormatChanged (BMDVideoInputFormatChangedEvents,
|
||||||
IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags)
|
IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags formatFlags)
|
||||||
{
|
{
|
||||||
|
BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
|
||||||
|
|
||||||
GST_INFO ("Video input format changed");
|
GST_INFO ("Video input format changed");
|
||||||
|
|
||||||
|
if (formatFlags & bmdDetectedVideoInputRGB444)
|
||||||
|
pixelFormat = bmdFormat8BitARGB;
|
||||||
|
|
||||||
g_mutex_lock (&m_input->lock);
|
g_mutex_lock (&m_input->lock);
|
||||||
m_input->input->PauseStreams ();
|
m_input->input->PauseStreams ();
|
||||||
m_input->input->EnableVideoInput (mode->GetDisplayMode (),
|
m_input->input->EnableVideoInput (mode->GetDisplayMode (),
|
||||||
bmdFormat8BitYUV, bmdVideoInputEnableFormatDetection);
|
pixelFormat, bmdVideoInputEnableFormatDetection);
|
||||||
m_input->input->FlushStreams ();
|
m_input->input->FlushStreams ();
|
||||||
m_input->input->StartStreams ();
|
m_input->input->StartStreams ();
|
||||||
m_input->mode =
|
m_input->mode =
|
||||||
gst_decklink_get_mode (gst_decklink_get_mode_enum_from_bmd
|
gst_decklink_get_mode (gst_decklink_get_mode_enum_from_bmd
|
||||||
(mode->GetDisplayMode ()));
|
(mode->GetDisplayMode ()));
|
||||||
|
m_input->format = pixelFormat;
|
||||||
g_mutex_unlock (&m_input->lock);
|
g_mutex_unlock (&m_input->lock);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -126,7 +126,7 @@ struct _GstDecklinkMode {
|
||||||
const GstDecklinkMode * gst_decklink_get_mode (GstDecklinkModeEnum e);
|
const GstDecklinkMode * gst_decklink_get_mode (GstDecklinkModeEnum e);
|
||||||
const GstDecklinkModeEnum gst_decklink_get_mode_enum_from_bmd (BMDDisplayMode mode);
|
const GstDecklinkModeEnum gst_decklink_get_mode_enum_from_bmd (BMDDisplayMode mode);
|
||||||
const BMDVideoConnection gst_decklink_get_connection (GstDecklinkConnectionEnum e);
|
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);
|
GstCaps * gst_decklink_mode_get_template_caps (void);
|
||||||
|
|
||||||
typedef struct _GstDecklinkOutput GstDecklinkOutput;
|
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);
|
void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime capture_duration);
|
||||||
/* Configured mode or NULL */
|
/* Configured mode or NULL */
|
||||||
const GstDecklinkMode *mode;
|
const GstDecklinkMode *mode;
|
||||||
|
BMDPixelFormat format;
|
||||||
|
|
||||||
/* Set by the audio source */
|
/* Set by the audio source */
|
||||||
void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time);
|
void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time);
|
||||||
|
|
|
@ -330,7 +330,7 @@ gst_decklink_video_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
|
||||||
if (self->mode == GST_DECKLINK_MODE_AUTO)
|
if (self->mode == GST_DECKLINK_MODE_AUTO)
|
||||||
mode_caps = gst_decklink_mode_get_template_caps ();
|
mode_caps = gst_decklink_mode_get_template_caps ();
|
||||||
else
|
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);
|
mode_caps = gst_caps_make_writable (mode_caps);
|
||||||
/* For output we support any framerate and only really care about timestamps */
|
/* For output we support any framerate and only really care about timestamps */
|
||||||
gst_caps_map_in_place (mode_caps, reset_framerate, NULL);
|
gst_caps_map_in_place (mode_caps, reset_framerate, NULL);
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef struct
|
||||||
IDeckLinkVideoInputFrame *frame;
|
IDeckLinkVideoInputFrame *frame;
|
||||||
GstClockTime capture_time, capture_duration;
|
GstClockTime capture_time, capture_duration;
|
||||||
GstDecklinkModeEnum mode;
|
GstDecklinkModeEnum mode;
|
||||||
|
BMDPixelFormat format;
|
||||||
} CaptureFrame;
|
} CaptureFrame;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -178,6 +179,7 @@ gst_decklink_video_src_init (GstDecklinkVideoSrc * self)
|
||||||
{
|
{
|
||||||
self->mode = DEFAULT_MODE;
|
self->mode = DEFAULT_MODE;
|
||||||
self->caps_mode = GST_DECKLINK_MODE_AUTO;
|
self->caps_mode = GST_DECKLINK_MODE_AUTO;
|
||||||
|
self->caps_format = bmdFormat8BitYUV;
|
||||||
self->connection = DEFAULT_CONNECTION;
|
self->connection = DEFAULT_CONNECTION;
|
||||||
self->device_number = 0;
|
self->device_number = 0;
|
||||||
self->buffer_size = DEFAULT_BUFFER_SIZE;
|
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);
|
g_mutex_lock (&self->lock);
|
||||||
if (self->caps_mode != GST_DECKLINK_MODE_AUTO)
|
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
|
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);
|
g_mutex_unlock (&self->lock);
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
|
@ -481,6 +483,7 @@ gst_decklink_video_src_got_frame (GstElement * element,
|
||||||
f->capture_time = capture_time;
|
f->capture_time = capture_time;
|
||||||
f->capture_duration = capture_duration;
|
f->capture_duration = capture_duration;
|
||||||
f->mode = mode;
|
f->mode = mode;
|
||||||
|
f->format = frame->GetPixelFormat ();
|
||||||
frame->AddRef ();
|
frame->AddRef ();
|
||||||
g_queue_push_tail (&self->current_frames, f);
|
g_queue_push_tail (&self->current_frames, f);
|
||||||
g_cond_signal (&self->cond);
|
g_cond_signal (&self->cond);
|
||||||
|
@ -515,12 +518,14 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mutex_lock (&self->lock);
|
g_mutex_lock (&self->lock);
|
||||||
if (self->mode == GST_DECKLINK_MODE_AUTO && self->caps_mode != f->mode) {
|
if (self->mode == GST_DECKLINK_MODE_AUTO &&
|
||||||
GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode,
|
(self->caps_mode != f->mode || self->caps_format != f->format)) {
|
||||||
f->mode);
|
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_mode = f->mode;
|
||||||
|
self->caps_format = f->format;
|
||||||
g_mutex_unlock (&self->lock);
|
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_video_info_from_caps (&self->info, caps);
|
||||||
gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
|
gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (self),
|
gst_element_post_message (GST_ELEMENT_CAST (self),
|
||||||
|
|
|
@ -52,6 +52,7 @@ struct _GstDecklinkVideoSrc
|
||||||
|
|
||||||
GstDecklinkModeEnum mode;
|
GstDecklinkModeEnum mode;
|
||||||
GstDecklinkModeEnum caps_mode;
|
GstDecklinkModeEnum caps_mode;
|
||||||
|
BMDPixelFormat caps_format;
|
||||||
GstDecklinkConnectionEnum connection;
|
GstDecklinkConnectionEnum connection;
|
||||||
gint device_number;
|
gint device_number;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue