Commit Graph

29 Commits

Author SHA1 Message Date
Jonas Dreßler
9cb40c4814 screencastService: Add fallback mechanism for gstreamer pipelines
Introduce a fallback mechanism for gstreamer pipelines that allows to
define multiple pipelines and prefer them over each other.

The way this works is that we introduce a new STARTING PipelineState.
While the Recorder is in that state, it is allowed to tear down the
current pipeline and start another one whenever an error happens, this is
used to try multiple pipelines in a fixed order until a working one is
found.

Right now there's just a single pipeline using the existing vp8 encoder, the
actual new encoders and pipelines will be added in a separate commit.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2609>
2023-04-26 11:39:16 +02:00
robert.mader@collabora.com
46517e02dd screencastService: Drop always-copy condition
The check for the Pipewire version was originally introduced in
d32c0348 which states:
> Since it is not clear yet when a proper solution will arrive,
> this makes use of `always-copy` as a workaround for now and
> should be reverted once it is no longer needed.

The check for a stable Gstreamer version with the mention proper fix was
introduced in d7b44319 and carried for the 43 cycle.

By the time Gnome 44 will be released all distros should have had enough
time to update their Gstreamer version - or backport the patches, in
case of not ustream-supported versions.

Thus lets drop it now.

Note: `always-copy` is not suitable for dmabuf buffers as it copies via
mmap.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2609>
2023-04-25 20:28:28 +02:00
Jonas Dreßler
cad01d154c screencastService: Set PipelineState to PLAYING on actual state-change
Right now when we tell gstreamer to move the pipeline to the state
PLAYING, we pretend that happens immediately and set our PipelineState
to PLAYING right afterwards.

In reality though it's more complicated than that: Gstreamer changes
states asynchronously and set_state() returns a Gst.StateChangeReturn.ASYNC.
In that case we should wait until the according STATE_CHANGED event happens
on the bus, and only then set our PipelineState to PLAYING.

Since the STATE_CHANGED event will also happen when set_state() returns
SUCCESS, we can use the same async logic for that.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
2023-04-25 18:57:51 +02:00
Jonas Dreßler
42af7e53a2 screencastService: Handle more gstreamer errors
Gstreamer can produce various errors, we shouldn't pretend those don't
exist and go on as usual when one happens. Instead, when an error
happens, tear down the pipeline, set our PipelineState to the new ERROR
state and bail out with a proper error message.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
2023-04-25 18:57:47 +02:00
Jonas Dreßler
cbfbdc4be5 screencastService: Streamline teardown and error handling
We're tracking three different state-machines in the Recorder object:
The state of the gstreamer pipeline, the state of the screencast
session, and the sender of our dbus invocation that might vanish.

Properly handling errors that might appear in any of those three "black
boxes" is not easy, especially tearing down the other two when one of
them breaks.

So refactor the error handling here: Add a single error path for each of
those three states we're tracking, and make them all subsequently call
the _bailOutOnError() method. From there we tear down the other states and
call the error callbacks.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
2023-04-25 17:17:41 +02:00
Jonas Dreßler
e6196b5b9f screencastService: Add an ERROR state for the pipeline state tracking
This will be useful when we start actually listening for ERROR events on
the gstreamer bus.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
2023-04-25 17:17:41 +02:00
Jonas Dreßler
98cfce0ebe screencastService: Use strings for states
Using strings instead of numbers allows for easier debugging, it means
we can just log the state itself.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
2023-04-25 17:17:41 +02:00
Jonas Dreßler
9eea48536a screencastService: Promisify Recorder start/stopRecording functions
This will allow for cleaner error handling in the following commits.

A benefit we get from it right now is having one less callback when
calling startRecording/stopRecording().

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
2023-04-25 17:17:41 +02:00
Jonas Dreßler
617997412e screencastService: Handle case where no videos directory exists
The videos directory doesn't necessarily have to exist, users are free to
delete it. Right now we don't handle this case and screencasting fails.

Let's handle it and fall back to the users home directory instead when
xdg-videos doesn't exist.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2594>
2023-01-11 16:51:30 +00:00
Florian Müllner
a2acecb491 dbusService/screencast: Hold during gstreamer checks
Some gstreamer plugins require a connection to the display server,
so they block until the server is up and running. That's why we
moved the check into the D-Bus service, so that the blocking would
not lock up the compositor itself.

However the block can still delay the service initialization so
much that auto-shutdown hits immediately when returning from the
constructor. If that happens, the proxy on the shell side is no
longer backed by a remote object when the init callback runs, and
all properties therefore resolve as `null`.

As a result, gnome-shell thinks that screencasts aren't supported
and hides the screencast button.

Fix this by holding the service during the gstreamer checks, so
that the auto-shutdown timeout only starts after the service is
ready.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6051

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2533>
2022-11-09 11:15:04 +00:00
Florian Müllner
3cdcd075ef dbusServices/screencast: Check for all require elements
Instead of assuming that gst-plugins-good has been compiled with
all the plugins we need enabled, explicitly check for the ones
we use.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5710

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2519>
2022-11-04 09:51:20 +00:00
Florian Müllner
f266c2ca15 screenshot: Move HAVE_RECORDER check into screencast service
Some gstreamer plugins require a connection to the display server,
so if we end up initializing gstreamer before we are ourselves
fully initialized, we may end up with a locked compositor.

Avoid this by moving the runtime recorder check into the screencast
D-Bus service, so that all gstreamer calls happen out of process.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5710

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2519>
2022-11-04 09:51:20 +00:00
Sebastian Keller
d7b443197b screencast: Don't force buffer copies on recent gstreamer versions
Gstreamer 1.20.4 includes a fix in the videoconvert element that makes
it no longer necessary to always copy buffers in pipewiresrc to have
smooth recordings. This change now skips those otherwise unnecessary
copies when using a new enough videoconvert.

Related: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2928
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2503>
2022-10-20 13:56:47 +00:00
Sebastian Keller
d32c03488f screencast: Always copy buffers in pipewiresrc
Pipewire 0.3.52 via commit a1f33a99 introduced a change that affects how
long pipewiresrc holds onto the pw_buffers it dequeued. Before that
change the pw_buffer was held until the end of the videoconvert element
at the beginning of the pipeline. After that change the pw_buffer was
held onto until the filesink at the end of the pipeline. This was
starving MetaScreenCastStreamSrc of pw_buffers to record new frames
into, resulting in the majority of frames being missed, especially in
situations in which the encoder was taking longer.

Pipewire 0.3.57 via commit 1ea1d525 will allow queuing the pw_buffer
early again via the `always-copy` option. This however is only a
workaround until a proper solution is found in either pipewire or
gstreamer that does not depend on copying the buffer contents and
instead queues the pw_buffer again after videoconvert as prior to
a1f33a99.

Since it is not clear yet when a proper solution will arrive, this makes
use of `always-copy` as a workaround for now and should be reverted once
it is no longer needed.

Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5585
Related: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/2461
Related: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/283
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2436>
2022-09-03 15:15:31 +00:00
Alessandro Bono
b63c6ac0ef cleanup: Use deepUnpack() intead of deep_unpack()
deep_unpack() is just a backwards compability alias for deepUnpack()[1].
The new name makes it more clear that this is not a C function, start to
use it.

[1] 13e662a29d

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2416>
2022-08-10 10:29:24 +00:00
Emmanuele Bassi
317fa8222e screencast: Use the same format for screencasts and screenshot file names
Screenshots use `%Y-%m-%d %H-%M-%S` for the timestamp, which has the
advantage of allowing proper lexicographical sorting.

The screencast file name pattern, on the other hand, uses
locale-dependent expansions, which break sorting based on file name, and
introduces the chance of potentially invalid characters on different
file systems.

Fixes: #5115
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2300>
2022-07-27 13:50:10 +00:00
Evan Welsh
83c08e17cf dbusServices: Refactor service utilities from fileUtils into dbusUtils
To enable porting services to ECMAScript modules independently of
the shell, split DBus service utility functions into a new file,
dbusUtils.js

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2365>
2022-07-05 03:41:41 -04:00
Florian Müllner
a8c5d77872 dbusServices/screencast: Install unconditionally
We currently decide at build time whether to include screencast
support, based on whether the required gst/pipewire library headers
are installed.

That check is imprecise, because having the library headers available
at build time doesn't necessarily mean that the libraries are there
at runtime, or that the corresponding typelibs are installed.

It makes more sense to check the requirements at runtime, so prepare
for that by installing the screencast service unconditionally, but
bail out early if the dependencies aren't met.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2297>
2022-05-20 12:00:22 +00:00
Simon McVittie
7f4f328a7f Specify API versions for all public GIR APIs, except GLib
If one of these libraries breaks its GIR API in future, then upgrading
packages unrelated to gnome-shell might pull in the newer version,
causing gnome-shell to crash when it gets a newer GIR API that is
incompatible with its expectations. For example, this seems to be
happening in Debian testing at the moment, when GNOME Shell 41.4
imports GWeather and can get version 4.0 instead of the version 3.0 that
it expected.

