gst/playback/gstplaybin2.c: Remove stream-info, we going for something easier.

Original commit message from CVS:
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(get_group), (get_n_pads), (gst_play_bin_get_property),
(pad_added_cb), (no_more_pads_cb), (perform_eos),
(autoplug_select_cb), (deactivate_group):
Remove stream-info, we going for something easier.
Refactor getting the current group.
Implement getting the number of audio/video/text streams.
* gst/playback/gststreamselector.c:
(gst_stream_selector_class_init), (gst_stream_selector_init),
(gst_stream_selector_get_property),
(gst_stream_selector_request_new_pad),
(gst_stream_selector_release_pad):
* gst/playback/gststreamselector.h:
Add property for number of pads.
* tests/examples/seek/seek.c: (set_scale), (update_flag),
(vis_toggle_cb), (audio_toggle_cb), (video_toggle_cb),
(text_toggle_cb), (update_streams), (msg_async_done),
(msg_state_changed), (main):
Block slider callback when updating the slider position.
Add gui elements for controlling playbin2.
Add callback for async_done that updates position/duration.
This commit is contained in:
Wim Taymans 2008-02-01 16:44:21 +00:00
parent f37ad5da3e
commit 899330d904
5 changed files with 228 additions and 33 deletions

View file

@ -1,3 +1,29 @@
2008-02-01 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(get_group), (get_n_pads), (gst_play_bin_get_property),
(pad_added_cb), (no_more_pads_cb), (perform_eos),
(autoplug_select_cb), (deactivate_group):
Remove stream-info, we going for something easier.
Refactor getting the current group.
Implement getting the number of audio/video/text streams.
* gst/playback/gststreamselector.c:
(gst_stream_selector_class_init), (gst_stream_selector_init),
(gst_stream_selector_get_property),
(gst_stream_selector_request_new_pad),
(gst_stream_selector_release_pad):
* gst/playback/gststreamselector.h:
Add property for number of pads.
* tests/examples/seek/seek.c: (set_scale), (update_flag),
(vis_toggle_cb), (audio_toggle_cb), (video_toggle_cb),
(text_toggle_cb), (update_streams), (msg_async_done),
(msg_state_changed), (main):
Block slider callback when updating the slider position.
Add gui elements for controlling playbin2.
Add callback for async_done that updates position/duration.
2008-02-01 Stefan Kost <ensonic@users.sf.net>
* docs/plugins/Makefile.am:

View file

@ -336,7 +336,6 @@ struct _GstPlayBinClass
/* props */
#define DEFAULT_URI NULL
#define DEFAULT_SUBURI NULL
#define DEFAULT_STREAMINFO NULL
#define DEFAULT_SOURCE NULL
#define DEFAULT_FLAGS GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \
GST_PLAY_FLAG_SOFT_VOLUME
@ -360,7 +359,6 @@ enum
PROP_0,
PROP_URI,
PROP_SUBURI,
PROP_STREAMINFO,
PROP_SOURCE,
PROP_FLAGS,
PROP_N_VIDEO,
@ -476,12 +474,6 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_STREAMINFO,
g_param_spec_value_array ("stream-info",
"StreamInfo GValueArray", "value array of streaminfo",
g_param_spec_object ("streaminfo", "StreamInfo", "Streaminfo object",
GST_TYPE_STREAM_INFO, G_PARAM_READABLE), G_PARAM_READABLE));
g_object_class_install_property (gobject_klass, PROP_SOURCE,
g_param_spec_object ("source", "Source", "Source element",
GST_TYPE_ELEMENT, G_PARAM_READABLE));
@ -753,6 +745,32 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
}
}
/* get the currently playing group or if nothing is playing, the next
* group. Must be called with the LOCK. */
static GstSourceGroup *
get_group (GstPlayBin * playbin)
{
GstSourceGroup *result;
if (!(result = playbin->curr_group))
result = playbin->next_group;
return result;
}
static gint
get_n_pads (GstSourceSelect * select)
{
gint res;
if (select->selector == NULL)
return 0;
g_object_get (select->selector, "n-pads", &res, NULL);
return res;
}
static void
gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
@ -763,36 +781,58 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
switch (prop_id) {
case PROP_URI:
{
GstSourceGroup *group;
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, playbin->next_group->uri);
group = get_group (playbin);
g_value_set_string (value, group->uri);
GST_OBJECT_UNLOCK (playbin);
break;
}
case PROP_SUBURI:
{
GstSourceGroup *group;
GST_OBJECT_LOCK (playbin);
/* get the currently playing group first, then the queued one */
if (playbin->curr_group)
g_value_set_string (value, playbin->curr_group->suburi);
else
g_value_set_string (value, playbin->next_group->suburi);
group = get_group (playbin);
g_value_set_string (value, group->suburi);
GST_OBJECT_UNLOCK (playbin);
break;
case PROP_STREAMINFO:
break;
}
case PROP_SOURCE:
break;
case PROP_FLAGS:
g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink));
break;
case PROP_N_VIDEO:
{
GstSourceGroup *group;
gint n_rawvideo, n_video;
GST_OBJECT_LOCK (playbin);
group = get_group (playbin);
n_rawvideo = get_n_pads (&group->selector[2]);
n_video = get_n_pads (&group->selector[3]);
g_value_set_int (value, n_rawvideo + n_video);
GST_OBJECT_UNLOCK (playbin);
break;
}
case PROP_CURRENT_VIDEO:
break;
case PROP_N_AUDIO:
{
GstSourceGroup *group;
gint n_rawaudio, n_audio;
GST_OBJECT_LOCK (playbin);
group = get_group (playbin);
n_rawaudio = get_n_pads (&group->selector[0]);
n_audio = get_n_pads (&group->selector[1]);
g_value_set_int (value, n_rawaudio + n_audio);
GST_OBJECT_UNLOCK (playbin);
break;
}
break;
case PROP_CURRENT_AUDIO:
break;
@ -878,7 +918,7 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
GST_DEBUG_PAD_NAME (pad), caps, group);
/* major type of the pad, this determines the selector to use */
for (i = 0; i < 3; i++) {
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
if (g_str_has_prefix (name, group->selector[i].media)) {
select = &group->selector[i];
break;
@ -1011,7 +1051,7 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
for (i = 0; i < 3; i++) {
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
GstSourceSelect *select = &group->selector[i];
if (select->selector) {
@ -1035,7 +1075,7 @@ perform_eos (GstPlayBin * playbin, GstSourceGroup * group)
GST_DEBUG_OBJECT (playbin, "doing EOS in group %p", group);
event = gst_event_new_eos ();
for (i = 0; i < 3; i++) {
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
GstSourceSelect *select = &group->selector[i];
if (select->selector) {
@ -1231,7 +1271,7 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
for (i = 0; i < 3; i++) {
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
GstSourceSelect *select = &group->selector[i];
if (!select->selector)

View file

@ -54,7 +54,10 @@ GST_STATIC_PAD_TEMPLATE ("src",
enum
{
PROP_ACTIVE_PAD = 1
PROP_0,
PROP_N_PADS,
PROP_ACTIVE_PAD,
PROP_LAST
};
static gboolean gst_stream_selector_is_active_sinkpad (GstStreamSelector * sel,
@ -422,14 +425,20 @@ gst_stream_selector_class_init (GstStreamSelectorClass * klass)
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = gst_stream_selector_dispose;
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_stream_selector_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_stream_selector_get_property);
g_object_class_install_property (gobject_class, PROP_N_PADS,
g_param_spec_int ("n-pads", "Number of Pads",
"The number of sink pads", 0, G_MAXINT, 0, G_PARAM_READABLE));
g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
g_param_spec_string ("active-pad", "Active pad",
"Name of the currently" " active sink pad", NULL, G_PARAM_READWRITE));
gobject_class->dispose = gst_stream_selector_dispose;
gstelement_class->request_new_pad = gst_stream_selector_request_new_pad;
gstelement_class->release_pad = gst_stream_selector_release_pad;
}
@ -445,7 +454,8 @@ gst_stream_selector_init (GstStreamSelector * sel)
gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
/* sinkpad management */
sel->active_sinkpad = NULL;
sel->nb_sinkpads = 0;
sel->padcount = 0;
sel->n_pads = 0;
gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
}
@ -511,6 +521,11 @@ gst_stream_selector_get_property (GObject * object, guint prop_id,
GstStreamSelector *sel = GST_STREAM_SELECTOR (object);
switch (prop_id) {
case PROP_N_PADS:
GST_OBJECT_LOCK (object);
g_value_set_int (value, sel->n_pads);
GST_OBJECT_UNLOCK (object);
break;
case PROP_ACTIVE_PAD:{
GST_OBJECT_LOCK (object);
if (sel->active_sinkpad != NULL) {
@ -635,9 +650,10 @@ gst_stream_selector_request_new_pad (GstElement * element,
sel = GST_STREAM_SELECTOR (element);
g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
GST_LOG_OBJECT (sel, "Creating new pad %d", sel->nb_sinkpads);
GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount);
GST_OBJECT_LOCK (sel);
name = g_strdup_printf ("sink%d", sel->nb_sinkpads++);
name = g_strdup_printf ("sink%d", sel->padcount++);
sel->n_pads++;
sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD,
"name", name, "direction", templ->direction, "template", templ, NULL);
g_free (name);
@ -673,6 +689,7 @@ gst_stream_selector_release_pad (GstElement * element, GstPad * pad)
GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad));
sel->active_sinkpad = NULL;
}
sel->n_pads--;
GST_OBJECT_UNLOCK (sel);
gst_pad_set_active (pad, FALSE);

View file

@ -44,8 +44,10 @@ struct _GstStreamSelector {
GstPad *srcpad;
guint padcount;
GstPad *active_sinkpad;
guint nb_sinkpads;
guint n_pads;
GstSegment segment;
};

View file

@ -86,6 +86,9 @@ static guint update_id = 0;
static guint seek_timeout_id = 0;
static gulong changed_id;
static GtkWidget *video_combo, *audio_combo, *text_combo;
static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
static GtkWidget *text_checkbox;
/* pipeline construction */
@ -1047,6 +1050,7 @@ static gboolean start_seek (GtkWidget * widget, GdkEventButton * event,
gpointer user_data);
static gboolean stop_seek (GtkWidget * widget, GdkEventButton * event,
gpointer user_data);
static void seek_cb (GtkWidget * widget);
static void
set_scale (gdouble value)
@ -1055,11 +1059,14 @@ set_scale (gdouble value)
(void *) pipeline);
g_signal_handlers_block_by_func (hscale, (void *) stop_seek,
(void *) pipeline);
g_signal_handlers_block_by_func (hscale, (void *) seek_cb, (void *) pipeline);
gtk_adjustment_set_value (adjustment, value);
g_signal_handlers_unblock_by_func (hscale, (void *) start_seek,
(void *) pipeline);
g_signal_handlers_unblock_by_func (hscale, (void *) stop_seek,
(void *) pipeline);
g_signal_handlers_unblock_by_func (hscale, (void *) seek_cb,
(void *) pipeline);
gtk_widget_queue_draw (hscale);
}
@ -1454,6 +1461,57 @@ rate_spinbutton_changed_cb (GtkSpinButton * button, GstPipeline * pipeline)
g_print ("seek failed\n");
}
static void
update_flag (GstPipeline * pipeline, gint num, gboolean state)
{
gint flags;
g_object_get (pipeline, "flags", &flags, NULL);
if (state)
flags |= (1 << num);
else
flags &= ~(1 << num);
g_object_set (pipeline, "flags", flags, NULL);
}
static void
vis_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
{
update_flag (pipeline, 3, gtk_toggle_button_get_active (button));
}
static void
audio_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
{
update_flag (pipeline, 1, gtk_toggle_button_get_active (button));
}
static void
video_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
{
update_flag (pipeline, 0, gtk_toggle_button_get_active (button));
}
static void
text_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
{
update_flag (pipeline, 2, gtk_toggle_button_get_active (button));
}
static void
update_streams (GstPipeline * pipeline)
{
gint n_video, n_audio, n_text;
/* here we get and update the different streams detected by playbin2 */
g_object_get (pipeline, "n-video", &n_video, NULL);
g_object_get (pipeline, "n-audio", &n_audio, NULL);
g_object_get (pipeline, "n-text", &n_text, NULL);
g_print ("video %d, audio %d, text %d\n", n_video, n_audio, n_text);
}
static void
message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
@ -1474,6 +1532,18 @@ message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
}
}
static void
msg_async_done (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
GST_DEBUG ("async done");
/* when we get ASYNC_DONE we can query position, duration and other
* properties */
update_scale (pipeline);
/* update the available streams */
update_streams (pipeline);
}
static void
msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
@ -1487,7 +1557,7 @@ msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
gst_message_parse_state_changed (message, &old, &new, &pending);
/* When state of the pipeline changes to playing we start updating scale */
/* When state of the pipeline changes to paused or playing we start updating scale */
if (new == GST_STATE_PLAYING) {
set_update_scale (TRUE);
} else {
@ -1542,7 +1612,7 @@ print_usage (int argc, char **argv)
int
main (int argc, char **argv)
{
GtkWidget *window, *hbox, *vbox, *flagtable;
GtkWidget *window, *hbox, *vbox, *panel, *boxes, *flagtable;
GtkWidget *play_button, *pause_button, *stop_button;
GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox, *flush_checkbox;
GtkWidget *scrub_checkbox, *play_scrub_checkbox, *rate_spinbutton;
@ -1655,6 +1725,40 @@ main (int argc, char **argv)
gtk_signal_connect (GTK_OBJECT (hscale),
"format_value", G_CALLBACK (format_value), pipeline);
if (pipeline_type == 16) {
/* the playbin2 panel controls for the video/audio/subtitle tracks */
panel = gtk_hbox_new (FALSE, 0);
boxes = gtk_hbox_new (FALSE, 0);
video_combo = gtk_combo_box_new_text ();
audio_combo = gtk_combo_box_new_text ();
text_combo = gtk_combo_box_new_text ();
gtk_box_pack_start (GTK_BOX (panel), video_combo, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (panel), audio_combo, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (panel), text_combo, TRUE, TRUE, 2);
vis_checkbox = gtk_check_button_new_with_label ("Vis");
video_checkbox = gtk_check_button_new_with_label ("Video");
audio_checkbox = gtk_check_button_new_with_label ("Audio");
text_checkbox = gtk_check_button_new_with_label ("Text");
gtk_box_pack_start (GTK_BOX (boxes), vis_checkbox, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (boxes), audio_checkbox, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (boxes), video_checkbox, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (boxes), text_checkbox, TRUE, TRUE, 2);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vis_checkbox), TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (audio_checkbox), TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (video_checkbox), TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_checkbox), TRUE);
g_signal_connect (G_OBJECT (vis_checkbox), "toggled",
G_CALLBACK (vis_toggle_cb), pipeline);
g_signal_connect (G_OBJECT (audio_checkbox), "toggled",
G_CALLBACK (audio_toggle_cb), pipeline);
g_signal_connect (G_OBJECT (video_checkbox), "toggled",
G_CALLBACK (video_toggle_cb), pipeline);
g_signal_connect (G_OBJECT (text_checkbox), "toggled",
G_CALLBACK (text_toggle_cb), pipeline);
} else {
panel = boxes = NULL;
}
/* do the packing stuff ... */
gtk_window_set_default_size (GTK_WINDOW (window), 250, 96);
gtk_container_add (GTK_CONTAINER (window), vbox);
@ -1674,6 +1778,10 @@ main (int argc, char **argv)
gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_label, 3, 4, 0, 1);
gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_spinbutton, 3, 4, 1,
2);
if (panel && boxes) {
gtk_box_pack_start (GTK_BOX (vbox), panel, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), boxes, TRUE, TRUE, 2);
}
gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);
/* connect things ... */
@ -1717,6 +1825,8 @@ main (int argc, char **argv)
(GCallback) msg_state_changed, pipeline);
g_signal_connect (bus, "message::segment-done",
(GCallback) msg_segment_done, pipeline);
g_signal_connect (bus, "message::async-done",
(GCallback) msg_async_done, pipeline);
g_signal_connect (bus, "message::new-clock", (GCallback) message_received,
pipeline);