PROP_0,
PROP_RUNNER,
PROP_HANDLES_STATE,
+ PROP_EXECUTE_ON_IDLE,
PROP_LAST
};
struct _GstValidateScenarioPrivate
{
GstValidateRunner *runner;
+ gboolean execute_on_idle;
GMutex lock;
gboolean handles_state;
- guint get_pos_id;
+ guint get_pos_id; /* Protect with SCENARIO_LOCK */
guint wait_id;
gboolean buffering;
return TRUE;
}
-static gboolean
+static inline gboolean
_add_get_position_source (GstValidateScenario * scenario)
{
GstValidateScenarioPrivate *priv = scenario->priv;
+ SCENARIO_LOCK (scenario);
if (priv->get_pos_id == 0 && priv->wait_id == 0) {
- priv->get_pos_id = g_timeout_add (50, (GSourceFunc) get_position, scenario);
+ priv->get_pos_id = g_idle_add ((GSourceFunc) get_position, scenario);
+ SCENARIO_UNLOCK (scenario);
GST_DEBUG_OBJECT (scenario, "Start checking position again");
return TRUE;
}
+ SCENARIO_UNLOCK (scenario);
GST_DEBUG_OBJECT (scenario, "No need to start a new gsource");
return FALSE;
if (has_pos && has_dur) {
if (position > duration) {
+ _add_get_position_source (scenario);
+
GST_VALIDATE_REPORT (scenario,
QUERY_POSITION_SUPERIOR_DURATION,
"Reported position %" GST_TIME_FORMAT " > reported duration %"
_check_position (scenario, rate, position);
- if (!_should_execute_action (scenario, act, position, rate))
+ if (!_should_execute_action (scenario, act, position, rate)) {
+ _add_get_position_source (scenario);
+
return TRUE;
+ }
type = _find_action_type (act->type);
/* Recurse to the next action if it is possible
* to execute right away */
- return get_position (scenario);
+ if (!scenario->priv->execute_on_idle) {
+ GST_DEBUG_OBJECT (scenario, "linking next action execution");
+
+ return get_position (scenario);
+ } else {
+ _add_get_position_source (scenario);
+ GST_DEBUG_OBJECT (scenario, "Executing only on idle, waiting for"
+ " next dispatch");
+
+ return TRUE;
+ }
+ } else {
+ GST_DEBUG_OBJECT (scenario, "Remove source, waiting for action"
+ " to be done.");
+
+ SCENARIO_LOCK (scenario);
+ priv->get_pos_id = 0;
+ SCENARIO_UNLOCK (scenario);
+
+ return G_SOURCE_REMOVE;
}
return TRUE;
gst_validate_printf (action->scenario, "Stop waiting\n");
+ SCENARIO_LOCK (scenario);
scenario->priv->wait_id = 0;
+ SCENARIO_UNLOCK (scenario);
+
gst_validate_action_set_done (action);
_add_get_position_source (scenario);
"Waiting for %" GST_TIME_FORMAT " (wait_multiplier: %f)\n",
GST_TIME_ARGS (duration), wait_multiplier);
+ SCENARIO_LOCK (scenario);
if (priv->get_pos_id) {
g_source_remove (priv->get_pos_id);
priv->get_pos_id = 0;
}
+ SCENARIO_UNLOCK (scenario);
+ SCENARIO_LOCK (scenario);
priv->wait_id = g_timeout_add (duration / G_USEC_PER_SEC,
(GSourceFunc) stop_waiting, action);
+ SCENARIO_UNLOCK (scenario);
return GST_VALIDATE_EXECUTE_ACTION_ASYNC;
}
{
GstValidateScenarioPrivate *priv = scenario->priv;
+ SCENARIO_LOCK (scenario);
if (priv->get_pos_id) {
g_source_remove (priv->get_pos_id);
priv->get_pos_id = 0;
g_source_remove (priv->wait_id);
priv->wait_id = 0;
}
+ SCENARIO_UNLOCK (scenario);
+
scenario->pipeline = NULL;
GST_DEBUG_OBJECT (scenario, "pipeline was freed");
gst_validate_scenario_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
+ GstValidateScenario *self = GST_VALIDATE_SCENARIO (object);
+
switch (prop_id) {
case PROP_RUNNER:
/* we assume the runner is valid as long as this scenario is,
case PROP_HANDLES_STATE:
g_assert_not_reached ();
break;
+ case PROP_EXECUTE_ON_IDLE:
+ self->priv->execute_on_idle = g_value_get_boolean (value);
+ break;
default:
break;
}
case PROP_HANDLES_STATE:
g_value_set_boolean (value, self->priv->handles_state);
break;
+ case PROP_EXECUTE_ON_IDLE:
+ g_value_set_boolean (value, self->priv->execute_on_idle);
+ break;
default:
break;
}
" False if it is application responsibility",
FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_EXECUTE_ON_IDLE,
+ g_param_spec_boolean ("execute-on-idle",
+ "Force waiting between actions",
+ "Always execute actions on idle and do not chain them"
+ " to execute as fast as possible. That is usefull if action execution"
+ " can lead to the addition of source on the same main loop."
+ " It allows those other GSources to have a chance to be dispatch between"
+ " validate actions execution", FALSE, G_PARAM_READWRITE));
+
/**
* GstValidateScenario::done:
* @scenario: The scenario runing
void
gst_validate_action_set_done (GstValidateAction * action)
{
+ GstValidateScenario *scenario = action->scenario;
+
if (action->state == GST_VALIDATE_EXECUTE_ACTION_INTERLACED) {
if (action->scenario) {
}
action->state = _execute_sub_action_action (action);
+ if (action->state == GST_VALIDATE_EXECUTE_ACTION_ASYNC) {
+ GST_DEBUG_OBJECT (scenario, "Sub action executed ASYNC");
+
+ return;
+ }
- if (action->scenario) {
+ if (scenario) {
if (GPOINTER_TO_INT (g_private_get (&main_thread_priv))) {
- GST_DEBUG_OBJECT (action->scenario, "Right thread, executing next?");
- get_position (action->scenario);
- } else {
+ if (!scenario->priv->execute_on_idle) {
+ GST_DEBUG_OBJECT (scenario, "Right thread, executing next?");
+ get_position (scenario);
+
+ return;
+ } else
+ GST_DEBUG_OBJECT (scenario, "Right thread, but executing only on idle");
+ } else
GST_DEBUG_OBJECT (action->scenario, "Not doing anything outside the"
" 'main' thread");
-
- }
}
+
+ _add_get_position_source (scenario);
}
/**