diff options
author | Youness Alaoui <youness.alaoui@collabora.co.uk> | 2012-09-10 16:09:26 -0400 |
---|---|---|
committer | Olivier CrΓͺte <olivier.crete@collabora.com> | 2012-09-10 16:09:26 -0400 |
commit | 1ba24e1306dd1623bae3400e12e073c9f6fc8d51 (patch) | |
tree | fe2df82a40468ac40fe25a58fc7479a7e2e3a3d4 /tests/examples | |
parent | 1ef529601b0a9dfd9d278e37dbe141f21b9b8525 (diff) |
UVC H264 plugin
Diffstat (limited to 'tests/examples')
-rw-r--r-- | tests/examples/Makefile.am | 10 | ||||
-rw-r--r-- | tests/examples/uvch264/Makefile.am | 36 | ||||
-rw-r--r-- | tests/examples/uvch264/boolean_property.glade | 94 | ||||
-rw-r--r-- | tests/examples/uvch264/enum_property.glade | 88 | ||||
-rw-r--r-- | tests/examples/uvch264/enum_property_gtk2.glade | 88 | ||||
-rw-r--r-- | tests/examples/uvch264/int_property.glade | 147 | ||||
-rw-r--r-- | tests/examples/uvch264/test-uvch264.c | 673 | ||||
-rw-r--r-- | tests/examples/uvch264/window.glade | 345 |
8 files changed, 1479 insertions, 2 deletions
diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index eef73e6c9..d166a6605 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -1,5 +1,11 @@ +if USE_UVCH264 +UVCH264_DIR=uvch264 +else +UVCH264_DIR= +endif + if HAVE_GTK -GTK_EXAMPLES=mxf scaletempo camerabin2 +GTK_EXAMPLES=mxf scaletempo camerabin2 $(UVCH264_DIR) else GTK_EXAMPLES= endif @@ -13,6 +19,6 @@ endif OPENCV_EXAMPLES=opencv SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(OPENCV_EXAMPLES) -DIST_SUBDIRS= camerabin2 directfb mxf scaletempo opencv +DIST_SUBDIRS= camerabin2 directfb mxf scaletempo opencv uvch264 include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/tests/examples/uvch264/Makefile.am b/tests/examples/uvch264/Makefile.am new file mode 100644 index 000000000..e02b88821 --- /dev/null +++ b/tests/examples/uvch264/Makefile.am @@ -0,0 +1,36 @@ +TEST_UVCH264_GLADE_FILES = window.glade \ + boolean_property.glade \ + enum_property.glade \ + int_property.glade + +if HAVE_GTK + +TEST_UVCH264_EXAMPLES = test-uvch264 + +test_uvch264_SOURCES = test-uvch264.c +test_uvch264_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_VIDEO_CFLAGS) \ + $(GST_CFLAGS) \ + $(GTK_CFLAGS) \ + $(GMODULE_EXPORT_CFLAGS) \ + -DGST_USE_UNSTABLE_API +test_uvch264_LDADD = \ + $(GST_PLUGINS_BASE_LIBS) \ + $(GST_VIDEO_LIBS) \ + $(GST_LIBS) \ + -lgstinterfaces-@GST_MAJORMINOR@ \ + $(GTK_LIBS) \ + $(GMODULE_EXPORT_LIBS) + +noinst_DATA = $(TEST_UVCH264_GLADE_FILES) + +else +TEST_UVCH264_EXAMPLES = +endif + +noinst_PROGRAMS = $(TEST_UVCH264_EXAMPLES) + +EXTRA_DIST = $(TEST_UVCH264_GLADE_FILES) + diff --git a/tests/examples/uvch264/boolean_property.glade b/tests/examples/uvch264/boolean_property.glade new file mode 100644 index 000000000..d391a58c6 --- /dev/null +++ b/tests/examples/uvch264/boolean_property.glade @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkHBox" id="boolean-property"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="width_chars">18</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="value"> + <property name="label" translatable="yes"> Disabled </property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="toggled" handler="on_button_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="get"> + <property name="label" translatable="yes">Get</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_get_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="set"> + <property name="label" translatable="yes">Set</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_set_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label66"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Default</property> + <property name="width_chars">8</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkToggleButton" id="default"> + <property name="label" translatable="yes"> Disabled </property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="toggled" handler="on_button_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + </object> +</interface> diff --git a/tests/examples/uvch264/enum_property.glade b/tests/examples/uvch264/enum_property.glade new file mode 100644 index 000000000..0dfb9747f --- /dev/null +++ b/tests/examples/uvch264/enum_property.glade @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkHBox" id="enum-property"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="width_chars">18</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBoxText" id="value"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="get"> + <property name="label" translatable="yes">Get</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_get_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="set"> + <property name="label" translatable="yes">Set</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_set_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label72"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Default</property> + <property name="width_chars">8</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="default"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="invisible_char_set">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + </object> +</interface> diff --git a/tests/examples/uvch264/enum_property_gtk2.glade b/tests/examples/uvch264/enum_property_gtk2.glade new file mode 100644 index 000000000..487efbe5c --- /dev/null +++ b/tests/examples/uvch264/enum_property_gtk2.glade @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkHBox" id="enum-property"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="width_chars">18</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="value"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="get"> + <property name="label" translatable="yes">Get</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_get_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="set"> + <property name="label" translatable="yes">Set</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_set_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label72"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Default</property> + <property name="width_chars">8</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="default"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="invisible_char_set">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + </object> +</interface> diff --git a/tests/examples/uvch264/int_property.glade b/tests/examples/uvch264/int_property.glade new file mode 100644 index 000000000..422ce1cdc --- /dev/null +++ b/tests/examples/uvch264/int_property.glade @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkHBox" id="int-property"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="width_chars">18</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="value"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="width_chars">10</property> + <property name="invisible_char_set">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="get"> + <property name="label" translatable="yes">Get</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_get_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="set"> + <property name="label" translatable="yes">Set</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_set_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Minimum</property> + <property name="width_chars">8</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="minimum"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="width_chars">10</property> + <property name="invisible_char_set">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Default</property> + <property name="width_chars">8</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">6</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="default"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="width_chars">10</property> + <property name="invisible_char_set">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">7</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Maximum</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">8</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="maximum"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="width_chars">10</property> + <property name="invisible_char_set">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">9</property> + </packing> + </child> + </object> +</interface> diff --git a/tests/examples/uvch264/test-uvch264.c b/tests/examples/uvch264/test-uvch264.c new file mode 100644 index 000000000..78d8ac110 --- /dev/null +++ b/tests/examples/uvch264/test-uvch264.c @@ -0,0 +1,673 @@ +#include <gst/gst.h> +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <gst/interfaces/xoverlay.h> +#include <gst/video/video.h> + +#define WINDOW_GLADE "window.glade" +#define INT_PROPERTY_GLADE "int_property.glade" +#define ENUM_PROPERTY_GLADE "enum_property.glade" +#define BOOL_PROPERTY_GLADE "boolean_property.glade" + +#define PROPERTY_TO_VBOX \ + properties[i].dynamic ? GTK_BOX (dynamic_vbox) : GTK_BOX (static_vbox) + +#define GET_WIDGET(object, type, name) \ + type (gtk_builder_get_object ((object)->builder, name)) + +#define GET_PROP_WIDGET(type, name) GET_WIDGET (&(properties[i]), type, name) + +static guint h264_xid, preview_xid; + +typedef struct +{ + GtkBuilder *builder; + GstElement *src; + enum + { NONE, INT, ENUM, BOOL } type; + const gchar *property_name; + gboolean readonly; + gboolean dynamic; +} Prop; + +typedef struct +{ + GtkBuilder *builder; + GstElement *bin; + GstElement *src; + GstElement *identity; + GstElement *vid_capsfilter; + GstElement *vf_capsfilter; +} Main; + +Prop properties[] = { + {NULL, NULL, INT, "initial-bitrate", FALSE, FALSE}, + {NULL, NULL, INT, "slice-units", FALSE, FALSE}, + {NULL, NULL, ENUM, "slice-mode", FALSE, FALSE}, + {NULL, NULL, INT, "iframe-period", FALSE, FALSE}, + {NULL, NULL, ENUM, "usage-type", FALSE, FALSE}, + {NULL, NULL, ENUM, "entropy", FALSE, FALSE}, + {NULL, NULL, BOOL, "enable-sei", FALSE, FALSE}, + {NULL, NULL, INT, "num-reorder-frames", FALSE, FALSE}, + {NULL, NULL, BOOL, "preview-flipped", FALSE, FALSE}, + {NULL, NULL, INT, "leaky-bucket-size", FALSE, FALSE}, + {NULL, NULL, INT, "num-clock-samples", FALSE, TRUE}, + {NULL, NULL, ENUM, "rate-control", FALSE, TRUE}, + {NULL, NULL, BOOL, "fixed-framerate", FALSE, TRUE}, + {NULL, NULL, INT, "max-mbps", TRUE, TRUE}, + {NULL, NULL, INT, "level-idc", FALSE, TRUE}, + {NULL, NULL, INT, "peak-bitrate", FALSE, TRUE}, + {NULL, NULL, INT, "average-bitrate", FALSE, TRUE}, + {NULL, NULL, INT, "min-iframe-qp", FALSE, TRUE}, + {NULL, NULL, INT, "max-iframe-qp", FALSE, TRUE}, + {NULL, NULL, INT, "min-pframe-qp", FALSE, TRUE}, + {NULL, NULL, INT, "max-pframe-qp", FALSE, TRUE}, + {NULL, NULL, INT, "min-bframe-qp", FALSE, TRUE}, + {NULL, NULL, INT, "max-bframe-qp", FALSE, TRUE}, + {NULL, NULL, INT, "ltr-buffer-size", FALSE, TRUE}, + {NULL, NULL, INT, "ltr-encoder-control", FALSE, TRUE}, +}; + +static void set_drop_probability (Main * self); +static void get_all_properties (void); +static void probe_all_properties (gboolean playing); + +/* Callbacks */ +void on_button_toggled (GtkToggleButton * button, gpointer user_data); +void on_get_button_clicked (GtkButton * button, gpointer user_data); +void on_set_button_clicked (GtkButton * button, gpointer user_data); +void on_button_ready_clicked (GtkButton * button, gpointer user_data); +void on_button_null_clicked (GtkButton * button, gpointer user_data); +void on_button_playing_clicked (GtkButton * button, gpointer user_data); +void on_iframe_button_clicked (GtkButton * button, gpointer user_data); +void on_renegotiate_button_clicked (GtkButton * button, gpointer user_data); +void on_start_capture_button_clicked (GtkButton * button, gpointer user_data); +void on_stop_capture_button_clicked (GtkButton * button, gpointer user_data); +void on_window_destroyed (GtkWindow * window, gpointer user_data); + +static GstEvent * +new_upstream_force_key_unit (GstClockTime running_time, + gboolean all_headers, guint count) +{ + GstEvent *force_key_unit_event; + GstStructure *s; + + s = gst_structure_new ("GstForceKeyUnit", + "running-time", GST_TYPE_CLOCK_TIME, running_time, + "all-headers", G_TYPE_BOOLEAN, all_headers, + "count", G_TYPE_UINT, count, NULL); + force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s); + + return force_key_unit_event; +} + +void +on_get_button_clicked (GtkButton * button, gpointer user_data) +{ + Prop *property = user_data; + + switch (property->type) { + case INT: + { + gchar *val; + gint val_int; + g_object_get (property->src, property->property_name, &val_int, NULL); + val = g_strdup_printf ("%d", val_int); + gtk_entry_set_text (GET_WIDGET (property, GTK_ENTRY, "value"), val); + g_free (val); + } + break; + case ENUM: + { + GParamSpec *param; + gint val; + + g_object_get (property->src, property->property_name, &val, NULL); + param = g_object_class_find_property (G_OBJECT_GET_CLASS (property->src), + property->property_name); + if (G_IS_PARAM_SPEC_ENUM (param)) { + GEnumValue *values; + guint i = 0; + + values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values; + + while (values[i].value_name) { + if (values[i].value == val) { + gtk_combo_box_set_active (GET_WIDGET (property, + (GtkComboBox *), "value"), i); + break; + } + i++; + } + } + } + break; + case BOOL: + { + gboolean val; + + g_object_get (property->src, property->property_name, &val, NULL); + gtk_toggle_button_set_active (GET_WIDGET (property, + (GtkToggleButton *), "value"), val); + } + break; + case NONE: + default: + break; + } +} + +void +on_set_button_clicked (GtkButton * button, gpointer user_data) +{ + Prop *property = user_data; + + switch (property->type) { + case INT: + { + int val_int; + const gchar *val; + + val = gtk_entry_get_text (GET_WIDGET (property, GTK_ENTRY, "value")); + val_int = (int) g_ascii_strtoll (val, NULL, 0); + g_object_set (property->src, property->property_name, val_int, NULL); + } + break; + case ENUM: + { + GParamSpec *param; + + param = g_object_class_find_property (G_OBJECT_GET_CLASS (property->src), + property->property_name); + if (G_IS_PARAM_SPEC_ENUM (param)) { + GEnumValue *values; + guint val = 0; + + values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values; + + val = gtk_combo_box_get_active (GET_WIDGET (property, + (GtkComboBox *), "value")); + g_object_set (property->src, property->property_name, + values[val].value, NULL); + } + } + break; + case BOOL: + { + gboolean val; + + val = gtk_toggle_button_get_active (GET_WIDGET (property, + (GtkToggleButton *), "value")); + g_object_set (property->src, property->property_name, val, NULL); + } + break; + case NONE: + default: + break; + } + get_all_properties (); +} + +void +on_button_toggled (GtkToggleButton * button, gpointer user_data) +{ + if (gtk_toggle_button_get_active (button)) + gtk_button_set_label (GTK_BUTTON (button), " Enabled "); + else + gtk_button_set_label (GTK_BUTTON (button), " Disabled "); +} + +static gboolean +set_caps (Main * self, gboolean send_event) +{ + const gchar *h264_filter; + const gchar *raw_filter; + GstCaps *h264_caps = NULL; + GstCaps *raw_caps = NULL; + gboolean ret = TRUE; + + h264_filter = gtk_entry_get_text (GET_WIDGET (self, GTK_ENTRY, "h264_caps")); + raw_filter = + gtk_entry_get_text (GET_WIDGET (self, GTK_ENTRY, "preview_caps")); + if (h264_filter) + h264_caps = gst_caps_from_string (h264_filter); + if (raw_filter) + raw_caps = gst_caps_from_string (raw_filter); + + g_debug ("H264 caps : %s", gst_caps_to_string (h264_caps)); + g_debug ("Preview caps : %s", gst_caps_to_string (raw_caps)); + if (!h264_caps || !raw_caps) { + g_debug ("Invalid caps"); + ret = FALSE; + goto end; + } + + g_object_set (self->vid_capsfilter, "caps", h264_caps, NULL); + g_object_set (self->vf_capsfilter, "caps", raw_caps, NULL); + + if (send_event) { + gst_element_send_event (GST_ELEMENT (self->src), + gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, + gst_structure_new ("renegotiate", NULL))); + } + +end: + if (h264_caps) + gst_caps_unref (h264_caps); + if (raw_caps) + gst_caps_unref (raw_caps); + + return ret; +} + +void +on_button_ready_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + + set_caps (self, FALSE); + gst_element_set_state (self->bin, GST_STATE_READY); + probe_all_properties (FALSE); + get_all_properties (); +} + +void +on_button_null_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + + gst_element_set_state (self->bin, GST_STATE_NULL); + probe_all_properties (FALSE); + get_all_properties (); +} + +void +on_button_playing_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + + if (gst_element_set_state (self->bin, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + g_debug ("Unable to go to state PLAYING"); + } + set_caps (self, FALSE); + probe_all_properties (TRUE); + get_all_properties (); + + set_drop_probability (self); +} + +void +on_iframe_button_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + GstEvent *event; + gboolean pps_sps; + + set_drop_probability (self); + pps_sps = gtk_toggle_button_get_active (GET_WIDGET (self, (GtkToggleButton *), + "pps_sps")); + + event = new_upstream_force_key_unit (GST_CLOCK_TIME_NONE, pps_sps, 0); + gst_element_send_event (GST_ELEMENT (self->src), event); +} + +void +on_renegotiate_button_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + + set_caps (self, TRUE); + probe_all_properties (GST_STATE (self->bin) >= GST_STATE_PAUSED); + get_all_properties (); +} + +void +on_start_capture_button_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + + set_caps (self, FALSE); + g_signal_emit_by_name (G_OBJECT (self->src), "start-capture", NULL); + probe_all_properties (GST_STATE (self->bin) >= GST_STATE_PAUSED); + get_all_properties (); +} + +void +on_stop_capture_button_clicked (GtkButton * button, gpointer user_data) +{ + Main *self = user_data; + + set_caps (self, FALSE); + g_signal_emit_by_name (G_OBJECT (self->src), "stop-capture", NULL); + probe_all_properties (GST_STATE (self->bin) >= GST_STATE_PAUSED); + get_all_properties (); +} + +void +on_window_destroyed (GtkWindow * window, gpointer user_data) +{ + gtk_main_quit (); +} + +static gboolean +_bus_callback (GstBus * bus, GstMessage * message, gpointer user_data) +{ + const GstStructure *s = gst_message_get_structure (message); + GstObject *source = NULL; + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT && + gst_structure_has_name (s, "prepare-xwindow-id")) { + source = GST_MESSAGE_SRC (message); + if (!g_strcmp0 (gst_object_get_name (source), "h264_sink")) + gst_x_overlay_set_window_handle (GST_X_OVERLAY (source), h264_xid); + else + gst_x_overlay_set_window_handle (GST_X_OVERLAY (source), preview_xid); + } + + return TRUE; +} + +static void +set_drop_probability (Main * self) +{ + const gchar *drop; + gdouble drop_probability = 0.0; + + drop = gtk_entry_get_text (GET_WIDGET (self, GTK_ENTRY, "drop")); + drop_probability = g_ascii_strtod (drop, NULL); + g_debug ("Setting drop probability to : %f", drop_probability); + g_object_set (self->identity, "drop-probability", drop_probability, NULL); +} + +static void +get_all_properties (void) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (properties); i++) + on_get_button_clicked (NULL, &properties[i]); + +} + +static void +probe_all_properties (gboolean playing) +{ + int i; + + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + gboolean return_value, changeable, default_bool; + guint mask, minimum, maximum, default_int; + GParamSpec *param; + + /* When playing, ignore static controls */ + if (playing && !properties[i].dynamic) + continue; + + switch (properties[i].type) { + case INT: + g_signal_emit_by_name (G_OBJECT (properties[i].src), "get-int-setting", + properties[i].property_name, &minimum, &default_int, &maximum, + &return_value, NULL); + if (return_value) { + gchar *min, *def, *max; + + min = g_strdup_printf ("%d", minimum); + def = g_strdup_printf ("%d", default_int); + max = g_strdup_printf ("%d", maximum); + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "minimum"), min); + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "default"), def); + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "maximum"), max); + g_free (min); + g_free (def); + g_free (max); + } else { + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "minimum"), ""); + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "default"), ""); + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "maximum"), ""); + } + break; + case ENUM: + g_signal_emit_by_name (G_OBJECT (properties[i].src), "get-enum-setting", + properties[i].property_name, &mask, &default_int, &return_value, + NULL); + param = + g_object_class_find_property (G_OBJECT_GET_CLASS (properties + [i].src), properties[i].property_name); + if (G_IS_PARAM_SPEC_ENUM (param)) { + GEnumValue *values; + guint j = 0; + + values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values; + + if (return_value) { + while (values[j].value_name) { + if (values[j].value == default_int) { + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "default"), + values[j].value_name); + break; + } + j++; + } + } else { + gtk_entry_set_text (GET_PROP_WIDGET (GTK_ENTRY, "default"), ""); + } + + j = 0; + while (values[j].value_name) { +#if !GTK_CHECK_VERSION (2, 24, 0) + gtk_combo_box_remove_text (GET_PROP_WIDGET ((GtkComboBox *), + "value"), 0); +#else + gtk_combo_box_text_remove (GET_PROP_WIDGET ((GtkComboBoxText *), + "value"), 0); +#endif + j++; + } + + j = 0; + while (values[j].value_name) { + gchar *val; + if (return_value && (mask & (1 << values[j].value)) != 0) + val = g_strdup_printf ("**%s**", values[j].value_name); + else + val = g_strdup (values[j].value_name); + +#if !GTK_CHECK_VERSION (2, 24, 0) + gtk_combo_box_append_text (GET_PROP_WIDGET ((GtkComboBox *), + "value"), val); +#else + gtk_combo_box_text_append_text (GET_PROP_WIDGET ((GtkComboBoxText + *), "value"), val); +#endif + g_free (val); + j++; + } + } + break; + case BOOL: + g_signal_emit_by_name (G_OBJECT (properties[i].src), + "get-boolean-setting", properties[i].property_name, + &changeable, &default_bool, &return_value, NULL); + if (return_value) { + gtk_widget_set_sensitive (GET_PROP_WIDGET (GTK_WIDGET, "value"), + changeable); + gtk_widget_set_sensitive (GET_PROP_WIDGET (GTK_WIDGET, "get"), + changeable); + gtk_widget_set_sensitive (GET_PROP_WIDGET (GTK_WIDGET, "set"), + changeable); + gtk_toggle_button_set_active (GET_PROP_WIDGET ((GtkToggleButton *), + "default"), default_bool); + } + break; + case NONE: + default: + break; + } + } +} + +int +main (int argc, char *argv[]) +{ + Main self = { NULL, NULL, NULL, NULL }; + GstBus *bus = NULL; + GtkWidget *window, *static_vbox, *dynamic_vbox, *da; + gchar *drop; + gdouble drop_probability; + GdkWindow *gdk_win = NULL; + const char *device = "/dev/video0"; + GError *error = NULL; + int i; + + gtk_init (&argc, &argv); + gst_init (&argc, &argv); + + if (argc > 1) + device = argv[1]; + else + g_print ("Usage : %s [device]\nUsing default device : %s\n", + argv[0], device); + + + self.bin = gst_parse_launch ("uvch264_src name=src src.vidsrc ! queue ! " + "capsfilter name=vid_cf ! identity name=identity ! ffdec_h264 ! " + "xvimagesink name=h264_sink async=false " + "src.vfsrc ! queue ! capsfilter name=vf_cf ! " + "xvimagesink name=preview_sink async=false", NULL); + + if (!self.bin) + return -1; + + /* Listen to the bus for messages */ + bus = gst_element_get_bus (self.bin); + gst_bus_add_watch (bus, _bus_callback, self.bin); + gst_object_unref (bus); + + self.src = gst_bin_get_by_name (GST_BIN (self.bin), "src"); + self.identity = gst_bin_get_by_name (GST_BIN (self.bin), "identity"); + self.vid_capsfilter = gst_bin_get_by_name (GST_BIN (self.bin), "vid_cf"); + self.vf_capsfilter = gst_bin_get_by_name (GST_BIN (self.bin), "vf_cf"); + + self.builder = gtk_builder_new (); + gtk_builder_add_from_file (self.builder, WINDOW_GLADE, &error); + if (error) { + g_debug ("Unable to load glade file : %s", error->message); + goto end; + } + gtk_builder_connect_signals (self.builder, &self); + + g_object_get (self.identity, "drop-probability", &drop_probability, NULL); + drop = g_strdup_printf ("%f", drop_probability); + gtk_entry_set_text (GET_WIDGET (&self, GTK_ENTRY, "drop"), drop); + g_free (drop); + window = GET_WIDGET (&self, GTK_WIDGET, "window"); + static_vbox = GET_WIDGET (&self, GTK_WIDGET, "static"); + dynamic_vbox = GET_WIDGET (&self, GTK_WIDGET, "dynamic"); + da = GET_WIDGET (&self, GTK_WIDGET, "h264"); + gtk_widget_realize (da); + gdk_win = gtk_widget_get_window (da); + h264_xid = GDK_WINDOW_XID (gdk_win); + da = GET_WIDGET (&self, GTK_WIDGET, "preview"); + gtk_widget_realize (da); + gdk_win = gtk_widget_get_window (da); + preview_xid = GDK_WINDOW_XID (gdk_win); + + set_caps (&self, FALSE); + + g_object_set (self.src, "device", device, NULL); + if (gst_element_set_state (self.bin, GST_STATE_READY) == + GST_STATE_CHANGE_FAILURE) { + g_debug ("Unable to go to state READY"); + goto end; + } + + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + switch (properties[i].type) { + case INT: + properties[i].src = self.src; + properties[i].builder = gtk_builder_new (); + gtk_builder_add_from_file (properties[i].builder, INT_PROPERTY_GLADE, + NULL); + gtk_builder_connect_signals (properties[i].builder, &properties[i]); + gtk_box_pack_start (PROPERTY_TO_VBOX, + GET_PROP_WIDGET (GTK_WIDGET, "int-property"), TRUE, TRUE, 2); + gtk_label_set_label (GET_PROP_WIDGET (GTK_LABEL, "label"), + properties[i].property_name); + if (properties[i].readonly) + gtk_widget_set_sensitive (GET_PROP_WIDGET (GTK_WIDGET, "set"), FALSE); + break; + case ENUM: + properties[i].src = self.src; + properties[i].builder = gtk_builder_new (); +#if !GTK_CHECK_VERSION (2, 24, 0) + gtk_builder_add_from_file (properties[i].builder, + "enum_property_gtk2.glade", NULL); +#else + gtk_builder_add_from_file (properties[i].builder, ENUM_PROPERTY_GLADE, + NULL); +#endif + gtk_builder_connect_signals (properties[i].builder, &properties[i]); + gtk_box_pack_start (PROPERTY_TO_VBOX, + GET_PROP_WIDGET (GTK_WIDGET, "enum-property"), TRUE, TRUE, 2); + gtk_label_set_label (GET_PROP_WIDGET (GTK_LABEL, "label"), + properties[i].property_name); +#if !GTK_CHECK_VERSION (2, 24, 0) + { + GtkComboBox *combo_box; + GtkCellRenderer *cell; + GtkListStore *store; + + combo_box = GET_PROP_WIDGET ((GtkComboBox *), "value"); + store = gtk_list_store_new (1, G_TYPE_STRING); + gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (store)); + g_object_unref (store); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell, + "text", 0, NULL); + } +#endif + if (properties[i].readonly) + gtk_widget_set_sensitive (GET_PROP_WIDGET (GTK_WIDGET, "set"), FALSE); + break; + case BOOL: + properties[i].src = self.src; + properties[i].builder = gtk_builder_new (); + gtk_builder_add_from_file (properties[i].builder, BOOL_PROPERTY_GLADE, + NULL); + gtk_builder_connect_signals (properties[i].builder, &properties[i]); + gtk_box_pack_start (PROPERTY_TO_VBOX, + GET_PROP_WIDGET (GTK_WIDGET, "boolean-property"), TRUE, TRUE, 2); + gtk_label_set_label (GET_PROP_WIDGET (GTK_LABEL, "label"), + properties[i].property_name); + if (properties[i].readonly) + gtk_widget_set_sensitive (GET_PROP_WIDGET (GTK_WIDGET, "set"), FALSE); + break; + case NONE: + default: + break; + } + } + probe_all_properties (FALSE); + get_all_properties (); + + gtk_widget_show (window); + gtk_main (); + +end: + g_object_unref (G_OBJECT (self.builder)); + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + if (properties[i].builder) + g_object_unref (G_OBJECT (properties[i].builder)); + } + gst_element_set_state (self.bin, GST_STATE_NULL); + gst_object_unref (self.src); + gst_object_unref (self.identity); + gst_object_unref (self.vid_capsfilter); + gst_object_unref (self.vf_capsfilter); + gst_object_unref (self.bin); + + return 0; +} diff --git a/tests/examples/uvch264/window.glade b/tests/examples/uvch264/window.glade new file mode 100644 index 000000000..8b7624a9f --- /dev/null +++ b/tests/examples/uvch264/window.glade @@ -0,0 +1,345 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkWindow" id="window"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">Test for uvch264_src</property> + <signal name="destroy" handler="on_window_destroyed" swapped="no"/> + <child> + <object class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkVBox" id="vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkHBox" id="box26"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="homogeneous">True</property> + <child> + <object class="GtkButton" id="button2"> + <property name="label" translatable="yes">State NULL</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_button_null_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button51"> + <property name="label" translatable="yes">State READY</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_button_ready_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button52"> + <property name="label" translatable="yes">State PLAYING</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_button_playing_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button3"> + <property name="label" translatable="yes">Start capture</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_start_capture_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button4"> + <property name="label" translatable="yes">Stop capture</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_stop_capture_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button5"> + <property name="label" translatable="yes">Renegotiate</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_renegotiate_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Static controls</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="static"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Dynamic controls</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="dynamic"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="box1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Drop probability % (between 0.0 and 1.0)</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="drop"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="pps_sps"> + <property name="label" translatable="yes">With SPS/PPS</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button1"> + <property name="label" translatable="yes">Request keyframe</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <signal name="clicked" handler="on_iframe_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="box2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">H264</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="h264_caps"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="text" translatable="yes">video/x-h264,width=640,height=480,profile=constrained-baseline,stream-format=bytestream,framerate=15/1</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkDrawingArea" id="h264"> + <property name="width_request">320</property> + <property name="height_request">240</property> + <property name="visible">True</property> + <property name="app_paintable">True</property> + <property name="can_focus">False</property> + <property name="double_buffered">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Preview</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="preview_caps"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">β</property> + <property name="text" translatable="yes">video/x-raw-yuv,width=320,height=240,format=(fourcc)YUY2,framerate=15/1</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkDrawingArea" id="preview"> + <property name="width_request">320</property> + <property name="height_request">240</property> + <property name="visible">True</property> + <property name="app_paintable">True</property> + <property name="can_focus">False</property> + <property name="double_buffered">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface> |