mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
validate: use new API when switching track with playbin3
Move all the implementations of 'switch-track' to gst-validate-scenario.c while doing so. Differential Revision: https://phabricator.freedesktop.org/D1227
This commit is contained in:
parent
7117e3e3df
commit
15e5e23e32
4 changed files with 404 additions and 151 deletions
|
@ -46,10 +46,27 @@ enum
|
||||||
G_DEFINE_TYPE (GstValidatePipelineMonitor, gst_validate_pipeline_monitor,
|
G_DEFINE_TYPE (GstValidatePipelineMonitor, gst_validate_pipeline_monitor,
|
||||||
GST_TYPE_VALIDATE_BIN_MONITOR);
|
GST_TYPE_VALIDATE_BIN_MONITOR);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_validate_pipeline_monitor_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
GstValidatePipelineMonitor *self = (GstValidatePipelineMonitor *) object;
|
||||||
|
|
||||||
|
g_clear_object (&self->stream_collection);
|
||||||
|
if (self->streams_selected) {
|
||||||
|
g_list_free_full (self->streams_selected, gst_object_unref);
|
||||||
|
self->streams_selected = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_validate_pipeline_monitor_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_validate_pipeline_monitor_class_init (GstValidatePipelineMonitorClass *
|
gst_validate_pipeline_monitor_class_init (GstValidatePipelineMonitorClass *
|
||||||
klass)
|
klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = gst_validate_pipeline_monitor_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -179,6 +196,33 @@ _bus_handler (GstBus * bus, GstMessage * message,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GST_MESSAGE_STREAM_COLLECTION:
|
||||||
|
{
|
||||||
|
GstStreamCollection *collection = NULL;
|
||||||
|
gst_message_parse_stream_collection (message, &collection);
|
||||||
|
gst_object_replace ((GstObject **) & monitor->stream_collection,
|
||||||
|
(GstObject *) collection);
|
||||||
|
gst_object_unref (collection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GST_MESSAGE_STREAMS_SELECTED:
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (monitor->streams_selected) {
|
||||||
|
g_list_free_full (monitor->streams_selected, gst_object_unref);
|
||||||
|
monitor->streams_selected = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < gst_message_streams_selected_get_size (message); i++) {
|
||||||
|
GstStream *stream =
|
||||||
|
gst_message_streams_selected_get_stream (message, i);
|
||||||
|
|
||||||
|
monitor->streams_selected =
|
||||||
|
g_list_append (monitor->streams_selected, stream);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -248,5 +292,10 @@ gst_validate_pipeline_monitor_new (GstPipeline * pipeline,
|
||||||
|
|
||||||
gst_object_unref (bus);
|
gst_object_unref (bus);
|
||||||
|
|
||||||
|
if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin") == 0)
|
||||||
|
monitor->is_playbin = TRUE;
|
||||||
|
else if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin3") == 0)
|
||||||
|
monitor->is_playbin3 = TRUE;
|
||||||
|
|
||||||
return monitor;
|
return monitor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,16 @@ struct _GstValidatePipelineMonitor {
|
||||||
guint print_pos_srcid;
|
guint print_pos_srcid;
|
||||||
gboolean buffering;
|
gboolean buffering;
|
||||||
gboolean got_error;
|
gboolean got_error;
|
||||||
|
|
||||||
|
/* TRUE if monitoring a playbin2 pipeline */
|
||||||
|
gboolean is_playbin;
|
||||||
|
/* TRUE if monitoring a playbin3 pipeline */
|
||||||
|
gboolean is_playbin3;
|
||||||
|
|
||||||
|
/* Latest collection received from GST_MESSAGE_STREAM_COLLECTION */
|
||||||
|
GstStreamCollection *stream_collection;
|
||||||
|
/* Latest GstStream received from GST_MESSAGE_STREAMS_SELECTED */
|
||||||
|
GList *streams_selected;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "validate.h"
|
#include "validate.h"
|
||||||
#include <gst/validate/gst-validate-override.h>
|
#include <gst/validate/gst-validate-override.h>
|
||||||
#include <gst/validate/gst-validate-override-registry.h>
|
#include <gst/validate/gst-validate-override-registry.h>
|
||||||
|
#include <gst/validate/gst-validate-pipeline-monitor.h>
|
||||||
|
|
||||||
#define GST_VALIDATE_SCENARIO_GET_PRIVATE(o) \
|
#define GST_VALIDATE_SCENARIO_GET_PRIVATE(o) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_VALIDATE_SCENARIO, GstValidateScenarioPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_VALIDATE_SCENARIO, GstValidateScenarioPrivate))
|
||||||
|
@ -70,6 +71,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_validate_scenario_debug);
|
||||||
gst_validate_register_action_type ((_tname), "core", (_function), (_params), (_desc), (_is_config)); \
|
gst_validate_register_action_type ((_tname), "core", (_function), (_params), (_desc), (_is_config)); \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define ACTION_EXPECTED_STREAM_QUARK g_quark_from_static_string ("ACTION_EXPECTED_STREAM_QUARK")
|
||||||
|
|
||||||
#define SCENARIO_LOCK(scenario) (g_mutex_lock(&scenario->priv->lock))
|
#define SCENARIO_LOCK(scenario) (g_mutex_lock(&scenario->priv->lock))
|
||||||
#define SCENARIO_UNLOCK(scenario) (g_mutex_unlock(&scenario->priv->lock))
|
#define SCENARIO_UNLOCK(scenario) (g_mutex_unlock(&scenario->priv->lock))
|
||||||
enum
|
enum
|
||||||
|
@ -145,6 +148,10 @@ struct _GstValidateScenarioPrivate
|
||||||
GList *overrides;
|
GList *overrides;
|
||||||
|
|
||||||
gchar *pipeline_name;
|
gchar *pipeline_name;
|
||||||
|
|
||||||
|
/* 'switch-track action' currently waiting for
|
||||||
|
* GST_MESSAGE_STREAMS_SELECTED to be completed. */
|
||||||
|
GstValidateAction *pending_switch_track;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct KeyFileGroupName
|
typedef struct KeyFileGroupName
|
||||||
|
@ -855,7 +862,7 @@ _check_select_pad_done (GstPad * pad, GstPadProbeInfo * info,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_execute_switch_track (GstValidateScenario * scenario,
|
execute_switch_track_default (GstValidateScenario * scenario,
|
||||||
GstValidateAction * action)
|
GstValidateAction * action)
|
||||||
{
|
{
|
||||||
guint index;
|
guint index;
|
||||||
|
@ -923,6 +930,278 @@ _execute_switch_track (GstValidateScenario * scenario,
|
||||||
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstPadProbeReturn
|
||||||
|
_check_pad_event_selection_done (GstPad * pad, GstPadProbeInfo * info,
|
||||||
|
GstValidateAction * action)
|
||||||
|
{
|
||||||
|
if (GST_EVENT_TYPE (info->data) == GST_EVENT_STREAM_START) {
|
||||||
|
gst_validate_action_set_done (action);
|
||||||
|
return GST_PAD_PROBE_REMOVE;
|
||||||
|
}
|
||||||
|
return GST_PAD_PROBE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
execute_switch_track_pb (GstValidateScenario * scenario,
|
||||||
|
GstValidateAction * action)
|
||||||
|
{
|
||||||
|
gint index, n;
|
||||||
|
const gchar *type, *str_index;
|
||||||
|
|
||||||
|
gint flags, current, tflag;
|
||||||
|
gchar *tmp, *current_txt;
|
||||||
|
|
||||||
|
gint res = GST_VALIDATE_EXECUTE_ACTION_OK;
|
||||||
|
gboolean relative = FALSE, disabling = FALSE;
|
||||||
|
|
||||||
|
if (!(type = gst_structure_get_string (action->structure, "type")))
|
||||||
|
type = "audio";
|
||||||
|
|
||||||
|
tflag =
|
||||||
|
gst_validate_utils_flags_from_str (g_type_from_name ("GstPlayFlags"),
|
||||||
|
type);
|
||||||
|
current_txt = g_strdup_printf ("current-%s", type);
|
||||||
|
|
||||||
|
tmp = g_strdup_printf ("n-%s", type);
|
||||||
|
g_object_get (scenario->pipeline, "flags", &flags, tmp, &n,
|
||||||
|
current_txt, ¤t, NULL);
|
||||||
|
|
||||||
|
/* Don't try to use -1 */
|
||||||
|
if (current == -1)
|
||||||
|
current = 0;
|
||||||
|
|
||||||
|
g_free (tmp);
|
||||||
|
|
||||||
|
if (gst_structure_has_field (action->structure, "disable")) {
|
||||||
|
disabling = TRUE;
|
||||||
|
flags &= ~tflag;
|
||||||
|
index = -1;
|
||||||
|
} else if (!(str_index =
|
||||||
|
gst_structure_get_string (action->structure, "index"))) {
|
||||||
|
if (!gst_structure_get_int (action->structure, "index", &index)) {
|
||||||
|
GST_WARNING ("No index given, defaulting to +1");
|
||||||
|
index = 1;
|
||||||
|
relative = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
relative = strchr ("+-", str_index[0]) != NULL;
|
||||||
|
index = g_ascii_strtoll (str_index, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relative) { /* We are changing track relatively to current track */
|
||||||
|
index = (current + index) % n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!disabling) {
|
||||||
|
GstState state, next;
|
||||||
|
GstPad *oldpad, *newpad;
|
||||||
|
tmp = g_strdup_printf ("get-%s-pad", type);
|
||||||
|
g_signal_emit_by_name (G_OBJECT (scenario->pipeline), tmp, current,
|
||||||
|
&oldpad);
|
||||||
|
g_signal_emit_by_name (G_OBJECT (scenario->pipeline), tmp, index, &newpad);
|
||||||
|
|
||||||
|
gst_validate_printf (action, "Switching to track number: %i,"
|
||||||
|
" (from %s:%s to %s:%s)\n", index, GST_DEBUG_PAD_NAME (oldpad),
|
||||||
|
GST_DEBUG_PAD_NAME (newpad));
|
||||||
|
flags |= tflag;
|
||||||
|
g_free (tmp);
|
||||||
|
|
||||||
|
if (gst_element_get_state (scenario->pipeline, &state, &next, 0) &&
|
||||||
|
state == GST_STATE_PLAYING && next == GST_STATE_VOID_PENDING) {
|
||||||
|
GstPad *srcpad = NULL;
|
||||||
|
GstElement *combiner = NULL;
|
||||||
|
if (newpad == oldpad) {
|
||||||
|
srcpad = gst_pad_get_peer (oldpad);
|
||||||
|
} else if (newpad) {
|
||||||
|
combiner = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (newpad)));
|
||||||
|
if (combiner) {
|
||||||
|
srcpad = gst_element_get_static_pad (combiner, "src");
|
||||||
|
gst_object_unref (combiner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcpad) {
|
||||||
|
gst_pad_add_probe (srcpad,
|
||||||
|
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
|
||||||
|
(GstPadProbeCallback) _check_pad_event_selection_done, action,
|
||||||
|
NULL);
|
||||||
|
gst_object_unref (srcpad);
|
||||||
|
|
||||||
|
res = GST_VALIDATE_EXECUTE_ACTION_ASYNC;
|
||||||
|
} else
|
||||||
|
res = GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldpad)
|
||||||
|
gst_object_unref (oldpad);
|
||||||
|
gst_object_unref (newpad);
|
||||||
|
} else {
|
||||||
|
gst_validate_printf (action, "Disabling track type %s", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set (scenario->pipeline, "flags", flags, current_txt, index, NULL);
|
||||||
|
g_free (current_txt);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstStreamType
|
||||||
|
stream_type_from_string (const gchar * type)
|
||||||
|
{
|
||||||
|
if (!g_strcmp0 (type, "video"))
|
||||||
|
return GST_STREAM_TYPE_VIDEO;
|
||||||
|
else if (!g_strcmp0 (type, "text"))
|
||||||
|
return GST_STREAM_TYPE_TEXT;
|
||||||
|
|
||||||
|
/* default */
|
||||||
|
return GST_STREAM_TYPE_AUDIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a list of stream ID all the currently selected streams but the ones
|
||||||
|
* of type @type */
|
||||||
|
static GList *
|
||||||
|
disable_stream (GstValidatePipelineMonitor * monitor, GstStreamType type)
|
||||||
|
{
|
||||||
|
GList *streams = NULL, *l;
|
||||||
|
|
||||||
|
for (l = monitor->streams_selected; l; l = g_list_next (l)) {
|
||||||
|
GstStream *s = l->data;
|
||||||
|
|
||||||
|
if (gst_stream_get_stream_type (s) != type) {
|
||||||
|
streams = g_list_append (streams, (gpointer) s->stream_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return streams;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
switch_stream (GstValidatePipelineMonitor * monitor, GstValidateAction * action,
|
||||||
|
GstStreamType type, gint index, gboolean relative)
|
||||||
|
{
|
||||||
|
guint nb_streams;
|
||||||
|
guint i, n = 0, current = 0;
|
||||||
|
GList *result = NULL, *l;
|
||||||
|
GstStream *streams[256], *s, *current_stream = NULL;
|
||||||
|
|
||||||
|
/* Keep all streams which are not @type */
|
||||||
|
for (l = monitor->streams_selected; l; l = g_list_next (l)) {
|
||||||
|
s = l->data;
|
||||||
|
|
||||||
|
if (gst_stream_get_stream_type (s) != type) {
|
||||||
|
result = g_list_append (result, (gpointer) s->stream_id);
|
||||||
|
} else if (!current_stream) {
|
||||||
|
/* Assume the stream we want to switch from is the first one */
|
||||||
|
current_stream = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the number of @type streams */
|
||||||
|
nb_streams = gst_stream_collection_get_size (monitor->stream_collection);
|
||||||
|
for (i = 0; i < nb_streams; i++) {
|
||||||
|
s = gst_stream_collection_get_stream (monitor->stream_collection, i);
|
||||||
|
|
||||||
|
if (gst_stream_get_stream_type (s) == type) {
|
||||||
|
streams[n] = s;
|
||||||
|
|
||||||
|
if (current_stream
|
||||||
|
&& !g_strcmp0 (s->stream_id, current_stream->stream_id))
|
||||||
|
current = n;
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relative) { /* We are changing track relatively to current track */
|
||||||
|
index = (current + index) % n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the new stream we want to switch to */
|
||||||
|
s = streams[index];
|
||||||
|
|
||||||
|
gst_validate_printf (action, "Switching from stream %s to %s",
|
||||||
|
current_stream ? current_stream->stream_id : "", s->stream_id);
|
||||||
|
|
||||||
|
return g_list_append (result, (gpointer) s->stream_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
execute_switch_track_pb3 (GstValidateScenario * scenario,
|
||||||
|
GstValidateAction * action)
|
||||||
|
{
|
||||||
|
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||||
|
gint index;
|
||||||
|
GstStreamType stype;
|
||||||
|
const gchar *type, *str_index;
|
||||||
|
GList *new_streams = NULL;
|
||||||
|
GstValidatePipelineMonitor *monitor =
|
||||||
|
(GstValidatePipelineMonitor *) (g_object_get_data ((GObject *)
|
||||||
|
scenario->pipeline, "validate-monitor"));
|
||||||
|
|
||||||
|
if (!monitor->stream_collection) {
|
||||||
|
GST_ERROR ("No stream collection message received on the bus");
|
||||||
|
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!monitor->streams_selected) {
|
||||||
|
GST_ERROR ("No streams selected message received on the bus");
|
||||||
|
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = gst_structure_get_string (action->structure, "type");
|
||||||
|
stype = stream_type_from_string (type);
|
||||||
|
|
||||||
|
if (gst_structure_has_field (action->structure, "disable")) {
|
||||||
|
gst_validate_printf (action, "Disabling track type %s", type);
|
||||||
|
new_streams = disable_stream (monitor, stype);
|
||||||
|
} else {
|
||||||
|
gboolean relative = FALSE;
|
||||||
|
|
||||||
|
if (!(str_index = gst_structure_get_string (action->structure, "index"))) {
|
||||||
|
if (!gst_structure_get_int (action->structure, "index", &index)) {
|
||||||
|
GST_WARNING ("No index given, defaulting to +1");
|
||||||
|
index = 1;
|
||||||
|
relative = TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
relative = strchr ("+-", str_index[0]) != NULL;
|
||||||
|
index = g_ascii_strtoll (str_index, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_streams = switch_stream (monitor, action, stype, index, relative);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (action),
|
||||||
|
ACTION_EXPECTED_STREAM_QUARK, g_list_copy (new_streams),
|
||||||
|
(GDestroyNotify) g_list_free);
|
||||||
|
|
||||||
|
priv->pending_switch_track = action;
|
||||||
|
|
||||||
|
if (!gst_element_send_event (scenario->pipeline,
|
||||||
|
gst_event_new_select_streams (new_streams))) {
|
||||||
|
GST_ERROR ("select-streams event not handled");
|
||||||
|
return GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_VALIDATE_EXECUTE_ACTION_ASYNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_execute_switch_track (GstValidateScenario * scenario,
|
||||||
|
GstValidateAction * action)
|
||||||
|
{
|
||||||
|
GstValidatePipelineMonitor *monitor =
|
||||||
|
(GstValidatePipelineMonitor *) (g_object_get_data ((GObject *)
|
||||||
|
scenario->pipeline, "validate-monitor"));
|
||||||
|
|
||||||
|
if (monitor->is_playbin)
|
||||||
|
return execute_switch_track_pb (scenario, action);
|
||||||
|
else if (monitor->is_playbin3)
|
||||||
|
return execute_switch_track_pb3 (scenario, action);
|
||||||
|
|
||||||
|
return execute_switch_track_default (scenario, action);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_set_rank (GstValidateScenario * scenario, GstValidateAction * action)
|
_set_rank (GstValidateScenario * scenario, GstValidateAction * action)
|
||||||
{
|
{
|
||||||
|
@ -2056,6 +2335,21 @@ _check_waiting_for_message (GstValidateScenario * scenario,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
streams_list_contain (GList * streams, const gchar * stream_id)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = streams; l; l = g_list_next (l)) {
|
||||||
|
GstStream *s = l->data;
|
||||||
|
|
||||||
|
if (!g_strcmp0 (s->stream_id, stream_id))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
|
message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
|
||||||
{
|
{
|
||||||
|
@ -2212,6 +2506,55 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
|
||||||
g_print ("%s %d%% \r", "Buffering...", percent);
|
g_print ("%s %d%% \r", "Buffering...", percent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GST_MESSAGE_STREAMS_SELECTED:
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
GList *streams_selected = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < gst_message_streams_selected_get_size (message); i++) {
|
||||||
|
GstStream *stream =
|
||||||
|
gst_message_streams_selected_get_stream (message, i);
|
||||||
|
|
||||||
|
streams_selected = g_list_append (streams_selected, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there a pending switch-track action waiting for the new streams to
|
||||||
|
* be selected? */
|
||||||
|
if (priv->pending_switch_track) {
|
||||||
|
GList *expected, *l;
|
||||||
|
|
||||||
|
expected =
|
||||||
|
gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST
|
||||||
|
(priv->pending_switch_track), ACTION_EXPECTED_STREAM_QUARK);
|
||||||
|
|
||||||
|
if (g_list_length (expected) != g_list_length (streams_selected)) {
|
||||||
|
GST_VALIDATE_REPORT (priv->pending_switch_track->scenario,
|
||||||
|
SCENARIO_ACTION_EXECUTION_ERROR,
|
||||||
|
"Was expecting %d selected streams but got %d",
|
||||||
|
g_list_length (expected), g_list_length (streams_selected));
|
||||||
|
goto action_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = expected; l; l = g_list_next (l)) {
|
||||||
|
const gchar *stream_id = l->data;
|
||||||
|
|
||||||
|
if (!streams_list_contain (streams_selected, stream_id)) {
|
||||||
|
GST_VALIDATE_REPORT (priv->pending_switch_track->scenario,
|
||||||
|
SCENARIO_ACTION_EXECUTION_ERROR,
|
||||||
|
"Stream %s has not be activated", stream_id);
|
||||||
|
goto action_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action_done:
|
||||||
|
gst_validate_action_set_done (priv->pending_switch_track);
|
||||||
|
priv->pending_switch_track = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free_full (streams_selected, gst_object_unref);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <gst/validate/gst-validate-utils.h>
|
#include <gst/validate/gst-validate-utils.h>
|
||||||
#include <gst/validate/media-descriptor-parser.h>
|
#include <gst/validate/media-descriptor-parser.h>
|
||||||
#include <gst/validate/gst-validate-bin-monitor.h>
|
#include <gst/validate/gst-validate-bin-monitor.h>
|
||||||
|
#include <gst/validate/gst-validate-pipeline-monitor.h>
|
||||||
|
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
|
@ -256,121 +257,6 @@ _execute_set_subtitles (GstValidateScenario * scenario,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPadProbeReturn
|
|
||||||
_check_pad_event_selection_done (GstPad * pad, GstPadProbeInfo * info,
|
|
||||||
GstValidateAction * action)
|
|
||||||
{
|
|
||||||
if (GST_EVENT_TYPE (info->data) == GST_EVENT_STREAM_START) {
|
|
||||||
gst_validate_action_set_done (action);
|
|
||||||
return GST_PAD_PROBE_REMOVE;
|
|
||||||
}
|
|
||||||
return GST_PAD_PROBE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_execute_switch_track (GstValidateScenario * scenario,
|
|
||||||
GstValidateAction * action)
|
|
||||||
{
|
|
||||||
gint index, n;
|
|
||||||
const gchar *type, *str_index;
|
|
||||||
|
|
||||||
gint flags, current, tflag;
|
|
||||||
gchar *tmp, *current_txt;
|
|
||||||
|
|
||||||
gint res = GST_VALIDATE_EXECUTE_ACTION_OK;
|
|
||||||
gboolean relative = FALSE, disabling = FALSE;
|
|
||||||
|
|
||||||
if (!(type = gst_structure_get_string (action->structure, "type")))
|
|
||||||
type = "audio";
|
|
||||||
|
|
||||||
tflag =
|
|
||||||
gst_validate_utils_flags_from_str (g_type_from_name ("GstPlayFlags"),
|
|
||||||
type);
|
|
||||||
current_txt = g_strdup_printf ("current-%s", type);
|
|
||||||
|
|
||||||
tmp = g_strdup_printf ("n-%s", type);
|
|
||||||
g_object_get (scenario->pipeline, "flags", &flags, tmp, &n,
|
|
||||||
current_txt, ¤t, NULL);
|
|
||||||
|
|
||||||
/* Don't try to use -1 */
|
|
||||||
if (current == -1)
|
|
||||||
current = 0;
|
|
||||||
|
|
||||||
g_free (tmp);
|
|
||||||
|
|
||||||
if (gst_structure_has_field (action->structure, "disable")) {
|
|
||||||
disabling = TRUE;
|
|
||||||
flags &= ~tflag;
|
|
||||||
index = -1;
|
|
||||||
} else if (!(str_index =
|
|
||||||
gst_structure_get_string (action->structure, "index"))) {
|
|
||||||
if (!gst_structure_get_int (action->structure, "index", &index)) {
|
|
||||||
GST_WARNING ("No index given, defaulting to +1");
|
|
||||||
index = 1;
|
|
||||||
relative = TRUE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
relative = strchr ("+-", str_index[0]) != NULL;
|
|
||||||
index = g_ascii_strtoll (str_index, NULL, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (relative) { /* We are changing track relatively to current track */
|
|
||||||
index = (current + index) % n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!disabling) {
|
|
||||||
GstState state, next;
|
|
||||||
GstPad *oldpad, *newpad;
|
|
||||||
tmp = g_strdup_printf ("get-%s-pad", type);
|
|
||||||
g_signal_emit_by_name (G_OBJECT (scenario->pipeline), tmp, current,
|
|
||||||
&oldpad);
|
|
||||||
g_signal_emit_by_name (G_OBJECT (scenario->pipeline), tmp, index, &newpad);
|
|
||||||
|
|
||||||
gst_validate_printf (action, "Switching to track number: %i,"
|
|
||||||
" (from %s:%s to %s:%s)\n", index, GST_DEBUG_PAD_NAME (oldpad),
|
|
||||||
GST_DEBUG_PAD_NAME (newpad));
|
|
||||||
flags |= tflag;
|
|
||||||
g_free (tmp);
|
|
||||||
|
|
||||||
if (gst_element_get_state (scenario->pipeline, &state, &next, 0) &&
|
|
||||||
state == GST_STATE_PLAYING && next == GST_STATE_VOID_PENDING) {
|
|
||||||
GstPad *srcpad = NULL;
|
|
||||||
GstElement *combiner = NULL;
|
|
||||||
if (newpad == oldpad) {
|
|
||||||
srcpad = gst_pad_get_peer (oldpad);
|
|
||||||
} else if (newpad) {
|
|
||||||
combiner = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (newpad)));
|
|
||||||
if (combiner) {
|
|
||||||
srcpad = gst_element_get_static_pad (combiner, "src");
|
|
||||||
gst_object_unref (combiner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srcpad) {
|
|
||||||
gst_pad_add_probe (srcpad,
|
|
||||||
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
|
|
||||||
(GstPadProbeCallback) _check_pad_event_selection_done, action,
|
|
||||||
NULL);
|
|
||||||
gst_object_unref (srcpad);
|
|
||||||
|
|
||||||
res = GST_VALIDATE_EXECUTE_ACTION_ASYNC;
|
|
||||||
} else
|
|
||||||
res = GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldpad)
|
|
||||||
gst_object_unref (oldpad);
|
|
||||||
gst_object_unref (newpad);
|
|
||||||
} else {
|
|
||||||
gst_validate_printf (action, "Disabling track type %s", type);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_set (scenario->pipeline, "flags", flags, current_txt, index, NULL);
|
|
||||||
g_free (current_txt);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_register_playbin_actions (void)
|
_register_playbin_actions (void)
|
||||||
{
|
{
|
||||||
|
@ -394,41 +280,6 @@ _register_playbin_actions (void)
|
||||||
"and action looks like 'set-subtitle, subtitle-file=en.srt'\n"
|
"and action looks like 'set-subtitle, subtitle-file=en.srt'\n"
|
||||||
"the subtitle URI will be set to 'file:///some/uri.mov.en.srt'\n",
|
"the subtitle URI will be set to 'file:///some/uri.mov.en.srt'\n",
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
/* Overriding default implementation */
|
|
||||||
gst_validate_register_action_type ("switch-track", "validate-launcher", _execute_switch_track,
|
|
||||||
(GstValidateActionParameter []) {
|
|
||||||
{
|
|
||||||
.name = "type",
|
|
||||||
.description = "Selects which track type to change (can be 'audio', 'video',"
|
|
||||||
" or 'text').",
|
|
||||||
.mandatory = FALSE,
|
|
||||||
.types = "string",
|
|
||||||
.possible_variables = NULL,
|
|
||||||
.def = "audio",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "index",
|
|
||||||
.description = "Selects which track of this type to use: it can be either a number,\n"
|
|
||||||
"which will be the Nth track of the given type, or a number with a '+' or\n"
|
|
||||||
"'-' prefix, which means a relative change (eg, '+1' means 'next track',\n"
|
|
||||||
"'-1' means 'previous track')",
|
|
||||||
.mandatory = FALSE,
|
|
||||||
.types = "string: to switch track relatively\n"
|
|
||||||
"int: To use the actual index to use",
|
|
||||||
.possible_variables = NULL,
|
|
||||||
.def = "+1",
|
|
||||||
},
|
|
||||||
{NULL}
|
|
||||||
},
|
|
||||||
"The 'switch-track' command can be used to switch tracks.\n"
|
|
||||||
"The 'type' argument selects which track type to change (can be 'audio', 'video',"
|
|
||||||
" or 'text').\nThe 'index' argument selects which track of this type\n"
|
|
||||||
"to use: it can be either a number, which will be the Nth track of\n"
|
|
||||||
"the given type, or a number with a '+' or '-' prefix, which means\n"
|
|
||||||
"a relative change (eg, '+1' means 'next track', '-1' means 'previous\n"
|
|
||||||
"track'), note that you need to state that it is a string in the scenario file\n"
|
|
||||||
"prefixing it with (string).", FALSE);
|
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue