Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gstreamer encoder #3706

Closed
totaam opened this issue Dec 11, 2022 · 17 comments
Closed

gstreamer encoder #3706

totaam opened this issue Dec 11, 2022 · 17 comments
Labels
encoding enhancement New feature or request

Comments

@totaam
Copy link
Collaborator

totaam commented Dec 11, 2022

Worth a try.
We already have appsink and appsrc working code so it should be possible to feed BGRX or YUV420P to a video encoder (initially x264) and get the stream as output.
This can be used for testing hardware encoders and see what the difference is with libva (#451): perhaps this one won't lock up the system quite so easily?

If that pans out, we can try to feed the pixel data to the pipeline without copying it.
It should be possible to implement this as an element in python:
Implementing an audio plotter
How to use Gstreamer AppSrc in Python

As for the pipeline option, there are some examples of gstreamer syntax that match what we already do with x264 in Cython code:
Realtime/zero-latency video stream: what codec parameters to use?

Element references:

Some information on EOS handling: How to wait for x264enc to encode buffered frames on end-of-stream

@totaam
Copy link
Collaborator Author

totaam commented Dec 13, 2022

Works pretty well!
Still TODO:

  • seems to be re-cycled too often - and this is more expensive than with the plain x264 encoder
  • define gpu / cpu costs in encoder spec
  • find image input size limits dynamically
  • avoid concatenating the YUV planes into a single buffer somehow? (or perhaps hack it so that csc_libyuv spits out YUV420 without the P in a single buffer, unpadded)
  • verify that Gst.Buffer.new_wrapped_full does what we want, without leaking - referencing memory without refcounting it
  • test on more hardware - even on AMD?
  • test with other elements: nvh264enc / nvautogpuh264enc / nvcudah264enc,
  • this element only accepts I420 input - how can we use even pseudo-lossless without 444?
  • tune encoder settings based on our speed and quality knobs
  • try to support B-frames?
  • implement simple decoder? ie: vaapidecode or even nvh264dec? could support hardware decoding quite easily - but not sure about opengl buffer sharing..
  • implement a csc module using videoconvert? or even cudaconvert

totaam added a commit that referenced this issue Dec 14, 2022
hard-coded for vp8 for now - just a PoC
totaam added a commit that referenced this issue Dec 15, 2022
totaam added a commit that referenced this issue Dec 15, 2022
totaam added a commit that referenced this issue Dec 15, 2022
@totaam
Copy link
Collaborator Author

totaam commented Dec 15, 2022

The commits above allows us to add av1 encoding almost for free, and h264 via avcodec.
But there are also some new issues:

  • the performance of these encoders is vastly different: av1enc is unbearably slow..
  • not all encoders can be tuned for zerolatency and not buffer frames..
  • out private ffmpeg library conflicts with the one gstreamer links against... perhaps time to drop it?
    • csc: RPM distros still have libyuv
    • encoders: the new gstreamer encoder is already more useful than the ffmpeg one
    • decoding: the h264 avcodec decoder would be missed - perhaps the gstreamer avcodec decoder can take its place if we find a way to avoid copying the YUV pixel data: either handling the opengl pixel upload via gstreamer's GstVideoGLTextureUploadMeta, or taking buffer ownership?

The trick for decoding raw h264 NALs was found here: https://discourse.gnome.org/t/gstreamer-how-to-decode-h264-from-appsrc/10020/7

@totaam
Copy link
Collaborator Author

totaam commented Jan 6, 2023

This is likely to sway the decision of how to deal with ffmpeg conflicts between our private library and the one used by gstreamer: F37 Xorg server processes crashes with nvidia drivers installed and the gstreamer encoder:

xpra start --no-daemon :200
(..)
2023-01-06 10:32:12,756 31.3GB of system memory
Xorg: ../../../include/privates.h:121: dixGetPrivateAddr: Assertion `key->initialized' failed.
(EE) 
(EE) Backtrace:
(EE) 0: /usr/libexec/Xorg (OsLookupColor+0x13d) [0x5649171fe0bd]
(EE) 1: /lib64/libc.so.6 (__sigaction+0x50) [0x7f35b5aa2b50]
(EE) 2: /lib64/libc.so.6 (__pthread_kill_implementation+0x10c) [0x7f35b5af2e7c]
(EE) 3: /lib64/libc.so.6 (gsignal+0x16) [0x7f35b5aa2aa6]
(EE) 4: /lib64/libc.so.6 (abort+0xd7) [0x7f35b5a8c7fc]
(EE) 5: /lib64/libc.so.6 (__assert_fail_base.cold+0xf) [0x7f35b5a8c71b]
(EE) 6: /lib64/libc.so.6 (__assert_fail+0x46) [0x7f35b5a9b656]
(EE) 7: /usr/libexec/Xorg (SrvXkbResizeKeyType+0x825) [0x5649171c6a25]
(EE) 8: /usr/libexec/Xorg (DRI2Authenticate+0xb5) [0x5649171c70d5]
(EE) 9: /usr/libexec/Xorg (DRI2ScreenInit+0x8e1) [0x5649171c9b91]
(EE) 10: /usr/libexec/Xorg (miPutImage+0x163d) [0x56491708bdb4]
(EE) 11: /lib64/libc.so.6 (__libc_start_call_main+0x80) [0x7f35b5a8d510]
(EE) 12: /lib64/libc.so.6 (__libc_start_main+0x89) [0x7f35b5a8d5c9]
(EE) 13: /usr/libexec/Xorg (_start+0x25) [0x56491708c0f5]
(EE) 
(EE) 
Fatal server error:
(EE) Caught signal 6 (Aborted). Server aborting
(EE) 
(EE) 
Please consult the The X.Org Foundation support 
	 at http://wiki.x.org
 for help. 
(EE) Please also check the log file at "./Xorg.log" for additional information.
(EE) 
(EE) Server terminated with error (1). Closing log file.
X connection to :200 broken (explicit kill or server shutdown).
X connection to :200 broken (explicit kill or server shutdown).

Similar to #2764 : segfault in OsLookupColor : OsLookupColor is just a default function the backtracer seems to pick up when it craps itself out
Edit: this happened again today after applying the system updates.

totaam added a commit that referenced this issue Jan 10, 2023
totaam added a commit that referenced this issue Jan 12, 2023
totaam added a commit that referenced this issue Jan 12, 2023
doesn't seem to work, even with 'nvidia-vaapi-driver' installed
This was referenced Jan 29, 2023
totaam added a commit that referenced this issue Feb 1, 2023
as it would be checked using isinstance by the window video source
totaam added a commit that referenced this issue Feb 2, 2023
we can't specify the input image's rowstride, so this is the best we can do
totaam added a commit that referenced this issue Feb 2, 2023
(not done yet for YUV input)
totaam added a commit that referenced this issue Feb 3, 2023
@totaam
Copy link
Collaborator Author

totaam commented Feb 14, 2023

Interesting, it may soon be possible to use vaapi via WSL2: Microsoft Officially Launches D3D12 GPU Video Acceleration For WSL Linux Use

totaam added a commit that referenced this issue Feb 18, 2023
but do provide an environment variable to override this which is also useful on Linux to disable a potentially crashy element
@totaam totaam mentioned this issue Feb 21, 2023
@totaam
Copy link
Collaborator Author

totaam commented Apr 10, 2023

Do we need to set the GstVideoColorimetry to full range? ffmpeg does it.
gst_video_color_range_offsets: https://github.com/GStreamer/gst-plugins-base/blob/ce937bcb21412d7b3539a2da0509cc96260562f8/gst-libs/gst/video/video-color.c#L204
Set GstVideoInfo using caps?

For x264enc, we should also handle bandwidth limits by switching to [cbr mode] (https://gstreamer.freedesktop.org/documentation/x264/index.html?gi-language=c#GstX264EncPass) and still set qp-max?
Only use intra-refresh when bandwidth is limited? (with lossy transports?)

totaam added a commit that referenced this issue Apr 14, 2023
totaam added a commit that referenced this issue Apr 14, 2023
totaam added a commit that referenced this issue Apr 14, 2023
totaam added a commit that referenced this issue Apr 14, 2023
and handle NV12 output pixel format
totaam added a commit that referenced this issue Apr 14, 2023
as it has context limit issues that can trip up the tests or unsuspecting users
totaam added a commit that referenced this issue Apr 14, 2023
totaam added a commit that referenced this issue Apr 14, 2023
so we can re-use the same code for screen capture and bus messages
totaam added a commit that referenced this issue Apr 14, 2023
@totaam
Copy link
Collaborator Author

totaam commented Apr 14, 2023

We can also do nvenc via gstreamer, but this is currently disabled by default:

NVENC = envbool("XPRA_GSTREAMER_NVENC", False)

Because when we hit the artificial context limit on consumer cards, the gstreamer pipeline will just timeout instead of erroring out quickly - which is problematic. The error can be seen at higher debug logging levels.

totaam added a commit that referenced this issue Apr 15, 2023
despite showing it in the caps options for vaapih264enc
totaam added a commit that referenced this issue Apr 15, 2023
totaam added a commit that referenced this issue Apr 15, 2023
@totaam
Copy link
Collaborator Author

totaam commented Apr 21, 2023

Testing the same version of the code that works perfectly on an old Skylake laptop, this time on a brand new Intel Corporation DG2 [Arc A770] and the GStreamer pipelines now fail 😞

$ gst-launch-1.0 videotestsrc ! videoconvert ! vaapih264enc ! fakesink
ERROR: from element /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0: Internal data stream error.

Judging by my searches, it could be anything and that's a common problem with vaapi..
Perhaps I should upgrade to Fedora 38 - but then I would no longer be able to test anything NVidia related: #3808

@algeorge
Copy link

algeorge commented Aug 2, 2023

I'd like to check the current status of Xpra encoding and decoding with Intel QuickSync. I could not find any information on the internet as this is a rapidly moving project.

Does it work via vaapi through gstreamer? Apologies if this is the wrong place for this but I've looked everywhere I can.

@totaam
Copy link
Collaborator Author

totaam commented Aug 2, 2023

@algeorge the gstreamer encoder in this ticket is included in all v5 official builds (currently in the beta area only) but it is disabled by default:

video-encoders = all,-gstreamer

In the future, I would like to add utilities to make it easier for end users to test and enable the pipeline combinations that work best on their specific hardware.
For now, this is a manual process.

@algeorge
Copy link

algeorge commented Aug 2, 2023

@totaam

Manual is great! Because it even works!

As far as settings to pass through, are there any options for gstreamer anywhere? To modify colorspace, bit-depth, quality, bitrate... etc. Or is that handled as part of the regular Xpra profile as written in the referenced conf file. I'd like to know if "profiles" can be made for certain connections using Gstreamer passthrough.

@algeorge
Copy link

algeorge commented Aug 2, 2023

As for the pipeline option, there are some examples of gstreamer syntax that match what we already do with x264 in Cython code:
Realtime/zero-latency video stream: what codec parameters to use?

I would like to add that this depends on the encoder which is why I am so interested in QuickSync. MJPEG has a sub 1ms latency for encoding with a fairly high bitrate. MPEG2 is in the same ballpark with latency because the codec is so simple.

@totaam
Copy link
Collaborator Author

totaam commented Aug 4, 2023

We used to have MPEG1 and MPEG2 support via the ffmpeg encoder, but this was removed recently.
The trade-offs and limitations were just no longer justifiable compared to modern codecs.
For tuning the ffmpeg encoder, we can use the link you posted and also this one: https://github.com/selkies-project/selkies-gstreamer/blob/master/src/selkies_gstreamer/gstwebrtc_app.py as a base.
But the key thing that allows xpra to perform so well is its ability to dynamically tune encoder settings to better adapt to content and bandwidth conditions.
This is more tricky to implement when the exact pipelines vary. This will take time.

@totaam
Copy link
Collaborator Author

totaam commented Aug 15, 2023

Will follow up in #3964

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
encoding enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants