gst/playback/gstplaybin2.c: Code cleanups.

Original commit message from CVS:
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(gst_play_bin_finalize), (gst_play_bin_set_uri),
(gst_play_bin_set_suburi), (gst_play_bin_set_property),
(gst_play_bin_get_property), (pad_removed_cb), (drained_cb),
(autoplug_select_cb), (activate_group), (deactivate_group),
(setup_next_source), (save_current_group),
(gst_play_bin_change_state):
Code cleanups.
Remove next-uri, we can use the uri property just fine.
Fix some crasher.
Unref uridecodebin when switching.
Fix going to READY.
* gst/playback/gstplaysink.c: (gst_play_sink_class_init),
(gst_play_sink_init), (gst_play_sink_dispose),
(gst_play_sink_finalize), (gst_play_sink_vis_unblocked),
(gst_play_sink_vis_blocked), (gst_play_sink_set_video_sink),
(gst_play_sink_set_audio_sink), (gst_play_sink_set_vis_plugin),
(gst_play_sink_set_property), (gst_play_sink_get_property),
(gen_video_chain), (gen_text_element), (gen_audio_chain),
(gen_vis_element), (gst_play_sink_get_mode),
(gst_play_sink_set_mode), (gst_play_sink_set_flags),
(gst_play_sink_get_flags), (gst_play_sink_request_pad),
(gst_play_sink_release_pad), (gst_play_sink_send_event_to_sink),
(gst_play_sink_change_state):
* gst/playback/gstplaysink.h:
Add some locking to make things threadsafe.
* gst/playback/test7.c: (about_to_finish_cb):
Fix test.
This commit is contained in:
Wim Taymans 2007-12-28 09:00:27 +00:00
parent bd01fd3a57
commit 7cb7bffb9e
5 changed files with 431 additions and 274 deletions

View file

@ -1,3 +1,36 @@
2007-12-28 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(gst_play_bin_finalize), (gst_play_bin_set_uri),
(gst_play_bin_set_suburi), (gst_play_bin_set_property),
(gst_play_bin_get_property), (pad_removed_cb), (drained_cb),
(autoplug_select_cb), (activate_group), (deactivate_group),
(setup_next_source), (save_current_group),
(gst_play_bin_change_state):
Code cleanups.
Remove next-uri, we can use the uri property just fine.
Fix some crasher.
Unref uridecodebin when switching.
Fix going to READY.
* gst/playback/gstplaysink.c: (gst_play_sink_class_init),
(gst_play_sink_init), (gst_play_sink_dispose),
(gst_play_sink_finalize), (gst_play_sink_vis_unblocked),
(gst_play_sink_vis_blocked), (gst_play_sink_set_video_sink),
(gst_play_sink_set_audio_sink), (gst_play_sink_set_vis_plugin),
(gst_play_sink_set_property), (gst_play_sink_get_property),
(gen_video_chain), (gen_text_element), (gen_audio_chain),
(gen_vis_element), (gst_play_sink_get_mode),
(gst_play_sink_set_mode), (gst_play_sink_set_flags),
(gst_play_sink_get_flags), (gst_play_sink_request_pad),
(gst_play_sink_release_pad), (gst_play_sink_send_event_to_sink),
(gst_play_sink_change_state):
* gst/playback/gstplaysink.h:
Add some locking to make things threadsafe.
* gst/playback/test7.c: (about_to_finish_cb):
Fix test.
2007-12-22 Tim-Philipp Müller <tim at centricular dot net>
* gst/videoscale/gstvideoscale.c: (gst_video_scale_set_property),

View file

