From 58de82b3d463b69f4c0bef75667e47020924e28b Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Tue, 3 Sep 2019 13:00:30 +0200 Subject: 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 --- libcheese/cheese-camera-device.c | 5 ++-- libcheese/cheese-camera.c | 55 ++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 12 deletions(-) (limited to 'libcheese') 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 @@ -350,6 +350,25 @@ cheese_camera_detect_camera_devices (CheeseCamera *camera) cheese_camera_device_monitor_coldplug (priv->monitor); } +/* + * 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); -- cgit v1.2.1