Adding explicit API versions at the time the newer version is released
is too late, because that will still let the newer version of the GIR API
break pre-existing GNOME Shell packages. Prevent similar crashes in
future by making the desired versions explicit.

This is done for all third-party libraries except GLib, similar to the
common practice in Python code; if GLib breaks API, then that will be
a disruptive change to the whole GLib/GObject ecosystem, regardless.

Gvc, Meta, Shell, Shew, St are not included because they're private
(only exist in a non-default search path entry).

Clutter and Cogl *are* included, because we need to import the fork of
them that comes with Meta, as opposed to their deprecated standalone
versions.

Signed-off-by: Simon McVittie <smcv@debian.org>
Bug-Debian: https://bugs.debian.org/1008926
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2261>
2022-04-04 17:55:25 +01:00
Florian Müllner
00e41383c7 dbusServices/screencast: Removed unused properties
Those have been superseded by corresponding state enums.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2165>
2022-02-09 13:00:04 +01:00
Ivan Molodetskikh
0e4b87fe5a screencastService: Create directory if it doesn't exist
Instead of testing if the videos directory exists and using the home
directory otherwise, just try to create the target directory. This
aligns with how the screenshot UI handles the screenshots folder, and
it's convenient for putting screencasts into a subdirectory.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2102>
2022-01-14 18:42:47 +00:00
Florian Müllner
dc0491ade8 dbusServices/screencast: Handle pipeline failures gracefully
If parsing the pipeline fails for some reason, we currently end up
with a zombie session that leads to a stuck recording indicator in
gnome-shell.

Instead, properly tear down the session to allow mutter and gnome-shell
to correctly update their state.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1878>
2021-06-09 15:21:35 +00:00
Jonas Dreßler
51bf7ec176 screencastService: Improve the gstreamer pipeline for recording
The current gstreamer pipeline performs quite bad on slower machines and
is dropping lots of frames, improve the pipeline by changing a few
things:

- Use threads for videoconvert and improve speed of videoconvert by
disabling some unneeded things
- Add a queue before the encoding step, this allows the encoder to work
at its own pace and will lead to a lot more stability
- Remove the fixed quantizer and only set a max quantizer, this helps
quite a bit with performance
- Change the deadline parameter of vp8enc to 1: This makes the encoder
go into real time mode, which will make it a lot faster
- Set cpu-used to 16, the maximum possible value.
- Set static-threshold to 1000, static-threshold is the motion detection
threshold, and while a value of 100 is recommended for screencasting in
the gstreamer documentation (see [1]), using 1000 appears to perform a
lot better and still outputs fairly good quality
- Set a larger buffer size than the default size, this seems to get a
bit more stability during high load scenarios

All in all, those changes make the pipeline drop no more frames when
recording at 30 FPS and 2K screen resolution. That was tested on a
fairly recent mobile core-i5 processor.

Also, because we now have two %T replacement strings for the number of
threads, we need to switch to replaceAll(). For that to work, we have to
put the %T matching expression into quotes.

[1] https://gstreamer.freedesktop.org/documentation/vpx/GstVPXEnc.html?gi-language=c#GstVPXEnc:static-threshold

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1633>
2021-05-04 13:45:57 +00:00
Florian Müllner
2e9a2e68b7 dbusServices/screencast: Use GTK4
The separate screencast service has some minimal GTK usage, which
we can trivially move to GTK4.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1591>
2021-01-25 21:09:22 +01:00
Florian Müllner
8a47f1c667 cleanup: Remove empty leading/trailing lines in blocks
gjs added a new rule to its eslint ruleset that forbids "block padding",
so make sure we conform to that rule before syncing up the configuration.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1498
2020-11-16 18:04:23 +00:00
Florian Müllner
386d25e6f8 dbusServices/screencast: Add recordings to recent items
This is useful functionality that got lost when replacing the built-in
recorder with an external screencast service; bring it back.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3171
2020-09-14 21:15:13 +00:00
Florian Müllner
b3f35912be dbusServices/screencast: Save under resolved file path
... instead of using the original template as file name.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3097
2020-09-02 16:28:48 +02:00
Florian Müllner
9d6ccb6072 dbusServices/screencast: Quote filename in pipeline
Otherwise Gst fails to parse the pipeline string if the filename
contains spaces, as all words following the first are interpreted
as additional Gst elements.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1403
2020-08-11 11:50:44 +00:00
Jonas Ådahl
2b0731ab81 Move screencasting into a separate service process
Move the screencasting into a separate D-Bus service process, using
PipeWire instead of Clutter API. The service is implemented in
Javascript using the dbusService.js helper, and implements the same API
as was done by screencast.js and the corresponding C code.

https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1372
2020-07-31 10:51:12 +02:00