mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-02 16:52:42 +00:00
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:
parent
bd01fd3a57
commit
7cb7bffb9e
5 changed files with 431 additions and 274 deletions
33
ChangeLog
33
ChangeLog
|
@ -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),
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue