obs-ffmpeg: Add ROI support for VAAPI
Description
Add ROI support for VAAPI
Motivation and Context
ROI support for VAAPI
How Has This Been Tested?
Tested with mesa driver using AMD gpu.
Types of changes
- New feature (non-breaking change which adds functionality)
Checklist:
- [x] My code has been run through clang-format.
- [x] I have read the contributing document.
- [x] My code is not on the master branch.
- [x] The code has been tested.
- [x] All commit messages are properly formatted and commits squashed where appropriate.
- [x] I have included updates to all appropriate documentation.
Looks fine to me, can't test it on my machine due to NVIDIA right now, hopefully one of our Linux folks can double check.
Hello @nowrep, I would love to help you testing this code. I have an Arch Linux and an AMD GPU with AV1 encoder. I saw the artifacts generated and there is no flatpak version available. Is there a way to generate this artifact again so I can test?
You'll need to build it yourself anyway because there's no UI yet for ROI afaik.
The compilation failed for some reason:
[lucas@debian build]$ ninja
[6/135] Building CXX object plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/requesthandler/RequestHandler_SceneItems.cpp.o
FAILED: plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/requesthandler/RequestHandler_SceneItems.cpp.o
/usr/bin/ccache /usr/bin/c++ -DASIO_STANDALONE -DENABLE_HEVC -DHAVE_OBSCONFIG_H -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_SVG_LIB -DQT_WIDGETS_LIB -Dobs_websocket_EXPORTS -I/home/lucas/code/tmp/obs/obs-studio/build/plugins/obs-websocket/obs-websocket_autogen/include -I/home/lucas/code/tmp/obs/obs-studio/build/plugins/obs-websocket -I/home/lucas/code/tmp/obs/obs-studio/libobs -I/home/lucas/code/tmp/obs/obs-studio/build/config -I/home/lucas/code/tmp/obs/obs-studio/UI/obs-frontend-api -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtSvg -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/qrcodegen -O2 -g -DNDEBUG -fPIC -Werror -Wextra -Wvla -Wswitch -Wno-error=switch -Wformat -Wformat-security -Wunused-parameter -Wno-unused-function -Wno-missing-field-initializers -fno-strict-aliasing -Wconversion-null -Wno-error=maybe-uninitialized -Wall -Wno-error=format-overflow -mmmx -msse -msse2 -fPIC -std=c++17 -MD -MT plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/requesthandler/RequestHandler_SceneItems.cpp.o -MF plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/requesthandler/RequestHandler_SceneItems.cpp.o.d -o plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/requesthandler/RequestHandler_SceneItems.cpp.o -c /home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/requesthandler/RequestHandler_SceneItems.cpp
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/requesthandler/RequestHandler_SceneItems.cpp: In member function 'RequestResult RequestHandler::DuplicateSceneItem(const Request&)':
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/requesthandler/RequestHandler_SceneItems.cpp:311:9: error: 'obs_sceneitem_get_info2' was not declared in this scope; did you mean 'obs_sceneitem_get_info'?
311 | obs_sceneitem_get_info2(sceneItem, &sceneItemTransform);
| ^~~~~~~~~~~~~~~~~~~~~~~
| obs_sceneitem_get_info
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/requesthandler/RequestHandler_SceneItems.cpp: In member function 'RequestResult RequestHandler::SetSceneItemTransform(const Request&)':
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/requesthandler/RequestHandler_SceneItems.cpp:389:9: error: 'obs_sceneitem_get_info2' was not declared in this scope; did you mean 'obs_sceneitem_get_info'?
389 | obs_sceneitem_get_info2(sceneItem, &sceneItemTransform);
| ^~~~~~~~~~~~~~~~~~~~~~~
| obs_sceneitem_get_info
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/requesthandler/RequestHandler_SceneItems.cpp:506:17: error: 'obs_sceneitem_set_info2' was not declared in this scope; did you mean 'obs_sceneitem_set_info'?
506 | obs_sceneitem_set_info2(sceneItem, &sceneItemTransform);
| ^~~~~~~~~~~~~~~~~~~~~~~
| obs_sceneitem_set_info
[10/135] Building CXX object plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ObjectHelper.cpp.o
FAILED: plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ObjectHelper.cpp.o
/usr/bin/ccache /usr/bin/c++ -DASIO_STANDALONE -DENABLE_HEVC -DHAVE_OBSCONFIG_H -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_SVG_LIB -DQT_WIDGETS_LIB -Dobs_websocket_EXPORTS -I/home/lucas/code/tmp/obs/obs-studio/build/plugins/obs-websocket/obs-websocket_autogen/include -I/home/lucas/code/tmp/obs/obs-studio/build/plugins/obs-websocket -I/home/lucas/code/tmp/obs/obs-studio/libobs -I/home/lucas/code/tmp/obs/obs-studio/build/config -I/home/lucas/code/tmp/obs/obs-studio/UI/obs-frontend-api -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtSvg -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/qrcodegen -O2 -g -DNDEBUG -fPIC -Werror -Wextra -Wvla -Wswitch -Wno-error=switch -Wformat -Wformat-security -Wunused-parameter -Wno-unused-function -Wno-missing-field-initializers -fno-strict-aliasing -Wconversion-null -Wno-error=maybe-uninitialized -Wall -Wno-error=format-overflow -mmmx -msse -msse2 -fPIC -std=c++17 -MD -MT plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ObjectHelper.cpp.o -MF plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ObjectHelper.cpp.o.d -o plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ObjectHelper.cpp.o -c /home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/utils/Obs_ObjectHelper.cpp
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/utils/Obs_ObjectHelper.cpp: In function 'json Utils::Obs::ObjectHelper::GetSceneItemTransform(obs_sceneitem_t*)':
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/utils/Obs_ObjectHelper.cpp:53:9: error: 'obs_sceneitem_get_info2' was not declared in this scope; did you mean 'obs_sceneitem_get_info'?
53 | obs_sceneitem_get_info2(item, &osi);
| ^~~~~~~~~~~~~~~~~~~~~~~
| obs_sceneitem_get_info
[13/135] Building CXX object plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ActionHelper.cpp.o
FAILED: plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ActionHelper.cpp.o
/usr/bin/ccache /usr/bin/c++ -DASIO_STANDALONE -DENABLE_HEVC -DHAVE_OBSCONFIG_H -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_SVG_LIB -DQT_WIDGETS_LIB -Dobs_websocket_EXPORTS -I/home/lucas/code/tmp/obs/obs-studio/build/plugins/obs-websocket/obs-websocket_autogen/include -I/home/lucas/code/tmp/obs/obs-studio/build/plugins/obs-websocket -I/home/lucas/code/tmp/obs/obs-studio/libobs -I/home/lucas/code/tmp/obs/obs-studio/build/config -I/home/lucas/code/tmp/obs/obs-studio/UI/obs-frontend-api -isystem /usr/include/x86_64-linux-gnu/qt6/QtCore -isystem /usr/include/x86_64-linux-gnu/qt6 -isystem /usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -isystem /usr/include/x86_64-linux-gnu/qt6/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt6/QtGui -isystem /usr/include/x86_64-linux-gnu/qt6/QtSvg -isystem /usr/include/x86_64-linux-gnu/qt6/QtNetwork -isystem /usr/include/qrcodegen -O2 -g -DNDEBUG -fPIC -Werror -Wextra -Wvla -Wswitch -Wno-error=switch -Wformat -Wformat-security -Wunused-parameter -Wno-unused-function -Wno-missing-field-initializers -fno-strict-aliasing -Wconversion-null -Wno-error=maybe-uninitialized -Wall -Wno-error=format-overflow -mmmx -msse -msse2 -fPIC -std=c++17 -MD -MT plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ActionHelper.cpp.o -MF plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ActionHelper.cpp.o.d -o plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Obs_ActionHelper.cpp.o -c /home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/utils/Obs_ActionHelper.cpp
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/utils/Obs_ActionHelper.cpp: In function 'void CreateSceneItemHelper(void*, obs_scene_t*)':
/home/lucas/code/tmp/obs/obs-studio/plugins/obs-websocket/src/utils/Obs_ActionHelper.cpp:36:17: error: 'obs_sceneitem_set_info2' was not declared in this scope; did you mean 'obs_sceneitem_set_info'?
36 | obs_sceneitem_set_info2(data->sceneItem, data->sceneItemTransform);
| ^~~~~~~~~~~~~~~~~~~~~~~
| obs_sceneitem_set_info
[19/135] Building CXX object plugins/obs-websocket/CMakeFiles/obs-websocket.dir/src/utils/Json.cpp.o
ninja: build stopped: subcommand failed.
I'm using Arch Linux, it was compiled inside a debian bookworm container using distrobox and arch itself both gave this error.
@LucasSnatiago
This branch is behind and does not include the commit that added obs_sceneitem_get_info2. Rebase the branch, or downgrade submodules back to before they were updated.
That said, I'd like this thread to not become a debugging session unless it's actually about the code in this PR. The comments should be focused on PR review itself so that maintainers don't have to sift through unrelated comments.
@nowrep I compiled and recorded a video using it, but how can I test if it is really working? I thought it would be easy to notice the differences, but it is not. How can I enable it?
Do you prefer screenshot of the recordings at the same bitrate with this feature on and off? Or another approach?
You can test with this patch
diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c
index a8e03fbcd..db629585b 100644
--- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c
+++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c
@@ -429,6 +429,21 @@ static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder,
enc = bzalloc(sizeof(*enc));
enc->encoder = encoder;
+ obs_encoder_add_roi(enc->encoder, &(struct obs_encoder_roi){
+ .top = 100,
+ .bottom = 400,
+ .left = 100,
+ .right = 400,
+ .priority = -1.0,
+ });
+ obs_encoder_add_roi(enc->encoder, &(struct obs_encoder_roi){
+ .top = 500,
+ .bottom = 700,
+ .left = 500,
+ .right = 700,
+ .priority = -1.0,
+ });
+
enc->codec = codec;
enc->vaapi = avcodec_find_encoder_by_name(vaapi_encoder_name(codec));
There will be two regions with very low quality, one screenshot is enough.
I made some tests and I could not notice any differences here are some tests:
Original video
All videos are recorded using your patch.
- Recording at 2500Kbps : AMD AV1 ROI 2500kbps
- Recording with CQP set to 16: AMD AV1 ROI CQP 16
- Recording at 6Kbps, but with the ROI area increased: AMD AV1 ROI 6000kbps - Bigger ROI Area
I record at 2k60fps so I made an increase in the area size for the last test (3.):
obs_encoder_add_roi(enc->encoder, &(struct obs_encoder_roi){
.top = 100,
.bottom = 800,
.left = 100,
.right = 800,
.priority = -1.0,
});
obs_encoder_add_roi(enc->encoder, &(struct obs_encoder_roi){
.top = 500,
.bottom = 1000,
.left = 500,
.right = 1000,
.priority = -1.0,
});
I'm completely up to do a lot more tests if needed.
It works with H264/HEVC, is broken with AV1. Fix https://github.com/FFmpeg/FFmpeg/commit/3f863f089c679be62827034d3645f152f9e4fa2f
I'm still not convinced it works, maybe I'm doing something wrong:
None of them I can see any difference. All ffprobe details are available on the video description if you want to see. For some reason all first 4 videos have like 14Mbps bitrate, but with noticeable worse video quality do you know why it happens?
I'm still using this code to set the ROI region:
obs_encoder_add_roi(enc->encoder, &(struct obs_encoder_roi){
.top = 100,
.bottom = 800,
.left = 100,
.right = 800,
.priority = -1.0,
});
obs_encoder_add_roi(enc->encoder, &(struct obs_encoder_roi){
.top = 500,
.bottom = 1000,
.left = 500,
.right = 1000,
.priority = -1.0,
});
You need Mesa 24.0 or newer, other than that I have no idea why it wouldn't work for you.
Well, that's my Mesa's version:
Mesa version
========== VULKANINFO ==========Vulkan Instance Version: 1.3.279
Instance Extensions: count = 24
VK_EXT_acquire_drm_display : extension revision 1 VK_EXT_acquire_xlib_display : extension revision 1 VK_EXT_debug_report : extension revision 10 VK_EXT_debug_utils : extension revision 2 VK_EXT_direct_mode_display : extension revision 1 VK_EXT_display_surface_counter : extension revision 1 VK_EXT_headless_surface : extension revision 1 VK_EXT_surface_maintenance1 : extension revision 1 VK_EXT_swapchain_colorspace : extension revision 4 VK_KHR_device_group_creation : extension revision 1 VK_KHR_display : extension revision 23 VK_KHR_external_fence_capabilities : extension revision 1 VK_KHR_external_memory_capabilities : extension revision 1 VK_KHR_external_semaphore_capabilities : extension revision 1 VK_KHR_get_display_properties2 : extension revision 1 VK_KHR_get_physical_device_properties2 : extension revision 2 VK_KHR_get_surface_capabilities2 : extension revision 1 VK_KHR_portability_enumeration : extension revision 1 VK_KHR_surface : extension revision 25 VK_KHR_surface_protected_capabilities : extension revision 1 VK_KHR_wayland_surface : extension revision 6 VK_KHR_xcb_surface : extension revision 6 VK_KHR_xlib_surface : extension revision 6 VK_LUNARG_direct_driver_loading : extension revision 1
Instance Layers: count = 12
VK_LAYER_AMD_switchable_graphics_32 AMD switchable graphics layer 1.3.279 version 1 VK_LAYER_FROG_gamescope_wsi_x86_64 Gamescope WSI (XWayland Bypass) Layer (x86_64) 1.3.221 version 1 VK_LAYER_MANGOAPP_overlay Mangoapp Layer 1.3.0 version 1 VK_LAYER_MANGOAPP_overlay Mangoapp Layer 1.3.0 version 1 VK_LAYER_MANGOHUD_overlay_x86 Vulkan Hud Overlay 1.3.0 version 1 VK_LAYER_MANGOHUD_overlay_x86_64 Vulkan Hud Overlay 1.3.0 version 1 VK_LAYER_MESA_device_select Linux device selection layer 1.3.211 version 1 VK_LAYER_MESA_overlay Mesa Overlay layer 1.3.211 version 1 VK_LAYER_VALVE_steam_fossilize_32 Steam Pipeline Caching Layer 1.3.207 version 1 VK_LAYER_VALVE_steam_fossilize_64 Steam Pipeline Caching Layer 1.3.207 version 1 VK_LAYER_VALVE_steam_overlay_32 Steam Overlay Layer 1.3.207 version 1 VK_LAYER_VALVE_steam_overlay_64 Steam Overlay Layer 1.3.207 version 1
Devices:
GPU0: apiVersion = 1.3.278 driverVersion = 24.0.99 vendorID = 0x1002 deviceID = 0x7480 deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU deviceName = AMD Radeon RX 7600 (RADV NAVI33) driverID = DRIVER_ID_MESA_RADV driverName = radv driverInfo = Mesa 24.1.0-devel (git-eb4036a4be) conformanceVersion = 1.3.0.0 deviceUUID = 00000000-0b00-0000-0000-000000000000 driverUUID = 414d442d-4d45-5341-2d44-525600000000
I don't know if it is necessary, but here is my ffmpeg details:
ffmpeg version
ffmpeg version n6.1.1 Copyright (c) 2000-2023 the FFmpeg developers built with gcc 13.2.1 (GCC) 20230801 configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-frei0r --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libharfbuzz --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libplacebo --enable-libpulse --enable-librav1e --enable-librsvg --enable-librubberband --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpl --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-shared --enable-vapoursynth --enable-version3 --enable-vulkan libavutil 58. 29.100 / 58. 29.100 libavcodec 60. 31.102 / 60. 31.102 libavformat 60. 16.100 / 60. 16.100 libavdevice 60. 3.100 / 60. 3.100 libavfilter 9. 12.100 / 9. 12.100 libswscale 7. 5.100 / 7. 5.100 libswresample 4. 12.100 / 4. 12.100 libpostproc 57. 3.100 / 57. 3.100
What else can I check?