@ -291,6 +291,7 @@ struct _GstSourceGroup
GstPlayBin *playbin;
gboolean valid; /* the group has valid info to start playback */
gboolean active; /* the group is active */
/* properties */
gchar *uri;
@ -316,6 +317,8 @@ struct _GstPlayBin
GstSourceGroup *curr_group; /* pointer to the currently playing group */
GstSourceGroup *next_group; /* pointer to the next group */
gboolean about_to_finish; /* the about-to-finish signal is emited */
/* properties */
guint connection_speed; /* connection speed in bits/sec (0 = unknown) */
@ -338,8 +341,6 @@ enum
PROP_0,
PROP_URI,
PROP_SUBURI,
PROP_NEXT_URI,
PROP_NEXT_SUBURI,
PROP_STREAMINFO,
PROP_SOURCE,
PROP_CURRENT_VIDEO,
@ -363,7 +364,7 @@ enum
};
static void gst_play_bin_class_init (GstPlayBinClass * klass);
static void gst_play_bin_init (GstPlayBin * play_bin);
static void gst_play_bin_init (GstPlayBin * playbin);
static void gst_play_bin_finalize (GObject * object);
static void gst_play_bin_set_property (GObject * object, guint prop_id,
@ -438,12 +439,6 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
g_object_class_install_property (gobject_klass, PROP_SUBURI,
g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_NEXT_URI,
g_param_spec_string ("next-uri", "Next URI",
"URI of the next media to play", NULL, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_NEXT_SUBURI,
g_param_spec_string ("next-suburi", "Next .sub-URI",
"Optional URI of a next subtitle", NULL, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_STREAMINFO,
g_param_spec_value_array ("stream-info",
@ -569,17 +564,17 @@ gst_play_bin_init (GstPlayBin * playbin)
static void
gst_play_bin_finalize (GObject * object)
{
GstPlayBin *play_bin;
GstPlayBin *playbin;
play_bin = GST_PLAY_BIN (object);
playbin = GST_PLAY_BIN (object);
g_value_array_free (play_bin->elements);
g_value_array_free (playbin->elements);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_play_bin_set_uri (GstPlayBin * play_bin, const gchar * uri)
gst_play_bin_set_uri (GstPlayBin * playbin, const gchar * uri)
{
GstSourceGroup *group;
@ -588,8 +583,8 @@ gst_play_bin_set_uri (GstPlayBin * play_bin, const gchar * uri)
return;
}
GST_OBJECT_LOCK (play_bin);
group = play_bin->next_group;
GST_OBJECT_LOCK (playbin);
group = playbin->next_group;
/* if we have no previous uri, or the new uri is different from the
* old one, replug */
@ -598,16 +593,16 @@ gst_play_bin_set_uri (GstPlayBin * play_bin, const gchar * uri)
group->valid = TRUE;
GST_DEBUG ("setting new uri to %s", uri);
GST_OBJECT_UNLOCK (play_bin);
GST_OBJECT_UNLOCK (playbin);
}
static void
gst_play_bin_set_suburi (GstPlayBin * play_bin, const gchar * suburi)
gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi)
{
GstSourceGroup *group;
GST_OBJECT_LOCK (play_bin);
group = play_bin->next_group;
GST_OBJECT_LOCK (playbin);
group = playbin->next_group;
if ((!suburi && !group->suburi) ||
(suburi && group->suburi && !strcmp (group->suburi, suburi)))
@ -619,29 +614,23 @@ gst_play_bin_set_suburi (GstPlayBin * play_bin, const gchar * suburi)
GST_DEBUG ("setting new .sub uri to %s", suburi);
done:
GST_OBJECT_UNLOCK (play_bin);
GST_OBJECT_UNLOCK (playbin);
}
static void
gst_play_bin_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstPlayBin *play_bin;
GstPlayBin *playbin;
play_bin = GST_PLAY_BIN (object);
playbin = GST_PLAY_BIN (object);
switch (prop_id) {
case PROP_URI:
gst_play_bin_set_uri (play_bin, g_value_get_string (value));
gst_play_bin_set_uri (playbin, g_value_get_string (value));
break;
case PROP_SUBURI:
gst_play_bin_set_suburi (play_bin, g_value_get_string (value));
break;
case PROP_NEXT_URI:
gst_play_bin_set_uri (play_bin, g_value_get_string (value));
break;
case PROP_NEXT_SUBURI:
gst_play_bin_set_suburi (play_bin, g_value_get_string (value));
gst_play_bin_set_suburi (playbin, g_value_get_string (value));
break;
case PROP_VIDEO_SINK:
break;
@ -654,9 +643,9 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
case PROP_FONT_DESC:
break;
case PROP_CONNECTION_SPEED:
GST_OBJECT_LOCK (play_bin);
play_bin->connection_speed = g_value_get_uint (value) * 1000;
GST_OBJECT_UNLOCK (play_bin);
GST_OBJECT_LOCK (playbin);
playbin->connection_speed = g_value_get_uint (value) * 1000;
GST_OBJECT_UNLOCK (playbin);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -668,38 +657,29 @@ static void
gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstPlayBin *play_bin;
GstPlayBin *playbin;
play_bin = GST_PLAY_BIN (object);
playbin = GST_PLAY_BIN (object);
switch (prop_id) {
case PROP_URI:
GST_OBJECT_LOCK (play_bin);
/* get the currently playing group first, then the queued one */
if (play_bin->curr_group)
g_value_set_string (value, play_bin->curr_group->uri);
GST_OBJECT_LOCK (playbin);
/* get the currently playing group first, then the queued one, just in
* case we did not yet start playback. */
if (playbin->curr_group)
g_value_set_string (value, playbin->curr_group->uri);
else
g_value_set_string (value, play_bin->next_group->uri);
GST_OBJECT_UNLOCK (play_bin);
g_value_set_string (value, playbin->next_group->uri);
GST_OBJECT_UNLOCK (playbin);
break;
case PROP_SUBURI:
GST_OBJECT_LOCK (play_bin);
GST_OBJECT_LOCK (playbin);
/* get the currently playing group first, then the queued one */
if (play_bin->curr_group)
g_value_set_string (value, play_bin->curr_group->suburi);
if (playbin->curr_group)
g_value_set_string (value, playbin->curr_group->suburi);
else
g_value_set_string (value, play_bin->next_group->suburi);
GST_OBJECT_UNLOCK (play_bin);
break;
case PROP_NEXT_URI:
GST_OBJECT_LOCK (play_bin);
g_value_set_string (value, play_bin->next_group->uri);
GST_OBJECT_UNLOCK (play_bin);
break;
case PROP_NEXT_SUBURI:
GST_OBJECT_LOCK (play_bin);
g_value_set_string (value, play_bin->next_group->suburi);
GST_OBJECT_UNLOCK (play_bin);
g_value_set_string (value, playbin->next_group->suburi);
GST_OBJECT_UNLOCK (playbin);
break;
case PROP_VIDEO_SINK:
break;
@ -712,9 +692,9 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_FRAME:
break;
case PROP_CONNECTION_SPEED:
GST_OBJECT_LOCK (play_bin);
g_value_set_uint (value, play_bin->connection_speed / 1000);
GST_OBJECT_UNLOCK (play_bin);
GST_OBJECT_LOCK (playbin);
g_value_set_uint (value, playbin->connection_speed / 1000);
GST_OBJECT_UNLOCK (playbin);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -861,8 +841,11 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
/* unlink the pad now (can fail, the pad is unlinked before it's removed) */
gst_pad_unlink (pad, peer);
/* get selector */
/* get selector, this can be NULL when the element is removing the pads
* because it's being disposed. */
selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer));
if (!selector)
goto no_selector;
/* release the pad to the selector, this will make the selector choose a new
* pad. */
@ -878,6 +861,11 @@ not_linked:
GST_DEBUG_OBJECT (playbin, "pad not linked");
return;
}
no_selector:
{
GST_DEBUG_OBJECT (playbin, "selector not found");
return;
}
}
/* we get called when all pads are available and we must connect the sinks to
@ -947,10 +935,16 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group)
GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group);
/* mark use as sending out the about-to-finish signal. When the app sets a URI
* when this signal is emited, we're marking it as next-uri */
playbin->about_to_finish = TRUE;
/* after this call, we should have a next group to activate or we EOS */
g_signal_emit (G_OBJECT (playbin),
gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
playbin->about_to_finish = FALSE;
/* now activate the next group. If the app did not set a next-uri, this will
* fail and we can do EOS */
if (!setup_next_source (playbin)) {
@ -1048,42 +1042,20 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
return GST_AUTOPLUG_SELECT_EXPOSE;
}
/* unlink a group of uridecodebins from the sink */
static void
unlink_group (GstPlayBin * playbin, GstSourceGroup * group)
{
gint i;
GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
for (i = 0; i < 3; i++) {
GstSourceSelect *select = &group->selector[i];
if (!select->selector)
continue;
GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
gst_pad_unlink (select->srcpad, select->sinkpad);
/* release back */
gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
select->sinkpad = NULL;
gst_object_unref (select->srcpad);
select->srcpad = NULL;
gst_element_set_state (select->selector, GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
select->selector = NULL;
}
group->valid = FALSE;
}
static gboolean
activate_group (GstPlayBin * playbin, GstSourceGroup * group)
{
GstElement *uridecodebin;
g_return_val_if_fail (group->valid, FALSE);
g_return_val_if_fail (!group->active, FALSE);
if (group->uridecodebin) {
gst_element_set_state (group->uridecodebin, GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin);
group->uridecodebin = NULL;
}
uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
if (!uridecodebin)
goto no_decodebin;
@ -1116,6 +1088,8 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
gst_element_set_state (uridecodebin, GST_STATE_PAUSED);
group->active = TRUE;
return TRUE;
/* ERRORS */
@ -1125,7 +1099,45 @@ no_decodebin:
}
}
/* setup the next group to play */
/* unlink a group of uridecodebins from the sink */
static gboolean
deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
{
gint i;
g_return_val_if_fail (group->valid, FALSE);
g_return_val_if_fail (group->active, FALSE);
GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
for (i = 0; i < 3; i++) {
GstSourceSelect *select = &group->selector[i];
if (!select->selector)
continue;
GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
gst_pad_unlink (select->srcpad, select->sinkpad);
/* release back */
gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
select->sinkpad = NULL;
gst_object_unref (select->srcpad);
select->srcpad = NULL;
gst_element_set_state (select->selector, GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
select->selector = NULL;
}
group->active = FALSE;
return TRUE;
}
/* setup the next group to play, this assumes the next_group is valid and
* configured. It swaps out the current_group and activates the valid
* next_group. */
static gboolean
setup_next_source (GstPlayBin * playbin)
{
@ -1142,7 +1154,8 @@ setup_next_source (GstPlayBin * playbin)
old_group = playbin->curr_group;
if (old_group && old_group->valid) {
/* unlink our pads with the sink */
unlink_group (playbin, old_group);
deactivate_group (playbin, old_group);
old_group->valid = FALSE;
}
/* activate the new group */
@ -1168,22 +1181,45 @@ activate_failed:
}
}
/* The group that is currently playing is copied again to the
* next_group.
*/
static gboolean
save_current_group (GstPlayBin * playbin)
{
GstSourceGroup *curr_group;
GST_DEBUG_OBJECT (playbin, "save current group");
/* see if there is a current group */
curr_group = playbin->curr_group;
if (curr_group && curr_group->valid) {
/* unlink our pads with the sink */
deactivate_group (playbin, curr_group);
}
/* swap old and new */
playbin->curr_group = playbin->next_group;
playbin->next_group = curr_group;
return TRUE;
}
static GstStateChangeReturn
gst_play_bin_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstPlayBin *play_bin;
GstPlayBin *playbin;
play_bin = GST_PLAY_BIN (element);
playbin = GST_PLAY_BIN (element);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
if (play_bin->playsink == NULL) {
play_bin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
gst_bin_add (GST_BIN_CAST (play_bin),
GST_ELEMENT_CAST (play_bin->playsink));
if (playbin->playsink == NULL) {
playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
gst_bin_add (GST_BIN_CAST (playbin),
GST_ELEMENT_CAST (playbin->playsink));
}
if (!setup_next_source (play_bin))
if (!setup_next_source (playbin))
goto source_failed;
break;
default:
@ -1201,10 +1237,13 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
/* FIXME Release audio device when we implement that */
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
if (play_bin->playsink) {
gst_bin_remove (GST_BIN_CAST (play_bin),
GST_ELEMENT_CAST (play_bin->playsink));
play_bin->playsink = NULL;
save_current_group (playbin);
if (playbin->playsink) {
gst_element_set_state (GST_ELEMENT_CAST (playbin->playsink),
GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (playbin),
GST_ELEMENT_CAST (playbin->playsink));
playbin->playsink = NULL;
}
break;
default:

View file

@ -64,11 +64,18 @@ typedef struct
GstElement *sink;
} GstPlayVideoChain;
#define GST_PLAY_SINK_GET_LOCK(playsink) (((GstPlaySink *)playsink)->lock)
#define GST_PLAY_SINK_LOCK(playsink) g_mutex_lock (GST_PLAY_SINK_GET_LOCK (playsink))
#define GST_PLAY_SINK_UNLOCK(playsink) g_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink))
struct _GstPlaySink
{
GstBin bin;
GMutex *lock;
GstPlaySinkMode mode;
GstPlaySinkFlags flags;
GstPlayChain *audiochain;
GstPlayChain *videochain;
@ -120,8 +127,9 @@ enum
};
static void gst_play_sink_class_init (GstPlaySinkClass * klass);
static void gst_play_sink_init (GstPlaySink * play_sink);
static void gst_play_sink_init (GstPlaySink * playsink);
static void gst_play_sink_dispose (GObject * object);
static void gst_play_sink_finalize (GObject * object);
static void gst_play_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * spec);
@ -186,6 +194,7 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
gobject_klass->get_property = gst_play_sink_get_property;
gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_sink_dispose);
gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_sink_finalize);
g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
g_param_spec_object ("video-sink", "Video Sink",
@ -222,97 +231,112 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
}
static void
gst_play_sink_init (GstPlaySink * play_sink)
gst_play_sink_init (GstPlaySink * playsink)
{
/* init groups */
play_sink->video_sink = NULL;
play_sink->audio_sink = NULL;
play_sink->visualisation = NULL;
play_sink->pending_visualisation = NULL;
play_sink->textoverlay_element = NULL;
play_sink->volume = 1.0;
play_sink->font_desc = NULL;
playsink->video_sink = NULL;
playsink->audio_sink = NULL;
playsink->visualisation = NULL;
playsink->pending_visualisation = NULL;
playsink->textoverlay_element = NULL;
playsink->volume = 1.0;
playsink->font_desc = NULL;
playsink->flags = GST_PLAY_SINK_FLAG_SOFT_VOLUME;
playsink->lock = g_mutex_new ();
}
static void
gst_play_sink_dispose (GObject * object)
{
GstPlaySink *play_sink;
GstPlaySink *playsink;
play_sink = GST_PLAY_SINK (object);
playsink = GST_PLAY_SINK (object);
if (play_sink->audio_sink != NULL) {
gst_element_set_state (play_sink->audio_sink, GST_STATE_NULL);
gst_object_unref (play_sink->audio_sink);
play_sink->audio_sink = NULL;
if (playsink->audio_sink != NULL) {
gst_element_set_state (playsink->audio_sink, GST_STATE_NULL);
gst_object_unref (playsink->audio_sink);
playsink->audio_sink = NULL;
}
if (play_sink->video_sink != NULL) {
gst_element_set_state (play_sink->video_sink, GST_STATE_NULL);
gst_object_unref (play_sink->video_sink);
play_sink->video_sink = NULL;
if (playsink->video_sink != NULL) {
gst_element_set_state (playsink->video_sink, GST_STATE_NULL);
gst_object_unref (playsink->video_sink);
playsink->video_sink = NULL;
}
if (play_sink->visualisation != NULL) {
gst_element_set_state (play_sink->visualisation, GST_STATE_NULL);
gst_object_unref (play_sink->visualisation);
play_sink->visualisation = NULL;
if (playsink->visualisation != NULL) {
gst_element_set_state (playsink->visualisation, GST_STATE_NULL);
gst_object_unref (playsink->visualisation);
playsink->visualisation = NULL;
}
if (play_sink->pending_visualisation != NULL) {
gst_element_set_state (play_sink->pending_visualisation, GST_STATE_NULL);
gst_object_unref (play_sink->pending_visualisation);
play_sink->pending_visualisation = NULL;
if (playsink->pending_visualisation != NULL) {
gst_element_set_state (playsink->pending_visualisation, GST_STATE_NULL);
gst_object_unref (playsink->pending_visualisation);
playsink->pending_visualisation = NULL;
}
if (play_sink->textoverlay_element != NULL) {
gst_object_unref (play_sink->textoverlay_element);
play_sink->textoverlay_element = NULL;
if (playsink->textoverlay_element != NULL) {
gst_object_unref (playsink->textoverlay_element);
playsink->textoverlay_element = NULL;
}
g_free (play_sink->font_desc);
play_sink->font_desc = NULL;
g_free (playsink->font_desc);
playsink->font_desc = NULL;
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_play_sink_finalize (GObject * object)
{
GstPlaySink *playsink;
playsink = GST_PLAY_SINK (object);
g_mutex_free (playsink->lock);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_play_sink_vis_unblocked (GstPad * tee_pad, gboolean blocked,
gpointer user_data)
{
GstPlaySink *play_sink = GST_PLAY_SINK (user_data);
GstPlaySink *playsink = GST_PLAY_SINK (user_data);
if (play_sink->pending_visualisation)
if (playsink->pending_visualisation)
gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked,
play_sink);
playsink);
}
static void
gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked,
gpointer user_data)
{
GstPlaySink *play_sink = GST_PLAY_SINK (user_data);
GstPlaySink *playsink = GST_PLAY_SINK (user_data);
GstBin *vis_bin = NULL;
GstPad *vis_sink_pad = NULL, *vis_src_pad = NULL, *vqueue_pad = NULL;
GstState bin_state;
GstElement *pending_visualisation;
GST_OBJECT_LOCK (play_sink);
pending_visualisation = play_sink->pending_visualisation;
play_sink->pending_visualisation = NULL;
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
pending_visualisation = playsink->pending_visualisation;
playsink->pending_visualisation = NULL;
GST_OBJECT_UNLOCK (playsink);
/* We want to disable visualisation */
if (!GST_IS_ELEMENT (pending_visualisation)) {
/* Set visualisation element to READY */
gst_element_set_state (play_sink->visualisation, GST_STATE_READY);
gst_element_set_state (playsink->visualisation, GST_STATE_READY);
goto beach;
}
vis_bin =
GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (play_sink->
GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (playsink->
visualisation)));
if (!GST_IS_BIN (vis_bin) || !GST_IS_PAD (tee_pad)) {
goto beach;
}
vis_src_pad = gst_element_get_pad (play_sink->visualisation, "src");
vis_src_pad = gst_element_get_pad (playsink->visualisation, "src");
vis_sink_pad = gst_pad_get_peer (tee_pad);
/* Can be fakesink */
@ -341,11 +365,11 @@ gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked,
}
/* Remove from vis_bin */
gst_bin_remove (vis_bin, play_sink->visualisation);
gst_bin_remove (vis_bin, playsink->visualisation);
/* Set state to NULL */
gst_element_set_state (play_sink->visualisation, GST_STATE_NULL);
gst_element_set_state (playsink->visualisation, GST_STATE_NULL);
/* And loose our ref */
gst_object_unref (play_sink->visualisation);
gst_object_unref (playsink->visualisation);
if (pending_visualisation) {
/* Ref this new visualisation element before adding to the bin */
@ -368,8 +392,8 @@ gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked,
}
/* We are done */
gst_object_unref (play_sink->visualisation);
play_sink->visualisation = pending_visualisation;
gst_object_unref (playsink->visualisation);
playsink->visualisation = pending_visualisation;
beach:
if (vis_sink_pad) {
@ -387,41 +411,41 @@ beach:
/* Unblock the pad */
gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked,
play_sink);
playsink);
}
void
gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink)
gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink)
{
GST_OBJECT_LOCK (play_sink);
if (play_sink->video_sink)
gst_object_unref (play_sink->video_sink);
GST_OBJECT_LOCK (playsink);
if (playsink->video_sink)
gst_object_unref (playsink->video_sink);
if (sink) {
gst_object_ref (sink);
gst_object_sink (sink);
}
play_sink->video_sink = sink;
GST_OBJECT_UNLOCK (play_sink);
playsink->video_sink = sink;
GST_OBJECT_UNLOCK (playsink);
}
void
gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink)
gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink)
{
GST_OBJECT_LOCK (play_sink);
if (play_sink->audio_sink)
gst_object_unref (play_sink->audio_sink);
GST_OBJECT_LOCK (playsink);
if (playsink->audio_sink)
gst_object_unref (playsink->audio_sink);
if (sink) {
gst_object_ref (sink);
gst_object_sink (sink);
}
play_sink->audio_sink = sink;
GST_OBJECT_UNLOCK (play_sink);
playsink->audio_sink = sink;
GST_OBJECT_UNLOCK (playsink);
}
void
gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
gst_play_sink_set_vis_plugin (GstPlaySink * playsink,
GstElement * pending_visualisation)
{
/* Take ownership */
@ -432,19 +456,19 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
/* Do we already have a visualisation change pending? If yes, change the
* pending vis with the new one. */
GST_OBJECT_LOCK (play_sink);
if (play_sink->pending_visualisation) {
gst_object_unref (play_sink->pending_visualisation);
play_sink->pending_visualisation = pending_visualisation;
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
if (playsink->pending_visualisation) {
gst_object_unref (playsink->pending_visualisation);
playsink->pending_visualisation = pending_visualisation;
GST_OBJECT_UNLOCK (playsink);
} else {
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_UNLOCK (playsink);
/* Was there a visualisation already set ? */
if (play_sink->visualisation != NULL) {
if (playsink->visualisation != NULL) {
GstBin *vis_bin = NULL;
vis_bin =
GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (play_sink->
GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (playsink->
visualisation)));
/* Check if the visualisation is already in a bin */
@ -452,7 +476,7 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
GstPad *vis_sink_pad = NULL, *tee_pad = NULL;
/* Now get tee pad and block it async */
vis_sink_pad = gst_element_get_pad (play_sink->visualisation, "sink");
vis_sink_pad = gst_element_get_pad (playsink->visualisation, "sink");
if (!GST_IS_PAD (vis_sink_pad)) {
goto beach;
}
@ -461,10 +485,10 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
goto beach;
}
play_sink->pending_visualisation = pending_visualisation;
playsink->pending_visualisation = pending_visualisation;
/* Block with callback */
gst_pad_set_blocked_async (tee_pad, TRUE, gst_play_sink_vis_blocked,
play_sink);
playsink);
beach:
if (vis_sink_pad) {
gst_object_unref (vis_sink_pad);
@ -474,10 +498,10 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink,
}
gst_object_unref (vis_bin);
} else {
play_sink->visualisation = pending_visualisation;
playsink->visualisation = pending_visualisation;
}
} else {
play_sink->visualisation = pending_visualisation;
playsink->visualisation = pending_visualisation;
}
}
}
@ -486,34 +510,34 @@ static void
gst_play_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstPlaySink *play_sink;
GstPlaySink *playsink;
play_sink = GST_PLAY_SINK (object);
playsink = GST_PLAY_SINK (object);
switch (prop_id) {
case PROP_VIDEO_SINK:
gst_play_sink_set_video_sink (play_sink, g_value_get_object (value));
gst_play_sink_set_video_sink (playsink, g_value_get_object (value));
break;
case PROP_AUDIO_SINK:
gst_play_sink_set_audio_sink (play_sink, g_value_get_object (value));
gst_play_sink_set_audio_sink (playsink, g_value_get_object (value));
break;
case PROP_VIS_PLUGIN:
gst_play_sink_set_vis_plugin (play_sink, g_value_get_object (value));
gst_play_sink_set_vis_plugin (playsink, g_value_get_object (value));
break;
case PROP_VOLUME:
GST_OBJECT_LOCK (play_sink);
play_sink->volume = g_value_get_double (value);
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
playsink->volume = g_value_get_double (value);
GST_OBJECT_UNLOCK (playsink);
break;
case PROP_FONT_DESC:
GST_OBJECT_LOCK (play_sink);
g_free (play_sink->font_desc);
play_sink->font_desc = g_strdup (g_value_get_string (value));
if (play_sink->textoverlay_element) {
g_object_set (G_OBJECT (play_sink->textoverlay_element),
GST_OBJECT_LOCK (playsink);
g_free (playsink->font_desc);
playsink->font_desc = g_strdup (g_value_get_string (value));
if (playsink->textoverlay_element) {
g_object_set (G_OBJECT (playsink->textoverlay_element),
"font-desc", g_value_get_string (value), NULL);
}
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_UNLOCK (playsink);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -525,30 +549,30 @@ static void
gst_play_sink_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstPlaySink *play_sink;
GstPlaySink *playsink;
play_sink = GST_PLAY_SINK (object);
playsink = GST_PLAY_SINK (object);
switch (prop_id) {
case PROP_VIDEO_SINK:
GST_OBJECT_LOCK (play_sink);
g_value_set_object (value, play_sink->video_sink);
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
g_value_set_object (value, playsink->video_sink);
GST_OBJECT_UNLOCK (playsink);
break;
case PROP_AUDIO_SINK:
GST_OBJECT_LOCK (play_sink);
g_value_set_object (value, play_sink->audio_sink);
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
g_value_set_object (value, playsink->audio_sink);
GST_OBJECT_UNLOCK (playsink);
break;
case PROP_VIS_PLUGIN:
GST_OBJECT_LOCK (play_sink);
g_value_set_object (value, play_sink->visualisation);
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
g_value_set_object (value, playsink->visualisation);
GST_OBJECT_UNLOCK (playsink);
break;
case PROP_VOLUME:
GST_OBJECT_LOCK (play_sink);
g_value_set_double (value, play_sink->volume);
GST_OBJECT_UNLOCK (play_sink);
GST_OBJECT_LOCK (playsink);
g_value_set_double (value, playsink->volume);
GST_OBJECT_UNLOCK (playsink);
break;
case PROP_FRAME:
{
@ -624,17 +648,17 @@ activate_chain (GstPlayChain * chain, gboolean activate)
*
*/
static GstPlayChain *
gen_video_chain (GstPlaySink * play_sink, gboolean raw)
gen_video_chain (GstPlaySink * playsink, gboolean raw)
{
GstPlayVideoChain *chain;
GstBin *bin;
GstPad *pad;
chain = g_new0 (GstPlayVideoChain, 1);
chain->chain.playsink = gst_object_ref (play_sink);
chain->chain.playsink = gst_object_ref (playsink);
if (play_sink->video_sink) {
chain->sink = play_sink->video_sink;
if (playsink->video_sink) {
chain->sink = playsink->video_sink;
} else {
chain->sink = gst_element_factory_make ("autovideosink", "videosink");
if (chain->sink == NULL) {
@ -697,8 +721,8 @@ gen_video_chain (GstPlaySink * play_sink, gboolean raw)
/* ERRORS */
no_sinks:
{
post_missing_element_message (play_sink, "autovideosink");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "autovideosink");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Both autovideosink and xvimagesink elements are missing.")),
(NULL));
free_chain ((GstPlayChain *) chain);
@ -706,8 +730,8 @@ no_sinks:
}
no_colorspace:
{
post_missing_element_message (play_sink, "ffmpegcolorspace");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "ffmpegcolorspace");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"ffmpegcolorspace"), (NULL));
free_chain ((GstPlayChain *) chain);
@ -716,8 +740,8 @@ no_colorspace:
no_videoscale:
{
post_missing_element_message (play_sink, "videoscale");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "videoscale");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"videoscale"), ("possibly a liboil version mismatch?"));
free_chain ((GstPlayChain *) chain);
@ -725,7 +749,7 @@ no_videoscale:
}
link_failed:
{
GST_ELEMENT_ERROR (play_sink, CORE, PAD,
GST_ELEMENT_ERROR (playsink, CORE, PAD,
(NULL), ("Failed to configure the video sink."));
free_chain ((GstPlayChain *) chain);
return NULL;
@ -748,13 +772,13 @@ link_failed:
* videosink without the text_sink pad.
*/
static GstElement *
gen_text_element (GstPlaySink * play_sink)
gen_text_element (GstPlaySink * playsink)
{
GstElement *element, *csp, *overlay, *vbin;
GstPad *pad;
/* Create the video rendering bin, error is posted when this fails. */
vbin = gen_video_element (play_sink);
vbin = gen_video_element (playsink);
if (!vbin)
return NULL;
@ -771,12 +795,12 @@ gen_text_element (GstPlaySink * play_sink)
/* Set some parameters */
g_object_set (G_OBJECT (overlay),
"halign", "center", "valign", "bottom", NULL);
if (play_sink->font_desc) {
g_object_set (G_OBJECT (overlay), "font-desc", play_sink->font_desc, NULL);
if (playsink->font_desc) {
g_object_set (G_OBJECT (overlay), "font-desc", playsink->font_desc, NULL);
}
/* Take a ref */
play_sink->textoverlay_element = GST_ELEMENT_CAST (gst_object_ref (overlay));
playsink->textoverlay_element = GST_ELEMENT_CAST (gst_object_ref (overlay));
/* we know this will succeed, as the video bin already created one before */
csp = gst_element_factory_make ("ffmpegcolorspace", "subtitlecsp");
@ -805,8 +829,8 @@ gen_text_element (GstPlaySink * play_sink)
/* ERRORS */
no_overlay:
{
post_missing_element_message (play_sink, "textoverlay");
GST_WARNING_OBJECT (play_sink,
post_missing_element_message (playsink, "textoverlay");
GST_WARNING_OBJECT (playsink,
"No overlay (pango) element, subtitles disabled");
return vbin;
}
@ -827,7 +851,7 @@ no_overlay:
* +-------------------------------------------------------------+
*/
static GstPlayChain *
gen_audio_chain (GstPlaySink * play_sink, gboolean raw)
gen_audio_chain (GstPlaySink * playsink, gboolean raw)
{
GstPlayAudioChain *chain;
GstBin *bin;
@ -835,10 +859,10 @@ gen_audio_chain (GstPlaySink * play_sink, gboolean raw)
GstPad *pad;
chain = g_new0 (GstPlayAudioChain, 1);
chain->chain.playsink = gst_object_ref (play_sink);
chain->chain.playsink = gst_object_ref (playsink);
if (play_sink->audio_sink) {
chain->sink = play_sink->audio_sink;
if (playsink->audio_sink) {
chain->sink = playsink->audio_sink;
} else {
chain->sink = gst_element_factory_make ("autoaudiosink", "audiosink");
if (chain->sink == NULL) {
@ -864,14 +888,19 @@ gen_audio_chain (GstPlaySink * play_sink, gboolean raw)
goto no_audioresample;
gst_bin_add (bin, chain->resample);
chain->volume = gst_element_factory_make ("volume", "volume");
g_object_set (G_OBJECT (chain->volume), "volume", play_sink->volume, NULL);
gst_bin_add (bin, chain->volume);
res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
res &=
gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
if (playsink->flags & GST_PLAY_SINK_FLAG_SOFT_VOLUME) {
chain->volume = gst_element_factory_make ("volume", "volume");
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
gst_bin_add (bin, chain->volume);
res &=
gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
} else {
res &= gst_element_link_pads (chain->resample, "src", chain->sink, NULL);
}
if (!res)
goto link_failed;
@ -888,16 +917,16 @@ gen_audio_chain (GstPlaySink * play_sink, gboolean raw)
/* ERRORS */
no_sinks:
{
post_missing_element_message (play_sink, "autoaudiosink");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "autoaudiosink");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Both autoaudiosink and alsasink elements are missing.")), (NULL));
free_chain ((GstPlayChain *) chain);
return NULL;
}
no_audioconvert:
{
post_missing_element_message (play_sink, "audioconvert");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "audioconvert");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"audioconvert"), ("possibly a liboil version mismatch?"));
free_chain ((GstPlayChain *) chain);
@ -906,8 +935,8 @@ no_audioconvert:
no_audioresample:
{
post_missing_element_message (play_sink, "audioresample");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "audioresample");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"audioresample"), ("possibly a liboil version mismatch?"));
free_chain ((GstPlayChain *) chain);
@ -915,7 +944,7 @@ no_audioresample:
}
link_failed:
{
GST_ELEMENT_ERROR (play_sink, CORE, PAD,
GST_ELEMENT_ERROR (playsink, CORE, PAD,
(NULL), ("Failed to configure the audio sink."));
free_chain ((GstPlayChain *) chain);
return NULL;
@ -947,7 +976,7 @@ link_failed:
* +-----------------------------------------------------------------------+
*/
static GstElement *
gen_vis_element (GstPlaySink * play_sink)
gen_vis_element (GstPlaySink * playsink)
{
gboolean res;
GstElement *element;
@ -962,10 +991,10 @@ gen_vis_element (GstPlaySink * play_sink)
GstPad *pad, *rpad;
/* errors are already posted when these fail. */
asink = gen_audio_element (play_sink);
asink = gen_audio_element (playsink);
if (!asink)
return NULL;
vsink = gen_video_element (play_sink);
vsink = gen_video_element (playsink);
if (!vsink) {
gst_object_unref (asink);
return NULL;
@ -998,9 +1027,9 @@ gen_vis_element (GstPlaySink * play_sink)
goto no_audioconvert;
gst_bin_add (GST_BIN_CAST (element), conv2);
if (play_sink->visualisation) {
gst_object_ref (play_sink->visualisation);
vis = play_sink->visualisation;
if (playsink->visualisation) {
gst_object_ref (playsink->visualisation);
vis = playsink->visualisation;
} else {
vis = gst_element_factory_make ("goom", "vis");
if (!vis)
@ -1038,8 +1067,8 @@ gen_vis_element (GstPlaySink * play_sink)
/* ERRORS */
no_audioconvert:
{
post_missing_element_message (play_sink, "audioconvert");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "audioconvert");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"audioconvert"), ("possibly a liboil version mismatch?"));
gst_object_unref (element);
@ -1047,8 +1076,8 @@ no_audioconvert:
}
no_audioresample:
{
post_missing_element_message (play_sink, "audioresample");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "audioresample");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"audioresample"), (NULL));
gst_object_unref (element);
@ -1056,8 +1085,8 @@ no_audioresample:
}
no_goom:
{
post_missing_element_message (play_sink, "goom");
GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN,
post_missing_element_message (playsink, "goom");
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"goom"), (NULL));
gst_object_unref (element);
@ -1065,7 +1094,7 @@ no_goom:
}
link_failed:
{
GST_ELEMENT_ERROR (play_sink, CORE, PAD,
GST_ELEMENT_ERROR (playsink, CORE, PAD,
(NULL), ("Failed to configure the visualisation element."));
gst_object_unref (element);
return NULL;
@ -1078,9 +1107,9 @@ gst_play_sink_get_mode (GstPlaySink * playsink)
{
GstPlaySinkMode res;
GST_OBJECT_LOCK (playsink);
GST_PLAY_SINK_LOCK (playsink);
res = playsink->mode;
GST_OBJECT_LOCK (playsink);
GST_PLAY_SINK_UNLOCK (playsink);
return res;
}
@ -1091,6 +1120,9 @@ gst_play_sink_get_mode (GstPlaySink * playsink)
gboolean
gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
{
GST_DEBUG_OBJECT (playsink, "setting mode to %d", mode);
GST_PLAY_SINK_LOCK (playsink);
if (mode & GST_PLAY_SINK_MODE_AUDIO && playsink->audio_pad) {
if (!playsink->audiochain)
playsink->audiochain =
@ -1126,10 +1158,38 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
}
playsink->mode = mode;
GST_PLAY_SINK_UNLOCK (playsink);
return TRUE;
}
gboolean
gst_play_sink_set_flags (GstPlaySink * playsink, GstPlaySinkFlags flags)
{
g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), FALSE);
GST_OBJECT_LOCK (playsink);
playsink->flags = flags;
GST_OBJECT_LOCK (playsink);
return TRUE;
}
GstPlaySinkFlags
gst_play_sink_get_flags (GstPlaySink * playsink)
{
GstPlaySinkFlags res;
g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), 0);
GST_OBJECT_LOCK (playsink);
res = playsink->flags;
GST_OBJECT_LOCK (playsink);
return res;
}
GstPad *
gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
{
@ -1137,6 +1197,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
gboolean created = FALSE;
gboolean raw = FALSE;
GST_PLAY_SINK_LOCK (playsink);
switch (type) {
case GST_PLAY_SINK_TYPE_AUDIO_RAW:
raw = TRUE;
@ -1172,10 +1233,13 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
res = NULL;
break;
}
GST_PLAY_SINK_UNLOCK (playsink);
if (created && res) {
gst_pad_set_active (res, TRUE);
gst_element_add_pad (GST_ELEMENT_CAST (playsink), res);
}
return res;
}
@ -1184,6 +1248,7 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad)
{
GstPad **res = NULL;
GST_PLAY_SINK_LOCK (playsink);
if (pad == playsink->video_pad) {
res = &playsink->video_pad;
} else if (pad == playsink->audio_pad) {
@ -1191,6 +1256,7 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad)
} else if (pad == playsink->text_pad) {
res = &playsink->text_pad;
}
GST_PLAY_SINK_UNLOCK (playsink);
if (*res) {
gst_pad_set_active (*res, FALSE);
@ -1203,25 +1269,25 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad)
* remaining sinks (unlike GstBin)
*/
static gboolean
gst_play_sink_send_event_to_sink (GstPlaySink * play_sink, GstEvent * event)
gst_play_sink_send_event_to_sink (GstPlaySink * playsink, GstEvent * event)
{
gboolean res = TRUE;
if (play_sink->audiochain) {
if (playsink->audiochain) {
gst_event_ref (event);
if ((res = gst_element_send_event (play_sink->audiochain->bin, event))) {
GST_DEBUG_OBJECT (play_sink, "Sent event succesfully to audio sink");
if ((res = gst_element_send_event (playsink->audiochain->bin, event))) {
GST_DEBUG_OBJECT (playsink, "Sent event succesfully to audio sink");
goto done;
}
GST_DEBUG_OBJECT (play_sink, "Event failed when sent to audio sink");
GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink");
}
if (play_sink->videochain) {
if (playsink->videochain) {
gst_event_ref (event);
if ((res = gst_element_send_event (play_sink->videochain->bin, event))) {
GST_DEBUG_OBJECT (play_sink, "Sent event succesfully to video sink");
if ((res = gst_element_send_event (playsink->videochain->bin, event))) {
GST_DEBUG_OBJECT (playsink, "Sent event succesfully to video sink");
goto done;
}
GST_DEBUG_OBJECT (play_sink, "Event failed when sent to video sink");
GST_DEBUG_OBJECT (playsink, "Event failed when sent to video sink");
}
done:
gst_event_unref (event);
@ -1253,9 +1319,9 @@ static GstStateChangeReturn
gst_play_sink_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstPlaySink *play_sink;
GstPlaySink *playsink;
play_sink = GST_PLAY_SINK (element);
playsink = GST_PLAY_SINK (element);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:

View file

@ -71,6 +71,22 @@ typedef enum {
GST_PLAY_SINK_TYPE_LAST = 5
} GstPlaySinkType;
/**
* GstPlaySinkFlags:
* @GST_PLAY_SINK_FLAG_SOFT_VOLUME: Use software volume in the sink
* @GST_PLAY_SINK_FLAG_NATIVE_AUDIO: only allow native audio formats, this omits
* configuration of audioconvert and audioresample.
* @GST_PLAY_SINK_FLAG_NATIVE_VIDEO: only allow native video formats, this omits
* configuration of ffmpegcolorspace and videoscale.
*
* Extra flags to configure the behaviour of the sinks.
*/
typedef enum {
GST_PLAY_SINK_FLAG_SOFT_VOLUME = (1 << 0),
GST_PLAY_SINK_FLAG_NATIVE_AUDIO = (1 << 1),
GST_PLAY_SINK_FLAG_NATIVE_VIDEO = (1 << 2)
} GstPlaySinkFlags;
typedef struct _GstPlaySink GstPlaySink;
typedef struct _GstPlaySinkClass GstPlaySinkClass;
@ -79,12 +95,15 @@ GType gst_play_sink_get_type (void);
GstPad * gst_play_sink_request_pad (GstPlaySink *playsink, GstPlaySinkType type);
void gst_play_sink_release_pad (GstPlaySink *playsink, GstPad *pad);
void gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink);
void gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink);
void gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, GstElement * vis);
void gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink);
void gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink);
void gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis);
gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlaySinkFlags flags);
GstPlaySinkFlags gst_play_sink_get_flags (GstPlaySink * playsink);
GstPlaySinkMode gst_play_sink_get_mode (GstPlaySink *playsink);
gboolean gst_play_sink_set_mode (GstPlaySink *playsink, GstPlaySinkMode mode);
GstPlaySinkMode gst_play_sink_get_mode (GstPlaySink *playsink);
G_END_DECLS

View file

@ -92,7 +92,7 @@ static void
about_to_finish_cb (GstElement * element, gchar * uri[])
{
if (arg_count < max_count) {
g_object_set (G_OBJECT (element), "next-uri", uri[arg_count], NULL);
g_object_set (G_OBJECT (element), "uri", uri[arg_count], NULL);
arg_count++;
}
}