[longomatch/livecapture2: 1/31] Rework on the camera capturer: merged camerabin API changes, embeded video widget and fixed indentat
- From: Andoni Morales Alastruey <amorales src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [longomatch/livecapture2: 1/31] Rework on the camera capturer: merged camerabin API changes, embeded video widget and fixed indentat
- Date: Mon, 3 May 2010 22:38:53 +0000 (UTC)
commit 9ec8adb00b8e033587158a5873fb3a28b5abaf39
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date: Mon Mar 29 00:10:21 2010 +0200
Rework on the camera capturer: merged camerabin API changes, embeded video
widget and fixed indentation
CesarPlayer/Capturer/GstCameraCapturer.cs | 48 +-
libcesarplayer/src/gst-camera-capturer.c | 1138 +++++++++++++++++++----------
libcesarplayer/src/gst-camera-capturer.h | 48 +-
3 files changed, 806 insertions(+), 428 deletions(-)
---
diff --git a/CesarPlayer/Capturer/GstCameraCapturer.cs b/CesarPlayer/Capturer/GstCameraCapturer.cs
index 7b4d9ac..206159a 100644
--- a/CesarPlayer/Capturer/GstCameraCapturer.cs
+++ b/CesarPlayer/Capturer/GstCameraCapturer.cs
@@ -237,25 +237,6 @@ namespace LongoMatch.Video.Capturer {
}
[DllImport("libcesarplayer.dll")]
- static extern bool gst_camera_capturer_set_video_muxer(IntPtr raw, int type);
-
- public bool SetVideoMuxer(LongoMatch.Video.Capturer.GccVideoMuxerType type) {
- bool raw_ret = gst_camera_capturer_set_video_muxer(Handle, (int) type);
- bool ret = raw_ret;
- return ret;
- }
-
-
- [DllImport("libcesarplayer.dll")]
- static extern bool gst_camera_capturer_set_video_encoder(IntPtr raw, int type);
-
- public bool SetVideoEncoder(LongoMatch.Video.Capturer.GccVideoEncoderType type) {
- bool raw_ret = gst_camera_capturer_set_video_encoder(Handle, (int) type);
- bool ret = raw_ret;
- return ret;
- }
-
- [DllImport("libcesarplayer.dll")]
static extern void gst_camera_capturer_init_backend(out int argc, IntPtr argv);
public static int InitBackend(string argv) {
@@ -293,12 +274,37 @@ namespace LongoMatch.Video.Capturer {
public void Run() {
gst_camera_capturer_run(Handle);
}
+
+ [DllImport("libcesarplayer.dll")]
+ static extern bool gst_camera_capturer_set_video_muxer(IntPtr raw, int type, out IntPtr error);
+ public bool SetVideoMuxer(LongoMatch.Video.Capturer.GccVideoMuxerType type) {
+ IntPtr error = IntPtr.Zero;
+ bool raw_ret = gst_camera_capturer_set_video_muxer(Handle, (int) type, out error);
+ if (error != IntPtr.Zero) throw new GLib.GException (error);
+ bool ret = raw_ret;
+ return ret;
+ }
+
+
[DllImport("libcesarplayer.dll")]
- static extern bool gst_camera_capturer_set_audio_encoder(IntPtr raw, int type);
+ static extern bool gst_camera_capturer_set_video_encoder(IntPtr raw, int type, out IntPtr error);
+
+ public bool SetVideoEncoder(LongoMatch.Video.Capturer.GccVideoEncoderType type) {
+ IntPtr error = IntPtr.Zero;
+ bool raw_ret = gst_camera_capturer_set_video_encoder(Handle, (int) type, out error);
+ if (error != IntPtr.Zero) throw new GLib.GException (error);
+ bool ret = raw_ret;
+ return ret;
+ }
+
+ [DllImport("libcesarplayer.dll")]
+ static extern bool gst_camera_capturer_set_audio_encoder(IntPtr raw, int type, out IntPtr error);
public bool SetAudioEncoder(LongoMatch.Video.Capturer.GccAudioEncoderType type) {
- bool raw_ret = gst_camera_capturer_set_audio_encoder(Handle, (int) type);
+ IntPtr error = IntPtr.Zero;
+ bool raw_ret = gst_camera_capturer_set_audio_encoder(Handle, (int) type, out error);
+ if (error != IntPtr.Zero) throw new GLib.GException (error);
bool ret = raw_ret;
return ret;
}
diff --git a/libcesarplayer/src/gst-camera-capturer.c b/libcesarplayer/src/gst-camera-capturer.c
index b78d9f9..9f8590c 100644
--- a/libcesarplayer/src/gst-camera-capturer.c
+++ b/libcesarplayer/src/gst-camera-capturer.c
@@ -17,15 +17,16 @@
*
* You should have received a copy of the GNU General Public License
* along with foob. If not, write to:
-* The Free Software Foundation, Inc.,
-* 51 Franklin Street, Fifth Floor
-* Boston, MA 02110-1301, USA.
+* The Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor
+* Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <stdio.h>
#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/propertyprobe.h>
#include <gst/gst.h>
#include <gst/video/video.h>
@@ -35,9 +36,11 @@
/*Default video source*/
#ifdef WIN32
-#define VIDEOSRC "ksvideosrc"
+#define VIDEOSRC "dshowvideosrc"
+#define AUDIOSRC "dshowaudiosrc"
#else
-#define VIDEOSRC "v4l2src"
+#define VIDEOSRC "gconfvideosrc"
+#define AUDIOSRC "gconfaudiosrc"
#endif
/* gtk+/gnome */
@@ -61,8 +64,8 @@ enum
enum
{
PROP_0,
- PROP_ENCODE_HEIGHT,
- PROP_ENCODE_WIDTH,
+ PROP_OUTPUT_HEIGHT,
+ PROP_OUTPUT_WIDTH,
PROP_VIDEO_BITRATE,
PROP_AUDIO_BITRATE,
PROP_OUTPUT_FILE,
@@ -74,19 +77,21 @@ struct GstCameraCapturerPrivate
/*Encoding properties */
gchar *output_file;
- guint encode_height;
- guint encode_width;
+ guint output_height;
+ guint output_width;
+ guint output_fps_n;
+ guint output_fps_d;
guint audio_bitrate;
guint video_bitrate;
GccVideoEncoderType video_encoder_type;
GccAudioEncoderType audio_encoder_type;
/*Video input info */
- gint video_width; /* Movie width */
- gint video_height; /* Movie height */
- const GValue *movie_par; /* Movie pixel aspect ratio */
- gint video_width_pixels; /* Scaled movie width */
- gint video_height_pixels; /* Scaled movie height */
+ gint video_width; /* Movie width */
+ gint video_height; /* Movie height */
+ const GValue *movie_par; /* Movie pixel aspect ratio */
+ gint video_width_pixels; /* Scaled movie width */
+ gint video_height_pixels; /* Scaled movie height */
gint video_fps_n;
gint video_fps_d;
gboolean media_has_video;
@@ -103,13 +108,15 @@ struct GstCameraCapturerPrivate
GstElement *videomux;
/*Overlay */
- GstXOverlay *xoverlay; /* protect with lock */
+ GstXOverlay *xoverlay; /* protect with lock */
+ guint interface_update_id; /* protect with lock */
GMutex *lock;
/*Videobox */
- GtkWidget *video_window;
+ GdkWindow *video_window;
gboolean logo_mode;
GdkPixbuf *logo_pixbuf;
+ float zoom;
/*GStreamer bus */
GstBus *bus;
@@ -117,28 +124,26 @@ struct GstCameraCapturerPrivate
gulong sig_bus_sync;
};
+static GtkWidgetClass *parent_class = NULL;
+
+static GThread *gui_thread;
+
static int gcc_signals[LAST_SIGNAL] = { 0 };
static void gcc_error_msg (GstCameraCapturer * gcc, GstMessage * msg);
static void gcc_bus_message_cb (GstBus * bus, GstMessage * message,
- gpointer data);
+ gpointer data);
static void gst_camera_capturer_get_property (GObject * object,
- guint property_id,
- GValue * value,
- GParamSpec * pspec);
+ guint property_id, GValue * value, GParamSpec * pspec);
static void gst_camera_capturer_set_property (GObject * object,
- guint property_id,
- const GValue * value,
- GParamSpec * pspec);
+ guint property_id, const GValue * value, GParamSpec * pspec);
static void gcc_element_msg_sync (GstBus * bus, GstMessage * msg,
- gpointer data);
+ gpointer data);
static void gcc_update_interface_implementations (GstCameraCapturer * gcc);
static int gcc_parse_video_stream_info (GstCaps * caps,
- GstCameraCapturer * gcc);
-
-G_DEFINE_TYPE (GstCameraCapturer, gst_camera_capturer, GTK_TYPE_HBOX);
-
+ GstCameraCapturer * gcc);
+G_DEFINE_TYPE (GstCameraCapturer, gst_camera_capturer, GTK_TYPE_EVENT_BOX);
static void
@@ -146,8 +151,20 @@ gst_camera_capturer_init (GstCameraCapturer * object)
{
GstCameraCapturerPrivate *priv;
object->priv = priv =
- G_TYPE_INSTANCE_GET_PRIVATE (object, GST_TYPE_CAMERA_CAPTURER,
- GstCameraCapturerPrivate);
+ G_TYPE_INSTANCE_GET_PRIVATE (object, GST_TYPE_CAMERA_CAPTURER,
+ GstCameraCapturerPrivate);
+
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (object), GTK_CAN_FOCUS);
+ GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (object), GTK_DOUBLE_BUFFERED);
+
+ priv->zoom = 1.0;
+ priv->output_height = 576;
+ priv->output_width = 720;
+ priv->output_fps_n = 25;
+ priv->output_fps_d = 1;
+ priv->audio_bitrate = 128;
+ priv->video_bitrate = 5000;
+
priv->lock = g_mutex_new ();
}
@@ -156,131 +173,516 @@ gst_camera_capturer_finalize (GObject * object)
{
GstCameraCapturer *gcc = (GstCameraCapturer *) object;
- gtk_widget_destroy (gcc->priv->video_window);
- gtk_widget_unref (gcc->priv->video_window);
- gcc->priv->video_window = NULL;
+ if (gcc->priv->bus) {
+ /* make bus drop all messages to make sure none of our callbacks is ever
+ * called again (main loop might be run again to display error dialog) */
+ gst_bus_set_flushing (gcc->priv->bus, TRUE);
- if (gcc->priv->bus)
- {
- /* make bus drop all messages to make sure none of our callbacks is ever
- * called again (main loop might be run again to display error dialog) */
- gst_bus_set_flushing (gcc->priv->bus, TRUE);
-
- if (gcc->priv->sig_bus_async)
- g_signal_handler_disconnect (gcc->priv->bus,
- gcc->priv->sig_bus_async);
- gst_object_unref (gcc->priv->bus);
- gcc->priv->bus = NULL;
- }
+ if (gcc->priv->sig_bus_async)
+ g_signal_handler_disconnect (gcc->priv->bus, gcc->priv->sig_bus_async);
+ gst_object_unref (gcc->priv->bus);
+ gcc->priv->bus = NULL;
+ }
g_free (gcc->priv->output_file);
gcc->priv->output_file = NULL;
+ if (gcc->priv->interface_update_id) {
+ g_source_remove (gcc->priv->interface_update_id);
+ gcc->priv->interface_update_id = 0;
+ }
if (gcc->priv->main_pipeline != NULL
- && GST_IS_ELEMENT (gcc->priv->main_pipeline))
- {
- gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
- gst_object_unref (gcc->priv->main_pipeline);
- gcc->priv->main_pipeline = NULL;
- }
+ && GST_IS_ELEMENT (gcc->priv->main_pipeline)) {
+ gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
+ gst_object_unref (gcc->priv->main_pipeline);
+ gcc->priv->main_pipeline = NULL;
+ }
- if (gcc->priv->camerabin != NULL && GST_IS_ELEMENT (gcc->priv->camerabin))
- {
- gst_object_unref (gcc->priv->camerabin);
- gcc->priv->camerabin = NULL;
+ g_mutex_free (gcc->priv->lock);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_camera_capturer_apply_resolution (GstCameraCapturer * gcc)
+{
+ GstCaps *caps;
+ gchar * caps_string;
+
+ GST_INFO_OBJECT(gcc, "Changed video resolution to %dx%d %d/%dfps",
+ gcc->priv->output_width, gcc->priv->output_height,
+ gcc->priv->output_fps_n, gcc->priv->output_fps_d);
+
+ caps_string = g_strdup_printf("video/x-raw-yuv, format=(fourcc)I420,width=(int)%d,height=(int)%d",
+ gcc->priv->output_width, gcc->priv->output_height);
+ caps = gst_caps_from_string(caps_string);
+ g_object_set (gcc->priv->camerabin, "filter-caps", caps, NULL);
+ gst_caps_unref(caps);
+ g_free(caps_string);
+}
+
+static void
+gst_camera_capturer_set_video_bit_rate (GstCameraCapturer * gcc, gint bitrate)
+{
+ gcc->priv->video_bitrate = bitrate;
+ g_object_set (gcc->priv->videoenc, "bitrate", gcc->priv->video_bitrate, NULL);
+ GST_INFO_OBJECT (gcc,"Changed video bitrate to :\n%d", gcc->priv->video_bitrate);
+
+}
+
+static void
+gst_camera_capturer_set_audio_bit_rate (GstCameraCapturer * gcc, gint bitrate)
+{
+
+ gcc->priv->audio_bitrate = bitrate;
+ g_object_set (gcc->priv->audioenc, "bitrate", bitrate, NULL);
+ GST_INFO_OBJECT (gcc,"Changed audio bitrate to :\n%d", gcc->priv->audio_bitrate);
+
+}
+
+static void
+gst_camera_capturer_set_output_file (GstCameraCapturer * gcc,
+ const gchar * file)
+{
+ gcc->priv->output_file = g_strdup (file);
+ g_object_set (gcc->priv->camerabin, "filename", file, NULL);
+ GST_INFO_OBJECT (gcc,"Changed output filename to :\n%s", file);
+
+}
+
+/***********************************
+*
+* GTK Widget
+*
+************************************/
+
+static void
+gst_camera_capturer_size_request (GtkWidget * widget,
+ GtkRequisition * requisition)
+{
+ requisition->width = 320;
+ requisition->height = 240;
+}
+
+static void
+get_media_size (GstCameraCapturer * gcc, gint * width, gint * height)
+{
+ if (gcc->priv->logo_mode) {
+ if (gcc->priv->logo_pixbuf) {
+ *width = gdk_pixbuf_get_width (gcc->priv->logo_pixbuf);
+ *height = gdk_pixbuf_get_height (gcc->priv->logo_pixbuf);
+ } else {
+ *width = 0;
+ *height = 0;
}
+ } else {
- if (gcc->priv->videosrc != NULL && GST_IS_ELEMENT (gcc->priv->videosrc))
- {
- gst_object_unref (gcc->priv->videosrc);
- gcc->priv->videosrc = NULL;
+ GValue *disp_par = NULL;
+ guint movie_par_n, movie_par_d, disp_par_n, disp_par_d, num, den;
+
+ /* Create and init the fraction value */
+ disp_par = g_new0 (GValue, 1);
+ g_value_init (disp_par, GST_TYPE_FRACTION);
+
+ /* Square pixel is our default */
+ gst_value_set_fraction (disp_par, 1, 1);
+
+ /* Now try getting display's pixel aspect ratio */
+ if (gcc->priv->xoverlay) {
+ GObjectClass *klass;
+ GParamSpec *pspec;
+
+ klass = G_OBJECT_GET_CLASS (gcc->priv->xoverlay);
+ pspec = g_object_class_find_property (klass, "pixel-aspect-ratio");
+
+ if (pspec != NULL) {
+ GValue disp_par_prop = { 0, };
+
+ g_value_init (&disp_par_prop, pspec->value_type);
+ g_object_get_property (G_OBJECT (gcc->priv->xoverlay),
+ "pixel-aspect-ratio", &disp_par_prop);
+
+ if (!g_value_transform (&disp_par_prop, disp_par)) {
+ GST_WARNING ("Transform failed, assuming pixel-aspect-ratio = 1/1");
+ gst_value_set_fraction (disp_par, 1, 1);
+ }
+
+ g_value_unset (&disp_par_prop);
+ }
}
- if (gcc->priv->audiosrc != NULL && GST_IS_ELEMENT (gcc->priv->audiosrc))
- {
- gst_object_unref (gcc->priv->audiosrc);
- gcc->priv->audiosrc = NULL;
+ disp_par_n = gst_value_get_fraction_numerator (disp_par);
+ disp_par_d = gst_value_get_fraction_denominator (disp_par);
+
+ GST_DEBUG ("display PAR is %d/%d", disp_par_n, disp_par_d);
+
+ /* Use the movie pixel aspect ratio if any */
+ if (gcc->priv->movie_par) {
+ movie_par_n = gst_value_get_fraction_numerator (gcc->priv->movie_par);
+ movie_par_d = gst_value_get_fraction_denominator (gcc->priv->movie_par);
+ } else {
+ /* Square pixels */
+ movie_par_n = 1;
+ movie_par_d = 1;
}
- if (gcc->priv->videoenc != NULL && GST_IS_ELEMENT (gcc->priv->videoenc))
- {
- gst_object_unref (gcc->priv->videoenc);
- gcc->priv->videoenc = NULL;
+ GST_DEBUG ("movie PAR is %d/%d", movie_par_n, movie_par_d);
+
+ if (gcc->priv->video_width == 0 || gcc->priv->video_height == 0) {
+ GST_DEBUG ("width and/or height 0, assuming 1/1 ratio");
+ num = 1;
+ den = 1;
+ } else if (!gst_video_calculate_display_ratio (&num, &den,
+ gcc->priv->video_width,
+ gcc->priv->video_height,
+ movie_par_n, movie_par_d, disp_par_n, disp_par_d)) {
+ GST_WARNING ("overflow calculating display aspect ratio!");
+ num = 1; /* FIXME: what values to use here? */
+ den = 1;
}
- if (gcc->priv->audioenc != NULL && GST_IS_ELEMENT (gcc->priv->audioenc))
- {
- gst_object_unref (gcc->priv->audioenc);
- gcc->priv->audioenc = NULL;
+ GST_DEBUG ("calculated scaling ratio %d/%d for video %dx%d", num,
+ den, gcc->priv->video_width, gcc->priv->video_height);
+
+ /* now find a width x height that respects this display ratio.
+ * prefer those that have one of w/h the same as the incoming video
+ * using wd / hd = num / den */
+
+ /* start with same height, because of interlaced video */
+ /* check hd / den is an integer scale factor, and scale wd with the PAR */
+ if (gcc->priv->video_height % den == 0) {
+ GST_DEBUG ("keeping video height");
+ gcc->priv->video_width_pixels =
+ (guint) gst_util_uint64_scale (gcc->priv->video_height, num, den);
+ gcc->priv->video_height_pixels = gcc->priv->video_height;
+ } else if (gcc->priv->video_width % num == 0) {
+ GST_DEBUG ("keeping video width");
+ gcc->priv->video_width_pixels = gcc->priv->video_width;
+ gcc->priv->video_height_pixels =
+ (guint) gst_util_uint64_scale (gcc->priv->video_width, den, num);
+ } else {
+ GST_DEBUG ("approximating while keeping video height");
+ gcc->priv->video_width_pixels =
+ (guint) gst_util_uint64_scale (gcc->priv->video_height, num, den);
+ gcc->priv->video_height_pixels = gcc->priv->video_height;
}
+ GST_DEBUG ("scaling to %dx%d", gcc->priv->video_width_pixels,
+ gcc->priv->video_height_pixels);
- g_mutex_free (gcc->priv->lock);
+ *width = gcc->priv->video_width_pixels;
+ *height = gcc->priv->video_height_pixels;
- G_OBJECT_CLASS (gst_camera_capturer_parent_class)->finalize (object);
+ /* Free the PAR fraction */
+ g_value_unset (disp_par);
+ g_free (disp_par);
+
+ }
}
+static void
+resize_video_window (GstCameraCapturer * gcc)
+{
+ const GtkAllocation *allocation;
+ gfloat width, height, ratio, x, y;
+ int w, h;
+
+ g_return_if_fail (gcc != NULL);
+ g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
+
+ allocation = >K_WIDGET (gcc)->allocation;
+ get_media_size (gcc, &w, &h);
+
+ if (!w || !h) {
+ w = allocation->width;
+ h = allocation->height;
+ }
+ width = w;
+ height = h;
+
+ /* calculate ratio for fitting video into the available space */
+ if ((gfloat) allocation->width / width > (gfloat) allocation->height / height) {
+ ratio = (gfloat) allocation->height / height;
+ } else {
+ ratio = (gfloat) allocation->width / width;
+ }
+
+ /* apply zoom factor */
+ ratio = ratio * gcc->priv->zoom;
+
+ width *= ratio;
+ height *= ratio;
+ x = (allocation->width - width) / 2;
+ y = (allocation->height - height) / 2;
+
+ gdk_window_move_resize (gcc->priv->video_window, x, y, width, height);
+ gtk_widget_queue_draw (GTK_WIDGET (gcc));
+}
static void
-gst_camera_capturer_set_encode_width (GstCameraCapturer * gcc, gint width)
+gst_camera_capturer_size_allocate (GtkWidget * widget,
+ GtkAllocation * allocation)
{
+ GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GST_IS_CAMERA_CAPTURER (widget));
+
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget)) {
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ allocation->x, allocation->y, allocation->width, allocation->height);
+ resize_video_window (gcc);
+ }
}
-static void
-gst_camera_capturer_set_encode_height (GstCameraCapturer * gcc, gint height)
+static gboolean
+gst_camera_capturer_configure_event (GtkWidget * widget,
+ GdkEventConfigure * event, GstCameraCapturer * gcc)
{
+ GstXOverlay *xoverlay = NULL;
+
+ g_return_val_if_fail (gcc != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
+
+ xoverlay = gcc->priv->xoverlay;
+ if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
+ gst_x_overlay_expose (xoverlay);
+ }
+
+ return FALSE;
}
static void
-gst_camera_capturer_set_video_bit_rate (GstCameraCapturer * gcc, gint bitrate)
+gst_camera_capturer_realize (GtkWidget * widget)
{
- gcc->priv->video_bitrate = bitrate;
- g_object_set (gcc->priv->videoenc, "bitrate", gcc->priv->video_bitrate,
- NULL);
- GST_INFO ("Changed video bitrate to :\n%d", gcc->priv->video_bitrate);
+ GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+ GdkWindowAttr attributes;
+ gint attributes_mask, w, h;
+ GdkColor colour;
+ GdkWindow *window;
+ GdkEventMask event_mask;
+
+ event_mask = gtk_widget_get_events (widget)
+ | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK;
+ gtk_widget_set_events (widget, event_mask);
+
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ window = gtk_widget_get_window (widget);
+
+ /* Creating our video window */
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = 0;
+ attributes.y = 0;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_EXPOSURE_MASK |
+ GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ gcc->priv->video_window = gdk_window_new (window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (gcc->priv->video_window, widget);
+
+ gdk_color_parse ("black", &colour);
+ gdk_colormap_alloc_color (gtk_widget_get_colormap (widget),
+ &colour, TRUE, TRUE);
+ gdk_window_set_background (window, &colour);
+ gtk_widget_set_style (widget,
+ gtk_style_attach (gtk_widget_get_style (widget), window));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ /* Connect to configure event on the top level window */
+ g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (widget)),
+ "configure-event", G_CALLBACK (gst_camera_capturer_configure_event), gcc);
+
+ /* nice hack to show the logo fullsize, while still being resizable */
+ get_media_size (GST_CAMERA_CAPTURER (widget), &w, &h);
+}
+
+static void
+gst_camera_capturer_unrealize (GtkWidget * widget)
+{
+ GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+
+ gdk_window_set_user_data (gcc->priv->video_window, NULL);
+ gdk_window_destroy (gcc->priv->video_window);
+ gcc->priv->video_window = NULL;
+ GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}
static void
-gst_camera_capturer_set_audio_bit_rate (GstCameraCapturer * gcc, gint bitrate)
+gst_camera_capturer_show (GtkWidget * widget)
{
+ GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+ GdkWindow *window;
- gcc->priv->audio_bitrate = bitrate;
- g_object_set (gcc->priv->audioenc, "bitrate", bitrate, NULL);
- GST_INFO ("Changed audio bitrate to :\n%d", gcc->priv->audio_bitrate);
+ window = gtk_widget_get_window (widget);
+ if (window)
+ gdk_window_show (window);
+ if (gcc->priv->video_window)
+ gdk_window_show (gcc->priv->video_window);
+ if (GTK_WIDGET_CLASS (parent_class)->show)
+ GTK_WIDGET_CLASS (parent_class)->show (widget);
}
static void
-gst_camera_capturer_set_output_file (GstCameraCapturer * gcc,
- const gchar * file)
+gst_camera_capturer_hide (GtkWidget * widget)
{
- gcc->priv->output_file = g_strdup (file);
- g_object_set (gcc->priv->camerabin, "filename", file, NULL);
- GST_INFO ("Changed output filename to :\n%s", file);
+ GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+ GdkWindow *window;
+
+ window = gtk_widget_get_window (widget);
+ if (window)
+ gdk_window_hide (window);
+ if (gcc->priv->video_window)
+ gdk_window_hide (gcc->priv->video_window);
+ if (GTK_WIDGET_CLASS (parent_class)->hide)
+ GTK_WIDGET_CLASS (parent_class)->hide (widget);
}
+static gboolean
+gst_camera_capturer_expose_event (GtkWidget * widget, GdkEventExpose * event)
+{
+ GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (widget);
+ GstCaps *caps = NULL;
+ GstXOverlay *xoverlay;
+ gboolean draw_logo;
+ GdkWindow *win;
+
+ if (event && event->count > 0)
+ return TRUE;
+
+ g_mutex_lock (gcc->priv->lock);
+ xoverlay = gcc->priv->xoverlay;
+ if (xoverlay == NULL) {
+ gcc_update_interface_implementations (gcc);
+ g_object_get (gcc->priv->camerabin, "filter-caps", &caps, NULL);
+ gcc_parse_video_stream_info (caps, gcc);
+ gst_caps_unref (caps);
+ xoverlay = gcc->priv->xoverlay;
+ }
+ if (xoverlay != NULL)
+ gst_object_ref (xoverlay);
+
+ g_mutex_unlock (gcc->priv->lock);
+
+ if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
+#ifdef WIN32
+ gst_x_overlay_set_xwindow_id (gcc->priv->xoverlay,
+ GDK_WINDOW_HWND (gcc->priv->video_window));
+#else
+ gst_x_overlay_set_xwindow_id (gcc->priv->xoverlay,
+ GDK_WINDOW_XID (gcc->priv->video_window));
+#endif
+ }
+
+ /* Start with a nice black canvas */
+ win = gtk_widget_get_window (widget);
+ gdk_draw_rectangle (win, gtk_widget_get_style (widget)->black_gc, TRUE, 0,
+ 0, widget->allocation.width, widget->allocation.height);
+
+ /* if there's only audio and no visualisation, draw the logo as well */
+ draw_logo = gcc->priv->media_has_audio && !gcc->priv->media_has_video;
+
+ if (gcc->priv->logo_mode || draw_logo) {
+ if (gcc->priv->logo_pixbuf != NULL) {
+ GdkPixbuf *frame;
+ guchar *pixels;
+ int rowstride;
+ gint width, height, alloc_width, alloc_height, logo_x, logo_y;
+ gfloat ratio;
+
+ /* Checking if allocated space is smaller than our logo */
+ width = gdk_pixbuf_get_width (gcc->priv->logo_pixbuf);
+ height = gdk_pixbuf_get_height (gcc->priv->logo_pixbuf);
+ alloc_width = widget->allocation.width;
+ alloc_height = widget->allocation.height;
+
+ if ((gfloat) alloc_width / width > (gfloat) alloc_height / height) {
+ ratio = (gfloat) alloc_height / height;
+ } else {
+ ratio = (gfloat) alloc_width / width;
+ }
+
+ width *= ratio;
+ height *= ratio;
+
+ logo_x = (alloc_width / 2) - (width / 2);
+ logo_y = (alloc_height / 2) - (height / 2);
+
+ /* Drawing our frame */
+ /* Scaling to available space */
+ frame = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ FALSE, 8, widget->allocation.width, widget->allocation.height);
+
+ gdk_pixbuf_composite (gcc->priv->logo_pixbuf,
+ frame,
+ 0, 0,
+ alloc_width, alloc_height,
+ logo_x, logo_y, ratio, ratio, GDK_INTERP_BILINEAR, 255);
+
+ rowstride = gdk_pixbuf_get_rowstride (frame);
+
+ pixels = gdk_pixbuf_get_pixels (frame) +
+ rowstride * event->area.y + event->area.x * 3;
+
+ gdk_draw_rgb_image_dithalign (widget->window,
+ widget->style->black_gc,
+ event->area.x, event->area.y,
+ event->area.width,
+ event->area.height,
+ GDK_RGB_DITHER_NORMAL, pixels,
+ rowstride, event->area.x, event->area.y);
+
+ g_object_unref (frame);
+ } else if (win) {
+ /* No pixbuf, just draw a black background then */
+ gdk_window_clear_area (win,
+ 0, 0, widget->allocation.width, widget->allocation.height);
+ }
+ } else {
+ /* no logo, pass the expose to gst */
+ if (xoverlay != NULL && GST_IS_X_OVERLAY (xoverlay)) {
+ gst_x_overlay_expose (xoverlay);
+ } else {
+ /* No xoverlay to expose yet */
+ gdk_window_clear_area (win,
+ 0, 0, widget->allocation.width, widget->allocation.height);
+ }
+ }
+ if (xoverlay != NULL)
+ gst_object_unref (xoverlay);
+ return TRUE;
+}
static void
gst_camera_capturer_set_property (GObject * object, guint property_id,
- const GValue * value, GParamSpec * pspec)
+ const GValue * value, GParamSpec * pspec)
{
GstCameraCapturer *gcc;
gcc = GST_CAMERA_CAPTURER (object);
- switch (property_id)
- {
- case PROP_ENCODE_HEIGHT:
- gst_camera_capturer_set_encode_height (gcc, g_value_get_uint (value));
+ switch (property_id) {
+ case PROP_OUTPUT_HEIGHT:
+ gcc->priv->output_height = g_value_get_uint (value);
+ gst_camera_capturer_apply_resolution (gcc);
break;
- case PROP_ENCODE_WIDTH:
- gst_camera_capturer_set_encode_width (gcc, g_value_get_uint (value));
+ case PROP_OUTPUT_WIDTH:
+ gcc->priv->output_width = g_value_get_uint (value);
+ gst_camera_capturer_apply_resolution (gcc);
break;
case PROP_VIDEO_BITRATE:
gst_camera_capturer_set_video_bit_rate (gcc, g_value_get_uint (value));
@@ -294,24 +696,23 @@ gst_camera_capturer_set_property (GObject * object, guint property_id,
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
- }
+ }
}
static void
gst_camera_capturer_get_property (GObject * object, guint property_id,
- GValue * value, GParamSpec * pspec)
+ GValue * value, GParamSpec * pspec)
{
GstCameraCapturer *gcc;
gcc = GST_CAMERA_CAPTURER (object);
- switch (property_id)
- {
- case PROP_ENCODE_HEIGHT:
- g_value_set_uint (value, gcc->priv->encode_height);
+ switch (property_id) {
+ case PROP_OUTPUT_HEIGHT:
+ g_value_set_uint (value, gcc->priv->output_height);
break;
- case PROP_ENCODE_WIDTH:
- g_value_set_uint (value, gcc->priv->encode_width);
+ case PROP_OUTPUT_WIDTH:
+ g_value_set_uint (value, gcc->priv->output_width);
break;
case PROP_AUDIO_BITRATE:
g_value_set_uint (value, gcc->priv->audio_bitrate);
@@ -325,65 +726,68 @@ gst_camera_capturer_get_property (GObject * object, guint property_id,
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
- }
+ }
}
static void
gst_camera_capturer_class_init (GstCameraCapturerClass * klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
- object_class->finalize = gst_camera_capturer_finalize;
+ object_class = (GObjectClass *) klass;
+ widget_class = (GtkWidgetClass *) klass;
+ parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (object_class, sizeof (GstCameraCapturerPrivate));
+ /* GtkWidget */
+ widget_class->size_request = gst_camera_capturer_size_request;
+ widget_class->size_allocate = gst_camera_capturer_size_allocate;
+ widget_class->realize = gst_camera_capturer_realize;
+ widget_class->unrealize = gst_camera_capturer_unrealize;
+ widget_class->show = gst_camera_capturer_show;
+ widget_class->hide = gst_camera_capturer_hide;
+ widget_class->expose_event = gst_camera_capturer_expose_event;
+
/* GObject */
object_class->set_property = gst_camera_capturer_set_property;
object_class->get_property = gst_camera_capturer_get_property;
object_class->finalize = gst_camera_capturer_finalize;
/* Properties */
- g_object_class_install_property (object_class, PROP_ENCODE_HEIGHT,
- g_param_spec_uint ("encode_height", NULL,
- NULL, 180, 5600, 576,
- G_PARAM_READWRITE));
- g_object_class_install_property (object_class, PROP_ENCODE_WIDTH,
- g_param_spec_uint ("encode_width", NULL,
- NULL, 180, 5600, 720,
- G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_OUTPUT_HEIGHT,
+ g_param_spec_uint ("output_height", NULL,
+ NULL, 180, 5600, 576, G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_OUTPUT_WIDTH,
+ g_param_spec_uint ("output_width", NULL,
+ NULL, 180, 5600, 720, G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_VIDEO_BITRATE,
- g_param_spec_uint ("video_bitrate", NULL,
- NULL, 100, G_MAXUINT,
- 1000,
- G_PARAM_READWRITE));
+ g_param_spec_uint ("video_bitrate", NULL,
+ NULL, 100, G_MAXUINT, 1000, G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_AUDIO_BITRATE,
- g_param_spec_uint ("audio_bitrate", NULL,
- NULL, 12, G_MAXUINT,
- 128,
- G_PARAM_READWRITE));
+ g_param_spec_uint ("audio_bitrate", NULL,
+ NULL, 12, G_MAXUINT, 128, G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_OUTPUT_FILE,
- g_param_spec_string ("output_file", NULL,
- NULL, FALSE,
- G_PARAM_READWRITE));
+ g_param_spec_string ("output_file", NULL,
+ NULL, FALSE, G_PARAM_READWRITE));
/* Signals */
gcc_signals[SIGNAL_ERROR] =
- g_signal_new ("error",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstCameraCapturerClass, error),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
+ g_signal_new ("error",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstCameraCapturerClass, error),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
gcc_signals[SIGNAL_EOS] =
- g_signal_new ("eos",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstCameraCapturerClass, eos),
- NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
+ g_signal_new ("eos",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GstCameraCapturerClass, eos),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
void
@@ -392,52 +796,14 @@ gst_camera_capturer_init_backend (int *argc, char ***argv)
gst_init (argc, argv);
}
-static gboolean
-gcc_expose_event (GtkWidget * widget, GdkEventExpose * event,
- gpointer user_data)
-{
- GstCameraCapturer *gcc;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GST_IS_VIDEO_WIDGET (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- gcc = GST_CAMERA_CAPTURER (user_data);
-
- //Delegate the expose to the widget
- gst_video_widget_force_expose (widget, event);
- if (gcc->priv->xoverlay != NULL && !gcc->priv->logo_mode)
- {
- gst_x_overlay_expose (gcc->priv->xoverlay);
- }
- return TRUE;
-}
-
-static void
-gcc_window_construct (int width, int height, GstCameraCapturer * gcc)
-{
-
- //Create the Video Widget
- gcc->priv->video_window = gst_video_widget_new ();
- gtk_container_add (GTK_CONTAINER (gcc), gcc->priv->video_window);
- gst_video_widget_set_minimum_size (GST_VIDEO_WIDGET
- (gcc->priv->video_window), 120, 80);
- gst_video_widget_set_source_size (GST_VIDEO_WIDGET
- (gcc->priv->video_window), 720, 576);
- gtk_widget_show (gcc->priv->video_window);
- g_signal_connect (G_OBJECT (gcc->priv->video_window), "expose_event",
- G_CALLBACK (gcc_expose_event), gcc);
-}
-
GQuark
gst_camera_capturer_error_quark (void)
{
- static GQuark q; /* 0 */
+ static GQuark q; /* 0 */
- if (G_UNLIKELY (q == 0))
- {
- q = g_quark_from_static_string ("gcc-error-quark");
- }
+ if (G_UNLIKELY (q == 0)) {
+ q = g_quark_from_static_string ("gcc-error-quark");
+ }
return q;
}
@@ -445,92 +811,65 @@ GstCameraCapturer *
gst_camera_capturer_new (gchar * filename, GError ** err)
{
GstCameraCapturer *gcc = NULL;
- GstState state;
gcc = g_object_new (GST_TYPE_CAMERA_CAPTURER, NULL);
- /*Handled by Properties? */
- gcc->priv->encode_height = 576;
- gcc->priv->encode_width = 720;
- gcc->priv->audio_bitrate = 128;
- gcc->priv->video_bitrate = 5000;
-
- gcc_window_construct (720, 576, gcc);
-
gcc->priv->main_pipeline = gst_pipeline_new ("main_pipeline");
- if (!gcc->priv->main_pipeline)
- {
- g_set_error (err, GCC_ERROR, GCC_ERROR_PLUGIN_LOAD,
- ("Failed to create a GStreamer Bin. "
- "Please check your GStreamer installation."));
- g_object_ref_sink (gcc);
- g_object_unref (gcc);
- return NULL;
- }
+ if (!gcc->priv->main_pipeline) {
+ g_set_error (err, GCC_ERROR, GCC_ERROR_PLUGIN_LOAD,
+ ("Failed to create a GStreamer Bin. "
+ "Please check your GStreamer installation."));
+ g_object_ref_sink (gcc);
+ g_object_unref (gcc);
+ return NULL;
+ }
/* Setup */
- GST_INFO ("Initializing camerabin");
+ GST_INFO_OBJECT (gcc,"Initializing camerabin");
gcc->priv->camerabin = gst_element_factory_make ("camerabin", "camerabin");
gst_bin_add (GST_BIN (gcc->priv->main_pipeline), gcc->priv->camerabin);
- GST_INFO ("Setting capture mode to \"video\"");
+ GST_INFO_OBJECT (gcc,"Setting capture mode to \"video\"");
g_object_set (gcc->priv->camerabin, "mode", 1, NULL);
- GST_INFO ("Setting video source ");
+ GST_INFO_OBJECT (gcc,"Setting video source ");
gcc->priv->videosrc = gst_element_factory_make (VIDEOSRC, "videosource");
- g_object_set (gcc->priv->camerabin, "videosrc", gcc->priv->videosrc, NULL);
+ g_object_set (gcc->priv->camerabin, "video-source", gcc->priv->videosrc,
+ NULL);
g_object_set (gcc->priv->videosrc, "do-timestamp", TRUE, NULL);
- GST_INFO ("Setting audio source ");
- gcc->priv->audiosrc =
- gst_element_factory_make ("dshowaudiosrc", "audiosource");
- g_object_set (gcc->priv->camerabin, "audiosrc", gcc->priv->audiosrc, NULL);
-
- /*gcc->priv->videoenc = gst_element_factory_make ("ffenc_mpeg4","videoenc");
- g_object_set (gcc->priv->camerabin,"videoenc",gcc->priv->videoenc,NULL);
- gcc->priv->audioenc = gst_element_factory_make ("faac","audioenc");
- g_object_set (gcc->priv->camerabin,"audioenc",gcc->priv->audioenc,NULL);
- gcc->priv->videomux = gst_element_factory_make ("avimux","videomux");
- g_object_set (gcc->priv->camerabin,"videomux",gcc->priv->videomux,NULL); */
-
-
+ GST_INFO_OBJECT (gcc,"Setting audio source ");
+ gcc->priv->audiosrc = gst_element_factory_make (AUDIOSRC, "audiosource");
+ g_object_set (gcc->priv->camerabin, "audio-source", gcc->priv->audiosrc,
+ NULL);
- GST_INFO ("Setting capture mode to \"video\"");
+ GST_INFO_OBJECT (gcc,"Setting capture mode to \"video\"");
g_object_set (gcc->priv->camerabin, "mode", 1, NULL);
g_object_set (gcc->priv->camerabin, "mute", TRUE, NULL);
+ /* assume we're always called from the main Gtk+ GUI thread */
+ gui_thread = g_thread_self ();
+
/*Connect bus signals */
- GST_INFO ("Connecting bus signals");
- gcc->priv->bus =
- gst_element_get_bus (GST_ELEMENT (gcc->priv->main_pipeline));
+ GST_INFO_OBJECT (gcc,"Connecting bus signals");
+ gcc->priv->bus = gst_element_get_bus (GST_ELEMENT (gcc->priv->main_pipeline));
gst_bus_add_signal_watch (gcc->priv->bus);
gcc->priv->sig_bus_async =
- g_signal_connect (gcc->priv->bus, "message",
- G_CALLBACK (gcc_bus_message_cb), gcc);
+ g_signal_connect (gcc->priv->bus, "message",
+ G_CALLBACK (gcc_bus_message_cb), gcc);
/* we want to catch "prepare-xwindow-id" element messages synchronously */
gst_bus_set_sync_handler (gcc->priv->bus, gst_bus_sync_signal_handler, gcc);
gcc->priv->sig_bus_sync =
- g_signal_connect (gcc->priv->bus, "sync-message::element",
- G_CALLBACK (gcc_element_msg_sync), gcc);
-
+ g_signal_connect (gcc->priv->bus, "sync-message::element",
+ G_CALLBACK (gcc_element_msg_sync), gcc);
- /*gst_element_set_state (gcc->priv->camerabin, GST_STATE_NULL);
- do
- {
- gst_element_get_state(gcc->priv->camerabin, &state, NULL,
- GST_CLOCK_TIME_NONE);
-
- }
- while(state != GST_STATE_NULL); */
-
- return gcc;
+ return gcc;
}
-
void
gst_camera_capturer_run (GstCameraCapturer * gcc)
{
@@ -538,130 +877,177 @@ gst_camera_capturer_run (GstCameraCapturer * gcc)
}
void
+gst_camera_capturer_close (GstCameraCapturer * gcc)
+{
+ gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
+}
+
+void
gst_camera_capturer_start (GstCameraCapturer * gcc)
{
g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
- g_signal_emit_by_name (G_OBJECT (gcc->priv->camerabin), "user-start", 0, 0);
+ g_signal_emit_by_name (G_OBJECT (gcc->priv->camerabin), "capture-start", 0,
+ 0);
}
-
void
gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc)
{
g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
- g_signal_emit_by_name (G_OBJECT (gcc->priv->camerabin), "user-pause", 0, 0);
+ g_signal_emit_by_name (G_OBJECT (gcc->priv->camerabin), "capture-pause", 0,
+ 0);
}
void
gst_camera_capturer_stop (GstCameraCapturer * gcc)
{
g_return_if_fail (GST_IS_CAMERA_CAPTURER (gcc));
- g_signal_emit_by_name (G_OBJECT (gcc->priv->camerabin), "user-stop", 0, 0);
+ g_signal_emit_by_name (G_OBJECT (gcc->priv->camerabin), "capture-stop", 0, 0);
}
-
gboolean
gst_camera_capturer_set_video_encoder (GstCameraCapturer * gcc,
- GccVideoEncoderType type)
+ GccVideoEncoderType type, GError ** err)
{
+ gchar *name = NULL;
+
g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
- switch (type)
- {
+
+ switch (type) {
case GCC_VIDEO_ENCODER_TYPE_MPEG4:
gcc->priv->videoenc =
- gst_element_factory_make ("ffenc_mpeg4", "videoenc");
- g_object_set (gcc->priv->camerabin, "videoenc", gcc->priv->videoenc,
- NULL);
+ gst_element_factory_make ("ffenc_mpeg4", "video-encoder");
+ name = "FFmpeg mpeg4 video encoder";
break;
case GCC_VIDEO_ENCODER_TYPE_XVID:
- gcc->priv->videoenc = gst_element_factory_make ("xvid_enc", "videoenc");
- g_object_set (gcc->priv->camerabin, "videoenc", gcc->priv->videoenc,
- NULL);
+ gcc->priv->videoenc =
+ gst_element_factory_make ("xvidenc", "video-encoder");
+ name = "Xvid video encoder";
break;
case GCC_VIDEO_ENCODER_TYPE_THEORA:
gcc->priv->videoenc =
- gst_element_factory_make ("theoraenc", "videoenc");
- g_object_set (gcc->priv->camerabin, "videoenc", gcc->priv->videoenc,
- NULL);
+ gst_element_factory_make ("theoraenc", "video-encoder");
+ name = "Theora video encoder";
break;
case GCC_VIDEO_ENCODER_TYPE_H264:
- gcc->priv->videoenc = gst_element_factory_make ("x264enc", "videoenc");
- g_object_set (gcc->priv->camerabin, "videoenc", gcc->priv->videoenc,
- NULL);
+ gcc->priv->videoenc =
+ gst_element_factory_make ("x264enc", "video-encoder");
+ name = "X264 video encoder";
break;
-
- }
+ }
+ if (!gcc->priv->videoenc) {
+ g_set_error (err,
+ GCC_ERROR,
+ GCC_ERROR_PLUGIN_LOAD,
+ "Failed to create the %s element. "
+ "Please check your GStreamer installation.", name);
+ } else {
+ g_object_set (gcc->priv->camerabin, "video-encoder", gcc->priv->videoenc,
+ NULL);
+ }
return TRUE;
}
gboolean
gst_camera_capturer_set_audio_encoder (GstCameraCapturer * gcc,
- GccAudioEncoderType type)
+ GccAudioEncoderType type, GError ** err)
{
+ gchar *name = NULL;
+
g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
- switch (type)
- {
+ switch (type) {
case GCC_AUDIO_ENCODER_MP3:
gcc->priv->audioenc =
- gst_element_factory_make ("ffenc_libmp3lame", "audioenc");
- g_object_set (gcc->priv->camerabin, "audioenc", gcc->priv->audioenc,
- NULL);
+ gst_element_factory_make ("lame", "audio-encoder");
+ name = "Mp3 audio encoder";
break;
case GCC_AUDIO_ENCODER_AAC:
- gcc->priv->audioenc = gst_element_factory_make ("faac", "audioenc");
- g_object_set (gcc->priv->camerabin, "audioenc", gcc->priv->audioenc,
- NULL);
+ gcc->priv->audioenc = gst_element_factory_make ("faac", "audio-encoder");
+ name = "AAC audio encoder";
break;
case GCC_AUDIO_ENCODER_VORBIS:
gcc->priv->audioenc =
- gst_element_factory_make ("vorbisenc", "audioenc");
- g_object_set (gcc->priv->camerabin, "audioenc", gcc->priv->audioenc,
- NULL);
+ gst_element_factory_make ("vorbisenc", "audio-encoder");
+ name = "Vorbis audio encoder";
break;
- }
+ }
+
+ if (!gcc->priv->audioenc) {
+ g_set_error (err,
+ GCC_ERROR,
+ GCC_ERROR_PLUGIN_LOAD,
+ "Failed to create the %s element. "
+ "Please check your GStreamer installation.", name);
+ } else {
+ g_object_set (gcc->priv->camerabin, "audio-encoder", gcc->priv->audioenc,
+ NULL);
+ }
return TRUE;
-
}
gboolean
gst_camera_capturer_set_video_muxer (GstCameraCapturer * gcc,
- GccVideoMuxerType type)
+ GccVideoMuxerType type, GError ** err)
{
+ gchar *name = NULL;
+
g_return_val_if_fail (GST_IS_CAMERA_CAPTURER (gcc), FALSE);
- switch (type)
- {
+ switch (type) {
case GCC_VIDEO_MUXER_OGG:
- gcc->priv->videomux = gst_element_factory_make ("oggmux", "videomux");
- g_object_set (gcc->priv->camerabin, "videomux", gcc->priv->audioenc,
- NULL);
+ name = "OGG muxer";
+ gcc->priv->videomux = gst_element_factory_make ("oggmux", "video-muxer");
break;
case GCC_VIDEO_MUXER_AVI:
- gcc->priv->videomux = gst_element_factory_make ("avimux", "videomux");
- g_object_set (gcc->priv->camerabin, "videomux", gcc->priv->audioenc,
- NULL);
+ name = "AVI muxer";
+ gcc->priv->videomux = gst_element_factory_make ("avimux", "video-muxer");
+ break;
+ case GCC_VIDEO_MUXER_MP4:
+ name = "MP4 muxer";
+ gcc->priv->videomux = gst_element_factory_make ("qtmux", "video-muxer");
break;
case GCC_VIDEO_MUXER_MATROSKA:
+ name = "Matroska muxer";
gcc->priv->videomux =
- gst_element_factory_make ("matroskamux", "videomux");
- g_object_set (gcc->priv->camerabin, "videomux", gcc->priv->audioenc,
- NULL);
+ gst_element_factory_make ("matroskamux", "video-muxer");
break;
- }
+ }
+
+ if (!gcc->priv->videomux) {
+ g_set_error (err,
+ GCC_ERROR,
+ GCC_ERROR_PLUGIN_LOAD,
+ "Failed to create the %s element. "
+ "Please check your GStreamer installation.", name);
+ } else {
+ g_object_set (gcc->priv->camerabin, "video-muxer", gcc->priv->videomux,
+ NULL);
+ }
return TRUE;
}
-
-
-
+GValueArray *
+gst_camera_capture_enum_devices (GstCameraCapturer * gcc)
+{
+ GstElement *videodevicesrc;
+ GstPropertyProbe *probe;
+ GValueArray *va;
+
+ videodevicesrc = gst_element_factory_make (VIDEOSRC, "source");
+ probe = GST_PROPERTY_PROBE (videodevicesrc);
+ va = gst_property_probe_get_values_name (probe, "device-name");
+ gst_element_set_state (videodevicesrc, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (videodevicesrc));
+ return va;
+}
static void
gcc_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data)
@@ -674,33 +1060,32 @@ gcc_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data)
msg_type = GST_MESSAGE_TYPE (message);
- switch (msg_type)
- {
+ switch (msg_type) {
case GST_MESSAGE_ERROR:
- {
- gcc_error_msg (gcc, message);
- if (gcc->priv->main_pipeline)
- gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
- break;
- }
+ {
+ gcc_error_msg (gcc, message);
+ if (gcc->priv->main_pipeline)
+ gst_element_set_state (gcc->priv->main_pipeline, GST_STATE_NULL);
+ break;
+ }
case GST_MESSAGE_WARNING:
- {
- GST_WARNING ("Warning message: %" GST_PTR_FORMAT, message);
- break;
- }
+ {
+ GST_WARNING ("Warning message: %" GST_PTR_FORMAT, message);
+ break;
+ }
case GST_MESSAGE_EOS:
- {
- GST_INFO ("EOS message");
- g_signal_emit (gcc, gcc_signals[SIGNAL_EOS], 0);
- break;
- }
+ {
+ GST_INFO_OBJECT (gcc,"EOS message");
+ g_signal_emit (gcc, gcc_signals[SIGNAL_EOS], 0);
+ break;
+ }
default:
GST_LOG ("Unhandled message: %" GST_PTR_FORMAT, message);
break;
- }
+ }
}
static void
@@ -710,59 +1095,66 @@ gcc_error_msg (GstCameraCapturer * gcc, GstMessage * msg)
gchar *dbg = NULL;
gst_message_parse_error (msg, &err, &dbg);
- if (err)
- {
- GST_ERROR ("message = %s", GST_STR_NULL (err->message));
- GST_ERROR ("domain = %d (%s)", err->domain,
- GST_STR_NULL (g_quark_to_string (err->domain)));
- GST_ERROR ("code = %d", err->code);
- GST_ERROR ("debug = %s", GST_STR_NULL (dbg));
- GST_ERROR ("source = %" GST_PTR_FORMAT, msg->src);
-
-
- g_message ("Error: %s\n%s\n", GST_STR_NULL (err->message),
- GST_STR_NULL (dbg));
- g_signal_emit (gcc, gcc_signals[SIGNAL_ERROR], 0, err->message);
- g_error_free (err);
- }
+ if (err) {
+ GST_ERROR ("message = %s", GST_STR_NULL (err->message));
+ GST_ERROR ("domain = %d (%s)", err->domain,
+ GST_STR_NULL (g_quark_to_string (err->domain)));
+ GST_ERROR ("code = %d", err->code);
+ GST_ERROR ("debug = %s", GST_STR_NULL (dbg));
+ GST_ERROR ("source = %" GST_PTR_FORMAT, msg->src);
+
+
+ g_message ("Error: %s\n%s\n", GST_STR_NULL (err->message),
+ GST_STR_NULL (dbg));
+ g_signal_emit (gcc, gcc_signals[SIGNAL_ERROR], 0, err->message);
+ g_error_free (err);
+ }
g_free (dbg);
}
+static gboolean
+gcc_update_interfaces_delayed (GstCameraCapturer * gcc)
+{
+ GST_DEBUG ("Delayed updating interface implementations");
+ g_mutex_lock (gcc->priv->lock);
+ gcc_update_interface_implementations (gcc);
+ gcc->priv->interface_update_id = 0;
+ g_mutex_unlock (gcc->priv->lock);
+
+ return FALSE;
+}
static void
gcc_update_interface_implementations (GstCameraCapturer * gcc)
{
- GstXOverlay *old_xoverlay = gcc->priv->xoverlay;
GstElement *element = NULL;
- GST_INFO ("Retrieving xoverlay from bin ...");
- element = gst_bin_get_by_interface (GST_BIN (gcc->priv->camerabin),
- GST_TYPE_X_OVERLAY);
+ if (g_thread_self () != gui_thread) {
+ if (gcc->priv->interface_update_id)
+ g_source_remove (gcc->priv->interface_update_id);
+ gcc->priv->interface_update_id =
+ g_idle_add ((GSourceFunc) gcc_update_interfaces_delayed, gcc);
+ return;
+ }
- if (GST_IS_X_OVERLAY (element))
- {
- gcc->priv->xoverlay = GST_X_OVERLAY (element);
- }
- else
- {
- gcc->priv->xoverlay = NULL;
- }
- if (old_xoverlay)
- gst_object_unref (GST_OBJECT (old_xoverlay));
+ GST_INFO_OBJECT (gcc,"Retrieving xoverlay from bin ...");
+ element = gst_bin_get_by_interface (GST_BIN (gcc->priv->camerabin),
+ GST_TYPE_X_OVERLAY);
+ if (GST_IS_X_OVERLAY (element)) {
+ gcc->priv->xoverlay = GST_X_OVERLAY (element);
+ } else {
+ gcc->priv->xoverlay = NULL;
+ }
}
static void
gcc_element_msg_sync (GstBus * bus, GstMessage * msg, gpointer data)
{
-
GstCameraCapturer *gcc = GST_CAMERA_CAPTURER (data);
- GstElement *video_sink = NULL;
GstCaps *caps = NULL;
- g_object_get (gcc->priv->camerabin, "vfsink", &video_sink, NULL);
-
g_assert (msg->type == GST_MESSAGE_ELEMENT);
if (msg->structure == NULL)
@@ -770,42 +1162,28 @@ gcc_element_msg_sync (GstBus * bus, GstMessage * msg, gpointer data)
/* This only gets sent if we haven't set an ID yet. This is our last
* chance to set it before the video sink will create its own window */
- if (gst_structure_has_name (msg->structure, "prepare-xwindow-id"))
- {
- GdkWindow *window;
- g_object_get (gcc->priv->camerabin, "filter-caps", &caps, NULL);
- gcc_parse_video_stream_info (caps, gcc);
- gst_caps_unref (caps);
+ if (gst_structure_has_name (msg->structure, "prepare-xwindow-id")) {
+ g_object_get (gcc->priv->camerabin, "filter-caps", &caps, NULL);
+ gcc_parse_video_stream_info (caps, gcc);
+ gst_caps_unref (caps);
- g_mutex_lock (gcc->priv->lock);
- gcc_update_interface_implementations (gcc);
- g_mutex_unlock (gcc->priv->lock);
+ g_mutex_lock (gcc->priv->lock);
+ gcc_update_interface_implementations (gcc);
+ g_mutex_unlock (gcc->priv->lock);
- g_return_if_fail (gcc->priv->xoverlay != NULL);
- g_return_if_fail (gcc->priv->video_window != NULL);
+ g_return_if_fail (gcc->priv->xoverlay != NULL);
+ g_return_if_fail (gcc->priv->video_window != NULL);
- GST_INFO ("Setting xwindow: %d", gcc->priv->video_width);
-
- window =
- gst_video_widget_get_video_window (GST_VIDEO_WIDGET
- (gcc->priv->video_window));
#ifdef WIN32
- gst_x_overlay_set_xwindow_id (gcc->priv->xoverlay,
- GDK_WINDOW_HWND (window));
+ gst_x_overlay_set_xwindow_id (gcc->priv->xoverlay,
+ GDK_WINDOW_HWND (gcc->priv->video_window));
#else
- gst_x_overlay_set_xwindow_id (gcc->priv->xoverlay,
- GDK_WINDOW_XID (window));
+ gst_x_overlay_set_xwindow_id (gcc->priv->xoverlay,
+ GDK_WINDOW_XID (gcc->priv->video_window));
#endif
-
- GST_INFO ("\nSetting Source size: %d", gcc->priv->video_width);
- gst_video_widget_set_source_size (GST_VIDEO_WIDGET
- (gcc->priv->video_window),
- gcc->priv->video_width,
- gcc->priv->video_height);
- }
+ }
}
-
static int
gcc_parse_video_stream_info (GstCaps * caps, GstCameraCapturer * gcc)
{
@@ -816,18 +1194,16 @@ gcc_parse_video_stream_info (GstCaps * caps, GstCameraCapturer * gcc)
/* Get video decoder caps */
s = gst_caps_get_structure (caps, 0);
- if (s)
- {
- /* We need at least width/height and framerate */
- if (!
- (gst_structure_get_fraction
- (s, "framerate", &gcc->priv->video_fps_n, &gcc->priv->video_fps_d)
- && gst_structure_get_int (s, "width", &gcc->priv->video_width)
- && gst_structure_get_int (s, "height", &gcc->priv->video_height)))
- return -1;
- /* Get the movie PAR if available */
- gcc->priv->movie_par =
- gst_structure_get_value (s, "pixel-aspect-ratio");
- }
+ if (s) {
+ /* We need at least width/height and framerate */
+ if (!
+ (gst_structure_get_fraction
+ (s, "framerate", &gcc->priv->video_fps_n, &gcc->priv->video_fps_d)
+ && gst_structure_get_int (s, "width", &gcc->priv->video_width)
+ && gst_structure_get_int (s, "height", &gcc->priv->video_height)))
+ return -1;
+ /* Get the movie PAR if available */
+ gcc->priv->movie_par = gst_structure_get_value (s, "pixel-aspect-ratio");
+ }
return 1;
}
diff --git a/libcesarplayer/src/gst-camera-capturer.h b/libcesarplayer/src/gst-camera-capturer.h
index 0b2b13d..f6af702 100644
--- a/libcesarplayer/src/gst-camera-capturer.h
+++ b/libcesarplayer/src/gst-camera-capturer.h
@@ -59,7 +59,7 @@ struct _GstCameraCapturerClass
struct _GstCameraCapturer
{
- GtkHBox parent_instance;
+ GtkEventBox parent;
GstCameraCapturerPrivate *priv;
};
@@ -112,36 +112,32 @@ typedef enum
typedef enum
{
GCC_VIDEO_MUXER_AVI,
+ GCC_VIDEO_MUXER_MP4,
GCC_VIDEO_MUXER_MATROSKA,
GCC_VIDEO_MUXER_OGG
} GccVideoMuxerType;
-EXPORT GType
-gst_camera_capturer_get_type (void)
- G_GNUC_CONST;
-
- EXPORT void gst_camera_capturer_init_backend (int *argc, char ***argv);
- EXPORT GstCameraCapturer *gst_camera_capturer_new (gchar * filename,
- GError ** err);
- EXPORT void gst_camera_capturer_run (GstCameraCapturer * gcc);
- EXPORT void gst_camera_capturer_start (GstCameraCapturer * gcc);
- EXPORT void gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc);
- EXPORT void gst_camera_capturer_stop (GstCameraCapturer * gcc);
- EXPORT gboolean gst_camera_capturer_set_video_encoder (GstCameraCapturer
- * gcc,
- GccVideoEncoderType
- type);
- EXPORT gboolean gst_camera_capturer_set_audio_encoder (GstCameraCapturer
- * gcc,
- GccAudioEncoderType
- type);
- EXPORT gboolean gst_camera_capturer_set_video_muxer (GstCameraCapturer *
- gcc,
- GccVideoMuxerType
- type);
-
-
+EXPORT GType gst_camera_capturer_get_type (void) G_GNUC_CONST;
+
+EXPORT void gst_camera_capturer_init_backend (int *argc, char ***argv);
+EXPORT GstCameraCapturer *gst_camera_capturer_new (gchar * filename,
+ GError ** err);
+EXPORT void gst_camera_capturer_run (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_close (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_start (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_toggle_pause (GstCameraCapturer * gcc);
+EXPORT void gst_camera_capturer_stop (GstCameraCapturer * gcc);
+EXPORT gboolean gst_camera_capturer_set_video_encoder (GstCameraCapturer * gcc,
+ GccVideoEncoderType type,
+ GError ** err);
+EXPORT gboolean gst_camera_capturer_set_audio_encoder (GstCameraCapturer * gcc,
+ GccAudioEncoderType type,
+ GError ** err);
+EXPORT gboolean gst_camera_capturer_set_video_muxer (GstCameraCapturer * gcc,
+ GccVideoMuxerType type,
+ GError ** err);
+EXPORT GValueArray gst_camera_capturer_enum_devices (GstCameraCapturer * gcc);
G_END_DECLS
#endif /* _GST_CAMERA_CAPTURER_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]