mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
decklinkaudiosrc/decklinkvideosrc: Do nothing in BaseSrc::negotiate() and always set caps in ::create()
We don't support negotiation with downstream but simply set caps based on the buffers we receive. This prevents renegotiation to other formats, and negotiation to NTSC in mode=auto in the beginning until the first buffer is received. As side-effect of this, also remove various other caps handling code that was working around the behaviour of the default BaseSrc::negotiate().
This commit is contained in:
parent
8257159909
commit
ab8bd0aa44
2 changed files with 64 additions and 131 deletions
|
@ -123,10 +123,6 @@ static GstStateChangeReturn
|
|||
gst_decklink_audio_src_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
|
||||
static gboolean gst_decklink_audio_src_set_caps (GstBaseSrc * bsrc,
|
||||
GstCaps * caps);
|
||||
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,
|
||||
|
@ -158,9 +154,8 @@ gst_decklink_audio_src_class_init (GstDecklinkAudioSrcClass * klass)
|
|||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_decklink_audio_src_change_state);
|
||||
|
||||
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->negotiate = NULL;
|
||||
basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock);
|
||||
basesrc_class->unlock_stop =
|
||||
GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock_stop);
|
||||
|
@ -234,6 +229,8 @@ gst_decklink_audio_src_init (GstDecklinkAudioSrc * self)
|
|||
gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
|
||||
gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
|
||||
|
||||
gst_pad_use_fixed_caps (GST_BASE_SRC_PAD (self));
|
||||
|
||||
g_mutex_init (&self->lock);
|
||||
g_cond_init (&self->cond);
|
||||
|
||||
|
@ -332,47 +329,42 @@ gst_decklink_audio_src_finalize (GObject * object)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_decklink_audio_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
||||
gst_decklink_audio_src_start (GstDecklinkAudioSrc * self)
|
||||
{
|
||||
GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
|
||||
BMDAudioSampleType sample_depth;
|
||||
GstCaps *current_caps;
|
||||
HRESULT ret;
|
||||
BMDAudioConnection conn = (BMDAudioConnection) - 1;
|
||||
GstCaps *allowed_caps, *caps;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Setting caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
if ((current_caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc)))) {
|
||||
GstCaps *curcaps_cp;
|
||||
GstStructure *cur_st, *caps_st;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Pad already has caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
curcaps_cp = gst_caps_make_writable (current_caps);
|
||||
cur_st = gst_caps_get_structure (curcaps_cp, 0);
|
||||
caps_st = gst_caps_get_structure (caps, 0);
|
||||
gst_structure_remove_field (cur_st, "channel-mask");
|
||||
|
||||
if (!gst_structure_can_intersect (caps_st, cur_st)) {
|
||||
GST_ERROR_OBJECT (self, "New caps are not compatible with old caps");
|
||||
gst_caps_unref (current_caps);
|
||||
gst_caps_unref (curcaps_cp);
|
||||
return FALSE;
|
||||
} else {
|
||||
gst_caps_unref (current_caps);
|
||||
gst_caps_unref (curcaps_cp);
|
||||
g_mutex_lock (&self->input->lock);
|
||||
if (self->input->audio_enabled) {
|
||||
g_mutex_unlock (&self->input->lock);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (&self->input->lock);
|
||||
|
||||
if (!gst_audio_info_from_caps (&self->info, caps))
|
||||
return FALSE;
|
||||
/* Negotiate the format / sample depth with downstream */
|
||||
allowed_caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (self));
|
||||
if (!allowed_caps)
|
||||
allowed_caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (self));
|
||||
|
||||
if (self->info.finfo->format == GST_AUDIO_FORMAT_S16LE) {
|
||||
sample_depth = bmdAudioSampleType16bitInteger;
|
||||
} else {
|
||||
sample_depth = bmdAudioSampleType32bitInteger;
|
||||
if (!gst_caps_is_empty (allowed_caps)) {
|
||||
GstStructure *s;
|
||||
|
||||
allowed_caps = gst_caps_simplify (allowed_caps);
|
||||
|
||||
s = gst_caps_get_structure (allowed_caps, 0);
|
||||
|
||||
/* If it's not a string then both formats are supported */
|
||||
if (gst_structure_has_field_typed (s, "format", G_TYPE_STRING)) {
|
||||
const gchar *format = gst_structure_get_string (s, "format");
|
||||
if (g_str_equal (format, "S16LE")) {
|
||||
sample_depth = bmdAudioSampleType16bitInteger;
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_caps_unref (allowed_caps);
|
||||
|
||||
switch (self->connection) {
|
||||
case GST_DECKLINK_AUDIO_CONNECTION_AUTO:{
|
||||
|
@ -449,12 +441,16 @@ gst_decklink_audio_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
|||
}
|
||||
|
||||
ret = self->input->input->EnableAudioInput (bmdAudioSampleRate48kHz,
|
||||
sample_depth, self->info.channels);
|
||||
sample_depth, self->channels_found);
|
||||
if (ret != S_OK) {
|
||||
GST_WARNING_OBJECT (self, "Failed to enable audio input: 0x%08lx",
|
||||
(unsigned long) ret);
|
||||
return FALSE;
|
||||
}
|
||||
gst_audio_info_set_format (&self->info,
|
||||
sample_depth ==
|
||||
bmdAudioSampleType16bitInteger ? GST_AUDIO_FORMAT_S16LE :
|
||||
GST_AUDIO_FORMAT_S32LE, 48000, self->channels_found, NULL);
|
||||
|
||||
g_mutex_lock (&self->input->lock);
|
||||
self->input->audio_enabled = TRUE;
|
||||
|
@ -462,46 +458,15 @@ gst_decklink_audio_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
|||
self->input->start_streams (self->input->videosrc);
|
||||
g_mutex_unlock (&self->input->lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||
{
|
||||
GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
|
||||
GstCaps *caps;
|
||||
|
||||
// We don't support renegotiation
|
||||
caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc));
|
||||
|
||||
if (!caps) {
|
||||
GstCaps *channel_filter, *templ;
|
||||
|
||||
templ = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
|
||||
if (self->channels_found > 0) {
|
||||
channel_filter =
|
||||
gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT,
|
||||
self->channels_found, NULL);
|
||||
} else if (self->channels > 0) {
|
||||
channel_filter =
|
||||
gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT,
|
||||
self->channels, NULL);
|
||||
} else {
|
||||
channel_filter = gst_caps_new_empty_simple ("audio/x-raw");
|
||||
}
|
||||
caps = gst_caps_intersect (channel_filter, templ);
|
||||
gst_caps_unref (channel_filter);
|
||||
gst_caps_unref (templ);
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
GstCaps *tmp =
|
||||
gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
|
||||
caps = gst_audio_info_to_caps (&self->info);
|
||||
if (!gst_base_src_set_caps (GST_BASE_SRC (self), caps)) {
|
||||
gst_caps_unref (caps);
|
||||
caps = tmp;
|
||||
GST_WARNING_OBJECT (self, "Failed to set caps");
|
||||
return FALSE;
|
||||
}
|
||||
gst_caps_unref (caps);
|
||||
|
||||
return caps;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -615,6 +580,10 @@ gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
|
|||
static GstStaticCaps hardware_reference =
|
||||
GST_STATIC_CAPS ("timestamp/x-decklink-hardware");
|
||||
|
||||
if (!gst_decklink_audio_src_start (self)) {
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
||||
retry:
|
||||
g_mutex_lock (&self->lock);
|
||||
while (gst_queue_array_is_empty (self->current_packets) && !self->flushing) {
|
||||
|
|
|
@ -223,10 +223,6 @@ static GstStateChangeReturn
|
|||
gst_decklink_video_src_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
|
||||
static gboolean gst_decklink_video_src_set_caps (GstBaseSrc * bsrc,
|
||||
GstCaps * caps);
|
||||
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);
|
||||
|
@ -261,9 +257,8 @@ gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass)
|
|||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_decklink_video_src_change_state);
|
||||
|
||||
basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_video_src_get_caps);
|
||||
basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_decklink_video_src_set_caps);
|
||||
basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_video_src_query);
|
||||
basesrc_class->negotiate = NULL;
|
||||
basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock);
|
||||
basesrc_class->unlock_stop =
|
||||
GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock_stop);
|
||||
|
@ -408,6 +403,8 @@ gst_decklink_video_src_init (GstDecklinkVideoSrc * self)
|
|||
gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
|
||||
gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
|
||||
|
||||
gst_pad_use_fixed_caps (GST_BASE_SRC_PAD (self));
|
||||
|
||||
g_mutex_init (&self->lock);
|
||||
g_cond_init (&self->cond);
|
||||
|
||||
|
@ -574,36 +571,19 @@ gst_decklink_video_src_finalize (GObject * object)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_decklink_video_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
||||
gst_decklink_video_src_start (GstDecklinkVideoSrc * self)
|
||||
{
|
||||
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
|
||||
GstCaps *current_caps;
|
||||
const GstDecklinkMode *mode;
|
||||
BMDVideoInputFlags flags;
|
||||
HRESULT ret;
|
||||
BMDPixelFormat format;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Setting caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
if ((current_caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc)))) {
|
||||
GST_DEBUG_OBJECT (self, "Pad already has caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
if (!gst_caps_is_equal (caps, current_caps)) {
|
||||
GST_DEBUG_OBJECT (self, "New caps, reconfiguring");
|
||||
gst_caps_unref (current_caps);
|
||||
if (self->mode == GST_DECKLINK_MODE_AUTO) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
gst_caps_unref (current_caps);
|
||||
g_mutex_lock (&self->input->lock);
|
||||
if (self->input->video_enabled) {
|
||||
g_mutex_unlock (&self->input->lock);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gst_video_info_from_caps (&self->info, caps))
|
||||
return FALSE;
|
||||
g_mutex_unlock (&self->input->lock);
|
||||
|
||||
if (self->input->config && self->connection != GST_DECKLINK_CONNECTION_AUTO) {
|
||||
ret = self->input->config->SetInt (bmdDeckLinkConfigVideoInputConnection,
|
||||
|
@ -672,32 +652,6 @@ gst_decklink_video_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_decklink_video_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||
{
|
||||
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
|
||||
GstCaps *mode_caps, *caps;
|
||||
BMDPixelFormat format;
|
||||
GstDecklinkModeEnum mode;
|
||||
|
||||
g_mutex_lock (&self->lock);
|
||||
mode = self->caps_mode;
|
||||
format = self->caps_format;
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
mode_caps = gst_decklink_mode_get_caps (mode, format, TRUE);
|
||||
|
||||
if (filter) {
|
||||
caps =
|
||||
gst_caps_intersect_full (filter, mode_caps, GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (mode_caps);
|
||||
} else {
|
||||
caps = mode_caps;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_decklink_video_src_update_time_mapping (GstDecklinkVideoSrc * self,
|
||||
GstClockTime capture_time, GstClockTime stream_time)
|
||||
|
@ -1207,6 +1161,10 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
|
|||
static GstStaticCaps hardware_reference =
|
||||
GST_STATIC_CAPS ("timestamp/x-decklink-hardware");
|
||||
|
||||
if (!gst_decklink_video_src_start (self)) {
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
||||
g_mutex_lock (&self->lock);
|
||||
retry:
|
||||
while (gst_queue_array_is_empty (self->current_frames) && !self->flushing) {
|
||||
|
@ -1252,8 +1210,13 @@ retry:
|
|||
// If we're not flushing, we should have a valid frame from the queue
|
||||
g_assert (f.frame != NULL);
|
||||
|
||||
if (!gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
|
||||
caps_changed = TRUE;
|
||||
}
|
||||
|
||||
if (self->caps_mode != f.mode) {
|
||||
if (self->mode == GST_DECKLINK_MODE_AUTO) {
|
||||
if (self->mode == GST_DECKLINK_MODE_AUTO
|
||||
|| !gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
|
||||
GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode,
|
||||
f.mode);
|
||||
caps_changed = TRUE;
|
||||
|
@ -1268,7 +1231,8 @@ retry:
|
|||
}
|
||||
}
|
||||
if (self->caps_format != f.format) {
|
||||
if (self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO) {
|
||||
if (self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO
|
||||
|| !gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
|
||||
GST_DEBUG_OBJECT (self, "Format changed from %d to %d", self->caps_format,
|
||||
f.format);
|
||||
caps_changed = TRUE;
|
||||
|
|
Loading…
Reference in a new issue