Re: Trying to turn on gstreamer vaapi {en,de}coding

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Sun, Nov 27, 2022 at 4:04 PM Victor Toso <victortoso@xxxxxxxxxx> wrote:
Hi,
On Fri, Nov 25, 2022 at 12:32:57PM +0000, Lévai, Dániel wrote:
> Hi all!
>
> First time here, and was a bit hesitant to post tbh, as this is
> not a "-devel" sort of thing, but reading through the posts
> here it seamed there have been some technical questions
> already, so I'm trying my luck. The post is a bit longwinded,
> it has a bunch of debug outputs and parameters in-line, please
> let me know if you prefer sharing these in another way.

It is fine to post it here.

> I'm using a couple of VMs with libvirt/qemu hosted on an Ubuntu
> 22.04.1 LTS, accessing them via Spice from an Arch system. The
> connection between Hypevisor and client are via Internet, so
> despite 'localhost' being the host in the tests/examples below,
> they don't actually run on the same system, it's just a tunnel
> via `stunnel`.

> What I wanted to do is speed up the display (drawing) so it
> won't lag that much when browsing through spreadsheets and
> using console (with small fonts, admittedly). The resolution
> also plays a role in this at 2560x1440 (only one spice
> display).

Note that host video encoding will lag a bit. This is what you
are trying. It should be better with spice-streaming-agent by
setting up a video card to the guest, an example:

    https://www.spice-space.org/demos.html#accelerated-spice-streaming-with-intel


> What I've tried already is changing the spice section in the domain configuration in libvirt:
>     <graphics type='spice' port='5912' autoport='no' listen='127.0.0.1'>
>       <listen type='address' address='127.0.0.1'/>
>       <image compression='auto_glz'/>
>       <jpeg compression='never'/>
>       <zlib compression='never'/>
>       <streaming mode='all'/>
>       <filetransfer enable='yes'/>
>       <gl enable='no'/>
>     </graphics>

> Which translates into this -spice qemu parameter:
> -spice port=5912,addr=127.0.0.1,disable-ticketing=on,image-compression=auto_glz,jpeg-wan-compression=never,zlib-glz-wan-compression=never,streaming-video=all,seamless-migration=on

> ... with the complete command as follows:
> /usr/bin/qemu-system-x86_64 -name guest=arch,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain-22-arch/master-key.aes"} -machine pc-q35-4.2,usb=off,vmport=off,dump-guest-core=off,memory-backend=pc.ram -accel kvm -cpu Cooperlake,ss=on,vmx=on,pdcm=on,hypervisor=on,tsc-adjust=on,sha-ni=on,umip=on,waitpkg=on,gfni=on,vaes=on,vpclmulqdq=on,rdpid=on,movdiri=on,movdir64b=on,fsrm=on,md-clear=on,avx-vnni=on,xsaves=on,ibpb=on,ibrs=on,amd-stibp=on,amd-ssbd=on,hle=off,rtm=off,avx512f=off,avx512dq=off,avx512cd=off,avx512bw=off,avx512vl=off,avx512vnni=off,avx512-bf16=off,taa-no=off -m 16384 -object {"qom-type":"memory-backend-ram","id":"pc.ram","size":17179869184} -overcommit mem-lock=off -smp 4,sockets=4,cores=1,threads=1 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=38,server=on,wait=off -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -no-shutdown -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 -boot strict=on -device pcie-root-port,port=16,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,addr=0x2 -device pcie-root-port,port=17,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 -device pcie-root-port,port=18,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 -device pcie-root-port,port=19,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x3 -device pcie-root-port,port=20,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x4 -device pcie-root-port,port=21,chassis=6,id=pci.6,bus=pcie.0,addr=0x2.0x5 -device pcie-root-port,port=22,chassis=7,id=pci.7,bus=pcie.0,addr=0x2.0x6 -device pcie-root-port,port=23,chassis=8,id=pci.8,bus=pcie.0,addr=0x2.0x7 -device qemu-xhci,p2=15,p3=15,id=usb,bus=pci.2,addr=0x0 -device virtio-serial-pci,id=virtio-serial0,bus=pci.3,addr=0x0 -blockdev {"driver":"file","filename":"/var/lib/libvirt/images/archlinux.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":false,"driver":"qcow2","file":"libvirt-2-storage","backing":null} -device virtio-blk-pci,bus=pci.4,addr=0x0,drive=libvirt-2-format,id=virtio-disk0,bootindex=1 -device ide-cd,bus=ide.0,id=sata0-0-0 -netdev tap,fd=39,id=hostnet0,vhost=on,vhostfd=41 -device virtio-net-pci,netdev=hostnet0,id=net0,bus=pci.1,addr=0x0 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev socket,id=charchannel0,fd=35,server=on,wait=off -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.0 -chardev spicevmc,id=charchannel1,name=vdagent -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1,name=com.redhat.spice.0 -device usb-tablet,id=input0,bus=usb.0,port=1 -device virtio-keyboard-pci,id=input2,bus=pci.7,addr=0x0 -device usb-mouse,id=input3,bus=usb.0,port=4 -audiodev {"id":"audio1","driver":"spice"} -spice port=5912,addr=127.0.0.1,disable-ticketing=on,image-compression=auto_glz,jpeg-wan-compression=never,zlib-glz-wan-compression=never,streaming-video=all,seamless-migration=on -device virtio-vga,id=video0,max_outputs=1,bus=pcie.0,addr=0x1 -device ich9-intel-hda,id=sound0,bus=pcie.0,addr=0x1b -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0,audiodev=audio1 -chardev spicevmc,id=charredir0,name=usbredir -device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2 -chardev spicevmc,id=charredir1,name=usbredir -device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3 -device virtio-balloon-pci,id=balloon0,bus=pci.5,addr=0x0 -object {"qom-type":"rng-random","id":"objrng0","filename":"/dev/urandom"} -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.6,addr=0x0 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on

> Basically, I thought turning 'streaming mode'/'streaming-video'
> to 'all' would make spice think it needs to stream the whole
> screen content regardless of its heuristics detecting a video
> stream.

I'm replying by memory here, so I might be a little off. But just
to add a bit more info. The streaming mode set to 'all' means
that all regions being updated too often in the Display are
included in one video stream that encapsulate those regions. The
'filter' mode, iirc, would split the different regions in
different video streams.

The whole screen streaming only happens if needed, even with
mode set to 'all'.

Only areas on the screen that are recognized as video are sent as video-stream, not
the whole screen.
IIRC, "all" is for all areas that are recognized, while "filter" does not stream small areas.
Every area/region has its own video-stream.

What you (Daniel) want is for qemu (+spice-server) to, at intervals, render the
whole screen, hardware-encode it and send it as a video stream to the client.
Currently, this feature is not implemented.
I think some years ago Frediano wrote some code that does that as an
experiment. IIRC, there was an issue with the gstreamer ORC library
running in the environment libvirt creates for the qemu-kvm process.


Regards,
    Uri


> I thought if I could enable HW encoding/decoding with
> these options, I'd get better performance out of it.

Yeah, that's a fair assumption. The main issue in general is with
latency that video encoding adds, be it software or hardware.

<snipped, package information>

>
> As part of troubleshooting here, I checked if I have the
> necessary codecs/encoders/decoders with gstreamer on the
> different systems:
>
> On the hypervisor host (with Intel Alderlake (12th gen) graphics):
>
> As my unrpivileged user:
> $ gst-inspect-1.0 |grep -F -i vaapi
> vaapi:  vaapiav1dec: VA-API AV1 decoder
> vaapi:  vaapidecodebin: VA-API Decode Bin
> vaapi:  vaapih264dec: VA-API H264 decoder
> vaapi:  vaapih264enc: VA-API H264 encoder
> vaapi:  vaapih265dec: VA-API H265 decoder
> vaapi:  vaapih265enc: VA-API H265 encoder
> vaapi:  vaapijpegdec: VA-API JPEG decoder
> vaapi:  vaapijpegenc: VA-API JPEG encoder
> vaapi:  vaapimpeg2dec: VA-API MPEG2 decoder
> vaapi:  vaapimpeg2enc: VA-API MPEG-2 encoder
> vaapi:  vaapioverlay: VA-API overlay
> vaapi:  vaapipostproc: VA-API video postprocessing
> vaapi:  vaapisink: VA-API sink
> vaapi:  vaapivc1dec: VA-API VC1 decoder
> vaapi:  vaapivp9dec: VA-API VP9 decoder
> vaapi:  vaapivp9enc: VA-API VP9 encoder
>
> As the libvirt user that runs qemu:
> # sudo -u libvirt-qemu gst-inspect-1.0 |grep -F -i vaapi
> vaapi:  vaapiav1dec: VA-API AV1 decoder
> vaapi:  vaapidecodebin: VA-API Decode Bin
> vaapi:  vaapih264dec: VA-API H264 decoder
> vaapi:  vaapih264enc: VA-API H264 encoder
> vaapi:  vaapih265dec: VA-API H265 decoder
> vaapi:  vaapih265enc: VA-API H265 encoder
> vaapi:  vaapijpegdec: VA-API JPEG decoder
> vaapi:  vaapijpegenc: VA-API JPEG encoder
> vaapi:  vaapimpeg2dec: VA-API MPEG2 decoder
> vaapi:  vaapimpeg2enc: VA-API MPEG-2 encoder
> vaapi:  vaapioverlay: VA-API overlay
> vaapi:  vaapipostproc: VA-API video postprocessing
> vaapi:  vaapisink: VA-API sink
> vaapi:  vaapivc1dec: VA-API VC1 decoder
> vaapi:  vaapivp9dec: VA-API VP9 decoder
> vaapi:  vaapivp9enc: VA-API VP9 encoder
>
> On the client (with Intel CometLake (10th gen) graphics):
> As my user running the client (spicy/remote-viewer):
> $ gst-inspect-1.0 |grep -F -i vaapi
> vaapi:  vaapidecodebin: VA-API Decode Bin
> vaapi:  vaapih264dec: VA-API H264 decoder
> vaapi:  vaapih264enc: VA-API H264 encoder
> vaapi:  vaapih265dec: VA-API H265 decoder
> vaapi:  vaapih265enc: VA-API H265 encoder
> vaapi:  vaapijpegdec: VA-API JPEG decoder
> vaapi:  vaapijpegenc: VA-API JPEG encoder
> vaapi:  vaapimpeg2dec: VA-API MPEG2 decoder
> vaapi:  vaapimpeg2enc: VA-API MPEG-2 encoder
> vaapi:  vaapioverlay: VA-API overlay
> vaapi:  vaapipostproc: VA-API video postprocessing
> vaapi:  vaapisink: VA-API sink
> vaapi:  vaapivc1dec: VA-API VC1 decoder
> vaapi:  vaapivp8dec: VA-API VP8 decoder
> vaapi:  vaapivp8enc: VA-API VP8 encoder
> vaapi:  vaapivp9dec: VA-API VP9 decoder
>
> (a good common ground could be VP9 as the host can encode and
> the client can decode, or h264/h265 as both can encode/decode)

There are a lot of settings that you'll likely need to tweak in
spice server (host) for good optimization and even hardware
encoding. You can see at [0] that the plugin for video encoding
is hardcoded with x264enc. I can't see if you have it or not in
your host because of the grep, but that could be another reason
for not being able to encode in h264 (edit: seems to be present
in the logs)

[0] https://gitlab.freedesktop.org/spice/spice/-/blob/master/server/gstreamer-encoder.c#L887

The spice-gtk (client) uses GStreamer's most generic elements to
give it the possibility to setup a video decoding in the best way
possible, preferably with hardware encoded although that was not
guaranteed when I implemented that logic.

> As an example of using vaapi, tested with mpv (--vo=gpu):

<snipped, it works>
 
> This works fine, while also can check the GPU utilization with
> intel_gpu_top - the /Video/ metric keeps changing during
> playback.
>
> So I'm testing with `spicy` first and foremost because it
> actually has a menu option to switch between video encodings,
> which I don't know how to do with e.g. remote-viewer or
> virt-viewer.
>
> $ GST_DEBUG=4 spicy --spice-debug -p 5912 -h localhost
>
> Long story short, while the client output shows that gstreamer
> picks up its vaapi plugin, and actually loads the intel iHD DRI
> driver, it still doesn't use the GPU to decode.

> I'm afraid something lies underneath the configuration and the
> protocol that I don't understand. Maybe the host doesn't even
> encode its stream into e.g. h264 even though the client
> (=spicy) requests so, therefore it can't very well decode it
> with the GPU.

> I imagined something along the lines of Spice encoding the
> stream on the host with the help of the GPU (gstreamer + vaapi)
> and then the client could decode it on the other end with its
> GPU as well - as far as they agree on a codec that both support
> (more specifically the host supports encoding to it and the
> client suppports decoding from it).
>
> I was afraid of posting the full output with --spice-debug,
> becuase it had a ton of "decode-glz.c:335 decode_header:" and
> "scroll event" lines, so I snipped these out from it.


<snipped, log lines>

> If you have any suggestions as to what I am doing wrong or what
> I'm missing, I'd be greatful if you'd let me know.

>From what I could see, you have set the h264 video-codec
preference at 13:06:46 and terminated spicy around 13:06:49.

So, perhaps the first issue is the assumption that as soon as you
set the video-codec preference, that the stream will start. It'll
not. The streaming will happen based on update frequency on the
display. For example, a clock updating the seconds, once every
second, will not create a video streaming. You should try running
an App that has high update frequency or just a video.

GStreamer needs to be enabled in spice-server at build time too.
You can check with ldd in libspice-server.so...

So, the logs from spice-server would be useful to know what issue
might have happened at encoding if it doesn't work.

Just trying to give you some ideas and directions to go.

Cheers,
Victor

[Index of Archives]     [Linux Virtualization]     [Linux Virtualization]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]