[cheese] Some other step towards better cap handling



commit 7a54c29574f5f3a756d8e2e5d20818204ab3be68
Author: Filippo Argiolas <filippo argiolas gmail com>
Date:   Sun Dec 13 12:26:27 2009 +0100

    Some other step towards better cap handling
    
    Boxify CheeseVideoFormat. Add some convenience method for getting caps
    from formats.

 libcheese/cheese-camera-device.c |   44 ++++++++++++++++++-
 libcheese/cheese-camera-device.h |    6 ++-
 libcheese/cheese-camera.c        |   87 ++++++++++++++++++++++++++++----------
 libcheese/cheese-camera.h        |    2 +-
 4 files changed, 111 insertions(+), 28 deletions(-)
---
diff --git a/libcheese/cheese-camera-device.c b/libcheese/cheese-camera-device.c
index 4fb5f18..ac9a91f 100644
--- a/libcheese/cheese-camera-device.c
+++ b/libcheese/cheese-camera-device.c
@@ -19,6 +19,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
 #ifdef HAVE_CONFIG_H
   #include <cheese-config.h>
 #endif
@@ -61,6 +62,37 @@ typedef struct
   GList *formats;
 } CheeseCameraDevicePrivate;
 
+
+/* CheeseVideoFormat */
+
+static CheeseVideoFormat*
+cheese_video_format_copy (const CheeseVideoFormat *format)
+{
+  return g_slice_dup (CheeseVideoFormat, format);
+}
+
+static void
+cheese_video_format_free (CheeseVideoFormat *format)
+{
+  if (G_LIKELY (format != NULL))
+    g_slice_free (CheeseVideoFormat, format);
+}
+
+GType
+cheese_video_format_get_type (void)
+{
+  static GType our_type = 0;
+
+  if (G_UNLIKELY (our_type == 0))
+    our_type =
+      g_boxed_type_register_static ("CheeseVideoFormat",
+                                    (GBoxedCopyFunc) cheese_video_format_copy,
+                                    (GBoxedFreeFunc) cheese_video_format_free);
+  return our_type;
+}
+
+/* the rest */
+
 static gint
 compare_formats (gconstpointer a, gconstpointer b)
 {
@@ -104,7 +136,7 @@ cheese_camera_device_add_format (CheeseCameraDevice *device, CheeseVideoFormat *
 }
 
 static void
-free_formats_list (CheeseCameraDevice *device)
+free_format_list (CheeseCameraDevice *device)
 {
   CheeseCameraDevicePrivate *priv =
     CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
@@ -130,7 +162,7 @@ cheese_webcam_device_update_format_table (CheeseCameraDevice *device)
    * merely perceivable refresh reate gain. I'd say let's throw away
    * everything over 30/1 */
 
-  free_formats_list (device);
+  free_format_list (device);
 
   num_structures = gst_caps_get_size (priv->caps);
   for (i = 0; i < num_structures; i++)
@@ -280,7 +312,8 @@ cheese_camera_device_finalize (GObject *object)
   g_free (priv->src);
   g_free (priv->name);
 
-  // free_formats_list (priv->formats);
+  gst_caps_unref (priv->caps);
+  free_format_list (device);
 }
 
 static void
@@ -379,6 +412,11 @@ const gchar *cheese_camera_device_get_device_file (CheeseCameraDevice *device)
   return priv->device;
 }
 
+CheeseVideoFormat *cheese_camera_device_get_best_format (CheeseCameraDevice *device)
+{
+  return (CheeseVideoFormat *) cheese_camera_device_get_format_list (device)->data;
+}
+
 GstCaps *cheese_camera_device_get_caps_for_format (CheeseCameraDevice *device,
                                                    CheeseVideoFormat *format)
 {
diff --git a/libcheese/cheese-camera-device.h b/libcheese/cheese-camera-device.h
index ec9fcc4..fedf547 100644
--- a/libcheese/cheese-camera-device.h
+++ b/libcheese/cheese-camera-device.h
@@ -46,17 +46,21 @@ typedef struct
   GObjectClass parent_class;
 } CheeseCameraDeviceClass;
 
+#define CHEESE_TYPE_VIDEO_FORMAT (cheese_video_format_get_type ())
+
 typedef struct
 {
   int   width;
   int   height;
 } CheeseVideoFormat;
 
+GType cheese_video_format_get_type (void) G_GNUC_CONST;
+
 CheeseCameraDevice        *cheese_camera_device_new (void);
 GstCaps                   *cheese_camera_device_get_caps_for_format (CheeseCameraDevice *device,
                                                                      CheeseVideoFormat *format);
+CheeseVideoFormat         *cheese_camera_device_get_best_format (CheeseCameraDevice *device);
 
-GList                     *cheese_camera_device_get_readable_format_list (CheeseCameraDevice *device);
 const gchar               *cheese_camera_device_get_name (CheeseCameraDevice *device);
 const gchar               *cheese_camera_device_get_src (CheeseCameraDevice *device);
 const gchar               *cheese_camera_device_get_id (CheeseCameraDevice *device);
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index 9a567eb..aab40b9 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -97,6 +97,7 @@ enum
   PROP_0,
   PROP_VIDEO_WINDOW,
   PROP_DEVICE_NAME,
+  PROP_FORMAT,
   PROP_X_RESOLUTION,
   PROP_Y_RESOLUTION
 };
@@ -363,8 +364,9 @@ cheese_camera_get_camera_device_data (CheeseCamera       *camera,
       g_print ("Device: %s (%s)\n", name, devpath);
       pad  = gst_element_get_pad (src, "src");
       caps = gst_pad_get_caps (pad);
-      gst_object_unref (pad);
       g_object_set (G_OBJECT (device), "caps", caps, NULL);
+
+      gst_object_unref (pad);
       gst_caps_unref (caps);
     }
     gst_element_set_state (pipeline, GST_STATE_NULL);
@@ -424,14 +426,14 @@ cheese_camera_create_camera_source_bin (CheeseCamera *camera)
   GError *err = NULL;
   char   *camera_input;
 
-  GstCaps *caps;
-
   if (priv->num_camera_devices == 0)
   {
     priv->camera_source_bin = gst_parse_bin_from_description (
       "videotestsrc name=video_source ! capsfilter name=capsfilter ! identity",
       TRUE,
       &err);
+    priv->video_source = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "video_source");
+    priv->capsfilter   = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "capsfilter");
   }
   else
   {
@@ -458,12 +460,20 @@ cheese_camera_create_camera_source_bin (CheeseCamera *camera)
     CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
     format->width = priv->x_resolution;
     format->height = priv->y_resolution;
-    caps = cheese_camera_device_get_caps_for_format (selected_camera, format);
+    GstCaps *caps = cheese_camera_device_get_caps_for_format (selected_camera, format);
+    g_free (format);
 
     if (gst_caps_is_empty (caps))
     {
+      g_warning ("CAPS_ARE_EMPTY");
       gst_caps_unref (caps);
-      g_object_get (G_OBJECT (selected_camera), "caps", &caps, NULL);
+      format = cheese_camera_device_get_best_format (selected_camera);
+      caps = cheese_camera_device_get_caps_for_format (selected_camera, format);
+      if (gst_caps_is_empty (caps)) {
+        g_warning ("CAPS_ARE_STILL_EMPTY");
+        gst_caps_unref (caps);
+        goto fallback;
+      }
     }
 
     camera_input = g_strdup_printf (
@@ -475,19 +485,20 @@ cheese_camera_create_camera_source_bin (CheeseCamera *camera)
 
     priv->camera_source_bin = gst_parse_bin_from_description (camera_input,
                                                               TRUE, &err);
+
     g_free (camera_input);
 
-    if (priv->camera_source_bin == NULL)
+    if (priv->camera_source_bin == NULL) {
+      gst_caps_unref (caps);
       goto fallback;
-  }
-
-  priv->video_source = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "video_source");
-  priv->capsfilter   = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "capsfilter");
+    }
 
-  GST_ERROR ("caps are %" GST_PTR_FORMAT, caps);
+    priv->video_source = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "video_source");
+    priv->capsfilter   = gst_bin_get_by_name (GST_BIN (priv->camera_source_bin), "capsfilter");
+    g_object_set (G_OBJECT (priv->capsfilter), "caps", caps, NULL);
+    gst_caps_unref (caps);
 
-  g_object_set (G_OBJECT (priv->capsfilter), "caps", caps, NULL);
-  gst_caps_unref (caps);
+  }
 
   return TRUE;
 
@@ -1075,6 +1086,9 @@ cheese_camera_get_property (GObject *object, guint prop_id, GValue *value,
     case PROP_DEVICE_NAME:
       g_value_set_string (value, priv->device_name);
       break;
+    case PROP_FORMAT:
+      g_value_set_boxed (value, priv->current_format);
+      break;
     case PROP_X_RESOLUTION:
       g_value_set_int (value, priv->x_resolution);
       break;
@@ -1107,11 +1121,8 @@ cheese_camera_set_property (GObject *object, guint prop_id, const GValue *value,
       g_free (priv->device_name);
       priv->device_name = g_value_dup_string (value);
       break;
-    case PROP_X_RESOLUTION:
-      priv->x_resolution = g_value_get_int (value);
-      break;
-    case PROP_Y_RESOLUTION:
-      priv->y_resolution = g_value_get_int (value);
+    case PROP_FORMAT:
+      cheese_camera_set_video_format (self, g_value_get_boxed (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1163,6 +1174,14 @@ cheese_camera_class_init (CheeseCameraClass *klass)
                                                         "",
                                                         G_PARAM_READWRITE));
 
+  g_object_class_install_property (object_class, PROP_FORMAT,
+                                   g_param_spec_boxed ("format",
+                                                       NULL,
+                                                       NULL,
+                                                       CHEESE_TYPE_VIDEO_FORMAT,
+                                                       G_PARAM_READWRITE));
+
+
   g_object_class_install_property (object_class, PROP_X_RESOLUTION,
                                    g_param_spec_int ("x-resolution",
                                                      NULL,
@@ -1320,21 +1339,43 @@ cheese_camera_get_video_formats (CheeseCamera *camera)
 //  return cheese_camera_device_get_readable_format_list (device);
 }
 
+gboolean
+cheese_camera_is_playing (CheeseCamera *camera)
+{
+  CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
+  return priv->pipeline_is_playing;
+}
+
 void
 cheese_camera_set_video_format (CheeseCamera *camera, CheeseVideoFormat *format)
 {
 #if 0
   CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
+  GstCaps *caps;
 
-  GstCaps *caps = cheese_camera_device_get_caps_for_format (priv->selected_camera, format);
+  if ((format->width == priv->current_format->width) &&
+      (format->height == priv->current_format->height)) {
+    goto out;
+  }
 
-  cheese_camera_stop (camera);
-  g_object_set (priv->capsfilter, "caps", caps, NULL);
-  cheese_camera_play (camera);
+  caps = cheese_camera_device_get_caps_for_format (selected_camera, format);
+
+  if (cheese_camera_is_playing (camera)) {
+    /* shouldn't this be done async? */
+    cheese_camera_stop (camera);
+    g_object_set (priv->capsfilter, "caps", caps, NULL);
+    cheese_camera_play (camera);
+  } else {
+    g_object_set (priv->capsfilter, "caps", caps, NULL);
+  }
+out:
+  if (G_LIKELY (priv->current_format) != NULL) {
+    g_free (priv->current_format);
+  }
 #endif
 }
 
-CheeseVideoFormat *
+const CheeseVideoFormat *
 cheese_camera_get_current_video_format (CheeseCamera *camera)
 {
   CheeseCameraPrivate *priv = CHEESE_CAMERA_GET_PRIVATE (camera);
diff --git a/libcheese/cheese-camera.h b/libcheese/cheese-camera.h
index f7f15cf..3ed45d0 100644
--- a/libcheese/cheese-camera.h
+++ b/libcheese/cheese-camera.h
@@ -74,7 +74,7 @@ CheeseCamera *cheese_camera_new (GtkWidget *video_window,
                                  int        x_resolution,
                                  int        y_resolution);
 
-CheeseVideoFormat *cheese_camera_get_current_video_format (CheeseCamera *camera);
+const CheeseVideoFormat *cheese_camera_get_current_video_format (CheeseCamera *camera);
 void               cheese_camera_setup (CheeseCamera *camera, char *udi, GError **error);
 void               cheese_camera_play (CheeseCamera *camera);
 void               cheese_camera_stop (CheeseCamera *camera);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]