Commit ea97973e authored by Wim Taymans's avatar Wim Taymans Committed by Wim Taymans
Browse files

add framestepping to playbin2 and seek

parent d8e0b5a4
......@@ -201,6 +201,8 @@ static gboolean gst_play_sink_send_event (GstElement * element,
static GstStateChangeReturn gst_play_sink_change_state (GstElement * element,
GstStateChange transition);
static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message);
/* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
static const GstElementDetails gst_play_sink_details =
......@@ -231,6 +233,9 @@ gst_play_sink_class_init (GstPlaySinkClass * klass)
GST_DEBUG_FUNCPTR (gst_play_sink_change_state);
gstelement_klass->send_event = GST_DEBUG_FUNCPTR (gst_play_sink_send_event);
gstbin_klass->handle_message =
GST_DEBUG_FUNCPTR (gst_play_sink_handle_message);
GST_DEBUG_CATEGORY_INIT (gst_play_sink_debug, "playsink", 0, "play bin");
}
......@@ -2299,6 +2304,51 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad)
}
}
static void
gst_play_sink_handle_message (GstBin * bin, GstMessage * message)
{
GstPlaySink *playsink;
playsink = GST_PLAY_SINK_CAST (bin);
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_STEP_DONE:
{
GstFormat format;
guint64 amount;
gdouble rate;
gboolean flush, intermediate, res;
guint64 duration;
GST_INFO_OBJECT (playsink, "Handling step-done message");
gst_message_parse_step_done (message, &format, &amount, &rate, &flush,
&intermediate, &duration);
if (format == GST_FORMAT_BUFFERS) {
/* for the buffer format, we align the other streams */
if (playsink->audiochain) {
GstEvent *event;
event =
gst_event_new_step (GST_FORMAT_TIME, duration, rate, flush,
intermediate);
if (!(res =
gst_element_send_event (playsink->audiochain->chain.bin,
event))) {
GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink");
}
}
}
GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message);
break;
}
default:
GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message);
break;
}
}
/* Send an event to our sinks until one of them works; don't then send to the
* remaining sinks (unlike GstBin)
*/
......@@ -2336,12 +2386,36 @@ gst_play_sink_send_event (GstElement * element, GstEvent * event)
{
gboolean res = FALSE;
GstEventType event_type = GST_EVENT_TYPE (event);
GstPlaySink *playsink;
playsink = GST_PLAY_SINK_CAST (element);
switch (event_type) {
case GST_EVENT_SEEK:
GST_DEBUG_OBJECT (element, "Sending seek event to a sink");
res = gst_play_sink_send_event_to_sink (GST_PLAY_SINK (element), event);
GST_DEBUG_OBJECT (element, "Sending event to a sink");
res = gst_play_sink_send_event_to_sink (playsink, event);
break;
case GST_EVENT_STEP:
{
GstFormat format;
guint64 amount;
gdouble rate;
gboolean flush, intermediate;
gst_event_parse_step (event, &format, &amount, &rate, &flush,
&intermediate);
if (format == GST_FORMAT_BUFFERS) {
/* for buffers, we will try to step video frames, for other formats we
* send the step to all sinks */
res = gst_play_sink_send_event_to_sink (playsink, event);
} else {
res =
GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
event);
}
break;
}
default:
res =
GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
......
......@@ -110,7 +110,10 @@ static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton;
static GtkWidget *skip_checkbox, *video_window;
GList *paths = NULL, *l = NULL;
static GtkWidget *format_combo, *step_amount_spinbutton, *step_rate_spinbutton;
static GtkWidget *step_flush_checkbox, *step_button;
static GList *paths = NULL, *l = NULL;
/* we keep an array of the visualisation entries so that we can easily switch
* with the combo box index. */
......@@ -1217,6 +1220,7 @@ update_scale (gpointer data)
}
query_rates ();
}
if (position >= duration)
duration = position;
......@@ -2007,6 +2011,43 @@ shot_cb (GtkButton * button, gpointer data)
}
}
/* called when the Step button is pressed */
static void
step_cb (GtkButton * button, gpointer data)
{
GstEvent *event;
GstFormat format;
guint64 amount;
gdouble rate;
gboolean flush, res;
gint active;
active = gtk_combo_box_get_active (GTK_COMBO_BOX (format_combo));
amount =
gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON
(step_amount_spinbutton));
rate = gtk_spin_button_get_value (GTK_SPIN_BUTTON (step_rate_spinbutton));
flush =
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (step_flush_checkbox));
switch (active) {
case 0:
format = GST_FORMAT_BUFFERS;
break;
case 1:
format = GST_FORMAT_TIME;
amount *= GST_MSECOND;
break;
default:
format = GST_FORMAT_UNDEFINED;
break;
}
event = gst_event_new_step (format, amount, rate, flush, FALSE);
res = send_event (event);
}
static void
message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
......@@ -2240,6 +2281,12 @@ msg_eos (GstBus * bus, GstMessage * message, GstPipeline * data)
}
}
static void
msg_step_done (GstBus * bus, GstMessage * message, GstPipeline * data)
{
message_received (bus, message, data);
}
static void
connect_bus_signals (GstElement * pipeline)
{
......@@ -2277,6 +2324,8 @@ connect_bus_signals (GstElement * pipeline)
pipeline);
g_signal_connect (bus, "message::buffering", (GCallback) msg_buffering,
pipeline);
g_signal_connect (bus, "message::step-done", (GCallback) msg_step_done,
pipeline);
gst_object_unref (bus);
}
......@@ -2339,7 +2388,7 @@ int
main (int argc, char **argv)
{
GtkWidget *window, *hbox, *vbox, *panel, *expander, *pb2vbox, *boxes,
*flagtable, *boxes2;
*flagtable, *boxes2, *step;
GtkWidget *play_button, *pause_button, *stop_button, *shot_button;
GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox, *flush_checkbox;
GtkWidget *scrub_checkbox, *play_scrub_checkbox, *rate_spinbutton;
......@@ -2458,6 +2507,45 @@ main (int argc, char **argv)
gtk_spin_button_set_value (GTK_SPIN_BUTTON (rate_spinbutton), rate);
/* step expander */
{
GtkWidget *hbox;
step = gtk_expander_new ("step options");
hbox = gtk_hbox_new (FALSE, 0);
format_combo = gtk_combo_box_new_text ();
gtk_combo_box_append_text (GTK_COMBO_BOX (format_combo), "frames");
gtk_combo_box_append_text (GTK_COMBO_BOX (format_combo), "time (ms)");
gtk_combo_box_set_active (GTK_COMBO_BOX (format_combo), 0);
gtk_box_pack_start (GTK_BOX (hbox), format_combo, FALSE, FALSE, 2);
step_amount_spinbutton = gtk_spin_button_new_with_range (1, 1000, 1);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_amount_spinbutton), 0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_amount_spinbutton), 1.0);
gtk_box_pack_start (GTK_BOX (hbox), step_amount_spinbutton, FALSE, FALSE,
2);
step_rate_spinbutton = gtk_spin_button_new_with_range (0.0, 100, 0.1);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_rate_spinbutton), 3);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_rate_spinbutton), 1.0);
gtk_box_pack_start (GTK_BOX (hbox), step_rate_spinbutton, FALSE, FALSE, 2);
step_flush_checkbox = gtk_check_button_new_with_label ("Flush");
gtk_box_pack_start (GTK_BOX (hbox), step_flush_checkbox, FALSE, FALSE, 2);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (step_flush_checkbox),
TRUE);
step_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_FORWARD);
gtk_button_set_label (GTK_BUTTON (step_button), "Step");
gtk_box_pack_start (GTK_BOX (hbox), step_button, FALSE, FALSE, 2);
g_signal_connect (G_OBJECT (step_button), "clicked", G_CALLBACK (step_cb),
pipeline);
gtk_container_add (GTK_CONTAINER (step), hbox);
}
/* seek bar */
adjustment =
GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0));
......@@ -2582,6 +2670,7 @@ main (int argc, char **argv)
gtk_container_add (GTK_CONTAINER (expander), pb2vbox);
gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 2);
}
gtk_box_pack_start (GTK_BOX (vbox), step, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hscale, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 2);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment