From 0ef2d627bebfef459815474f4d5c3a226b68b7f4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 29 Dec 2011 12:47:48 -0300 Subject: [PATCH 1/4] examples: camerabin2: add format selection for camerabin2 example Adds a combobox for selecting the video profile for recordings. Useful for testing multiple formats a/v sync when recording. --- tests/examples/camerabin2/Makefile.am | 1 + tests/examples/camerabin2/gst-camera2.c | 111 +++++++++++++++++++++++ tests/examples/camerabin2/gst-camera2.h | 3 + tests/examples/camerabin2/gst-camera2.ui | 86 +++++++++++++++--- 4 files changed, 187 insertions(+), 14 deletions(-) diff --git a/tests/examples/camerabin2/Makefile.am b/tests/examples/camerabin2/Makefile.am index 6b38bd2786..4431e94447 100644 --- a/tests/examples/camerabin2/Makefile.am +++ b/tests/examples/camerabin2/Makefile.am @@ -15,6 +15,7 @@ gst_camera2_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ $(GST_PLUGINS_BASE_LIBS) \ -lgstinterfaces-@GST_MAJORMINOR@ \ + -lgstpbutils-@GST_MAJORMINOR@ \ $(GST_LIBS) \ $(GTK_LIBS) \ $(GMODULE_EXPORT_LIBS) diff --git a/tests/examples/camerabin2/gst-camera2.c b/tests/examples/camerabin2/gst-camera2.c index bd612e7014..e57709487b 100644 --- a/tests/examples/camerabin2/gst-camera2.c +++ b/tests/examples/camerabin2/gst-camera2.c @@ -31,6 +31,9 @@ #include "gst-camera2.h" +#include + +#include #include #include #include @@ -42,6 +45,77 @@ static GstElement *camera; static GtkBuilder *builder; +typedef struct +{ + const gchar *name; + GstEncodingProfile *(*create_profile) (); +} GstCameraVideoFormat; + +static GstEncodingProfile * +create_ogg_profile (void) +{ + GstEncodingContainerProfile *container; + + container = gst_encoding_container_profile_new ("ogg", NULL, + gst_caps_new_simple ("application/ogg", NULL), NULL); + + gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) + gst_encoding_video_profile_new (gst_caps_new_simple ("video/theora", + NULL), NULL, NULL, 1)); + gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) + gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/vorbis", + NULL), NULL, NULL, 1)); + + return (GstEncodingProfile *) container; +} + +static GstEncodingProfile * +create_webm_profile (void) +{ + GstEncodingContainerProfile *container; + + container = gst_encoding_container_profile_new ("webm", NULL, + gst_caps_new_simple ("video/webm", NULL), NULL); + + gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) + gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-vp8", NULL), + NULL, NULL, 1)); + gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) + gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/vorbis", + NULL), NULL, NULL, 1)); + + return (GstEncodingProfile *) container; +} + +static GstEncodingProfile * +create_mp4_profile (void) +{ + GstEncodingContainerProfile *container; + + container = gst_encoding_container_profile_new ("mp4", NULL, + gst_caps_new_simple ("video/quicktime", "variant", G_TYPE_STRING, "iso", + NULL), NULL); + + gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) + gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-h264", + NULL), NULL, NULL, 1)); + gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) + gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/mpeg", + "version", G_TYPE_INT, 4, NULL), NULL, NULL, 1)); + + return (GstEncodingProfile *) container; +} + +GstCameraVideoFormat formats[] = { + {"ogg (theora/vorbis)", create_ogg_profile} + , + {"webm (vp8/vorbis)", create_webm_profile} + , + {"mp4 (h264+aac)", create_mp4_profile} + , + {NULL, NULL} +}; + void on_mainWindow_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data) { @@ -84,6 +158,23 @@ on_viewfinderArea_realize (GtkWidget * widget, gpointer data) #endif } +void +on_formatComboBox_changed (GtkWidget * widget, gpointer data) +{ + GstEncodingProfile *profile = NULL; + gint index = gtk_combo_box_get_active (GTK_COMBO_BOX (widget)); + + if (formats[index].create_profile) { + profile = formats[index].create_profile (); + } + + g_return_if_fail (profile != NULL); + gst_element_set_state (camera, GST_STATE_NULL); + g_object_set (camera, "video-profile", profile, NULL); + gst_element_set_state (camera, GST_STATE_PLAYING); + gst_encoding_profile_unref (profile); +} + static GstBusSyncReply bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data) { @@ -152,6 +243,24 @@ bus_callback (GstBus * bus, GstMessage * message, gpointer data) return TRUE; } +static void +init_gtkwidgets_data (void) +{ + gint i; + GtkComboBoxText *combobox = + GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "formatComboBox")); + + /* init formats combobox */ + i = 0; + while (formats[i].name) { + gtk_combo_box_text_append_text (combobox, formats[i].name); + i++; + } + + /* default to the first one -> ogg */ + gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), 0); +} + int main (int argc, char *argv[]) { @@ -176,6 +285,8 @@ main (int argc, char *argv[]) gst_bus_set_sync_handler (bus, bus_sync_callback, NULL); gst_object_unref (bus); + init_gtkwidgets_data (); + ui_main_window = GTK_WIDGET (gtk_builder_get_object (builder, "mainWindow")); gtk_builder_connect_signals (builder, NULL); gtk_widget_show_all (ui_main_window); diff --git a/tests/examples/camerabin2/gst-camera2.h b/tests/examples/camerabin2/gst-camera2.h index d96e2de63a..10bea027aa 100644 --- a/tests/examples/camerabin2/gst-camera2.h +++ b/tests/examples/camerabin2/gst-camera2.h @@ -45,4 +45,7 @@ on_videoRButton_toggled (GtkToggleButton * button, gpointer user_data); void on_viewfinderArea_realize (GtkWidget * widget, gpointer data); +void +on_formatComboBox_changed (GtkWidget * widget, gpointer data); + #endif /* __GST_CAMERA_BIN_H__ */ diff --git a/tests/examples/camerabin2/gst-camera2.ui b/tests/examples/camerabin2/gst-camera2.ui index 48fe1410ab..9dc1fee3d5 100644 --- a/tests/examples/camerabin2/gst-camera2.ui +++ b/tests/examples/camerabin2/gst-camera2.ui @@ -1,43 +1,53 @@ - + False 800 600 - + True + False True + False Image + False True True False + False True True - + + True + True 0 Video + False True True False + False True True imageRButton - + + True + True 1 @@ -51,39 +61,44 @@ True + False True - + False + + True + True 0 True + False - - Capture + True - True - True - + False + Actions False - False + True 0 - - Stop Capture + + Capture + False True True True - + False + False @@ -91,6 +106,47 @@ 1 + + + Stop Capture + False + True + True + True + False + + + + False + False + 2 + + + + + True + False + Video format + + + False + True + 5 + 3 + + + + + True + False + + + + False + True + 4 + + False @@ -100,6 +156,8 @@ + True + True 1 From b778d8a27ece2fb5065f71232313b9cf4e63debb Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 29 Dec 2011 13:30:13 -0300 Subject: [PATCH 2/4] examples: camerabin2: add some error handling for format changing Check that the format could be initialized and shows a modal dialog in case it couldn't. --- tests/examples/camerabin2/gst-camera2.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/examples/camerabin2/gst-camera2.c b/tests/examples/camerabin2/gst-camera2.c index e57709487b..13299eac57 100644 --- a/tests/examples/camerabin2/gst-camera2.c +++ b/tests/examples/camerabin2/gst-camera2.c @@ -44,6 +44,7 @@ static GstElement *camera; static GtkBuilder *builder; +static GtkWidget *ui_main_window; typedef struct { @@ -60,10 +61,10 @@ create_ogg_profile (void) gst_caps_new_simple ("application/ogg", NULL), NULL); gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) - gst_encoding_video_profile_new (gst_caps_new_simple ("video/theora", + gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-theora", NULL), NULL, NULL, 1)); gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) - gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/vorbis", + gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/x-vorbis", NULL), NULL, NULL, 1)); return (GstEncodingProfile *) container; @@ -81,7 +82,7 @@ create_webm_profile (void) gst_encoding_video_profile_new (gst_caps_new_simple ("video/x-vp8", NULL), NULL, NULL, 1)); gst_encoding_container_profile_add_profile (container, (GstEncodingProfile *) - gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/vorbis", + gst_encoding_audio_profile_new (gst_caps_new_simple ("audio/x-vorbis", NULL), NULL, NULL, 1)); return (GstEncodingProfile *) container; @@ -171,8 +172,21 @@ on_formatComboBox_changed (GtkWidget * widget, gpointer data) g_return_if_fail (profile != NULL); gst_element_set_state (camera, GST_STATE_NULL); g_object_set (camera, "video-profile", profile, NULL); - gst_element_set_state (camera, GST_STATE_PLAYING); gst_encoding_profile_unref (profile); + + if (GST_STATE_CHANGE_FAILURE == gst_element_set_state (camera, + GST_STATE_PLAYING)) { + GtkWidget *dialog = + gtk_message_dialog_new (GTK_WINDOW (ui_main_window), GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + "Could not initialize camerabin2 with the " + "selected format. Your system might not have the required plugins installed.\n" + "Please select another format."); + + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + } } static GstBusSyncReply @@ -265,7 +279,6 @@ int main (int argc, char *argv[]) { int ret = 0; - GtkWidget *ui_main_window; GError *error = NULL; GstBus *bus; From e4d3d2dcd115ce6b3744ab852adeed04d438ac04 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 30 Dec 2011 00:02:19 -0300 Subject: [PATCH 3/4] camerabin2: clarify some message logs Be explicit on which encodebin we're switching profiles on the log messages --- gst/camerabin2/gstcamerabin2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 073cb6f679..ff9f13423a 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -1679,7 +1679,7 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera) NULL); if (camera->video_profile_switch) { - GST_DEBUG_OBJECT (camera, "Switching encodebin's profile"); + GST_DEBUG_OBJECT (camera, "Switching video-encodebin's profile"); g_object_set (camera->video_encodebin, "profile", camera->video_profile, NULL); if (GST_PAD_LINK_FAILED (gst_camera_bin_link_encodebin (camera, @@ -1694,7 +1694,7 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera) } if (camera->image_profile_switch) { - GST_DEBUG_OBJECT (camera, "Switching encodebin's profile"); + GST_DEBUG_OBJECT (camera, "Switching image-encodebin's profile"); g_object_set (camera->image_encodebin, "profile", camera->image_profile, NULL); if (GST_PAD_LINK_FAILED (gst_camera_bin_link_encodebin (camera, From 51f399686eb172baf7b27b300b8b84869fdb85fa Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 30 Dec 2011 00:02:46 -0300 Subject: [PATCH 4/4] basevideocodec: Reset should reset current caps New caps will need to be negotiated when reset happens (PAUSED to READY). Without reseting the internal stored format, basevideoencoder/decoder wouldn't call the configuration function when the same caps was negotiated again as they would believe this was the same caps as before. The issue is that _stop has been called when going to READY and the elements would have reset their internal codec libs/state as well. A new configuration should be done. --- gst-libs/gst/video/gstbasevideocodec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst-libs/gst/video/gstbasevideocodec.c b/gst-libs/gst/video/gstbasevideocodec.c index a1dc91db46..9c130ed5e3 100644 --- a/gst-libs/gst/video/gstbasevideocodec.c +++ b/gst-libs/gst/video/gstbasevideocodec.c @@ -134,6 +134,8 @@ gst_base_video_codec_reset (GstBaseVideoCodec * base_video_codec) gst_buffer_replace (&base_video_codec->state.codec_data, NULL); gst_caps_replace (&base_video_codec->state.caps, NULL); + memset (&base_video_codec->state, 0, sizeof (GstVideoState)); + base_video_codec->state.format = GST_VIDEO_FORMAT_UNKNOWN; GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_codec); }