validate: Make accessing Scenario.pipeline thread safe

The fact that Scenario.pipeline was not accessible in a thread way lead
to the fact that all users had to take the unref the last pipeline ref
in the main thread, otherwise we were crying. This was an ugly
restriction which lead to issue when using scenario on gst-rtsp-server.

This break the API as this commit remove the GstValidateScenario.pipeline
field but it is worth it.
This commit is contained in:
Thibault Saunier 2017-04-28 18:02:05 -03:00
parent 2dd729ccf9
commit 8f123cbc6f
6 changed files with 337 additions and 187 deletions

File diff suppressed because it is too large Load diff

View file

@ -103,7 +103,6 @@ struct _GstValidateAction
const gchar *type;
const gchar *name;
GstStructure *structure;
GstValidateScenario *scenario;
/* < private > */
guint action_number;
@ -112,7 +111,7 @@ struct _GstValidateAction
GstValidateActionPrivate *priv;
gpointer _gst_reserved[GST_PADDING_LARGE - 2]; /* ->scenario + ->priv */
gpointer _gst_reserved[GST_PADDING_LARGE - 1]; /* ->priv */
};
void gst_validate_action_set_done (GstValidateAction *action);
@ -243,12 +242,11 @@ struct _GstValidateScenario
GstObject parent;
/*< public >*/
GstElement *pipeline;
/*< private >*/
GstValidateScenarioPrivate *priv;
gpointer _gst_reserved[GST_PADDING];
gpointer _gst_reserved[GST_PADDING + 1];
};
GType gst_validate_scenario_get_type (void);
@ -287,7 +285,8 @@ gboolean gst_validate_action_get_clocktime (GstValidateScenario * scenario,
const gchar * name,
GstClockTime * retval);
gboolean gst_validate_scenario_execute_seek (GstValidateScenario *scenario,
GstValidateExecuteActionReturn
gst_validate_scenario_execute_seek (GstValidateScenario *scenario,
GstValidateAction *action,
gdouble rate,
GstFormat format,
@ -306,6 +305,9 @@ gst_validate_execute_action (GstValidateActionType * action_type
GstState
gst_validate_scenario_get_target_state (GstValidateScenario *scenario);
GstElement *
gst_validate_scenario_get_pipeline (GstValidateScenario * scenario);
void gst_validate_scenario_deinit (void);
G_END_DECLS

View file

@ -131,25 +131,26 @@ _create_keyboard_events (GstValidateAction * action,
#endif
GList *events = NULL;
GdkDevice *device = NULL;
GstValidateScenario *scenario = gst_validate_action_get_scenario (action);
if (etype == GDK_NOTHING) {
etype = GDK_KEY_PRESS;
} else if (etype != GDK_KEY_PRESS && etype != GDK_KEY_RELEASE) {
GST_VALIDATE_REPORT (action->scenario,
GST_VALIDATE_REPORT (scenario,
g_quark_from_static_string ("scenario::execution-error"),
"GdkEvent type %s does not work with the 'keys' parameter",
gst_structure_get_string (action->structure, "type"));
return NULL;
goto fail;
}
#if GTK_CHECK_VERSION(3,20,0)
display = gdk_display_get_default ();
if (display == NULL) {
GST_VALIDATE_REPORT (action->scenario,
GST_VALIDATE_REPORT (scenario,
g_quark_from_static_string ("scenario::execution-error"),
"Could not find a display");
return NULL;
goto fail;
}
seat = gdk_display_get_default_seat (display);
@ -158,11 +159,11 @@ _create_keyboard_events (GstValidateAction * action,
device = get_device (action, GDK_SOURCE_KEYBOARD);
#endif
if (device == NULL) {
GST_VALIDATE_REPORT (action->scenario,
GST_VALIDATE_REPORT (scenario,
g_quark_from_static_string ("scenario::execution-error"),
"Could not find a keyboard device");
return NULL;
goto fail;
}
if (keyname) {
@ -189,7 +190,13 @@ _create_keyboard_events (GstValidateAction * action,
}
}
gst_object_unref (scenario);
return events;
fail:
gst_object_unref (scenario);
return NULL;
}
typedef struct

View file

@ -66,15 +66,14 @@ GST_END_TEST;
GST_START_TEST (monitors_cleanup)
{
GstElement *src, *sink;
GstValidateRunner *runner;
GstValidateMonitor *monitor, *pmonitor1, *pmonitor2;
GstValidateRunner *runner = gst_validate_runner_new ();
GstElement *pipeline = gst_pipeline_new ("validate-pipeline");
src = gst_element_factory_make ("fakesrc", "source");
sink = gst_element_factory_make ("fakesink", "sink");
runner = gst_validate_runner_new ();
monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline),
runner, NULL);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);

View file

@ -46,7 +46,6 @@ _stop_monitoring_bin (GstBin * bin, GstValidateRunner * runner)
monitor =
(GstValidateMonitor *) g_object_get_data (G_OBJECT (bin),
"validate-monitor");
ASSERT_OBJECT_REFCOUNT (bin, "bin", 1);
gst_object_unref (bin);
ASSERT_OBJECT_REFCOUNT (monitor, "monitor", 1);
gst_object_unref (monitor);

View file

@ -228,12 +228,26 @@ _execute_set_subtitles (GstValidateScenario * scenario,
gchar *uri, *fname;
GFile *tmpfile, *folder;
const gchar *subtitle_file, *subtitle_dir;
GstElement *pipeline = gst_validate_scenario_get_pipeline (scenario);
if (pipeline == NULL) {
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
"Can't execute a '%s' action after the pipeline "
"has been destroyed.", action->type);
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
}
subtitle_file = gst_structure_get_string (action->structure, "subtitle-file");
g_return_val_if_fail (subtitle_file != NULL, FALSE);
subtitle_dir = gst_structure_get_string (action->structure, "subtitle-dir");
if (subtitle_file == NULL) {
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
"No 'subtitle-file' specified in 'set-subtile'");
gst_object_unref (pipeline);
g_object_get (scenario->pipeline, "current-uri", &uri, NULL);
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
}
subtitle_dir = gst_structure_get_string (action->structure, "subtitle-dir");
g_object_get (pipeline, "current-uri", &uri, NULL);
tmpfile = g_file_new_for_uri (uri);
g_free (uri);
@ -251,8 +265,9 @@ _execute_set_subtitles (GstValidateScenario * scenario,
uri = g_file_get_uri (tmpfile);
gst_validate_printf (action, "Setting subtitle file to: %s", uri);
g_object_set (scenario->pipeline, "suburi", uri, NULL);
g_object_set (pipeline, "suburi", uri, NULL);
g_free (uri);
gst_object_unref (pipeline);
return TRUE;
}