obs-studio icon indicating copy to clipboard operation
obs-studio copied to clipboard

obs-ffmpeg: Add ROI support for VAAPI

Open nowrep opened this issue 1 year ago • 12 comments

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.

nowrep avatar Jan 24 '24 11:01 nowrep

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.

derrod avatar Jan 27 '24 23:01 derrod

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?

LucasSnatiago avatar Mar 26 '24 21:03 LucasSnatiago

You'll need to build it yourself anyway because there's no UI yet for ROI afaik.

nowrep avatar Mar 28 '24 06:03 nowrep

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 avatar Mar 28 '24 13:03 LucasSnatiago

@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.

RytoEX avatar Mar 28 '24 17:03 RytoEX

@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?

LucasSnatiago avatar Mar 31 '24 19:03 LucasSnatiago

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.

nowrep avatar Apr 01 '24 07:04 nowrep

I made some tests and I could not notice any differences here are some tests:

Original video

All videos are recorded using your patch.

  1. Recording at 2500Kbps : AMD AV1 ROI 2500kbps
  2. Recording with CQP set to 16: AMD AV1 ROI CQP 16
  3. 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.

LucasSnatiago avatar Apr 01 '24 15:04 LucasSnatiago

It works with H264/HEVC, is broken with AV1. Fix https://github.com/FFmpeg/FFmpeg/commit/3f863f089c679be62827034d3645f152f9e4fa2f

nowrep avatar Apr 01 '24 16:04 nowrep

I'm still not convinced it works, maybe I'm doing something wrong:

  1. 2500Kbps ROI H264
  2. 2500Kbps ROI HEVC
  3. 5Mbps ROI H264
  4. 5Mbps ROI HEVC
  5. CQP 16 ROI H264
  6. CQP 16 ROI HEVC

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,
	});

LucasSnatiago avatar Apr 02 '24 19:04 LucasSnatiago

You need Mesa 24.0 or newer, other than that I have no idea why it wouldn't work for you.

nowrep avatar Apr 03 '24 09:04 nowrep

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?

LucasSnatiago avatar Apr 03 '24 14:04 LucasSnatiago