v4l2: use GstV4l2Error in gst_v4l2_open()

gst_v4l2_open() is called by gst_v4l2_device_provider_probe_device(),
where the GstV4l2Object is created without an associated GstElement.

If gst_v4l2_open() fails, it raises a bus message, but without an
element, a precondition check fails on
gst_element_message_full_with_details() generating a crash if running
with fatal-warnings debug mode.

GstV4l2Error is a helper to raise error bus messages when it is
appropiated. This patch changes the direct bus messages to this
helper, and the elements will actually send the error message.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/694>
This commit is contained in:
Víctor Manuel Jáquez Leal 2020-08-06 13:15:10 +02:00 committed by GStreamer Merge Bot
parent c95cc6a015
commit 078560e70a
10 changed files with 43 additions and 28 deletions

View file

@ -116,7 +116,7 @@ gst_v4l2_device_provider_probe_device (GstV4l2DeviceProvider * provider,
v4l2obj = gst_v4l2_object_new (NULL, GST_OBJECT (provider),
V4L2_BUF_TYPE_VIDEO_CAPTURE, device_path, NULL, NULL, NULL);
if (!gst_v4l2_open (v4l2obj))
if (!gst_v4l2_open (v4l2obj, NULL))
goto destroy;
gst_structure_set (props, "device.api", G_TYPE_STRING, "v4l2", NULL);

View file

@ -896,9 +896,9 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
}
gboolean
gst_v4l2_object_open (GstV4l2Object * v4l2object)
gst_v4l2_object_open (GstV4l2Object * v4l2object, GstV4l2Error * error)
{
if (gst_v4l2_open (v4l2object))
if (gst_v4l2_open (v4l2object, error))
gst_v4l2_set_defaults (v4l2object);
else
return FALSE;

View file

@ -274,7 +274,7 @@ gboolean gst_v4l2_object_get_property_helper (GstV4l2Object *v4l2objec
guint prop_id, GValue * value,
GParamSpec * pspec);
/* open/close */
gboolean gst_v4l2_object_open (GstV4l2Object * v4l2object);
gboolean gst_v4l2_object_open (GstV4l2Object * v4l2object, GstV4l2Error * error);
gboolean gst_v4l2_object_open_shared (GstV4l2Object * v4l2object, GstV4l2Object * other);
gboolean gst_v4l2_object_close (GstV4l2Object * v4l2object);
@ -317,7 +317,7 @@ GstStructure * gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
/* TODO Move to proper namespace */
/* open/close the device */
gboolean gst_v4l2_open (GstV4l2Object * v4l2object);
gboolean gst_v4l2_open (GstV4l2Object * v4l2object, GstV4l2Error * error);
gboolean gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other);
gboolean gst_v4l2_close (GstV4l2Object * v4l2object);

View file

@ -350,12 +350,12 @@ gst_v4l2radio_finalize (GstV4l2Radio * radio)
}
static gboolean
gst_v4l2radio_open (GstV4l2Radio * radio)
gst_v4l2radio_open (GstV4l2Radio * radio, GstV4l2Error * error)
{
GstV4l2Object *v4l2object;
v4l2object = radio->v4l2object;
if (gst_v4l2_open (v4l2object))
if (gst_v4l2_open (v4l2object, error))
return gst_v4l2radio_fill_channel_list (radio);
else
return FALSE;
@ -406,9 +406,9 @@ gst_v4l2radio_set_defaults (GstV4l2Radio * radio)
}
static gboolean
gst_v4l2radio_start (GstV4l2Radio * radio)
gst_v4l2radio_start (GstV4l2Radio * radio, GstV4l2Error * error)
{
if (!gst_v4l2radio_open (radio))
if (!gst_v4l2radio_open (radio, error))
return FALSE;
gst_v4l2radio_set_defaults (radio);
@ -429,13 +429,14 @@ static GstStateChangeReturn
gst_v4l2radio_change_state (GstElement * element, GstStateChange transition)
{
GstV4l2Radio *radio;
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
radio = GST_V4L2RADIO (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
/*start radio */
if (!gst_v4l2radio_start (radio))
if (!gst_v4l2radio_start (radio, &error))
ret = GST_STATE_CHANGE_FAILURE;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
@ -457,6 +458,7 @@ gst_v4l2radio_change_state (GstElement * element, GstStateChange transition)
break;
}
gst_v4l2_error (radio, &error);
return ret;
}

View file

@ -437,6 +437,7 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstV4l2Sink *v4l2sink = GST_V4L2SINK (element);
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GST_DEBUG_OBJECT (v4l2sink, "%d -> %d",
GST_STATE_TRANSITION_CURRENT (transition),
@ -445,8 +446,10 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
/* open the device */
if (!gst_v4l2_object_open (v4l2sink->v4l2object))
if (!gst_v4l2_object_open (v4l2sink->v4l2object, &error)) {
gst_v4l2_error (v4l2sink, &error);
return GST_STATE_CHANGE_FAILURE;
}
break;
default:
break;

View file

@ -794,12 +794,15 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstV4l2Src *v4l2src = GST_V4L2SRC (element);
GstV4l2Object *obj = v4l2src->v4l2object;
GstV4l2Error error = GST_V4L2_ERROR_INIT;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
/* open the device */
if (!gst_v4l2_object_open (obj))
if (!gst_v4l2_object_open (obj, &error)) {
gst_v4l2_error (v4l2src, &error);
return GST_STATE_CHANGE_FAILURE;
}
break;
default:
break;

View file

@ -115,9 +115,11 @@ gst_v4l2_transform_get_property (GObject * object,
static gboolean
gst_v4l2_transform_open (GstV4l2Transform * self)
{
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GST_DEBUG_OBJECT (self, "Opening");
if (!gst_v4l2_object_open (self->v4l2output))
if (!gst_v4l2_object_open (self->v4l2output, &error))
goto failure;
if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
@ -160,6 +162,8 @@ failure:
gst_caps_replace (&self->probed_srccaps, NULL);
gst_caps_replace (&self->probed_sinkcaps, NULL);
gst_v4l2_error (self, &error);
return FALSE;
}

View file

@ -119,11 +119,12 @@ static gboolean
gst_v4l2_video_dec_open (GstVideoDecoder * decoder)
{
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstCaps *codec_caps;
GST_DEBUG_OBJECT (self, "Opening");
if (!gst_v4l2_object_open (self->v4l2output))
if (!gst_v4l2_object_open (self->v4l2output, &error))
goto failure;
if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
@ -155,6 +156,8 @@ failure:
gst_caps_replace (&self->probed_srccaps, NULL);
gst_caps_replace (&self->probed_sinkcaps, NULL);
gst_v4l2_error (self, &error);
return FALSE;
}

View file

@ -110,11 +110,12 @@ static gboolean
gst_v4l2_video_enc_open (GstVideoEncoder * encoder)
{
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstCaps *codec_caps;
GST_DEBUG_OBJECT (self, "Opening");
if (!gst_v4l2_object_open (self->v4l2output))
if (!gst_v4l2_object_open (self->v4l2output, &error))
goto failure;
if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
@ -159,6 +160,8 @@ failure:
gst_caps_replace (&self->probed_srccaps, NULL);
gst_caps_replace (&self->probed_sinkcaps, NULL);
gst_v4l2_error (self, &error);
return FALSE;
}

View file

@ -516,7 +516,7 @@ gst_v4l2_adjust_buf_type (GstV4l2Object * v4l2object)
* return value: TRUE on success, FALSE on error
******************************************************/
gboolean
gst_v4l2_open (GstV4l2Object * v4l2object)
gst_v4l2_open (GstV4l2Object * v4l2object, GstV4l2Error * error)
{
struct stat st;
int libv4l2_fd = -1;
@ -605,46 +605,43 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
/* ERRORS */
stat_failed:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
GST_V4L2_ERROR (error, RESOURCE, NOT_FOUND,
(_("Cannot identify device '%s'."), v4l2object->videodev),
GST_ERROR_SYSTEM);
goto error;
}
no_device:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
GST_V4L2_ERROR (error, RESOURCE, NOT_FOUND,
(_("This isn't a device '%s'."), v4l2object->videodev),
GST_ERROR_SYSTEM);
goto error;
}
not_open:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ_WRITE,
GST_V4L2_ERROR (error, RESOURCE, OPEN_READ_WRITE,
(_("Could not open device '%s' for reading and writing."),
v4l2object->videodev), GST_ERROR_SYSTEM);
goto error;
}
not_capture:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a capture device."),
v4l2object->videodev),
GST_V4L2_ERROR (error, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a capture device."), v4l2object->videodev),
("Capabilities: 0x%x", v4l2object->device_caps));
goto error;
}
not_output:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a output device."),
v4l2object->videodev),
GST_V4L2_ERROR (error, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a output device."), v4l2object->videodev),
("Capabilities: 0x%x", v4l2object->device_caps));
goto error;
}
not_m2m:
{
GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a M2M device."),
v4l2object->videodev),
GST_V4L2_ERROR (error, RESOURCE, NOT_FOUND,
(_("Device '%s' is not a M2M device."), v4l2object->videodev),
("Capabilities: 0x%x", v4l2object->device_caps));
goto error;
}