{
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"},
#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},
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,
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;
}
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) {
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++;
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)
{
IDeckLinkVideoInputFrame *frame;
GstClockTime capture_time;
+ GstDecklinkModeEnum mode;
} CaptureFrame;
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;
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);
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);
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);
VideoFrame *vf;
CaptureFrame *f;
GstClockTime timestamp, duration;
+ GstCaps *caps;
g_mutex_lock (&self->lock);
while (g_queue_is_empty (&self->current_frames) && !self->flushing) {
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;
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;
gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
{
const GstDecklinkMode *mode;
+ BMDVideoInputFlags flags;
+ bool autoDetection;
GstCaps *caps;
HRESULT ret;
}
}
+ 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,
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);