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), v4l2obj = gst_v4l2_object_new (NULL, GST_OBJECT (provider),
V4L2_BUF_TYPE_VIDEO_CAPTURE, device_path, NULL, NULL, NULL); V4L2_BUF_TYPE_VIDEO_CAPTURE, device_path, NULL, NULL, NULL);
if (!gst_v4l2_open (v4l2obj)) if (!gst_v4l2_open (v4l2obj, NULL))
goto destroy; goto destroy;
gst_structure_set (props, "device.api", G_TYPE_STRING, "v4l2", NULL); gst_structure_set (props, "device.api", G_TYPE_STRING, "v4l2", NULL);

View file

@ -896,9 +896,9 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
} }
gboolean 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); gst_v4l2_set_defaults (v4l2object);
else else
return FALSE; return FALSE;

View file

@ -274,7 +274,7 @@ gboolean gst_v4l2_object_get_property_helper (GstV4l2Object *v4l2objec
guint prop_id, GValue * value, guint prop_id, GValue * value,
GParamSpec * pspec); GParamSpec * pspec);
/* open/close */ /* 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_open_shared (GstV4l2Object * v4l2object, GstV4l2Object * other);
gboolean gst_v4l2_object_close (GstV4l2Object * v4l2object); 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 */ /* TODO Move to proper namespace */
/* open/close the device */ /* 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_dup (GstV4l2Object * v4l2object, GstV4l2Object * other);
gboolean gst_v4l2_close (GstV4l2Object * v4l2object); gboolean gst_v4l2_close (GstV4l2Object * v4l2object);

View file

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

View file

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

View file

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

View file

@ -115,9 +115,11 @@ gst_v4l2_transform_get_property (GObject * object,
static gboolean static gboolean
gst_v4l2_transform_open (GstV4l2Transform * self) gst_v4l2_transform_open (GstV4l2Transform * self)
{ {
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GST_DEBUG_OBJECT (self, "Opening"); GST_DEBUG_OBJECT (self, "Opening");
if (!gst_v4l2_object_open (self->v4l2output)) if (!gst_v4l2_object_open (self->v4l2output, &error))
goto failure; goto failure;
if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output)) 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_srccaps, NULL);
gst_caps_replace (&self->probed_sinkcaps, NULL); gst_caps_replace (&self->probed_sinkcaps, NULL);
gst_v4l2_error (self, &error);
return FALSE; return FALSE;
} }

View file

@ -119,11 +119,12 @@ static gboolean
gst_v4l2_video_dec_open (GstVideoDecoder * decoder) gst_v4l2_video_dec_open (GstVideoDecoder * decoder)
{ {
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder); GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstCaps *codec_caps; GstCaps *codec_caps;
GST_DEBUG_OBJECT (self, "Opening"); GST_DEBUG_OBJECT (self, "Opening");
if (!gst_v4l2_object_open (self->v4l2output)) if (!gst_v4l2_object_open (self->v4l2output, &error))
goto failure; goto failure;
if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output)) 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_srccaps, NULL);
gst_caps_replace (&self->probed_sinkcaps, NULL); gst_caps_replace (&self->probed_sinkcaps, NULL);
gst_v4l2_error (self, &error);
return FALSE; return FALSE;
} }

View file

@ -110,11 +110,12 @@ static gboolean
gst_v4l2_video_enc_open (GstVideoEncoder * encoder) gst_v4l2_video_enc_open (GstVideoEncoder * encoder)
{ {
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder); GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
GstV4l2Error error = GST_V4L2_ERROR_INIT;
GstCaps *codec_caps; GstCaps *codec_caps;
GST_DEBUG_OBJECT (self, "Opening"); GST_DEBUG_OBJECT (self, "Opening");
if (!gst_v4l2_object_open (self->v4l2output)) if (!gst_v4l2_object_open (self->v4l2output, &error))
goto failure; goto failure;
if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output)) 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_srccaps, NULL);
gst_caps_replace (&self->probed_sinkcaps, NULL); gst_caps_replace (&self->probed_sinkcaps, NULL);
gst_v4l2_error (self, &error);
return FALSE; return FALSE;
} }

View file

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