#define NTSC 10, 11, false, "bt601"
#define PAL 12, 11, true, "bt601"
-#define HD 1, 1, false, "bt709"
-#define UHD 1, 1, false, "bt2020"
+#define HD 1, 1, true, "bt709"
+#define UHD 1, 1, true, "bt2020"
static const GstDecklinkMode modes[] = {
{bmdModeNTSC, 720, 486, 30000, 1001, true, NTSC}, // default is ntsc
}
static GstStructure *
-gst_decklink_mode_get_structure (GstDecklinkModeEnum e, BMDPixelFormat f)
+gst_decklink_mode_get_structure (GstDecklinkModeEnum e, BMDPixelFormat f, gboolean input)
{
const GstDecklinkMode *mode = &modes[e];
GstStructure *s = gst_structure_new ("video/x-raw",
mode->interlaced ? "interleaved" : "progressive",
"framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d, NULL);
+ if (input && mode->interlaced) {
+ if (mode->tff)
+ gst_structure_set (s, "field-order", G_TYPE_STRING, "top-field-first", NULL);
+ else
+ gst_structure_set (s, "field-order", G_TYPE_STRING, "bottom-field-first", NULL);
+ }
+
switch (f) {
case bmdFormat8BitYUV: /* '2vuy' */
gst_structure_set (s, "format", G_TYPE_STRING, "UYVY",
}
GstCaps *
-gst_decklink_mode_get_caps (GstDecklinkModeEnum e, BMDPixelFormat f)
+gst_decklink_mode_get_caps (GstDecklinkModeEnum e, BMDPixelFormat f, gboolean input)
{
GstCaps *caps;
caps = gst_caps_new_empty ();
caps =
- gst_caps_merge_structure (caps, gst_decklink_mode_get_structure (e, f));
+ gst_caps_merge_structure (caps, gst_decklink_mode_get_structure (e, f, input));
return caps;
}
GstCaps *
-gst_decklink_mode_get_caps_all_formats (GstDecklinkModeEnum e)
+gst_decklink_mode_get_caps_all_formats (GstDecklinkModeEnum e, gboolean input)
{
GstCaps *caps;
guint i;
for (i = 1; i < G_N_ELEMENTS (formats); i++)
caps =
gst_caps_merge_structure (caps, gst_decklink_mode_get_structure (e,
- formats[i].format));
+ formats[i].format, input));
return caps;
}
GstCaps *
-gst_decklink_pixel_format_get_caps (BMDPixelFormat f)
+gst_decklink_pixel_format_get_caps (BMDPixelFormat f, gboolean input)
{
int i;
GstCaps *caps;
caps = gst_caps_new_empty ();
for (i = 1; i < (int) G_N_ELEMENTS (modes); i++) {
- s = gst_decklink_mode_get_structure ((GstDecklinkModeEnum) i, f);
+ s = gst_decklink_mode_get_structure ((GstDecklinkModeEnum) i, f, input);
caps = gst_caps_merge_structure (caps, s);
}
}
GstCaps *
-gst_decklink_mode_get_template_caps (void)
+gst_decklink_mode_get_template_caps (gboolean input)
{
int i;
GstCaps *caps;
for (i = 1; i < (int) G_N_ELEMENTS (modes); i++)
caps =
gst_caps_merge (caps,
- gst_decklink_mode_get_caps_all_formats ((GstDecklinkModeEnum) i));
+ gst_decklink_mode_get_caps_all_formats ((GstDecklinkModeEnum) i, input));
return caps;
}
return NULL;
for (i = 1; i < (int) G_N_ELEMENTS (modes); i++) {
- mode_caps = gst_decklink_mode_get_caps ((GstDecklinkModeEnum) i, *format);
+ mode_caps = gst_decklink_mode_get_caps ((GstDecklinkModeEnum) i, *format, FALSE);
if (gst_caps_can_intersect (caps, mode_caps)) {
gst_caps_unref (mode_caps);
return gst_decklink_get_mode ((GstDecklinkModeEnum) i);
GST_WARNING ("selected device does not have input interface: 0x%08x",
ret);
} else {
+ IDeckLinkDisplayModeIterator *mode_iter;
+
devices[i].input.device = decklink;
devices[i].input.
input->SetCallback (new GStreamerDecklinkInputCallback (&devices[i].
input));
+
+ if ((ret =
+ devices[i].input.input->GetDisplayModeIterator (&mode_iter)) ==
+ S_OK) {
+ IDeckLinkDisplayMode *mode;
+
+ GST_DEBUG ("Input %d supports:", i);
+ while ((ret = mode_iter->Next (&mode)) == S_OK) {
+ const char *name;
+
+ mode->GetName (&name);
+ GST_DEBUG (" %s mode: 0x%08x width: %ld height: %ld"
+ " fields: 0x%08x flags: 0x%08x", name,
+ (int) mode->GetDisplayMode (), mode->GetWidth (),
+ mode->GetHeight (), (int) mode->GetFieldDominance (),
+ (int) mode->GetFlags ());
+ mode->Release ();
+ }
+ mode_iter->Release ();
+ }
+ ret = S_OK;
}
ret = decklink->QueryInterface (IID_IDeckLinkOutput,
GST_WARNING ("selected device does not have output interface: 0x%08x",
ret);
} else {
+ IDeckLinkDisplayModeIterator *mode_iter;
+
devices[i].output.device = decklink;
devices[i].output.clock =
gst_decklink_clock_new ("GstDecklinkOutputClock");
GST_DECKLINK_CLOCK_CAST (devices[i].output.clock)->output =
&devices[i].output;
+
+ if ((ret =
+ devices[i].output.output->GetDisplayModeIterator (&mode_iter)) ==
+ S_OK) {
+ IDeckLinkDisplayMode *mode;
+
+ GST_DEBUG ("Output %d supports:", i);
+ while ((ret = mode_iter->Next (&mode)) == S_OK) {
+ const char *name;
+
+ mode->GetName (&name);
+ GST_DEBUG (" %s mode: 0x%08x width: %ld height: %ld"
+ " fields: 0x%08x flags: 0x%08x", name,
+ (int) mode->GetDisplayMode (), mode->GetWidth (),
+ mode->GetHeight (), (int) mode->GetFieldDominance (),
+ (int) mode->GetFlags ());
+ mode->Release ();
+ }
+ mode_iter->Release ();
+ }
+ ret = S_OK;
}
ret = decklink->QueryInterface (IID_IDeckLinkConfiguration,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
- templ_caps = gst_decklink_mode_get_template_caps ();
+ templ_caps = gst_decklink_mode_get_template_caps (FALSE);
templ_caps = gst_caps_make_writable (templ_caps);
/* For output we support any framerate and only really care about timestamps */
gst_caps_map_in_place (templ_caps, reset_framerate, NULL);
if (self->mode == GST_DECKLINK_MODE_AUTO
&& self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO)
- mode_caps = gst_decklink_mode_get_template_caps ();
+ mode_caps = gst_decklink_mode_get_template_caps (FALSE);
else if (self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO)
- mode_caps = gst_decklink_mode_get_caps_all_formats (self->mode);
+ mode_caps = gst_decklink_mode_get_caps_all_formats (self->mode, FALSE);
else if (self->mode == GST_DECKLINK_MODE_AUTO)
mode_caps =
gst_decklink_pixel_format_get_caps (gst_decklink_pixel_format_from_type
- (self->video_format));
+ (self->video_format), FALSE);
else
mode_caps =
gst_decklink_mode_get_caps (self->mode,
- gst_decklink_pixel_format_from_type (self->video_format));
+ gst_decklink_pixel_format_from_type (self->video_format), FALSE);
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);
DEFAULT_DROP_NO_SIGNAL_FRAMES,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
- templ_caps = gst_decklink_mode_get_template_caps ();
+ templ_caps = gst_decklink_mode_get_template_caps (TRUE);
gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps));
gst_caps_unref (templ_caps);
format = self->caps_format;
g_mutex_unlock (&self->lock);
- mode_caps = gst_decklink_mode_get_caps (mode, format);
+ mode_caps = gst_decklink_mode_get_caps (mode, format, TRUE);
if (filter) {
caps =
CaptureFrame *f;
GstCaps *caps;
gboolean caps_changed = FALSE;
+ const GstDecklinkMode *mode;
g_mutex_lock (&self->lock);
while (g_queue_is_empty (&self->current_frames) && !self->flushing) {
g_mutex_unlock (&self->lock);
if (caps_changed) {
- caps = gst_decklink_mode_get_caps (f->mode, f->format);
+ caps = gst_decklink_mode_get_caps (f->mode, f->format, TRUE);
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),
GST_BUFFER_DURATION (*buffer) = f->duration;
gst_buffer_add_video_time_code_meta (*buffer, f->tc);
+ mode = gst_decklink_get_mode (self->mode);
+ if (mode->interlaced && mode->tff)
+ GST_BUFFER_FLAG_SET (*buffer, GST_VIDEO_BUFFER_FLAG_TFF | GST_VIDEO_BUFFER_FLAG_INTERLACED);
+
GST_DEBUG_OBJECT (self,
"Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)),