korejan / ALVR

Stream VR games from your PC to your headset via Wi-Fi
https://alvr-org.github.io/
MIT License
186 stars 27 forks source link

Low image quality on PICO 4 despite using high resolution and high bitrate on ALVR server #70

Closed wolfallein closed 1 year ago

wolfallein commented 1 year ago

Description

Thank you for the great work!

I'm using the latest alxr nightly client alxr-client-pico.apk v0.10.0+nightly.2023.01.14 on PICO 4 with the latest firmware update 5.3.2.

The main issue I'm facing is with the image quality on the headset. On the alvr server, I set video encoding resolution and Preferred game resolution to absolute 4320x2160. On SteamVR it reports correctly what I specified on alvr but the image quality on the headset is very low, probably around 720p (maybe even worse). I also set the bitrate to 150 and the refresh rate to 90 Hz, HEVC encoding.

Is there an option that I'm missing to get higher image quality on the PICO 4 headset?

image

General Troubleshooting

Environement

Hardware

Note: for Linux, an upload to the hw-probe database is preferred: hw-probe -all -upload

CPU: i7-8700K

GPU: Radeon 7900 XTX

Audio:

Installation

ALVR Version: 1.8.2.3

SteamVR Version: 1.24.7

Install Type:

OS Name and Version (winver on Windows or grep PRETTY_NAME /etc/os-release on most Linux distributions): win10 22H2

korejan commented 1 year ago

Hello, do you have foveated encoding on/off? I don't have a Pico 4 but i'll try this resolution on PN3L, note I'm very close to pushing fixes/improvements for Pico headsets to github.

korejan commented 1 year ago

I have an idea what maybe happening but I need a log from Pico 4 headset to verify it, if you can use the debug build and send me logcat log during start-up upto the when the stream starts.

wolfallein commented 1 year ago

Hi, thank you for your help. Foveated encoding is disabled on the ALVR server. I used your last debug build (v0.10.0+nightly.2023.01.15), and I attach the logcat, but I could not find the ALXR debug entries on it; maybe you can...

logcat_alxr.txt

I can also say that the device was very unstable after trying to close the app, and I needed to hard reset it to get it back to normal.

I can help to debug for PICO 4 whenever you need.

wolfallein commented 1 year ago

Hi, I started again, and I managed to filter some alxr logs with adb logcat RustStdoutStderr:D *:F

Here is the file:

logcat_alxr2.txt

From the log, it seems that the resolution is correct, but the image quality is really bad. Do you think that could be something to do with the encoder or decoder?

korejan commented 1 year ago

@wolfallein Thanks, log looks okay. Is SteamVR set to dynamic resolution? other than that I've heard people mention issues with certain AMD GPU driver versions being unable to encode at high bitrates.

Try this build, it's using the newer Pico OpenXR SDK, removed some legacy non-standard conformance Pico stuff, some fixes/improvements and support for passthrough modes, left menu (- button) + A (mask mode) or B (blend mode)

Still want to do one more thing before push these changes to github.

wolfallein commented 1 year ago

Thank you!

The app doesn't seem to crash the system anymore đŸ˜„, although I had a problem allowing the storage permission, which was happening with the previous build as well. I had to go to the device settings>General>Manage apps and enable permission for alxr from there.

I just tested, and the image is still with poor quality. SteamVR resolution was set to auto, but I changed to custom to test as well, restarted everything, and it still looks the same. Strangely enough, from the screenshot I took using the PICO, the image looks alright....

Screenshot_com alvr alxr_client_2023 01 16-23 14 02 486_072

Maybe it is not that the resolution is low. I checked my network adapter and I see that it is transmitting only at 25Mbps

image

and alvr is set to 150 Mbps

image

image

So it could be something related to the GPU driver as you say.

By the way, I tested the passthrough modes and they are amazing!

wolfallein commented 1 year ago

I tested a few different bitrates, and up to 100 Mbps works well. More than that, it reduces to 25 Mbps for whatever reason... The issue could be related to AMD encoding support...

korejan commented 1 year ago

Sounds like that is most likely the issue, it's came up often not only for ALXR. I think the main problem is the ALVR server, until very recently in the main repository it has been using a very old version of AMF SDK (from 2018).

Either I make a custom version of the server with cherry picked changes or I make ALXR compatible with v20 server. Latter I will do eventually although I don't know if it has actually been fixed there.

wolfallein commented 1 year ago

Thanks a lot!

I found this issue on alvr (https://github.com/alvr-org/ALVR/issues/1308). It is a problem with AMD drivers (https://github.com/GPUOpen-LibrariesAndSDKs/AMF/issues/364), as you said.

So it probably doesn't help if you create a custom server. The thing is that 100 Mbps should be enough to give me good image quality, but as mentioned in the alvr issue, it could be that even if the system shows a higher bitrate, the effective bitrate is still about 30 Mbps, and filler data is inserted (https://github.com/alvr-org/ALVR/issues/1308#issuecomment-1374903425).

What I don't get is that VD can give images with no visible compressing artifacts at 150 Mbps, and it should have been having the same issue as alvr if this is a driver problem. It may be possible to change some quality presets of the AMF encoder and get better pictures even with actual driver limitations.

I see two recent commits on alvr that could help: https://github.com/alvr-org/ALVR/commit/0c05c342dc5820d083d379f77c2752477a6c01aa and https://github.com/alvr-org/ALVR/commit/2142f2baf128f441b5154a82cc50f671975ef654 it let the user configure the AMF encoding and hopefully improve visuals.

wolfallein commented 1 year ago

I have an Nvidia GTX 1070 on another computer and decided to do some tests to compare picture quality. To my surprise, the Nvidia card gave about the same quality as I was getting from the RTX 7900 XTX. The maximum bitrate I could set on the 1070 before massive lag was ~100Mbps.

I decided to try VD on this computer as well, and the picture quality was like I got on my other computer, very sharp image. If you want, I can provide some screenshots from both.

So, even if we have a problem with drivers for the AMD GPU, some encoding quality settings could be changed to improve overall quality, maybe..... It could be that default encoding setting are always in favor of lower latency on ALVR server.

wolfallein commented 1 year ago

Hi,

I did manage to improve visuals by adjusting a few settings in the encoder. I used the alvr source branch v18.2.3 and compiled the server by adjusting these settings:

diff --git a/alvr/server/cpp/platform/win32/VideoEncoderVCE.cpp b/alvr/server/cpp/platform/win32/VideoEncoderVCE.cpp
index 6626e3cb..b30beaac 100644
--- a/alvr/server/cpp/platform/win32/VideoEncoderVCE.cpp
+++ b/alvr/server/cpp/platform/win32/VideoEncoderVCE.cpp
@@ -64,16 +64,18 @@ AMFTextureEncoder::AMFTextureEncoder(const amf::AMFContextPtr &amfContext
        {
                m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_USAGE, AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY);
                m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE, bitRateIn);
+               m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, bitRateIn);
                m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, ::AMFConstructSize(width, height));
                m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_FRAMERATE, ::AMFConstructRate(frameRateIn, 1));

                //No noticable visual difference between PRESET_QUALITY and PRESET_SPEED but the latter has better latency when the GPU is under heavy load
-               m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED);
+               //m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED);

                //No noticable performance difference and should improve subjective quality by allocating more bits to smooth areas
-               m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, true);
+               //m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, true);

                //Fixes rythmic pixelation. I-frames were overcompressed on default settings
+               m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 30);
                m_amfEncoder->SetProperty(AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 30);

                //Does not seem to make a difference but turned on anyway in case it does on other hardware

The main change was setting AMF_VIDEO_ENCODER_HEVC_MAX_QP_P to a lower value, 30 in this case. According to the AMF API (AMF_Video_Encode_HEVC_API.pdf), the AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY is peak constrained VBR by default, so I added AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, I'm not sure if this setting is changed in another part of the ALVR code, though, LATENCY_CONSTRAINED_VBR. VBAQ was giving me huge latency, so I disabled it.

The good thing is that by lowering QP, the image is almost perfect without crazy supersampling. If the AMD drivers get fixed at some point, I should be able to go higher than ~100 Mbps and improve even more.

It would be interesting to change the QP values on the ALVR GUI so the user can test the better settings for his setup.

Thanks for your help. I'm closing this issue.

korejan commented 1 year ago

Cool, this change is very local so no need to worry about that. About the UI changes I think that may have been done in latest of the main repository from what I've glanced at a few days ago.

deiteris commented 1 year ago

VBAQ was giving me huge latency, so I disabled it.

This is what actually improved your picture, not QP setting. There seems to be a bug with VBAQ that causes massive compression artifacts. You can see related issue here, it affects both h264 and hevc: https://github.com/GPUOpen-LibrariesAndSDKs/AMF/issues/330

QP just controls the amount of compression applied to certain areas of picture (macroblocks). Decreasing the maximum compression while you have insufficient bitrate budget won't make any difference (in fact, it could actually hurt the overall perceived quality because the bits probably would distribute less even). On the other end, increasing min QP could potentially help a bit to better distribute the bitrate in case some areas require a lot of it and could receive less bits without noticeable quality loss.

wolfallein commented 1 year ago

@deiteris, you are correct. I thought that wasn't the case because VBAQ was supposed to improve the image, not make it worse.

QP should vary depending on the bitrate, as you say, and in more recent AMF documentation (AMF Video Encode SDK) all presets (Ultra low latency, transcoding, etc.) shares the same QP range (from 0 to 51, all the QP range), so the compression should adapt with the bitrate freely.

Thanks for your work on ALVR. I hope the AMD drivers get fixed soon so we get a better experience in general. The main problem now is the 100Mbps limit.

sandr1x commented 1 year ago

VBAQ was giving me huge latency, so I disabled it.

This is what actually improved your picture, not QP setting. There seems to be a bug with VBAQ that causes massive compression artifacts. You can see related issue here, it affects both h264 and hevc: GPUOpen-LibrariesAndSDKs/AMF#330

QP just controls the amount of compression applied to certain areas of picture (macroblocks). Decreasing the maximum compression while you have insufficient bitrate budget won't make any difference (in fact, it could actually hurt the overall perceived quality because the bits probably would distribute less even). On the other end, increasing min QP could potentially help a bit to better distribute the bitrate in case some areas require a lot of it and could receive less bits without noticeable quality loss.

This problem is still relevant. Can you report?