summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Adam <jakub.adam@collabora.com>2019-09-03 13:00:30 +0200
committerDavid King <amigadave@amigadave.com>2020-09-21 10:01:20 +0100
commit58de82b3d463b69f4c0bef75667e47020924e28b (patch)
tree3d7f6b50a2e2558e16c8688c3022b35907b15098
parentd2e32b97a055814af5f620d19ba49ea937730e57 (diff)
downloadcheese-58de82b3d463b69f4c0bef75667e47020924e28b.tar.gz
Support camera video formats with MJPEG output
This enables higher resolutions and framerates with cameras like Logitech C910, which can do e.g. 1920x1080 @ 30fps, but only through image/jpeg output. https://gitlab.gnome.org/GNOME/cheese/-/merge_requests/17 https://gitlab.gnome.org/GNOME/cheese/-/issues/28
-rw-r--r--libcheese/cheese-camera-device.c5
-rw-r--r--libcheese/cheese-camera.c55
2 files changed, 48 insertions, 12 deletions
diff --git a/libcheese/cheese-camera-device.c b/libcheese/cheese-camera-device.c
index 08a0a26a..34b846a5 100644
--- a/libcheese/cheese-camera-device.c
+++ b/libcheese/cheese-camera-device.c
@@ -70,8 +70,9 @@ GST_DEBUG_CATEGORY (cheese_camera_device_cat);
#define GST_CAT_DEFAULT cheese_camera_device_cat
static const gchar * const supported_formats[] = {
- "video/x-raw",
- NULL
+ "video/x-raw",
+ "image/jpeg",
+ NULL
};
/* FIXME: make this configurable */
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index 7aa38066..c6cb44a2 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -351,6 +351,25 @@ cheese_camera_detect_camera_devices (CheeseCamera *camera)
}
/*
+ * cheese_camera_on_decodebin_pad_added:
+ * @camera: a #CheeseCamera
+ * @pad: new decode bin #GstPad
+ *
+ * A callback fired when a new source pad appears on the video source decodebin.
+ * Exposes the pad as the source pad of @video_source #GstBin.
+ */
+static void
+cheese_camera_on_decodebin_pad_added (CheeseCamera *camera, GstPad *pad)
+{
+ CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
+ GstPad *ghostpad;
+
+ ghostpad = gst_element_get_static_pad (priv->video_source, "src");
+ gst_ghost_pad_set_target (GST_GHOST_PAD (ghostpad), pad);
+ gst_object_unref (ghostpad);
+}
+
+/*
* cheese_camera_set_camera_source:
* @camera: a #CheeseCamera
*
@@ -363,11 +382,9 @@ static gboolean
cheese_camera_set_camera_source (CheeseCamera *camera)
{
CheeseCameraPrivate *priv = cheese_camera_get_instance_private (camera);
-
- guint i;
- CheeseCameraDevice *selected_camera;
- GstElement *src, *filter;
- GstPad *srcpad;
+ guint i;
+ CheeseCameraDevice *selected_camera;
+ GstElement *src, *filter, *decodebin;
if (priv->video_source)
gst_object_unref (priv->video_source);
@@ -399,12 +416,16 @@ cheese_camera_set_camera_source (CheeseCamera *camera)
filter = gst_element_factory_make ("capsfilter", "video_source_filter");
gst_bin_add (GST_BIN (priv->video_source), filter);
- gst_element_link (src, filter);
+ decodebin = gst_element_factory_make ("decodebin", NULL);
+ g_signal_connect_swapped (decodebin, "pad-added",
+ G_CALLBACK (cheese_camera_on_decodebin_pad_added),
+ camera);
+ gst_bin_add (GST_BIN (priv->video_source), decodebin);
+
+ gst_element_link_many (src, filter, decodebin, NULL);
- srcpad = gst_element_get_static_pad (filter, "src");
- gst_element_add_pad (priv->video_source,
- gst_ghost_pad_new ("src", srcpad));
- gst_object_unref (srcpad);
+ gst_element_add_pad (priv->video_source,
+ gst_ghost_pad_new_no_target ("src", GST_PAD_SRC));
return TRUE;
}
@@ -746,9 +767,23 @@ cheese_camera_set_new_caps (CheeseCamera *camera)
if (!gst_caps_is_empty (caps))
{
+ guint i;
+
GST_INFO_OBJECT (camera, "SETTING caps %" GST_PTR_FORMAT, caps);
g_object_set (gst_bin_get_by_name (GST_BIN (priv->video_source),
"video_source_filter"), "caps", caps, NULL);
+
+ /* If the selected caps are image/jpeg, video_source will convert them
+ * to raw video internally. Therefore, camerabin should always use
+ * video/x-raw regardless of the caps passed to video_source_filter. */
+ caps = gst_caps_make_writable (caps);
+
+ for (i = 0; i != gst_caps_get_size (caps); ++i)
+ {
+ gst_structure_set_name (gst_caps_get_structure (caps, i),
+ "video/x-raw");
+ }
+
g_object_set (priv->camerabin, "viewfinder-caps", caps,
"image-capture-caps", caps, NULL);