mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
decklinkvideosrc: Add automatic mode detection
https://bugzilla.gnome.org/show_bug.cgi?id=739284
This commit is contained in:
parent
9dcf650a17
commit
9480d91ad4
4 changed files with 178 additions and 11 deletions
|
@ -38,6 +38,8 @@ gst_decklink_mode_get_type (void)
|
|||
{
|
||||
static gsize id = 0;
|
||||
static const GEnumValue modes[] = {
|
||||
{GST_DECKLINK_MODE_AUTO, "auto", "Automatic detection"},
|
||||
|
||||
{GST_DECKLINK_MODE_NTSC, "ntsc", "NTSC SD 60i"},
|
||||
{GST_DECKLINK_MODE_NTSC2398, "ntsc2398", "NTSC SD 60i (24 fps)"},
|
||||
{GST_DECKLINK_MODE_PAL, "pal", "PAL SD 50i"},
|
||||
|
@ -140,6 +142,8 @@ gst_decklink_audio_connection_get_type (void)
|
|||
#define HD 1, 1, false, true
|
||||
|
||||
static const GstDecklinkMode modes[] = {
|
||||
{bmdModeNTSC, 720, 486, 30000, 1001, true, NTSC}, // default is ntsc
|
||||
|
||||
{bmdModeNTSC, 720, 486, 30000, 1001, true, NTSC},
|
||||
{bmdModeNTSC2398, 720, 486, 24000, 1001, true, NTSC},
|
||||
{bmdModePAL, 720, 576, 25, 1, true, PAL},
|
||||
|
@ -181,11 +185,113 @@ static const GstDecklinkMode modes[] = {
|
|||
const GstDecklinkMode *
|
||||
gst_decklink_get_mode (GstDecklinkModeEnum e)
|
||||
{
|
||||
if (e < GST_DECKLINK_MODE_NTSC || e > GST_DECKLINK_MODE_3184p60)
|
||||
if (e < GST_DECKLINK_MODE_AUTO || e > GST_DECKLINK_MODE_3184p60)
|
||||
return NULL;
|
||||
return &modes[e];
|
||||
}
|
||||
|
||||
const GstDecklinkModeEnum
|
||||
gst_decklink_get_mode_enum_from_bmd (BMDDisplayMode mode)
|
||||
{
|
||||
GstDecklinkModeEnum displayMode = GST_DECKLINK_MODE_NTSC;
|
||||
switch (mode) {
|
||||
case bmdModeNTSC:
|
||||
displayMode = GST_DECKLINK_MODE_NTSC;
|
||||
break;
|
||||
case bmdModeNTSC2398:
|
||||
displayMode = GST_DECKLINK_MODE_NTSC2398;
|
||||
break;
|
||||
case bmdModePAL:
|
||||
displayMode = GST_DECKLINK_MODE_PAL;
|
||||
break;
|
||||
case bmdModeNTSCp:
|
||||
displayMode = GST_DECKLINK_MODE_NTSC_P;
|
||||
break;
|
||||
case bmdModePALp:
|
||||
displayMode = GST_DECKLINK_MODE_PAL_P;
|
||||
break;
|
||||
case bmdModeHD1080p2398:
|
||||
displayMode = GST_DECKLINK_MODE_1080p2398;
|
||||
break;
|
||||
case bmdModeHD1080p24:
|
||||
displayMode = GST_DECKLINK_MODE_1080p24;
|
||||
break;
|
||||
case bmdModeHD1080p25:
|
||||
displayMode = GST_DECKLINK_MODE_1080p25;
|
||||
break;
|
||||
case bmdModeHD1080p2997:
|
||||
displayMode = GST_DECKLINK_MODE_1080p2997;
|
||||
break;
|
||||
case bmdModeHD1080p30:
|
||||
displayMode = GST_DECKLINK_MODE_1080p30;
|
||||
break;
|
||||
case bmdModeHD1080i50:
|
||||
displayMode = GST_DECKLINK_MODE_1080i50;
|
||||
break;
|
||||
case bmdModeHD1080i5994:
|
||||
displayMode = GST_DECKLINK_MODE_1080i5994;
|
||||
break;
|
||||
case bmdModeHD1080i6000:
|
||||
displayMode = GST_DECKLINK_MODE_1080i60;
|
||||
break;
|
||||
case bmdModeHD1080p50:
|
||||
displayMode = GST_DECKLINK_MODE_1080p50;
|
||||
break;
|
||||
case bmdModeHD1080p5994:
|
||||
displayMode = GST_DECKLINK_MODE_1080p5994;
|
||||
break;
|
||||
case bmdModeHD1080p6000:
|
||||
displayMode = GST_DECKLINK_MODE_1080p60;
|
||||
break;
|
||||
case bmdModeHD720p50:
|
||||
displayMode = GST_DECKLINK_MODE_720p50;
|
||||
break;
|
||||
case bmdModeHD720p5994:
|
||||
displayMode = GST_DECKLINK_MODE_720p5994;
|
||||
break;
|
||||
case bmdModeHD720p60:
|
||||
displayMode = GST_DECKLINK_MODE_720p60;
|
||||
break;
|
||||
case bmdMode2k2398:
|
||||
displayMode = GST_DECKLINK_MODE_2048p2398;
|
||||
break;
|
||||
case bmdMode2k24:
|
||||
displayMode = GST_DECKLINK_MODE_2048p24;
|
||||
break;
|
||||
case bmdMode2k25:
|
||||
displayMode = GST_DECKLINK_MODE_2048p25;
|
||||
break;
|
||||
case bmdMode4K2160p2398:
|
||||
displayMode = GST_DECKLINK_MODE_3184p2398;
|
||||
break;
|
||||
case bmdMode4K2160p24:
|
||||
displayMode = GST_DECKLINK_MODE_3184p24;
|
||||
break;
|
||||
case bmdMode4K2160p25:
|
||||
displayMode = GST_DECKLINK_MODE_3184p25;
|
||||
break;
|
||||
case bmdMode4K2160p2997:
|
||||
displayMode = GST_DECKLINK_MODE_3184p2997;
|
||||
break;
|
||||
case bmdMode4K2160p30:
|
||||
displayMode = GST_DECKLINK_MODE_3184p30;
|
||||
break;
|
||||
case bmdMode4K2160p50:
|
||||
displayMode = GST_DECKLINK_MODE_3184p50;
|
||||
break;
|
||||
case bmdMode4K2160p5994:
|
||||
displayMode = GST_DECKLINK_MODE_3184p5994;
|
||||
break;
|
||||
case bmdMode4K2160p60:
|
||||
displayMode = GST_DECKLINK_MODE_3184p60;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
return displayMode;
|
||||
}
|
||||
|
||||
static const BMDVideoConnection connections[] = {
|
||||
0, /* auto */
|
||||
bmdVideoConnectionSDI,
|
||||
|
@ -346,9 +452,21 @@ public:
|
|||
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
VideoInputFormatChanged (BMDVideoInputFormatChangedEvents,
|
||||
IDeckLinkDisplayMode *, BMDDetectedVideoInputFormatFlags)
|
||||
IDeckLinkDisplayMode * mode, BMDDetectedVideoInputFormatFlags)
|
||||
{
|
||||
GST_FIXME ("Video input format change not supported yet");
|
||||
GST_INFO ("Video input format changed");
|
||||
|
||||
g_mutex_lock (&m_input->lock);
|
||||
m_input->input->PauseStreams ();
|
||||
m_input->input->EnableVideoInput (mode->GetDisplayMode (),
|
||||
bmdFormat8BitYUV, 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 ()));
|
||||
g_mutex_unlock (&m_input->lock);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -362,7 +480,9 @@ public:
|
|||
if (m_input->got_video_frame) {
|
||||
GstClockTime capture_time = clock_time -
|
||||
gst_element_get_base_time (m_input->videosrc);
|
||||
m_input->got_video_frame (m_input->videosrc, video_frame, capture_time);
|
||||
m_input->got_video_frame (m_input->videosrc, video_frame,
|
||||
gst_decklink_get_mode_enum_from_bmd (m_input->mode->mode),
|
||||
capture_time);
|
||||
}
|
||||
|
||||
if (m_input->got_audio_packet) {
|
||||
|
@ -493,6 +613,12 @@ init_devices (gpointer data)
|
|||
GST_WARNING ("selected device does not have config interface");
|
||||
}
|
||||
|
||||
ret = decklink->QueryInterface (IID_IDeckLinkAttributes,
|
||||
(void **) &devices[i].input.attributes);
|
||||
if (ret != S_OK) {
|
||||
GST_WARNING ("selected device does not have attributes interface");
|
||||
}
|
||||
|
||||
ret = iterator->Next (&decklink);
|
||||
i++;
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#endif /* _MSC_VER */
|
||||
|
||||
typedef enum {
|
||||
GST_DECKLINK_MODE_AUTO,
|
||||
|
||||
GST_DECKLINK_MODE_NTSC,
|
||||
GST_DECKLINK_MODE_NTSC2398,
|
||||
GST_DECKLINK_MODE_PAL,
|
||||
|
@ -122,6 +124,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_template_caps (void);
|
||||
|
@ -152,13 +155,14 @@ struct _GstDecklinkInput {
|
|||
IDeckLink *device;
|
||||
IDeckLinkInput *input;
|
||||
IDeckLinkConfiguration *config;
|
||||
IDeckLinkAttributes *attributes;
|
||||
GstClock *clock;
|
||||
|
||||
/* Everything below protected by mutex */
|
||||
GMutex lock;
|
||||
|
||||
/* Set by the video source */
|
||||
void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstClockTime capture_time);
|
||||
void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time);
|
||||
/* Configured mode or NULL */
|
||||
const GstDecklinkMode *mode;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_decklink_video_src_debug);
|
||||
#define GST_CAT_DEFAULT gst_decklink_video_src_debug
|
||||
|
||||
#define DEFAULT_MODE (GST_DECKLINK_MODE_NTSC)
|
||||
#define DEFAULT_MODE (GST_DECKLINK_MODE_AUTO)
|
||||
#define DEFAULT_CONNECTION (GST_DECKLINK_CONNECTION_AUTO)
|
||||
#define DEFAULT_BUFFER_SIZE (5)
|
||||
|
||||
|
@ -46,6 +46,7 @@ typedef struct
|
|||
{
|
||||
IDeckLinkVideoInputFrame *frame;
|
||||
GstClockTime capture_time;
|
||||
GstDecklinkModeEnum mode;
|
||||
} CaptureFrame;
|
||||
|
||||
static void
|
||||
|
@ -169,6 +170,7 @@ static void
|
|||
gst_decklink_video_src_init (GstDecklinkVideoSrc * self)
|
||||
{
|
||||
self->mode = DEFAULT_MODE;
|
||||
self->caps_mode = DEFAULT_MODE;
|
||||
self->connection = DEFAULT_CONNECTION;
|
||||
self->device_number = 0;
|
||||
self->buffer_size = DEFAULT_BUFFER_SIZE;
|
||||
|
@ -249,7 +251,7 @@ gst_decklink_video_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
|||
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
|
||||
GstCaps *mode_caps, *caps;
|
||||
|
||||
mode_caps = gst_decklink_mode_get_caps (self->mode);
|
||||
mode_caps = gst_decklink_mode_get_caps (self->caps_mode);
|
||||
if (filter) {
|
||||
caps =
|
||||
gst_caps_intersect_full (filter, mode_caps, GST_CAPS_INTERSECT_FIRST);
|
||||
|
@ -263,7 +265,8 @@ gst_decklink_video_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
|||
|
||||
static void
|
||||
gst_decklink_video_src_got_frame (GstElement * element,
|
||||
IDeckLinkVideoInputFrame * frame, GstClockTime capture_time)
|
||||
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
|
||||
GstClockTime capture_time)
|
||||
{
|
||||
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
|
||||
|
||||
|
@ -284,6 +287,7 @@ gst_decklink_video_src_got_frame (GstElement * element,
|
|||
f = (CaptureFrame *) g_malloc0 (sizeof (CaptureFrame));
|
||||
f->frame = frame;
|
||||
f->capture_time = capture_time;
|
||||
f->mode = mode;
|
||||
frame->AddRef ();
|
||||
g_queue_push_tail (&self->current_frames, f);
|
||||
g_cond_signal (&self->cond);
|
||||
|
@ -301,6 +305,7 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
|
|||
VideoFrame *vf;
|
||||
CaptureFrame *f;
|
||||
GstClockTime timestamp, duration;
|
||||
GstCaps *caps;
|
||||
|
||||
g_mutex_lock (&self->lock);
|
||||
while (g_queue_is_empty (&self->current_frames) && !self->flushing) {
|
||||
|
@ -316,6 +321,14 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
|
|||
return GST_FLOW_FLUSHING;
|
||||
}
|
||||
|
||||
if (self->caps_mode != f->mode) {
|
||||
self->caps_mode = f->mode;
|
||||
caps = gst_decklink_mode_get_caps (self->caps_mode);
|
||||
gst_video_info_from_caps (&self->info, caps);
|
||||
gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
f->frame->GetBytes ((gpointer *) & data);
|
||||
data_size = self->info.size;
|
||||
|
||||
|
@ -362,7 +375,7 @@ gst_decklink_video_src_query (GstBaseSrc * bsrc, GstQuery * query)
|
|||
GstClockTime min, max;
|
||||
const GstDecklinkMode *mode;
|
||||
|
||||
mode = gst_decklink_get_mode (self->mode);
|
||||
mode = gst_decklink_get_mode (self->caps_mode);
|
||||
|
||||
min = gst_util_uint64_scale_ceil (GST_SECOND, mode->fps_d, mode->fps_n);
|
||||
max = self->buffer_size * min;
|
||||
|
@ -414,6 +427,8 @@ static gboolean
|
|||
gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
|
||||
{
|
||||
const GstDecklinkMode *mode;
|
||||
BMDVideoInputFlags flags;
|
||||
bool autoDetection;
|
||||
GstCaps *caps;
|
||||
HRESULT ret;
|
||||
|
||||
|
@ -446,11 +461,31 @@ gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
|
|||
}
|
||||
}
|
||||
|
||||
flags = bmdVideoInputFlagDefault;
|
||||
if (self->mode == GST_DECKLINK_MODE_AUTO) {
|
||||
if (self->input->attributes) {
|
||||
ret =
|
||||
self->input->
|
||||
attributes->GetFlag (BMDDeckLinkSupportsInputFormatDetection,
|
||||
&autoDetection);
|
||||
if (ret != S_OK) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get attribute (autodetection)");
|
||||
return FALSE;
|
||||
}
|
||||
if (autoDetection)
|
||||
flags |= bmdVideoInputEnableFormatDetection;
|
||||
}
|
||||
if (!autoDetection) {
|
||||
GST_ERROR_OBJECT (self, "Failed to activate auto-detection");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
mode = gst_decklink_get_mode (self->mode);
|
||||
g_assert (mode != NULL);
|
||||
|
||||
ret = self->input->input->EnableVideoInput (mode->mode,
|
||||
bmdFormat8BitYUV, bmdVideoOutputFlagDefault);
|
||||
bmdFormat8BitYUV, flags);
|
||||
if (ret != S_OK) {
|
||||
GST_WARNING_OBJECT (self, "Failed to enable video input");
|
||||
gst_decklink_release_nth_input (self->device_number,
|
||||
|
@ -463,7 +498,8 @@ gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
|
|||
self->input->got_video_frame = gst_decklink_video_src_got_frame;
|
||||
g_mutex_unlock (&self->input->lock);
|
||||
|
||||
caps = gst_decklink_mode_get_caps (self->mode);
|
||||
self->caps_mode = gst_decklink_get_mode_enum_from_bmd (mode->mode);
|
||||
caps = gst_decklink_mode_get_caps (self->caps_mode);
|
||||
gst_video_info_from_caps (&self->info, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ struct _GstDecklinkVideoSrc
|
|||
GstPushSrc parent;
|
||||
|
||||
GstDecklinkModeEnum mode;
|
||||
GstDecklinkModeEnum caps_mode;
|
||||
GstDecklinkConnectionEnum connection;
|
||||
gint device_number;
|
||||
|
||||
|
|
Loading…
Reference in a new issue