3 * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 * This is a demo application to test the camerabin element.
22 * If you have question don't hesitate in contact me edgard.lima@indt.org.br
32 #include "gst-camera2.h"
36 #include <gst/pbutils/encoding-profile.h>
38 #include <gst/interfaces/xoverlay.h>
41 #include <gdk/gdkkeysyms.h>
43 #define UI_FILE CAMERA_APPS_UIDIR G_DIR_SEPARATOR_S "gst-camera2.ui"
45 static GstElement *camera;
46 static GtkBuilder *builder;
47 static GtkWidget *ui_main_window;
52 GstEncodingProfile *(*create_profile) ();
53 } GstCameraVideoFormat;
55 static GstEncodingProfile *
56 create_ogg_profile (void)
58 GstEncodingContainerProfile *container;
60 container = gst_encoding_container_profile_new ("ogg", NULL,
61 gst_caps_new_simple ("application/ogg", NULL), NULL);
63 gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *)
64 gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-theora",
65 NULL), NULL, NULL, 1));
66 gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *)
67 gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/x-vorbis",
68 NULL), NULL, NULL, 1));
70 return (GstEncodingProfile *) container;
73 static GstEncodingProfile *
74 create_webm_profile (void)
76 GstEncodingContainerProfile *container;
78 container = gst_encoding_container_profile_new ("webm", NULL,
79 gst_caps_new_simple ("video/webm", NULL), NULL);
81 gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *)
82 gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-vp8", NULL),
84 gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *)
85 gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/x-vorbis",
86 NULL), NULL, NULL, 1));
88 return (GstEncodingProfile *) container;
91 static GstEncodingProfile *
92 create_mp4_profile (void)
94 GstEncodingContainerProfile *container;
96 container = gst_encoding_container_profile_new ("mp4", NULL,
97 gst_caps_new_simple ("video/quicktime", "variant", G_TYPE_STRING, "iso",
100 gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *)
101 gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-h264",
102 NULL), NULL, NULL, 1));
103 gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *)
104 gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/mpeg",
105 "version", G_TYPE_INT, 4, NULL), NULL, NULL, 1));
107 return (GstEncodingProfile *) container;
110 GstCameraVideoFormat formats[] = {
111 {"ogg (theora/vorbis)", create_ogg_profile}
113 {"webm (vp8/vorbis)", create_webm_profile}
115 {"mp4 (h264+aac)", create_mp4_profile}
121 on_mainWindow_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data)
127 on_captureButton_clicked (GtkButton * button, gpointer user_data)
129 g_signal_emit_by_name (camera, "start-capture", NULL);
133 on_stopCaptureButton_clicked (GtkButton * button, gpointer user_data)
135 g_signal_emit_by_name (camera, "stop-capture", NULL);
139 on_imageRButton_toggled (GtkToggleButton * button, gpointer user_data)
141 if (gtk_toggle_button_get_active (button)) {
142 g_object_set (camera, "mode", 1, NULL); /* Image mode */
147 on_videoRButton_toggled (GtkToggleButton * button, gpointer user_data)
149 if (gtk_toggle_button_get_active (button)) {
150 g_object_set (camera, "mode", 2, NULL); /* Video mode */
155 on_viewfinderArea_realize (GtkWidget * widget, gpointer data)
157 #if GTK_CHECK_VERSION (2, 18, 0)
158 gdk_window_ensure_native (gtk_widget_get_window (widget));
163 on_formatComboBox_changed (GtkWidget * widget, gpointer data)
165 GstEncodingProfile *profile = NULL;
166 gint index = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
168 if (formats[index].create_profile) {
169 profile = formats[index].create_profile ();
172 g_return_if_fail (profile != NULL);
173 gst_element_set_state (camera, GST_STATE_NULL);
174 g_object_set (camera, "video-profile", profile, NULL);
175 gst_encoding_profile_unref (profile);
177 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (camera,
178 GST_STATE_PLAYING)) {
180 gtk_message_dialog_new (GTK_WINDOW (ui_main_window), GTK_DIALOG_MODAL,
181 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
182 "Could not initialize camerabin2 with the "
183 "selected format. Your system might not have the required plugins installed.\n"
184 "Please select another format.");
186 gtk_dialog_run (GTK_DIALOG (dialog));
188 gtk_widget_destroy (dialog);
192 static GstBusSyncReply
193 bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
195 GtkWidget *ui_drawing;
197 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
200 if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
203 /* FIXME: make sure to get XID in main thread */
204 ui_drawing = GTK_WIDGET (gtk_builder_get_object (builder, "viewfinderArea"));
205 gst_x_overlay_set_window_handle (GST_X_OVERLAY (message->src),
206 #if GTK_CHECK_VERSION (2, 91, 6)
207 GDK_WINDOW_XID (gtk_widget_get_window (ui_drawing)));
209 GDK_WINDOW_XWINDOW (gtk_widget_get_window (ui_drawing)));
212 gst_message_unref (message);
218 bus_callback (GstBus * bus, GstMessage * message, gpointer data)
220 switch (GST_MESSAGE_TYPE (message)) {
221 case GST_MESSAGE_WARNING:{
225 gst_message_parse_warning (message, &err, &debug);
226 g_print ("Warning: %s\n", err->message);
231 case GST_MESSAGE_ERROR:{
235 gst_message_parse_error (message, &err, &debug);
236 g_print ("Error: %s : %s\n", err->message, debug);
243 case GST_MESSAGE_EOS:
248 case GST_MESSAGE_ELEMENT:
250 //handle_element_message (message);
254 /* unhandled message */
261 init_gtkwidgets_data (void)
263 #if GTK_CHECK_VERSION(2,24,0)
265 GtkComboBoxText *combobox =
266 GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "formatComboBox"));
268 /* init formats combobox */
270 while (formats[i].name) {
271 gtk_combo_box_text_append_text (combobox, formats[i].name);
275 /* default to the first one -> ogg */
276 gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0);
279 g_warning ("This needs a newer version of GTK (2.24 at least)");
285 main (int argc, char *argv[])
288 GError *error = NULL;
291 gst_init (&argc, &argv);
292 gtk_init (&argc, &argv);
294 builder = gtk_builder_new ();
295 if (!gtk_builder_add_from_file (builder, UI_FILE, &error)) {
296 g_warning ("Error: %s", error->message);
297 g_error_free (error);
301 camera = gst_element_factory_make ("camerabin2", "camera");
302 bus = gst_pipeline_get_bus (GST_PIPELINE (camera));
303 gst_bus_add_watch (bus, bus_callback, NULL);
304 gst_bus_set_sync_handler (bus, bus_sync_callback, NULL);
305 gst_object_unref (bus);
307 if (!init_gtkwidgets_data ()) {
311 ui_main_window = GTK_WIDGET (gtk_builder_get_object (builder, "mainWindow"));
312 gtk_builder_connect_signals (builder, NULL);
313 gtk_widget_show_all (ui_main_window);
315 gst_element_set_state (camera, GST_STATE_PLAYING);
320 gst_element_set_state (camera, GST_STATE_NULL);
321 gst_object_unref (camera);