mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +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 *
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -52,6 +52,7 @@ struct _GstDecklinkVideoSrc
|
|||
|
||||
GstDecklinkModeEnum mode;
|
||||
GstDecklinkModeEnum caps_mode;
|
||||
BMDPixelFormat caps_format;
|
||||
GstDecklinkConnectionEnum connection;
|
||||
gint device_number;
|
||||
|
||||
|
|
Loading…
Reference in a new issue