mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
add framestepping to playbin2 and seek
This commit is contained in:
parent
d8e0b5a4da
commit
ea97973efe
2 changed files with 167 additions and 4 deletions
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue