Commit aac0027e authored by Sebastian Dröge's avatar Sebastian Dröge 🍵

decklink: Implement latency query in sources and remember selected mode

parent 23d6eaaa
......@@ -121,6 +121,10 @@ struct _GstDecklinkOutput {
/* Everything below protected by mutex */
GMutex lock;
/* Set by the video source */
/* Configured mode or NULL */
const GstDecklinkMode *mode;
/* Set by the audio sink */
GstClock *audio_clock;
......@@ -141,6 +145,8 @@ struct _GstDecklinkInput {
/* Set by the video source */
void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstClockTime capture_time);
/* Configured mode or NULL */
const GstDecklinkMode *mode;
/* Set by the audio source */
void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time);
......
......@@ -498,8 +498,11 @@ gst_decklink_audio_sink_init (GstDecklinkAudioSink * self)
{
self->device_number = 0;
// 25ms latency time seems to be needed at least,
// 25.000ms latency time seems to be needed at least,
// everything below can cause drop-outs
// TODO: This is probably related to the video mode that
// is selected, but not directly it seems. Choosing the
// duration of a frame does not work.
GST_AUDIO_BASE_SINK_CAST (self)->latency_time = 25000;
}
......
......@@ -60,6 +60,8 @@ static GstCaps *gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc,
GstCaps * filter);
static gboolean gst_decklink_audio_src_unlock (GstBaseSrc * bsrc);
static gboolean gst_decklink_audio_src_unlock_stop (GstBaseSrc * bsrc);
static gboolean gst_decklink_audio_src_query (GstBaseSrc * bsrc,
GstQuery * query);
static GstFlowReturn gst_decklink_audio_src_create (GstPushSrc * psrc,
GstBuffer ** buffer);
......@@ -89,6 +91,7 @@ gst_decklink_audio_src_class_init (GstDecklinkAudioSrcClass * klass)
basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_get_caps);
basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_set_caps);
basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_query);
basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock);
basesrc_class->unlock_stop =
GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock_stop);
......@@ -333,6 +336,44 @@ gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
return flow_ret;
}
static gboolean
gst_decklink_audio_src_query (GstBaseSrc * bsrc, GstQuery * query)
{
GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
gboolean ret = TRUE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:{
if (self->input) {
g_mutex_lock (&self->input->lock);
if (self->input->mode) {
GstClockTime min, max;
min =
gst_util_uint64_scale_ceil (GST_MSECOND, self->input->mode->fps_d,
self->input->mode->fps_n);
max = min;
gst_query_set_latency (query, TRUE, min, max);
ret = TRUE;
} else {
ret = FALSE;
}
g_mutex_unlock (&self->input->lock);
} else {
ret = FALSE;
}
break;
}
default:
ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
break;
}
return ret;
}
static gboolean
gst_decklink_audio_src_unlock (GstBaseSrc * bsrc)
{
......
......@@ -313,6 +313,10 @@ gst_decklink_video_sink_open (GstBaseSink * bsink)
return FALSE;
}
g_mutex_lock (&self->output->lock);
self->output->mode = mode;
g_mutex_unlock (&self->output->lock);
caps = gst_decklink_mode_get_caps (self->mode);
gst_video_info_from_caps (&self->info, caps);
gst_caps_unref (caps);
......@@ -328,6 +332,10 @@ gst_decklink_video_sink_close (GstBaseSink * bsink)
GST_DEBUG_OBJECT (self, "Stopping");
if (self->output) {
g_mutex_lock (&self->output->lock);
self->output->mode = NULL;
g_mutex_unlock (&self->output->lock);
self->output->output->DisableVideoOutput ();
gst_decklink_release_nth_output (self->device_number,
GST_ELEMENT_CAST (self), FALSE);
......
......@@ -48,6 +48,8 @@ static GstClock *gst_decklink_video_src_provide_clock (GstElement * element);
static GstCaps *gst_decklink_video_src_get_caps (GstBaseSrc * bsrc,
GstCaps * filter);
static gboolean gst_decklink_video_src_query (GstBaseSrc * bsrc,
GstQuery * query);
static gboolean gst_decklink_video_src_unlock (GstBaseSrc * bsrc);
static gboolean gst_decklink_video_src_unlock_stop (GstBaseSrc * bsrc);
......@@ -79,6 +81,7 @@ gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass)
GST_DEBUG_FUNCPTR (gst_decklink_video_src_provide_clock);
basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_video_src_get_caps);
basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_video_src_query);
basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock);
basesrc_class->unlock_stop =
GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock_stop);
......@@ -197,7 +200,8 @@ gst_decklink_video_src_got_frame (GstElement * element,
{
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
GST_LOG_OBJECT (self, "Got video frame at %" GST_TIME_FORMAT, GST_TIME_ARGS (capture_time));
GST_LOG_OBJECT (self, "Got video frame at %" GST_TIME_FORMAT,
GST_TIME_ARGS (capture_time));
g_mutex_lock (&self->lock);
if (!self->flushing) {
......@@ -276,6 +280,40 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
return flow_ret;
}
static gboolean
gst_decklink_video_src_query (GstBaseSrc * bsrc, GstQuery * query)
{
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
gboolean ret = TRUE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:{
if (self->input) {
GstClockTime min, max;
const GstDecklinkMode *mode;
mode = gst_decklink_get_mode (self->mode);
min =
gst_util_uint64_scale_ceil (GST_MSECOND, mode->fps_d, mode->fps_n);
max = min;
gst_query_set_latency (query, TRUE, min, max);
ret = TRUE;
} else {
ret = FALSE;
}
break;
}
default:
ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
break;
}
return ret;
}
static gboolean
gst_decklink_video_src_unlock (GstBaseSrc * bsrc)
{
......@@ -331,6 +369,7 @@ gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
}
g_mutex_lock (&self->input->lock);
self->input->mode = mode;
self->input->got_video_frame = gst_decklink_video_src_got_frame;
g_mutex_unlock (&self->input->lock);
......@@ -350,6 +389,7 @@ gst_decklink_video_src_close (GstDecklinkVideoSrc * self)
if (self->input) {
g_mutex_lock (&self->input->lock);
self->input->got_video_frame = NULL;
self->input->mode = NULL;
g_mutex_unlock (&self->input->lock);
self->input->input->DisableVideoInput ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment