summaryrefslogtreecommitdiff
path: root/sys/decklink
diff options
context:
space:
mode:
authorVivia Nikolaidou <vivia@toolsonair.com>2016-05-15 17:25:44 +0300
committerSebastian Dröge <sebastian@centricular.com>2016-08-04 19:08:27 +0300
commitde1f42a28462ab71cc38830fd14c3e4d6fc4c85b (patch)
tree7a6345df5b893ba83cbee0002dae748d34df5539 /sys/decklink
parent8faa36e105ef4e0e525ba03f7710bc6f5c3b857f (diff)
downloadgstreamer-plugins-bad-de1f42a28462ab71cc38830fd14c3e4d6fc4c85b.tar.gz
decklinkvideosink: Add support for GstVideoTimeCode
The timecode will be fetched from the video buffer and outputted on the decklink video sink. https://bugzilla.gnome.org/show_bug.cgi?id=766419
Diffstat (limited to 'sys/decklink')
-rw-r--r--sys/decklink/gstdecklinkvideosink.cpp70
-rw-r--r--sys/decklink/gstdecklinkvideosink.h1
2 files changed, 68 insertions, 3 deletions
diff --git a/sys/decklink/gstdecklinkvideosink.cpp b/sys/decklink/gstdecklinkvideosink.cpp
index 551e5d7c0..7b842e6fb 100644
--- a/sys/decklink/gstdecklinkvideosink.cpp
+++ b/sys/decklink/gstdecklinkvideosink.cpp
@@ -119,7 +119,8 @@ enum
PROP_0,
PROP_MODE,
PROP_DEVICE_NUMBER,
- PROP_VIDEO_FORMAT
+ PROP_VIDEO_FORMAT,
+ PROP_TIMECODE_FORMAT
};
static void gst_decklink_video_sink_set_property (GObject * object,
@@ -213,6 +214,14 @@ gst_decklink_video_sink_class_init (GstDecklinkVideoSinkClass * klass)
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
+ g_object_class_install_property (gobject_class, PROP_TIMECODE_FORMAT,
+ g_param_spec_enum ("timecode-format", "Timecode format",
+ "Timecode format type to use for playback",
+ GST_TYPE_DECKLINK_TIMECODE_FORMAT,
+ GST_DECKLINK_TIMECODE_FORMAT_RP188ANY,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT)));
+
templ_caps = gst_decklink_mode_get_template_caps ();
templ_caps = gst_caps_make_writable (templ_caps);
/* For output we support any framerate and only really care about timestamps */
@@ -235,6 +244,8 @@ gst_decklink_video_sink_init (GstDecklinkVideoSink * self)
self->mode = GST_DECKLINK_MODE_NTSC;
self->device_number = 0;
self->video_format = GST_DECKLINK_VIDEO_FORMAT_8BIT_YUV;
+ /* VITC is legacy, we should expect RP188 in modern use cases */
+ self->timecode_format = bmdTimecodeRP188Any;
gst_base_sink_set_max_lateness (GST_BASE_SINK_CAST (self), 20 * GST_MSECOND);
gst_base_sink_set_qos_enabled (GST_BASE_SINK_CAST (self), TRUE);
@@ -268,6 +279,11 @@ gst_decklink_video_sink_set_property (GObject * object, guint property_id,
break;
}
break;
+ case PROP_TIMECODE_FORMAT:
+ self->timecode_format =
+ gst_decklink_timecode_format_from_enum ((GstDecklinkTimecodeFormat)
+ g_value_get_enum (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -290,6 +306,10 @@ gst_decklink_video_sink_get_property (GObject * object, guint property_id,
case PROP_VIDEO_FORMAT:
g_value_set_enum (value, self->video_format);
break;
+ case PROP_TIMECODE_FORMAT:
+ g_value_set_enum (value,
+ gst_decklink_timecode_format_to_enum (self->timecode_format));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -310,6 +330,7 @@ gst_decklink_video_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (bsink);
const GstDecklinkMode *mode;
HRESULT ret;
+ BMDVideoOutputFlags flags;
GST_DEBUG_OBJECT (self, "Setting caps %" GST_PTR_FORMAT, caps);
@@ -341,8 +362,21 @@ gst_decklink_video_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
g_assert (mode != NULL);
};
- ret = self->output->output->EnableVideoOutput (mode->mode,
- bmdVideoOutputFlagDefault);
+ /* The timecode_format itself is used when we embed the actual timecode data
+ * into the frame. Now we only need to know which of the two standards the
+ * timecode format will adhere to: VITC or RP188, and send the appropriate
+ * flag to EnableVideoOutput. The exact format is specified later.
+ *
+ * Note that this flag will have no effect in practice if the video stream
+ * does not contain timecode metadata.
+ */
+ if (self->timecode_format == GST_DECKLINK_TIMECODE_FORMAT_VITC ||
+ self->timecode_format == GST_DECKLINK_TIMECODE_FORMAT_VITCFIELD2)
+ flags = bmdVideoOutputVITC;
+ else
+ flags = bmdVideoOutputRP188;
+
+ ret = self->output->output->EnableVideoOutput (mode->mode, flags);
if (ret != S_OK) {
GST_WARNING_OBJECT (self, "Failed to enable video output");
return FALSE;
@@ -503,6 +537,7 @@ gst_decklink_video_sink_prepare (GstBaseSink * bsink, GstBuffer * buffer)
GstDecklinkVideoFormat caps_format;
BMDPixelFormat format;
gint bpp;
+ GstVideoTimeCodeMeta *tc_meta;
GST_DEBUG_OBJECT (self, "Preparing buffer %p", buffer);
@@ -575,6 +610,35 @@ gst_decklink_video_sink_prepare (GstBaseSink * bsink, GstBuffer * buffer)
}
gst_video_frame_unmap (&vframe);
+ tc_meta = gst_buffer_get_video_time_code_meta (buffer);
+ if (tc_meta) {
+ BMDTimecodeFlags bflags = (BMDTimecodeFlags) 0;
+ gchar *tc_str;
+
+ if (((GstVideoTimeCodeFlags) (tc_meta->tc.
+ config.flags)) & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME)
+ bflags = (BMDTimecodeFlags) (bflags | bmdTimecodeIsDropFrame);
+ else
+ bflags = (BMDTimecodeFlags) (bflags | bmdTimecodeFlagDefault);
+ if (tc_meta->tc.field_count == 2)
+ bflags = (BMDTimecodeFlags) (bflags | bmdTimecodeFieldMark);
+
+ tc_str = gst_video_time_code_to_string (&tc_meta->tc);
+ ret = frame->SetTimecodeFromComponents (self->timecode_format,
+ (uint8_t) tc_meta->tc.hours,
+ (uint8_t) tc_meta->tc.minutes,
+ (uint8_t) tc_meta->tc.seconds, (uint8_t) tc_meta->tc.frames, bflags);
+ if (ret != S_OK) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set timecode %s to video frame: 0x%08x", tc_str, ret);
+ flow_ret = GST_FLOW_ERROR;
+ g_free (tc_str);
+ goto out;
+ }
+ GST_DEBUG_OBJECT (self, "Set frame timecode to %s", tc_str);
+ g_free (tc_str);
+ }
+
convert_to_internal_clock (self, &running_time, &running_time_duration);
GST_LOG_OBJECT (self, "Scheduling video frame %p at %" GST_TIME_FORMAT
diff --git a/sys/decklink/gstdecklinkvideosink.h b/sys/decklink/gstdecklinkvideosink.h
index fb95591d2..b9aca283f 100644
--- a/sys/decklink/gstdecklinkvideosink.h
+++ b/sys/decklink/gstdecklinkvideosink.h
@@ -52,6 +52,7 @@ struct _GstDecklinkVideoSink
GstDecklinkModeEnum mode;
gint device_number;
GstDecklinkVideoFormat video_format;
+ BMDTimecodeFormat timecode_format;
GstVideoInfo info;