diff --git a/src/Widgets/CameraView.vala b/src/Widgets/CameraView.vala index 765c04b53..70b1a7ac0 100644 --- a/src/Widgets/CameraView.vala +++ b/src/Widgets/CameraView.vala @@ -211,7 +211,10 @@ public class Camera.Widgets.CameraView : Gtk.Box { for (uint i = 0; i < caps.get_size (); i++) { unowned var s = caps.get_structure (i); - if (s.get_name () == "image/jpeg") { + // Consider raw modes too: some cameras (e.g. the PCIe FaceTime + // HD on 2015 MacBook Pros) offer no JPEG caps at all, and the + // 640×480 fallback distorts photos from 16:9-only sensors + if (s.get_name () == "image/jpeg" || s.get_name () == "video/x-raw") { int w, h; s.get_int ("width", out w); s.get_int ("height", out h); @@ -246,6 +249,14 @@ public class Camera.Widgets.CameraView : Gtk.Box { videorate.drop_only = true; dynamic Gst.Element gtksink = Gst.ElementFactory.make ("gtk4paintablesink", "sink"); + if (gtksink == null) { + // Without this check the preview silently stays black while + // capture keeps working, since the preview branch dead-ends + // behind the leaky queue + string[] messages = { Gst.PbUtils.missing_element_installer_detail_new ("gtk4paintablesink") }; + Gst.PbUtils.install_plugins_async (messages, null, (result) => {}); + throw new IOError.NOT_FOUND ("Missing GStreamer element \"gtk4paintablesink\""); + } pipeline.add (gtksink); pipeline.get_by_name ("videoscale").link (gtksink); @@ -347,6 +358,14 @@ public class Camera.Widgets.CameraView : Gtk.Box { var encoder = Gst.ElementFactory.make ("vp8enc", null); if (encoder == null) { missing_messages += Gst.PbUtils.missing_element_installer_detail_new ("vp8enc"); + } else { + // vp8enc defaults (256 kbps target, exhaustive-quality deadline) + // cannot encode HD in real time: frames drop and quality collapses + encoder["deadline"] = (int64) 1; + encoder["cpu-used"] = 4; + encoder["threads"] = (int) GLib.get_num_processors (); + encoder["keyframe-max-dist"] = 60; + encoder["target-bitrate"] = picture_width * picture_height * 4; } var muxer = Gst.ElementFactory.make ("webmmux", null);