From ef830a0c932092d830214b2e47f91da8af7da7ad Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Thu, 21 Jan 2021 13:55:58 +0100 Subject: [PATCH] Update to 85.0 --- .gitignore | 2 + ffvpx.patch | 9589 --------------- firefox-testing.patch | 35 +- firefox-tests-reftest.patch | 287 +- firefox-tests-xpcshell.patch | 70 +- firefox-vaapi-extra-frames.patch | 12 - firefox.spec | 43 +- mozilla-1667096.patch | 30 +- mozilla-1678680.patch | 73 - mozilla-1680505.patch | 34 - mozilla-1687931.patch | 28 + pgo.patch | 58 +- pw1.patch | 78 - pw2.patch | 901 -- pw3.patch | 183 - pw4.patch | 18928 ----------------------------- pw5.patch | 53 - pw6.patch | 163 - sources | 4 +- 19 files changed, 270 insertions(+), 30301 deletions(-) delete mode 100644 ffvpx.patch delete mode 100644 firefox-vaapi-extra-frames.patch delete mode 100644 mozilla-1678680.patch delete mode 100644 mozilla-1680505.patch create mode 100644 mozilla-1687931.patch delete mode 100644 pw1.patch delete mode 100644 pw2.patch delete mode 100644 pw3.patch delete mode 100644 pw4.patch delete mode 100644 pw5.patch delete mode 100644 pw6.patch diff --git a/.gitignore b/.gitignore index 66d5c6b..120cbfe 100644 --- a/.gitignore +++ b/.gitignore @@ -443,3 +443,5 @@ firefox-3.6.4.source.tar.bz2 /firefox-langpacks-84.0.1-20201222.tar.xz /firefox-84.0.2.source.tar.xz /firefox-langpacks-84.0.2-20210106.tar.xz +/firefox-85.0.source.tar.xz +/firefox-langpacks-85.0-20210120.tar.xz diff --git a/ffvpx.patch b/ffvpx.patch deleted file mode 100644 index 73c2f57..0000000 --- a/ffvpx.patch +++ /dev/null @@ -1,9589 +0,0 @@ -diff -up firefox-84.0/dom/media/platforms/ffmpeg/ffmpeg58/moz.build.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/ffmpeg58/moz.build ---- firefox-84.0/dom/media/platforms/ffmpeg/ffmpeg58/moz.build.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/ffmpeg58/moz.build 2020-12-10 20:36:08.398441034 +0100 -@@ -27,8 +27,6 @@ if CONFIG['CC_TYPE'] == 'gcc': - ] - if CONFIG['MOZ_WAYLAND']: - CXXFLAGS += CONFIG['TK_CFLAGS'] -- CXXFLAGS += CONFIG['MOZ_WAYLAND_CFLAGS'] - DEFINES['MOZ_WAYLAND_USE_VAAPI'] = 1 -- include('/ipc/chromium/chromium-config.mozbuild') - - FINAL_LIBRARY = 'xul' -diff -up firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp ---- firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp 2020-12-10 20:40:53.388541336 +0100 -@@ -11,6 +11,10 @@ - #include "mozilla/Types.h" - #include "PlatformDecoderModule.h" - #include "prlink.h" -+#ifdef MOZ_WAYLAND -+# include "mozilla/widget/DMABufLibWrapper.h" -+# include "mozilla/StaticPrefs_media.h" -+#endif - - #define AV_LOG_DEBUG 48 - #define AV_LOG_INFO 32 -@@ -254,6 +258,46 @@ void FFmpegLibWrapper::Unlink() { - } - - #ifdef MOZ_WAYLAND -+void FFmpegLibWrapper::LinkVAAPILibs() { -+ if (widget::GetDMABufDevice()->IsDMABufVAAPIEnabled()) { -+ PRLibSpec lspec; -+ lspec.type = PR_LibSpec_Pathname; -+ const char* libDrm = "libva-drm.so.2"; -+ lspec.value.pathname = libDrm; -+ mVALibDrm = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -+ if (!mVALibDrm) { -+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", libDrm); -+ } -+ -+ if (!StaticPrefs::media_ffmpeg_vaapi_drm_display_enabled()) { -+ const char* libWayland = "libva-wayland.so.2"; -+ lspec.value.pathname = libWayland; -+ mVALibWayland = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -+ if (!mVALibWayland) { -+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", libWayland); -+ } -+ } -+ -+ if (mVALibWayland || mVALibDrm) { -+ const char* lib = "libva.so.2"; -+ lspec.value.pathname = lib; -+ mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -+ // Don't use libva when it's missing vaExportSurfaceHandle. -+ if (mVALib && !PR_FindSymbol(mVALib, "vaExportSurfaceHandle")) { -+ PR_UnloadLibrary(mVALib); -+ mVALib = nullptr; -+ } -+ if (!mVALib) { -+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib); -+ } -+ } -+ } else { -+ FFMPEG_LOG("VA-API FFmpeg is disabled by platform"); -+ } -+} -+#endif -+ -+#ifdef MOZ_WAYLAND - bool FFmpegLibWrapper::IsVAAPIAvailable() { - # define VA_FUNC_LOADED(func) (func != nullptr) - return VA_FUNC_LOADED(avcodec_get_hw_config) && -diff -up firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h ---- firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h 2020-12-10 20:40:53.388541336 +0100 -@@ -56,6 +56,7 @@ struct MOZ_ONLY_USED_TO_AVOID_STATIC_CON - #ifdef MOZ_WAYLAND - // Check if mVALib are available and we can use HW decode. - bool IsVAAPIAvailable(); -+ void LinkVAAPILibs(); - #endif - - // indicate the version of libavcodec linked to. -diff -up firefox-84.0/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp ---- firefox-84.0/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp 2020-12-10 20:40:53.388541336 +0100 -@@ -9,10 +9,6 @@ - #include "mozilla/ArrayUtils.h" - #include "FFmpegLog.h" - #include "prlink.h" --#ifdef MOZ_WAYLAND --# include "mozilla/widget/DMABufLibWrapper.h" --# include "mozilla/StaticPrefs_media.h" --#endif - - namespace mozilla { - -@@ -58,43 +54,7 @@ bool FFmpegRuntimeLinker::Init() { - } - - #ifdef MOZ_WAYLAND -- if (widget::GetDMABufDevice()->IsDMABufVAAPIEnabled()) { -- PRLibSpec lspec; -- lspec.type = PR_LibSpec_Pathname; -- const char* libDrm = "libva-drm.so.2"; -- lspec.value.pathname = libDrm; -- sLibAV.mVALibDrm = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -- if (!sLibAV.mVALibDrm) { -- FFMPEG_LOG("VA-API support: Missing or old %s library.\n", libDrm); -- } -- -- if (!StaticPrefs::media_ffmpeg_vaapi_drm_display_enabled()) { -- const char* libWayland = "libva-wayland.so.2"; -- lspec.value.pathname = libWayland; -- sLibAV.mVALibWayland = -- PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -- if (!sLibAV.mVALibWayland) { -- FFMPEG_LOG("VA-API support: Missing or old %s library.\n", libWayland); -- } -- } -- -- if (sLibAV.mVALibWayland || sLibAV.mVALibDrm) { -- const char* lib = "libva.so.2"; -- lspec.value.pathname = lib; -- sLibAV.mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -- // Don't use libva when it's missing vaExportSurfaceHandle. -- if (sLibAV.mVALib && -- !PR_FindSymbol(sLibAV.mVALib, "vaExportSurfaceHandle")) { -- PR_UnloadLibrary(sLibAV.mVALib); -- sLibAV.mVALib = nullptr; -- } -- if (!sLibAV.mVALib) { -- FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib); -- } -- } -- } else { -- FFMPEG_LOG("VA-API FFmpeg is disabled by platform"); -- } -+ sLibAV.LinkVAAPILibs(); - #endif - - // While going through all possible libs, this status will be updated with a -diff -up firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2020-12-10 20:40:53.392541452 +0100 -@@ -32,6 +32,8 @@ - # define AV_PIX_FMT_NONE PIX_FMT_NONE - #endif - #include "mozilla/PodOperations.h" -+#include "mozilla/ScopeExit.h" -+#include "mozilla/StaticPrefs_media.h" - #include "mozilla/TaskQueue.h" - #include "nsThreadUtils.h" - #include "prsystem.h" -@@ -45,7 +47,7 @@ typedef int VAStatus; - #endif - - // Use some extra HW frames for potential rendering lags. --#define EXTRA_HW_FRAMES 6 -+#define EXTRA_HW_FRAMES 20 - - typedef mozilla::layers::Image Image; - typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage; -@@ -124,8 +126,8 @@ static AVPixelFormat ChooseVAAPIPixelFor - return AV_PIX_FMT_NONE; - } - --DMABufSurfaceWrapper::DMABufSurfaceWrapper(DMABufSurface* aSurface, -- FFmpegLibWrapper* aLib) -+DMABufSurfaceWrapper::DMABufSurfaceWrapper(DMABufSurface* aSurface, -+ FFmpegLibWrapper* aLib) - : mSurface(aSurface), - mLib(aLib), - mAVHWFramesContext(nullptr), -@@ -138,8 +140,8 @@ DMABufSurfaceWrapper::DMABufSurfaceWrapp - mSurface->GetUID()); - } - --void DMABufSurfaceWrapper::LockVAAPIData(AVCodecContext* aAVCodecContext, -- AVFrame* aAVFrame) { -+void DMABufSurfaceWrapper::LockVAAPIData( -+ AVCodecContext* aAVCodecContext, AVFrame* aAVFrame) { - FFMPEG_LOG("DMABufSurfaceWrapper: VAAPI locking dmabuf surface UID = %d", - mSurface->GetUID()); - if (aAVCodecContext && aAVFrame) { -@@ -148,7 +150,7 @@ void DMABufSurfaceWrapper::LockVAAPIData - } - } - --void DMABufSurfaceWrapper::ReleaseVAAPIData() { -+void DMABufSurfaceWrapper::ReleaseVAAPIData() { - FFMPEG_LOG("DMABufSurfaceWrapper: VAAPI releasing dmabuf surface UID = %d", - mSurface->GetUID()); - if (mHWAVBuffer && mAVHWFramesContext) { -@@ -158,7 +160,7 @@ void DMABufSurfaceWrapper::ReleaseVAAPID - mSurface->ReleaseSurface(); - } - --DMABufSurfaceWrapper::~DMABufSurfaceWrapper() { -+DMABufSurfaceWrapper::~DMABufSurfaceWrapper() { - FFMPEG_LOG("DMABufSurfaceWrapper: deleting dmabuf surface UID = %d", - mSurface->GetUID()); - ReleaseVAAPIData(); -@@ -181,7 +183,14 @@ AVCodec* FFmpegVideoDecoder:: - return nullptr; - } - --class VAAPIDisplayHolder { -+template -+class VAAPIDisplayHolder {}; -+ -+template <> -+class VAAPIDisplayHolder; -+ -+template <> -+class VAAPIDisplayHolder { - public: - VAAPIDisplayHolder(FFmpegLibWrapper* aLib, VADisplay aDisplay) - : mLib(aLib), mDisplay(aDisplay){}; -@@ -193,7 +202,8 @@ class VAAPIDisplayHolder { - }; - - static void VAAPIDisplayReleaseCallback(struct AVHWDeviceContext* hwctx) { -- auto displayHolder = static_cast(hwctx->user_opaque); -+ auto displayHolder = -+ static_cast*>(hwctx->user_opaque); - delete displayHolder; - } - -@@ -229,7 +239,7 @@ bool FFmpegVideoDecoder::Crea - } - } - -- hwctx->user_opaque = new VAAPIDisplayHolder(mLib, mDisplay); -+ hwctx->user_opaque = new VAAPIDisplayHolder(mLib, mDisplay); - hwctx->free = VAAPIDisplayReleaseCallback; - - int major, minor; -@@ -703,7 +713,7 @@ void FFmpegVideoDecoder::Rele - } - } - --DMABufSurfaceWrapper* -+DMABufSurfaceWrapper* - FFmpegVideoDecoder::GetUnusedDMABufSurfaceWrapper() { - int len = mDMABufSurfaces.Length(); - for (int i = 0; i < len; i++) { -@@ -769,7 +779,8 @@ MediaResult FFmpegVideoDecoder surface; - -- DMABufSurfaceWrapper* surfaceWrapper = GetUnusedDMABufSurfaceWrapper(); -+ DMABufSurfaceWrapper* surfaceWrapper = -+ GetUnusedDMABufSurfaceWrapper(); - if (!surfaceWrapper) { - if (mVAAPIDeviceContext) { - surface = DMABufSurfaceYUV::CreateYUVSurface(vaDesc); -diff -up firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h ---- firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h 2020-12-10 20:40:53.388541336 +0100 -@@ -55,7 +55,14 @@ namespace mozilla { - // We own the DMABufSurface underlying GPU data and we use it for - // repeated rendering of video frames. - // --class DMABufSurfaceWrapper final { -+template -+class DMABufSurfaceWrapper {}; -+ -+template <> -+class DMABufSurfaceWrapper; -+ -+template <> -+class DMABufSurfaceWrapper final { - public: - DMABufSurfaceWrapper(DMABufSurface* aSurface, FFmpegLibWrapper* aLib); - ~DMABufSurfaceWrapper(); -@@ -162,7 +169,7 @@ class FFmpegVideoDecoder - MediaDataDecoder::DecodedData& aResults); - - void ReleaseUnusedVAAPIFrames(); -- DMABufSurfaceWrapper* GetUnusedDMABufSurfaceWrapper(); -+ DMABufSurfaceWrapper* GetUnusedDMABufSurfaceWrapper(); - void ReleaseDMABufSurfaces(); - #endif - -@@ -180,7 +187,7 @@ class FFmpegVideoDecoder - const bool mDisableHardwareDecoding; - VADisplay mDisplay; - bool mUseDMABufSurfaces; -- nsTArray mDMABufSurfaces; -+ nsTArray> mDMABufSurfaces; - #endif - RefPtr mImageAllocator; - RefPtr mImageContainer; -diff -up firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp ---- firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp 2020-12-10 20:40:53.388541336 +0100 -@@ -64,6 +64,10 @@ bool FFVPXRuntimeLinker::Init() { - MOZ_ASSERT(NS_IsMainThread()); - sLinkStatus = LinkStatus_FAILED; - -+#ifdef MOZ_WAYLAND -+ sFFVPXLib.LinkVAAPILibs(); -+#endif -+ - // We retrieve the path of the lgpllibs library as this is where mozavcodec - // and mozavutil libs are located. - PathString lgpllibsname = GetLibraryName(nullptr, "lgpllibs"); -diff -up firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/moz.build.ffvpx firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/moz.build ---- firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/moz.build.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/platforms/ffmpeg/ffvpx/moz.build 2020-12-10 20:36:08.431441959 +0100 -@@ -36,4 +36,8 @@ if CONFIG["CC_TYPE"] == "gcc": - DEFINES["FFVPX_VERSION"] = 46465650 - DEFINES["USING_MOZFFVPX"] = True - -+if CONFIG["MOZ_WAYLAND"]: -+ CXXFLAGS += CONFIG["TK_CFLAGS"] -+ DEFINES["MOZ_WAYLAND_USE_VAAPI"] = 1 -+ - FINAL_LIBRARY = "xul" -diff -up firefox-84.0/gfx/layers/DMABUFSurfaceImage.cpp.ffvpx firefox-84.0/gfx/layers/DMABUFSurfaceImage.cpp ---- firefox-84.0/gfx/layers/DMABUFSurfaceImage.cpp.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/gfx/layers/DMABUFSurfaceImage.cpp 2020-12-10 20:36:08.308438509 +0100 -@@ -5,16 +5,23 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "DMABUFSurfaceImage.h" --#include "gfxPlatform.h" -+#include "mozilla/widget/DMABufSurface.h" - #include "mozilla/layers/CompositableClient.h" - #include "mozilla/layers/CompositableForwarder.h" - #include "mozilla/layers/DMABUFTextureClientOGL.h" --#include "mozilla/UniquePtr.h" -+#include "mozilla/layers/TextureForwarder.h" - - using namespace mozilla; - using namespace mozilla::layers; - using namespace mozilla::gfx; - -+DMABUFSurfaceImage::DMABUFSurfaceImage(DMABufSurface* aSurface) -+ : Image(nullptr, ImageFormat::DMABUF), mSurface(aSurface) { -+ mSurface->GlobalRefAdd(); -+} -+ -+DMABUFSurfaceImage::~DMABUFSurfaceImage() { mSurface->GlobalRefRelease(); } -+ - TextureClient* DMABUFSurfaceImage::GetTextureClient( - KnowsCompositor* aKnowsCompositor) { - if (!mTextureClient) { -@@ -25,3 +32,7 @@ TextureClient* DMABUFSurfaceImage::GetTe - } - return mTextureClient; - } -+ -+gfx::IntSize DMABUFSurfaceImage::GetSize() const { -+ return gfx::IntSize::Truncate(mSurface->GetWidth(), mSurface->GetHeight()); -+} -diff -up firefox-84.0/gfx/layers/DMABUFSurfaceImage.h.ffvpx firefox-84.0/gfx/layers/DMABUFSurfaceImage.h ---- firefox-84.0/gfx/layers/DMABUFSurfaceImage.h.ffvpx 2020-12-10 20:53:45.300792876 +0100 -+++ firefox-84.0/gfx/layers/DMABUFSurfaceImage.h 2020-12-10 20:36:08.279437696 +0100 -@@ -8,32 +8,24 @@ - #define SURFACE_DMABUF_H - - #include "ImageContainer.h" --#include "mozilla/widget/DMABufSurface.h" --#include "mozilla/gfx/Point.h" --#include "mozilla/layers/TextureClient.h" -+ -+class DMABufSurface; - - namespace mozilla { - namespace layers { - -+class TextureClient; -+ - class DMABUFSurfaceImage : public Image { - public: -- explicit DMABUFSurfaceImage(DMABufSurface* aSurface) -- : Image(nullptr, ImageFormat::DMABUF), mSurface(aSurface) { -- mSurface->GlobalRefAdd(); -- } -- -- ~DMABUFSurfaceImage() { mSurface->GlobalRefRelease(); } -+ explicit DMABUFSurfaceImage(DMABufSurface* aSurface); -+ ~DMABUFSurfaceImage(); - - DMABufSurface* GetSurface() { return mSurface; } -- -- gfx::IntSize GetSize() const override { -- return gfx::IntSize::Truncate(mSurface->GetWidth(), mSurface->GetHeight()); -- } -- -+ gfx::IntSize GetSize() const override; - already_AddRefed GetAsSourceSurface() override { - return nullptr; - } -- - TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) override; - - private: -diff -up firefox-84.0/media/ffvpx/changes.patch.ffvpx firefox-84.0/media/ffvpx/changes.patch ---- firefox-84.0/media/ffvpx/changes.patch.ffvpx 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/media/ffvpx/changes.patch 2020-12-10 20:40:53.388541336 +0100 -@@ -50,3 +50,27 @@ index 9fb8d0a..97ad3b9 100644 - rgba_color[0] = rgba >> 24; - rgba_color[1] = rgba >> 16; - rgba_color[2] = rgba >> 8; -+diff --git a/media/ffvpx/libavutil/hwcontext_vaapi.c b/media/ffvpx/libavutil/hwcontext_vaapi.c -+--- a/media/ffvpx/libavutil/hwcontext_vaapi.c -++++ b/media/ffvpx/libavutil/hwcontext_vaapi.c -+@@ -39,17 +39,19 @@ -+ # include -+ #endif -+ -+ -+ #include "avassert.h" -+ #include "buffer.h" -+ #include "common.h" -+ #include "hwcontext.h" -++#if CONFIG_LIBDRM -+ #include "hwcontext_drm.h" -++#endif -+ #include "hwcontext_internal.h" -+ #include "hwcontext_vaapi.h" -+ #include "mem.h" -+ #include "pixdesc.h" -+ #include "pixfmt.h" -+ -+ -+ typedef struct VAAPIDevicePriv { -+ -diff -up firefox-84.0/media/ffvpx/config_common.h.ffvpx firefox-84.0/media/ffvpx/config_common.h ---- firefox-84.0/media/ffvpx/config_common.h.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/config_common.h 2020-12-10 20:40:53.388541336 +0100 -@@ -18,4 +18,13 @@ - #define CONFIG_RDFT 1 - #endif - -+#ifdef MOZ_WAYLAND -+#undef CONFIG_VAAPI -+#undef CONFIG_VP8_VAAPI_HWACCEL -+#undef CONFIG_VP9_VAAPI_HWACCEL -+#define CONFIG_VAAPI 1 -+#define CONFIG_VP8_VAAPI_HWACCEL 1 -+#define CONFIG_VP9_VAAPI_HWACCEL 1 -+#endif -+ - #endif -diff -up firefox-84.0/media/ffvpx/FILES.ffvpx firefox-84.0/media/ffvpx/FILES ---- firefox-84.0/media/ffvpx/FILES.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/FILES 2020-12-10 20:40:53.388541336 +0100 -@@ -131,6 +131,11 @@ - ./libavcodec/thread.h - ./libavcodec/unary.h - ./libavcodec/utils.c -+./libavcodec/vaapi.h -+./libavcodec/vaapi_decode.h -+./libavcodec/vaapi_decode.c -+./libavcodec/vaapi_vp8.c -+./libavcodec/vaapi_vp9.c - ./libavcodec/version.h - ./libavcodec/videodsp.c - ./libavcodec/videodsp.h -@@ -264,6 +269,8 @@ - ./libavutil/hwcontext.c - ./libavutil/hwcontext.h - ./libavutil/hwcontext_internal.h -+./libavutil/hwcontext_vaapi.h -+./libavutil/hwcontext_vaapi.c - ./libavutil/imgutils.c - ./libavutil/imgutils.h - ./libavutil/imgutils_internal.h -diff -up firefox-84.0/media/ffvpx/libavcodec/avcodec.symbols.ffvpx firefox-84.0/media/ffvpx/libavcodec/avcodec.symbols ---- firefox-84.0/media/ffvpx/libavcodec/avcodec.symbols.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/avcodec.symbols 2020-12-10 20:40:53.389541365 +0100 -@@ -28,6 +28,11 @@ av_get_pcm_codec - av_get_profile_name - av_grow_packet - av_hwaccel_next -+av_hwdevice_ctx_init -+av_hwdevice_ctx_alloc -+av_hwdevice_ctx_create_derived -+av_hwframe_transfer_get_formats -+av_hwframe_ctx_alloc - av_init_packet - av_lockmgr_register - av_new_packet -@@ -93,6 +98,7 @@ avcodec_free_context - avcodec_get_class - avcodec_get_context_defaults3 - avcodec_get_frame_class -+avcodec_get_hw_config - avcodec_get_name - avcodec_get_subtitle_rect_class - avcodec_get_type -diff -up firefox-84.0/media/ffvpx/libavcodec/moz.build.ffvpx firefox-84.0/media/ffvpx/libavcodec/moz.build ---- firefox-84.0/media/ffvpx/libavcodec/moz.build.ffvpx 2020-12-10 20:40:53.383541192 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/moz.build 2020-12-10 20:40:53.389541365 +0100 -@@ -96,6 +96,13 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: - 'vp9prob.c', - 'vp9recon.c' - ] -+ if CONFIG['MOZ_WAYLAND']: -+ SOURCES += [ -+ 'vaapi_decode.c', -+ 'vaapi_vp8.c', -+ 'vaapi_vp9.c', -+ ] -+ USE_LIBS += ['mozva'] - - if CONFIG['MOZ_FDK_AAC']: - SOURCES += [ -diff -up firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.c.ffvpx firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.c ---- firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.c.ffvpx 2020-12-10 20:40:53.389541365 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.c 2020-12-10 20:40:53.389541365 +0100 -@@ -0,0 +1,732 @@ -+/* -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "libavutil/avassert.h" -+#include "libavutil/common.h" -+#include "libavutil/pixdesc.h" -+ -+#include "avcodec.h" -+#include "decode.h" -+#include "internal.h" -+#include "vaapi_decode.h" -+ -+ -+int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic, -+ int type, -+ const void *data, -+ size_t size) -+{ -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ VAStatus vas; -+ VABufferID buffer; -+ -+ av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS); -+ -+ vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, -+ type, size, 1, (void*)data, &buffer); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to create parameter " -+ "buffer (type %d): %d (%s).\n", -+ type, vas, vaErrorStr(vas)); -+ return AVERROR(EIO); -+ } -+ -+ pic->param_buffers[pic->nb_param_buffers++] = buffer; -+ -+ av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes) " -+ "is %#x.\n", type, size, buffer); -+ return 0; -+} -+ -+ -+int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic, -+ const void *params_data, -+ size_t params_size, -+ const void *slice_data, -+ size_t slice_size) -+{ -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ VAStatus vas; -+ int index; -+ -+ av_assert0(pic->nb_slices <= pic->slices_allocated); -+ if (pic->nb_slices == pic->slices_allocated) { -+ if (pic->slices_allocated > 0) -+ pic->slices_allocated *= 2; -+ else -+ pic->slices_allocated = 64; -+ -+ pic->slice_buffers = -+ av_realloc_array(pic->slice_buffers, -+ pic->slices_allocated, -+ 2 * sizeof(*pic->slice_buffers)); -+ if (!pic->slice_buffers) -+ return AVERROR(ENOMEM); -+ } -+ av_assert0(pic->nb_slices + 1 <= pic->slices_allocated); -+ -+ index = 2 * pic->nb_slices; -+ -+ vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, -+ VASliceParameterBufferType, -+ params_size, 1, (void*)params_data, -+ &pic->slice_buffers[index]); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to create slice " -+ "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas)); -+ return AVERROR(EIO); -+ } -+ -+ av_log(avctx, AV_LOG_DEBUG, "Slice %d param buffer (%zu bytes) " -+ "is %#x.\n", pic->nb_slices, params_size, -+ pic->slice_buffers[index]); -+ -+ vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, -+ VASliceDataBufferType, -+ slice_size, 1, (void*)slice_data, -+ &pic->slice_buffers[index + 1]); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to create slice " -+ "data buffer (size %zu): %d (%s).\n", -+ slice_size, vas, vaErrorStr(vas)); -+ vaDestroyBuffer(ctx->hwctx->display, -+ pic->slice_buffers[index]); -+ return AVERROR(EIO); -+ } -+ -+ av_log(avctx, AV_LOG_DEBUG, "Slice %d data buffer (%zu bytes) " -+ "is %#x.\n", pic->nb_slices, slice_size, -+ pic->slice_buffers[index + 1]); -+ -+ ++pic->nb_slices; -+ return 0; -+} -+ -+static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic) -+{ -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ VAStatus vas; -+ int i; -+ -+ for (i = 0; i < pic->nb_param_buffers; i++) { -+ vas = vaDestroyBuffer(ctx->hwctx->display, -+ pic->param_buffers[i]); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to destroy " -+ "parameter buffer %#x: %d (%s).\n", -+ pic->param_buffers[i], vas, vaErrorStr(vas)); -+ } -+ } -+ -+ for (i = 0; i < 2 * pic->nb_slices; i++) { -+ vas = vaDestroyBuffer(ctx->hwctx->display, -+ pic->slice_buffers[i]); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to destroy slice " -+ "slice buffer %#x: %d (%s).\n", -+ pic->slice_buffers[i], vas, vaErrorStr(vas)); -+ } -+ } -+} -+ -+int ff_vaapi_decode_issue(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic) -+{ -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ VAStatus vas; -+ int err; -+ -+ av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n", -+ pic->output_surface); -+ -+ vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context, -+ pic->output_surface); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to begin picture decode " -+ "issue: %d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail_with_picture; -+ } -+ -+ vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, -+ pic->param_buffers, pic->nb_param_buffers); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to upload decode " -+ "parameters: %d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail_with_picture; -+ } -+ -+ vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, -+ pic->slice_buffers, 2 * pic->nb_slices); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to upload slices: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail_with_picture; -+ } -+ -+ vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode " -+ "issue: %d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & -+ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) -+ goto fail; -+ else -+ goto fail_at_end; -+ } -+ -+ if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & -+ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) -+ ff_vaapi_decode_destroy_buffers(avctx, pic); -+ -+ err = 0; -+ goto exit; -+ -+fail_with_picture: -+ vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode " -+ "after error: %d (%s).\n", vas, vaErrorStr(vas)); -+ } -+fail: -+ ff_vaapi_decode_destroy_buffers(avctx, pic); -+fail_at_end: -+exit: -+ pic->nb_param_buffers = 0; -+ pic->nb_slices = 0; -+ pic->slices_allocated = 0; -+ av_freep(&pic->slice_buffers); -+ -+ return err; -+} -+ -+int ff_vaapi_decode_cancel(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic) -+{ -+ ff_vaapi_decode_destroy_buffers(avctx, pic); -+ -+ pic->nb_param_buffers = 0; -+ pic->nb_slices = 0; -+ pic->slices_allocated = 0; -+ av_freep(&pic->slice_buffers); -+ -+ return 0; -+} -+ -+static const struct { -+ uint32_t fourcc; -+ enum AVPixelFormat pix_fmt; -+} vaapi_format_map[] = { -+#define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av } -+ // 4:0:0 -+ MAP(Y800, GRAY8), -+ // 4:2:0 -+ MAP(NV12, NV12), -+ MAP(YV12, YUV420P), -+ MAP(IYUV, YUV420P), -+#ifdef VA_FOURCC_I420 -+ MAP(I420, YUV420P), -+#endif -+ MAP(IMC3, YUV420P), -+ // 4:1:1 -+ MAP(411P, YUV411P), -+ // 4:2:2 -+ MAP(422H, YUV422P), -+#ifdef VA_FOURCC_YV16 -+ MAP(YV16, YUV422P), -+#endif -+ // 4:4:0 -+ MAP(422V, YUV440P), -+ // 4:4:4 -+ MAP(444P, YUV444P), -+ // 4:2:0 10-bit -+#ifdef VA_FOURCC_P010 -+ MAP(P010, P010), -+#endif -+#ifdef VA_FOURCC_I010 -+ MAP(I010, YUV420P10), -+#endif -+#undef MAP -+}; -+ -+static int vaapi_decode_find_best_format(AVCodecContext *avctx, -+ AVHWDeviceContext *device, -+ VAConfigID config_id, -+ AVHWFramesContext *frames) -+{ -+ AVVAAPIDeviceContext *hwctx = device->hwctx; -+ VAStatus vas; -+ VASurfaceAttrib *attr; -+ enum AVPixelFormat source_format, best_format, format; -+ uint32_t best_fourcc, fourcc; -+ int i, j, nb_attr; -+ -+ source_format = avctx->sw_pix_fmt; -+ av_assert0(source_format != AV_PIX_FMT_NONE); -+ -+ vas = vaQuerySurfaceAttributes(hwctx->display, config_id, -+ NULL, &nb_attr); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ return AVERROR(ENOSYS); -+ } -+ -+ attr = av_malloc_array(nb_attr, sizeof(*attr)); -+ if (!attr) -+ return AVERROR(ENOMEM); -+ -+ vas = vaQuerySurfaceAttributes(hwctx->display, config_id, -+ attr, &nb_attr); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ av_freep(&attr); -+ return AVERROR(ENOSYS); -+ } -+ -+ best_format = AV_PIX_FMT_NONE; -+ -+ for (i = 0; i < nb_attr; i++) { -+ if (attr[i].type != VASurfaceAttribPixelFormat) -+ continue; -+ -+ fourcc = attr[i].value.value.i; -+ for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) { -+ if (fourcc == vaapi_format_map[j].fourcc) -+ break; -+ } -+ if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) { -+ av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format %#x.\n", -+ fourcc); -+ continue; -+ } -+ format = vaapi_format_map[j].pix_fmt; -+ av_log(avctx, AV_LOG_DEBUG, "Considering format %#x -> %s.\n", -+ fourcc, av_get_pix_fmt_name(format)); -+ -+ best_format = av_find_best_pix_fmt_of_2(format, best_format, -+ source_format, 0, NULL); -+ if (format == best_format) -+ best_fourcc = fourcc; -+ } -+ -+ av_freep(&attr); -+ -+ if (best_format == AV_PIX_FMT_NONE) { -+ av_log(avctx, AV_LOG_ERROR, "No usable formats for decoding!\n"); -+ return AVERROR(EINVAL); -+ } -+ -+ av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for %s.\n", -+ av_get_pix_fmt_name(best_format), best_fourcc, -+ av_get_pix_fmt_name(source_format)); -+ -+ frames->sw_format = best_format; -+ if (avctx->internal->hwaccel_priv_data) { -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ AVVAAPIFramesContext *avfc = frames->hwctx; -+ -+ ctx->pixel_format_attribute = (VASurfaceAttrib) { -+ .type = VASurfaceAttribPixelFormat, -+ .value.value.i = best_fourcc, -+ }; -+ -+ avfc->attributes = &ctx->pixel_format_attribute; -+ avfc->nb_attributes = 1; -+ } -+ -+ return 0; -+} -+ -+static const struct { -+ enum AVCodecID codec_id; -+ int codec_profile; -+ VAProfile va_profile; -+} vaapi_profile_map[] = { -+#define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v } -+ MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ), -+ MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ), -+ MAP(H263, UNKNOWN, H263Baseline), -+ MAP(MPEG4, MPEG4_SIMPLE, MPEG4Simple ), -+ MAP(MPEG4, MPEG4_ADVANCED_SIMPLE, -+ MPEG4AdvancedSimple), -+ MAP(MPEG4, MPEG4_MAIN, MPEG4Main ), -+ MAP(H264, H264_CONSTRAINED_BASELINE, -+ H264ConstrainedBaseline), -+ MAP(H264, H264_MAIN, H264Main ), -+ MAP(H264, H264_HIGH, H264High ), -+#if VA_CHECK_VERSION(0, 37, 0) -+ MAP(HEVC, HEVC_MAIN, HEVCMain ), -+ MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ), -+#endif -+ MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT, -+ JPEGBaseline), -+ MAP(WMV3, VC1_SIMPLE, VC1Simple ), -+ MAP(WMV3, VC1_MAIN, VC1Main ), -+ MAP(WMV3, VC1_COMPLEX, VC1Advanced ), -+ MAP(WMV3, VC1_ADVANCED, VC1Advanced ), -+ MAP(VC1, VC1_SIMPLE, VC1Simple ), -+ MAP(VC1, VC1_MAIN, VC1Main ), -+ MAP(VC1, VC1_COMPLEX, VC1Advanced ), -+ MAP(VC1, VC1_ADVANCED, VC1Advanced ), -+ MAP(VP8, UNKNOWN, VP8Version0_3 ), -+#if VA_CHECK_VERSION(0, 38, 0) -+ MAP(VP9, VP9_0, VP9Profile0 ), -+#endif -+#if VA_CHECK_VERSION(0, 39, 0) -+ MAP(VP9, VP9_2, VP9Profile2 ), -+#endif -+#undef MAP -+}; -+ -+/* -+ * Set *va_config and the frames_ref fields from the current codec parameters -+ * in avctx. -+ */ -+static int vaapi_decode_make_config(AVCodecContext *avctx, -+ AVBufferRef *device_ref, -+ VAConfigID *va_config, -+ AVBufferRef *frames_ref) -+{ -+ AVVAAPIHWConfig *hwconfig = NULL; -+ AVHWFramesConstraints *constraints = NULL; -+ VAStatus vas; -+ int err, i, j; -+ const AVCodecDescriptor *codec_desc; -+ VAProfile *profile_list = NULL, matched_va_profile; -+ int profile_count, exact_match, matched_ff_profile; -+ -+ AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; -+ AVVAAPIDeviceContext *hwctx = device->hwctx; -+ -+ codec_desc = avcodec_descriptor_get(avctx->codec_id); -+ if (!codec_desc) { -+ err = AVERROR(EINVAL); -+ goto fail; -+ } -+ -+ profile_count = vaMaxNumProfiles(hwctx->display); -+ profile_list = av_malloc_array(profile_count, -+ sizeof(VAProfile)); -+ if (!profile_list) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ vas = vaQueryConfigProfiles(hwctx->display, -+ profile_list, &profile_count); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(ENOSYS); -+ goto fail; -+ } -+ -+ matched_va_profile = VAProfileNone; -+ exact_match = 0; -+ -+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) { -+ int profile_match = 0; -+ if (avctx->codec_id != vaapi_profile_map[i].codec_id) -+ continue; -+ if (avctx->profile == vaapi_profile_map[i].codec_profile || -+ vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN) -+ profile_match = 1; -+ for (j = 0; j < profile_count; j++) { -+ if (vaapi_profile_map[i].va_profile == profile_list[j]) { -+ exact_match = profile_match; -+ break; -+ } -+ } -+ if (j < profile_count) { -+ matched_va_profile = vaapi_profile_map[i].va_profile; -+ matched_ff_profile = vaapi_profile_map[i].codec_profile; -+ if (exact_match) -+ break; -+ } -+ } -+ av_freep(&profile_list); -+ -+ if (matched_va_profile == VAProfileNone) { -+ av_log(avctx, AV_LOG_ERROR, "No support for codec %s " -+ "profile %d.\n", codec_desc->name, avctx->profile); -+ err = AVERROR(ENOSYS); -+ goto fail; -+ } -+ if (!exact_match) { -+ if (avctx->hwaccel_flags & -+ AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) { -+ av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " -+ "supported for hardware decode.\n", -+ codec_desc->name, avctx->profile); -+ av_log(avctx, AV_LOG_WARNING, "Using possibly-" -+ "incompatible profile %d instead.\n", -+ matched_ff_profile); -+ } else { -+ av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " -+ "supported for hardware decode.\n", -+ codec_desc->name, avctx->profile); -+ err = AVERROR(EINVAL); -+ goto fail; -+ } -+ } -+ -+ vas = vaCreateConfig(hwctx->display, matched_va_profile, -+ VAEntrypointVLD, NULL, 0, -+ va_config); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to create decode " -+ "configuration: %d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ -+ hwconfig = av_hwdevice_hwconfig_alloc(device_ref); -+ if (!hwconfig) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ hwconfig->config_id = *va_config; -+ -+ constraints = -+ av_hwdevice_get_hwframe_constraints(device_ref, hwconfig); -+ if (!constraints) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ if (avctx->coded_width < constraints->min_width || -+ avctx->coded_height < constraints->min_height || -+ avctx->coded_width > constraints->max_width || -+ avctx->coded_height > constraints->max_height) { -+ av_log(avctx, AV_LOG_ERROR, "Hardware does not support image " -+ "size %dx%d (constraints: width %d-%d height %d-%d).\n", -+ avctx->coded_width, avctx->coded_height, -+ constraints->min_width, constraints->max_width, -+ constraints->min_height, constraints->max_height); -+ err = AVERROR(EINVAL); -+ goto fail; -+ } -+ if (!constraints->valid_sw_formats || -+ constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) { -+ av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any " -+ "usable surface formats.\n"); -+ err = AVERROR(EINVAL); -+ goto fail; -+ } -+ -+ if (frames_ref) { -+ AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; -+ -+ frames->format = AV_PIX_FMT_VAAPI; -+ frames->width = avctx->coded_width; -+ frames->height = avctx->coded_height; -+ -+ err = vaapi_decode_find_best_format(avctx, device, -+ *va_config, frames); -+ if (err < 0) -+ goto fail; -+ -+ frames->initial_pool_size = 1; -+ // Add per-codec number of surfaces used for storing reference frames. -+ switch (avctx->codec_id) { -+ case AV_CODEC_ID_H264: -+ case AV_CODEC_ID_HEVC: -+ frames->initial_pool_size += 16; -+ break; -+ case AV_CODEC_ID_VP9: -+ frames->initial_pool_size += 8; -+ break; -+ case AV_CODEC_ID_VP8: -+ frames->initial_pool_size += 3; -+ break; -+ default: -+ frames->initial_pool_size += 2; -+ } -+ } -+ -+ av_hwframe_constraints_free(&constraints); -+ av_freep(&hwconfig); -+ -+ return 0; -+ -+fail: -+ av_hwframe_constraints_free(&constraints); -+ av_freep(&hwconfig); -+ if (*va_config != VA_INVALID_ID) { -+ vaDestroyConfig(hwctx->display, *va_config); -+ *va_config = VA_INVALID_ID; -+ } -+ av_freep(&profile_list); -+ return err; -+} -+ -+int ff_vaapi_common_frame_params(AVCodecContext *avctx, -+ AVBufferRef *hw_frames_ctx) -+{ -+ AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data; -+ AVHWDeviceContext *device_ctx = hw_frames->device_ctx; -+ AVVAAPIDeviceContext *hwctx; -+ VAConfigID va_config = VA_INVALID_ID; -+ int err; -+ -+ if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI) -+ return AVERROR(EINVAL); -+ hwctx = device_ctx->hwctx; -+ -+ err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config, -+ hw_frames_ctx); -+ if (err) -+ return err; -+ -+ if (va_config != VA_INVALID_ID) -+ vaDestroyConfig(hwctx->display, va_config); -+ -+ return 0; -+} -+ -+int ff_vaapi_decode_init(AVCodecContext *avctx) -+{ -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ VAStatus vas; -+ int err; -+ -+ ctx->va_config = VA_INVALID_ID; -+ ctx->va_context = VA_INVALID_ID; -+ -+#if FF_API_STRUCT_VAAPI_CONTEXT -+ if (avctx->hwaccel_context) { -+ av_log(avctx, AV_LOG_WARNING, "Using deprecated struct " -+ "vaapi_context in decode.\n"); -+ -+ ctx->have_old_context = 1; -+ ctx->old_context = avctx->hwaccel_context; -+ -+ // Really we only want the VAAPI device context, but this -+ // allocates a whole generic device context because we don't -+ // have any other way to determine how big it should be. -+ ctx->device_ref = -+ av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI); -+ if (!ctx->device_ref) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ ctx->device = (AVHWDeviceContext*)ctx->device_ref->data; -+ ctx->hwctx = ctx->device->hwctx; -+ -+ ctx->hwctx->display = ctx->old_context->display; -+ -+ // The old VAAPI decode setup assumed this quirk was always -+ // present, so set it here to avoid the behaviour changing. -+ ctx->hwctx->driver_quirks = -+ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS; -+ -+ } -+#endif -+ -+#if FF_API_STRUCT_VAAPI_CONTEXT -+ if (ctx->have_old_context) { -+ ctx->va_config = ctx->old_context->config_id; -+ ctx->va_context = ctx->old_context->context_id; -+ -+ av_log(avctx, AV_LOG_DEBUG, "Using user-supplied decoder " -+ "context: %#x/%#x.\n", ctx->va_config, ctx->va_context); -+ } else { -+#endif -+ -+ err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI); -+ if (err < 0) -+ goto fail; -+ -+ ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; -+ ctx->hwfc = ctx->frames->hwctx; -+ ctx->device = ctx->frames->device_ctx; -+ ctx->hwctx = ctx->device->hwctx; -+ -+ err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, -+ &ctx->va_config, avctx->hw_frames_ctx); -+ if (err) -+ goto fail; -+ -+ vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, -+ avctx->coded_width, avctx->coded_height, -+ VA_PROGRESSIVE, -+ ctx->hwfc->surface_ids, -+ ctx->hwfc->nb_surfaces, -+ &ctx->va_context); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to create decode " -+ "context: %d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ -+ av_log(avctx, AV_LOG_DEBUG, "Decode context initialised: " -+ "%#x/%#x.\n", ctx->va_config, ctx->va_context); -+#if FF_API_STRUCT_VAAPI_CONTEXT -+ } -+#endif -+ -+ return 0; -+ -+fail: -+ ff_vaapi_decode_uninit(avctx); -+ return err; -+} -+ -+int ff_vaapi_decode_uninit(AVCodecContext *avctx) -+{ -+ VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; -+ VAStatus vas; -+ -+#if FF_API_STRUCT_VAAPI_CONTEXT -+ if (ctx->have_old_context) { -+ av_buffer_unref(&ctx->device_ref); -+ } else { -+#endif -+ -+ if (ctx->va_context != VA_INVALID_ID) { -+ vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode " -+ "context %#x: %d (%s).\n", -+ ctx->va_context, vas, vaErrorStr(vas)); -+ } -+ } -+ if (ctx->va_config != VA_INVALID_ID) { -+ vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode " -+ "configuration %#x: %d (%s).\n", -+ ctx->va_config, vas, vaErrorStr(vas)); -+ } -+ } -+ -+#if FF_API_STRUCT_VAAPI_CONTEXT -+ } -+#endif -+ -+ return 0; -+} -diff -up firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.h.ffvpx firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.h ---- firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.h.ffvpx 2020-12-10 20:40:53.389541365 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.h 2020-12-10 20:40:53.389541365 +0100 -@@ -0,0 +1,105 @@ -+/* -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef AVCODEC_VAAPI_DECODE_H -+#define AVCODEC_VAAPI_DECODE_H -+ -+#include -+#include -+ -+#include "libavutil/frame.h" -+#include "libavutil/hwcontext.h" -+#include "libavutil/hwcontext_vaapi.h" -+ -+#include "avcodec.h" -+ -+#include "version.h" -+#if FF_API_STRUCT_VAAPI_CONTEXT -+#include "vaapi.h" -+#endif -+ -+static inline VASurfaceID ff_vaapi_get_surface_id(AVFrame *pic) -+{ -+ return (uintptr_t)pic->data[3]; -+} -+ -+enum { -+ MAX_PARAM_BUFFERS = 16, -+}; -+ -+typedef struct VAAPIDecodePicture { -+ VASurfaceID output_surface; -+ -+ int nb_param_buffers; -+ VABufferID param_buffers[MAX_PARAM_BUFFERS]; -+ -+ int nb_slices; -+ VABufferID *slice_buffers; -+ int slices_allocated; -+} VAAPIDecodePicture; -+ -+typedef struct VAAPIDecodeContext { -+ VAConfigID va_config; -+ VAContextID va_context; -+ -+#if FF_API_STRUCT_VAAPI_CONTEXT -+FF_DISABLE_DEPRECATION_WARNINGS -+ int have_old_context; -+ struct vaapi_context *old_context; -+ AVBufferRef *device_ref; -+FF_ENABLE_DEPRECATION_WARNINGS -+#endif -+ -+ AVHWDeviceContext *device; -+ AVVAAPIDeviceContext *hwctx; -+ -+ AVHWFramesContext *frames; -+ AVVAAPIFramesContext *hwfc; -+ -+ enum AVPixelFormat surface_format; -+ int surface_count; -+ -+ VASurfaceAttrib pixel_format_attribute; -+} VAAPIDecodeContext; -+ -+ -+int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic, -+ int type, -+ const void *data, -+ size_t size); -+ -+int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic, -+ const void *params_data, -+ size_t params_size, -+ const void *slice_data, -+ size_t slice_size); -+ -+int ff_vaapi_decode_issue(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic); -+int ff_vaapi_decode_cancel(AVCodecContext *avctx, -+ VAAPIDecodePicture *pic); -+ -+int ff_vaapi_decode_init(AVCodecContext *avctx); -+int ff_vaapi_decode_uninit(AVCodecContext *avctx); -+ -+int ff_vaapi_common_frame_params(AVCodecContext *avctx, -+ AVBufferRef *hw_frames_ctx); -+ -+#endif /* AVCODEC_VAAPI_DECODE_H */ -diff -up firefox-84.0/media/ffvpx/libavcodec/vaapi.h.ffvpx firefox-84.0/media/ffvpx/libavcodec/vaapi.h ---- firefox-84.0/media/ffvpx/libavcodec/vaapi.h.ffvpx 2020-12-10 20:40:53.389541365 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/vaapi.h 2020-12-10 20:40:53.389541365 +0100 -@@ -0,0 +1,86 @@ -+/* -+ * Video Acceleration API (shared data between FFmpeg and the video player) -+ * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 -+ * -+ * Copyright (C) 2008-2009 Splitted-Desktop Systems -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef AVCODEC_VAAPI_H -+#define AVCODEC_VAAPI_H -+ -+/** -+ * @file -+ * @ingroup lavc_codec_hwaccel_vaapi -+ * Public libavcodec VA API header. -+ */ -+ -+#include -+#include "libavutil/attributes.h" -+#include "version.h" -+ -+#if FF_API_STRUCT_VAAPI_CONTEXT -+ -+/** -+ * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding -+ * @ingroup lavc_codec_hwaccel -+ * @{ -+ */ -+ -+/** -+ * This structure is used to share data between the FFmpeg library and -+ * the client video application. -+ * This shall be zero-allocated and available as -+ * AVCodecContext.hwaccel_context. All user members can be set once -+ * during initialization or through each AVCodecContext.get_buffer() -+ * function call. In any case, they must be valid prior to calling -+ * decoding functions. -+ * -+ * Deprecated: use AVCodecContext.hw_frames_ctx instead. -+ */ -+struct attribute_deprecated vaapi_context { -+ /** -+ * Window system dependent data -+ * -+ * - encoding: unused -+ * - decoding: Set by user -+ */ -+ void *display; -+ -+ /** -+ * Configuration ID -+ * -+ * - encoding: unused -+ * - decoding: Set by user -+ */ -+ uint32_t config_id; -+ -+ /** -+ * Context ID (video decode pipeline) -+ * -+ * - encoding: unused -+ * - decoding: Set by user -+ */ -+ uint32_t context_id; -+}; -+ -+/* @} */ -+ -+#endif /* FF_API_STRUCT_VAAPI_CONTEXT */ -+ -+#endif /* AVCODEC_VAAPI_H */ -diff -up firefox-84.0/media/ffvpx/libavcodec/vaapi_vp8.c.ffvpx firefox-84.0/media/ffvpx/libavcodec/vaapi_vp8.c ---- firefox-84.0/media/ffvpx/libavcodec/vaapi_vp8.c.ffvpx 2020-12-10 20:40:53.389541365 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/vaapi_vp8.c 2020-12-10 20:40:53.389541365 +0100 -@@ -0,0 +1,237 @@ -+/* -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include -+#include -+ -+#include "hwaccel.h" -+#include "vaapi_decode.h" -+#include "vp8.h" -+ -+static VASurfaceID vaapi_vp8_surface_id(VP8Frame *vf) -+{ -+ if (vf) -+ return ff_vaapi_get_surface_id(vf->tf.f); -+ else -+ return VA_INVALID_SURFACE; -+} -+ -+static int vaapi_vp8_start_frame(AVCodecContext *avctx, -+ av_unused const uint8_t *buffer, -+ av_unused uint32_t size) -+{ -+ const VP8Context *s = avctx->priv_data; -+ VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; -+ VAPictureParameterBufferVP8 pp; -+ VAProbabilityDataBufferVP8 prob; -+ VAIQMatrixBufferVP8 quant; -+ int err, i, j, k; -+ -+ pic->output_surface = vaapi_vp8_surface_id(s->framep[VP56_FRAME_CURRENT]); -+ -+ pp = (VAPictureParameterBufferVP8) { -+ .frame_width = avctx->width, -+ .frame_height = avctx->height, -+ -+ .last_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_PREVIOUS]), -+ .golden_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_GOLDEN]), -+ .alt_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_GOLDEN2]), -+ .out_of_loop_frame = VA_INVALID_SURFACE, -+ -+ .pic_fields.bits = { -+ .key_frame = !s->keyframe, -+ .version = s->profile, -+ -+ .segmentation_enabled = s->segmentation.enabled, -+ .update_mb_segmentation_map = s->segmentation.update_map, -+ .update_segment_feature_data = s->segmentation.update_feature_data, -+ -+ .filter_type = s->filter.simple, -+ .sharpness_level = s->filter.sharpness, -+ -+ .loop_filter_adj_enable = s->lf_delta.enabled, -+ .mode_ref_lf_delta_update = s->lf_delta.update, -+ -+ .sign_bias_golden = s->sign_bias[VP56_FRAME_GOLDEN], -+ .sign_bias_alternate = s->sign_bias[VP56_FRAME_GOLDEN2], -+ -+ .mb_no_coeff_skip = s->mbskip_enabled, -+ .loop_filter_disable = s->filter.level == 0, -+ }, -+ -+ .prob_skip_false = s->prob->mbskip, -+ .prob_intra = s->prob->intra, -+ .prob_last = s->prob->last, -+ .prob_gf = s->prob->golden, -+ }; -+ -+ for (i = 0; i < 3; i++) -+ pp.mb_segment_tree_probs[i] = s->prob->segmentid[i]; -+ -+ for (i = 0; i < 4; i++) { -+ if (s->segmentation.enabled) { -+ pp.loop_filter_level[i] = s->segmentation.filter_level[i]; -+ if (!s->segmentation.absolute_vals) -+ pp.loop_filter_level[i] += s->filter.level; -+ } else { -+ pp.loop_filter_level[i] = s->filter.level; -+ } -+ pp.loop_filter_level[i] = av_clip_uintp2(pp.loop_filter_level[i], 6); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ pp.loop_filter_deltas_ref_frame[i] = s->lf_delta.ref[i]; -+ pp.loop_filter_deltas_mode[i] = s->lf_delta.mode[i + 4]; -+ } -+ -+ if (s->keyframe) { -+ static const uint8_t keyframe_y_mode_probs[4] = { -+ 145, 156, 163, 128 -+ }; -+ static const uint8_t keyframe_uv_mode_probs[3] = { -+ 142, 114, 183 -+ }; -+ memcpy(pp.y_mode_probs, keyframe_y_mode_probs, 4); -+ memcpy(pp.uv_mode_probs, keyframe_uv_mode_probs, 3); -+ } else { -+ for (i = 0; i < 4; i++) -+ pp.y_mode_probs[i] = s->prob->pred16x16[i]; -+ for (i = 0; i < 3; i++) -+ pp.uv_mode_probs[i] = s->prob->pred8x8c[i]; -+ } -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < 19; j++) -+ pp.mv_probs[i][j] = s->prob->mvc[i][j]; -+ -+ pp.bool_coder_ctx.range = s->coder_state_at_header_end.range; -+ pp.bool_coder_ctx.value = s->coder_state_at_header_end.value; -+ pp.bool_coder_ctx.count = s->coder_state_at_header_end.bit_count; -+ -+ err = ff_vaapi_decode_make_param_buffer(avctx, pic, -+ VAPictureParameterBufferType, -+ &pp, sizeof(pp)); -+ if (err < 0) -+ goto fail; -+ -+ for (i = 0; i < 4; i++) { -+ for (j = 0; j < 8; j++) { -+ static const int coeff_bands_inverse[8] = { -+ 0, 1, 2, 3, 5, 6, 4, 15 -+ }; -+ int coeff_pos = coeff_bands_inverse[j]; -+ -+ for (k = 0; k < 3; k++) { -+ memcpy(prob.dct_coeff_probs[i][j][k], -+ s->prob->token[i][coeff_pos][k], 11); -+ } -+ } -+ } -+ -+ err = ff_vaapi_decode_make_param_buffer(avctx, pic, -+ VAProbabilityBufferType, -+ &prob, sizeof(prob)); -+ if (err < 0) -+ goto fail; -+ -+ for (i = 0; i < 4; i++) { -+ int base_qi = s->segmentation.base_quant[i]; -+ if (!s->segmentation.absolute_vals) -+ base_qi += s->quant.yac_qi; -+ -+ quant.quantization_index[i][0] = av_clip_uintp2(base_qi, 7); -+ quant.quantization_index[i][1] = av_clip_uintp2(base_qi + s->quant.ydc_delta, 7); -+ quant.quantization_index[i][2] = av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7); -+ quant.quantization_index[i][3] = av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7); -+ quant.quantization_index[i][4] = av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7); -+ quant.quantization_index[i][5] = av_clip_uintp2(base_qi + s->quant.uvac_delta, 7); -+ } -+ -+ err = ff_vaapi_decode_make_param_buffer(avctx, pic, -+ VAIQMatrixBufferType, -+ &quant, sizeof(quant)); -+ if (err < 0) -+ goto fail; -+ -+ return 0; -+ -+fail: -+ ff_vaapi_decode_cancel(avctx, pic); -+ return err; -+} -+ -+static int vaapi_vp8_end_frame(AVCodecContext *avctx) -+{ -+ const VP8Context *s = avctx->priv_data; -+ VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; -+ -+ return ff_vaapi_decode_issue(avctx, pic); -+} -+ -+static int vaapi_vp8_decode_slice(AVCodecContext *avctx, -+ const uint8_t *buffer, -+ uint32_t size) -+{ -+ const VP8Context *s = avctx->priv_data; -+ VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; -+ VASliceParameterBufferVP8 sp; -+ int err, i; -+ -+ unsigned int header_size = 3 + 7 * s->keyframe; -+ const uint8_t *data = buffer + header_size; -+ unsigned int data_size = size - header_size; -+ -+ sp = (VASliceParameterBufferVP8) { -+ .slice_data_size = data_size, -+ .slice_data_offset = 0, -+ .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, -+ -+ .macroblock_offset = (8 * (s->coder_state_at_header_end.input - data) - -+ s->coder_state_at_header_end.bit_count - 8), -+ .num_of_partitions = s->num_coeff_partitions + 1, -+ }; -+ -+ sp.partition_size[0] = s->header_partition_size - ((sp.macroblock_offset + 7) / 8); -+ for (i = 0; i < 8; i++) -+ sp.partition_size[i+1] = s->coeff_partition_size[i]; -+ -+ err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), data, data_size); -+ if (err) -+ goto fail; -+ -+ return 0; -+ -+fail: -+ ff_vaapi_decode_cancel(avctx, pic); -+ return err; -+} -+ -+const AVHWAccel ff_vp8_vaapi_hwaccel = { -+ .name = "vp8_vaapi", -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = AV_CODEC_ID_VP8, -+ .pix_fmt = AV_PIX_FMT_VAAPI, -+ .start_frame = &vaapi_vp8_start_frame, -+ .end_frame = &vaapi_vp8_end_frame, -+ .decode_slice = &vaapi_vp8_decode_slice, -+ .frame_priv_data_size = sizeof(VAAPIDecodePicture), -+ .init = &ff_vaapi_decode_init, -+ .uninit = &ff_vaapi_decode_uninit, -+ .frame_params = &ff_vaapi_common_frame_params, -+ .priv_data_size = sizeof(VAAPIDecodeContext), -+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, -+}; -diff -up firefox-84.0/media/ffvpx/libavcodec/vaapi_vp9.c.ffvpx firefox-84.0/media/ffvpx/libavcodec/vaapi_vp9.c ---- firefox-84.0/media/ffvpx/libavcodec/vaapi_vp9.c.ffvpx 2020-12-10 20:40:53.389541365 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/vaapi_vp9.c 2020-12-10 20:40:53.389541365 +0100 -@@ -0,0 +1,185 @@ -+/* -+ * VP9 HW decode acceleration through VA API -+ * -+ * Copyright (C) 2015 Timo Rothenpieler -+ * -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "libavutil/pixdesc.h" -+ -+#include "hwaccel.h" -+#include "vaapi_decode.h" -+#include "vp9shared.h" -+ -+static VASurfaceID vaapi_vp9_surface_id(const VP9Frame *vf) -+{ -+ if (vf) -+ return ff_vaapi_get_surface_id(vf->tf.f); -+ else -+ return VA_INVALID_SURFACE; -+} -+ -+static int vaapi_vp9_start_frame(AVCodecContext *avctx, -+ av_unused const uint8_t *buffer, -+ av_unused uint32_t size) -+{ -+ const VP9SharedContext *h = avctx->priv_data; -+ VAAPIDecodePicture *pic = h->frames[CUR_FRAME].hwaccel_picture_private; -+ VADecPictureParameterBufferVP9 pic_param; -+ const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); -+ int err, i; -+ -+ pic->output_surface = vaapi_vp9_surface_id(&h->frames[CUR_FRAME]); -+ -+ pic_param = (VADecPictureParameterBufferVP9) { -+ .frame_width = avctx->width, -+ .frame_height = avctx->height, -+ -+ .pic_fields.bits = { -+ .subsampling_x = pixdesc->log2_chroma_w, -+ .subsampling_y = pixdesc->log2_chroma_h, -+ .frame_type = !h->h.keyframe, -+ .show_frame = !h->h.invisible, -+ .error_resilient_mode = h->h.errorres, -+ .intra_only = h->h.intraonly, -+ .allow_high_precision_mv = h->h.keyframe ? 0 : h->h.highprecisionmvs, -+ .mcomp_filter_type = h->h.filtermode ^ (h->h.filtermode <= 1), -+ .frame_parallel_decoding_mode = h->h.parallelmode, -+ .reset_frame_context = h->h.resetctx, -+ .refresh_frame_context = h->h.refreshctx, -+ .frame_context_idx = h->h.framectxid, -+ -+ .segmentation_enabled = h->h.segmentation.enabled, -+ .segmentation_temporal_update = h->h.segmentation.temporal, -+ .segmentation_update_map = h->h.segmentation.update_map, -+ -+ .last_ref_frame = h->h.refidx[0], -+ .last_ref_frame_sign_bias = h->h.signbias[0], -+ .golden_ref_frame = h->h.refidx[1], -+ .golden_ref_frame_sign_bias = h->h.signbias[1], -+ .alt_ref_frame = h->h.refidx[2], -+ .alt_ref_frame_sign_bias = h->h.signbias[2], -+ .lossless_flag = h->h.lossless, -+ }, -+ -+ .filter_level = h->h.filter.level, -+ .sharpness_level = h->h.filter.sharpness, -+ .log2_tile_rows = h->h.tiling.log2_tile_rows, -+ .log2_tile_columns = h->h.tiling.log2_tile_cols, -+ -+ .frame_header_length_in_bytes = h->h.uncompressed_header_size, -+ .first_partition_size = h->h.compressed_header_size, -+ -+ .profile = h->h.profile, -+ .bit_depth = h->h.bpp, -+ }; -+ -+ for (i = 0; i < 7; i++) -+ pic_param.mb_segment_tree_probs[i] = h->h.segmentation.prob[i]; -+ -+ if (h->h.segmentation.temporal) { -+ for (i = 0; i < 3; i++) -+ pic_param.segment_pred_probs[i] = h->h.segmentation.pred_prob[i]; -+ } else { -+ memset(pic_param.segment_pred_probs, 255, sizeof(pic_param.segment_pred_probs)); -+ } -+ -+ for (i = 0; i < 8; i++) { -+ if (h->refs[i].f->buf[0]) -+ pic_param.reference_frames[i] = ff_vaapi_get_surface_id(h->refs[i].f); -+ else -+ pic_param.reference_frames[i] = VA_INVALID_ID; -+ } -+ -+ err = ff_vaapi_decode_make_param_buffer(avctx, pic, -+ VAPictureParameterBufferType, -+ &pic_param, sizeof(pic_param)); -+ if (err < 0) { -+ ff_vaapi_decode_cancel(avctx, pic); -+ return err; -+ } -+ -+ return 0; -+} -+ -+static int vaapi_vp9_end_frame(AVCodecContext *avctx) -+{ -+ const VP9SharedContext *h = avctx->priv_data; -+ VAAPIDecodePicture *pic = h->frames[CUR_FRAME].hwaccel_picture_private; -+ -+ return ff_vaapi_decode_issue(avctx, pic); -+} -+ -+static int vaapi_vp9_decode_slice(AVCodecContext *avctx, -+ const uint8_t *buffer, -+ uint32_t size) -+{ -+ const VP9SharedContext *h = avctx->priv_data; -+ VAAPIDecodePicture *pic = h->frames[CUR_FRAME].hwaccel_picture_private; -+ VASliceParameterBufferVP9 slice_param; -+ int err, i; -+ -+ slice_param = (VASliceParameterBufferVP9) { -+ .slice_data_size = size, -+ .slice_data_offset = 0, -+ .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, -+ }; -+ -+ for (i = 0; i < 8; i++) { -+ slice_param.seg_param[i] = (VASegmentParameterVP9) { -+ .segment_flags.fields = { -+ .segment_reference_enabled = h->h.segmentation.feat[i].ref_enabled, -+ .segment_reference = h->h.segmentation.feat[i].ref_val, -+ .segment_reference_skipped = h->h.segmentation.feat[i].skip_enabled, -+ }, -+ -+ .luma_dc_quant_scale = h->h.segmentation.feat[i].qmul[0][0], -+ .luma_ac_quant_scale = h->h.segmentation.feat[i].qmul[0][1], -+ .chroma_dc_quant_scale = h->h.segmentation.feat[i].qmul[1][0], -+ .chroma_ac_quant_scale = h->h.segmentation.feat[i].qmul[1][1], -+ }; -+ -+ memcpy(slice_param.seg_param[i].filter_level, h->h.segmentation.feat[i].lflvl, sizeof(slice_param.seg_param[i].filter_level)); -+ } -+ -+ err = ff_vaapi_decode_make_slice_buffer(avctx, pic, -+ &slice_param, sizeof(slice_param), -+ buffer, size); -+ if (err) { -+ ff_vaapi_decode_cancel(avctx, pic); -+ return err; -+ } -+ -+ return 0; -+} -+ -+const AVHWAccel ff_vp9_vaapi_hwaccel = { -+ .name = "vp9_vaapi", -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = AV_CODEC_ID_VP9, -+ .pix_fmt = AV_PIX_FMT_VAAPI, -+ .start_frame = vaapi_vp9_start_frame, -+ .end_frame = vaapi_vp9_end_frame, -+ .decode_slice = vaapi_vp9_decode_slice, -+ .frame_priv_data_size = sizeof(VAAPIDecodePicture), -+ .init = ff_vaapi_decode_init, -+ .uninit = ff_vaapi_decode_uninit, -+ .frame_params = ff_vaapi_common_frame_params, -+ .priv_data_size = sizeof(VAAPIDecodeContext), -+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE, -+}; -diff -up firefox-84.0/media/ffvpx/libavutil/avutil.symbols.ffvpx firefox-84.0/media/ffvpx/libavutil/avutil.symbols ---- firefox-84.0/media/ffvpx/libavutil/avutil.symbols.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/libavutil/avutil.symbols 2020-12-10 20:40:53.389541365 +0100 -@@ -158,6 +158,9 @@ av_get_token - av_gettime - av_gettime_relative - av_gettime_relative_is_monotonic -+av_hwdevice_get_hwframe_constraints -+av_hwdevice_hwconfig_alloc -+av_hwframe_constraints_free - av_hwframe_get_buffer - av_image_alloc - av_image_check_sar -@@ -320,5 +323,9 @@ avpriv_slicethread_free - av_hwdevice_get_type_name - av_hwframe_ctx_alloc - av_hwframe_ctx_init -+av_hwdevice_ctx_alloc -+av_hwdevice_ctx_init -+av_hwframe_transfer_get_formats -+av_hwdevice_ctx_create_derived - av_malloc_array - av_mallocz_array -diff -up firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.c.ffvpx firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.c ---- firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.c.ffvpx 2020-12-10 20:40:53.390541394 +0100 -+++ firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.c 2020-12-10 20:40:53.389541365 +0100 -@@ -0,0 +1,1691 @@ -+/* -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#include "config.h" -+ -+#if HAVE_VAAPI_X11 -+# include -+#endif -+#if HAVE_VAAPI_DRM -+# include -+#endif -+ -+#if CONFIG_LIBDRM -+# include -+# include -+# include -+# ifndef DRM_FORMAT_MOD_INVALID -+# define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) -+# endif -+#endif -+ -+#include -+#if HAVE_UNISTD_H -+# include -+#endif -+ -+ -+#include "avassert.h" -+#include "buffer.h" -+#include "common.h" -+#include "hwcontext.h" -+#if CONFIG_LIBDRM -+#include "hwcontext_drm.h" -+#endif -+#include "hwcontext_internal.h" -+#include "hwcontext_vaapi.h" -+#include "mem.h" -+#include "pixdesc.h" -+#include "pixfmt.h" -+ -+ -+typedef struct VAAPIDevicePriv { -+#if HAVE_VAAPI_X11 -+ Display *x11_display; -+#endif -+ -+ int drm_fd; -+} VAAPIDevicePriv; -+ -+typedef struct VAAPISurfaceFormat { -+ enum AVPixelFormat pix_fmt; -+ VAImageFormat image_format; -+} VAAPISurfaceFormat; -+ -+typedef struct VAAPIDeviceContext { -+ // Surface formats which can be used with this device. -+ VAAPISurfaceFormat *formats; -+ int nb_formats; -+} VAAPIDeviceContext; -+ -+typedef struct VAAPIFramesContext { -+ // Surface attributes set at create time. -+ VASurfaceAttrib *attributes; -+ int nb_attributes; -+ // RT format of the underlying surface (Intel driver ignores this anyway). -+ unsigned int rt_format; -+ // Whether vaDeriveImage works. -+ int derive_works; -+} VAAPIFramesContext; -+ -+typedef struct VAAPIMapping { -+ // Handle to the derived or copied image which is mapped. -+ VAImage image; -+ // The mapping flags actually used. -+ int flags; -+} VAAPIMapping; -+ -+typedef struct VAAPIFormat { -+ unsigned int fourcc; -+ unsigned int rt_format; -+ enum AVPixelFormat pix_fmt; -+ int chroma_planes_swapped; -+} VAAPIFormatDescriptor; -+ -+#define MAP(va, rt, av, swap_uv) { \ -+ VA_FOURCC_ ## va, \ -+ VA_RT_FORMAT_ ## rt, \ -+ AV_PIX_FMT_ ## av, \ -+ swap_uv, \ -+ } -+// The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V -+// plane swap cases. The frame handling below tries to hide these. -+static const VAAPIFormatDescriptor vaapi_format_map[] = { -+ MAP(NV12, YUV420, NV12, 0), -+#ifdef VA_FOURCC_I420 -+ MAP(I420, YUV420, YUV420P, 0), -+#endif -+ MAP(YV12, YUV420, YUV420P, 1), -+ MAP(IYUV, YUV420, YUV420P, 0), -+ MAP(422H, YUV422, YUV422P, 0), -+#ifdef VA_FOURCC_YV16 -+ MAP(YV16, YUV422, YUV422P, 1), -+#endif -+ MAP(UYVY, YUV422, UYVY422, 0), -+ MAP(YUY2, YUV422, YUYV422, 0), -+ MAP(411P, YUV411, YUV411P, 0), -+ MAP(422V, YUV422, YUV440P, 0), -+ MAP(444P, YUV444, YUV444P, 0), -+ MAP(Y800, YUV400, GRAY8, 0), -+#ifdef VA_FOURCC_P010 -+ MAP(P010, YUV420_10BPP, P010, 0), -+#endif -+ MAP(BGRA, RGB32, BGRA, 0), -+ MAP(BGRX, RGB32, BGR0, 0), -+ MAP(RGBA, RGB32, RGBA, 0), -+ MAP(RGBX, RGB32, RGB0, 0), -+#ifdef VA_FOURCC_ABGR -+ MAP(ABGR, RGB32, ABGR, 0), -+ MAP(XBGR, RGB32, 0BGR, 0), -+#endif -+ MAP(ARGB, RGB32, ARGB, 0), -+ MAP(XRGB, RGB32, 0RGB, 0), -+}; -+#undef MAP -+ -+static const VAAPIFormatDescriptor * -+ vaapi_format_from_fourcc(unsigned int fourcc) -+{ -+ int i; -+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) -+ if (vaapi_format_map[i].fourcc == fourcc) -+ return &vaapi_format_map[i]; -+ return NULL; -+} -+ -+static const VAAPIFormatDescriptor * -+ vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt) -+{ -+ int i; -+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) -+ if (vaapi_format_map[i].pix_fmt == pix_fmt) -+ return &vaapi_format_map[i]; -+ return NULL; -+} -+ -+static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc) -+{ -+ const VAAPIFormatDescriptor *desc; -+ desc = vaapi_format_from_fourcc(fourcc); -+ if (desc) -+ return desc->pix_fmt; -+ else -+ return AV_PIX_FMT_NONE; -+} -+ -+static int vaapi_get_image_format(AVHWDeviceContext *hwdev, -+ enum AVPixelFormat pix_fmt, -+ VAImageFormat **image_format) -+{ -+ VAAPIDeviceContext *ctx = hwdev->internal->priv; -+ int i; -+ -+ for (i = 0; i < ctx->nb_formats; i++) { -+ if (ctx->formats[i].pix_fmt == pix_fmt) { -+ if (image_format) -+ *image_format = &ctx->formats[i].image_format; -+ return 0; -+ } -+ } -+ return AVERROR(EINVAL); -+} -+ -+static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, -+ const void *hwconfig, -+ AVHWFramesConstraints *constraints) -+{ -+ AVVAAPIDeviceContext *hwctx = hwdev->hwctx; -+ const AVVAAPIHWConfig *config = hwconfig; -+ VAAPIDeviceContext *ctx = hwdev->internal->priv; -+ VASurfaceAttrib *attr_list = NULL; -+ VAStatus vas; -+ enum AVPixelFormat pix_fmt; -+ unsigned int fourcc; -+ int err, i, j, attr_count, pix_fmt_count; -+ -+ if (config && -+ !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES)) { -+ attr_count = 0; -+ vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id, -+ 0, &attr_count); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(ENOSYS); -+ goto fail; -+ } -+ -+ attr_list = av_malloc(attr_count * sizeof(*attr_list)); -+ if (!attr_list) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id, -+ attr_list, &attr_count); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ err = AVERROR(ENOSYS); -+ goto fail; -+ } -+ -+ pix_fmt_count = 0; -+ for (i = 0; i < attr_count; i++) { -+ switch (attr_list[i].type) { -+ case VASurfaceAttribPixelFormat: -+ fourcc = attr_list[i].value.value.i; -+ pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); -+ if (pix_fmt != AV_PIX_FMT_NONE) { -+ ++pix_fmt_count; -+ } else { -+ // Something unsupported - ignore. -+ } -+ break; -+ case VASurfaceAttribMinWidth: -+ constraints->min_width = attr_list[i].value.value.i; -+ break; -+ case VASurfaceAttribMinHeight: -+ constraints->min_height = attr_list[i].value.value.i; -+ break; -+ case VASurfaceAttribMaxWidth: -+ constraints->max_width = attr_list[i].value.value.i; -+ break; -+ case VASurfaceAttribMaxHeight: -+ constraints->max_height = attr_list[i].value.value.i; -+ break; -+ } -+ } -+ if (pix_fmt_count == 0) { -+ // Nothing usable found. Presumably there exists something which -+ // works, so leave the set null to indicate unknown. -+ constraints->valid_sw_formats = NULL; -+ } else { -+ constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1, -+ sizeof(pix_fmt)); -+ if (!constraints->valid_sw_formats) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ for (i = j = 0; i < attr_count; i++) { -+ if (attr_list[i].type != VASurfaceAttribPixelFormat) -+ continue; -+ fourcc = attr_list[i].value.value.i; -+ pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); -+ if (pix_fmt != AV_PIX_FMT_NONE) -+ constraints->valid_sw_formats[j++] = pix_fmt; -+ } -+ av_assert0(j == pix_fmt_count); -+ constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE; -+ } -+ } else { -+ // No configuration supplied. -+ // Return the full set of image formats known by the implementation. -+ constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1, -+ sizeof(pix_fmt)); -+ if (!constraints->valid_sw_formats) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ for (i = 0; i < ctx->nb_formats; i++) -+ constraints->valid_sw_formats[i] = ctx->formats[i].pix_fmt; -+ constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE; -+ } -+ -+ constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt)); -+ if (!constraints->valid_hw_formats) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI; -+ constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; -+ -+ err = 0; -+fail: -+ av_freep(&attr_list); -+ return err; -+} -+ -+static const struct { -+ const char *friendly_name; -+ const char *match_string; -+ unsigned int quirks; -+} vaapi_driver_quirks_table[] = { -+#if !VA_CHECK_VERSION(1, 0, 0) -+ // The i965 driver did not conform before version 2.0. -+ { -+ "Intel i965 (Quick Sync)", -+ "i965", -+ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS, -+ }, -+#endif -+ { -+ "Intel iHD", -+ "ubit", -+ AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE, -+ }, -+ { -+ "VDPAU wrapper", -+ "Splitted-Desktop Systems VDPAU backend for VA-API", -+ AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES, -+ }, -+}; -+ -+static int vaapi_device_init(AVHWDeviceContext *hwdev) -+{ -+ VAAPIDeviceContext *ctx = hwdev->internal->priv; -+ AVVAAPIDeviceContext *hwctx = hwdev->hwctx; -+ VAImageFormat *image_list = NULL; -+ VAStatus vas; -+ const char *vendor_string; -+ int err, i, image_count; -+ enum AVPixelFormat pix_fmt; -+ unsigned int fourcc; -+ -+ image_count = vaMaxNumImageFormats(hwctx->display); -+ if (image_count <= 0) { -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ image_list = av_malloc(image_count * sizeof(*image_list)); -+ if (!image_list) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ vas = vaQueryImageFormats(hwctx->display, image_list, &image_count); -+ if (vas != VA_STATUS_SUCCESS) { -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ -+ ctx->formats = av_malloc(image_count * sizeof(*ctx->formats)); -+ if (!ctx->formats) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ ctx->nb_formats = 0; -+ for (i = 0; i < image_count; i++) { -+ fourcc = image_list[i].fourcc; -+ pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); -+ if (pix_fmt == AV_PIX_FMT_NONE) { -+ av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> unknown.\n", -+ fourcc); -+ } else { -+ av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n", -+ fourcc, av_get_pix_fmt_name(pix_fmt)); -+ ctx->formats[ctx->nb_formats].pix_fmt = pix_fmt; -+ ctx->formats[ctx->nb_formats].image_format = image_list[i]; -+ ++ctx->nb_formats; -+ } -+ } -+ -+ vendor_string = vaQueryVendorString(hwctx->display); -+ if (vendor_string) -+ av_log(hwdev, AV_LOG_VERBOSE, "VAAPI driver: %s.\n", vendor_string); -+ -+ if (hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_USER_SET) { -+ av_log(hwdev, AV_LOG_VERBOSE, "Using quirks set by user (%#x).\n", -+ hwctx->driver_quirks); -+ } else { -+ // Detect the driver in use and set quirk flags if necessary. -+ hwctx->driver_quirks = 0; -+ if (vendor_string) { -+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) { -+ if (strstr(vendor_string, -+ vaapi_driver_quirks_table[i].match_string)) { -+ av_log(hwdev, AV_LOG_VERBOSE, "Matched driver string " -+ "as known nonstandard driver \"%s\", setting " -+ "quirks (%#x).\n", -+ vaapi_driver_quirks_table[i].friendly_name, -+ vaapi_driver_quirks_table[i].quirks); -+ hwctx->driver_quirks |= -+ vaapi_driver_quirks_table[i].quirks; -+ break; -+ } -+ } -+ if (!(i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table))) { -+ av_log(hwdev, AV_LOG_VERBOSE, "Driver not found in known " -+ "nonstandard list, using standard behaviour.\n"); -+ } -+ } else { -+ av_log(hwdev, AV_LOG_VERBOSE, "Driver has no vendor string, " -+ "assuming standard behaviour.\n"); -+ } -+ } -+ -+ av_free(image_list); -+ return 0; -+fail: -+ av_freep(&ctx->formats); -+ av_free(image_list); -+ return err; -+} -+ -+static void vaapi_device_uninit(AVHWDeviceContext *hwdev) -+{ -+ VAAPIDeviceContext *ctx = hwdev->internal->priv; -+ -+ av_freep(&ctx->formats); -+} -+ -+static void vaapi_buffer_free(void *opaque, uint8_t *data) -+{ -+ AVHWFramesContext *hwfc = opaque; -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ -+ surface_id = (VASurfaceID)(uintptr_t)data; -+ -+ vas = vaDestroySurfaces(hwctx->display, &surface_id, 1); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: " -+ "%d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ } -+} -+ -+static AVBufferRef *vaapi_pool_alloc(void *opaque, int size) -+{ -+ AVHWFramesContext *hwfc = opaque; -+ VAAPIFramesContext *ctx = hwfc->internal->priv; -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ AVVAAPIFramesContext *avfc = hwfc->hwctx; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ AVBufferRef *ref; -+ -+ if (hwfc->initial_pool_size > 0 && -+ avfc->nb_surfaces >= hwfc->initial_pool_size) -+ return NULL; -+ -+ vas = vaCreateSurfaces(hwctx->display, ctx->rt_format, -+ hwfc->width, hwfc->height, -+ &surface_id, 1, -+ ctx->attributes, ctx->nb_attributes); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ return NULL; -+ } -+ av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id); -+ -+ ref = av_buffer_create((uint8_t*)(uintptr_t)surface_id, -+ sizeof(surface_id), &vaapi_buffer_free, -+ hwfc, AV_BUFFER_FLAG_READONLY); -+ if (!ref) { -+ vaDestroySurfaces(hwctx->display, &surface_id, 1); -+ return NULL; -+ } -+ -+ if (hwfc->initial_pool_size > 0) { -+ // This is a fixed-size pool, so we must still be in the initial -+ // allocation sequence. -+ av_assert0(avfc->nb_surfaces < hwfc->initial_pool_size); -+ avfc->surface_ids[avfc->nb_surfaces] = surface_id; -+ ++avfc->nb_surfaces; -+ } -+ -+ return ref; -+} -+ -+static int vaapi_frames_init(AVHWFramesContext *hwfc) -+{ -+ AVVAAPIFramesContext *avfc = hwfc->hwctx; -+ VAAPIFramesContext *ctx = hwfc->internal->priv; -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ const VAAPIFormatDescriptor *desc; -+ VAImageFormat *expected_format; -+ AVBufferRef *test_surface = NULL; -+ VASurfaceID test_surface_id; -+ VAImage test_image; -+ VAStatus vas; -+ int err, i; -+ -+ desc = vaapi_format_from_pix_fmt(hwfc->sw_format); -+ if (!desc) { -+ av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n", -+ av_get_pix_fmt_name(hwfc->sw_format)); -+ return AVERROR(EINVAL); -+ } -+ -+ if (!hwfc->pool) { -+ if (!(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES)) { -+ int need_memory_type = !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE); -+ int need_pixel_format = 1; -+ for (i = 0; i < avfc->nb_attributes; i++) { -+ if (avfc->attributes[i].type == VASurfaceAttribMemoryType) -+ need_memory_type = 0; -+ if (avfc->attributes[i].type == VASurfaceAttribPixelFormat) -+ need_pixel_format = 0; -+ } -+ ctx->nb_attributes = -+ avfc->nb_attributes + need_memory_type + need_pixel_format; -+ -+ ctx->attributes = av_malloc(ctx->nb_attributes * -+ sizeof(*ctx->attributes)); -+ if (!ctx->attributes) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ for (i = 0; i < avfc->nb_attributes; i++) -+ ctx->attributes[i] = avfc->attributes[i]; -+ if (need_memory_type) { -+ ctx->attributes[i++] = (VASurfaceAttrib) { -+ .type = VASurfaceAttribMemoryType, -+ .flags = VA_SURFACE_ATTRIB_SETTABLE, -+ .value.type = VAGenericValueTypeInteger, -+ .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA, -+ }; -+ } -+ if (need_pixel_format) { -+ ctx->attributes[i++] = (VASurfaceAttrib) { -+ .type = VASurfaceAttribPixelFormat, -+ .flags = VA_SURFACE_ATTRIB_SETTABLE, -+ .value.type = VAGenericValueTypeInteger, -+ .value.value.i = desc->fourcc, -+ }; -+ } -+ av_assert0(i == ctx->nb_attributes); -+ } else { -+ ctx->attributes = NULL; -+ ctx->nb_attributes = 0; -+ } -+ -+ ctx->rt_format = desc->rt_format; -+ -+ if (hwfc->initial_pool_size > 0) { -+ // This pool will be usable as a render target, so we need to store -+ // all of the surface IDs somewhere that vaCreateContext() calls -+ // will be able to access them. -+ avfc->nb_surfaces = 0; -+ avfc->surface_ids = av_malloc(hwfc->initial_pool_size * -+ sizeof(*avfc->surface_ids)); -+ if (!avfc->surface_ids) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ } else { -+ // This pool allows dynamic sizing, and will not be usable as a -+ // render target. -+ avfc->nb_surfaces = 0; -+ avfc->surface_ids = NULL; -+ } -+ -+ hwfc->internal->pool_internal = -+ av_buffer_pool_init2(sizeof(VASurfaceID), hwfc, -+ &vaapi_pool_alloc, NULL); -+ if (!hwfc->internal->pool_internal) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n"); -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ } -+ -+ // Allocate a single surface to test whether vaDeriveImage() is going -+ // to work for the specific configuration. -+ if (hwfc->pool) { -+ test_surface = av_buffer_pool_get(hwfc->pool); -+ if (!test_surface) { -+ av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " -+ "user-configured buffer pool.\n"); -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ } else { -+ test_surface = av_buffer_pool_get(hwfc->internal->pool_internal); -+ if (!test_surface) { -+ av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " -+ "internal buffer pool.\n"); -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ } -+ test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data; -+ -+ ctx->derive_works = 0; -+ -+ err = vaapi_get_image_format(hwfc->device_ctx, -+ hwfc->sw_format, &expected_format); -+ if (err == 0) { -+ vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image); -+ if (vas == VA_STATUS_SUCCESS) { -+ if (expected_format->fourcc == test_image.format.fourcc) { -+ av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n"); -+ ctx->derive_works = 1; -+ } else { -+ av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " -+ "derived image format %08x does not match " -+ "expected format %08x.\n", -+ expected_format->fourcc, test_image.format.fourcc); -+ } -+ vaDestroyImage(hwctx->display, test_image.image_id); -+ } else { -+ av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " -+ "deriving image does not work: " -+ "%d (%s).\n", vas, vaErrorStr(vas)); -+ } -+ } else { -+ av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " -+ "image format is not supported.\n"); -+ } -+ -+ av_buffer_unref(&test_surface); -+ return 0; -+ -+fail: -+ av_buffer_unref(&test_surface); -+ av_freep(&avfc->surface_ids); -+ av_freep(&ctx->attributes); -+ return err; -+} -+ -+static void vaapi_frames_uninit(AVHWFramesContext *hwfc) -+{ -+ AVVAAPIFramesContext *avfc = hwfc->hwctx; -+ VAAPIFramesContext *ctx = hwfc->internal->priv; -+ -+ av_freep(&avfc->surface_ids); -+ av_freep(&ctx->attributes); -+} -+ -+static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) -+{ -+ frame->buf[0] = av_buffer_pool_get(hwfc->pool); -+ if (!frame->buf[0]) -+ return AVERROR(ENOMEM); -+ -+ frame->data[3] = frame->buf[0]->data; -+ frame->format = AV_PIX_FMT_VAAPI; -+ frame->width = hwfc->width; -+ frame->height = hwfc->height; -+ -+ return 0; -+} -+ -+static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, -+ enum AVHWFrameTransferDirection dir, -+ enum AVPixelFormat **formats) -+{ -+ VAAPIDeviceContext *ctx = hwfc->device_ctx->internal->priv; -+ enum AVPixelFormat *pix_fmts; -+ int i, k, sw_format_available; -+ -+ sw_format_available = 0; -+ for (i = 0; i < ctx->nb_formats; i++) { -+ if (ctx->formats[i].pix_fmt == hwfc->sw_format) -+ sw_format_available = 1; -+ } -+ -+ pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts)); -+ if (!pix_fmts) -+ return AVERROR(ENOMEM); -+ -+ if (sw_format_available) { -+ pix_fmts[0] = hwfc->sw_format; -+ k = 1; -+ } else { -+ k = 0; -+ } -+ for (i = 0; i < ctx->nb_formats; i++) { -+ if (ctx->formats[i].pix_fmt == hwfc->sw_format) -+ continue; -+ av_assert0(k < ctx->nb_formats); -+ pix_fmts[k++] = ctx->formats[i].pix_fmt; -+ } -+ pix_fmts[k] = AV_PIX_FMT_NONE; -+ -+ *formats = pix_fmts; -+ return 0; -+} -+ -+static void vaapi_unmap_frame(AVHWFramesContext *hwfc, -+ HWMapDescriptor *hwmap) -+{ -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ VAAPIMapping *map = hwmap->priv; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ -+ surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; -+ av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id); -+ -+ vas = vaUnmapBuffer(hwctx->display, map->image.buf); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface " -+ "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ } -+ -+ if ((map->flags & AV_HWFRAME_MAP_WRITE) && -+ !(map->flags & AV_HWFRAME_MAP_DIRECT)) { -+ vas = vaPutImage(hwctx->display, surface_id, map->image.image_id, -+ 0, 0, hwfc->width, hwfc->height, -+ 0, 0, hwfc->width, hwfc->height); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface " -+ "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ } -+ } -+ -+ vas = vaDestroyImage(hwctx->display, map->image.image_id); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface " -+ "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ } -+ -+ av_free(map); -+} -+ -+static int vaapi_map_frame(AVHWFramesContext *hwfc, -+ AVFrame *dst, const AVFrame *src, int flags) -+{ -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ VAAPIFramesContext *ctx = hwfc->internal->priv; -+ VASurfaceID surface_id; -+ const VAAPIFormatDescriptor *desc; -+ VAImageFormat *image_format; -+ VAAPIMapping *map; -+ VAStatus vas; -+ void *address = NULL; -+ int err, i; -+ -+ surface_id = (VASurfaceID)(uintptr_t)src->data[3]; -+ av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id); -+ -+ if (!ctx->derive_works && (flags & AV_HWFRAME_MAP_DIRECT)) { -+ // Requested direct mapping but it is not possible. -+ return AVERROR(EINVAL); -+ } -+ if (dst->format == AV_PIX_FMT_NONE) -+ dst->format = hwfc->sw_format; -+ if (dst->format != hwfc->sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) { -+ // Requested direct mapping but the formats do not match. -+ return AVERROR(EINVAL); -+ } -+ -+ err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format); -+ if (err < 0) { -+ // Requested format is not a valid output format. -+ return AVERROR(EINVAL); -+ } -+ -+ map = av_malloc(sizeof(*map)); -+ if (!map) -+ return AVERROR(ENOMEM); -+ map->flags = flags; -+ map->image.image_id = VA_INVALID_ID; -+ -+ vas = vaSyncSurface(hwctx->display, surface_id); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface " -+ "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ -+ // The memory which we map using derive need not be connected to the CPU -+ // in a way conducive to fast access. On Gen7-Gen9 Intel graphics, the -+ // memory is mappable but not cached, so normal memcpy()-like access is -+ // very slow to read it (but writing is ok). It is possible to read much -+ // faster with a copy routine which is aware of the limitation, but we -+ // assume for now that the user is not aware of that and would therefore -+ // prefer not to be given direct-mapped memory if they request read access. -+ if (ctx->derive_works && dst->format == hwfc->sw_format && -+ ((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) { -+ vas = vaDeriveImage(hwctx->display, surface_id, &map->image); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " -+ "surface %#x: %d (%s).\n", -+ surface_id, vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ if (map->image.format.fourcc != image_format->fourcc) { -+ av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x " -+ "is in wrong format: expected %#08x, got %#08x.\n", -+ surface_id, image_format->fourcc, map->image.format.fourcc); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ map->flags |= AV_HWFRAME_MAP_DIRECT; -+ } else { -+ vas = vaCreateImage(hwctx->display, image_format, -+ hwfc->width, hwfc->height, &map->image); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to create image for " -+ "surface %#x: %d (%s).\n", -+ surface_id, vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) { -+ vas = vaGetImage(hwctx->display, surface_id, 0, 0, -+ hwfc->width, hwfc->height, map->image.image_id); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to read image from " -+ "surface %#x: %d (%s).\n", -+ surface_id, vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ } -+ } -+ -+ vas = vaMapBuffer(hwctx->display, map->image.buf, &address); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface " -+ "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ -+ err = ff_hwframe_map_create(src->hw_frames_ctx, -+ dst, src, &vaapi_unmap_frame, map); -+ if (err < 0) -+ goto fail; -+ -+ dst->width = src->width; -+ dst->height = src->height; -+ -+ for (i = 0; i < map->image.num_planes; i++) { -+ dst->data[i] = (uint8_t*)address + map->image.offsets[i]; -+ dst->linesize[i] = map->image.pitches[i]; -+ } -+ -+ desc = vaapi_format_from_fourcc(map->image.format.fourcc); -+ if (desc && desc->chroma_planes_swapped) { -+ // Chroma planes are YVU rather than YUV, so swap them. -+ FFSWAP(uint8_t*, dst->data[1], dst->data[2]); -+ } -+ -+ return 0; -+ -+fail: -+ if (map) { -+ if (address) -+ vaUnmapBuffer(hwctx->display, map->image.buf); -+ if (map->image.image_id != VA_INVALID_ID) -+ vaDestroyImage(hwctx->display, map->image.image_id); -+ av_free(map); -+ } -+ return err; -+} -+ -+static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, -+ AVFrame *dst, const AVFrame *src) -+{ -+ AVFrame *map; -+ int err; -+ -+ if (dst->width > hwfc->width || dst->height > hwfc->height) -+ return AVERROR(EINVAL); -+ -+ map = av_frame_alloc(); -+ if (!map) -+ return AVERROR(ENOMEM); -+ map->format = dst->format; -+ -+ err = vaapi_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ); -+ if (err) -+ goto fail; -+ -+ map->width = dst->width; -+ map->height = dst->height; -+ -+ err = av_frame_copy(dst, map); -+ if (err) -+ goto fail; -+ -+ err = 0; -+fail: -+ av_frame_free(&map); -+ return err; -+} -+ -+static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, -+ AVFrame *dst, const AVFrame *src) -+{ -+ AVFrame *map; -+ int err; -+ -+ if (src->width > hwfc->width || src->height > hwfc->height) -+ return AVERROR(EINVAL); -+ -+ map = av_frame_alloc(); -+ if (!map) -+ return AVERROR(ENOMEM); -+ map->format = src->format; -+ -+ err = vaapi_map_frame(hwfc, map, dst, AV_HWFRAME_MAP_WRITE | AV_HWFRAME_MAP_OVERWRITE); -+ if (err) -+ goto fail; -+ -+ map->width = src->width; -+ map->height = src->height; -+ -+ err = av_frame_copy(map, src); -+ if (err) -+ goto fail; -+ -+ err = 0; -+fail: -+ av_frame_free(&map); -+ return err; -+} -+ -+static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+ int err; -+ -+ if (dst->format != AV_PIX_FMT_NONE) { -+ err = vaapi_get_image_format(hwfc->device_ctx, dst->format, NULL); -+ if (err < 0) -+ return AVERROR(ENOSYS); -+ } -+ -+ err = vaapi_map_frame(hwfc, dst, src, flags); -+ if (err) -+ return err; -+ -+ err = av_frame_copy_props(dst, src); -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+#if CONFIG_LIBDRM -+ -+#define DRM_MAP(va, layers, ...) { \ -+ VA_FOURCC_ ## va, \ -+ layers, \ -+ { __VA_ARGS__ } \ -+ } -+static const struct { -+ uint32_t va_fourcc; -+ int nb_layer_formats; -+ uint32_t layer_formats[AV_DRM_MAX_PLANES]; -+} vaapi_drm_format_map[] = { -+#ifdef DRM_FORMAT_R8 -+ DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), -+#endif -+ DRM_MAP(NV12, 1, DRM_FORMAT_NV12), -+#if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -+ DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616), -+#endif -+ DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888), -+ DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888), -+ DRM_MAP(RGBA, 1, DRM_FORMAT_ABGR8888), -+ DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888), -+#ifdef VA_FOURCC_ABGR -+ DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888), -+ DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888), -+#endif -+ DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888), -+ DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888), -+}; -+#undef DRM_MAP -+ -+static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, -+ HWMapDescriptor *hwmap) -+{ -+ AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; -+ -+ VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->priv; -+ -+ av_log(dst_fc, AV_LOG_DEBUG, "Destroy surface %#x.\n", surface_id); -+ -+ vaDestroySurfaces(dst_dev->display, &surface_id, 1); -+} -+ -+static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+ AVHWFramesContext *dst_fc = -+ (AVHWFramesContext*)dst->hw_frames_ctx->data; -+ AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; -+ const AVDRMFrameDescriptor *desc; -+ const VAAPIFormatDescriptor *format_desc; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ uint32_t va_fourcc; -+ int err, i, j, k; -+ -+ unsigned long buffer_handle; -+ VASurfaceAttribExternalBuffers buffer_desc; -+ VASurfaceAttrib attrs[2] = { -+ { -+ .type = VASurfaceAttribMemoryType, -+ .flags = VA_SURFACE_ATTRIB_SETTABLE, -+ .value.type = VAGenericValueTypeInteger, -+ .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -+ }, -+ { -+ .type = VASurfaceAttribExternalBufferDescriptor, -+ .flags = VA_SURFACE_ATTRIB_SETTABLE, -+ .value.type = VAGenericValueTypePointer, -+ .value.value.p = &buffer_desc, -+ } -+ }; -+ -+ desc = (AVDRMFrameDescriptor*)src->data[0]; -+ -+ if (desc->nb_objects != 1) { -+ av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames " -+ "made from a single DRM object.\n"); -+ return AVERROR(EINVAL); -+ } -+ -+ va_fourcc = 0; -+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { -+ if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats) -+ continue; -+ for (j = 0; j < desc->nb_layers; j++) { -+ if (desc->layers[j].format != -+ vaapi_drm_format_map[i].layer_formats[j]) -+ break; -+ } -+ if (j != desc->nb_layers) -+ continue; -+ va_fourcc = vaapi_drm_format_map[i].va_fourcc; -+ break; -+ } -+ if (!va_fourcc) { -+ av_log(dst_fc, AV_LOG_ERROR, "DRM format not supported " -+ "by VAAPI.\n"); -+ return AVERROR(EINVAL); -+ } -+ -+ av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as " -+ "%08x.\n", desc->objects[0].fd, va_fourcc); -+ -+ format_desc = vaapi_format_from_fourcc(va_fourcc); -+ av_assert0(format_desc); -+ -+ buffer_handle = desc->objects[0].fd; -+ buffer_desc.pixel_format = va_fourcc; -+ buffer_desc.width = src_fc->width; -+ buffer_desc.height = src_fc->height; -+ buffer_desc.data_size = desc->objects[0].size; -+ buffer_desc.buffers = &buffer_handle; -+ buffer_desc.num_buffers = 1; -+ buffer_desc.flags = 0; -+ -+ k = 0; -+ for (i = 0; i < desc->nb_layers; i++) { -+ for (j = 0; j < desc->layers[i].nb_planes; j++) { -+ buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -+ buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -+ ++k; -+ } -+ } -+ buffer_desc.num_planes = k; -+ -+ if (format_desc->chroma_planes_swapped && -+ buffer_desc.num_planes == 3) { -+ FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]); -+ FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]); -+ } -+ -+ vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, -+ src->width, src->height, -+ &surface_id, 1, -+ attrs, FF_ARRAY_ELEMS(attrs)); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM " -+ "object: %d (%s).\n", vas, vaErrorStr(vas)); -+ return AVERROR(EIO); -+ } -+ av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id); -+ -+ err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, -+ &vaapi_unmap_from_drm, -+ (void*)(uintptr_t)surface_id); -+ if (err < 0) -+ return err; -+ -+ dst->width = src->width; -+ dst->height = src->height; -+ dst->data[3] = (uint8_t*)(uintptr_t)surface_id; -+ -+ av_log(dst_fc, AV_LOG_DEBUG, "Mapped DRM object %d to " -+ "surface %#x.\n", desc->objects[0].fd, surface_id); -+ -+ return 0; -+} -+ -+#if VA_CHECK_VERSION(1, 1, 0) -+static void vaapi_unmap_to_drm_esh(AVHWFramesContext *hwfc, -+ HWMapDescriptor *hwmap) -+{ -+ AVDRMFrameDescriptor *drm_desc = hwmap->priv; -+ int i; -+ -+ for (i = 0; i < drm_desc->nb_objects; i++) -+ close(drm_desc->objects[i].fd); -+ -+ av_freep(&drm_desc); -+} -+ -+static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ VADRMPRIMESurfaceDescriptor va_desc; -+ AVDRMFrameDescriptor *drm_desc = NULL; -+ uint32_t export_flags; -+ int err, i, j; -+ -+ surface_id = (VASurfaceID)(uintptr_t)src->data[3]; -+ -+ export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS; -+ if (flags & AV_HWFRAME_MAP_READ) -+ export_flags |= VA_EXPORT_SURFACE_READ_ONLY; -+ if (flags & AV_HWFRAME_MAP_WRITE) -+ export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY; -+ -+ vas = vaExportSurfaceHandle(hwctx->display, surface_id, -+ VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, -+ export_flags, &va_desc); -+ if (vas != VA_STATUS_SUCCESS) { -+ if (vas == VA_STATUS_ERROR_UNIMPLEMENTED) -+ return AVERROR(ENOSYS); -+ av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: " -+ "%d (%s).\n", surface_id, vas, vaErrorStr(vas)); -+ return AVERROR(EIO); -+ } -+ -+ drm_desc = av_mallocz(sizeof(*drm_desc)); -+ if (!drm_desc) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ // By some bizarre coincidence, these structures are very similar... -+ drm_desc->nb_objects = va_desc.num_objects; -+ for (i = 0; i < va_desc.num_objects; i++) { -+ drm_desc->objects[i].fd = va_desc.objects[i].fd; -+ drm_desc->objects[i].size = va_desc.objects[i].size; -+ drm_desc->objects[i].format_modifier = -+ va_desc.objects[i].drm_format_modifier; -+ } -+ drm_desc->nb_layers = va_desc.num_layers; -+ for (i = 0; i < va_desc.num_layers; i++) { -+ drm_desc->layers[i].format = va_desc.layers[i].drm_format; -+ drm_desc->layers[i].nb_planes = va_desc.layers[i].num_planes; -+ for (j = 0; j < va_desc.layers[i].num_planes; j++) { -+ drm_desc->layers[i].planes[j].object_index = -+ va_desc.layers[i].object_index[j]; -+ drm_desc->layers[i].planes[j].offset = -+ va_desc.layers[i].offset[j]; -+ drm_desc->layers[i].planes[j].pitch = -+ va_desc.layers[i].pitch[j]; -+ } -+ } -+ -+ err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, -+ &vaapi_unmap_to_drm_esh, drm_desc); -+ if (err < 0) -+ goto fail; -+ -+ dst->width = src->width; -+ dst->height = src->height; -+ dst->data[0] = (uint8_t*)drm_desc; -+ -+ return 0; -+ -+fail: -+ for (i = 0; i < va_desc.num_objects; i++) -+ close(va_desc.objects[i].fd); -+ av_freep(&drm_desc); -+ return err; -+} -+#endif -+ -+#if VA_CHECK_VERSION(0, 36, 0) -+typedef struct VAAPIDRMImageBufferMapping { -+ VAImage image; -+ VABufferInfo buffer_info; -+ -+ AVDRMFrameDescriptor drm_desc; -+} VAAPIDRMImageBufferMapping; -+ -+static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc, -+ HWMapDescriptor *hwmap) -+{ -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ VAAPIDRMImageBufferMapping *mapping = hwmap->priv; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ -+ surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; -+ av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n", -+ surface_id); -+ -+ // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(), -+ // so we shouldn't close them separately. -+ -+ vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer " -+ "handle of image %#x (derived from surface %#x): " -+ "%d (%s).\n", mapping->image.buf, surface_id, -+ vas, vaErrorStr(vas)); -+ } -+ -+ vas = vaDestroyImage(hwctx->display, mapping->image.image_id); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image " -+ "derived from surface %#x: %d (%s).\n", -+ surface_id, vas, vaErrorStr(vas)); -+ } -+ -+ av_free(mapping); -+} -+ -+static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+ AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; -+ VAAPIDRMImageBufferMapping *mapping = NULL; -+ VASurfaceID surface_id; -+ VAStatus vas; -+ int err, i, p; -+ -+ surface_id = (VASurfaceID)(uintptr_t)src->data[3]; -+ av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n", -+ surface_id); -+ -+ mapping = av_mallocz(sizeof(*mapping)); -+ if (!mapping) -+ return AVERROR(ENOMEM); -+ -+ vas = vaDeriveImage(hwctx->display, surface_id, -+ &mapping->image); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " -+ "surface %#x: %d (%s).\n", -+ surface_id, vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail; -+ } -+ -+ for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { -+ if (vaapi_drm_format_map[i].va_fourcc == -+ mapping->image.format.fourcc) -+ break; -+ } -+ if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) { -+ av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for " -+ "VAAPI format %#x.\n", mapping->image.format.fourcc); -+ err = AVERROR(EINVAL); -+ goto fail_derived; -+ } -+ -+ mapping->buffer_info.mem_type = -+ VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; -+ -+ mapping->drm_desc.nb_layers = -+ vaapi_drm_format_map[i].nb_layer_formats; -+ if (mapping->drm_desc.nb_layers > 1) { -+ if (mapping->drm_desc.nb_layers != mapping->image.num_planes) { -+ av_log(hwfc, AV_LOG_ERROR, "Image properties do not match " -+ "expected format: got %d planes, but expected %d.\n", -+ mapping->image.num_planes, mapping->drm_desc.nb_layers); -+ err = AVERROR(EINVAL); -+ goto fail_derived; -+ } -+ -+ for(p = 0; p < mapping->drm_desc.nb_layers; p++) { -+ mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) { -+ .format = vaapi_drm_format_map[i].layer_formats[p], -+ .nb_planes = 1, -+ .planes[0] = { -+ .object_index = 0, -+ .offset = mapping->image.offsets[p], -+ .pitch = mapping->image.pitches[p], -+ }, -+ }; -+ } -+ } else { -+ mapping->drm_desc.layers[0].format = -+ vaapi_drm_format_map[i].layer_formats[0]; -+ mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes; -+ for (p = 0; p < mapping->image.num_planes; p++) { -+ mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) { -+ .object_index = 0, -+ .offset = mapping->image.offsets[p], -+ .pitch = mapping->image.pitches[p], -+ }; -+ } -+ } -+ -+ vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf, -+ &mapping->buffer_info); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer " -+ "handle from image %#x (derived from surface %#x): " -+ "%d (%s).\n", mapping->image.buf, surface_id, -+ vas, vaErrorStr(vas)); -+ err = AVERROR(EIO); -+ goto fail_derived; -+ } -+ -+ av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n", -+ mapping->buffer_info.handle); -+ -+ mapping->drm_desc.nb_objects = 1; -+ mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) { -+ .fd = mapping->buffer_info.handle, -+ .size = mapping->image.data_size, -+ // There is no way to get the format modifier with this API. -+ .format_modifier = DRM_FORMAT_MOD_INVALID, -+ }; -+ -+ err = ff_hwframe_map_create(src->hw_frames_ctx, -+ dst, src, &vaapi_unmap_to_drm_abh, -+ mapping); -+ if (err < 0) -+ goto fail_mapped; -+ -+ dst->data[0] = (uint8_t*)&mapping->drm_desc; -+ dst->width = src->width; -+ dst->height = src->height; -+ -+ return 0; -+ -+fail_mapped: -+ vaReleaseBufferHandle(hwctx->display, mapping->image.buf); -+fail_derived: -+ vaDestroyImage(hwctx->display, mapping->image.image_id); -+fail: -+ av_freep(&mapping); -+ return err; -+} -+#endif -+ -+static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+#if VA_CHECK_VERSION(1, 1, 0) -+ int err; -+ err = vaapi_map_to_drm_esh(hwfc, dst, src, flags); -+ if (err != AVERROR(ENOSYS)) -+ return err; -+#endif -+#if VA_CHECK_VERSION(0, 36, 0) -+ return vaapi_map_to_drm_abh(hwfc, dst, src, flags); -+#endif -+ return AVERROR(ENOSYS); -+} -+ -+#endif /* CONFIG_LIBDRM */ -+ -+static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+ switch (src->format) { -+#if CONFIG_LIBDRM -+ case AV_PIX_FMT_DRM_PRIME: -+ return vaapi_map_from_drm(hwfc, dst, src, flags); -+#endif -+ default: -+ return AVERROR(ENOSYS); -+ } -+} -+ -+static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, -+ const AVFrame *src, int flags) -+{ -+ switch (dst->format) { -+#if CONFIG_LIBDRM -+ case AV_PIX_FMT_DRM_PRIME: -+ return vaapi_map_to_drm(hwfc, dst, src, flags); -+#endif -+ default: -+ return vaapi_map_to_memory(hwfc, dst, src, flags); -+ } -+} -+ -+static void vaapi_device_free(AVHWDeviceContext *ctx) -+{ -+ AVVAAPIDeviceContext *hwctx = ctx->hwctx; -+ VAAPIDevicePriv *priv = ctx->user_opaque; -+ -+ if (hwctx->display) -+ vaTerminate(hwctx->display); -+ -+#if HAVE_VAAPI_X11 -+ if (priv->x11_display) -+ XCloseDisplay(priv->x11_display); -+#endif -+ -+ if (priv->drm_fd >= 0) -+ close(priv->drm_fd); -+ -+ av_freep(&priv); -+} -+ -+#if CONFIG_VAAPI_1 -+static void vaapi_device_log_error(void *context, const char *message) -+{ -+ AVHWDeviceContext *ctx = context; -+ -+ av_log(ctx, AV_LOG_ERROR, "libva: %s", message); -+} -+ -+static void vaapi_device_log_info(void *context, const char *message) -+{ -+ AVHWDeviceContext *ctx = context; -+ -+ av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message); -+} -+#endif -+ -+static int vaapi_device_connect(AVHWDeviceContext *ctx, -+ VADisplay display) -+{ -+ AVVAAPIDeviceContext *hwctx = ctx->hwctx; -+ int major, minor; -+ VAStatus vas; -+ -+#if CONFIG_VAAPI_1 -+ vaSetErrorCallback(display, &vaapi_device_log_error, ctx); -+ vaSetInfoCallback (display, &vaapi_device_log_info, ctx); -+#endif -+ -+ hwctx->display = display; -+ -+ vas = vaInitialize(display, &major, &minor); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI " -+ "connection: %d (%s).\n", vas, vaErrorStr(vas)); -+ return AVERROR(EIO); -+ } -+ av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: " -+ "version %d.%d\n", major, minor); -+ -+ return 0; -+} -+ -+static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, -+ AVDictionary *opts, int flags) -+{ -+ VAAPIDevicePriv *priv; -+ VADisplay display = NULL; -+ const AVDictionaryEntry *ent; -+ int try_drm, try_x11, try_all; -+ -+ priv = av_mallocz(sizeof(*priv)); -+ if (!priv) -+ return AVERROR(ENOMEM); -+ -+ priv->drm_fd = -1; -+ -+ ctx->user_opaque = priv; -+ ctx->free = vaapi_device_free; -+ -+ ent = av_dict_get(opts, "connection_type", NULL, 0); -+ if (ent) { -+ try_all = try_drm = try_x11 = 0; -+ if (!strcmp(ent->value, "drm")) { -+ try_drm = 1; -+ } else if (!strcmp(ent->value, "x11")) { -+ try_x11 = 1; -+ } else { -+ av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n", -+ ent->value); -+ return AVERROR(EINVAL); -+ } -+ } else { -+ try_all = 1; -+ try_drm = HAVE_VAAPI_DRM; -+ try_x11 = HAVE_VAAPI_X11; -+ } -+ -+#if HAVE_VAAPI_DRM -+ while (!display && try_drm) { -+ // If the device is specified, try to open it as a DRM device node. -+ // If not, look for a usable render node, possibly restricted to those -+ // using a specified kernel driver. -+ int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR; -+ if (device) { -+ priv->drm_fd = open(device, O_RDWR); -+ if (priv->drm_fd < 0) { -+ av_log(ctx, loglevel, "Failed to open %s as " -+ "DRM device node.\n", device); -+ break; -+ } -+ } else { -+ char path[64]; -+ int n, max_devices = 8; -+#if CONFIG_LIBDRM -+ const AVDictionaryEntry *kernel_driver; -+ kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0); -+#endif -+ for (n = 0; n < max_devices; n++) { -+ snprintf(path, sizeof(path), -+ "/dev/dri/renderD%d", 128 + n); -+ priv->drm_fd = open(path, O_RDWR); -+ if (priv->drm_fd < 0) { -+ av_log(ctx, AV_LOG_VERBOSE, "Cannot open " -+ "DRM render node for device %d.\n", n); -+ break; -+ } -+#if CONFIG_LIBDRM -+ if (kernel_driver) { -+ drmVersion *info; -+ info = drmGetVersion(priv->drm_fd); -+ if (strcmp(kernel_driver->value, info->name)) { -+ av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d " -+ "with non-matching kernel driver (%s).\n", -+ n, info->name); -+ drmFreeVersion(info); -+ close(priv->drm_fd); -+ priv->drm_fd = -1; -+ continue; -+ } -+ av_log(ctx, AV_LOG_VERBOSE, "Trying to use " -+ "DRM render node for device %d, " -+ "with matching kernel driver (%s).\n", -+ n, info->name); -+ drmFreeVersion(info); -+ } else -+#endif -+ { -+ av_log(ctx, AV_LOG_VERBOSE, "Trying to use " -+ "DRM render node for device %d.\n", n); -+ } -+ break; -+ } -+ if (n >= max_devices) -+ break; -+ } -+ -+ display = vaGetDisplayDRM(priv->drm_fd); -+ if (!display) { -+ av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display " -+ "from DRM device %s.\n", device); -+ return AVERROR_EXTERNAL; -+ } -+ break; -+ } -+#endif -+ -+#if HAVE_VAAPI_X11 -+ if (!display && try_x11) { -+ // Try to open the device as an X11 display. -+ priv->x11_display = XOpenDisplay(device); -+ if (!priv->x11_display) { -+ av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display " -+ "%s.\n", XDisplayName(device)); -+ } else { -+ display = vaGetDisplay(priv->x11_display); -+ if (!display) { -+ av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " -+ "from X11 display %s.\n", XDisplayName(device)); -+ return AVERROR_UNKNOWN; -+ } -+ -+ av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " -+ "X11 display %s.\n", XDisplayName(device)); -+ } -+ } -+#endif -+ -+ if (!display) { -+ if (device) -+ av_log(ctx, AV_LOG_ERROR, "No VA display found for " -+ "device %s.\n", device); -+ else -+ av_log(ctx, AV_LOG_ERROR, "No VA display found for " -+ "any default device.\n"); -+ return AVERROR(EINVAL); -+ } -+ -+ ent = av_dict_get(opts, "driver", NULL, 0); -+ if (ent) { -+#if VA_CHECK_VERSION(0, 38, 0) -+ VAStatus vas; -+ vas = vaSetDriverName(display, ent->value); -+ if (vas != VA_STATUS_SUCCESS) { -+ av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to " -+ "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas)); -+ vaTerminate(display); -+ return AVERROR_EXTERNAL; -+ } -+#else -+ av_log(ctx, AV_LOG_WARNING, "Driver name setting is not " -+ "supported with this VAAPI version.\n"); -+#endif -+ } -+ -+ return vaapi_device_connect(ctx, display); -+} -+ -+static int vaapi_device_derive(AVHWDeviceContext *ctx, -+ AVHWDeviceContext *src_ctx, int flags) -+{ -+#if HAVE_VAAPI_DRM -+ if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) { -+ AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; -+ VADisplay *display; -+ VAAPIDevicePriv *priv; -+ -+ if (src_hwctx->fd < 0) { -+ av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated " -+ "device to derive a VA display from.\n"); -+ return AVERROR(EINVAL); -+ } -+ -+ priv = av_mallocz(sizeof(*priv)); -+ if (!priv) -+ return AVERROR(ENOMEM); -+ -+ // Inherits the fd from the source context, which will close it. -+ priv->drm_fd = -1; -+ -+ ctx->user_opaque = priv; -+ ctx->free = &vaapi_device_free; -+ -+ display = vaGetDisplayDRM(src_hwctx->fd); -+ if (!display) { -+ av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from " -+ "DRM device.\n"); -+ return AVERROR(EIO); -+ } -+ -+ return vaapi_device_connect(ctx, display); -+ } -+#endif -+ return AVERROR(ENOSYS); -+} -+ -+const HWContextType ff_hwcontext_type_vaapi = { -+ .type = AV_HWDEVICE_TYPE_VAAPI, -+ .name = "VAAPI", -+ -+ .device_hwctx_size = sizeof(AVVAAPIDeviceContext), -+ .device_priv_size = sizeof(VAAPIDeviceContext), -+ .device_hwconfig_size = sizeof(AVVAAPIHWConfig), -+ .frames_hwctx_size = sizeof(AVVAAPIFramesContext), -+ .frames_priv_size = sizeof(VAAPIFramesContext), -+ -+ .device_create = &vaapi_device_create, -+ .device_derive = &vaapi_device_derive, -+ .device_init = &vaapi_device_init, -+ .device_uninit = &vaapi_device_uninit, -+ .frames_get_constraints = &vaapi_frames_get_constraints, -+ .frames_init = &vaapi_frames_init, -+ .frames_uninit = &vaapi_frames_uninit, -+ .frames_get_buffer = &vaapi_get_buffer, -+ .transfer_get_formats = &vaapi_transfer_get_formats, -+ .transfer_data_to = &vaapi_transfer_data_to, -+ .transfer_data_from = &vaapi_transfer_data_from, -+ .map_to = &vaapi_map_to, -+ .map_from = &vaapi_map_from, -+ -+ .pix_fmts = (const enum AVPixelFormat[]) { -+ AV_PIX_FMT_VAAPI, -+ AV_PIX_FMT_NONE -+ }, -+}; -diff -up firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.h.ffvpx firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.h ---- firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.h.ffvpx 2020-12-10 20:40:53.390541394 +0100 -+++ firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.h 2020-12-10 20:40:53.390541394 +0100 -@@ -0,0 +1,117 @@ -+/* -+ * This file is part of FFmpeg. -+ * -+ * FFmpeg is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * FFmpeg is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with FFmpeg; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef AVUTIL_HWCONTEXT_VAAPI_H -+#define AVUTIL_HWCONTEXT_VAAPI_H -+ -+#include -+ -+/** -+ * @file -+ * API-specific header for AV_HWDEVICE_TYPE_VAAPI. -+ * -+ * Dynamic frame pools are supported, but note that any pool used as a render -+ * target is required to be of fixed size in order to be be usable as an -+ * argument to vaCreateContext(). -+ * -+ * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs -+ * with the data pointer set to a VASurfaceID. -+ */ -+ -+enum { -+ /** -+ * The quirks field has been set by the user and should not be detected -+ * automatically by av_hwdevice_ctx_init(). -+ */ -+ AV_VAAPI_DRIVER_QUIRK_USER_SET = (1 << 0), -+ /** -+ * The driver does not destroy parameter buffers when they are used by -+ * vaRenderPicture(). Additional code will be required to destroy them -+ * separately afterwards. -+ */ -+ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS = (1 << 1), -+ -+ /** -+ * The driver does not support the VASurfaceAttribMemoryType attribute, -+ * so the surface allocation code will not try to use it. -+ */ -+ AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE = (1 << 2), -+ -+ /** -+ * The driver does not support surface attributes at all. -+ * The surface allocation code will never pass them to surface allocation, -+ * and the results of the vaQuerySurfaceAttributes() call will be faked. -+ */ -+ AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES = (1 << 3), -+}; -+ -+/** -+ * VAAPI connection details. -+ * -+ * Allocated as AVHWDeviceContext.hwctx -+ */ -+typedef struct AVVAAPIDeviceContext { -+ /** -+ * The VADisplay handle, to be filled by the user. -+ */ -+ VADisplay display; -+ /** -+ * Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), -+ * with reference to a table of known drivers, unless the -+ * AV_VAAPI_DRIVER_QUIRK_USER_SET bit is already present. The user -+ * may need to refer to this field when performing any later -+ * operations using VAAPI with the same VADisplay. -+ */ -+ unsigned int driver_quirks; -+} AVVAAPIDeviceContext; -+ -+/** -+ * VAAPI-specific data associated with a frame pool. -+ * -+ * Allocated as AVHWFramesContext.hwctx. -+ */ -+typedef struct AVVAAPIFramesContext { -+ /** -+ * Set by the user to apply surface attributes to all surfaces in -+ * the frame pool. If null, default settings are used. -+ */ -+ VASurfaceAttrib *attributes; -+ int nb_attributes; -+ /** -+ * The surfaces IDs of all surfaces in the pool after creation. -+ * Only valid if AVHWFramesContext.initial_pool_size was positive. -+ * These are intended to be used as the render_targets arguments to -+ * vaCreateContext(). -+ */ -+ VASurfaceID *surface_ids; -+ int nb_surfaces; -+} AVVAAPIFramesContext; -+ -+/** -+ * VAAPI hardware pipeline configuration details. -+ * -+ * Allocated with av_hwdevice_hwconfig_alloc(). -+ */ -+typedef struct AVVAAPIHWConfig { -+ /** -+ * ID of a VAAPI pipeline configuration. -+ */ -+ VAConfigID config_id; -+} AVVAAPIHWConfig; -+ -+#endif /* AVUTIL_HWCONTEXT_VAAPI_H */ -diff -up firefox-84.0/media/ffvpx/libavutil/moz.build.ffvpx firefox-84.0/media/ffvpx/libavutil/moz.build ---- firefox-84.0/media/ffvpx/libavutil/moz.build.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/libavutil/moz.build 2020-12-10 20:40:53.390541394 +0100 -@@ -45,6 +45,11 @@ SOURCES += [ - 'time.c', - 'utils.c' - ] -+if CONFIG['MOZ_WAYLAND']: -+ SOURCES += [ -+ 'hwcontext_vaapi.c', -+ ] -+ USE_LIBS += ['mozva'] - - if not CONFIG['MOZ_FFVPX_AUDIOONLY']: - SOURCES += [ -diff -up firefox-84.0/media/ffvpx/moz.build.ffvpx firefox-84.0/media/ffvpx/moz.build ---- firefox-84.0/media/ffvpx/moz.build.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/moz.build 2020-12-10 20:40:53.390541394 +0100 -@@ -11,3 +11,8 @@ DIRS += [ - 'libavutil', - 'libavcodec' - ] -+ -+if CONFIG['MOZ_WAYLAND']: -+ DIRS += [ -+ 'mozva', -+ ] -diff -up firefox-84.0/media/ffvpx/mozva/moz.build.ffvpx firefox-84.0/media/ffvpx/mozva/moz.build ---- firefox-84.0/media/ffvpx/mozva/moz.build.ffvpx 2020-12-10 20:40:53.390541394 +0100 -+++ firefox-84.0/media/ffvpx/mozva/moz.build 2020-12-10 20:40:53.390541394 +0100 -@@ -0,0 +1,13 @@ -+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -+# vim: set filetype=python: -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+SOURCES += [ -+ 'mozva.c', -+] -+ -+LOCAL_INCLUDES += ['/media/ffvpx'] -+ -+Library('mozva') -diff -up firefox-84.0/media/ffvpx/mozva/mozva.c.ffvpx firefox-84.0/media/ffvpx/mozva/mozva.c ---- firefox-84.0/media/ffvpx/mozva/mozva.c.ffvpx 2020-12-10 20:40:53.390541394 +0100 -+++ firefox-84.0/media/ffvpx/mozva/mozva.c 2020-12-10 20:40:53.390541394 +0100 -@@ -0,0 +1,406 @@ -+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=4: -+ */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#pragma GCC visibility push(default) -+#include -+#pragma GCC visibility pop -+ -+#include "mozilla/Types.h" -+#include -+#include -+#include -+ -+#define GET_FUNC(func, lib) (func##Fn = dlsym(lib, #func)) -+ -+#define IS_FUNC_LOADED(func) (func##Fn != NULL) -+ -+static VAStatus (*vaDestroyBufferFn)(VADisplay dpy, VABufferID buffer_id); -+static VAStatus (*vaBeginPictureFn)(VADisplay dpy, VAContextID context, -+ VASurfaceID render_target); -+static VAStatus (*vaEndPictureFn)(VADisplay dpy, VAContextID context); -+static VAStatus (*vaRenderPictureFn)(VADisplay dpy, VAContextID context, -+ VABufferID* buffers, int num_buffers); -+static int (*vaMaxNumProfilesFn)(VADisplay dpy); -+static VAStatus (*vaCreateContextFn)(VADisplay dpy, VAConfigID config_id, -+ int picture_width, int picture_height, -+ int flag, VASurfaceID* render_targets, -+ int num_render_targets, -+ VAContextID* context /* out */); -+static VAStatus (*vaDestroyContextFn)(VADisplay dpy, VAContextID context); -+static VAStatus (*vaCreateBufferFn)(VADisplay dpy, VAContextID context, -+ VABufferType type, /* in */ -+ unsigned int size, /* in */ -+ unsigned int num_elements, /* in */ -+ void* data, /* in */ -+ VABufferID* buf_id /* out */); -+static VAStatus (*vaQuerySurfaceAttributesFn)(VADisplay dpy, VAConfigID config, -+ VASurfaceAttrib* attrib_list, -+ unsigned int* num_attribs); -+static VAStatus (*vaQueryConfigProfilesFn)(VADisplay dpy, -+ VAProfile* profile_list, /* out */ -+ int* num_profiles /* out */); -+static const char* (*vaErrorStrFn)(VAStatus error_status); -+static VAStatus (*vaCreateConfigFn)(VADisplay dpy, VAProfile profile, -+ VAEntrypoint entrypoint, -+ VAConfigAttrib* attrib_list, -+ int num_attribs, -+ VAConfigID* config_id /* out */); -+static VAStatus (*vaDestroyConfigFn)(VADisplay dpy, VAConfigID config_id); -+static int (*vaMaxNumImageFormatsFn)(VADisplay dpy); -+static VAStatus (*vaQueryImageFormatsFn)(VADisplay dpy, -+ VAImageFormat* format_list, /* out */ -+ int* num_formats /* out */); -+static const char* (*vaQueryVendorStringFn)(VADisplay dpy); -+static VAStatus (*vaDestroySurfacesFn)(VADisplay dpy, VASurfaceID* surfaces, -+ int num_surfaces); -+static VAStatus (*vaCreateSurfacesFn)(VADisplay dpy, unsigned int format, -+ unsigned int width, unsigned int height, -+ VASurfaceID* surfaces, -+ unsigned int num_surfaces, -+ VASurfaceAttrib* attrib_list, -+ unsigned int num_attribs); -+static VAStatus (*vaDeriveImageFn)(VADisplay dpy, VASurfaceID surface, -+ VAImage* image /* out */); -+static VAStatus (*vaDestroyImageFn)(VADisplay dpy, VAImageID image); -+static VAStatus (*vaPutImageFn)(VADisplay dpy, VASurfaceID surface, -+ VAImageID image, int src_x, int src_y, -+ unsigned int src_width, unsigned int src_height, -+ int dest_x, int dest_y, unsigned int dest_width, -+ unsigned int dest_height); -+static VAStatus (*vaSyncSurfaceFn)(VADisplay dpy, VASurfaceID render_target); -+static VAStatus (*vaCreateImageFn)(VADisplay dpy, VAImageFormat* format, -+ int width, int height, -+ VAImage* image /* out */); -+static VAStatus (*vaGetImageFn)( -+ VADisplay dpy, VASurfaceID surface, -+ int x, /* coordinates of the upper left source pixel */ -+ int y, unsigned int width, /* width and height of the region */ -+ unsigned int height, VAImageID image); -+static VAStatus (*vaMapBufferFn)(VADisplay dpy, VABufferID buf_id, /* in */ -+ void** pbuf /* out */); -+static VAStatus (*vaUnmapBufferFn)(VADisplay dpy, VABufferID buf_id /* in */); -+static VAStatus (*vaTerminateFn)(VADisplay dpy); -+static VAStatus (*vaInitializeFn)(VADisplay dpy, int* major_version, /* out */ -+ int* minor_version /* out */); -+static VAStatus (*vaSetDriverNameFn)(VADisplay dpy, char* driver_name); -+ -+int LoadVALibrary() { -+ static pthread_mutex_t sVALock = PTHREAD_MUTEX_INITIALIZER; -+ static void* sVALib = NULL; -+ static int sVAInitialized = 0; -+ static int sVALoaded = 0; -+ -+ pthread_mutex_lock(&sVALock); -+ -+ if (!sVAInitialized) { -+ sVAInitialized = 1; -+ sVALib = dlopen("libva.so.2", RTLD_LAZY); -+ if (!sVALib) { -+ pthread_mutex_unlock(&sVALock); -+ return 0; -+ } -+ GET_FUNC(vaDestroyBuffer, sVALib); -+ GET_FUNC(vaBeginPicture, sVALib); -+ GET_FUNC(vaEndPicture, sVALib); -+ GET_FUNC(vaRenderPicture, sVALib); -+ GET_FUNC(vaMaxNumProfiles, sVALib); -+ GET_FUNC(vaCreateContext, sVALib); -+ GET_FUNC(vaDestroyContext, sVALib); -+ GET_FUNC(vaCreateBuffer, sVALib); -+ GET_FUNC(vaQuerySurfaceAttributes, sVALib); -+ GET_FUNC(vaQueryConfigProfiles, sVALib); -+ GET_FUNC(vaErrorStr, sVALib); -+ GET_FUNC(vaCreateConfig, sVALib); -+ GET_FUNC(vaDestroyConfig, sVALib); -+ GET_FUNC(vaMaxNumImageFormats, sVALib); -+ GET_FUNC(vaQueryImageFormats, sVALib); -+ GET_FUNC(vaQueryVendorString, sVALib); -+ GET_FUNC(vaDestroySurfaces, sVALib); -+ GET_FUNC(vaCreateSurfaces, sVALib); -+ GET_FUNC(vaDeriveImage, sVALib); -+ GET_FUNC(vaDestroyImage, sVALib); -+ GET_FUNC(vaPutImage, sVALib); -+ GET_FUNC(vaSyncSurface, sVALib); -+ GET_FUNC(vaCreateImage, sVALib); -+ GET_FUNC(vaGetImage, sVALib); -+ GET_FUNC(vaMapBuffer, sVALib); -+ GET_FUNC(vaUnmapBuffer, sVALib); -+ GET_FUNC(vaTerminate, sVALib); -+ GET_FUNC(vaInitialize, sVALib); -+ GET_FUNC(vaSetDriverName, sVALib); -+ -+ sVALoaded = -+ (IS_FUNC_LOADED(vaDestroyBuffer) && IS_FUNC_LOADED(vaBeginPicture) && -+ IS_FUNC_LOADED(vaEndPicture) && IS_FUNC_LOADED(vaRenderPicture) && -+ IS_FUNC_LOADED(vaMaxNumProfiles) && IS_FUNC_LOADED(vaCreateContext) && -+ IS_FUNC_LOADED(vaDestroyContext) && IS_FUNC_LOADED(vaCreateBuffer) && -+ IS_FUNC_LOADED(vaQuerySurfaceAttributes) && -+ IS_FUNC_LOADED(vaQueryConfigProfiles) && IS_FUNC_LOADED(vaErrorStr) && -+ IS_FUNC_LOADED(vaCreateConfig) && IS_FUNC_LOADED(vaDestroyConfig) && -+ IS_FUNC_LOADED(vaMaxNumImageFormats) && -+ IS_FUNC_LOADED(vaQueryImageFormats) && -+ IS_FUNC_LOADED(vaQueryVendorString) && -+ IS_FUNC_LOADED(vaDestroySurfaces) && -+ IS_FUNC_LOADED(vaCreateSurfaces) && IS_FUNC_LOADED(vaDeriveImage) && -+ IS_FUNC_LOADED(vaDestroyImage) && IS_FUNC_LOADED(vaPutImage) && -+ IS_FUNC_LOADED(vaSyncSurface) && IS_FUNC_LOADED(vaCreateImage) && -+ IS_FUNC_LOADED(vaGetImage) && IS_FUNC_LOADED(vaMapBuffer) && -+ IS_FUNC_LOADED(vaUnmapBuffer) && IS_FUNC_LOADED(vaTerminate) && -+ IS_FUNC_LOADED(vaInitialize) && IS_FUNC_LOADED(vaSetDriverName)); -+ } -+ pthread_mutex_unlock(&sVALock); -+ return sVALoaded; -+} -+ -+#pragma GCC visibility push(default) -+ -+VAStatus vaDestroyBuffer(VADisplay dpy, VABufferID buffer_id) { -+ if (LoadVALibrary()) { -+ return vaDestroyBufferFn(dpy, buffer_id); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaBeginPicture(VADisplay dpy, VAContextID context, -+ VASurfaceID render_target) { -+ if (LoadVALibrary()) { -+ return vaBeginPictureFn(dpy, context, render_target); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaEndPicture(VADisplay dpy, VAContextID context) { -+ if (LoadVALibrary()) { -+ return vaEndPictureFn(dpy, context); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaRenderPicture(VADisplay dpy, VAContextID context, -+ VABufferID* buffers, int num_buffers) { -+ if (LoadVALibrary()) { -+ return vaRenderPictureFn(dpy, context, buffers, num_buffers); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+int vaMaxNumProfiles(VADisplay dpy) { -+ if (LoadVALibrary()) { -+ return vaMaxNumProfilesFn(dpy); -+ } -+ return 0; -+} -+ -+VAStatus vaCreateContext(VADisplay dpy, VAConfigID config_id, int picture_width, -+ int picture_height, int flag, -+ VASurfaceID* render_targets, int num_render_targets, -+ VAContextID* context /* out */) { -+ if (LoadVALibrary()) { -+ return vaCreateContextFn(dpy, config_id, picture_width, picture_height, -+ flag, render_targets, num_render_targets, context); -+ } -+ *context = 0; -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaDestroyContext(VADisplay dpy, VAContextID context) { -+ if (LoadVALibrary()) { -+ return vaDestroyContextFn(dpy, context); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaCreateBuffer(VADisplay dpy, VAContextID context, -+ VABufferType type, /* in */ -+ unsigned int size, /* in */ -+ unsigned int num_elements, /* in */ -+ void* data, /* in */ -+ VABufferID* buf_id /* out */) { -+ if (LoadVALibrary()) { -+ return vaCreateBufferFn(dpy, context, type, size, num_elements, data, -+ buf_id); -+ } -+ *buf_id = 0; -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaQuerySurfaceAttributes(VADisplay dpy, VAConfigID config, -+ VASurfaceAttrib* attrib_list, -+ unsigned int* num_attribs) { -+ if (LoadVALibrary()) { -+ return vaQuerySurfaceAttributesFn(dpy, config, attrib_list, num_attribs); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaQueryConfigProfiles(VADisplay dpy, VAProfile* profile_list, /* out */ -+ int* num_profiles /* out */) { -+ if (LoadVALibrary()) { -+ return vaQueryConfigProfilesFn(dpy, profile_list, num_profiles); -+ } -+ *num_profiles = 0; -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+const char* vaErrorStr(VAStatus error_status) { -+ if (LoadVALibrary()) { -+ return vaErrorStrFn(error_status); -+ } -+ static char tmp[] = "Unimplemented"; -+ return tmp; -+} -+ -+VAStatus vaCreateConfig(VADisplay dpy, VAProfile profile, -+ VAEntrypoint entrypoint, VAConfigAttrib* attrib_list, -+ int num_attribs, VAConfigID* config_id /* out */) { -+ if (LoadVALibrary()) { -+ return vaCreateConfigFn(dpy, profile, entrypoint, attrib_list, num_attribs, -+ config_id); -+ } -+ *config_id = 0; -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaDestroyConfig(VADisplay dpy, VAConfigID config_id) { -+ if (LoadVALibrary()) { -+ return vaDestroyConfigFn(dpy, config_id); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+int vaMaxNumImageFormats(VADisplay dpy) { -+ if (LoadVALibrary()) { -+ return vaMaxNumImageFormatsFn(dpy); -+ } -+ return 0; -+} -+ -+VAStatus vaQueryImageFormats(VADisplay dpy, VAImageFormat* format_list, -+ int* num_formats) { -+ if (LoadVALibrary()) { -+ return vaQueryImageFormatsFn(dpy, format_list, num_formats); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+const char* vaQueryVendorString(VADisplay dpy) { -+ if (LoadVALibrary()) { -+ return vaQueryVendorStringFn(dpy); -+ } -+ return NULL; -+} -+ -+VAStatus vaDestroySurfaces(VADisplay dpy, VASurfaceID* surfaces, -+ int num_surfaces) { -+ if (LoadVALibrary()) { -+ return vaDestroySurfacesFn(dpy, surfaces, num_surfaces); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaCreateSurfaces(VADisplay dpy, unsigned int format, -+ unsigned int width, unsigned int height, -+ VASurfaceID* surfaces, unsigned int num_surfaces, -+ VASurfaceAttrib* attrib_list, -+ unsigned int num_attribs) { -+ if (LoadVALibrary()) { -+ return vaCreateSurfacesFn(dpy, format, width, height, surfaces, -+ num_surfaces, attrib_list, num_attribs); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaDeriveImage(VADisplay dpy, VASurfaceID surface, -+ VAImage* image /* out */) { -+ if (LoadVALibrary()) { -+ return vaDeriveImageFn(dpy, surface, image); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaDestroyImage(VADisplay dpy, VAImageID image) { -+ if (LoadVALibrary()) { -+ return vaDestroyImageFn(dpy, image); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaPutImage(VADisplay dpy, VASurfaceID surface, VAImageID image, -+ int src_x, int src_y, unsigned int src_width, -+ unsigned int src_height, int dest_x, int dest_y, -+ unsigned int dest_width, unsigned int dest_height) { -+ if (LoadVALibrary()) { -+ return vaPutImageFn(dpy, surface, image, src_x, src_y, src_width, -+ src_height, dest_x, dest_y, dest_width, dest_height); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaSyncSurface(VADisplay dpy, VASurfaceID render_target) { -+ if (LoadVALibrary()) { -+ return vaSyncSurfaceFn(dpy, render_target); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaCreateImage(VADisplay dpy, VAImageFormat* format, int width, -+ int height, VAImage* image /* out */) { -+ if (LoadVALibrary()) { -+ return vaCreateImageFn(dpy, format, width, height, image); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaGetImage(VADisplay dpy, VASurfaceID surface, -+ int x, /* coordinates of the upper left source pixel */ -+ int y, -+ unsigned int width, /* width and height of the region */ -+ unsigned int height, VAImageID image) { -+ if (LoadVALibrary()) { -+ return vaGetImageFn(dpy, surface, x, y, width, height, image); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaMapBuffer(VADisplay dpy, VABufferID buf_id, /* in */ -+ void** pbuf /* out */) { -+ if (LoadVALibrary()) { -+ return vaMapBufferFn(dpy, buf_id, pbuf); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaUnmapBuffer(VADisplay dpy, VABufferID buf_id /* in */) { -+ if (LoadVALibrary()) { -+ return vaUnmapBufferFn(dpy, buf_id); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaTerminate(VADisplay dpy) { -+ if (LoadVALibrary()) { -+ return vaTerminateFn(dpy); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaInitialize(VADisplay dpy, int* major_version, /* out */ -+ int* minor_version /* out */) { -+ if (LoadVALibrary()) { -+ return vaInitializeFn(dpy, major_version, minor_version); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+VAStatus vaSetDriverName(VADisplay dpy, char* driver_name) { -+ if (LoadVALibrary()) { -+ return vaSetDriverNameFn(dpy, driver_name); -+ } -+ return VA_STATUS_ERROR_UNIMPLEMENTED; -+} -+ -+#pragma GCC visibility pop -diff -up firefox-84.0/media/ffvpx/README_MOZILLA.ffvpx firefox-84.0/media/ffvpx/README_MOZILLA ---- firefox-84.0/media/ffvpx/README_MOZILLA.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/README_MOZILLA 2020-12-10 20:40:53.390541394 +0100 -@@ -56,3 +56,5 @@ $ for i in `cat $PATH_CENTRAL/media/ffvp - Then apply patch.diff on the ffvpx tree. - - Compilation will reveal if any files are missing. -+ -+Apply linux-vaapi-build.patch patch to enable build VA-API support for Linux. -diff -up firefox-84.0/media/ffvpx/va/README.ffvpx firefox-84.0/media/ffvpx/va/README ---- firefox-84.0/media/ffvpx/va/README.ffvpx 2020-12-10 20:40:53.390541394 +0100 -+++ firefox-84.0/media/ffvpx/va/README 2020-12-10 20:40:53.390541394 +0100 -@@ -0,0 +1,2 @@ -+There are libva headers from libva 1.7.0 used to build vaapi support for in-tree ffvpx. -+Apply va.patch when you update it to new versions. -\ No newline at end of file -diff -up firefox-84.0/media/ffvpx/va/va_dec_vp8.h.ffvpx firefox-84.0/media/ffvpx/va/va_dec_vp8.h ---- firefox-84.0/media/ffvpx/va/va_dec_vp8.h.ffvpx 2020-12-10 20:40:53.390541394 +0100 -+++ firefox-84.0/media/ffvpx/va/va_dec_vp8.h 2020-12-10 20:40:53.390541394 +0100 -@@ -0,0 +1,254 @@ -+/* -+ * Copyright (c) 2007-2012 Intel Corporation. All Rights Reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sub license, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -+ * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/** -+ * \file va_dec_vp.h -+ * \brief VP8 decoding API -+ * -+ * This file contains the \ref api_dec_vp8 "VP8 decoding API". -+ */ -+ -+#ifndef VA_DEC_VP8_H -+#define VA_DEC_VP8_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * \defgroup api_dec_vp8 VP8 decoding API -+ * -+ * @{ -+ */ -+ -+/** -+ * \brief VPX Bool Coder Context structure -+ * -+ * This common structure is defined for potential sharing by other VP formats -+ * -+ */ -+typedef struct _VABoolCoderContextVPX -+{ -+ /* partition 0 "range" */ -+ uint8_t range; -+ /* partition 0 "value" */ -+ uint8_t value; -+ /* -+ * 'partition 0 number of shifts before an output byte is available' -+ * it is the number of remaining bits in 'value' for decoding, range [0, 7]. -+ */ -+ -+ uint8_t count; -+} VABoolCoderContextVPX; -+ -+/** -+ * \brief VP8 Decoding Picture Parameter Buffer Structure -+ * -+ * This structure conveys frame level parameters and should be sent once -+ * per frame. -+ * -+ */ -+typedef struct _VAPictureParameterBufferVP8 -+{ -+ /* frame width in pixels */ -+ uint32_t frame_width; -+ /* frame height in pixels */ -+ uint32_t frame_height; -+ -+ /* specifies the "last" reference frame */ -+ VASurfaceID last_ref_frame; -+ /* specifies the "golden" reference frame */ -+ VASurfaceID golden_ref_frame; -+ /* specifies the "alternate" referrence frame */ -+ VASurfaceID alt_ref_frame; -+ /* specifies the out-of-loop deblocked frame, not used currently */ -+ VASurfaceID out_of_loop_frame; -+ -+ union { -+ struct { -+ /* same as key_frame in bitstream syntax, 0 means a key frame */ -+ uint32_t key_frame : 1; -+ /* same as version in bitstream syntax */ -+ uint32_t version : 3; -+ /* same as segmentation_enabled in bitstream syntax */ -+ uint32_t segmentation_enabled : 1; -+ /* same as update_mb_segmentation_map in bitstream syntax */ -+ uint32_t update_mb_segmentation_map : 1; -+ /* same as update_segment_feature_data in bitstream syntax */ -+ uint32_t update_segment_feature_data : 1; -+ /* same as filter_type in bitstream syntax */ -+ uint32_t filter_type : 1; -+ /* same as sharpness_level in bitstream syntax */ -+ uint32_t sharpness_level : 3; -+ /* same as loop_filter_adj_enable in bitstream syntax */ -+ uint32_t loop_filter_adj_enable : 1; -+ /* same as mode_ref_lf_delta_update in bitstream syntax */ -+ uint32_t mode_ref_lf_delta_update : 1; -+ /* same as sign_bias_golden in bitstream syntax */ -+ uint32_t sign_bias_golden : 1; -+ /* same as sign_bias_alternate in bitstream syntax */ -+ uint32_t sign_bias_alternate : 1; -+ /* same as mb_no_coeff_skip in bitstream syntax */ -+ uint32_t mb_no_coeff_skip : 1; -+ /* flag to indicate that loop filter should be disabled */ -+ uint32_t loop_filter_disable : 1; -+ } bits; -+ uint32_t value; -+ } pic_fields; -+ -+ /* -+ * probabilities of the segment_id decoding tree and same as -+ * mb_segment_tree_probs in the spec. -+ */ -+ uint8_t mb_segment_tree_probs[3]; -+ -+ /* Post-adjustment loop filter levels for the 4 segments */ -+ uint8_t loop_filter_level[4]; -+ /* loop filter deltas for reference frame based MB level adjustment */ -+ int8_t loop_filter_deltas_ref_frame[4]; -+ /* loop filter deltas for coding mode based MB level adjustment */ -+ int8_t loop_filter_deltas_mode[4]; -+ -+ /* same as prob_skip_false in bitstream syntax */ -+ uint8_t prob_skip_false; -+ /* same as prob_intra in bitstream syntax */ -+ uint8_t prob_intra; -+ /* same as prob_last in bitstream syntax */ -+ uint8_t prob_last; -+ /* same as prob_gf in bitstream syntax */ -+ uint8_t prob_gf; -+ -+ /* -+ * list of 4 probabilities of the luma intra prediction mode decoding -+ * tree and same as y_mode_probs in frame header -+ */ -+ uint8_t y_mode_probs[4]; -+ /* -+ * list of 3 probabilities of the chroma intra prediction mode decoding -+ * tree and same as uv_mode_probs in frame header -+ */ -+ uint8_t uv_mode_probs[3]; -+ /* -+ * updated mv decoding probabilities and same as mv_probs in -+ * frame header -+ */ -+ uint8_t mv_probs[2][19]; -+ -+ VABoolCoderContextVPX bool_coder_ctx; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAPictureParameterBufferVP8; -+ -+/** -+ * \brief VP8 Slice Parameter Buffer Structure -+ * -+ * This structure conveys parameters related to data partitions and should be -+ * sent once per frame. Slice data buffer of VASliceDataBufferType is used -+ * to send the partition data. -+ * -+ */ -+typedef struct _VASliceParameterBufferVP8 -+{ -+ /* -+ * number of bytes in the slice data buffer for the partitions -+ */ -+ uint32_t slice_data_size; -+ /* -+ * offset to the first byte of partition data (control partition) -+ */ -+ uint32_t slice_data_offset; -+ /* -+ * see VA_SLICE_DATA_FLAG_XXX definitions -+ */ -+ uint32_t slice_data_flag; -+ /* -+ * offset to the first bit of MB from the first byte of partition data(slice_data_offset) -+ */ -+ uint32_t macroblock_offset; -+ -+ /* -+ * Partitions -+ * (1<lvl[seg][ref][mode] in VP9 code, -+ * where m is [ref], and n is [mode] in FilterLevel[m][n]. -+ */ -+ uint8_t filter_level[4][2]; -+ /** \brief Specifies per segment Luma AC quantization scale. -+ * Corresponding to y_dequant[qindex][1] in vp9_mb_init_quantizer() -+ * function of VP9 code. -+ */ -+ int16_t luma_ac_quant_scale; -+ /** \brief Specifies per segment Luma DC quantization scale. -+ * Corresponding to y_dequant[qindex][0] in vp9_mb_init_quantizer() -+ * function of VP9 code. -+ */ -+ int16_t luma_dc_quant_scale; -+ /** \brief Specifies per segment Chroma AC quantization scale. -+ * Corresponding to uv_dequant[qindex][1] in vp9_mb_init_quantizer() -+ * function of VP9 code. -+ */ -+ int16_t chroma_ac_quant_scale; -+ /** \brief Specifies per segment Chroma DC quantization scale. -+ * Corresponding to uv_dequant[qindex][0] in vp9_mb_init_quantizer() -+ * function of VP9 code. -+ */ -+ int16_t chroma_dc_quant_scale; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+ -+} VASegmentParameterVP9; -+ -+ -+ -+/** -+ * \brief VP9 Slice Parameter Buffer Structure -+ * -+ * This structure conveys parameters related to segmentation data and should be -+ * sent once per frame. -+ * -+ * When segmentation is disabled, only SegParam[0] has valid values, -+ * all other entries should be populated with 0. -+ * Otherwise, all eight entries should be valid. -+ * -+ * Slice data buffer of VASliceDataBufferType is used -+ * to send the bitstream which should include whole or part of partition 0 -+ * (at least compressed header) to the end of frame. -+ * -+ */ -+typedef struct _VASliceParameterBufferVP9 -+{ -+ /** \brief The byte count of current frame in the bitstream buffer, -+ * starting from first byte of the buffer. -+ * It uses the name slice_data_size to be consitent with other codec, -+ * but actually means frame_data_size. -+ */ -+ uint32_t slice_data_size; -+ /** -+ * offset to the first byte of partition data (control partition) -+ */ -+ uint32_t slice_data_offset; -+ /** -+ * see VA_SLICE_DATA_FLAG_XXX definitions -+ */ -+ uint32_t slice_data_flag; -+ -+ /** -+ * \brief per segment information -+ */ -+ VASegmentParameterVP9 seg_param[8]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+ -+} VASliceParameterBufferVP9; -+ -+ -+/**@}*/ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* VA_DEC_VP9_H */ -diff -up firefox-84.0/media/ffvpx/va/va.h.ffvpx firefox-84.0/media/ffvpx/va/va.h ---- firefox-84.0/media/ffvpx/va/va.h.ffvpx 2020-12-10 20:40:53.391541423 +0100 -+++ firefox-84.0/media/ffvpx/va/va.h 2020-12-10 20:40:53.391541423 +0100 -@@ -0,0 +1,4636 @@ -+/* -+ * Copyright (c) 2007-2009 Intel Corporation. All Rights Reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sub license, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -+ * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+/* -+ * Video Acceleration (VA) API Specification -+ * -+ * Rev. 0.30 -+ * -+ * -+ * Revision History: -+ * rev 0.10 (12/10/2006 Jonathan Bian) - Initial draft -+ * rev 0.11 (12/15/2006 Jonathan Bian) - Fixed some errors -+ * rev 0.12 (02/05/2007 Jonathan Bian) - Added VC-1 data structures for slice level decode -+ * rev 0.13 (02/28/2007 Jonathan Bian) - Added GetDisplay() -+ * rev 0.14 (04/13/2007 Jonathan Bian) - Fixed MPEG-2 PictureParameter structure, cleaned up a few funcs. -+ * rev 0.15 (04/20/2007 Jonathan Bian) - Overhauled buffer management -+ * rev 0.16 (05/02/2007 Jonathan Bian) - Added error codes and fixed some issues with configuration -+ * rev 0.17 (05/07/2007 Jonathan Bian) - Added H.264/AVC data structures for slice level decode. -+ * rev 0.18 (05/14/2007 Jonathan Bian) - Added data structures for MPEG-4 slice level decode -+ * and MPEG-2 motion compensation. -+ * rev 0.19 (08/06/2007 Jonathan Bian) - Removed extra type for bitplane data. -+ * rev 0.20 (08/08/2007 Jonathan Bian) - Added missing fields to VC-1 PictureParameter structure. -+ * rev 0.21 (08/20/2007 Jonathan Bian) - Added image and subpicture support. -+ * rev 0.22 (08/27/2007 Jonathan Bian) - Added support for chroma-keying and global alpha. -+ * rev 0.23 (09/11/2007 Jonathan Bian) - Fixed some issues with images and subpictures. -+ * rev 0.24 (09/18/2007 Jonathan Bian) - Added display attributes. -+ * rev 0.25 (10/18/2007 Jonathan Bian) - Changed to use IDs only for some types. -+ * rev 0.26 (11/07/2007 Waldo Bastian) - Change vaCreateBuffer semantics -+ * rev 0.27 (11/19/2007 Matt Sottek) - Added DeriveImage -+ * rev 0.28 (12/06/2007 Jonathan Bian) - Added new versions of PutImage and AssociateSubpicture -+ * to enable scaling -+ * rev 0.29 (02/07/2008 Jonathan Bian) - VC1 parameter fixes, -+ * added VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED -+ * rev 0.30 (03/01/2009 Jonathan Bian) - Added encoding support for H.264 BP and MPEG-4 SP and fixes -+ * for ISO C conformance. -+ * rev 0.31 (09/02/2009 Gwenole Beauchesne) - VC-1/H264 fields change for VDPAU and XvBA backend -+ * Application needs to relink with the new library. -+ * -+ * rev 0.31.1 (03/29/2009) - Data structure for JPEG encode -+ * rev 0.31.2 (01/13/2011 Anthony Pabon)- Added a flag to indicate Subpicture coordinates are screen -+ * screen relative rather than source video relative. -+ * rev 0.32.0 (01/13/2011 Xiang Haihao) - Add profile into VAPictureParameterBufferVC1 -+ * update VAAPI to 0.32.0 -+ * -+ * Acknowledgements: -+ * Some concepts borrowed from XvMC and XvImage. -+ * Waldo Bastian (Intel), Matt Sottek (Intel), Austin Yuan (Intel), and Gwenole Beauchesne (SDS) -+ * contributed to various aspects of the API. -+ */ -+ -+/** -+ * \file va.h -+ * \brief The Core API -+ * -+ * This file contains the \ref api_core "Core API". -+ */ -+ -+#ifndef _VA_H_ -+#define _VA_H_ -+ -+#include -+#include -+#include "va_version.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#if defined(__GNUC__) && !defined(__COVERITY__) -+#define va_deprecated __attribute__((deprecated)) -+#if __GNUC__ >= 6 -+#define va_deprecated_enum va_deprecated -+#else -+#define va_deprecated_enum -+#endif -+#else -+#define va_deprecated -+#define va_deprecated_enum -+#endif -+ -+/** -+ * \mainpage Video Acceleration (VA) API -+ * -+ * \section intro Introduction -+ * -+ * The main motivation for VA-API (Video Acceleration API) is to -+ * enable hardware accelerated video decode and encode at various -+ * entry-points (VLD, IDCT, Motion Compensation etc.) for the -+ * prevailing coding standards today (MPEG-2, MPEG-4 ASP/H.263, MPEG-4 -+ * AVC/H.264, VC-1/VMW3, and JPEG, HEVC/H265, VP8, VP9) and video pre/post -+ * processing -+ * -+ * VA-API is split into several modules: -+ * - \ref api_core -+ * - Encoder (H264, HEVC, JPEG, MPEG2, VP8, VP9) -+ * - \ref api_enc_h264 -+ * - \ref api_enc_hevc -+ * - \ref api_enc_jpeg -+ * - \ref api_enc_mpeg2 -+ * - \ref api_enc_vp8 -+ * - \ref api_enc_vp9 -+ * - Decoder (HEVC, JPEG, VP8, VP9) -+ * - \ref api_dec_hevc -+ * - \ref api_dec_jpeg -+ * - \ref api_dec_vp8 -+ * - \ref api_dec_vp9 -+ * - \ref api_vpp -+ * - FEI (H264, HEVC) -+ * - \ref api_fei -+ * - \ref api_fei_h264 -+ * - \ref api_fei_hevc -+ */ -+ -+/** -+ * \defgroup api_core Core API -+ * -+ * @{ -+ */ -+ -+/** -+Overview -+ -+The VA API is intended to provide an interface between a video decode/encode/processing -+application (client) and a hardware accelerator (server), to off-load -+video decode/encode/processing operations from the host to the hardware accelerator at various -+entry-points. -+ -+The basic operation steps are: -+ -+- Negotiate a mutually acceptable configuration with the server to lock -+ down profile, entrypoints, and other attributes that will not change on -+ a frame-by-frame basis. -+- Create a video decode, encode or processing context which represents a -+ "virtualized" hardware device -+- Get and fill the render buffers with the corresponding data (depending on -+ profiles and entrypoints) -+- Pass the render buffers to the server to handle the current frame -+ -+Initialization & Configuration Management -+ -+- Find out supported profiles -+- Find out entrypoints for a given profile -+- Find out configuration attributes for a given profile/entrypoint pair -+- Create a configuration for use by the application -+ -+*/ -+ -+typedef void* VADisplay; /* window system dependent */ -+ -+typedef int VAStatus; /** Return status type from functions */ -+/** Values for the return status */ -+#define VA_STATUS_SUCCESS 0x00000000 -+#define VA_STATUS_ERROR_OPERATION_FAILED 0x00000001 -+#define VA_STATUS_ERROR_ALLOCATION_FAILED 0x00000002 -+#define VA_STATUS_ERROR_INVALID_DISPLAY 0x00000003 -+#define VA_STATUS_ERROR_INVALID_CONFIG 0x00000004 -+#define VA_STATUS_ERROR_INVALID_CONTEXT 0x00000005 -+#define VA_STATUS_ERROR_INVALID_SURFACE 0x00000006 -+#define VA_STATUS_ERROR_INVALID_BUFFER 0x00000007 -+#define VA_STATUS_ERROR_INVALID_IMAGE 0x00000008 -+#define VA_STATUS_ERROR_INVALID_SUBPICTURE 0x00000009 -+#define VA_STATUS_ERROR_ATTR_NOT_SUPPORTED 0x0000000a -+#define VA_STATUS_ERROR_MAX_NUM_EXCEEDED 0x0000000b -+#define VA_STATUS_ERROR_UNSUPPORTED_PROFILE 0x0000000c -+#define VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT 0x0000000d -+#define VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT 0x0000000e -+#define VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE 0x0000000f -+#define VA_STATUS_ERROR_SURFACE_BUSY 0x00000010 -+#define VA_STATUS_ERROR_FLAG_NOT_SUPPORTED 0x00000011 -+#define VA_STATUS_ERROR_INVALID_PARAMETER 0x00000012 -+#define VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED 0x00000013 -+#define VA_STATUS_ERROR_UNIMPLEMENTED 0x00000014 -+#define VA_STATUS_ERROR_SURFACE_IN_DISPLAYING 0x00000015 -+#define VA_STATUS_ERROR_INVALID_IMAGE_FORMAT 0x00000016 -+#define VA_STATUS_ERROR_DECODING_ERROR 0x00000017 -+#define VA_STATUS_ERROR_ENCODING_ERROR 0x00000018 -+/** -+ * \brief An invalid/unsupported value was supplied. -+ * -+ * This is a catch-all error code for invalid or unsupported values. -+ * e.g. value exceeding the valid range, invalid type in the context -+ * of generic attribute values. -+ */ -+#define VA_STATUS_ERROR_INVALID_VALUE 0x00000019 -+/** \brief An unsupported filter was supplied. */ -+#define VA_STATUS_ERROR_UNSUPPORTED_FILTER 0x00000020 -+/** \brief An invalid filter chain was supplied. */ -+#define VA_STATUS_ERROR_INVALID_FILTER_CHAIN 0x00000021 -+/** \brief Indicate HW busy (e.g. run multiple encoding simultaneously). */ -+#define VA_STATUS_ERROR_HW_BUSY 0x00000022 -+/** \brief An unsupported memory type was supplied. */ -+#define VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE 0x00000024 -+/** \brief Indicate allocated buffer size is not enough for input or output. */ -+#define VA_STATUS_ERROR_NOT_ENOUGH_BUFFER 0x00000025 -+#define VA_STATUS_ERROR_UNKNOWN 0xFFFFFFFF -+ -+/** -+ * 1. De-interlacing flags for vaPutSurface() -+ * 2. Surface sample type for input/output surface flag -+ * - Progressive: VA_FRAME_PICTURE -+ * - Interleaved: VA_TOP_FIELD_FIRST, VA_BOTTOM_FIELD_FIRST -+ * - Field: VA_TOP_FIELD, VA_BOTTOM_FIELD -+*/ -+#define VA_FRAME_PICTURE 0x00000000 -+#define VA_TOP_FIELD 0x00000001 -+#define VA_BOTTOM_FIELD 0x00000002 -+#define VA_TOP_FIELD_FIRST 0x00000004 -+#define VA_BOTTOM_FIELD_FIRST 0x00000008 -+ -+/** -+ * Enabled the positioning/cropping/blending feature: -+ * 1, specify the video playback position in the isurface -+ * 2, specify the cropping info for video playback -+ * 3, encoded video will blend with background color -+ */ -+#define VA_ENABLE_BLEND 0x00000004 /* video area blend with the constant color */ -+ -+/** -+ * Clears the drawable with background color. -+ * for hardware overlay based implementation this flag -+ * can be used to turn off the overlay -+ */ -+#define VA_CLEAR_DRAWABLE 0x00000008 -+ -+/** Color space conversion flags for vaPutSurface() */ -+#define VA_SRC_COLOR_MASK 0x000000f0 -+#define VA_SRC_BT601 0x00000010 -+#define VA_SRC_BT709 0x00000020 -+#define VA_SRC_SMPTE_240 0x00000040 -+ -+/** Scaling flags for vaPutSurface() */ -+#define VA_FILTER_SCALING_DEFAULT 0x00000000 -+#define VA_FILTER_SCALING_FAST 0x00000100 -+#define VA_FILTER_SCALING_HQ 0x00000200 -+#define VA_FILTER_SCALING_NL_ANAMORPHIC 0x00000300 -+#define VA_FILTER_SCALING_MASK 0x00000f00 -+ -+/** Padding size in 4-bytes */ -+#define VA_PADDING_LOW 4 -+#define VA_PADDING_MEDIUM 8 -+#define VA_PADDING_HIGH 16 -+#define VA_PADDING_LARGE 32 -+ -+/** -+ * Returns a short english description of error_status -+ */ -+const char *vaErrorStr(VAStatus error_status); -+ -+typedef struct _VARectangle -+{ -+ int16_t x; -+ int16_t y; -+ uint16_t width; -+ uint16_t height; -+} VARectangle; -+ -+/** \brief Generic motion vector data structure. */ -+typedef struct _VAMotionVector { -+ /** \mv0[0]: horizontal motion vector for past reference */ -+ /** \mv0[1]: vertical motion vector for past reference */ -+ /** \mv1[0]: horizontal motion vector for future reference */ -+ /** \mv1[1]: vertical motion vector for future reference */ -+ int16_t mv0[2]; /* past reference */ -+ int16_t mv1[2]; /* future reference */ -+} VAMotionVector; -+ -+/** Type of a message callback, used for both error and info log. */ -+typedef void (*VAMessageCallback)(void *user_context, const char *message); -+ -+/** -+ * Set the callback for error messages, or NULL for no logging. -+ * Returns the previous one, or NULL if it was disabled. -+ */ -+VAMessageCallback vaSetErrorCallback(VADisplay dpy, VAMessageCallback callback, void *user_context); -+ -+/** -+ * Set the callback for info messages, or NULL for no logging. -+ * Returns the previous one, or NULL if it was disabled. -+ */ -+VAMessageCallback vaSetInfoCallback(VADisplay dpy, VAMessageCallback callback, void *user_context); -+ -+/** -+ * Initialization: -+ * A display must be obtained by calling vaGetDisplay() before calling -+ * vaInitialize() and other functions. This connects the API to the -+ * native window system. -+ * For X Windows, native_dpy would be from XOpenDisplay() -+ */ -+typedef void* VANativeDisplay; /* window system dependent */ -+ -+int vaDisplayIsValid(VADisplay dpy); -+ -+/** -+ * Set the override driver name instead of queried driver driver. -+ */ -+VAStatus vaSetDriverName(VADisplay dpy, -+ char *driver_name -+); -+ -+/** -+ * Initialize the library -+ */ -+VAStatus vaInitialize ( -+ VADisplay dpy, -+ int *major_version, /* out */ -+ int *minor_version /* out */ -+); -+ -+/** -+ * After this call, all library internal resources will be cleaned up -+ */ -+VAStatus vaTerminate ( -+ VADisplay dpy -+); -+ -+/** -+ * vaQueryVendorString returns a pointer to a zero-terminated string -+ * describing some aspects of the VA implemenation on a specific -+ * hardware accelerator. The format of the returned string is vendor -+ * specific and at the discretion of the implementer. -+ * e.g. for the Intel GMA500 implementation, an example would be: -+ * "Intel GMA500 - 2.0.0.32L.0005" -+ */ -+const char *vaQueryVendorString ( -+ VADisplay dpy -+); -+ -+typedef int (*VAPrivFunc)(void); -+ -+/** -+ * Return a function pointer given a function name in the library. -+ * This allows private interfaces into the library -+ */ -+VAPrivFunc vaGetLibFunc ( -+ VADisplay dpy, -+ const char *func -+); -+ -+/** Currently defined profiles */ -+typedef enum -+{ -+ /** \brief Profile ID used for video processing. */ -+ VAProfileNone = -1, -+ VAProfileMPEG2Simple = 0, -+ VAProfileMPEG2Main = 1, -+ VAProfileMPEG4Simple = 2, -+ VAProfileMPEG4AdvancedSimple = 3, -+ VAProfileMPEG4Main = 4, -+ VAProfileH264Baseline va_deprecated_enum = 5, -+ VAProfileH264Main = 6, -+ VAProfileH264High = 7, -+ VAProfileVC1Simple = 8, -+ VAProfileVC1Main = 9, -+ VAProfileVC1Advanced = 10, -+ VAProfileH263Baseline = 11, -+ VAProfileJPEGBaseline = 12, -+ VAProfileH264ConstrainedBaseline = 13, -+ VAProfileVP8Version0_3 = 14, -+ VAProfileH264MultiviewHigh = 15, -+ VAProfileH264StereoHigh = 16, -+ VAProfileHEVCMain = 17, -+ VAProfileHEVCMain10 = 18, -+ VAProfileVP9Profile0 = 19, -+ VAProfileVP9Profile1 = 20, -+ VAProfileVP9Profile2 = 21, -+ VAProfileVP9Profile3 = 22, -+ VAProfileHEVCMain12 = 23, -+ VAProfileHEVCMain422_10 = 24, -+ VAProfileHEVCMain422_12 = 25, -+ VAProfileHEVCMain444 = 26, -+ VAProfileHEVCMain444_10 = 27, -+ VAProfileHEVCMain444_12 = 28, -+ VAProfileHEVCSccMain = 29, -+ VAProfileHEVCSccMain10 = 30, -+ VAProfileHEVCSccMain444 = 31 -+} VAProfile; -+ -+/** -+ * Currently defined entrypoints -+ */ -+typedef enum -+{ -+ VAEntrypointVLD = 1, -+ VAEntrypointIZZ = 2, -+ VAEntrypointIDCT = 3, -+ VAEntrypointMoComp = 4, -+ VAEntrypointDeblocking = 5, -+ VAEntrypointEncSlice = 6, /* slice level encode */ -+ VAEntrypointEncPicture = 7, /* pictuer encode, JPEG, etc */ -+ /* -+ * For an implementation that supports a low power/high performance variant -+ * for slice level encode, it can choose to expose the -+ * VAEntrypointEncSliceLP entrypoint. Certain encoding tools may not be -+ * available with this entrypoint (e.g. interlace, MBAFF) and the -+ * application can query the encoding configuration attributes to find -+ * out more details if this entrypoint is supported. -+ */ -+ VAEntrypointEncSliceLP = 8, -+ VAEntrypointVideoProc = 10, /**< Video pre/post-processing. */ -+ /** -+ * \brief VAEntrypointFEI -+ * -+ * The purpose of FEI (Flexible Encoding Infrastructure) is to allow applications to -+ * have more controls and trade off quality for speed with their own IPs. -+ * The application can optionally provide input to ENC for extra encode control -+ * and get the output from ENC. Application can chose to modify the ENC -+ * output/PAK input during encoding, but the performance impact is significant. -+ * -+ * On top of the existing buffers for normal encode, there will be -+ * one extra input buffer (VAEncMiscParameterFEIFrameControl) and -+ * three extra output buffers (VAEncFEIMVBufferType, VAEncFEIMBModeBufferType -+ * and VAEncFEIDistortionBufferType) for VAEntrypointFEI entry function. -+ * If separate PAK is set, two extra input buffers -+ * (VAEncFEIMVBufferType, VAEncFEIMBModeBufferType) are needed for PAK input. -+ **/ -+ VAEntrypointFEI = 11, -+ /** -+ * \brief VAEntrypointStats -+ * -+ * A pre-processing function for getting some statistics and motion vectors is added, -+ * and some extra controls for Encode pipeline are provided. The application can -+ * optionally call the statistics function to get motion vectors and statistics like -+ * variances, distortions before calling Encode function via this entry point. -+ * -+ * Checking whether Statistics is supported can be performed with vaQueryConfigEntrypoints(). -+ * If Statistics entry point is supported, then the list of returned entry-points will -+ * include #VAEntrypointStats. Supported pixel format, maximum resolution and statistics -+ * specific attributes can be obtained via normal attribute query. One input buffer -+ * (VAStatsStatisticsParameterBufferType) and one or two output buffers -+ * (VAStatsStatisticsBufferType, VAStatsStatisticsBottomFieldBufferType (for interlace only) -+ * and VAStatsMVBufferType) are needed for this entry point. -+ **/ -+ VAEntrypointStats = 12, -+} VAEntrypoint; -+ -+/** Currently defined configuration attribute types */ -+typedef enum -+{ -+ VAConfigAttribRTFormat = 0, -+ VAConfigAttribSpatialResidual = 1, -+ VAConfigAttribSpatialClipping = 2, -+ VAConfigAttribIntraResidual = 3, -+ VAConfigAttribEncryption = 4, -+ VAConfigAttribRateControl = 5, -+ -+ /** @name Attributes for decoding */ -+ /**@{*/ -+ /** -+ * \brief Slice Decoding mode. Read/write. -+ * -+ * This attribute determines what mode the driver supports for slice -+ * decoding, through vaGetConfigAttributes(); and what mode the user -+ * will be providing to the driver, through vaCreateConfig(), if the -+ * driver supports those. If this attribute is not set by the user then -+ * it is assumed that VA_DEC_SLICE_MODE_NORMAL mode is used. -+ * -+ * See \c VA_DEC_SLICE_MODE_xxx for the list of slice decoding modes. -+ */ -+ VAConfigAttribDecSliceMode = 6, -+ /** -+ * \brief JPEG decoding attribute. Read-only. -+ * -+ * This attribute exposes a number of capabilities of the underlying -+ * JPEG implementation. The attribute value is partitioned into fields as defined in the -+ * VAConfigAttribValDecJPEG union. -+ */ -+ VAConfigAttribDecJPEG = 7, -+ /** -+ * \brief Decode processing support. Read/write. -+ * -+ * This attribute determines if the driver supports video processing -+ * with decoding using the decoding context in a single call, through -+ * vaGetConfigAttributes(); and if the user may use this feature, -+ * through vaCreateConfig(), if the driver supports the user scenario. -+ * The user will essentially create a regular decode VAContext. Therefore, -+ * the parameters of vaCreateContext() such as picture_width, picture_height -+ * and render_targets are in relation to the decode output parameters -+ * (not processing output parameters) as normal. -+ * If this attribute is not set by the user then it is assumed that no -+ * extra processing is done after decoding for this decode context. -+ * -+ * Since essentially the application is creating a decoder config and context, -+ * all function calls that take in the config (e.g. vaQuerySurfaceAttributes()) -+ * or context are in relation to the decoder, except those video processing -+ * function specified in the next paragraph. -+ * -+ * Once the decode config and context are created, the user must further -+ * query the supported processing filters using vaQueryVideoProcFilters(), -+ * vaQueryVideoProcFilterCaps(), vaQueryVideoProcPipelineCaps() by specifying -+ * the created decode context. The user must provide processing information -+ * and extra processing output surfaces as "additional_outputs" to the driver -+ * through VAProcPipelineParameterBufferType. The render_target specified -+ * at vaBeginPicture() time refers to the decode output surface. The -+ * target surface for the output of processing needs to be a different -+ * surface since the decode process requires the original reconstructed buffer. -+ * The “surface” member of VAProcPipelineParameterBuffer should be set to the -+ * same as “render_target” set in vaBeginPicture(), but the driver may choose -+ * to ignore this parameter. -+ */ -+ VAConfigAttribDecProcessing = 8, -+ /** @name Attributes for encoding */ -+ /**@{*/ -+ /** -+ * \brief Packed headers mode. Read/write. -+ * -+ * This attribute determines what packed headers the driver supports, -+ * through vaGetConfigAttributes(); and what packed headers the user -+ * will be providing to the driver, through vaCreateConfig(), if the -+ * driver supports those. -+ * -+ * See \c VA_ENC_PACKED_HEADER_xxx for the list of packed headers. -+ */ -+ VAConfigAttribEncPackedHeaders = 10, -+ /** -+ * \brief Interlaced mode. Read/write. -+ * -+ * This attribute determines what kind of interlaced encoding mode -+ * the driver supports. -+ * -+ * See \c VA_ENC_INTERLACED_xxx for the list of interlaced modes. -+ */ -+ VAConfigAttribEncInterlaced = 11, -+ /** -+ * \brief Maximum number of reference frames. Read-only. -+ * -+ * This attribute determines the maximum number of reference -+ * frames supported for encoding. -+ * -+ * Note: for H.264 encoding, the value represents the maximum number -+ * of reference frames for both the reference picture list 0 (bottom -+ * 16 bits) and the reference picture list 1 (top 16 bits). -+ */ -+ VAConfigAttribEncMaxRefFrames = 13, -+ /** -+ * \brief Maximum number of slices per frame. Read-only. -+ * -+ * This attribute determines the maximum number of slices the -+ * driver can support to encode a single frame. -+ */ -+ VAConfigAttribEncMaxSlices = 14, -+ /** -+ * \brief Slice structure. Read-only. -+ * -+ * This attribute determines slice structures supported by the -+ * driver for encoding. This attribute is a hint to the user so -+ * that he can choose a suitable surface size and how to arrange -+ * the encoding process of multiple slices per frame. -+ * -+ * More specifically, for H.264 encoding, this attribute -+ * determines the range of accepted values to -+ * VAEncSliceParameterBufferH264::macroblock_address and -+ * VAEncSliceParameterBufferH264::num_macroblocks. -+ * -+ * See \c VA_ENC_SLICE_STRUCTURE_xxx for the supported slice -+ * structure types. -+ */ -+ VAConfigAttribEncSliceStructure = 15, -+ /** -+ * \brief Macroblock information. Read-only. -+ * -+ * This attribute determines whether the driver supports extra -+ * encoding information per-macroblock. e.g. QP. -+ * -+ * More specifically, for H.264 encoding, if the driver returns a non-zero -+ * value for this attribute, this means the application can create -+ * additional #VAEncMacroblockParameterBufferH264 buffers referenced -+ * through VAEncSliceParameterBufferH264::macroblock_info. -+ */ -+ VAConfigAttribEncMacroblockInfo = 16, -+ /** -+ * \brief Maximum picture width. Read-only. -+ * -+ * This attribute determines the maximum picture width the driver supports -+ * for a given configuration. -+ */ -+ VAConfigAttribMaxPictureWidth = 18, -+ /** -+ * \brief Maximum picture height. Read-only. -+ * -+ * This attribute determines the maximum picture height the driver supports -+ * for a given configuration. -+ */ -+ VAConfigAttribMaxPictureHeight = 19, -+ /** -+ * \brief JPEG encoding attribute. Read-only. -+ * -+ * This attribute exposes a number of capabilities of the underlying -+ * JPEG implementation. The attribute value is partitioned into fields as defined in the -+ * VAConfigAttribValEncJPEG union. -+ */ -+ VAConfigAttribEncJPEG = 20, -+ /** -+ * \brief Encoding quality range attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports different quality level settings -+ * for encoding. A value less than or equal to 1 means that the encoder only has a single -+ * quality setting, and a value greater than 1 represents the number of quality levels -+ * that can be configured. e.g. a value of 2 means there are two distinct quality levels. -+ */ -+ VAConfigAttribEncQualityRange = 21, -+ /** -+ * \brief Encoding quantization attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports certain types of quantization methods -+ * for encoding (e.g. trellis). See \c VA_ENC_QUANTIZATION_xxx for the list of quantization methods -+ */ -+ VAConfigAttribEncQuantization = 22, -+ /** -+ * \brief Encoding intra refresh attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports certain types of intra refresh methods -+ * for encoding (e.g. adaptive intra refresh or rolling intra refresh). -+ * See \c VA_ENC_INTRA_REFRESH_xxx for intra refresh methods -+ */ -+ VAConfigAttribEncIntraRefresh = 23, -+ /** -+ * \brief Encoding skip frame attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports sending skip frame parameters -+ * (VAEncMiscParameterTypeSkipFrame) to the encoder's rate control, when the user has -+ * externally skipped frames. -+ */ -+ VAConfigAttribEncSkipFrame = 24, -+ /** -+ * \brief Encoding region-of-interest (ROI) attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports region-of-interest (ROI) encoding, -+ * based on user provided ROI rectangles. The attribute value is partitioned into fields -+ * as defined in the VAConfigAttribValEncROI union. -+ * -+ * If ROI encoding is supported, the ROI information is passed to the driver using -+ * VAEncMiscParameterTypeROI. -+ */ -+ VAConfigAttribEncROI = 25, -+ /** -+ * \brief Encoding extended rate control attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports any extended rate control features -+ * The attribute value is partitioned into fields as defined in the -+ * VAConfigAttribValEncRateControlExt union. -+ */ -+ VAConfigAttribEncRateControlExt = 26, -+ /** -+ * \brief Processing rate reporting attribute. Read-only. -+ * -+ * This attribute conveys whether the driver supports reporting of -+ * encode/decode processing rate based on certain set of parameters -+ * (i.e. levels, I frame internvals) for a given configuration. -+ * If this is supported, vaQueryProcessingRate() can be used to get -+ * encode or decode processing rate. -+ * See \c VA_PROCESSING_RATE_xxx for encode/decode processing rate -+ */ -+ VAConfigAttribProcessingRate = 27, -+ /** -+ * \brief Encoding dirty rectangle. Read-only. -+ * -+ * This attribute conveys whether the driver supports dirty rectangle. -+ * encoding, based on user provided ROI rectangles which indicate the rectangular areas -+ * where the content has changed as compared to the previous picture. The regions of the -+ * picture that are not covered by dirty rect rectangles are assumed to have not changed -+ * compared to the previous picture. The encoder may do some optimizations based on -+ * this information. The attribute value returned indicates the number of regions that -+ * are supported. e.g. A value of 0 means dirty rect encoding is not supported. If dirty -+ * rect encoding is supported, the ROI information is passed to the driver using -+ * VAEncMiscParameterTypeDirtyRect. -+ */ -+ VAConfigAttribEncDirtyRect = 28, -+ /** -+ * \brief Parallel Rate Control (hierachical B) attribute. Read-only. -+ * -+ * This attribute conveys whether the encoder supports parallel rate control. -+ * It is a integer value 0 - unsupported, > 0 - maximum layer supported. -+ * This is the way when hireachical B frames are encoded, multiple independent B frames -+ * on the same layer may be processed at same time. If supported, app may enable it by -+ * setting enable_parallel_brc in VAEncMiscParameterRateControl,and the number of B frames -+ * per layer per GOP will be passed to driver through VAEncMiscParameterParallelRateControl -+ * structure.Currently three layers are defined. -+ */ -+ VAConfigAttribEncParallelRateControl = 29, -+ /** -+ * \brief Dynamic Scaling Attribute. Read-only. -+ * -+ * This attribute conveys whether encoder is capable to determine dynamic frame -+ * resolutions adaptive to bandwidth utilization and processing power, etc. -+ * It is a boolean value 0 - unsupported, 1 - supported. -+ * If it is supported,for VP9, suggested frame resolution can be retrieved from VACodedBufferVP9Status. -+ */ -+ VAConfigAttribEncDynamicScaling = 30, -+ /** -+ * \brief frame size tolerance support -+ * it indicates the tolerance of frame size -+ */ -+ VAConfigAttribFrameSizeToleranceSupport = 31, -+ /** -+ * \brief Encode function type for FEI. -+ * -+ * This attribute conveys whether the driver supports different function types for encode. -+ * It can be VA_FEI_FUNCTION_ENC, VA_FEI_FUNCTION_PAK, or VA_FEI_FUNCTION_ENC_PAK. Currently -+ * it is for FEI entry point only. -+ * Default is VA_FEI_FUNCTION_ENC_PAK. -+ */ -+ VAConfigAttribFEIFunctionType = 32, -+ /** -+ * \brief Maximum number of FEI MV predictors. Read-only. -+ * -+ * This attribute determines the maximum number of MV predictors the driver -+ * can support to encode a single frame. 0 means no MV predictor is supported. -+ * Currently it is for FEI entry point only. -+ */ -+ VAConfigAttribFEIMVPredictors = 33, -+ /** -+ * \brief Statistics attribute. Read-only. -+ * -+ * This attribute exposes a number of capabilities of the VAEntrypointStats entry -+ * point. The attribute value is partitioned into fields as defined in the -+ * VAConfigAttribValStats union. Currently it is for VAEntrypointStats only. -+ */ -+ VAConfigAttribStats = 34, -+ /** -+ * \brief Tile Support Attribute. Read-only. -+ * -+ * This attribute conveys whether encoder is capable to support tiles. -+ * If not supported, the tile related parameters sent to encoder, such as -+ * tiling structure, should be ignored. 0 - unsupported, 1 - supported. -+ */ -+ VAConfigAttribEncTileSupport = 35, -+ /** -+ * \brief whether accept rouding setting from application. Read-only. -+ * This attribute is for encode quality, if it is report, -+ * application can change the rounding setting by VAEncMiscParameterTypeCustomRoundingControl -+ */ -+ VAConfigAttribCustomRoundingControl = 36, -+ /** -+ * \brief Encoding QP info block size attribute. Read-only. -+ * This attribute conveys the block sizes that underlying driver -+ * support for QP info for buffer #VAEncQpBuffer. -+ */ -+ VAConfigAttribQPBlockSize = 37, -+ /** -+ * \brief encode max frame size attribute. Read-only -+ * attribute value \c VAConfigAttribValMaxFrameSize represent max frame size support -+ */ -+ VAConfigAttribMaxFrameSize = 38, -+ /** \brief inter frame prediction directrion attribute. Read-only. -+ * this attribute conveys the prediction direction (backward or forword) for specific config -+ * the value could be VA_PREDICTION_DIRECTION_XXXX. it can be combined with VAConfigAttribEncMaxRefFrames -+ * to describe reference list , and the prediction direction. if this attrib is not present,both direction -+ * should be supported, no restriction. -+ * for example: normal HEVC encoding , maximum reference frame number in reflist 0 and reflist 1 is deduced -+ * by VAConfigAttribEncMaxRefFrames. so there are typical P frame, B frame, -+ * if VAConfigAttribPredictionDirection is also present. it will stipulate prediction direction in both -+ * reference list. if only one prediction direction present(such as PREVIOUS),all reference frame should be -+ * previous frame (PoC < current). -+ */ -+ VAConfigAttribPredictionDirection = 39, -+ /** \brief combined submission of multiple frames from different streams, it is optimization for different HW -+ * implementation, multiple frames encode/decode can improve HW concurrency -+ */ -+ VAConfigAttribMultipleFrame = 40, -+ /**@}*/ -+ VAConfigAttribTypeMax -+} VAConfigAttribType; -+ -+/** -+ * Configuration attributes -+ * If there is more than one value for an attribute, a default -+ * value will be assigned to the attribute if the client does not -+ * specify the attribute when creating a configuration -+ */ -+typedef struct _VAConfigAttrib { -+ VAConfigAttribType type; -+ uint32_t value; /* OR'd flags (bits) for this attribute */ -+} VAConfigAttrib; -+ -+/* Attribute values for VAConfigAttribRTFormat. */ -+ -+#define VA_RT_FORMAT_YUV420 0x00000001 ///< YUV 4:2:0 8-bit. -+#define VA_RT_FORMAT_YUV422 0x00000002 ///< YUV 4:2:2 8-bit. -+#define VA_RT_FORMAT_YUV444 0x00000004 ///< YUV 4:4:4 8-bit. -+#define VA_RT_FORMAT_YUV411 0x00000008 ///< YUV 4:1:1 8-bit. -+#define VA_RT_FORMAT_YUV400 0x00000010 ///< Greyscale 8-bit. -+#define VA_RT_FORMAT_YUV420_10 0x00000100 ///< YUV 4:2:0 10-bit. -+#define VA_RT_FORMAT_YUV422_10 0x00000200 ///< YUV 4:2:2 10-bit. -+#define VA_RT_FORMAT_YUV444_10 0x00000400 ///< YUV 4:4:4 10-bit. -+#define VA_RT_FORMAT_YUV420_12 0x00001000 ///< YUV 4:2:0 12-bit. -+#define VA_RT_FORMAT_YUV422_12 0x00002000 ///< YUV 4:2:2 12-bit. -+#define VA_RT_FORMAT_YUV444_12 0x00004000 ///< YUV 4:4:4 12-bit. -+ -+#define VA_RT_FORMAT_RGB16 0x00010000 ///< Packed RGB, 16 bits per pixel. -+#define VA_RT_FORMAT_RGB32 0x00020000 ///< Packed RGB, 32 bits per pixel, 8 bits per colour sample. -+#define VA_RT_FORMAT_RGBP 0x00100000 ///< Planar RGB, 8 bits per sample. -+#define VA_RT_FORMAT_RGB32_10 0x00200000 ///< Packed RGB, 32 bits per pixel, 10 bits per colour sample. -+ -+#define VA_RT_FORMAT_PROTECTED 0x80000000 -+ -+#define VA_RT_FORMAT_RGB32_10BPP VA_RT_FORMAT_RGB32_10 ///< @deprecated use VA_RT_FORMAT_RGB32_10 instead. -+#define VA_RT_FORMAT_YUV420_10BPP VA_RT_FORMAT_YUV420_10 ///< @deprecated use VA_RT_FORMAT_YUV420_10 instead. -+ -+/** @name Attribute values for VAConfigAttribRateControl */ -+/**@{*/ -+/** \brief Driver does not support any form of rate control. */ -+#define VA_RC_NONE 0x00000001 -+/** \brief Constant bitrate. */ -+#define VA_RC_CBR 0x00000002 -+/** \brief Variable bitrate. */ -+#define VA_RC_VBR 0x00000004 -+/** \brief Video conference mode. */ -+#define VA_RC_VCM 0x00000008 -+/** \brief Constant QP. */ -+#define VA_RC_CQP 0x00000010 -+/** \brief Variable bitrate with peak rate higher than average bitrate. */ -+#define VA_RC_VBR_CONSTRAINED 0x00000020 -+/** \brief Intelligent Constant Quality. Provided an initial ICQ_quality_factor, -+ * adjusts QP at a frame and MB level based on motion to improve subjective quality. */ -+#define VA_RC_ICQ 0x00000040 -+/** \brief Macroblock based rate control. Per MB control is decided -+ * internally in the encoder. It may be combined with other RC modes, except CQP. */ -+#define VA_RC_MB 0x00000080 -+/** \brief Constant Frame Size, it is used for small tolerent */ -+#define VA_RC_CFS 0x00000100 -+/** \brief Parallel BRC, for hierachical B. -+ * -+ * For hierachical B, B frames can be refered by other B frames. -+ * Currently three layers of hierachy are defined: -+ * B0 - regular B, no reference to other B frames. -+ * B1 - reference to only I, P and regular B0 frames. -+ * B2 - reference to any other frames, including B1. -+ * In Hierachical B structure, B frames on the same layer can be processed -+ * simultaneously. And BRC would adjust accordingly. This is so called -+ * Parallel BRC. */ -+#define VA_RC_PARALLEL 0x00000200 -+/** \brief Quality defined VBR -+ * Use Quality factor to determine the good enough QP for each MB such that -+ * good enough quality can be obtained without waste of bits -+ * for this BRC mode, you must set all legacy VBR parameters -+ * and reuse quality_factor in \c VAEncMiscParameterRateControl -+ * */ -+#define VA_RC_QVBR 0x00000400 -+/** \brief Average VBR -+ * Average variable bitrate control algorithm focuses on overall encoding -+ * quality while meeting the specified target bitrate, within the accuracy -+ * range, after a convergence period. -+ * bits_per_second in VAEncMiscParameterRateControl is target bitrate for AVBR. -+ * Convergence is specified in the unit of frame. -+ * window_size in VAEncMiscParameterRateControl is equal to convergence for AVBR. -+ * Accuracy is in the range of [1,100], 1 means one percent, and so on. -+ * target_percentage in VAEncMiscParameterRateControl is equal to accuracy for AVBR. */ -+#define VA_RC_AVBR 0x00000800 -+ -+/**@}*/ -+ -+/** @name Attribute values for VAConfigAttribDecSliceMode */ -+/**@{*/ -+/** \brief Driver supports normal mode for slice decoding */ -+#define VA_DEC_SLICE_MODE_NORMAL 0x00000001 -+/** \brief Driver supports base mode for slice decoding */ -+#define VA_DEC_SLICE_MODE_BASE 0x00000002 -+ -+/** @name Attribute values for VAConfigAttribDecJPEG */ -+/**@{*/ -+typedef union _VAConfigAttribValDecJPEG { -+ struct { -+ /** \brief Set to (1 << VA_ROTATION_xxx) for supported rotation angles. */ -+ uint32_t rotation : 4; -+ /** \brief Reserved for future use. */ -+ uint32_t reserved : 28; -+ } bits; -+ uint32_t value; -+} VAConfigAttribValDecJPEG; -+/** @name Attribute values for VAConfigAttribDecProcessing */ -+/**@{*/ -+/** \brief No decoding + processing in a single decoding call. */ -+#define VA_DEC_PROCESSING_NONE 0x00000000 -+/** \brief Decode + processing in a single decoding call. */ -+#define VA_DEC_PROCESSING 0x00000001 -+/**@}*/ -+ -+/** @name Attribute values for VAConfigAttribEncPackedHeaders */ -+/**@{*/ -+/** \brief Driver does not support any packed headers mode. */ -+#define VA_ENC_PACKED_HEADER_NONE 0x00000000 -+/** -+ * \brief Driver supports packed sequence headers. e.g. SPS for H.264. -+ * -+ * Application must provide it to driver once this flag is returned through -+ * vaGetConfigAttributes() -+ */ -+#define VA_ENC_PACKED_HEADER_SEQUENCE 0x00000001 -+/** -+ * \brief Driver supports packed picture headers. e.g. PPS for H.264. -+ * -+ * Application must provide it to driver once this falg is returned through -+ * vaGetConfigAttributes() -+ */ -+#define VA_ENC_PACKED_HEADER_PICTURE 0x00000002 -+/** -+ * \brief Driver supports packed slice headers. e.g. slice_header() for H.264. -+ * -+ * Application must provide it to driver once this flag is returned through -+ * vaGetConfigAttributes() -+ */ -+#define VA_ENC_PACKED_HEADER_SLICE 0x00000004 -+/** -+ * \brief Driver supports misc packed headers. e.g. SEI for H.264. -+ * -+ * @deprecated -+ * This is a deprecated packed header flag, All applications can use -+ * \c VA_ENC_PACKED_HEADER_RAW_DATA to pass the corresponding packed -+ * header data buffer to the driver -+ */ -+#define VA_ENC_PACKED_HEADER_MISC 0x00000008 -+/** \brief Driver supports raw packed header, see VAEncPackedHeaderRawData */ -+#define VA_ENC_PACKED_HEADER_RAW_DATA 0x00000010 -+/**@}*/ -+ -+/** @name Attribute values for VAConfigAttribEncInterlaced */ -+/**@{*/ -+/** \brief Driver does not support interlaced coding. */ -+#define VA_ENC_INTERLACED_NONE 0x00000000 -+/** \brief Driver supports interlaced frame coding. */ -+#define VA_ENC_INTERLACED_FRAME 0x00000001 -+/** \brief Driver supports interlaced field coding. */ -+#define VA_ENC_INTERLACED_FIELD 0x00000002 -+/** \brief Driver supports macroblock adaptive frame field coding. */ -+#define VA_ENC_INTERLACED_MBAFF 0x00000004 -+/** \brief Driver supports picture adaptive frame field coding. */ -+#define VA_ENC_INTERLACED_PAFF 0x00000008 -+/**@}*/ -+ -+/** @name Attribute values for VAConfigAttribEncSliceStructure */ -+/**@{*/ -+/** \brief Driver supports a power-of-two number of rows per slice. */ -+#define VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS 0x00000001 -+/** \brief Driver supports an arbitrary number of macroblocks per slice. */ -+#define VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS 0x00000002 -+/** \brief Dirver support 1 rows per slice */ -+#define VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS 0x00000004 -+/** \brief Dirver support max encoded slice size per slice */ -+#define VA_ENC_SLICE_STRUCTURE_MAX_SLICE_SIZE 0x00000008 -+/** \brief Driver supports an arbitrary number of rows per slice. */ -+#define VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS 0x00000010 -+/**@}*/ -+ -+/** \brief Attribute value for VAConfigAttribMaxFrameSize */ -+typedef union _VAConfigAttribValMaxFrameSize { -+ struct { -+ /** \brief support max frame size -+ * if max_frame_size == 1, VAEncMiscParameterTypeMaxFrameSize/VAEncMiscParameterBufferMaxFrameSize -+ * could be used to set the frame size, if multiple_pass also equal 1, VAEncMiscParameterTypeMultiPassFrameSize -+ * VAEncMiscParameterBufferMultiPassFrameSize could be used to set frame size and pass information -+ */ -+ uint32_t max_frame_size : 1; -+ /** \brief multiple_pass support */ -+ uint32_t multiple_pass : 1; -+ /** \brief reserved bits for future, must be zero*/ -+ uint32_t reserved :30; -+ } bits; -+ uint32_t value; -+} VAConfigAttribValMaxFrameSize; -+ -+/** \brief Attribute value for VAConfigAttribEncJPEG */ -+typedef union _VAConfigAttribValEncJPEG { -+ struct { -+ /** \brief set to 1 for arithmatic coding. */ -+ uint32_t arithmatic_coding_mode : 1; -+ /** \brief set to 1 for progressive dct. */ -+ uint32_t progressive_dct_mode : 1; -+ /** \brief set to 1 for non-interleaved. */ -+ uint32_t non_interleaved_mode : 1; -+ /** \brief set to 1 for differential. */ -+ uint32_t differential_mode : 1; -+ uint32_t max_num_components : 3; -+ uint32_t max_num_scans : 4; -+ uint32_t max_num_huffman_tables : 3; -+ uint32_t max_num_quantization_tables : 3; -+ } bits; -+ uint32_t value; -+} VAConfigAttribValEncJPEG; -+ -+/** @name Attribute values for VAConfigAttribEncQuantization */ -+/**@{*/ -+/** \brief Driver does not support special types of quantization */ -+#define VA_ENC_QUANTIZATION_NONE 0x00000000 -+/** \brief Driver supports trellis quantization */ -+#define VA_ENC_QUANTIZATION_TRELLIS_SUPPORTED 0x00000001 -+/**@}*/ -+ -+/** @name Attribute values for VAConfigAttribPredictionDirection */ -+/**@{*/ -+/** \brief Driver support forward reference frame (inter frame for vpx, P frame for H26x MPEG) -+ * can work with the VAConfigAttribEncMaxRefFrames. for example: low delay B frame of HEVC. -+ * these value can be OR'd together. typical value should be VA_PREDICTION_DIRECTION_PREVIOUS -+ * or VA_PREDICTION_DIRECTION_PREVIOUS | VA_PREDICTION_DIRECTION_FUTURE, theoretically, there -+ * are no stream only include future reference frame. -+ */ -+#define VA_PREDICTION_DIRECTION_PREVIOUS 0x00000001 -+/** \brief Driver support backward prediction frame/slice */ -+#define VA_PREDICTION_DIRECTION_FUTURE 0x00000002 -+/**@}*/ -+ -+/** @name Attribute values for VAConfigAttribEncIntraRefresh */ -+/**@{*/ -+/** \brief Driver does not support intra refresh */ -+#define VA_ENC_INTRA_REFRESH_NONE 0x00000000 -+/** \brief Driver supports column based rolling intra refresh */ -+#define VA_ENC_INTRA_REFRESH_ROLLING_COLUMN 0x00000001 -+/** \brief Driver supports row based rolling intra refresh */ -+#define VA_ENC_INTRA_REFRESH_ROLLING_ROW 0x00000002 -+/** \brief Driver supports adaptive intra refresh */ -+#define VA_ENC_INTRA_REFRESH_ADAPTIVE 0x00000010 -+/** \brief Driver supports cyclic intra refresh */ -+#define VA_ENC_INTRA_REFRESH_CYCLIC 0x00000020 -+/** \brief Driver supports intra refresh of P frame*/ -+#define VA_ENC_INTRA_REFRESH_P_FRAME 0x00010000 -+/** \brief Driver supports intra refresh of B frame */ -+#define VA_ENC_INTRA_REFRESH_B_FRAME 0x00020000 -+/** \brief Driver supports intra refresh of multiple reference encoder */ -+#define VA_ENC_INTRA_REFRESH_MULTI_REF 0x00040000 -+ -+/**@}*/ -+ -+/** \brief Attribute value for VAConfigAttribEncROI */ -+typedef union _VAConfigAttribValEncROI { -+ struct { -+ /** \brief The number of ROI regions supported, 0 if ROI is not supported. */ -+ uint32_t num_roi_regions : 8; -+ /** -+ * \brief A flag indicates whether ROI priority is supported -+ * -+ * \ref roi_rc_priority_support equal to 1 specifies the underlying driver supports -+ * ROI priority when VAConfigAttribRateControl != VA_RC_CQP, user can use \c roi_value -+ * in #VAEncROI to set ROI priority. \ref roi_rc_priority_support equal to 0 specifies -+ * the underlying driver doesn't support ROI priority. -+ * -+ * User should ignore \ref roi_rc_priority_support when VAConfigAttribRateControl == VA_RC_CQP -+ * because ROI delta QP is always required when VAConfigAttribRateControl == VA_RC_CQP. -+ */ -+ uint32_t roi_rc_priority_support : 1; -+ /** -+ * \brief A flag indicates whether ROI delta QP is supported -+ * -+ * \ref roi_rc_qp_delta_support equal to 1 specifies the underlying driver supports -+ * ROI delta QP when VAConfigAttribRateControl != VA_RC_CQP, user can use \c roi_value -+ * in #VAEncROI to set ROI delta QP. \ref roi_rc_qp_delta_support equal to 0 specifies -+ * the underlying driver doesn't support ROI delta QP. -+ * -+ * User should ignore \ref roi_rc_qp_delta_support when VAConfigAttribRateControl == VA_RC_CQP -+ * because ROI delta QP is always required when VAConfigAttribRateControl == VA_RC_CQP. -+ */ -+ uint32_t roi_rc_qp_delta_support : 1; -+ uint32_t reserved : 22; -+ } bits; -+ uint32_t value; -+} VAConfigAttribValEncROI; -+ -+/** \brief Attribute value for VAConfigAttribEncRateControlExt */ -+typedef union _VAConfigAttribValEncRateControlExt { -+ struct { -+ /** -+ * \brief The maximum number of temporal layers minus 1 -+ * -+ * \ref max_num_temporal_layers_minus1 plus 1 specifies the maximum number of temporal -+ * layers that supported by the underlying driver. \ref max_num_temporal_layers_minus1 -+ * equal to 0 implies the underlying driver doesn't support encoding with temporal layer. -+ */ -+ uint32_t max_num_temporal_layers_minus1 : 8; -+ -+ /** -+ * /brief support temporal layer bit-rate control flag -+ * -+ * \ref temporal_layer_bitrate_control_flag equal to 1 specifies the underlying driver -+ * can support bit-rate control per temporal layer when (#VAConfigAttribRateControl == #VA_RC_CBR || -+ * #VAConfigAttribRateControl == #VA_RC_VBR). -+ * -+ * The underlying driver must set \ref temporal_layer_bitrate_control_flag to 0 when -+ * \c max_num_temporal_layers_minus1 is equal to 0 -+ * -+ * To use bit-rate control per temporal layer, an application must send the right layer -+ * structure via #VAEncMiscParameterTemporalLayerStructure at the beginning of a coded sequence -+ * and then followed by #VAEncMiscParameterRateControl and #VAEncMiscParameterFrameRate structures -+ * for each layer, using the \c temporal_id field as the layer identifier. Otherwise -+ * the driver doesn't use bitrate control per temporal layer if an application doesn't send the -+ * layer structure via #VAEncMiscParameterTemporalLayerStructure to the driver. The driver returns -+ * VA_STATUS_ERROR_INVALID_PARAMETER if an application sends a wrong layer structure or doesn't send -+ * #VAEncMiscParameterRateControl and #VAEncMiscParameterFrameRate for each layer. -+ * -+ * The driver will ignore #VAEncMiscParameterTemporalLayerStructure and the \c temporal_id field -+ * in #VAEncMiscParameterRateControl and #VAEncMiscParameterFrameRate if -+ * \ref temporal_layer_bitrate_control_flag is equal to 0 or #VAConfigAttribRateControl == #VA_RC_CQP -+ */ -+ uint32_t temporal_layer_bitrate_control_flag : 1; -+ uint32_t reserved : 23; -+ } bits; -+ uint32_t value; -+} VAConfigAttribValEncRateControlExt; -+ -+/** \brief Attribute value for VAConfigAttribMultipleFrame*/ -+typedef union _VAConfigAttribValMultipleFrame { -+ struct { -+ /** \brief max num of concurrent frames from different stream */ -+ uint32_t max_num_concurrent_frames : 8; -+ /** \brief indicate whether all stream must support same quality level -+ * if mixed_quality_level == 0, same quality level setting for multple streams is required -+ * if mixed_quality_level == 1, different stream can have different quality level*/ -+ uint32_t mixed_quality_level : 1; -+ /** \brief reserved bit for future, must be zero */ -+ uint32_t reserved : 23; -+ } bits; -+ uint32_t value; -+}VAConfigAttribValMultipleFrame; -+ -+/** @name Attribute values for VAConfigAttribProcessingRate. */ -+/**@{*/ -+/** \brief Driver does not support processing rate report */ -+#define VA_PROCESSING_RATE_NONE 0x00000000 -+/** \brief Driver supports encode processing rate report */ -+#define VA_PROCESSING_RATE_ENCODE 0x00000001 -+/** \brief Driver supports decode processing rate report */ -+#define VA_PROCESSING_RATE_DECODE 0x00000002 -+/**@}*/ -+/** -+ * if an attribute is not applicable for a given -+ * profile/entrypoint pair, then set the value to the following -+ */ -+#define VA_ATTRIB_NOT_SUPPORTED 0x80000000 -+ -+/** Get maximum number of profiles supported by the implementation */ -+int vaMaxNumProfiles ( -+ VADisplay dpy -+); -+ -+/** Get maximum number of entrypoints supported by the implementation */ -+int vaMaxNumEntrypoints ( -+ VADisplay dpy -+); -+ -+/** Get maximum number of attributs supported by the implementation */ -+int vaMaxNumConfigAttributes ( -+ VADisplay dpy -+); -+ -+/** -+ * Query supported profiles -+ * The caller must provide a "profile_list" array that can hold at -+ * least vaMaxNumProfile() entries. The actual number of profiles -+ * returned in "profile_list" is returned in "num_profile". -+ */ -+VAStatus vaQueryConfigProfiles ( -+ VADisplay dpy, -+ VAProfile *profile_list, /* out */ -+ int *num_profiles /* out */ -+); -+ -+/** -+ * Query supported entrypoints for a given profile -+ * The caller must provide an "entrypoint_list" array that can hold at -+ * least vaMaxNumEntrypoints() entries. The actual number of entrypoints -+ * returned in "entrypoint_list" is returned in "num_entrypoints". -+ */ -+VAStatus vaQueryConfigEntrypoints ( -+ VADisplay dpy, -+ VAProfile profile, -+ VAEntrypoint *entrypoint_list, /* out */ -+ int *num_entrypoints /* out */ -+); -+ -+/** -+ * Get attributes for a given profile/entrypoint pair -+ * The caller must provide an "attrib_list" with all attributes to be -+ * retrieved. Upon return, the attributes in "attrib_list" have been -+ * updated with their value. Unknown attributes or attributes that are -+ * not supported for the given profile/entrypoint pair will have their -+ * value set to VA_ATTRIB_NOT_SUPPORTED -+ */ -+VAStatus vaGetConfigAttributes ( -+ VADisplay dpy, -+ VAProfile profile, -+ VAEntrypoint entrypoint, -+ VAConfigAttrib *attrib_list, /* in/out */ -+ int num_attribs -+); -+ -+/** Generic ID type, can be re-typed for specific implementation */ -+typedef unsigned int VAGenericID; -+ -+typedef VAGenericID VAConfigID; -+ -+/** -+ * Create a configuration for the video decode/encode/processing pipeline -+ * it passes in the attribute list that specifies the attributes it cares -+ * about, with the rest taking default values. -+ */ -+VAStatus vaCreateConfig ( -+ VADisplay dpy, -+ VAProfile profile, -+ VAEntrypoint entrypoint, -+ VAConfigAttrib *attrib_list, -+ int num_attribs, -+ VAConfigID *config_id /* out */ -+); -+ -+/** -+ * Free resources associdated with a given config -+ */ -+VAStatus vaDestroyConfig ( -+ VADisplay dpy, -+ VAConfigID config_id -+); -+ -+/** -+ * Query all attributes for a given configuration -+ * The profile of the configuration is returned in "profile" -+ * The entrypoint of the configuration is returned in "entrypoint" -+ * The caller must provide an "attrib_list" array that can hold at least -+ * vaMaxNumConfigAttributes() entries. The actual number of attributes -+ * returned in "attrib_list" is returned in "num_attribs" -+ */ -+VAStatus vaQueryConfigAttributes ( -+ VADisplay dpy, -+ VAConfigID config_id, -+ VAProfile *profile, /* out */ -+ VAEntrypoint *entrypoint, /* out */ -+ VAConfigAttrib *attrib_list,/* out */ -+ int *num_attribs /* out */ -+); -+ -+ -+/** -+ * Contexts and Surfaces -+ * -+ * Context represents a "virtual" video decode, encode or video processing -+ * pipeline. Surfaces are render targets for a given context. The data in the -+ * surfaces are not accessible to the client except if derived image is supported -+ * and the internal data format of the surface is implementation specific. -+ * -+ * Surfaces are provided as a hint of what surfaces will be used when the context -+ * is created through vaCreateContext(). A surface may be used by different contexts -+ * at the same time as soon as application can make sure the operations are synchronized -+ * between different contexts, e.g. a surface is used as the output of a decode context -+ * and the input of a video process context. Surfaces can only be destroyed after all -+ * contexts using these surfaces have been destroyed. -+ * -+ * Both contexts and surfaces are identified by unique IDs and its -+ * implementation specific internals are kept opaque to the clients -+ */ -+ -+typedef VAGenericID VAContextID; -+ -+typedef VAGenericID VASurfaceID; -+ -+#define VA_INVALID_ID 0xffffffff -+#define VA_INVALID_SURFACE VA_INVALID_ID -+ -+/** \brief Generic value types. */ -+typedef enum { -+ VAGenericValueTypeInteger = 1, /**< 32-bit signed integer. */ -+ VAGenericValueTypeFloat, /**< 32-bit floating-point value. */ -+ VAGenericValueTypePointer, /**< Generic pointer type */ -+ VAGenericValueTypeFunc /**< Pointer to function */ -+} VAGenericValueType; -+ -+/** \brief Generic function type. */ -+typedef void (*VAGenericFunc)(void); -+ -+/** \brief Generic value. */ -+typedef struct _VAGenericValue { -+ /** \brief Value type. See #VAGenericValueType. */ -+ VAGenericValueType type; -+ /** \brief Value holder. */ -+ union { -+ /** \brief 32-bit signed integer. */ -+ int32_t i; -+ /** \brief 32-bit float. */ -+ float f; -+ /** \brief Generic pointer. */ -+ void *p; -+ /** \brief Pointer to function. */ -+ VAGenericFunc fn; -+ } value; -+} VAGenericValue; -+ -+/** @name Surface attribute flags */ -+/**@{*/ -+/** \brief Surface attribute is not supported. */ -+#define VA_SURFACE_ATTRIB_NOT_SUPPORTED 0x00000000 -+/** \brief Surface attribute can be got through vaQuerySurfaceAttributes(). */ -+#define VA_SURFACE_ATTRIB_GETTABLE 0x00000001 -+/** \brief Surface attribute can be set through vaCreateSurfaces(). */ -+#define VA_SURFACE_ATTRIB_SETTABLE 0x00000002 -+/**@}*/ -+ -+/** \brief Surface attribute types. */ -+typedef enum { -+ VASurfaceAttribNone = 0, -+ /** -+ * \brief Pixel format (fourcc). -+ * -+ * The value is meaningful as input to vaQuerySurfaceAttributes(). -+ * If zero, the driver returns the optimal pixel format for the -+ * specified config. Otherwise, if non-zero, the value represents -+ * a pixel format (FOURCC) that is kept as is on output, if the -+ * driver supports it. Otherwise, the driver sets the value to -+ * zero and drops the \c VA_SURFACE_ATTRIB_SETTABLE flag. -+ */ -+ VASurfaceAttribPixelFormat, -+ /** \brief Minimal width in pixels (int, read-only). */ -+ VASurfaceAttribMinWidth, -+ /** \brief Maximal width in pixels (int, read-only). */ -+ VASurfaceAttribMaxWidth, -+ /** \brief Minimal height in pixels (int, read-only). */ -+ VASurfaceAttribMinHeight, -+ /** \brief Maximal height in pixels (int, read-only). */ -+ VASurfaceAttribMaxHeight, -+ /** \brief Surface memory type expressed in bit fields (int, read/write). */ -+ VASurfaceAttribMemoryType, -+ /** \brief External buffer descriptor (pointer, write). -+ * -+ * Refer to the documentation for the memory type being created to -+ * determine what descriptor structure to pass here. If not otherwise -+ * stated, the common VASurfaceAttribExternalBuffers should be used. -+ */ -+ VASurfaceAttribExternalBufferDescriptor, -+ /** \brief Surface usage hint, gives the driver a hint of intended usage -+ * to optimize allocation (e.g. tiling) (int, read/write). */ -+ VASurfaceAttribUsageHint, -+ /** \brief Number of surface attributes. */ -+ VASurfaceAttribCount -+} VASurfaceAttribType; -+ -+/** \brief Surface attribute. */ -+typedef struct _VASurfaceAttrib { -+ /** \brief Type. */ -+ VASurfaceAttribType type; -+ /** \brief Flags. See "Surface attribute flags". */ -+ uint32_t flags; -+ /** \brief Value. See "Surface attribute types" for the expected types. */ -+ VAGenericValue value; -+} VASurfaceAttrib; -+ -+/** -+ * @name VASurfaceAttribMemoryType values in bit fields. -+ * Bit 0:7 are reserved for generic types, Bit 31:28 are reserved for -+ * Linux DRM, Bit 23:20 are reserved for Android. DRM and Android specific -+ * types are defined in DRM and Android header files. -+ */ -+/**@{*/ -+/** \brief VA memory type (default) is supported. */ -+#define VA_SURFACE_ATTRIB_MEM_TYPE_VA 0x00000001 -+/** \brief V4L2 buffer memory type is supported. */ -+#define VA_SURFACE_ATTRIB_MEM_TYPE_V4L2 0x00000002 -+/** \brief User pointer memory type is supported. */ -+#define VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR 0x00000004 -+/**@}*/ -+ -+/** -+ * \brief VASurfaceAttribExternalBuffers structure for -+ * the VASurfaceAttribExternalBufferDescriptor attribute. -+ */ -+typedef struct _VASurfaceAttribExternalBuffers { -+ /** \brief pixel format in fourcc. */ -+ uint32_t pixel_format; -+ /** \brief width in pixels. */ -+ uint32_t width; -+ /** \brief height in pixels. */ -+ uint32_t height; -+ /** \brief total size of the buffer in bytes. */ -+ uint32_t data_size; -+ /** \brief number of planes for planar layout */ -+ uint32_t num_planes; -+ /** \brief pitch for each plane in bytes */ -+ uint32_t pitches[4]; -+ /** \brief offset for each plane in bytes */ -+ uint32_t offsets[4]; -+ /** \brief buffer handles or user pointers */ -+ uintptr_t *buffers; -+ /** \brief number of elements in the "buffers" array */ -+ uint32_t num_buffers; -+ /** \brief flags. See "Surface external buffer descriptor flags". */ -+ uint32_t flags; -+ /** \brief reserved for passing private data */ -+ void *private_data; -+} VASurfaceAttribExternalBuffers; -+ -+/** @name VASurfaceAttribExternalBuffers flags */ -+/**@{*/ -+/** \brief Enable memory tiling */ -+#define VA_SURFACE_EXTBUF_DESC_ENABLE_TILING 0x00000001 -+/** \brief Memory is cacheable */ -+#define VA_SURFACE_EXTBUF_DESC_CACHED 0x00000002 -+/** \brief Memory is non-cacheable */ -+#define VA_SURFACE_EXTBUF_DESC_UNCACHED 0x00000004 -+/** \brief Memory is write-combined */ -+#define VA_SURFACE_EXTBUF_DESC_WC 0x00000008 -+/** \brief Memory is protected */ -+#define VA_SURFACE_EXTBUF_DESC_PROTECTED 0x80000000 -+ -+/** @name VASurfaceAttribUsageHint attribute usage hint flags */ -+/**@{*/ -+/** \brief Surface usage not indicated. */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC 0x00000000 -+/** \brief Surface used by video decoder. */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_DECODER 0x00000001 -+/** \brief Surface used by video encoder. */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_ENCODER 0x00000002 -+/** \brief Surface read by video post-processing. */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ 0x00000004 -+/** \brief Surface written by video post-processing. */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE 0x00000008 -+/** \brief Surface used for display. */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_DISPLAY 0x00000010 -+/** \brief Surface used for export to third-party APIs, e.g. via -+ * vaExportSurfaceHandle(). */ -+#define VA_SURFACE_ATTRIB_USAGE_HINT_EXPORT 0x00000020 -+ -+/**@}*/ -+ -+/** -+ * \brief Queries surface attributes for the supplied config. -+ * -+ * This function queries for all supported attributes for the -+ * supplied VA @config. In particular, if the underlying hardware -+ * supports the creation of VA surfaces in various formats, then -+ * this function will enumerate all pixel formats that are supported. -+ * -+ * The \c attrib_list array is allocated by the user and \c -+ * num_attribs shall be initialized to the number of allocated -+ * elements in that array. Upon successful return, the actual number -+ * of attributes will be overwritten into \c num_attribs. Otherwise, -+ * \c VA_STATUS_ERROR_MAX_NUM_EXCEEDED is returned and \c num_attribs -+ * is adjusted to the number of elements that would be returned if -+ * enough space was available. -+ * -+ * Note: it is perfectly valid to pass NULL to the \c attrib_list -+ * argument when vaQuerySurfaceAttributes() is used to determine the -+ * actual number of elements that need to be allocated. -+ * -+ * @param[in] dpy the VA display -+ * @param[in] config the config identifying a codec or a video -+ * processing pipeline -+ * @param[out] attrib_list the output array of #VASurfaceAttrib elements -+ * @param[in,out] num_attribs the number of elements allocated on -+ * input, the number of elements actually filled in output -+ */ -+VAStatus -+vaQuerySurfaceAttributes( -+ VADisplay dpy, -+ VAConfigID config, -+ VASurfaceAttrib *attrib_list, -+ unsigned int *num_attribs -+); -+ -+/** -+ * \brief Creates an array of surfaces -+ * -+ * Creates an array of surfaces. The optional list of attributes shall -+ * be constructed based on what the underlying hardware could expose -+ * through vaQuerySurfaceAttributes(). -+ * -+ * @param[in] dpy the VA display -+ * @param[in] format the desired surface format. See \c VA_RT_FORMAT_* -+ * @param[in] width the surface width -+ * @param[in] height the surface height -+ * @param[out] surfaces the array of newly created surfaces -+ * @param[in] num_surfaces the number of surfaces to create -+ * @param[in] attrib_list the list of (optional) attributes, or \c NULL -+ * @param[in] num_attribs the number of attributes supplied in -+ * \c attrib_list, or zero -+ */ -+VAStatus -+vaCreateSurfaces( -+ VADisplay dpy, -+ unsigned int format, -+ unsigned int width, -+ unsigned int height, -+ VASurfaceID *surfaces, -+ unsigned int num_surfaces, -+ VASurfaceAttrib *attrib_list, -+ unsigned int num_attribs -+); -+ -+/** -+ * vaDestroySurfaces - Destroy resources associated with surfaces. -+ * Surfaces can only be destroyed after all contexts using these surfaces have been -+ * destroyed. -+ * dpy: display -+ * surfaces: array of surfaces to destroy -+ * num_surfaces: number of surfaces in the array to be destroyed. -+ */ -+VAStatus vaDestroySurfaces ( -+ VADisplay dpy, -+ VASurfaceID *surfaces, -+ int num_surfaces -+); -+ -+#define VA_PROGRESSIVE 0x1 -+/** -+ * vaCreateContext - Create a context -+ * dpy: display -+ * config_id: configuration for the context -+ * picture_width: coded picture width -+ * picture_height: coded picture height -+ * flag: any combination of the following: -+ * VA_PROGRESSIVE (only progressive frame pictures in the sequence when set) -+ * render_targets: a hint for render targets (surfaces) tied to the context -+ * num_render_targets: number of render targets in the above array -+ * context: created context id upon return -+ */ -+VAStatus vaCreateContext ( -+ VADisplay dpy, -+ VAConfigID config_id, -+ int picture_width, -+ int picture_height, -+ int flag, -+ VASurfaceID *render_targets, -+ int num_render_targets, -+ VAContextID *context /* out */ -+); -+ -+/** -+ * vaDestroyContext - Destroy a context -+ * dpy: display -+ * context: context to be destroyed -+ */ -+VAStatus vaDestroyContext ( -+ VADisplay dpy, -+ VAContextID context -+); -+ -+//Multi-frame context -+typedef VAGenericID VAMFContextID; -+/** -+ * vaCreateMFContext - Create a multi-frame context -+ * interface encapsulating common for all streams memory objects and structures -+ * required for single GPU task submission from several VAContextID's. -+ * Allocation: This call only creates an instance, doesn't allocate any additional memory. -+ * Support identification: Application can identify multi-frame feature support by ability -+ * to create multi-frame context. If driver supports multi-frame - call successful, -+ * mf_context != NULL and VAStatus = VA_STATUS_SUCCESS, otherwise if multi-frame processing -+ * not supported driver returns VA_STATUS_ERROR_UNIMPLEMENTED and mf_context = NULL. -+ * return values: -+ * VA_STATUS_SUCCESS - operation successful. -+ * VA_STATUS_ERROR_UNIMPLEMENTED - no support for multi-frame. -+ * dpy: display adapter. -+ * mf_context: Multi-Frame context encapsulating all associated context -+ * for multi-frame submission. -+ */ -+VAStatus vaCreateMFContext ( -+ VADisplay dpy, -+ VAMFContextID *mf_context /* out */ -+); -+ -+/** -+ * vaMFAddContext - Provide ability to associate each context used for -+ * Multi-Frame submission and common Multi-Frame context. -+ * Try to add context to understand if it is supported. -+ * Allocation: this call allocates and/or reallocates all memory objects -+ * common for all contexts associated with particular Multi-Frame context. -+ * All memory required for each context(pixel buffers, internal driver -+ * buffers required for processing) allocated during standard vaCreateContext call for each context. -+ * Runtime dependency - if current implementation doesn't allow to run different entry points/profile, -+ * first context added will set entry point/profile for whole Multi-Frame context, -+ * all other entry points and profiles can be rejected to be added. -+ * Return values: -+ * VA_STATUS_SUCCESS - operation successful, context was added. -+ * VA_STATUS_ERROR_OPERATION_FAILED - something unexpected happened - application have to close -+ * current mf_context and associated contexts and start working with new ones. -+ * VA_STATUS_ERROR_INVALID_CONTEXT - ContextID is invalid, means: -+ * 1 - mf_context is not valid context or -+ * 2 - driver can't suport different VAEntrypoint or VAProfile simultaneosly -+ * and current context contradicts with previously added, application can continue with current mf_context -+ * and other contexts passed this call, rejected context can continue work in stand-alone -+ * mode or other mf_context. -+ * VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT - particular context being added was created with with -+ * unsupported VAEntrypoint. Application can continue with current mf_context -+ * and other contexts passed this call, rejected context can continue work in stand-alone -+ * mode. -+ * VA_STATUS_ERROR_UNSUPPORTED_PROFILE - Current context with Particular VAEntrypoint is supported -+ * but VAProfile is not supported. Application can continue with current mf_context -+ * and other contexts passed this call, rejected context can continue work in stand-alone -+ * mode. -+ * dpy: display adapter. -+ * context: context being associated with Multi-Frame context. -+ * mf_context: - multi-frame context used to associate contexts for multi-frame submission. -+ */ -+VAStatus vaMFAddContext ( -+ VADisplay dpy, -+ VAMFContextID mf_context, -+ VAContextID context -+); -+ -+/** -+ * vaMFReleaseContext - Removes context from multi-frame and -+ * association with multi-frame context. -+ * After association removed vaEndPicture will submit tasks, but not vaMFSubmit. -+ * Return values: -+ * VA_STATUS_SUCCESS - operation successful, context was removed. -+ * VA_STATUS_ERROR_OPERATION_FAILED - something unexpected happened. -+ * application need to destroy this VAMFContextID and all assotiated VAContextID -+ * dpy: display -+ * mf_context: VAMFContextID where context is added -+ * context: VAContextID to be added -+ */ -+VAStatus vaMFReleaseContext ( -+ VADisplay dpy, -+ VAMFContextID mf_context, -+ VAContextID context -+); -+ -+/** -+ * Buffers -+ * Buffers are used to pass various types of data from the -+ * client to the server. The server maintains a data store -+ * for each buffer created, and the client idenfies a buffer -+ * through a unique buffer id assigned by the server. -+ */ -+ -+typedef VAGenericID VABufferID; -+ -+typedef enum -+{ -+ VAPictureParameterBufferType = 0, -+ VAIQMatrixBufferType = 1, -+ VABitPlaneBufferType = 2, -+ VASliceGroupMapBufferType = 3, -+ VASliceParameterBufferType = 4, -+ VASliceDataBufferType = 5, -+ VAMacroblockParameterBufferType = 6, -+ VAResidualDataBufferType = 7, -+ VADeblockingParameterBufferType = 8, -+ VAImageBufferType = 9, -+ VAProtectedSliceDataBufferType = 10, -+ VAQMatrixBufferType = 11, -+ VAHuffmanTableBufferType = 12, -+ VAProbabilityBufferType = 13, -+ -+/* Following are encode buffer types */ -+ VAEncCodedBufferType = 21, -+ VAEncSequenceParameterBufferType = 22, -+ VAEncPictureParameterBufferType = 23, -+ VAEncSliceParameterBufferType = 24, -+ VAEncPackedHeaderParameterBufferType = 25, -+ VAEncPackedHeaderDataBufferType = 26, -+ VAEncMiscParameterBufferType = 27, -+ VAEncMacroblockParameterBufferType = 28, -+ VAEncMacroblockMapBufferType = 29, -+ -+ /** -+ * \brief Encoding QP buffer -+ * -+ * This buffer contains QP per MB for encoding. Currently -+ * VAEncQPBufferH264 is defined for H.264 encoding, see -+ * #VAEncQPBufferH264 for details -+ */ -+ VAEncQPBufferType = 30, -+/* Following are video processing buffer types */ -+ /** -+ * \brief Video processing pipeline parameter buffer. -+ * -+ * This buffer describes the video processing pipeline. See -+ * #VAProcPipelineParameterBuffer for details. -+ */ -+ VAProcPipelineParameterBufferType = 41, -+ /** -+ * \brief Video filter parameter buffer. -+ * -+ * This buffer describes the video filter parameters. All buffers -+ * inherit from #VAProcFilterParameterBufferBase, thus including -+ * a unique filter buffer type. -+ * -+ * The default buffer used by most filters is #VAProcFilterParameterBuffer. -+ * Filters requiring advanced parameters include, but are not limited to, -+ * deinterlacing (#VAProcFilterParameterBufferDeinterlacing), -+ * color balance (#VAProcFilterParameterBufferColorBalance), etc. -+ */ -+ VAProcFilterParameterBufferType = 42, -+ /** -+ * \brief FEI specific buffer types -+ */ -+ VAEncFEIMVBufferType = 43, -+ VAEncFEIMBCodeBufferType = 44, -+ VAEncFEIDistortionBufferType = 45, -+ VAEncFEIMBControlBufferType = 46, -+ VAEncFEIMVPredictorBufferType = 47, -+ VAStatsStatisticsParameterBufferType = 48, -+ /** \brief Statistics output for VAEntrypointStats progressive and top field of interlaced case*/ -+ VAStatsStatisticsBufferType = 49, -+ /** \brief Statistics output for VAEntrypointStats bottom field of interlaced case*/ -+ VAStatsStatisticsBottomFieldBufferType = 50, -+ VAStatsMVBufferType = 51, -+ VAStatsMVPredictorBufferType = 52, -+ /** Force MB's to be non skip for encode.it's per-mb control buffer, The width of the MB map -+ * Surface is (width of the Picture in MB unit) * 1 byte, multiple of 64 bytes. -+ * The height is (height of the picture in MB unit). The picture is either -+ * frame or non-interleaved top or bottom field. If the application provides this -+ *surface, it will override the "skipCheckDisable" setting in VAEncMiscParameterEncQuality. -+ */ -+ VAEncMacroblockDisableSkipMapBufferType = 53, -+ /** -+ * \brief HEVC FEI CTB level cmd buffer -+ * it is CTB level information for future usage. -+ */ -+ VAEncFEICTBCmdBufferType = 54, -+ /** -+ * \brief HEVC FEI CU level data buffer -+ * it's CTB level information for future usage -+ */ -+ VAEncFEICURecordBufferType = 55, -+ /** decode stream out buffer, intermedia data of decode, it may include MV, MB mode etc. -+ * it can be used to detect motion and analyze the frame contain */ -+ VADecodeStreamoutBufferType = 56, -+ -+ /** \brief HEVC Decoding Subset Parameter buffer type -+ * -+ * The subsets parameter buffer is concatenation with one or multiple -+ * subset entry point offsets. All the offset values are layed out one -+ * by one according to slice order with first slice segment first, second -+ * slice segment second, etc... The entry number is indicated by parameter -+ * \ref num_entry_point_offsets. And the first entry position of the entry -+ * point offsets for any slice segment is indicated by parameter -+ * entry_offset_to_subset_array in VAPictureParameterBufferHEVC data structure. -+ */ -+ VASubsetsParameterBufferType = 57, -+ -+ VABufferTypeMax -+} VABufferType; -+ -+/** -+ * Processing rate parameter for encode. -+ */ -+typedef struct _VAProcessingRateParameterEnc { -+ /** \brief Profile level */ -+ uint8_t level_idc; -+ uint8_t reserved[3]; -+ /** \brief quality level. When set to 0, default quality -+ * level is used. -+ */ -+ uint32_t quality_level; -+ /** \brief Period between I frames. */ -+ uint32_t intra_period; -+ /** \brief Period between I/P frames. */ -+ uint32_t ip_period; -+} VAProcessingRateParameterEnc; -+ -+/** -+ * Processing rate parameter for decode. -+ */ -+typedef struct _VAProcessingRateParameterDec { -+ /** \brief Profile level */ -+ uint8_t level_idc; -+ uint8_t reserved0[3]; -+ uint32_t reserved; -+} VAProcessingRateParameterDec; -+ -+typedef struct _VAProcessingRateParameter { -+ union { -+ VAProcessingRateParameterEnc proc_buf_enc; -+ VAProcessingRateParameterDec proc_buf_dec; -+ }; -+} VAProcessingRateParameter; -+ -+/** -+ * \brief Queries processing rate for the supplied config. -+ * -+ * This function queries the processing rate based on parameters in -+ * \c proc_buf for the given \c config. Upon successful return, the processing -+ * rate value will be stored in \c processing_rate. Processing rate is -+ * specified as the number of macroblocks/CTU per second. -+ * -+ * If NULL is passed to the \c proc_buf, the default processing rate for the -+ * given configuration will be returned. -+ * -+ * @param[in] dpy the VA display -+ * @param[in] config the config identifying a codec or a video -+ * processing pipeline -+ * @param[in] proc_buf the buffer that contains the parameters for -+ either the encode or decode processing rate -+ * @param[out] processing_rate processing rate in number of macroblocks per -+ second constrained by parameters specified in proc_buf -+ * -+ */ -+VAStatus -+vaQueryProcessingRate( -+ VADisplay dpy, -+ VAConfigID config, -+ VAProcessingRateParameter *proc_buf, -+ unsigned int *processing_rate -+); -+ -+typedef enum -+{ -+ VAEncMiscParameterTypeFrameRate = 0, -+ VAEncMiscParameterTypeRateControl = 1, -+ VAEncMiscParameterTypeMaxSliceSize = 2, -+ VAEncMiscParameterTypeAIR = 3, -+ /** \brief Buffer type used to express a maximum frame size (in bits). */ -+ VAEncMiscParameterTypeMaxFrameSize = 4, -+ /** \brief Buffer type used for HRD parameters. */ -+ VAEncMiscParameterTypeHRD = 5, -+ VAEncMiscParameterTypeQualityLevel = 6, -+ /** \brief Buffer type used for Rolling intra refresh */ -+ VAEncMiscParameterTypeRIR = 7, -+ /** \brief Buffer type used for quantization parameters, it's per-sequence parameter*/ -+ VAEncMiscParameterTypeQuantization = 8, -+ /** \brief Buffer type used for sending skip frame parameters to the encoder's -+ * rate control, when the user has externally skipped frames. */ -+ VAEncMiscParameterTypeSkipFrame = 9, -+ /** \brief Buffer type used for region-of-interest (ROI) parameters. */ -+ VAEncMiscParameterTypeROI = 10, -+ /** \brief Buffer type used to express a maximum frame size (in bytes) settings for multiple pass. */ -+ VAEncMiscParameterTypeMultiPassFrameSize = 11, -+ /** \brief Buffer type used for temporal layer structure */ -+ VAEncMiscParameterTypeTemporalLayerStructure = 12, -+ /** \brief Buffer type used for dirty region-of-interest (ROI) parameters. */ -+ VAEncMiscParameterTypeDirtyRect = 13, -+ /** \brief Buffer type used for parallel BRC parameters. */ -+ VAEncMiscParameterTypeParallelBRC = 14, -+ /** \brief Set MB partion mode mask and Half-pel/Quant-pel motion search */ -+ VAEncMiscParameterTypeSubMbPartPel = 15, -+ /** \brief set encode quality tuning */ -+ VAEncMiscParameterTypeEncQuality = 16, -+ /** \brief Buffer type used for encoder rounding offset parameters. */ -+ VAEncMiscParameterTypeCustomRoundingControl = 17, -+ /** \brief Buffer type used for FEI input frame level parameters */ -+ VAEncMiscParameterTypeFEIFrameControl = 18, -+ /** \brief encode extension buffer, ect. MPEG2 Sequence extenstion data */ -+ VAEncMiscParameterTypeExtensionData = 19 -+} VAEncMiscParameterType; -+ -+/** \brief Packed header type. */ -+typedef enum { -+ /** \brief Packed sequence header. */ -+ VAEncPackedHeaderSequence = 1, -+ /** \brief Packed picture header. */ -+ VAEncPackedHeaderPicture = 2, -+ /** \brief Packed slice header. */ -+ VAEncPackedHeaderSlice = 3, -+ /** -+ * \brief Packed raw header. -+ * -+ * Packed raw data header can be used by the client to insert a header -+ * into the bitstream data buffer at the point it is passed, the driver -+ * will handle the raw packed header based on "has_emulation_bytes" field -+ * in the packed header parameter structure. -+ */ -+ VAEncPackedHeaderRawData = 4, -+ /** -+ * \brief Misc packed header. See codec-specific definitions. -+ * -+ * @deprecated -+ * This is a deprecated packed header type. All applications can use -+ * \c VAEncPackedHeaderRawData to insert a codec-specific packed header -+ */ -+ VAEncPackedHeaderMiscMask va_deprecated_enum = 0x80000000, -+} VAEncPackedHeaderType; -+ -+/** \brief Packed header parameter. */ -+typedef struct _VAEncPackedHeaderParameterBuffer { -+ /** Type of the packed header buffer. See #VAEncPackedHeaderType. */ -+ uint32_t type; -+ /** \brief Size of the #VAEncPackedHeaderDataBuffer in bits. */ -+ uint32_t bit_length; -+ /** \brief Flag: buffer contains start code emulation prevention bytes? */ -+ uint8_t has_emulation_bytes; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncPackedHeaderParameterBuffer; -+ -+/** -+ * For application, e.g. set a new bitrate -+ * VABufferID buf_id; -+ * VAEncMiscParameterBuffer *misc_param; -+ * VAEncMiscParameterRateControl *misc_rate_ctrl; -+ * -+ * vaCreateBuffer(dpy, context, VAEncMiscParameterBufferType, -+ * sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl), -+ * 1, NULL, &buf_id); -+ * -+ * vaMapBuffer(dpy,buf_id,(void **)&misc_param); -+ * misc_param->type = VAEncMiscParameterTypeRateControl; -+ * misc_rate_ctrl= (VAEncMiscParameterRateControl *)misc_param->data; -+ * misc_rate_ctrl->bits_per_second = 6400000; -+ * vaUnmapBuffer(dpy, buf_id); -+ * vaRenderPicture(dpy, context, &buf_id, 1); -+ */ -+typedef struct _VAEncMiscParameterBuffer -+{ -+ VAEncMiscParameterType type; -+ uint32_t data[]; -+} VAEncMiscParameterBuffer; -+ -+/** \brief Temporal layer Structure*/ -+typedef struct _VAEncMiscParameterTemporalLayerStructure -+{ -+ /** \brief The number of temporal layers */ -+ uint32_t number_of_layers; -+ /** \brief The length of the array defining frame layer membership. Should be 1-32 */ -+ uint32_t periodicity; -+ /** -+ * \brief The array indicating the layer id for each frame -+ * -+ * The layer id for the first frame in a coded sequence is always 0, so layer_id[] specifies the layer -+ * ids for frames starting from the 2nd frame. -+ */ -+ uint32_t layer_id[32]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterTemporalLayerStructure; -+ -+ -+/** \brief Rate control parameters */ -+typedef struct _VAEncMiscParameterRateControl -+{ -+ /** The maximum bit-rate which the the rate controller should generate. */ -+ uint32_t bits_per_second; -+ /** The target bit-rate which the rate controller should generate, as a percentage of the -+ * maximum bit-rate. -+ * -+ * In CBR mode this value is ignored (treated as 100%). -+ */ -+ uint32_t target_percentage; -+ /** Rate control window size in milliseconds. -+ * -+ * The rate controller will attempt to guarantee that the target and maximum bit-rates are -+ * correct over this window. -+ */ -+ uint32_t window_size; -+ /** Initial quantiser value used at the start of the stream. -+ * -+ * Ignored if set to zero. -+ */ -+ uint32_t initial_qp; -+ /** Minimum quantiser value to use. -+ * -+ * The quantiser will not go below the value - if this limit is hit, the output bitrate may -+ * be lower than the target. Ignored if set to zero. -+ */ -+ uint32_t min_qp; -+ /** Basic unit size. -+ * -+ * Only used by some drivers - see driver documentation for details. Set to zero if unused. -+ */ -+ uint32_t basic_unit_size; -+ union -+ { -+ struct -+ { -+ /** Force rate controller reset. -+ * -+ * The next frame will be treated as the start of a new stream, with all rate -+ * controller state reset to its initial values. -+ */ -+ uint32_t reset : 1; -+ /** Disable frame skip in rate control mode. */ -+ uint32_t disable_frame_skip : 1; -+ /** Disable bit stuffing in rate control mode. */ -+ uint32_t disable_bit_stuffing : 1; -+ /** Macroblock-level rate control. -+ * -+ * 0: use default, 1: always enable, 2: always disable, other: reserved. -+ * -+ * This feature is only available if VAConfigAttribRateControl has the -+ * \ref VA_RC_MB bit set. -+ */ -+ uint32_t mb_rate_control : 4; -+ /** The temporal layer that these rate control parameters apply to. */ -+ uint32_t temporal_id : 8; -+ /** Ensure that intra frames also conform to the constant frame size. */ -+ uint32_t cfs_I_frames : 1; -+ /** Enable parallel rate control for hierarchical B frames. -+ * -+ * See \ref VA_RC_PARALLEL. -+ */ -+ uint32_t enable_parallel_brc : 1; -+ uint32_t enable_dynamic_scaling : 1; -+ /** Frame tolerance mode. -+ * -+ * Indicates the tolerance the application has to variations in the frame size. -+ * For example, wireless display scenarios may require very steady bit rate to -+ * reduce buffering time. It affects the rate control algorithm used, -+ * but may or may not have an effect based on the combination of other BRC -+ * parameters. Only valid when the driver reports support for -+ * #VAConfigAttribFrameSizeToleranceSupport. -+ * -+ * equals 0 -- normal mode; -+ * equals 1 -- maps to sliding window; -+ * equals 2 -- maps to low delay mode; -+ * other -- invalid. -+ */ -+ uint32_t frame_tolerance_mode : 2; -+ /** Reserved for future use, must be zero. */ -+ uint32_t reserved : 12; -+ } bits; -+ uint32_t value; -+ } rc_flags; -+ /** Initial quality factor used in ICQ mode. -+ * -+ * This value must be between 1 and 51. -+ * this value will be deprecated in future, to use quality_factor instead of it. -+ */ -+ uint32_t ICQ_quality_factor; -+ /** Maximum quantiser value to use. -+ * -+ * The quantiser will not go above this value - if this limit is hit, the output bitrate -+ * may exceed the target. Ignored if set to zero. -+ */ -+ uint32_t max_qp; -+ /** Quality factor -+ * -+ * the range will be different for different codec -+ */ -+ uint32_t quality_factor; -+ /** Reserved bytes for future use, must be zero. */ -+ uint32_t va_reserved[VA_PADDING_MEDIUM - 3]; -+} VAEncMiscParameterRateControl; -+ -+/** Encode framerate parameters. -+ * -+ * Sets the encode framerate used by the rate controller. This should be -+ * provided in all modes using a bitrate target (variable framerate is not -+ * supported). -+ */ -+typedef struct _VAEncMiscParameterFrameRate -+{ -+ /** Encode framerate. -+ * -+ * The framerate is specified as a number of frames per second, as a -+ * fraction. The denominator of the fraction is given in the top half -+ * (the high two bytes) of the framerate field, and the numerator is -+ * given in the bottom half (the low two bytes). -+ * -+ * That is: -+ * denominator = framerate >> 16 & 0xffff; -+ * numerator = framerate & 0xffff; -+ * fps = numerator / denominator; -+ * -+ * For example, if framerate is set to (100 << 16 | 750), this is -+ * 750 / 100, hence 7.5fps. -+ * -+ * If the denominator is zero (the high two bytes are both zero) then -+ * it takes the value one instead, so the framerate is just the integer -+ * in the low 2 bytes. -+ */ -+ uint32_t framerate; -+ union -+ { -+ struct -+ { -+ /** The temporal layer that these framerate parameters apply to. */ -+ uint32_t temporal_id : 8; -+ /** Reserved for future use, must be zero. */ -+ uint32_t reserved : 24; -+ } bits; -+ uint32_t value; -+ } framerate_flags; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterFrameRate; -+ -+/** -+ * Allow a maximum slice size to be specified (in bits). -+ * The encoder will attempt to make sure that individual slices do not exceed this size -+ * Or to signal applicate if the slice size exceed this size, see "status" of VACodedBufferSegment -+ */ -+typedef struct _VAEncMiscParameterMaxSliceSize -+{ -+ uint32_t max_slice_size; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterMaxSliceSize; -+ -+typedef struct _VAEncMiscParameterAIR -+{ -+ uint32_t air_num_mbs; -+ uint32_t air_threshold; -+ uint32_t air_auto; /* if set to 1 then hardware auto-tune the AIR threshold */ -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterAIR; -+ -+/* -+ * \brief Rolling intra refresh data structure for encoding. -+ */ -+typedef struct _VAEncMiscParameterRIR -+{ -+ union -+ { -+ struct -+ /** -+ * \brief Indicate if intra refresh is enabled in column/row. -+ * -+ * App should query VAConfigAttribEncIntraRefresh to confirm RIR support -+ * by the driver before sending this structure. -+ */ -+ { -+ /* \brief enable RIR in column */ -+ uint32_t enable_rir_column : 1; -+ /* \brief enable RIR in row */ -+ uint32_t enable_rir_row : 1; -+ uint32_t reserved : 30; -+ } bits; -+ uint32_t value; -+ } rir_flags; -+ /** -+ * \brief Indicates the column or row location in MB. It is ignored if -+ * rir_flags is 0. -+ */ -+ uint16_t intra_insertion_location; -+ /** -+ * \brief Indicates the number of columns or rows in MB. It is ignored if -+ * rir_flags is 0. -+ */ -+ uint16_t intra_insert_size; -+ /** -+ * \brief indicates the Qp difference for inserted intra columns or rows. -+ * App can use this to adjust intra Qp based on bitrate & max frame size. -+ */ -+ uint8_t qp_delta_for_inserted_intra; -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterRIR; -+ -+/** HRD / VBV buffering parameters for encoding. -+ * -+ * This sets the HRD / VBV parameters which will be used by the rate -+ * controller for encoding. It should be specified in modes using a bitrate -+ * target when the buffering of the output stream needs to be constrained. -+ * -+ * If not provided, the encoder may use arbitrary amounts of buffering. -+ */ -+typedef struct _VAEncMiscParameterHRD -+{ -+ /** The initial fullness of the HRD coded picture buffer, in bits. -+ * -+ * This sets how full the CPB is when encoding begins - that is, how much -+ * buffering will happen on the decoder side before the first frame. -+ * The CPB fullness will be reset to this value after any rate control -+ * reset (a change in parameters or an explicit reset). -+ * -+ * For H.264, it should match the value of initial_cpb_removal_delay in -+ * buffering_period SEI messages. -+ */ -+ uint32_t initial_buffer_fullness; -+ /** The HRD coded picture buffer size, in bits. -+ * -+ * For H.264, it should match the value of cpb_size_value_minus1 in the VUI -+ * parameters. -+ */ -+ uint32_t buffer_size; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterHRD; -+ -+/** -+ * \brief Defines a maximum frame size (in bits). -+ * -+ * This misc parameter buffer defines the maximum size of a frame (in -+ * bits). The encoder will try to make sure that each frame does not -+ * exceed this size. Otherwise, if the frame size exceeds this size, -+ * the \c status flag of #VACodedBufferSegment will contain -+ * #VA_CODED_BUF_STATUS_FRAME_SIZE_OVERFLOW. -+ */ -+typedef struct _VAEncMiscParameterBufferMaxFrameSize { -+ /** \brief Type. Shall be set to #VAEncMiscParameterTypeMaxFrameSize. */ -+ /** duplicated with VAEncMiscParameterBuffer, should be deprecated*/ -+ va_deprecated VAEncMiscParameterType type; -+ /** \brief Maximum size of a frame (in bits). */ -+ uint32_t max_frame_size; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterBufferMaxFrameSize; -+ -+/** -+ * \brief Maximum frame size (in bytes) settings for multiple pass. -+ * -+ * This misc parameter buffer defines the maximum size of a frame (in -+ * bytes) settings for multiple pass. currently only AVC encoder can -+ * support this settings in multiple pass case. If the frame size exceeds -+ * this size, the encoder will do more pak passes to adjust the QP value -+ * to control the frame size. -+ */ -+typedef struct _VAEncMiscParameterBufferMultiPassFrameSize { -+ /** \brief Type. Shall be set to #VAEncMiscParameterTypeMultiPassMaxFrameSize. */ -+ /** duplicated with VAEncMiscParameterBuffer, should be deprecated*/ -+ va_deprecated VAEncMiscParameterType type; -+ /** \brief Maximum size of a frame (in byte) */ -+ uint32_t max_frame_size; -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t reserved; -+ /** \brief number of passes, every pass has different QP, currently AVC encoder can support up to 4 passes */ -+ uint8_t num_passes; -+ /** \brief delta QP list for every pass */ -+ uint8_t *delta_qp; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ unsigned long va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterBufferMultiPassFrameSize; -+ -+/** -+ * \brief Encoding quality level. -+ * -+ * The encoding quality could be set through this structure, if the implementation -+ * supports multiple quality levels. The quality level set through this structure is -+ * persistent over the entire coded sequence, or until a new structure is being sent. -+ * The quality level range can be queried through the VAConfigAttribEncQualityRange -+ * attribute. A lower value means higher quality, and a value of 1 represents the highest -+ * quality. The quality level setting is used as a trade-off between quality and speed/power -+ * consumption, with higher quality corresponds to lower speed and higher power consumption. -+ */ -+typedef struct _VAEncMiscParameterBufferQualityLevel { -+ /** \brief Encoding quality level setting. When set to 0, default quality -+ * level is used. -+ */ -+ uint32_t quality_level; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterBufferQualityLevel; -+ -+/** -+ * \brief Quantization settings for encoding. -+ * -+ * Some encoders support special types of quantization such as trellis, and this structure -+ * can be used by the app to control these special types of quantization by the encoder. -+ */ -+typedef struct _VAEncMiscParameterQuantization -+{ -+ union -+ { -+ /* if no flags is set then quantization is determined by the driver */ -+ struct -+ { -+ /* \brief disable trellis for all frames/fields */ -+ uint32_t disable_trellis : 1; -+ /* \brief enable trellis for I frames/fields */ -+ uint32_t enable_trellis_I : 1; -+ /* \brief enable trellis for P frames/fields */ -+ uint32_t enable_trellis_P : 1; -+ /* \brief enable trellis for B frames/fields */ -+ uint32_t enable_trellis_B : 1; -+ uint32_t reserved : 28; -+ } bits; -+ uint32_t value; -+ } quantization_flags; -+ uint32_t va_reserved; -+} VAEncMiscParameterQuantization; -+ -+/** -+ * \brief Encoding skip frame. -+ * -+ * The application may choose to skip frames externally to the encoder (e.g. drop completely or -+ * code as all skip's). For rate control purposes the encoder will need to know the size and number -+ * of skipped frames. Skip frame(s) indicated through this structure is applicable only to the -+ * current frame. It is allowed for the application to still send in packed headers for the driver to -+ * pack, although no frame will be encoded (e.g. for HW to encrypt the frame). -+ */ -+typedef struct _VAEncMiscParameterSkipFrame { -+ /** \brief Indicates skip frames as below. -+ * 0: Encode as normal, no skip. -+ * 1: One or more frames were skipped prior to the current frame, encode the current frame as normal. -+ * 2: The current frame is to be skipped, do not encode it but pack/encrypt the packed header contents -+ * (all except VAEncPackedHeaderSlice) which could contain actual frame contents (e.g. pack the frame -+ * in VAEncPackedHeaderPicture). */ -+ uint8_t skip_frame_flag; -+ /** \brief The number of frames skipped prior to the current frame. Valid when skip_frame_flag = 1. */ -+ uint8_t num_skip_frames; -+ /** \brief When skip_frame_flag = 1, the size of the skipped frames in bits. When skip_frame_flag = 2, -+ * the size of the current skipped frame that is to be packed/encrypted in bits. */ -+ uint32_t size_skip_frames; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterSkipFrame; -+ -+/** -+ * \brief Encoding region-of-interest (ROI). -+ * -+ * The encoding ROI can be set through VAEncMiscParameterBufferROI, if the implementation -+ * supports ROI input. The ROI set through this structure is applicable only to the -+ * current frame or field, so must be sent every frame or field to be applied. The number of -+ * supported ROIs can be queried through the VAConfigAttribEncROI. The encoder will use the -+ * ROI information to adjust the QP values of the MB's that fall within the ROIs. -+ */ -+typedef struct _VAEncROI -+{ -+ /** \brief Defines the ROI boundary in pixels, the driver will map it to appropriate -+ * codec coding units. It is relative to frame coordinates for the frame case and -+ * to field coordinates for the field case. */ -+ VARectangle roi_rectangle; -+ /** -+ * \brief ROI value -+ * -+ * \ref roi_value specifies ROI delta QP or ROI priority. -+ * -- ROI delta QP is the value that will be added on top of the frame level QP. -+ * -- ROI priority specifies the priority of a region, it can be positive (more important) -+ * or negative (less important) values and is compared with non-ROI region (taken as value 0), -+ * E.g. ROI region with \ref roi_value -3 is less important than the non-ROI region (\ref roi_value -+ * implied to be 0) which is less important than ROI region with roi_value +2. For overlapping -+ * regions, the roi_value that is first in the ROI array will have priority. -+ * -+ * \ref roi_value always specifes ROI delta QP when VAConfigAttribRateControl == VA_RC_CQP, no matter -+ * the value of \c roi_value_is_qp_delta in #VAEncMiscParameterBufferROI. -+ * -+ * \ref roi_value depends on \c roi_value_is_qp_delta in #VAEncMiscParameterBufferROI when -+ * VAConfigAttribRateControl != VA_RC_CQP. \ref roi_value specifies ROI_delta QP if \c roi_value_is_qp_delta -+ * in VAEncMiscParameterBufferROI is 1, otherwise \ref roi_value specifies ROI priority. -+ */ -+ int8_t roi_value; -+} VAEncROI; -+ -+typedef struct _VAEncMiscParameterBufferROI { -+ /** \brief Number of ROIs being sent.*/ -+ uint32_t num_roi; -+ -+ /** \brief Valid when VAConfigAttribRateControl != VA_RC_CQP, then the encoder's -+ * rate control will determine actual delta QPs. Specifies the max/min allowed delta -+ * QPs. */ -+ int8_t max_delta_qp; -+ int8_t min_delta_qp; -+ -+ /** \brief Pointer to a VAEncROI array with num_roi elements. It is relative to frame -+ * coordinates for the frame case and to field coordinates for the field case.*/ -+ VAEncROI *roi; -+ union { -+ struct { -+ /** -+ * \brief An indication for roi value. -+ * -+ * \ref roi_value_is_qp_delta equal to 1 indicates \c roi_value in #VAEncROI should -+ * be used as ROI delta QP. \ref roi_value_is_qp_delta equal to 0 indicates \c roi_value -+ * in #VAEncROI should be used as ROI priority. -+ * -+ * \ref roi_value_is_qp_delta is only available when VAConfigAttribRateControl != VA_RC_CQP, -+ * the setting must comply with \c roi_rc_priority_support and \c roi_rc_qp_delta_support in -+ * #VAConfigAttribValEncROI. The underlying driver should ignore this field -+ * when VAConfigAttribRateControl == VA_RC_CQP. -+ */ -+ uint32_t roi_value_is_qp_delta : 1; -+ uint32_t reserved : 31; -+ } bits; -+ uint32_t value; -+ } roi_flags; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncMiscParameterBufferROI; -+/* -+ * \brief Dirty rectangle data structure for encoding. -+ * -+ * The encoding dirty rect can be set through VAEncMiscParameterBufferDirtyRect, if the -+ * implementation supports dirty rect input. The rect set through this structure is applicable -+ * only to the current frame or field, so must be sent every frame or field to be applied. -+ * The number of supported rects can be queried through the VAConfigAttribEncDirtyRect. The -+ * encoder will use the rect information to know those rectangle areas have changed while the -+ * areas not covered by dirty rect rectangles are assumed to have not changed compared to the -+ * previous picture. The encoder may do some internal optimizations. -+ */ -+typedef struct _VAEncMiscParameterBufferDirtyRect -+{ -+ /** \brief Number of Rectangle being sent.*/ -+ uint32_t num_roi_rectangle; -+ -+ /** \brief Pointer to a VARectangle array with num_roi_rectangle elements.*/ -+ VARectangle *roi_rectangle; -+} VAEncMiscParameterBufferDirtyRect; -+ -+/** \brief Attribute value for VAConfigAttribEncParallelRateControl */ -+typedef struct _VAEncMiscParameterParallelRateControl { -+ /** brief Number of layers*/ -+ uint32_t num_layers; -+ /** brief Number of B frames per layer per GOP. -+ * -+ * it should be allocated by application, and the is num_layers. -+ * num_b_in_gop[0] is the number of regular B which refers to only I or P frames. */ -+ uint32_t *num_b_in_gop; -+} VAEncMiscParameterParallelRateControl; -+ -+/** per frame encoder quality controls, once set they will persist for all future frames -+ *till it is updated again. */ -+typedef struct _VAEncMiscParameterEncQuality -+{ -+ union -+ { -+ struct -+ { -+ /** Use raw frames for reference instead of reconstructed frames. -+ * it only impact motion estimation (ME) stage, and will not impact MC stage -+ * so the reconstruct picture will can match with decode side */ -+ uint32_t useRawPicForRef : 1; -+ /** Disables skip check for ME stage, it will increase the bistream size -+ * but will improve the qulity */ -+ uint32_t skipCheckDisable : 1; -+ /** Indicates app will override default driver FTQ settings using FTQEnable. -+ * FTQ is forward transform quantization */ -+ uint32_t FTQOverride : 1; -+ /** Enables/disables FTQ. */ -+ uint32_t FTQEnable : 1; -+ /** Indicates the app will provide the Skip Threshold LUT to use when FTQ is -+ * enabled (FTQSkipThresholdLUT), else default driver thresholds will be used. */ -+ uint32_t FTQSkipThresholdLUTInput : 1; -+ /** Indicates the app will provide the Skip Threshold LUT to use when FTQ is -+ * disabled (NonFTQSkipThresholdLUT), else default driver thresholds will be used. */ -+ uint32_t NonFTQSkipThresholdLUTInput : 1; -+ uint32_t ReservedBit : 1; -+ /** Control to enable the ME mode decision algorithm to bias to fewer B Direct/Skip types. -+ * Applies only to B frames, all other frames will ignore this setting. */ -+ uint32_t directBiasAdjustmentEnable : 1; -+ /** Enables global motion bias. global motion also is called HME (Heirarchical Motion Estimation ) -+ * HME is used to handle large motions and avoiding local minima in the video encoding process -+ * down scaled the input and reference picture, then do ME. the result will be a predictor to next level HME or ME -+ * current interface divide the HME to 3 level. UltraHME , SuperHME, and HME, result of UltraHME will be input of SurperHME, -+ * result of superHME will be a input for HME. HME result will be input of ME. it is a switch for HMEMVCostScalingFactor -+ * can change the HME bias inside RDO stage*/ -+ uint32_t globalMotionBiasAdjustmentEnable : 1; -+ /** MV cost scaling ratio for HME ( predictors. It is used when -+ * globalMotionBiasAdjustmentEnable == 1, else it is ignored. Values are: -+ * 0: set MV cost to be 0 for HME predictor. -+ * 1: scale MV cost to be 1/2 of the default value for HME predictor. -+ * 2: scale MV cost to be 1/4 of the default value for HME predictor. -+ * 3: scale MV cost to be 1/8 of the default value for HME predictor. */ -+ uint32_t HMEMVCostScalingFactor : 2; -+ /**disable HME, if it is disabled. Super*ultraHME should also be disabled */ -+ uint32_t HMEDisable : 1; -+ /**disable Super HME, if it is disabled, ultraHME should be disabled */ -+ uint32_t SuperHMEDisable : 1; -+ /** disable Ultra HME */ -+ uint32_t UltraHMEDisable : 1; -+ /** disable panic mode. Panic mode happened when there are extreme BRC (bit rate control) requirement -+ * frame size cant achieve the target of BRC. when Panic mode is triggered, Coefficients will -+ * be set to zero. disable panic mode will improve quality but will impact BRC */ -+ uint32_t PanicModeDisable : 1; -+ /** Force RepartitionCheck -+ * 0: DEFAULT - follow driver default settings. -+ * 1: FORCE_ENABLE - enable this feature totally for all cases. -+ * 2: FORCE_DISABLE - disable this feature totally for all cases. */ -+ uint32_t ForceRepartitionCheck : 2; -+ -+ }; -+ uint32_t encControls; -+ }; -+ -+ /** Maps QP to skip thresholds when FTQ is enabled. Valid range is 0-255. */ -+ uint8_t FTQSkipThresholdLUT[52]; -+ /** Maps QP to skip thresholds when FTQ is disabled. Valid range is 0-65535. */ -+ uint16_t NonFTQSkipThresholdLUT[52]; -+ -+ uint32_t reserved[VA_PADDING_HIGH]; // Reserved for future use. -+ -+} VAEncMiscParameterEncQuality; -+ -+/** -+ * \brief Custom Encoder Rounding Offset Control. -+ * Application may use this structure to set customized rounding -+ * offset parameters for quantization. -+ * Valid when \c VAConfigAttribCustomRoundingControl equals 1. -+ */ -+typedef struct _VAEncMiscParameterCustomRoundingControl -+{ -+ union { -+ struct { -+ /** \brief Enable customized rounding offset for intra blocks. -+ * If 0, default value would be taken by driver for intra -+ * rounding offset. -+ */ -+ uint32_t enable_custom_rouding_intra : 1 ; -+ -+ /** \brief Intra rounding offset -+ * Ignored if \c enable_custom_rouding_intra equals 0. -+ */ -+ uint32_t rounding_offset_intra : 7; -+ -+ /** \brief Enable customized rounding offset for inter blocks. -+ * If 0, default value would be taken by driver for inter -+ * rounding offset. -+ */ -+ uint32_t enable_custom_rounding_inter : 1 ; -+ -+ /** \brief Inter rounding offset -+ * Ignored if \c enable_custom_rouding_inter equals 0. -+ */ -+ uint32_t rounding_offset_inter : 7; -+ -+ /* Reserved */ -+ uint32_t reserved :16; -+ } bits; -+ uint32_t value; -+ } rounding_offset_setting; -+} VAEncMiscParameterCustomRoundingControl; -+/** -+ * There will be cases where the bitstream buffer will not have enough room to hold -+ * the data for the entire slice, and the following flags will be used in the slice -+ * parameter to signal to the server for the possible cases. -+ * If a slice parameter buffer and slice data buffer pair is sent to the server with -+ * the slice data partially in the slice data buffer (BEGIN and MIDDLE cases below), -+ * then a slice parameter and data buffer needs to be sent again to complete this slice. -+ */ -+#define VA_SLICE_DATA_FLAG_ALL 0x00 /* whole slice is in the buffer */ -+#define VA_SLICE_DATA_FLAG_BEGIN 0x01 /* The beginning of the slice is in the buffer but the end if not */ -+#define VA_SLICE_DATA_FLAG_MIDDLE 0x02 /* Neither beginning nor end of the slice is in the buffer */ -+#define VA_SLICE_DATA_FLAG_END 0x04 /* end of the slice is in the buffer */ -+ -+/* Codec-independent Slice Parameter Buffer base */ -+typedef struct _VASliceParameterBufferBase -+{ -+ uint32_t slice_data_size; /* number of bytes in the slice data buffer for this slice */ -+ uint32_t slice_data_offset; /* the offset to the first byte of slice data */ -+ uint32_t slice_data_flag; /* see VA_SLICE_DATA_FLAG_XXX definitions */ -+} VASliceParameterBufferBase; -+ -+/********************************** -+ * JPEG common data structures -+ **********************************/ -+/** -+ * \brief Huffman table for JPEG decoding. -+ * -+ * This structure holds the complete Huffman tables. This is an -+ * aggregation of all Huffman table (DHT) segments maintained by the -+ * application. i.e. up to 2 Huffman tables are stored in there for -+ * baseline profile. -+ * -+ * The #load_huffman_table array can be used as a hint to notify the -+ * VA driver implementation about which table(s) actually changed -+ * since the last submission of this buffer. -+ */ -+typedef struct _VAHuffmanTableBufferJPEGBaseline { -+ /** \brief Specifies which #huffman_table is valid. */ -+ uint8_t load_huffman_table[2]; -+ /** \brief Huffman tables indexed by table identifier (Th). */ -+ struct { -+ /** @name DC table (up to 12 categories) */ -+ /**@{*/ -+ /** \brief Number of Huffman codes of length i + 1 (Li). */ -+ uint8_t num_dc_codes[16]; -+ /** \brief Value associated with each Huffman code (Vij). */ -+ uint8_t dc_values[12]; -+ /**@}*/ -+ /** @name AC table (2 special codes + up to 16 * 10 codes) */ -+ /**@{*/ -+ /** \brief Number of Huffman codes of length i + 1 (Li). */ -+ uint8_t num_ac_codes[16]; -+ /** \brief Value associated with each Huffman code (Vij). */ -+ uint8_t ac_values[162]; -+ /** \brief Padding to 4-byte boundaries. Must be set to zero. */ -+ uint8_t pad[2]; -+ /**@}*/ -+ } huffman_table[2]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAHuffmanTableBufferJPEGBaseline; -+ -+/**************************** -+ * MPEG-2 data structures -+ ****************************/ -+ -+/* MPEG-2 Picture Parameter Buffer */ -+/* -+ * For each frame or field, and before any slice data, a single -+ * picture parameter buffer must be send. -+ */ -+typedef struct _VAPictureParameterBufferMPEG2 -+{ -+ uint16_t horizontal_size; -+ uint16_t vertical_size; -+ VASurfaceID forward_reference_picture; -+ VASurfaceID backward_reference_picture; -+ /* meanings of the following fields are the same as in the standard */ -+ int32_t picture_coding_type; -+ int32_t f_code; /* pack all four fcode into this */ -+ union { -+ struct { -+ uint32_t intra_dc_precision : 2; -+ uint32_t picture_structure : 2; -+ uint32_t top_field_first : 1; -+ uint32_t frame_pred_frame_dct : 1; -+ uint32_t concealment_motion_vectors : 1; -+ uint32_t q_scale_type : 1; -+ uint32_t intra_vlc_format : 1; -+ uint32_t alternate_scan : 1; -+ uint32_t repeat_first_field : 1; -+ uint32_t progressive_frame : 1; -+ uint32_t is_first_field : 1; /* indicate whether the current field -+ * is the first field for field picture -+ */ -+ } bits; -+ uint32_t value; -+ } picture_coding_extension; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAPictureParameterBufferMPEG2; -+ -+/** MPEG-2 Inverse Quantization Matrix Buffer */ -+typedef struct _VAIQMatrixBufferMPEG2 -+{ -+ /** \brief Same as the MPEG-2 bitstream syntax element. */ -+ int32_t load_intra_quantiser_matrix; -+ /** \brief Same as the MPEG-2 bitstream syntax element. */ -+ int32_t load_non_intra_quantiser_matrix; -+ /** \brief Same as the MPEG-2 bitstream syntax element. */ -+ int32_t load_chroma_intra_quantiser_matrix; -+ /** \brief Same as the MPEG-2 bitstream syntax element. */ -+ int32_t load_chroma_non_intra_quantiser_matrix; -+ /** \brief Luminance intra matrix, in zig-zag scan order. */ -+ uint8_t intra_quantiser_matrix[64]; -+ /** \brief Luminance non-intra matrix, in zig-zag scan order. */ -+ uint8_t non_intra_quantiser_matrix[64]; -+ /** \brief Chroma intra matrix, in zig-zag scan order. */ -+ uint8_t chroma_intra_quantiser_matrix[64]; -+ /** \brief Chroma non-intra matrix, in zig-zag scan order. */ -+ uint8_t chroma_non_intra_quantiser_matrix[64]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAIQMatrixBufferMPEG2; -+ -+/** MPEG-2 Slice Parameter Buffer */ -+typedef struct _VASliceParameterBufferMPEG2 -+{ -+ uint32_t slice_data_size;/* number of bytes in the slice data buffer for this slice */ -+ uint32_t slice_data_offset;/* the offset to the first byte of slice data */ -+ uint32_t slice_data_flag; /* see VA_SLICE_DATA_FLAG_XXX defintions */ -+ uint32_t macroblock_offset;/* the offset to the first bit of MB from the first byte of slice data */ -+ uint32_t slice_horizontal_position; -+ uint32_t slice_vertical_position; -+ int32_t quantiser_scale_code; -+ int32_t intra_slice_flag; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VASliceParameterBufferMPEG2; -+ -+/** MPEG-2 Macroblock Parameter Buffer */ -+typedef struct _VAMacroblockParameterBufferMPEG2 -+{ -+ uint16_t macroblock_address; -+ /* -+ * macroblock_address (in raster scan order) -+ * top-left: 0 -+ * bottom-right: picture-height-in-mb*picture-width-in-mb - 1 -+ */ -+ uint8_t macroblock_type; /* see definition below */ -+ union { -+ struct { -+ uint32_t frame_motion_type : 2; -+ uint32_t field_motion_type : 2; -+ uint32_t dct_type : 1; -+ } bits; -+ uint32_t value; -+ } macroblock_modes; -+ uint8_t motion_vertical_field_select; -+ /* -+ * motion_vertical_field_select: -+ * see section 6.3.17.2 in the spec -+ * only the lower 4 bits are used -+ * bit 0: first vector forward -+ * bit 1: first vector backward -+ * bit 2: second vector forward -+ * bit 3: second vector backward -+ */ -+ int16_t PMV[2][2][2]; /* see Table 7-7 in the spec */ -+ uint16_t coded_block_pattern; -+ /* -+ * The bitplanes for coded_block_pattern are described -+ * in Figure 6.10-12 in the spec -+ */ -+ -+ /* Number of skipped macroblocks after this macroblock */ -+ uint16_t num_skipped_macroblocks; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAMacroblockParameterBufferMPEG2; -+ -+/* -+ * OR'd flags for macroblock_type (section 6.3.17.1 in the spec) -+ */ -+#define VA_MB_TYPE_MOTION_FORWARD 0x02 -+#define VA_MB_TYPE_MOTION_BACKWARD 0x04 -+#define VA_MB_TYPE_MOTION_PATTERN 0x08 -+#define VA_MB_TYPE_MOTION_INTRA 0x10 -+ -+/** -+ * MPEG-2 Residual Data Buffer -+ * For each macroblock, there wil be 64 shorts (16-bit) in the -+ * residual data buffer -+ */ -+ -+/**************************** -+ * MPEG-4 Part 2 data structures -+ ****************************/ -+ -+/* MPEG-4 Picture Parameter Buffer */ -+/* -+ * For each frame or field, and before any slice data, a single -+ * picture parameter buffer must be send. -+ */ -+typedef struct _VAPictureParameterBufferMPEG4 -+{ -+ uint16_t vop_width; -+ uint16_t vop_height; -+ VASurfaceID forward_reference_picture; -+ VASurfaceID backward_reference_picture; -+ union { -+ struct { -+ uint32_t short_video_header : 1; -+ uint32_t chroma_format : 2; -+ uint32_t interlaced : 1; -+ uint32_t obmc_disable : 1; -+ uint32_t sprite_enable : 2; -+ uint32_t sprite_warping_accuracy : 2; -+ uint32_t quant_type : 1; -+ uint32_t quarter_sample : 1; -+ uint32_t data_partitioned : 1; -+ uint32_t reversible_vlc : 1; -+ uint32_t resync_marker_disable : 1; -+ } bits; -+ uint32_t value; -+ } vol_fields; -+ uint8_t no_of_sprite_warping_points; -+ int16_t sprite_trajectory_du[3]; -+ int16_t sprite_trajectory_dv[3]; -+ uint8_t quant_precision; -+ union { -+ struct { -+ uint32_t vop_coding_type : 2; -+ uint32_t backward_reference_vop_coding_type : 2; -+ uint32_t vop_rounding_type : 1; -+ uint32_t intra_dc_vlc_thr : 3; -+ uint32_t top_field_first : 1; -+ uint32_t alternate_vertical_scan_flag : 1; -+ } bits; -+ uint32_t value; -+ } vop_fields; -+ uint8_t vop_fcode_forward; -+ uint8_t vop_fcode_backward; -+ uint16_t vop_time_increment_resolution; -+ /* short header related */ -+ uint8_t num_gobs_in_vop; -+ uint8_t num_macroblocks_in_gob; -+ /* for direct mode prediction */ -+ int16_t TRB; -+ int16_t TRD; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAPictureParameterBufferMPEG4; -+ -+/** MPEG-4 Inverse Quantization Matrix Buffer */ -+typedef struct _VAIQMatrixBufferMPEG4 -+{ -+ /** Same as the MPEG-4:2 bitstream syntax element. */ -+ int32_t load_intra_quant_mat; -+ /** Same as the MPEG-4:2 bitstream syntax element. */ -+ int32_t load_non_intra_quant_mat; -+ /** The matrix for intra blocks, in zig-zag scan order. */ -+ uint8_t intra_quant_mat[64]; -+ /** The matrix for non-intra blocks, in zig-zag scan order. */ -+ uint8_t non_intra_quant_mat[64]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAIQMatrixBufferMPEG4; -+ -+/** MPEG-4 Slice Parameter Buffer */ -+typedef struct _VASliceParameterBufferMPEG4 -+{ -+ uint32_t slice_data_size;/* number of bytes in the slice data buffer for this slice */ -+ uint32_t slice_data_offset;/* the offset to the first byte of slice data */ -+ uint32_t slice_data_flag; /* see VA_SLICE_DATA_FLAG_XXX defintions */ -+ uint32_t macroblock_offset;/* the offset to the first bit of MB from the first byte of slice data */ -+ uint32_t macroblock_number; -+ int32_t quant_scale; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VASliceParameterBufferMPEG4; -+ -+/** -+ VC-1 data structures -+*/ -+ -+typedef enum /* see 7.1.1.32 */ -+{ -+ VAMvMode1Mv = 0, -+ VAMvMode1MvHalfPel = 1, -+ VAMvMode1MvHalfPelBilinear = 2, -+ VAMvModeMixedMv = 3, -+ VAMvModeIntensityCompensation = 4 -+} VAMvModeVC1; -+ -+/** VC-1 Picture Parameter Buffer */ -+/* -+ * For each picture, and before any slice data, a picture parameter -+ * buffer must be send. Multiple picture parameter buffers may be -+ * sent for a single picture. In that case picture parameters will -+ * apply to all slice data that follow it until a new picture -+ * parameter buffer is sent. -+ * -+ * Notes: -+ * pic_quantizer_type should be set to the applicable quantizer -+ * type as defined by QUANTIZER (J.1.19) and either -+ * PQUANTIZER (7.1.1.8) or PQINDEX (7.1.1.6) -+ */ -+typedef struct _VAPictureParameterBufferVC1 -+{ -+ VASurfaceID forward_reference_picture; -+ VASurfaceID backward_reference_picture; -+ /* if out-of-loop post-processing is done on the render -+ target, then we need to keep the in-loop decoded -+ picture as a reference picture */ -+ VASurfaceID inloop_decoded_picture; -+ -+ /* sequence layer for AP or meta data for SP and MP */ -+ union { -+ struct { -+ uint32_t pulldown : 1; /* SEQUENCE_LAYER::PULLDOWN */ -+ uint32_t interlace : 1; /* SEQUENCE_LAYER::INTERLACE */ -+ uint32_t tfcntrflag : 1; /* SEQUENCE_LAYER::TFCNTRFLAG */ -+ uint32_t finterpflag : 1; /* SEQUENCE_LAYER::FINTERPFLAG */ -+ uint32_t psf : 1; /* SEQUENCE_LAYER::PSF */ -+ uint32_t multires : 1; /* METADATA::MULTIRES */ -+ uint32_t overlap : 1; /* METADATA::OVERLAP */ -+ uint32_t syncmarker : 1; /* METADATA::SYNCMARKER */ -+ uint32_t rangered : 1; /* METADATA::RANGERED */ -+ uint32_t max_b_frames : 3; /* METADATA::MAXBFRAMES */ -+ uint32_t profile : 2; /* SEQUENCE_LAYER::PROFILE or The MSB of METADATA::PROFILE */ -+ } bits; -+ uint32_t value; -+ } sequence_fields; -+ -+ uint16_t coded_width; /* ENTRY_POINT_LAYER::CODED_WIDTH */ -+ uint16_t coded_height; /* ENTRY_POINT_LAYER::CODED_HEIGHT */ -+ union { -+ struct { -+ uint32_t broken_link : 1; /* ENTRY_POINT_LAYER::BROKEN_LINK */ -+ uint32_t closed_entry : 1; /* ENTRY_POINT_LAYER::CLOSED_ENTRY */ -+ uint32_t panscan_flag : 1; /* ENTRY_POINT_LAYER::PANSCAN_FLAG */ -+ uint32_t loopfilter : 1; /* ENTRY_POINT_LAYER::LOOPFILTER */ -+ } bits; -+ uint32_t value; -+ } entrypoint_fields; -+ uint8_t conditional_overlap_flag; /* ENTRY_POINT_LAYER::CONDOVER */ -+ uint8_t fast_uvmc_flag; /* ENTRY_POINT_LAYER::FASTUVMC */ -+ union { -+ struct { -+ uint32_t luma_flag : 1; /* ENTRY_POINT_LAYER::RANGE_MAPY_FLAG */ -+ uint32_t luma : 3; /* ENTRY_POINT_LAYER::RANGE_MAPY */ -+ uint32_t chroma_flag : 1; /* ENTRY_POINT_LAYER::RANGE_MAPUV_FLAG */ -+ uint32_t chroma : 3; /* ENTRY_POINT_LAYER::RANGE_MAPUV */ -+ } bits; -+ uint32_t value; -+ } range_mapping_fields; -+ -+ uint8_t b_picture_fraction; /* Index for PICTURE_LAYER::BFRACTION value in Table 40 (7.1.1.14) */ -+ uint8_t cbp_table; /* PICTURE_LAYER::CBPTAB/ICBPTAB */ -+ uint8_t mb_mode_table; /* PICTURE_LAYER::MBMODETAB */ -+ uint8_t range_reduction_frame;/* PICTURE_LAYER::RANGEREDFRM */ -+ uint8_t rounding_control; /* PICTURE_LAYER::RNDCTRL */ -+ uint8_t post_processing; /* PICTURE_LAYER::POSTPROC */ -+ uint8_t picture_resolution_index; /* PICTURE_LAYER::RESPIC */ -+ uint8_t luma_scale; /* PICTURE_LAYER::LUMSCALE */ -+ uint8_t luma_shift; /* PICTURE_LAYER::LUMSHIFT */ -+ -+ union { -+ struct { -+ uint32_t picture_type : 3; /* PICTURE_LAYER::PTYPE */ -+ uint32_t frame_coding_mode : 3; /* PICTURE_LAYER::FCM */ -+ uint32_t top_field_first : 1; /* PICTURE_LAYER::TFF */ -+ uint32_t is_first_field : 1; /* set to 1 if it is the first field */ -+ uint32_t intensity_compensation : 1; /* PICTURE_LAYER::INTCOMP */ -+ } bits; -+ uint32_t value; -+ } picture_fields; -+ union { -+ struct { -+ uint32_t mv_type_mb : 1; /* PICTURE::MVTYPEMB */ -+ uint32_t direct_mb : 1; /* PICTURE::DIRECTMB */ -+ uint32_t skip_mb : 1; /* PICTURE::SKIPMB */ -+ uint32_t field_tx : 1; /* PICTURE::FIELDTX */ -+ uint32_t forward_mb : 1; /* PICTURE::FORWARDMB */ -+ uint32_t ac_pred : 1; /* PICTURE::ACPRED */ -+ uint32_t overflags : 1; /* PICTURE::OVERFLAGS */ -+ } flags; -+ uint32_t value; -+ } raw_coding; -+ union { -+ struct { -+ uint32_t bp_mv_type_mb : 1; /* PICTURE::MVTYPEMB */ -+ uint32_t bp_direct_mb : 1; /* PICTURE::DIRECTMB */ -+ uint32_t bp_skip_mb : 1; /* PICTURE::SKIPMB */ -+ uint32_t bp_field_tx : 1; /* PICTURE::FIELDTX */ -+ uint32_t bp_forward_mb : 1; /* PICTURE::FORWARDMB */ -+ uint32_t bp_ac_pred : 1; /* PICTURE::ACPRED */ -+ uint32_t bp_overflags : 1; /* PICTURE::OVERFLAGS */ -+ } flags; -+ uint32_t value; -+ } bitplane_present; /* signal what bitplane is being passed via the bitplane buffer */ -+ union { -+ struct { -+ uint32_t reference_distance_flag : 1;/* PICTURE_LAYER::REFDIST_FLAG */ -+ uint32_t reference_distance : 5;/* PICTURE_LAYER::REFDIST */ -+ uint32_t num_reference_pictures: 1;/* PICTURE_LAYER::NUMREF */ -+ uint32_t reference_field_pic_indicator : 1;/* PICTURE_LAYER::REFFIELD */ -+ } bits; -+ uint32_t value; -+ } reference_fields; -+ union { -+ struct { -+ uint32_t mv_mode : 3; /* PICTURE_LAYER::MVMODE */ -+ uint32_t mv_mode2 : 3; /* PICTURE_LAYER::MVMODE2 */ -+ uint32_t mv_table : 3; /* PICTURE_LAYER::MVTAB/IMVTAB */ -+ uint32_t two_mv_block_pattern_table: 2; /* PICTURE_LAYER::2MVBPTAB */ -+ uint32_t four_mv_switch : 1; /* PICTURE_LAYER::4MVSWITCH */ -+ uint32_t four_mv_block_pattern_table : 2; /* PICTURE_LAYER::4MVBPTAB */ -+ uint32_t extended_mv_flag : 1; /* ENTRY_POINT_LAYER::EXTENDED_MV */ -+ uint32_t extended_mv_range : 2; /* PICTURE_LAYER::MVRANGE */ -+ uint32_t extended_dmv_flag : 1; /* ENTRY_POINT_LAYER::EXTENDED_DMV */ -+ uint32_t extended_dmv_range : 2; /* PICTURE_LAYER::DMVRANGE */ -+ } bits; -+ uint32_t value; -+ } mv_fields; -+ union { -+ struct { -+ uint32_t dquant : 2; /* ENTRY_POINT_LAYER::DQUANT */ -+ uint32_t quantizer : 2; /* ENTRY_POINT_LAYER::QUANTIZER */ -+ uint32_t half_qp : 1; /* PICTURE_LAYER::HALFQP */ -+ uint32_t pic_quantizer_scale : 5;/* PICTURE_LAYER::PQUANT */ -+ uint32_t pic_quantizer_type : 1;/* PICTURE_LAYER::PQUANTIZER */ -+ uint32_t dq_frame : 1; /* VOPDQUANT::DQUANTFRM */ -+ uint32_t dq_profile : 2; /* VOPDQUANT::DQPROFILE */ -+ uint32_t dq_sb_edge : 2; /* VOPDQUANT::DQSBEDGE */ -+ uint32_t dq_db_edge : 2; /* VOPDQUANT::DQDBEDGE */ -+ uint32_t dq_binary_level : 1; /* VOPDQUANT::DQBILEVEL */ -+ uint32_t alt_pic_quantizer : 5;/* VOPDQUANT::ALTPQUANT */ -+ } bits; -+ uint32_t value; -+ } pic_quantizer_fields; -+ union { -+ struct { -+ uint32_t variable_sized_transform_flag : 1;/* ENTRY_POINT_LAYER::VSTRANSFORM */ -+ uint32_t mb_level_transform_type_flag : 1;/* PICTURE_LAYER::TTMBF */ -+ uint32_t frame_level_transform_type : 2;/* PICTURE_LAYER::TTFRM */ -+ uint32_t transform_ac_codingset_idx1 : 2;/* PICTURE_LAYER::TRANSACFRM */ -+ uint32_t transform_ac_codingset_idx2 : 2;/* PICTURE_LAYER::TRANSACFRM2 */ -+ uint32_t intra_transform_dc_table : 1;/* PICTURE_LAYER::TRANSDCTAB */ -+ } bits; -+ uint32_t value; -+ } transform_fields; -+ -+ uint8_t luma_scale2; /* PICTURE_LAYER::LUMSCALE2 */ -+ uint8_t luma_shift2; /* PICTURE_LAYER::LUMSHIFT2 */ -+ uint8_t intensity_compensation_field; /* Index for PICTURE_LAYER::INTCOMPFIELD value in Table 109 (9.1.1.48) */ -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_MEDIUM - 1]; -+} VAPictureParameterBufferVC1; -+ -+/** VC-1 Bitplane Buffer -+There will be at most three bitplanes coded in any picture header. To send -+the bitplane data more efficiently, each byte is divided in two nibbles, with -+each nibble carrying three bitplanes for one macroblock. The following table -+shows the bitplane data arrangement within each nibble based on the picture -+type. -+ -+Picture Type Bit3 Bit2 Bit1 Bit0 -+I or BI OVERFLAGS ACPRED FIELDTX -+P MYTYPEMB SKIPMB DIRECTMB -+B FORWARDMB SKIPMB DIRECTMB -+ -+Within each byte, the lower nibble is for the first MB and the upper nibble is -+for the second MB. E.g. the lower nibble of the first byte in the bitplane -+buffer is for Macroblock #1 and the upper nibble of the first byte is for -+Macroblock #2 in the first row. -+*/ -+ -+/* VC-1 Slice Parameter Buffer */ -+typedef struct _VASliceParameterBufferVC1 -+{ -+ uint32_t slice_data_size;/* number of bytes in the slice data buffer for this slice */ -+ uint32_t slice_data_offset;/* the offset to the first byte of slice data */ -+ uint32_t slice_data_flag; /* see VA_SLICE_DATA_FLAG_XXX defintions */ -+ uint32_t macroblock_offset;/* the offset to the first bit of MB from the first byte of slice data */ -+ uint32_t slice_vertical_position; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VASliceParameterBufferVC1; -+ -+/* VC-1 Slice Data Buffer */ -+/* -+This is simplely a buffer containing raw bit-stream bytes -+*/ -+ -+/**************************** -+ * H.264/AVC data structures -+ ****************************/ -+ -+typedef struct _VAPictureH264 -+{ -+ VASurfaceID picture_id; -+ uint32_t frame_idx; -+ uint32_t flags; -+ int32_t TopFieldOrderCnt; -+ int32_t BottomFieldOrderCnt; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAPictureH264; -+/* flags in VAPictureH264 could be OR of the following */ -+#define VA_PICTURE_H264_INVALID 0x00000001 -+#define VA_PICTURE_H264_TOP_FIELD 0x00000002 -+#define VA_PICTURE_H264_BOTTOM_FIELD 0x00000004 -+#define VA_PICTURE_H264_SHORT_TERM_REFERENCE 0x00000008 -+#define VA_PICTURE_H264_LONG_TERM_REFERENCE 0x00000010 -+ -+/** H.264 Picture Parameter Buffer */ -+/* -+ * For each picture, and before any slice data, a single -+ * picture parameter buffer must be send. -+ */ -+typedef struct _VAPictureParameterBufferH264 -+{ -+ VAPictureH264 CurrPic; -+ VAPictureH264 ReferenceFrames[16]; /* in DPB */ -+ uint16_t picture_width_in_mbs_minus1; -+ uint16_t picture_height_in_mbs_minus1; -+ uint8_t bit_depth_luma_minus8; -+ uint8_t bit_depth_chroma_minus8; -+ uint8_t num_ref_frames; -+ union { -+ struct { -+ uint32_t chroma_format_idc : 2; -+ uint32_t residual_colour_transform_flag : 1; /* Renamed to separate_colour_plane_flag in newer standard versions. */ -+ uint32_t gaps_in_frame_num_value_allowed_flag : 1; -+ uint32_t frame_mbs_only_flag : 1; -+ uint32_t mb_adaptive_frame_field_flag : 1; -+ uint32_t direct_8x8_inference_flag : 1; -+ uint32_t MinLumaBiPredSize8x8 : 1; /* see A.3.3.2 */ -+ uint32_t log2_max_frame_num_minus4 : 4; -+ uint32_t pic_order_cnt_type : 2; -+ uint32_t log2_max_pic_order_cnt_lsb_minus4 : 4; -+ uint32_t delta_pic_order_always_zero_flag : 1; -+ } bits; -+ uint32_t value; -+ } seq_fields; -+ // FMO is not supported. -+ va_deprecated uint8_t num_slice_groups_minus1; -+ va_deprecated uint8_t slice_group_map_type; -+ va_deprecated uint16_t slice_group_change_rate_minus1; -+ int8_t pic_init_qp_minus26; -+ int8_t pic_init_qs_minus26; -+ int8_t chroma_qp_index_offset; -+ int8_t second_chroma_qp_index_offset; -+ union { -+ struct { -+ uint32_t entropy_coding_mode_flag : 1; -+ uint32_t weighted_pred_flag : 1; -+ uint32_t weighted_bipred_idc : 2; -+ uint32_t transform_8x8_mode_flag : 1; -+ uint32_t field_pic_flag : 1; -+ uint32_t constrained_intra_pred_flag : 1; -+ uint32_t pic_order_present_flag : 1; /* Renamed to bottom_field_pic_order_in_frame_present_flag in newer standard versions. */ -+ uint32_t deblocking_filter_control_present_flag : 1; -+ uint32_t redundant_pic_cnt_present_flag : 1; -+ uint32_t reference_pic_flag : 1; /* nal_ref_idc != 0 */ -+ } bits; -+ uint32_t value; -+ } pic_fields; -+ uint16_t frame_num; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_MEDIUM]; -+} VAPictureParameterBufferH264; -+ -+/** H.264 Inverse Quantization Matrix Buffer */ -+typedef struct _VAIQMatrixBufferH264 -+{ -+ /** \brief 4x4 scaling list, in raster scan order. */ -+ uint8_t ScalingList4x4[6][16]; -+ /** \brief 8x8 scaling list, in raster scan order. */ -+ uint8_t ScalingList8x8[2][64]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAIQMatrixBufferH264; -+ -+/** H.264 Slice Parameter Buffer */ -+typedef struct _VASliceParameterBufferH264 -+{ -+ uint32_t slice_data_size;/* number of bytes in the slice data buffer for this slice */ -+ /** \brief Byte offset to the NAL Header Unit for this slice. */ -+ uint32_t slice_data_offset; -+ uint32_t slice_data_flag; /* see VA_SLICE_DATA_FLAG_XXX defintions */ -+ /** -+ * \brief Bit offset from NAL Header Unit to the begining of slice_data(). -+ * -+ * This bit offset is relative to and includes the NAL unit byte -+ * and represents the number of bits parsed in the slice_header() -+ * after the removal of any emulation prevention bytes in -+ * there. However, the slice data buffer passed to the hardware is -+ * the original bitstream, thus including any emulation prevention -+ * bytes. -+ */ -+ uint16_t slice_data_bit_offset; -+ uint16_t first_mb_in_slice; -+ uint8_t slice_type; -+ uint8_t direct_spatial_mv_pred_flag; -+ /** -+ * H264/AVC syntax element -+ * -+ * if num_ref_idx_active_override_flag equals 0, host decoder should -+ * set its value to num_ref_idx_l0_default_active_minus1. -+ */ -+ uint8_t num_ref_idx_l0_active_minus1; -+ /** -+ * H264/AVC syntax element -+ * -+ * if num_ref_idx_active_override_flag equals 0, host decoder should -+ * set its value to num_ref_idx_l1_default_active_minus1. -+ */ -+ uint8_t num_ref_idx_l1_active_minus1; -+ uint8_t cabac_init_idc; -+ int8_t slice_qp_delta; -+ uint8_t disable_deblocking_filter_idc; -+ int8_t slice_alpha_c0_offset_div2; -+ int8_t slice_beta_offset_div2; -+ VAPictureH264 RefPicList0[32]; /* See 8.2.4.2 */ -+ VAPictureH264 RefPicList1[32]; /* See 8.2.4.2 */ -+ uint8_t luma_log2_weight_denom; -+ uint8_t chroma_log2_weight_denom; -+ uint8_t luma_weight_l0_flag; -+ int16_t luma_weight_l0[32]; -+ int16_t luma_offset_l0[32]; -+ uint8_t chroma_weight_l0_flag; -+ int16_t chroma_weight_l0[32][2]; -+ int16_t chroma_offset_l0[32][2]; -+ uint8_t luma_weight_l1_flag; -+ int16_t luma_weight_l1[32]; -+ int16_t luma_offset_l1[32]; -+ uint8_t chroma_weight_l1_flag; -+ int16_t chroma_weight_l1[32][2]; -+ int16_t chroma_offset_l1[32][2]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VASliceParameterBufferH264; -+ -+/**************************** -+ * Common encode data structures -+ ****************************/ -+typedef enum -+{ -+ VAEncPictureTypeIntra = 0, -+ VAEncPictureTypePredictive = 1, -+ VAEncPictureTypeBidirectional = 2, -+} VAEncPictureType; -+ -+/** -+ * \brief Encode Slice Parameter Buffer. -+ * -+ * @deprecated -+ * This is a deprecated encode slice parameter buffer, All applications -+ * \c can use VAEncSliceParameterBufferXXX (XXX = MPEG2, HEVC, H264, JPEG) -+ */ -+typedef struct _VAEncSliceParameterBuffer -+{ -+ uint32_t start_row_number; /* starting MB row number for this slice */ -+ uint32_t slice_height; /* slice height measured in MB */ -+ union { -+ struct { -+ uint32_t is_intra : 1; -+ uint32_t disable_deblocking_filter_idc : 2; -+ uint32_t uses_long_term_ref :1; -+ uint32_t is_long_term_ref :1; -+ } bits; -+ uint32_t value; -+ } slice_flags; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncSliceParameterBuffer; -+ -+ -+/**************************** -+ * H.263 specific encode data structures -+ ****************************/ -+ -+typedef struct _VAEncSequenceParameterBufferH263 -+{ -+ uint32_t intra_period; -+ uint32_t bits_per_second; -+ uint32_t frame_rate; -+ uint32_t initial_qp; -+ uint32_t min_qp; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncSequenceParameterBufferH263; -+ -+typedef struct _VAEncPictureParameterBufferH263 -+{ -+ VASurfaceID reference_picture; -+ VASurfaceID reconstructed_picture; -+ VABufferID coded_buf; -+ uint16_t picture_width; -+ uint16_t picture_height; -+ VAEncPictureType picture_type; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncPictureParameterBufferH263; -+ -+/**************************** -+ * MPEG-4 specific encode data structures -+ ****************************/ -+ -+typedef struct _VAEncSequenceParameterBufferMPEG4 -+{ -+ uint8_t profile_and_level_indication; -+ uint32_t intra_period; -+ uint32_t video_object_layer_width; -+ uint32_t video_object_layer_height; -+ uint32_t vop_time_increment_resolution; -+ uint32_t fixed_vop_rate; -+ uint32_t fixed_vop_time_increment; -+ uint32_t bits_per_second; -+ uint32_t frame_rate; -+ uint32_t initial_qp; -+ uint32_t min_qp; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncSequenceParameterBufferMPEG4; -+ -+typedef struct _VAEncPictureParameterBufferMPEG4 -+{ -+ VASurfaceID reference_picture; -+ VASurfaceID reconstructed_picture; -+ VABufferID coded_buf; -+ uint16_t picture_width; -+ uint16_t picture_height; -+ uint32_t modulo_time_base; /* number of 1s */ -+ uint32_t vop_time_increment; -+ VAEncPictureType picture_type; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAEncPictureParameterBufferMPEG4; -+ -+ -+ -+/** Buffer functions */ -+ -+/** -+ * Creates a buffer for "num_elements" elements of "size" bytes and -+ * initalize with "data". -+ * if "data" is null, then the contents of the buffer data store -+ * are undefined. -+ * Basically there are two ways to get buffer data to the server side. One is -+ * to call vaCreateBuffer() with a non-null "data", which results the data being -+ * copied to the data store on the server side. A different method that -+ * eliminates this copy is to pass null as "data" when calling vaCreateBuffer(), -+ * and then use vaMapBuffer() to map the data store from the server side to the -+ * client address space for access. -+ * The user must call vaDestroyBuffer() to destroy a buffer. -+ * Note: image buffers are created by the library, not the client. Please see -+ * vaCreateImage on how image buffers are managed. -+ */ -+VAStatus vaCreateBuffer ( -+ VADisplay dpy, -+ VAContextID context, -+ VABufferType type, /* in */ -+ unsigned int size, /* in */ -+ unsigned int num_elements, /* in */ -+ void *data, /* in */ -+ VABufferID *buf_id /* out */ -+); -+ -+/** -+ * Create a buffer for given width & height get unit_size, pitch, buf_id for 2D buffer -+ * for permb qp buffer, it will return unit_size for one MB or LCU and the pitch for alignments -+ * can call vaMapBuffer with this Buffer ID to get virtual address. -+ * e.g. AVC 1080P encode, 1920x1088, the size in MB is 120x68,but inside driver, -+ * maybe it should align with 256, and one byte present one Qp.so, call the function. -+ * then get unit_size = 1, pitch = 256. call vaMapBuffer to get the virtual address (pBuf). -+ * then read write the memory like 2D. the size is 256x68, application can only use 120x68 -+ * pBuf + 256 is the start of next line. -+ * different driver implementation maybe return different unit_size and pitch -+ */ -+VAStatus vaCreateBuffer2( -+ VADisplay dpy, -+ VAContextID context, -+ VABufferType type, -+ unsigned int width, -+ unsigned int height, -+ unsigned int *unit_size, -+ unsigned int *pitch, -+ VABufferID *buf_id -+); -+ -+/** -+ * Convey to the server how many valid elements are in the buffer. -+ * e.g. if multiple slice parameters are being held in a single buffer, -+ * this will communicate to the server the number of slice parameters -+ * that are valid in the buffer. -+ */ -+VAStatus vaBufferSetNumElements ( -+ VADisplay dpy, -+ VABufferID buf_id, /* in */ -+ unsigned int num_elements /* in */ -+); -+ -+ -+/** -+ * device independent data structure for codedbuffer -+ */ -+ -+/* -+ * FICTURE_AVE_QP(bit7-0): The average Qp value used during this frame -+ * LARGE_SLICE(bit8):At least one slice in the current frame was large -+ * enough for the encoder to attempt to limit its size. -+ * SLICE_OVERFLOW(bit9): At least one slice in the current frame has -+ * exceeded the maximum slice size specified. -+ * BITRATE_OVERFLOW(bit10): The peak bitrate was exceeded for this frame. -+ * BITRATE_HIGH(bit11): The frame size got within the safety margin of the maximum size (VCM only) -+ * AIR_MB_OVER_THRESHOLD: the number of MBs adapted to Intra MB -+ */ -+#define VA_CODED_BUF_STATUS_PICTURE_AVE_QP_MASK 0xff -+#define VA_CODED_BUF_STATUS_LARGE_SLICE_MASK 0x100 -+#define VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK 0x200 -+#define VA_CODED_BUF_STATUS_BITRATE_OVERFLOW 0x400 -+#define VA_CODED_BUF_STATUS_BITRATE_HIGH 0x800 -+/** -+ * \brief The frame has exceeded the maximum requested size. -+ * -+ * This flag indicates that the encoded frame size exceeds the value -+ * specified through a misc parameter buffer of type -+ * #VAEncMiscParameterTypeMaxFrameSize. -+ */ -+#define VA_CODED_BUF_STATUS_FRAME_SIZE_OVERFLOW 0x1000 -+/** -+ * \brief the bitstream is bad or corrupt. -+ */ -+#define VA_CODED_BUF_STATUS_BAD_BITSTREAM 0x8000 -+#define VA_CODED_BUF_STATUS_AIR_MB_OVER_THRESHOLD 0xff0000 -+ -+/** -+ * \brief The coded buffer segment status contains frame encoding passes number -+ * -+ * This is the mask to get the number of encoding passes from the coded -+ * buffer segment status. -+ * NUMBER_PASS(bit24~bit27): the number for encoding passes executed for the coded frame. -+ * -+ */ -+#define VA_CODED_BUF_STATUS_NUMBER_PASSES_MASK 0xf000000 -+ -+/** -+ * \brief The coded buffer segment contains a single NAL unit. -+ * -+ * This flag indicates that the coded buffer segment contains a -+ * single NAL unit. This flag might be useful to the user for -+ * processing the coded buffer. -+ */ -+#define VA_CODED_BUF_STATUS_SINGLE_NALU 0x10000000 -+ -+/** -+ * \brief Coded buffer segment. -+ * -+ * #VACodedBufferSegment is an element of a linked list describing -+ * some information on the coded buffer. The coded buffer segment -+ * could contain either a single NAL unit, or more than one NAL unit. -+ * It is recommended (but not required) to return a single NAL unit -+ * in a coded buffer segment, and the implementation should set the -+ * VA_CODED_BUF_STATUS_SINGLE_NALU status flag if that is the case. -+ */ -+typedef struct _VACodedBufferSegment { -+ /** -+ * \brief Size of the data buffer in this segment (in bytes). -+ */ -+ uint32_t size; -+ /** \brief Bit offset into the data buffer where the video data starts. */ -+ uint32_t bit_offset; -+ /** \brief Status set by the driver. See \c VA_CODED_BUF_STATUS_*. */ -+ uint32_t status; -+ /** \brief Reserved for future use. */ -+ uint32_t reserved; -+ /** \brief Pointer to the start of the data buffer. */ -+ void *buf; -+ /** -+ * \brief Pointer to the next #VACodedBufferSegment element, -+ * or \c NULL if there is none. -+ */ -+ void *next; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VACodedBufferSegment; -+ -+/** -+ * Map data store of the buffer into the client's address space -+ * vaCreateBuffer() needs to be called with "data" set to NULL before -+ * calling vaMapBuffer() -+ * -+ * if buffer type is VAEncCodedBufferType, pbuf points to link-list of -+ * VACodedBufferSegment, and the list is terminated if "next" is NULL -+ */ -+VAStatus vaMapBuffer ( -+ VADisplay dpy, -+ VABufferID buf_id, /* in */ -+ void **pbuf /* out */ -+); -+ -+/** -+ * After client making changes to a mapped data store, it needs to -+ * "Unmap" it to let the server know that the data is ready to be -+ * consumed by the server -+ */ -+VAStatus vaUnmapBuffer ( -+ VADisplay dpy, -+ VABufferID buf_id /* in */ -+); -+ -+/** -+ * After this call, the buffer is deleted and this buffer_id is no longer valid -+ * -+ * A buffer can be re-used and sent to the server by another Begin/Render/End -+ * sequence if vaDestroyBuffer() is not called with this buffer. -+ * -+ * Note re-using a shared buffer (e.g. a slice data buffer) between the host and the -+ * hardware accelerator can result in performance dropping. -+ */ -+VAStatus vaDestroyBuffer ( -+ VADisplay dpy, -+ VABufferID buffer_id -+); -+ -+/** \brief VA buffer information */ -+typedef struct { -+ /** \brief Buffer handle */ -+ uintptr_t handle; -+ /** \brief Buffer type (See \ref VABufferType). */ -+ uint32_t type; -+ /** -+ * \brief Buffer memory type (See \ref VASurfaceAttribMemoryType). -+ * -+ * On input to vaAcquireBufferHandle(), this field can serve as a hint -+ * to specify the set of memory types the caller is interested in. -+ * On successful return from vaAcquireBufferHandle(), the field is -+ * updated with the best matching memory type. -+ */ -+ uint32_t mem_type; -+ /** \brief Size of the underlying buffer. */ -+ size_t mem_size; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VABufferInfo; -+ -+/** -+ * \brief Acquires buffer handle for external API usage -+ * -+ * Locks the VA buffer object \ref buf_id for external API usage like -+ * EGL or OpenCL (OCL). This function is a synchronization point. This -+ * means that any pending operation is guaranteed to be completed -+ * prior to returning from the function. -+ * -+ * If the referenced VA buffer object is the backing store of a VA -+ * surface, then this function acts as if vaSyncSurface() on the -+ * parent surface was called first. -+ * -+ * The \ref VABufferInfo argument shall be zero'ed on input. On -+ * successful output, the data structure is filled in with all the -+ * necessary buffer level implementation details like handle, type, -+ * memory type and memory size. -+ * -+ * Note: the external API implementation, or the application, can -+ * express the memory types it is interested in by filling in the \ref -+ * mem_type field accordingly. On successful output, the memory type -+ * that fits best the request and that was used is updated in the \ref -+ * VABufferInfo data structure. If none of the supplied memory types -+ * is supported, then a \ref VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE -+ * error is returned. -+ * -+ * The \ref VABufferInfo data is valid until vaReleaseBufferHandle() -+ * is called. Besides, no additional operation is allowed on any of -+ * the buffer parent object until vaReleaseBufferHandle() is called. -+ * e.g. decoding into a VA surface backed with the supplied VA buffer -+ * object \ref buf_id would fail with a \ref VA_STATUS_ERROR_SURFACE_BUSY -+ * error. -+ * -+ * Possible errors: -+ * - \ref VA_STATUS_ERROR_UNIMPLEMENTED: the VA driver implementation -+ * does not support this interface -+ * - \ref VA_STATUS_ERROR_INVALID_DISPLAY: an invalid display was supplied -+ * - \ref VA_STATUS_ERROR_INVALID_BUFFER: an invalid buffer was supplied -+ * - \ref VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: the implementation -+ * does not support exporting buffers of the specified type -+ * - \ref VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE: none of the requested -+ * memory types in \ref VABufferInfo.mem_type was supported -+ * -+ * @param[in] dpy the VA display -+ * @param[in] buf_id the VA buffer -+ * @param[in,out] buf_info the associated VA buffer information -+ * @return VA_STATUS_SUCCESS if successful -+ */ -+VAStatus -+vaAcquireBufferHandle(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info); -+ -+/** -+ * \brief Releases buffer after usage from external API -+ * -+ * Unlocks the VA buffer object \ref buf_id from external API usage like -+ * EGL or OpenCL (OCL). This function is a synchronization point. This -+ * means that any pending operation is guaranteed to be completed -+ * prior to returning from the function. -+ * -+ * The \ref VABufferInfo argument shall point to the original data -+ * structure that was obtained from vaAcquireBufferHandle(), unaltered. -+ * This is necessary so that the VA driver implementation could -+ * deallocate any resources that were needed. -+ * -+ * In any case, returning from this function invalidates any contents -+ * in \ref VABufferInfo. i.e. the underlyng buffer handle is no longer -+ * valid. Therefore, VA driver implementations are free to reset this -+ * data structure to safe defaults. -+ * -+ * Possible errors: -+ * - \ref VA_STATUS_ERROR_UNIMPLEMENTED: the VA driver implementation -+ * does not support this interface -+ * - \ref VA_STATUS_ERROR_INVALID_DISPLAY: an invalid display was supplied -+ * - \ref VA_STATUS_ERROR_INVALID_BUFFER: an invalid buffer was supplied -+ * - \ref VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: the implementation -+ * does not support exporting buffers of the specified type -+ * -+ * @param[in] dpy the VA display -+ * @param[in] buf_id the VA buffer -+ * @return VA_STATUS_SUCCESS if successful -+ */ -+VAStatus -+vaReleaseBufferHandle(VADisplay dpy, VABufferID buf_id); -+ -+/** @name vaExportSurfaceHandle() flags -+ * -+ * @{ -+ */ -+/** Export surface to be read by external API. */ -+#define VA_EXPORT_SURFACE_READ_ONLY 0x0001 -+/** Export surface to be written by external API. */ -+#define VA_EXPORT_SURFACE_WRITE_ONLY 0x0002 -+/** Export surface to be both read and written by external API. */ -+#define VA_EXPORT_SURFACE_READ_WRITE 0x0003 -+/** Export surface with separate layers. -+ * -+ * For example, NV12 surfaces should be exported as two separate -+ * planes for luma and chroma. -+ */ -+#define VA_EXPORT_SURFACE_SEPARATE_LAYERS 0x0004 -+/** Export surface with composed layers. -+ * -+ * For example, NV12 surfaces should be exported as a single NV12 -+ * composed object. -+ */ -+#define VA_EXPORT_SURFACE_COMPOSED_LAYERS 0x0008 -+ -+/** @} */ -+ -+/** -+ * \brief Export a handle to a surface for use with an external API -+ * -+ * The exported handles are owned by the caller, and the caller is -+ * responsible for freeing them when no longer needed (e.g. by closing -+ * DRM PRIME file descriptors). -+ * -+ * This does not perform any synchronisation. If the contents of the -+ * surface will be read, vaSyncSurface() must be called before doing so. -+ * If the contents of the surface are written, then all operations must -+ * be completed externally before using the surface again by via VA-API -+ * functions. -+ * -+ * @param[in] dpy VA display. -+ * @param[in] surface_id Surface to export. -+ * @param[in] mem_type Memory type to export to. -+ * @param[in] flags Combination of flags to apply -+ * (VA_EXPORT_SURFACE_*). -+ * @param[out] descriptor Pointer to the descriptor structure to fill -+ * with the handle details. The type of this structure depends on -+ * the value of mem_type. -+ * -+ * @return Status code: -+ * - VA_STATUS_SUCCESS: Success. -+ * - VA_STATUS_ERROR_INVALID_DISPLAY: The display is not valid. -+ * - VA_STATUS_ERROR_UNIMPLEMENTED: The driver does not implement -+ * this interface. -+ * - VA_STATUS_ERROR_INVALID_SURFACE: The surface is not valid, or -+ * the surface is not exportable in the specified way. -+ * - VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE: The driver does not -+ * support exporting surfaces to the specified memory type. -+ */ -+VAStatus vaExportSurfaceHandle(VADisplay dpy, -+ VASurfaceID surface_id, -+ uint32_t mem_type, uint32_t flags, -+ void *descriptor); -+ -+/** -+ * Render (Video Decode/Encode/Processing) Pictures -+ * -+ * A picture represents either a frame or a field. -+ * -+ * The Begin/Render/End sequence sends the video decode/encode/processing buffers -+ * to the server -+ */ -+ -+/** -+ * Get ready for a video pipeline -+ * - decode a picture to a target surface -+ * - encode a picture from a target surface -+ * - process a picture to a target surface -+ */ -+VAStatus vaBeginPicture ( -+ VADisplay dpy, -+ VAContextID context, -+ VASurfaceID render_target -+); -+ -+/** -+ * Send video decode, encode or processing buffers to the server. -+ */ -+VAStatus vaRenderPicture ( -+ VADisplay dpy, -+ VAContextID context, -+ VABufferID *buffers, -+ int num_buffers -+); -+ -+/** -+ * Make the end of rendering for a picture. -+ * The server should start processing all pending operations for this -+ * surface. This call is non-blocking. The client can start another -+ * Begin/Render/End sequence on a different render target. -+ * if VAContextID used in this function previously successfully passed -+ * vaMFAddContext call, real processing will be started during vaMFSubmit -+ */ -+VAStatus vaEndPicture ( -+ VADisplay dpy, -+ VAContextID context -+); -+ -+/** -+ * Make the end of rendering for a pictures in contexts passed with submission. -+ * The server should start processing all pending operations for contexts. -+ * All contexts passed should be associated through vaMFAddContext -+ * and call sequence Begin/Render/End performed. -+ * This call is non-blocking. The client can start another -+ * Begin/Render/End/vaMFSubmit sequence on a different render targets. -+ * Return values: -+ * VA_STATUS_SUCCESS - operation successful, context was removed. -+ * VA_STATUS_ERROR_INVALID_CONTEXT - mf_context or one of contexts are invalid -+ * due to mf_context not created or one of contexts not assotiated with mf_context -+ * through vaAddContext. -+ * VA_STATUS_ERROR_INVALID_PARAMETER - one of context has not submitted it's frame -+ * through vaBeginPicture vaRenderPicture vaEndPicture call sequence. -+ * dpy: display -+ * mf_context: Multi-Frame context -+ * contexts: list of contexts submitting their tasks for multi-frame operation. -+ * num_contexts: number of passed contexts. -+ */ -+VAStatus vaMFSubmit ( -+ VADisplay dpy, -+ VAMFContextID mf_context, -+ VAContextID * contexts, -+ int num_contexts -+); -+ -+/* -+ -+Synchronization -+ -+*/ -+ -+/** -+ * This function blocks until all pending operations on the render target -+ * have been completed. Upon return it is safe to use the render target for a -+ * different picture. -+ */ -+VAStatus vaSyncSurface ( -+ VADisplay dpy, -+ VASurfaceID render_target -+); -+ -+typedef enum -+{ -+ VASurfaceRendering = 1, /* Rendering in progress */ -+ VASurfaceDisplaying = 2, /* Displaying in progress (not safe to render into it) */ -+ /* this status is useful if surface is used as the source */ -+ /* of an overlay */ -+ VASurfaceReady = 4, /* not being rendered or displayed */ -+ VASurfaceSkipped = 8 /* Indicate a skipped frame during encode */ -+} VASurfaceStatus; -+ -+/** -+ * Find out any pending ops on the render target -+ */ -+VAStatus vaQuerySurfaceStatus ( -+ VADisplay dpy, -+ VASurfaceID render_target, -+ VASurfaceStatus *status /* out */ -+); -+ -+typedef enum -+{ -+ VADecodeSliceMissing = 0, -+ VADecodeMBError = 1, -+} VADecodeErrorType; -+ -+/** -+ * Client calls vaQuerySurfaceError with VA_STATUS_ERROR_DECODING_ERROR, server side returns -+ * an array of structure VASurfaceDecodeMBErrors, and the array is terminated by setting status=-1 -+*/ -+typedef struct _VASurfaceDecodeMBErrors -+{ -+ int32_t status; /* 1 if hardware has returned detailed info below, -1 means this record is invalid */ -+ uint32_t start_mb; /* start mb address with errors */ -+ uint32_t end_mb; /* end mb address with errors */ -+ VADecodeErrorType decode_error_type; -+ uint32_t num_mb; /* number of mbs with errors */ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW - 1]; -+} VASurfaceDecodeMBErrors; -+ -+/** -+ * After the application gets VA_STATUS_ERROR_DECODING_ERROR after calling vaSyncSurface(), -+ * it can call vaQuerySurfaceError to find out further details on the particular error. -+ * VA_STATUS_ERROR_DECODING_ERROR should be passed in as "error_status", -+ * upon the return, error_info will point to an array of _VASurfaceDecodeMBErrors structure, -+ * which is allocated and filled by libVA with detailed information on the missing or error macroblocks. -+ * The array is terminated if "status==-1" is detected. -+ */ -+VAStatus vaQuerySurfaceError( -+ VADisplay dpy, -+ VASurfaceID surface, -+ VAStatus error_status, -+ void **error_info -+); -+ -+/** -+ * Images and Subpictures -+ * VAImage is used to either get the surface data to client memory, or -+ * to copy image data in client memory to a surface. -+ * Both images, subpictures and surfaces follow the same 2D coordinate system where origin -+ * is at the upper left corner with positive X to the right and positive Y down -+ */ -+#define VA_FOURCC(ch0, ch1, ch2, ch3) \ -+ ((unsigned long)(unsigned char) (ch0) | ((unsigned long)(unsigned char) (ch1) << 8) | \ -+ ((unsigned long)(unsigned char) (ch2) << 16) | ((unsigned long)(unsigned char) (ch3) << 24 )) -+ -+/* Pre-defined fourcc codes. */ -+ -+/** NV12: two-plane 8-bit YUV 4:2:0. -+ * The first plane contains Y, the second plane contains U and V in pairs of bytes. -+ */ -+#define VA_FOURCC_NV12 0x3231564E -+/** NV21: two-plane 8-bit YUV 4:2:0. -+ * Same as NV12, but with U and V swapped. -+ */ -+#define VA_FOURCC_NV21 0x3132564E -+ -+/** AI44: packed 4-bit YA. -+ * -+ * The bottom half of each byte contains luma, the top half contains alpha. -+ */ -+#define VA_FOURCC_AI44 0x34344149 -+ -+/** RGBA: packed 8-bit RGBA. -+ * -+ * Four bytes per pixel: red, green, blue, alpha. -+ */ -+#define VA_FOURCC_RGBA 0x41424752 -+/** RGBX: packed 8-bit RGB. -+ * -+ * Four bytes per pixel: red, green, blue, unspecified. -+ */ -+#define VA_FOURCC_RGBX 0x58424752 -+/** BGRA: packed 8-bit RGBA. -+ * -+ * Four bytes per pixel: blue, green, red, alpha. -+ */ -+#define VA_FOURCC_BGRA 0x41524742 -+/** BGRX: packed 8-bit RGB. -+ * -+ * Four bytes per pixel: blue, green, red, unspecified. -+ */ -+#define VA_FOURCC_BGRX 0x58524742 -+/** ARGB: packed 8-bit RGBA. -+ * -+ * Four bytes per pixel: alpha, red, green, blue. -+ */ -+#define VA_FOURCC_ARGB 0x42475241 -+/** XRGB: packed 8-bit RGB. -+ * -+ * Four bytes per pixel: unspecified, red, green, blue. -+ */ -+#define VA_FOURCC_XRGB 0x42475258 -+/** ABGR: packed 8-bit RGBA. -+ * -+ * Four bytes per pixel: alpha, blue, green, red. -+ */ -+#define VA_FOURCC_ABGR 0x52474241 -+/** XBGR: packed 8-bit RGB. -+ * -+ * Four bytes per pixel: unspecified, blue, green, red. -+ */ -+#define VA_FOURCC_XBGR 0x52474258 -+ -+/** UYUV: packed 8-bit YUV 4:2:2. -+ * -+ * Four bytes per pair of pixels: U, Y, U, V. -+ */ -+#define VA_FOURCC_UYVY 0x59565955 -+/** YUY2: packed 8-bit YUV 4:2:2. -+ * -+ * Four bytes per pair of pixels: Y, U, Y, V. -+ */ -+#define VA_FOURCC_YUY2 0x32595559 -+/** AYUV: packed 8-bit YUVA 4:4:4. -+ * -+ * Four bytes per pixel: A, Y, U, V. -+ */ -+#define VA_FOURCC_AYUV 0x56555941 -+/** NV11: two-plane 8-bit YUV 4:1:1. -+ * -+ * The first plane contains Y, the second plane contains U and V in pairs of bytes. -+ */ -+#define VA_FOURCC_NV11 0x3131564e -+/** YV12: three-plane 8-bit YUV 4:2:0. -+ * -+ * The three planes contain Y, V and U respectively. -+ */ -+#define VA_FOURCC_YV12 0x32315659 -+/** P208: two-plane 8-bit YUV 4:2:2. -+ * -+ * The first plane contains Y, the second plane contains U and V in pairs of bytes. -+ */ -+#define VA_FOURCC_P208 0x38303250 -+/** I420: three-plane 8-bit YUV 4:2:0. -+ * -+ * The three planes contain Y, U and V respectively. -+ */ -+#define VA_FOURCC_I420 0x30323449 -+/** YV24: three-plane 8-bit YUV 4:4:4. -+ * -+ * The three planes contain Y, V and U respectively. -+ */ -+#define VA_FOURCC_YV24 0x34325659 -+/** YV32: four-plane 8-bit YUVA 4:4:4 -+ * -+ * The four planes contain Y, V, U and A respectively. -+ */ -+#define VA_FOURCC_YV32 0x32335659 -+/** Y800: 8-bit greyscale. -+ */ -+#define VA_FOURCC_Y800 0x30303859 -+/** IMC3: three-plane 8-bit YUV 4:2:0. -+ * -+ * Equivalent to YV12, but with the additional constraint that the pitch of all three planes -+ * must be the same. -+ */ -+#define VA_FOURCC_IMC3 0x33434D49 -+/** 411P: three-plane 8-bit YUV 4:1:1. -+ * -+ * The three planes contain Y, U and V respectively. -+ */ -+#define VA_FOURCC_411P 0x50313134 -+/** 411R: three-plane 8-bit YUV. -+ * -+ * The subsampling is the transpose of 4:1:1 - full chroma appears on every fourth line. -+ * The three planes contain Y, U and V respectively. -+ */ -+#define VA_FOURCC_411R 0x52313134 -+/** 422H: three-plane 8-bit YUV 4:2:2. -+ * -+ * The three planes contain Y, U and V respectively. -+ */ -+#define VA_FOURCC_422H 0x48323234 -+/** 422V: three-plane 8-bit YUV 4:4:0. -+ * -+ * The three planes contain Y, U and V respectively. -+ */ -+#define VA_FOURCC_422V 0x56323234 -+/** 444P: three-plane 8-bit YUV 4:4:4. -+ * -+ * The three planes contain Y, U and V respectively. -+ */ -+#define VA_FOURCC_444P 0x50343434 -+ -+/** RGBP: three-plane 8-bit RGB. -+ * -+ * The three planes contain red, green and blue respectively. -+ */ -+#define VA_FOURCC_RGBP 0x50424752 -+/** BGRP: three-plane 8-bit RGB. -+ * -+ * The three planes contain blue, green and red respectively. -+ */ -+#define VA_FOURCC_BGRP 0x50524742 -+/** RG16: packed 5/6-bit RGB. -+ * -+ * Each pixel is a two-byte little-endian value. -+ * Red, green and blue are found in bits 15:11, 10:5, 4:0 respectively. -+ */ -+#define VA_FOURCC_RGB565 0x36314752 -+/** BG16: packed 5/6-bit RGB. -+ * -+ * Each pixel is a two-byte little-endian value. -+ * Blue, green and red are found in bits 15:11, 10:5, 4:0 respectively. -+ */ -+#define VA_FOURCC_BGR565 0x36314742 -+ -+/** Y210: packed 10-bit YUV 4:2:2. -+ * -+ * Eight bytes represent a pair of pixels. Each sample is a two-byte little-endian value, -+ * with the bottom six bits ignored. The samples are in the order Y, U, Y, V. -+ */ -+#define VA_FOURCC_Y210 0x30313259 -+/** Y216: packed 16-bit YUV 4:2:2. -+ * -+ * Eight bytes represent a pair of pixels. Each sample is a two-byte little-endian value. -+ * The samples are in the order Y, U, Y, V. -+ */ -+#define VA_FOURCC_Y216 0x36313259 -+/** Y410: packed 10-bit YUVA 4:4:4. -+ * -+ * Each pixel is a four-byte little-endian value. -+ * A, V, Y, U are found in bits 31:30, 29:20, 19:10, 9:0 respectively. -+ */ -+#define VA_FOURCC_Y410 0x30313459 -+/** Y416: packed 16-bit YUVA 4:4:4. -+ * -+ * Each pixel is a set of four samples, each of which is a two-byte little-endian value. -+ * The samples are in the order A, V, Y, U. -+ */ -+#define VA_FOURCC_Y416 0x36313459 -+ -+/** YV16: three-plane 8-bit YUV 4:2:2. -+ * -+ * The three planes contain Y, V and U respectively. -+ */ -+#define VA_FOURCC_YV16 0x36315659 -+/** P010: two-plane 10-bit YUV 4:2:0. -+ * -+ * Each sample is a two-byte little-endian value with the bottom six bits ignored. -+ * The first plane contains Y, the second plane contains U and V in pairs of samples. -+ */ -+#define VA_FOURCC_P010 0x30313050 -+/** P016: two-plane 16-bit YUV 4:2:0. -+ * -+ * Each sample is a two-byte little-endian value. The first plane contains Y, the second -+ * plane contains U and V in pairs of samples. -+ */ -+#define VA_FOURCC_P016 0x36313050 -+ -+/** I010: three-plane 10-bit YUV 4:2:0. -+ * -+ * Each sample is a two-byte little-endian value with the top six bits ignored. -+ * The three planes contain Y, V and U respectively. -+ */ -+#define VA_FOURCC_I010 0x30313049 -+ -+/** IYUV: three-plane 8-bit YUV 4:2:0. -+ * -+ * @deprecated Use I420 instead. -+ */ -+#define VA_FOURCC_IYUV 0x56555949 -+/** -+ * 10-bit Pixel RGB formats. -+ */ -+#define VA_FOURCC_A2R10G10B10 0x30335241 /* VA_FOURCC('A','R','3','0') */ -+/** -+ * 10-bit Pixel BGR formats. -+ */ -+#define VA_FOURCC_A2B10G10R10 0x30334241 /* VA_FOURCC('A','B','3','0') */ -+ -+/** Y8: 8-bit greyscale. -+ * -+ * Only a single sample, 8 bit Y plane for monochrome images -+ */ -+#define VA_FOURCC_Y8 0x20203859 -+/** Y16: 16-bit greyscale. -+ * -+ * Only a single sample, 16 bit Y plane for monochrome images -+ */ -+#define VA_FOURCC_Y16 0x20363159 -+/** VYUV: packed 8-bit YUV 4:2:2. -+ * -+ * Four bytes per pair of pixels: V, Y, U, V. -+ */ -+#define VA_FOURCC_VYUY 0x59555956 -+/** YVYU: packed 8-bit YUV 4:2:2. -+ * -+ * Four bytes per pair of pixels: Y, V, Y, U. -+ */ -+#define VA_FOURCC_YVYU 0x55595659 -+/** AGRB64: three-plane 16-bit ARGB 16:16:16:16 -+ * -+ * The four planes contain: alpha, red, green, blue respectively. -+ */ -+#define VA_FOURCC_ARGB64 0x34475241 -+/** ABGR64: three-plane 16-bit ABGR 16:16:16:16 -+ * -+ * The four planes contain: alpha, blue, green, red respectively. -+ */ -+#define VA_FOURCC_ABGR64 0x34474241 -+ -+/* byte order */ -+#define VA_LSB_FIRST 1 -+#define VA_MSB_FIRST 2 -+ -+typedef struct _VAImageFormat -+{ -+ uint32_t fourcc; -+ uint32_t byte_order; /* VA_LSB_FIRST, VA_MSB_FIRST */ -+ uint32_t bits_per_pixel; -+ /* for RGB formats */ -+ uint32_t depth; /* significant bits per pixel */ -+ uint32_t red_mask; -+ uint32_t green_mask; -+ uint32_t blue_mask; -+ uint32_t alpha_mask; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAImageFormat; -+ -+typedef VAGenericID VAImageID; -+ -+typedef struct _VAImage -+{ -+ VAImageID image_id; /* uniquely identify this image */ -+ VAImageFormat format; -+ VABufferID buf; /* image data buffer */ -+ /* -+ * Image data will be stored in a buffer of type VAImageBufferType to facilitate -+ * data store on the server side for optimal performance. The buffer will be -+ * created by the CreateImage function, and proper storage allocated based on the image -+ * size and format. This buffer is managed by the library implementation, and -+ * accessed by the client through the buffer Map/Unmap functions. -+ */ -+ uint16_t width; -+ uint16_t height; -+ uint32_t data_size; -+ uint32_t num_planes; /* can not be greater than 3 */ -+ /* -+ * An array indicating the scanline pitch in bytes for each plane. -+ * Each plane may have a different pitch. Maximum 3 planes for planar formats -+ */ -+ uint32_t pitches[3]; -+ /* -+ * An array indicating the byte offset from the beginning of the image data -+ * to the start of each plane. -+ */ -+ uint32_t offsets[3]; -+ -+ /* The following fields are only needed for paletted formats */ -+ int32_t num_palette_entries; /* set to zero for non-palette images */ -+ /* -+ * Each component is one byte and entry_bytes indicates the number of components in -+ * each entry (eg. 3 for YUV palette entries). set to zero for non-palette images -+ */ -+ int32_t entry_bytes; -+ /* -+ * An array of ascii characters describing the order of the components within the bytes. -+ * Only entry_bytes characters of the string are used. -+ */ -+ int8_t component_order[4]; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAImage; -+ -+/** Get maximum number of image formats supported by the implementation */ -+int vaMaxNumImageFormats ( -+ VADisplay dpy -+); -+ -+/** -+ * Query supported image formats -+ * The caller must provide a "format_list" array that can hold at -+ * least vaMaxNumImageFormats() entries. The actual number of formats -+ * returned in "format_list" is returned in "num_formats". -+ */ -+VAStatus vaQueryImageFormats ( -+ VADisplay dpy, -+ VAImageFormat *format_list, /* out */ -+ int *num_formats /* out */ -+); -+ -+/** -+ * Create a VAImage structure -+ * The width and height fields returned in the VAImage structure may get -+ * enlarged for some YUV formats. Upon return from this function, -+ * image->buf has been created and proper storage allocated by the library. -+ * The client can access the image through the Map/Unmap calls. -+ */ -+VAStatus vaCreateImage ( -+ VADisplay dpy, -+ VAImageFormat *format, -+ int width, -+ int height, -+ VAImage *image /* out */ -+); -+ -+/** -+ * Should call DestroyImage before destroying the surface it is bound to -+ */ -+VAStatus vaDestroyImage ( -+ VADisplay dpy, -+ VAImageID image -+); -+ -+VAStatus vaSetImagePalette ( -+ VADisplay dpy, -+ VAImageID image, -+ /* -+ * pointer to an array holding the palette data. The size of the array is -+ * num_palette_entries * entry_bytes in size. The order of the components -+ * in the palette is described by the component_order in VAImage struct -+ */ -+ unsigned char *palette -+); -+ -+/** -+ * Retrive surface data into a VAImage -+ * Image must be in a format supported by the implementation -+ */ -+VAStatus vaGetImage ( -+ VADisplay dpy, -+ VASurfaceID surface, -+ int x, /* coordinates of the upper left source pixel */ -+ int y, -+ unsigned int width, /* width and height of the region */ -+ unsigned int height, -+ VAImageID image -+); -+ -+/** -+ * Copy data from a VAImage to a surface -+ * Image must be in a format supported by the implementation -+ * Returns a VA_STATUS_ERROR_SURFACE_BUSY if the surface -+ * shouldn't be rendered into when this is called -+ */ -+VAStatus vaPutImage ( -+ VADisplay dpy, -+ VASurfaceID surface, -+ VAImageID image, -+ int src_x, -+ int src_y, -+ unsigned int src_width, -+ unsigned int src_height, -+ int dest_x, -+ int dest_y, -+ unsigned int dest_width, -+ unsigned int dest_height -+); -+ -+/** -+ * Derive an VAImage from an existing surface. -+ * This interface will derive a VAImage and corresponding image buffer from -+ * an existing VA Surface. The image buffer can then be mapped/unmapped for -+ * direct CPU access. This operation is only possible on implementations with -+ * direct rendering capabilities and internal surface formats that can be -+ * represented with a VAImage. When the operation is not possible this interface -+ * will return VA_STATUS_ERROR_OPERATION_FAILED. Clients should then fall back -+ * to using vaCreateImage + vaPutImage to accomplish the same task in an -+ * indirect manner. -+ * -+ * Implementations should only return success when the resulting image buffer -+ * would be useable with vaMap/Unmap. -+ * -+ * When directly accessing a surface special care must be taken to insure -+ * proper synchronization with the graphics hardware. Clients should call -+ * vaQuerySurfaceStatus to insure that a surface is not the target of concurrent -+ * rendering or currently being displayed by an overlay. -+ * -+ * Additionally nothing about the contents of a surface should be assumed -+ * following a vaPutSurface. Implementations are free to modify the surface for -+ * scaling or subpicture blending within a call to vaPutImage. -+ * -+ * Calls to vaPutImage or vaGetImage using the same surface from which the image -+ * has been derived will return VA_STATUS_ERROR_SURFACE_BUSY. vaPutImage or -+ * vaGetImage with other surfaces is supported. -+ * -+ * An image created with vaDeriveImage should be freed with vaDestroyImage. The -+ * image and image buffer structures will be destroyed; however, the underlying -+ * surface will remain unchanged until freed with vaDestroySurfaces. -+ */ -+VAStatus vaDeriveImage ( -+ VADisplay dpy, -+ VASurfaceID surface, -+ VAImage *image /* out */ -+); -+ -+/** -+ * Subpictures -+ * Subpicture is a special type of image that can be blended -+ * with a surface during vaPutSurface(). Subpicture can be used to render -+ * DVD sub-titles or closed captioning text etc. -+ */ -+ -+typedef VAGenericID VASubpictureID; -+ -+/** Get maximum number of subpicture formats supported by the implementation */ -+int vaMaxNumSubpictureFormats ( -+ VADisplay dpy -+); -+ -+/** flags for subpictures */ -+#define VA_SUBPICTURE_CHROMA_KEYING 0x0001 -+#define VA_SUBPICTURE_GLOBAL_ALPHA 0x0002 -+#define VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD 0x0004 -+/** -+ * Query supported subpicture formats -+ * The caller must provide a "format_list" array that can hold at -+ * least vaMaxNumSubpictureFormats() entries. The flags arrary holds the flag -+ * for each format to indicate additional capabilities for that format. The actual -+ * number of formats returned in "format_list" is returned in "num_formats". -+ * flags: returned value to indicate addtional capabilities -+ * VA_SUBPICTURE_CHROMA_KEYING - supports chroma-keying -+ * VA_SUBPICTURE_GLOBAL_ALPHA - supports global alpha -+ * VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD - supports unscaled screen relative subpictures for On Screen Display -+ */ -+ -+VAStatus vaQuerySubpictureFormats ( -+ VADisplay dpy, -+ VAImageFormat *format_list, /* out */ -+ unsigned int *flags, /* out */ -+ unsigned int *num_formats /* out */ -+); -+ -+/** -+ * Subpictures are created with an image associated. -+ */ -+VAStatus vaCreateSubpicture ( -+ VADisplay dpy, -+ VAImageID image, -+ VASubpictureID *subpicture /* out */ -+); -+ -+/** -+ * Destroy the subpicture before destroying the image it is assocated to -+ */ -+VAStatus vaDestroySubpicture ( -+ VADisplay dpy, -+ VASubpictureID subpicture -+); -+ -+/** -+ * Bind an image to the subpicture. This image will now be associated with -+ * the subpicture instead of the one at creation. -+ */ -+VAStatus vaSetSubpictureImage ( -+ VADisplay dpy, -+ VASubpictureID subpicture, -+ VAImageID image -+); -+ -+/** -+ * If chromakey is enabled, then the area where the source value falls within -+ * the chromakey [min, max] range is transparent -+ * The chromakey component format is the following: -+ * For RGB: [0:7] Red [8:15] Blue [16:23] Green -+ * For YUV: [0:7] V [8:15] U [16:23] Y -+ * The chromakey mask can be used to mask out certain components for chromakey -+ * comparision -+ */ -+VAStatus vaSetSubpictureChromakey ( -+ VADisplay dpy, -+ VASubpictureID subpicture, -+ unsigned int chromakey_min, -+ unsigned int chromakey_max, -+ unsigned int chromakey_mask -+); -+ -+/** -+ * Global alpha value is between 0 and 1. A value of 1 means fully opaque and -+ * a value of 0 means fully transparent. If per-pixel alpha is also specified then -+ * the overall alpha is per-pixel alpha multiplied by the global alpha -+ */ -+VAStatus vaSetSubpictureGlobalAlpha ( -+ VADisplay dpy, -+ VASubpictureID subpicture, -+ float global_alpha -+); -+ -+/** -+ * vaAssociateSubpicture associates the subpicture with target_surfaces. -+ * It defines the region mapping between the subpicture and the target -+ * surfaces through source and destination rectangles (with the same width and height). -+ * Both will be displayed at the next call to vaPutSurface. Additional -+ * associations before the call to vaPutSurface simply overrides the association. -+ */ -+VAStatus vaAssociateSubpicture ( -+ VADisplay dpy, -+ VASubpictureID subpicture, -+ VASurfaceID *target_surfaces, -+ int num_surfaces, -+ int16_t src_x, /* upper left offset in subpicture */ -+ int16_t src_y, -+ uint16_t src_width, -+ uint16_t src_height, -+ int16_t dest_x, /* upper left offset in surface */ -+ int16_t dest_y, -+ uint16_t dest_width, -+ uint16_t dest_height, -+ /* -+ * whether to enable chroma-keying, global-alpha, or screen relative mode -+ * see VA_SUBPICTURE_XXX values -+ */ -+ uint32_t flags -+); -+ -+/** -+ * vaDeassociateSubpicture removes the association of the subpicture with target_surfaces. -+ */ -+VAStatus vaDeassociateSubpicture ( -+ VADisplay dpy, -+ VASubpictureID subpicture, -+ VASurfaceID *target_surfaces, -+ int num_surfaces -+); -+ -+/** -+ * Display attributes -+ * Display attributes are used to control things such as contrast, hue, saturation, -+ * brightness etc. in the rendering process. The application can query what -+ * attributes are supported by the driver, and then set the appropriate attributes -+ * before calling vaPutSurface() -+ */ -+/* PowerVR IEP Lite attributes */ -+typedef enum -+{ -+ VADISPLAYATTRIB_BLE_OFF = 0x00, -+ VADISPLAYATTRIB_BLE_LOW, -+ VADISPLAYATTRIB_BLE_MEDIUM, -+ VADISPLAYATTRIB_BLE_HIGH, -+ VADISPLAYATTRIB_BLE_NONE, -+} VADisplayAttribBLEMode; -+ -+/** attribute value for VADisplayAttribRotation */ -+#define VA_ROTATION_NONE 0x00000000 -+#define VA_ROTATION_90 0x00000001 -+#define VA_ROTATION_180 0x00000002 -+#define VA_ROTATION_270 0x00000003 -+/**@}*/ -+ -+/** -+ * @name Mirroring directions -+ * -+ * Those values could be used for VADisplayAttribMirror attribute or -+ * VAProcPipelineParameterBuffer::mirror_state. -+ -+ */ -+/**@{*/ -+/** \brief No Mirroring. */ -+#define VA_MIRROR_NONE 0x00000000 -+/** \brief Horizontal Mirroring. */ -+#define VA_MIRROR_HORIZONTAL 0x00000001 -+/** \brief Vertical Mirroring. */ -+#define VA_MIRROR_VERTICAL 0x00000002 -+/**@}*/ -+ -+/** attribute value for VADisplayAttribOutOfLoopDeblock */ -+#define VA_OOL_DEBLOCKING_FALSE 0x00000000 -+#define VA_OOL_DEBLOCKING_TRUE 0x00000001 -+ -+/** Render mode */ -+#define VA_RENDER_MODE_UNDEFINED 0 -+#define VA_RENDER_MODE_LOCAL_OVERLAY 1 -+#define VA_RENDER_MODE_LOCAL_GPU 2 -+#define VA_RENDER_MODE_EXTERNAL_OVERLAY 4 -+#define VA_RENDER_MODE_EXTERNAL_GPU 8 -+ -+/** Render device */ -+#define VA_RENDER_DEVICE_UNDEFINED 0 -+#define VA_RENDER_DEVICE_LOCAL 1 -+#define VA_RENDER_DEVICE_EXTERNAL 2 -+ -+/** Currently defined display attribute types */ -+typedef enum -+{ -+ VADisplayAttribBrightness = 0, -+ VADisplayAttribContrast = 1, -+ VADisplayAttribHue = 2, -+ VADisplayAttribSaturation = 3, -+ /* client can specifiy a background color for the target window -+ * the new feature of video conference, -+ * the uncovered area of the surface is filled by this color -+ * also it will blend with the decoded video color -+ */ -+ VADisplayAttribBackgroundColor = 4, -+ /* -+ * this is a gettable only attribute. For some implementations that use the -+ * hardware overlay, after PutSurface is called, the surface can not be -+ * re-used until after the subsequent PutSurface call. If this is the case -+ * then the value for this attribute will be set to 1 so that the client -+ * will not attempt to re-use the surface right after returning from a call -+ * to PutSurface. -+ * -+ * Don't use it, use flag VASurfaceDisplaying of vaQuerySurfaceStatus since -+ * driver may use overlay or GPU alternatively -+ */ -+ VADisplayAttribDirectSurface = 5, -+ VADisplayAttribRotation = 6, -+ VADisplayAttribOutofLoopDeblock = 7, -+ -+ /* PowerVR IEP Lite specific attributes */ -+ VADisplayAttribBLEBlackMode = 8, -+ VADisplayAttribBLEWhiteMode = 9, -+ VADisplayAttribBlueStretch = 10, -+ VADisplayAttribSkinColorCorrection = 11, -+ /* -+ * For type VADisplayAttribCSCMatrix, "value" field is a pointer to the color -+ * conversion matrix. Each element in the matrix is float-point -+ */ -+ VADisplayAttribCSCMatrix = 12, -+ /* specify the constant color used to blend with video surface -+ * Cd = Cv*Cc*Ac + Cb *(1 - Ac) C means the constant RGB -+ * d: the final color to overwrite into the frame buffer -+ * v: decoded video after color conversion, -+ * c: video color specified by VADisplayAttribBlendColor -+ * b: background color of the drawable -+ */ -+ VADisplayAttribBlendColor = 13, -+ /* -+ * Indicate driver to skip painting color key or not. -+ * only applicable if the render is overlay -+ */ -+ VADisplayAttribOverlayAutoPaintColorKey = 14, -+ /* -+ * customized overlay color key, the format is RGB888 -+ * [23:16] = Red, [15:08] = Green, [07:00] = Blue. -+ */ -+ VADisplayAttribOverlayColorKey = 15, -+ /* -+ * The hint for the implementation of vaPutSurface -+ * normally, the driver could use an overlay or GPU to render the surface on the screen -+ * this flag provides APP the flexibity to switch the render dynamically -+ */ -+ VADisplayAttribRenderMode = 16, -+ /* -+ * specify if vaPutSurface needs to render into specified monitors -+ * one example is that one external monitor (e.g. HDMI) is enabled, -+ * but the window manager is not aware of it, and there is no associated drawable -+ */ -+ VADisplayAttribRenderDevice = 17, -+ /* -+ * specify vaPutSurface render area if there is no drawable on the monitor -+ */ -+ VADisplayAttribRenderRect = 18, -+} VADisplayAttribType; -+ -+/* flags for VADisplayAttribute */ -+#define VA_DISPLAY_ATTRIB_NOT_SUPPORTED 0x0000 -+#define VA_DISPLAY_ATTRIB_GETTABLE 0x0001 -+#define VA_DISPLAY_ATTRIB_SETTABLE 0x0002 -+ -+typedef struct _VADisplayAttribute -+{ -+ VADisplayAttribType type; -+ int32_t min_value; -+ int32_t max_value; -+ int32_t value; /* used by the set/get attribute functions */ -+/* flags can be VA_DISPLAY_ATTRIB_GETTABLE or VA_DISPLAY_ATTRIB_SETTABLE or OR'd together */ -+ uint32_t flags; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VADisplayAttribute; -+ -+/** Get maximum number of display attributs supported by the implementation */ -+int vaMaxNumDisplayAttributes ( -+ VADisplay dpy -+); -+ -+/** -+ * Query display attributes -+ * The caller must provide a "attr_list" array that can hold at -+ * least vaMaxNumDisplayAttributes() entries. The actual number of attributes -+ * returned in "attr_list" is returned in "num_attributes". -+ */ -+VAStatus vaQueryDisplayAttributes ( -+ VADisplay dpy, -+ VADisplayAttribute *attr_list, /* out */ -+ int *num_attributes /* out */ -+); -+ -+/** -+ * Get display attributes -+ * This function returns the current attribute values in "attr_list". -+ * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field -+ * from vaQueryDisplayAttributes() can have their values retrieved. -+ */ -+VAStatus vaGetDisplayAttributes ( -+ VADisplay dpy, -+ VADisplayAttribute *attr_list, /* in/out */ -+ int num_attributes -+); -+ -+/** -+ * Set display attributes -+ * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field -+ * from vaQueryDisplayAttributes() can be set. If the attribute is not settable or -+ * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED -+ */ -+VAStatus vaSetDisplayAttributes ( -+ VADisplay dpy, -+ VADisplayAttribute *attr_list, -+ int num_attributes -+); -+ -+/**************************** -+ * HEVC data structures -+ ****************************/ -+/** -+ * \brief Description of picture properties of those in DPB surfaces. -+ * -+ * If only progressive scan is supported, each surface contains one whole -+ * frame picture. -+ * Otherwise, each surface contains two fields of whole picture. -+ * In this case, two entries of ReferenceFrames[] may share same picture_id -+ * value. -+ */ -+typedef struct _VAPictureHEVC -+{ -+ /** \brief reconstructed picture buffer surface index -+ * invalid when taking value VA_INVALID_SURFACE. -+ */ -+ VASurfaceID picture_id; -+ /** \brief picture order count. -+ * in HEVC, POCs for top and bottom fields of same picture should -+ * take different values. -+ */ -+ int32_t pic_order_cnt; -+ /* described below */ -+ uint32_t flags; -+ -+ /** \brief Reserved bytes for future use, must be zero */ -+ uint32_t va_reserved[VA_PADDING_LOW]; -+} VAPictureHEVC; -+ -+/* flags in VAPictureHEVC could be OR of the following */ -+#define VA_PICTURE_HEVC_INVALID 0x00000001 -+/** \brief indication of interlace scan picture. -+ * should take same value for all the pictures in sequence. -+ */ -+#define VA_PICTURE_HEVC_FIELD_PIC 0x00000002 -+/** \brief polarity of the field picture. -+ * top field takes even lines of buffer surface. -+ * bottom field takes odd lines of buffer surface. -+ */ -+#define VA_PICTURE_HEVC_BOTTOM_FIELD 0x00000004 -+/** \brief Long term reference picture */ -+#define VA_PICTURE_HEVC_LONG_TERM_REFERENCE 0x00000008 -+/** -+ * VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE, VA_PICTURE_HEVC_RPS_ST_CURR_AFTER -+ * and VA_PICTURE_HEVC_RPS_LT_CURR of any picture in ReferenceFrames[] should -+ * be exclusive. No more than one of them can be set for any picture. -+ * Sum of NumPocStCurrBefore, NumPocStCurrAfter and NumPocLtCurr -+ * equals NumPocTotalCurr, which should be equal to or smaller than 8. -+ * Application should provide valid values for both short format and long format. -+ * The pictures in DPB with any of these three flags turned on are referred by -+ * the current picture. -+ */ -+/** \brief RefPicSetStCurrBefore of HEVC spec variable -+ * Number of ReferenceFrames[] entries with this bit set equals -+ * NumPocStCurrBefore. -+ */ -+#define VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE 0x00000010 -+/** \brief RefPicSetStCurrAfter of HEVC spec variable -+ * Number of ReferenceFrames[] entries with this bit set equals -+ * NumPocStCurrAfter. -+ */ -+#define VA_PICTURE_HEVC_RPS_ST_CURR_AFTER 0x00000020 -+/** \brief RefPicSetLtCurr of HEVC spec variable -+ * Number of ReferenceFrames[] entries with this bit set equals -+ * NumPocLtCurr. -+ */ -+#define VA_PICTURE_HEVC_RPS_LT_CURR 0x00000040 -+ -+//#include -+//#include -+#include "va_dec_vp8.h" -+#include "va_dec_vp9.h" -+//#include -+//#include -+//#include -+//#include -+//#include -+//#include -+//#include -+//#include -+//#include -+//#include -+ -+/**@}*/ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _VA_H_ */ -diff -up firefox-84.0/media/ffvpx/va/va.patch.ffvpx firefox-84.0/media/ffvpx/va/va.patch ---- firefox-84.0/media/ffvpx/va/va.patch.ffvpx 2020-12-10 20:40:53.391541423 +0100 -+++ firefox-84.0/media/ffvpx/va/va.patch 2020-12-10 20:40:53.391541423 +0100 -@@ -0,0 +1,33 @@ -+--- va.h.old 2020-10-22 10:41:57.805112031 +0200 -++++ va.h 2020-10-22 10:37:22.597088670 +0200 -+@@ -4613,18 +4613,18 @@ -+ #define VA_PICTURE_HEVC_RPS_LT_CURR 0x00000040 -+ -+-#include -+-#include -++//#include -++//#include -+ #include "va_dec_vp8.h" -+ #include "va_dec_vp9.h" -+-#include -+-#include -+-#include -+-#include -+-#include -+-#include -+-#include -+-#include -+-#include -+-#include -++//#include -++//#include -++//#include -++//#include -++//#include -++//#include -++//#include -++//#include -++//#include -++//#include -+ -+ /**@}*/ -diff -up firefox-84.0/media/ffvpx/va/va_version.h.ffvpx firefox-84.0/media/ffvpx/va/va_version.h ---- firefox-84.0/media/ffvpx/va/va_version.h.ffvpx 2020-12-10 20:40:53.391541423 +0100 -+++ firefox-84.0/media/ffvpx/va/va_version.h 2020-12-10 20:40:53.391541423 +0100 -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sub license, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef VA_VERSION_H -+#define VA_VERSION_H -+ -+/** -+ * VA_MAJOR_VERSION: -+ * -+ * The major version of VA-API (1, if %VA_VERSION is 1.2.3) -+ */ -+#define VA_MAJOR_VERSION 1 -+ -+/** -+ * VA_MINOR_VERSION: -+ * -+ * The minor version of VA-API (2, if %VA_VERSION is 1.2.3) -+ */ -+#define VA_MINOR_VERSION 7 -+ -+/** -+ * VA_MICRO_VERSION: -+ * -+ * The micro version of VA-API (3, if %VA_VERSION is 1.2.3) -+ */ -+#define VA_MICRO_VERSION 0 -+ -+/** -+ * VA_VERSION: -+ * -+ * The full version of VA-API, like 1.2.3 -+ */ -+#define VA_VERSION 1.7.0 -+ -+/** -+ * VA_VERSION_S: -+ * -+ * The full version of VA-API, in string form (suited for string -+ * concatenation) -+ */ -+#define VA_VERSION_S "1.7.0" -+ -+/** -+ * VA_VERSION_HEX: -+ * -+ * Numerically encoded version of VA-API, like 0x010203 -+ */ -+#define VA_VERSION_HEX ((VA_MAJOR_VERSION << 24) | \ -+ (VA_MINOR_VERSION << 16) | \ -+ (VA_MICRO_VERSION << 8)) -+ -+/** -+ * VA_CHECK_VERSION: -+ * @major: major version, like 1 in 1.2.3 -+ * @minor: minor version, like 2 in 1.2.3 -+ * @micro: micro version, like 3 in 1.2.3 -+ * -+ * Evaluates to %TRUE if the version of VA-API is greater than -+ * @major, @minor and @micro -+ */ -+#define VA_CHECK_VERSION(major,minor,micro) \ -+ (VA_MAJOR_VERSION > (major) || \ -+ (VA_MAJOR_VERSION == (major) && VA_MINOR_VERSION > (minor)) || \ -+ (VA_MAJOR_VERSION == (major) && VA_MINOR_VERSION == (minor) && VA_MICRO_VERSION >= (micro))) -+ -+#endif /* VA_VERSION_H */ -diff -up firefox-84.0/widget/gtk/DMABufSurface.h.ffvpx firefox-84.0/widget/gtk/DMABufSurface.h ---- firefox-84.0/widget/gtk/DMABufSurface.h.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/widget/gtk/DMABufSurface.h 2020-12-10 20:40:53.391541423 +0100 -@@ -8,10 +8,9 @@ - #define DMABufSurface_h__ - - #include --#include "GLContext.h" --#include "GLContextTypes.h" - #include "mozilla/widget/nsWaylandDisplay.h" - #include "mozilla/widget/va_drmcommon.h" -+#include "GLTypes.h" - - typedef void* EGLImageKHR; - typedef void* EGLSyncKHR; -@@ -23,6 +22,9 @@ namespace layers { - class SurfaceDescriptor; - class SurfaceDescriptorDMABuf; - } // namespace layers -+namespace gl { -+class GLContext; -+} - } // namespace mozilla - - typedef enum { -diff -up firefox-84.0/widget/gtk/nsWaylandDisplay.cpp.ffvpx firefox-84.0/widget/gtk/nsWaylandDisplay.cpp ---- firefox-84.0/widget/gtk/nsWaylandDisplay.cpp.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/widget/gtk/nsWaylandDisplay.cpp 2020-12-10 20:40:53.391541423 +0100 -@@ -6,6 +6,10 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "nsWaylandDisplay.h" -+ -+#include "base/message_loop.h" // for MessageLoop -+#include "base/task.h" // for NewRunnableMethod, etc -+#include "mozilla/StaticMutex.h" - #include "mozilla/StaticPrefs_widget.h" - - namespace mozilla { -diff -up firefox-84.0/widget/gtk/nsWaylandDisplay.h.ffvpx firefox-84.0/widget/gtk/nsWaylandDisplay.h ---- firefox-84.0/widget/gtk/nsWaylandDisplay.h.ffvpx 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/widget/gtk/nsWaylandDisplay.h 2020-12-10 20:40:53.391541423 +0100 -@@ -10,10 +10,6 @@ - - #include "DMABufLibWrapper.h" - --#include "base/message_loop.h" // for MessageLoop --#include "base/task.h" // for NewRunnableMethod, etc --#include "mozilla/StaticMutex.h" -- - #include "mozilla/widget/mozwayland.h" - #include "mozilla/widget/gbm.h" - #include "mozilla/widget/gtk-primary-selection-client-protocol.h" diff --git a/firefox-testing.patch b/firefox-testing.patch index 965dd1a..ae07de4 100644 --- a/firefox-testing.patch +++ b/firefox-testing.patch @@ -1,6 +1,6 @@ -diff -up firefox-84.0/docshell/base/crashtests/crashtests.list.testing firefox-84.0/docshell/base/crashtests/crashtests.list ---- firefox-84.0/docshell/base/crashtests/crashtests.list.testing 2020-12-07 23:32:58.000000000 +0100 -+++ firefox-84.0/docshell/base/crashtests/crashtests.list 2020-12-10 12:42:49.725237640 +0100 +diff -up firefox-85.0/docshell/base/crashtests/crashtests.list.testing firefox-85.0/docshell/base/crashtests/crashtests.list +--- firefox-85.0/docshell/base/crashtests/crashtests.list.testing 2021-01-18 19:29:32.000000000 +0100 ++++ firefox-85.0/docshell/base/crashtests/crashtests.list 2021-01-21 09:45:17.767276466 +0100 @@ -13,7 +13,6 @@ load 614499-1.html load 678872-1.html skip-if(Android) pref(dom.disable_open_during_load,false) load 914521.html # Android bug 1584562 @@ -9,21 +9,20 @@ diff -up firefox-84.0/docshell/base/crashtests/crashtests.list.testing firefox-8 load 1341657.html load 1584467.html load 1614211-1.html -diff -up firefox-84.0/dom/media/tests/crashtests/crashtests.list.testing firefox-84.0/dom/media/tests/crashtests/crashtests.list ---- firefox-84.0/dom/media/tests/crashtests/crashtests.list.testing 2020-12-08 00:35:04.000000000 +0100 -+++ firefox-84.0/dom/media/tests/crashtests/crashtests.list 2020-12-10 12:42:49.725237640 +0100 -@@ -24,7 +24,7 @@ asserts-if(Android,0-1) pref(browser.lin - asserts-if(Android,0-1) pref(browser.link.open_newwindow,2) load 1429507_2.html # window.open() in tab doesn't work for crashtest in e10s, this opens a new window instead +diff -up firefox-85.0/dom/media/tests/crashtests/crashtests.list.testing firefox-85.0/dom/media/tests/crashtests/crashtests.list +--- firefox-85.0/dom/media/tests/crashtests/crashtests.list.testing 2021-01-21 09:45:17.767276466 +0100 ++++ firefox-85.0/dom/media/tests/crashtests/crashtests.list 2021-01-21 09:48:35.245124690 +0100 +@@ -25,7 +25,6 @@ asserts-if(Android,0-1) pref(browser.lin + load 1443212.html asserts-if(Android,0-2) load 1453030.html load 1468451.html -skip-if(Android) load 1490700.html # No screenshare on Android -+#skip-if(Android) load 1490700.html # No screenshare on Android and Wayland load 1505957.html load 1509442.html load 1511130.html -diff -up firefox-84.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.testing firefox-84.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py ---- firefox-84.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.testing 2020-12-10 12:42:49.725237640 +0100 -+++ firefox-84.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py 2020-12-10 12:54:22.885925814 +0100 +diff -up firefox-85.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.testing firefox-85.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py +--- firefox-85.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.testing 2021-01-18 19:30:26.000000000 +0100 ++++ firefox-85.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py 2021-01-21 09:45:17.767276466 +0100 @@ -69,15 +69,7 @@ class TestMarionette(MarionetteTestCase) def test_application_update_disabled(self): @@ -41,18 +40,18 @@ diff -up firefox-84.0/testing/marionette/harness/marionette_harness/tests/unit/t self.assertFalse(update_allowed) -diff --git a/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt b/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt ---- a/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt -+++ b/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt +diff -up firefox-85.0/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt.testing firefox-85.0/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt +--- firefox-85.0/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt.testing 2021-01-18 19:30:19.000000000 +0100 ++++ firefox-85.0/testing/tools/websocketprocessbridge/websocketprocessbridge_requirements_3.txt 2021-01-21 09:45:17.767276466 +0100 @@ -1,4 +1,5 @@ # This file is the websocketprocess requirements.txt used with python 3. +pyrsistent # needed by txws, and we'd like pip to get it from the local server before setuptools tries pypi six -diff -up firefox-84.0/toolkit/crashreporter/test/unit/xpcshell.ini.old firefox-84.0/toolkit/crashreporter/test/unit/xpcshell.ini ---- firefox-84.0/toolkit/crashreporter/test/unit/xpcshell.ini.old 2020-12-15 12:21:16.177169732 +0100 -+++ firefox-84.0/toolkit/crashreporter/test/unit/xpcshell.ini 2020-12-15 12:21:22.336348783 +0100 +diff -up firefox-85.0/toolkit/crashreporter/test/unit/xpcshell.ini.testing firefox-85.0/toolkit/crashreporter/test/unit/xpcshell.ini +--- firefox-85.0/toolkit/crashreporter/test/unit/xpcshell.ini.testing 2021-01-18 19:31:16.000000000 +0100 ++++ firefox-85.0/toolkit/crashreporter/test/unit/xpcshell.ini 2021-01-21 09:45:17.767276466 +0100 @@ -37,7 +37,7 @@ skip-if = (os != 'win' && os != 'linux') [test_crash_AsyncShutdown.js] diff --git a/firefox-tests-reftest.patch b/firefox-tests-reftest.patch index d18f6fd..625661c 100644 --- a/firefox-tests-reftest.patch +++ b/firefox-tests-reftest.patch @@ -1,6 +1,6 @@ -diff -up firefox-84.0.2/dom/canvas/test/reftest/filters/reftest.list.firefox-tests-reftest firefox-84.0.2/dom/canvas/test/reftest/filters/reftest.list ---- firefox-84.0.2/dom/canvas/test/reftest/filters/reftest.list.firefox-tests-reftest 2021-01-05 19:12:22.000000000 +0100 -+++ firefox-84.0.2/dom/canvas/test/reftest/filters/reftest.list 2021-01-12 20:30:45.682412237 +0100 +diff -up firefox-85.0/dom/canvas/test/reftest/filters/reftest.list.firefox-tests-reftest firefox-85.0/dom/canvas/test/reftest/filters/reftest.list +--- firefox-85.0/dom/canvas/test/reftest/filters/reftest.list.firefox-tests-reftest 2021-01-18 19:29:38.000000000 +0100 ++++ firefox-85.0/dom/canvas/test/reftest/filters/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -18,7 +18,6 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test( == svg-off-screen.html ref.html == units.html ref.html @@ -9,9 +9,9 @@ diff -up firefox-84.0.2/dom/canvas/test/reftest/filters/reftest.list.firefox-tes == units-off-screen.html ref.html fuzzy(0-2,0-700) == fillText-with-filter-opacity-1.html fillText-with-filter-opacity-1-ref.html fuzzy(0-1,0-302) == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2-ref.html -diff -up firefox-84.0.2/dom/html/reftests/reftest.list.firefox-tests-reftest firefox-84.0.2/dom/html/reftests/reftest.list ---- firefox-84.0.2/dom/html/reftests/reftest.list.firefox-tests-reftest 2021-01-05 19:12:22.000000000 +0100 -+++ firefox-84.0.2/dom/html/reftests/reftest.list 2021-01-12 20:30:45.682412237 +0100 +diff -up firefox-85.0/dom/html/reftests/reftest.list.firefox-tests-reftest firefox-85.0/dom/html/reftests/reftest.list +--- firefox-85.0/dom/html/reftests/reftest.list.firefox-tests-reftest 2021-01-18 19:29:38.000000000 +0100 ++++ firefox-85.0/dom/html/reftests/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -43,7 +43,6 @@ skip-if(Android) == 649134-2.html 649134 # image-orientation when determining the size of the image. # (Fuzzy necessary due to pixel-wise comparison of different JPEGs. @@ -20,15 +20,15 @@ diff -up firefox-84.0.2/dom/html/reftests/reftest.list.firefox-tests-reftest fir fuzzy(0-3,0-640) fuzzy-if(skiaContent,0-3,0-7544) fuzzy-if(webrender&&!geckoview,2-3,50-7544) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 # Test support for SVG-as-image in elements. -diff -up firefox-84.0.2/dom/media/webvtt/test/reftest/reftest.list.firefox-tests-reftest firefox-84.0.2/dom/media/webvtt/test/reftest/reftest.list ---- firefox-84.0.2/dom/media/webvtt/test/reftest/reftest.list.firefox-tests-reftest 2021-01-05 19:12:23.000000000 +0100 -+++ firefox-84.0.2/dom/media/webvtt/test/reftest/reftest.list 2021-01-12 20:30:45.682412237 +0100 +diff -up firefox-85.0/dom/media/webvtt/test/reftest/reftest.list.firefox-tests-reftest firefox-85.0/dom/media/webvtt/test/reftest/reftest.list +--- firefox-85.0/dom/media/webvtt/test/reftest/reftest.list.firefox-tests-reftest 2021-01-18 19:29:39.000000000 +0100 ++++ firefox-85.0/dom/media/webvtt/test/reftest/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -1,2 +1 @@ skip-if(Android) fuzzy-if((/^Windows\x20NT\x2010\.0/.test(http.oscpu))&&(/^aarch64-msvc/.test(xulRuntime.XPCOMABI)),0-136,0-427680) == vtt_update_display_after_removed_cue.html vtt_update_display_after_removed_cue_ref.html -skip-if(Android) fuzzy-if(winWidget,0-170,0-170) == vtt_overlapping_time.html vtt_overlapping_time-ref.html -diff -up firefox-84.0.2/gfx/layers/apz/test/reftest/reftest.list.firefox-tests-reftest firefox-84.0.2/gfx/layers/apz/test/reftest/reftest.list ---- firefox-84.0.2/gfx/layers/apz/test/reftest/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/gfx/layers/apz/test/reftest/reftest.list 2021-01-12 20:30:45.682412237 +0100 +diff -up firefox-85.0/gfx/layers/apz/test/reftest/reftest.list.firefox-tests-reftest firefox-85.0/gfx/layers/apz/test/reftest/reftest.list +--- firefox-85.0/gfx/layers/apz/test/reftest/reftest.list.firefox-tests-reftest 2021-01-18 19:29:39.000000000 +0100 ++++ firefox-85.0/gfx/layers/apz/test/reftest/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -4,11 +4,8 @@ skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v.html about:blank skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v-ref.html about:blank @@ -41,9 +41,9 @@ diff -up firefox-84.0.2/gfx/layers/apz/test/reftest/reftest.list.firefox-tests-r # Different async zoom levels. Since the scrollthumb gets async-scaled in the # compositor, the border-radius ends of the scrollthumb are going to be a little -diff -up firefox-84.0.2/gfx/tests/reftest/reftest.list.firefox-tests-reftest firefox-84.0.2/gfx/tests/reftest/reftest.list ---- firefox-84.0.2/gfx/tests/reftest/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/gfx/tests/reftest/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/gfx/tests/reftest/reftest.list.firefox-tests-reftest firefox-85.0/gfx/tests/reftest/reftest.list +--- firefox-85.0/gfx/tests/reftest/reftest.list.firefox-tests-reftest 2021-01-18 19:29:44.000000000 +0100 ++++ firefox-85.0/gfx/tests/reftest/reftest.list 2021-01-21 09:55:01.721579128 +0100 @@ -12,7 +12,6 @@ fuzzy(0-100,0-30) == 1149923.html 114992 == 1429411.html 1429411-ref.html fuzzy-if(winWidget,0-1,0-4) == 1435143.html 1435143-ref.html @@ -52,14 +52,16 @@ diff -up firefox-84.0.2/gfx/tests/reftest/reftest.list.firefox-tests-reftest fir == 1461313.html 1461313-ref.html fuzzy(5-32,21908-26621) fuzzy-if(webrender,4-5,868-1039) == 1463802.html 1463802-ref.html fuzzy(0-11,0-4) == 1474722.html 1474722-ref.html -@@ -24,4 +23,3 @@ fuzzy-if(webrender,2-7,17500-36908) == 1 +@@ -24,6 +23,5 @@ fuzzy-if(webrender,2-7,17500-36908) == 1 == bug1523410-translate-scale-snap.html bug1523410-translate-scale-snap-ref.html == 1523080.html 1523080-ref.html == 1616444-same-color-different-paths.html 1616444-same-color-different-paths-ref.html -skip-if(!asyncPan||!webrender||Android) fuzzy-if(winWidget,94-94,3415-3415) pref(apz.allow_zooming,true) == picture-caching-on-async-zoom.html picture-caching-on-async-zoom.html?ref -diff -up firefox-84.0.2/image/test/reftest/downscaling/reftest.list.firefox-tests-reftest firefox-84.0.2/image/test/reftest/downscaling/reftest.list ---- firefox-84.0.2/image/test/reftest/downscaling/reftest.list.firefox-tests-reftest 2021-01-05 19:12:23.000000000 +0100 -+++ firefox-84.0.2/image/test/reftest/downscaling/reftest.list 2021-01-14 10:43:43.676262718 +0100 + pref(apz.allow_zooming,true) == 1662062-1-no-blurry.html 1662062-1-ref.html + == 1681610.html 1681610-ref.html +diff -up firefox-85.0/image/test/reftest/downscaling/reftest.list.firefox-tests-reftest firefox-85.0/image/test/reftest/downscaling/reftest.list +--- firefox-85.0/image/test/reftest/downscaling/reftest.list.firefox-tests-reftest 2021-01-18 19:29:39.000000000 +0100 ++++ firefox-85.0/image/test/reftest/downscaling/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -87,10 +87,6 @@ fuzzy(0-20,0-999) != downscale-2c.html?2 fuzzy(0-20,0-999) != downscale-2d.html?205,53,bottom about:blank fuzzy(0-20,0-999) fails-if(OSX>=1008&&!skiaContent) != downscale-2e.html?205,53,bottom about:blank @@ -83,10 +85,10 @@ diff -up firefox-84.0.2/image/test/reftest/downscaling/reftest.list.firefox-test == downscale-png.html?16,16,interlaced downscale-png.html?16,16,normal == downscale-png.html?24,24,interlaced downscale-png.html?24,24,normal -diff -up firefox-84.0.2/layout/reftests/abs-pos/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/abs-pos/reftest.list ---- firefox-84.0.2/layout/reftests/abs-pos/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/abs-pos/reftest.list 2021-01-12 20:30:45.683412265 +0100 -@@ -49,11 +49,9 @@ fuzzy-if(/^Windows\x20NT\x206\.1/.test(h +diff -up firefox-85.0/layout/reftests/abs-pos/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/abs-pos/reftest.list +--- firefox-85.0/layout/reftests/abs-pos/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/abs-pos/reftest.list 2021-01-21 09:52:08.485439676 +0100 +@@ -51,11 +51,9 @@ pref(layout.display-list.improve-fragmen == continuation-positioned-inline-1.html continuation-positioned-inline-ref.html == continuation-positioned-inline-2.html continuation-positioned-inline-ref.html == scrollframe-1.html scrollframe-1-ref.html @@ -98,9 +100,9 @@ diff -up firefox-84.0.2/layout/reftests/abs-pos/reftest.list.firefox-tests-refte == multi-column-1.html multi-column-1-ref.html == button-1.html button-1-ref.html == button-2.html button-2-ref.html -diff -up firefox-84.0.2/layout/reftests/async-scrolling/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/async-scrolling/reftest.list ---- firefox-84.0.2/layout/reftests/async-scrolling/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/async-scrolling/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/async-scrolling/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/async-scrolling/reftest.list +--- firefox-85.0/layout/reftests/async-scrolling/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/async-scrolling/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -53,7 +53,6 @@ fuzzy-if(Android,0-6,0-4) fuzzy-if(skiaC fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&>kWidget,34-34,30-32) fuzzy-if(webrender&&cocoaWidget,7-7,38-39) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html # Bug 1604338 fuzzy-if(Android,0-6,0-4) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item @@ -125,9 +127,9 @@ diff -up firefox-84.0.2/layout/reftests/async-scrolling/reftest.list.firefox-tes fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,10-10,4-4) fuzzy-if(webrender&>kWidget,20-20,32-32) fuzzy-if(webrender&&cocoaWidget,15-16,44-44) skip-if(!asyncPan) == position-sticky-transformed-in-scrollframe-2.html position-sticky-transformed-in-scrollframe-2-ref.html # Bug 1604338 fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,13-13,4-4) fuzzy-if(webrender&>kWidget,26-27,30-32) fuzzy-if(webrender&&cocoaWidget,16-16,44-44) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-1.html position-sticky-in-transformed-scrollframe-ref.html # Bug 1604338 fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,13-13,4-4) fuzzy-if(webrender&>kWidget,26-27,30-32) fuzzy-if(webrender&&cocoaWidget,16-16,44-44) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-2.html position-sticky-in-transformed-scrollframe-ref.html # Bug 1604338 -diff -up firefox-84.0.2/layout/reftests/bidi/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/bidi/reftest.list ---- firefox-84.0.2/layout/reftests/bidi/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/bidi/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/bidi/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/bidi/reftest.list +--- firefox-85.0/layout/reftests/bidi/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/bidi/reftest.list 2021-01-21 09:52:08.485439676 +0100 @@ -30,8 +30,6 @@ random-if(cocoaWidget) == mirroring-02.h == mixedChartype-00-j.html mixedChartype-00-ref.html == mixedChartype-01.html mixedChartype-01-ref.html @@ -160,9 +162,9 @@ diff -up firefox-84.0.2/layout/reftests/bidi/reftest.list.firefox-tests-reftest == 1217833-1.html 1217833-1-ref.html == 1217833-2.html 1217833-2-ref.html == 1231175-1.html 1231175-1-ref.html -diff -up firefox-84.0.2/layout/reftests/border-radius/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/border-radius/reftest.list ---- firefox-84.0.2/layout/reftests/border-radius/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/border-radius/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/border-radius/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/border-radius/reftest.list +--- firefox-85.0/layout/reftests/border-radius/reftest.list.firefox-tests-reftest 2021-01-18 19:29:50.000000000 +0100 ++++ firefox-85.0/layout/reftests/border-radius/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -51,7 +51,6 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test( fuzzy-if(skiaContent,0-1,0-77) == clipping-5-overflow-hidden.html clipping-5-ref.html fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-4) fuzzy-if(Android,0-5,0-21) fuzzy-if(skiaContent,0-1,0-97) == clipping-5-refi.html clipping-5-ref.html @@ -171,20 +173,20 @@ diff -up firefox-84.0.2/layout/reftests/border-radius/reftest.list.firefox-tests fuzzy-if(true,0-2,0-29) fuzzy-if(d2d,0-46,0-71) fuzzy-if(Android,0-255,0-586) fuzzy-if(skiaContent,0-28,0-97) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures). fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),0-1,0-5) == clipping-and-zindex-1.html clipping-and-zindex-1-ref.html fuzzy-if(cocoaWidget,0-1,0-4) fuzzy-if(d2d,0-59,0-342) fuzzy-if(d3d11&&advancedLayers&&!d2d,0-30,0-3) == intersecting-clipping-1-canvas.html intersecting-clipping-1-refc.html -diff -up firefox-84.0.2/layout/reftests/box-shadow/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/box-shadow/reftest.list ---- firefox-84.0.2/layout/reftests/box-shadow/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/box-shadow/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/box-shadow/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/box-shadow/reftest.list +--- firefox-85.0/layout/reftests/box-shadow/reftest.list.firefox-tests-reftest 2021-01-21 09:52:08.486439705 +0100 ++++ firefox-85.0/layout/reftests/box-shadow/reftest.list 2021-01-21 09:53:36.154040097 +0100 @@ -15,7 +15,6 @@ fuzzy-if(OSX==1010,0-1,0-24) fuzzy-if(d2 == boxshadow-fileupload.html boxshadow-fileupload-ref.html fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-98,0-152) fuzzy-if(skiaContent,0-13,0-28) fuzzy-if(webrender,19-19,47-47) == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg --fuzzy-if(skiaContent,0-1,0-17) random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html +-fuzzy-if(skiaContent,0-1,0-18) random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html fuzzy-if(skiaContent,0-1,0-17) == boxshadow-mixed-2.html boxshadow-mixed-2-ref.html random-if(d2d) fuzzy-if(skiaContent,0-1,0-212) fuzzy-if(webrender,0-127,0-3528) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html fuzzy-if(skiaContent,0-1,0-50) == chrome://reftest/content/box-shadow/boxshadow-dynamic.xhtml chrome://reftest/content/box-shadow/boxshadow-dynamic-ref.xhtml -diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/bugs/reftest.list ---- firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/bugs/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/bugs/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/bugs/reftest.list +--- firefox-85.0/layout/reftests/bugs/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/bugs/reftest.list 2021-01-21 09:54:18.891308234 +0100 @@ -461,7 +461,6 @@ random == 328829-1.xhtml 328829-1-ref.xh != 338251-pre.html about:blank == 338251-pre-oh.html 338251-pre-oh-ref.html @@ -201,7 +203,7 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest != 363706-1.html about:blank == 363728-1.html 363728-1-ref.html == 363728-2.html 363728-2-ref.html -@@ -927,8 +925,6 @@ fuzzy-if(winWidget,0-123,0-1600) fuzzy-i +@@ -924,8 +922,6 @@ fuzzy-if(winWidget,0-123,0-1600) fuzzy-i != 409659-1c.html 409659-1-ref.html fuzzy-if(winWidget,0-123,0-1900) fuzzy-if(webrender&&swgl,0-1,0-39) == 409659-1d.html 409659-1-ref.html # Bug 1128229 == 410621-1.html 410621-1-ref.html @@ -210,23 +212,23 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest == 411367-2.html 411367-2-ref.html == 411367-3.html 411367-3-ref.html == 411585-1.html 411585-1-ref.html -@@ -1001,7 +997,6 @@ fuzzy-if(skiaContent,0-1,0-40) == 421632 - fails-if(Android) fuzzy-if(webrender,63-64,1024-1024) fails-if(usesRepeatResampling&&!(webrender&&winWidget)) == 421885-1.xml 421885-1-ref.xml +@@ -998,7 +994,6 @@ fuzzy-if(skiaContent,0-1,0-40) == 421632 + fails-if(Android) fuzzy-if(webrender,63-65,1024-1024) fails-if(usesRepeatResampling&&!(webrender&&winWidget)) == 421885-1.xml 421885-1-ref.xml == 421955-1.html 421955-1-ref.html == 422249-1.html 422249-1-ref.html -== 422394-1.html 422394-1-ref.html == 422678-1.html 422678-1-ref.html == 423130-1.html 423130-1-ref.html == 423385-1.html 423385-1-ref.html -@@ -1176,7 +1171,6 @@ fuzzy-if(webrender,0-4,0-361) == 449519- +@@ -1173,7 +1168,6 @@ fuzzy-if(webrender,0-4,0-361) == 449519- == 455171-5.html 455171-5-ref.html == 455280-1.xhtml 455280-1-ref.xhtml fails-if(Android) == 455826-1.html 455826-1-ref.html -fails-if(Android||cocoaWidget||winWidget) == chrome://reftest/content/bugs/456147.xhtml 456147-ref.html # bug 458047 fuzzy-if(Android,0-11,0-41) fuzzy-if(winWidget||gtkWidget,0-4,0-6) fuzzy-if(d2d,0-16,0-95) fuzzy-if(skiaContent,0-42,0-154) fuzzy-if(webrender,56-60,449-570) == 456219-1a.html 456219-1-ref.html # bug 1128229 - fuzzy-if(Android,0-11,0-41) fuzzy-if(winWidget||gtkWidget,0-4,0-6) fuzzy-if(d2d,0-16,0-99) fuzzy-if(skiaContent,0-42,0-154) fuzzy-if(webrender,56-60,449-570) == 456219-1b.html 456219-1-ref.html # bug 1128229 + fuzzy-if(Android,0-11,0-41) fuzzy-if(winWidget||gtkWidget,0-4,0-6) fuzzy-if(d2d,0-16,0-99) fuzzy-if(skiaContent,0-42,0-154) fuzzy-if(webrender,56-60,449-1251) == 456219-1b.html 456219-1-ref.html # bug 1128229 fuzzy-if(Android,0-11,0-41) fuzzy-if(winWidget||gtkWidget,0-4,0-6) fuzzy-if(d2d,0-16,0-99) fuzzy-if(skiaContent,0-42,0-154) fuzzy-if(webrender,56-60,449-497) fuzzy-if(geckoview&&webrender&&device,60-60,499-4421) == 456219-1c.html 456219-1-ref.html # bug 1128229 -@@ -1387,8 +1381,6 @@ fuzzy-if(Android,0-5,0-1656) fuzzy-if(sk +@@ -1384,8 +1378,6 @@ fuzzy-if(Android,0-5,0-1656) fuzzy-if(sk == 512631-1.html 512631-1-ref.html fuzzy-if(Android,0-1,0-2) == 513153-1a.html 513153-1-ref.html fuzzy-if(Android,0-1,0-2) == 513153-1b.html 513153-1-ref.html @@ -235,7 +237,7 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest == chrome://reftest/content/bugs/513318-1.xhtml chrome://reftest/content/bugs/513318-1-ref.xhtml fails-if(Android&&(!asyncPan)) != chrome://reftest/content/bugs/513318-2.xhtml chrome://reftest/content/bugs/513318-2-ref.xhtml == 514917-1.html 514917-1-ref.html -@@ -1831,7 +1823,6 @@ pref(layout.css.moz-document.content.ena +@@ -1828,7 +1820,6 @@ pref(layout.css.moz-document.content.ena fails-if(webrender) == 1059498-1.html 1059498-1-ref.html # WebRender: see bug 1504290 fails-if(webrender) == 1059498-2.html 1059498-1-ref.html # WebRender: see bug 1504290 fails-if(webrender) == 1059498-3.html 1059498-1-ref.html # WebRender: see bug 1499113 @@ -243,7 +245,7 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest == 1062792-1.html 1062792-1-ref.html == 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html == 1066554-1.html 1066554-1-ref.html -@@ -2032,8 +2023,6 @@ needs-focus != 1377447-1.html 1377447-2. +@@ -2029,8 +2020,6 @@ needs-focus != 1377447-1.html 1377447-2. == 1401317.html 1401317-ref.html == 1401992.html 1401992-ref.html == 1405878-1.xml 1405878-1-ref.xml @@ -252,7 +254,7 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest fuzzy-if(webrender,0-129,0-48) == 1406179.html 1406179-ref.html == 1406183-1.html 1406183-1-ref.html == 1410028.html 1410028-ref.html -@@ -2077,7 +2066,6 @@ fuzzy-if(!webrender,1-5,66-547) fuzzy-if +@@ -2074,7 +2063,6 @@ fuzzy-if(!webrender,1-5,66-547) fuzzy-if fuzzy-if(!webrender,0-6,0-34) fuzzy-if(Android,9-14,44-60) fails-if(webrender) == 1529992-2.html 1529992-2-ref.html == 1535040-1.html 1535040-1-ref.html == 1545360-1.xhtml 1545360-1-ref.xhtml @@ -260,7 +262,7 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest == 1546856-1.html 1546856-ref.html == 1546856-2.html 1546856-ref.html == 1547759-1.html 1547759-1-ref.html -@@ -2088,7 +2076,6 @@ pref(image.downscale-during-decode.enabl +@@ -2085,7 +2073,6 @@ pref(image.downscale-during-decode.enabl != 1563484.html 1563484-notref.html == 1563484.html 1563484-ref.html fuzzy-if(!webrender||!winWidget,251-255,464-1613) fuzzy-if(geckoview&&webrender,251-255,1392-1405) skip-if(Android&&webrender) == 1562733-rotated-nastaliq-1.html 1562733-rotated-nastaliq-1-ref.html #Bug 1604765 @@ -268,9 +270,9 @@ diff -up firefox-84.0.2/layout/reftests/bugs/reftest.list.firefox-tests-reftest test-pref(plain_text.wrap_long_lines,false) != 1565129.txt 1565129.txt fuzzy(0-32,0-8) fuzzy-if(Android&&webrender,0-32,0-1458) == 1576553-1.html 1576553-1-ref.html fuzzy(0-1,0-10000) == 1577566-1.html 1577566-1-ref.html -diff -up firefox-84.0.2/layout/reftests/canvas/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/canvas/reftest.list ---- firefox-84.0.2/layout/reftests/canvas/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/canvas/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/canvas/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/canvas/reftest.list +--- firefox-85.0/layout/reftests/canvas/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/canvas/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -48,10 +48,7 @@ fuzzy-if(azureSkiaGL,0-10,0-400) == text != text-bidi-ltr-test.html text-bidi-ltr-notref.html # for bug 698185 == text-bidi-rtl-test.html text-bidi-rtl-ref.html @@ -282,9 +284,9 @@ diff -up firefox-84.0.2/layout/reftests/canvas/reftest.list.firefox-tests-reftes random-if(!d2d) != text-subpixel-1.html text-subpixel-1-ref.html -diff -up firefox-84.0.2/layout/reftests/columns/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/columns/reftest.list ---- firefox-84.0.2/layout/reftests/columns/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/columns/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/columns/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/columns/reftest.list +--- firefox-85.0/layout/reftests/columns/reftest.list.firefox-tests-reftest 2021-01-18 19:30:05.000000000 +0100 ++++ firefox-85.0/layout/reftests/columns/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -5,7 +5,6 @@ == min-width-1a.html pref-width-1-ref.html == min-width-1b.html min-width-1-ref.html @@ -293,9 +295,9 @@ diff -up firefox-84.0.2/layout/reftests/columns/reftest.list.firefox-tests-refte == column-balancing-overflow-000.html column-balancing-overflow-000.ref.html == column-balancing-overflow-001.html column-balancing-overflow-000.ref.html == column-balancing-overflow-002.html column-balancing-overflow-002.ref.html -diff -up firefox-84.0.2/layout/reftests/css-blending/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/css-blending/reftest.list ---- firefox-84.0.2/layout/reftests/css-blending/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/css-blending/reftest.list 2021-01-12 20:30:45.683412265 +0100 +diff -up firefox-85.0/layout/reftests/css-blending/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/css-blending/reftest.list +--- firefox-85.0/layout/reftests/css-blending/reftest.list.firefox-tests-reftest 2021-01-18 19:29:50.000000000 +0100 ++++ firefox-85.0/layout/reftests/css-blending/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -87,9 +87,6 @@ test-pref(image.animation_mode,"none") = == background-blending-background-attachement-fixed.html background-blending-background-attachement-fixed-ref.html == background-blending-background-attachement-fixed-scroll.html background-blending-background-attachement-fixed-scroll-ref.html @@ -306,9 +308,9 @@ diff -up firefox-84.0.2/layout/reftests/css-blending/reftest.list.firefox-tests- == background-blending-moz-element.html background-blending-moz-element-ref.html fuzzy(0-1,0-40000) == mix-blend-mode-soft-light.html mix-blend-mode-soft-light-ref.html -diff -up firefox-84.0.2/layout/reftests/css-break/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/css-break/reftest.list ---- firefox-84.0.2/layout/reftests/css-break/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/css-break/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/css-break/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/css-break/reftest.list +--- firefox-85.0/layout/reftests/css-break/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/css-break/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -1,6 +1,3 @@ -== box-decoration-break-1.html box-decoration-break-1-ref.html -fuzzy(0-1,0-20) fuzzy-if(skiaContent,0-1,0-700) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html @@ -316,9 +318,9 @@ diff -up firefox-84.0.2/layout/reftests/css-break/reftest.list.firefox-tests-ref == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html == box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding-ref.html == box-decoration-break-block-margin.html box-decoration-break-block-margin-ref.html -diff -up firefox-84.0.2/layout/reftests/css-grid/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/css-grid/reftest.list ---- firefox-84.0.2/layout/reftests/css-grid/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/css-grid/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/css-grid/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/css-grid/reftest.list +--- firefox-85.0/layout/reftests/css-grid/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/css-grid/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -71,7 +71,6 @@ random-if(/^Windows\x20NT\x206\.1/.test( random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-min-content-min-sizing-transferred-size-003.html grid-min-content-min-sizing-transferred-size-003-ref.html # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == grid-min-content-min-sizing-transferred-size-004.html grid-min-content-min-sizing-transferred-size-004-ref.html # Bug 1392106 @@ -327,9 +329,9 @@ diff -up firefox-84.0.2/layout/reftests/css-grid/reftest.list.firefox-tests-reft fuzzy-if(webrender&&winWidget,0-1,0-75) == grid-track-intrinsic-sizing-002.html grid-track-intrinsic-sizing-002-ref.html fuzzy-if(webrender&&winWidget,0-1,0-75) == grid-track-intrinsic-sizing-003.html grid-track-intrinsic-sizing-003-ref.html == grid-track-intrinsic-sizing-004.html grid-track-intrinsic-sizing-004-ref.html -diff -up firefox-84.0.2/layout/reftests/css-ruby/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/css-ruby/reftest.list ---- firefox-84.0.2/layout/reftests/css-ruby/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/css-ruby/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/css-ruby/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/css-ruby/reftest.list +--- firefox-85.0/layout/reftests/css-ruby/reftest.list.firefox-tests-reftest 2021-01-18 19:29:51.000000000 +0100 ++++ firefox-85.0/layout/reftests/css-ruby/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -14,18 +14,12 @@ test-pref(font.minimum-size.ja,16) == mi == line-height-3.html line-height-3-ref.html == line-height-4.html line-height-4-ref.html @@ -349,9 +351,9 @@ diff -up firefox-84.0.2/layout/reftests/css-ruby/reftest.list.firefox-tests-reft pref(layout.css.ruby.intercharacter.enabled,false) != ruby-intercharacter-2.htm ruby-intercharacter-2-ref.htm # Testing a specific bug for RTL handling. -diff -up firefox-84.0.2/layout/reftests/font-face/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/font-face/reftest.list ---- firefox-84.0.2/layout/reftests/font-face/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/font-face/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/font-face/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/font-face/reftest.list +--- firefox-85.0/layout/reftests/font-face/reftest.list.firefox-tests-reftest 2021-01-18 19:29:50.000000000 +0100 ++++ firefox-85.0/layout/reftests/font-face/reftest.list 2021-01-21 09:52:08.486439705 +0100 @@ -6,7 +6,6 @@ random-if(winWidget||gtkWidget) == downl asserts-if(Android&&!asyncPan,1-8) != download-3-notref.html download-3.html # bug 1019192 asserts-if(Android,0-8) == download-3-ref.html download-3.html # same bugs as above @@ -398,9 +400,9 @@ diff -up firefox-84.0.2/layout/reftests/font-face/reftest.list.firefox-tests-ref HTTP(..) == bug-1481905-cancel-load.html bug-1481905-cancel-load-ref.html -diff -up firefox-84.0.2/layout/reftests/font-matching/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/font-matching/reftest.list ---- firefox-84.0.2/layout/reftests/font-matching/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/font-matching/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/font-matching/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/font-matching/reftest.list +--- firefox-85.0/layout/reftests/font-matching/reftest.list.firefox-tests-reftest 2021-01-18 19:29:51.000000000 +0100 ++++ firefox-85.0/layout/reftests/font-matching/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -117,14 +117,10 @@ skip-if(!cocoaWidget) != apple-symbols-1 # distinguish between italic and oblique random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == simple-oblique.html simple-oblique-ref.html # Bug 1392106 @@ -416,9 +418,9 @@ diff -up firefox-84.0.2/layout/reftests/font-matching/reftest.list.firefox-tests random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) != italic-oblique-kinnari.html italic-oblique-kinnari-ref.html # Bug 1392106 # GTK and Windows 7 don't have full emoji and symbol font, so emoji-fallback-2 -diff -up firefox-84.0.2/layout/reftests/forms/fieldset/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/forms/fieldset/reftest.list ---- firefox-84.0.2/layout/reftests/forms/fieldset/reftest.list.firefox-tests-reftest 2021-01-05 19:12:27.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/forms/fieldset/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/forms/fieldset/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/forms/fieldset/reftest.list +--- firefox-85.0/layout/reftests/forms/fieldset/reftest.list.firefox-tests-reftest 2021-01-18 19:29:59.000000000 +0100 ++++ firefox-85.0/layout/reftests/forms/fieldset/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -5,7 +5,6 @@ fuzzy-if(skiaContent,0-2,0-13) == dynami == fieldset-scroll-1.html fieldset-scroll-1-ref.html == fieldset-scrolled-1.html fieldset-scrolled-1-ref.html @@ -427,18 +429,18 @@ diff -up firefox-84.0.2/layout/reftests/forms/fieldset/reftest.list.firefox-test == relpos-legend-1.html relpos-legend-1-ref.html == relpos-legend-2.html relpos-legend-2-ref.html == relpos-legend-3.html relpos-legend-3-ref.html -diff -up firefox-84.0.2/layout/reftests/forms/input/text/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/forms/input/text/reftest.list ---- firefox-84.0.2/layout/reftests/forms/input/text/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/forms/input/text/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/forms/input/text/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/forms/input/text/reftest.list +--- firefox-85.0/layout/reftests/forms/input/text/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/forms/input/text/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -1,5 +1,4 @@ == bounds-1.html bounds-1-ref.html -fuzzy-if(asyncPan&&!layersGPUAccelerated,0-151,0-111) fuzzy-if(webrender,0-65,0-3) == size-1.html size-1-ref.html == size-2.html size-2-ref.html == baseline-1.html baseline-1-ref.html == chrome://reftest/content/forms/input/text/centering-1.xhtml chrome://reftest/content/forms/input/text/centering-1-ref.xhtml -diff -up firefox-84.0.2/layout/reftests/forms/placeholder/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/forms/placeholder/reftest.list ---- firefox-84.0.2/layout/reftests/forms/placeholder/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/forms/placeholder/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/forms/placeholder/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/forms/placeholder/reftest.list +--- firefox-85.0/layout/reftests/forms/placeholder/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/forms/placeholder/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -17,9 +17,6 @@ == placeholder-4.html placeholder-overridden-ref.html == placeholder-5.html placeholder-visible-ref.html @@ -449,9 +451,9 @@ diff -up firefox-84.0.2/layout/reftests/forms/placeholder/reftest.list.firefox-t skip-if(Android&&asyncPan) == placeholder-6-textarea.html placeholder-overflow-textarea-ref.html # needs-focus == placeholder-7.html placeholder-focus-ref.html # needs-focus == placeholder-8.html placeholder-focus-ref.html -diff -up firefox-84.0.2/layout/reftests/forms/textbox/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/forms/textbox/reftest.list ---- firefox-84.0.2/layout/reftests/forms/textbox/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/forms/textbox/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/forms/textbox/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/forms/textbox/reftest.list +--- firefox-85.0/layout/reftests/forms/textbox/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/forms/textbox/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -1,11 +1,9 @@ # access-key tests are no use on OS X because access keys are not indicated visually # no real XUL theme on Android so we just skip @@ -464,9 +466,9 @@ diff -up firefox-84.0.2/layout/reftests/forms/textbox/reftest.list.firefox-tests skip-if(cocoaWidget||Android) != chrome://reftest/content/forms/textbox/accesskey-4.xhtml chrome://reftest/content/forms/textbox/accesskey-4-notref.xhtml skip-if(Android) == chrome://reftest/content/forms/textbox/align-baseline-1.xhtml chrome://reftest/content/forms/textbox/align-baseline-1-ref.xhtml # test for bug 494901 skip-if(Android) == chrome://reftest/content/forms/textbox/setsize.xhtml chrome://reftest/content/forms/textbox/setsize-ref.xhtml -diff -up firefox-84.0.2/layout/reftests/image-element/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/image-element/reftest.list ---- firefox-84.0.2/layout/reftests/image-element/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/image-element/reftest.list 2021-01-14 10:44:36.106810339 +0100 +diff -up firefox-85.0/layout/reftests/image-element/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/image-element/reftest.list +--- firefox-85.0/layout/reftests/image-element/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/image-element/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -7,7 +7,6 @@ random == bug-364968.html bug-364968-ref == canvas-outside-document-invalidate-01.html about:blank fails-if(azureSkia&&!(webrender&&winWidget)) fails-if(cocoaWidget) == canvas-outside-document-invalidate-02.html about:blank # See bug 666800 @@ -483,9 +485,9 @@ diff -up firefox-84.0.2/layout/reftests/image-element/reftest.list.firefox-tests fails-if(usesRepeatResampling&&!(webrender&&winWidget)) == element-paint-subimage-sampling-restriction.html about:blank == element-paint-clippath.html element-paint-clippath-ref.html fuzzy-if(webrender,36-36,712-738) == element-paint-sharpness-01a.html element-paint-sharpness-01b.html -diff -up firefox-84.0.2/layout/reftests/mathml/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/mathml/reftest.list ---- firefox-84.0.2/layout/reftests/mathml/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/mathml/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/mathml/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/mathml/reftest.list +--- firefox-85.0/layout/reftests/mathml/reftest.list.firefox-tests-reftest 2021-01-18 19:29:51.000000000 +0100 ++++ firefox-85.0/layout/reftests/mathml/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -23,7 +23,6 @@ fuzzy-if(cocoaWidget,0-135,0-56) == dir- == css-spacing-1.html css-spacing-1-ref.html pref(mathml.disabled,true) == disabled-scriptlevel-1.html disabled-scriptlevel-1-ref.html @@ -510,26 +512,26 @@ diff -up firefox-84.0.2/layout/reftests/mathml/reftest.list.firefox-tests-reftes fails-if(Android&&emulator) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mathvariant-1a.html mathvariant-1a-ref.html # Bug 1010679, Bug 1392106 fails-if(Android&&emulator) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mathvariant-1b.html mathvariant-1b-ref.html # Bug 1010679, Bug 1392106 fails-if(Android&&emulator) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == mathvariant-1c.html mathvariant-1c-ref.html # Bug 1010679, Bug 1392106 -diff -up firefox-84.0.2/layout/reftests/outline/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/outline/reftest.list ---- firefox-84.0.2/layout/reftests/outline/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/outline/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/outline/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/outline/reftest.list +--- firefox-85.0/layout/reftests/outline/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/outline/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -15,4 +15,3 @@ pref(layout.css.outline-style-auto.enabl == outline-on-table.html outline-on-table-ref.html == outline-table-caption.html outline-table-caption-ref.html == outline-table-caption-invisible.html about:blank -== outline-wrapped-span-1.html outline-wrapped-span-1-ref.html -diff -up firefox-84.0.2/layout/reftests/position-dynamic-changes/relative/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/position-dynamic-changes/relative/reftest.list ---- firefox-84.0.2/layout/reftests/position-dynamic-changes/relative/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/position-dynamic-changes/relative/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/position-dynamic-changes/relative/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/position-dynamic-changes/relative/reftest.list +--- firefox-85.0/layout/reftests/position-dynamic-changes/relative/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/position-dynamic-changes/relative/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -1,5 +1 @@ -fuzzy-if(cocoaWidget,0-1,0-2) fuzzy-if(d2d,0-47,0-26) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-169,0-970) == move-right-bottom.html move-right-bottom-ref.html -fuzzy-if(cocoaWidget,0-1,0-2) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-169,0-970) == move-top-left.html move-top-left-ref.html # Bug 688545 -fuzzy-if(cocoaWidget,0-1,0-3) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-144,0-580) == move-right-bottom-table.html move-right-bottom-table-ref.html -fuzzy-if(cocoaWidget,0-1,0-3) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-144,0-580) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545 == percent.html percent-ref.html -diff -up firefox-84.0.2/layout/reftests/position-sticky/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/position-sticky/reftest.list ---- firefox-84.0.2/layout/reftests/position-sticky/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/position-sticky/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/position-sticky/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/position-sticky/reftest.list +--- firefox-85.0/layout/reftests/position-sticky/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/position-sticky/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -50,6 +50,5 @@ fuzzy-if(Android,0-8,0-630) fuzzy-if(OSX == block-in-inline-continuations.html block-in-inline-continuations-ref.html == iframe-1.html iframe-1-ref.html @@ -537,9 +539,9 @@ diff -up firefox-84.0.2/layout/reftests/position-sticky/reftest.list.firefox-tes -fuzzy-if(Android,0-4,0-4) fuzzy-if(webrender&>kWidget,16-17,28-32) fuzzy-if(webrender&&cocoaWidget,8-8,38-42) skip-if(!asyncPan) == transformed-2.html transformed-2-ref.html # Bug 1604644 skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(webrender&>kWidget,29-30,30-32) fuzzy-if(webrender&&cocoaWidget,15-16,44-44) == nested-sticky-1.html nested-sticky-1-ref.html # Bug 1604644 skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(webrender&>kWidget,29-30,30-32) fuzzy-if(webrender&&cocoaWidget,15-16,44-44) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),0-4,0-104) == nested-sticky-2.html nested-sticky-2-ref.html # Bug 1604644 -diff -up firefox-84.0.2/layout/reftests/reftest-sanity/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/reftest-sanity/reftest.list ---- firefox-84.0.2/layout/reftests/reftest-sanity/reftest.list.firefox-tests-reftest 2021-01-05 19:12:27.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/reftest-sanity/reftest.list 2021-01-12 20:30:45.684412292 +0100 +diff -up firefox-85.0/layout/reftests/reftest-sanity/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/reftest-sanity/reftest.list +--- firefox-85.0/layout/reftests/reftest-sanity/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/reftest-sanity/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -128,12 +128,12 @@ pref(font.size.variable.x-western,24) != fails pref(font.size.variable.x-western,false) == font-size-16.html font-default.html fails pref(font.size.variable.x-western,"foo") == font-size-16.html font-default.html @@ -559,10 +561,10 @@ diff -up firefox-84.0.2/layout/reftests/reftest-sanity/reftest.list.firefox-test # tests for ref-pref, and test-pref ref-pref(font.size.variable.x-western,16) == font-size-16.html font-default.html ref-pref(font.size.variable.x-western,16) != font-size-24.html font-default.html -diff -up firefox-84.0.2/layout/reftests/svg/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/svg/reftest.list ---- firefox-84.0.2/layout/reftests/svg/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/svg/reftest.list 2021-01-12 20:30:45.685412320 +0100 -@@ -477,9 +477,7 @@ random-if(/^Windows\x20NT\x206\.1/.test( +diff -up firefox-85.0/layout/reftests/svg/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/svg/reftest.list +--- firefox-85.0/layout/reftests/svg/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/svg/reftest.list 2021-01-21 09:52:08.487439735 +0100 +@@ -478,9 +478,7 @@ random-if(/^Windows\x20NT\x206\.1/.test( == text-in-link-02.svg text-in-link-02-ref.svg == text-in-link-03.svg text-in-link-03-ref.svg # Tests for bug 546813: sanity-check using HTML text, then test SVG behavior. @@ -572,7 +574,7 @@ diff -up firefox-84.0.2/layout/reftests/svg/reftest.list.firefox-tests-reftest f random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-layout-02.svg text-layout-02-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-layout-03.svg text-layout-03-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-layout-04.svg text-layout-04-ref.svg # Bug 1392106 -@@ -487,7 +485,6 @@ random-if(/^Windows\x20NT\x206\.1/.test( +@@ -488,7 +486,6 @@ random-if(/^Windows\x20NT\x206\.1/.test( fuzzy-if(cocoaWidget&&layersGPUAccelerated,0-1,0-3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-layout-06.svg text-layout-06-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-layout-07.svg text-layout-07-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-layout-08.svg text-layout-08-ref.svg # Bug 1392106 @@ -580,9 +582,9 @@ diff -up firefox-84.0.2/layout/reftests/svg/reftest.list.firefox-tests-reftest f random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-scale-01.svg text-scale-01-ref.svg # Bug 1392106 fuzzy-if(skiaContent,0-2,0-1000) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-scale-02.svg text-scale-02-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == text-scale-03.svg text-scale-03-ref.svg # Bug 1392106 -diff -up firefox-84.0.2/layout/reftests/svg/svg-integration/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/svg/svg-integration/reftest.list ---- firefox-84.0.2/layout/reftests/svg/svg-integration/reftest.list.firefox-tests-reftest 2021-01-05 19:12:27.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/svg/svg-integration/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/svg/svg-integration/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/svg/svg-integration/reftest.list +--- firefox-85.0/layout/reftests/svg/svg-integration/reftest.list.firefox-tests-reftest 2021-01-18 19:29:51.000000000 +0100 ++++ firefox-85.0/layout/reftests/svg/svg-integration/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -47,6 +47,5 @@ fuzzy(0-1,0-5000) == mask-clipPath-opaci == transform-outer-svg-01.xhtml transform-outer-svg-01-ref.xhtml @@ -590,9 +592,9 @@ diff -up firefox-84.0.2/layout/reftests/svg/svg-integration/reftest.list.firefox -fuzzy-if(Android,0-4,0-10) == box-decoration-break-01.xhtml box-decoration-break-01-ref.xhtml fuzzy(0-119,0-16) == box-decoration-break-02.xhtml box-decoration-break-02-ref.xhtml fuzzy(0-67,0-238) == box-decoration-break-03.xhtml box-decoration-break-01-ref.xhtml -diff -up firefox-84.0.2/layout/reftests/svg/text/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/svg/text/reftest.list ---- firefox-84.0.2/layout/reftests/svg/text/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/svg/text/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/svg/text/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/svg/text/reftest.list +--- firefox-85.0/layout/reftests/svg/text/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/svg/text/reftest.list 2021-01-21 09:52:08.487439735 +0100 @@ -1,14 +1,5 @@ -random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(webrender&&winWidget,122-127,221-254) == simple.svg simple-ref.html # Bug 1392106 == simple-2.svg simple.svg @@ -637,7 +639,7 @@ diff -up firefox-84.0.2/layout/reftests/svg/text/reftest.list.firefox-tests-reft random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-a.svg textpath-a-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-anchor-middle.svg textpath-anchor-middle-ref.svg # Bug 1392106 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == textpath-anchor-end.svg textpath-anchor-end-ref.svg # Bug 1392106 -@@ -196,13 +183,7 @@ needs-focus == deselectAll.svg deselectA +@@ -198,13 +185,7 @@ needs-focus == deselectAll.svg deselectA fuzzy-if(skiaContent,0-1,0-250) needs-focus == selectSubString.svg selectSubString-ref.svg fuzzy-if(skiaContent,0-1,0-600) needs-focus == selectSubString-2.svg selectSubString-2-ref.svg fuzzy-if(skiaContent,0-1,0-250) needs-focus == selectSubString-3.svg selectSubString-3-ref.svg @@ -651,9 +653,9 @@ diff -up firefox-84.0.2/layout/reftests/svg/text/reftest.list.firefox-tests-reft # letter-spacing and word-spacing pref(svg.text-spacing.enabled,true) == simple-letter-spacing.svg simple-letter-spacing-ref.svg -diff -up firefox-84.0.2/layout/reftests/tab-size/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/tab-size/reftest.list ---- firefox-84.0.2/layout/reftests/tab-size/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/tab-size/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/tab-size/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/tab-size/reftest.list +--- firefox-85.0/layout/reftests/tab-size/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/tab-size/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -1,10 +1,4 @@ == tab-size-8.html tab-size-initial.html -== tab-size-8.html spaces-8.html @@ -665,18 +667,18 @@ diff -up firefox-84.0.2/layout/reftests/tab-size/reftest.list.firefox-tests-reft == tab-size-0.html spaces-0.html == tab-size-negative.html tab-size-initial.html == tab-size-change-1a.html tab-size-change-1-ref.html -diff -up firefox-84.0.2/layout/reftests/text-decoration/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/text-decoration/reftest.list ---- firefox-84.0.2/layout/reftests/text-decoration/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/text-decoration/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/text-decoration/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/text-decoration/reftest.list +--- firefox-85.0/layout/reftests/text-decoration/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/text-decoration/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -1,5 +1,3 @@ -fuzzy-if(webrender&>kWidget,0-208,0-12) == complex-decoration-style-quirks.html complex-decoration-style-quirks-ref.html -fuzzy-if(webrender&>kWidget,0-208,0-12) == complex-decoration-style-standards.html complex-decoration-style-standards-ref.html == decoration-color-quirks.html decoration-color-quirks-ref.html == decoration-color-standards.html decoration-color-standards-ref.html == decoration-style-quirks.html decoration-style-quirks-ref.html -diff -up firefox-84.0.2/layout/reftests/text-overflow/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/text-overflow/reftest.list ---- firefox-84.0.2/layout/reftests/text-overflow/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/text-overflow/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/text-overflow/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/text-overflow/reftest.list +--- firefox-85.0/layout/reftests/text-overflow/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/text-overflow/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -3,7 +3,6 @@ fuzzy-if(Android,0-16,0-244) fuzzy-if(webrender,0-47,0-6) == marker-basic.html marker-basic-ref.html # Bug 1128229 == marker-string.html marker-string-ref.html @@ -693,9 +695,9 @@ diff -up firefox-84.0.2/layout/reftests/text-overflow/reftest.list.firefox-tests # The vertical-text pref setting can be removed after bug 1138384 lands == vertical-decorations-1.html vertical-decorations-1-ref.html -diff -up firefox-84.0.2/layout/reftests/text/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/text/reftest.list ---- firefox-84.0.2/layout/reftests/text/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/text/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/text/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/text/reftest.list +--- firefox-85.0/layout/reftests/text/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/text/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -34,7 +34,6 @@ fuzzy-if(Android,0-255,0-325) == pre-lin == pre-line-3.html pre-line-3-ref.html == pre-line-4.html pre-line-4-ref.html @@ -758,9 +760,9 @@ diff -up firefox-84.0.2/layout/reftests/text/reftest.list.firefox-tests-reftest # osx-font-smoothing - with and without subpixel AA, only under OSX fails-if(!cocoaWidget) != osx-font-smoothing.html osx-font-smoothing-ref.html -diff -up firefox-84.0.2/layout/reftests/text-shadow/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/text-shadow/reftest.list ---- firefox-84.0.2/layout/reftests/text-shadow/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/text-shadow/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/text-shadow/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/text-shadow/reftest.list +--- firefox-85.0/layout/reftests/text-shadow/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/text-shadow/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -27,9 +27,7 @@ fuzzy-if(webrender&&swgl,2-2,6320-6320) fuzzy-if(cocoaWidget,0-27,0-2) fuzzy-if(winWidget,0-47,0-2) == overflow-clip.html overflow-clip-ref.html @@ -771,9 +773,9 @@ diff -up firefox-84.0.2/layout/reftests/text-shadow/reftest.list.firefox-tests-r # bug 692744 fuzzy-if(webrender,0-19,0-2872) == text-shadow-on-space-1.html text-shadow-on-space-1-ref.html -diff -up firefox-84.0.2/layout/reftests/text-transform/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/text-transform/reftest.list ---- firefox-84.0.2/layout/reftests/text-transform/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/text-transform/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/text-transform/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/text-transform/reftest.list +--- firefox-85.0/layout/reftests/text-transform/reftest.list.firefox-tests-reftest 2021-01-18 19:30:14.000000000 +0100 ++++ firefox-85.0/layout/reftests/text-transform/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -9,9 +9,6 @@ == capitalize-8.html capitalize-8-ref.html == lowercase-1.html lowercase-ref.html @@ -784,9 +786,9 @@ diff -up firefox-84.0.2/layout/reftests/text-transform/reftest.list.firefox-test != opentype-small-caps-1.html opentype-small-caps-1-notref.html == graphite-small-caps-1.html graphite-small-caps-1-ref.html != graphite-small-caps-1.html graphite-small-caps-1-notref.html -diff -up firefox-84.0.2/layout/reftests/transform-3d/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/transform-3d/reftest.list ---- firefox-84.0.2/layout/reftests/transform-3d/reftest.list.firefox-tests-reftest 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/transform-3d/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/transform-3d/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/transform-3d/reftest.list +--- firefox-85.0/layout/reftests/transform-3d/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/transform-3d/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -11,7 +11,6 @@ fuzzy-if(webrender,0-1,0-6) == rotatey-1 == rotatex-perspective-1c.html rotatex-1-ref.html == rotatex-perspective-3a.html rotatex-perspective-3-ref.html @@ -804,9 +806,9 @@ diff -up firefox-84.0.2/layout/reftests/transform-3d/reftest.list.firefox-tests- == scale3d-xz.html scale3d-1-ref.html == translatez-1a.html translatez-1-ref.html != translatez-1b.html translatez-1-ref.html -diff -up firefox-84.0.2/layout/reftests/writing-mode/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/writing-mode/reftest.list ---- firefox-84.0.2/layout/reftests/writing-mode/reftest.list.firefox-tests-reftest 2021-01-05 19:12:26.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/writing-mode/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/writing-mode/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/writing-mode/reftest.list +--- firefox-85.0/layout/reftests/writing-mode/reftest.list.firefox-tests-reftest 2021-01-18 19:30:10.000000000 +0100 ++++ firefox-85.0/layout/reftests/writing-mode/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -31,7 +31,6 @@ random-if(/^Windows\x20NT\x206\.1/.test( == 1105268-2-min-max-dimensions.html 1105268-2-min-max-dimensions-ref.html == 1106669-1-intrinsic-for-container.html 1106669-1-intrinsic-for-container-ref.html @@ -823,9 +825,9 @@ diff -up firefox-84.0.2/layout/reftests/writing-mode/reftest.list.firefox-tests- fuzzy-if(winWidget,0-255,0-163) fuzzy-if(skiaContent,0-159,0-111) == 1136557-1-nested-spans.html 1136557-1-nested-spans-ref.html fuzzy-if(winWidget,0-255,0-221) fuzzy-if(skiaContent,0-159,0-111) == 1136557-2-nested-spans.html 1136557-2-nested-spans-ref.html fuzzy-if(winWidget,0-255,0-236) == 1136557-3-nested-spans.html 1136557-3-nested-spans-ref.html -diff -up firefox-84.0.2/layout/reftests/xul/reftest.list.firefox-tests-reftest firefox-84.0.2/layout/reftests/xul/reftest.list ---- firefox-84.0.2/layout/reftests/xul/reftest.list.firefox-tests-reftest 2021-01-05 20:58:39.000000000 +0100 -+++ firefox-84.0.2/layout/reftests/xul/reftest.list 2021-01-12 20:30:45.685412320 +0100 +diff -up firefox-85.0/layout/reftests/xul/reftest.list.firefox-tests-reftest firefox-85.0/layout/reftests/xul/reftest.list +--- firefox-85.0/layout/reftests/xul/reftest.list.firefox-tests-reftest 2021-01-18 19:29:51.000000000 +0100 ++++ firefox-85.0/layout/reftests/xul/reftest.list 2021-01-21 09:52:08.488439764 +0100 @@ -12,7 +12,6 @@ pref(layout.css.xul-tree-pseudos.content skip-if(!cocoaWidget) fails-if(webrender&&cocoaWidget) == chrome://reftest/content/xul/mac-tab-toolbar.xhtml chrome://reftest/content/xul/mac-tab-toolbar-ref.xhtml pref(layout.css.xul-tree-pseudos.content.enabled,true) != chrome://reftest/content/xul/tree-row-outline-1.xhtml chrome://reftest/content/xul/tree-row-outline-1-notref.xhtml @@ -834,4 +836,3 @@ diff -up firefox-84.0.2/layout/reftests/xul/reftest.list.firefox-tests-reftest f fuzzy-if(skiaContent,0-1,0-60) fuzzy-if(cocoaWidget&&browserIsRemote&&!skiaContent,0-1,0-31) fuzzy-if(winWidget&&browserIsRemote&&layersGPUAccelerated,0-1,0-50) fuzzy-if(webrender,0-1,350-1050) == chrome://reftest/content/xul/inactive-fixed-bg-bug1205630.xhtml inactive-fixed-bg-bug1205630-ref.html fuzzy-if(skiaContent,0-1,0-60) fuzzy-if(cocoaWidget&&browserIsRemote&&!skiaContent,0-1,0-31) fuzzy-if(winWidget&&browserIsRemote&&layersGPUAccelerated,0-1,0-50) fuzzy-if(webrender,0-1,450-1100) == chrome://reftest/content/xul/inactive-fixed-bg-bug1272525.xhtml inactive-fixed-bg-bug1272525-ref.html - diff --git a/firefox-tests-xpcshell.patch b/firefox-tests-xpcshell.patch index 96c27b8..8f9edf8 100644 --- a/firefox-tests-xpcshell.patch +++ b/firefox-tests-xpcshell.patch @@ -1,6 +1,6 @@ -diff -up firefox-84.0.2/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini ---- firefox-84.0.2/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-05 19:12:21.000000000 +0100 -+++ firefox-84.0.2/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini 2021-01-12 20:30:45.681412210 +0100 +diff -up firefox-85.0/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini +--- firefox-85.0/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:29:32.000000000 +0100 ++++ firefox-85.0/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini 2021-01-21 09:49:44.587178226 +0100 @@ -6,7 +6,6 @@ support-files = [test_3rdparty.js] @@ -9,9 +9,9 @@ diff -up firefox-84.0.2/browser/components/enterprisepolicies/tests/xpcshell/xpc [test_bug1658259.js] [test_cleanup.js] [test_clear_blocked_cookies.js] -diff -up firefox-84.0.2/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini ---- firefox-84.0.2/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-05 19:12:22.000000000 +0100 -+++ firefox-84.0.2/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini 2021-01-12 20:30:45.681412210 +0100 +diff -up firefox-85.0/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini +--- firefox-85.0/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:29:32.000000000 +0100 ++++ firefox-85.0/devtools/client/shared/remote-debugging/adb/xpcshell/xpcshell.ini 2021-01-21 09:49:44.587178226 +0100 @@ -6,6 +6,5 @@ skip-if = toolkit == 'android' || socket support-files = adb.py @@ -19,9 +19,9 @@ diff -up firefox-84.0.2/devtools/client/shared/remote-debugging/adb/xpcshell/xpc -[test_adb.js] run-sequentially = An extension having the same id is installed/uninstalled in different tests [test_prepare-tcp-connection.js] -diff -up firefox-84.0.2/netwerk/test/unit_ipc/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/netwerk/test/unit_ipc/xpcshell.ini ---- firefox-84.0.2/netwerk/test/unit_ipc/xpcshell.ini.firefox-tests-xpcshell 2021-01-14 11:03:10.741711483 +0100 -+++ firefox-84.0.2/netwerk/test/unit_ipc/xpcshell.ini 2021-01-14 11:03:17.498910928 +0100 +diff -up firefox-85.0/netwerk/test/unit_ipc/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/netwerk/test/unit_ipc/xpcshell.ini +--- firefox-85.0/netwerk/test/unit_ipc/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:29:59.000000000 +0100 ++++ firefox-85.0/netwerk/test/unit_ipc/xpcshell.ini 2021-01-21 09:49:44.587178226 +0100 @@ -70,7 +70,6 @@ support-files = [test_channel_close_wrap.js] [test_cookiejars_wrap.js] @@ -30,9 +30,9 @@ diff -up firefox-84.0.2/netwerk/test/unit_ipc/xpcshell.ini.firefox-tests-xpcshel [test_duplicate_headers_wrap.js] [test_event_sink_wrap.js] [test_head_wrap.js] -diff -up firefox-84.0.2/netwerk/test/unit/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/netwerk/test/unit/xpcshell.ini ---- firefox-84.0.2/netwerk/test/unit/xpcshell.ini.firefox-tests-xpcshell 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/netwerk/test/unit/xpcshell.ini 2021-01-14 11:02:39.939802295 +0100 +diff -up firefox-85.0/netwerk/test/unit/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/netwerk/test/unit/xpcshell.ini +--- firefox-85.0/netwerk/test/unit/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:30:19.000000000 +0100 ++++ firefox-85.0/netwerk/test/unit/xpcshell.ini 2021-01-21 09:50:27.536450133 +0100 @@ -199,7 +199,6 @@ skip-if = true # Bug 863738 [test_cookies_upgrade_10.js] [test_dns_cancel.js] @@ -77,15 +77,15 @@ diff -up firefox-84.0.2/netwerk/test/unit/xpcshell.ini.firefox-tests-xpcshell fi @@ -409,7 +403,6 @@ skip-if = tsan || socketprocess_networki run-sequentially = node server exceptions dont replay well skip-if = socketprocess_networking - [test_esni_dns_fetch.js] + [test_dns_by_type_resolve.js] -[test_network_connectivity_service.js] [test_suspend_channel_on_authRetry.js] [test_suspend_channel_on_examine_merged_response.js] [test_bug1527293.js] -diff -up firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell.ini ---- firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell.ini.firefox-tests-xpcshell 2021-01-14 11:05:59.458691431 +0100 -+++ firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell.ini 2021-01-14 11:06:51.073214918 +0100 -@@ -175,7 +175,6 @@ run-sequentially = hardcoded ports +diff -up firefox-85.0/security/manager/ssl/tests/unit/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/security/manager/ssl/tests/unit/xpcshell.ini +--- firefox-85.0/security/manager/ssl/tests/unit/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:29:59.000000000 +0100 ++++ firefox-85.0/security/manager/ssl/tests/unit/xpcshell.ini 2021-01-21 09:49:44.588178255 +0100 +@@ -180,7 +180,6 @@ run-sequentially = hardcoded ports run-sequentially = hardcoded ports [test_ocsp_url.js] run-sequentially = hardcoded ports @@ -93,9 +93,9 @@ diff -up firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell.ini.firefox-tes [test_osreauthenticator.js] # Reauthentication has been implemented on Windows and MacOS, so running this # test results in the OS popping up a dialog, which means we can't run it in -diff -up firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell-smartcards.ini.firefox-tests-xpcshell firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell-smartcards.ini ---- firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell-smartcards.ini.firefox-tests-xpcshell 2021-01-05 19:12:27.000000000 +0100 -+++ firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell-smartcards.ini 2021-01-12 20:30:45.681412210 +0100 +diff -up firefox-85.0/security/manager/ssl/tests/unit/xpcshell-smartcards.ini.firefox-tests-xpcshell firefox-85.0/security/manager/ssl/tests/unit/xpcshell-smartcards.ini +--- firefox-85.0/security/manager/ssl/tests/unit/xpcshell-smartcards.ini.firefox-tests-xpcshell 2021-01-18 19:29:59.000000000 +0100 ++++ firefox-85.0/security/manager/ssl/tests/unit/xpcshell-smartcards.ini 2021-01-21 09:49:44.588178255 +0100 @@ -7,7 +7,6 @@ support-files = [test_osclientcerts_module.js] @@ -104,18 +104,18 @@ diff -up firefox-84.0.2/security/manager/ssl/tests/unit/xpcshell-smartcards.ini. [test_pkcs11_moduleDB.js] [test_pkcs11_safe_mode.js] [test_pkcs11_slot.js] -diff -up firefox-84.0.2/toolkit/components/commandlines/test/unit/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/toolkit/components/commandlines/test/unit/xpcshell.ini ---- firefox-84.0.2/toolkit/components/commandlines/test/unit/xpcshell.ini.firefox-tests-xpcshell 2021-01-05 19:12:33.000000000 +0100 -+++ firefox-84.0.2/toolkit/components/commandlines/test/unit/xpcshell.ini 2021-01-12 20:30:45.681412210 +0100 +diff -up firefox-85.0/toolkit/components/commandlines/test/unit/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/toolkit/components/commandlines/test/unit/xpcshell.ini +--- firefox-85.0/toolkit/components/commandlines/test/unit/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:31:16.000000000 +0100 ++++ firefox-85.0/toolkit/components/commandlines/test/unit/xpcshell.ini 2021-01-21 09:49:44.588178255 +0100 @@ -7,4 +7,3 @@ support-files = [test_classinfo.js] [test_bug666224.js] -[test_resolvefile.js] -diff -up firefox-84.0.2/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini.firefox-tests-xpcshell firefox-84.0.2/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini ---- firefox-84.0.2/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini.firefox-tests-xpcshell 2021-01-14 11:07:47.513880856 +0100 -+++ firefox-84.0.2/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini 2021-01-14 11:08:33.169228446 +0100 -@@ -69,8 +69,6 @@ skip-if = socketprocess_networking +diff -up firefox-85.0/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini.firefox-tests-xpcshell firefox-85.0/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini +--- firefox-85.0/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini.firefox-tests-xpcshell 2021-01-18 19:31:16.000000000 +0100 ++++ firefox-85.0/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini 2021-01-21 09:49:44.588178255 +0100 +@@ -73,8 +73,6 @@ skip-if = socketprocess_networking || os skip-if = os == "android" # downloads API needs to be implemented in GeckoView - bug 1538348 [test_ext_downloads_download.js] skip-if = appname == "thunderbird" || os == "android" || tsan # tsan: bug 1612707 @@ -124,7 +124,7 @@ diff -up firefox-84.0.2/toolkit/components/extensions/test/xpcshell/xpcshell-com [test_ext_downloads_private.js] skip-if = os == "android" [test_ext_downloads_search.js] -@@ -230,8 +228,6 @@ skip-if = appname == "thunderbird" || os +@@ -241,8 +239,6 @@ skip-if = appname == "thunderbird" || os skip-if = appname == "thunderbird" || os == "android" # Bug 1350559 [test_ext_permissions_uninstall.js] skip-if = appname == "thunderbird" || os == "android" # Bug 1350559 @@ -133,9 +133,9 @@ diff -up firefox-84.0.2/toolkit/components/extensions/test/xpcshell/xpcshell-com [test_proxy_incognito.js] skip-if = os == "android" # incognito not supported on android [test_proxy_info_results.js] -diff -up firefox-84.0.2/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini ---- firefox-84.0.2/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-05 19:12:34.000000000 +0100 -+++ firefox-84.0.2/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini 2021-01-12 20:30:45.681412210 +0100 +diff -up firefox-85.0/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini +--- firefox-85.0/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:30:38.000000000 +0100 ++++ firefox-85.0/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini 2021-01-21 09:49:44.588178255 +0100 @@ -7,6 +7,5 @@ support-files = data_text_file.txt data_test_script.py @@ -143,10 +143,10 @@ diff -up firefox-84.0.2/toolkit/modules/subprocess/test/xpcshell/xpcshell.ini.fi -[test_subprocess.js] [test_subprocess_getEnvironment.js] [test_subprocess_pathSearch.js] -diff -up firefox-84.0.2/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-84.0.2/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini ---- firefox-84.0.2/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-05 21:29:48.000000000 +0100 -+++ firefox-84.0.2/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini 2021-01-12 20:30:45.681412210 +0100 -@@ -97,7 +97,6 @@ tags = webextensions +diff -up firefox-85.0/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell firefox-85.0/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +--- firefox-85.0/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini.firefox-tests-xpcshell 2021-01-18 19:30:38.000000000 +0100 ++++ firefox-85.0/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini 2021-01-21 09:49:44.588178255 +0100 +@@ -94,7 +94,6 @@ tags = webextensions head = head_addons.js head_sideload.js skip-if = os == "linux" # Bug 1613268 [test_sideloads.js] diff --git a/firefox-vaapi-extra-frames.patch b/firefox-vaapi-extra-frames.patch deleted file mode 100644 index e26158a..0000000 --- a/firefox-vaapi-extra-frames.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp.old firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp.old 2020-05-13 14:28:26.556800474 +0200 -+++ firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2020-05-13 14:28:31.562768959 +0200 -@@ -43,7 +43,7 @@ typedef int VAStatus; - #endif - - // Use some extra HW frames for potential rendering lags. --#define EXTRA_HW_FRAMES 6 -+#define EXTRA_HW_FRAMES 20 - - typedef mozilla::layers::Image Image; - typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage; diff --git a/firefox.spec b/firefox.spec index 956e39c..2f84ea8 100644 --- a/firefox.spec +++ b/firefox.spec @@ -14,7 +14,7 @@ # as the build is *very* slow. %global debug_build 0 -%global system_nss 1 +%global system_nss 0 %global build_with_clang 0 %global build_with_asan 0 %global test_offscreen 1 @@ -146,13 +146,13 @@ ExcludeArch: s390x Summary: Mozilla Firefox Web browser Name: firefox -Version: 84.0.2 -Release: 8%{?pre_tag}%{?dist} +Version: 85.0 +Release: 1%{?pre_tag}%{?dist} URL: https://www.mozilla.org/firefox/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz %if %{with langpacks} -Source1: firefox-langpacks-%{version}%{?pre_version}-20210106.tar.xz +Source1: firefox-langpacks-%{version}%{?pre_version}-20210120.tar.xz %endif Source2: cbindgen-vendor.tar.xz Source10: firefox-mozconfig @@ -226,19 +226,7 @@ Patch422: mozilla-1631061.patch Patch423: mozilla-1681107.patch Patch424: firefox-wayland-fix-mzbz-1642949-regression.patch Patch425: mozilla-1645695.patch - -# Upstream patches from mozbz#1672944 -Patch450: pw1.patch -Patch451: pw2.patch -Patch452: pw3.patch -Patch453: pw4.patch -Patch454: pw5.patch -Patch455: pw6.patch - -Patch500: ffvpx.patch - -#VA-API patches -Patch585: firefox-vaapi-extra-frames.patch +Patch426: mozilla-1687931.patch # PGO/LTO patches Patch600: pgo.patch @@ -414,7 +402,7 @@ This package contains results of tests executed during build. %endif %patch3 -p1 -b .arm %patch44 -p1 -b .build-arm-libopus -%patch46 -p1 -b .nss-version +#%patch46 -p1 -b .nss-version %patch47 -p1 -b .fedora-shebang %patch48 -p1 -b .build-arm-wasm %patch49 -p1 -b .build-arm-libaom @@ -445,24 +433,10 @@ This package contains results of tests executed during build. %patch415 -p1 -b .1670333 %patch418 -p1 -b .1556931-s390x-hidden-syms -#%patch450 -p1 -b .pw1 -#%patch451 -p1 -b .pw2 -#%patch452 -p1 -b .pw3 -#%patch453 -p1 -b .pw4 -#%patch454 -p1 -b .pw5 -%patch455 -p1 -b .pw6 -%patch420 -p1 -b .1678680 -%patch421 -p1 -b .1680505 -#%patch422 -p1 -b .1631061 %patch423 -p1 -b .1681107 %patch424 -p1 -b .fix-mzbz-1642949-regression %patch425 -p1 -b .1645695 - -%patch500 -p1 -b .ffvpx - -# VA-API fixes -# merged with ffvpx -# %patch585 -p1 -b .firefox-vaapi-extra-frames +%patch426 -p1 -b .1687931 # PGO patches %if %{build_with_pgo} @@ -1043,6 +1017,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Wed Jan 20 2021 Martin Stransky - 85.0-1 +- Update to 85.0. + * Wed Jan 20 2021 Jan Horak - 84.0.2-8 - Fixing package requires/provides diff --git a/mozilla-1667096.patch b/mozilla-1667096.patch index cbe8aea..981ced4 100644 --- a/mozilla-1667096.patch +++ b/mozilla-1667096.patch @@ -1,6 +1,6 @@ -diff -up firefox-84.0/media/ffvpx/libavcodec/codec_list.c.1667096 firefox-84.0/media/ffvpx/libavcodec/codec_list.c ---- firefox-84.0/media/ffvpx/libavcodec/codec_list.c.1667096 2020-12-07 23:33:03.000000000 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/codec_list.c 2020-12-10 12:57:14.722762321 +0100 +diff -up firefox-85.0/media/ffvpx/libavcodec/codec_list.c.1667096 firefox-85.0/media/ffvpx/libavcodec/codec_list.c +--- firefox-85.0/media/ffvpx/libavcodec/codec_list.c.1667096 2021-01-18 19:29:51.000000000 +0100 ++++ firefox-85.0/media/ffvpx/libavcodec/codec_list.c 2021-01-21 09:56:17.637831802 +0100 @@ -11,4 +11,8 @@ static const AVCodec * const codec_list[ #if CONFIG_MP3_DECODER &ff_mp3_decoder, @@ -10,9 +10,9 @@ diff -up firefox-84.0/media/ffvpx/libavcodec/codec_list.c.1667096 firefox-84.0/m +#endif + NULL }; -diff -up firefox-84.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 firefox-84.0/media/ffvpx/libavcodec/libfdk-aacdec.c ---- firefox-84.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 2020-12-10 12:57:14.722762321 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/libfdk-aacdec.c 2020-12-10 12:57:14.722762321 +0100 +diff -up firefox-85.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 firefox-85.0/media/ffvpx/libavcodec/libfdk-aacdec.c +--- firefox-85.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 2021-01-21 09:56:17.638831832 +0100 ++++ firefox-85.0/media/ffvpx/libavcodec/libfdk-aacdec.c 2021-01-21 09:56:17.638831832 +0100 @@ -0,0 +1,409 @@ +/* + * AAC decoder wrapper @@ -423,12 +423,12 @@ diff -up firefox-84.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 firefox-84. + FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libfdk", +}; -diff -up firefox-84.0/media/ffvpx/libavcodec/moz.build.1667096 firefox-84.0/media/ffvpx/libavcodec/moz.build ---- firefox-84.0/media/ffvpx/libavcodec/moz.build.1667096 2020-12-08 00:35:05.000000000 +0100 -+++ firefox-84.0/media/ffvpx/libavcodec/moz.build 2020-12-10 12:57:14.722762321 +0100 -@@ -97,6 +97,12 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: - 'vp9recon.c' - ] +diff -up firefox-85.0/media/ffvpx/libavcodec/moz.build.1667096 firefox-85.0/media/ffvpx/libavcodec/moz.build +--- firefox-85.0/media/ffvpx/libavcodec/moz.build.1667096 2021-01-21 09:56:17.638831832 +0100 ++++ firefox-85.0/media/ffvpx/libavcodec/moz.build 2021-01-21 10:06:18.958716728 +0100 +@@ -104,6 +104,12 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: + ] + USE_LIBS += ['mozva'] +if CONFIG['MOZ_FDK_AAC']: + SOURCES += [ @@ -439,9 +439,9 @@ diff -up firefox-84.0/media/ffvpx/libavcodec/moz.build.1667096 firefox-84.0/medi if CONFIG['MOZ_LIBAV_FFT']: SOURCES += [ 'avfft.c', -diff -up firefox-84.0/toolkit/moz.configure.1667096 firefox-84.0/toolkit/moz.configure ---- firefox-84.0/toolkit/moz.configure.1667096 2020-12-10 12:57:14.723762349 +0100 -+++ firefox-84.0/toolkit/moz.configure 2020-12-10 12:58:29.051855203 +0100 +diff -up firefox-85.0/toolkit/moz.configure.1667096 firefox-85.0/toolkit/moz.configure +--- firefox-85.0/toolkit/moz.configure.1667096 2021-01-21 09:56:17.603830793 +0100 ++++ firefox-85.0/toolkit/moz.configure 2021-01-21 09:56:17.638831832 +0100 @@ -1868,6 +1868,14 @@ with only_when(compile_environment): set_define("MOZ_LIBAV_FFT", depends(when=libav_fft)(lambda: True)) set_config("LIBAV_FFT_ASFLAGS", libav_fft.flags) diff --git a/mozilla-1678680.patch b/mozilla-1678680.patch deleted file mode 100644 index 5c4953a..0000000 --- a/mozilla-1678680.patch +++ /dev/null @@ -1,73 +0,0 @@ -changeset: 560838:7a5a1784b5d1 -tag: tip -parent: 560835:7184fb5a42fb -user: Martin Stransky -date: Fri Nov 27 17:29:07 2020 +0100 -files: third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -description: -Bug 1678680 [PipeWire] Lock current_frame_ access as it can be used from multiple threads, r?dminor - -Differential Revision: https://phabricator.services.mozilla.com/D98080 - - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -@@ -396,16 +396,17 @@ void BaseCapturerPipeWire::HandleBuffer( - DesktopSize video_size_prev = video_size_; - if (video_metadata_use_) { - video_size_ = DesktopSize(video_metadata->region.size.width, - video_metadata->region.size.height); - } else { - video_size_ = desktop_size_; - } - -+ rtc::CritScope lock(¤t_frame_lock_); - if (!current_frame_ || - (video_metadata_use_ && !video_size_.equals(video_size_prev))) { - current_frame_ = - std::make_unique - (video_size_.width() * video_size_.height() * kBytesPerPixel); - } - - const int32_t dstStride = video_size_.width() * kBytesPerPixel; -@@ -872,16 +873,17 @@ void BaseCapturerPipeWire::Start(Callbac - } - - void BaseCapturerPipeWire::CaptureFrame() { - if (portal_init_failed_) { - callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); - return; - } - -+ rtc::CritScope lock(¤t_frame_lock_); - if (!current_frame_) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - - DesktopSize frame_size = desktop_size_; - if (video_metadata_use_) { - frame_size = video_size_; -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -@@ -79,16 +79,17 @@ class BaseCapturerPipeWire : public Desk - guint sources_request_signal_id_ = 0; - guint start_request_signal_id_ = 0; - - bool video_metadata_use_ = false; - DesktopSize video_size_; - DesktopSize desktop_size_ = {}; - DesktopCaptureOptions options_ = {}; - -+ rtc::CriticalSection current_frame_lock_; - std::unique_ptr current_frame_; - Callback* callback_ = nullptr; - - bool portal_init_failed_ = false; - - void InitPortal(); - void InitPipeWire(); - - diff --git a/mozilla-1680505.patch b/mozilla-1680505.patch deleted file mode 100644 index dba9b7c..0000000 --- a/mozilla-1680505.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff --git a/widget/GfxInfoX11.cpp b/widget/GfxInfoX11.cpp ---- a/widget/GfxInfoX11.cpp -+++ b/widget/GfxInfoX11.cpp -@@ -705,6 +705,14 @@ - DRIVER_GREATER_THAN_OR_EQUAL, V(18, 0, 0, 0), - "FEATURE_ROLLOUT_INTEL_GNOME_X11_MESA", "Mesa 18.0.0.0"); - -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::SmallAndMedium, -+ BatteryStatus::All, DesktopEnvironment::GNOME, WindowProtocol::Wayland, -+ DriverVendor::MesaAll, DeviceFamily::IntelRolloutWebRender, -+ nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, -+ DRIVER_GREATER_THAN_OR_EQUAL, V(18, 0, 0, 0), -+ "FEATURE_ROLLOUT_INTEL_GNOME_WAYLAND_MESA", "Mesa 18.0.0.0"); -+ - // ATI Mesa baseline, chosen arbitrarily. - APPEND_TO_DRIVER_BLOCKLIST_EXT( - OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -@@ -713,6 +721,14 @@ - nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_GREATER_THAN_OR_EQUAL, - V(18, 0, 0, 0), "FEATURE_ROLLOUT_ATI_GNOME_X11_MESA", "Mesa 18.0.0.0"); - -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -+ DesktopEnvironment::GNOME, WindowProtocol::Wayland, -+ DriverVendor::MesaAll, DeviceFamily::AtiRolloutWebRender, -+ nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, -+ DRIVER_GREATER_THAN_OR_EQUAL, V(18, 0, 0, 0), -+ "FEATURE_ROLLOUT_ATI_GNOME_WAYLAND_MESA", "Mesa 18.0.0.0"); -+ - #ifdef EARLY_BETA_OR_EARLIER - // Intel Mesa baseline, chosen arbitrarily. - APPEND_TO_DRIVER_BLOCKLIST_EXT( - diff --git a/mozilla-1687931.patch b/mozilla-1687931.patch new file mode 100644 index 0000000..91f7e9c --- /dev/null +++ b/mozilla-1687931.patch @@ -0,0 +1,28 @@ +changeset: 565888:91903b2fd4ab +tag: tip +parent: 565886:1a895ef04f9f +user: stransky +date: Thu Jan 21 12:27:43 2021 +0100 +files: widget/gtk/nsWindow.cpp +description: +Bug 1687931 [Wayland] Don't cache monitor scale factor, r?jhorak + +Differential Revision: https://phabricator.services.mozilla.com/D102590 + + +diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp +--- a/widget/gtk/nsWindow.cpp ++++ b/widget/gtk/nsWindow.cpp +@@ -7714,10 +7714,10 @@ gint nsWindow::GdkScaleFactor() { + (gint(*)(GdkWindow*))dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); + if (sGdkWindowGetScaleFactorPtr && scaledGdkWindow) { + mWindowScaleFactor = (*sGdkWindowGetScaleFactorPtr)(scaledGdkWindow); ++ mWindowScaleFactorChanged = false; + } else { + mWindowScaleFactor = ScreenHelperGTK::GetGTKMonitorScaleFactor(); + } +- mWindowScaleFactorChanged = false; + + return mWindowScaleFactor; + } + diff --git a/pgo.patch b/pgo.patch index f6b4953..12b8940 100644 --- a/pgo.patch +++ b/pgo.patch @@ -1,7 +1,7 @@ -diff -up firefox-84.0/build/moz.configure/lto-pgo.configure.pgo firefox-84.0/build/moz.configure/lto-pgo.configure ---- firefox-84.0/build/moz.configure/lto-pgo.configure.pgo 2020-12-10 15:55:41.932635998 +0100 -+++ firefox-84.0/build/moz.configure/lto-pgo.configure 2020-12-10 16:01:24.674052547 +0100 -@@ -228,13 +228,13 @@ def lto(value, c_compiler, ld64_known_go +diff -up firefox-85.0/build/moz.configure/lto-pgo.configure.pgo firefox-85.0/build/moz.configure/lto-pgo.configure +--- firefox-85.0/build/moz.configure/lto-pgo.configure.pgo 2021-01-18 19:29:32.000000000 +0100 ++++ firefox-85.0/build/moz.configure/lto-pgo.configure 2021-01-21 10:23:59.499111297 +0100 +@@ -240,13 +240,13 @@ def lto( cflags.append("-flto") ldflags.append("-flto") else: @@ -18,18 +18,9 @@ diff -up firefox-84.0/build/moz.configure/lto-pgo.configure.pgo firefox-84.0/bui # With clang-cl, -flto can only be used with -c or -fuse-ld=lld. # AC_TRY_LINKs during configure don't have -c, so pass -fuse-ld=lld. cflags.append("-fuse-ld=lld") -@@ -268,7 +268,7 @@ def lto(value, c_compiler, ld64_known_go - if len(value) and value[0].lower() == "full": - cflags.append("-flto") - else: -- cflags.append("-flto=thin") -+ cflags.append("-flto") - cflags.append("-flifetime-dse=1") - - ldflags.append("-flto=%s" % num_cores) -diff -up firefox-84.0/build/pgo/profileserver.py.pgo firefox-84.0/build/pgo/profileserver.py ---- firefox-84.0/build/pgo/profileserver.py.pgo 2020-12-07 23:32:58.000000000 +0100 -+++ firefox-84.0/build/pgo/profileserver.py 2020-12-10 16:05:16.278668657 +0100 +diff -up firefox-85.0/build/pgo/profileserver.py.pgo firefox-85.0/build/pgo/profileserver.py +--- firefox-85.0/build/pgo/profileserver.py.pgo 2021-01-18 19:29:32.000000000 +0100 ++++ firefox-85.0/build/pgo/profileserver.py 2021-01-21 10:23:59.499111297 +0100 @@ -11,7 +11,7 @@ import glob import subprocess @@ -76,9 +67,9 @@ diff -up firefox-84.0/build/pgo/profileserver.py.pgo firefox-84.0/build/pgo/prof llvm_profdata = env.get("LLVM_PROFDATA") if llvm_profdata: profraw_files = glob.glob("*.profraw") -diff -up firefox-84.0/build/unix/mozconfig.unix.pgo firefox-84.0/build/unix/mozconfig.unix ---- firefox-84.0/build/unix/mozconfig.unix.pgo 2020-12-07 23:32:58.000000000 +0100 -+++ firefox-84.0/build/unix/mozconfig.unix 2020-12-10 15:55:41.933636031 +0100 +diff -up firefox-85.0/build/unix/mozconfig.unix.pgo firefox-85.0/build/unix/mozconfig.unix +--- firefox-85.0/build/unix/mozconfig.unix.pgo 2021-01-18 19:29:32.000000000 +0100 ++++ firefox-85.0/build/unix/mozconfig.unix 2021-01-21 10:23:59.499111297 +0100 @@ -6,6 +6,15 @@ if [ -n "$FORCE_GCC" ]; then CC="$MOZ_FETCHES_DIR/gcc/bin/gcc" CXX="$MOZ_FETCHES_DIR/gcc/bin/g++" @@ -95,34 +86,19 @@ diff -up firefox-84.0/build/unix/mozconfig.unix.pgo firefox-84.0/build/unix/mozc # We want to make sure we use binutils and other binaries in the tooltool # package. mk_add_options "export PATH=$MOZ_FETCHES_DIR/gcc/bin:$PATH" -diff -up firefox-84.0/extensions/spellcheck/src/moz.build.pgo firefox-84.0/extensions/spellcheck/src/moz.build ---- firefox-84.0/extensions/spellcheck/src/moz.build.pgo 2020-12-10 15:55:41.933636031 +0100 -+++ firefox-84.0/extensions/spellcheck/src/moz.build 2020-12-10 16:16:05.897011122 +0100 +diff -up firefox-85.0/extensions/spellcheck/src/moz.build.pgo firefox-85.0/extensions/spellcheck/src/moz.build +--- firefox-85.0/extensions/spellcheck/src/moz.build.pgo 2021-01-18 19:29:38.000000000 +0100 ++++ firefox-85.0/extensions/spellcheck/src/moz.build 2021-01-21 10:23:59.499111297 +0100 @@ -31,3 +31,5 @@ EXPORTS.mozilla += [ if CONFIG["CC_TYPE"] in ("clang", "gcc"): CXXFLAGS += ["-Wno-error=shadow"] + +CXXFLAGS += ['-fno-devirtualize'] -diff -up firefox-84.0/python/mozbuild/mozbuild/build_commands.py.pgo firefox-84.0/python/mozbuild/mozbuild/build_commands.py ---- firefox-84.0/python/mozbuild/mozbuild/build_commands.py.pgo 2020-12-10 15:55:41.933636031 +0100 -+++ firefox-84.0/python/mozbuild/mozbuild/build_commands.py 2020-12-10 16:14:30.017272529 +0100 -@@ -126,9 +126,8 @@ class Build(MachCommandBase): - return status - - pgo_env = os.environ.copy() -- pgo_env["LLVM_PROFDATA"] = instr.config_environment.substs.get( -- "LLVM_PROFDATA" -- ) -+ if instr.config_environment.substs.get('CC_TYPE') != 'gcc': -+ pgo_env["LLVM_PROFDATA"] = instr.config_environment.substs.get("LLVM_PROFDATA") - pgo_env["JARLOG_FILE"] = mozpath.join(orig_topobjdir, "jarlog/en-US.log") - pgo_cmd = [ - instr.virtualenv_manager.python_path, -diff -up firefox-84.0/toolkit/components/terminator/nsTerminator.cpp.pgo firefox-84.0/toolkit/components/terminator/nsTerminator.cpp ---- firefox-84.0/toolkit/components/terminator/nsTerminator.cpp.pgo 2020-12-07 23:33:08.000000000 +0100 -+++ firefox-84.0/toolkit/components/terminator/nsTerminator.cpp 2020-12-10 15:55:41.933636031 +0100 -@@ -418,6 +418,11 @@ void nsTerminator::StartWatchdog() { +diff -up firefox-85.0/toolkit/components/terminator/nsTerminator.cpp.pgo firefox-85.0/toolkit/components/terminator/nsTerminator.cpp +--- firefox-85.0/toolkit/components/terminator/nsTerminator.cpp.pgo 2021-01-18 19:31:16.000000000 +0100 ++++ firefox-85.0/toolkit/components/terminator/nsTerminator.cpp 2021-01-21 10:23:59.500111327 +0100 +@@ -430,6 +430,11 @@ void nsTerminator::StartWatchdog() { } #endif diff --git a/pw1.patch b/pw1.patch deleted file mode 100644 index 1f88545..0000000 --- a/pw1.patch +++ /dev/null @@ -1,78 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604562416 0 -# Node ID 1c126b520042591194e88618ae11a6adc1da9a08 -# Parent 6e2e4f0e4a95b0cae777dda9369a9e9bf49a51b1 -Bug 1672987 Use PipeWire when Wayland display is actually used, r=dminor - -Right now PipeWire is enabled when Wayland session is used regardless of an active Gtk backend (X11/Wayland). -Let's use PipeWire only when Wayland Gtk backend is used and disable it for X11 one to avoid possible regressions. - -Differential Revision: https://phabricator.services.mozilla.com/D94588 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -@@ -8,16 +8,21 @@ - * be found in the AUTHORS file in the root of the source tree. - */ - - #include "modules/desktop_capture/desktop_capturer.h" - - #include "modules/desktop_capture/desktop_capture_options.h" - #include "modules/desktop_capture/desktop_capturer_differ_wrapper.h" - -+#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) -+#include -+#include -+#endif -+ - namespace webrtc { - - DesktopCapturer::~DesktopCapturer() = default; - - void DesktopCapturer::SetSharedMemoryFactory( - std::unique_ptr shared_memory_factory) {} - - void DesktopCapturer::SetExcludedWindow(WindowId window) {} -@@ -67,21 +72,37 @@ std::unique_ptr Desktop - if (capturer && options.detect_updated_region()) { - capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer))); - } - - return capturer; - } - - #if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) --bool DesktopCapturer::IsRunningUnderWayland() { -+// Return true if Firefox is actually running with Wayland backend. -+static bool IsWaylandDisplayUsed() { -+ const auto display = gdk_display_get_default(); -+ if (display == nullptr) { -+ // We're running in headless mode. -+ return false; -+ } -+ return !GDK_IS_X11_DISPLAY(display); -+} -+ -+// Return true if Firefox is actually running on Wayland enabled session. -+// It means some screensharing capabilities may be limited. -+static bool IsWaylandSessionUsed() { - const char* xdg_session_type = getenv("XDG_SESSION_TYPE"); - if (!xdg_session_type || strncmp(xdg_session_type, "wayland", 7) != 0) - return false; - - if (!(getenv("WAYLAND_DISPLAY"))) - return false; - - return true; - } -+ -+bool DesktopCapturer::IsRunningUnderWayland() { -+ return IsWaylandSessionUsed() ? IsWaylandDisplayUsed() : false; -+} - #endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - - } // namespace webrtc - diff --git a/pw2.patch b/pw2.patch deleted file mode 100644 index 9390460..0000000 --- a/pw2.patch +++ /dev/null @@ -1,901 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604560111 0 -# Node ID 998e6d0b24e4a560e5664aaef87307e9c069ad87 -# Parent 1c126b520042591194e88618ae11a6adc1da9a08 -Bug 1672947 Update PipeWire WebRTC code to PipeWire 0.3, r=ng - -Differential Revision: https://phabricator.services.mozilla.com/D94589 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -@@ -10,18 +10,20 @@ - - #include "modules/desktop_capture/linux/base_capturer_pipewire.h" - - #include - #include - - #include - #include --#include --#include -+ -+#include -+#include -+#include - - #include - #include - - #include "modules/desktop_capture/desktop_capture_options.h" - #include "modules/desktop_capture/desktop_capturer.h" - #include "rtc_base/checks.h" - #include "rtc_base/logging.h" -@@ -32,180 +34,166 @@ const char kDesktopBusName[] = "org.free - const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; - const char kDesktopRequestObjectPath[] = - "/org/freedesktop/portal/desktop/request"; - const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; - const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; - const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; - - // static --void BaseCapturerPipeWire::OnStateChanged(void* data, -- pw_remote_state old_state, -- pw_remote_state state, -- const char* error_message) { -- BaseCapturerPipeWire* that = static_cast(data); -- RTC_DCHECK(that); -+struct dma_buf_sync { -+ uint64_t flags; -+}; -+#define DMA_BUF_SYNC_READ (1 << 0) -+#define DMA_BUF_SYNC_START (0 << 2) -+#define DMA_BUF_SYNC_END (1 << 2) -+#define DMA_BUF_BASE 'b' -+#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) - -- switch (state) { -- case PW_REMOTE_STATE_ERROR: -- RTC_LOG(LS_ERROR) << "PipeWire remote state error: " << error_message; -+static void SyncDmaBuf(int fd, uint64_t start_or_end) { -+ struct dma_buf_sync sync = { 0 }; -+ -+ sync.flags = start_or_end | DMA_BUF_SYNC_READ; -+ -+ while(true) { -+ int ret; -+ ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync); -+ if (ret == -1 && errno == EINTR) { -+ continue; -+ } else if (ret == -1) { -+ RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " << g_strerror(errno); - break; -- case PW_REMOTE_STATE_CONNECTED: -- RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; -- that->CreateReceivingStream(); -+ } else { - break; -- case PW_REMOTE_STATE_CONNECTING: -- RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; -- break; -- case PW_REMOTE_STATE_UNCONNECTED: -- RTC_LOG(LS_INFO) << "PipeWire remote state: unconnected."; -- break; -+ } - } - } - - // static -+void BaseCapturerPipeWire::OnCoreError(void *data, -+ uint32_t id, -+ int seq, -+ int res, -+ const char *message) { -+ RTC_LOG(LS_ERROR) << "core error: " << message; -+} -+ -+// static - void BaseCapturerPipeWire::OnStreamStateChanged(void* data, - pw_stream_state old_state, - pw_stream_state state, - const char* error_message) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - - switch (state) { - case PW_STREAM_STATE_ERROR: - RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; - break; -- case PW_STREAM_STATE_CONFIGURE: -- pw_stream_set_active(that->pw_stream_, true); -- break; -+ case PW_STREAM_STATE_PAUSED: -+ case PW_STREAM_STATE_STREAMING: - case PW_STREAM_STATE_UNCONNECTED: - case PW_STREAM_STATE_CONNECTING: -- case PW_STREAM_STATE_READY: -- case PW_STREAM_STATE_PAUSED: -- case PW_STREAM_STATE_STREAMING: - break; - } - } - - // static --void BaseCapturerPipeWire::OnStreamFormatChanged(void* data, -- const struct spa_pod* format) { -+void BaseCapturerPipeWire::OnStreamParamChanged(void *data, uint32_t id, -+ const struct spa_pod *format) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - -- RTC_LOG(LS_INFO) << "PipeWire stream format changed."; -+ RTC_LOG(LS_INFO) << "PipeWire stream param changed."; - -- if (!format) { -- pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr, -- /*n_params=*/0); -+ if (!format || id != SPA_PARAM_Format) { - return; - } - -- that->spa_video_format_ = new spa_video_info_raw(); -- spa_format_video_raw_parse(format, that->spa_video_format_, -- &that->pw_type_->format_video); -+ spa_format_video_raw_parse(format, &that->spa_video_format_); - -- auto width = that->spa_video_format_->size.width; -- auto height = that->spa_video_format_->size.height; -+ auto width = that->spa_video_format_.size.width; -+ auto height = that->spa_video_format_.size.height; - auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4); - auto size = height * stride; - -+ that->desktop_size_ = DesktopSize(width, height); -+ - uint8_t buffer[1024] = {}; - auto builder = spa_pod_builder{buffer, sizeof(buffer)}; - - // Setup buffers and meta header for new format. -- const struct spa_pod* params[2]; -- params[0] = reinterpret_cast(spa_pod_builder_object( -- &builder, -- // id to enumerate buffer requirements -- that->pw_core_type_->param.idBuffers, -- that->pw_core_type_->param_buffers.Buffers, -- // Size: specified as integer (i) and set to specified size -- ":", that->pw_core_type_->param_buffers.size, "i", size, -- // Stride: specified as integer (i) and set to specified stride -- ":", that->pw_core_type_->param_buffers.stride, "i", stride, -- // Buffers: specifies how many buffers we want to deal with, set as -- // integer (i) where preferred number is 8, then allowed number is defined -- // as range (r) from min and max values and it is undecided (u) to allow -- // negotiation -- ":", that->pw_core_type_->param_buffers.buffers, "iru", 8, -- SPA_POD_PROP_MIN_MAX(1, 32), -- // Align: memory alignment of the buffer, set as integer (i) to specified -- // value -- ":", that->pw_core_type_->param_buffers.align, "i", 16)); -- params[1] = reinterpret_cast(spa_pod_builder_object( -- &builder, -- // id to enumerate supported metadata -- that->pw_core_type_->param.idMeta, that->pw_core_type_->param_meta.Meta, -- // Type: specified as id or enum (I) -- ":", that->pw_core_type_->param_meta.type, "I", -- that->pw_core_type_->meta.Header, -- // Size: size of the metadata, specified as integer (i) -- ":", that->pw_core_type_->param_meta.size, "i", -- sizeof(struct spa_meta_header))); -- -- pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/2); -+ const struct spa_pod* params[3]; -+ params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, -+ SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), -+ SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride), -+ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32))); -+ params[1] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, -+ SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), -+ SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)))); -+ params[2] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, -+ SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop), -+ SPA_PARAM_META_size, SPA_POD_Int (sizeof(struct spa_meta_region)))); -+ pw_stream_update_params(that->pw_stream_, params, 3); - } - - // static - void BaseCapturerPipeWire::OnStreamProcess(void* data) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - -- pw_buffer* buf = nullptr; -+ struct pw_buffer *next_buffer; -+ struct pw_buffer *buffer = nullptr; - -- if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { -+ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); -+ while (next_buffer) { -+ buffer = next_buffer; -+ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); -+ -+ if (next_buffer) { -+ pw_stream_queue_buffer (that->pw_stream_, buffer); -+ } -+ } -+ -+ if (!buffer) { - return; - } - -- that->HandleBuffer(buf); -+ that->HandleBuffer(buffer); - -- pw_stream_queue_buffer(that->pw_stream_, buf); -+ pw_stream_queue_buffer(that->pw_stream_, buffer); - } - - BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) - : capture_source_type_(source_type) {} - - BaseCapturerPipeWire::~BaseCapturerPipeWire() { - if (pw_main_loop_) { - pw_thread_loop_stop(pw_main_loop_); - } - -- if (pw_type_) { -- delete pw_type_; -- } -- -- if (spa_video_format_) { -- delete spa_video_format_; -- } -- - if (pw_stream_) { - pw_stream_destroy(pw_stream_); - } - -- if (pw_remote_) { -- pw_remote_destroy(pw_remote_); -+ if (pw_core_) { -+ pw_core_disconnect(pw_core_); - } - -- if (pw_core_) { -- pw_core_destroy(pw_core_); -+ if (pw_context_) { -+ pw_context_destroy(pw_context_); - } - - if (pw_main_loop_) { - pw_thread_loop_destroy(pw_main_loop_); - } - -- if (pw_loop_) { -- pw_loop_destroy(pw_loop_); -- } -- -- if (current_frame_) { -- free(current_frame_); -- } -- - if (start_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); - } - if (sources_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, - sources_request_signal_id_); - } - if (session_request_signal_id_) { -@@ -245,143 +233,210 @@ void BaseCapturerPipeWire::InitPortal() - kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName, - /*cancellable=*/nullptr, - reinterpret_cast(OnProxyRequested), this); - } - - void BaseCapturerPipeWire::InitPipeWire() { - pw_init(/*argc=*/nullptr, /*argc=*/nullptr); - -- pw_loop_ = pw_loop_new(/*properties=*/nullptr); -- pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); -+ pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); -+ pw_context_ = pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); -+ if (!pw_context_) { -+ RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; -+ return; -+ } - -- pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); -- pw_core_type_ = pw_core_get_type(pw_core_); -- pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); -- -- InitPipeWireTypes(); -+ pw_core_ = pw_context_connect(pw_context_, nullptr, 0); -+ if (!pw_core_) { -+ RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; -+ return; -+ } - - // Initialize event handlers, remote end and stream-related. -- pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS; -- pw_remote_events_.state_changed = &OnStateChanged; -+ pw_core_events_.version = PW_VERSION_CORE_EVENTS; -+ pw_core_events_.error = &OnCoreError; - - pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; - pw_stream_events_.state_changed = &OnStreamStateChanged; -- pw_stream_events_.format_changed = &OnStreamFormatChanged; -+ pw_stream_events_.param_changed = &OnStreamParamChanged; - pw_stream_events_.process = &OnStreamProcess; - -- pw_remote_add_listener(pw_remote_, &spa_remote_listener_, &pw_remote_events_, -- this); -- pw_remote_connect_fd(pw_remote_, pw_fd_); -+ pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, this); -+ -+ pw_stream_ = CreateReceivingStream(); -+ if (!pw_stream_) { -+ RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream"; -+ return; -+ } - - if (pw_thread_loop_start(pw_main_loop_) < 0) { - RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; - portal_init_failed_ = true; - } - } - --void BaseCapturerPipeWire::InitPipeWireTypes() { -- spa_type_map* map = pw_core_type_->map; -- pw_type_ = new PipeWireType(); -- -- spa_type_media_type_map(map, &pw_type_->media_type); -- spa_type_media_subtype_map(map, &pw_type_->media_subtype); -- spa_type_format_video_map(map, &pw_type_->format_video); -- spa_type_video_format_map(map, &pw_type_->video_format); --} -+pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { -+ spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; -+ spa_rectangle pwMaxScreenBounds = spa_rectangle{UINT32_MAX, UINT32_MAX}; - --void BaseCapturerPipeWire::CreateReceivingStream() { -- spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; -- spa_rectangle pwScreenBounds = -- spa_rectangle{static_cast(desktop_size_.width()), -- static_cast(desktop_size_.height())}; -+ auto stream = pw_stream_new(pw_core_, "webrtc-pipewire-stream", nullptr); - -- spa_fraction pwFrameRateMin = spa_fraction{0, 1}; -- spa_fraction pwFrameRateMax = spa_fraction{60, 1}; -- -- pw_properties* reuseProps = pw_properties_new("pipewire.client.reuse", "1", -- /*end of varargs*/ nullptr); -- pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); -+ if (!stream) { -+ RTC_LOG(LS_ERROR) << "Could not create receiving stream."; -+ return nullptr; -+ } - - uint8_t buffer[1024] = {}; -- const spa_pod* params[1]; -- spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; -- params[0] = reinterpret_cast(spa_pod_builder_object( -- &builder, -- // id to enumerate formats -- pw_core_type_->param.idEnumFormat, pw_core_type_->spa_format, "I", -- pw_type_->media_type.video, "I", pw_type_->media_subtype.raw, -- // Video format: specified as id or enum (I), preferred format is BGRx, -- // then allowed formats are enumerated (e) and the format is undecided (u) -- // to allow negotiation -- ":", pw_type_->format_video.format, "Ieu", pw_type_->video_format.BGRx, -- SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx, -- pw_type_->video_format.BGRx), -- // Video size: specified as rectangle (R), preferred size is specified as -- // first parameter, then allowed size is defined as range (r) from min and -- // max values and the format is undecided (u) to allow negotiation -- ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2, -- &pwMinScreenBounds, &pwScreenBounds, -- // Frame rate: specified as fraction (F) and set to minimum frame rate -- // value -- ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin, -- // Max frame rate: specified as fraction (F), preferred frame rate is set -- // to maximum value, then allowed frame rate is defined as range (r) from -- // min and max values and it is undecided (u) to allow negotiation -- ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, -- &pwFrameRateMin, &pwFrameRateMax)); -+ const spa_pod* params[2]; -+ spa_pod_builder builder = SPA_POD_BUILDER_INIT(buffer, sizeof (buffer)); - -- pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_, -- this); -- pw_stream_flags flags = static_cast( -- PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | -- PW_STREAM_FLAG_MAP_BUFFERS); -- if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, /*port_path=*/nullptr, -- flags, params, -- /*n_params=*/1) != 0) { -+ params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), -+ SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA, -+ SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_BGRA), -+ SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMinScreenBounds, -+ &pwMinScreenBounds, -+ &pwMaxScreenBounds), -+ 0)); -+ pw_stream_add_listener(stream, &spa_stream_listener_, &pw_stream_events_, this); -+ -+ if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pw_stream_node_id_, -+ PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) { - RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; - portal_init_failed_ = true; -- return; -+ } -+ -+ return stream; -+} -+ -+static void SpaBufferUnmap(unsigned char *map, int map_size, bool IsDMABuf, int fd) { -+ if (map) { -+ if (IsDMABuf) { -+ SyncDmaBuf(fd, DMA_BUF_SYNC_END); -+ } -+ munmap(map, map_size); - } - } - - void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { - spa_buffer* spaBuffer = buffer->buffer; -- void* src = nullptr; -+ uint8_t *map = nullptr; -+ uint8_t* src = nullptr; - -- if (!(src = spaBuffer->datas[0].data)) { -+ if (spaBuffer->datas[0].chunk->size == 0) { -+ RTC_LOG(LS_ERROR) << "Failed to get video stream: Zero size."; - return; - } - -- uint32_t maxSize = spaBuffer->datas[0].maxsize; -- int32_t srcStride = spaBuffer->datas[0].chunk->stride; -- if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { -- RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " -- << srcStride -- << " != " << (desktop_size_.width() * kBytesPerPixel); -- portal_init_failed_ = true; -+ switch (spaBuffer->datas[0].type) { -+ case SPA_DATA_MemFd: -+ case SPA_DATA_DmaBuf: -+ map = static_cast(mmap( -+ nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)); -+ if (map == MAP_FAILED) { -+ RTC_LOG(LS_ERROR) << "Failed to mmap memory: " << std::strerror(errno); -+ return; -+ } -+ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { -+ SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_START); -+ } -+ src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t); -+ break; -+ case SPA_DATA_MemPtr: -+ map = nullptr; -+ src = static_cast(spaBuffer->datas[0].data); -+ break; -+ default: -+ return; -+ } -+ -+ if (!src) { -+ RTC_LOG(LS_ERROR) << "Failed to get video stream: Wrong data after mmap()"; -+ SpaBufferUnmap(map, -+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); -+ return; -+ } -+ -+ struct spa_meta_region* video_metadata = -+ static_cast( -+ spa_buffer_find_meta_data(spaBuffer, SPA_META_VideoCrop, sizeof(*video_metadata))); -+ -+ // Video size from metada is bigger than an actual video stream size. -+ // The metadata are wrong or we should up-scale te video...in both cases -+ // just quit now. -+ if (video_metadata && -+ (video_metadata->region.size.width > (uint32_t)desktop_size_.width() || -+ video_metadata->region.size.height > (uint32_t)desktop_size_.height())) { -+ RTC_LOG(LS_ERROR) << "Stream metadata sizes are wrong!"; -+ SpaBufferUnmap(map, -+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); - return; - } - -- if (!current_frame_) { -- current_frame_ = static_cast(malloc(maxSize)); -+ // Use video metada when video size from metadata is set and smaller than -+ // video stream size, so we need to adjust it. -+ video_metadata_use_ = (video_metadata && -+ video_metadata->region.size.width != 0 && -+ video_metadata->region.size.height != 0 && -+ (video_metadata->region.size.width < (uint32_t)desktop_size_.width() || -+ video_metadata->region.size.height < (uint32_t)desktop_size_.height())); -+ -+ DesktopSize video_size_prev = video_size_; -+ if (video_metadata_use_) { -+ video_size_ = DesktopSize(video_metadata->region.size.width, -+ video_metadata->region.size.height); -+ } else { -+ video_size_ = desktop_size_; - } -- RTC_DCHECK(current_frame_ != nullptr); -+ -+ if (!current_frame_ || -+ (video_metadata_use_ && !video_size_.equals(video_size_prev))) { -+ current_frame_ = -+ std::make_unique -+ (video_size_.width() * video_size_.height() * kBytesPerPixel); -+ } -+ -+ const int32_t dstStride = video_size_.width() * kBytesPerPixel; -+ const int32_t srcStride = spaBuffer->datas[0].chunk->stride; - -- // If both sides decided to go with the RGBx format we need to convert it to -- // BGRx to match color format expected by WebRTC. -- if (spa_video_format_->format == pw_type_->video_format.RGBx) { -- uint8_t* tempFrame = static_cast(malloc(maxSize)); -- std::memcpy(tempFrame, src, maxSize); -- ConvertRGBxToBGRx(tempFrame, maxSize); -- std::memcpy(current_frame_, tempFrame, maxSize); -- free(tempFrame); -- } else { -- std::memcpy(current_frame_, src, maxSize); -+ // Adjust source content based on metadata video position -+ if (video_metadata_use_ && -+ (video_metadata->region.position.y + video_size_.height() <= desktop_size_.height())) { -+ src += srcStride * video_metadata->region.position.y; - } -+ const int xOffset = -+ video_metadata_use_ && -+ (video_metadata->region.position.x + video_size_.width() <= desktop_size_.width()) -+ ? video_metadata->region.position.x * kBytesPerPixel -+ : 0; -+ -+ uint8_t* dst = current_frame_.get(); -+ for (int i = 0; i < video_size_.height(); ++i) { -+ // Adjust source content based on crop video position if needed -+ src += xOffset; -+ std::memcpy(dst, src, dstStride); -+ // If both sides decided to go with the RGBx format we need to convert it to -+ // BGRx to match color format expected by WebRTC. -+ if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || -+ spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { -+ ConvertRGBxToBGRx(dst, dstStride); -+ } -+ src += srcStride - xOffset; -+ dst += dstStride; -+ } -+ -+ SpaBufferUnmap(map, -+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); - } - - void BaseCapturerPipeWire::ConvertRGBxToBGRx(uint8_t* frame, uint32_t size) { - // Change color format for KDE KWin which uses RGBx and not BGRx - for (uint32_t i = 0; i < size; i += 4) { - uint8_t tempR = frame[i]; - uint8_t tempB = frame[i + 2]; - frame[i] = tempB; -@@ -713,27 +768,22 @@ void BaseCapturerPipeWire::OnStartReques - // Array of PipeWire streams. See - // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml - // documentation for . - if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) { - GVariant* variant; - - while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) { - guint32 stream_id; -- gint32 width; -- gint32 height; - GVariant* options; - - g_variant_get(variant, "(u@a{sv})", &stream_id, &options); - RTC_DCHECK(options != nullptr); - -- g_variant_lookup(options, "size", "(ii)", &width, &height); -- -- that->desktop_size_.set(width, height); -- -+ that->pw_stream_node_id_ = stream_id; - g_variant_unref(options); - g_variant_unref(variant); - } - } - g_variant_iter_free(iter); - g_variant_unref(response_data); - - that->OpenPipeWireRemote(); -@@ -808,20 +858,25 @@ void BaseCapturerPipeWire::CaptureFrame( - return; - } - - if (!current_frame_) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - -- std::unique_ptr result(new BasicDesktopFrame(desktop_size_)); -+ DesktopSize frame_size = desktop_size_; -+ if (video_metadata_use_) { -+ frame_size = video_size_; -+ } -+ -+ std::unique_ptr result(new BasicDesktopFrame(frame_size)); - result->CopyPixelsFrom( -- current_frame_, (desktop_size_.width() * kBytesPerPixel), -- DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height())); -+ current_frame_.get(), (frame_size.width() * kBytesPerPixel), -+ DesktopRect::MakeWH(frame_size.width(), frame_size.height())); - if (!result) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); - } - - bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { -@@ -832,9 +887,27 @@ bool BaseCapturerPipeWire::GetSourceList - return true; - } - - bool BaseCapturerPipeWire::SelectSource(SourceId id) { - // Screen selection is handled by the xdg-desktop-portal. - return true; - } - -+// static -+std::unique_ptr -+BaseCapturerPipeWire::CreateRawScreenCapturer( -+ const DesktopCaptureOptions& options) { -+ std::unique_ptr capturer = -+ std::make_unique(BaseCapturerPipeWire::CaptureSourceType::kAny); -+ return std::move(capturer);} -+ -+// static -+std::unique_ptr -+BaseCapturerPipeWire::CreateRawWindowCapturer( -+ const DesktopCaptureOptions& options) { -+ -+ std::unique_ptr capturer = -+ std::make_unique(BaseCapturerPipeWire::CaptureSourceType::kAny); -+ return std::move(capturer); -+} -+ - } // namespace webrtc -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -@@ -17,99 +17,102 @@ - #include - - #include "modules/desktop_capture/desktop_capture_options.h" - #include "modules/desktop_capture/desktop_capturer.h" - #include "rtc_base/constructormagic.h" - - namespace webrtc { - --class PipeWireType { -- public: -- spa_type_media_type media_type; -- spa_type_media_subtype media_subtype; -- spa_type_format_video format_video; -- spa_type_video_format video_format; --}; -- - class BaseCapturerPipeWire : public DesktopCapturer { - public: -- enum CaptureSourceType { Screen = 1, Window }; -+ enum CaptureSourceType : uint32_t { -+ kScreen = 0b01, -+ kWindow = 0b10, -+ kAny = 0b11 -+ }; - - explicit BaseCapturerPipeWire(CaptureSourceType source_type); - ~BaseCapturerPipeWire() override; - - // DesktopCapturer interface. - void Start(Callback* delegate) override; - void CaptureFrame() override; - bool GetSourceList(SourceList* sources) override; - bool SelectSource(SourceId id) override; - -+ static std::unique_ptr CreateRawScreenCapturer( -+ const DesktopCaptureOptions& options); -+ -+ static std::unique_ptr CreateRawWindowCapturer( -+ const DesktopCaptureOptions& options); -+ - private: - // PipeWire types --> -+ pw_context* pw_context_ = nullptr; - pw_core* pw_core_ = nullptr; -- pw_type* pw_core_type_ = nullptr; - pw_stream* pw_stream_ = nullptr; -- pw_remote* pw_remote_ = nullptr; -- pw_loop* pw_loop_ = nullptr; - pw_thread_loop* pw_main_loop_ = nullptr; -- PipeWireType* pw_type_ = nullptr; - -+ spa_hook spa_core_listener_ = {}; - spa_hook spa_stream_listener_ = {}; -- spa_hook spa_remote_listener_ = {}; - -+ pw_core_events pw_core_events_ = {}; - pw_stream_events pw_stream_events_ = {}; -- pw_remote_events pw_remote_events_ = {}; - -- spa_video_info_raw* spa_video_format_ = nullptr; -+ struct spa_video_info_raw spa_video_format_; - -+ guint32 pw_stream_node_id_ = 0; - gint32 pw_fd_ = -1; - - CaptureSourceType capture_source_type_ = -- BaseCapturerPipeWire::CaptureSourceType::Screen; -+ BaseCapturerPipeWire::CaptureSourceType::kAny; - - // <-- end of PipeWire types - - GDBusConnection* connection_ = nullptr; - GDBusProxy* proxy_ = nullptr; - gchar* portal_handle_ = nullptr; - gchar* session_handle_ = nullptr; - gchar* sources_handle_ = nullptr; - gchar* start_handle_ = nullptr; - guint session_request_signal_id_ = 0; - guint sources_request_signal_id_ = 0; - guint start_request_signal_id_ = 0; - -+ bool video_metadata_use_ = false; -+ DesktopSize video_size_; - DesktopSize desktop_size_ = {}; - DesktopCaptureOptions options_ = {}; - -- uint8_t* current_frame_ = nullptr; -+ std::unique_ptr current_frame_; - Callback* callback_ = nullptr; - - bool portal_init_failed_ = false; - - void InitPortal(); - void InitPipeWire(); -- void InitPipeWireTypes(); - -- void CreateReceivingStream(); -+ pw_stream* CreateReceivingStream(); - void HandleBuffer(pw_buffer* buffer); - - void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); - -- static void OnStateChanged(void* data, -- pw_remote_state old_state, -- pw_remote_state state, -- const char* error); -+ static void OnCoreError(void *data, -+ uint32_t id, -+ int seq, -+ int res, -+ const char *message); -+ static void OnStreamParamChanged(void *data, -+ uint32_t id, -+ const struct spa_pod *format); - static void OnStreamStateChanged(void* data, - pw_stream_state old_state, - pw_stream_state state, - const char* error_message); -- -- static void OnStreamFormatChanged(void* data, const struct spa_pod* format); - static void OnStreamProcess(void* data); - static void OnNewBuffer(void* data, uint32_t id); - - guint SetupRequestResponseSignal(const gchar* object_path, - GDBusSignalCallback callback); - - static void OnProxyRequested(GObject* object, - GAsyncResult* result, -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc -@@ -10,17 +10,17 @@ - - #include "modules/desktop_capture/linux/screen_capturer_pipewire.h" - - #include - - namespace webrtc { - - ScreenCapturerPipeWire::ScreenCapturerPipeWire() -- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} -+ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kScreen) {} - ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} - - // static - std::unique_ptr - ScreenCapturerPipeWire::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { - return std::make_unique(); - } -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc -@@ -10,17 +10,17 @@ - - #include "modules/desktop_capture/linux/window_capturer_pipewire.h" - - #include - - namespace webrtc { - - WindowCapturerPipeWire::WindowCapturerPipeWire() -- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} -+ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kWindow) {} - WindowCapturerPipeWire::~WindowCapturerPipeWire() {} - - // static - std::unique_ptr - WindowCapturerPipeWire::CreateRawWindowCapturer( - const DesktopCaptureOptions& options) { - return std::make_unique(); - } -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc -@@ -21,17 +21,17 @@ - - namespace webrtc { - - // static - std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { - #if defined(WEBRTC_USE_PIPEWIRE) - if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { -- return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); -+ return BaseCapturerPipeWire::CreateRawScreenCapturer(options); - } - #endif // defined(WEBRTC_USE_PIPEWIRE) - - #if defined(USE_X11) - return ScreenCapturerX11::CreateRawScreenCapturer(options); - #endif // defined(USE_X11) - - return nullptr; -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc -@@ -21,17 +21,17 @@ - - namespace webrtc { - - // static - std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( - const DesktopCaptureOptions& options) { - #if defined(WEBRTC_USE_PIPEWIRE) - if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { -- return WindowCapturerPipeWire::CreateRawWindowCapturer(options); -+ return BaseCapturerPipeWire::CreateRawWindowCapturer(options); - } - #endif // defined(WEBRTC_USE_PIPEWIRE) - - #if defined(USE_X11) - return WindowCapturerX11::CreateRawWindowCapturer(options); - #endif // defined(USE_X11) - - return nullptr; - diff --git a/pw3.patch b/pw3.patch deleted file mode 100644 index 82d451e..0000000 --- a/pw3.patch +++ /dev/null @@ -1,183 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604562423 0 -# Node ID d1a244822d7811575f5bb3cd024f8f324275aec2 -# Parent 998e6d0b24e4a560e5664aaef87307e9c069ad87 -Bug 1672989 Build PipeWire as a part of default builds, r=dminor - -Differential Revision: https://phabricator.services.mozilla.com/D94590 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn b/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn -@@ -152,22 +152,17 @@ if (rtc_include_tests) { - "../../rtc_base:rtc_base_approved", - "../../test:test_support", - ] - } - } - - if (is_linux) { - if (rtc_use_pipewire) { -- pkg_config("pipewire") { -- packages = [ "libpipewire-0.2" ] -- -- defines = [ "WEBRTC_USE_PIPEWIRE" ] -- } -- -+ defines = [ "WEBRTC_USE_PIPEWIRE" ] - pkg_config("gio") { - packages = [ - "gio-2.0", - "gio-unix-2.0", - ] - } - } - } -@@ -326,16 +321,17 @@ rtc_static_library("desktop_capture_gene - } else { - sources += [ - "fake_desktop_capturer.cc", - "fake_desktop_capturer.h", - ] - } - - if (use_x11 || rtc_use_pipewire) { -+ include_dirs = [ "/third_party/libwebrtc/third_party/pipewire" ] - sources += [ - "mouse_cursor_monitor_linux.cc", - "screen_capturer_linux.cc", - "window_capturer_linux.cc", - ] - } - - if (use_x11) { -@@ -367,16 +363,17 @@ rtc_static_library("desktop_capture_gene - "linux/desktop_device_info_x11.h", - "linux/shared_x_util.cc", - "linux/shared_x_util.h", - ] - } - } - - if (rtc_use_pipewire) { -+ include_dirs = [ "/third_party/libwebrtc/third_party/pipewire" ] - sources += [ - "linux/base_capturer_pipewire.cc", - "linux/base_capturer_pipewire.h", - "linux/screen_capturer_pipewire.cc", - "linux/screen_capturer_pipewire.h", - "linux/window_capturer_pipewire.cc", - "linux/window_capturer_pipewire.h", - ] -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build -@@ -20,17 +20,18 @@ DEFINES["WEBRTC_RESTRICT_LOGGING"] = Tru - FINAL_LIBRARY = "webrtc" - - - LOCAL_INCLUDES += [ - "!/ipc/ipdl/_ipdlheaders", - "/ipc/chromium/src", - "/ipc/glue", - "/media/libyuv/libyuv/include/", -- "/third_party/libwebrtc/webrtc/" -+ "/third_party/libwebrtc/webrtc/", -+ "/third_party/pipewire" - ] - - UNIFIED_SOURCES += [ - "/third_party/libwebrtc/webrtc/modules/desktop_capture/blank_detector_desktop_capturer_wrapper.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/capture_result_desktop_capturer_wrapper.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/cropped_desktop_frame.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/cropping_window_capturer.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_and_cursor_composer.cc", -@@ -156,16 +157,17 @@ if CONFIG["OS_TARGET"] == "FreeBSD": - - if CONFIG["OS_TARGET"] == "Linux": - - DEFINES["USE_NSS_CERTS"] = "1" - DEFINES["USE_X11"] = "1" - DEFINES["WEBRTC_LINUX"] = True - DEFINES["WEBRTC_POSIX"] = True - DEFINES["_FILE_OFFSET_BITS"] = "64" -+ DEFINES["WEBRTC_USE_PIPEWIRE"] = "1" - - OS_LIBS += [ - "rt", - "X11", - "X11-xcb", - "xcb", - "Xcomposite", - "Xcursor", -@@ -188,16 +190,24 @@ if CONFIG["OS_TARGET"] == "Linux": - "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/x_atom_cache.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/x_error_trap.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/x_server_pixel_buffer.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc" - ] - -+ CXXFLAGS += CONFIG['TK_CFLAGS'] -+ -+ UNIFIED_SOURCES += [ -+ "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", -+ "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", -+ "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" -+ ] -+ - if CONFIG["OS_TARGET"] == "NetBSD": - - DEFINES["USE_X11"] = "1" - DEFINES["WEBRTC_BSD"] = True - DEFINES["WEBRTC_POSIX"] = True - DEFINES["_FILE_OFFSET_BITS"] = "64" - - OS_LIBS += [ -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h -@@ -136,15 +136,15 @@ class DesktopCaptureOptions { - #if defined(USE_X11) - bool use_update_notifications_ = false; - #else - bool use_update_notifications_ = true; - #endif - bool disable_effects_ = true; - bool detect_updated_region_ = false; - #if defined(WEBRTC_USE_PIPEWIRE) -- bool allow_pipewire_ = false; -+ bool allow_pipewire_ = true; - #endif - }; - - } // namespace webrtc - - #endif // MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_ -diff --git a/third_party/libwebrtc/webrtc/moz.build b/third_party/libwebrtc/webrtc/moz.build ---- a/third_party/libwebrtc/webrtc/moz.build -+++ b/third_party/libwebrtc/webrtc/moz.build -@@ -181,16 +181,19 @@ if CONFIG["OS_TARGET"] == "Linux": - - DIRS += [ - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/primitives_gn", - "/third_party/libwebrtc/webrtc/modules/video_capture/video_capture_internal_impl_gn", - "/third_party/libwebrtc/webrtc/system_wrappers/cpu_features_linux_gn" - ] -+ DIRS += [ -+ "/third_party/pipewire/libpipewire" -+ ] - - if CONFIG["OS_TARGET"] == "NetBSD": - - DIRS += [ - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/primitives_gn", - "/third_party/libwebrtc/webrtc/modules/video_capture/video_capture_internal_impl_gn" - diff --git a/pw4.patch b/pw4.patch deleted file mode 100644 index 03bda37..0000000 --- a/pw4.patch +++ /dev/null @@ -1,18928 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604009732 0 -# Node ID e5e706b532041baa3ef46420c9bf10629b0cb3ba -# Parent 7dad14e6de1a80a5c6a194df8a7b16504fb3d617 -Bug 1672945 Ship PipeWire 0.3 headers and library wrapper to build PW support out of the box, r=dminor - -- Ship PipeWire 0.3 headers at third_party/pipewire/pipewire -- Ship SPA 0.2 headers at third_party/pipewire/spa -- Ship PipeWire library wrapper at third_party/pipewire/libpipewire - -Differential Revision: https://phabricator.services.mozilla.com/D94580 - -diff --git a/third_party/pipewire/README b/third_party/pipewire/README -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/README -@@ -0,0 +1,4 @@ -+Libpipewire is a pipewire library wrapper needed to build and run Firefox with -+Pipewire support on Linux (https://pipewire.org/). -+ -+Pipewire directory stores headers of pipewire-0.2 and spa-0.2 needed for build only. -diff --git a/third_party/pipewire/libpipewire/moz.build b/third_party/pipewire/libpipewire/moz.build -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/libpipewire/moz.build -@@ -0,0 +1,15 @@ -+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -+# vim: set filetype=python: -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+SOURCES += [ -+ 'mozpipewire.cpp', -+] -+ -+CXXFLAGS += CONFIG['TK_CFLAGS'] -+ -+LOCAL_INCLUDES += ['/third_party/pipewire'] -+ -+FINAL_LIBRARY = 'xul' -diff --git a/third_party/pipewire/libpipewire/mozpipewire.cpp b/third_party/pipewire/libpipewire/mozpipewire.cpp -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/libpipewire/mozpipewire.cpp -@@ -0,0 +1,312 @@ -+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=4: -+ */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include -+#include "mozilla/Types.h" -+#include "prlink.h" -+ -+#include -+ -+#define GET_FUNC(func, lib) \ -+ func##_fn = \ -+ (decltype(func##_fn))PR_FindFunctionSymbol(lib, #func) \ -+ -+#define IS_FUNC_LOADED(func) \ -+ (func != nullptr) \ -+ -+struct GUnixFDList; -+ -+extern "C" gint -+g_unix_fd_list_get(struct GUnixFDList *list, -+ gint index_, -+ GError **error) -+{ -+ static PRLibrary* gioLib = nullptr; -+ static bool gioInitialized = false; -+ static gint (*g_unix_fd_list_get_fn)(struct GUnixFDList *list, -+ gint index_, GError **error) = nullptr; -+ -+ if (!gioInitialized) { -+ gioInitialized = true; -+ gioLib = PR_LoadLibrary("libgio-2.0.so.0"); -+ if (!gioLib) { -+ return -1; -+ } -+ GET_FUNC(g_unix_fd_list_get, gioLib); -+ } -+ -+ if (!g_unix_fd_list_get_fn) { -+ return -1; -+ } -+ -+ return g_unix_fd_list_get_fn(list, index_, error); -+} -+ -+static struct pw_core * (*pw_context_connect_fn)(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size); -+static void (*pw_context_destroy_fn)(struct pw_context *context); -+struct pw_context * (*pw_context_new_fn)(struct pw_loop *main_loop, -+ struct pw_properties *props, -+ size_t user_data_size); -+static int (*pw_core_disconnect_fn)(struct pw_core *core); -+static void (*pw_init_fn)(int *argc, char **argv[]); -+static void (*pw_stream_add_listener_fn)(struct pw_stream *stream, -+ struct spa_hook *listener, -+ const struct pw_stream_events *events, -+ void *data); -+static int (*pw_stream_connect_fn)(struct pw_stream *stream, -+ enum pw_direction direction, -+ uint32_t target_id, -+ enum pw_stream_flags flags, -+ const struct spa_pod **params, -+ uint32_t n_params); -+static struct pw_buffer* (*pw_stream_dequeue_buffer_fn)(struct pw_stream *stream); -+static void (*pw_stream_destroy_fn)(struct pw_stream *stream); -+static struct pw_stream* (*pw_stream_new_fn)(struct pw_core *core, -+ const char *name, -+ struct pw_properties *props); -+static int (*pw_stream_queue_buffer_fn)(struct pw_stream *stream, -+ struct pw_buffer *buffer); -+static int (*pw_stream_update_params_fn)(struct pw_stream *stream, -+ const struct spa_pod **params, -+ uint32_t n_params); -+static void (*pw_thread_loop_destroy_fn)(struct pw_thread_loop *loop); -+static struct pw_loop* (*pw_thread_loop_get_loop_fn)(struct pw_thread_loop *loop); -+static struct pw_thread_loop* (*pw_thread_loop_new_fn)(const char *name, -+ const struct spa_dict *props); -+static int (*pw_thread_loop_start_fn)(struct pw_thread_loop *loop); -+static void (*pw_thread_loop_stop_fn)(struct pw_thread_loop *loop); -+ -+bool IsPwLibraryLoaded() { -+ static bool isLoaded = -+ (IS_FUNC_LOADED(pw_context_connect_fn) && -+ IS_FUNC_LOADED(pw_context_destroy_fn) && -+ IS_FUNC_LOADED(pw_context_new_fn) && -+ IS_FUNC_LOADED(pw_core_disconnect_fn) && -+ IS_FUNC_LOADED(pw_init_fn) && -+ IS_FUNC_LOADED(pw_stream_add_listener_fn) && -+ IS_FUNC_LOADED(pw_stream_connect_fn) && -+ IS_FUNC_LOADED(pw_stream_dequeue_buffer_fn) && -+ IS_FUNC_LOADED(pw_stream_destroy_fn) && -+ IS_FUNC_LOADED(pw_stream_new_fn) && -+ IS_FUNC_LOADED(pw_stream_queue_buffer_fn) && -+ IS_FUNC_LOADED(pw_stream_update_params_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_destroy_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_get_loop_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_new_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_start_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_stop_fn)); -+ -+ return isLoaded; -+} -+ -+bool LoadPWLibrary() { -+ static PRLibrary* pwLib = nullptr; -+ static bool pwInitialized = false; -+ -+ //TODO Thread safe -+ if (!pwInitialized) { -+ pwInitialized = true; -+ pwLib = PR_LoadLibrary("libpipewire-0.3.so.0"); -+ if (!pwLib) { -+ return false; -+ } -+ -+ GET_FUNC(pw_context_connect, pwLib); -+ GET_FUNC(pw_context_destroy, pwLib); -+ GET_FUNC(pw_context_new, pwLib); -+ GET_FUNC(pw_core_disconnect, pwLib); -+ GET_FUNC(pw_init, pwLib); -+ GET_FUNC(pw_stream_add_listener, pwLib); -+ GET_FUNC(pw_stream_connect, pwLib); -+ GET_FUNC(pw_stream_dequeue_buffer, pwLib); -+ GET_FUNC(pw_stream_destroy, pwLib); -+ GET_FUNC(pw_stream_new, pwLib); -+ GET_FUNC(pw_stream_queue_buffer, pwLib); -+ GET_FUNC(pw_stream_update_params, pwLib); -+ GET_FUNC(pw_thread_loop_destroy, pwLib); -+ GET_FUNC(pw_thread_loop_get_loop, pwLib); -+ GET_FUNC(pw_thread_loop_new, pwLib); -+ GET_FUNC(pw_thread_loop_start, pwLib); -+ GET_FUNC(pw_thread_loop_stop, pwLib); -+ } -+ -+ return IsPwLibraryLoaded(); -+} -+ -+struct pw_core * -+pw_context_connect(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_context_connect_fn(context, properties, user_data_size); -+} -+ -+void -+pw_context_destroy(struct pw_context *context) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ pw_context_destroy_fn(context); -+} -+ -+struct pw_context * -+pw_context_new(struct pw_loop *main_loop, -+ struct pw_properties *props, -+ size_t user_data_size) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_context_new_fn(main_loop, props, user_data_size); -+} -+ -+int -+pw_core_disconnect(struct pw_core *core) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_core_disconnect_fn(core); -+} -+ -+void -+pw_init(int *argc, char **argv[]) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_init_fn(argc, argv); -+} -+ -+void -+pw_stream_add_listener(struct pw_stream *stream, -+ struct spa_hook *listener, -+ const struct pw_stream_events *events, -+ void *data) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_stream_add_listener_fn(stream, listener, events, data); -+} -+ -+int -+pw_stream_connect(struct pw_stream *stream, -+ enum pw_direction direction, -+ uint32_t target_id, -+ enum pw_stream_flags flags, -+ const struct spa_pod **params, -+ uint32_t n_params) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_stream_connect_fn(stream, direction, target_id, flags, -+ params, n_params); -+} -+ -+struct pw_buffer * -+pw_stream_dequeue_buffer(struct pw_stream *stream) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_stream_dequeue_buffer_fn(stream); -+} -+ -+void -+pw_stream_destroy(struct pw_stream *stream) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_stream_destroy_fn(stream); -+} -+ -+struct pw_stream * -+pw_stream_new(struct pw_core *core, -+ const char *name, -+ struct pw_properties *props) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_stream_new_fn(core, name, props); -+} -+ -+int -+pw_stream_queue_buffer(struct pw_stream *stream, -+ struct pw_buffer *buffer) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_stream_queue_buffer_fn(stream, buffer); -+} -+ -+int -+pw_stream_update_params(struct pw_stream *stream, -+ const struct spa_pod **params, -+ uint32_t n_params) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_stream_update_params_fn(stream, params, n_params); -+} -+ -+void -+pw_thread_loop_destroy(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_thread_loop_destroy_fn(loop); -+} -+ -+struct pw_loop * -+pw_thread_loop_get_loop(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_thread_loop_get_loop_fn(loop); -+} -+ -+struct pw_thread_loop * -+pw_thread_loop_new(const char *name, -+ const struct spa_dict *props) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_thread_loop_new_fn(name, props); -+} -+ -+int -+pw_thread_loop_start(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_thread_loop_start_fn(loop); -+} -+ -+void -+pw_thread_loop_stop(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_thread_loop_stop_fn(loop); -+} -diff --git a/third_party/pipewire/pipewire/array.h b/third_party/pipewire/pipewire/array.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/array.h -@@ -0,0 +1,165 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_ARRAY_H -+#define PIPEWIRE_ARRAY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+/** \class pw_array -+ * -+ * \brief An array object -+ * -+ * The array is a dynamically resizable data structure that can -+ * hold items of the same size. -+ */ -+struct pw_array { -+ void *data; /**< pointer to array data */ -+ size_t size; /**< length of array in bytes */ -+ size_t alloc; /**< number of allocated memory in \a data */ -+ size_t extend; /**< number of bytes to extend with */ -+}; -+ -+#define PW_ARRAY_INIT(extend) (struct pw_array) { NULL, 0, 0, extend } -+ -+#define pw_array_get_len_s(a,s) ((a)->size / (s)) -+#define pw_array_get_unchecked_s(a,idx,s,t) SPA_MEMBER((a)->data,(idx)*(s),t) -+#define pw_array_check_index_s(a,idx,s) ((idx) < pw_array_get_len_s(a,s)) -+ -+/** Get the number of items of type \a t in array \memberof pw_array */ -+#define pw_array_get_len(a,t) pw_array_get_len_s(a,sizeof(t)) -+/** Get the item with index \a idx and type \a t from array \memberof pw_array */ -+#define pw_array_get_unchecked(a,idx,t) pw_array_get_unchecked_s(a,idx,sizeof(t),t) -+/** Check if an item with index \a idx and type \a t exist in array \memberof pw_array */ -+#define pw_array_check_index(a,idx,t) pw_array_check_index_s(a,idx,sizeof(t)) -+ -+#define pw_array_first(a) ((a)->data) -+#define pw_array_end(a) SPA_MEMBER((a)->data, (a)->size, void) -+#define pw_array_check(a,p) (SPA_MEMBER(p,sizeof(*p),void) <= pw_array_end(a)) -+ -+#define pw_array_for_each(pos, array) \ -+ for (pos = (__typeof__(pos)) pw_array_first(array); \ -+ pw_array_check(array, pos); \ -+ (pos)++) -+ -+#define pw_array_consume(pos, array) \ -+ for (pos = (__typeof__(pos)) pw_array_first(array); \ -+ pw_array_check(array, pos); \ -+ pos = (__typeof__(pos)) pw_array_first(array)) -+ -+#define pw_array_remove(a,p) \ -+({ \ -+ (a)->size -= sizeof(*(p)); \ -+ memmove(p, SPA_MEMBER((p), sizeof(*(p)), void), \ -+ SPA_PTRDIFF(pw_array_end(a),(p))); \ -+}) -+ -+/** Initialize the array with given extend \memberof pw_array */ -+static inline void pw_array_init(struct pw_array *arr, size_t extend) -+{ -+ arr->data = NULL; -+ arr->size = arr->alloc = 0; -+ arr->extend = extend; -+} -+ -+/** Clear the array */ -+static inline void pw_array_clear(struct pw_array *arr) -+{ -+ free(arr->data); -+} -+ -+/** Reset the array */ -+static inline void pw_array_reset(struct pw_array *arr) -+{ -+ arr->size = 0; -+} -+ -+/** Make sure \a size bytes can be added to the array \memberof pw_array */ -+static inline int pw_array_ensure_size(struct pw_array *arr, size_t size) -+{ -+ size_t alloc, need; -+ -+ alloc = arr->alloc; -+ need = arr->size + size; -+ -+ if (SPA_UNLIKELY(alloc < need)) { -+ void *data; -+ alloc = SPA_MAX(alloc, arr->extend); -+ while (alloc < need) -+ alloc *= 2; -+ if (SPA_UNLIKELY((data = realloc(arr->data, alloc)) == NULL)) -+ return -errno; -+ arr->data = data; -+ arr->alloc = alloc; -+ } -+ return 0; -+} -+ -+/** Add \a ref size bytes to \a arr. A pointer to memory that can -+ * hold at least \a size bytes is returned \memberof pw_array */ -+static inline void *pw_array_add(struct pw_array *arr, size_t size) -+{ -+ void *p; -+ -+ if (pw_array_ensure_size(arr, size) < 0) -+ return NULL; -+ -+ p = SPA_MEMBER(arr->data, arr->size, void); -+ arr->size += size; -+ -+ return p; -+} -+ -+/** Add \a ref size bytes to \a arr. When there is not enough memory to -+ * hold \a size bytes, NULL is returned \memberof pw_array */ -+static inline void *pw_array_add_fixed(struct pw_array *arr, size_t size) -+{ -+ void *p; -+ -+ if (SPA_UNLIKELY(arr->alloc < arr->size + size)) { -+ errno = ENOSPC; -+ return NULL; -+ } -+ -+ p = SPA_MEMBER(arr->data, arr->size, void); -+ arr->size += size; -+ -+ return p; -+} -+ -+/** Add a pointer to array \memberof pw_array */ -+#define pw_array_add_ptr(a,p) \ -+ *((void**) pw_array_add(a, sizeof(void*))) = (p) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_ARRAY_H */ -diff --git a/third_party/pipewire/pipewire/buffers.h b/third_party/pipewire/pipewire/buffers.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/buffers.h -@@ -0,0 +1,60 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_BUFFERS_H -+#define PIPEWIRE_BUFFERS_H -+ -+#include -+ -+#include -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define PW_BUFFERS_FLAG_NONE 0 -+#define PW_BUFFERS_FLAG_NO_MEM (1<<0) /**< don't allocate buffer memory */ -+#define PW_BUFFERS_FLAG_SHARED (1<<1) /**< buffers can be shared */ -+#define PW_BUFFERS_FLAG_DYNAMIC (1<<2) /**< buffers have dynamic data */ -+ -+struct pw_buffers { -+ struct pw_memblock *mem; /**< allocated buffer memory */ -+ struct spa_buffer **buffers; /**< port buffers */ -+ uint32_t n_buffers; /**< number of port buffers */ -+ uint32_t flags; /**< flags */ -+}; -+ -+int pw_buffers_negotiate(struct pw_context *context, uint32_t flags, -+ struct spa_node *outnode, uint32_t out_port_id, -+ struct spa_node *innode, uint32_t in_port_id, -+ struct pw_buffers *result); -+ -+void pw_buffers_clear(struct pw_buffers *buffers); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_BUFFERS_H */ -diff --git a/third_party/pipewire/pipewire/client.h b/third_party/pipewire/pipewire/client.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/client.h -@@ -0,0 +1,171 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CLIENT_H -+#define PIPEWIRE_CLIENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+#define PW_TYPE_INTERFACE_Client PW_TYPE_INFO_INTERFACE_BASE "Client" -+ -+#define PW_VERSION_CLIENT 3 -+struct pw_client; -+ -+/* default ID of the current client after connect */ -+#define PW_ID_CLIENT 1 -+ -+/** The client information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_client_info { -+ uint32_t id; /**< id of the global */ -+#define PW_CLIENT_CHANGE_MASK_PROPS (1 << 0) -+#define PW_CLIENT_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+}; -+ -+/** Update and existing \ref pw_client_info with \a update \memberof pw_introspect */ -+struct pw_client_info * -+pw_client_info_update(struct pw_client_info *info, -+ const struct pw_client_info *update); -+ -+/** Free a \ref pw_client_info \memberof pw_introspect */ -+void pw_client_info_free(struct pw_client_info *info); -+ -+ -+#define PW_CLIENT_EVENT_INFO 0 -+#define PW_CLIENT_EVENT_PERMISSIONS 1 -+#define PW_CLIENT_EVENT_NUM 2 -+ -+/** Client events */ -+struct pw_client_events { -+#define PW_VERSION_CLIENT_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify client info -+ * -+ * \param info info about the client -+ */ -+ void (*info) (void *object, const struct pw_client_info *info); -+ /** -+ * Notify a client permission -+ * -+ * Event emitted as a result of the get_permissions method. -+ * -+ * \param default_permissions the default permissions -+ * \param index the index of the first permission entry -+ * \param n_permissions the number of permissions -+ * \param permissions the permissions -+ */ -+ void (*permissions) (void *object, -+ uint32_t index, -+ uint32_t n_permissions, -+ const struct pw_permission *permissions); -+}; -+ -+ -+#define PW_CLIENT_METHOD_ADD_LISTENER 0 -+#define PW_CLIENT_METHOD_ERROR 1 -+#define PW_CLIENT_METHOD_UPDATE_PROPERTIES 2 -+#define PW_CLIENT_METHOD_GET_PERMISSIONS 3 -+#define PW_CLIENT_METHOD_UPDATE_PERMISSIONS 4 -+#define PW_CLIENT_METHOD_NUM 5 -+ -+/** Client methods */ -+struct pw_client_methods { -+#define PW_VERSION_CLIENT_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_client_events *events, -+ void *data); -+ /** -+ * Send an error to a client -+ * -+ * \param id the global id to report the error on -+ * \param res an errno style error code -+ * \param message an error string -+ */ -+ int (*error) (void *object, uint32_t id, int res, const char *message); -+ /** -+ * Update client properties -+ * -+ * \param props new properties -+ */ -+ int (*update_properties) (void *object, const struct spa_dict *props); -+ -+ /** -+ * Get client permissions -+ * -+ * A permissions event will be emitted with the permissions. -+ * -+ * \param index the first index to query, 0 for first -+ * \param num the maximum number of items to get -+ */ -+ int (*get_permissions) (void *object, uint32_t index, uint32_t num); -+ /** -+ * Manage the permissions of the global objects for this -+ * client -+ * -+ * Update the permissions of the global objects using the -+ * provided array with permissions -+ * -+ * Globals can use the default permissions or can have specific -+ * permissions assigned to them. -+ * -+ * \param n_permissions number of permissions -+ * \param permissions array of permissions -+ */ -+ int (*update_permissions) (void *object, uint32_t n_permissions, -+ const struct pw_permission *permissions); -+}; -+ -+#define pw_client_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_client_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_client_add_listener(c,...) pw_client_method(c,add_listener,0,__VA_ARGS__) -+#define pw_client_error(c,...) pw_client_method(c,error,0,__VA_ARGS__) -+#define pw_client_update_properties(c,...) pw_client_method(c,update_properties,0,__VA_ARGS__) -+#define pw_client_get_permissions(c,...) pw_client_method(c,get_permissions,0,__VA_ARGS__) -+#define pw_client_update_permissions(c,...) pw_client_method(c,update_permissions,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_CLIENT_H */ -diff --git a/third_party/pipewire/pipewire/context.h b/third_party/pipewire/pipewire/context.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/context.h -@@ -0,0 +1,188 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CONTEXT_H -+#define PIPEWIRE_CONTEXT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class pw_context -+ * -+ * \brief the PipeWire context -+ * -+ * The context object manages all locally available resources. It -+ * is used by both clients and servers. -+ * -+ * The context is used to: -+ * -+ * - Load modules and extend the functionality. This includes -+ * extending the protocol with new object types or creating -+ * any of the available objects. -+ * -+ * - Create implementations of various objects like nodes, -+ * devices, factories, modules, etc.. This will usually also -+ * create pw_global objects that can then be shared with -+ * clients. -+ * -+ * - Connect to another PipeWire instance (the main daemon, for -+ * example) and interact with it (See \subpage page_core_api). -+ * -+ * - Export a local implementation of an object to another -+ * instance. -+ */ -+struct pw_context; -+ -+struct pw_global; -+struct pw_impl_client; -+ -+#include -+#include -+#include -+ -+/** \page page_context_api Core API -+ * -+ * \section page_context_overview Overview -+ * -+ * \subpage page_context -+ * -+ * \subpage page_global -+ * -+ * \subpage page_client -+ * -+ * \subpage page_resource -+ * -+ * \subpage page_node -+ * -+ * \subpage page_port -+ * -+ * \subpage page_link -+ */ -+ -+/** \page page_context Context -+ * -+ * \section page_context_overview Overview -+ * -+ * The context object is an object that manages the state and -+ * resources of a PipeWire instance. -+ */ -+ -+/** context events emitted by the context object added with \ref pw_context_add_listener */ -+struct pw_context_events { -+#define PW_VERSION_CONTEXT_EVENTS 0 -+ uint32_t version; -+ -+ /** The context is being destroyed */ -+ void (*destroy) (void *data); -+ /** The context is being freed */ -+ void (*free) (void *data); -+ /** a new client object is added */ -+ void (*check_access) (void *data, struct pw_impl_client *client); -+ /** a new global object was added */ -+ void (*global_added) (void *data, struct pw_global *global); -+ /** a global object was removed */ -+ void (*global_removed) (void *data, struct pw_global *global); -+}; -+ -+/** Make a new context object for a given main_loop. Ownership of the properties is taken */ -+struct pw_context * pw_context_new(struct pw_loop *main_loop, /**< a main loop to run in */ -+ struct pw_properties *props, /**< extra properties */ -+ size_t user_data_size /**< extra user data size */); -+ -+/** destroy a context object, all resources except the main_loop will be destroyed */ -+void pw_context_destroy(struct pw_context *context); -+ -+/** Get the context user data */ -+void *pw_context_get_user_data(struct pw_context *context); -+ -+/** Add a new event listener to a context */ -+void pw_context_add_listener(struct pw_context *context, -+ struct spa_hook *listener, -+ const struct pw_context_events *events, -+ void *data); -+ -+/** Get the context properties */ -+const struct pw_properties *pw_context_get_properties(struct pw_context *context); -+ -+/** Update the context properties */ -+int pw_context_update_properties(struct pw_context *context, const struct spa_dict *dict); -+ -+/** Get the context support objects */ -+const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support); -+ -+/** get the context main loop */ -+struct pw_loop *pw_context_get_main_loop(struct pw_context *context); -+ -+/** Iterate the globals of the context. The callback should return -+ * 0 to fetch the next item, any other value stops the iteration and returns -+ * the value. When all callbacks return 0, this function returns 0 when all -+ * globals are iterated. */ -+int pw_context_for_each_global(struct pw_context *context, /**< the context */ -+ int (*callback) (void *data, struct pw_global *global), -+ void *data); -+ -+/** Find a context global by id */ -+struct pw_global *pw_context_find_global(struct pw_context *context, /**< the context */ -+ uint32_t id /**< the global id */); -+ -+/** add a spa library for the given factory_name regex */ -+int pw_context_add_spa_lib(struct pw_context *context, const char *factory_regex, const char *lib); -+ -+/** find the library name for a spa factory */ -+const char * pw_context_find_spa_lib(struct pw_context *context, const char *factory_name); -+ -+struct spa_handle *pw_context_load_spa_handle(struct pw_context *context, -+ const char *factory_name, -+ const struct spa_dict *info); -+ -+ -+/** data for registering export functions */ -+struct pw_export_type { -+ struct spa_list link; -+ const char *type; -+ struct pw_proxy * (*func) (struct pw_core *core, -+ const char *type, const struct spa_dict *props, void *object, -+ size_t user_data_size); -+}; -+ -+/** register a type that can be exported on a context_proxy. This is usually used by -+ * extension modules */ -+int pw_context_register_export_type(struct pw_context *context, struct pw_export_type *type); -+/** find information about registered export type */ -+const struct pw_export_type *pw_context_find_export_type(struct pw_context *context, const char *type); -+ -+/** add an object to the context */ -+int pw_context_set_object(struct pw_context *context, const char *type, void *value); -+/** get an object from the context */ -+void *pw_context_get_object(struct pw_context *context, const char *type); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_CONTEXT_H */ -diff --git a/third_party/pipewire/pipewire/control.h b/third_party/pipewire/pipewire/control.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/control.h -@@ -0,0 +1,79 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CONTROL_H -+#define PIPEWIRE_CONTROL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_control Control -+ * -+ * \section page_control_overview Overview -+ * -+ * A control can be used to control a port property. -+ */ -+/** \class pw_control -+ * -+ * The control object -+ */ -+struct pw_control; -+ -+#include -+ -+/** Port events, use \ref pw_control_add_listener */ -+struct pw_control_events { -+#define PW_VERSION_CONTROL_EVENTS 0 -+ uint32_t version; -+ -+ /** The control is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** The control is freed */ -+ void (*free) (void *data); -+ -+ /** control is linked to another control */ -+ void (*linked) (void *data, struct pw_control *other); -+ /** control is unlinked from another control */ -+ void (*unlinked) (void *data, struct pw_control *other); -+ -+}; -+ -+/** Get the control parent port or NULL when not set */ -+struct pw_impl_port *pw_control_get_port(struct pw_control *control); -+ -+/** Add an event listener on the control */ -+void pw_control_add_listener(struct pw_control *control, -+ struct spa_hook *listener, -+ const struct pw_control_events *events, -+ void *data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_CONTROL_H */ -diff --git a/third_party/pipewire/pipewire/core.h b/third_party/pipewire/pipewire/core.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/core.h -@@ -0,0 +1,584 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CORE_H -+#define PIPEWIRE_CORE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Core PW_TYPE_INFO_INTERFACE_BASE "Core" -+#define PW_TYPE_INTERFACE_Registry PW_TYPE_INFO_INTERFACE_BASE "Registry" -+ -+#define PW_VERSION_CORE 3 -+struct pw_core; -+#define PW_VERSION_REGISTRY 3 -+struct pw_registry; -+ -+/* the default remote name to connect to */ -+#define PW_DEFAULT_REMOTE "pipewire-0" -+ -+/* default ID for the core object after connect */ -+#define PW_ID_CORE 0 -+ -+/* invalid ID that matches any object when used for permissions */ -+#define PW_ID_ANY (uint32_t)(0xffffffff) -+ -+/** The core information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_core_info { -+ uint32_t id; /**< id of the global */ -+ uint32_t cookie; /**< a random cookie for identifying this instance of PipeWire */ -+ const char *user_name; /**< name of the user that started the core */ -+ const char *host_name; /**< name of the machine the core is running on */ -+ const char *version; /**< version of the core */ -+ const char *name; /**< name of the core */ -+#define PW_CORE_CHANGE_MASK_PROPS (1 << 0) -+#define PW_CORE_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+}; -+ -+#include -+#include -+#include -+ -+/** Update and existing \ref pw_core_info with \a update \memberof pw_introspect */ -+struct pw_core_info * -+pw_core_info_update(struct pw_core_info *info, -+ const struct pw_core_info *update); -+ -+/** Free a \ref pw_core_info \memberof pw_introspect */ -+void pw_core_info_free(struct pw_core_info *info); -+ -+/** -+ * \page page_iface_pw_core pw_core -+ * \section page_iface_pw_core_desc Description -+ * -+ * The core global object. This is a special singleton object. It -+ * is used for internal PipeWire protocol features. -+ * \section page_iface_pw_core API -+ */ -+ -+/** Core */ -+ -+#define PW_CORE_EVENT_INFO 0 -+#define PW_CORE_EVENT_DONE 1 -+#define PW_CORE_EVENT_PING 2 -+#define PW_CORE_EVENT_ERROR 3 -+#define PW_CORE_EVENT_REMOVE_ID 4 -+#define PW_CORE_EVENT_BOUND_ID 5 -+#define PW_CORE_EVENT_ADD_MEM 6 -+#define PW_CORE_EVENT_REMOVE_MEM 7 -+#define PW_CORE_EVENT_NUM 8 -+ -+/** \struct pw_core_events -+ * \brief Core events -+ * \ingroup pw_core_interface The pw_core interface -+ */ -+struct pw_core_events { -+#define PW_VERSION_CORE_EVENTS 0 -+ uint32_t version; -+ -+ /** -+ * Notify new core info -+ * -+ * This event is emitted when first bound to the core or when the -+ * hello method is called. -+ * -+ * \param info new core info -+ */ -+ void (*info) (void *object, const struct pw_core_info *info); -+ /** -+ * Emit a done event -+ * -+ * The done event is emitted as a result of a sync method with the -+ * same seq number. -+ * -+ * \param seq the seq number passed to the sync method call -+ */ -+ void (*done) (void *object, uint32_t id, int seq); -+ -+ /** Emit a ping event -+ * -+ * The client should reply with a pong reply with the same seq -+ * number. -+ */ -+ void (*ping) (void *object, uint32_t id, int seq); -+ -+ /** -+ * Fatal error event -+ * -+ * The error event is sent out when a fatal (non-recoverable) -+ * error has occurred. The id argument is the proxy object where -+ * the error occurred, most often in response to a request to that -+ * object. The message is a brief description of the error, -+ * for (debugging) convenience. -+ * -+ * This event is usually also emitted on the proxy object with -+ * \a id. -+ * -+ * \param id object where the error occurred -+ * \param seq the sequence number that generated the error -+ * \param res error code -+ * \param message error description -+ */ -+ void (*error) (void *object, uint32_t id, int seq, int res, const char *message); -+ /** -+ * Remove an object ID -+ * -+ * This event is used internally by the object ID management -+ * logic. When a client deletes an object, the server will send -+ * this event to acknowledge that it has seen the delete request. -+ * When the client receives this event, it will know that it can -+ * safely reuse the object ID. -+ * -+ * \param id deleted object ID -+ */ -+ void (*remove_id) (void *object, uint32_t id); -+ -+ /** -+ * Notify an object binding -+ * -+ * This event is emitted when a local object ID is bound to a -+ * global ID. It is emitted before the global becomes visible in the -+ * registry. -+ * -+ * \param id bound object ID -+ * \param global_id the global id bound to -+ */ -+ void (*bound_id) (void *object, uint32_t id, uint32_t global_id); -+ -+ /** -+ * Add memory for a client -+ * -+ * Memory is given to a client as \a fd of a certain -+ * memory \a type. -+ * -+ * Further references to this fd will be made with the per memory -+ * unique identifier \a id. -+ * -+ * \param id the unique id of the memory -+ * \param type the memory type, one of enum spa_data_type -+ * \param fd the file descriptor -+ * \param flags extra flags -+ */ -+ void (*add_mem) (void *object, uint32_t id, uint32_t type, int fd, uint32_t flags); -+ -+ /** -+ * Remove memory for a client -+ * -+ * \param id the memory id to remove -+ */ -+ void (*remove_mem) (void *object, uint32_t id); -+}; -+ -+#define PW_CORE_METHOD_ADD_LISTENER 0 -+#define PW_CORE_METHOD_HELLO 1 -+#define PW_CORE_METHOD_SYNC 2 -+#define PW_CORE_METHOD_PONG 3 -+#define PW_CORE_METHOD_ERROR 4 -+#define PW_CORE_METHOD_GET_REGISTRY 5 -+#define PW_CORE_METHOD_CREATE_OBJECT 6 -+#define PW_CORE_METHOD_DESTROY 7 -+#define PW_CORE_METHOD_NUM 8 -+ -+/** -+ * \struct pw_core_methods -+ * \brief Core methods -+ * -+ * The core global object. This is a singleton object used for -+ * creating new objects in the remote PipeWire instance. It is -+ * also used for internal features. -+ */ -+struct pw_core_methods { -+#define PW_VERSION_CORE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_core_events *events, -+ void *data); -+ /** -+ * Start a conversation with the server. This will send -+ * the core info and will destroy all resources for the client -+ * (except the core and client resource). -+ */ -+ int (*hello) (void *object, uint32_t version); -+ /** -+ * Do server roundtrip -+ * -+ * Ask the server to emit the 'done' event with \a seq. -+ * -+ * Since methods are handled in-order and events are delivered -+ * in-order, this can be used as a barrier to ensure all previous -+ * methods and the resulting events have been handled. -+ * -+ * \param seq the seq number passed to the done event -+ */ -+ int (*sync) (void *object, uint32_t id, int seq); -+ /** -+ * Reply to a server ping event. -+ * -+ * Reply to the server ping event with the same seq. -+ * -+ * \param seq the seq number received in the ping event -+ */ -+ int (*pong) (void *object, uint32_t id, int seq); -+ /** -+ * Fatal error event -+ * -+ * The error method is sent out when a fatal (non-recoverable) -+ * error has occurred. The id argument is the proxy object where -+ * the error occurred, most often in response to an event on that -+ * object. The message is a brief description of the error, -+ * for (debugging) convenience. -+ * -+ * This method is usually also emitted on the resource object with -+ * \a id. -+ * -+ * \param id object where the error occurred -+ * \param res error code -+ * \param message error description -+ */ -+ int (*error) (void *object, uint32_t id, int seq, int res, const char *message); -+ /** -+ * Get the registry object -+ * -+ * Create a registry object that allows the client to list and bind -+ * the global objects available from the PipeWire server -+ * \param version the client version -+ * \param user_data_size extra size -+ */ -+ struct pw_registry * (*get_registry) (void *object, uint32_t version, -+ size_t user_data_size); -+ -+ /** -+ * Create a new object on the PipeWire server from a factory. -+ * -+ * \param factory_name the factory name to use -+ * \param type the interface to bind to -+ * \param version the version of the interface -+ * \param props extra properties -+ * \param user_data_size extra size -+ */ -+ void * (*create_object) (void *object, -+ const char *factory_name, -+ const char *type, -+ uint32_t version, -+ const struct spa_dict *props, -+ size_t user_data_size); -+ /** -+ * Destroy an resource -+ * -+ * Destroy the server resource for the given proxy. -+ * -+ * \param obj the proxy to destroy -+ */ -+ int (*destroy) (void *object, void *proxy); -+}; -+ -+#define pw_core_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_core_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_core_add_listener(c,...) pw_core_method(c,add_listener,0,__VA_ARGS__) -+#define pw_core_hello(c,...) pw_core_method(c,hello,0,__VA_ARGS__) -+#define pw_core_sync(c,...) pw_core_method(c,sync,0,__VA_ARGS__) -+#define pw_core_pong(c,...) pw_core_method(c,pong,0,__VA_ARGS__) -+#define pw_core_error(c,...) pw_core_method(c,error,0,__VA_ARGS__) -+ -+ -+static inline -+SPA_PRINTF_FUNC(5, 0) int -+pw_core_errorv(struct pw_core *core, uint32_t id, int seq, -+ int res, const char *message, va_list args) -+{ -+ char buffer[1024]; -+ vsnprintf(buffer, sizeof(buffer), message, args); -+ buffer[1023] = '\0'; -+ return pw_core_error(core, id, seq, res, buffer); -+} -+ -+static inline -+SPA_PRINTF_FUNC(5, 6) int -+pw_core_errorf(struct pw_core *core, uint32_t id, int seq, -+ int res, const char *message, ...) -+{ -+ va_list args; -+ int r; -+ va_start(args, message); -+ r = pw_core_errorv(core, id, seq, res, message, args); -+ va_end(args); -+ return r; -+} -+ -+static inline struct pw_registry * -+pw_core_get_registry(struct pw_core *core, uint32_t version, size_t user_data_size) -+{ -+ struct pw_registry *res = NULL; -+ spa_interface_call_res((struct spa_interface*)core, -+ struct pw_core_methods, res, -+ get_registry, 0, version, user_data_size); -+ return res; -+} -+ -+static inline void * -+pw_core_create_object(struct pw_core *core, -+ const char *factory_name, -+ const char *type, -+ uint32_t version, -+ const struct spa_dict *props, -+ size_t user_data_size) -+{ -+ void *res = NULL; -+ spa_interface_call_res((struct spa_interface*)core, -+ struct pw_core_methods, res, -+ create_object, 0, factory_name, -+ type, version, props, user_data_size); -+ return res; -+} -+ -+#define pw_core_destroy(c,...) pw_core_method(c,destroy,0,__VA_ARGS__) -+ -+/** \page page_registry Registry -+ * -+ * \section page_registry_overview Overview -+ * -+ * The registry object is a singleton object that keeps track of -+ * global objects on the PipeWire instance. See also \ref page_global. -+ * -+ * Global objects typically represent an actual object in PipeWire -+ * (for example, a module or node) or they are singleton -+ * objects such as the core. -+ * -+ * When a client creates a registry object, the registry object -+ * will emit a global event for each global currently in the -+ * registry. Globals come and go as a result of device hotplugs or -+ * reconfiguration or other events, and the registry will send out -+ * global and global_remove events to keep the client up to date -+ * with the changes. To mark the end of the initial burst of -+ * events, the client can use the pw_core.sync methosd immediately -+ * after calling pw_core.get_registry. -+ * -+ * A client can bind to a global object by using the bind -+ * request. This creates a client-side proxy that lets the object -+ * emit events to the client and lets the client invoke methods on -+ * the object. See \ref page_proxy -+ * -+ * Clients can also change the permissions of the global objects that -+ * it can see. This is interesting when you want to configure a -+ * pipewire session before handing it to another application. You -+ * can, for example, hide certain existing or new objects or limit -+ * the access permissions on an object. -+ */ -+ -+#define PW_REGISTRY_EVENT_GLOBAL 0 -+#define PW_REGISTRY_EVENT_GLOBAL_REMOVE 1 -+#define PW_REGISTRY_EVENT_NUM 2 -+ -+/** Registry events */ -+struct pw_registry_events { -+#define PW_VERSION_REGISTRY_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify of a new global object -+ * -+ * The registry emits this event when a new global object is -+ * available. -+ * -+ * \param id the global object id -+ * \param permissions the permissions of the object -+ * \param type the type of the interface -+ * \param version the version of the interface -+ * \param props extra properties of the global -+ */ -+ void (*global) (void *object, uint32_t id, -+ uint32_t permissions, const char *type, uint32_t version, -+ const struct spa_dict *props); -+ /** -+ * Notify of a global object removal -+ * -+ * Emitted when a global object was removed from the registry. -+ * If the client has any bindings to the global, it should destroy -+ * those. -+ * -+ * \param id the id of the global that was removed -+ */ -+ void (*global_remove) (void *object, uint32_t id); -+}; -+ -+#define PW_REGISTRY_METHOD_ADD_LISTENER 0 -+#define PW_REGISTRY_METHOD_BIND 1 -+#define PW_REGISTRY_METHOD_DESTROY 2 -+#define PW_REGISTRY_METHOD_NUM 3 -+ -+/** Registry methods */ -+struct pw_registry_methods { -+#define PW_VERSION_REGISTRY_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_registry_events *events, -+ void *data); -+ /** -+ * Bind to a global object -+ * -+ * Bind to the global object with \a id and use the client proxy -+ * with new_id as the proxy. After this call, methods can be -+ * send to the remote global object and events can be received -+ * -+ * \param id the global id to bind to -+ * \param type the interface type to bind to -+ * \param version the interface version to use -+ * \returns the new object -+ */ -+ void * (*bind) (void *object, uint32_t id, const char *type, uint32_t version, -+ size_t use_data_size); -+ -+ /** -+ * Attempt to destroy a global object -+ * -+ * Try to destroy the global object. -+ * -+ * \param id the global id to destroy -+ */ -+ int (*destroy) (void *object, uint32_t id); -+}; -+ -+#define pw_registry_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_registry_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+/** Registry */ -+#define pw_registry_add_listener(p,...) pw_registry_method(p,add_listener,0,__VA_ARGS__) -+ -+static inline void * -+pw_registry_bind(struct pw_registry *registry, -+ uint32_t id, const char *type, uint32_t version, -+ size_t user_data_size) -+{ -+ void *res = NULL; -+ spa_interface_call_res((struct spa_interface*)registry, -+ struct pw_registry_methods, res, -+ bind, 0, id, type, version, user_data_size); -+ return res; -+} -+ -+#define pw_registry_destroy(p,...) pw_registry_method(p,destroy,0,__VA_ARGS__) -+ -+ -+/** Connect to a PipeWire instance \memberof pw_core -+ * \return a pw_core on success or NULL with errno set on error. The core -+ * will have an id of PW_ID_CORE (0) */ -+struct pw_core * -+pw_context_connect(struct pw_context *context, /**< a \ref pw_context */ -+ struct pw_properties *properties, /**< optional properties, ownership of -+ * the properties is taken.*/ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Connect to a PipeWire instance on the given socket \memberof pw_core -+ * \param fd the connected socket to use, the socket will be closed -+ * automatically on disconnect or error. -+ * \return a pw_core on success or NULL with errno set on error */ -+struct pw_core * -+pw_context_connect_fd(struct pw_context *context, /**< a \ref pw_context */ -+ int fd, /**< an fd */ -+ struct pw_properties *properties, /**< optional properties, ownership of -+ * the properties is taken.*/ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Connect to a given PipeWire instance \memberof pw_core -+ * \return a pw_core on success or NULL with errno set on error */ -+struct pw_core * -+pw_context_connect_self(struct pw_context *context, /**< a \ref pw_context to connect to */ -+ struct pw_properties *properties, /**< optional properties, ownership of -+ * the properties is taken.*/ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Steal the fd of the core connection or < 0 on error. The core -+ * will be disconnected after this call. */ -+int pw_core_steal_fd(struct pw_core *core); -+ -+/** Pause or resume the core. When the core is paused, no new events -+ * will be dispatched until the core is resumed again. */ -+int pw_core_set_paused(struct pw_core *core, bool paused); -+ -+/** disconnect and destroy a core */ -+int pw_core_disconnect(struct pw_core *core); -+ -+/** Get the user_data. It is of the size specified when this object was -+ * constructed */ -+void *pw_core_get_user_data(struct pw_core *core); -+ -+/** Get the client proxy of the connected core. This will have the id -+ * of PW_ID_CLIENT (1) */ -+struct pw_client * pw_core_get_client(struct pw_core *core); -+ -+/** Get the context object used to created this core */ -+struct pw_context * pw_core_get_context(struct pw_core *core); -+ -+/** Get properties from the core */ -+const struct pw_properties *pw_core_get_properties(struct pw_core *core); -+ -+/** Update the core properties. This updates the properties -+ * of the associated client. -+ * \return the number of properties that were updated */ -+int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict); -+ -+/** Get the core mempool object */ -+struct pw_mempool * pw_core_get_mempool(struct pw_core *core); -+ -+/** Get the proxy with the given id */ -+struct pw_proxy *pw_core_find_proxy(struct pw_core *core, uint32_t id); -+ -+/** Export an object into the PipeWire instance associated with core */ -+struct pw_proxy *pw_core_export(struct pw_core *core, /**< the core */ -+ const char *type, /**< the type of object */ -+ const struct spa_dict *props, /**< extra properties */ -+ void *object, /**< object to export */ -+ size_t user_data_size /**< extra user data */); -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_CORE_H */ -diff --git a/third_party/pipewire/pipewire/data-loop.h b/third_party/pipewire/pipewire/data-loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/data-loop.h -@@ -0,0 +1,95 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_DATA_LOOP_H -+#define PIPEWIRE_DATA_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \class pw_data_loop -+ * -+ * PipeWire rt-loop object. This loop starts a new real-time thread that -+ * is designed to run the processing graph. -+ */ -+struct pw_data_loop; -+ -+#include -+#include -+ -+/** Loop events, use \ref pw_data_loop_add_listener to add a listener */ -+struct pw_data_loop_events { -+#define PW_VERSION_DATA_LOOP_EVENTS 0 -+ uint32_t version; -+ /** The loop is destroyed */ -+ void (*destroy) (void *data); -+}; -+ -+/** Make a new loop. */ -+struct pw_data_loop * -+pw_data_loop_new(const struct spa_dict *props); -+ -+/** Add an event listener to loop */ -+void pw_data_loop_add_listener(struct pw_data_loop *loop, -+ struct spa_hook *listener, -+ const struct pw_data_loop_events *events, -+ void *data); -+ -+/** wait for activity on the loop up to \a timeout milliseconds. -+ * Should be called from the loop function */ -+int pw_data_loop_wait(struct pw_data_loop *loop, int timeout); -+ -+/** make sure the thread will exit. Can be called from a loop callback */ -+void pw_data_loop_exit(struct pw_data_loop *loop); -+ -+/** Get the loop implementation of this data loop */ -+struct pw_loop * -+pw_data_loop_get_loop(struct pw_data_loop *loop); -+ -+/** Destroy the loop */ -+void pw_data_loop_destroy(struct pw_data_loop *loop); -+ -+/** Start the processing thread */ -+int pw_data_loop_start(struct pw_data_loop *loop); -+ -+/** Stop the processing thread */ -+int pw_data_loop_stop(struct pw_data_loop *loop); -+ -+/** Check if the current thread is the processing thread */ -+bool pw_data_loop_in_thread(struct pw_data_loop *loop); -+ -+/** invoke func in the context of the thread or in the caller thread when -+ * the loop is not running. Since 0.3.3 */ -+int pw_data_loop_invoke(struct pw_data_loop *loop, -+ spa_invoke_func_t func, uint32_t seq, const void *data, size_t size, -+ bool block, void *user_data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_DATA_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/device.h b/third_party/pipewire/pipewire/device.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/device.h -@@ -0,0 +1,162 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_DEVICE_H -+#define PIPEWIRE_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Device PW_TYPE_INFO_INTERFACE_BASE "Device" -+ -+#define PW_VERSION_DEVICE 3 -+struct pw_device; -+ -+/** The device information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_device_info { -+ uint32_t id; /**< id of the global */ -+#define PW_DEVICE_CHANGE_MASK_PROPS (1 << 0) -+#define PW_DEVICE_CHANGE_MASK_PARAMS (1 << 1) -+#define PW_DEVICE_CHANGE_MASK_ALL ((1 << 2)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+ struct spa_param_info *params; /**< parameters */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+/** Update and existing \ref pw_device_info with \a update \memberof pw_introspect */ -+struct pw_device_info * -+pw_device_info_update(struct pw_device_info *info, -+ const struct pw_device_info *update); -+ -+/** Free a \ref pw_device_info \memberof pw_introspect */ -+void pw_device_info_free(struct pw_device_info *info); -+ -+#define PW_DEVICE_EVENT_INFO 0 -+#define PW_DEVICE_EVENT_PARAM 1 -+#define PW_DEVICE_EVENT_NUM 2 -+ -+/** Device events */ -+struct pw_device_events { -+#define PW_VERSION_DEVICE_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify device info -+ * -+ * \param info info about the device -+ */ -+ void (*info) (void *object, const struct pw_device_info *info); -+ /** -+ * Notify a device param -+ * -+ * Event emitted as a result of the enum_params method. -+ * -+ * \param seq the sequence number of the request -+ * \param id the param id -+ * \param index the param index -+ * \param next the param index of the next param -+ * \param param the parameter -+ */ -+ void (*param) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ const struct spa_pod *param); -+}; -+ -+ -+#define PW_DEVICE_METHOD_ADD_LISTENER 0 -+#define PW_DEVICE_METHOD_SUBSCRIBE_PARAMS 1 -+#define PW_DEVICE_METHOD_ENUM_PARAMS 2 -+#define PW_DEVICE_METHOD_SET_PARAM 3 -+#define PW_DEVICE_METHOD_NUM 4 -+ -+/** Device methods */ -+struct pw_device_methods { -+#define PW_VERSION_DEVICE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_device_events *events, -+ void *data); -+ /** -+ * Subscribe to parameter changes -+ * -+ * Automatically emit param events for the given ids when -+ * they are changed. -+ * -+ * \param ids an array of param ids -+ * \param n_ids the number of ids in \a ids -+ */ -+ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids); -+ -+ /** -+ * Enumerate device parameters -+ * -+ * Start enumeration of device parameters. For each param, a -+ * param event will be emitted. -+ * -+ * \param seq a sequence number to place in the reply -+ * \param id the parameter id to enum or PW_ID_ANY for all -+ * \param start the start index or 0 for the first param -+ * \param num the maximum number of params to retrieve -+ * \param filter a param filter or NULL -+ */ -+ int (*enum_params) (void *object, int seq, uint32_t id, uint32_t start, uint32_t num, -+ const struct spa_pod *filter); -+ /** -+ * Set a parameter on the device -+ * -+ * \param id the parameter id to set -+ * \param flags extra parameter flags -+ * \param param the parameter to set -+ */ -+ int (*set_param) (void *object, uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+}; -+ -+#define pw_device_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_device_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_device_add_listener(c,...) pw_device_method(c,add_listener,0,__VA_ARGS__) -+#define pw_device_subscribe_params(c,...) pw_device_method(c,subscribe_params,0,__VA_ARGS__) -+#define pw_device_enum_params(c,...) pw_device_method(c,enum_params,0,__VA_ARGS__) -+#define pw_device_set_param(c,...) pw_device_method(c,set_param,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_DEVICE_H */ -diff --git a/third_party/pipewire/pipewire/factory.h b/third_party/pipewire/pipewire/factory.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/factory.h -@@ -0,0 +1,109 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_FACTORY_H -+#define PIPEWIRE_FACTORY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Factory PW_TYPE_INFO_INTERFACE_BASE "Factory" -+ -+#define PW_VERSION_FACTORY 3 -+struct pw_factory; -+ -+/** The factory information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_factory_info { -+ uint32_t id; /**< id of the global */ -+ const char *name; /**< name the factory */ -+ const char *type; /**< type of the objects created by this factory */ -+ uint32_t version; /**< version of the objects */ -+#define PW_FACTORY_CHANGE_MASK_PROPS (1 << 0) -+#define PW_FACTORY_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< the properties of the factory */ -+}; -+ -+struct pw_factory_info * -+pw_factory_info_update(struct pw_factory_info *info, -+ const struct pw_factory_info *update); -+ -+void -+pw_factory_info_free(struct pw_factory_info *info); -+ -+ -+#define PW_FACTORY_EVENT_INFO 0 -+#define PW_FACTORY_EVENT_NUM 1 -+ -+/** Factory events */ -+struct pw_factory_events { -+#define PW_VERSION_FACTORY_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify factory info -+ * -+ * \param info info about the factory -+ */ -+ void (*info) (void *object, const struct pw_factory_info *info); -+}; -+ -+#define PW_FACTORY_METHOD_ADD_LISTENER 0 -+#define PW_FACTORY_METHOD_NUM 1 -+ -+/** Factory methods */ -+struct pw_factory_methods { -+#define PW_VERSION_FACTORY_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_factory_events *events, -+ void *data); -+}; -+ -+#define pw_factory_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_factory_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_factory_add_listener(c,...) pw_factory_method(c,add_listener,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_FACTORY_H */ -diff --git a/third_party/pipewire/pipewire/filter.h b/third_party/pipewire/pipewire/filter.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/filter.h -@@ -0,0 +1,240 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_FILTER_H -+#define PIPEWIRE_FILTER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_filter -+ * -+ * \brief PipeWire filter object class -+ * -+ * The filter object provides a convenient way to implement -+ * processing filters. -+ * -+ * See also \ref page_filters and \ref page_core_api -+ */ -+struct pw_filter; -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+/** \enum pw_filter_state The state of a filter \memberof pw_filter */ -+enum pw_filter_state { -+ PW_FILTER_STATE_ERROR = -1, /**< the strean is in error */ -+ PW_FILTER_STATE_UNCONNECTED = 0, /**< unconnected */ -+ PW_FILTER_STATE_CONNECTING = 1, /**< connection is in progress */ -+ PW_FILTER_STATE_PAUSED = 2, /**< filter is connected and paused */ -+ PW_FILTER_STATE_STREAMING = 3 /**< filter is streaming */ -+}; -+ -+#if 0 -+struct pw_buffer { -+ struct spa_buffer *buffer; /**< the spa buffer */ -+ void *user_data; /**< user data attached to the buffer */ -+ uint64_t size; /**< For input ports, this field is set by pw_filter -+ * with the duration of the buffer in ticks. -+ * For output ports, this field is set by the user. -+ * This field is added for all queued buffers and -+ * returned in the time info. */ -+}; -+#endif -+ -+/** Events for a filter. These events are always called from the mainloop -+ * unless explicitly documented otherwise. */ -+struct pw_filter_events { -+#define PW_VERSION_FILTER_EVENTS 0 -+ uint32_t version; -+ -+ void (*destroy) (void *data); -+ /** when the filter state changes */ -+ void (*state_changed) (void *data, enum pw_filter_state old, -+ enum pw_filter_state state, const char *error); -+ -+ /** when io changed on a port of the filter (when port_data is NULL). */ -+ void (*io_changed) (void *data, void *port_data, -+ uint32_t id, void *area, uint32_t size); -+ /** when a parameter changed on a port of the filter (when port_data is NULL). */ -+ void (*param_changed) (void *data, void *port_data, -+ uint32_t id, const struct spa_pod *param); -+ -+ /** when a new buffer was created for a port */ -+ void (*add_buffer) (void *data, void *port_data, struct pw_buffer *buffer); -+ /** when a buffer was destroyed for a port */ -+ void (*remove_buffer) (void *data, void *port_data, struct pw_buffer *buffer); -+ -+ /** do processing. This is normally called from the -+ * mainloop but can also be called directly from the realtime data -+ * thread if the user is prepared to deal with this. */ -+ void (*process) (void *data, struct spa_io_position *position); -+ -+ /** The filter is drained */ -+ void (*drained) (void *data); -+}; -+ -+/** Convert a filter state to a readable string \memberof pw_filter */ -+const char * pw_filter_state_as_string(enum pw_filter_state state); -+ -+/** \enum pw_filter_flags Extra flags that can be used in \ref pw_filter_connect() \memberof pw_filter */ -+enum pw_filter_flags { -+ PW_FILTER_FLAG_NONE = 0, /**< no flags */ -+ PW_FILTER_FLAG_INACTIVE = (1 << 0), /**< start the filter inactive, -+ * pw_filter_set_active() needs to be -+ * called explicitly */ -+ PW_FILTER_FLAG_DRIVER = (1 << 1), /**< be a driver */ -+ PW_FILTER_FLAG_RT_PROCESS = (1 << 2), /**< call process from the realtime -+ * thread */ -+}; -+ -+enum pw_filter_port_flags { -+ PW_FILTER_PORT_FLAG_NONE = 0, /**< no flags */ -+ PW_FILTER_PORT_FLAG_MAP_BUFFERS = (1 << 0), /**< mmap the buffers */ -+ PW_FILTER_PORT_FLAG_ALLOC_BUFFERS = (1 << 1), /**< the application will allocate buffer -+ * memory. In the add_buffer event, the -+ * data of the buffer should be set */ -+}; -+ -+/** Create a new unconneced \ref pw_filter \memberof pw_filter -+ * \return a newly allocated \ref pw_filter */ -+struct pw_filter * -+pw_filter_new(struct pw_core *core, /**< a \ref pw_core */ -+ const char *name, /**< a filter media name */ -+ struct pw_properties *props /**< filter properties, ownership is taken */); -+ -+struct pw_filter * -+pw_filter_new_simple(struct pw_loop *loop, /**< a \ref pw_loop to use */ -+ const char *name, /**< a filter media name */ -+ struct pw_properties *props, /**< filter properties, ownership is taken */ -+ const struct pw_filter_events *events, /**< filter events */ -+ void *data /**< data passed to events */); -+ -+/** Destroy a filter \memberof pw_filter */ -+void pw_filter_destroy(struct pw_filter *filter); -+ -+void pw_filter_add_listener(struct pw_filter *filter, -+ struct spa_hook *listener, -+ const struct pw_filter_events *events, -+ void *data); -+ -+enum pw_filter_state pw_filter_get_state(struct pw_filter *filter, const char **error); -+ -+const char *pw_filter_get_name(struct pw_filter *filter); -+ -+struct pw_core *pw_filter_get_core(struct pw_filter *filter); -+ -+/** Connect a filter for processing. \memberof pw_filter -+ * \return 0 on success < 0 on error. -+ * -+ * You should connect to the process event and use pw_filter_dequeue_buffer() -+ * to get the latest metadata and data. */ -+int -+pw_filter_connect(struct pw_filter *filter, /**< a \ref pw_filter */ -+ enum pw_filter_flags flags, /**< filter flags */ -+ const struct spa_pod **params, /**< an array with params. */ -+ uint32_t n_params /**< number of items in \a params */); -+ -+/** Get the node ID of the filter. \memberof pw_filter -+ * \return node ID. */ -+uint32_t -+pw_filter_get_node_id(struct pw_filter *filter); -+ -+/** Disconnect \a filter \memberof pw_filter */ -+int pw_filter_disconnect(struct pw_filter *filter); -+ -+/** add a port to the filter, returns user data of port_data_size. */ -+void *pw_filter_add_port(struct pw_filter *filter, -+ enum pw_direction direction, /**< port direction */ -+ enum pw_filter_port_flags flags, /**< port flags */ -+ size_t port_data_size, /**< allocated and given to the user as port_data */ -+ struct pw_properties *props, /**< port properties, ownership is taken */ -+ const struct spa_pod **params, /**< an array of params. The params should -+ * ideally contain the supported formats */ -+ uint32_t n_params /**< number of elements in \a params */); -+ -+/** remove a port from the filter */ -+int pw_filter_remove_port(void *port_data /**< data associated with port */); -+ -+/** get properties, port_data of NULL will give global properties */ -+const struct pw_properties *pw_filter_get_properties(struct pw_filter *filter, -+ void *port_data); -+ -+/** Update properties, use NULL port_data for global filter properties */ -+int pw_filter_update_properties(struct pw_filter *filter, -+ void *port_data, const struct spa_dict *dict); -+ -+/** Set the filter in error state */ -+int pw_filter_set_error(struct pw_filter *filter, /**< a \ref pw_filter */ -+ int res, /**< a result code */ -+ const char *error, ... /**< an error message */) SPA_PRINTF_FUNC(3, 4); -+ -+/** Update params, use NULL port_data for global filter params */ -+int -+pw_filter_update_params(struct pw_filter *filter, /**< a \ref pw_filter */ -+ void *port_data, /**< data associated with port */ -+ const struct spa_pod **params, /**< an array of params. */ -+ uint32_t n_params /**< number of elements in \a params */); -+ -+ -+#if 0 -+/** A time structure \memberof pw_filter */ -+struct pw_time { -+ int64_t now; /**< the monotonic time */ -+ struct spa_fraction rate; /**< the rate of \a ticks and delay */ -+ uint64_t ticks; /**< the ticks at \a now. This is the current time that -+ * the remote end is reading/writing. */ -+}; -+#endif -+ -+/** Query the time on the filter \memberof pw_filter */ -+int pw_filter_get_time(struct pw_filter *filter, struct pw_time *time); -+ -+/** Get a buffer that can be filled for output ports or consumed -+ * for input ports. */ -+struct pw_buffer *pw_filter_dequeue_buffer(void *port_data); -+ -+/** Submit a buffer for playback or recycle a buffer for capture. */ -+int pw_filter_queue_buffer(void *port_data, struct pw_buffer *buffer); -+ -+/** Get a data pointer to the buffer data */ -+void *pw_filter_get_dsp_buffer(void *port_data, uint32_t n_samples); -+ -+/** Activate or deactivate the filter \memberof pw_filter */ -+int pw_filter_set_active(struct pw_filter *filter, bool active); -+ -+/** Flush a filter. When \a drain is true, the drained callback will -+ * be called when all data is played or recorded */ -+int pw_filter_flush(struct pw_filter *filter, bool drain); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_FILTER_H */ -diff --git a/third_party/pipewire/pipewire/global.h b/third_party/pipewire/pipewire/global.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/global.h -@@ -0,0 +1,155 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_GLOBAL_H -+#define PIPEWIRE_GLOBAL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \page page_global Global -+ * -+ * Global objects represent resources that are available on the PipeWire -+ * context and are accessible to remote clients. -+ * Globals come and go when devices or other resources become available for -+ * clients. -+ * -+ * Remote clients receives a list of globals when it binds to the registry -+ * object. See \ref page_registry. -+ * -+ * A client can bind to a global to send methods or receive events from -+ * the global. -+ */ -+/** \class pw_global -+ * -+ * \brief A global object visible to remote clients -+ * -+ * A global object is visible to remote clients and represents a resource -+ * that can be used or inspected. -+ * -+ * See \ref page_remote_api -+ */ -+struct pw_global; -+ -+#include -+ -+typedef int (*pw_global_bind_func_t) (void *object, -+ struct pw_impl_client *client, /**< client that binds */ -+ uint32_t permissions, /**< permissions for the bind */ -+ uint32_t version, /**< client interface version */ -+ uint32_t id /**< client proxy id */); -+ -+/** Global events, use \ref pw_global_add_listener */ -+struct pw_global_events { -+#define PW_VERSION_GLOBAL_EVENTS 0 -+ uint32_t version; -+ -+ /** The global is destroyed */ -+ void (*destroy) (void *data); -+ /** The global is freed */ -+ void (*free) (void *data); -+ /** The permissions changed for a client */ -+ void (*permissions_changed) (void *data, -+ struct pw_impl_client *client, -+ uint32_t old_permissions, -+ uint32_t new_permissions); -+}; -+ -+/** Create a new global object */ -+struct pw_global * -+pw_global_new(struct pw_context *context, /**< the context */ -+ const char *type, /**< the interface type of the global */ -+ uint32_t version, /**< the interface version of the global */ -+ struct pw_properties *properties, /**< extra properties */ -+ pw_global_bind_func_t func, /**< function to bind */ -+ void *object /**< global object */); -+ -+/** Register a global object to the context registry */ -+int pw_global_register(struct pw_global *global); -+ -+/** Add an event listener on the global */ -+void pw_global_add_listener(struct pw_global *global, -+ struct spa_hook *listener, -+ const struct pw_global_events *events, -+ void *data); -+ -+/** Get the permissions of the global for a given client */ -+uint32_t pw_global_get_permissions(struct pw_global *global, struct pw_impl_client *client); -+ -+/** Get the context object of this global */ -+struct pw_context *pw_global_get_context(struct pw_global *global); -+ -+/** Get the global type */ -+const char *pw_global_get_type(struct pw_global *global); -+ -+/** Check a global type */ -+bool pw_global_is_type(struct pw_global *global, const char *type); -+ -+/** Get the global version */ -+uint32_t pw_global_get_version(struct pw_global *global); -+ -+/** Get the global properties */ -+const struct pw_properties *pw_global_get_properties(struct pw_global *global); -+ -+/** Update the global properties, must be done when unregistered */ -+int pw_global_update_keys(struct pw_global *global, -+ const struct spa_dict *dict, const char *keys[]); -+ -+/** Get the object associated with the global. This depends on the type of the -+ * global */ -+void *pw_global_get_object(struct pw_global *global); -+ -+/** Get the unique id of the global */ -+uint32_t pw_global_get_id(struct pw_global *global); -+ -+/** Add a resource to a global */ -+int pw_global_add_resource(struct pw_global *global, struct pw_resource *resource); -+ -+/** Iterate all resources added to the global The callback should return -+ * 0 to fetch the next item, any other value stops the iteration and returns -+ * the value. When all callbacks return 0, this function returns 0 when all -+ * items are iterated. */ -+int pw_global_for_each_resource(struct pw_global *global, -+ int (*callback) (void *data, struct pw_resource *resource), -+ void *data); -+ -+/** Let a client bind to a global */ -+int pw_global_bind(struct pw_global *global, -+ struct pw_impl_client *client, -+ uint32_t permissions, -+ uint32_t version, -+ uint32_t id); -+ -+int pw_global_update_permissions(struct pw_global *global, struct pw_impl_client *client, -+ uint32_t old_permissions, uint32_t new_permissions); -+ -+/** Destroy a global */ -+void pw_global_destroy(struct pw_global *global); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_GLOBAL_H */ -diff --git a/third_party/pipewire/pipewire/impl-client.h b/third_party/pipewire/pipewire/impl-client.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-client.h -@@ -0,0 +1,174 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_CLIENT_H -+#define PIPEWIRE_IMPL_CLIENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \class pw_impl_client -+ * -+ * \brief PipeWire client object class. -+ * -+ * The client object represents a client connection with the PipeWire -+ * server. -+ * -+ * Each client has its own list of resources it is bound to along with -+ * a mapping between the client types and server types. -+ */ -+struct pw_impl_client; -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** \page page_client Client -+ * -+ * \section sec_page_client_overview Overview -+ * -+ * The \ref pw_impl_client object is created by a protocol implementation when -+ * a new client connects. -+ * -+ * The client is used to keep track of all resources belonging to one -+ * connection with the PipeWire server. -+ * -+ * \section sec_page_client_credentials Credentials -+ * -+ * The client object will have its credentials filled in by the protocol. -+ * This information is used to check if a resource or action is available -+ * for this client. See also \ref page_access -+ * -+ * \section sec_page_client_types Types -+ * -+ * The client and server maintain a mapping between the client and server -+ * types. All type ids that are in messages exchanged between the client -+ * and server will automatically be remapped. See also \ref page_types. -+ * -+ * \section sec_page_client_resources Resources -+ * -+ * When a client binds to context global object, a resource is made for this -+ * binding and a unique id is assigned to the resources. The client and -+ * server will use this id as the destination when exchanging messages. -+ * See also \ref page_resource -+ */ -+ -+/** The events that a client can emit */ -+struct pw_impl_client_events { -+#define PW_VERSION_IMPL_CLIENT_EVENTS 0 -+ uint32_t version; -+ -+ /** emitted when the client is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** emitted right before the client is freed */ -+ void (*free) (void *data); -+ -+ /** the client is initialized */ -+ void (*initialized) (void *data); -+ -+ /** emitted when the client info changed */ -+ void (*info_changed) (void *data, const struct pw_client_info *info); -+ -+ /** emitted when a new resource is added for client */ -+ void (*resource_added) (void *data, struct pw_resource *resource); -+ -+ /** emitted when a resource is removed */ -+ void (*resource_removed) (void *data, struct pw_resource *resource); -+ -+ /** emitted when the client becomes busy processing an asynchronous -+ * message. In the busy state no messages should be processed. -+ * Processing should resume when the client becomes not busy */ -+ void (*busy_changed) (void *data, bool busy); -+}; -+ -+/** Create a new client. This is mainly used by protocols. */ -+struct pw_impl_client * -+pw_context_create_client(struct pw_impl_core *core, /**< the core object */ -+ struct pw_protocol *prototol, /**< the client protocol */ -+ struct pw_properties *properties, /**< client properties */ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Destroy a previously created client */ -+void pw_impl_client_destroy(struct pw_impl_client *client); -+ -+/** Finish configuration and register a client */ -+int pw_impl_client_register(struct pw_impl_client *client, /**< the client to register */ -+ struct pw_properties *properties/**< extra properties */); -+ -+/** Get the client user data */ -+void *pw_impl_client_get_user_data(struct pw_impl_client *client); -+ -+/** Get the client information */ -+const struct pw_client_info *pw_impl_client_get_info(struct pw_impl_client *client); -+ -+/** Update the client properties */ -+int pw_impl_client_update_properties(struct pw_impl_client *client, const struct spa_dict *dict); -+ -+/** Update the client permissions */ -+int pw_impl_client_update_permissions(struct pw_impl_client *client, uint32_t n_permissions, -+ const struct pw_permission *permissions); -+ -+/** check if a client has permissions for global_id, Since 0.3.9 */ -+int pw_impl_client_check_permissions(struct pw_impl_client *client, -+ uint32_t global_id, uint32_t permissions); -+ -+/** Get the client properties */ -+const struct pw_properties *pw_impl_client_get_properties(struct pw_impl_client *client); -+ -+/** Get the context used to create this client */ -+struct pw_context *pw_impl_client_get_context(struct pw_impl_client *client); -+/** Get the protocol used to create this client */ -+struct pw_protocol *pw_impl_client_get_protocol(struct pw_impl_client *client); -+ -+/** Get the client core resource */ -+struct pw_resource *pw_impl_client_get_core_resource(struct pw_impl_client *client); -+ -+/** Get a resource with the given id */ -+struct pw_resource *pw_impl_client_find_resource(struct pw_impl_client *client, uint32_t id); -+ -+/** Get the global associated with this client */ -+struct pw_global *pw_impl_client_get_global(struct pw_impl_client *client); -+ -+/** listen to events from this client */ -+void pw_impl_client_add_listener(struct pw_impl_client *client, -+ struct spa_hook *listener, -+ const struct pw_impl_client_events *events, -+ void *data); -+ -+ -+/** Mark the client busy. This can be used when an asynchronous operation is -+ * started and no further processing is allowed to happen for the client */ -+void pw_impl_client_set_busy(struct pw_impl_client *client, bool busy); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_CLIENT_H */ -diff --git a/third_party/pipewire/pipewire/impl-core.h b/third_party/pipewire/pipewire/impl-core.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-core.h -@@ -0,0 +1,94 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_CORE_H -+#define PIPEWIRE_IMPL_CORE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_core -+ * -+ * \brief PipeWire core interface. -+ * -+ * The core is used to make objects on demand. -+ */ -+struct pw_impl_core; -+ -+#include -+#include -+#include -+#include -+ -+/** Factory events, listen to them with \ref pw_impl_core_add_listener */ -+struct pw_impl_core_events { -+#define PW_VERSION_IMPL_CORE_EVENTS 0 -+ uint32_t version; -+ -+ /** the core is destroyed */ -+ void (*destroy) (void *data); -+ /** the core is freed */ -+ void (*free) (void *data); -+ /** the core is initialized */ -+ void (*initialized) (void *data); -+}; -+ -+struct pw_impl_core *pw_context_create_core(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size); -+ -+/* get the default core in a context */ -+struct pw_impl_core *pw_context_get_default_core(struct pw_context *context); -+ -+/** Get the core properties */ -+const struct pw_properties *pw_impl_core_get_properties(struct pw_impl_core *core); -+ -+/** Get the core information */ -+const struct pw_core_info *pw_impl_core_get_info(struct pw_impl_core *core); -+ -+/** Update the core properties */ -+int pw_impl_core_update_properties(struct pw_impl_core *core, const struct spa_dict *dict); -+ -+int pw_impl_core_register(struct pw_impl_core *core, -+ struct pw_properties *properties); -+ -+void pw_impl_core_destroy(struct pw_impl_core *core); -+ -+void *pw_impl_core_get_user_data(struct pw_impl_core *core); -+ -+/** Get the global of this core */ -+struct pw_global *pw_impl_core_get_global(struct pw_impl_core *core); -+ -+/** Add an event listener */ -+void pw_impl_core_add_listener(struct pw_impl_core *core, -+ struct spa_hook *listener, -+ const struct pw_impl_core_events *events, -+ void *data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_CORE_H */ -diff --git a/third_party/pipewire/pipewire/impl-device.h b/third_party/pipewire/pipewire/impl-device.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-device.h -@@ -0,0 +1,109 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_DEVICE_H -+#define PIPEWIRE_IMPL_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_device -+ * -+ * \brief PipeWire device interface. -+ * -+ * The device is an object that manages nodes. It typically -+ * corresponds to a physical hardware device but it does not -+ * have to be. -+ * -+ * The purpose of the device is to provide an interface to -+ * dynamically create/remove/configure the nodes it manages. -+ */ -+struct pw_impl_device; -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+/** Device events, listen to them with \ref pw_impl_device_add_listener */ -+struct pw_impl_device_events { -+#define PW_VERSION_IMPL_DEVICE_EVENTS 0 -+ uint32_t version; -+ -+ /** the device is destroyed */ -+ void (*destroy) (void *data); -+ /** the device is freed */ -+ void (*free) (void *data); -+ /** the device is initialized */ -+ void (*initialized) (void *data); -+ -+ /** the device info changed */ -+ void (*info_changed) (void *data, const struct pw_device_info *info); -+}; -+ -+struct pw_impl_device *pw_context_create_device(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size); -+ -+int pw_impl_device_register(struct pw_impl_device *device, -+ struct pw_properties *properties); -+ -+void pw_impl_device_destroy(struct pw_impl_device *device); -+ -+void *pw_impl_device_get_user_data(struct pw_impl_device *device); -+ -+/** Set the device implementation */ -+int pw_impl_device_set_implementation(struct pw_impl_device *device, struct spa_device *spa_device); -+/** Get the device implementation */ -+struct spa_device *pw_impl_device_get_implementation(struct pw_impl_device *device); -+ -+/** Get the global of this device */ -+struct pw_global *pw_impl_device_get_global(struct pw_impl_device *device); -+ -+/** Add an event listener */ -+void pw_impl_device_add_listener(struct pw_impl_device *device, -+ struct spa_hook *listener, -+ const struct pw_impl_device_events *events, -+ void *data); -+ -+int pw_impl_device_update_properties(struct pw_impl_device *device, const struct spa_dict *dict); -+ -+const struct pw_properties *pw_impl_device_get_properties(struct pw_impl_device *device); -+ -+int pw_impl_device_for_each_param(struct pw_impl_device *device, -+ int seq, uint32_t param_id, -+ uint32_t index, uint32_t max, -+ const struct spa_pod *filter, -+ int (*callback) (void *data, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ struct spa_pod *param), -+ void *data); -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_DEVICE_H */ -diff --git a/third_party/pipewire/pipewire/impl-factory.h b/third_party/pipewire/pipewire/impl-factory.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-factory.h -@@ -0,0 +1,124 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_FACTORY_H -+#define PIPEWIRE_IMPL_FACTORY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_factory -+ * -+ * \brief PipeWire factory interface. -+ * -+ * The factory is used to make objects on demand. -+ */ -+struct pw_impl_factory; -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** Factory events, listen to them with \ref pw_impl_factory_add_listener */ -+struct pw_impl_factory_events { -+#define PW_VERSION_IMPL_FACTORY_EVENTS 0 -+ uint32_t version; -+ -+ /** the factory is destroyed */ -+ void (*destroy) (void *data); -+ /** the factory is freed */ -+ void (*free) (void *data); -+ /** the factory is initialized */ -+ void (*initialized) (void *data); -+}; -+ -+struct pw_impl_factory_implementation { -+#define PW_VERSION_IMPL_FACTORY_IMPLEMENTATION 0 -+ uint32_t version; -+ -+ /** The function to create an object from this factory */ -+ void *(*create_object) (void *data, -+ struct pw_resource *resource, -+ const char *type, -+ uint32_t version, -+ struct pw_properties *properties, -+ uint32_t new_id); -+}; -+ -+struct pw_impl_factory *pw_context_create_factory(struct pw_context *context, -+ const char *name, -+ const char *type, -+ uint32_t version, -+ struct pw_properties *properties, -+ size_t user_data_size); -+ -+/** Get the factory properties */ -+const struct pw_properties *pw_impl_factory_get_properties(struct pw_impl_factory *factory); -+ -+/** Get the factory info */ -+const struct pw_factory_info *pw_impl_factory_get_info(struct pw_impl_factory *factory); -+ -+/** Update the factory properties */ -+int pw_impl_factory_update_properties(struct pw_impl_factory *factory, const struct spa_dict *dict); -+ -+int pw_impl_factory_register(struct pw_impl_factory *factory, -+ struct pw_properties *properties); -+ -+void pw_impl_factory_destroy(struct pw_impl_factory *factory); -+ -+void *pw_impl_factory_get_user_data(struct pw_impl_factory *factory); -+ -+/** Get the global of this factory */ -+struct pw_global *pw_impl_factory_get_global(struct pw_impl_factory *factory); -+ -+/** Add an event listener */ -+void pw_impl_factory_add_listener(struct pw_impl_factory *factory, -+ struct spa_hook *listener, -+ const struct pw_impl_factory_events *events, -+ void *data); -+ -+void pw_impl_factory_set_implementation(struct pw_impl_factory *factory, -+ const struct pw_impl_factory_implementation *implementation, -+ void *data); -+ -+void *pw_impl_factory_create_object(struct pw_impl_factory *factory, -+ struct pw_resource *resource, -+ const char *type, -+ uint32_t version, -+ struct pw_properties *properties, -+ uint32_t new_id); -+ -+/** Find a factory by name */ -+struct pw_impl_factory * -+pw_context_find_factory(struct pw_context *context /**< the context */, -+ const char *name /**< the factory name */); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_FACTORY_H */ -diff --git a/third_party/pipewire/pipewire/impl-link.h b/third_party/pipewire/pipewire/impl-link.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-link.h -@@ -0,0 +1,128 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_LINK_H -+#define PIPEWIRE_IMPL_LINK_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_link -+ * -+ * PipeWire link object. -+ */ -+struct pw_impl_link; -+struct pw_impl_port; -+ -+#include -+ -+/** \page page_link Link -+ * -+ * \section page_link_overview Overview -+ * -+ * A link is the connection between 2 nodes (\ref page_node). Nodes are -+ * linked together on ports. -+ * -+ * The link is responsible for negotiating the format and buffers for -+ * the nodes. -+ */ -+ -+/** link events added with \ref pw_impl_link_add_listener */ -+struct pw_impl_link_events { -+#define PW_VERSION_IMPL_LINK_EVENTS 0 -+ uint32_t version; -+ -+ /** A link is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** A link is freed */ -+ void (*free) (void *data); -+ -+ /** a Link is initialized */ -+ void (*initialized) (void *data); -+ -+ /** The info changed on a link */ -+ void (*info_changed) (void *data, const struct pw_link_info *info); -+ -+ /** The link state changed, \a error is only valid when the state is -+ * in error. */ -+ void (*state_changed) (void *data, enum pw_link_state old, -+ enum pw_link_state state, const char *error); -+ -+ /** A port is unlinked */ -+ void (*port_unlinked) (void *data, struct pw_impl_port *port); -+}; -+ -+ -+/** Make a new link between two ports \memberof pw_impl_link -+ * \return a newly allocated link */ -+struct pw_impl_link * -+pw_context_create_link(struct pw_context *context, /**< the context object */ -+ struct pw_impl_port *output, /**< an output port */ -+ struct pw_impl_port *input, /**< an input port */ -+ struct spa_pod *format_filter, /**< an optional format filter */ -+ struct pw_properties *properties /**< extra properties */, -+ size_t user_data_size /**< extra user data size */); -+ -+/** Destroy a link \memberof pw_impl_link */ -+void pw_impl_link_destroy(struct pw_impl_link *link); -+ -+/** Add an event listener to \a link */ -+void pw_impl_link_add_listener(struct pw_impl_link *link, -+ struct spa_hook *listener, -+ const struct pw_impl_link_events *events, -+ void *data); -+ -+/** Finish link configuration and register */ -+int pw_impl_link_register(struct pw_impl_link *link, /**< the link to register */ -+ struct pw_properties *properties /**< extra properties */); -+ -+/** Get the context of a link */ -+struct pw_context *pw_impl_link_get_context(struct pw_impl_link *link); -+ -+/** Get the user_data of a link, the size of the memory is given when -+ * constructing the link */ -+void *pw_impl_link_get_user_data(struct pw_impl_link *link); -+ -+/** Get the link info */ -+const struct pw_link_info *pw_impl_link_get_info(struct pw_impl_link *link); -+ -+/** Get the global of the link */ -+struct pw_global *pw_impl_link_get_global(struct pw_impl_link *link); -+ -+/** Get the output port of the link */ -+struct pw_impl_port *pw_impl_link_get_output(struct pw_impl_link *link); -+ -+/** Get the input port of the link */ -+struct pw_impl_port *pw_impl_link_get_input(struct pw_impl_link *link); -+ -+/** Find the link between 2 ports \memberof pw_impl_link */ -+struct pw_impl_link *pw_impl_link_find(struct pw_impl_port *output, struct pw_impl_port *input); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_LINK_H */ -diff --git a/third_party/pipewire/pipewire/impl-module.h b/third_party/pipewire/pipewire/impl-module.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-module.h -@@ -0,0 +1,110 @@ -+/* PipeWire -+ * Copyright © 2016 Axis Communications -+ * @author Linus Svensson -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_MODULE_H -+#define PIPEWIRE_IMPL_MODULE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+#define PIPEWIRE_SYMBOL_MODULE_INIT "pipewire__module_init" -+#define PIPEWIRE_MODULE_PREFIX "libpipewire-" -+ -+/** \class pw_impl_module -+ * -+ * A dynamically loadable module -+ */ -+struct pw_impl_module; -+ -+/** Module init function signature -+ * -+ * \param module A \ref pw_impl_module -+ * \param args Arguments to the module -+ * \return 0 on success, < 0 otherwise with an errno style error -+ * -+ * A module should provide an init function with this signature. This function -+ * will be called when a module is loaded. -+ * -+ * \memberof pw_impl_module -+ */ -+typedef int (*pw_impl_module_init_func_t) (struct pw_impl_module *module, const char *args); -+ -+/** Module events added with \ref pw_impl_module_add_listener */ -+struct pw_impl_module_events { -+#define PW_VERSION_IMPL_MODULE_EVENTS 0 -+ uint32_t version; -+ -+ /** The module is destroyed */ -+ void (*destroy) (void *data); -+ /** The module is freed */ -+ void (*free) (void *data); -+ /** The module is initialized */ -+ void (*initialized) (void *data); -+ -+ /** The module is registered. This is a good time to register -+ * objectes created from the module. */ -+ void (*registered) (void *data); -+}; -+ -+struct pw_impl_module * -+pw_context_load_module(struct pw_context *context, -+ const char *name, /**< name of the module */ -+ const char *args /**< arguments of the module */, -+ struct pw_properties *properties /**< extra global properties */); -+ -+/** Get the context of a module */ -+struct pw_context * pw_impl_module_get_context(struct pw_impl_module *module); -+ -+/** Get the global of a module */ -+struct pw_global * pw_impl_module_get_global(struct pw_impl_module *module); -+ -+/** Get the node properties */ -+const struct pw_properties *pw_impl_module_get_properties(struct pw_impl_module *module); -+ -+/** Update the module properties */ -+int pw_impl_module_update_properties(struct pw_impl_module *module, const struct spa_dict *dict); -+ -+/** Get the module info */ -+const struct pw_module_info *pw_impl_module_get_info(struct pw_impl_module *module); -+ -+/** Add an event listener to a module */ -+void pw_impl_module_add_listener(struct pw_impl_module *module, -+ struct spa_hook *listener, -+ const struct pw_impl_module_events *events, -+ void *data); -+ -+/** Destroy a module */ -+void pw_impl_module_destroy(struct pw_impl_module *module); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_MODULE_H */ -diff --git a/third_party/pipewire/pipewire/impl-node.h b/third_party/pipewire/pipewire/impl-node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-node.h -@@ -0,0 +1,182 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_NODE_H -+#define PIPEWIRE_IMPL_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \page page_node Node -+ * -+ * \section page_node_overview Overview -+ * -+ * The node object processes data. The node has a list of -+ * input and output ports (\ref page_port) on which it -+ * will receive and send out buffers respectively. -+ */ -+/** \class pw_impl_node -+ * -+ * PipeWire node class. -+ */ -+struct pw_impl_node; -+struct pw_impl_port; -+ -+#include -+#include -+ -+#include -+ -+/** Node events, listen to them with \ref pw_impl_node_add_listener */ -+struct pw_impl_node_events { -+#define PW_VERSION_IMPL_NODE_EVENTS 0 -+ uint32_t version; -+ -+ /** the node is destroyed */ -+ void (*destroy) (void *data); -+ /** the node is about to be freed */ -+ void (*free) (void *data); -+ /** the node is initialized */ -+ void (*initialized) (void *data); -+ -+ /** a port is being initialized on the node */ -+ void (*port_init) (void *data, struct pw_impl_port *port); -+ /** a port was added */ -+ void (*port_added) (void *data, struct pw_impl_port *port); -+ /** a port was removed */ -+ void (*port_removed) (void *data, struct pw_impl_port *port); -+ -+ /** the node info changed */ -+ void (*info_changed) (void *data, const struct pw_node_info *info); -+ /** a port on the node changed info */ -+ void (*port_info_changed) (void *data, struct pw_impl_port *port, -+ const struct pw_port_info *info); -+ /** the node active state changed */ -+ void (*active_changed) (void *data, bool active); -+ -+ /** a new state is requested on the node */ -+ void (*state_request) (void *data, enum pw_node_state state); -+ /** the state of the node changed */ -+ void (*state_changed) (void *data, enum pw_node_state old, -+ enum pw_node_state state, const char *error); -+ -+ /** a result was received */ -+ void (*result) (void *data, int seq, int res, uint32_t type, const void *result); -+ -+ /** an event is emitted */ -+ void (*event) (void *data, const struct spa_event *event); -+ -+ /** the driver of the node changed */ -+ void (*driver_changed) (void *data, struct pw_impl_node *old, struct pw_impl_node *driver); -+ -+ /** a peer was added */ -+ void (*peer_added) (void *data, struct pw_impl_node *peer); -+ /** a peer was removed */ -+ void (*peer_removed) (void *data, struct pw_impl_node *peer); -+}; -+ -+/** Create a new node \memberof pw_impl_node */ -+struct pw_impl_node * -+pw_context_create_node(struct pw_context *context, /**< the context */ -+ struct pw_properties *properties, /**< extra properties */ -+ size_t user_data_size /**< user data size */); -+ -+/** Complete initialization of the node and register */ -+int pw_impl_node_register(struct pw_impl_node *node, /**< node to register */ -+ struct pw_properties *properties /**< extra properties */); -+ -+/** Destroy a node */ -+void pw_impl_node_destroy(struct pw_impl_node *node); -+ -+/** Get the node info */ -+const struct pw_node_info *pw_impl_node_get_info(struct pw_impl_node *node); -+ -+/** Get node user_data. The size of the memory was given in \ref pw_context_create_node */ -+void * pw_impl_node_get_user_data(struct pw_impl_node *node); -+ -+/** Get the context of this node */ -+struct pw_context *pw_impl_node_get_context(struct pw_impl_node *node); -+ -+/** Get the global of this node */ -+struct pw_global *pw_impl_node_get_global(struct pw_impl_node *node); -+ -+/** Get the node properties */ -+const struct pw_properties *pw_impl_node_get_properties(struct pw_impl_node *node); -+ -+/** Update the node properties */ -+int pw_impl_node_update_properties(struct pw_impl_node *node, const struct spa_dict *dict); -+ -+/** Set the node implementation */ -+int pw_impl_node_set_implementation(struct pw_impl_node *node, struct spa_node *spa_node); -+ -+/** Get the node implementation */ -+struct spa_node *pw_impl_node_get_implementation(struct pw_impl_node *node); -+ -+/** Add an event listener */ -+void pw_impl_node_add_listener(struct pw_impl_node *node, -+ struct spa_hook *listener, -+ const struct pw_impl_node_events *events, -+ void *data); -+ -+/** Iterate the ports in the given direction. The callback should return -+ * 0 to fetch the next item, any other value stops the iteration and returns -+ * the value. When all callbacks return 0, this function returns 0 when all -+ * items are iterated. */ -+int pw_impl_node_for_each_port(struct pw_impl_node *node, -+ enum pw_direction direction, -+ int (*callback) (void *data, struct pw_impl_port *port), -+ void *data); -+ -+int pw_impl_node_for_each_param(struct pw_impl_node *node, -+ int seq, uint32_t param_id, -+ uint32_t index, uint32_t max, -+ const struct spa_pod *filter, -+ int (*callback) (void *data, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ struct spa_pod *param), -+ void *data); -+ -+/** Find the port with direction and port_id or NULL when not found. Passing -+ * PW_ID_ANY for port_id will return any port, preferably an unlinked one. */ -+struct pw_impl_port * -+pw_impl_node_find_port(struct pw_impl_node *node, enum pw_direction direction, uint32_t port_id); -+ -+/** Get a free unused port_id from the node */ -+uint32_t pw_impl_node_get_free_port_id(struct pw_impl_node *node, enum pw_direction direction); -+ -+int pw_impl_node_initialized(struct pw_impl_node *node); -+ -+/** Set a node active. This will start negotiation with all linked active -+ * nodes and start data transport */ -+int pw_impl_node_set_active(struct pw_impl_node *node, bool active); -+ -+/** Check if a node is active */ -+bool pw_impl_node_is_active(struct pw_impl_node *node); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_NODE_H */ -diff --git a/third_party/pipewire/pipewire/impl-port.h b/third_party/pipewire/pipewire/impl-port.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-port.h -@@ -0,0 +1,138 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_PORT_H -+#define PIPEWIRE_IMPL_PORT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_port Port -+ * -+ * \section page_node_overview Overview -+ * -+ * A port can be used to link two nodes. -+ */ -+/** \class pw_impl_port -+ * -+ * The port object -+ */ -+struct pw_impl_port; -+struct pw_impl_link; -+struct pw_control; -+ -+#include -+ -+enum pw_impl_port_state { -+ PW_IMPL_PORT_STATE_ERROR = -1, /**< the port is in error */ -+ PW_IMPL_PORT_STATE_INIT = 0, /**< the port is being created */ -+ PW_IMPL_PORT_STATE_CONFIGURE = 1, /**< the port is ready for format negotiation */ -+ PW_IMPL_PORT_STATE_READY = 2, /**< the port is ready for buffer allocation */ -+ PW_IMPL_PORT_STATE_PAUSED = 3, /**< the port is paused */ -+}; -+ -+/** Port events, use \ref pw_impl_port_add_listener */ -+struct pw_impl_port_events { -+#define PW_VERSION_IMPL_PORT_EVENTS 1 -+ uint32_t version; -+ -+ /** The port is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** The port is freed */ -+ void (*free) (void *data); -+ -+ /** The port is initialized */ -+ void (*initialized) (void *data); -+ -+ /** the port info changed */ -+ void (*info_changed) (void *data, const struct pw_port_info *info); -+ -+ /** a new link is added on this port */ -+ void (*link_added) (void *data, struct pw_impl_link *link); -+ -+ /** a link is removed from this port */ -+ void (*link_removed) (void *data, struct pw_impl_link *link); -+ -+ /** the state of the port changed */ -+ void (*state_changed) (void *data, enum pw_impl_port_state old, -+ enum pw_impl_port_state state, const char *error); -+ -+ /** a control was added to the port */ -+ void (*control_added) (void *data, struct pw_control *control); -+ -+ /** a control was removed from the port */ -+ void (*control_removed) (void *data, struct pw_control *control); -+ -+ /** a parameter changed, since version 1 */ -+ void (*param_changed) (void *data, uint32_t id); -+}; -+ -+/** Create a new port \memberof pw_impl_port -+ * \return a newly allocated port */ -+struct pw_impl_port * -+pw_context_create_port(struct pw_context *context, -+ enum pw_direction direction, -+ uint32_t port_id, -+ const struct spa_port_info *info, -+ size_t user_data_size); -+ -+/** Get the port direction */ -+enum pw_direction pw_impl_port_get_direction(struct pw_impl_port *port); -+ -+/** Get the port properties */ -+const struct pw_properties *pw_impl_port_get_properties(struct pw_impl_port *port); -+ -+/** Update the port properties */ -+int pw_impl_port_update_properties(struct pw_impl_port *port, const struct spa_dict *dict); -+ -+/** Get the port info */ -+const struct pw_port_info *pw_impl_port_get_info(struct pw_impl_port *port); -+ -+/** Get the port id */ -+uint32_t pw_impl_port_get_id(struct pw_impl_port *port); -+ -+/** Get the port parent node or NULL when not yet set */ -+struct pw_impl_node *pw_impl_port_get_node(struct pw_impl_port *port); -+ -+/** check is a port has links, return 0 if not, 1 if it is linked */ -+int pw_impl_port_is_linked(struct pw_impl_port *port); -+ -+/** Add a port to a node \memberof pw_impl_port */ -+int pw_impl_port_add(struct pw_impl_port *port, struct pw_impl_node *node); -+ -+/** Add an event listener on the port */ -+void pw_impl_port_add_listener(struct pw_impl_port *port, -+ struct spa_hook *listener, -+ const struct pw_impl_port_events *events, -+ void *data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_PORT_H */ -diff --git a/third_party/pipewire/pipewire/impl.h b/third_party/pipewire/pipewire/impl.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl.h -@@ -0,0 +1,57 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_H -+#define PIPEWIRE_IMPL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct pw_impl_client; -+struct pw_impl_module; -+struct pw_global; -+struct pw_node; -+struct pw_impl_port; -+struct pw_resource; -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_H */ -diff --git a/third_party/pipewire/pipewire/keys.h b/third_party/pipewire/pipewire/keys.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/keys.h -@@ -0,0 +1,278 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_KEYS_H -+#define PIPEWIRE_KEYS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * A collection of keys that are used to add extra information on objects. -+ * -+ * Keys that start with "pipewire." are in general set-once and then -+ * read-only. They are usually used for security sensitive information that -+ * needs to be fixed. -+ * -+ * Properties from other objects can also appear. This usually suggests some -+ * sort of parent/child or owner/owned relationship. -+ */ -+#define PW_KEY_PROTOCOL "pipewire.protocol" /**< protocol used for connection */ -+#define PW_KEY_ACCESS "pipewire.access" /**< how the client access is controlled */ -+ -+/** Various keys related to the identity of a client process and its security. -+ * Must be obtained from trusted sources by the protocol and placed as -+ * read-only properties. */ -+#define PW_KEY_SEC_PID "pipewire.sec.pid" /**< Client pid, set by protocol */ -+#define PW_KEY_SEC_UID "pipewire.sec.uid" /**< Client uid, set by protocol*/ -+#define PW_KEY_SEC_GID "pipewire.sec.gid" /**< client gid, set by protocol*/ -+#define PW_KEY_SEC_LABEL "pipewire.sec.label" /**< client security label, set by protocol*/ -+ -+#define PW_KEY_LIBRARY_NAME_SYSTEM "library.name.system" /**< name of the system library to use */ -+#define PW_KEY_LIBRARY_NAME_LOOP "library.name.loop" /**< name of the loop library to use */ -+#define PW_KEY_LIBRARY_NAME_DBUS "library.name.dbus" /**< name of the dbus library to use */ -+ -+#define PW_KEY_OBJECT_PATH "object.path" /**< unique path to construct the object */ -+#define PW_KEY_OBJECT_ID "object.id" /**< a global object id */ -+ -+/* context */ -+#define PW_KEY_CONTEXT_PROFILE_MODULES "context.profile.modules" /**< a context profile for modules */ -+#define PW_KEY_USER_NAME "context.user-name" /**< The user name that runs pipewire */ -+#define PW_KEY_HOST_NAME "context.host-name" /**< The host name of the machine */ -+ -+/* core */ -+#define PW_KEY_CORE_NAME "core.name" /**< The name of the core. Default is -+ * pipewire--, overwritten -+ * by env(PIPEWIRE_CORE) */ -+#define PW_KEY_CORE_VERSION "core.version" /**< The version of the core. */ -+#define PW_KEY_CORE_DAEMON "core.daemon" /**< If the core is listening for connections. */ -+ -+#define PW_KEY_CORE_ID "core.id" /**< the core id */ -+#define PW_KEY_CORE_MONITORS "core.monitors" /**< the apis monitored by core. */ -+ -+/* cpu */ -+#define PW_KEY_CPU_MAX_ALIGN "cpu.max-align" /**< maximum alignment needed to support -+ * all CPU optimizations */ -+#define PW_KEY_CPU_CORES "cpu.cores" /**< number of cores */ -+ -+/* priorities */ -+#define PW_KEY_PRIORITY_SESSION "priority.session" /**< priority in session manager */ -+#define PW_KEY_PRIORITY_DRIVER "priority.driver" /**< priority to be a driver */ -+ -+/* remote keys */ -+#define PW_KEY_REMOTE_NAME "remote.name" /**< The name of the remote to connect to, -+ * default pipewire-0, overwritten by -+ * env(PIPEWIRE_REMOTE) */ -+#define PW_KEY_REMOTE_INTENTION "remote.intention" /**< The intention of the remote connection, -+ * "generic", "screencast" */ -+ -+/** application keys */ -+#define PW_KEY_APP_NAME "application.name" /**< application name. Ex: "Totem Music Player" */ -+#define PW_KEY_APP_ID "application.id" /**< a textual id for identifying an -+ * application logically. Ex: "org.gnome.Totem" */ -+#define PW_KEY_APP_VERSION "application.version" -+#define PW_KEY_APP_ICON "application.icon" /**< aa base64 blob with PNG image data */ -+#define PW_KEY_APP_ICON_NAME "application.icon-name" /**< an XDG icon name for the application. -+ * Ex: "totem" */ -+#define PW_KEY_APP_LANGUAGE "application.language" /**< application language if applicable, in -+ * standard POSIX format. Ex: "en_GB" */ -+ -+#define PW_KEY_APP_PROCESS_ID "application.process.id" /**< process id (pid)*/ -+#define PW_KEY_APP_PROCESS_BINARY "application.process.binary" /**< binary name */ -+#define PW_KEY_APP_PROCESS_USER "application.process.user" /**< user name */ -+#define PW_KEY_APP_PROCESS_HOST "application.process.host" /**< host name */ -+#define PW_KEY_APP_PROCESS_MACHINE_ID "application.process.machine-id" /**< the D-Bus host id the -+ * application runs on */ -+#define PW_KEY_APP_PROCESS_SESSION_ID "application.process.session-id" /**< login session of the -+ * application, on Unix the -+ * value of $XDG_SESSION_ID. */ -+/** window system */ -+#define PW_KEY_WINDOW_X11_DISPLAY "window.x11.display" /**< the X11 display string. Ex. ":0.0" */ -+ -+/** Client properties */ -+#define PW_KEY_CLIENT_ID "client.id" /**< a client id */ -+#define PW_KEY_CLIENT_NAME "client.name" /**< the client name */ -+#define PW_KEY_CLIENT_API "client.api" /**< the client api used to access -+ * PipeWire */ -+ -+/** Node keys */ -+#define PW_KEY_NODE_ID "node.id" /**< node id */ -+#define PW_KEY_NODE_NAME "node.name" /**< node name */ -+#define PW_KEY_NODE_NICK "node.nick" /**< short node name */ -+#define PW_KEY_NODE_DESCRIPTION "node.description" /**< localized human readable node one-line -+ * description. Ex. "Foobar USB Headset" */ -+#define PW_KEY_NODE_PLUGGED "node.plugged" /**< when the node was created. As a uint64 in -+ * nanoseconds. */ -+ -+#define PW_KEY_NODE_SESSION "node.session" /**< the session id this node is part of */ -+#define PW_KEY_NODE_GROUP "node.group" /**< the group id this node is part of. Nodes -+ * in the same group are always scheduled -+ * with the same driver. */ -+#define PW_KEY_NODE_EXCLUSIVE "node.exclusive" /**< node wants exclusive access to resources */ -+#define PW_KEY_NODE_AUTOCONNECT "node.autoconnect" /**< node wants to be automatically connected -+ * to a compatible node */ -+#define PW_KEY_NODE_TARGET "node.target" /**< node wants to be connected to the target -+ * node/session */ -+#define PW_KEY_NODE_LATENCY "node.latency" /**< the requested latency of the node as -+ * a fraction. Ex: 128/48000 */ -+#define PW_KEY_NODE_DONT_RECONNECT "node.dont-reconnect" /**< don't reconnect this node */ -+#define PW_KEY_NODE_ALWAYS_PROCESS "node.always-process" /**< process even when unlinked */ -+#define PW_KEY_NODE_PAUSE_ON_IDLE "node.pause-on-idle" /**< pause the node when idle */ -+#define PW_KEY_NODE_DRIVER "node.driver" /**< node can drive the graph */ -+#define PW_KEY_NODE_STREAM "node.stream" /**< node is a stream, the server side should -+ * add a converter */ -+/** Port keys */ -+#define PW_KEY_PORT_ID "port.id" /**< port id */ -+#define PW_KEY_PORT_NAME "port.name" /**< port name */ -+#define PW_KEY_PORT_DIRECTION "port.direction" /**< the port direction, one of "in" or "out" -+ * or "control" and "notify" for control ports */ -+#define PW_KEY_PORT_ALIAS "port.alias" /**< port alias */ -+#define PW_KEY_PORT_PHYSICAL "port.physical" /**< if this is a physical port */ -+#define PW_KEY_PORT_TERMINAL "port.terminal" /**< if this port consumes the data */ -+#define PW_KEY_PORT_CONTROL "port.control" /**< if this port is a control port */ -+#define PW_KEY_PORT_MONITOR "port.monitor" /**< if this port is a monitor port */ -+ -+/** link properties */ -+#define PW_KEY_LINK_ID "link.id" /**< a link id */ -+#define PW_KEY_LINK_INPUT_NODE "link.input.node" /**< input node id of a link */ -+#define PW_KEY_LINK_INPUT_PORT "link.input.port" /**< input port id of a link */ -+#define PW_KEY_LINK_OUTPUT_NODE "link.output.node" /**< output node id of a link */ -+#define PW_KEY_LINK_OUTPUT_PORT "link.output.port" /**< output port id of a link */ -+#define PW_KEY_LINK_PASSIVE "link.passive" /**< indicate that a link is passive and -+ * does not cause the graph to be -+ * runnable. */ -+/** device properties */ -+#define PW_KEY_DEVICE_ID "device.id" /**< device id */ -+#define PW_KEY_DEVICE_NAME "device.name" /**< device name */ -+#define PW_KEY_DEVICE_PLUGGED "device.plugged" /**< when the device was created. As a uint64 in -+ * nanoseconds. */ -+#define PW_KEY_DEVICE_NICK "device.nick" /**< a short device nickname */ -+#define PW_KEY_DEVICE_STRING "device.string" /**< device string in the underlying layer's -+ * format. Ex. "surround51:0" */ -+#define PW_KEY_DEVICE_API "device.api" /**< API this device is accessed with. -+ * Ex. "alsa", "v4l2" */ -+#define PW_KEY_DEVICE_DESCRIPTION "device.description" /**< localized human readable device one-line -+ * description. Ex. "Foobar USB Headset" */ -+#define PW_KEY_DEVICE_BUS_PATH "device.bus-path" /**< bus path to the device in the OS' -+ * format. Ex. "pci-0000:00:14.0-usb-0:3.2:1.0" */ -+#define PW_KEY_DEVICE_SERIAL "device.serial" /**< Serial number if applicable */ -+#define PW_KEY_DEVICE_VENDOR_ID "device.vendor.id" /**< vendor ID if applicable */ -+#define PW_KEY_DEVICE_VENDOR_NAME "device.vendor.name" /**< vendor name if applicable */ -+#define PW_KEY_DEVICE_PRODUCT_ID "device.product.id" /**< product ID if applicable */ -+#define PW_KEY_DEVICE_PRODUCT_NAME "device.product.name" /**< product name if applicable */ -+#define PW_KEY_DEVICE_CLASS "device.class" /**< device class */ -+#define PW_KEY_DEVICE_FORM_FACTOR "device.form-factor" /**< form factor if applicable. One of -+ * "internal", "speaker", "handset", "tv", -+ * "webcam", "microphone", "headset", -+ * "headphone", "hands-free", "car", "hifi", -+ * "computer", "portable" */ -+#define PW_KEY_DEVICE_BUS "device.bus" /**< bus of the device if applicable. One of -+ * "isa", "pci", "usb", "firewire", -+ * "bluetooth" */ -+#define PW_KEY_DEVICE_SUBSYSTEM "device.subsystem" /**< device subsystem */ -+#define PW_KEY_DEVICE_ICON "device.icon" /**< icon for the device. A base64 blob -+ * containing PNG image data */ -+#define PW_KEY_DEVICE_ICON_NAME "device.icon-name" /**< an XDG icon name for the device. -+ * Ex. "sound-card-speakers-usb" */ -+#define PW_KEY_DEVICE_INTENDED_ROLES "device.intended-roles" /**< intended use. A space separated list of -+ * roles (see PW_KEY_MEDIA_ROLE) this device -+ * is particularly well suited for, due to -+ * latency, quality or form factor. */ -+ -+/** module properties */ -+#define PW_KEY_MODULE_ID "module.id" /**< the module id */ -+#define PW_KEY_MODULE_NAME "module.name" /**< the name of the module */ -+#define PW_KEY_MODULE_AUTHOR "module.author" /**< the author's name */ -+#define PW_KEY_MODULE_DESCRIPTION "module.description" /**< a human readable one-line description -+ * of the module's purpose.*/ -+#define PW_KEY_MODULE_USAGE "module.usage" /**< a human readable usage description of -+ * the module's arguments. */ -+#define PW_KEY_MODULE_VERSION "module.version" /**< a version string for the module. */ -+ -+/** Factory properties */ -+#define PW_KEY_FACTORY_ID "factory.id" /**< the factory id */ -+#define PW_KEY_FACTORY_NAME "factory.name" /**< the name of the factory */ -+#define PW_KEY_FACTORY_USAGE "factory.usage" /**< the usage of the factory */ -+#define PW_KEY_FACTORY_TYPE_NAME "factory.type.name" /**< the name of the type created by a factory */ -+#define PW_KEY_FACTORY_TYPE_VERSION "factory.type.version" /**< the version of the type created by a factory */ -+ -+/** Stream properties */ -+#define PW_KEY_STREAM_IS_LIVE "stream.is-live" /**< Indicates that the stream is live. */ -+#define PW_KEY_STREAM_LATENCY_MIN "stream.latency.min" /**< The minimum latency of the stream. */ -+#define PW_KEY_STREAM_LATENCY_MAX "stream.latency.max" /**< The maximum latency of the stream */ -+#define PW_KEY_STREAM_MONITOR "stream.monitor" /**< Indicates that the stream is monitoring -+ * and might select a less accurate but faster -+ * conversion algorithm. */ -+#define PW_KEY_STREAM_DONT_REMIX "stream.dont-remix" /**< don't remix channels */ -+ -+/** object properties */ -+#define PW_KEY_OBJECT_LINGER "object.linger" /**< the object lives on even after the client -+ * that created it has been destroyed */ -+ -+/** Media */ -+#define PW_KEY_MEDIA_TYPE "media.type" /**< Media type, one of -+ * Audio, Video, Midi */ -+#define PW_KEY_MEDIA_CATEGORY "media.category" /**< Media Category: -+ * Playback, Capture, Duplex, Monitor */ -+#define PW_KEY_MEDIA_ROLE "media.role" /**< Role: Movie, Music, Camera, -+ * Screen, Communication, Game, -+ * Notification, DSP, Production, -+ * Accessibility, Test */ -+#define PW_KEY_MEDIA_CLASS "media.class" /**< class Ex: "Video/Source" */ -+#define PW_KEY_MEDIA_NAME "media.name" /**< media name. Ex: "Pink Floyd: Time" */ -+#define PW_KEY_MEDIA_TITLE "media.title" /**< title. Ex: "Time" */ -+#define PW_KEY_MEDIA_ARTIST "media.artist" /**< artist. Ex: "Pink Floyd" */ -+#define PW_KEY_MEDIA_COPYRIGHT "media.copyright" /**< copyright string */ -+#define PW_KEY_MEDIA_SOFTWARE "media.software" /**< generator software */ -+#define PW_KEY_MEDIA_LANGUAGE "media.language" /**< language in POSIX format. Ex: en_GB */ -+#define PW_KEY_MEDIA_FILENAME "media.filename" /**< filename */ -+#define PW_KEY_MEDIA_ICON "media.icon" /**< icon for the media, a base64 blob with -+ * PNG image data */ -+#define PW_KEY_MEDIA_ICON_NAME "media.icon-name" /**< an XDG icon name for the media. -+ * Ex: "audio-x-mp3" */ -+ -+/** format related properties */ -+#define PW_KEY_FORMAT_DSP "format.dsp" /**< a dsp format. -+ * Ex: "32 bit float mono audio" */ -+/** audio related properties */ -+#define PW_KEY_AUDIO_CHANNEL "audio.channel" /**< an audio channel. Ex: "FL" */ -+#define PW_KEY_AUDIO_RATE "audio.samplerate" /**< an audio samplerate */ -+#define PW_KEY_AUDIO_CHANNELS "audio.channels" /**< number of audio channels */ -+#define PW_KEY_AUDIO_FORMAT "audio.format" /**< an audio format. Ex: "S16LE" */ -+ -+/** video related properties */ -+#define PW_KEY_VIDEO_RATE "video.framerate" /**< a video framerate */ -+#define PW_KEY_VIDEO_FORMAT "video.format" /**< a video format */ -+#define PW_KEY_VIDEO_SIZE "video.size" /**< a video size as "x -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Link PW_TYPE_INFO_INTERFACE_BASE "Link" -+ -+#define PW_VERSION_LINK 3 -+struct pw_link; -+ -+/** \enum pw_link_state The different link states \memberof pw_link */ -+enum pw_link_state { -+ PW_LINK_STATE_ERROR = -2, /**< the link is in error */ -+ PW_LINK_STATE_UNLINKED = -1, /**< the link is unlinked */ -+ PW_LINK_STATE_INIT = 0, /**< the link is initialized */ -+ PW_LINK_STATE_NEGOTIATING = 1, /**< the link is negotiating formats */ -+ PW_LINK_STATE_ALLOCATING = 2, /**< the link is allocating buffers */ -+ PW_LINK_STATE_PAUSED = 3, /**< the link is paused */ -+}; -+ -+/** Convert a \ref pw_link_state to a readable string \memberof pw_link */ -+const char * pw_link_state_as_string(enum pw_link_state state); -+/** The link information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_link_info { -+ uint32_t id; /**< id of the global */ -+ uint32_t output_node_id; /**< server side output node id */ -+ uint32_t output_port_id; /**< output port id */ -+ uint32_t input_node_id; /**< server side input node id */ -+ uint32_t input_port_id; /**< input port id */ -+#define PW_LINK_CHANGE_MASK_STATE (1 << 0) -+#define PW_LINK_CHANGE_MASK_FORMAT (1 << 1) -+#define PW_LINK_CHANGE_MASK_PROPS (1 << 2) -+#define PW_LINK_CHANGE_MASK_ALL ((1 << 3)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ enum pw_link_state state; /**< the current state of the link */ -+ const char *error; /**< an error reason if \a state is error */ -+ struct spa_pod *format; /**< format over link */ -+ struct spa_dict *props; /**< the properties of the link */ -+}; -+ -+struct pw_link_info * -+pw_link_info_update(struct pw_link_info *info, -+ const struct pw_link_info *update); -+ -+void -+pw_link_info_free(struct pw_link_info *info); -+ -+ -+#define PW_LINK_EVENT_INFO 0 -+#define PW_LINK_EVENT_NUM 1 -+ -+/** Link events */ -+struct pw_link_events { -+#define PW_VERSION_LINK_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify link info -+ * -+ * \param info info about the link -+ */ -+ void (*info) (void *object, const struct pw_link_info *info); -+}; -+ -+#define PW_LINK_METHOD_ADD_LISTENER 0 -+#define PW_LINK_METHOD_NUM 1 -+ -+/** Link methods */ -+struct pw_link_methods { -+#define PW_VERSION_LINK_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_link_events *events, -+ void *data); -+}; -+ -+#define pw_link_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_link_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_link_add_listener(c,...) pw_link_method(c,add_listener,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_LINK_H */ -diff --git a/third_party/pipewire/pipewire/log.h b/third_party/pipewire/pipewire/log.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/log.h -@@ -0,0 +1,97 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_LOG_H -+#define PIPEWIRE_LOG_H -+ -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_log -+ * -+ * Logging functions of PipeWire -+ * -+ * Logging is performed to stdout and stderr. Trace logging is performed -+ * in a lockfree ringbuffer and written out from the main thread as to not -+ * block the realtime threads. -+ */ -+ -+/** The global log level */ -+extern enum spa_log_level pw_log_level; -+ -+/** Configure a logging module. This is usually done automatically -+ * in pw_init() but you can install a custom logger before calling -+ * pw_init(). */ -+void pw_log_set(struct spa_log *log); -+ -+/** Get the log interface */ -+struct spa_log *pw_log_get(void); -+ -+/** Configure the logging level */ -+void pw_log_set_level(enum spa_log_level level); -+ -+ -+/** Log a message */ -+void -+pw_log_log(enum spa_log_level level, -+ const char *file, -+ int line, const char *func, -+ const char *fmt, ...) SPA_PRINTF_FUNC(5, 6); -+ -+/** Log a message */ -+void -+pw_log_logv(enum spa_log_level level, -+ const char *file, -+ int line, const char *func, -+ const char *fmt, va_list args) SPA_PRINTF_FUNC(5, 0); -+ -+ -+/** Check if a loglevel is enabled \memberof pw_log */ -+#define pw_log_level_enabled(lev) (pw_log_level >= (lev)) -+ -+#define pw_log(lev,...) \ -+({ \ -+ if (SPA_UNLIKELY(pw_log_level_enabled (lev))) \ -+ pw_log_log(lev,__FILE__,__LINE__,__func__,__VA_ARGS__); \ -+}) -+ -+#define pw_log_error(...) pw_log(SPA_LOG_LEVEL_ERROR,__VA_ARGS__) -+#define pw_log_warn(...) pw_log(SPA_LOG_LEVEL_WARN,__VA_ARGS__) -+#define pw_log_info(...) pw_log(SPA_LOG_LEVEL_INFO,__VA_ARGS__) -+#define pw_log_debug(...) pw_log(SPA_LOG_LEVEL_DEBUG,__VA_ARGS__) -+#define pw_log_trace(...) pw_log(SPA_LOG_LEVEL_TRACE,__VA_ARGS__) -+ -+#ifndef FASTPATH -+#define pw_log_trace_fp(...) pw_log(SPA_LOG_LEVEL_TRACE,__VA_ARGS__) -+#else -+#define pw_log_trace_fp(...) -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+#endif /* PIPEWIRE_LOG_H */ -diff --git a/third_party/pipewire/pipewire/loop.h b/third_party/pipewire/pipewire/loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/loop.h -@@ -0,0 +1,80 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_LOOP_H -+#define PIPEWIRE_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class pw_loop -+ * -+ * PipeWire loop object provides an implementation of -+ * the spa loop interfaces. It can be used to implement various -+ * event loops. -+ */ -+struct pw_loop { -+ struct spa_system *system; /**< system utils */ -+ struct spa_loop *loop; /**< wrapped loop */ -+ struct spa_loop_control *control; /**< loop control */ -+ struct spa_loop_utils *utils; /**< loop utils */ -+}; -+ -+struct pw_loop * -+pw_loop_new(const struct spa_dict *props); -+ -+void -+pw_loop_destroy(struct pw_loop *loop); -+ -+#define pw_loop_add_source(l,...) spa_loop_add_source((l)->loop,__VA_ARGS__) -+#define pw_loop_update_source(l,...) spa_loop_update_source(__VA_ARGS__) -+#define pw_loop_remove_source(l,...) spa_loop_remove_source(__VA_ARGS__) -+#define pw_loop_invoke(l,...) spa_loop_invoke((l)->loop,__VA_ARGS__) -+ -+#define pw_loop_get_fd(l) spa_loop_control_get_fd((l)->control) -+#define pw_loop_add_hook(l,...) spa_loop_control_add_hook((l)->control,__VA_ARGS__) -+#define pw_loop_enter(l) spa_loop_control_enter((l)->control) -+#define pw_loop_iterate(l,...) spa_loop_control_iterate((l)->control,__VA_ARGS__) -+#define pw_loop_leave(l) spa_loop_control_leave((l)->control) -+ -+#define pw_loop_add_io(l,...) spa_loop_utils_add_io((l)->utils,__VA_ARGS__) -+#define pw_loop_update_io(l,...) spa_loop_utils_update_io((l)->utils,__VA_ARGS__) -+#define pw_loop_add_idle(l,...) spa_loop_utils_add_idle((l)->utils,__VA_ARGS__) -+#define pw_loop_enable_idle(l,...) spa_loop_utils_enable_idle((l)->utils,__VA_ARGS__) -+#define pw_loop_add_event(l,...) spa_loop_utils_add_event((l)->utils,__VA_ARGS__) -+#define pw_loop_signal_event(l,...) spa_loop_utils_signal_event((l)->utils,__VA_ARGS__) -+#define pw_loop_add_timer(l,...) spa_loop_utils_add_timer((l)->utils,__VA_ARGS__) -+#define pw_loop_update_timer(l,...) spa_loop_utils_update_timer((l)->utils,__VA_ARGS__) -+#define pw_loop_add_signal(l,...) spa_loop_utils_add_signal((l)->utils,__VA_ARGS__) -+#define pw_loop_destroy_source(l,...) spa_loop_utils_destroy_source((l)->utils,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/main-loop.h b/third_party/pipewire/pipewire/main-loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/main-loop.h -@@ -0,0 +1,78 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MAIN_LOOP_H -+#define PIPEWIRE_MAIN_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_main_loop -+ * -+ * \brief PipeWire main-loop interface. -+ * -+ * A main loop object -+ */ -+/** A main loop object \memberof pw_main_loop */ -+struct pw_main_loop; -+ -+#include -+ -+/** Events of the main loop */ -+struct pw_main_loop_events { -+#define PW_VERSION_MAIN_LOOP_EVENTS 0 -+ uint32_t version; -+ -+ /** Emitted when the main loop is destroyed */ -+ void (*destroy) (void *data); -+}; -+ -+/** Create a new main loop. */ -+struct pw_main_loop * -+pw_main_loop_new(const struct spa_dict *props); -+ -+/** Add an event listener */ -+void pw_main_loop_add_listener(struct pw_main_loop *loop, -+ struct spa_hook *listener, -+ const struct pw_main_loop_events *events, -+ void *data); -+ -+/** Get the loop implementation */ -+struct pw_loop * pw_main_loop_get_loop(struct pw_main_loop *loop); -+ -+/** Destroy a loop */ -+void pw_main_loop_destroy(struct pw_main_loop *loop); -+ -+/** Run a main loop. This blocks until \ref pw_main_loop_quit is called */ -+int pw_main_loop_run(struct pw_main_loop *loop); -+ -+/** Quit a main loop */ -+int pw_main_loop_quit(struct pw_main_loop *loop); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_MAIN_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/map.h b/third_party/pipewire/pipewire/map.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/map.h -@@ -0,0 +1,206 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MAP_H -+#define PIPEWIRE_MAP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+/** \class pw_map -+ * -+ * A map that holds objects indexed by id -+ */ -+ -+/** An entry in the map \memberof pw_map */ -+union pw_map_item { -+ uint32_t next; /**< next free index */ -+ void *data; /**< data of this item, must be an even address */ -+}; -+ -+/** A map \memberof pw_map */ -+struct pw_map { -+ struct pw_array items; /**< an array with the map items */ -+ uint32_t free_list; /**< the free items */ -+}; -+ -+#define PW_MAP_INIT(extend) (struct pw_map) { PW_ARRAY_INIT(extend), 0 } -+ -+#define pw_map_get_size(m) pw_array_get_len(&(m)->items, union pw_map_item) -+#define pw_map_get_item(m,id) pw_array_get_unchecked(&(m)->items,id,union pw_map_item) -+#define pw_map_item_is_free(item) ((item)->next & 0x1) -+#define pw_map_id_is_free(m,id) (pw_map_item_is_free(pw_map_get_item(m,id))) -+#define pw_map_check_id(m,id) ((id) < pw_map_get_size(m)) -+#define pw_map_has_item(m,id) (pw_map_check_id(m,id) && !pw_map_id_is_free(m, id)) -+#define pw_map_lookup_unchecked(m,id) pw_map_get_item(m,id)->data -+ -+/** Convert an id to a pointer that can be inserted into the map \memberof pw_map */ -+#define PW_MAP_ID_TO_PTR(id) (SPA_UINT32_TO_PTR((id)<<1)) -+/** Convert a pointer to an id that can be retrieved from the map \memberof pw_map */ -+#define PW_MAP_PTR_TO_ID(p) (SPA_PTR_TO_UINT32(p)>>1) -+ -+/** Initialize a map -+ * \param map the map to initialize -+ * \param size the initial size of the map -+ * \param extend the amount to bytes to grow the map with when needed -+ * \memberof pw_map -+ */ -+static inline void pw_map_init(struct pw_map *map, size_t size, size_t extend) -+{ -+ pw_array_init(&map->items, extend); -+ pw_array_ensure_size(&map->items, size * sizeof(union pw_map_item)); -+ map->free_list = SPA_ID_INVALID; -+} -+ -+/** Clear a map -+ * \param map the map to clear -+ * \memberof pw_map -+ */ -+static inline void pw_map_clear(struct pw_map *map) -+{ -+ pw_array_clear(&map->items); -+} -+ -+static inline void pw_map_reset(struct pw_map *map) -+{ -+ pw_array_reset(&map->items); -+ map->free_list = SPA_ID_INVALID; -+} -+ -+/** Insert data in the map -+ * \param map the map to insert into -+ * \param data the item to add -+ * \return the id where the item was inserted or SPA_ID_INVALID when the -+ * item can not be inserted. -+ * \memberof pw_map -+ */ -+static inline uint32_t pw_map_insert_new(struct pw_map *map, void *data) -+{ -+ union pw_map_item *start, *item; -+ uint32_t id; -+ -+ if (map->free_list != SPA_ID_INVALID) { -+ start = (union pw_map_item *) map->items.data; -+ item = &start[map->free_list >> 1]; -+ map->free_list = item->next; -+ } else { -+ item = (union pw_map_item *) pw_array_add(&map->items, sizeof(union pw_map_item)); -+ if (item == NULL) -+ return SPA_ID_INVALID; -+ start = (union pw_map_item *) map->items.data; -+ } -+ item->data = data; -+ id = (item - start); -+ return id; -+} -+ -+/** Insert data in the map at an index -+ * \param map the map to inser into -+ * \param id the index to insert at -+ * \param data the data to insert -+ * \return 0 on success, -ENOSPC value when the index is invalid or a < 0 -+ * errno value. -+ * \memberof pw_map -+ */ -+static inline int pw_map_insert_at(struct pw_map *map, uint32_t id, void *data) -+{ -+ size_t size = pw_map_get_size(map); -+ union pw_map_item *item; -+ -+ if (id > size) -+ return -ENOSPC; -+ else if (id == size) { -+ item = (union pw_map_item *) pw_array_add(&map->items, sizeof(union pw_map_item)); -+ if (item == NULL) -+ return -errno; -+ } -+ else { -+ item = pw_map_get_item(map, id); -+ } -+ item->data = data; -+ return 0; -+} -+ -+/** Remove an item at index -+ * \param map the map to remove from -+ * \param id the index to remove -+ * \memberof pw_map -+ */ -+static inline void pw_map_remove(struct pw_map *map, uint32_t id) -+{ -+ pw_map_get_item(map, id)->next = map->free_list; -+ map->free_list = (id << 1) | 1; -+} -+ -+/** Find an item in the map -+ * \param map the map to use -+ * \param id the index to look at -+ * \return the item at \a id or NULL when no such item exists -+ * \memberof pw_map -+ */ -+static inline void *pw_map_lookup(struct pw_map *map, uint32_t id) -+{ -+ if (SPA_LIKELY(pw_map_check_id(map, id))) { -+ union pw_map_item *item = pw_map_get_item(map, id); -+ if (!pw_map_item_is_free(item)) -+ return item->data; -+ } -+ return NULL; -+} -+ -+/** Iterate all map items -+ * \param map the map to iterate -+ * \param func the function to call for each item, the item data and \a data is -+ * passed to the function. When \a func returns a non-zero result, -+ * iteration ends and the result is returned. -+ * \param data data to pass to \a func -+ * \return the result of the last call to \a func or 0 when all callbacks returned 0. -+ * \memberof pw_map -+ */ -+static inline int pw_map_for_each(struct pw_map *map, -+ int (*func) (void *item_data, void *data), void *data) -+{ -+ union pw_map_item *item; -+ int res = 0; -+ -+ pw_array_for_each(item, &map->items) { -+ if (!pw_map_item_is_free(item)) -+ if ((res = func(item->data, data)) != 0) -+ break; -+ } -+ return res; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_MAP_H */ -diff --git a/third_party/pipewire/pipewire/mem.h b/third_party/pipewire/pipewire/mem.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/mem.h -@@ -0,0 +1,199 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MEM_H -+#define PIPEWIRE_MEM_H -+ -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** Flags passed to \ref pw_mempool_alloc() \memberof pw_memblock */ -+enum pw_memblock_flags { -+ PW_MEMBLOCK_FLAG_NONE = 0, -+ PW_MEMBLOCK_FLAG_READABLE = (1 << 0), /**< memory is readable */ -+ PW_MEMBLOCK_FLAG_WRITABLE = (1 << 1), /**< memory is writable */ -+ PW_MEMBLOCK_FLAG_SEAL = (1 << 2), /**< seal the fd */ -+ PW_MEMBLOCK_FLAG_MAP = (1 << 3), /**< mmap the fd */ -+ PW_MEMBLOCK_FLAG_DONT_CLOSE = (1 << 4), /**< don't close fd */ -+ PW_MEMBLOCK_FLAG_DONT_NOTIFY = (1 << 5), /**< don't notify events */ -+ -+ PW_MEMBLOCK_FLAG_READWRITE = PW_MEMBLOCK_FLAG_READABLE | PW_MEMBLOCK_FLAG_WRITABLE, -+}; -+ -+enum pw_memmap_flags { -+ PW_MEMMAP_FLAG_NONE = 0, -+ PW_MEMMAP_FLAG_READ = (1 << 0), /**< map in read mode */ -+ PW_MEMMAP_FLAG_WRITE = (1 << 1), /**< map in write mode */ -+ PW_MEMMAP_FLAG_TWICE = (1 << 2), /**< map the same area twice after each other, -+ * creating a circular ringbuffer */ -+ PW_MEMMAP_FLAG_PRIVATE = (1 << 3), /**< writes will be private */ -+ PW_MEMMAP_FLAG_READWRITE = PW_MEMMAP_FLAG_READ | PW_MEMMAP_FLAG_WRITE, -+}; -+ -+struct pw_memchunk; -+ -+/** \class pw_memblock -+ * -+ * A memory pool is a collection of pw_memblocks */ -+struct pw_mempool { -+ struct pw_properties *props; -+}; -+ -+/** \class pw_memblock -+ * Memory block structure */ -+struct pw_memblock { -+ struct pw_mempool *pool; /**< owner pool */ -+ uint32_t id; /**< unique id */ -+ int ref; /**< refcount */ -+ uint32_t flags; /**< flags for the memory block on of enum pw_memblock_flags */ -+ uint32_t type; /**< type of the fd, one of enum spa_data_type */ -+ int fd; /**< fd */ -+ uint32_t size; /**< size of memory */ -+ struct pw_memmap *map; /**< optional map when PW_MEMBLOCK_FLAG_MAP was given */ -+}; -+ -+/** a mapped region of a pw_memblock */ -+struct pw_memmap { -+ struct pw_memblock *block; /**< owner memblock */ -+ void *ptr; /**< mapped pointer */ -+ uint32_t flags; /**< flags for the mapping on of enum pw_memmap_flags */ -+ uint32_t offset; /**< offset in memblock */ -+ uint32_t size; /**< size in memblock */ -+ uint32_t tag[5]; /**< user tag */ -+}; -+ -+struct pw_mempool_events { -+#define PW_VERSION_MEMPOOL_EVENTS 0 -+ uint32_t version; -+ -+ /** the pool is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** a new memory block is added to the pool */ -+ void (*added) (void *data, struct pw_memblock *block); -+ -+ /** a memory block is removed from the pool */ -+ void (*removed) (void *data, struct pw_memblock *block); -+}; -+ -+/** Create a new memory pool */ -+struct pw_mempool *pw_mempool_new(struct pw_properties *props); -+ -+/** Listen for events */ -+void pw_mempool_add_listener(struct pw_mempool *pool, -+ struct spa_hook *listener, -+ const struct pw_mempool_events *events, -+ void *data); -+ -+/** Clear a pool */ -+void pw_mempool_clear(struct pw_mempool *pool); -+ -+/** Clear and destroy a pool */ -+void pw_mempool_destroy(struct pw_mempool *pool); -+ -+ -+/** Allocate a memory block from the pool */ -+struct pw_memblock * pw_mempool_alloc(struct pw_mempool *pool, -+ enum pw_memblock_flags flags, uint32_t type, size_t size); -+ -+/** Import a block from another pool */ -+struct pw_memblock * pw_mempool_import_block(struct pw_mempool *pool, -+ struct pw_memblock *mem); -+ -+/** Import an fd into the pool */ -+struct pw_memblock * pw_mempool_import(struct pw_mempool *pool, -+ enum pw_memblock_flags flags, uint32_t type, int fd); -+ -+/** Free a memblock regardless of the refcount and destroy all mappings */ -+void pw_memblock_free(struct pw_memblock *mem); -+ -+/** Unref a memblock */ -+static inline void pw_memblock_unref(struct pw_memblock *mem) -+{ -+ if (--mem->ref == 0) -+ pw_memblock_free(mem); -+} -+ -+/** Remove a memblock for given \a id */ -+int pw_mempool_remove_id(struct pw_mempool *pool, uint32_t id); -+ -+/** Find memblock for given \a ptr */ -+struct pw_memblock * pw_mempool_find_ptr(struct pw_mempool *pool, const void *ptr); -+ -+/** Find memblock for given \a id */ -+struct pw_memblock * pw_mempool_find_id(struct pw_mempool *pool, uint32_t id); -+ -+/** Find memblock for given \a fd */ -+struct pw_memblock * pw_mempool_find_fd(struct pw_mempool *pool, int fd); -+ -+ -+/** Map a region of a memory block */ -+struct pw_memmap * pw_memblock_map(struct pw_memblock *block, -+ enum pw_memmap_flags flags, uint32_t offset, uint32_t size, -+ uint32_t tag[5]); -+ -+/** Map a region of a memory block with \a id */ -+struct pw_memmap * pw_mempool_map_id(struct pw_mempool *pool, uint32_t id, -+ enum pw_memmap_flags flags, uint32_t offset, uint32_t size, -+ uint32_t tag[5]); -+ -+struct pw_memmap * pw_mempool_import_map(struct pw_mempool *pool, -+ struct pw_mempool *other, void *data, uint32_t size, uint32_t tag[5]); -+ -+/** find a map with the given tag */ -+struct pw_memmap * pw_mempool_find_tag(struct pw_mempool *pool, uint32_t tag[5], size_t size); -+ -+/** Unmap a region */ -+int pw_memmap_free(struct pw_memmap *map); -+ -+ -+/** parameters to map a memory range */ -+struct pw_map_range { -+ uint32_t start; /** offset in first page with start of data */ -+ uint32_t offset; /** page aligned offset to map */ -+ uint32_t size; /** size to map */ -+}; -+ -+#define PW_MAP_RANGE_INIT (struct pw_map_range){ 0, } -+ -+/** Calculate parameters to mmap() memory into \a range so that -+ * \a size bytes at \a offset can be mapped with mmap(). */ -+static inline void pw_map_range_init(struct pw_map_range *range, -+ uint32_t offset, uint32_t size, -+ uint32_t page_size) -+{ -+ range->offset = SPA_ROUND_DOWN_N(offset, page_size); -+ range->start = offset - range->offset; -+ range->size = SPA_ROUND_UP_N(range->start + size, page_size); -+} -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_MEM_H */ -diff --git a/third_party/pipewire/pipewire/module.h b/third_party/pipewire/pipewire/module.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/module.h -@@ -0,0 +1,106 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MODULE_H -+#define PIPEWIRE_MODULE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Module PW_TYPE_INFO_INTERFACE_BASE "Module" -+ -+#define PW_VERSION_MODULE 3 -+struct pw_module; -+ -+/** The module information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_module_info { -+ uint32_t id; /**< id of the global */ -+ const char *name; /**< name of the module */ -+ const char *filename; /**< filename of the module */ -+ const char *args; /**< arguments passed to the module */ -+#define PW_MODULE_CHANGE_MASK_PROPS (1 << 0) -+#define PW_MODULE_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+}; -+ -+/** Update and existing \ref pw_module_info with \a update \memberof pw_introspect */ -+struct pw_module_info * -+pw_module_info_update(struct pw_module_info *info, -+ const struct pw_module_info *update); -+ -+/** Free a \ref pw_module_info \memberof pw_introspect */ -+void pw_module_info_free(struct pw_module_info *info); -+ -+#define PW_MODULE_EVENT_INFO 0 -+#define PW_MODULE_EVENT_NUM 1 -+ -+/** Module events */ -+struct pw_module_events { -+#define PW_VERSION_MODULE_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify module info -+ * -+ * \param info info about the module -+ */ -+ void (*info) (void *object, const struct pw_module_info *info); -+}; -+ -+#define PW_MODULE_METHOD_ADD_LISTENER 0 -+#define PW_MODULE_METHOD_NUM 1 -+ -+/** Module methods */ -+struct pw_module_methods { -+#define PW_VERSION_MODULE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_module_events *events, -+ void *data); -+}; -+ -+#define pw_module_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_module_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_module_add_listener(c,...) pw_module_method(c,add_listener,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_MODULE_H */ -diff --git a/third_party/pipewire/pipewire/node.h b/third_party/pipewire/pipewire/node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/node.h -@@ -0,0 +1,200 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_NODE_H -+#define PIPEWIRE_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Node PW_TYPE_INFO_INTERFACE_BASE "Node" -+ -+#define PW_VERSION_NODE 3 -+struct pw_node; -+ -+/** \enum pw_node_state The different node states \memberof pw_node */ -+enum pw_node_state { -+ PW_NODE_STATE_ERROR = -1, /**< error state */ -+ PW_NODE_STATE_CREATING = 0, /**< the node is being created */ -+ PW_NODE_STATE_SUSPENDED = 1, /**< the node is suspended, the device might -+ * be closed */ -+ PW_NODE_STATE_IDLE = 2, /**< the node is running but there is no active -+ * port */ -+ PW_NODE_STATE_RUNNING = 3, /**< the node is running */ -+}; -+ -+/** Convert a \ref pw_node_state to a readable string \memberof pw_node */ -+const char * pw_node_state_as_string(enum pw_node_state state); -+ -+/** The node information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_node_info { -+ uint32_t id; /**< id of the global */ -+ uint32_t max_input_ports; /**< maximum number of inputs */ -+ uint32_t max_output_ports; /**< maximum number of outputs */ -+#define PW_NODE_CHANGE_MASK_INPUT_PORTS (1 << 0) -+#define PW_NODE_CHANGE_MASK_OUTPUT_PORTS (1 << 1) -+#define PW_NODE_CHANGE_MASK_STATE (1 << 2) -+#define PW_NODE_CHANGE_MASK_PROPS (1 << 3) -+#define PW_NODE_CHANGE_MASK_PARAMS (1 << 4) -+#define PW_NODE_CHANGE_MASK_ALL ((1 << 5)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ uint32_t n_input_ports; /**< number of inputs */ -+ uint32_t n_output_ports; /**< number of outputs */ -+ enum pw_node_state state; /**< the current state of the node */ -+ const char *error; /**< an error reason if \a state is error */ -+ struct spa_dict *props; /**< the properties of the node */ -+ struct spa_param_info *params; /**< parameters */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+struct pw_node_info * -+pw_node_info_update(struct pw_node_info *info, -+ const struct pw_node_info *update); -+ -+void -+pw_node_info_free(struct pw_node_info *info); -+ -+#define PW_NODE_EVENT_INFO 0 -+#define PW_NODE_EVENT_PARAM 1 -+#define PW_NODE_EVENT_NUM 2 -+ -+/** Node events */ -+struct pw_node_events { -+#define PW_VERSION_NODE_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify node info -+ * -+ * \param info info about the node -+ */ -+ void (*info) (void *object, const struct pw_node_info *info); -+ /** -+ * Notify a node param -+ * -+ * Event emitted as a result of the enum_params method. -+ * -+ * \param seq the sequence number of the request -+ * \param id the param id -+ * \param index the param index -+ * \param next the param index of the next param -+ * \param param the parameter -+ */ -+ void (*param) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ const struct spa_pod *param); -+}; -+ -+#define PW_NODE_METHOD_ADD_LISTENER 0 -+#define PW_NODE_METHOD_SUBSCRIBE_PARAMS 1 -+#define PW_NODE_METHOD_ENUM_PARAMS 2 -+#define PW_NODE_METHOD_SET_PARAM 3 -+#define PW_NODE_METHOD_SEND_COMMAND 4 -+#define PW_NODE_METHOD_NUM 5 -+ -+/** Node methods */ -+struct pw_node_methods { -+#define PW_VERSION_NODE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_node_events *events, -+ void *data); -+ /** -+ * Subscribe to parameter changes -+ * -+ * Automatically emit param events for the given ids when -+ * they are changed. -+ * -+ * \param ids an array of param ids -+ * \param n_ids the number of ids in \a ids -+ */ -+ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids); -+ -+ /** -+ * Enumerate node parameters -+ * -+ * Start enumeration of node parameters. For each param, a -+ * param event will be emitted. -+ * -+ * \param seq a sequence number to place in the reply -+ * \param id the parameter id to enum or PW_ID_ANY for all -+ * \param start the start index or 0 for the first param -+ * \param num the maximum number of params to retrieve -+ * \param filter a param filter or NULL -+ */ -+ int (*enum_params) (void *object, int seq, uint32_t id, -+ uint32_t start, uint32_t num, -+ const struct spa_pod *filter); -+ -+ /** -+ * Set a parameter on the node -+ * -+ * \param id the parameter id to set -+ * \param flags extra parameter flags -+ * \param param the parameter to set -+ */ -+ int (*set_param) (void *object, uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+ -+ /** -+ * Send a command to the node -+ * -+ * \param command the command to send -+ */ -+ int (*send_command) (void *object, const struct spa_command *command); -+}; -+ -+#define pw_node_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_node_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+/** Node */ -+#define pw_node_add_listener(c,...) pw_node_method(c,add_listener,0,__VA_ARGS__) -+#define pw_node_subscribe_params(c,...) pw_node_method(c,subscribe_params,0,__VA_ARGS__) -+#define pw_node_enum_params(c,...) pw_node_method(c,enum_params,0,__VA_ARGS__) -+#define pw_node_set_param(c,...) pw_node_method(c,set_param,0,__VA_ARGS__) -+#define pw_node_send_command(c,...) pw_node_method(c,send_command,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_NODE_H */ -diff --git a/third_party/pipewire/pipewire/permission.h b/third_party/pipewire/pipewire/permission.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/permission.h -@@ -0,0 +1,79 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PERMISSION_H -+#define PIPEWIRE_PERMISSION_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \class pw_permission -+ * -+ * \brief a PipeWire permission -+ * -+ * Permissions are kept for a client and describe what the client is -+ * allowed to do with an object. -+ * -+ * See \ref page_core_api -+ */ -+ -+#define PW_PERM_R 0400 /**< object can be seen and events can be received */ -+#define PW_PERM_W 0200 /**< methods can be called that modify the object */ -+#define PW_PERM_X 0100 /**< methods can be called on the object. The W flag must be -+ * present in order to call methods that modify the object. */ -+#define PW_PERM_M 0010 /**< metadata can be set on object, Since 0.3.9 */ -+ -+#define PW_PERM_RWX (PW_PERM_R|PW_PERM_W|PW_PERM_X) -+#define PW_PERM_RWXM (PW_PERM_RWX|PW_PERM_M) -+ -+#define PW_PERM_IS_R(p) (((p)&PW_PERM_R) == PW_PERM_R) -+#define PW_PERM_IS_W(p) (((p)&PW_PERM_W) == PW_PERM_W) -+#define PW_PERM_IS_X(p) (((p)&PW_PERM_X) == PW_PERM_X) -+#define PW_PERM_IS_M(p) (((p)&PW_PERM_M) == PW_PERM_M) -+ -+#define PW_PERM_ALL PW_PERM_RWXM -+#define PW_PERM_INVALID (uint32_t)(0xffffffff) -+ -+struct pw_permission { -+ uint32_t id; /**< id of object, PW_ID_ANY for default permission */ -+ uint32_t permissions; /**< bitmask of above permissions */ -+}; -+ -+#define PW_PERMISSION_INIT(id,p) (struct pw_permission){ (id), (p) } -+ -+#define PW_PERMISSION_FORMAT "%c%c%c%c" -+#define PW_PERMISSION_ARGS(permission) \ -+ (permission) & PW_PERM_R ? 'r' : '-', \ -+ (permission) & PW_PERM_W ? 'w' : '-', \ -+ (permission) & PW_PERM_X ? 'x' : '-', \ -+ (permission) & PW_PERM_M ? 'm' : '-' -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_PERMISSION_H */ -diff --git a/third_party/pipewire/pipewire/pipewire.h b/third_party/pipewire/pipewire/pipewire.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/pipewire.h -@@ -0,0 +1,158 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_H -+#define PIPEWIRE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** \mainpage -+ * -+ * \section sec_intro Introduction -+ * -+ * This document describes the API for the PipeWire multimedia framework. -+ * The API consists of two parts: -+ * -+ * \li The core API to access a PipeWire instance. -+ * (See \subpage page_core_api) -+ * \li The implementation API and tools to build new objects and -+ * modules (See \subpage page_implementation_api) -+ * -+ * \section sec_errors Error reporting -+ * -+ * Functions return either NULL with errno set or a negative int error -+ * code when an error occurs. Error codes are used from the SPA plugin -+ * library on which PipeWire is built. -+ * -+ * Some functions might return asynchronously. The error code for such -+ * functions is positive and SPA_RESULT_IS_ASYNC() will return true. -+ * SPA_RESULT_ASYNC_SEQ() can be used to get the unique sequence number -+ * associated with the async operation. -+ * -+ * The object returning the async result code will have some way to -+ * signal the completion of the async operation (with, for example, a -+ * callback). The sequence number can be used to see which operation -+ * completed. -+ * -+ * \section sec_logging Logging -+ * -+ * The 'PIPEWIRE_DEBUG' environment variable can be used to enable -+ * more debugging. The format is: -+ * -+ * <level>[:<category>,...] -+ * -+ * - <level>: specifies the log level: -+ * + `0`: no logging is enabled -+ * + `1`: Error logging is enabled -+ * + `2`: Warnings are enabled -+ * + `3`: Informational messages are enabled -+ * + `4`: Debug messages are enabled -+ * + `5`: Trace messages are enabled. These messages can be logged -+ * from the realtime threads. -+ * -+ * - <category>: Specifies a string category to enable. Many categories -+ * can be separated by commas. Current categories are: -+ * + `connection`: to log connection messages -+ */ -+ -+/** \class pw_pipewire -+ * -+ * \brief PipeWire initialization and infrastructure functions -+ */ -+void -+pw_init(int *argc, char **argv[]); -+ -+void pw_deinit(void); -+ -+bool -+pw_debug_is_category_enabled(const char *name); -+ -+const char * -+pw_get_application_name(void); -+ -+const char * -+pw_get_prgname(void); -+ -+const char * -+pw_get_user_name(void); -+ -+const char * -+pw_get_host_name(void); -+ -+const char * -+pw_get_client_name(void); -+ -+bool pw_in_valgrind(void); -+ -+enum pw_direction -+pw_direction_reverse(enum pw_direction direction); -+ -+uint32_t pw_get_support(struct spa_support *support, uint32_t max_support); -+ -+struct spa_handle *pw_load_spa_handle(const char *lib, -+ const char *factory_name, -+ const struct spa_dict *info, -+ uint32_t n_support, -+ const struct spa_support support[]); -+ -+int pw_unload_spa_handle(struct spa_handle *handle); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_H */ -diff --git a/third_party/pipewire/pipewire/port.h b/third_party/pipewire/pipewire/port.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/port.h -@@ -0,0 +1,169 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PORT_H -+#define PIPEWIRE_PORT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Port PW_TYPE_INFO_INTERFACE_BASE "Port" -+ -+#define PW_VERSION_PORT 3 -+struct pw_port; -+ -+/** \enum pw_direction The direction of a port \memberof pw_introspect */ -+#define pw_direction spa_direction -+#define PW_DIRECTION_INPUT SPA_DIRECTION_INPUT -+#define PW_DIRECTION_OUTPUT SPA_DIRECTION_OUTPUT -+ -+/** Convert a \ref pw_direction to a readable string \memberof pw_introspect */ -+const char * pw_direction_as_string(enum pw_direction direction); -+ -+ -+/** \class pw_introspect -+ * -+ * The introspection methods and structures are used to get information -+ * about the object in the PipeWire server -+ */ -+ -+struct pw_port_info { -+ uint32_t id; /**< id of the global */ -+ enum pw_direction direction; /**< port direction */ -+#define PW_PORT_CHANGE_MASK_PROPS (1 << 0) -+#define PW_PORT_CHANGE_MASK_PARAMS (1 << 1) -+#define PW_PORT_CHANGE_MASK_ALL ((1 << 2)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< the properties of the port */ -+ struct spa_param_info *params; /**< parameters */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+struct pw_port_info * -+pw_port_info_update(struct pw_port_info *info, -+ const struct pw_port_info *update); -+ -+void -+pw_port_info_free(struct pw_port_info *info); -+ -+#define PW_PORT_EVENT_INFO 0 -+#define PW_PORT_EVENT_PARAM 1 -+#define PW_PORT_EVENT_NUM 2 -+ -+/** Port events */ -+struct pw_port_events { -+#define PW_VERSION_PORT_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify port info -+ * -+ * \param info info about the port -+ */ -+ void (*info) (void *object, const struct pw_port_info *info); -+ /** -+ * Notify a port param -+ * -+ * Event emitted as a result of the enum_params method. -+ * -+ * \param seq the sequence number of the request -+ * \param id the param id -+ * \param index the param index -+ * \param next the param index of the next param -+ * \param param the parameter -+ */ -+ void (*param) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ const struct spa_pod *param); -+}; -+ -+#define PW_PORT_METHOD_ADD_LISTENER 0 -+#define PW_PORT_METHOD_SUBSCRIBE_PARAMS 1 -+#define PW_PORT_METHOD_ENUM_PARAMS 2 -+#define PW_PORT_METHOD_NUM 3 -+ -+/** Port methods */ -+struct pw_port_methods { -+#define PW_VERSION_PORT_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_port_events *events, -+ void *data); -+ /** -+ * Subscribe to parameter changes -+ * -+ * Automatically emit param events for the given ids when -+ * they are changed. -+ * -+ * \param ids an array of param ids -+ * \param n_ids the number of ids in \a ids -+ */ -+ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids); -+ -+ /** -+ * Enumerate port parameters -+ * -+ * Start enumeration of port parameters. For each param, a -+ * param event will be emitted. -+ * -+ * \param seq a sequence number returned in the reply -+ * \param id the parameter id to enumerate -+ * \param start the start index or 0 for the first param -+ * \param num the maximum number of params to retrieve -+ * \param filter a param filter or NULL -+ */ -+ int (*enum_params) (void *object, int seq, -+ uint32_t id, uint32_t start, uint32_t num, -+ const struct spa_pod *filter); -+}; -+ -+#define pw_port_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_port_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_port_add_listener(c,...) pw_port_method(c,add_listener,0,__VA_ARGS__) -+#define pw_port_subscribe_params(c,...) pw_port_method(c,subscribe_params,0,__VA_ARGS__) -+#define pw_port_enum_params(c,...) pw_port_method(c,enum_params,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_PORT_H */ -diff --git a/third_party/pipewire/pipewire/properties.h b/third_party/pipewire/pipewire/properties.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/properties.h -@@ -0,0 +1,121 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PROPERTIES_H -+#define PIPEWIRE_PROPERTIES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+/** \class pw_properties -+ * -+ * \brief A collection of key/value pairs -+ * -+ * Properties are used to pass around arbitrary key/value pairs. -+ * Both keys and values are strings which keeps things simple. -+ * Encoding of arbitrary values should be done by using a string -+ * serialization such as base64 for binary blobs. -+ */ -+struct pw_properties { -+ struct spa_dict dict; /**< dictionary of key/values */ -+ uint32_t flags; /**< extra flags */ -+}; -+ -+struct pw_properties * -+pw_properties_new(const char *key, ...) SPA_SENTINEL; -+ -+struct pw_properties * -+pw_properties_new_dict(const struct spa_dict *dict); -+ -+struct pw_properties * -+pw_properties_new_string(const char *args); -+ -+struct pw_properties * -+pw_properties_copy(const struct pw_properties *properties); -+ -+int pw_properties_update_keys(struct pw_properties *props, -+ const struct spa_dict *dict, const char *keys[]); -+ -+int pw_properties_update(struct pw_properties *oldprops, -+ const struct spa_dict *dict); -+ -+int pw_properties_add(struct pw_properties *oldprops, -+ const struct spa_dict *dict); -+int pw_properties_add_keys(struct pw_properties *oldprops, -+ const struct spa_dict *dict, const char *keys[]); -+ -+void pw_properties_clear(struct pw_properties *properties); -+ -+void -+pw_properties_free(struct pw_properties *properties); -+ -+int -+pw_properties_set(struct pw_properties *properties, const char *key, const char *value); -+ -+int -+pw_properties_setf(struct pw_properties *properties, -+ const char *key, const char *format, ...) SPA_PRINTF_FUNC(3, 4); -+int -+pw_properties_setva(struct pw_properties *properties, -+ const char *key, const char *format, va_list args) SPA_PRINTF_FUNC(3,0); -+const char * -+pw_properties_get(const struct pw_properties *properties, const char *key); -+ -+const char * -+pw_properties_iterate(const struct pw_properties *properties, void **state); -+ -+static inline bool pw_properties_parse_bool(const char *value) { -+ return (strcmp(value, "true") == 0 || atoi(value) == 1); -+} -+ -+static inline int pw_properties_parse_int(const char *value) { -+ return strtol(value, NULL, 0); -+} -+ -+static inline int64_t pw_properties_parse_int64(const char *value) { -+ return strtoll(value, NULL, 0); -+} -+ -+static inline uint64_t pw_properties_parse_uint64(const char *value) { -+ return strtoull(value, NULL, 0); -+} -+ -+static inline float pw_properties_parse_float(const char *value) { -+ return strtof(value, NULL); -+} -+ -+static inline double pw_properties_parse_double(const char *value) { -+ return strtod(value, NULL); -+} -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_PROPERTIES_H */ -diff --git a/third_party/pipewire/pipewire/protocol.h b/third_party/pipewire/pipewire/protocol.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/protocol.h -@@ -0,0 +1,152 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PROTOCOL_H -+#define PIPEWIRE_PROTOCOL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+struct pw_protocol; -+ -+#include -+#include -+#include -+ -+#define PW_TYPE_INFO_Protocol "PipeWire:Protocol" -+#define PW_TYPE_INFO_PROTOCOL_BASE PW_TYPE_INFO_Protocol ":" -+ -+struct pw_protocol_client { -+ struct spa_list link; /**< link in protocol client_list */ -+ struct pw_protocol *protocol; /**< the owner protocol */ -+ -+ struct pw_core *core; -+ -+ int (*connect) (struct pw_protocol_client *client, -+ const struct spa_dict *props, -+ void (*done_callback) (void *data, int result), -+ void *data); -+ int (*connect_fd) (struct pw_protocol_client *client, int fd, bool close); -+ int (*steal_fd) (struct pw_protocol_client *client); -+ void (*disconnect) (struct pw_protocol_client *client); -+ void (*destroy) (struct pw_protocol_client *client); -+ int (*set_paused) (struct pw_protocol_client *client, bool paused); -+}; -+ -+#define pw_protocol_client_connect(c,p,cb,d) ((c)->connect(c,p,cb,d)) -+#define pw_protocol_client_connect_fd(c,fd,cl) ((c)->connect_fd(c,fd,cl)) -+#define pw_protocol_client_steal_fd(c) ((c)->steal_fd(c)) -+#define pw_protocol_client_disconnect(c) ((c)->disconnect(c)) -+#define pw_protocol_client_destroy(c) ((c)->destroy(c)) -+#define pw_protocol_client_set_paused(c,p) ((c)->set_paused(c,p)) -+ -+struct pw_protocol_server { -+ struct spa_list link; /**< link in protocol server_list */ -+ struct pw_protocol *protocol; /**< the owner protocol */ -+ -+ struct pw_impl_core *core; -+ -+ struct spa_list client_list; /**< list of clients of this protocol */ -+ -+ void (*destroy) (struct pw_protocol_server *listen); -+}; -+ -+#define pw_protocol_server_destroy(l) ((l)->destroy(l)) -+ -+struct pw_protocol_marshal { -+ const char *type; /**< interface type */ -+ uint32_t version; /**< version */ -+#define PW_PROTOCOL_MARSHAL_FLAG_IMPL (1 << 0) /**< marshal for implementations */ -+ uint32_t flags; /**< version */ -+ uint32_t n_client_methods; /**< number of client methods */ -+ uint32_t n_server_methods; /**< number of server methods */ -+ const void *client_marshal; -+ const void *server_demarshal; -+ const void *server_marshal; -+ const void *client_demarshal; -+}; -+ -+struct pw_protocol_implementaton { -+#define PW_VERSION_PROTOCOL_IMPLEMENTATION 0 -+ uint32_t version; -+ -+ struct pw_protocol_client * (*new_client) (struct pw_protocol *protocol, -+ struct pw_core *core, -+ const struct spa_dict *props); -+ struct pw_protocol_server * (*add_server) (struct pw_protocol *protocol, -+ struct pw_impl_core *core, -+ const struct spa_dict *props); -+}; -+ -+struct pw_protocol_events { -+#define PW_VERSION_PROTOCOL_EVENTS 0 -+ uint32_t version; -+ -+ void (*destroy) (void *data); -+}; -+ -+#define pw_protocol_new_client(p,...) (pw_protocol_get_implementation(p)->new_client(p,__VA_ARGS__)) -+#define pw_protocol_add_server(p,...) (pw_protocol_get_implementation(p)->add_server(p,__VA_ARGS__)) -+#define pw_protocol_ext(p,type,method,...) (((type*)pw_protocol_get_extension(p))->method( __VA_ARGS__)) -+ -+struct pw_protocol *pw_protocol_new(struct pw_context *context, const char *name, size_t user_data_size); -+ -+void pw_protocol_destroy(struct pw_protocol *protocol); -+ -+struct pw_context *pw_protocol_get_context(struct pw_protocol *protocol); -+ -+void *pw_protocol_get_user_data(struct pw_protocol *protocol); -+ -+const struct pw_protocol_implementaton * -+pw_protocol_get_implementation(struct pw_protocol *protocol); -+ -+const void * -+pw_protocol_get_extension(struct pw_protocol *protocol); -+ -+ -+void pw_protocol_add_listener(struct pw_protocol *protocol, -+ struct spa_hook *listener, -+ const struct pw_protocol_events *events, -+ void *data); -+ -+/** \class pw_protocol -+ * -+ * \brief Manages protocols and their implementation -+ */ -+int pw_protocol_add_marshal(struct pw_protocol *protocol, -+ const struct pw_protocol_marshal *marshal); -+ -+const struct pw_protocol_marshal * -+pw_protocol_get_marshal(struct pw_protocol *protocol, const char *type, uint32_t version, uint32_t flags); -+ -+struct pw_protocol * pw_context_find_protocol(struct pw_context *context, const char *name); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_PROTOCOL_H */ -diff --git a/third_party/pipewire/pipewire/proxy.h b/third_party/pipewire/pipewire/proxy.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/proxy.h -@@ -0,0 +1,207 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PROXY_H -+#define PIPEWIRE_PROXY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_proxy Proxy -+ * -+ * \section sec_page_proxy_overview Overview -+ * -+ * The proxy object is a client side representation of a resource -+ * that lives on a remote PipeWire instance. -+ * -+ * It is used to communicate with the remote object. -+ * -+ * \section sec_page_proxy_core Core proxy -+ * -+ * A proxy for a remote core object can be obtained by making -+ * a remote connection with \ref pw_core_connect. -+ * See \ref pw_page_remote_api -+ * -+ * Some methods on proxy object allow creation of more proxy objects or -+ * create a binding between a local proxy and global resource. -+ * -+ * \section sec_page_proxy_create Create -+ * -+ * A client first creates a new proxy object with pw_proxy_new(). A -+ * type must be provided for this object. -+ * -+ * The protocol of the context will usually install an interface to -+ * translate method calls and events to the wire format. -+ * -+ * The creator of the proxy will usually also install an event -+ * implementation of the particular object type. -+ * -+ * \section sec_page_proxy_bind Bind -+ * -+ * To actually use the proxy object, one needs to create a server -+ * side resource for it. This can be done by, for example, binding -+ * to a global object or by calling a method that creates and binds -+ * to a new remote object. In all cases, the local id is passed to -+ * the server and is used to create a resource with the same id. -+ * -+ * \section sec_page_proxy_methods Methods -+ * -+ * To call a method on the proxy use the interface methods. Calling -+ * any interface method will result in a request to the server to -+ * perform the requested action on the corresponding resource. -+ * -+ * \section sec_page_proxy_events Events -+ * -+ * Events send from the server to the proxy will be demarshalled by -+ * the protocol and will then result in a call to the installed -+ * implementation of the proxy. -+ * -+ * \section sec_page_proxy_destroy Destroy -+ * -+ * Use pw_proxy_destroy() to destroy the client side object. This -+ * is usually done automatically when the server removes the resource -+ * associated to the proxy. -+ */ -+ -+/** \class pw_proxy -+ * -+ * \brief Represents an object on the client side. -+ * -+ * A pw_proxy acts as a client side proxy to an object existing in a remote -+ * pipewire instance. The proxy is responsible for converting interface functions -+ * invoked by the client to PipeWire messages. Events will call the handlers -+ * set in listener. -+ * -+ * See \ref page_proxy -+ */ -+struct pw_proxy; -+ -+#include -+ -+/** Proxy events, use \ref pw_proxy_add_listener */ -+struct pw_proxy_events { -+#define PW_VERSION_PROXY_EVENTS 0 -+ uint32_t version; -+ -+ /** The proxy is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** a proxy is bound to a global id */ -+ void (*bound) (void *data, uint32_t global_id); -+ -+ /** a proxy is removed from the server. Use pw_proxy_destroy to -+ * free the proxy. */ -+ void (*removed) (void *data); -+ -+ /** a reply to a sync method completed */ -+ void (*done) (void *data, int seq); -+ -+ /** an error occurred on the proxy */ -+ void (*error) (void *data, int seq, int res, const char *message); -+}; -+ -+/** Make a new proxy object. The id can be used to bind to a remote object and -+ * can be retrieved with \ref pw_proxy_get_id . */ -+struct pw_proxy * -+pw_proxy_new(struct pw_proxy *factory, /**< factory */ -+ const char *type, /**< interface type */ -+ uint32_t version, /**< interface version */ -+ size_t user_data_size /**< size of user data */); -+ -+/** Add an event listener to proxy */ -+void pw_proxy_add_listener(struct pw_proxy *proxy, -+ struct spa_hook *listener, -+ const struct pw_proxy_events *events, -+ void *data); -+ -+/** Add a listener for the events received from the remote object. The -+ * events depend on the type of the remote object type. */ -+void pw_proxy_add_object_listener(struct pw_proxy *proxy, /**< the proxy */ -+ struct spa_hook *listener, /**< listener */ -+ const void *funcs, /**< proxied functions */ -+ void *data /**< data passed to events */); -+ -+/** destroy a proxy */ -+void pw_proxy_destroy(struct pw_proxy *proxy); -+ -+/** Get the user_data. The size was given in \ref pw_proxy_new */ -+void *pw_proxy_get_user_data(struct pw_proxy *proxy); -+ -+/** Get the local id of the proxy */ -+uint32_t pw_proxy_get_id(struct pw_proxy *proxy); -+ -+/** Get the type and version of the proxy */ -+const char *pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version); -+ -+/** Get the protocol used for the proxy */ -+struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy); -+ -+/** Generate an sync method for a proxy. This will generate a done event -+ * with the same seq number of the reply. */ -+int pw_proxy_sync(struct pw_proxy *proxy, int seq); -+ -+/** Set the global id this proxy is bound to. This is usually used internally -+ * and will also emit the bound event */ -+int pw_proxy_set_bound_id(struct pw_proxy *proxy, uint32_t global_id); -+/** Get the global id bound to this proxy of SPA_ID_INVALID when not bound -+ * to a global */ -+uint32_t pw_proxy_get_bound_id(struct pw_proxy *proxy); -+ -+/** Generate an error for a proxy */ -+int pw_proxy_error(struct pw_proxy *proxy, int res, const char *error); -+int pw_proxy_errorf(struct pw_proxy *proxy, int res, const char *error, ...) SPA_PRINTF_FUNC(3, 4); -+ -+/** Get the listener of proxy */ -+struct spa_hook_list *pw_proxy_get_object_listeners(struct pw_proxy *proxy); -+ -+/** Get the marshal functions for the proxy */ -+const struct pw_protocol_marshal *pw_proxy_get_marshal(struct pw_proxy *proxy); -+ -+/** Install a marshal function on a proxy */ -+int pw_proxy_install_marshal(struct pw_proxy *proxy, bool implementor); -+ -+#define pw_proxy_notify(p,type,event,version,...) \ -+ spa_hook_list_call(pw_proxy_get_object_listeners(p), \ -+ type, event, version, ## __VA_ARGS__) -+ -+#define pw_proxy_call(p,type,method,version,...) \ -+ spa_interface_call((struct spa_interface*)p, \ -+ type, method, version, ##__VA_ARGS__) -+ -+#define pw_proxy_call_res(p,type,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)p, \ -+ type, _res, method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_PROXY_H */ -diff --git a/third_party/pipewire/pipewire/resource.h b/third_party/pipewire/pipewire/resource.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/resource.h -@@ -0,0 +1,168 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_RESOURCE_H -+#define PIPEWIRE_RESOURCE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_resource Resource -+ * -+ * \section sec_page_resource Overview -+ * -+ * Resources represent objects owned by a \ref pw_impl_client. They are -+ * the result of binding to a global resource or by calling API that -+ * creates client owned objects. -+ * -+ * The client usually has a proxy object associated with the resource -+ * that it can use to communicate with the resource. See \ref page_proxy. -+ * -+ * Resources are destroyed when the client or the bound object is -+ * destroyed. -+ * -+ */ -+ -+/** \class pw_resource -+ * -+ * \brief Client owned objects -+ * -+ * Resources are objects owned by a client and are destroyed when the -+ * client disappears. -+ * -+ * See also \ref page_resource -+ */ -+struct pw_resource; -+ -+#include -+ -+/** Resource events */ -+struct pw_resource_events { -+#define PW_VERSION_RESOURCE_EVENTS 0 -+ uint32_t version; -+ -+ /** The resource is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** a reply to a ping event completed */ -+ void (*pong) (void *data, int seq); -+ -+ /** an error occurred on the resource */ -+ void (*error) (void *data, int seq, int res, const char *message); -+}; -+ -+/** Make a new resource for client */ -+struct pw_resource * -+pw_resource_new(struct pw_impl_client *client, /**< the client owning the resource */ -+ uint32_t id, /**< the remote per client id */ -+ uint32_t permissions, /**< permissions on this resource */ -+ const char *type, /**< interface of the resource */ -+ uint32_t version, /**< requested interface version */ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Destroy a resource */ -+void pw_resource_destroy(struct pw_resource *resource); -+ -+/** Remove a resource, like pw_resource_destroy but without sending a -+ * remove_id message to the client */ -+void pw_resource_remove(struct pw_resource *resource); -+ -+/** Get the client owning this resource */ -+struct pw_impl_client *pw_resource_get_client(struct pw_resource *resource); -+ -+/** Get the unique id of this resource */ -+uint32_t pw_resource_get_id(struct pw_resource *resource); -+ -+/** Get the permissions of this resource */ -+uint32_t pw_resource_get_permissions(struct pw_resource *resource); -+ -+/** Get the type and optionally the version of this resource */ -+const char *pw_resource_get_type(struct pw_resource *resource, uint32_t *version); -+ -+/** Get the protocol used for this resource */ -+struct pw_protocol *pw_resource_get_protocol(struct pw_resource *resource); -+ -+/** Get the user data for the resource, the size was given in \ref pw_resource_new */ -+void *pw_resource_get_user_data(struct pw_resource *resource); -+ -+/** Add an event listener */ -+void pw_resource_add_listener(struct pw_resource *resource, -+ struct spa_hook *listener, -+ const struct pw_resource_events *events, -+ void *data); -+ -+/** Set the resource implementation. */ -+void pw_resource_add_object_listener(struct pw_resource *resource, -+ struct spa_hook *listener, -+ const void *funcs, -+ void *data); -+ -+/** Generate an ping event for a resource. This will generate a pong event -+ * with the same \a sequence number in the return value. */ -+int pw_resource_ping(struct pw_resource *resource, int seq); -+ -+/** Notify global id this resource is bound to */ -+int pw_resource_set_bound_id(struct pw_resource *resource, uint32_t global_id); -+ -+/** Get the global id this resource is bound to or SPA_ID_INVALID when not bound */ -+uint32_t pw_resource_get_bound_id(struct pw_resource *resource); -+ -+/** Generate an error for a resource */ -+void pw_resource_error(struct pw_resource *resource, int res, const char *error); -+void pw_resource_errorf(struct pw_resource *resource, int res, const char *error, ...) SPA_PRINTF_FUNC(3, 4); -+void pw_resource_errorf_id(struct pw_resource *resource, uint32_t id, int res, const char *error, ...) SPA_PRINTF_FUNC(4, 5); -+ -+/** Get the list of object listeners from a resource */ -+struct spa_hook_list *pw_resource_get_object_listeners(struct pw_resource *resource); -+ -+/** Get the marshal functions for the resource */ -+const struct pw_protocol_marshal *pw_resource_get_marshal(struct pw_resource *resource); -+ -+/** install a marshal function on a resource */ -+int pw_resource_install_marshal(struct pw_resource *resource, bool implementor); -+ -+#define pw_resource_notify(r,type,event,version,...) \ -+ spa_hook_list_call(pw_resource_get_object_listeners(r), \ -+ type, event, version, ## __VA_ARGS__) -+ -+#define pw_resource_call(r,type,method,version,...) \ -+ spa_interface_call((struct spa_interface*)r, \ -+ type, method, version, ##__VA_ARGS__) -+ -+#define pw_resource_call_res(r,type,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)r, \ -+ type, _res, method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_RESOURCE_H */ -diff --git a/third_party/pipewire/pipewire/stream.h b/third_party/pipewire/pipewire/stream.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/stream.h -@@ -0,0 +1,358 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_STREAM_H -+#define PIPEWIRE_STREAM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \page page_streams Media Streams -+ * -+ * \section sec_overview Overview -+ * -+ * Media streams are used to exchange data with the PipeWire server. A -+ * stream is a wrapper around a proxy for a \ref pw_client_node with -+ * an adapter. This means the stream will automatically do conversion -+ * to the type required by the server. -+ * -+ * Streams can be used to: -+ * -+ * \li Consume a stream from PipeWire. This is a PW_DIRECTION_INPUT stream. -+ * \li Produce a stream to PipeWire. This is a PW_DIRECTION_OUTPUT stream -+ * -+ * You can connect the stream port to a specific server port or let PipeWire -+ * choose a port for you. -+ * -+ * For more complicated nodes such as filters or ports with multiple -+ * inputs and/or outputs you will need to use the pw_filter or make -+ * a pw_node yourself and export it with \ref pw_core_export. -+ * -+ * \section sec_create Create -+ * -+ * Make a new stream with \ref pw_stream_new(). You will need to specify -+ * a name for the stream and extra properties. You can use \ref -+ * pw_fill_stream_properties() to get a basic set of properties for the -+ * stream. -+ * -+ * Once the stream is created, the state_changed event should be used to -+ * track the state of the stream. -+ * -+ * \section sec_connect Connect -+ * -+ * The stream is initially unconnected. To connect the stream, use -+ * \ref pw_stream_connect(). Pass the desired direction as an argument. -+ * -+ * \subsection ssec_stream_target Stream target -+ * -+ * To make the newly connected stream automatically connect to an existing -+ * PipeWire node, use the \ref PW_STREAM_FLAG_AUTOCONNECT and the port_path -+ * argument while connecting. -+ * -+ * \subsection ssec_stream_formats Stream formats -+ * -+ * An array of possible formats that this stream can consume or provide -+ * must be specified. -+ * -+ * \section sec_format Format negotiation -+ * -+ * After connecting the stream, the server will want to configure some -+ * parameters on the stream. You will be notified of these changes -+ * with the param_changed event. -+ * -+ * When a format param change is emitted, the client should now prepare -+ * itself to deal with the format and complete the negotiation procedure -+ * with a call to \ref pw_stream_update_params(). -+ * -+ * As arguments to \ref pw_stream_update_params() an array of spa_param -+ * structures must be given. They contain parameters such as buffer size, -+ * number of buffers, required metadata and other parameters for the -+ * media buffers. -+ * -+ * \section sec_buffers Buffer negotiation -+ * -+ * After completing the format negotiation, PipeWire will allocate and -+ * notify the stream of the buffers that will be used to exchange data -+ * between client and server. -+ * -+ * With the add_buffer event, a stream will be notified of a new buffer -+ * that can be used for data transport. You can attach user_data to these -+ * buffers. -+ * -+ * After the buffers are negotiated, the stream will transition to the -+ * \ref PW_STREAM_STATE_PAUSED state. -+ * -+ * \section sec_streaming Streaming -+ * -+ * From the \ref PW_STREAM_STATE_PAUSED state, the stream can be set to -+ * the \ref PW_STREAM_STATE_STREAMING state by the PipeWire server when -+ * data transport is started. -+ * -+ * Depending on how the stream was connected it will need to Produce or -+ * Consume data for/from PipeWire as explained in the following -+ * subsections. -+ * -+ * \subsection ssec_consume Consume data -+ * -+ * The process event is emitted for each new buffer that can can be -+ * consumed. -+ * -+ * \ref pw_stream_dequeue_buffer() should be used to get the data and -+ * metadata of the buffer. -+ * -+ * When the buffer is no longer in use, call \ref pw_stream_queue_buffer() -+ * to let PipeWire reuse the buffer. -+ * -+ * \subsection ssec_produce Produce data -+ * -+ * \ref pw_stream_dequeue_buffer() gives an empty buffer that can be filled. -+ * -+ * Filled buffers should be queued with \ref pw_stream_queue_buffer(). -+ * -+ * The process event is emitted when PipeWire has emptied a buffer that -+ * can now be refilled. -+ * -+ * \section sec_stream_disconnect Disconnect -+ * -+ * Use \ref pw_stream_disconnect() to disconnect a stream after use. -+ */ -+/** \class pw_stream -+ * -+ * \brief PipeWire stream object class -+ * -+ * The stream object provides a convenient way to send and -+ * receive data streams from/to PipeWire. -+ * -+ * See also \ref page_streams and \ref page_context_api -+ */ -+struct pw_stream; -+ -+#include -+#include -+ -+/** \enum pw_stream_state The state of a stream \memberof pw_stream */ -+enum pw_stream_state { -+ PW_STREAM_STATE_ERROR = -1, /**< the stream is in error */ -+ PW_STREAM_STATE_UNCONNECTED = 0, /**< unconnected */ -+ PW_STREAM_STATE_CONNECTING = 1, /**< connection is in progress */ -+ PW_STREAM_STATE_PAUSED = 2, /**< paused */ -+ PW_STREAM_STATE_STREAMING = 3 /**< streaming */ -+}; -+ -+struct pw_buffer { -+ struct spa_buffer *buffer; /**< the spa buffer */ -+ void *user_data; /**< user data attached to the buffer */ -+ uint64_t size; /**< This field is set by the user and the sum of -+ * all queued buffer is returned in the time info */ -+}; -+ -+struct pw_stream_control { -+ const char *name; /**< name of the control */ -+ uint32_t flags; /**< extra flags (unused) */ -+ float def; /**< default value */ -+ float min; /**< min value */ -+ float max; /**< max value */ -+ float *values; /**< array of values */ -+ uint32_t n_values; /**< number of values in array */ -+ uint32_t max_values; /**< max values that can be set on this control */ -+}; -+ -+/** A time structure \memberof pw_stream */ -+struct pw_time { -+ int64_t now; /**< the monotonic time */ -+ struct spa_fraction rate; /**< the rate of \a ticks and delay */ -+ uint64_t ticks; /**< the ticks at \a now. This is the current time that -+ * the remote end is reading/writing. */ -+ int64_t delay; /**< delay to device, add to ticks to get the time of the -+ * device. Positive for INPUT streams and -+ * negative for OUTPUT streams. */ -+ uint64_t queued; /**< data queued in the stream, this is the sum -+ * of the size fields in the pw_buffer that are -+ * currently queued */ -+}; -+ -+#include -+ -+/** Events for a stream. These events are always called from the mainloop -+ * unless explicitly documented otherwise. */ -+struct pw_stream_events { -+#define PW_VERSION_STREAM_EVENTS 0 -+ uint32_t version; -+ -+ void (*destroy) (void *data); -+ /** when the stream state changes */ -+ void (*state_changed) (void *data, enum pw_stream_state old, -+ enum pw_stream_state state, const char *error); -+ -+ /** Notify information about a control. */ -+ void (*control_info) (void *data, uint32_t id, const struct pw_stream_control *control); -+ -+ /** when io changed on the stream. */ -+ void (*io_changed) (void *data, uint32_t id, void *area, uint32_t size); -+ /** when a parameter changed */ -+ void (*param_changed) (void *data, uint32_t id, const struct spa_pod *param); -+ -+ /** when a new buffer was created for this stream */ -+ void (*add_buffer) (void *data, struct pw_buffer *buffer); -+ /** when a buffer was destroyed for this stream */ -+ void (*remove_buffer) (void *data, struct pw_buffer *buffer); -+ -+ /** when a buffer can be queued (for playback streams) or -+ * dequeued (for capture streams). This is normally called from the -+ * mainloop but can also be called directly from the realtime data -+ * thread if the user is prepared to deal with this. */ -+ void (*process) (void *data); -+ -+ /** The stream is drained */ -+ void (*drained) (void *data); -+ -+}; -+ -+/** Convert a stream state to a readable string \memberof pw_stream */ -+const char * pw_stream_state_as_string(enum pw_stream_state state); -+ -+/** \enum pw_stream_flags Extra flags that can be used in \ref pw_stream_connect() \memberof pw_stream */ -+enum pw_stream_flags { -+ PW_STREAM_FLAG_NONE = 0, /**< no flags */ -+ PW_STREAM_FLAG_AUTOCONNECT = (1 << 0), /**< try to automatically connect -+ * this stream */ -+ PW_STREAM_FLAG_INACTIVE = (1 << 1), /**< start the stream inactive, -+ * pw_stream_set_active() needs to be -+ * called explicitly */ -+ PW_STREAM_FLAG_MAP_BUFFERS = (1 << 2), /**< mmap the buffers */ -+ PW_STREAM_FLAG_DRIVER = (1 << 3), /**< be a driver */ -+ PW_STREAM_FLAG_RT_PROCESS = (1 << 4), /**< call process from the realtime -+ * thread. You MUST use RT safe functions -+ * in the process callback. */ -+ PW_STREAM_FLAG_NO_CONVERT = (1 << 5), /**< don't convert format */ -+ PW_STREAM_FLAG_EXCLUSIVE = (1 << 6), /**< require exclusive access to the -+ * device */ -+ PW_STREAM_FLAG_DONT_RECONNECT = (1 << 7), /**< don't try to reconnect this stream -+ * when the sink/source is removed */ -+ PW_STREAM_FLAG_ALLOC_BUFFERS = (1 << 8), /**< the application will allocate buffer -+ * memory. In the add_buffer event, the -+ * data of the buffer should be set */ -+}; -+ -+/** Create a new unconneced \ref pw_stream \memberof pw_stream -+ * \return a newly allocated \ref pw_stream */ -+struct pw_stream * -+pw_stream_new(struct pw_core *core, /**< a \ref pw_core */ -+ const char *name, /**< a stream media name */ -+ struct pw_properties *props /**< stream properties, ownership is taken */); -+ -+struct pw_stream * -+pw_stream_new_simple(struct pw_loop *loop, /**< a \ref pw_loop to use */ -+ const char *name, /**< a stream media name */ -+ struct pw_properties *props,/**< stream properties, ownership is taken */ -+ const struct pw_stream_events *events, /**< stream events */ -+ void *data /**< data passed to events */); -+ -+/** Destroy a stream \memberof pw_stream */ -+void pw_stream_destroy(struct pw_stream *stream); -+ -+void pw_stream_add_listener(struct pw_stream *stream, -+ struct spa_hook *listener, -+ const struct pw_stream_events *events, -+ void *data); -+ -+enum pw_stream_state pw_stream_get_state(struct pw_stream *stream, const char **error); -+ -+const char *pw_stream_get_name(struct pw_stream *stream); -+ -+struct pw_core *pw_stream_get_core(struct pw_stream *stream); -+ -+const struct pw_properties *pw_stream_get_properties(struct pw_stream *stream); -+ -+int pw_stream_update_properties(struct pw_stream *stream, const struct spa_dict *dict); -+ -+/** Connect a stream for input or output on \a port_path. \memberof pw_stream -+ * \return 0 on success < 0 on error. -+ * -+ * You should connect to the process event and use pw_stream_dequeue_buffer() -+ * to get the latest metadata and data. */ -+int -+pw_stream_connect(struct pw_stream *stream, /**< a \ref pw_stream */ -+ enum pw_direction direction, /**< the stream direction */ -+ uint32_t target_id, /**< the target object id to connect to or -+ * PW_ID_ANY to let the manager -+ * select a target. */ -+ enum pw_stream_flags flags, /**< stream flags */ -+ const struct spa_pod **params, /**< an array with params. The params -+ * should ideally contain supported -+ * formats. */ -+ uint32_t n_params /**< number of items in \a params */); -+ -+/** Get the node ID of the stream. \memberof pw_stream -+ * \return node ID. */ -+uint32_t -+pw_stream_get_node_id(struct pw_stream *stream); -+ -+/** Disconnect \a stream \memberof pw_stream */ -+int pw_stream_disconnect(struct pw_stream *stream); -+ -+/** Set the stream in error state */ -+int pw_stream_set_error(struct pw_stream *stream, /**< a \ref pw_stream */ -+ int res, /**< a result code */ -+ const char *error, ... /**< an error message */) SPA_PRINTF_FUNC(3, 4); -+ -+/** Complete the negotiation process with result code \a res \memberof pw_stream -+ * -+ * This function should be called after notification of the format. -+ -+ * When \a res indicates success, \a params contain the parameters for the -+ * allocation state. */ -+int -+pw_stream_update_params(struct pw_stream *stream, /**< a \ref pw_stream */ -+ const struct spa_pod **params, /**< an array of params. The params should -+ * ideally contain parameters for doing -+ * buffer allocation. */ -+ uint32_t n_params /**< number of elements in \a params */); -+ -+/** Set control values */ -+int pw_stream_set_control(struct pw_stream *stream, uint32_t id, uint32_t n_values, float *values, ...); -+ -+/** Query the time on the stream \memberof pw_stream */ -+int pw_stream_get_time(struct pw_stream *stream, struct pw_time *time); -+ -+/** Get a buffer that can be filled for playback streams or consumed -+ * for capture streams. */ -+struct pw_buffer *pw_stream_dequeue_buffer(struct pw_stream *stream); -+ -+/** Submit a buffer for playback or recycle a buffer for capture. */ -+int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer); -+ -+/** Activate or deactivate the stream \memberof pw_stream */ -+int pw_stream_set_active(struct pw_stream *stream, bool active); -+ -+/** Flush a stream. When \a drain is true, the drained callback will -+ * be called when all data is played or recorded */ -+int pw_stream_flush(struct pw_stream *stream, bool drain); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_STREAM_H */ -diff --git a/third_party/pipewire/pipewire/thread-loop.h b/third_party/pipewire/pipewire/thread-loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/thread-loop.h -@@ -0,0 +1,168 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_THREAD_LOOP_H -+#define PIPEWIRE_THREAD_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_thread_loop Threaded Loop -+ * -+ * \section sec_thread_loop_overview Overview -+ * -+ * The threaded loop implementation is a special wrapper around the -+ * regular \ref pw_loop implementation. -+ * -+ * The added feature in the threaded loop is that it spawns a new thread -+ * that runs the wrapped loop. This allows a synchronous application to use -+ * the asynchronous API without risking to stall the PipeWire library. -+ * -+ * \section sec_thread_loop_create Creation -+ * -+ * A \ref pw_thread_loop object is created using pw_thread_loop_new(). -+ * The \ref pw_loop to wrap must be given as an argument along with the name -+ * for the thread that will be spawned. -+ * -+ * After allocating the object, the thread must be started with -+ * pw_thread_loop_start() -+ * -+ * \section sec_thread_loop_destruction Destruction -+ * -+ * When the PipeWire connection has been terminated, the thread must be -+ * stopped and the resources freed. Stopping the thread is done using -+ * pw_thread_loop_stop(), which must be called without the lock (see -+ * below) held. When that function returns, the thread is stopped and the -+ * \ref pw_thread_loop object can be freed using pw_thread_loop_destroy(). -+ * -+ * \section sec_thread_loop_locking Locking -+ * -+ * Since the PipeWire API doesn't allow concurrent accesses to objects, -+ * a locking scheme must be used to guarantee safe usage. The threaded -+ * loop API provides such a scheme through the functions -+ * pw_thread_loop_lock() and pw_thread_loop_unlock(). -+ * -+ * The lock is recursive, so it's safe to use it multiple times from the same -+ * thread. Just make sure you call pw_thread_loop_unlock() the same -+ * number of times you called pw_thread_loop_lock(). -+ * -+ * The lock needs to be held whenever you call any PipeWire function that -+ * uses an object associated with this loop. Make sure you do not hold -+ * on to the lock more than necessary though, as the threaded loop stops -+ * while the lock is held. -+ * -+ * \section sec_thread_loop_events Events and Callbacks -+ * -+ * All events and callbacks are called with the thread lock held. -+ * -+ */ -+/** \class pw_thread_loop -+ * -+ * \brief PipeWire threaded loop object -+ * -+ * The threaded loop object runs a \ref pw_loop in a separate thread -+ * and ensures proper locking is done. -+ * -+ * All of the loop callbacks will be executed with the loop -+ * lock held. -+ * -+ * See also \ref page_thread_loop -+ */ -+struct pw_thread_loop; -+ -+/** Thread loop events */ -+struct pw_thread_loop_events { -+#define PW_VERSION_THREAD_LOOP_EVENTS 0 -+ uint32_t version; -+ -+ /** the loop is destroyed */ -+ void (*destroy) (void *data); -+}; -+ -+/** Make a new thread loop with the given name and optional properties. */ -+struct pw_thread_loop * -+pw_thread_loop_new(const char *name, const struct spa_dict *props); -+ -+/** Make a new thread loop with the given loop, name and optional properties. -+ * When \a loop is NULL, a new loop will be created. */ -+struct pw_thread_loop * -+pw_thread_loop_new_full(struct pw_loop *loop, const char *name, const struct spa_dict *props); -+ -+/** Destroy a thread loop */ -+void pw_thread_loop_destroy(struct pw_thread_loop *loop); -+ -+/** Add an event listener */ -+void pw_thread_loop_add_listener(struct pw_thread_loop *loop, -+ struct spa_hook *listener, -+ const struct pw_thread_loop_events *events, -+ void *data); -+ -+/** Get the loop implementation of the thread loop */ -+struct pw_loop * pw_thread_loop_get_loop(struct pw_thread_loop *loop); -+ -+/** Start the thread loop */ -+int pw_thread_loop_start(struct pw_thread_loop *loop); -+ -+/** Stop the thread loop */ -+void pw_thread_loop_stop(struct pw_thread_loop *loop); -+ -+/** Lock the loop. This ensures exclusive ownership of the loop */ -+void pw_thread_loop_lock(struct pw_thread_loop *loop); -+ -+/** Unlock the loop */ -+void pw_thread_loop_unlock(struct pw_thread_loop *loop); -+ -+/** Release the lock and wait until some thread calls \ref pw_thread_loop_signal */ -+void pw_thread_loop_wait(struct pw_thread_loop *loop); -+ -+/** Release the lock and wait a maximum of 'wait_max_sec' seconds -+ * until some thread calls \ref pw_thread_loop_signal or time out */ -+int pw_thread_loop_timed_wait(struct pw_thread_loop *loop, int wait_max_sec); -+ -+/** Get a struct timespec suitable for \ref pw_thread_loop_timed_wait_full. -+ * Since: 0.3.7 */ -+int pw_thread_loop_get_time(struct pw_thread_loop *loop, struct timespec *abstime, int64_t timeout); -+ -+/** Release the lock and wait up to \a abstime until some thread calls -+ * \ref pw_thread_loop_signal. Use \ref pw_thread_loop_get_time to make a timeout. -+ * Since: 0.3.7 */ -+int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, struct timespec *abstime); -+ -+/** Signal all threads waiting with \ref pw_thread_loop_wait */ -+void pw_thread_loop_signal(struct pw_thread_loop *loop, bool wait_for_accept); -+ -+/** Signal all threads executing \ref pw_thread_loop_signal with wait_for_accept */ -+void pw_thread_loop_accept(struct pw_thread_loop *loop); -+ -+/** Check if inside the thread */ -+bool pw_thread_loop_in_thread(struct pw_thread_loop *loop); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_THREAD_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/type.h b/third_party/pipewire/pipewire/type.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/type.h -@@ -0,0 +1,52 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_TYPE_H -+#define PIPEWIRE_TYPE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+enum { -+ PW_TYPE_FIRST = SPA_TYPE_VENDOR_PipeWire, -+}; -+ -+#define PW_TYPE_INFO_BASE "PipeWire:" -+ -+#define PW_TYPE_INFO_Object PW_TYPE_INFO_BASE "Object" -+#define PW_TYPE_INFO_OBJECT_BASE PW_TYPE_INFO_Object ":" -+ -+#define PW_TYPE_INFO_Interface PW_TYPE_INFO_BASE "Interface" -+#define PW_TYPE_INFO_INTERFACE_BASE PW_TYPE_INFO_Interface ":" -+ -+const struct spa_type_info * pw_type_info(void); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_TYPE_H */ -diff --git a/third_party/pipewire/pipewire/utils.h b/third_party/pipewire/pipewire/utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/utils.h -@@ -0,0 +1,59 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_UTILS_H -+#define PIPEWIRE_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class pw_utils -+ * -+ * Various utility functions -+ */ -+ -+/** a function to destroy an item \memberof pw_utils */ -+typedef void (*pw_destroy_t) (void *object); -+ -+const char * -+pw_split_walk(const char *str, const char *delimiter, size_t *len, const char **state); -+ -+char ** -+pw_split_strv(const char *str, const char *delimiter, int max_tokens, int *n_tokens); -+ -+void -+pw_free_strv(char **str); -+ -+char * -+pw_strip(char *str, const char *whitespace); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_UTILS_H */ -diff --git a/third_party/pipewire/pipewire/version.h b/third_party/pipewire/pipewire/version.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/version.h -@@ -0,0 +1,68 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_VERSION_H -+#define PIPEWIRE_VERSION_H -+ -+/* WARNING: Make sure to edit the real source file version.h.in! */ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** Return the version of the header files. Keep in mind that this is -+a macro and not a function, so it is impossible to get the pointer of -+it. */ -+#define pw_get_headers_version() ("0.3.13") -+ -+/** Return the version of the library the current application is -+ * linked to. */ -+const char* pw_get_library_version(void); -+ -+/** The current API version. Versions prior to 0.2.0 have -+ * PW_API_VERSION undefined. Please note that this is only ever -+ * increased on incompatible API changes! */ -+#define PW_API_VERSION "0.3" -+ -+/** The major version of PipeWire. \since 0.2.0 */ -+#define PW_MAJOR 0 -+ -+/** The minor version of PipeWire. \since 0.2.0 */ -+#define PW_MINOR 3 -+ -+/** The micro version of PipeWire. \since 0.2.0 */ -+#define PW_MICRO 13 -+ -+/** Evaluates to TRUE if the PipeWire library version is equal or -+ * newer than the specified. \since 0.2.0 */ -+#define PW_CHECK_VERSION(major,minor,micro) \ -+ ((PW_MAJOR > (major)) || \ -+ (PW_MAJOR == (major) && PW_MINOR > (minor)) || \ -+ (PW_MAJOR == (major) && PW_MINOR == (minor) && PW_MICRO >= (micro))) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_VERION_H */ -diff --git a/third_party/pipewire/pipewire/work-queue.h b/third_party/pipewire/pipewire/work-queue.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/work-queue.h -@@ -0,0 +1,63 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_WORK_QUEUE_H -+#define PIPEWIRE_WORK_QUEUE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_work_queue -+ * -+ * PipeWire work queue object -+ */ -+struct pw_work_queue; -+ -+#include -+ -+typedef void (*pw_work_func_t) (void *obj, void *data, int res, uint32_t id); -+ -+struct pw_work_queue * -+pw_work_queue_new(struct pw_loop *loop); -+ -+void -+pw_work_queue_destroy(struct pw_work_queue *queue); -+ -+uint32_t -+pw_work_queue_add(struct pw_work_queue *queue, -+ void *obj, int res, -+ pw_work_func_t func, void *data); -+ -+int -+pw_work_queue_cancel(struct pw_work_queue *queue, void *obj, uint32_t id); -+ -+int -+pw_work_queue_complete(struct pw_work_queue *queue, void *obj, uint32_t seq, int res); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_WORK_QUEUE_H */ -diff --git a/third_party/pipewire/spa/buffer/alloc.h b/third_party/pipewire/spa/buffer/alloc.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/alloc.h -@@ -0,0 +1,338 @@ -+/* Simple Plugin API -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+#ifndef SPA_BUFFER_ALLOC_H -+#define SPA_BUFFER_ALLOC_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** information about the buffer layout */ -+struct spa_buffer_alloc_info { -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_META (1<<0) /**< add metadata data in the skeleton */ -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK (1<<1) /**< add chunk data in the skeleton */ -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA (1<<2) /**< add buffer data to the skeleton */ -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL 0b111 -+#define SPA_BUFFER_ALLOC_FLAG_NO_DATA (1<<3) /**< don't set data pointers */ -+ uint32_t flags; -+ uint32_t max_align; /**< max of all alignments */ -+ uint32_t n_metas; -+ uint32_t n_datas; -+ struct spa_meta *metas; -+ struct spa_data *datas; -+ uint32_t *data_aligns; -+ size_t skel_size; /**< size of the struct spa_buffer and inlined meta/chunk/data */ -+ size_t meta_size; /**< size of the meta if not inlined */ -+ size_t chunk_size; /**< size of the chunk if not inlined */ -+ size_t data_size; /**< size of the data if not inlined */ -+ size_t mem_size; /**< size of the total memory if not inlined */ -+}; -+ -+/** -+ * Fill buffer allocation information -+ * -+ * Fill \a info with allocation information needed to allocate buffers -+ * with the given number of metadata and data members. -+ * -+ * The required size of the skeleton (the struct spa_buffer) information -+ * and the memory (for the metadata, chunk and buffer memory) will be -+ * calculated. -+ * -+ * The flags member in \a info should be configured before calling this -+ * functions. -+ * -+ * \param info the information to fill -+ * \param n_metas the number of metadatas for the buffer -+ * \param metas an array of metadata items -+ * \param n_datas the number of datas for the buffer -+ * \param datas an array of \a n_datas items -+ * \param data_aligns \a n_datas alignments -+ * \return 0 on success. -+ * */ -+static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info, -+ uint32_t n_metas, struct spa_meta metas[], -+ uint32_t n_datas, struct spa_data datas[], -+ uint32_t data_aligns[]) -+{ -+ size_t size, *target; -+ uint32_t i; -+ -+ info->n_metas = n_metas; -+ info->metas = metas; -+ info->n_datas = n_datas; -+ info->datas = datas; -+ info->data_aligns = data_aligns; -+ info->max_align = 16; -+ info->mem_size = 0; -+ /* -+ * The buffer skeleton is placed in memory like below and can -+ * be accessed as a regular structure. -+ * -+ * +==============================+ -+ * | struct spa_buffer | -+ * | uint32_t n_metas | number of metas -+ * | uint32_t n_datas | number of datas -+ * +-| struct spa_meta *metas | pointer to array of metas -+ * +|-| struct spa_data *datas | pointer to array of datas -+ * || +------------------------------+ -+ * |+>| struct spa_meta | -+ * | | uint32_t type | metadata -+ * | | uint32_t size | size of metadata -+ * +|--| void *data | pointer to metadata -+ * || | ... | more spa_meta follow -+ * || +------------------------------+ -+ * |+->| struct spa_data | -+ * | | uint32_t type | memory type -+ * | | uint32_t flags | -+ * | | int fd | fd of shared memory block -+ * | | uint32_t mapoffset | offset in shared memory of data -+ * | | uint32_t maxsize | size of data block -+ * | +-| void *data | pointer to data -+ * |+|-| struct spa_chunk *chunk | pointer to chunk -+ * ||| | ... | more spa_data follow -+ * ||| +==============================+ -+ * VVV -+ * -+ * metadata, chunk and memory can either be placed right -+ * after the skeleton (inlined) or in a separate piece of memory. -+ * -+ * vvv -+ * ||| +==============================+ -+ * +-->| meta data memory | metadata memory, 8 byte aligned -+ * || | ... | -+ * || +------------------------------+ -+ * +->| struct spa_chunk | memory for n_datas chunks -+ * | | uint32_t offset | -+ * | | uint32_t size | -+ * | | int32_t stride | -+ * | | int32_t dummy | -+ * | | ... chunks | -+ * | +------------------------------+ -+ * +>| data | memory for n_datas data, aligned -+ * | ... blocks | according to alignments -+ * +==============================+ -+ */ -+ info->skel_size = sizeof(struct spa_buffer); -+ info->skel_size += n_metas * sizeof(struct spa_meta); -+ info->skel_size += n_datas * sizeof(struct spa_data); -+ -+ for (i = 0, size = 0; i < n_metas; i++) -+ size += SPA_ROUND_UP_N(metas[i].size, 8); -+ info->meta_size = size; -+ -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META)) -+ target = &info->skel_size; -+ else -+ target = &info->mem_size; -+ *target += info->meta_size; -+ -+ info->chunk_size = n_datas * sizeof(struct spa_chunk); -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) -+ target = &info->skel_size; -+ else -+ target = &info->mem_size; -+ *target += info->chunk_size; -+ -+ for (i = 0, size = 0; i < n_datas; i++) { -+ info->max_align = SPA_MAX(info->max_align, data_aligns[i]); -+ size = SPA_ROUND_UP_N(size, data_aligns[i]); -+ size += datas[i].maxsize; -+ } -+ info->data_size = size; -+ -+ if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) && -+ SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA)) -+ target = &info->skel_size; -+ else -+ target = &info->mem_size; -+ -+ *target = SPA_ROUND_UP_N(*target, n_datas ? data_aligns[0] : 1); -+ *target += info->data_size; -+ *target = SPA_ROUND_UP_N(*target, info->max_align); -+ -+ return 0; -+} -+ -+/** -+ * Fill skeleton and data according to the allocation info -+ * -+ * Use the allocation info to create a \ref struct spa_buffer into -+ * \a skel_mem and \a data_mem. -+ * -+ * Depending on the flags given when calling \ref -+ * spa_buffer_alloc_fill_info(), the buffer meta, chunk and memory -+ * will be referenced in either skel_mem or data_mem. -+ * -+ * \param info an allocation info -+ * \param skel_mem memory to hold the \ref struct spa_buffer and the -+ * pointers to meta, chunk and memory. -+ * \param data_mem memory to hold the meta, chunk and memory -+ * \return a \ref struct spa_buffer in \a skel_mem -+ */ -+static inline struct spa_buffer * -+spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, -+ void *skel_mem, void *data_mem) -+{ -+ struct spa_buffer *b = (struct spa_buffer*)skel_mem; -+ size_t size; -+ uint32_t i; -+ void **dp, *skel, *data; -+ struct spa_chunk *cp; -+ -+ b->n_metas = info->n_metas; -+ b->metas = SPA_MEMBER(b, sizeof(struct spa_buffer), struct spa_meta); -+ b->n_datas = info->n_datas; -+ b->datas = SPA_MEMBER(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data); -+ -+ skel = SPA_MEMBER(b->datas, info->n_datas * sizeof(struct spa_data), void); -+ data = data_mem; -+ -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META)) -+ dp = &skel; -+ else -+ dp = &data; -+ -+ for (i = 0; i < info->n_metas; i++) { -+ struct spa_meta *m = &b->metas[i]; -+ *m = info->metas[i]; -+ m->data = *dp; -+ *dp = SPA_MEMBER(*dp, SPA_ROUND_UP_N(m->size, 8), void); -+ } -+ -+ size = info->n_datas * sizeof(struct spa_chunk); -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) { -+ cp = (struct spa_chunk*)skel; -+ skel = SPA_MEMBER(skel, size, void); -+ } -+ else { -+ cp = (struct spa_chunk*)data; -+ data = SPA_MEMBER(data, size, void); -+ } -+ -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA)) -+ dp = &skel; -+ else -+ dp = &data; -+ -+ for (i = 0; i < info->n_datas; i++) { -+ struct spa_data *d = &b->datas[i]; -+ -+ *d = info->datas[i]; -+ d->chunk = &cp[i]; -+ if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) { -+ *dp = SPA_PTR_ALIGN(*dp, info->data_aligns[i], void); -+ d->data = *dp; -+ *dp = SPA_MEMBER(*dp, d->maxsize, void); -+ } -+ } -+ return b; -+} -+ -+/** -+ * Layout an array of buffers -+ * -+ * Use the allocation info to layout the memory of an array of buffers. -+ * -+ * \a skel_mem should point to at least info->skel_size * \a n_buffers bytes -+ * of memory. -+ * \a data_mem should point to at least info->mem_size * \a n_buffers bytes -+ * of memory. -+ * -+ * \param info the allocation info for one buffer -+ * \param n_buffers the number of buffers to create -+ * \param buffer a array with space to hold \a n_buffers pointers to buffers -+ * \param skel_mem memory for the \ref struct spa_buffer -+ * \param data_mem memory for the meta, chunk, memory of the buffer if not -+ * inlined in the skeleton. -+ * \return 0 on success. -+ * -+ */ -+static inline int -+spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info, -+ uint32_t n_buffers, struct spa_buffer *buffers[], -+ void *skel_mem, void *data_mem) -+{ -+ uint32_t i; -+ for (i = 0; i < n_buffers; i++) { -+ buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem); -+ skel_mem = SPA_MEMBER(skel_mem, info->skel_size, void); -+ data_mem = SPA_MEMBER(data_mem, info->mem_size, void); -+ } -+ return 0; -+} -+ -+/** -+ * Allocate an array of buffers -+ * -+ * Allocate \a n_buffers with the given metadata, memory and alignment -+ * information. -+ * -+ * The buffer array, structures, data and metadata will all be allocated -+ * in one block of memory with the proper requested alignment. -+ * -+ * \param n_buffers the number of buffers to create -+ * \param flags extra flags -+ * \param n_metas number of metadatas -+ * \param metas \a n_metas metadata specification -+ * \param n_datas number of datas -+ * \param datas \a n_datas memory specification -+ * \param data_aligns \a n_datas alignment specifications -+ * \returns an array of \a n_buffers pointers to \ref struct spa_buffer -+ * with the given metadata, data and alignment or NULL when -+ * allocation failed. -+ * -+ */ -+static inline struct spa_buffer ** -+spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags, -+ uint32_t n_metas, struct spa_meta metas[], -+ uint32_t n_datas, struct spa_data datas[], -+ uint32_t data_aligns[]) -+{ -+ -+ struct spa_buffer **buffers; -+ struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL, }; -+ void *skel; -+ -+ spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns); -+ -+ buffers = (struct spa_buffer **)calloc(1, info.max_align + -+ n_buffers * (sizeof(struct spa_buffer *) + info.skel_size)); -+ if (buffers == NULL) -+ return NULL; -+ -+ skel = SPA_MEMBER(buffers, sizeof(struct spa_buffer *) * n_buffers, void); -+ skel = SPA_PTR_ALIGN(skel, info.max_align, void); -+ -+ spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL); -+ -+ return buffers; -+} -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_BUFFER_ALLOC_H */ -diff --git a/third_party/pipewire/spa/buffer/buffer.h b/third_party/pipewire/spa/buffer/buffer.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/buffer.h -@@ -0,0 +1,114 @@ -+/* Simple Plugin API -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_BUFFER_H -+#define SPA_BUFFER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \page page_buffer Buffers -+ * -+ * Buffers describe the data and metadata that is exchanged between -+ * ports of a node. -+ */ -+ -+enum spa_data_type { -+ SPA_DATA_Invalid, -+ SPA_DATA_MemPtr, /**< pointer to memory, the data field in -+ * struct spa_data is set. */ -+ SPA_DATA_MemFd, /**< generic fd, mmap to get to memory */ -+ SPA_DATA_DmaBuf, /**< fd to dmabuf memory */ -+ SPA_DATA_MemId, /**< memory is identified with an id */ -+ -+ SPA_DATA_LAST, /**< not part of ABI */ -+}; -+ -+/** Chunk of memory, can change for each buffer */ -+struct spa_chunk { -+ uint32_t offset; /**< offset of valid data. Should be taken -+ * modulo the data maxsize to get the offset -+ * in the data memory. */ -+ uint32_t size; /**< size of valid data. Should be clamped to -+ * maxsize. */ -+ int32_t stride; /**< stride of valid data */ -+#define SPA_CHUNK_FLAG_NONE 0 -+#define SPA_CHUNK_FLAG_CORRUPTED (1u<<0) /**< chunk data is corrupted in some way */ -+ int32_t flags; /**< chunk flags */ -+}; -+ -+/** Data for a buffer this stays constant for a buffer */ -+struct spa_data { -+ uint32_t type; /**< memory type, one of enum spa_data_type, when -+ * allocating memory, the type contains a bitmask -+ * of allowed types */ -+#define SPA_DATA_FLAG_NONE 0 -+#define SPA_DATA_FLAG_READABLE (1u<<0) /**< data is readable */ -+#define SPA_DATA_FLAG_WRITABLE (1u<<1) /**< data is writable */ -+#define SPA_DATA_FLAG_DYNAMIC (1u<<2) /**< data pointer can be changed */ -+#define SPA_DATA_FLAG_READWRITE (SPA_DATA_FLAG_READABLE|SPA_DATA_FLAG_WRITABLE) -+ uint32_t flags; /**< data flags */ -+ int64_t fd; /**< optional fd for data */ -+ uint32_t mapoffset; /**< offset to map fd at */ -+ uint32_t maxsize; /**< max size of data */ -+ void *data; /**< optional data pointer */ -+ struct spa_chunk *chunk; /**< valid chunk of memory */ -+}; -+ -+/** A Buffer */ -+struct spa_buffer { -+ uint32_t n_metas; /**< number of metadata */ -+ uint32_t n_datas; /**< number of data members */ -+ struct spa_meta *metas; /**< array of metadata */ -+ struct spa_data *datas; /**< array of data members */ -+}; -+ -+/** Find metadata in a buffer */ -+static inline struct spa_meta *spa_buffer_find_meta(const struct spa_buffer *b, uint32_t type) -+{ -+ uint32_t i; -+ -+ for (i = 0; i < b->n_metas; i++) -+ if (b->metas[i].type == type) -+ return &b->metas[i]; -+ -+ return NULL; -+} -+ -+static inline void *spa_buffer_find_meta_data(const struct spa_buffer *b, uint32_t type, size_t size) -+{ -+ struct spa_meta *m; -+ if ((m = spa_buffer_find_meta(b, type)) && m->size >= size) -+ return m->data; -+ return NULL; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_BUFFER_H */ -diff --git a/third_party/pipewire/spa/buffer/meta.h b/third_party/pipewire/spa/buffer/meta.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/meta.h -@@ -0,0 +1,151 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_META_H -+#define SPA_META_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \page page_meta Metadata -+ * -+ * Metadata contains extra information on a buffer. -+ */ -+enum spa_meta_type { -+ SPA_META_Invalid, -+ SPA_META_Header, /**< struct spa_meta_header */ -+ SPA_META_VideoCrop, /**< struct spa_meta_region with cropping data */ -+ SPA_META_VideoDamage, /**< array of struct spa_meta_region with damage */ -+ SPA_META_Bitmap, /**< struct spa_meta_bitmap */ -+ SPA_META_Cursor, /**< struct spa_meta_cursor */ -+ SPA_META_Control, /**< metadata contains a spa_meta_control -+ * associated with the data */ -+ -+ SPA_META_LAST, /**< not part of ABI/API */ -+}; -+ -+/** -+ * A metadata element. -+ * -+ * This structure is available on the buffer structure and contains -+ * the type of the metadata and a pointer/size to the actual metadata -+ * itself. -+ */ -+struct spa_meta { -+ uint32_t type; /**< metadata type, one of enum spa_meta_type */ -+ uint32_t size; /**< size of metadata */ -+ void *data; /**< pointer to metadata */ -+}; -+ -+#define spa_meta_first(m) ((m)->data) -+#define spa_meta_end(m) SPA_MEMBER((m)->data,(m)->size,void) -+#define spa_meta_check(p,m) (SPA_MEMBER(p,sizeof(*p),void) <= spa_meta_end(m)) -+ -+/** -+ * Describes essential buffer header metadata such as flags and -+ * timestamps. -+ */ -+struct spa_meta_header { -+#define SPA_META_HEADER_FLAG_DISCONT (1 << 0) /**< data is not continuous with previous buffer */ -+#define SPA_META_HEADER_FLAG_CORRUPTED (1 << 1) /**< data might be corrupted */ -+#define SPA_META_HEADER_FLAG_MARKER (1 << 2) /**< media specific marker */ -+#define SPA_META_HEADER_FLAG_HEADER (1 << 3) /**< data contains a codec specific header */ -+#define SPA_META_HEADER_FLAG_GAP (1 << 4) /**< data contains media neutral data */ -+#define SPA_META_HEADER_FLAG_DELTA_UNIT (1 << 5) /**< cannot be decoded independently */ -+ uint32_t flags; /**< flags */ -+ uint32_t offset; /**< offset in current cycle */ -+ int64_t pts; /**< presentation timestamp */ -+ int64_t dts_offset; /**< decoding timestamp as a difference with pts */ -+ uint64_t seq; /**< sequence number, increments with a -+ * media specific frequency */ -+}; -+ -+/** metadata structure for Region or an array of these for RegionArray */ -+struct spa_meta_region { -+ struct spa_region region; -+}; -+ -+#define spa_meta_region_is_valid(m) ((m)->region.size.width != 0 && (m)->region.size.height != 0) -+ -+/** iterate all the items in a metadata */ -+#define spa_meta_for_each(pos,meta) \ -+ for (pos = (__typeof(pos))spa_meta_first(meta); \ -+ spa_meta_check(pos, meta); \ -+ (pos)++) -+ -+#define spa_meta_bitmap_is_valid(m) ((m)->format != 0) -+ -+/** -+ * Bitmap information -+ * -+ * This metadata contains a bitmap image in the given format and size. -+ * It is typically used for cursor images or other small images that are -+ * better transferred inline. -+ */ -+struct spa_meta_bitmap { -+ uint32_t format; /**< bitmap video format, one of enum spa_video_format. 0 is -+ * and invalid format and should be handled as if there is -+ * no new bitmap information. */ -+ struct spa_rectangle size; /**< width and height of bitmap */ -+ int32_t stride; /**< stride of bitmap data */ -+ uint32_t offset; /**< offset of bitmap data in this structure. An offset of -+ * 0 means no image data (invisible), an offset >= -+ * sizeof(struct spa_meta_bitmap) contains valid bitmap -+ * info. */ -+}; -+ -+#define spa_meta_cursor_is_valid(m) ((m)->id != 0) -+ -+/** -+ * Cursor information -+ * -+ * Metadata to describe the position and appearance of a pointing device. -+ */ -+struct spa_meta_cursor { -+ uint32_t id; /**< cursor id. an id of 0 is an invalid id and means that -+ * there is no new cursor data */ -+ uint32_t flags; /**< extra flags */ -+ struct spa_point position; /**< position on screen */ -+ struct spa_point hotspot; /**< offsets for hotspot in bitmap, this field has no meaning -+ * when there is no valid bitmap (see below) */ -+ uint32_t bitmap_offset; /**< offset of bitmap meta in this structure. When the offset -+ * is 0, there is no new bitmap information. When the offset is -+ * >= sizeof(struct spa_meta_cursor) there is a -+ * struct spa_meta_bitmap at the offset. */ -+}; -+ -+/** a timed set of events associated with the buffer */ -+struct spa_meta_control { -+ struct spa_pod_sequence sequence; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_META_H */ -diff --git a/third_party/pipewire/spa/buffer/type-info.h b/third_party/pipewire/spa/buffer/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/type-info.h -@@ -0,0 +1,83 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_BUFFER_TYPES_H -+#define SPA_BUFFER_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+#define SPA_TYPE_INFO_Buffer SPA_TYPE_INFO_POINTER_BASE "Buffer" -+#define SPA_TYPE_INFO_BUFFER_BASE SPA_TYPE_INFO_Buffer ":" -+ -+/** Buffers contain data of a certain type */ -+#define SPA_TYPE_INFO_Data SPA_TYPE_INFO_ENUM_BASE "Data" -+#define SPA_TYPE_INFO_DATA_BASE SPA_TYPE_INFO_Data ":" -+ -+/** base type for fd based memory */ -+#define SPA_TYPE_INFO_DATA_Fd SPA_TYPE_INFO_DATA_BASE "Fd" -+#define SPA_TYPE_INFO_DATA_FD_BASE SPA_TYPE_INFO_DATA_Fd ":" -+ -+static const struct spa_type_info spa_type_data_type[] = { -+ { SPA_DATA_Invalid, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "Invalid", NULL }, -+ { SPA_DATA_MemPtr, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "MemPtr", NULL }, -+ { SPA_DATA_MemFd, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_FD_BASE "MemFd", NULL }, -+ { SPA_DATA_DmaBuf, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_FD_BASE "DmaBuf", NULL }, -+ { SPA_DATA_MemId, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "MemId", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_Meta SPA_TYPE_INFO_POINTER_BASE "Meta" -+#define SPA_TYPE_INFO_META_BASE SPA_TYPE_INFO_Meta ":" -+ -+#define SPA_TYPE_INFO_META_Array SPA_TYPE_INFO_META_BASE "Array" -+#define SPA_TYPE_INFO_META_ARRAY_BASE SPA_TYPE_INFO_META_Array ":" -+ -+#define SPA_TYPE_INFO_META_Region SPA_TYPE_INFO_META_BASE "Region" -+#define SPA_TYPE_INFO_META_REGION_BASE SPA_TYPE_INFO_META_Region ":" -+ -+#define SPA_TYPE_INFO_META_ARRAY_Region SPA_TYPE_INFO_META_ARRAY_BASE "Region" -+#define SPA_TYPE_INFO_META_ARRAY_REGION_BASE SPA_TYPE_INFO_META_ARRAY_Region ":" -+ -+static const struct spa_type_info spa_type_meta_type[] = { -+ { SPA_META_Invalid, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Invalid", NULL }, -+ { SPA_META_Header, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Header", NULL }, -+ { SPA_META_VideoCrop, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_REGION_BASE "VideoCrop", NULL }, -+ { SPA_META_VideoDamage, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_ARRAY_REGION_BASE "VideoDamage", NULL }, -+ { SPA_META_Bitmap, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Bitmap", NULL }, -+ { SPA_META_Cursor, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Cursor", NULL }, -+ { SPA_META_Control, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Control", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_BUFFER_TYPES_H */ -diff --git a/third_party/pipewire/spa/control/control.h b/third_party/pipewire/spa/control/control.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/control/control.h -@@ -0,0 +1,53 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_CONTROL_H -+#define SPA_CONTROL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** Controls -+ * -+ */ -+ -+/** Different Control types */ -+enum spa_control_type { -+ SPA_CONTROL_Invalid, -+ SPA_CONTROL_Properties, /**< data contains a SPA_TYPE_OBJECT_Props */ -+ SPA_CONTROL_Midi, /**< data contains a spa_pod_bytes with raw midi data */ -+ SPA_CONTROL_OSC, /**< data contains a spa_pod_bytes with an OSC packet */ -+ -+ SPA_CONTROL_LAST, /**< not part of ABI */ -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_CONTROL_H */ -diff --git a/third_party/pipewire/spa/control/type-info.h b/third_party/pipewire/spa/control/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/control/type-info.h -@@ -0,0 +1,52 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_CONTROL_TYPES_H -+#define SPA_CONTROL_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_Control SPA_TYPE_INFO_ENUM_BASE "Control" -+#define SPA_TYPE_INFO_CONTROL_BASE SPA_TYPE_INFO_Control ":" -+ -+static const struct spa_type_info spa_type_control[] = { -+ { SPA_CONTROL_Invalid, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Invalid", NULL }, -+ { SPA_CONTROL_Properties, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Properties", NULL }, -+ { SPA_CONTROL_Midi, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Midi", NULL }, -+ { SPA_CONTROL_OSC, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "OSC", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_CONTROL_TYPES_H */ -diff --git a/third_party/pipewire/spa/debug/buffer.h b/third_party/pipewire/spa/debug/buffer.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/buffer.h -@@ -0,0 +1,119 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_BUFFER_H -+#define SPA_DEBUG_BUFFER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_buffer(int indent, const struct spa_buffer *buffer) -+{ -+ uint32_t i; -+ -+ spa_debug("%*s" "struct spa_buffer %p:", indent, "", buffer); -+ spa_debug("%*s" " n_metas: %u (at %p)", indent, "", buffer->n_metas, buffer->metas); -+ for (i = 0; i < buffer->n_metas; i++) { -+ struct spa_meta *m = &buffer->metas[i]; -+ const char *type_name; -+ -+ type_name = spa_debug_type_find_name(spa_type_meta_type, m->type); -+ spa_debug("%*s" " meta %d: type %d (%s), data %p, size %d:", indent, "", i, m->type, -+ type_name, m->data, m->size); -+ -+ switch (m->type) { -+ case SPA_META_Header: -+ { -+ struct spa_meta_header *h = (struct spa_meta_header*)m->data; -+ spa_debug("%*s" " struct spa_meta_header:", indent, ""); -+ spa_debug("%*s" " flags: %08x", indent, "", h->flags); -+ spa_debug("%*s" " offset: %u", indent, "", h->offset); -+ spa_debug("%*s" " seq: %" PRIu64, indent, "", h->seq); -+ spa_debug("%*s" " pts: %" PRIi64, indent, "", h->pts); -+ spa_debug("%*s" " dts_offset: %" PRIi64, indent, "", h->dts_offset); -+ break; -+ } -+ case SPA_META_VideoCrop: -+ { -+ struct spa_meta_region *h = (struct spa_meta_region*)m->data; -+ spa_debug("%*s" " struct spa_meta_region:", indent, ""); -+ spa_debug("%*s" " x: %d", indent, "", h->region.position.x); -+ spa_debug("%*s" " y: %d", indent, "", h->region.position.y); -+ spa_debug("%*s" " width: %d", indent, "", h->region.size.width); -+ spa_debug("%*s" " height: %d", indent, "", h->region.size.height); -+ break; -+ } -+ case SPA_META_VideoDamage: -+ { -+ struct spa_meta_region *h; -+ spa_meta_for_each(h, m) { -+ spa_debug("%*s" " struct spa_meta_region:", indent, ""); -+ spa_debug("%*s" " x: %d", indent, "", h->region.position.x); -+ spa_debug("%*s" " y: %d", indent, "", h->region.position.y); -+ spa_debug("%*s" " width: %d", indent, "", h->region.size.width); -+ spa_debug("%*s" " height: %d", indent, "", h->region.size.height); -+ } -+ break; -+ } -+ case SPA_META_Bitmap: -+ break; -+ case SPA_META_Cursor: -+ break; -+ default: -+ spa_debug("%*s" " Unknown:", indent, ""); -+ spa_debug_mem(5, m->data, m->size); -+ } -+ } -+ spa_debug("%*s" " n_datas: \t%u (at %p)", indent, "", buffer->n_datas, buffer->datas); -+ for (i = 0; i < buffer->n_datas; i++) { -+ struct spa_data *d = &buffer->datas[i]; -+ spa_debug("%*s" " type: %d (%s)", indent, "", d->type, -+ spa_debug_type_find_name(spa_type_data_type, d->type)); -+ spa_debug("%*s" " flags: %d", indent, "", d->flags); -+ spa_debug("%*s" " data: %p", indent, "", d->data); -+ spa_debug("%*s" " fd: %" PRIi64, indent, "", d->fd); -+ spa_debug("%*s" " offset: %d", indent, "", d->mapoffset); -+ spa_debug("%*s" " maxsize: %u", indent, "", d->maxsize); -+ spa_debug("%*s" " chunk: %p", indent, "", d->chunk); -+ spa_debug("%*s" " offset: %d", indent, "", d->chunk->offset); -+ spa_debug("%*s" " size: %u", indent, "", d->chunk->size); -+ spa_debug("%*s" " stride: %d", indent, "", d->chunk->stride); -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_BUFFER_H */ -diff --git a/third_party/pipewire/spa/debug/dict.h b/third_party/pipewire/spa/debug/dict.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/dict.h -@@ -0,0 +1,52 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_DICT_H -+#define SPA_DEBUG_DICT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_dict(int indent, const struct spa_dict *dict) -+{ -+ const struct spa_dict_item *item; -+ spa_debug("%*sflags:%08x n_items:%d", indent, "", dict->flags, dict->n_items); -+ spa_dict_for_each(item, dict) { -+ spa_debug("%*s %s = \"%s\"", indent, "", item->key, item->value); -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_DICT_H */ -diff --git a/third_party/pipewire/spa/debug/format.h b/third_party/pipewire/spa/debug/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/format.h -@@ -0,0 +1,201 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_FORMAT_H -+#define SPA_DEBUG_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+static inline int -+spa_debug_format_value(const struct spa_type_info *info, -+ uint32_t type, void *body, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_Bool: -+ fprintf(stderr, "%s", *(int32_t *) body ? "true" : "false"); -+ break; -+ case SPA_TYPE_Id: -+ { -+ const char *str = spa_debug_type_find_short_name(info, *(int32_t *) body); -+ char tmp[64]; -+ if (str == NULL) { -+ snprintf(tmp, sizeof(tmp), "%d", *(int32_t*)body); -+ str = tmp; -+ } -+ fprintf(stderr, "%s", str); -+ break; -+ } -+ case SPA_TYPE_Int: -+ fprintf(stderr, "%d", *(int32_t *) body); -+ break; -+ case SPA_TYPE_Long: -+ fprintf(stderr, "%" PRIi64, *(int64_t *) body); -+ break; -+ case SPA_TYPE_Float: -+ fprintf(stderr, "%f", *(float *) body); -+ break; -+ case SPA_TYPE_Double: -+ fprintf(stderr, "%g", *(double *) body); -+ break; -+ case SPA_TYPE_String: -+ fprintf(stderr, "%s", (char *) body); -+ break; -+ case SPA_TYPE_Rectangle: -+ { -+ struct spa_rectangle *r = (struct spa_rectangle *)body; -+ fprintf(stderr, "%" PRIu32 "x%" PRIu32, r->width, r->height); -+ break; -+ } -+ case SPA_TYPE_Fraction: -+ { -+ struct spa_fraction *f = (struct spa_fraction *)body; -+ fprintf(stderr, "%" PRIu32 "/%" PRIu32, f->num, f->denom); -+ break; -+ } -+ case SPA_TYPE_Bitmap: -+ fprintf(stderr, "Bitmap"); -+ break; -+ case SPA_TYPE_Bytes: -+ fprintf(stderr, "Bytes"); -+ break; -+ case SPA_TYPE_Array: -+ { -+ void *p; -+ struct spa_pod_array_body *b = (struct spa_pod_array_body *)body; -+ int i = 0; -+ fprintf(stderr, "< "); -+ SPA_POD_ARRAY_BODY_FOREACH(b, size, p) { -+ if (i++ > 0) -+ fprintf(stderr, ", "); -+ spa_debug_format_value(info, b->child.type, p, b->child.size); -+ } -+ fprintf(stderr, " >"); -+ break; -+ } -+ default: -+ fprintf(stderr, "INVALID type %d", type); -+ break; -+ } -+ return 0; -+} -+ -+static inline int spa_debug_format(int indent, -+ const struct spa_type_info *info, const struct spa_pod *format) -+{ -+ const char *media_type; -+ const char *media_subtype; -+ struct spa_pod_prop *prop; -+ uint32_t mtype, mstype; -+ -+ if (info == NULL) -+ info = spa_type_format; -+ -+ if (format == NULL || SPA_POD_TYPE(format) != SPA_TYPE_Object) -+ return -EINVAL; -+ -+ if (spa_format_parse(format, &mtype, &mstype) < 0) -+ return -EINVAL; -+ -+ media_type = spa_debug_type_find_name(spa_type_media_type, mtype); -+ media_subtype = spa_debug_type_find_name(spa_type_media_subtype, mstype); -+ -+ fprintf(stderr, "%*s %s/%s\n", indent, "", -+ media_type ? spa_debug_type_short_name(media_type) : "unknown", -+ media_subtype ? spa_debug_type_short_name(media_subtype) : "unknown"); -+ -+ SPA_POD_OBJECT_FOREACH((struct spa_pod_object*)format, prop) { -+ const char *key; -+ const struct spa_type_info *ti; -+ uint32_t i, type, size, n_vals, choice; -+ const struct spa_pod *val; -+ void *vals; -+ -+ if (prop->key == SPA_FORMAT_mediaType || -+ prop->key == SPA_FORMAT_mediaSubtype) -+ continue; -+ -+ val = spa_pod_get_values(&prop->value, &n_vals, &choice); -+ -+ type = val->type; -+ size = val->size; -+ vals = SPA_POD_BODY(val); -+ -+ if (type < SPA_TYPE_None || type >= SPA_TYPE_LAST) -+ continue; -+ -+ ti = spa_debug_type_find(info, prop->key); -+ key = ti ? ti->name : NULL; -+ -+ fprintf(stderr, "%*s %16s : (%s) ", indent, "", -+ key ? spa_debug_type_short_name(key) : "unknown", -+ spa_debug_type_short_name(spa_types[type].name)); -+ -+ if (choice == SPA_CHOICE_None) { -+ spa_debug_format_value(ti ? ti->values : NULL, type, vals, size); -+ } else { -+ const char *ssep, *esep, *sep; -+ -+ switch (choice) { -+ case SPA_CHOICE_Range: -+ case SPA_CHOICE_Step: -+ ssep = "[ "; -+ sep = ", "; -+ esep = " ]"; -+ break; -+ default: -+ case SPA_CHOICE_Enum: -+ case SPA_CHOICE_Flags: -+ ssep = "{ "; -+ sep = ", "; -+ esep = " }"; -+ break; -+ } -+ -+ fprintf(stderr, "%s", ssep); -+ -+ for (i = 1; i < n_vals; i++) { -+ vals = SPA_MEMBER(vals, size, void); -+ if (i > 1) -+ fprintf(stderr, "%s", sep); -+ spa_debug_format_value(ti ? ti->values : NULL, type, vals, size); -+ } -+ fprintf(stderr, "%s", esep); -+ } -+ fprintf(stderr, "\n"); -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_FORMAT_H */ -diff --git a/third_party/pipewire/spa/debug/mem.h b/third_party/pipewire/spa/debug/mem.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/mem.h -@@ -0,0 +1,60 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_MEM_H -+#define SPA_DEBUG_MEM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_mem(int indent, const void *data, size_t size) -+{ -+ const uint8_t *t = (const uint8_t*)data; -+ char buffer[512]; -+ size_t i; -+ int pos = 0; -+ -+ for (i = 0; i < size; i++) { -+ if (i % 16 == 0) -+ pos = sprintf(buffer, "%p: ", &t[i]); -+ pos += sprintf(buffer + pos, "%02x ", t[i]); -+ if (i % 16 == 15 || i == size - 1) { -+ spa_debug("%*s" "%s", indent, "", buffer); -+ } -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_MEM_H */ -diff --git a/third_party/pipewire/spa/debug/node.h b/third_party/pipewire/spa/debug/node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/node.h -@@ -0,0 +1,57 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_NODE_H -+#define SPA_DEBUG_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_port_info(int indent, const struct spa_port_info *info) -+{ -+ spa_debug("%*s" "struct spa_port_info %p:", indent, "", info); -+ spa_debug("%*s" " flags: \t%08" PRIx64, indent, "", info->flags); -+ spa_debug("%*s" " rate: \t%d/%d", indent, "", info->rate.num, info->rate.denom); -+ spa_debug("%*s" " props:", indent, ""); -+ if (info->props) -+ spa_debug_dict(indent + 2, info->props); -+ else -+ spa_debug("%*s" " none", indent, ""); -+ return 0; -+} -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_NODE_H */ -diff --git a/third_party/pipewire/spa/debug/pod.h b/third_party/pipewire/spa/debug/pod.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/pod.h -@@ -0,0 +1,207 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_POD_H -+#define SPA_DEBUG_POD_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int -+spa_debug_pod_value(int indent, const struct spa_type_info *info, -+ uint32_t type, void *body, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_Bool: -+ spa_debug("%*s" "Bool %s", indent, "", (*(int32_t *) body) ? "true" : "false"); -+ break; -+ case SPA_TYPE_Id: -+ spa_debug("%*s" "Id %-8d (%s)", indent, "", *(int32_t *) body, -+ spa_debug_type_find_name(info, *(int32_t *) body)); -+ break; -+ case SPA_TYPE_Int: -+ spa_debug("%*s" "Int %d", indent, "", *(int32_t *) body); -+ break; -+ case SPA_TYPE_Long: -+ spa_debug("%*s" "Long %" PRIi64 "", indent, "", *(int64_t *) body); -+ break; -+ case SPA_TYPE_Float: -+ spa_debug("%*s" "Float %f", indent, "", *(float *) body); -+ break; -+ case SPA_TYPE_Double: -+ spa_debug("%*s" "Double %f", indent, "", *(double *) body); -+ break; -+ case SPA_TYPE_String: -+ spa_debug("%*s" "String \"%s\"", indent, "", (char *) body); -+ break; -+ case SPA_TYPE_Fd: -+ spa_debug("%*s" "Fd %d", indent, "", *(int *) body); -+ break; -+ case SPA_TYPE_Pointer: -+ { -+ struct spa_pod_pointer_body *b = (struct spa_pod_pointer_body *)body; -+ spa_debug("%*s" "Pointer %s %p", indent, "", -+ spa_debug_type_find_name(SPA_TYPE_ROOT, b->type), b->value); -+ break; -+ } -+ case SPA_TYPE_Rectangle: -+ { -+ struct spa_rectangle *r = (struct spa_rectangle *)body; -+ spa_debug("%*s" "Rectangle %dx%d", indent, "", r->width, r->height); -+ break; -+ } -+ case SPA_TYPE_Fraction: -+ { -+ struct spa_fraction *f = (struct spa_fraction *)body; -+ spa_debug("%*s" "Fraction %d/%d", indent, "", f->num, f->denom); -+ break; -+ } -+ case SPA_TYPE_Bitmap: -+ spa_debug("%*s" "Bitmap", indent, ""); -+ break; -+ case SPA_TYPE_Array: -+ { -+ struct spa_pod_array_body *b = (struct spa_pod_array_body *)body; -+ void *p; -+ const struct spa_type_info *ti = spa_debug_type_find(SPA_TYPE_ROOT, b->child.type); -+ -+ spa_debug("%*s" "Array: child.size %d, child.type %s", indent, "", -+ b->child.size, ti ? ti->name : "unknown"); -+ -+ SPA_POD_ARRAY_BODY_FOREACH(b, size, p) -+ spa_debug_pod_value(indent + 2, info, b->child.type, p, b->child.size); -+ break; -+ } -+ case SPA_TYPE_Choice: -+ { -+ struct spa_pod_choice_body *b = (struct spa_pod_choice_body *)body; -+ void *p; -+ const struct spa_type_info *ti = spa_debug_type_find(spa_type_choice, b->type); -+ -+ spa_debug("%*s" "Choice: type %s, flags %08x %d %d", indent, "", -+ ti ? ti->name : "unknown", b->flags, size, b->child.size); -+ -+ SPA_POD_CHOICE_BODY_FOREACH(b, size, p) -+ spa_debug_pod_value(indent + 2, info, b->child.type, p, b->child.size); -+ break; -+ } -+ case SPA_TYPE_Struct: -+ { -+ struct spa_pod *b = (struct spa_pod *)body, *p; -+ spa_debug("%*s" "Struct: size %d", indent, "", size); -+ SPA_POD_FOREACH(b, size, p) -+ spa_debug_pod_value(indent + 2, info, p->type, SPA_POD_BODY(p), p->size); -+ break; -+ } -+ case SPA_TYPE_Object: -+ { -+ struct spa_pod_object_body *b = (struct spa_pod_object_body *)body; -+ struct spa_pod_prop *p; -+ const struct spa_type_info *ti, *ii; -+ -+ ti = spa_debug_type_find(info, b->type); -+ ii = ti ? spa_debug_type_find(ti->values, 0) : NULL; -+ ii = ii ? spa_debug_type_find(ii->values, b->id) : NULL; -+ -+ spa_debug("%*s" "Object: size %d, type %s (%d), id %s (%d)", indent, "", size, -+ ti ? ti->name : "unknown", b->type, ii ? ii->name : "unknown", b->id); -+ -+ info = ti ? ti->values : info; -+ -+ SPA_POD_OBJECT_BODY_FOREACH(b, size, p) { -+ ii = spa_debug_type_find(info, p->key); -+ -+ spa_debug("%*s" "Prop: key %s (%d), flags %08x", indent+2, "", -+ ii ? ii->name : "unknown", p->key, p->flags); -+ -+ spa_debug_pod_value(indent + 4, ii ? ii->values : NULL, -+ p->value.type, -+ SPA_POD_CONTENTS(struct spa_pod_prop, p), -+ p->value.size); -+ } -+ break; -+ } -+ case SPA_TYPE_Sequence: -+ { -+ struct spa_pod_sequence_body *b = (struct spa_pod_sequence_body *)body; -+ const struct spa_type_info *ti, *ii; -+ struct spa_pod_control *c; -+ -+ ti = spa_debug_type_find(info, b->unit); -+ -+ spa_debug("%*s" "Sequence: size %d, unit %s", indent, "", size, -+ ti ? ti->name : "unknown"); -+ -+ SPA_POD_SEQUENCE_BODY_FOREACH(b, size, c) { -+ ii = spa_debug_type_find(spa_type_control, c->type); -+ -+ spa_debug("%*s" "Control: offset %d, type %s", indent+2, "", -+ c->offset, ii ? ii->name : "unknown"); -+ -+ spa_debug_pod_value(indent + 4, ii ? ii->values : NULL, -+ c->value.type, -+ SPA_POD_CONTENTS(struct spa_pod_control, c), -+ c->value.size); -+ } -+ break; -+ } -+ case SPA_TYPE_Bytes: -+ spa_debug("%*s" "Bytes", indent, ""); -+ spa_debug_mem(indent + 2, body, size); -+ break; -+ case SPA_TYPE_None: -+ spa_debug("%*s" "None", indent, ""); -+ spa_debug_mem(indent + 2, body, size); -+ break; -+ default: -+ spa_debug("%*s" "unhandled POD type %d", indent, "", type); -+ break; -+ } -+ return 0; -+} -+ -+static inline int spa_debug_pod(int indent, -+ const struct spa_type_info *info, const struct spa_pod *pod) -+{ -+ return spa_debug_pod_value(indent, info ? info : SPA_TYPE_ROOT, -+ SPA_POD_TYPE(pod), -+ SPA_POD_BODY(pod), -+ SPA_POD_BODY_SIZE(pod)); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_POD_H */ -diff --git a/third_party/pipewire/spa/debug/types.h b/third_party/pipewire/spa/debug/types.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/types.h -@@ -0,0 +1,98 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_TYPES_H -+#define SPA_DEBUG_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+static inline const struct spa_type_info *spa_debug_type_find(const struct spa_type_info *info, uint32_t type) -+{ -+ const struct spa_type_info *res; -+ -+ if (info == NULL) -+ info = SPA_TYPE_ROOT; -+ -+ while (info && info->name) { -+ if (info->type == SPA_ID_INVALID) { -+ if (info->values && (res = spa_debug_type_find(info->values, type))) -+ return res; -+ } -+ else if (info->type == type) -+ return info; -+ info++; -+ } -+ return NULL; -+} -+ -+static inline const char *spa_debug_type_short_name(const char *name) -+{ -+ const char *h; -+ if ((h = strrchr(name, ':')) != NULL) -+ name = h + 1; -+ return name; -+} -+ -+static inline const char *spa_debug_type_find_name(const struct spa_type_info *info, uint32_t type) -+{ -+ if ((info = spa_debug_type_find(info, type)) == NULL) -+ return NULL; -+ return info->name; -+} -+ -+static inline const char *spa_debug_type_find_short_name(const struct spa_type_info *info, uint32_t type) -+{ -+ const char *str; -+ if ((str = spa_debug_type_find_name(info, type)) == NULL) -+ return NULL; -+ return spa_debug_type_short_name(str); -+} -+ -+static inline uint32_t spa_debug_type_find_type(const struct spa_type_info *info, const char *name) -+{ -+ if (info == NULL) -+ info = SPA_TYPE_ROOT; -+ -+ while (info && info->name) { -+ uint32_t res; -+ if (strcmp(info->name, name) == 0) -+ return info->type; -+ if (info->values && (res = spa_debug_type_find_type(info->values, name)) != SPA_ID_INVALID) -+ return res; -+ info++; -+ } -+ return SPA_ID_INVALID; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_NODE_H */ -diff --git a/third_party/pipewire/spa/graph/graph.h b/third_party/pipewire/spa/graph/graph.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/graph/graph.h -@@ -0,0 +1,352 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_GRAPH_H -+#define SPA_GRAPH_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) -+#endif -+ -+struct spa_graph; -+struct spa_graph_node; -+struct spa_graph_link; -+struct spa_graph_port; -+ -+struct spa_graph_state { -+ int status; /**< current status */ -+ int32_t required; /**< required number of signals */ -+ int32_t pending; /**< number of pending signals */ -+}; -+ -+static inline void spa_graph_state_reset(struct spa_graph_state *state) -+{ -+ state->pending = state->required; -+} -+ -+struct spa_graph_link { -+ struct spa_list link; -+ struct spa_graph_state *state; -+ int (*signal) (void *data); -+ void *signal_data; -+}; -+ -+#define spa_graph_link_signal(l) ((l)->signal((l)->signal_data)) -+ -+#define spa_graph_state_dec(s,c) (__atomic_sub_fetch(&(s)->pending, c, __ATOMIC_SEQ_CST) == 0) -+ -+static inline int spa_graph_link_trigger(struct spa_graph_link *link) -+{ -+ struct spa_graph_state *state = link->state; -+ -+ spa_debug("link %p: state %p: pending %d/%d", link, state, -+ state->pending, state->required); -+ -+ if (spa_graph_state_dec(state, 1)) -+ spa_graph_link_signal(link); -+ -+ return state->status; -+} -+struct spa_graph { -+ uint32_t flags; /* flags */ -+ struct spa_graph_node *parent; /* parent node or NULL when driver */ -+ struct spa_graph_state *state; /* state of graph */ -+ struct spa_list nodes; /* list of nodes of this graph */ -+}; -+ -+struct spa_graph_node_callbacks { -+#define SPA_VERSION_GRAPH_NODE_CALLBACKS 0 -+ uint32_t version; -+ -+ int (*process) (void *data, struct spa_graph_node *node); -+ int (*reuse_buffer) (void *data, struct spa_graph_node *node, -+ uint32_t port_id, uint32_t buffer_id); -+}; -+ -+struct spa_graph_node { -+ struct spa_list link; /**< link in graph nodes list */ -+ struct spa_graph *graph; /**< owner graph */ -+ struct spa_list ports[2]; /**< list of input and output ports */ -+ struct spa_list links; /**< list of links to next nodes */ -+ uint32_t flags; /**< node flags */ -+ struct spa_graph_state *state; /**< state of the node */ -+ struct spa_graph_link graph_link; /**< link in graph */ -+ struct spa_graph *subgraph; /**< subgraph or NULL */ -+ struct spa_callbacks callbacks; -+ struct spa_list sched_link; /**< link for scheduler */ -+}; -+ -+#define spa_graph_node_call(n,method,version,...) \ -+({ \ -+ int __res = 0; \ -+ spa_callbacks_call_res(&(n)->callbacks, \ -+ struct spa_graph_node_callbacks, __res, \ -+ method, version, ##__VA_ARGS__); \ -+ __res; \ -+}) -+ -+#define spa_graph_node_process(n) spa_graph_node_call(n, process, 0, n) -+#define spa_graph_node_reuse_buffer(n,p,i) spa_graph_node_call(n, reuse_buffer, 0, n, p, i) -+ -+struct spa_graph_port { -+ struct spa_list link; /**< link in node port list */ -+ struct spa_graph_node *node; /**< owner node */ -+ enum spa_direction direction; /**< port direction */ -+ uint32_t port_id; /**< port id */ -+ uint32_t flags; /**< port flags */ -+ struct spa_graph_port *peer; /**< peer */ -+}; -+ -+static inline int spa_graph_node_trigger(struct spa_graph_node *node) -+{ -+ struct spa_graph_link *l; -+ spa_debug("node %p trigger", node); -+ spa_list_for_each(l, &node->links, link) -+ spa_graph_link_trigger(l); -+ return 0; -+} -+ -+static inline int spa_graph_run(struct spa_graph *graph) -+{ -+ struct spa_graph_node *n, *t; -+ struct spa_list pending; -+ -+ spa_graph_state_reset(graph->state); -+ spa_debug("graph %p run with state %p pending %d/%d", graph, graph->state, -+ graph->state->pending, graph->state->required); -+ -+ spa_list_init(&pending); -+ -+ spa_list_for_each(n, &graph->nodes, link) { -+ struct spa_graph_state *s = n->state; -+ spa_graph_state_reset(s); -+ spa_debug("graph %p node %p: state %p pending %d/%d status %d", graph, n, -+ s, s->pending, s->required, s->status); -+ if (--s->pending == 0) -+ spa_list_append(&pending, &n->sched_link); -+ } -+ spa_list_for_each_safe(n, t, &pending, sched_link) -+ spa_graph_node_process(n); -+ -+ return 0; -+} -+ -+static inline int spa_graph_finish(struct spa_graph *graph) -+{ -+ spa_debug("graph %p finish", graph); -+ if (graph->parent) -+ return spa_graph_node_trigger(graph->parent); -+ return 0; -+} -+static inline int spa_graph_link_signal_node(void *data) -+{ -+ struct spa_graph_node *node = (struct spa_graph_node *)data; -+ spa_debug("node %p call process", node); -+ return spa_graph_node_process(node); -+} -+ -+static inline int spa_graph_link_signal_graph(void *data) -+{ -+ struct spa_graph_node *node = (struct spa_graph_node *)data; -+ return spa_graph_finish(node->graph); -+} -+ -+static inline void spa_graph_init(struct spa_graph *graph, struct spa_graph_state *state) -+{ -+ spa_list_init(&graph->nodes); -+ graph->flags = 0; -+ graph->state = state; -+ spa_debug("graph %p init state %p", graph, state); -+} -+ -+static inline void -+spa_graph_link_add(struct spa_graph_node *out, -+ struct spa_graph_state *state, -+ struct spa_graph_link *link) -+{ -+ link->state = state; -+ state->required++; -+ spa_debug("node %p add link %p to state %p %d", out, link, state, state->required); -+ spa_list_append(&out->links, &link->link); -+} -+ -+static inline void spa_graph_link_remove(struct spa_graph_link *link) -+{ -+ link->state->required--; -+ spa_debug("link %p state %p remove %d", link, link->state, link->state->required); -+ spa_list_remove(&link->link); -+} -+ -+static inline void -+spa_graph_node_init(struct spa_graph_node *node, struct spa_graph_state *state) -+{ -+ spa_list_init(&node->ports[SPA_DIRECTION_INPUT]); -+ spa_list_init(&node->ports[SPA_DIRECTION_OUTPUT]); -+ spa_list_init(&node->links); -+ node->flags = 0; -+ node->subgraph = NULL; -+ node->state = state; -+ node->state->required = node->state->pending = 0; -+ node->state->status = SPA_STATUS_OK; -+ node->graph_link.signal = spa_graph_link_signal_graph; -+ node->graph_link.signal_data = node; -+ spa_debug("node %p init state %p", node, state); -+} -+ -+ -+static inline int spa_graph_node_impl_sub_process(void *data, struct spa_graph_node *node) -+{ -+ struct spa_graph *graph = node->subgraph; -+ spa_debug("node %p: sub process %p", node, graph); -+ return spa_graph_run(graph); -+} -+ -+static const struct spa_graph_node_callbacks spa_graph_node_sub_impl_default = { -+ SPA_VERSION_GRAPH_NODE_CALLBACKS, -+ .process = spa_graph_node_impl_sub_process, -+}; -+ -+static inline void spa_graph_node_set_subgraph(struct spa_graph_node *node, -+ struct spa_graph *subgraph) -+{ -+ node->subgraph = subgraph; -+ subgraph->parent = node; -+ spa_debug("node %p set subgraph %p", node, subgraph); -+} -+ -+static inline void -+spa_graph_node_set_callbacks(struct spa_graph_node *node, -+ const struct spa_graph_node_callbacks *callbacks, -+ void *data) -+{ -+ node->callbacks = SPA_CALLBACKS_INIT(callbacks, data); -+} -+ -+static inline void -+spa_graph_node_add(struct spa_graph *graph, -+ struct spa_graph_node *node) -+{ -+ node->graph = graph; -+ spa_list_append(&graph->nodes, &node->link); -+ node->state->required++; -+ spa_debug("node %p add to graph %p, state %p required %d", -+ node, graph, node->state, node->state->required); -+ spa_graph_link_add(node, graph->state, &node->graph_link); -+} -+ -+static inline void spa_graph_node_remove(struct spa_graph_node *node) -+{ -+ spa_debug("node %p remove from graph %p, state %p required %d", -+ node, node->graph, node->state, node->state->required); -+ spa_graph_link_remove(&node->graph_link); -+ node->state->required--; -+ spa_list_remove(&node->link); -+} -+ -+ -+static inline void -+spa_graph_port_init(struct spa_graph_port *port, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t flags) -+{ -+ spa_debug("port %p init type %d id %d", port, direction, port_id); -+ port->direction = direction; -+ port->port_id = port_id; -+ port->flags = flags; -+} -+ -+static inline void -+spa_graph_port_add(struct spa_graph_node *node, -+ struct spa_graph_port *port) -+{ -+ spa_debug("port %p add to node %p", port, node); -+ port->node = node; -+ spa_list_append(&node->ports[port->direction], &port->link); -+} -+ -+static inline void spa_graph_port_remove(struct spa_graph_port *port) -+{ -+ spa_debug("port %p remove", port); -+ spa_list_remove(&port->link); -+} -+ -+static inline void -+spa_graph_port_link(struct spa_graph_port *out, struct spa_graph_port *in) -+{ -+ spa_debug("port %p link to %p %p %p", out, in, in->node, in->node->state); -+ out->peer = in; -+ in->peer = out; -+} -+ -+static inline void -+spa_graph_port_unlink(struct spa_graph_port *port) -+{ -+ spa_debug("port %p unlink from %p", port, port->peer); -+ if (port->peer) { -+ port->peer->peer = NULL; -+ port->peer = NULL; -+ } -+} -+ -+static inline int spa_graph_node_impl_process(void *data, struct spa_graph_node *node) -+{ -+ struct spa_node *n = (struct spa_node *)data; -+ struct spa_graph_state *state = node->state; -+ -+ spa_debug("node %p: process state %p: %d, node %p", node, state, state->status, n); -+ if ((state->status = spa_node_process(n)) != SPA_STATUS_OK) -+ spa_graph_node_trigger(node); -+ -+ return state->status; -+} -+ -+static inline int spa_graph_node_impl_reuse_buffer(void *data, struct spa_graph_node *node, -+ uint32_t port_id, uint32_t buffer_id) -+{ -+ struct spa_node *n = (struct spa_node *)data; -+ return spa_node_port_reuse_buffer(n, port_id, buffer_id); -+} -+ -+static const struct spa_graph_node_callbacks spa_graph_node_impl_default = { -+ SPA_VERSION_GRAPH_NODE_CALLBACKS, -+ .process = spa_graph_node_impl_process, -+ .reuse_buffer = spa_graph_node_impl_reuse_buffer, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_GRAPH_H */ -diff --git a/third_party/pipewire/spa/monitor/device.h b/third_party/pipewire/spa/monitor/device.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/monitor/device.h -@@ -0,0 +1,297 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEVICE_H -+#define SPA_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+/** -+ * spa_device: -+ * -+ * The device interface can be used to monitor all kinds of devices -+ * and create objects as a result. Objects a typically other -+ * Devices or Nodes. -+ * -+ */ -+#define SPA_TYPE_INTERFACE_Device SPA_TYPE_INFO_INTERFACE_BASE "Device" -+ -+#define SPA_VERSION_DEVICE 0 -+struct spa_device { struct spa_interface iface; }; -+ -+/** -+ * Information about the device and parameters it supports -+ * -+ * This information is part of the info event on a device. -+ */ -+struct spa_device_info { -+#define SPA_VERSION_DEVICE_INFO 0 -+ uint32_t version; -+ -+#define SPA_DEVICE_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_DEVICE_CHANGE_MASK_PROPS (1u<<1) -+#define SPA_DEVICE_CHANGE_MASK_PARAMS (1u<<2) -+ uint64_t change_mask; -+ uint64_t flags; -+ const struct spa_dict *props; /**< device properties */ -+ struct spa_param_info *params; /**< supported parameters */ -+ uint32_t n_params; /**< number of elements in params */ -+}; -+ -+#define SPA_DEVICE_INFO_INIT() (struct spa_device_info){ SPA_VERSION_DEVICE_INFO, } -+ -+/** -+ * Information about a device object -+ * -+ * This information is part of the object_info event on the device. -+ */ -+struct spa_device_object_info { -+#define SPA_VERSION_DEVICE_OBJECT_INFO 0 -+ uint32_t version; -+ -+ const char *type; /**< the object type managed by this device */ -+ const char *factory_name; /**< a factory name that implements the object */ -+ -+#define SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS (1u<<1) -+ uint64_t change_mask; -+ uint64_t flags; -+ const struct spa_dict *props; /**< extra object properties */ -+}; -+ -+#define SPA_DEVICE_OBJECT_INFO_INIT() (struct spa_device_object_info){ SPA_VERSION_DEVICE_OBJECT_INFO, } -+ -+/** the result of spa_device_enum_params() */ -+#define SPA_RESULT_TYPE_DEVICE_PARAMS 1 -+struct spa_result_device_params { -+ uint32_t id; -+ uint32_t index; -+ uint32_t next; -+ struct spa_pod *param; -+}; -+ -+#define SPA_DEVICE_EVENT_INFO 0 -+#define SPA_DEVICE_EVENT_RESULT 1 -+#define SPA_DEVICE_EVENT_EVENT 2 -+#define SPA_DEVICE_EVENT_OBJECT_INFO 3 -+#define SPA_DEVICE_EVENT_NUM 4 -+ -+/** -+ * spa_device_events: -+ * -+ * Events are always emitted from the main thread -+ */ -+struct spa_device_events { -+ /** version of the structure */ -+#define SPA_VERSION_DEVICE_EVENTS 0 -+ uint32_t version; -+ -+ /** notify extra information about the device */ -+ void (*info) (void *data, const struct spa_device_info *info); -+ -+ /** notify a result */ -+ void (*result) (void *data, int seq, int res, uint32_t type, const void *result); -+ -+ /** a device event */ -+ void (*event) (void *data, const struct spa_event *event); -+ -+ /** info changed for an object managed by the device, info is NULL when -+ * the object is removed */ -+ void (*object_info) (void *data, uint32_t id, -+ const struct spa_device_object_info *info); -+}; -+ -+#define SPA_DEVICE_METHOD_ADD_LISTENER 0 -+#define SPA_DEVICE_METHOD_SYNC 1 -+#define SPA_DEVICE_METHOD_ENUM_PARAMS 2 -+#define SPA_DEVICE_METHOD_SET_PARAM 3 -+#define SPA_DEVICE_METHOD_NUM 4 -+ -+/** -+ * spa_device_methods: -+ */ -+struct spa_device_methods { -+ /* the version of the methods. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_DEVICE_METHODS 0 -+ uint32_t version; -+ -+ /** -+ * Set events to receive asynchronous notifications from -+ * the device. -+ * -+ * Setting the events will trigger the info event and an -+ * object_info event for each managed object on the new -+ * listener. -+ * -+ * \param device a #spa_device -+ * \param listener a listener -+ * \param events a #struct spa_device_events -+ * \param data data passed as first argument in functions of \a events -+ * \return 0 on success -+ * < 0 errno on error -+ */ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct spa_device_events *events, -+ void *data); -+ /** -+ * Perform a sync operation. -+ * -+ * This method will emit the result event with the given sequence -+ * number synchronously or with the returned async return value -+ * asynchronously. -+ * -+ * Because all methods are serialized in the device, this can be used -+ * to wait for completion of all previous method calls. -+ * -+ * \param seq a sequence number -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ * an async result -+ */ -+ int (*sync) (void *object, int seq); -+ -+ /** -+ * Enumerate the parameters of a device. -+ * -+ * Parameters are identified with an \a id. Some parameters can have -+ * multiple values, see the documentation of the parameter id. -+ * -+ * Parameters can be filtered by passing a non-NULL \a filter. -+ * -+ * The result callback will be called at most \max times with a -+ * struct spa_result_device_params as the result. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param device a \ref spa_device -+ * \param seq a sequence number to pass to the result function -+ * \param id the param id to enumerate -+ * \param index the index of enumeration, pass 0 for the first item. -+ * \param max the maximum number of items to iterate -+ * \param filter and optional filter to use -+ * \return 0 when there are no more parameters to enumerate -+ * -EINVAL when invalid arguments are given -+ * -ENOENT the parameter \a id is unknown -+ * -ENOTSUP when there are no parameters -+ * implemented on \a device -+ */ -+ int (*enum_params) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t max, -+ const struct spa_pod *filter); -+ -+ /** -+ * Set the configurable parameter in \a device. -+ * -+ * Usually, \a param will be obtained from enum_params and then -+ * modified but it is also possible to set another spa_pod -+ * as long as its keys and types match a supported object. -+ * -+ * Objects with property keys that are not known are ignored. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param device a \ref spa_device -+ * \param id the parameter id to configure -+ * \param flags additional flags -+ * \param param the parameter to configure -+ * -+ * \return 0 on success -+ * -EINVAL when invalid arguments are given -+ * -ENOTSUP when there are no parameters implemented on \a device -+ * -ENOENT the parameter is unknown -+ */ -+ int (*set_param) (void *object, -+ uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+}; -+ -+#define spa_device_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_device *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_device_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_device_add_listener(d,...) spa_device_method(d, add_listener, 0, __VA_ARGS__) -+#define spa_device_sync(d,...) spa_device_method(d, sync, 0, __VA_ARGS__) -+#define spa_device_enum_params(d,...) spa_device_method(d, enum_params, 0, __VA_ARGS__) -+#define spa_device_set_param(d,...) spa_device_method(d, set_param, 0, __VA_ARGS__) -+ -+#define SPA_KEY_DEVICE_ENUM_API "device.enum.api" /**< the api used to discover this -+ * device */ -+#define SPA_KEY_DEVICE_API "device.api" /**< the api used by the device -+ * Ex. "udev", "alsa", "v4l2". */ -+#define SPA_KEY_DEVICE_NAME "device.name" /**< the name of the device */ -+#define SPA_KEY_DEVICE_ALIAS "device.alias" /**< alternative name of the device */ -+#define SPA_KEY_DEVICE_NICK "device.nick" /**< the device short name */ -+#define SPA_KEY_DEVICE_DESCRIPTION "device.description" /**< a device description */ -+#define SPA_KEY_DEVICE_ICON "device.icon" /**< icon for the device. A base64 blob -+ * containing PNG image data */ -+#define SPA_KEY_DEVICE_ICON_NAME "device.icon-name" /**< an XDG icon name for the device. -+ * Ex. "sound-card-speakers-usb" */ -+#define SPA_KEY_DEVICE_PLUGGED_USEC "device.plugged.usec" /**< when the device was plugged */ -+ -+#define SPA_KEY_DEVICE_BUS_ID "device.bus-id" /**< the device bus-id */ -+#define SPA_KEY_DEVICE_BUS_PATH "device.bus-path" /**< bus path to the device in the OS' -+ * format. -+ * Ex. "pci-0000:00:14.0-usb-0:3.2:1.0" */ -+#define SPA_KEY_DEVICE_BUS "device.bus" /**< bus of the device if applicable. One of -+ * "isa", "pci", "usb", "firewire", -+ * "bluetooth" */ -+#define SPA_KEY_DEVICE_SUBSYSTEM "device.subsystem" /**< device subsystem */ -+#define SPA_KEY_DEVICE_SYSFS_PATH "device.sysfs.path" /**< device sysfs path */ -+ -+#define SPA_KEY_DEVICE_VENDOR_ID "device.vendor.id" /**< vendor ID if applicable */ -+#define SPA_KEY_DEVICE_VENDOR_NAME "device.vendor.name" /**< vendor name if applicable */ -+#define SPA_KEY_DEVICE_PRODUCT_ID "device.product.id" /**< product ID if applicable */ -+#define SPA_KEY_DEVICE_PRODUCT_NAME "device.product.name" /**< product name if applicable */ -+#define SPA_KEY_DEVICE_SERIAL "device.serial" /**< Serial number if applicable */ -+#define SPA_KEY_DEVICE_CLASS "device.class" /**< device class */ -+#define SPA_KEY_DEVICE_CAPABILITIES "device.capabilities" /**< api specific device capabilities */ -+#define SPA_KEY_DEVICE_FORM_FACTOR "device.form-factor" /**< form factor if applicable. One of -+ * "internal", "speaker", "handset", "tv", -+ * "webcam", "microphone", "headset", -+ * "headphone", "hands-free", "car", "hifi", -+ * "computer", "portable" */ -+#define SPA_KEY_DEVICE_PROFILE "device.profile " /**< profile for the device */ -+#define SPA_KEY_DEVICE_PROFILE_SET "device.profile-set" /**< profile set for the device */ -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEVICE_H */ -diff --git a/third_party/pipewire/spa/monitor/event.h b/third_party/pipewire/spa/monitor/event.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/monitor/event.h -@@ -0,0 +1,54 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2020 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_EVENT_DEVICE_H -+#define SPA_EVENT_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/* object id of SPA_TYPE_EVENT_Device */ -+enum spa_device_event { -+ SPA_DEVICE_EVENT_ObjectConfig, -+}; -+ -+#define SPA_DEVICE_EVENT_ID(ev) SPA_EVENT_ID(ev, SPA_TYPE_EVENT_Device) -+#define SPA_DEVICE_EVENT_INIT(id) SPA_EVENT_INIT(SPA_TYPE_EVENT_Device, id) -+ -+/* properties for SPA_TYPE_EVENT_Device */ -+enum spa_event_device { -+ SPA_EVENT_DEVICE_START, -+ -+ SPA_EVENT_DEVICE_Object, /* an object id (Int) */ -+ SPA_EVENT_DEVICE_Props, /* properties for an object (SPA_TYPE_OBJECT_Props) */ -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_EVENT_DEVICE */ -diff --git a/third_party/pipewire/spa/monitor/utils.h b/third_party/pipewire/spa/monitor/utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/monitor/utils.h -@@ -0,0 +1,95 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEVICE_UTILS_H -+#define SPA_DEVICE_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_result_device_params_data { -+ struct spa_pod_builder *builder; -+ struct spa_result_device_params data; -+}; -+ -+static inline void spa_result_func_device_params(void *data, int seq, int res, -+ uint32_t type, const void *result) -+{ -+ struct spa_result_device_params_data *d = -+ (struct spa_result_device_params_data *)data; -+ const struct spa_result_device_params *r = -+ (const struct spa_result_device_params *)result; -+ uint32_t offset = d->builder->state.offset; -+ spa_pod_builder_raw_padded(d->builder, r->param, SPA_POD_SIZE(r->param)); -+ d->data.next = r->next; -+ d->data.param = SPA_MEMBER(d->builder->data, offset, struct spa_pod); -+} -+ -+static inline int spa_device_enum_params_sync(struct spa_device *device, -+ uint32_t id, uint32_t *index, -+ const struct spa_pod *filter, -+ struct spa_pod **param, -+ struct spa_pod_builder *builder) -+{ -+ struct spa_result_device_params_data data = { builder, }; -+ struct spa_hook listener = { 0 }; -+ static const struct spa_device_events device_events = { -+ SPA_VERSION_DEVICE_EVENTS, -+ .result = spa_result_func_device_params, -+ }; -+ int res; -+ -+ spa_device_add_listener(device, &listener, &device_events, &data); -+ res = spa_device_enum_params(device, 0, id, *index, 1, filter); -+ spa_hook_remove(&listener); -+ -+ if (data.data.param == NULL) { -+ if (res > 0) -+ res = 0; -+ } else { -+ *index = data.data.next; -+ *param = data.data.param; -+ res = 1; -+ } -+ return res; -+} -+ -+#define spa_device_emit(hooks,method,version,...) \ -+ spa_hook_list_call_simple(hooks, struct spa_device_events, \ -+ method, version, ##__VA_ARGS__) -+ -+#define spa_device_emit_info(hooks,i) spa_device_emit(hooks,info, 0, i) -+#define spa_device_emit_result(hooks,s,r,t,res) spa_device_emit(hooks,result, 0, s, r, t, res) -+#define spa_device_emit_event(hooks,e) spa_device_emit(hooks,event, 0, e) -+#define spa_device_emit_object_info(hooks,id,i) spa_device_emit(hooks,object_info, 0, id, i) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEVICE_UTILS_H */ -diff --git a/third_party/pipewire/spa/node/command.h b/third_party/pipewire/spa/node/command.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/command.h -@@ -0,0 +1,54 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_COMMAND_NODE_H -+#define SPA_COMMAND_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/* object id of SPA_TYPE_COMMAND_Node */ -+enum spa_node_command { -+ SPA_NODE_COMMAND_Suspend, -+ SPA_NODE_COMMAND_Pause, -+ SPA_NODE_COMMAND_Start, -+ SPA_NODE_COMMAND_Enable, -+ SPA_NODE_COMMAND_Disable, -+ SPA_NODE_COMMAND_Flush, -+ SPA_NODE_COMMAND_Drain, -+ SPA_NODE_COMMAND_Marker, -+}; -+ -+#define SPA_NODE_COMMAND_ID(cmd) SPA_COMMAND_ID(cmd, SPA_TYPE_COMMAND_Node) -+#define SPA_NODE_COMMAND_INIT(id) SPA_COMMAND_INIT(SPA_TYPE_COMMAND_Node, id) -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_COMMAND_NODE_H */ -diff --git a/third_party/pipewire/spa/node/event.h b/third_party/pipewire/spa/node/event.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/event.h -@@ -0,0 +1,48 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_EVENT_NODE_H -+#define SPA_EVENT_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/* object id of SPA_TYPE_EVENT_Node */ -+enum spa_node_event { -+ SPA_NODE_EVENT_Error, -+ SPA_NODE_EVENT_Buffering, -+ SPA_NODE_EVENT_RequestRefresh, -+}; -+ -+#define SPA_NODE_EVENT_ID(ev) SPA_EVENT_ID(ev, SPA_TYPE_EVENT_Node) -+#define SPA_NODE_EVENT_INIT(id) SPA_EVENT_INIT(SPA_TYPE_EVENT_Node, id) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_EVENT_NODE_H */ -diff --git a/third_party/pipewire/spa/node/io.h b/third_party/pipewire/spa/node/io.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/io.h -@@ -0,0 +1,294 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_IO_H -+#define SPA_IO_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** IO areas -+ * -+ * IO information for a port on a node. This is allocated -+ * by the host and configured on a node or all ports for which -+ * IO is requested. -+ * -+ * The plugin will communicate with the host through the IO -+ * areas. -+ */ -+ -+/** Different IO area types */ -+enum spa_io_type { -+ SPA_IO_Invalid, -+ SPA_IO_Buffers, /**< area to exchange buffers, struct spa_io_buffers */ -+ SPA_IO_Range, /**< expected byte range, struct spa_io_range */ -+ SPA_IO_Clock, /**< area to update clock information, struct spa_io_clock */ -+ SPA_IO_Latency, /**< latency reporting, struct spa_io_latency */ -+ SPA_IO_Control, /**< area for control messages, struct spa_io_sequence */ -+ SPA_IO_Notify, /**< area for notify messages, struct spa_io_sequence */ -+ SPA_IO_Position, /**< position information in the graph, struct spa_io_position */ -+ SPA_IO_RateMatch, /**< rate matching between nodes, struct spa_io_rate_match */ -+ SPA_IO_Memory, /**< memory pointer, struct spa_io_memory */ -+}; -+ -+/** -+ * IO area to exchange buffers. -+ * -+ * A set of buffers should first be configured on the node/port. -+ * Further references to those buffers will be made by using the -+ * id of the buffer. -+ * -+ * If status is SPA_STATUS_OK, the host should ignore -+ * the io area. -+ * -+ * If status is SPA_STATUS_NEED_DATA, the host should: -+ * 1) recycle the buffer in buffer_id, if possible -+ * 2) prepare a new buffer and place the id in buffer_id. -+ * -+ * If status is SPA_STATUS_HAVE_DATA, the host should consume -+ * the buffer in buffer_id and set the state to -+ * SPA_STATUS_NEED_DATA when new data is requested. -+ * -+ * If status is SPA_STATUS_STOPPED, some error occurred on the -+ * port. -+ * -+ * If status is SPA_STATUS_DRAINED, data from the io area was -+ * used to drain. -+ * -+ * Status can also be a negative errno value to indicate errors. -+ * such as: -+ * -EINVAL: buffer_id is invalid -+ * -EPIPE: no more buffers available -+ */ -+struct spa_io_buffers { -+#define SPA_STATUS_OK 0 -+#define SPA_STATUS_NEED_DATA (1<<0) -+#define SPA_STATUS_HAVE_DATA (1<<1) -+#define SPA_STATUS_STOPPED (1<<2) -+#define SPA_STATUS_DRAINED (1<<3) -+ int32_t status; /**< the status code */ -+ uint32_t buffer_id; /**< a buffer id */ -+}; -+ -+#define SPA_IO_BUFFERS_INIT (struct spa_io_buffers) { SPA_STATUS_OK, SPA_ID_INVALID, } -+ -+/** -+ * IO area to exchange a memory region -+ */ -+struct spa_io_memory { -+ int32_t status; /**< the status code */ -+ uint32_t size; /**< the size of \a data */ -+ void *data; /**< a memory pointer */ -+}; -+#define SPA_IO_MEMORY_INIT (struct spa_io_memory) { SPA_STATUS_OK, 0, NULL, } -+ -+/** A range, suitable for input ports that can suggest a range to output ports */ -+struct spa_io_range { -+ uint64_t offset; /**< offset in range */ -+ uint32_t min_size; /**< minimum size of data */ -+ uint32_t max_size; /**< maximum size of data */ -+}; -+ -+/** -+ * Absolute time reporting. -+ * -+ * Nodes that can report clocking information will receive this io block. -+ * The application sets the id. This is usually set as part of the -+ * position information but can also be set separately. -+ * -+ * The clock counts the elapsed time according to the clock provider -+ * since the provider was last started. -+ */ -+struct spa_io_clock { -+ uint32_t flags; /**< clock flags */ -+ uint32_t id; /**< unique clock id, set by application */ -+ char name[64]; /**< clock name prefixed with API, set by node. The clock name -+ * is unique per clock and can be used to check if nodes -+ * share the same clock. */ -+ uint64_t nsec; /**< time in nanoseconds against monotonic clock */ -+ struct spa_fraction rate; /**< rate for position/duration/delay */ -+ uint64_t position; /**< current position */ -+ uint64_t duration; /**< duration of current cycle */ -+ int64_t delay; /**< delay between position and hardware, -+ * positive for capture, negative for playback */ -+ double rate_diff; /**< rate difference between clock and monotonic time */ -+ uint64_t next_nsec; /**< extimated next wakeup time in nanoseconds */ -+ uint32_t padding[8]; -+}; -+ -+/* the size of the video in this cycle */ -+struct spa_io_video_size { -+#define SPA_IO_VIDEO_SIZE_VALID (1<<0) -+ uint32_t flags; /**< optional flags */ -+ uint32_t stride; /**< video stride in bytes */ -+ struct spa_rectangle size; /**< the video size */ -+ struct spa_fraction framerate; /**< the minimum framerate, the cycle duration is -+ * always smaller to ensure there is only one -+ * video frame per cycle. */ -+ uint32_t padding[4]; -+}; -+ -+/** latency reporting */ -+struct spa_io_latency { -+ struct spa_fraction rate; /**< rate for min/max */ -+ uint64_t min; /**< min latency */ -+ uint64_t max; /**< max latency */ -+}; -+ -+/** control stream, io area for SPA_IO_Control and SPA_IO_Notify */ -+struct spa_io_sequence { -+ struct spa_pod_sequence sequence; /**< sequence of timed events */ -+}; -+ -+/** bar and beat segment */ -+struct spa_io_segment_bar { -+#define SPA_IO_SEGMENT_BAR_FLAG_VALID (1<<0) -+ uint32_t flags; /**< extra flags */ -+ uint32_t offset; /**< offset in segment of this beat */ -+ float signature_num; /**< time signature numerator */ -+ float signature_denom; /**< time signature denominator */ -+ double bpm; /**< beats per minute */ -+ double beat; /**< current beat in segment */ -+ uint32_t padding[8]; -+}; -+ -+/** video frame segment */ -+struct spa_io_segment_video { -+#define SPA_IO_SEGMENT_VIDEO_FLAG_VALID (1<<0) -+#define SPA_IO_SEGMENT_VIDEO_FLAG_DROP_FRAME (1<<1) -+#define SPA_IO_SEGMENT_VIDEO_FLAG_PULL_DOWN (1<<2) -+#define SPA_IO_SEGMENT_VIDEO_FLAG_INTERLACED (1<<3) -+ uint32_t flags; /**< flags */ -+ uint32_t offset; /**< offset in segment */ -+ struct spa_fraction framerate; -+ uint32_t hours; -+ uint32_t minutes; -+ uint32_t seconds; -+ uint32_t frames; -+ uint32_t field_count; /**< 0 for progressive, 1 and 2 for interlaced */ -+ uint32_t padding[11]; -+}; -+ -+/** -+ * A segment converts a running time to a segment (stream) position. -+ * -+ * The segment position is valid when the current running time is between -+ * start and start + duration. The position is then -+ * calculated as: -+ * -+ * (running time - start) * rate + position; -+ * -+ * Support for looping is done by specifying the LOOPING flags with a -+ * non-zero duration. When the running time reaches start + duration, -+ * duration is added to start and the loop repeats. -+ * -+ * Care has to be taken when the running time + clock.duration extends -+ * past the start + duration from the segment; the user should correctly -+ * wrap around and partially repeat the loop in the current cycle. -+ * -+ * Extra information can be placed in the segment by setting the valid flags -+ * and filling up the corresponding structures. -+ */ -+struct spa_io_segment { -+ uint32_t version; -+#define SPA_IO_SEGMENT_FLAG_LOOPING (1<<0) /**< after the duration, the segment repeats */ -+#define SPA_IO_SEGMENT_FLAG_NO_POSITION (1<<1) /**< position is invalid. The position can be invalid -+ * after a seek, for example, when the exact mapping -+ * of the extra segment info (bar, video, ...) to -+ * position has not been determined yet */ -+ uint32_t flags; /**< extra flags */ -+ uint64_t start; /**< value of running time when this -+ * info is active. Can be in the future for -+ * pending changes. It does not have to be in -+ * exact multiples of the clock duration. */ -+ uint64_t duration; /**< duration when this info becomes invalid expressed -+ * in running time. If the duration is 0, this -+ * segment extends to the next segment. If the -+ * segment becomes invalid and the looping flag is -+ * set, the segment repeats. */ -+ double rate; /**< overal rate of the segment, can be negative for -+ * backwards time reporting. */ -+ uint64_t position; /**< The position when the running time == start. -+ * can be invalid when the owner of the extra segment -+ * information has not yet made the mapping. */ -+ -+ struct spa_io_segment_bar bar; -+ struct spa_io_segment_video video; -+}; -+ -+enum spa_io_position_state { -+ SPA_IO_POSITION_STATE_STOPPED, -+ SPA_IO_POSITION_STATE_STARTING, -+ SPA_IO_POSITION_STATE_RUNNING, -+}; -+ -+/** the maximum number of segments visible in the future */ -+#define SPA_IO_POSITION_MAX_SEGMENTS 8 -+ -+/** -+ * The position information adds extra meaning to the raw clock times. -+ * -+ * It is set on all nodes and the clock id will contain the clock of the -+ * driving node in the graph. -+ * -+ * The position information contains 1 or more segments that convert the -+ * raw clock times to a stream time. They are sorted based on their -+ * start times, and thus the order in which they will activate in -+ * the future. This makes it possible to look ahead in the scheduled -+ * segments and anticipate the changes in the timeline. -+ */ -+struct spa_io_position { -+ struct spa_io_clock clock; /**< clock position of driver, always valid and -+ * read only */ -+ struct spa_io_video_size video; /**< size of the video in the current cycle */ -+ int64_t offset; /**< an offset to subtract from the clock position -+ * to get a running time. This is the time that -+ * the state has been in the RUNNING state and the -+ * time that should be used to compare the segment -+ * start values against. */ -+ uint32_t state; /**< one of enum spa_io_position_state */ -+ -+ uint32_t n_segments; /**< number of segments */ -+ struct spa_io_segment segments[SPA_IO_POSITION_MAX_SEGMENTS]; /**< segments */ -+}; -+ -+/** rate matching */ -+struct spa_io_rate_match { -+ uint32_t delay; /**< extra delay in samples for resampler */ -+ uint32_t size; /**< requested input size for resampler */ -+ double rate; /**< rate for resampler */ -+#define SPA_IO_RATE_MATCH_FLAG_ACTIVE (1 << 0) -+ uint32_t flags; /**< extra flags */ -+ uint32_t padding[7]; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_IO_H */ -diff --git a/third_party/pipewire/spa/node/keys.h b/third_party/pipewire/spa/node/keys.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/keys.h -@@ -0,0 +1,54 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_KEYS_H -+#define SPA_NODE_KEYS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** node keys */ -+#define SPA_KEY_NODE_NAME "node.name" /**< a node name */ -+#define SPA_KEY_NODE_LATENCY "node.latency" /**< the requested node latency */ -+ -+#define SPA_KEY_NODE_DRIVER "node.driver" /**< the node can be a driver */ -+#define SPA_KEY_NODE_ALWAYS_PROCESS "node.always-process" /**< call the process function even if -+ * not linked. */ -+#define SPA_KEY_NODE_PAUSE_ON_IDLE "node.pause-on-idle" /**< if the node should be paused -+ * immediately when idle. */ -+#define SPA_KEY_NODE_MONITOR "node.monitor" /**< the node has monitor ports */ -+ -+ -+/** port keys */ -+#define SPA_KEY_PORT_NAME "port.name" /**< a port name */ -+#define SPA_KEY_PORT_ALIAS "port.alias" /**< a port alias */ -+#define SPA_KEY_PORT_MONITOR "port.monitor" /**< this port is a monitor port */ -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_KEYS_H */ -diff --git a/third_party/pipewire/spa/node/node.h b/third_party/pipewire/spa/node/node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/node.h -@@ -0,0 +1,662 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_H -+#define SPA_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/** -+ * A spa_node is a component that can consume and produce buffers. -+ */ -+#define SPA_TYPE_INTERFACE_Node SPA_TYPE_INFO_INTERFACE_BASE "Node" -+ -+#define SPA_VERSION_NODE 0 -+struct spa_node { struct spa_interface iface; }; -+ -+/** -+ * Node information structure -+ * -+ * Contains the basic node information. -+ */ -+struct spa_node_info { -+ uint32_t max_input_ports; -+ uint32_t max_output_ports; -+#define SPA_NODE_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_NODE_CHANGE_MASK_PROPS (1u<<1) -+#define SPA_NODE_CHANGE_MASK_PARAMS (1u<<2) -+ uint64_t change_mask; -+ -+#define SPA_NODE_FLAG_RT (1u<<0) /**< node can do real-time processing */ -+#define SPA_NODE_FLAG_IN_DYNAMIC_PORTS (1u<<1) /**< input ports can be added/removed */ -+#define SPA_NODE_FLAG_OUT_DYNAMIC_PORTS (1u<<2) /**< output ports can be added/removed */ -+#define SPA_NODE_FLAG_IN_PORT_CONFIG (1u<<3) /**< input ports can be reconfigured with -+ * PortConfig parameter */ -+#define SPA_NODE_FLAG_OUT_PORT_CONFIG (1u<<4) /**< output ports can be reconfigured with -+ * PortConfig parameter */ -+#define SPA_NODE_FLAG_NEED_CONFIGURE (1u<<5) /**< node needs configuration before it can -+ * be started. */ -+#define SPA_NODE_FLAG_ASYNC (1u<<6) /**< the process function might not -+ * immediateley produce or consume data -+ * but might offload the work to a worker -+ * thread. */ -+ uint64_t flags; -+ struct spa_dict *props; /**< extra node properties */ -+ struct spa_param_info *params; /**< parameter information */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+#define SPA_NODE_INFO_INIT() (struct spa_node_info) { 0, } -+ -+/** -+ * Port information structure -+ * -+ * Contains the basic port information. -+ */ -+struct spa_port_info { -+#define SPA_PORT_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_PORT_CHANGE_MASK_RATE (1u<<1) -+#define SPA_PORT_CHANGE_MASK_PROPS (1u<<2) -+#define SPA_PORT_CHANGE_MASK_PARAMS (1u<<3) -+ uint64_t change_mask; -+ -+#define SPA_PORT_FLAG_REMOVABLE (1u<<0) /**< port can be removed */ -+#define SPA_PORT_FLAG_OPTIONAL (1u<<1) /**< processing on port is optional */ -+#define SPA_PORT_FLAG_CAN_ALLOC_BUFFERS (1u<<2) /**< the port can allocate buffer data */ -+#define SPA_PORT_FLAG_IN_PLACE (1u<<3) /**< the port can process data in-place and -+ * will need a writable input buffer */ -+#define SPA_PORT_FLAG_NO_REF (1u<<4) /**< the port does not keep a ref on the buffer. -+ * This means the node will always completely -+ * consume the input buffer and it will be -+ * recycled after process. */ -+#define SPA_PORT_FLAG_LIVE (1u<<5) /**< output buffers from this port are -+ * timestamped against a live clock. */ -+#define SPA_PORT_FLAG_PHYSICAL (1u<<6) /**< connects to some device */ -+#define SPA_PORT_FLAG_TERMINAL (1u<<7) /**< data was not created from this port -+ * or will not be made available on another -+ * port */ -+#define SPA_PORT_FLAG_DYNAMIC_DATA (1u<<8) /**< data pointer on buffers can be changed. -+ * Only the buffer data marked as DYNAMIC -+ * can be changed. */ -+ uint64_t flags; /**< port flags */ -+ struct spa_fraction rate; /**< rate of sequence numbers on port */ -+ const struct spa_dict *props; /**< extra port properties */ -+ struct spa_param_info *params; /**< parameter information */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+#define SPA_PORT_INFO_INIT() (struct spa_port_info) { 0, } -+ -+#define SPA_RESULT_TYPE_NODE_ERROR 1 -+#define SPA_RESULT_TYPE_NODE_PARAMS 2 -+ -+/** an error result */ -+struct spa_result_node_error { -+ const char *message; -+}; -+ -+/** the result of enum_params or port_enum_params. */ -+struct spa_result_node_params { -+ uint32_t id; /**< id of parameter */ -+ uint32_t index; /**< index of parameter */ -+ uint32_t next; /**< next index of iteration */ -+ struct spa_pod *param; /**< the result param */ -+}; -+ -+#define SPA_NODE_EVENT_INFO 0 -+#define SPA_NODE_EVENT_PORT_INFO 1 -+#define SPA_NODE_EVENT_RESULT 2 -+#define SPA_NODE_EVENT_EVENT 3 -+#define SPA_NODE_EVENT_NUM 4 -+ -+/** events from the spa_node. -+ * -+ * All event are called from the main thread and multiple -+ * listeners can be registered for the events with -+ * spa_node_add_listener(). -+ */ -+struct spa_node_events { -+#define SPA_VERSION_NODE_EVENTS 0 -+ uint32_t version; /**< version of this structure */ -+ -+ /** Emitted when info changes */ -+ void (*info) (void *data, const struct spa_node_info *info); -+ -+ /** Emitted when port info changes, NULL when port is removed */ -+ void (*port_info) (void *data, -+ enum spa_direction direction, uint32_t port, -+ const struct spa_port_info *info); -+ -+ /** notify a result. -+ * -+ * Some methods will trigger a result event with an optional -+ * result of the given type. Look at the documentation of the -+ * method to know when to expect a result event. -+ * -+ * The result event can be called synchronously, as an event -+ * called from inside the method itself, in which case the seq -+ * number passed to the method will be passed unchanged. -+ * -+ * The result event will be called asynchronously when the -+ * method returned an async return value. In this case, the seq -+ * number in the result will match the async return value of -+ * the method call. Users should match the seq number from -+ * request to the reply. -+ */ -+ void (*result) (void *data, int seq, int res, -+ uint32_t type, const void *result); -+ -+ /** -+ * \param node a spa_node -+ * \param event the event that was emitted -+ * -+ * This will be called when an out-of-bound event is notified -+ * on \a node. -+ */ -+ void (*event) (void *data, const struct spa_event *event); -+}; -+ -+#define SPA_NODE_CALLBACK_READY 0 -+#define SPA_NODE_CALLBACK_REUSE_BUFFER 1 -+#define SPA_NODE_CALLBACK_XRUN 2 -+#define SPA_NODE_CALLBACK_NUM 3 -+ -+/** Node callbacks -+ * -+ * Callbacks are called from the real-time data thread. Only -+ * one callback structure can be set on an spa_node. -+ */ -+struct spa_node_callbacks { -+#define SPA_VERSION_NODE_CALLBACKS 0 -+ uint32_t version; -+ /** -+ * \param node a spa_node -+ * -+ * The node is ready for processing. -+ * -+ * When this function is NULL, synchronous operation is requested -+ * on the ports. -+ */ -+ int (*ready) (void *data, int state); -+ -+ /** -+ * \param node a spa_node -+ * \param port_id an input port_id -+ * \param buffer_id the buffer id to be reused -+ * -+ * The node has a buffer that can be reused. -+ * -+ * When this function is NULL, the buffers to reuse will be set in -+ * the io area of the input ports. -+ */ -+ int (*reuse_buffer) (void *data, -+ uint32_t port_id, -+ uint32_t buffer_id); -+ -+ /** -+ * \param data user data -+ * \param trigger the timestamp in microseconds when the xrun happened -+ * \param delay the amount of microseconds of xrun. -+ * \param info an object with extra info (NULL for now) -+ * -+ * The node has encountered an over or underrun -+ * -+ * The info contains an object with more information -+ */ -+ int (*xrun) (void *data, uint64_t trigger, uint64_t delay, -+ struct spa_pod *info); -+}; -+ -+ -+/** flags that can be passed to set_param and port_set_param functions */ -+#define SPA_NODE_PARAM_FLAG_TEST_ONLY (1 << 0) /**< Just check if the param is accepted */ -+#define SPA_NODE_PARAM_FLAG_FIXATE (1 << 1) /**< Fixate the non-optional unset fields */ -+#define SPA_NODE_PARAM_FLAG_NEAREST (1 << 2) /**< Allow set fields to be rounded to the -+ * nearest allowed field value. */ -+ -+/** flags to pass to the use_buffers functions */ -+#define SPA_NODE_BUFFERS_FLAG_ALLOC (1 << 0) /**< Allocate memory for the buffers. This flag -+ * is ignored when the port does not have the -+ * SPA_PORT_FLAG_CAN_ALLOC_BUFFERS set. */ -+ -+ -+#define SPA_NODE_METHOD_ADD_LISTENER 0 -+#define SPA_NODE_METHOD_SET_CALLBACKS 1 -+#define SPA_NODE_METHOD_SYNC 2 -+#define SPA_NODE_METHOD_ENUM_PARAMS 3 -+#define SPA_NODE_METHOD_SET_PARAM 4 -+#define SPA_NODE_METHOD_SET_IO 5 -+#define SPA_NODE_METHOD_SEND_COMMAND 6 -+#define SPA_NODE_METHOD_ADD_PORT 7 -+#define SPA_NODE_METHOD_REMOVE_PORT 8 -+#define SPA_NODE_METHOD_PORT_ENUM_PARAMS 9 -+#define SPA_NODE_METHOD_PORT_SET_PARAM 10 -+#define SPA_NODE_METHOD_PORT_USE_BUFFERS 11 -+#define SPA_NODE_METHOD_PORT_SET_IO 12 -+#define SPA_NODE_METHOD_PORT_REUSE_BUFFER 13 -+#define SPA_NODE_METHOD_PROCESS 14 -+#define SPA_NODE_METHOD_NUM 15 -+ -+/** -+ * Node methods -+ */ -+struct spa_node_methods { -+ /* the version of the node methods. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_NODE_METHODS 0 -+ uint32_t version; -+ -+ /** -+ * Adds an event listener on \a node. -+ * -+ * Setting the events will trigger the info event and a -+ * port_info event for each managed port on the new -+ * listener. -+ * -+ * \param node a #spa_node -+ * \param listener a listener -+ * \param events a #struct spa_node_events -+ * \param data data passed as first argument in functions of \a events -+ * \return 0 on success -+ * < 0 errno on error -+ */ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct spa_node_events *events, -+ void *data); -+ /** -+ * Set callbacks to on \a node. -+ * if \a callbacks is NULL, the current callbacks are removed. -+ * -+ * This function must be called from the main thread. -+ * -+ * All callbacks are called from the data thread. -+ * -+ * \param node a spa_node -+ * \param callbacks callbacks to set -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ */ -+ int (*set_callbacks) (void *object, -+ const struct spa_node_callbacks *callbacks, -+ void *data); -+ /** -+ * Perform a sync operation. -+ * -+ * This method will emit the result event with the given sequence -+ * number synchronously or with the returned async return value -+ * asynchronously. -+ * -+ * Because all methods are serialized in the node, this can be used -+ * to wait for completion of all previous method calls. -+ * -+ * \param seq a sequence number -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ * an async result -+ */ -+ int (*sync) (void *object, int seq); -+ -+ /** -+ * Enumerate the parameters of a node. -+ * -+ * Parameters are identified with an \a id. Some parameters can have -+ * multiple values, see the documentation of the parameter id. -+ * -+ * Parameters can be filtered by passing a non-NULL \a filter. -+ * -+ * The function will emit the result event up to \a max times with -+ * the result value. The seq in the result will either be the \a seq -+ * number when executed synchronously or the async return value of -+ * this function when executed asynchronously. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a \ref spa_node -+ * \param seq a sequence number to pass to the result event when -+ * this method is executed synchronously. -+ * \param id the param id to enumerate -+ * \param start the index of enumeration, pass 0 for the first item -+ * \param max the maximum number of parameters to enumerate -+ * \param filter and optional filter to use -+ * -+ * \return 0 when no more items can be iterated. -+ * -EINVAL when invalid arguments are given -+ * -ENOENT the parameter \a id is unknown -+ * -ENOTSUP when there are no parameters -+ * implemented on \a node -+ * an async return value when the result event will be -+ * emitted later. -+ */ -+ int (*enum_params) (void *object, int seq, -+ uint32_t id, uint32_t start, uint32_t max, -+ const struct spa_pod *filter); -+ -+ /** -+ * Set the configurable parameter in \a node. -+ * -+ * Usually, \a param will be obtained from enum_params and then -+ * modified but it is also possible to set another spa_pod -+ * as long as its keys and types match a supported object. -+ * -+ * Objects with property keys that are not known are ignored. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a \ref spa_node -+ * \param id the parameter id to configure -+ * \param flags additional flags -+ * \param param the parameter to configure -+ * -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ * -ENOTSUP when there are no parameters implemented on \a node -+ * -ENOENT the parameter is unknown -+ */ -+ int (*set_param) (void *object, -+ uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+ -+ /** -+ * Configure the given memory area with \a id on \a node. This -+ * structure is allocated by the host and is used to exchange -+ * data and parameters with the node. -+ * -+ * Setting an \a io of NULL will disable the node io. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param id the id of the io area, the available ids can be -+ * enumerated with the node parameters. -+ * \param data a io area memory -+ * \param size the size of \a data -+ * \return 0 on success -+ * -EINVAL when invalid input is given -+ * -ENOENT when \a id is unknown -+ * -ENOSPC when \a size is too small -+ */ -+ int (*set_io) (void *object, -+ uint32_t id, void *data, size_t size); -+ -+ /** -+ * Send a command to a node. -+ * -+ * Upon completion, a command might change the state of a node. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a spa_node -+ * \param command a spa_command -+ * \return 0 on success -+ * -EINVAL when node or command is NULL -+ * -ENOTSUP when this node can't process commands -+ * -EINVAL \a command is an invalid command -+ */ -+ int (*send_command) (void *object, const struct spa_command *command); -+ -+ /** -+ * Make a new port with \a port_id. The caller should use the lowest unused -+ * port id for the given \a direction. -+ * -+ * Port ids should be between 0 and max_ports as obtained from the info -+ * event. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a spa_node -+ * \param direction a #enum spa_direction -+ * \param port_id an unused port id -+ * \param props extra properties -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ */ -+ int (*add_port) (void *object, -+ enum spa_direction direction, uint32_t port_id, -+ const struct spa_dict *props); -+ -+ /** -+ * Remove a port with \a port_id. -+ * -+ * \param node a spa_node -+ * \param direction a #enum spa_direction -+ * \param port_id a port id -+ * \return 0 on success -+ * -EINVAL when node is NULL or when port_id is unknown or -+ * when the port can't be removed. -+ */ -+ int (*remove_port) (void *object, -+ enum spa_direction direction, uint32_t port_id); -+ -+ /** -+ * Enumerate all possible parameters of \a id on \a port_id of \a node -+ * that are compatible with \a filter. -+ * -+ * The result parameters can be queried and modified and ultimately be used -+ * to call port_set_param. -+ * -+ * The function will emit the result event up to \a max times with -+ * the result value. The seq in the result event will either be the -+ * \a seq number when executed synchronously or the async return -+ * value of this function when executed asynchronously. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a spa_node -+ * \param seq a sequence number to pass to the result event when -+ * this method is executed synchronously. -+ * \param direction an spa_direction -+ * \param port_id the port to query -+ * \param id the parameter id to query -+ * \param start the first index to query, 0 to get the first item -+ * \param max the maximum number of params to query -+ * \param filter a parameter filter or NULL for no filter -+ * -+ * \return 0 when no more items can be iterated. -+ * -EINVAL when invalid parameters are given -+ * -ENOENT when \a id is unknown -+ * an async return value when the result event will be -+ * emitted later. -+ */ -+ int (*port_enum_params) (void *object, int seq, -+ enum spa_direction direction, uint32_t port_id, -+ uint32_t id, uint32_t start, uint32_t max, -+ const struct spa_pod *filter); -+ /** -+ * Set a parameter on \a port_id of \a node. -+ * -+ * When \a param is NULL, the parameter will be unset. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a #struct spa_node -+ * \param direction a #enum spa_direction -+ * \param port_id the port to configure -+ * \param id the parameter id to set -+ * \param flags optional flags -+ * \param param a #struct spa_pod with the parameter to set -+ * \return 0 on success -+ * 1 on success, the value of \a param might have been -+ * changed depending on \a flags and the final value can be found by -+ * doing port_enum_params. -+ * -EINVAL when node is NULL or invalid arguments are given -+ * -ESRCH when one of the mandatory param -+ * properties is not specified and SPA_NODE_PARAM_FLAG_FIXATE was -+ * not set in \a flags. -+ * -ESRCH when the type or size of a property is not correct. -+ * -ENOENT when the param id is not found -+ */ -+ int (*port_set_param) (void *object, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+ -+ /** -+ * Tell the port to use the given buffers -+ * -+ * When \a flags contains SPA_NODE_BUFFERS_FLAG_ALLOC, the data -+ * in the buffers should point to an array of at least 1 data entry -+ * with the desired supported type that will be filled by this function. -+ * -+ * The port should also have a spa_io_buffers io area configured to exchange -+ * the buffers with the port. -+ * -+ * For an input port, all the buffers will remain dequeued. -+ * Once a buffer has been queued on a port in the spa_io_buffers, -+ * it should not be reused until the reuse_buffer callback is notified -+ * or when the buffer has been returned in the spa_io_buffers of -+ * the port. -+ * -+ * For output ports, all buffers will be queued in the port. When process -+ * returns SPA_STATUS_HAVE_DATA, buffers are available in one or more -+ * of the spa_io_buffers areas. -+ * -+ * When a buffer can be reused, port_reuse_buffer() should be called or the -+ * buffer_id should be placed in the spa_io_buffers area before calling -+ * process. -+ * -+ * Passing NULL as \a buffers will remove the reference that the port has -+ * on the buffers. -+ * -+ * When this function returns async, use the spa_node_sync operation to -+ * wait for completion. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param object an object implementing the interface -+ * \param direction a port direction -+ * \param port_id a port id -+ * \param flags extra flags -+ * \param buffers an array of buffer pointers -+ * \param n_buffers number of elements in \a buffers -+ * \return 0 on success -+ */ -+ int (*port_use_buffers) (void *object, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t flags, -+ struct spa_buffer **buffers, -+ uint32_t n_buffers); -+ -+ /** -+ * Configure the given memory area with \a id on \a port_id. This -+ * structure is allocated by the host and is used to exchange -+ * data and parameters with the port. -+ * -+ * Setting an \a io of NULL will disable the port io. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param direction a spa_direction -+ * \param port_id a port id -+ * \param id the id of the io area, the available ids can be -+ * enumerated with the port parameters. -+ * \param data a io area memory -+ * \param size the size of \a data -+ * \return 0 on success -+ * -EINVAL when invalid input is given -+ * -ENOENT when \a id is unknown -+ * -ENOSPC when \a size is too small -+ */ -+ int (*port_set_io) (void *object, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t id, -+ void *data, size_t size); -+ -+ /** -+ * Tell an output port to reuse a buffer. -+ * -+ * This function must be called from the data thread. -+ * -+ * \param node a spa_node -+ * \param port_id a port id -+ * \param buffer_id a buffer id to reuse -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ */ -+ int (*port_reuse_buffer) (void *object, uint32_t port_id, uint32_t buffer_id); -+ -+ /** -+ * Process the node -+ * -+ * This function must be called from the data thread. -+ * -+ * Output io areas with SPA_STATUS_NEED_DATA will recycle the -+ * buffers if any. -+ * -+ * Input areas with SPA_STATUS_HAVE_DATA are consumed if possible -+ * and the status is set to SPA_STATUS_NEED_DATA or SPA_STATUS_OK. -+ * -+ * When the node has new output buffers, the SPA_STATUS_HAVE_DATA -+ * bit will be set. -+ * -+ * When the node can accept new input in the next cycle, the -+ * SPA_STATUS_NEED_DATA bit will be set. -+ */ -+ int (*process) (void *object); -+}; -+ -+#define spa_node_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_node *_n = o; \ -+ spa_interface_call_res(&_n->iface, \ -+ struct spa_node_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_node_add_listener(n,...) spa_node_method(n, add_listener, 0, __VA_ARGS__) -+#define spa_node_set_callbacks(n,...) spa_node_method(n, set_callbacks, 0, __VA_ARGS__) -+#define spa_node_sync(n,...) spa_node_method(n, sync, 0, __VA_ARGS__) -+#define spa_node_enum_params(n,...) spa_node_method(n, enum_params, 0, __VA_ARGS__) -+#define spa_node_set_param(n,...) spa_node_method(n, set_param, 0, __VA_ARGS__) -+#define spa_node_set_io(n,...) spa_node_method(n, set_io, 0, __VA_ARGS__) -+#define spa_node_send_command(n,...) spa_node_method(n, send_command, 0, __VA_ARGS__) -+#define spa_node_add_port(n,...) spa_node_method(n, add_port, 0, __VA_ARGS__) -+#define spa_node_remove_port(n,...) spa_node_method(n, remove_port, 0, __VA_ARGS__) -+#define spa_node_port_enum_params(n,...) spa_node_method(n, port_enum_params, 0, __VA_ARGS__) -+#define spa_node_port_set_param(n,...) spa_node_method(n, port_set_param, 0, __VA_ARGS__) -+#define spa_node_port_use_buffers(n,...) spa_node_method(n, port_use_buffers, 0, __VA_ARGS__) -+#define spa_node_port_set_io(n,...) spa_node_method(n, port_set_io, 0, __VA_ARGS__) -+ -+#define spa_node_port_reuse_buffer(n,...) spa_node_method(n, port_reuse_buffer, 0, __VA_ARGS__) -+#define spa_node_process(n) spa_node_method(n, process, 0) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_H */ -diff --git a/third_party/pipewire/spa/node/type-info.h b/third_party/pipewire/spa/node/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/type-info.h -@@ -0,0 +1,94 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_TYPES_H -+#define SPA_NODE_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+#include -+ -+#define SPA_TYPE_INFO_IO SPA_TYPE_INFO_ENUM_BASE "IO" -+#define SPA_TYPE_INFO_IO_BASE SPA_TYPE_INFO_IO ":" -+ -+static const struct spa_type_info spa_type_io[] = { -+ { SPA_IO_Invalid, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Invalid", NULL }, -+ { SPA_IO_Buffers, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Buffers", NULL }, -+ { SPA_IO_Range, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Range", NULL }, -+ { SPA_IO_Clock, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Clock", NULL }, -+ { SPA_IO_Latency, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Latency", NULL }, -+ { SPA_IO_Control, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Control", NULL }, -+ { SPA_IO_Notify, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Notify", NULL }, -+ { SPA_IO_Position, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Position", NULL }, -+ { SPA_IO_RateMatch, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "RateMatch", NULL }, -+ { SPA_IO_Memory, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Memory", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_NodeEvent SPA_TYPE_INFO_EVENT_BASE "Node" -+#define SPA_TYPE_INFO_NODE_EVENT_BASE SPA_TYPE_INFO_NodeEvent ":" -+ -+static const struct spa_type_info spa_type_node_event_id[] = { -+ { SPA_NODE_EVENT_Error, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Error", NULL }, -+ { SPA_NODE_EVENT_Buffering, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL }, -+ { SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+static const struct spa_type_info spa_type_node_event[] = { -+ { 0, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_EVENT_BASE, spa_type_node_event_id }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_NodeCommand SPA_TYPE_INFO_COMMAND_BASE "Node" -+#define SPA_TYPE_INFO_NODE_COMMAND_BASE SPA_TYPE_INFO_NodeCommand ":" -+ -+static const struct spa_type_info spa_type_node_command_id[] = { -+ { SPA_NODE_COMMAND_Suspend, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL }, -+ { SPA_NODE_COMMAND_Pause, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Pause", NULL }, -+ { SPA_NODE_COMMAND_Start, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Start", NULL }, -+ { SPA_NODE_COMMAND_Enable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Enable", NULL }, -+ { SPA_NODE_COMMAND_Disable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Disable", NULL }, -+ { SPA_NODE_COMMAND_Flush, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL }, -+ { SPA_NODE_COMMAND_Drain, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL }, -+ { SPA_NODE_COMMAND_Marker, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+static const struct spa_type_info spa_type_node_command[] = { -+ { 0, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_COMMAND_BASE, spa_type_node_command_id }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_TYPES_H */ -diff --git a/third_party/pipewire/spa/node/utils.h b/third_party/pipewire/spa/node/utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/utils.h -@@ -0,0 +1,144 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_UTILS_H -+#define SPA_NODE_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+struct spa_result_node_params_data { -+ struct spa_pod_builder *builder; -+ struct spa_result_node_params data; -+}; -+ -+static inline void spa_result_func_node_params(void *data, -+ int seq, int res, uint32_t type, const void *result) -+{ -+ struct spa_result_node_params_data *d = -+ (struct spa_result_node_params_data *) data; -+ const struct spa_result_node_params *r = -+ (const struct spa_result_node_params *) result; -+ uint32_t offset = d->builder->state.offset; -+ spa_pod_builder_raw_padded(d->builder, r->param, SPA_POD_SIZE(r->param)); -+ d->data.next = r->next; -+ d->data.param = SPA_MEMBER(d->builder->data, offset, struct spa_pod); -+} -+ -+static inline int spa_node_enum_params_sync(struct spa_node *node, -+ uint32_t id, uint32_t *index, -+ const struct spa_pod *filter, -+ struct spa_pod **param, -+ struct spa_pod_builder *builder) -+{ -+ struct spa_result_node_params_data data = { builder, }; -+ struct spa_hook listener = { 0 }; -+ static const struct spa_node_events node_events = { -+ SPA_VERSION_NODE_EVENTS, -+ .result = spa_result_func_node_params, -+ }; -+ int res; -+ -+ res = spa_node_add_listener(node, &listener, &node_events, &data); -+ if (res >= 0) { -+ res = spa_node_enum_params(node, 0, id, *index, 1, filter); -+ spa_hook_remove(&listener); -+ } -+ -+ if (data.data.param == NULL) { -+ if (res > 0) -+ res = 0; -+ } else { -+ *index = data.data.next; -+ *param = data.data.param; -+ res = 1; -+ } -+ return res; -+} -+ -+static inline int spa_node_port_enum_params_sync(struct spa_node *node, -+ enum spa_direction direction, uint32_t port_id, -+ uint32_t id, uint32_t *index, -+ const struct spa_pod *filter, -+ struct spa_pod **param, -+ struct spa_pod_builder *builder) -+{ -+ struct spa_result_node_params_data data = { builder, }; -+ struct spa_hook listener = { 0 }; -+ static const struct spa_node_events node_events = { -+ SPA_VERSION_NODE_EVENTS, -+ .result = spa_result_func_node_params, -+ }; -+ int res; -+ -+ res = spa_node_add_listener(node, &listener, &node_events, &data); -+ if (res >= 0) { -+ res = spa_node_port_enum_params(node, 0, direction, port_id, -+ id, *index, 1, filter); -+ spa_hook_remove(&listener); -+ } -+ -+ if (data.data.param == NULL) { -+ if (res > 0) -+ res = 0; -+ } else { -+ *index = data.data.next; -+ *param = data.data.param; -+ res = 1; -+ } -+ return res; -+} -+ -+#define spa_node_emit(hooks,method,version,...) \ -+ spa_hook_list_call_simple(hooks, struct spa_node_events, \ -+ method, version, ##__VA_ARGS__) -+ -+#define spa_node_emit_info(hooks,...) spa_node_emit(hooks,info, 0, __VA_ARGS__) -+#define spa_node_emit_port_info(hooks,...) spa_node_emit(hooks,port_info, 0, __VA_ARGS__) -+#define spa_node_emit_result(hooks,...) spa_node_emit(hooks,result, 0, __VA_ARGS__) -+#define spa_node_emit_event(hooks,...) spa_node_emit(hooks,event, 0, __VA_ARGS__) -+ -+ -+#define spa_node_call(callbacks,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_callbacks_call_res(callbacks, struct spa_node_callbacks, \ -+ _res, method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_node_call_ready(hook,...) spa_node_call(hook, ready, 0, __VA_ARGS__) -+#define spa_node_call_reuse_buffer(hook,...) spa_node_call(hook, reuse_buffer, 0, __VA_ARGS__) -+#define spa_node_call_xrun(hook,...) spa_node_call(hook, xrun, 0, __VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/audio/format-utils.h b/third_party/pipewire/spa/param/audio/format-utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/format-utils.h -@@ -0,0 +1,105 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_AUDIO_FORMAT_UTILS_H -+#define SPA_PARAM_AUDIO_FORMAT_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+#include -+#include -+#include -+#include -+ -+static inline int -+spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info) -+{ -+ struct spa_pod *position = NULL; -+ int res; -+ info->flags = 0; -+ res = spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format), -+ SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate), -+ SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info->channels), -+ SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); -+ if (position == NULL || -+ !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) -+ SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); -+ -+ return res; -+} -+ -+static inline int -+spa_format_audio_dsp_parse(const struct spa_pod *format, struct spa_audio_info_dsp *info) -+{ -+ int res; -+ res = spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format)); -+ return res; -+} -+ -+static inline struct spa_pod * -+spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_raw *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(info->format), -+ SPA_FORMAT_AUDIO_rate, SPA_POD_Int(info->rate), -+ SPA_FORMAT_AUDIO_channels, SPA_POD_Int(info->channels), -+ 0); -+ -+ if (!SPA_FLAG_IS_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { -+ spa_pod_builder_prop(builder, SPA_FORMAT_AUDIO_position, 0); -+ spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, -+ info->channels, info->position); -+ } -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+static inline struct spa_pod * -+spa_format_audio_dsp_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_dsp *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(info->format), -+ 0); -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_AUDIO_FORMAT_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/audio/format.h b/third_party/pipewire/spa/param/audio/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/format.h -@@ -0,0 +1,48 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_AUDIO_FORMAT_H -+#define SPA_PARAM_AUDIO_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_audio_info { -+ uint32_t media_type; -+ uint32_t media_subtype; -+ union { -+ struct spa_audio_info_raw raw; -+ struct spa_audio_info_dsp dsp; -+ } info; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_AUDIO_FORMAT_H */ -diff --git a/third_party/pipewire/spa/param/audio/layout.h b/third_party/pipewire/spa/param/audio/layout.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/layout.h -@@ -0,0 +1,184 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_AUDIO_LAYOUT_H -+#define SPA_AUDIO_LAYOUT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#ifndef __FreeBSD__ -+#include -+#endif -+ -+#include -+ -+struct spa_audio_layout_info { -+ uint32_t n_channels; -+ uint32_t position[SPA_AUDIO_MAX_CHANNELS]; -+}; -+ -+#define SPA_AUDIO_LAYOUT_Mono 1, { SPA_AUDIO_CHANNEL_MONO, } -+#define SPA_AUDIO_LAYOUT_Stereo 2, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, } -+#define SPA_AUDIO_LAYOUT_Quad 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, } -+#define SPA_AUDIO_LAYOUT_Pentagonal 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+#define SPA_AUDIO_LAYOUT_Hexagonal 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_Octagonal 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_Cube 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR }, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, \ -+ SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR, } -+ -+ -+#define SPA_AUDIO_LAYOUT_MPEG_1_0 SPA_AUDIO_LAYOUT_MONO -+#define SPA_AUDIO_LAYOUT_MPEG_2_0 SPA_AUDIO_LAYOUT_STEREO -+#define SPA_AUDIO_LAYOUT_MPEG_3_0A 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+#define SPA_AUDIO_LAYOUT_MPEG_3_0B 3, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, } -+#define SPA_AUDIO_LAYOUT_MPEG_4_0A 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_MPEG_4_0B 4, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0A 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0B 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0C 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FC, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0D 5, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1A 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1B 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1C 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FC, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1D 6, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_6_1A 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_MPEG_7_1A 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_7_1B 8, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RL, \ -+ SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_7_1C 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, } -+ -+ -+#define SPA_AUDIO_LAYOUT_2_1 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_LFE, } -+ -+#define SPA_AUDIO_LAYOUT_2RC 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_2FC 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+ -+#define SPA_AUDIO_LAYOUT_3_1 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_4_0 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_2_2 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+ -+#define SPA_AUDIO_LAYOUT_4_1 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_5_0 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_5_0R 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RL, \ -+ SPA_AUDIO_CHANNEL_RR, } -+#define SPA_AUDIO_LAYOUT_5_1 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_5_1R 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, } -+#define SPA_AUDIO_LAYOUT_6_0 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_6_0F 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FLC, SPA_AUDIO_CHANNEL_FRC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_6_1 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_6_1F 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_7_0 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RL, \ -+ SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_0F 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FLC, \ -+ SPA_AUDIO_CHANNEL_FRC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_1 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_1W 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_FLC, SPA_AUDIO_CHANNEL_FRC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_1WR 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FLC, SPA_AUDIO_CHANNEL_FRC, } -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_AUDIO_LAYOUT_H */ -diff --git a/third_party/pipewire/spa/param/audio/raw.h b/third_party/pipewire/spa/param/audio/raw.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/raw.h -@@ -0,0 +1,237 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_AUDIO_RAW_H -+#define SPA_AUDIO_RAW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef __FreeBSD__ -+#include -+#endif -+ -+#define SPA_AUDIO_MAX_CHANNELS 64u -+ -+enum spa_audio_format { -+ SPA_AUDIO_FORMAT_UNKNOWN, -+ SPA_AUDIO_FORMAT_ENCODED, -+ -+ /* interleaved formats */ -+ SPA_AUDIO_FORMAT_START_Interleaved = 0x100, -+ SPA_AUDIO_FORMAT_S8, -+ SPA_AUDIO_FORMAT_U8, -+ SPA_AUDIO_FORMAT_S16_LE, -+ SPA_AUDIO_FORMAT_S16_BE, -+ SPA_AUDIO_FORMAT_U16_LE, -+ SPA_AUDIO_FORMAT_U16_BE, -+ SPA_AUDIO_FORMAT_S24_32_LE, -+ SPA_AUDIO_FORMAT_S24_32_BE, -+ SPA_AUDIO_FORMAT_U24_32_LE, -+ SPA_AUDIO_FORMAT_U24_32_BE, -+ SPA_AUDIO_FORMAT_S32_LE, -+ SPA_AUDIO_FORMAT_S32_BE, -+ SPA_AUDIO_FORMAT_U32_LE, -+ SPA_AUDIO_FORMAT_U32_BE, -+ SPA_AUDIO_FORMAT_S24_LE, -+ SPA_AUDIO_FORMAT_S24_BE, -+ SPA_AUDIO_FORMAT_U24_LE, -+ SPA_AUDIO_FORMAT_U24_BE, -+ SPA_AUDIO_FORMAT_S20_LE, -+ SPA_AUDIO_FORMAT_S20_BE, -+ SPA_AUDIO_FORMAT_U20_LE, -+ SPA_AUDIO_FORMAT_U20_BE, -+ SPA_AUDIO_FORMAT_S18_LE, -+ SPA_AUDIO_FORMAT_S18_BE, -+ SPA_AUDIO_FORMAT_U18_LE, -+ SPA_AUDIO_FORMAT_U18_BE, -+ SPA_AUDIO_FORMAT_F32_LE, -+ SPA_AUDIO_FORMAT_F32_BE, -+ SPA_AUDIO_FORMAT_F64_LE, -+ SPA_AUDIO_FORMAT_F64_BE, -+ -+ /* planar formats */ -+ SPA_AUDIO_FORMAT_START_Planar = 0x200, -+ SPA_AUDIO_FORMAT_U8P, -+ SPA_AUDIO_FORMAT_S16P, -+ SPA_AUDIO_FORMAT_S24_32P, -+ SPA_AUDIO_FORMAT_S32P, -+ SPA_AUDIO_FORMAT_S24P, -+ SPA_AUDIO_FORMAT_F32P, -+ SPA_AUDIO_FORMAT_F64P, -+ -+ /* other formats start here */ -+ SPA_AUDIO_FORMAT_START_Other = 0x400, -+ -+ /* Aliases */ -+ -+ /* DSP formats */ -+ SPA_AUDIO_FORMAT_DSP_S32 = SPA_AUDIO_FORMAT_S24_32P, -+ SPA_AUDIO_FORMAT_DSP_F32 = SPA_AUDIO_FORMAT_F32P, -+ SPA_AUDIO_FORMAT_DSP_F64 = SPA_AUDIO_FORMAT_F64P, -+ -+ /* native endian */ -+#if __BYTE_ORDER == __BIG_ENDIAN -+ SPA_AUDIO_FORMAT_S16 = SPA_AUDIO_FORMAT_S16_BE, -+ SPA_AUDIO_FORMAT_U16 = SPA_AUDIO_FORMAT_U16_BE, -+ SPA_AUDIO_FORMAT_S24_32 = SPA_AUDIO_FORMAT_S24_32_BE, -+ SPA_AUDIO_FORMAT_U24_32 = SPA_AUDIO_FORMAT_U24_32_BE, -+ SPA_AUDIO_FORMAT_S32 = SPA_AUDIO_FORMAT_S32_BE, -+ SPA_AUDIO_FORMAT_U32 = SPA_AUDIO_FORMAT_U32_BE, -+ SPA_AUDIO_FORMAT_S24 = SPA_AUDIO_FORMAT_S24_BE, -+ SPA_AUDIO_FORMAT_U24 = SPA_AUDIO_FORMAT_U24_BE, -+ SPA_AUDIO_FORMAT_S20 = SPA_AUDIO_FORMAT_S20_BE, -+ SPA_AUDIO_FORMAT_U20 = SPA_AUDIO_FORMAT_U20_BE, -+ SPA_AUDIO_FORMAT_S18 = SPA_AUDIO_FORMAT_S18_BE, -+ SPA_AUDIO_FORMAT_U18 = SPA_AUDIO_FORMAT_U18_BE, -+ SPA_AUDIO_FORMAT_F32 = SPA_AUDIO_FORMAT_F32_BE, -+ SPA_AUDIO_FORMAT_F64 = SPA_AUDIO_FORMAT_F64_BE, -+ SPA_AUDIO_FORMAT_S16_OE = SPA_AUDIO_FORMAT_S16_LE, -+ SPA_AUDIO_FORMAT_U16_OE = SPA_AUDIO_FORMAT_U16_LE, -+ SPA_AUDIO_FORMAT_S24_32_OE = SPA_AUDIO_FORMAT_S24_32_LE, -+ SPA_AUDIO_FORMAT_U24_32_OE = SPA_AUDIO_FORMAT_U24_32_LE, -+ SPA_AUDIO_FORMAT_S32_OE = SPA_AUDIO_FORMAT_S32_LE, -+ SPA_AUDIO_FORMAT_U32_OE = SPA_AUDIO_FORMAT_U32_LE, -+ SPA_AUDIO_FORMAT_S24_OE = SPA_AUDIO_FORMAT_S24_LE, -+ SPA_AUDIO_FORMAT_U24_OE = SPA_AUDIO_FORMAT_U24_LE, -+ SPA_AUDIO_FORMAT_S20_OE = SPA_AUDIO_FORMAT_S20_LE, -+ SPA_AUDIO_FORMAT_U20_OE = SPA_AUDIO_FORMAT_U20_LE, -+ SPA_AUDIO_FORMAT_S18_OE = SPA_AUDIO_FORMAT_S18_LE, -+ SPA_AUDIO_FORMAT_U18_OE = SPA_AUDIO_FORMAT_U18_LE, -+ SPA_AUDIO_FORMAT_F32_OE = SPA_AUDIO_FORMAT_F32_LE, -+ SPA_AUDIO_FORMAT_F64_OE = SPA_AUDIO_FORMAT_F64_LE, -+#elif __BYTE_ORDER == __LITTLE_ENDIAN -+ SPA_AUDIO_FORMAT_S16 = SPA_AUDIO_FORMAT_S16_LE, -+ SPA_AUDIO_FORMAT_U16 = SPA_AUDIO_FORMAT_U16_LE, -+ SPA_AUDIO_FORMAT_S24_32 = SPA_AUDIO_FORMAT_S24_32_LE, -+ SPA_AUDIO_FORMAT_U24_32 = SPA_AUDIO_FORMAT_U24_32_LE, -+ SPA_AUDIO_FORMAT_S32 = SPA_AUDIO_FORMAT_S32_LE, -+ SPA_AUDIO_FORMAT_U32 = SPA_AUDIO_FORMAT_U32_LE, -+ SPA_AUDIO_FORMAT_S24 = SPA_AUDIO_FORMAT_S24_LE, -+ SPA_AUDIO_FORMAT_U24 = SPA_AUDIO_FORMAT_U24_LE, -+ SPA_AUDIO_FORMAT_S20 = SPA_AUDIO_FORMAT_S20_LE, -+ SPA_AUDIO_FORMAT_U20 = SPA_AUDIO_FORMAT_U20_LE, -+ SPA_AUDIO_FORMAT_S18 = SPA_AUDIO_FORMAT_S18_LE, -+ SPA_AUDIO_FORMAT_U18 = SPA_AUDIO_FORMAT_U18_LE, -+ SPA_AUDIO_FORMAT_F32 = SPA_AUDIO_FORMAT_F32_LE, -+ SPA_AUDIO_FORMAT_F64 = SPA_AUDIO_FORMAT_F64_LE, -+ SPA_AUDIO_FORMAT_S16_OE = SPA_AUDIO_FORMAT_S16_BE, -+ SPA_AUDIO_FORMAT_U16_OE = SPA_AUDIO_FORMAT_U16_BE, -+ SPA_AUDIO_FORMAT_S24_32_OE = SPA_AUDIO_FORMAT_S24_32_BE, -+ SPA_AUDIO_FORMAT_U24_32_OE = SPA_AUDIO_FORMAT_U24_32_BE, -+ SPA_AUDIO_FORMAT_S32_OE = SPA_AUDIO_FORMAT_S32_BE, -+ SPA_AUDIO_FORMAT_U32_OE = SPA_AUDIO_FORMAT_U32_BE, -+ SPA_AUDIO_FORMAT_S24_OE = SPA_AUDIO_FORMAT_S24_BE, -+ SPA_AUDIO_FORMAT_U24_OE = SPA_AUDIO_FORMAT_U24_BE, -+ SPA_AUDIO_FORMAT_S20_OE = SPA_AUDIO_FORMAT_S20_BE, -+ SPA_AUDIO_FORMAT_U20_OE = SPA_AUDIO_FORMAT_U20_BE, -+ SPA_AUDIO_FORMAT_S18_OE = SPA_AUDIO_FORMAT_S18_BE, -+ SPA_AUDIO_FORMAT_U18_OE = SPA_AUDIO_FORMAT_U18_BE, -+ SPA_AUDIO_FORMAT_F32_OE = SPA_AUDIO_FORMAT_F32_BE, -+ SPA_AUDIO_FORMAT_F64_OE = SPA_AUDIO_FORMAT_F64_BE, -+#endif -+}; -+ -+#define SPA_AUDIO_FORMAT_IS_INTERLEAVED(fmt) ((fmt) > SPA_AUDIO_FORMAT_START_Interleaved && (fmt) < SPA_AUDIO_FORMAT_START_Planar) -+#define SPA_AUDIO_FORMAT_IS_PLANAR(fmt) ((fmt) > SPA_AUDIO_FORMAT_START_Planar && (fmt) < SPA_AUDIO_FORMAT_START_Other) -+ -+enum spa_audio_channel { -+ SPA_AUDIO_CHANNEL_UNKNOWN, /**< unspecified */ -+ SPA_AUDIO_CHANNEL_NA, /**< N/A, silent */ -+ -+ SPA_AUDIO_CHANNEL_MONO, /**< mono stream */ -+ -+ SPA_AUDIO_CHANNEL_FL, /**< front left */ -+ SPA_AUDIO_CHANNEL_FR, /**< front right */ -+ SPA_AUDIO_CHANNEL_FC, /**< front center */ -+ SPA_AUDIO_CHANNEL_LFE, /**< LFE */ -+ SPA_AUDIO_CHANNEL_SL, /**< side left */ -+ SPA_AUDIO_CHANNEL_SR, /**< side right */ -+ SPA_AUDIO_CHANNEL_FLC, /**< front left center */ -+ SPA_AUDIO_CHANNEL_FRC, /**< front right center */ -+ SPA_AUDIO_CHANNEL_RC, /**< rear center */ -+ SPA_AUDIO_CHANNEL_RL, /**< rear left */ -+ SPA_AUDIO_CHANNEL_RR, /**< rear right */ -+ SPA_AUDIO_CHANNEL_TC, /**< top center */ -+ SPA_AUDIO_CHANNEL_TFL, /**< top front left */ -+ SPA_AUDIO_CHANNEL_TFC, /**< top front center */ -+ SPA_AUDIO_CHANNEL_TFR, /**< top front right */ -+ SPA_AUDIO_CHANNEL_TRL, /**< top rear left */ -+ SPA_AUDIO_CHANNEL_TRC, /**< top rear center */ -+ SPA_AUDIO_CHANNEL_TRR, /**< top rear right */ -+ SPA_AUDIO_CHANNEL_RLC, /**< rear left center */ -+ SPA_AUDIO_CHANNEL_RRC, /**< rear right center */ -+ SPA_AUDIO_CHANNEL_FLW, /**< front left wide */ -+ SPA_AUDIO_CHANNEL_FRW, /**< front right wide */ -+ SPA_AUDIO_CHANNEL_LFE2, /**< LFE 2 */ -+ SPA_AUDIO_CHANNEL_FLH, /**< front left high */ -+ SPA_AUDIO_CHANNEL_FCH, /**< front center high */ -+ SPA_AUDIO_CHANNEL_FRH, /**< front right high */ -+ SPA_AUDIO_CHANNEL_TFLC, /**< top front left center */ -+ SPA_AUDIO_CHANNEL_TFRC, /**< top front right center */ -+ SPA_AUDIO_CHANNEL_TSL, /**< top side left */ -+ SPA_AUDIO_CHANNEL_TSR, /**< top side right */ -+ SPA_AUDIO_CHANNEL_LLFE, /**< left LFE */ -+ SPA_AUDIO_CHANNEL_RLFE, /**< right LFE */ -+ SPA_AUDIO_CHANNEL_BC, /**< bottom center */ -+ SPA_AUDIO_CHANNEL_BLC, /**< bottom left center */ -+ SPA_AUDIO_CHANNEL_BRC, /**< bottom right center */ -+ -+ SPA_AUDIO_CHANNEL_CUSTOM_START = 0x10000, -+}; -+ -+/** Extra audio flags */ -+#define SPA_AUDIO_FLAG_NONE (0) /*< no valid flag */ -+#define SPA_AUDIO_FLAG_UNPOSITIONED (1 << 0) /*< the position array explicitly -+ * contains unpositioned channels. */ -+/** Audio information description */ -+struct spa_audio_info_raw { -+ enum spa_audio_format format; /*< format, one of enum spa_audio_format */ -+ uint32_t flags; /*< extra flags */ -+ uint32_t rate; /*< sample rate */ -+ uint32_t channels; /*< number of channels */ -+ uint32_t position[SPA_AUDIO_MAX_CHANNELS]; /*< channel position from enum spa_audio_channel */ -+}; -+ -+#define SPA_AUDIO_INFO_RAW_INIT(...) (struct spa_audio_info_raw) { __VA_ARGS__ } -+ -+#define SPA_KEY_AUDIO_CHANNEL "audio.channel" /**< an audio channel as string, -+ * Ex. "FL" */ -+#define SPA_KEY_AUDIO_CHANNELS "audio.channels" /**< an audio channel count as int */ -+#define SPA_KEY_AUDIO_RATE "audio.rate" /**< an audio sample rate as int */ -+ -+struct spa_audio_info_dsp { -+ enum spa_audio_format format; /*< format, one of the DSP formats in enum spa_audio_format_dsp */ -+}; -+ -+#define SPA_AUDIO_INFO_DSP_INIT(...) (struct spa_audio_info_dsp) { __VA_ARGS__ } -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_AUDIO_RAW_H */ -diff --git a/third_party/pipewire/spa/param/audio/type-info.h b/third_party/pipewire/spa/param/audio/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/type-info.h -@@ -0,0 +1,140 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_AUDIO_TYPES_H -+#define SPA_AUDIO_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#define SPA_TYPE_INFO_AudioFormat SPA_TYPE_INFO_ENUM_BASE "AudioFormat" -+#define SPA_TYPE_INFO_AUDIO_FORMAT_BASE SPA_TYPE_INFO_AudioFormat ":" -+ -+static const struct spa_type_info spa_type_audio_format[] = { -+ { SPA_AUDIO_FORMAT_UNKNOWN, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "UNKNOWN", NULL }, -+ { SPA_AUDIO_FORMAT_ENCODED, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "ENCODED", NULL }, -+ { SPA_AUDIO_FORMAT_S8, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S8", NULL }, -+ { SPA_AUDIO_FORMAT_U8, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U8", NULL }, -+ { SPA_AUDIO_FORMAT_S16_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S16LE", NULL }, -+ { SPA_AUDIO_FORMAT_S16_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S16BE", NULL }, -+ { SPA_AUDIO_FORMAT_U16_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U16LE", NULL }, -+ { SPA_AUDIO_FORMAT_U16_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U16BE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24_32LE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24_32BE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24_32LE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24_32BE", NULL }, -+ { SPA_AUDIO_FORMAT_S32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S32LE", NULL }, -+ { SPA_AUDIO_FORMAT_S32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S32BE", NULL }, -+ { SPA_AUDIO_FORMAT_U32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U32LE", NULL }, -+ { SPA_AUDIO_FORMAT_U32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U32BE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24LE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24BE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24LE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24BE", NULL }, -+ { SPA_AUDIO_FORMAT_S20_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S20LE", NULL }, -+ { SPA_AUDIO_FORMAT_S20_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S20BE", NULL }, -+ { SPA_AUDIO_FORMAT_U20_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U20LE", NULL }, -+ { SPA_AUDIO_FORMAT_U20_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U20BE", NULL }, -+ { SPA_AUDIO_FORMAT_S18_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S18LE", NULL }, -+ { SPA_AUDIO_FORMAT_S18_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S18BE", NULL }, -+ { SPA_AUDIO_FORMAT_U18_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U18LE", NULL }, -+ { SPA_AUDIO_FORMAT_U18_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U18BE", NULL }, -+ { SPA_AUDIO_FORMAT_F32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F32LE", NULL }, -+ { SPA_AUDIO_FORMAT_F32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F32BE", NULL }, -+ { SPA_AUDIO_FORMAT_F64_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F64LE", NULL }, -+ { SPA_AUDIO_FORMAT_F64_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F64BE", NULL }, -+ -+ { SPA_AUDIO_FORMAT_U8P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U8P", NULL }, -+ { SPA_AUDIO_FORMAT_S16P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S16P", NULL }, -+ { SPA_AUDIO_FORMAT_S24_32P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24_32P", NULL }, -+ { SPA_AUDIO_FORMAT_S32P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S32P", NULL }, -+ { SPA_AUDIO_FORMAT_S24P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24P", NULL }, -+ { SPA_AUDIO_FORMAT_F32P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F32P", NULL }, -+ { SPA_AUDIO_FORMAT_F64P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F64P", NULL }, -+ -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_AudioFlags SPA_TYPE_INFO_FLAGS_BASE "AudioFlags" -+#define SPA_TYPE_INFO_AUDIO_FLAGS_BASE SPA_TYPE_INFO_AudioFlags ":" -+ -+static const struct spa_type_info spa_type_audio_flags[] = { -+ { SPA_AUDIO_FLAG_NONE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FLAGS_BASE "none", NULL }, -+ { SPA_AUDIO_FLAG_UNPOSITIONED, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FLAGS_BASE "unpositioned", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_AudioChannel SPA_TYPE_INFO_ENUM_BASE "AudioChannel" -+#define SPA_TYPE_INFO_AUDIO_CHANNEL_BASE SPA_TYPE_INFO_AudioChannel ":" -+ -+static const struct spa_type_info spa_type_audio_channel[] = { -+ { SPA_AUDIO_CHANNEL_UNKNOWN, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "UNK", NULL }, -+ { SPA_AUDIO_CHANNEL_NA, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "NA", NULL }, -+ { SPA_AUDIO_CHANNEL_MONO, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "MONO", NULL }, -+ { SPA_AUDIO_CHANNEL_FL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FL", NULL }, -+ { SPA_AUDIO_CHANNEL_FR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FR", NULL }, -+ { SPA_AUDIO_CHANNEL_FC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FC", NULL }, -+ { SPA_AUDIO_CHANNEL_LFE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "LFE", NULL }, -+ { SPA_AUDIO_CHANNEL_SL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "SL", NULL }, -+ { SPA_AUDIO_CHANNEL_SR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "SR", NULL }, -+ { SPA_AUDIO_CHANNEL_FLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FLC", NULL }, -+ { SPA_AUDIO_CHANNEL_FRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FRC", NULL }, -+ { SPA_AUDIO_CHANNEL_RC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RC", NULL }, -+ { SPA_AUDIO_CHANNEL_RL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RL", NULL }, -+ { SPA_AUDIO_CHANNEL_RR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RR", NULL }, -+ { SPA_AUDIO_CHANNEL_TC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TC", NULL }, -+ { SPA_AUDIO_CHANNEL_TFL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFL", NULL }, -+ { SPA_AUDIO_CHANNEL_TFC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFC", NULL }, -+ { SPA_AUDIO_CHANNEL_TFR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFR", NULL }, -+ { SPA_AUDIO_CHANNEL_TRL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TRL", NULL }, -+ { SPA_AUDIO_CHANNEL_TRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TRC", NULL }, -+ { SPA_AUDIO_CHANNEL_TRR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TRR", NULL }, -+ { SPA_AUDIO_CHANNEL_RLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RLC", NULL }, -+ { SPA_AUDIO_CHANNEL_RRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RRC", NULL }, -+ { SPA_AUDIO_CHANNEL_FLW, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FLW", NULL }, -+ { SPA_AUDIO_CHANNEL_FRW, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FRW", NULL }, -+ { SPA_AUDIO_CHANNEL_LFE2, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "LFE2", NULL }, -+ { SPA_AUDIO_CHANNEL_FLH, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FLH", NULL }, -+ { SPA_AUDIO_CHANNEL_FCH, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FCH", NULL }, -+ { SPA_AUDIO_CHANNEL_FRH, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FRH", NULL }, -+ { SPA_AUDIO_CHANNEL_TFLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFLC", NULL }, -+ { SPA_AUDIO_CHANNEL_TFRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFRC", NULL }, -+ { SPA_AUDIO_CHANNEL_TSL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TSL", NULL }, -+ { SPA_AUDIO_CHANNEL_TSR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TSR", NULL }, -+ { SPA_AUDIO_CHANNEL_LLFE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "LLFR", NULL }, -+ { SPA_AUDIO_CHANNEL_RLFE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RLFE", NULL }, -+ { SPA_AUDIO_CHANNEL_BC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "BC", NULL }, -+ { SPA_AUDIO_CHANNEL_BLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "BLC", NULL }, -+ { SPA_AUDIO_CHANNEL_BRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "BRC", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_AUDIO_RAW_TYPES_H */ -diff --git a/third_party/pipewire/spa/param/format-utils.h b/third_party/pipewire/spa/param/format-utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/format-utils.h -@@ -0,0 +1,49 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_FORMAT_UTILS_H -+#define SPA_PARAM_FORMAT_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+#include -+#include -+ -+static inline int -+spa_format_parse(const struct spa_pod *format, uint32_t *media_type, uint32_t *media_subtype) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_mediaType, SPA_POD_Id(media_type), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(media_subtype)); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_FORMAT_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/format.h b/third_party/pipewire/spa/param/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/format.h -@@ -0,0 +1,147 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_FORMAT_H -+#define SPA_PARAM_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** media type for SPA_TYPE_OBJECT_Format */ -+enum spa_media_type { -+ SPA_MEDIA_TYPE_unknown, -+ SPA_MEDIA_TYPE_audio, -+ SPA_MEDIA_TYPE_video, -+ SPA_MEDIA_TYPE_image, -+ SPA_MEDIA_TYPE_binary, -+ SPA_MEDIA_TYPE_stream, -+ SPA_MEDIA_TYPE_application, -+}; -+ -+/** media subtype for SPA_TYPE_OBJECT_Format */ -+enum spa_media_subtype { -+ SPA_MEDIA_SUBTYPE_unknown, -+ SPA_MEDIA_SUBTYPE_raw, -+ SPA_MEDIA_SUBTYPE_dsp, -+ -+ SPA_MEDIA_SUBTYPE_START_Audio = 0x10000, -+ SPA_MEDIA_SUBTYPE_mp3, -+ SPA_MEDIA_SUBTYPE_aac, -+ SPA_MEDIA_SUBTYPE_vorbis, -+ SPA_MEDIA_SUBTYPE_wma, -+ SPA_MEDIA_SUBTYPE_ra, -+ SPA_MEDIA_SUBTYPE_sbc, -+ SPA_MEDIA_SUBTYPE_adpcm, -+ SPA_MEDIA_SUBTYPE_g723, -+ SPA_MEDIA_SUBTYPE_g726, -+ SPA_MEDIA_SUBTYPE_g729, -+ SPA_MEDIA_SUBTYPE_amr, -+ SPA_MEDIA_SUBTYPE_gsm, -+ -+ SPA_MEDIA_SUBTYPE_START_Video = 0x20000, -+ SPA_MEDIA_SUBTYPE_h264, -+ SPA_MEDIA_SUBTYPE_mjpg, -+ SPA_MEDIA_SUBTYPE_dv, -+ SPA_MEDIA_SUBTYPE_mpegts, -+ SPA_MEDIA_SUBTYPE_h263, -+ SPA_MEDIA_SUBTYPE_mpeg1, -+ SPA_MEDIA_SUBTYPE_mpeg2, -+ SPA_MEDIA_SUBTYPE_mpeg4, -+ SPA_MEDIA_SUBTYPE_xvid, -+ SPA_MEDIA_SUBTYPE_vc1, -+ SPA_MEDIA_SUBTYPE_vp8, -+ SPA_MEDIA_SUBTYPE_vp9, -+ SPA_MEDIA_SUBTYPE_bayer, -+ -+ SPA_MEDIA_SUBTYPE_START_Image = 0x30000, -+ SPA_MEDIA_SUBTYPE_jpeg, -+ -+ SPA_MEDIA_SUBTYPE_START_Binary = 0x40000, -+ -+ SPA_MEDIA_SUBTYPE_START_Stream = 0x50000, -+ SPA_MEDIA_SUBTYPE_midi, -+ -+ SPA_MEDIA_SUBTYPE_START_Application = 0x60000, -+ SPA_MEDIA_SUBTYPE_control, /**< control stream, data contains -+ * spa_pod_sequence with control info. */ -+}; -+ -+/** properties for audio SPA_TYPE_OBJECT_Format */ -+enum spa_format { -+ SPA_FORMAT_START, -+ -+ SPA_FORMAT_mediaType, /**< media type (Id enum spa_media_type) */ -+ SPA_FORMAT_mediaSubtype, /**< media subtype (Id enum spa_media_subtype) */ -+ -+ /* Audio format keys */ -+ SPA_FORMAT_START_Audio = 0x10000, -+ SPA_FORMAT_AUDIO_format, /**< audio format, (Id enum spa_audio_format) */ -+ SPA_FORMAT_AUDIO_flags, /**< optional flags (Int) */ -+ SPA_FORMAT_AUDIO_rate, /**< sample rate (Int) */ -+ SPA_FORMAT_AUDIO_channels, /**< number of audio channels (Int) */ -+ SPA_FORMAT_AUDIO_position, /**< channel positions (Id enum spa_audio_position) */ -+ -+ /* Video Format keys */ -+ SPA_FORMAT_START_Video = 0x20000, -+ SPA_FORMAT_VIDEO_format, /**< video format (Id enum spa_video_format) */ -+ SPA_FORMAT_VIDEO_modifier, /**< format modifier (Long) */ -+ SPA_FORMAT_VIDEO_size, /**< size (Rectangle) */ -+ SPA_FORMAT_VIDEO_framerate, /**< frame rate (Fraction) */ -+ SPA_FORMAT_VIDEO_maxFramerate, /**< maximum frame rate (Fraction) */ -+ SPA_FORMAT_VIDEO_views, /**< number of views (Int) */ -+ SPA_FORMAT_VIDEO_interlaceMode, /**< (Id enum spa_video_interlace_mode) */ -+ SPA_FORMAT_VIDEO_pixelAspectRatio, /**< (Rectangle) */ -+ SPA_FORMAT_VIDEO_multiviewMode, /**< (Id enum spa_video_multiview_mode) */ -+ SPA_FORMAT_VIDEO_multiviewFlags, /**< (Id enum spa_video_multiview_flags) */ -+ SPA_FORMAT_VIDEO_chromaSite, /**< /Id enum spa_video_chroma_site) */ -+ SPA_FORMAT_VIDEO_colorRange, /**< /Id enum spa_video_color_range) */ -+ SPA_FORMAT_VIDEO_colorMatrix, /**< /Id enum spa_video_color_matrix) */ -+ SPA_FORMAT_VIDEO_transferFunction, /**< /Id enum spa_video_transfer_function) */ -+ SPA_FORMAT_VIDEO_colorPrimaries, /**< /Id enum spa_video_color_primaries) */ -+ SPA_FORMAT_VIDEO_profile, /**< (Int) */ -+ SPA_FORMAT_VIDEO_level, /**< (Int) */ -+ SPA_FORMAT_VIDEO_H264_streamFormat, /**< (Id enum spa_h264_stream_format) */ -+ SPA_FORMAT_VIDEO_H264_alignment, /**< (Id enum spa_h264_alignment) */ -+ -+ /* Image Format keys */ -+ SPA_FORMAT_START_Image = 0x30000, -+ /* Binary Format keys */ -+ SPA_FORMAT_START_Binary = 0x40000, -+ /* Stream Format keys */ -+ SPA_FORMAT_START_Stream = 0x50000, -+ /* Application Format keys */ -+ SPA_FORMAT_START_Application = 0x60000, -+}; -+ -+#define SPA_KEY_FORMAT_DSP "format.dsp" /**< a predefined DSP format, -+ * Ex. "32 bit float mono audio" */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_FORMAT_H */ -diff --git a/third_party/pipewire/spa/param/param.h b/third_party/pipewire/spa/param/param.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/param.h -@@ -0,0 +1,166 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_H -+#define SPA_PARAM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** different parameter types that can be queried */ -+enum spa_param_type { -+ SPA_PARAM_Invalid, /**< invalid */ -+ SPA_PARAM_PropInfo, /**< property information as SPA_TYPE_OBJECT_PropInfo */ -+ SPA_PARAM_Props, /**< properties as SPA_TYPE_OBJECT_Props */ -+ SPA_PARAM_EnumFormat, /**< available formats as SPA_TYPE_OBJECT_Format */ -+ SPA_PARAM_Format, /**< configured format as SPA_TYPE_OBJECT_Format */ -+ SPA_PARAM_Buffers, /**< buffer configurations as SPA_TYPE_OBJECT_ParamBuffers*/ -+ SPA_PARAM_Meta, /**< allowed metadata for buffers as SPA_TYPE_OBJECT_ParamMeta*/ -+ SPA_PARAM_IO, /**< configurable IO areas as SPA_TYPE_OBJECT_ParamIO */ -+ SPA_PARAM_EnumProfile, /**< profile enumeration as SPA_TYPE_OBJECT_ParamProfile */ -+ SPA_PARAM_Profile, /**< profile configuration as SPA_TYPE_OBJECT_ParamProfile */ -+ SPA_PARAM_EnumPortConfig, /**< port configuration enumeration as SPA_TYPE_OBJECT_ParamPortConfig */ -+ SPA_PARAM_PortConfig, /**< port configuration as SPA_TYPE_OBJECT_ParamPortConfig */ -+ SPA_PARAM_EnumRoute, /**< routing enumeration as SPA_TYPE_OBJECT_ParamRoute */ -+ SPA_PARAM_Route, /**< routing configuration as SPA_TYPE_OBJECT_ParamRoute */ -+ SPA_PARAM_Control, /**< Control parameter, a SPA_TYPE_Sequence */ -+}; -+ -+/** information about a parameter */ -+struct spa_param_info { -+ uint32_t id; /**< enum spa_param_type */ -+#define SPA_PARAM_INFO_SERIAL (1<<0) /**< bit to signal update even when the -+ * read/write flags don't change */ -+#define SPA_PARAM_INFO_READ (1<<1) -+#define SPA_PARAM_INFO_WRITE (1<<2) -+#define SPA_PARAM_INFO_READWRITE (SPA_PARAM_INFO_WRITE|SPA_PARAM_INFO_READ) -+ uint32_t flags; -+ uint32_t user; /**< private user field. You can use this to keep -+ * state. */ -+ uint32_t padding[5]; -+}; -+ -+#define SPA_PARAM_INFO(id,flags) (struct spa_param_info){ (id), (flags) } -+ -+/** properties for SPA_TYPE_OBJECT_ParamBuffers */ -+enum spa_param_buffers { -+ SPA_PARAM_BUFFERS_START, -+ SPA_PARAM_BUFFERS_buffers, /**< number of buffers (Int) */ -+ SPA_PARAM_BUFFERS_blocks, /**< number of data blocks per buffer (Int) */ -+ SPA_PARAM_BUFFERS_size, /**< size of a data block memory (Int)*/ -+ SPA_PARAM_BUFFERS_stride, /**< stride of data block memory (Int) */ -+ SPA_PARAM_BUFFERS_align, /**< alignment of data block memory (Int) */ -+ SPA_PARAM_BUFFERS_dataType, /**< possible memory types (Int, mask of enum spa_data_type) */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamMeta */ -+enum spa_param_meta { -+ SPA_PARAM_META_START, -+ SPA_PARAM_META_type, /**< the metadata, one of enum spa_meta_type (Id enum spa_meta_type) */ -+ SPA_PARAM_META_size, /**< the expected maximum size the meta (Int) */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamIO */ -+enum spa_param_io { -+ SPA_PARAM_IO_START, -+ SPA_PARAM_IO_id, /**< type ID, uniquely identifies the io area (Id enum spa_io_type) */ -+ SPA_PARAM_IO_size, /**< size of the io area (Int) */ -+}; -+ -+enum spa_param_availability { -+ SPA_PARAM_AVAILABILITY_unknown, /**< unknown availability */ -+ SPA_PARAM_AVAILABILITY_no, /**< not available */ -+ SPA_PARAM_AVAILABILITY_yes, /**< available */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamProfile */ -+enum spa_param_profile { -+ SPA_PARAM_PROFILE_START, -+ SPA_PARAM_PROFILE_index, /**< profile index (Int) */ -+ SPA_PARAM_PROFILE_name, /**< profile name (String) */ -+ SPA_PARAM_PROFILE_description, /**< profile description (String) */ -+ SPA_PARAM_PROFILE_priority, /**< profile priority (Int) */ -+ SPA_PARAM_PROFILE_available, /**< availability of the profile -+ * (Id enum spa_param_availability) */ -+ SPA_PARAM_PROFILE_info, /**< info (Struct( -+ * Int : n_items, -+ * (String : key, -+ * String : value)*)) */ -+ SPA_PARAM_PROFILE_classes, /**< node classes provided by this profile -+ * (Struct( -+ * Int : number of items following -+ * Struct( -+ * String : class name (eg. "Audio/Source"), -+ * Int : number of nodes)*)) */ -+}; -+ -+enum spa_param_port_config_mode { -+ SPA_PARAM_PORT_CONFIG_MODE_none, /**< no configuration */ -+ SPA_PARAM_PORT_CONFIG_MODE_passthrough, /**< passthrough configuration */ -+ SPA_PARAM_PORT_CONFIG_MODE_convert, /**< convert configuration */ -+ SPA_PARAM_PORT_CONFIG_MODE_dsp, /**< dsp configuration, depending on the external -+ * format. For audio, ports will be configured for -+ * the given number of channels with F32 format. */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamPortConfig */ -+enum spa_param_port_config { -+ SPA_PARAM_PORT_CONFIG_START, -+ SPA_PARAM_PORT_CONFIG_direction, /**< direction, input/output (Id enum spa_direction) */ -+ SPA_PARAM_PORT_CONFIG_mode, /**< (Id enum spa_param_port_config_mode) mode */ -+ SPA_PARAM_PORT_CONFIG_monitor, /**< (Bool) enable monitor output ports on input ports */ -+ SPA_PARAM_PORT_CONFIG_control, /**< (Bool) enable control ports */ -+ SPA_PARAM_PORT_CONFIG_format, /**< (Object) format filter */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamRoute */ -+enum spa_param_route { -+ SPA_PARAM_ROUTE_START, -+ SPA_PARAM_ROUTE_index, /**< index of the routing destination (Int) */ -+ SPA_PARAM_ROUTE_direction, /**< direction, input/output (Id enum spa_direction) */ -+ SPA_PARAM_ROUTE_device, /**< device id (Int) */ -+ SPA_PARAM_ROUTE_name, /**< name of the routing destination (String) */ -+ SPA_PARAM_ROUTE_description, /**< description of the destination (String) */ -+ SPA_PARAM_ROUTE_priority, /**< priority of the destination (Int) */ -+ SPA_PARAM_ROUTE_available, /**< availability of the destination -+ * (Id enum spa_param_availability) */ -+ SPA_PARAM_ROUTE_info, /**< info (Struct( -+ * Int : n_items, -+ * (String : key, -+ * String : value)*)) */ -+ SPA_PARAM_ROUTE_profiles, /**< associated profile indexes (Array of Int) */ -+ SPA_PARAM_ROUTE_props, /**< properties SPA_TYPE_OBJECT_Props */ -+ SPA_PARAM_ROUTE_devices, /**< associated device indexes (Array of Int) */ -+ SPA_PARAM_ROUTE_profile, /**< profile id (Int) */ -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_H */ -diff --git a/third_party/pipewire/spa/param/profiler.h b/third_party/pipewire/spa/param/profiler.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/profiler.h -@@ -0,0 +1,84 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2020 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_PROFILER_H -+#define SPA_PARAM_PROFILER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** properties for SPA_TYPE_OBJECT_Profiler */ -+enum spa_profiler { -+ SPA_PROFILER_START, -+ -+ SPA_PROFILER_START_Driver = 0x10000, /**< driver related profiler properties */ -+ SPA_PROFILER_info, /**< Generic info, counter and CPU load, -+ * (Struct( -+ * Long : counter, -+ * Float : cpu_load fast, -+ * Float : cpu_load medium, -+ * Float : cpu_load slow)) */ -+ SPA_PROFILER_clock, /**< clock information -+ * (Struct( -+ * Int : clock flags, -+ * Int : clock id, -+ * String: clock name, -+ * Long : clock nsec, -+ * Fraction : clock rate, -+ * Long : clock position, -+ * Long : clock duration, -+ * Long : clock delay, -+ * Double : clock rate_diff, -+ * Long : clock next_nsec)) */ -+ SPA_PROFILER_driverBlock, /**< generic driver info block -+ * (Struct( -+ * Int : driver_id, -+ * String : name, -+ * Long : driver prev_signal, -+ * Long : driver signal, -+ * Long : driver awake, -+ * Long : driver finish, -+ * Int : driver status)) */ -+ -+ SPA_PROFILER_START_Follower = 0x20000, /**< follower related profiler properties */ -+ SPA_PROFILER_followerBlock, /**< generic follower info block -+ * (Struct( -+ * Int : id, -+ * String : name, -+ * Long : prev_signal, -+ * Long : signal, -+ * Long : awake, -+ * Long : finish, -+ * Int : status)) */ -+ SPA_PROFILER_START_CUSTOM = 0x1000000, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_PROFILER_H */ -diff --git a/third_party/pipewire/spa/param/props.h b/third_party/pipewire/spa/param/props.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/props.h -@@ -0,0 +1,99 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_PROPS_H -+#define SPA_PARAM_PROPS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** properties of SPA_TYPE_OBJECT_PropInfo */ -+enum spa_prop_info { -+ SPA_PROP_INFO_START, -+ SPA_PROP_INFO_id, /**< associated id of the property */ -+ SPA_PROP_INFO_name, /**< name of the property */ -+ SPA_PROP_INFO_type, /**< type and range/enums of property */ -+ SPA_PROP_INFO_labels, /**< labels of property if any, this is a -+ * struct with pairs of values, the first one -+ * is of the type of the property, the second -+ * one is a string with a user readable label -+ * for the value. */ -+}; -+ -+/** predefined properties for SPA_TYPE_OBJECT_Props */ -+enum spa_prop { -+ SPA_PROP_START, -+ -+ SPA_PROP_unknown, /**< an unknown property */ -+ -+ SPA_PROP_START_Device = 0x100, /**< device related properties */ -+ SPA_PROP_device, -+ SPA_PROP_deviceName, -+ SPA_PROP_deviceFd, -+ SPA_PROP_card, -+ SPA_PROP_cardName, -+ -+ SPA_PROP_minLatency, -+ SPA_PROP_maxLatency, -+ SPA_PROP_periods, -+ SPA_PROP_periodSize, -+ SPA_PROP_periodEvent, -+ SPA_PROP_live, -+ SPA_PROP_rate, -+ SPA_PROP_quality, -+ -+ SPA_PROP_START_Audio = 0x10000, /**< audio related properties */ -+ SPA_PROP_waveType, -+ SPA_PROP_frequency, -+ SPA_PROP_volume, /**< a volume (Float), 0.0 silence, 1.0 normal */ -+ SPA_PROP_mute, /**< mute (Bool) */ -+ SPA_PROP_patternType, -+ SPA_PROP_ditherType, -+ SPA_PROP_truncate, -+ SPA_PROP_channelVolumes, /**< a volume array, one volume per -+ * channel (Array of Float) */ -+ SPA_PROP_volumeBase, /**< a volume base (Float) */ -+ SPA_PROP_volumeStep, /**< a volume step (Float) */ -+ -+ SPA_PROP_START_Video = 0x20000, /**< video related properties */ -+ SPA_PROP_brightness, -+ SPA_PROP_contrast, -+ SPA_PROP_saturation, -+ SPA_PROP_hue, -+ SPA_PROP_gamma, -+ SPA_PROP_exposure, -+ SPA_PROP_gain, -+ SPA_PROP_sharpness, -+ -+ SPA_PROP_START_CUSTOM = 0x1000000, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_PROPS_H */ -diff --git a/third_party/pipewire/spa/param/type-info.h b/third_party/pipewire/spa/param/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/type-info.h -@@ -0,0 +1,362 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_TYPES_H -+#define SPA_PARAM_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_ParamId SPA_TYPE_INFO_ENUM_BASE "ParamId" -+#define SPA_TYPE_INFO_PARAM_ID_BASE SPA_TYPE_INFO_ParamId ":" -+ -+static const struct spa_type_info spa_type_param[] = { -+ { SPA_PARAM_Invalid, SPA_TYPE_None, SPA_TYPE_INFO_PARAM_ID_BASE "Invalid", NULL }, -+ { SPA_PARAM_PropInfo, SPA_TYPE_OBJECT_Props, SPA_TYPE_INFO_PARAM_ID_BASE "PropInfo", NULL }, -+ { SPA_PARAM_Props, SPA_TYPE_OBJECT_Props, SPA_TYPE_INFO_PARAM_ID_BASE "Props", NULL }, -+ { SPA_PARAM_EnumFormat, SPA_TYPE_OBJECT_Format, SPA_TYPE_INFO_PARAM_ID_BASE "EnumFormat", NULL }, -+ { SPA_PARAM_Format, SPA_TYPE_OBJECT_Format, SPA_TYPE_INFO_PARAM_ID_BASE "Format", NULL }, -+ { SPA_PARAM_Buffers, SPA_TYPE_OBJECT_ParamBuffers, SPA_TYPE_INFO_PARAM_ID_BASE "Buffers", NULL }, -+ { SPA_PARAM_Meta, SPA_TYPE_OBJECT_ParamMeta, SPA_TYPE_INFO_PARAM_ID_BASE "Meta", NULL }, -+ { SPA_PARAM_IO, SPA_TYPE_OBJECT_ParamIO, SPA_TYPE_INFO_PARAM_ID_BASE "IO", NULL }, -+ { SPA_PARAM_EnumProfile, SPA_TYPE_OBJECT_ParamProfile, SPA_TYPE_INFO_PARAM_ID_BASE "EnumProfile", NULL }, -+ { SPA_PARAM_Profile, SPA_TYPE_OBJECT_ParamProfile, SPA_TYPE_INFO_PARAM_ID_BASE "Profile", NULL }, -+ { SPA_PARAM_EnumPortConfig, SPA_TYPE_OBJECT_ParamPortConfig, SPA_TYPE_INFO_PARAM_ID_BASE "EnumPortConfig", NULL }, -+ { SPA_PARAM_PortConfig, SPA_TYPE_OBJECT_ParamPortConfig, SPA_TYPE_INFO_PARAM_ID_BASE "PortConfig", NULL }, -+ { SPA_PARAM_EnumRoute, SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_INFO_PARAM_ID_BASE "EnumRoute", NULL }, -+ { SPA_PARAM_Route, SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_INFO_PARAM_ID_BASE "Route", NULL }, -+ { SPA_PARAM_Control, SPA_TYPE_Sequence, SPA_TYPE_INFO_PARAM_ID_BASE "Control", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+/* base for parameter objects */ -+#define SPA_TYPE_INFO_Param SPA_TYPE_INFO_OBJECT_BASE "Param" -+#define SPA_TYPE_INFO_PARAM_BASE SPA_TYPE_INFO_Param ":" -+ -+#define SPA_TYPE_INFO_Props SPA_TYPE_INFO_PARAM_BASE "Props" -+#define SPA_TYPE_INFO_PROPS_BASE SPA_TYPE_INFO_Props ":" -+ -+static const struct spa_type_info spa_type_props[] = { -+ { SPA_PROP_START, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE, spa_type_param, }, -+ { SPA_PROP_unknown, SPA_TYPE_None, SPA_TYPE_INFO_PROPS_BASE "unknown", NULL }, -+ { SPA_PROP_device, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "device", NULL }, -+ { SPA_PROP_deviceName, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "deviceName", NULL }, -+ { SPA_PROP_deviceFd, SPA_TYPE_Fd, SPA_TYPE_INFO_PROPS_BASE "deviceFd", NULL }, -+ { SPA_PROP_card, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "card", NULL }, -+ { SPA_PROP_cardName, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "cardName", NULL }, -+ { SPA_PROP_minLatency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "minLatency", NULL }, -+ { SPA_PROP_maxLatency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "maxLatency", NULL }, -+ { SPA_PROP_periods, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "periods", NULL }, -+ { SPA_PROP_periodSize, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "periodSize", NULL }, -+ { SPA_PROP_periodEvent, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "periodEvent", NULL }, -+ { SPA_PROP_live, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "live", NULL }, -+ { SPA_PROP_rate, SPA_TYPE_Double, SPA_TYPE_INFO_PROPS_BASE "rate", NULL }, -+ { SPA_PROP_quality, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "quality", NULL }, -+ -+ { SPA_PROP_waveType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "waveType", NULL }, -+ { SPA_PROP_frequency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "frequency", NULL }, -+ { SPA_PROP_volume, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "volume", NULL }, -+ { SPA_PROP_mute, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "mute", NULL }, -+ { SPA_PROP_patternType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "patternType", NULL }, -+ { SPA_PROP_ditherType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "ditherType", NULL }, -+ { SPA_PROP_truncate, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "truncate", NULL }, -+ { SPA_PROP_channelVolumes, SPA_TYPE_Array, SPA_TYPE_INFO_PROPS_BASE "channelVolumes", NULL }, -+ { SPA_PROP_volumeBase, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "volumeBase", NULL }, -+ { SPA_PROP_volumeStep, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "volumeStep", NULL }, -+ -+ { SPA_PROP_brightness, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "brightness", NULL }, -+ { SPA_PROP_contrast, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "contrast", NULL }, -+ { SPA_PROP_saturation, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "saturation", NULL }, -+ { SPA_PROP_hue, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "hue", NULL }, -+ { SPA_PROP_gamma, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "gamma", NULL }, -+ { SPA_PROP_exposure, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "exposure", NULL }, -+ { SPA_PROP_gain, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "gain", NULL }, -+ { SPA_PROP_sharpness, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "sharpness", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+/** Enum Property info */ -+#define SPA_TYPE_INFO_PropInfo SPA_TYPE_INFO_PARAM_BASE "PropInfo" -+#define SPA_TYPE_INFO_PROP_INFO_BASE SPA_TYPE_INFO_PropInfo ":" -+ -+static const struct spa_type_info spa_type_prop_info[] = { -+ { SPA_PROP_INFO_START, SPA_TYPE_Id, SPA_TYPE_INFO_PROP_INFO_BASE, spa_type_param, }, -+ { SPA_PROP_INFO_id, SPA_TYPE_Id, SPA_TYPE_INFO_PROP_INFO_BASE "id", spa_type_props }, -+ { SPA_PROP_INFO_name, SPA_TYPE_String, SPA_TYPE_INFO_PROP_INFO_BASE "name", NULL }, -+ { SPA_PROP_INFO_type, SPA_TYPE_Pod, SPA_TYPE_INFO_PROP_INFO_BASE "type", NULL }, -+ { SPA_PROP_INFO_labels, SPA_TYPE_Struct, SPA_TYPE_INFO_PROP_INFO_BASE "labels", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_Meta SPA_TYPE_INFO_PARAM_BASE "Meta" -+#define SPA_TYPE_INFO_PARAM_META_BASE SPA_TYPE_INFO_PARAM_Meta ":" -+ -+static const struct spa_type_info spa_type_param_meta[] = { -+ { SPA_PARAM_META_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_META_BASE, spa_type_param }, -+ { SPA_PARAM_META_type, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_META_BASE "type", spa_type_meta_type }, -+ { SPA_PARAM_META_size, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_META_BASE "size", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+/** Base for parameters that describe IO areas to exchange data, -+ * control and properties with a node. -+ */ -+#define SPA_TYPE_INFO_PARAM_IO SPA_TYPE_INFO_PARAM_BASE "IO" -+#define SPA_TYPE_INFO_PARAM_IO_BASE SPA_TYPE_INFO_PARAM_IO ":" -+ -+static const struct spa_type_info spa_type_param_io[] = { -+ { SPA_PARAM_IO_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_IO_BASE, spa_type_param, }, -+ { SPA_PARAM_IO_id, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_IO_BASE "id", spa_type_io }, -+ { SPA_PARAM_IO_size, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_IO_BASE "size", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_Format SPA_TYPE_INFO_PARAM_BASE "Format" -+#define SPA_TYPE_INFO_FORMAT_BASE SPA_TYPE_INFO_Format ":" -+ -+#define SPA_TYPE_INFO_MediaType SPA_TYPE_INFO_ENUM_BASE "MediaType" -+#define SPA_TYPE_INFO_MEDIA_TYPE_BASE SPA_TYPE_INFO_MediaType ":" -+ -+#include -+#include -+ -+static const struct spa_type_info spa_type_media_type[] = { -+ { SPA_MEDIA_TYPE_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "unknown", NULL }, -+ { SPA_MEDIA_TYPE_audio, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "audio", NULL }, -+ { SPA_MEDIA_TYPE_video, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "video", NULL }, -+ { SPA_MEDIA_TYPE_image, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "image", NULL }, -+ { SPA_MEDIA_TYPE_binary, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "binary", NULL }, -+ { SPA_MEDIA_TYPE_stream, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "stream", NULL }, -+ { SPA_MEDIA_TYPE_application, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "application", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_MediaSubtype SPA_TYPE_INFO_ENUM_BASE "MediaSubtype" -+#define SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE SPA_TYPE_INFO_MediaSubtype ":" -+ -+static const struct spa_type_info spa_type_media_subtype[] = { -+ { SPA_MEDIA_SUBTYPE_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "unknown", NULL }, -+ /* generic subtypes */ -+ { SPA_MEDIA_SUBTYPE_raw, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "raw", NULL }, -+ { SPA_MEDIA_SUBTYPE_dsp, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "dsp", NULL }, -+ /* audio subtypes */ -+ { SPA_MEDIA_SUBTYPE_mp3, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mp3", NULL }, -+ { SPA_MEDIA_SUBTYPE_aac, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "aac", NULL }, -+ { SPA_MEDIA_SUBTYPE_vorbis, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vorbis", NULL }, -+ { SPA_MEDIA_SUBTYPE_wma, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "wma", NULL }, -+ { SPA_MEDIA_SUBTYPE_ra, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "ra", NULL }, -+ { SPA_MEDIA_SUBTYPE_sbc, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "sbc", NULL }, -+ { SPA_MEDIA_SUBTYPE_adpcm, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "adpcm", NULL }, -+ { SPA_MEDIA_SUBTYPE_g723, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "g723", NULL }, -+ { SPA_MEDIA_SUBTYPE_g726, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "g726", NULL }, -+ { SPA_MEDIA_SUBTYPE_g729, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "g729", NULL }, -+ { SPA_MEDIA_SUBTYPE_amr, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "amr", NULL }, -+ { SPA_MEDIA_SUBTYPE_gsm, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "gsm", NULL }, -+ /* video subtypes */ -+ { SPA_MEDIA_SUBTYPE_h264, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "h264", NULL }, -+ { SPA_MEDIA_SUBTYPE_mjpg, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mjpg", NULL }, -+ { SPA_MEDIA_SUBTYPE_dv, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "dv", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpegts, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpegts", NULL }, -+ { SPA_MEDIA_SUBTYPE_h263, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "h263", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpeg1, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpeg1", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpeg2, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpeg2", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpeg4, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpeg4", NULL }, -+ { SPA_MEDIA_SUBTYPE_xvid, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "xvid", NULL }, -+ { SPA_MEDIA_SUBTYPE_vc1, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vc1", NULL }, -+ { SPA_MEDIA_SUBTYPE_vp8, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vp8", NULL }, -+ { SPA_MEDIA_SUBTYPE_vp9, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vp9", NULL }, -+ { SPA_MEDIA_SUBTYPE_bayer, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "bayer", NULL }, -+ /* image subtypes */ -+ { SPA_MEDIA_SUBTYPE_jpeg, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "jpeg", NULL }, -+ /* stream subtypes */ -+ { SPA_MEDIA_SUBTYPE_midi, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "midi", NULL }, -+ /* application subtypes */ -+ { SPA_MEDIA_SUBTYPE_control, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "control", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_FormatAudio SPA_TYPE_INFO_FORMAT_BASE "Audio" -+#define SPA_TYPE_INFO_FORMAT_AUDIO_BASE SPA_TYPE_INFO_FormatAudio ":" -+ -+#define SPA_TYPE_INFO_FormatVideo SPA_TYPE_INFO_FORMAT_BASE "Video" -+#define SPA_TYPE_INFO_FORMAT_VIDEO_BASE SPA_TYPE_INFO_FormatVideo ":" -+ -+#define SPA_TYPE_INFO_FORMAT_VIDEO_H264 SPA_TYPE_INFO_FORMAT_VIDEO_BASE "H264" -+#define SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE SPA_TYPE_INFO_FORMAT_VIDEO_H264 ":" -+ -+static const struct spa_type_info spa_type_format[] = { -+ { SPA_FORMAT_START, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_BASE, spa_type_param, }, -+ -+ { SPA_FORMAT_mediaType, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_BASE "mediaType", -+ spa_type_media_type, }, -+ { SPA_FORMAT_mediaSubtype, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_BASE "mediaSubtype", -+ spa_type_media_subtype, }, -+ -+ { SPA_FORMAT_AUDIO_format, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "format", -+ spa_type_audio_format }, -+ { SPA_FORMAT_AUDIO_flags, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "flags", -+ spa_type_audio_flags }, -+ { SPA_FORMAT_AUDIO_rate, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "rate", NULL }, -+ { SPA_FORMAT_AUDIO_channels, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "channels", NULL }, -+ { SPA_FORMAT_AUDIO_position, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "position", -+ spa_type_audio_channel }, -+ -+ { SPA_FORMAT_VIDEO_format, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "format", -+ spa_type_video_format, }, -+ { SPA_FORMAT_VIDEO_modifier, SPA_TYPE_Long, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "modifier", NULL }, -+ { SPA_FORMAT_VIDEO_size, SPA_TYPE_Rectangle, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "size", NULL }, -+ { SPA_FORMAT_VIDEO_framerate, SPA_TYPE_Fraction, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "framerate", NULL }, -+ { SPA_FORMAT_VIDEO_maxFramerate, SPA_TYPE_Fraction, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "maxFramerate", NULL }, -+ { SPA_FORMAT_VIDEO_views, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "views", NULL }, -+ { SPA_FORMAT_VIDEO_interlaceMode, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "interlaceMode", NULL }, -+ { SPA_FORMAT_VIDEO_pixelAspectRatio, SPA_TYPE_Fraction, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "pixelAspectRatio", NULL }, -+ { SPA_FORMAT_VIDEO_multiviewMode, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "multiviewMode", NULL }, -+ { SPA_FORMAT_VIDEO_multiviewFlags, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "multiviewFlags", NULL }, -+ { SPA_FORMAT_VIDEO_chromaSite, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "chromaSite", NULL }, -+ { SPA_FORMAT_VIDEO_colorRange, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "colorRange", NULL }, -+ { SPA_FORMAT_VIDEO_colorMatrix, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "colorMatrix", NULL }, -+ { SPA_FORMAT_VIDEO_transferFunction, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "transferFunction", NULL }, -+ { SPA_FORMAT_VIDEO_colorPrimaries, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "colorPrimaries", NULL }, -+ { SPA_FORMAT_VIDEO_profile, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "profile", NULL }, -+ { SPA_FORMAT_VIDEO_level, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "level", NULL }, -+ -+ { SPA_FORMAT_VIDEO_H264_streamFormat, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE "streamFormat", NULL }, -+ { SPA_FORMAT_VIDEO_H264_alignment, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE "alignment", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_Buffers SPA_TYPE_INFO_PARAM_BASE "Buffers" -+#define SPA_TYPE_INFO_PARAM_BUFFERS_BASE SPA_TYPE_INFO_PARAM_Buffers ":" -+ -+#define SPA_TYPE_INFO_PARAM_BlockInfo SPA_TYPE_INFO_PARAM_BUFFERS_BASE "BlockInfo" -+#define SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE SPA_TYPE_INFO_PARAM_BlockInfo ":" -+ -+static const struct spa_type_info spa_type_param_buffers[] = { -+ { SPA_PARAM_BUFFERS_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_BUFFERS_BASE, spa_type_param, }, -+ { SPA_PARAM_BUFFERS_buffers, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BUFFERS_BASE "buffers", NULL }, -+ { SPA_PARAM_BUFFERS_blocks, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BUFFERS_BASE "blocks", NULL }, -+ { SPA_PARAM_BUFFERS_size, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "size", NULL }, -+ { SPA_PARAM_BUFFERS_stride, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "stride", NULL }, -+ { SPA_PARAM_BUFFERS_align, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "align", NULL }, -+ { SPA_PARAM_BUFFERS_dataType, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "dataType", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_ParamAvailability SPA_TYPE_INFO_ENUM_BASE "ParamAvailability" -+#define SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE SPA_TYPE_INFO_ParamAvailability ":" -+ -+static const struct spa_type_info spa_type_param_availability[] = { -+ { SPA_PARAM_AVAILABILITY_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE "unknown", NULL }, -+ { SPA_PARAM_AVAILABILITY_no, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE "no", NULL }, -+ { SPA_PARAM_AVAILABILITY_yes, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE "yes", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_Profile SPA_TYPE_INFO_PARAM_BASE "Profile" -+#define SPA_TYPE_INFO_PARAM_PROFILE_BASE SPA_TYPE_INFO_PARAM_Profile ":" -+ -+static const struct spa_type_info spa_type_param_profile[] = { -+ { SPA_PARAM_PROFILE_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PROFILE_BASE, spa_type_param, }, -+ { SPA_PARAM_PROFILE_index, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PROFILE_BASE "index", NULL }, -+ { SPA_PARAM_PROFILE_name, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_PROFILE_BASE "name", NULL }, -+ { SPA_PARAM_PROFILE_description, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_PROFILE_BASE "description", NULL }, -+ { SPA_PARAM_PROFILE_priority, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PROFILE_BASE "priority", NULL }, -+ { SPA_PARAM_PROFILE_available, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PROFILE_BASE "available", spa_type_param_availability, }, -+ { SPA_PARAM_PROFILE_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_PROFILE_BASE "info", NULL, }, -+ { SPA_PARAM_PROFILE_classes, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_PROFILE_BASE "classes", NULL, }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_ParamPortConfigMode SPA_TYPE_INFO_ENUM_BASE "ParamPortConfigMode" -+#define SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE SPA_TYPE_INFO_ParamPortConfigMode ":" -+ -+static const struct spa_type_info spa_type_param_port_config_mode[] = { -+ { SPA_PARAM_PORT_CONFIG_MODE_none, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "none", NULL }, -+ { SPA_PARAM_PORT_CONFIG_MODE_passthrough, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "passthrough", NULL }, -+ { SPA_PARAM_PORT_CONFIG_MODE_convert, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "convert", NULL }, -+ { SPA_PARAM_PORT_CONFIG_MODE_dsp, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "dsp", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_PortConfig SPA_TYPE_INFO_PARAM_BASE "PortConfig" -+#define SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE SPA_TYPE_INFO_PARAM_PortConfig ":" -+ -+static const struct spa_type_info spa_type_param_port_config[] = { -+ { SPA_PARAM_PORT_CONFIG_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE, spa_type_param, }, -+ { SPA_PARAM_PORT_CONFIG_direction, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "direction", spa_type_direction, }, -+ { SPA_PARAM_PORT_CONFIG_mode, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "mode", spa_type_param_port_config_mode }, -+ { SPA_PARAM_PORT_CONFIG_monitor, SPA_TYPE_Bool, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "monitor", NULL }, -+ { SPA_PARAM_PORT_CONFIG_control, SPA_TYPE_Bool, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "control", NULL }, -+ { SPA_PARAM_PORT_CONFIG_format, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "format", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+ -+#define SPA_TYPE_INFO_PARAM_Route SPA_TYPE_INFO_PARAM_BASE "Route" -+#define SPA_TYPE_INFO_PARAM_ROUTE_BASE SPA_TYPE_INFO_PARAM_Route ":" -+ -+static const struct spa_type_info spa_type_param_route[] = { -+ { SPA_PARAM_ROUTE_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE, spa_type_param, }, -+ { SPA_PARAM_ROUTE_index, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "index", NULL, }, -+ { SPA_PARAM_ROUTE_direction, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE "direction", spa_type_direction, }, -+ { SPA_PARAM_ROUTE_device, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "device", NULL, }, -+ { SPA_PARAM_ROUTE_name, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_ROUTE_BASE "name", NULL, }, -+ { SPA_PARAM_ROUTE_description, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_ROUTE_BASE "description", NULL, }, -+ { SPA_PARAM_ROUTE_priority, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "priority", NULL, }, -+ { SPA_PARAM_ROUTE_available, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE "available", spa_type_param_availability, }, -+ { SPA_PARAM_ROUTE_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_ROUTE_BASE "info", NULL, }, -+ { SPA_PARAM_ROUTE_profiles, SPA_TYPE_Array, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profiles", NULL, }, -+ { SPA_PARAM_ROUTE_props, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ROUTE_BASE "props", NULL, }, -+ { SPA_PARAM_ROUTE_devices, SPA_TYPE_Array, SPA_TYPE_INFO_PARAM_ROUTE_BASE "devices", NULL, }, -+ { SPA_PARAM_ROUTE_profile, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profile", NULL, }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#include -+ -+#define SPA_TYPE_INFO_Profiler SPA_TYPE_INFO_OBJECT_BASE "Profiler" -+#define SPA_TYPE_INFO_PROFILER_BASE SPA_TYPE_INFO_Profiler ":" -+ -+static const struct spa_type_info spa_type_profiler[] = { -+ { SPA_PROFILER_START, SPA_TYPE_Id, SPA_TYPE_INFO_PROFILER_BASE, spa_type_param, }, -+ { SPA_PROFILER_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "info", NULL, }, -+ { SPA_PROFILER_clock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "clock", NULL, }, -+ { SPA_PROFILER_driverBlock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "driverBlock", NULL, }, -+ { SPA_PROFILER_followerBlock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "followerBlock", NULL, }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_TYPES_H */ -diff --git a/third_party/pipewire/spa/param/video/chroma.h b/third_party/pipewire/spa/param/video/chroma.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/chroma.h -@@ -0,0 +1,60 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_CHROMA_H -+#define SPA_VIDEO_CHROMA_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** Various Chroma sitings. -+ * @SPA_VIDEO_CHROMA_SITE_UNKNOWN: unknown cositing -+ * @SPA_VIDEO_CHROMA_SITE_NONE: no cositing -+ * @SPA_VIDEO_CHROMA_SITE_H_COSITED: chroma is horizontally cosited -+ * @SPA_VIDEO_CHROMA_SITE_V_COSITED: chroma is vertically cosited -+ * @SPA_VIDEO_CHROMA_SITE_ALT_LINE: choma samples are sited on alternate lines -+ * @SPA_VIDEO_CHROMA_SITE_COSITED: chroma samples cosited with luma samples -+ * @SPA_VIDEO_CHROMA_SITE_JPEG: jpeg style cositing, also for mpeg1 and mjpeg -+ * @SPA_VIDEO_CHROMA_SITE_MPEG2: mpeg2 style cositing -+ * @SPA_VIDEO_CHROMA_SITE_DV: DV style cositing -+ */ -+enum spa_video_chroma_site { -+ SPA_VIDEO_CHROMA_SITE_UNKNOWN = 0, -+ SPA_VIDEO_CHROMA_SITE_NONE = (1 << 0), -+ SPA_VIDEO_CHROMA_SITE_H_COSITED = (1 << 1), -+ SPA_VIDEO_CHROMA_SITE_V_COSITED = (1 << 2), -+ SPA_VIDEO_CHROMA_SITE_ALT_LINE = (1 << 3), -+ /* some common chroma cositing */ -+ SPA_VIDEO_CHROMA_SITE_COSITED = (SPA_VIDEO_CHROMA_SITE_H_COSITED | SPA_VIDEO_CHROMA_SITE_V_COSITED), -+ SPA_VIDEO_CHROMA_SITE_JPEG = (SPA_VIDEO_CHROMA_SITE_NONE), -+ SPA_VIDEO_CHROMA_SITE_MPEG2 = (SPA_VIDEO_CHROMA_SITE_H_COSITED), -+ SPA_VIDEO_CHROMA_SITE_DV = (SPA_VIDEO_CHROMA_SITE_COSITED | SPA_VIDEO_CHROMA_SITE_ALT_LINE), -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_CHROMA_H */ -diff --git a/third_party/pipewire/spa/param/video/color.h b/third_party/pipewire/spa/param/video/color.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/color.h -@@ -0,0 +1,162 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_COLOR_H -+#define SPA_VIDEO_COLOR_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * spa_video_color_range: -+ * @SPA_VIDEO_COLOR_RANGE_UNKNOWN: unknown range -+ * @SPA_VIDEO_COLOR_RANGE_0_255: [0..255] for 8 bit components -+ * @SPA_VIDEO_COLOR_RANGE_16_235: [16..235] for 8 bit components. Chroma has -+ * [16..240] range. -+ * -+ * Possible color range values. These constants are defined for 8 bit color -+ * values and can be scaled for other bit depths. -+ */ -+enum spa_video_color_range { -+ SPA_VIDEO_COLOR_RANGE_UNKNOWN = 0, -+ SPA_VIDEO_COLOR_RANGE_0_255, -+ SPA_VIDEO_COLOR_RANGE_16_235 -+}; -+ -+/** -+ * spa_video_color_matrix: -+ * @SPA_VIDEO_COLOR_MATRIX_UNKNOWN: unknown matrix -+ * @SPA_VIDEO_COLOR_MATRIX_RGB: identity matrix -+ * @SPA_VIDEO_COLOR_MATRIX_FCC: FCC color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_BT709: ITU-R BT.709 color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_BT601: ITU-R BT.601 color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_SMPTE240M: SMPTE 240M color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_BT2020: ITU-R BT.2020 color matrix. Since: 1.6. -+ * -+ * The color matrix is used to convert between Y'PbPr and -+ * non-linear RGB (R'G'B') -+ */ -+enum spa_video_color_matrix { -+ SPA_VIDEO_COLOR_MATRIX_UNKNOWN = 0, -+ SPA_VIDEO_COLOR_MATRIX_RGB, -+ SPA_VIDEO_COLOR_MATRIX_FCC, -+ SPA_VIDEO_COLOR_MATRIX_BT709, -+ SPA_VIDEO_COLOR_MATRIX_BT601, -+ SPA_VIDEO_COLOR_MATRIX_SMPTE240M, -+ SPA_VIDEO_COLOR_MATRIX_BT2020 -+}; -+ -+/** -+ * spa_video_transfer_function: -+ * @SPA_VIDEO_TRANSFER_UNKNOWN: unknown transfer function -+ * @SPA_VIDEO_TRANSFER_GAMMA10: linear RGB, gamma 1.0 curve -+ * @SPA_VIDEO_TRANSFER_GAMMA18: Gamma 1.8 curve -+ * @SPA_VIDEO_TRANSFER_GAMMA20: Gamma 2.0 curve -+ * @SPA_VIDEO_TRANSFER_GAMMA22: Gamma 2.2 curve -+ * @SPA_VIDEO_TRANSFER_BT709: Gamma 2.2 curve with a linear segment in the lower -+ * range -+ * @SPA_VIDEO_TRANSFER_SMPTE240M: Gamma 2.2 curve with a linear segment in the -+ * lower range -+ * @SPA_VIDEO_TRANSFER_SRGB: Gamma 2.4 curve with a linear segment in the lower -+ * range -+ * @SPA_VIDEO_TRANSFER_GAMMA28: Gamma 2.8 curve -+ * @SPA_VIDEO_TRANSFER_LOG100: Logarithmic transfer characteristic -+ * 100:1 range -+ * @SPA_VIDEO_TRANSFER_LOG316: Logarithmic transfer characteristic -+ * 316.22777:1 range -+ * @SPA_VIDEO_TRANSFER_BT2020_12: Gamma 2.2 curve with a linear segment in the lower -+ * range. Used for BT.2020 with 12 bits per -+ * component. Since: 1.6. -+ * @SPA_VIDEO_TRANSFER_ADOBERGB: Gamma 2.19921875. Since: 1.8 -+ * -+ * The video transfer function defines the formula for converting between -+ * non-linear RGB (R'G'B') and linear RGB -+ */ -+enum spa_video_transfer_function { -+ SPA_VIDEO_TRANSFER_UNKNOWN = 0, -+ SPA_VIDEO_TRANSFER_GAMMA10, -+ SPA_VIDEO_TRANSFER_GAMMA18, -+ SPA_VIDEO_TRANSFER_GAMMA20, -+ SPA_VIDEO_TRANSFER_GAMMA22, -+ SPA_VIDEO_TRANSFER_BT709, -+ SPA_VIDEO_TRANSFER_SMPTE240M, -+ SPA_VIDEO_TRANSFER_SRGB, -+ SPA_VIDEO_TRANSFER_GAMMA28, -+ SPA_VIDEO_TRANSFER_LOG100, -+ SPA_VIDEO_TRANSFER_LOG316, -+ SPA_VIDEO_TRANSFER_BT2020_12, -+ SPA_VIDEO_TRANSFER_ADOBERGB -+}; -+ -+/** -+ * spa_video_color_primaries: -+ * @SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN: unknown color primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT709: BT709 primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT470M: BT470M primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT470BG: BT470BG primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_SMPTE170M: SMPTE170M primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_SMPTE240M: SMPTE240M primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_FILM: Generic film -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT2020: BT2020 primaries. Since: 1.6. -+ * @SPA_VIDEO_COLOR_PRIMARIES_ADOBERGB: Adobe RGB primaries. Since: 1.8 -+ * -+ * The color primaries define the how to transform linear RGB values to and from -+ * the CIE XYZ colorspace. -+ */ -+enum spa_video_color_primaries { -+ SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN = 0, -+ SPA_VIDEO_COLOR_PRIMARIES_BT709, -+ SPA_VIDEO_COLOR_PRIMARIES_BT470M, -+ SPA_VIDEO_COLOR_PRIMARIES_BT470BG, -+ SPA_VIDEO_COLOR_PRIMARIES_SMPTE170M, -+ SPA_VIDEO_COLOR_PRIMARIES_SMPTE240M, -+ SPA_VIDEO_COLOR_PRIMARIES_FILM, -+ SPA_VIDEO_COLOR_PRIMARIES_BT2020, -+ SPA_VIDEO_COLOR_PRIMARIES_ADOBERGB -+}; -+ -+/** -+ * spa_video_colorimetry: -+ * @range: the color range. This is the valid range for the samples. -+ * It is used to convert the samples to Y'PbPr values. -+ * @matrix: the color matrix. Used to convert between Y'PbPr and -+ * non-linear RGB (R'G'B') -+ * @transfer: the transfer function. used to convert between R'G'B' and RGB -+ * @primaries: color primaries. used to convert between R'G'B' and CIE XYZ -+ * -+ * Structure describing the color info. -+ */ -+struct spa_video_colorimetry { -+ enum spa_video_color_range range; -+ enum spa_video_color_matrix matrix; -+ enum spa_video_transfer_function transfer; -+ enum spa_video_color_primaries primaries; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_COLOR_H */ -diff --git a/third_party/pipewire/spa/param/video/encoded.h b/third_party/pipewire/spa/param/video/encoded.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/encoded.h -@@ -0,0 +1,65 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_ENCODED_H -+#define SPA_VIDEO_ENCODED_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+enum spa_h264_stream_format { -+ SPA_H264_STREAM_FORMAT_UNKNOWN = 0, -+ SPA_H264_STREAM_FORMAT_AVC, -+ SPA_H264_STREAM_FORMAT_AVC3, -+ SPA_H264_STREAM_FORMAT_BYTESTREAM -+}; -+ -+enum spa_h264_alignment { -+ SPA_H264_ALIGNMENT_UNKNOWN = 0, -+ SPA_H264_ALIGNMENT_AU, -+ SPA_H264_ALIGNMENT_NAL -+}; -+ -+struct spa_video_info_h264 { -+ struct spa_rectangle size; -+ struct spa_fraction framerate; -+ struct spa_fraction max_framerate; -+ enum spa_h264_stream_format stream_format; -+ enum spa_h264_alignment alignment; -+}; -+ -+struct spa_video_info_mjpg { -+ struct spa_rectangle size; -+ struct spa_fraction framerate; -+ struct spa_fraction max_framerate; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_ENCODED_H */ -diff --git a/third_party/pipewire/spa/param/video/format-utils.h b/third_party/pipewire/spa/param/video/format-utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/format-utils.h -@@ -0,0 +1,167 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_VIDEO_FORMAT_UTILS_H -+#define SPA_PARAM_VIDEO_FORMAT_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+static inline int -+spa_format_video_raw_parse(const struct spa_pod *format, -+ struct spa_video_info_raw *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(&info->format), -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_OPT_Long(&info->modifier), -+ SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&info->framerate), -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_OPT_Fraction(&info->max_framerate), -+ SPA_FORMAT_VIDEO_views, SPA_POD_OPT_Int(&info->views), -+ SPA_FORMAT_VIDEO_interlaceMode, SPA_POD_OPT_Id(&info->interlace_mode), -+ SPA_FORMAT_VIDEO_pixelAspectRatio, SPA_POD_OPT_Fraction(&info->pixel_aspect_ratio), -+ SPA_FORMAT_VIDEO_multiviewMode, SPA_POD_OPT_Id(&info->multiview_mode), -+ SPA_FORMAT_VIDEO_multiviewFlags, SPA_POD_OPT_Id(&info->multiview_flags), -+ SPA_FORMAT_VIDEO_chromaSite, SPA_POD_OPT_Id(&info->chroma_site), -+ SPA_FORMAT_VIDEO_colorRange, SPA_POD_OPT_Id(&info->color_range), -+ SPA_FORMAT_VIDEO_colorMatrix, SPA_POD_OPT_Id(&info->color_matrix), -+ SPA_FORMAT_VIDEO_transferFunction, SPA_POD_OPT_Id(&info->transfer_function), -+ SPA_FORMAT_VIDEO_colorPrimaries, SPA_POD_OPT_Id(&info->color_primaries)); -+} -+ -+static inline int -+spa_format_video_dsp_parse(const struct spa_pod *format, -+ struct spa_video_info_dsp *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(&info->format), -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_OPT_Long(&info->modifier)); -+} -+ -+static inline struct spa_pod * -+spa_format_video_raw_build(struct spa_pod_builder *builder, uint32_t id, -+ struct spa_video_info_raw *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(info->format), -+ SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&info->framerate), -+ 0); -+ if (info->modifier != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); -+ if (info->max_framerate.denom != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_Fraction(info->max_framerate), 0); -+ if (info->views != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_views, SPA_POD_Int(info->views), 0); -+ if (info->interlace_mode != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_interlaceMode, SPA_POD_Id(info->interlace_mode), 0); -+ if (info->pixel_aspect_ratio.denom != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_pixelAspectRatio,SPA_POD_Fraction(info->pixel_aspect_ratio), 0); -+ if (info->multiview_mode != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_multiviewMode, SPA_POD_Id(info->multiview_mode), 0); -+ if (info->multiview_flags != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_multiviewFlags,SPA_POD_Id(info->multiview_flags), 0); -+ if (info->chroma_site != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_chromaSite, SPA_POD_Id(info->chroma_site), 0); -+ if (info->color_range != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_colorRange, SPA_POD_Id(info->color_range), 0); -+ if (info->color_matrix != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_colorMatrix, SPA_POD_Id(info->color_matrix), 0); -+ if (info->transfer_function != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_transferFunction,SPA_POD_Id(info->transfer_function), 0); -+ if (info->color_primaries != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_colorPrimaries,SPA_POD_Id(info->color_primaries), 0); -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+static inline struct spa_pod * -+spa_format_video_dsp_build(struct spa_pod_builder *builder, uint32_t id, -+ struct spa_video_info_dsp *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(info->format), -+ 0); -+ if (info->modifier) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+static inline int -+spa_format_video_h264_parse(const struct spa_pod *format, -+ struct spa_video_info_h264 *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_size, SPA_POD_OPT_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_OPT_Fraction(&info->framerate), -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_OPT_Fraction(&info->max_framerate), -+ SPA_FORMAT_VIDEO_H264_streamFormat, SPA_POD_OPT_Id(&info->stream_format), -+ SPA_FORMAT_VIDEO_H264_alignment, SPA_POD_OPT_Id(&info->alignment)); -+} -+ -+static inline int -+spa_format_video_mjpg_parse(const struct spa_pod *format, -+ struct spa_video_info_mjpg *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_size, SPA_POD_OPT_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_OPT_Fraction(&info->framerate), -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_OPT_Fraction(&info->max_framerate)); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_VIDEO_FORMAT_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/video/format.h b/third_party/pipewire/spa/param/video/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/format.h -@@ -0,0 +1,50 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_VIDEO_FORMAT_H -+#define SPA_PARAM_VIDEO_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_video_info { -+ uint32_t media_type; -+ uint32_t media_subtype; -+ union { -+ struct spa_video_info_raw raw; -+ struct spa_video_info_dsp dsp; -+ struct spa_video_info_h264 h264; -+ struct spa_video_info_mjpg mjpg; -+ } info; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_VIDEO_FORMAT_H */ -diff --git a/third_party/pipewire/spa/param/video/multiview.h b/third_party/pipewire/spa/param/video/multiview.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/multiview.h -@@ -0,0 +1,140 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_MULTIVIEW_H -+#define SPA_VIDEO_MULTIVIEW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * spa_video_multiview_mode: -+ * @SPA_VIDEO_MULTIVIEW_MODE_NONE: A special value indicating -+ * no multiview information. Used in spa_video_info and other places to -+ * indicate that no specific multiview handling has been requested or -+ * provided. This value is never carried on caps. -+ * @SPA_VIDEO_MULTIVIEW_MODE_MONO: All frames are monoscopic. -+ * @SPA_VIDEO_MULTIVIEW_MODE_LEFT: All frames represent a left-eye view. -+ * @SPA_VIDEO_MULTIVIEW_MODE_RIGHT: All frames represent a right-eye view. -+ * @SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE: Left and right eye views are -+ * provided in the left and right half of the frame respectively. -+ * @SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX: Left and right eye -+ * views are provided in the left and right half of the frame, but -+ * have been sampled using quincunx method, with half-pixel offset -+ * between the 2 views. -+ * @SPA_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED: Alternating vertical -+ * columns of pixels represent the left and right eye view respectively. -+ * @SPA_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED: Alternating horizontal -+ * rows of pixels represent the left and right eye view respectively. -+ * @SPA_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM: The top half of the frame -+ * contains the left eye, and the bottom half the right eye. -+ * @SPA_VIDEO_MULTIVIEW_MODE_CHECKERBOARD: Pixels are arranged with -+ * alternating pixels representing left and right eye views in a -+ * checkerboard fashion. -+ * @SPA_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME: Left and right eye views -+ * are provided in separate frames alternately. -+ * @SPA_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME: Multiple -+ * independent views are provided in separate frames in sequence. -+ * This method only applies to raw video buffers at the moment. -+ * Specific view identification is via the #spa_video_multiview_meta -+ * on raw video buffers. -+ * @SPA_VIDEO_MULTIVIEW_MODE_SEPARATED: Multiple views are -+ * provided as separate #spa_data framebuffers attached to each -+ * #spa_buffer, described by the #spa_video_multiview_meta -+ * -+ * All possible stereoscopic 3D and multiview representations. -+ * In conjunction with #soa_video_multiview_flags, describes how -+ * multiview content is being transported in the stream. -+ */ -+enum spa_video_multiview_mode { -+ SPA_VIDEO_MULTIVIEW_MODE_NONE = -1, -+ SPA_VIDEO_MULTIVIEW_MODE_MONO = 0, -+ /* Single view modes */ -+ SPA_VIDEO_MULTIVIEW_MODE_LEFT, -+ SPA_VIDEO_MULTIVIEW_MODE_RIGHT, -+ /* Stereo view modes */ -+ SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE, -+ SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX, -+ SPA_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED, -+ SPA_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED, -+ SPA_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM, -+ SPA_VIDEO_MULTIVIEW_MODE_CHECKERBOARD, -+ /* Padding for new frame packing modes */ -+ -+ SPA_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME = 32, -+ /* Multivew mode(s) */ -+ SPA_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME, -+ SPA_VIDEO_MULTIVIEW_MODE_SEPARATED -+ /* future expansion for annotated modes */ -+}; -+ -+/** -+ * spa_video_multiview_flags: -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_NONE: No flags -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST: For stereo streams, the -+ * normal arrangement of left and right views is reversed. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED: The left view is vertically -+ * mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED: The left view is horizontally -+ * mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED: The right view is -+ * vertically mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED: The right view is -+ * horizontally mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT: For frame-packed -+ * multiview modes, indicates that the individual -+ * views have been encoded with half the true width or height -+ * and should be scaled back up for display. This flag -+ * is used for overriding input layout interpretation -+ * by adjusting pixel-aspect-ratio. -+ * For side-by-side, column interleaved or checkerboard packings, the -+ * pixel width will be doubled. For row interleaved and top-bottom -+ * encodings, pixel height will be doubled. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO: The video stream contains both -+ * mono and multiview portions, signalled on each buffer by the -+ * absence or presence of the @SPA_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW -+ * buffer flag. -+ * -+ * spa_video_multiview_flags are used to indicate extra properties of a -+ * stereo/multiview stream beyond the frame layout and buffer mapping -+ * that is conveyed in the #spa_video_multiview_mode. -+ */ -+enum spa_video_multiview_flags { -+ SPA_VIDEO_MULTIVIEW_FLAGS_NONE = 0, -+ SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST = (1 << 0), -+ SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED = (1 << 1), -+ SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED = (1 << 2), -+ SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED = (1 << 3), -+ SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED = (1 << 4), -+ SPA_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT = (1 << 14), -+ SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO = (1 << 15) -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_MULTIVIEW_H */ -diff --git a/third_party/pipewire/spa/param/video/raw.h b/third_party/pipewire/spa/param/video/raw.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/raw.h -@@ -0,0 +1,221 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_RAW_H -+#define SPA_VIDEO_RAW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#define SPA_VIDEO_MAX_PLANES 4 -+#define SPA_VIDEO_MAX_COMPONENTS 4 -+ -+enum spa_video_format { -+ SPA_VIDEO_FORMAT_UNKNOWN, -+ SPA_VIDEO_FORMAT_ENCODED, -+ -+ SPA_VIDEO_FORMAT_I420, -+ SPA_VIDEO_FORMAT_YV12, -+ SPA_VIDEO_FORMAT_YUY2, -+ SPA_VIDEO_FORMAT_UYVY, -+ SPA_VIDEO_FORMAT_AYUV, -+ SPA_VIDEO_FORMAT_RGBx, -+ SPA_VIDEO_FORMAT_BGRx, -+ SPA_VIDEO_FORMAT_xRGB, -+ SPA_VIDEO_FORMAT_xBGR, -+ SPA_VIDEO_FORMAT_RGBA, -+ SPA_VIDEO_FORMAT_BGRA, -+ SPA_VIDEO_FORMAT_ARGB, -+ SPA_VIDEO_FORMAT_ABGR, -+ SPA_VIDEO_FORMAT_RGB, -+ SPA_VIDEO_FORMAT_BGR, -+ SPA_VIDEO_FORMAT_Y41B, -+ SPA_VIDEO_FORMAT_Y42B, -+ SPA_VIDEO_FORMAT_YVYU, -+ SPA_VIDEO_FORMAT_Y444, -+ SPA_VIDEO_FORMAT_v210, -+ SPA_VIDEO_FORMAT_v216, -+ SPA_VIDEO_FORMAT_NV12, -+ SPA_VIDEO_FORMAT_NV21, -+ SPA_VIDEO_FORMAT_GRAY8, -+ SPA_VIDEO_FORMAT_GRAY16_BE, -+ SPA_VIDEO_FORMAT_GRAY16_LE, -+ SPA_VIDEO_FORMAT_v308, -+ SPA_VIDEO_FORMAT_RGB16, -+ SPA_VIDEO_FORMAT_BGR16, -+ SPA_VIDEO_FORMAT_RGB15, -+ SPA_VIDEO_FORMAT_BGR15, -+ SPA_VIDEO_FORMAT_UYVP, -+ SPA_VIDEO_FORMAT_A420, -+ SPA_VIDEO_FORMAT_RGB8P, -+ SPA_VIDEO_FORMAT_YUV9, -+ SPA_VIDEO_FORMAT_YVU9, -+ SPA_VIDEO_FORMAT_IYU1, -+ SPA_VIDEO_FORMAT_ARGB64, -+ SPA_VIDEO_FORMAT_AYUV64, -+ SPA_VIDEO_FORMAT_r210, -+ SPA_VIDEO_FORMAT_I420_10BE, -+ SPA_VIDEO_FORMAT_I420_10LE, -+ SPA_VIDEO_FORMAT_I422_10BE, -+ SPA_VIDEO_FORMAT_I422_10LE, -+ SPA_VIDEO_FORMAT_Y444_10BE, -+ SPA_VIDEO_FORMAT_Y444_10LE, -+ SPA_VIDEO_FORMAT_GBR, -+ SPA_VIDEO_FORMAT_GBR_10BE, -+ SPA_VIDEO_FORMAT_GBR_10LE, -+ SPA_VIDEO_FORMAT_NV16, -+ SPA_VIDEO_FORMAT_NV24, -+ SPA_VIDEO_FORMAT_NV12_64Z32, -+ SPA_VIDEO_FORMAT_A420_10BE, -+ SPA_VIDEO_FORMAT_A420_10LE, -+ SPA_VIDEO_FORMAT_A422_10BE, -+ SPA_VIDEO_FORMAT_A422_10LE, -+ SPA_VIDEO_FORMAT_A444_10BE, -+ SPA_VIDEO_FORMAT_A444_10LE, -+ SPA_VIDEO_FORMAT_NV61, -+ SPA_VIDEO_FORMAT_P010_10BE, -+ SPA_VIDEO_FORMAT_P010_10LE, -+ SPA_VIDEO_FORMAT_IYU2, -+ SPA_VIDEO_FORMAT_VYUY, -+ SPA_VIDEO_FORMAT_GBRA, -+ SPA_VIDEO_FORMAT_GBRA_10BE, -+ SPA_VIDEO_FORMAT_GBRA_10LE, -+ SPA_VIDEO_FORMAT_GBR_12BE, -+ SPA_VIDEO_FORMAT_GBR_12LE, -+ SPA_VIDEO_FORMAT_GBRA_12BE, -+ SPA_VIDEO_FORMAT_GBRA_12LE, -+ SPA_VIDEO_FORMAT_I420_12BE, -+ SPA_VIDEO_FORMAT_I420_12LE, -+ SPA_VIDEO_FORMAT_I422_12BE, -+ SPA_VIDEO_FORMAT_I422_12LE, -+ SPA_VIDEO_FORMAT_Y444_12BE, -+ SPA_VIDEO_FORMAT_Y444_12LE, -+ -+ SPA_VIDEO_FORMAT_RGBA_F16, -+ SPA_VIDEO_FORMAT_RGBA_F32, -+ -+ /* Aliases */ -+ SPA_VIDEO_FORMAT_DSP_F32 = SPA_VIDEO_FORMAT_RGBA_F32, -+}; -+ -+/** -+ * spa_video_flags: -+ * @SPA_VIDEO_FLAG_NONE: no flags -+ * @SPA_VIDEO_FLAG_VARIABLE_FPS: a variable fps is selected, fps_n and fps_d -+ * denote the maximum fps of the video -+ * @SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA: Each color has been scaled by the alpha -+ * value. -+ * -+ * Extra video flags -+ */ -+enum spa_video_flags { -+ SPA_VIDEO_FLAG_NONE = 0, -+ SPA_VIDEO_FLAG_VARIABLE_FPS = (1 << 0), -+ SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA = (1 << 1) -+}; -+ -+/** -+ * spa_video_interlace_mode: -+ * @SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE: all frames are progressive -+ * @SPA_VIDEO_INTERLACE_MODE_INTERLEAVED: 2 fields are interleaved in one video -+ * frame. Extra buffer flags describe the field order. -+ * @SPA_VIDEO_INTERLACE_MODE_MIXED: frames contains both interlaced and -+ * progressive video, the buffer flags describe the frame and fields. -+ * @SPA_VIDEO_INTERLACE_MODE_FIELDS: 2 fields are stored in one buffer, use the -+ * frame ID to get access to the required field. For multiview (the -+ * 'views' property > 1) the fields of view N can be found at frame ID -+ * (N * 2) and (N * 2) + 1. -+ * Each field has only half the amount of lines as noted in the -+ * height property. This mode requires multiple spa_data -+ * to describe the fields. -+ * -+ * The possible values of the #spa_video_interlace_mode describing the interlace -+ * mode of the stream. -+ */ -+enum spa_video_interlace_mode { -+ SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE = 0, -+ SPA_VIDEO_INTERLACE_MODE_INTERLEAVED, -+ SPA_VIDEO_INTERLACE_MODE_MIXED, -+ SPA_VIDEO_INTERLACE_MODE_FIELDS -+}; -+ -+/** -+ * spa_video_info_raw: -+ * @format: the format -+ * @modifier: format modifier -+ * @size: the frame size of the video -+ * @framerate: the framerate of the video 0/1 means variable rate -+ * @max_framerate: the maximum framerate of the video. This is only valid when -+ * @framerate is 0/1 -+ * @views: the number of views in this video -+ * @interlace_mode: the interlace mode -+ * @pixel_aspect_ratio: The pixel aspect ratio -+ * @multiview_mode: multiview mode -+ * @multiview_flags: multiview flags -+ * @chroma_site: the chroma siting -+ * @color_range: the color range. This is the valid range for the samples. -+ * It is used to convert the samples to Y'PbPr values. -+ * @color_matrix: the color matrix. Used to convert between Y'PbPr and -+ * non-linear RGB (R'G'B') -+ * @transfer_function: the transfer function. used to convert between R'G'B' and RGB -+ * @color_primaries: color primaries. used to convert between R'G'B' and CIE XYZ -+ */ -+struct spa_video_info_raw { -+ enum spa_video_format format; -+ int64_t modifier; -+ struct spa_rectangle size; -+ struct spa_fraction framerate; -+ struct spa_fraction max_framerate; -+ uint32_t views; -+ enum spa_video_interlace_mode interlace_mode; -+ struct spa_fraction pixel_aspect_ratio; -+ enum spa_video_multiview_mode multiview_mode; -+ enum spa_video_multiview_flags multiview_flags; -+ enum spa_video_chroma_site chroma_site; -+ enum spa_video_color_range color_range; -+ enum spa_video_color_matrix color_matrix; -+ enum spa_video_transfer_function transfer_function; -+ enum spa_video_color_primaries color_primaries; -+}; -+ -+#define SPA_VIDEO_INFO_RAW_INIT(...) (struct spa_video_info_raw) { __VA_ARGS__ } -+ -+struct spa_video_info_dsp { -+ enum spa_video_format format; -+ int64_t modifier; -+}; -+ -+#define SPA_VIDEO_INFO_DSP_INIT(...) (struct spa_video_info_dsp) { __VA_ARGS__ } -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_RAW_H */ -diff --git a/third_party/pipewire/spa/param/video/type-info.h b/third_party/pipewire/spa/param/video/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/type-info.h -@@ -0,0 +1,124 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_TYPES_H -+#define SPA_VIDEO_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#define SPA_TYPE_INFO_VideoFormat SPA_TYPE_INFO_ENUM_BASE "VideoFormat" -+#define SPA_TYPE_INFO_VIDEO_FORMAT_BASE SPA_TYPE_INFO_VideoFormat ":" -+ -+static const struct spa_type_info spa_type_video_format[] = { -+ { SPA_VIDEO_FORMAT_ENCODED, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "encoded", NULL }, -+ { SPA_VIDEO_FORMAT_I420, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420", NULL }, -+ { SPA_VIDEO_FORMAT_YV12, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YV12", NULL }, -+ { SPA_VIDEO_FORMAT_YUY2, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YUY2", NULL }, -+ { SPA_VIDEO_FORMAT_UYVY, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "UYVY", NULL }, -+ { SPA_VIDEO_FORMAT_AYUV, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "AYUV", NULL }, -+ { SPA_VIDEO_FORMAT_RGBx, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBx", NULL }, -+ { SPA_VIDEO_FORMAT_BGRx, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGRx", NULL }, -+ { SPA_VIDEO_FORMAT_xRGB, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "xRGB", NULL }, -+ { SPA_VIDEO_FORMAT_xBGR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "xBGR", NULL }, -+ { SPA_VIDEO_FORMAT_RGBA, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBA", NULL }, -+ { SPA_VIDEO_FORMAT_BGRA, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGRA", NULL }, -+ { SPA_VIDEO_FORMAT_ARGB, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ARGB", NULL }, -+ { SPA_VIDEO_FORMAT_ABGR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ABGR", NULL }, -+ { SPA_VIDEO_FORMAT_RGB, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB", NULL }, -+ { SPA_VIDEO_FORMAT_BGR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGR", NULL }, -+ { SPA_VIDEO_FORMAT_Y41B, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y41B", NULL }, -+ { SPA_VIDEO_FORMAT_Y42B, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y42B", NULL }, -+ { SPA_VIDEO_FORMAT_YVYU, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YVYU", NULL }, -+ { SPA_VIDEO_FORMAT_Y444, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444", NULL }, -+ { SPA_VIDEO_FORMAT_v210, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "v210", NULL }, -+ { SPA_VIDEO_FORMAT_v216, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "v216", NULL }, -+ { SPA_VIDEO_FORMAT_NV12, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV12", NULL }, -+ { SPA_VIDEO_FORMAT_NV21, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV21", NULL }, -+ { SPA_VIDEO_FORMAT_GRAY8, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GRAY8", NULL }, -+ { SPA_VIDEO_FORMAT_GRAY16_BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GRAY16_BE", NULL }, -+ { SPA_VIDEO_FORMAT_GRAY16_LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GRAY16_LE", NULL }, -+ { SPA_VIDEO_FORMAT_v308, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "v308", NULL }, -+ { SPA_VIDEO_FORMAT_RGB16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB16", NULL }, -+ { SPA_VIDEO_FORMAT_BGR16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGR16", NULL }, -+ { SPA_VIDEO_FORMAT_RGB15, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB15", NULL }, -+ { SPA_VIDEO_FORMAT_BGR15, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGR15", NULL }, -+ { SPA_VIDEO_FORMAT_UYVP, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "UYVP", NULL }, -+ { SPA_VIDEO_FORMAT_A420, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A420", NULL }, -+ { SPA_VIDEO_FORMAT_RGB8P, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB8P", NULL }, -+ { SPA_VIDEO_FORMAT_YUV9, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YUV9", NULL }, -+ { SPA_VIDEO_FORMAT_YVU9, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YVU9", NULL }, -+ { SPA_VIDEO_FORMAT_IYU1, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "IYU1", NULL }, -+ { SPA_VIDEO_FORMAT_ARGB64, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ARGB64", NULL }, -+ { SPA_VIDEO_FORMAT_AYUV64, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "AYUV64", NULL }, -+ { SPA_VIDEO_FORMAT_r210, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "r210", NULL }, -+ { SPA_VIDEO_FORMAT_I420_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_I420_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_NV16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV16", NULL }, -+ { SPA_VIDEO_FORMAT_NV24, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV24", NULL }, -+ { SPA_VIDEO_FORMAT_NV12_64Z32, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV12_64Z32", NULL }, -+ { SPA_VIDEO_FORMAT_A420_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A420_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_A420_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A420_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_A422_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A422_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_A422_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A422_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_A444_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A444_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_A444_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A444_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_NV61, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV61", NULL }, -+ { SPA_VIDEO_FORMAT_P010_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "P010_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_P010_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "P010_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_IYU2, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "IYU2", NULL }, -+ { SPA_VIDEO_FORMAT_VYUY, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "VYUY", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_I420_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_I420_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_RGBA_F16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBA_F16", NULL }, -+ { SPA_VIDEO_FORMAT_RGBA_F32, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBA_F32", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_RAW_TYPES_H */ -diff --git a/third_party/pipewire/spa/pod/builder.h b/third_party/pipewire/spa/pod/builder.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/builder.h -@@ -0,0 +1,671 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_BUILDER_H -+#define SPA_POD_BUILDER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+#include -+ -+struct spa_pod_builder_state { -+ uint32_t offset; -+#define SPA_POD_BUILDER_FLAG_BODY (1<<0) -+#define SPA_POD_BUILDER_FLAG_FIRST (1<<1) -+ uint32_t flags; -+ struct spa_pod_frame *frame; -+}; -+ -+struct spa_pod_builder; -+ -+struct spa_pod_builder_callbacks { -+#define SPA_VERSION_POD_BUILDER_CALLBACKS 0 -+ uint32_t version; -+ -+ int (*overflow) (void *data, uint32_t size); -+}; -+ -+struct spa_pod_builder { -+ void *data; -+ uint32_t size; -+ uint32_t _padding; -+ struct spa_pod_builder_state state; -+ struct spa_callbacks callbacks; -+}; -+ -+#define SPA_POD_BUILDER_INIT(buffer,size) (struct spa_pod_builder){ buffer, size, } -+ -+static inline void -+spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builder_state *state) -+{ -+ *state = builder->state; -+} -+ -+static inline void -+spa_pod_builder_set_callbacks(struct spa_pod_builder *builder, -+ const struct spa_pod_builder_callbacks *callbacks, void *data) -+{ -+ builder->callbacks = SPA_CALLBACKS_INIT(callbacks, data); -+} -+ -+static inline void -+spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state) -+{ -+ struct spa_pod_frame *f; -+ uint32_t size = builder->state.offset - state->offset; -+ builder->state = *state; -+ for (f = builder->state.frame; f ; f = f->parent) -+ f->pod.size -= size; -+} -+ -+static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size) -+{ -+ *builder = SPA_POD_BUILDER_INIT(data, size); -+} -+ -+static inline struct spa_pod * -+spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset) -+{ -+ uint32_t size = builder->size; -+ if (offset + 8 <= size) { -+ struct spa_pod *pod = SPA_MEMBER(builder->data, offset, struct spa_pod); -+ if (offset + SPA_POD_SIZE(pod) <= size) -+ return pod; -+ } -+ return NULL; -+} -+ -+static inline struct spa_pod * -+spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ if (frame->offset + SPA_POD_SIZE(&frame->pod) <= builder->size) -+ return SPA_MEMBER(builder->data, frame->offset, struct spa_pod); -+ return NULL; -+} -+ -+static inline void -+spa_pod_builder_push(struct spa_pod_builder *builder, -+ struct spa_pod_frame *frame, -+ const struct spa_pod *pod, -+ uint32_t offset) -+{ -+ frame->pod = *pod; -+ frame->offset = offset; -+ frame->parent = builder->state.frame; -+ frame->flags = builder->state.flags; -+ builder->state.frame = frame; -+ -+ if (frame->pod.type == SPA_TYPE_Array || frame->pod.type == SPA_TYPE_Choice) -+ builder->state.flags = SPA_POD_BUILDER_FLAG_FIRST | SPA_POD_BUILDER_FLAG_BODY; -+} -+ -+static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size) -+{ -+ int res = 0; -+ struct spa_pod_frame *f; -+ uint32_t offset = builder->state.offset; -+ -+ if (offset + size > builder->size) { -+ res = -ENOSPC; -+ spa_callbacks_call_res(&builder->callbacks, struct spa_pod_builder_callbacks, res, -+ overflow, 0, offset + size); -+ } -+ if (res == 0 && data) -+ memcpy(SPA_MEMBER(builder->data, offset, void), data, size); -+ -+ builder->state.offset += size; -+ -+ for (f = builder->state.frame; f ; f = f->parent) -+ f->pod.size += size; -+ -+ return res; -+} -+ -+static inline int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size) -+{ -+ uint64_t zeroes = 0; -+ size = SPA_ROUND_UP_N(size, 8) - size; -+ return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0; -+} -+ -+static inline int -+spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size) -+{ -+ int r, res = spa_pod_builder_raw(builder, data, size); -+ if ((r = spa_pod_builder_pad(builder, size)) < 0) -+ res = r; -+ return res; -+} -+ -+static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ struct spa_pod *pod; -+ -+ if ((pod = (struct spa_pod*)spa_pod_builder_frame(builder, frame)) != NULL) -+ *pod = frame->pod; -+ -+ builder->state.frame = frame->parent; -+ builder->state.flags = frame->flags; -+ spa_pod_builder_pad(builder, builder->state.offset); -+ return pod; -+} -+ -+static inline int -+spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p) -+{ -+ const void *data; -+ uint32_t size; -+ int r, res; -+ -+ if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) { -+ data = SPA_POD_BODY_CONST(p); -+ size = SPA_POD_BODY_SIZE(p); -+ } else { -+ data = p; -+ size = SPA_POD_SIZE(p); -+ SPA_FLAG_CLEAR(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST); -+ } -+ res = spa_pod_builder_raw(builder, data, size); -+ if (builder->state.flags != SPA_POD_BUILDER_FLAG_BODY) -+ if ((r = spa_pod_builder_pad(builder, size)) < 0) -+ res = r; -+ return res; -+} -+ -+#define SPA_POD_INIT(size,type) (struct spa_pod) { size, type } -+ -+#define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None) -+ -+static inline int spa_pod_builder_none(struct spa_pod_builder *builder) -+{ -+ const struct spa_pod p = SPA_POD_INIT_None(); -+ return spa_pod_builder_primitive(builder, &p); -+} -+ -+#define SPA_POD_INIT_Bool(val) (struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, val ? 1 : 0, 0 } -+ -+static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val) -+{ -+ const struct spa_pod_bool p = SPA_POD_INIT_Bool(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Id(val) (struct spa_pod_id){ { sizeof(uint32_t), SPA_TYPE_Id }, (uint32_t)val, 0 } -+ -+static inline int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val) -+{ -+ const struct spa_pod_id p = SPA_POD_INIT_Id(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Int(val) (struct spa_pod_int){ { sizeof(int32_t), SPA_TYPE_Int }, (int32_t)val, 0 } -+ -+static inline int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val) -+{ -+ const struct spa_pod_int p = SPA_POD_INIT_Int(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Long(val) (struct spa_pod_long){ { sizeof(int64_t), SPA_TYPE_Long }, (int64_t)val } -+ -+static inline int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val) -+{ -+ const struct spa_pod_long p = SPA_POD_INIT_Long(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Float(val) (struct spa_pod_float){ { sizeof(float), SPA_TYPE_Float }, val } -+ -+static inline int spa_pod_builder_float(struct spa_pod_builder *builder, float val) -+{ -+ const struct spa_pod_float p = SPA_POD_INIT_Float(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Double(val) (struct spa_pod_double){ { sizeof(double), SPA_TYPE_Double }, val } -+ -+static inline int spa_pod_builder_double(struct spa_pod_builder *builder, double val) -+{ -+ const struct spa_pod_double p = SPA_POD_INIT_Double(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_String(len) (struct spa_pod_string){ { len, SPA_TYPE_String } } -+ -+static inline int -+spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len) -+{ -+ int r, res; -+ res = spa_pod_builder_raw(builder, str, len); -+ if ((r = spa_pod_builder_raw(builder, "", 1)) < 0) -+ res = r; -+ if ((r = spa_pod_builder_pad(builder, builder->state.offset)) < 0) -+ res = r; -+ return res; -+} -+ -+static inline int -+spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len) -+{ -+ const struct spa_pod_string p = SPA_POD_INIT_String(len+1); -+ int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ if ((r = spa_pod_builder_write_string(builder, str, len)) < 0) -+ res = r; -+ return res; -+} -+ -+static inline int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str) -+{ -+ uint32_t len = str ? strlen(str) : 0; -+ return spa_pod_builder_string_len(builder, str ? str : "", len); -+} -+ -+#define SPA_POD_INIT_Bytes(len) (struct spa_pod_bytes){ { len, SPA_TYPE_Bytes } } -+ -+static inline int -+spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len) -+{ -+ const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len); -+ int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ if ((r = spa_pod_builder_raw_padded(builder, bytes, len)) < 0) -+ res = r; -+ return res; -+} -+static inline void * -+spa_pod_builder_reserve_bytes(struct spa_pod_builder *builder, uint32_t len) -+{ -+ uint32_t offset = builder->state.offset; -+ if (spa_pod_builder_bytes(builder, NULL, len) < 0) -+ return NULL; -+ return SPA_POD_BODY(spa_pod_builder_deref(builder, offset)); -+} -+ -+#define SPA_POD_INIT_Pointer(type,value) (struct spa_pod_pointer){ { sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { type, 0, value } } -+ -+static inline int -+spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val) -+{ -+ const struct spa_pod_pointer p = SPA_POD_INIT_Pointer(type, val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Fd(fd) (struct spa_pod_fd){ { sizeof(int64_t), SPA_TYPE_Fd }, fd } -+ -+static inline int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd) -+{ -+ const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Rectangle(val) (struct spa_pod_rectangle){ { sizeof(struct spa_rectangle), SPA_TYPE_Rectangle }, val } -+ -+static inline int -+spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height) -+{ -+ const struct spa_pod_rectangle p = SPA_POD_INIT_Rectangle(SPA_RECTANGLE(width, height)); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Fraction(val) (struct spa_pod_fraction){ { sizeof(struct spa_fraction), SPA_TYPE_Fraction }, val } -+ -+static inline int -+spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom) -+{ -+ const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom)); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+static inline int -+spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ const struct spa_pod_array p = -+ { {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array}, -+ {{0, 0}} }; -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+static inline int -+spa_pod_builder_array(struct spa_pod_builder *builder, -+ uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems) -+{ -+ const struct spa_pod_array p = { -+ {(uint32_t)(sizeof(struct spa_pod_array_body) + n_elems * child_size), SPA_TYPE_Array}, -+ {{child_size, child_type}} -+ }; -+ int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ if ((r = spa_pod_builder_raw_padded(builder, elems, child_size * n_elems)) < 0) -+ res = r; -+ return res; -+} -+ -+#define SPA_POD_INIT_CHOICE_BODY(type, flags, child_size, child_type) \ -+ (struct spa_pod_choice_body) { type, flags, { child_size, child_type }} -+ -+#define SPA_POD_INIT_Choice(type, ctype, child_type, n_vals, ...) \ -+ (struct { struct spa_pod_choice choice; ctype vals[n_vals];}) \ -+ { { { n_vals * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice }, \ -+ { type, 0, { sizeof(ctype), child_type } } }, { __VA_ARGS__ } } -+ -+static inline int -+spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame, -+ uint32_t type, uint32_t flags) -+{ -+ const struct spa_pod_choice p = -+ { {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice}, -+ { type, flags, {0, 0}} }; -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+#define SPA_POD_INIT_Struct(size) (struct spa_pod_struct){ { size, SPA_TYPE_Struct } } -+ -+static inline int -+spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ const struct spa_pod_struct p = SPA_POD_INIT_Struct(0); -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+#define SPA_POD_INIT_Object(size,type,id,...) (struct spa_pod_object){ { size, SPA_TYPE_Object }, { type, id }, ##__VA_ARGS__ } -+ -+static inline int -+spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame, -+ uint32_t type, uint32_t id) -+{ -+ const struct spa_pod_object p = -+ SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id); -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+#define SPA_POD_INIT_Prop(key,flags,size,type) \ -+ (struct spa_pod_prop){ key, flags, { size, type } } -+ -+static inline int -+spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags) -+{ -+ const struct { uint32_t key; uint32_t flags; } p = { key, flags }; -+ return spa_pod_builder_raw(builder, &p, sizeof(p)); -+} -+ -+#define SPA_POD_INIT_Sequence(size,unit) \ -+ (struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 } } -+ -+static inline int -+spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit) -+{ -+ const struct spa_pod_sequence p = -+ SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit); -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+static inline uint32_t -+spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type) -+{ -+ const struct { uint32_t offset; uint32_t type; } p = { offset, type }; -+ return spa_pod_builder_raw(builder, &p, sizeof(p)); -+} -+ -+static inline uint32_t spa_choice_from_id(char id) -+{ -+ switch (id) { -+ case 'r': -+ return SPA_CHOICE_Range; -+ case 's': -+ return SPA_CHOICE_Step; -+ case 'e': -+ return SPA_CHOICE_Enum; -+ case 'f': -+ return SPA_CHOICE_Flags; -+ case 'n': -+ default: -+ return SPA_CHOICE_None; -+ } -+} -+ -+#define SPA_POD_BUILDER_COLLECT(builder,type,args) \ -+do { \ -+ switch (type) { \ -+ case 'b': \ -+ spa_pod_builder_bool(builder, !!va_arg(args, int)); \ -+ break; \ -+ case 'I': \ -+ spa_pod_builder_id(builder, va_arg(args, uint32_t)); \ -+ break; \ -+ case 'i': \ -+ spa_pod_builder_int(builder, va_arg(args, int)); \ -+ break; \ -+ case 'l': \ -+ spa_pod_builder_long(builder, va_arg(args, int64_t)); \ -+ break; \ -+ case 'f': \ -+ spa_pod_builder_float(builder, va_arg(args, double)); \ -+ break; \ -+ case 'd': \ -+ spa_pod_builder_double(builder, va_arg(args, double)); \ -+ break; \ -+ case 's': \ -+ { \ -+ char *strval = va_arg(args, char *); \ -+ if (strval != NULL) { \ -+ size_t len = strlen(strval); \ -+ spa_pod_builder_string_len(builder, strval, len); \ -+ } \ -+ else \ -+ spa_pod_builder_none(builder); \ -+ break; \ -+ } \ -+ case 'S': \ -+ { \ -+ char *strval = va_arg(args, char *); \ -+ size_t len = va_arg(args, int); \ -+ spa_pod_builder_string_len(builder, strval, len); \ -+ break; \ -+ } \ -+ case 'y': \ -+ { \ -+ void *ptr = va_arg(args, void *); \ -+ int len = va_arg(args, int); \ -+ spa_pod_builder_bytes(builder, ptr, len); \ -+ break; \ -+ } \ -+ case 'R': \ -+ { \ -+ struct spa_rectangle *rectval = \ -+ va_arg(args, struct spa_rectangle *); \ -+ spa_pod_builder_rectangle(builder, \ -+ rectval->width, rectval->height); \ -+ break; \ -+ } \ -+ case 'F': \ -+ { \ -+ struct spa_fraction *fracval = \ -+ va_arg(args, struct spa_fraction *); \ -+ spa_pod_builder_fraction(builder, fracval->num, fracval->denom);\ -+ break; \ -+ } \ -+ case 'a': \ -+ { \ -+ int child_size = va_arg(args, int); \ -+ int child_type = va_arg(args, int); \ -+ int n_elems = va_arg(args, int); \ -+ void *elems = va_arg(args, void *); \ -+ spa_pod_builder_array(builder, child_size, \ -+ child_type, n_elems, elems); \ -+ break; \ -+ } \ -+ case 'p': \ -+ { \ -+ int t = va_arg(args, uint32_t); \ -+ spa_pod_builder_pointer(builder, t, va_arg(args, void *)); \ -+ break; \ -+ } \ -+ case 'h': \ -+ spa_pod_builder_fd(builder, va_arg(args, int)); \ -+ break; \ -+ case 'P': \ -+ case 'O': \ -+ case 'T': \ -+ case 'V': \ -+ { \ -+ struct spa_pod *pod = va_arg(args, struct spa_pod *); \ -+ if (pod == NULL) \ -+ spa_pod_builder_none(builder); \ -+ else \ -+ spa_pod_builder_primitive(builder, pod); \ -+ break; \ -+ } \ -+ } \ -+} while(false) -+ -+static inline int -+spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args) -+{ -+ int res = 0; -+ struct spa_pod_frame *f = builder->state.frame; -+ uint32_t ftype = f ? f->pod.type : (uint32_t)SPA_TYPE_None; -+ -+ do { -+ const char *format; -+ int n_values = 1; -+ struct spa_pod_frame f; -+ bool choice; -+ -+ switch (ftype) { -+ case SPA_TYPE_Object: -+ { -+ uint32_t key = va_arg(args, uint32_t); -+ if (key == 0) -+ goto exit; -+ spa_pod_builder_prop(builder, key, 0); -+ break; -+ } -+ case SPA_TYPE_Sequence: -+ { -+ uint32_t offset = va_arg(args, uint32_t); -+ uint32_t type = va_arg(args, uint32_t); -+ if (type == 0) -+ goto exit; -+ spa_pod_builder_control(builder, offset, type); -+ } -+ default: -+ break; -+ } -+ if ((format = va_arg(args, const char *)) == NULL) -+ break; -+ -+ choice = *format == '?'; -+ if (choice) { -+ uint32_t type = spa_choice_from_id(*++format); -+ if (*format != '\0') -+ format++; -+ -+ spa_pod_builder_push_choice(builder, &f, type, 0); -+ -+ n_values = va_arg(args, int); -+ } -+ while (n_values-- > 0) -+ SPA_POD_BUILDER_COLLECT(builder, *format, args); -+ -+ if (choice) -+ spa_pod_builder_pop(builder, &f); -+ } while (true); -+ -+ exit: -+ return res; -+} -+ -+static inline int spa_pod_builder_add(struct spa_pod_builder *builder, ...) -+{ -+ int res; -+ va_list args; -+ -+ va_start(args, builder); -+ res = spa_pod_builder_addv(builder, args); -+ va_end(args); -+ -+ return res; -+} -+ -+#define spa_pod_builder_add_object(b,type,id,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ spa_pod_builder_push_object(b, &_f, type, id); \ -+ spa_pod_builder_add(b, ##__VA_ARGS__, 0); \ -+ spa_pod_builder_pop(b, &_f); \ -+}) -+ -+#define spa_pod_builder_add_struct(b,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ spa_pod_builder_push_struct(b, &_f); \ -+ spa_pod_builder_add(b, ##__VA_ARGS__, NULL); \ -+ spa_pod_builder_pop(b, &_f); \ -+}) -+ -+#define spa_pod_builder_add_sequence(b,unit,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ spa_pod_builder_push_sequence(b, &_f, unit); \ -+ spa_pod_builder_add(b, ##__VA_ARGS__, 0, 0); \ -+ spa_pod_builder_pop(b, &_f); \ -+}) -+ -+/** Copy a pod structure */ -+static inline struct spa_pod * -+spa_pod_copy(const struct spa_pod *pod) -+{ -+ size_t size; -+ struct spa_pod *c; -+ -+ size = SPA_POD_SIZE(pod); -+ if ((c = (struct spa_pod *) malloc(size)) == NULL) -+ return NULL; -+ return (struct spa_pod *) memcpy(c, pod, size); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_BUILDER_H */ -diff --git a/third_party/pipewire/spa/pod/command.h b/third_party/pipewire/spa/pod/command.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/command.h -@@ -0,0 +1,61 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_COMMAND_H -+#define SPA_COMMAND_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_command_body { -+ struct spa_pod_object_body body; -+}; -+ -+struct spa_command { -+ struct spa_pod pod; -+ struct spa_command_body body; -+}; -+ -+#define SPA_COMMAND_TYPE(cmd) ((cmd)->body.body.type) -+#define SPA_COMMAND_ID(cmd,type) (SPA_COMMAND_TYPE(cmd) == type ? \ -+ (cmd)->body.body.id : SPA_ID_INVALID) -+ -+#define SPA_COMMAND_INIT_FULL(t,size,type,id,...) (t) \ -+ { { size, SPA_TYPE_Object }, \ -+ { { type, id }, ##__VA_ARGS__ } } \ -+ -+#define SPA_COMMAND_INIT(type,id) \ -+ SPA_COMMAND_INIT_FULL(struct spa_command, \ -+ sizeof(struct spa_command_body), type, id) -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_COMMAND_H */ -diff --git a/third_party/pipewire/spa/pod/compare.h b/third_party/pipewire/spa/pod/compare.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/compare.h -@@ -0,0 +1,181 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_COMPARE_H -+#define SPA_POD_COMPARE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static inline int spa_pod_compare_value(uint32_t type, const void *r1, const void *r2, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_None: -+ return 0; -+ case SPA_TYPE_Bool: -+ case SPA_TYPE_Id: -+ return *(uint32_t *) r1 == *(uint32_t *) r2 ? 0 : 1; -+ case SPA_TYPE_Int: -+ return *(int32_t *) r1 - *(int32_t *) r2; -+ case SPA_TYPE_Long: -+ return *(int64_t *) r1 - *(int64_t *) r2; -+ case SPA_TYPE_Float: -+ return *(float *) r1 - *(float *) r2; -+ case SPA_TYPE_Double: -+ return *(double *) r1 - *(double *) r2; -+ case SPA_TYPE_String: -+ return strcmp((char *)r1, (char *)r2); -+ case SPA_TYPE_Bytes: -+ return memcmp((char *)r1, (char *)r2, size); -+ case SPA_TYPE_Rectangle: -+ { -+ const struct spa_rectangle *rec1 = (struct spa_rectangle *) r1, -+ *rec2 = (struct spa_rectangle *) r2; -+ if (rec1->width == rec2->width && rec1->height == rec2->height) -+ return 0; -+ else if (rec1->width < rec2->width || rec1->height < rec2->height) -+ return -1; -+ else -+ return 1; -+ } -+ case SPA_TYPE_Fraction: -+ { -+ const struct spa_fraction *f1 = (struct spa_fraction *) r1, -+ *f2 = (struct spa_fraction *) r2; -+ int64_t n1, n2; -+ n1 = ((int64_t) f1->num) * f2->denom; -+ n2 = ((int64_t) f2->num) * f1->denom; -+ if (n1 < n2) -+ return -1; -+ else if (n1 > n2) -+ return 1; -+ else -+ return 0; -+ } -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static inline int spa_pod_compare(const struct spa_pod *pod1, -+ const struct spa_pod *pod2) -+{ -+ int res = 0; -+ uint32_t n_vals1, n_vals2; -+ uint32_t choice1, choice2; -+ -+ spa_return_val_if_fail(pod1 != NULL, -EINVAL); -+ spa_return_val_if_fail(pod2 != NULL, -EINVAL); -+ -+ pod1 = spa_pod_get_values(pod1, &n_vals1, &choice1); -+ pod2 = spa_pod_get_values(pod2, &n_vals2, &choice2); -+ -+ if (n_vals1 != n_vals2) -+ return -EINVAL; -+ -+ if (SPA_POD_TYPE(pod1) != SPA_POD_TYPE(pod2)) -+ return -EINVAL; -+ -+ switch (SPA_POD_TYPE(pod1)) { -+ case SPA_TYPE_Struct: -+ { -+ const struct spa_pod *p1, *p2; -+ size_t p1s, p2s; -+ -+ p1 = (const struct spa_pod*)SPA_POD_BODY_CONST(pod1); -+ p1s = SPA_POD_BODY_SIZE(pod1); -+ p2 = (const struct spa_pod*)SPA_POD_BODY_CONST(pod2); -+ p2s = SPA_POD_BODY_SIZE(pod2); -+ -+ while (true) { -+ if (!spa_pod_is_inside(pod1, p1s, p1) || -+ !spa_pod_is_inside(pod2, p2s, p2)) -+ return -EINVAL; -+ -+ if ((res = spa_pod_compare(p1, p2)) != 0) -+ return res; -+ -+ p1 = (const struct spa_pod*)spa_pod_next(p1); -+ p2 = (const struct spa_pod*)spa_pod_next(p2); -+ } -+ break; -+ } -+ case SPA_TYPE_Object: -+ { -+ const struct spa_pod_prop *p1, *p2; -+ const struct spa_pod_object *o1, *o2; -+ -+ o1 = (const struct spa_pod_object*)pod1; -+ o2 = (const struct spa_pod_object*)pod2; -+ -+ p2 = NULL; -+ SPA_POD_OBJECT_FOREACH(o1, p1) { -+ if ((p2 = spa_pod_object_find_prop(o2, p2, p1->key)) == NULL) -+ return 1; -+ if ((res = spa_pod_compare(&p1->value, &p2->value)) != 0) -+ return res; -+ } -+ p1 = NULL; -+ SPA_POD_OBJECT_FOREACH(o2, p2) { -+ if ((p1 = spa_pod_object_find_prop(o1, p1, p2->key)) == NULL) -+ return -1; -+ } -+ break; -+ } -+ case SPA_TYPE_Array: -+ { -+ if (SPA_POD_BODY_SIZE(pod1) != SPA_POD_BODY_SIZE(pod2)) -+ return -EINVAL; -+ res = memcmp(SPA_POD_BODY(pod1), SPA_POD_BODY(pod2), SPA_POD_BODY_SIZE(pod2)); -+ break; -+ } -+ default: -+ if (SPA_POD_BODY_SIZE(pod1) != SPA_POD_BODY_SIZE(pod2)) -+ return -EINVAL; -+ res = spa_pod_compare_value(SPA_POD_TYPE(pod1), -+ SPA_POD_BODY(pod1), SPA_POD_BODY(pod2), -+ SPA_POD_BODY_SIZE(pod1)); -+ break; -+ } -+ return res; -+} -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/third_party/pipewire/spa/pod/event.h b/third_party/pipewire/spa/pod/event.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/event.h -@@ -0,0 +1,59 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_EVENT_H -+#define SPA_EVENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+struct spa_event_body { -+ struct spa_pod_object_body body; -+}; -+ -+struct spa_event { -+ struct spa_pod pod; -+ struct spa_event_body body; -+}; -+ -+#define SPA_EVENT_TYPE(ev) ((ev)->body.body.type) -+#define SPA_EVENT_ID(ev,type) (SPA_EVENT_TYPE(ev) == type ? \ -+ (ev)->body.body.id : SPA_ID_INVALID) -+ -+#define SPA_EVENT_INIT_FULL(t,size,type,id,...) (t) \ -+ { { size, SPA_TYPE_OBJECT }, \ -+ { { type, id }, ##__VA_ARGS__ } } \ -+ -+#define SPA_EVENT_INIT(type,id) \ -+ SPA_EVENT_INIT_FULL(struct spa_event, \ -+ sizeof(struct spa_event_body), type, id) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_EVENT_H */ -diff --git a/third_party/pipewire/spa/pod/filter.h b/third_party/pipewire/spa/pod/filter.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/filter.h -@@ -0,0 +1,395 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+static inline int spa_pod_choice_fix_default(struct spa_pod_choice *choice) -+{ -+ void *val, *alt; -+ int i, nvals; -+ uint32_t type, size; -+ -+ nvals = SPA_POD_CHOICE_N_VALUES(choice); -+ type = SPA_POD_CHOICE_VALUE_TYPE(choice); -+ size = SPA_POD_CHOICE_VALUE_SIZE(choice); -+ alt = val = SPA_POD_CHOICE_VALUES(choice); -+ -+ switch (choice->body.type) { -+ case SPA_CHOICE_None: -+ break; -+ case SPA_CHOICE_Range: -+ case SPA_CHOICE_Step: -+ if (nvals > 1) { -+ alt = SPA_MEMBER(alt, size, void); -+ if (spa_pod_compare_value(type, val, alt, size) < 0) -+ memcpy(val, alt, size); -+ } -+ if (nvals > 2) { -+ alt = SPA_MEMBER(alt, size, void); -+ if (spa_pod_compare_value(type, val, alt, size) > 0) -+ memcpy(val, alt, size); -+ } -+ break; -+ case SPA_CHOICE_Flags: -+ case SPA_CHOICE_Enum: -+ { -+ void *best = NULL; -+ -+ for (i = 1; i < nvals; i++) { -+ alt = SPA_MEMBER(alt, size, void); -+ if (spa_pod_compare_value(type, val, alt, size) == 0) { -+ best = alt; -+ break; -+ } -+ if (best == NULL) -+ best = alt; -+ } -+ if (best) -+ memcpy(val, best, size); -+ -+ if (nvals <= 1) -+ choice->body.type = SPA_CHOICE_None; -+ break; -+ } -+ } -+ return 0; -+} -+ -+static inline int spa_pod_filter_flags_value(struct spa_pod_builder *b, -+ uint32_t type, const void *r1, const void *r2, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_Int: -+ { -+ int32_t val = (*(int32_t *) r1) & (*(int32_t *) r2); -+ if (val == 0) -+ return 0; -+ spa_pod_builder_int(b, val); -+ break; -+ } -+ case SPA_TYPE_Long: -+ { -+ int64_t val = (*(int64_t *) r1) & (*(int64_t *) r2); -+ if (val == 0) -+ return 0; -+ spa_pod_builder_long(b, val); -+ break; -+ } -+ default: -+ return -ENOTSUP; -+ } -+ return 1; -+} -+ -+ -+static inline int -+spa_pod_filter_prop(struct spa_pod_builder *b, -+ const struct spa_pod_prop *p1, -+ const struct spa_pod_prop *p2) -+{ -+ const struct spa_pod *v1, *v2; -+ struct spa_pod_choice *nc; -+ uint32_t j, k, nalt1, nalt2; -+ void *alt1, *alt2, *a1, *a2; -+ uint32_t type, size, p1c, p2c; -+ struct spa_pod_frame f; -+ -+ v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c); -+ alt1 = SPA_POD_BODY(v1); -+ v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c); -+ alt2 = SPA_POD_BODY(v2); -+ -+ type = v1->type; -+ size = v1->size; -+ -+ /* incompatible property types */ -+ if (type != v2->type || size != v2->size || p1->key != p2->key) -+ return -EINVAL; -+ -+ if (p1c == SPA_CHOICE_None || p1c == SPA_CHOICE_Flags) { -+ nalt1 = 1; -+ } else { -+ alt1 = SPA_MEMBER(alt1, size, void); -+ nalt1--; -+ } -+ -+ if (p2c == SPA_CHOICE_None || p2c == SPA_CHOICE_Flags) { -+ nalt2 = 1; -+ } else { -+ alt2 = SPA_MEMBER(alt2, size, void); -+ nalt2--; -+ } -+ -+ /* start with copying the property */ -+ spa_pod_builder_prop(b, p1->key, 0); -+ spa_pod_builder_push_choice(b, &f, 0, 0); -+ nc = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f); -+ -+ /* default value */ -+ spa_pod_builder_primitive(b, v1); -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Enum) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Enum)) { -+ int n_copied = 0; -+ /* copy all equal values but don't copy the default value again */ -+ for (j = 0, a1 = alt1; j < nalt1; j++, a1 = SPA_MEMBER(a1, size, void)) { -+ for (k = 0, a2 = alt2; k < nalt2; k++, a2 = SPA_MEMBER(a2,size,void)) { -+ if (spa_pod_compare_value(type, a1, a2, size) == 0) { -+ if (p1c == SPA_CHOICE_Enum || j > 0) -+ spa_pod_builder_raw(b, a1, size); -+ n_copied++; -+ } -+ } -+ } -+ if (n_copied == 0) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Enum; -+ } -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Range) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Range)) { -+ int n_copied = 0; -+ /* copy all values inside the range */ -+ for (j = 0, a1 = alt1, a2 = alt2; j < nalt1; j++, a1 = SPA_MEMBER(a1,size,void)) { -+ if (spa_pod_compare_value(type, a1, a2, size) < 0) -+ continue; -+ if (spa_pod_compare_value(type, a1, SPA_MEMBER(a2,size,void), size) > 0) -+ continue; -+ spa_pod_builder_raw(b, a1, size); -+ n_copied++; -+ } -+ if (n_copied == 0) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Enum; -+ } -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Step) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Step)) { -+ return -ENOTSUP; -+ } -+ -+ if ((p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Enum)) { -+ int n_copied = 0; -+ /* copy all values inside the range */ -+ for (k = 0, a1 = alt1, a2 = alt2; k < nalt2; k++, a2 = SPA_MEMBER(a2,size,void)) { -+ if (spa_pod_compare_value(type, a2, a1, size) < 0) -+ continue; -+ if (spa_pod_compare_value(type, a2, SPA_MEMBER(a1,size,void), size) > 0) -+ continue; -+ spa_pod_builder_raw(b, a2, size); -+ n_copied++; -+ } -+ if (n_copied == 0) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Enum; -+ } -+ -+ if ((p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Range) || -+ (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Step) || -+ (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Range) || -+ (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Step)) { -+ if (spa_pod_compare_value(type, alt1, alt2, size) < 0) -+ spa_pod_builder_raw(b, alt2, size); -+ else -+ spa_pod_builder_raw(b, alt1, size); -+ -+ alt1 = SPA_MEMBER(alt1,size,void); -+ alt2 = SPA_MEMBER(alt2,size,void); -+ -+ if (spa_pod_compare_value(type, alt1, alt2, size) < 0) -+ spa_pod_builder_raw(b, alt1, size); -+ else -+ spa_pod_builder_raw(b, alt2, size); -+ -+ nc->body.type = SPA_CHOICE_Range; -+ } -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Flags) || -+ (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Flags)) { -+ if (spa_pod_filter_flags_value(b, type, alt1, alt2, size) != 1) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Flags; -+ } -+ -+ if (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Flags) -+ return -ENOTSUP; -+ -+ if (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Flags) -+ return -ENOTSUP; -+ -+ if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_None) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Enum) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Flags) -+ return -ENOTSUP; -+ -+ if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Range) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Step) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Enum) -+ return -ENOTSUP; -+ -+ spa_pod_builder_pop(b, &f); -+ spa_pod_choice_fix_default(nc); -+ -+ return 0; -+} -+ -+static inline int spa_pod_filter_part(struct spa_pod_builder *b, -+ const struct spa_pod *pod, uint32_t pod_size, -+ const struct spa_pod *filter, uint32_t filter_size) -+{ -+ const struct spa_pod *pp, *pf; -+ int res = 0; -+ -+ pf = filter; -+ -+ SPA_POD_FOREACH(pod, pod_size, pp) { -+ bool do_copy = false, do_advance = false; -+ uint32_t filter_offset = 0; -+ struct spa_pod_frame f; -+ -+ switch (SPA_POD_TYPE(pp)) { -+ case SPA_TYPE_Object: -+ if (pf != NULL) { -+ struct spa_pod_object *op = (struct spa_pod_object *) pp; -+ struct spa_pod_object *of = (struct spa_pod_object *) pf; -+ const struct spa_pod_prop *p1, *p2; -+ -+ if (SPA_POD_TYPE(pf) != SPA_POD_TYPE(pp)) -+ return -EINVAL; -+ -+ spa_pod_builder_push_object(b, &f, op->body.type, op->body.id); -+ p2 = NULL; -+ SPA_POD_OBJECT_FOREACH(op, p1) { -+ p2 = spa_pod_object_find_prop(of, p2, p1->key); -+ if (p2 != NULL) -+ res = spa_pod_filter_prop(b, p1, p2); -+ else -+ spa_pod_builder_raw_padded(b, p1, SPA_POD_PROP_SIZE(p1)); -+ if (res < 0) -+ break; -+ } -+ if (res >= 0) { -+ p1 = NULL; -+ SPA_POD_OBJECT_FOREACH(of, p2) { -+ p1 = spa_pod_object_find_prop(op, p1, p2->key); -+ if (p1 != NULL) -+ continue; -+ -+ spa_pod_builder_raw_padded(b, p2, SPA_POD_PROP_SIZE(p2)); -+ } -+ } -+ spa_pod_builder_pop(b, &f); -+ do_advance = true; -+ } -+ else -+ do_copy = true; -+ break; -+ -+ case SPA_TYPE_Struct: -+ if (pf != NULL) { -+ if (SPA_POD_TYPE(pf) != SPA_POD_TYPE(pp)) -+ return -EINVAL; -+ -+ filter_offset = sizeof(struct spa_pod_struct); -+ spa_pod_builder_push_struct(b, &f); -+ res = spa_pod_filter_part(b, -+ SPA_MEMBER(pp,filter_offset,const struct spa_pod), -+ SPA_POD_SIZE(pp) - filter_offset, -+ SPA_MEMBER(pf,filter_offset,const struct spa_pod), -+ SPA_POD_SIZE(pf) - filter_offset); -+ spa_pod_builder_pop(b, &f); -+ do_advance = true; -+ } -+ else -+ do_copy = true; -+ break; -+ -+ default: -+ if (pf != NULL) { -+ if (SPA_POD_SIZE(pp) != SPA_POD_SIZE(pf)) -+ return -EINVAL; -+ if (memcmp(pp, pf, SPA_POD_SIZE(pp)) != 0) -+ return -EINVAL; -+ do_advance = true; -+ } -+ do_copy = true; -+ break; -+ } -+ if (do_copy) -+ spa_pod_builder_raw_padded(b, pp, SPA_POD_SIZE(pp)); -+ if (do_advance) { -+ pf = (const struct spa_pod*)spa_pod_next(pf); -+ if (!spa_pod_is_inside(filter, filter_size, pf)) -+ pf = NULL; -+ } -+ if (res < 0) -+ break; -+ } -+ return res; -+} -+ -+static inline int -+spa_pod_filter(struct spa_pod_builder *b, -+ struct spa_pod **result, -+ const struct spa_pod *pod, -+ const struct spa_pod *filter) -+{ -+ int res; -+ struct spa_pod_builder_state state; -+ -+ spa_return_val_if_fail(pod != NULL, -EINVAL); -+ spa_return_val_if_fail(b != NULL, -EINVAL); -+ -+ spa_pod_builder_get_state(b, &state); -+ if (filter == NULL) -+ res = spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod)); -+ else -+ res = spa_pod_filter_part(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter)); -+ -+ if (res < 0) { -+ spa_pod_builder_reset(b, &state); -+ } else if (result) { -+ *result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset); -+ if (*result == NULL) -+ res = -ENOSPC; -+ } -+ return res; -+} -diff --git a/third_party/pipewire/spa/pod/iter.h b/third_party/pipewire/spa/pod/iter.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/iter.h -@@ -0,0 +1,446 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_ITER_H -+#define SPA_POD_ITER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+struct spa_pod_frame { -+ struct spa_pod pod; -+ struct spa_pod_frame *parent; -+ uint32_t offset; -+ uint32_t flags; -+}; -+ -+static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter) -+{ -+ return SPA_POD_BODY(iter) <= SPA_MEMBER(pod, size, void) && -+ SPA_MEMBER(iter, SPA_POD_SIZE(iter), void) <= SPA_MEMBER(pod, size, void); -+} -+ -+static inline void *spa_pod_next(const void *iter) -+{ -+ return SPA_MEMBER(iter, SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), void); -+} -+ -+static inline struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_object_body *body) -+{ -+ return SPA_MEMBER(body, sizeof(struct spa_pod_object_body), struct spa_pod_prop); -+} -+ -+static inline bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body, -+ uint32_t size, const struct spa_pod_prop *iter) -+{ -+ return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_MEMBER(body, size, void) && -+ SPA_MEMBER(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_MEMBER(body, size, void); -+} -+ -+static inline struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter) -+{ -+ return SPA_MEMBER(iter, SPA_ROUND_UP_N(SPA_POD_PROP_SIZE(iter), 8), struct spa_pod_prop); -+} -+ -+static inline struct spa_pod_control *spa_pod_control_first(const struct spa_pod_sequence_body *body) -+{ -+ return SPA_MEMBER(body, sizeof(struct spa_pod_sequence_body), struct spa_pod_control); -+} -+ -+static inline bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body, -+ uint32_t size, const struct spa_pod_control *iter) -+{ -+ return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_MEMBER(body, size, void) && -+ SPA_MEMBER(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_MEMBER(body, size, void); -+} -+ -+static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter) -+{ -+ return SPA_MEMBER(iter, SPA_ROUND_UP_N(SPA_POD_CONTROL_SIZE(iter), 8), struct spa_pod_control); -+} -+ -+#define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \ -+ for ((iter) = (__typeof__(iter))SPA_MEMBER((body), sizeof(struct spa_pod_array_body), void); \ -+ (iter) < (__typeof__(iter))SPA_MEMBER((body), (_size), void); \ -+ (iter) = (__typeof__(iter))SPA_MEMBER((iter), (body)->child.size, void)) -+ -+#define SPA_POD_ARRAY_FOREACH(obj, iter) \ -+ SPA_POD_ARRAY_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_CHOICE_BODY_FOREACH(body, _size, iter) \ -+ for ((iter) = (__typeof__(iter))SPA_MEMBER((body), sizeof(struct spa_pod_choice_body), void); \ -+ (iter) < (__typeof__(iter))SPA_MEMBER((body), (_size), void); \ -+ (iter) = (__typeof__(iter))SPA_MEMBER((iter), (body)->child.size, void)) -+ -+#define SPA_POD_CHOICE_FOREACH(obj, iter) \ -+ SPA_POD_CHOICE_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_FOREACH(pod, size, iter) \ -+ for ((iter) = (pod); \ -+ spa_pod_is_inside(pod, size, iter); \ -+ (iter) = (__typeof__(iter))spa_pod_next(iter)) -+ -+#define SPA_POD_STRUCT_FOREACH(obj, iter) \ -+ SPA_POD_FOREACH(SPA_POD_BODY(obj), SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \ -+ for ((iter) = spa_pod_prop_first(body); \ -+ spa_pod_prop_is_inside(body, size, iter); \ -+ (iter) = spa_pod_prop_next(iter)) -+ -+#define SPA_POD_OBJECT_FOREACH(obj, iter) \ -+ SPA_POD_OBJECT_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_SEQUENCE_BODY_FOREACH(body, size, iter) \ -+ for ((iter) = spa_pod_control_first(body); \ -+ spa_pod_control_is_inside(body, size, iter); \ -+ (iter) = spa_pod_control_next(iter)) -+ -+#define SPA_POD_SEQUENCE_FOREACH(seq, iter) \ -+ SPA_POD_SEQUENCE_BODY_FOREACH(&(seq)->body, SPA_POD_BODY_SIZE(seq), iter) -+ -+ -+static inline void *spa_pod_from_data(void *data, size_t maxsize, off_t offset, size_t size) -+{ -+ void *pod; -+ if (size < sizeof(struct spa_pod) || offset + size > maxsize) -+ return NULL; -+ pod = SPA_MEMBER(data, offset, void); -+ if (SPA_POD_SIZE(pod) > size) -+ return NULL; -+ return pod; -+} -+ -+static inline int spa_pod_is_none(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_None); -+} -+ -+static inline int spa_pod_is_bool(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Bool && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t)); -+} -+ -+static inline int spa_pod_get_bool(const struct spa_pod *pod, bool *value) -+{ -+ if (!spa_pod_is_bool(pod)) -+ return -EINVAL; -+ *value = !!SPA_POD_VALUE(struct spa_pod_bool, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_id(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Id && SPA_POD_BODY_SIZE(pod) >= sizeof(uint32_t)); -+} -+ -+static inline int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value) -+{ -+ if (!spa_pod_is_id(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_id, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_int(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Int && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t)); -+} -+ -+static inline int spa_pod_get_int(const struct spa_pod *pod, int32_t *value) -+{ -+ if (!spa_pod_is_int(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_int, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_long(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Long && SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t)); -+} -+ -+static inline int spa_pod_get_long(const struct spa_pod *pod, int64_t *value) -+{ -+ if (!spa_pod_is_long(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_long, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_float(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Float && SPA_POD_BODY_SIZE(pod) >= sizeof(float)); -+} -+ -+static inline int spa_pod_get_float(const struct spa_pod *pod, float *value) -+{ -+ if (!spa_pod_is_float(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_float, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_double(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Double && SPA_POD_BODY_SIZE(pod) >= sizeof(double)); -+} -+ -+static inline int spa_pod_get_double(const struct spa_pod *pod, double *value) -+{ -+ if (!spa_pod_is_double(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_double, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_string(const struct spa_pod *pod) -+{ -+ const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_String && -+ SPA_POD_BODY_SIZE(pod) > 0 && -+ s[SPA_POD_BODY_SIZE(pod)-1] == '\0'); -+} -+ -+static inline int spa_pod_get_string(const struct spa_pod *pod, const char **value) -+{ -+ if (!spa_pod_is_string(pod)) -+ return -EINVAL; -+ *value = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); -+ return 0; -+} -+ -+static inline int spa_pod_copy_string(const struct spa_pod *pod, size_t maxlen, char *dest) -+{ -+ const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); -+ if (!spa_pod_is_string(pod) || maxlen < 1) -+ return -EINVAL; -+ strncpy(dest, s, maxlen-1); -+ dest[maxlen-1]= '\0'; -+ return 0; -+} -+ -+static inline int spa_pod_is_bytes(const struct spa_pod *pod) -+{ -+ return SPA_POD_TYPE(pod) == SPA_TYPE_Bytes; -+} -+ -+static inline int spa_pod_get_bytes(const struct spa_pod *pod, const void **value, uint32_t *len) -+{ -+ if (!spa_pod_is_bytes(pod)) -+ return -EINVAL; -+ *value = (const void *)SPA_POD_CONTENTS(struct spa_pod_bytes, pod); -+ *len = SPA_POD_BODY_SIZE(pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_pointer(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Pointer && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_pointer_body)); -+} -+ -+static inline int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *type, const void **value) -+{ -+ if (!spa_pod_is_pointer(pod)) -+ return -EINVAL; -+ *type = ((struct spa_pod_pointer*)pod)->body.type; -+ *value = ((struct spa_pod_pointer*)pod)->body.value; -+ return 0; -+} -+ -+static inline int spa_pod_is_fd(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Fd && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t)); -+} -+ -+static inline int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value) -+{ -+ if (!spa_pod_is_fd(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_fd, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_rectangle(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Rectangle && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_rectangle)); -+} -+ -+static inline int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa_rectangle *value) -+{ -+ if (!spa_pod_is_rectangle(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_rectangle, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_fraction(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Fraction && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_fraction)); -+} -+ -+static inline int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fraction *value) -+{ -+ spa_return_val_if_fail(spa_pod_is_fraction(pod), -EINVAL); -+ *value = SPA_POD_VALUE(struct spa_pod_fraction, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_bitmap(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Bitmap && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(uint8_t)); -+} -+ -+static inline int spa_pod_is_array(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Array && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_array_body)); -+} -+ -+static inline void *spa_pod_get_array(const struct spa_pod *pod, uint32_t *n_values) -+{ -+ spa_return_val_if_fail(spa_pod_is_array(pod), NULL); -+ *n_values = SPA_POD_ARRAY_N_VALUES(pod); -+ return SPA_POD_ARRAY_VALUES(pod); -+} -+ -+static inline uint32_t spa_pod_copy_array(const struct spa_pod *pod, uint32_t type, -+ void *values, uint32_t max_values) -+{ -+ uint32_t n_values; -+ void *v = spa_pod_get_array(pod, &n_values); -+ if (v == NULL || max_values == 0 || SPA_POD_ARRAY_VALUE_TYPE(pod) != type) -+ return 0; -+ n_values = SPA_MIN(n_values, max_values); -+ memcpy(values, v, SPA_POD_ARRAY_VALUE_SIZE(pod) * n_values); -+ return n_values; -+} -+ -+static inline int spa_pod_is_choice(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Choice && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_choice_body)); -+} -+ -+static inline struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice) -+{ -+ if (pod->type == SPA_TYPE_Choice) { -+ *choice = SPA_POD_CHOICE_TYPE(pod); -+ *n_vals = *choice == SPA_CHOICE_None ? 1 : SPA_POD_CHOICE_N_VALUES(pod); -+ return (struct spa_pod*)SPA_POD_CHOICE_CHILD(pod); -+ } else { -+ *n_vals = 1; -+ *choice = SPA_CHOICE_None; -+ return (struct spa_pod*)pod; -+ } -+} -+ -+static inline int spa_pod_is_struct(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Struct); -+} -+ -+static inline int spa_pod_is_object(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Object && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_object_body)); -+} -+ -+static inline bool spa_pod_is_object_type(const struct spa_pod *pod, uint32_t type) -+{ -+ return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_TYPE(pod) == type); -+} -+ -+static inline bool spa_pod_is_object_id(const struct spa_pod *pod, uint32_t id) -+{ -+ return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_ID(pod) == id); -+} -+ -+static inline int spa_pod_is_sequence(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Sequence && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_sequence_body)); -+} -+ -+static inline const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod, -+ const struct spa_pod_prop *start, uint32_t key) -+{ -+ const struct spa_pod_prop *first, *res; -+ -+ first = spa_pod_prop_first(&pod->body); -+ start = start ? spa_pod_prop_next(start) : first; -+ -+ for (res = start; spa_pod_prop_is_inside(&pod->body, pod->pod.size, res); -+ res = spa_pod_prop_next(res)) { -+ if (res->key == key) -+ return res; -+ } -+ for (res = first; res != start; res = spa_pod_prop_next(res)) { -+ if (res->key == key) -+ return res; -+ } -+ return NULL; -+} -+ -+static inline const struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod, -+ const struct spa_pod_prop *start, uint32_t key) -+{ -+ if (!spa_pod_is_object(pod)) -+ return NULL; -+ return spa_pod_object_find_prop((const struct spa_pod_object *)pod, start, key); -+} -+ -+static inline int spa_pod_object_fixate(struct spa_pod_object *pod) -+{ -+ struct spa_pod_prop *res; -+ SPA_POD_OBJECT_FOREACH(pod, res) { -+ if (res->value.type == SPA_TYPE_Choice) -+ ((struct spa_pod_choice*)&res->value)->body.type = SPA_CHOICE_None; -+ } -+ return 0; -+} -+ -+static inline int spa_pod_fixate(struct spa_pod *pod) -+{ -+ if (!spa_pod_is_object(pod)) -+ return -EINVAL; -+ return spa_pod_object_fixate((struct spa_pod_object *)pod); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_H */ -diff --git a/third_party/pipewire/spa/pod/parser.h b/third_party/pipewire/spa/pod/parser.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/parser.h -@@ -0,0 +1,573 @@ -+/* Spa -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_PARSER_H -+#define SPA_POD_PARSER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+struct spa_pod_parser_state { -+ uint32_t offset; -+ uint32_t flags; -+ struct spa_pod_frame *frame; -+}; -+ -+struct spa_pod_parser { -+ const void *data; -+ uint32_t size; -+ uint32_t _padding; -+ struct spa_pod_parser_state state; -+}; -+ -+#define SPA_POD_PARSER_INIT(buffer,size) (struct spa_pod_parser){ buffer, size, } -+ -+static inline void spa_pod_parser_init(struct spa_pod_parser *parser, -+ const void *data, uint32_t size) -+{ -+ *parser = SPA_POD_PARSER_INIT(data, size); -+} -+ -+static inline void spa_pod_parser_pod(struct spa_pod_parser *parser, -+ const struct spa_pod *pod) -+{ -+ spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod)); -+} -+ -+static inline void -+spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state) -+{ -+ *state = parser->state; -+} -+ -+static inline void -+spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state) -+{ -+ parser->state = *state; -+} -+ -+static inline struct spa_pod * -+spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size) -+{ -+ if (offset + 8 <= size) { -+ struct spa_pod *pod = SPA_MEMBER(parser->data, offset, struct spa_pod); -+ if (offset + SPA_POD_SIZE(pod) <= size) -+ return pod; -+ } -+ return NULL; -+} -+ -+static inline struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame) -+{ -+ return SPA_MEMBER(parser->data, frame->offset, struct spa_pod); -+} -+ -+static inline void spa_pod_parser_push(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset) -+{ -+ frame->pod = *pod; -+ frame->offset = offset; -+ frame->parent = parser->state.frame; -+ frame->flags = parser->state.flags; -+ parser->state.frame = frame; -+} -+ -+static inline struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser) -+{ -+ struct spa_pod_frame *f = parser->state.frame; -+ uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size; -+ return spa_pod_parser_deref(parser, parser->state.offset, size); -+} -+ -+static inline void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod) -+{ -+ parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), 8); -+} -+ -+static inline struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser) -+{ -+ struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod) -+ spa_pod_parser_advance(parser, pod); -+ return pod; -+} -+ -+static inline int spa_pod_parser_pop(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame) -+{ -+ parser->state.frame = frame->parent; -+ parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), 8); -+ return 0; -+} -+ -+static inline int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_bool(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_id(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_int(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_long(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_float(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_double(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_string(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_bytes(pod, value, len)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_pointer(pod, type, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_fd(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_rectangle(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_fraction(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value) -+{ -+ struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod == NULL) -+ return -EPIPE; -+ *value = pod; -+ spa_pod_parser_advance(parser, pod); -+ return 0; -+} -+static inline int spa_pod_parser_push_struct(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame) -+{ -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod == NULL) -+ return -EPIPE; -+ if (!spa_pod_is_struct(pod)) -+ return -EINVAL; -+ spa_pod_parser_push(parser, frame, pod, parser->state.offset); -+ parser->state.offset += sizeof(struct spa_pod_struct); -+ return 0; -+} -+ -+static inline int spa_pod_parser_push_object(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame, uint32_t type, uint32_t *id) -+{ -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod == NULL) -+ return -EPIPE; -+ if (!spa_pod_is_object(pod)) -+ return -EINVAL; -+ if (type != SPA_POD_OBJECT_TYPE(pod)) -+ return -EPROTO; -+ if (id != NULL) -+ *id = SPA_POD_OBJECT_ID(pod); -+ spa_pod_parser_push(parser, frame, pod, parser->state.offset); -+ parser->state.offset = parser->size; -+ return 0; -+} -+ -+static inline bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type) -+{ -+ if (pod == NULL) -+ return false; -+ -+ if (spa_pod_is_choice(pod) && -+ SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None && -+ spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type)) -+ return true; -+ -+ switch (type) { -+ case 'P': -+ return true; -+ case 'b': -+ return spa_pod_is_bool(pod); -+ case 'I': -+ return spa_pod_is_id(pod); -+ case 'i': -+ return spa_pod_is_int(pod); -+ case 'l': -+ return spa_pod_is_long(pod); -+ case 'f': -+ return spa_pod_is_float(pod); -+ case 'd': -+ return spa_pod_is_double(pod); -+ case 's': -+ return spa_pod_is_string(pod) || spa_pod_is_none(pod); -+ case 'S': -+ return spa_pod_is_string(pod); -+ case 'y': -+ return spa_pod_is_bytes(pod); -+ case 'R': -+ return spa_pod_is_rectangle(pod); -+ case 'F': -+ return spa_pod_is_fraction(pod); -+ case 'B': -+ return spa_pod_is_bitmap(pod); -+ case 'a': -+ return spa_pod_is_array(pod); -+ case 'p': -+ return spa_pod_is_pointer(pod); -+ case 'h': -+ return spa_pod_is_fd(pod); -+ case 'T': -+ return spa_pod_is_struct(pod) || spa_pod_is_none(pod); -+ case 'O': -+ return spa_pod_is_object(pod) || spa_pod_is_none(pod); -+ case 'V': -+ return spa_pod_is_choice(pod); -+ default: -+ return false; -+ } -+} -+ -+#define SPA_POD_PARSER_COLLECT(pod,_type,args) \ -+do { \ -+ switch (_type) { \ -+ case 'b': \ -+ *va_arg(args, bool*) = SPA_POD_VALUE(struct spa_pod_bool, pod); \ -+ break; \ -+ case 'I': \ -+ case 'i': \ -+ *va_arg(args, int32_t*) = SPA_POD_VALUE(struct spa_pod_int, pod); \ -+ break; \ -+ case 'l': \ -+ *va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_long, pod); \ -+ break; \ -+ case 'f': \ -+ *va_arg(args, float*) = SPA_POD_VALUE(struct spa_pod_float, pod); \ -+ break; \ -+ case 'd': \ -+ *va_arg(args, double*) = SPA_POD_VALUE(struct spa_pod_double, pod); \ -+ break; \ -+ case 's': \ -+ *va_arg(args, char**) = \ -+ (pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \ -+ ? NULL \ -+ : (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod)); \ -+ break; \ -+ case 'S': \ -+ { \ -+ char *dest = va_arg(args, char*); \ -+ uint32_t maxlen = va_arg(args, uint32_t); \ -+ strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \ -+ break; \ -+ } \ -+ case 'y': \ -+ *(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \ -+ *(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \ -+ break; \ -+ case 'R': \ -+ *va_arg(args, struct spa_rectangle*) = \ -+ SPA_POD_VALUE(struct spa_pod_rectangle, pod); \ -+ break; \ -+ case 'F': \ -+ *va_arg(args, struct spa_fraction*) = \ -+ SPA_POD_VALUE(struct spa_pod_fraction, pod); \ -+ break; \ -+ case 'B': \ -+ *va_arg(args, uint32_t **) = \ -+ (uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \ -+ break; \ -+ case 'a': \ -+ *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \ -+ *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \ -+ *va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \ -+ *va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \ -+ break; \ -+ case 'p': \ -+ { \ -+ struct spa_pod_pointer_body *b = \ -+ (struct spa_pod_pointer_body *) SPA_POD_BODY(pod); \ -+ *(va_arg(args, uint32_t *)) = b->type; \ -+ *(va_arg(args, const void **)) = b->value; \ -+ break; \ -+ } \ -+ case 'h': \ -+ *va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \ -+ break; \ -+ case 'P': \ -+ case 'T': \ -+ case 'O': \ -+ case 'V': \ -+ { \ -+ const struct spa_pod **d = va_arg(args, const struct spa_pod**); \ -+ if (d) \ -+ *d = (pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \ -+ ? NULL : pod); \ -+ break; \ -+ } \ -+ default: \ -+ break; \ -+ } \ -+} while(false) -+ -+#define SPA_POD_PARSER_SKIP(_type,args) \ -+do { \ -+ switch (_type) { \ -+ case 'S': \ -+ va_arg(args, char*); \ -+ va_arg(args, uint32_t); \ -+ break; \ -+ case 'a': \ -+ va_arg(args, void*); \ -+ va_arg(args, void*); \ -+ /* fallthrough */ \ -+ case 'p': \ -+ case 'y': \ -+ va_arg(args, void*); \ -+ /* fallthrough */ \ -+ case 'b': \ -+ case 'I': \ -+ case 'i': \ -+ case 'l': \ -+ case 'f': \ -+ case 'd': \ -+ case 's': \ -+ case 'R': \ -+ case 'F': \ -+ case 'B': \ -+ case 'h': \ -+ case 'V': \ -+ case 'P': \ -+ case 'T': \ -+ case 'O': \ -+ va_arg(args, void*); \ -+ break; \ -+ } \ -+} while(false) -+ -+static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args) -+{ -+ struct spa_pod_frame *f = parser->state.frame; -+ uint32_t ftype = f ? f->pod.type : (uint32_t)SPA_TYPE_Struct; -+ const struct spa_pod_prop *prop = NULL; -+ int count = 0; -+ -+ do { -+ bool optional; -+ const struct spa_pod *pod = NULL; -+ const char *format; -+ -+ if (ftype == SPA_TYPE_Object) { -+ uint32_t key = va_arg(args, uint32_t); -+ const struct spa_pod_object *object; -+ -+ if (key == 0) -+ break; -+ -+ object = (const struct spa_pod_object *)spa_pod_parser_frame(parser, f); -+ prop = spa_pod_object_find_prop(object, prop, key); -+ pod = prop ? &prop->value : NULL; -+ } -+ -+ if ((format = va_arg(args, char *)) == NULL) -+ break; -+ -+ if (ftype == SPA_TYPE_Struct) -+ pod = spa_pod_parser_next(parser); -+ -+ if ((optional = (*format == '?'))) -+ format++; -+ -+ if (!spa_pod_parser_can_collect(pod, *format)) { -+ if (!optional) { -+ if (pod == NULL) -+ return -ESRCH; -+ else -+ return -EPROTO; -+ } -+ SPA_POD_PARSER_SKIP(*format, args); -+ } else { -+ if (pod->type == SPA_TYPE_Choice && *format != 'V' && -+ SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None) -+ pod = SPA_POD_CHOICE_CHILD(pod); -+ -+ SPA_POD_PARSER_COLLECT(pod, *format, args); -+ count++; -+ } -+ } while (true); -+ -+ return count; -+} -+ -+static inline int spa_pod_parser_get(struct spa_pod_parser *parser, ...) -+{ -+ int res; -+ va_list args; -+ -+ va_start(args, parser); -+ res = spa_pod_parser_getv(parser, args); -+ va_end(args); -+ -+ return res; -+} -+ -+#define SPA_POD_OPT_Bool(val) "?" SPA_POD_Bool(val) -+#define SPA_POD_OPT_Id(val) "?" SPA_POD_Id(val) -+#define SPA_POD_OPT_Int(val) "?" SPA_POD_Int(val) -+#define SPA_POD_OPT_Long(val) "?" SPA_POD_Long(val) -+#define SPA_POD_OPT_Float(val) "?" SPA_POD_Float(val) -+#define SPA_POD_OPT_Double(val) "?" SPA_POD_Double(val) -+#define SPA_POD_OPT_String(val) "?" SPA_POD_String(val) -+#define SPA_POD_OPT_Stringn(val,len) "?" SPA_POD_Stringn(val,len) -+#define SPA_POD_OPT_Bytes(val,len) "?" SPA_POD_Bytes(val,len) -+#define SPA_POD_OPT_Rectangle(val) "?" SPA_POD_Rectangle(val) -+#define SPA_POD_OPT_Fraction(val) "?" SPA_POD_Fraction(val) -+#define SPA_POD_OPT_Array(csize,ctype,n_vals,vals) "?" SPA_POD_Array(csize,ctype,n_vals,vals) -+#define SPA_POD_OPT_Pointer(type,val) "?" SPA_POD_Pointer(type,val) -+#define SPA_POD_OPT_Fd(val) "?" SPA_POD_Fd(val) -+#define SPA_POD_OPT_Pod(val) "?" SPA_POD_Pod(val) -+#define SPA_POD_OPT_PodObject(val) "?" SPA_POD_PodObject(val) -+#define SPA_POD_OPT_PodStruct(val) "?" SPA_POD_PodStruct(val) -+#define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val) -+ -+#define spa_pod_parser_get_object(p,type,id,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ int _res; \ -+ if ((_res = spa_pod_parser_push_object(p, &_f, type, id)) == 0) { \ -+ _res = spa_pod_parser_get(p,##__VA_ARGS__, 0); \ -+ spa_pod_parser_pop(p, &_f); \ -+ } \ -+ _res; \ -+}) -+ -+#define spa_pod_parser_get_struct(p,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ int _res; \ -+ if ((_res = spa_pod_parser_push_struct(p, &_f)) == 0) { \ -+ _res = spa_pod_parser_get(p,##__VA_ARGS__, NULL); \ -+ spa_pod_parser_pop(p, &_f); \ -+ } \ -+ _res; \ -+}) -+ -+#define spa_pod_parse_object(pod,type,id,...) \ -+({ \ -+ struct spa_pod_parser _p; \ -+ spa_pod_parser_pod(&_p, pod); \ -+ spa_pod_parser_get_object(&_p,type,id,##__VA_ARGS__); \ -+}) -+ -+#define spa_pod_parse_struct(pod,...) \ -+({ \ -+ struct spa_pod_parser _p; \ -+ spa_pod_parser_pod(&_p, pod); \ -+ spa_pod_parser_get_struct(&_p,##__VA_ARGS__); \ -+}) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_PARSER_H */ -diff --git a/third_party/pipewire/spa/pod/pod.h b/third_party/pipewire/spa/pod/pod.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/pod.h -@@ -0,0 +1,231 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_H -+#define SPA_POD_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#define SPA_POD_BODY_SIZE(pod) (((struct spa_pod*)(pod))->size) -+#define SPA_POD_TYPE(pod) (((struct spa_pod*)(pod))->type) -+#define SPA_POD_SIZE(pod) (sizeof(struct spa_pod) + SPA_POD_BODY_SIZE(pod)) -+#define SPA_POD_CONTENTS_SIZE(type,pod) (SPA_POD_SIZE(pod)-sizeof(type)) -+ -+#define SPA_POD_CONTENTS(type,pod) SPA_MEMBER((pod),sizeof(type),void) -+#define SPA_POD_CONTENTS_CONST(type,pod) SPA_MEMBER((pod),sizeof(type),const void) -+#define SPA_POD_BODY(pod) SPA_MEMBER((pod),sizeof(struct spa_pod),void) -+#define SPA_POD_BODY_CONST(pod) SPA_MEMBER((pod),sizeof(struct spa_pod),const void) -+ -+struct spa_pod { -+ uint32_t size; /* size of the body */ -+ uint32_t type; /* a basic id of enum spa_type */ -+}; -+ -+#define SPA_POD_VALUE(type,pod) (((type*)pod)->value) -+ -+struct spa_pod_bool { -+ struct spa_pod pod; -+ int32_t value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_id { -+ struct spa_pod pod; -+ uint32_t value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_int { -+ struct spa_pod pod; -+ int32_t value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_long { -+ struct spa_pod pod; -+ int64_t value; -+}; -+ -+struct spa_pod_float { -+ struct spa_pod pod; -+ float value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_double { -+ struct spa_pod pod; -+ double value; -+}; -+ -+struct spa_pod_string { -+ struct spa_pod pod; -+ /* value here */ -+}; -+ -+struct spa_pod_bytes { -+ struct spa_pod pod; -+ /* value here */ -+}; -+ -+struct spa_pod_rectangle { -+ struct spa_pod pod; -+ struct spa_rectangle value; -+}; -+ -+struct spa_pod_fraction { -+ struct spa_pod pod; -+ struct spa_fraction value; -+}; -+ -+struct spa_pod_bitmap { -+ struct spa_pod pod; -+ /* array of uint8_t follows with the bitmap */ -+}; -+ -+#define SPA_POD_ARRAY_CHILD(arr) (&((struct spa_pod_array*)(arr))->body.child) -+#define SPA_POD_ARRAY_VALUE_TYPE(arr) (SPA_POD_TYPE(SPA_POD_ARRAY_CHILD(arr))) -+#define SPA_POD_ARRAY_VALUE_SIZE(arr) (SPA_POD_BODY_SIZE(SPA_POD_ARRAY_CHILD(arr))) -+#define SPA_POD_ARRAY_N_VALUES(arr) ((SPA_POD_BODY_SIZE(arr) - sizeof(struct spa_pod_array_body)) / SPA_POD_ARRAY_VALUE_SIZE(arr)) -+#define SPA_POD_ARRAY_VALUES(arr) SPA_POD_CONTENTS(struct spa_pod_array, arr) -+ -+struct spa_pod_array_body { -+ struct spa_pod child; -+ /* array with elements of child.size follows */ -+}; -+ -+struct spa_pod_array { -+ struct spa_pod pod; -+ struct spa_pod_array_body body; -+}; -+ -+#define SPA_POD_CHOICE_CHILD(choice) (&((struct spa_pod_choice*)(choice))->body.child) -+#define SPA_POD_CHOICE_TYPE(choice) (((struct spa_pod_choice*)(choice))->body.type) -+#define SPA_POD_CHOICE_FLAGS(choice) (((struct spa_pod_choice*)(choice))->body.flags) -+#define SPA_POD_CHOICE_VALUE_TYPE(choice) (SPA_POD_TYPE(SPA_POD_CHOICE_CHILD(choice))) -+#define SPA_POD_CHOICE_VALUE_SIZE(choice) (SPA_POD_BODY_SIZE(SPA_POD_CHOICE_CHILD(choice))) -+#define SPA_POD_CHOICE_N_VALUES(choice) ((SPA_POD_BODY_SIZE(choice) - sizeof(struct spa_pod_choice_body)) / SPA_POD_CHOICE_VALUE_SIZE(choice)) -+#define SPA_POD_CHOICE_VALUES(choice) (SPA_POD_CONTENTS(struct spa_pod_choice, choice)) -+ -+enum spa_choice_type { -+ SPA_CHOICE_None, /**< no choice, first value is current */ -+ SPA_CHOICE_Range, /**< range: default, min, max */ -+ SPA_CHOICE_Step, /**< range with step: default, min, max, step */ -+ SPA_CHOICE_Enum, /**< list: default, alternative,... */ -+ SPA_CHOICE_Flags, /**< flags: default, possible flags,... */ -+}; -+ -+struct spa_pod_choice_body { -+ uint32_t type; /**< type of choice, one of enum spa_choice_type */ -+ uint32_t flags; /**< extra flags */ -+ struct spa_pod child; -+ /* array with elements of child.size follows. Note that there might be more -+ * elements than required by \a type, which should be ignored. */ -+}; -+ -+struct spa_pod_choice { -+ struct spa_pod pod; -+ struct spa_pod_choice_body body; -+}; -+ -+struct spa_pod_struct { -+ struct spa_pod pod; -+ /* one or more spa_pod follow */ -+}; -+ -+#define SPA_POD_OBJECT_TYPE(obj) (((struct spa_pod_object*)(obj))->body.type) -+#define SPA_POD_OBJECT_ID(obj) (((struct spa_pod_object*)(obj))->body.id) -+ -+struct spa_pod_object_body { -+ uint32_t type; /**< one of enum spa_type */ -+ uint32_t id; /**< id of the object, depends on the object type */ -+ /* contents follow, series of spa_pod_prop */ -+}; -+ -+struct spa_pod_object { -+ struct spa_pod pod; -+ struct spa_pod_object_body body; -+}; -+ -+struct spa_pod_pointer_body { -+ uint32_t type; /**< pointer id, one of enum spa_type */ -+ uint32_t _padding; -+ const void *value; -+}; -+ -+struct spa_pod_pointer { -+ struct spa_pod pod; -+ struct spa_pod_pointer_body body; -+}; -+ -+struct spa_pod_fd { -+ struct spa_pod pod; -+ int64_t value; -+}; -+ -+#define SPA_POD_PROP_SIZE(prop) (sizeof(struct spa_pod_prop) + (prop)->value.size) -+ -+/* props can be inside an object */ -+struct spa_pod_prop { -+ uint32_t key; /**< key of property, list of valid keys depends on the -+ * object type */ -+#define SPA_POD_PROP_FLAG_READONLY (1u<<0) /**< is read-only */ -+#define SPA_POD_PROP_FLAG_HARDWARE (1u<<1) /**< some sort of hardware parameter */ -+ uint32_t flags; /**< flags for property */ -+ struct spa_pod value; -+ /* value follows */ -+}; -+ -+#define SPA_POD_CONTROL_SIZE(ev) (sizeof(struct spa_pod_control) + (ev)->value.size) -+ -+/* controls can be inside a sequence and mark timed values */ -+struct spa_pod_control { -+ uint32_t offset; /**< media offset */ -+ uint32_t type; /**< type of control, enum spa_control_type */ -+ struct spa_pod value; /**< control value, depends on type */ -+ /* value contents follow */ -+}; -+ -+struct spa_pod_sequence_body { -+ uint32_t unit; -+ uint32_t pad; -+ /* series of struct spa_pod_control follows */ -+}; -+ -+/** a sequence of timed controls */ -+struct spa_pod_sequence { -+ struct spa_pod pod; -+ struct spa_pod_sequence_body body; -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_H */ -diff --git a/third_party/pipewire/spa/pod/vararg.h b/third_party/pipewire/spa/pod/vararg.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/vararg.h -@@ -0,0 +1,104 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_VARARG_H -+#define SPA_POD_VARARG_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+#define SPA_POD_Prop(key,...) \ -+ key, ##__VA_ARGS__ -+ -+#define SPA_POD_Control(offset,type,...) \ -+ offset, type, ##__VA_ARGS__ -+ -+#define SPA_CHOICE_RANGE(def,min,max) 3,(def),(min),(max) -+#define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step) -+#define SPA_CHOICE_ENUM(n_vals,...) (n_vals),##__VA_ARGS__ -+#define SPA_CHOICE_FLAGS(flags) 1, (flags) -+#define SPA_CHOICE_BOOL(def) 3,(def),(def),!(def) -+ -+#define SPA_POD_Bool(val) "b", val -+#define SPA_POD_CHOICE_Bool(def) "?eb", SPA_CHOICE_BOOL(def) -+ -+#define SPA_POD_Id(val) "I", val -+#define SPA_POD_CHOICE_ENUM_Id(n_vals,...) "?eI", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+ -+#define SPA_POD_Int(val) "i", val -+#define SPA_POD_CHOICE_ENUM_Int(n_vals,...) "?ei", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Int(def,min,max) "?ri", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Int(def,min,max,step) "?si", SPA_CHOICE_STEP(def, min, max, step) -+#define SPA_POD_CHOICE_FLAGS_Int(flags) "?fi", SPA_CHOICE_FLAGS(flags) -+ -+#define SPA_POD_Long(val) "l", val -+#define SPA_POD_CHOICE_ENUM_Long(n_vals,...) "?el", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Long(def,min,max) "?rl", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Long(def,min,max,step) "?sl", SPA_CHOICE_STEP(def, min, max, step) -+#define SPA_POD_CHOICE_FLAGS_Long(flags) "?fl", SPA_CHOICE_FLAGS(flags) -+ -+#define SPA_POD_Float(val) "f", val -+#define SPA_POD_CHOICE_ENUM_Float(n_vals,...) "?ef", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Float(def,min,max) "?rf", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Float(def,min,max,step) "?sf", SPA_CHOICE_STEP(def, min, max, step) -+ -+#define SPA_POD_Double(val) "d", val -+#define SPA_POD_CHOICE_ENUM_Double(n_vals,...) "?ed", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Double(def,min,max) "?rd", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Double(def,min,max,step) "?sd", SPA_CHOICE_STEP(def, min, max, step) -+ -+#define SPA_POD_String(val) "s",val -+#define SPA_POD_Stringn(val,len) "S",val,len -+ -+#define SPA_POD_Bytes(val,len) "y",val,len -+ -+#define SPA_POD_Rectangle(val) "R",val -+#define SPA_POD_CHOICE_ENUM_Rectangle(n_vals,...) "?eR", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Rectangle(def,min,max) "?rR", SPA_CHOICE_RANGE((def),(min),(max)) -+#define SPA_POD_CHOICE_STEP_Rectangle(def,min,max,step) "?sR", SPA_CHOICE_STEP((def),(min),(max),(step)) -+ -+#define SPA_POD_Fraction(val) "F",val -+#define SPA_POD_CHOICE_ENUM_Fraction(n_vals,...) "?eF", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Fraction(def,min,max) "?rF", SPA_CHOICE_RANGE((def),(min),(max)) -+#define SPA_POD_CHOICE_STEP_Fraction(def,min,max,step) "?sF", SPA_CHOICE_STEP(def, min, max, step) -+ -+#define SPA_POD_Array(csize,ctype,n_vals,vals) "a", csize,ctype,n_vals,vals -+#define SPA_POD_Pointer(type,val) "p", type,val -+#define SPA_POD_Fd(val) "h", val -+#define SPA_POD_None() "P", NULL -+#define SPA_POD_Pod(val) "P", val -+#define SPA_POD_PodObject(val) "O", val -+#define SPA_POD_PodStruct(val) "T", val -+#define SPA_POD_PodChoice(val) "V", val -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_VARARG_H */ -diff --git a/third_party/pipewire/spa/support/cpu.h b/third_party/pipewire/spa/support/cpu.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/cpu.h -@@ -0,0 +1,126 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_CPU_H -+#define SPA_CPU_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+ -+/** -+ * The CPU features interface -+ */ -+#define SPA_TYPE_INTERFACE_CPU SPA_TYPE_INFO_INTERFACE_BASE "CPU" -+ -+#define SPA_VERSION_CPU 0 -+struct spa_cpu { struct spa_interface iface; }; -+ -+/* x86 specific */ -+#define SPA_CPU_FLAG_MMX (1<<0) /**< standard MMX */ -+#define SPA_CPU_FLAG_MMXEXT (1<<1) /**< SSE integer or AMD MMX ext */ -+#define SPA_CPU_FLAG_3DNOW (1<<2) /**< AMD 3DNOW */ -+#define SPA_CPU_FLAG_SSE (1<<3) /**< SSE */ -+#define SPA_CPU_FLAG_SSE2 (1<<4) /**< SSE2 */ -+#define SPA_CPU_FLAG_3DNOWEXT (1<<5) /**< AMD 3DNowExt */ -+#define SPA_CPU_FLAG_SSE3 (1<<6) /**< Prescott SSE3 */ -+#define SPA_CPU_FLAG_SSSE3 (1<<7) /**< Conroe SSSE3 */ -+#define SPA_CPU_FLAG_SSE41 (1<<8) /**< Penryn SSE4.1 */ -+#define SPA_CPU_FLAG_SSE42 (1<<9) /**< Nehalem SSE4.2 */ -+#define SPA_CPU_FLAG_AESNI (1<<10) /**< Advanced Encryption Standard */ -+#define SPA_CPU_FLAG_AVX (1<<11) /**< AVX */ -+#define SPA_CPU_FLAG_XOP (1<<12) /**< Bulldozer XOP */ -+#define SPA_CPU_FLAG_FMA4 (1<<13) /**< Bulldozer FMA4 */ -+#define SPA_CPU_FLAG_CMOV (1<<14) /**< supports cmov */ -+#define SPA_CPU_FLAG_AVX2 (1<<15) /**< AVX2 */ -+#define SPA_CPU_FLAG_FMA3 (1<<16) /**< Haswell FMA3 */ -+#define SPA_CPU_FLAG_BMI1 (1<<17) /**< Bit Manipulation Instruction Set 1 */ -+#define SPA_CPU_FLAG_BMI2 (1<<18) /**< Bit Manipulation Instruction Set 2 */ -+#define SPA_CPU_FLAG_AVX512 (1<<19) /**< AVX-512 */ -+#define SPA_CPU_FLAG_SLOW_UNALIGNED (1<<20) /**< unaligned loads/stores are slow */ -+ -+/* PPC specific */ -+#define SPA_CPU_FLAG_ALTIVEC (1<<0) /**< standard */ -+#define SPA_CPU_FLAG_VSX (1<<1) /**< ISA 2.06 */ -+#define SPA_CPU_FLAG_POWER8 (1<<2) /**< ISA 2.07 */ -+ -+/* ARM specific */ -+#define SPA_CPU_FLAG_ARMV5TE (1 << 0) -+#define SPA_CPU_FLAG_ARMV6 (1 << 1) -+#define SPA_CPU_FLAG_ARMV6T2 (1 << 2) -+#define SPA_CPU_FLAG_VFP (1 << 3) -+#define SPA_CPU_FLAG_VFPV3 (1 << 4) -+#define SPA_CPU_FLAG_NEON (1 << 5) -+#define SPA_CPU_FLAG_ARMV8 (1 << 6) -+ -+#define SPA_CPU_FORCE_AUTODETECT ((uint32_t)-1) -+/** -+ * methods -+ */ -+struct spa_cpu_methods { -+ /** the version of the methods. This can be used to expand this -+ structure in the future */ -+#define SPA_VERSION_CPU_METHODS 0 -+ uint32_t version; -+ -+ /** get CPU flags */ -+ uint32_t (*get_flags) (void *object); -+ -+ /** force CPU flags, use SPA_CPU_FORCE_AUTODETECT to autodetect CPU flags */ -+ int (*force_flags) (void *object, uint32_t flags); -+ -+ /** get number of CPU cores */ -+ uint32_t (*get_count) (void *object); -+ -+ /** get maximum required alignment of data */ -+ uint32_t (*get_max_align) (void *object); -+}; -+ -+#define spa_cpu_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_cpu *_c = o; \ -+ spa_interface_call_res(&_c->iface, \ -+ struct spa_cpu_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+#define spa_cpu_get_flags(c) spa_cpu_method(c, get_flags, 0) -+#define spa_cpu_force_flags(c,f) spa_cpu_method(c, force_flags, 0, f) -+#define spa_cpu_get_count(c) spa_cpu_method(c, get_count, 0) -+#define spa_cpu_get_max_align(c) spa_cpu_method(c, get_max_align, 0) -+ -+/** keys can be given when initializing the cpu handle */ -+#define SPA_KEY_CPU_FORCE "cpu.force" /**< force cpu flags */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_CPU_H */ -diff --git a/third_party/pipewire/spa/support/dbus.h b/third_party/pipewire/spa/support/dbus.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/dbus.h -@@ -0,0 +1,100 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DBUS_H -+#define SPA_DBUS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#define SPA_TYPE_INTERFACE_DBus SPA_TYPE_INFO_INTERFACE_BASE "DBus" -+ -+#define SPA_VERSION_DBUS 0 -+struct spa_dbus { struct spa_interface iface; }; -+ -+enum spa_dbus_type { -+ SPA_DBUS_TYPE_SESSION, /**< The login session bus */ -+ SPA_DBUS_TYPE_SYSTEM, /**< The systemwide bus */ -+ SPA_DBUS_TYPE_STARTER /**< The bus that started us, if any */ -+}; -+ -+struct spa_dbus_connection { -+#define SPA_VERSION_DBUS_CONNECTION 0 -+ uint32_t version; -+ /** -+ * Get the DBusConnection from a wrapper -+ * -+ * \param conn the spa_dbus_connection wrapper -+ * \return a pointer of type DBusConnection -+ */ -+ void *(*get) (struct spa_dbus_connection *conn); -+ /** -+ * Destroy a dbus connection wrapper -+ * -+ * \param conn the wrapper to destroy -+ */ -+ void (*destroy) (struct spa_dbus_connection *conn); -+}; -+ -+#define spa_dbus_connection_get(c) (c)->get((c)) -+#define spa_dbus_connection_destroy(c) (c)->destroy((c)) -+ -+struct spa_dbus_methods { -+#define SPA_VERSION_DBUS_METHODS 0 -+ uint32_t version; -+ -+ /** -+ * Get a new connection wrapper for the given bus type. -+ * -+ * The connection wrapper is completely configured to operate -+ * in the main context of the handle that manages the spa_dbus -+ * interface. -+ * -+ * \param dbus the dbus manager -+ * \param type the bus type to wrap -+ * \param error location for the DBusError -+ * \return a new dbus connection wrapper or NULL on error -+ */ -+ struct spa_dbus_connection * (*get_connection) (void *object, -+ enum spa_dbus_type type); -+}; -+ -+static inline struct spa_dbus_connection * -+spa_dbus_get_connection(struct spa_dbus *dbus, enum spa_dbus_type type) -+{ -+ struct spa_dbus_connection *res = NULL; -+ spa_interface_call_res(&dbus->iface, -+ struct spa_dbus_methods, res, -+ get_connection, 0, type); -+ return res; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DBUS_H */ -diff --git a/third_party/pipewire/spa/support/log-impl.h b/third_party/pipewire/spa/support/log-impl.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/log-impl.h -@@ -0,0 +1,86 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LOG_IMPL_H -+#define SPA_LOG_IMPL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+ -+static inline SPA_PRINTF_FUNC(6, 0) void spa_log_impl_logv(void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, -+ va_list args) -+{ -+ char text[512], location[1024]; -+ static const char *levels[] = { "-", "E", "W", "I", "D", "T" }; -+ -+ vsnprintf(text, sizeof(text), fmt, args); -+ snprintf(location, sizeof(location), "[%s][%s:%i %s()] %s\n", -+ levels[level], strrchr(file, '/') + 1, line, func, text); -+ fputs(location, stderr); -+} -+static inline SPA_PRINTF_FUNC(6,7) void spa_log_impl_log(void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, ...) -+{ -+ va_list args; -+ va_start(args, fmt); -+ spa_log_impl_logv(object, level, file, line, func, fmt, args); -+ va_end(args); -+} -+ -+#define SPA_LOG_IMPL_DEFINE(name) \ -+struct { \ -+ struct spa_log log; \ -+ struct spa_log_methods methods; \ -+} name -+ -+#define SPA_LOG_IMPL_INIT(name) \ -+ { { { SPA_TYPE_INTERFACE_Log, SPA_VERSION_LOG, \ -+ SPA_CALLBACKS_INIT(&name.methods, &name) }, \ -+ SPA_LOG_LEVEL_INFO, }, \ -+ { SPA_VERSION_LOG_METHODS, \ -+ spa_log_impl_log, \ -+ spa_log_impl_logv,} } -+ -+#define SPA_LOG_IMPL(name) \ -+ SPA_LOG_IMPL_DEFINE(name) = SPA_LOG_IMPL_INIT(name) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+#endif /* SPA_LOG_IMPL_H */ -diff --git a/third_party/pipewire/spa/support/log.h b/third_party/pipewire/spa/support/log.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/log.h -@@ -0,0 +1,179 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LOG_H -+#define SPA_LOG_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+ -+enum spa_log_level { -+ SPA_LOG_LEVEL_NONE = 0, -+ SPA_LOG_LEVEL_ERROR, -+ SPA_LOG_LEVEL_WARN, -+ SPA_LOG_LEVEL_INFO, -+ SPA_LOG_LEVEL_DEBUG, -+ SPA_LOG_LEVEL_TRACE, -+}; -+ -+/** -+ * The Log interface -+ */ -+#define SPA_TYPE_INTERFACE_Log SPA_TYPE_INFO_INTERFACE_BASE "Log" -+ -+#define SPA_VERSION_LOG 0 -+ -+struct spa_log { -+ /** the version of this log. This can be used to expand this -+ * structure in the future */ -+ struct spa_interface iface; -+ /** -+ * Logging level, everything above this level is not logged -+ */ -+ enum spa_log_level level; -+}; -+ -+struct spa_log_methods { -+#define SPA_VERSION_LOG_METHODS 0 -+ uint32_t version; -+ /** -+ * Log a message with the given log level. -+ * -+ * \param log a spa_log -+ * \param level a spa_log_level -+ * \param file the file name -+ * \param line the line number -+ * \param func the function name -+ * \param fmt printf style format -+ * \param ... format arguments -+ */ -+ void (*log) (void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, ...) SPA_PRINTF_FUNC(6, 7); -+ -+ /** -+ * Log a message with the given log level. -+ * -+ * \param log a spa_log -+ * \param level a spa_log_level -+ * \param file the file name -+ * \param line the line number -+ * \param func the function name -+ * \param fmt printf style format -+ * \param args format arguments -+ */ -+ void (*logv) (void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, -+ va_list args) SPA_PRINTF_FUNC(6, 0); -+}; -+ -+#define spa_log_level_enabled(l,lev) ((l) && (l)->level >= (lev)) -+ -+#if defined(__USE_ISOC11) || defined(__USE_ISOC99) || \ -+ (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) -+ -+#define spa_log_log(l,lev,...) \ -+({ \ -+ struct spa_log *_l = l; \ -+ if (SPA_UNLIKELY(spa_log_level_enabled(_l, lev))) \ -+ spa_interface_call(&_l->iface, \ -+ struct spa_log_methods, log, 0, lev, \ -+ __VA_ARGS__); \ -+}) -+ -+#define spa_log_logv(l,lev,...) \ -+({ \ -+ struct spa_log *_l = l; \ -+ if (SPA_UNLIKELY(spa_log_level_enabled(_l, lev))) \ -+ spa_interface_call(&_l->iface, \ -+ struct spa_log_methods, logv, 0, lev, \ -+ __VA_ARGS__); \ -+}) -+ -+#define spa_log_error(l,...) spa_log_log(l,SPA_LOG_LEVEL_ERROR,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_warn(l,...) spa_log_log(l,SPA_LOG_LEVEL_WARN,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_info(l,...) spa_log_log(l,SPA_LOG_LEVEL_INFO,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_debug(l,...) spa_log_log(l,SPA_LOG_LEVEL_DEBUG,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_trace(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) -+ -+#ifndef FASTPATH -+#define spa_log_trace_fp(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#else -+#define spa_log_trace_fp(l,...) -+#endif -+ -+#else -+ -+#define SPA_LOG_FUNC(name,lev) \ -+static inline SPA_PRINTF_FUNC(2,3) void spa_log_##name (struct spa_log *l, const char *format, ...) \ -+{ \ -+ if (SPA_UNLIKELY(spa_log_level_enabled(l, lev))) { \ -+ va_list varargs; \ -+ va_start (varargs, format); \ -+ spa_interface_call(&l->iface, \ -+ struct spa_log_methods, logv, 0, lev, \ -+ __FILE__,__LINE__,__func__,format,varargs); \ -+ va_end (varargs); \ -+ } \ -+} -+ -+SPA_LOG_FUNC(error, SPA_LOG_LEVEL_ERROR) -+SPA_LOG_FUNC(warn, SPA_LOG_LEVEL_WARN) -+SPA_LOG_FUNC(info, SPA_LOG_LEVEL_INFO) -+SPA_LOG_FUNC(debug, SPA_LOG_LEVEL_DEBUG) -+SPA_LOG_FUNC(trace, SPA_LOG_LEVEL_TRACE) -+ -+#ifndef FASTPATH -+SPA_LOG_FUNC(trace_fp, SPA_LOG_LEVEL_TRACE) -+#else -+static inline void spa_log_trace_fp (struct spa_log *l, const char *format, ...) { } -+#endif -+ -+#endif -+ -+/** keys can be given when initializing the logger handle */ -+#define SPA_KEY_LOG_LEVEL "log.level" /**< the default log level */ -+#define SPA_KEY_LOG_COLORS "log.colors" /**< enable colors in the logger */ -+#define SPA_KEY_LOG_FILE "log.file" /**< log to the specified file instead of -+ * stderr. */ -+#define SPA_KEY_LOG_TIMESTAMP "log.timestamp" /**< log timestamps */ -+#define SPA_KEY_LOG_LINE "log.line" /**< log file and line numbers */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+#endif /* SPA_LOG_H */ -diff --git a/third_party/pipewire/spa/support/loop.h b/third_party/pipewire/spa/support/loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/loop.h -@@ -0,0 +1,312 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LOOP_H -+#define SPA_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+#define SPA_TYPE_INTERFACE_Loop SPA_TYPE_INFO_INTERFACE_BASE "Loop" -+#define SPA_TYPE_INTERFACE_DataLoop SPA_TYPE_INFO_INTERFACE_BASE "DataLoop" -+#define SPA_VERSION_LOOP 0 -+struct spa_loop { struct spa_interface iface; }; -+ -+#define SPA_TYPE_INTERFACE_LoopControl SPA_TYPE_INFO_INTERFACE_BASE "LoopControl" -+#define SPA_VERSION_LOOP_CONTROL 0 -+struct spa_loop_control { struct spa_interface iface; }; -+ -+#define SPA_TYPE_INTERFACE_LoopUtils SPA_TYPE_INFO_INTERFACE_BASE "LoopUtils" -+#define SPA_VERSION_LOOP_UTILS 0 -+struct spa_loop_utils { struct spa_interface iface; }; -+ -+struct spa_source; -+ -+typedef void (*spa_source_func_t) (struct spa_source *source); -+ -+struct spa_source { -+ struct spa_loop *loop; -+ spa_source_func_t func; -+ void *data; -+ int fd; -+ uint32_t mask; -+ uint32_t rmask; -+}; -+ -+typedef int (*spa_invoke_func_t) (struct spa_loop *loop, -+ bool async, -+ uint32_t seq, -+ const void *data, -+ size_t size, -+ void *user_data); -+ -+/** -+ * Register sources and work items to an event loop -+ */ -+struct spa_loop_methods { -+ /* the version of this structure. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_LOOP_METHODS 0 -+ uint32_t version; -+ -+ /** add a source to the loop */ -+ int (*add_source) (void *object, -+ struct spa_source *source); -+ -+ /** update the source io mask */ -+ int (*update_source) (void *object, -+ struct spa_source *source); -+ -+ /** remove a source from the loop */ -+ int (*remove_source) (void *object, -+ struct spa_source *source); -+ -+ /** invoke a function in the context of this loop */ -+ int (*invoke) (void *object, -+ spa_invoke_func_t func, -+ uint32_t seq, -+ const void *data, -+ size_t size, -+ bool block, -+ void *user_data); -+}; -+ -+#define spa_loop_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_loop *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_loop_add_source(l,...) spa_loop_method(l,add_source,0,##__VA_ARGS__) -+#define spa_loop_update_source(l,...) spa_loop_method(l,update_source,0,##__VA_ARGS__) -+#define spa_loop_remove_source(l,...) spa_loop_method(l,remove_source,0,##__VA_ARGS__) -+#define spa_loop_invoke(l,...) spa_loop_method(l,invoke,0,##__VA_ARGS__) -+ -+ -+/** Control hooks. These hooks can't be removed from their -+ * callbacks and must be removed from a safe place (when the loop -+ * is not running or when it is locked). */ -+struct spa_loop_control_hooks { -+#define SPA_VERSION_LOOP_CONTROL_HOOKS 0 -+ uint32_t version; -+ /** Executed right before waiting for events. It is typically used to -+ * release locks. */ -+ void (*before) (void *data); -+ /** Executed right after waiting for events. It is typically used to -+ * reacquire locks. */ -+ void (*after) (void *data); -+}; -+ -+#define spa_loop_control_hook_before(l) \ -+({ \ -+ struct spa_hook_list *_l = l; \ -+ struct spa_hook *_h; \ -+ spa_list_for_each_reverse(_h, &_l->list, link) \ -+ spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, before, 0); \ -+}) -+ -+#define spa_loop_control_hook_after(l) \ -+({ \ -+ struct spa_hook_list *_l = l; \ -+ struct spa_hook *_h; \ -+ spa_list_for_each(_h, &_l->list, link) \ -+ spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, after, 0); \ -+}) -+ -+/** -+ * Control an event loop -+ */ -+struct spa_loop_control_methods { -+ /* the version of this structure. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_LOOP_CONTROL_METHODS 0 -+ uint32_t version; -+ -+ int (*get_fd) (void *object); -+ -+ /** Add a hook -+ * \param ctrl the control to change -+ * \param hooks the hooks to add -+ * -+ * Adds hooks to the loop controlled by \a ctrl. -+ */ -+ void (*add_hook) (void *object, -+ struct spa_hook *hook, -+ const struct spa_loop_control_hooks *hooks, -+ void *data); -+ -+ /** Enter a loop -+ * \param ctrl the control -+ * -+ * Start an iteration of the loop. This function should be called -+ * before calling iterate and is typically used to capture the thread -+ * that this loop will run in. -+ */ -+ void (*enter) (void *object); -+ /** Leave a loop -+ * \param ctrl the control -+ * -+ * Ends the iteration of a loop. This should be called after calling -+ * iterate. -+ */ -+ void (*leave) (void *object); -+ -+ /** Perform one iteration of the loop. -+ * \param ctrl the control -+ * \param timeout an optional timeout in milliseconds. -+ * 0 for no timeout, -1 for infinite timeout. -+ * -+ * This function will block -+ * up to \a timeout milliseconds and then dispatch the fds with activity. -+ * The number of dispatched fds is returned. -+ */ -+ int (*iterate) (void *object, int timeout); -+}; -+ -+#define spa_loop_control_method_v(o,method,version,...) \ -+({ \ -+ struct spa_loop_control *_o = o; \ -+ spa_interface_call(&_o->iface, \ -+ struct spa_loop_control_methods, \ -+ method, version, ##__VA_ARGS__); \ -+}) -+ -+#define spa_loop_control_method_r(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_loop_control *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_control_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_loop_control_get_fd(l) spa_loop_control_method_r(l,get_fd,0) -+#define spa_loop_control_add_hook(l,...) spa_loop_control_method_v(l,add_hook,0,__VA_ARGS__) -+#define spa_loop_control_enter(l) spa_loop_control_method_v(l,enter,0) -+#define spa_loop_control_leave(l) spa_loop_control_method_v(l,leave,0) -+#define spa_loop_control_iterate(l,...) spa_loop_control_method_r(l,iterate,0,__VA_ARGS__) -+ -+typedef void (*spa_source_io_func_t) (void *data, int fd, uint32_t mask); -+typedef void (*spa_source_idle_func_t) (void *data); -+typedef void (*spa_source_event_func_t) (void *data, uint64_t count); -+typedef void (*spa_source_timer_func_t) (void *data, uint64_t expirations); -+typedef void (*spa_source_signal_func_t) (void *data, int signal_number); -+ -+/** -+ * Create sources for an event loop -+ */ -+struct spa_loop_utils_methods { -+ /* the version of this structure. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_LOOP_UTILS_METHODS 0 -+ uint32_t version; -+ -+ struct spa_source *(*add_io) (void *object, -+ int fd, -+ uint32_t mask, -+ bool close, -+ spa_source_io_func_t func, void *data); -+ -+ int (*update_io) (void *object, struct spa_source *source, uint32_t mask); -+ -+ struct spa_source *(*add_idle) (void *object, -+ bool enabled, -+ spa_source_idle_func_t func, void *data); -+ int (*enable_idle) (void *object, struct spa_source *source, bool enabled); -+ -+ struct spa_source *(*add_event) (void *object, -+ spa_source_event_func_t func, void *data); -+ int (*signal_event) (void *object, struct spa_source *source); -+ -+ struct spa_source *(*add_timer) (void *object, -+ spa_source_timer_func_t func, void *data); -+ int (*update_timer) (void *object, -+ struct spa_source *source, -+ struct timespec *value, -+ struct timespec *interval, -+ bool absolute); -+ struct spa_source *(*add_signal) (void *object, -+ int signal_number, -+ spa_source_signal_func_t func, void *data); -+ -+ /** destroy a source allocated with this interface. This function -+ * should only be called when the loop is not running or from the -+ * context of the running loop */ -+ void (*destroy_source) (void *object, struct spa_source *source); -+}; -+ -+#define spa_loop_utils_method_v(o,method,version,...) \ -+({ \ -+ struct spa_loop_utils *_o = o; \ -+ spa_interface_call(&_o->iface, \ -+ struct spa_loop_utils_methods, \ -+ method, version, ##__VA_ARGS__); \ -+}) -+ -+#define spa_loop_utils_method_r(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_loop_utils *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_utils_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+#define spa_loop_utils_method_s(o,method,version,...) \ -+({ \ -+ struct spa_source *_res = NULL; \ -+ struct spa_loop_utils *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_utils_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+ -+#define spa_loop_utils_add_io(l,...) spa_loop_utils_method_s(l,add_io,0,__VA_ARGS__) -+#define spa_loop_utils_update_io(l,...) spa_loop_utils_method_r(l,update_io,0,__VA_ARGS__) -+#define spa_loop_utils_add_idle(l,...) spa_loop_utils_method_s(l,add_idle,0,__VA_ARGS__) -+#define spa_loop_utils_enable_idle(l,...) spa_loop_utils_method_r(l,enable_idle,0,__VA_ARGS__) -+#define spa_loop_utils_add_event(l,...) spa_loop_utils_method_s(l,add_event,0,__VA_ARGS__) -+#define spa_loop_utils_signal_event(l,...) spa_loop_utils_method_r(l,signal_event,0,__VA_ARGS__) -+#define spa_loop_utils_add_timer(l,...) spa_loop_utils_method_s(l,add_timer,0,__VA_ARGS__) -+#define spa_loop_utils_update_timer(l,...) spa_loop_utils_method_r(l,update_timer,0,__VA_ARGS__) -+#define spa_loop_utils_add_signal(l,...) spa_loop_utils_method_s(l,add_signal,0,__VA_ARGS__) -+#define spa_loop_utils_destroy_source(l,...) spa_loop_utils_method_v(l,destroy_source,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_LOOP_H */ -diff --git a/third_party/pipewire/spa/support/plugin.h b/third_party/pipewire/spa/support/plugin.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/plugin.h -@@ -0,0 +1,215 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PLUGIN_H -+#define SPA_PLUGIN_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_handle { -+ /** Version of this struct */ -+#define SPA_VERSION_HANDLE 0 -+ uint32_t version; -+ -+ /** -+ * Get the interface provided by \a handle with \a type. -+ * -+ * \a interface is always a struct spa_interface but depending on -+ * \a type, the struct might contain other information. -+ * -+ * \param handle a spa_handle -+ * \param type the interface type -+ * \param interface result to hold the interface. -+ * \return 0 on success -+ * -ENOTSUP when there are no interfaces -+ * -EINVAL when handle or info is NULL -+ */ -+ int (*get_interface) (struct spa_handle *handle, const char *type, void **interface); -+ /** -+ * Clean up the memory of \a handle. After this, \a handle should not be used -+ * anymore. -+ * -+ * \param handle a pointer to memory -+ * \return 0 on success -+ */ -+ int (*clear) (struct spa_handle *handle); -+}; -+ -+#define spa_handle_get_interface(h,...) (h)->get_interface((h),__VA_ARGS__) -+#define spa_handle_clear(h) (h)->clear((h)) -+ -+/** -+ * This structure lists the information about available interfaces on -+ * handles. -+ */ -+struct spa_interface_info { -+ const char *type; /*< the type of the interface, can be -+ * used to get the interface */ -+}; -+ -+/** -+ * Extra supporting infrastructure passed to the init() function of -+ * a factory. It can be extra information or interfaces such as logging. -+ */ -+struct spa_support { -+ const char *type; /*< the type of the support item */ -+ void *data; /*< specific data for the item */ -+}; -+ -+/** Find a support item of the given type */ -+static inline void *spa_support_find(const struct spa_support *support, -+ uint32_t n_support, -+ const char *type) -+{ -+ uint32_t i; -+ for (i = 0; i < n_support; i++) { -+ if (strcmp(support[i].type, type) == 0) -+ return support[i].data; -+ } -+ return NULL; -+} -+ -+#define SPA_SUPPORT_INIT(type,data) (struct spa_support) { (type), (data) } -+ -+struct spa_handle_factory { -+ /** The version of this structure */ -+#define SPA_VERSION_HANDLE_FACTORY 1 -+ uint32_t version; -+ /** -+ * The name of the factory contains a logical name that describes -+ * the function of the handle. Other plugins might contain an alternative -+ * implementation with the same name. -+ * -+ * See utils/names.h for the list of standard names. -+ * -+ * Examples include: -+ * -+ * api.alsa.pcm.sink: an object to write PCM samples to an alsa PLAYBACK -+ * device -+ * api.v4l2.source: an object to read from a v4l2 source. -+ */ -+ const char *name; -+ /** -+ * Extra information about the handles of this factory. -+ */ -+ const struct spa_dict *info; -+ /** -+ * Get the size of handles from this factory. -+ * -+ * \param factory a spa_handle_factory -+ * \param params extra parameters that determine the size of the -+ * handle. -+ */ -+ size_t (*get_size) (const struct spa_handle_factory *factory, -+ const struct spa_dict *params); -+ -+ /** -+ * Initialize an instance of this factory. The caller should allocate -+ * memory at least size bytes and pass this as \a handle. -+ * -+ * \a support can optionally contain extra interfaces or data items that the -+ * plugin can use such as a logger. -+ * -+ * \param factory a spa_handle_factory -+ * \param handle a pointer to memory -+ * \param info extra handle specific information, usually obtained -+ * from a spa_device. This can be used to configure the handle. -+ * \param support support items -+ * \param n_support number of elements in \a support -+ * \return 0 on success -+ * < 0 errno type error -+ */ -+ int (*init) (const struct spa_handle_factory *factory, -+ struct spa_handle *handle, -+ const struct spa_dict *info, -+ const struct spa_support *support, -+ uint32_t n_support); -+ -+ /** -+ * spa_handle_factory::enum_interface_info: -+ * \param factory: a #spa_handle_factory -+ * \param info: result to hold spa_interface_info. -+ * \param index: index to keep track of the enumeration, 0 for first item -+ * -+ * Enumerate the interface information for \a factory. -+ * -+ * \return 1 when an item is available -+ * 0 when no more items are available -+ * < 0 errno type error -+ */ -+ int (*enum_interface_info) (const struct spa_handle_factory *factory, -+ const struct spa_interface_info **info, -+ uint32_t *index); -+}; -+ -+#define spa_handle_factory_get_size(h,...) (h)->get_size((h),__VA_ARGS__) -+#define spa_handle_factory_init(h,...) (h)->init((h),__VA_ARGS__) -+#define spa_handle_factory_enum_interface_info(h,...) (h)->enum_interface_info((h),__VA_ARGS__) -+ -+/** -+ * The function signature of the entry point in a plugin. -+ * -+ * \param factory a location to hold the factory result -+ * \param index index to keep track of the enumeration -+ * \return 1 on success -+ * 0 when there are no more factories -+ * -EINVAL when factory is NULL -+ */ -+typedef int (*spa_handle_factory_enum_func_t) (const struct spa_handle_factory **factory, -+ uint32_t *index); -+ -+#define SPA_HANDLE_FACTORY_ENUM_FUNC_NAME "spa_handle_factory_enum" -+ -+/** -+ * The entry point in a plugin. -+ * -+ * \param factory a location to hold the factory result -+ * \param index index to keep track of the enumeration -+ * \return 1 on success -+ * 0 when no more items are available -+ * < 0 errno type error -+ */ -+int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index); -+ -+ -+ -+#define SPA_KEY_FACTORY_NAME "factory.name" /**< the name of a factory */ -+#define SPA_KEY_FACTORY_AUTHOR "factory.author" /**< a comma separated list of factory authors */ -+#define SPA_KEY_FACTORY_DESCRIPTION "factory.description" /**< description of a factory */ -+#define SPA_KEY_FACTORY_USAGE "factory.usage" /**< usage of a factory */ -+ -+#define SPA_KEY_LIBRARY_NAME "library.name" /**< the name of a library. This is usually -+ * the filename of the plugin without the -+ * path or the plugin extension. */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PLUGIN_H */ -diff --git a/third_party/pipewire/spa/support/system.h b/third_party/pipewire/spa/support/system.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/system.h -@@ -0,0 +1,152 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_SYSTEM_H -+#define SPA_SYSTEM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct itimerspec; -+ -+#include -+#include -+ -+#include -+#include -+ -+/** -+ * a collection of core system functions -+ */ -+#define SPA_TYPE_INTERFACE_System SPA_TYPE_INFO_INTERFACE_BASE "System" -+#define SPA_TYPE_INTERFACE_DataSystem SPA_TYPE_INFO_INTERFACE_BASE "DataSystem" -+ -+#define SPA_VERSION_SYSTEM 0 -+struct spa_system { struct spa_interface iface; }; -+ -+/* IO events */ -+#define SPA_IO_IN (1 << 0) -+#define SPA_IO_OUT (1 << 2) -+#define SPA_IO_ERR (1 << 3) -+#define SPA_IO_HUP (1 << 4) -+ -+/* flags */ -+#define SPA_FD_CLOEXEC (1<<0) -+#define SPA_FD_NONBLOCK (1<<1) -+#define SPA_FD_EVENT_SEMAPHORE (1<<2) -+#define SPA_FD_TIMER_ABSTIME (1<<3) -+#define SPA_FD_TIMER_CANCEL_ON_SET (1<<4) -+ -+struct spa_poll_event { -+ uint32_t events; -+ void *data; -+}; -+ -+struct spa_system_methods { -+#define SPA_VERSION_SYSTEM_METHODS 0 -+ uint32_t version; -+ -+ /* read/write/ioctl */ -+ ssize_t (*read) (void *object, int fd, void *buf, size_t count); -+ ssize_t (*write) (void *object, int fd, const void *buf, size_t count); -+ int (*ioctl) (void *object, int fd, unsigned long request, ...); -+ int (*close) (void *object, int fd); -+ -+ /* clock */ -+ int (*clock_gettime) (void *object, -+ int clockid, struct timespec *value); -+ int (*clock_getres) (void *object, -+ int clockid, struct timespec *res); -+ -+ /* poll */ -+ int (*pollfd_create) (void *object, int flags); -+ int (*pollfd_add) (void *object, int pfd, int fd, uint32_t events, void *data); -+ int (*pollfd_mod) (void *object, int pfd, int fd, uint32_t events, void *data); -+ int (*pollfd_del) (void *object, int pfd, int fd); -+ int (*pollfd_wait) (void *object, int pfd, -+ struct spa_poll_event *ev, int n_ev, int timeout); -+ -+ /* timers */ -+ int (*timerfd_create) (void *object, int clockid, int flags); -+ int (*timerfd_settime) (void *object, -+ int fd, int flags, -+ const struct itimerspec *new_value, -+ struct itimerspec *old_value); -+ int (*timerfd_gettime) (void *object, -+ int fd, struct itimerspec *curr_value); -+ int (*timerfd_read) (void *object, int fd, uint64_t *expirations); -+ -+ /* events */ -+ int (*eventfd_create) (void *object, int flags); -+ int (*eventfd_write) (void *object, int fd, uint64_t count); -+ int (*eventfd_read) (void *object, int fd, uint64_t *count); -+ -+ /* signals */ -+ int (*signalfd_create) (void *object, int signal, int flags); -+ int (*signalfd_read) (void *object, int fd, int *signal); -+}; -+ -+#define spa_system_method_r(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_system *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_system_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+ -+#define spa_system_read(s,...) spa_system_method_r(s,read,0,__VA_ARGS__) -+#define spa_system_write(s,...) spa_system_method_r(s,write,0,__VA_ARGS__) -+#define spa_system_ioctl(s,...) spa_system_method_r(s,ioctl,0,__VA_ARGS__) -+#define spa_system_close(s,...) spa_system_method_r(s,close,0,__VA_ARGS__) -+ -+#define spa_system_clock_gettime(s,...) spa_system_method_r(s,clock_gettime,0,__VA_ARGS__) -+#define spa_system_clock_getres(s,...) spa_system_method_r(s,clock_getres,0,__VA_ARGS__) -+ -+#define spa_system_pollfd_create(s,...) spa_system_method_r(s,pollfd_create,0,__VA_ARGS__) -+#define spa_system_pollfd_add(s,...) spa_system_method_r(s,pollfd_add,0,__VA_ARGS__) -+#define spa_system_pollfd_mod(s,...) spa_system_method_r(s,pollfd_mod,0,__VA_ARGS__) -+#define spa_system_pollfd_del(s,...) spa_system_method_r(s,pollfd_del,0,__VA_ARGS__) -+#define spa_system_pollfd_wait(s,...) spa_system_method_r(s,pollfd_wait,0,__VA_ARGS__) -+ -+#define spa_system_timerfd_create(s,...) spa_system_method_r(s,timerfd_create,0,__VA_ARGS__) -+#define spa_system_timerfd_settime(s,...) spa_system_method_r(s,timerfd_settime,0,__VA_ARGS__) -+#define spa_system_timerfd_gettime(s,...) spa_system_method_r(s,timerfd_gettime,0,__VA_ARGS__) -+#define spa_system_timerfd_read(s,...) spa_system_method_r(s,timerfd_read,0,__VA_ARGS__) -+ -+#define spa_system_eventfd_create(s,...) spa_system_method_r(s,eventfd_create,0,__VA_ARGS__) -+#define spa_system_eventfd_write(s,...) spa_system_method_r(s,eventfd_write,0,__VA_ARGS__) -+#define spa_system_eventfd_read(s,...) spa_system_method_r(s,eventfd_read,0,__VA_ARGS__) -+ -+#define spa_system_signalfd_create(s,...) spa_system_method_r(s,signalfd_create,0,__VA_ARGS__) -+#define spa_system_signalfd_read(s,...) spa_system_method_r(s,signalfd_read,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_SYSTEM_H */ -diff --git a/third_party/pipewire/spa/utils/defs.h b/third_party/pipewire/spa/utils/defs.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/defs.h -@@ -0,0 +1,265 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_DEFS_H -+#define SPA_UTILS_DEFS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#else -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+ -+#define SPA_FLAG_MASK(field,mask,flag) (((field) & (mask)) == (flag)) -+#define SPA_FLAG_IS_SET(field,flag) SPA_FLAG_MASK(field,flag,flag) -+#define SPA_FLAG_SET(field,flag) ((field) |= (flag)) -+#define SPA_FLAG_CLEAR(field,flag) ((field) &= ~(flag)) -+#define SPA_FLAG_UPDATE(field,flag,val) ((val) ? SPA_FLAG_SET(field,flag) : SPA_FLAG_CLEAR(field,flag)) -+ -+enum spa_direction { -+ SPA_DIRECTION_INPUT = 0, -+ SPA_DIRECTION_OUTPUT = 1, -+}; -+ -+#define SPA_DIRECTION_REVERSE(d) ((d) ^ 1) -+ -+#define SPA_RECTANGLE(width,height) (struct spa_rectangle){ width, height } -+struct spa_rectangle { -+ uint32_t width; -+ uint32_t height; -+}; -+ -+#define SPA_POINT(x,y) (struct spa_point){ x, y } -+struct spa_point { -+ int32_t x; -+ int32_t y; -+}; -+ -+#define SPA_REGION(x,y,width,height) (struct spa_region){ SPA_POINT(x,y), SPA_RECTANGLE(width,height) } -+struct spa_region { -+ struct spa_point position; -+ struct spa_rectangle size; -+}; -+ -+#define SPA_FRACTION(num,denom) (struct spa_fraction){ num, denom } -+struct spa_fraction { -+ uint32_t num; -+ uint32_t denom; -+}; -+ -+#define SPA_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0])) -+ -+#define SPA_MIN(a,b) \ -+({ \ -+ __typeof__(a) _a = (a); \ -+ __typeof__(b) _b = (b); \ -+ SPA_LIKELY(_a < _b) ? _a : _b; \ -+}) -+#define SPA_MAX(a,b) \ -+({ \ -+ __typeof__(a) _a = (a); \ -+ __typeof__(b) _b = (b); \ -+ SPA_LIKELY(_a > _b) ? _a : _b; \ -+}) -+#define SPA_CLAMP(v,low,high) \ -+({ \ -+ __typeof__(v) _v = (v); \ -+ __typeof__(low) _low = (low); \ -+ __typeof__(high) _high = (high); \ -+ SPA_MIN(SPA_MAX(_v, _low), _high); \ -+}) -+ -+#define SPA_SWAP(a,b) \ -+({ \ -+ __typeof__(a) _t = (a); \ -+ a = b; b = _t; \ -+}) -+ -+#define SPA_TYPECHECK(type,x) \ -+({ type _dummy; \ -+ typeof(x) _dummy2; \ -+ (void)(&_dummy == &_dummy2); \ -+ x; \ -+}) -+ -+#define SPA_MEMBER(b,o,t) ((t*)((uint8_t*)(b) + (int)(o))) -+#define SPA_MEMBER_ALIGN(b,o,a,t) SPA_PTR_ALIGN(SPA_MEMBER(b,o,t),a,t) -+ -+#define SPA_CONTAINER_OF(p,t,m) (t*)((uint8_t*)p - offsetof (t,m)) -+ -+#define SPA_PTRDIFF(p1,p2) ((uint8_t*)(p1) - (uint8_t*)(p2)) -+ -+#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p))) -+#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u))) -+ -+#define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p))) -+#define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u))) -+ -+#define SPA_TIME_INVALID ((int64_t)INT64_MIN) -+#define SPA_IDX_INVALID ((unsigned int)-1) -+#define SPA_ID_INVALID ((uint32_t)0xffffffff) -+ -+#define SPA_NSEC_PER_SEC (1000000000ll) -+#define SPA_NSEC_PER_MSEC (1000000ll) -+#define SPA_NSEC_PER_USEC (1000ll) -+#define SPA_USEC_PER_SEC (1000000ll) -+#define SPA_USEC_PER_MSEC (1000ll) -+#define SPA_MSEC_PER_SEC (1000ll) -+ -+#define SPA_TIMESPEC_TO_NSEC(ts) ((ts)->tv_sec * SPA_NSEC_PER_SEC + (ts)->tv_nsec) -+#define SPA_TIMESPEC_TO_USEC(ts) ((ts)->tv_sec * SPA_USEC_PER_SEC + (ts)->tv_nsec / SPA_NSEC_PER_USEC) -+#define SPA_TIMEVAL_TO_NSEC(tv) ((tv)->tv_sec * SPA_NSEC_PER_SEC + (tv)->tv_usec * SPA_NSEC_PER_USEC) -+#define SPA_TIMEVAL_TO_USEC(tv) ((tv)->tv_sec * SPA_USEC_PER_SEC + (tv)->tv_usec) -+ -+#ifdef __GNUC__ -+#define SPA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) -+#define SPA_ALIGNED(align) __attribute__((aligned(align))) -+#define SPA_DEPRECATED __attribute__ ((deprecated)) -+#define SPA_EXPORT __attribute__((visibility("default"))) -+#define SPA_SENTINEL __attribute__((__sentinel__)) -+#define SPA_UNUSED __attribute__ ((unused)) -+#else -+#define SPA_PRINTF_FUNC(fmt, arg1) -+#define SPA_ALIGNED(align) -+#define SPA_DEPRECATED -+#define SPA_EXPORT -+#define SPA_SENTINEL -+#define SPA_UNUSED -+#endif -+ -+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -+#define SPA_RESTRICT restrict -+#elif defined(__GNUC__) && __GNUC__ >= 4 -+#define SPA_RESTRICT __restrict__ -+#else -+#define SPA_RESTRICT -+#endif -+ -+#define SPA_ROUND_DOWN_N(num,align) ((num) & ~((align) - 1)) -+#define SPA_ROUND_UP_N(num,align) SPA_ROUND_DOWN_N((num) + ((align) - 1),align) -+ -+#define SPA_PTR_ALIGNMENT(p,align) ((intptr_t)(p) & ((align)-1)) -+#define SPA_IS_ALIGNED(p,align) (SPA_PTR_ALIGNMENT(p,align) == 0) -+#define SPA_PTR_ALIGN(p,align,type) (type*)SPA_ROUND_UP_N((intptr_t)(p), (intptr_t)(align)) -+ -+#ifndef SPA_LIKELY -+#ifdef __GNUC__ -+#define SPA_LIKELY(x) (__builtin_expect(!!(x),1)) -+#define SPA_UNLIKELY(x) (__builtin_expect(!!(x),0)) -+#else -+#define SPA_LIKELY(x) (x) -+#define SPA_UNLIKELY(x) (x) -+#endif -+#endif -+ -+#define SPA_STRINGIFY_1(...) #__VA_ARGS__ -+#define SPA_STRINGIFY(...) SPA_STRINGIFY_1(__VA_ARGS__) -+ -+#define spa_return_if_fail(expr) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ return; \ -+ } \ -+ } while(false) -+ -+#define spa_return_val_if_fail(expr, val) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ return (val); \ -+ } \ -+ } while(false) -+ -+/* spa_assert_se() is an assert which guarantees side effects of x, -+ * i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */ -+#define spa_assert_se(expr) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ abort(); \ -+ } \ -+ } while (false) -+ -+#define spa_assert(expr) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ abort(); \ -+ } \ -+ } while (false) -+ -+#define spa_assert_not_reached() \ -+ do { \ -+ fprintf(stderr, "Code should not be reached at %s:%u %s()\n", \ -+ __FILE__, __LINE__, __func__); \ -+ abort(); \ -+ } while (false) -+ -+/* Does exactly nothing */ -+#define spa_nop() do {} while (false) -+ -+#define spa_memzero(x,l) (memset((x), 0, (l))) -+#define spa_zero(x) (spa_memzero(&(x), sizeof(x))) -+ -+#ifdef SPA_DEBUG_MEMCPY -+#define spa_memcpy(d,s,n) \ -+({ \ -+ fprintf(stderr, "%s:%u %s() memcpy(%p, %p, %zd)\n", \ -+ __FILE__, __LINE__, __func__, (d), (s), (size_t)(n)); \ -+ memcpy(d,s,n); \ -+}) -+#define spa_memmove(d,s,n) \ -+({ \ -+ fprintf(stderr, "%s:%u %s() memmove(%p, %p, %zd)\n", \ -+ __FILE__, __LINE__, __func__, (d), (s), (size_t)(n)); \ -+ memmove(d,s,n); \ -+}) -+#else -+#define spa_memcpy(d,s,n) memcpy(d,s,n) -+#define spa_memmove(d,s,n) memmove(d,s,n) -+#endif -+ -+#define spa_aprintf(_fmt, ...) \ -+({ \ -+ char *_strp; \ -+ if (asprintf(&(_strp), (_fmt), ## __VA_ARGS__ ) == -1) \ -+ _strp = NULL; \ -+ _strp; \ -+}) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_DEFS_H */ -diff --git a/third_party/pipewire/spa/utils/dict.h b/third_party/pipewire/spa/utils/dict.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/dict.h -@@ -0,0 +1,104 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DICT_H -+#define SPA_DICT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+struct spa_dict_item { -+ const char *key; -+ const char *value; -+}; -+ -+#define SPA_DICT_ITEM_INIT(key,value) (struct spa_dict_item) { key, value } -+ -+struct spa_dict { -+#define SPA_DICT_FLAG_SORTED (1<<0) /**< items are sorted */ -+ uint32_t flags; -+ uint32_t n_items; -+ const struct spa_dict_item *items; -+}; -+ -+#define SPA_DICT_INIT(items,n_items) (struct spa_dict) { 0, n_items, items } -+#define SPA_DICT_INIT_ARRAY(items) (struct spa_dict) { 0, SPA_N_ELEMENTS(items), items } -+ -+#define spa_dict_for_each(item, dict) \ -+ for ((item) = (dict)->items; \ -+ (item) < &(dict)->items[(dict)->n_items]; \ -+ (item)++) -+ -+static inline int spa_dict_item_compare(const void *i1, const void *i2) -+{ -+ const struct spa_dict_item *it1 = (const struct spa_dict_item *)i1, -+ *it2 = (const struct spa_dict_item *)i2; -+ return strcmp(it1->key, it2->key); -+} -+ -+static inline void spa_dict_qsort(struct spa_dict *dict) -+{ -+ qsort((void*)dict->items, dict->n_items, sizeof(struct spa_dict_item), -+ spa_dict_item_compare); -+ SPA_FLAG_SET(dict->flags, SPA_DICT_FLAG_SORTED); -+} -+ -+static inline const struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *dict, -+ const char *key) -+{ -+ const struct spa_dict_item *item; -+ -+ if (SPA_FLAG_IS_SET(dict->flags, SPA_DICT_FLAG_SORTED)) { -+ struct spa_dict_item k = SPA_DICT_ITEM_INIT(key, NULL); -+ item = (const struct spa_dict_item *)bsearch(&k, -+ (const void *) dict->items, dict->n_items, -+ sizeof(struct spa_dict_item), -+ spa_dict_item_compare); -+ if (item != NULL) -+ return item; -+ } else { -+ spa_dict_for_each(item, dict) { -+ if (!strcmp(item->key, key)) -+ return item; -+ } -+ } -+ return NULL; -+} -+ -+static inline const char *spa_dict_lookup(const struct spa_dict *dict, const char *key) -+{ -+ const struct spa_dict_item *item = spa_dict_lookup_item(dict, key); -+ return item ? item->value : NULL; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DICT_H */ -diff --git a/third_party/pipewire/spa/utils/hook.h b/third_party/pipewire/spa/utils/hook.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/hook.h -@@ -0,0 +1,198 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_HOOK_H -+#define SPA_HOOK_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class spa_hook -+ * -+ * \brief a list of hooks -+ * -+ * The hook list provides a way to keep track of hooks. -+ */ -+/** A list of hooks */ -+struct spa_hook_list { -+ struct spa_list list; -+}; -+ -+/** Callbacks, contains the structure with functions and the data passed -+ * to the functions. The structure should also contain a version field that -+ * is checked. */ -+struct spa_callbacks { -+ const void *funcs; -+ void *data; -+}; -+ -+/** Check if a callback \c has method \m of version \v */ -+#define SPA_CALLBACK_CHECK(c,m,v) ((c) && ((v) == 0 || (c)->version > (v)-1) && (c)->m) -+ -+#define SPA_CALLBACKS_INIT(_funcs,_data) (struct spa_callbacks){ _funcs, _data, } -+ -+struct spa_interface { -+ const char *type; -+ uint32_t version; -+ struct spa_callbacks cb; -+}; -+ -+#define SPA_INTERFACE_INIT(_type,_version,_funcs,_data) \ -+ (struct spa_interface){ _type, _version, SPA_CALLBACKS_INIT(_funcs,_data), } -+ -+/** A hook, contains the structure with functions and the data passed -+ * to the functions. */ -+struct spa_hook { -+ struct spa_list link; -+ struct spa_callbacks cb; -+ /** callback and data for the hook list */ -+ void (*removed) (struct spa_hook *hook); -+ void *priv; -+}; -+ -+/** Initialize a hook list */ -+static inline void spa_hook_list_init(struct spa_hook_list *list) -+{ -+ spa_list_init(&list->list); -+} -+ -+static inline bool spa_hook_list_is_empty(struct spa_hook_list *list) -+{ -+ return spa_list_is_empty(&list->list); -+} -+ -+/** Append a hook \memberof spa_hook */ -+static inline void spa_hook_list_append(struct spa_hook_list *list, -+ struct spa_hook *hook, -+ const void *funcs, void *data) -+{ -+ hook->cb = SPA_CALLBACKS_INIT(funcs, data); -+ spa_list_append(&list->list, &hook->link); -+} -+ -+/** Prepend a hook \memberof spa_hook */ -+static inline void spa_hook_list_prepend(struct spa_hook_list *list, -+ struct spa_hook *hook, -+ const void *funcs, void *data) -+{ -+ hook->cb = SPA_CALLBACKS_INIT(funcs, data); -+ spa_list_prepend(&list->list, &hook->link); -+} -+ -+/** Remove a hook \memberof spa_hook */ -+static inline void spa_hook_remove(struct spa_hook *hook) -+{ -+ spa_list_remove(&hook->link); -+ if (hook->removed) -+ hook->removed(hook); -+} -+ -+static inline void -+spa_hook_list_isolate(struct spa_hook_list *list, -+ struct spa_hook_list *save, -+ struct spa_hook *hook, -+ const void *funcs, void *data) -+{ -+ /* init save list and move hooks to it */ -+ spa_hook_list_init(save); -+ spa_list_insert_list(&save->list, &list->list); -+ /* init hooks and add single hook */ -+ spa_hook_list_init(list); -+ spa_hook_list_append(list, hook, funcs, data); -+} -+ -+static inline void -+spa_hook_list_join(struct spa_hook_list *list, -+ struct spa_hook_list *save) -+{ -+ spa_list_insert_list(&list->list, &save->list); -+} -+ -+#define spa_callbacks_call(callbacks,type,method,vers,...) \ -+({ \ -+ const type *_f = (const type *) (callbacks)->funcs; \ -+ if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) \ -+ _f->method((callbacks)->data, ## __VA_ARGS__); \ -+}) -+ -+#define spa_callbacks_call_res(callbacks,type,res,method,vers,...) \ -+({ \ -+ const type *_f = (const type *) (callbacks)->funcs; \ -+ if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) \ -+ res = _f->method((callbacks)->data, ## __VA_ARGS__); \ -+ res; \ -+}) -+ -+#define spa_interface_call(iface,type,method,vers,...) \ -+ spa_callbacks_call(&(iface)->cb,type,method,vers,##__VA_ARGS__) -+ -+#define spa_interface_call_res(iface,type,res,method,vers,...) \ -+ spa_callbacks_call_res(&(iface)->cb,type,res,method,vers,##__VA_ARGS__) -+ -+#define spa_hook_list_call_simple(l,type,method,vers,...) \ -+({ \ -+ struct spa_hook_list *_l = l; \ -+ struct spa_hook *_h, *_t; \ -+ spa_list_for_each_safe(_h, _t, &_l->list, link) \ -+ spa_callbacks_call(&_h->cb,type,method,vers, ## __VA_ARGS__); \ -+}) -+ -+/** Call all hooks in a list, starting from the given one and optionally stopping -+ * after calling the first non-NULL function, returns the number of methods -+ * called */ -+#define spa_hook_list_do_call(l,start,type,method,vers,once,...) \ -+({ \ -+ struct spa_hook_list *list = l; \ -+ struct spa_list *s = start ? (struct spa_list *)start : &list->list; \ -+ struct spa_hook cursor = { 0 }, *ci; \ -+ int count = 0; \ -+ spa_list_cursor_start(cursor, s, link); \ -+ spa_list_for_each_cursor(ci, cursor, &list->list, link) { \ -+ const type *_f = (const type *)ci->cb.funcs; \ -+ if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) { \ -+ _f->method(ci->cb.data, ## __VA_ARGS__); \ -+ count++; \ -+ if (once) \ -+ break; \ -+ } \ -+ } \ -+ spa_list_cursor_end(cursor, link); \ -+ count; \ -+}) -+ -+#define spa_hook_list_call(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,false,##__VA_ARGS__) -+#define spa_hook_list_call_once(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,true,##__VA_ARGS__) -+ -+#define spa_hook_list_call_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,false,##__VA_ARGS__) -+#define spa_hook_list_call_once_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,true,##__VA_ARGS__) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* SPA_HOOK_H */ -diff --git a/third_party/pipewire/spa/utils/keys.h b/third_party/pipewire/spa/utils/keys.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/keys.h -@@ -0,0 +1,124 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_KEYS_H -+#define SPA_UTILS_KEYS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** for objects */ -+#define SPA_KEY_OBJECT_PATH "object.path" /**< a unique path to -+ * identity the object */ -+ -+#define SPA_KEY_MEDIA_CLASS "media.class" /**< Media class -+ * Ex. "Audio/Device", -+ * "Video/Source",... */ -+#define SPA_KEY_MEDIA_ROLE "media.role" /**< Role: Movie, Music, Camera, -+ * Screen, Communication, Game, -+ * Notification, DSP, Production, -+ * Accessibility, Test */ -+/** keys for udev api */ -+#define SPA_KEY_API_UDEV "api.udev" /**< key for the udev api */ -+#define SPA_KEY_API_UDEV_MATCH "api.udev.match" /**< udev subsystem match */ -+ -+/** keys for alsa api */ -+#define SPA_KEY_API_ALSA "api.alsa" /**< key for the alsa api */ -+#define SPA_KEY_API_ALSA_PATH "api.alsa.path" /**< alsa device path as can be -+ * used in snd_pcm_open() and -+ * snd_ctl_open(). */ -+#define SPA_KEY_API_ALSA_CARD "api.alsa.card" /**< alsa card number */ -+#define SPA_KEY_API_ALSA_USE_UCM "api.alsa.use-ucm" /**< if UCM should be used */ -+#define SPA_KEY_API_ALSA_IGNORE_DB "api.alsa.ignore-dB" /**< if decibel info should be ignored */ -+ -+/** info from alsa card_info */ -+#define SPA_KEY_API_ALSA_CARD_ID "api.alsa.card.id" /**< id from card_info */ -+#define SPA_KEY_API_ALSA_CARD_COMPONENTS \ -+ "api.alsa.card.components" /**< components from card_info */ -+#define SPA_KEY_API_ALSA_CARD_DRIVER "api.alsa.card.driver" /**< driver from card_info */ -+#define SPA_KEY_API_ALSA_CARD_NAME "api.alsa.card.name" /**< name from card_info */ -+#define SPA_KEY_API_ALSA_CARD_LONGNAME "api.alsa.card.longname" /**< longname from card_info */ -+#define SPA_KEY_API_ALSA_CARD_MIXERNAME "api.alsa.card.mixername" /**< mixername from card_info */ -+ -+/** info from alsa pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_ID "api.alsa.pcm.id" /**< id from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_CARD "api.alsa.pcm.card" /**< card from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_NAME "api.alsa.pcm.name" /**< name from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_SUBNAME "api.alsa.pcm.subname" /**< subdevice_name from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_STREAM "api.alsa.pcm.stream" /**< stream type from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_CLASS "api.alsa.pcm.class" /**< class from pcm_info as string */ -+#define SPA_KEY_API_ALSA_PCM_DEVICE "api.alsa.pcm.device" /**< device from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_SUBDEVICE "api.alsa.pcm.subdevice" /**< subdevice from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_SUBCLASS "api.alsa.pcm.subclass" /**< subclass from pcm_info as string */ -+#define SPA_KEY_API_ALSA_PCM_SYNC_ID "api.alsa.pcm.sync-id" /**< sync id */ -+ -+/** keys for v4l2 api */ -+#define SPA_KEY_API_V4L2 "api.v4l2" /**< key for the v4l2 api */ -+#define SPA_KEY_API_V4L2_PATH "api.v4l2.path" /**< v4l2 device path as can be -+ * used in open() */ -+ -+/** keys for libcamera api */ -+#define SPA_KEY_API_LIBCAMERA "api.libcamera" /**< key for the libcamera api */ -+#define SPA_KEY_API_LIBCAMERA_PATH "api.libcamera.path" /**< libcamera device path as can be -+ * used in open() */ -+ -+/** info from libcamera_capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_DRIVER "api.libcamera.cap.driver" /**< driver from capbility */ -+#define SPA_KEY_API_LIBCAMERA_CAP_CARD "api.libcamera.cap.card" /**< caps from capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_BUS_INFO "api.libcamera.cap.bus_info"/**< bus_info from capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_VERSION "api.libcamera.cap.version" /**< version from capability as %u.%u.%u */ -+#define SPA_KEY_API_LIBCAMERA_CAP_CAPABILITIES \ -+ "api.libcamera.cap.capabilities" /**< capabilities from capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_DEVICE_CAPS \ -+ "api.libcamera.cap.device-caps" /**< device_caps from capability */ -+/** info from v4l2_capability */ -+#define SPA_KEY_API_V4L2_CAP_DRIVER "api.v4l2.cap.driver" /**< driver from capbility */ -+#define SPA_KEY_API_V4L2_CAP_CARD "api.v4l2.cap.card" /**< caps from capability */ -+#define SPA_KEY_API_V4L2_CAP_BUS_INFO "api.v4l2.cap.bus_info" /**< bus_info from capability */ -+#define SPA_KEY_API_V4L2_CAP_VERSION "api.v4l2.cap.version" /**< version from capability as %u.%u.%u */ -+#define SPA_KEY_API_V4L2_CAP_CAPABILITIES \ -+ "api.v4l2.cap.capabilities" /**< capabilities from capability */ -+#define SPA_KEY_API_V4L2_CAP_DEVICE_CAPS \ -+ "api.v4l2.cap.device-caps" /**< device_caps from capability */ -+ -+ -+/** keys for bluez5 api */ -+#define SPA_KEY_API_BLUEZ5 "api.bluez5" /**< key for the bluez5 api */ -+#define SPA_KEY_API_BLUEZ5_PATH "api.bluez5.path" /**< a bluez5 path */ -+#define SPA_KEY_API_BLUEZ5_DEVICE "api.bluez5.device" /**< an internal bluez5 device */ -+#define SPA_KEY_API_BLUEZ5_TRANSPORT "api.bluez5.transport" /**< an internal bluez5 transport */ -+#define SPA_KEY_API_BLUEZ5_PROFILE "api.bluez5.profile" /**< a bluetooth profile */ -+#define SPA_KEY_API_BLUEZ5_ADDRESS "api.bluez5.address" /**< a bluetooth address */ -+ -+/** keys for jack api */ -+#define SPA_KEY_API_JACK "api.jack" /**< key for the JACK api */ -+#define SPA_KEY_API_JACK_SERVER "api.jack.server" /**< a jack server name */ -+#define SPA_KEY_API_JACK_CLIENT "api.jack.client" /**< an internal jack client */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_KEYS_H */ -diff --git a/third_party/pipewire/spa/utils/list.h b/third_party/pipewire/spa/utils/list.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/list.h -@@ -0,0 +1,138 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LIST_H -+#define SPA_LIST_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct spa_list { -+ struct spa_list *next; -+ struct spa_list *prev; -+}; -+ -+#define SPA_LIST_INIT(list) (struct spa_list){ list, list }; -+ -+static inline void spa_list_init(struct spa_list *list) -+{ -+ *list = SPA_LIST_INIT(list); -+} -+ -+#define spa_list_is_empty(l) ((l)->next == (l)) -+ -+static inline void spa_list_insert(struct spa_list *list, struct spa_list *elem) -+{ -+ elem->prev = list; -+ elem->next = list->next; -+ list->next = elem; -+ elem->next->prev = elem; -+} -+ -+static inline void spa_list_insert_list(struct spa_list *list, struct spa_list *other) -+{ -+ if (spa_list_is_empty(other)) -+ return; -+ other->next->prev = list; -+ other->prev->next = list->next; -+ list->next->prev = other->prev; -+ list->next = other->next; -+} -+ -+static inline void spa_list_remove(struct spa_list *elem) -+{ -+ elem->prev->next = elem->next; -+ elem->next->prev = elem->prev; -+} -+ -+#define spa_list_first(head, type, member) \ -+ SPA_CONTAINER_OF((head)->next, type, member) -+ -+#define spa_list_last(head, type, member) \ -+ SPA_CONTAINER_OF((head)->prev, type, member) -+ -+#define spa_list_append(list, item) \ -+ spa_list_insert((list)->prev, item) -+ -+#define spa_list_prepend(list, item) \ -+ spa_list_insert(list, item) -+ -+#define spa_list_is_end(pos, head, member) \ -+ (&(pos)->member == (head)) -+ -+#define spa_list_next(pos, member) \ -+ SPA_CONTAINER_OF((pos)->member.next, __typeof__(*pos), member) -+ -+#define spa_list_prev(pos, member) \ -+ SPA_CONTAINER_OF((pos)->member.prev, __typeof__(*pos), member) -+ -+#define spa_list_consume(pos, head, member) \ -+ for (pos = spa_list_first(head, __typeof__(*pos), member); \ -+ !spa_list_is_empty(head); \ -+ pos = spa_list_first(head, __typeof__(*pos), member)) -+ -+#define spa_list_for_each_next(pos, head, curr, member) \ -+ for (pos = spa_list_first(curr, __typeof__(*pos), member); \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = spa_list_next(pos, member)) -+ -+#define spa_list_for_each_prev(pos, head, curr, member) \ -+ for (pos = spa_list_last(curr, __typeof__(*pos), member); \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = spa_list_prev(pos, member)) -+ -+#define spa_list_for_each(pos, head, member) \ -+ spa_list_for_each_next(pos, head, head, member) -+ -+#define spa_list_for_each_reverse(pos, head, member) \ -+ spa_list_for_each_prev(pos, head, head, member) -+ -+#define spa_list_for_each_safe_next(pos, tmp, head, curr, member) \ -+ for (pos = spa_list_first(curr, __typeof__(*pos), member); \ -+ tmp = spa_list_next(pos, member), \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = tmp) -+ -+#define spa_list_for_each_safe(pos, tmp, head, member) \ -+ spa_list_for_each_safe_next(pos, tmp, head, head, member) -+ -+#define spa_list_cursor_start(cursor, head, member) \ -+ spa_list_prepend(head, &(cursor).member) -+ -+#define spa_list_for_each_cursor(pos, cursor, head, member) \ -+ for(pos = spa_list_first(&(cursor).member, __typeof__(*(pos)), member); \ -+ spa_list_remove(&(pos)->member), \ -+ spa_list_append(&(cursor).member, &(pos)->member), \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = spa_list_next(&cursor, member)) -+ -+#define spa_list_cursor_end(cursor, member) \ -+ spa_list_remove(&(cursor).member) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_LIST_H */ -diff --git a/third_party/pipewire/spa/utils/names.h b/third_party/pipewire/spa/utils/names.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/names.h -@@ -0,0 +1,137 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_NAMES_H -+#define SPA_UTILS_NAMES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** for factory names */ -+#define SPA_NAME_SUPPORT_CPU "support.cpu" /**< A CPU interface */ -+#define SPA_NAME_SUPPORT_DBUS "support.dbus" /**< A DBUS interface */ -+#define SPA_NAME_SUPPORT_LOG "support.log" /**< A Log interface */ -+#define SPA_NAME_SUPPORT_LOOP "support.loop" /**< A Loop/LoopControl/LoopUtils -+ * interface */ -+#define SPA_NAME_SUPPORT_SYSTEM "support.system" /**< A System interface */ -+ -+#define SPA_NAME_SUPPORT_NODE_DRIVER "support.node.driver" /**< A dummy driver node */ -+ -+/* control mixer */ -+#define SPA_NAME_CONTROL_MIXER "control.mixer" /**< mixes control streams */ -+ -+/* audio mixer */ -+#define SPA_NAME_AUDIO_MIXER "audio.mixer" /**< mixes the raw audio on N input -+ * ports together on the output -+ * port */ -+#define SPA_NAME_AUDIO_MIXER_DSP "audio.mixer.dsp" /**< mixes mono audio with fixed input -+ * and output buffer sizes. supported -+ * formats must include f32 and -+ * optionally f64 and s24_32 */ -+ -+/** audio processing */ -+#define SPA_NAME_AUDIO_PROCESS_FORMAT "audio.process.format" /**< processes raw audio from one format -+ * to another */ -+#define SPA_NAME_AUDIO_PROCESS_CHANNELMIX \ -+ "audio.process.channelmix" /**< mixes raw audio channels and applies -+ * volume change. */ -+#define SPA_NAME_AUDIO_PROCESS_RESAMPLE \ -+ "audio.process.resample" /**< resamples raw audio */ -+#define SPA_NAME_AUDIO_PROCESS_DEINTERLEAVE \ -+ "audio.process.deinterleave" /**< deinterleave raw audio channels */ -+#define SPA_NAME_AUDIO_PROCESS_INTERLEAVE \ -+ "audio.process.interleave" /**< interleave raw audio channels */ -+ -+ -+/** audio convert combines some of the audio processing */ -+#define SPA_NAME_AUDIO_CONVERT "audio.convert" /**< converts raw audio from one format -+ * to another. Must include at least -+ * format, channelmix and resample -+ * processing */ -+#define SPA_NAME_AUDIO_ADAPT "audio.adapt" /**< combination of a node and an -+ * audio.convert. Does clock slaving */ -+ -+/** video processing */ -+#define SPA_NAME_VIDEO_PROCESS_FORMAT "video.process.format" /**< processes raw video from one format -+ * to another */ -+#define SPA_NAME_VIDEO_PROCESS_SCALE "video.process.scale" /**< scales raw video */ -+ -+/** video convert combines some of the video processing */ -+#define SPA_NAME_VIDEO_CONVERT "video.convert" /**< converts raw video from one format -+ * to another. Must include at least -+ * format and scaling */ -+#define SPA_NAME_VIDEO_ADAPT "video.adapt" /**< combination of a node and a -+ * video.convert. */ -+/** keys for alsa factory names */ -+#define SPA_NAME_API_ALSA_ENUM_UDEV "api.alsa.enum.udev" /**< an alsa udev Device interface */ -+#define SPA_NAME_API_ALSA_PCM_DEVICE "api.alsa.pcm.device" /**< an alsa Device interface */ -+#define SPA_NAME_API_ALSA_PCM_SOURCE "api.alsa.pcm.source" /**< an alsa Node interface for -+ * capturing PCM */ -+#define SPA_NAME_API_ALSA_PCM_SINK "api.alsa.pcm.sink" /**< an alsa Node interface for -+ * playback PCM */ -+#define SPA_NAME_API_ALSA_SEQ_DEVICE "api.alsa.seq.device" /**< an alsa Midi device */ -+#define SPA_NAME_API_ALSA_SEQ_SOURCE "api.alsa.seq.source" /**< an alsa Node interface for -+ * capture of midi */ -+#define SPA_NAME_API_ALSA_SEQ_SINK "api.alsa.seq.sink" /**< an alsa Node interface for -+ * playback of midi */ -+#define SPA_NAME_API_ALSA_SEQ_BRIDGE "api.alsa.seq.bridge" /**< an alsa Node interface for -+ * bridging midi ports */ -+#define SPA_NAME_API_ALSA_ACP_DEVICE "api.alsa.acp.device" /**< an alsa ACP Device interface */ -+ -+/** keys for bluez5 factory names */ -+#define SPA_NAME_API_BLUEZ5_ENUM_DBUS "api.bluez5.enum.dbus" /**< a dbus Device interface */ -+#define SPA_NAME_API_BLUEZ5_DEVICE "api.bluez5.device" /**< a Device interface */ -+#define SPA_NAME_API_BLUEZ5_A2DP_SINK "api.bluez5.a2dp.sink" /**< a playback Node interface for A2DP profiles */ -+#define SPA_NAME_API_BLUEZ5_A2DP_SOURCE "api.bluez5.a2dp.source" /**< a capture Node interface for A2DP profiles */ -+#define SPA_NAME_API_BLUEZ5_SCO_SINK "api.bluez5.sco.sink" /**< a playback Node interface for HSP/HFP profiles */ -+#define SPA_NAME_API_BLUEZ5_SCO_SOURCE "api.bluez5.sco.source" /**< a capture Node interface for HSP/HFP profiles */ -+ -+/** keys for v4l2 factory names */ -+#define SPA_NAME_API_V4L2_ENUM_UDEV "api.v4l2.enum.udev" /**< a v4l2 udev Device interface */ -+#define SPA_NAME_API_V4L2_DEVICE "api.v4l2.device" /**< a v4l2 Device interface */ -+#define SPA_NAME_API_V4L2_SOURCE "api.v4l2.source" /**< a v4l2 Node interface for -+ * capturing */ -+ -+/** keys for libcamera factory names */ -+#define SPA_NAME_API_LIBCAMERA_ENUM_CLIENT "api.libcamera.enum.client" /**< a libcamera client Device interface */ -+#define SPA_NAME_API_LIBCAMERA_DEVICE "api.libcamera.device" /**< a libcamera Device interface */ -+#define SPA_NAME_API_LIBCAMERA_SOURCE "api.libcamera.source" /**< a libcamera Node interface for -+ * capturing */ -+ -+/** keys for jack factory names */ -+#define SPA_NAME_API_JACK_DEVICE "api.jack.device" /**< a jack device. This is a -+ * client connected to a server */ -+#define SPA_NAME_API_JACK_SOURCE "api.jack.source" /**< a jack source */ -+#define SPA_NAME_API_JACK_SINK "api.jack.sink" /**< a jack sink */ -+ -+/** keys for vulkan factory names */ -+#define SPA_NAME_API_VULKAN_COMPUTE_SOURCE \ -+ "api.vulkan.compute.source" /**< a vulkan compute source. */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_NAMES_H */ -diff --git a/third_party/pipewire/spa/utils/result.h b/third_party/pipewire/spa/utils/result.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/result.h -@@ -0,0 +1,58 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_RESULT_H -+#define SPA_UTILS_RESULT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#define SPA_ASYNC_BIT (1 << 30) -+#define SPA_ASYNC_MASK (3 << 30) -+#define SPA_ASYNC_SEQ_MASK (SPA_ASYNC_BIT - 1) -+ -+#define SPA_RESULT_IS_OK(res) ((res) >= 0) -+#define SPA_RESULT_IS_ERROR(res) ((res) < 0) -+#define SPA_RESULT_IS_ASYNC(res) (((res) & SPA_ASYNC_MASK) == SPA_ASYNC_BIT) -+ -+#define SPA_RESULT_ASYNC_SEQ(res) ((res) & SPA_ASYNC_SEQ_MASK) -+#define SPA_RESULT_RETURN_ASYNC(seq) (SPA_ASYNC_BIT | SPA_RESULT_ASYNC_SEQ(seq)) -+ -+#define spa_strerror(err) \ -+({ \ -+ int _err = -err; \ -+ if (SPA_RESULT_IS_ASYNC(err)) \ -+ _err = EINPROGRESS; \ -+ strerror(_err); \ -+}) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_RESULT_H */ -diff --git a/third_party/pipewire/spa/utils/ringbuffer.h b/third_party/pipewire/spa/utils/ringbuffer.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/ringbuffer.h -@@ -0,0 +1,174 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_RINGBUFFER_H -+#define SPA_RINGBUFFER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct spa_ringbuffer; -+ -+#include -+ -+#include -+ -+/** -+ * A ringbuffer type. -+ */ -+struct spa_ringbuffer { -+ uint32_t readindex; /*< the current read index */ -+ uint32_t writeindex; /*< the current write index */ -+}; -+ -+#define SPA_RINGBUFFER_INIT() (struct spa_ringbuffer) { 0, 0 } -+ -+/** -+ * Initialize a spa_ringbuffer with \a size. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param size the number of elements in the ringbuffer -+ */ -+static inline void spa_ringbuffer_init(struct spa_ringbuffer *rbuf) -+{ -+ *rbuf = SPA_RINGBUFFER_INIT(); -+} -+ -+/** -+ * Sets the pointers so that the ringbuffer contains \a size bytes. -+ * -+ * \param rbuf a spa_ringbuffer -+ */ -+static inline void spa_ringbuffer_set_avail(struct spa_ringbuffer *rbuf, uint32_t size) -+{ -+ rbuf->readindex = 0; -+ rbuf->writeindex = size; -+} -+ -+/** -+ * Get the read index and available bytes for reading. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index the value of readindex, should be taken modulo the size of the -+ * ringbuffer memory to get the offset in the ringbuffer memory -+ * \return number of available bytes to read. values < 0 mean -+ * there was an underrun. values > rbuf->size means there -+ * was an overrun. -+ */ -+static inline int32_t spa_ringbuffer_get_read_index(struct spa_ringbuffer *rbuf, uint32_t *index) -+{ -+ *index = __atomic_load_n(&rbuf->readindex, __ATOMIC_RELAXED); -+ return (int32_t) (__atomic_load_n(&rbuf->writeindex, __ATOMIC_ACQUIRE) - *index); -+} -+ -+/** -+ * Read \a len bytes from \a rbuf starting \a offset. \a offset must be taken -+ * modulo \a size and len should be smaller than \a size. -+ * -+ * \param rbuf a #struct spa_ringbuffer -+ * \param buffer memory to read from -+ * \param size the size of \a buffer -+ * \param offset offset in \a buffer to read from -+ * \param data destination memory -+ * \param len number of bytes to read -+ */ -+static inline void -+spa_ringbuffer_read_data(struct spa_ringbuffer *rbuf, -+ const void *buffer, uint32_t size, -+ uint32_t offset, void *data, uint32_t len) -+{ -+ uint32_t l0 = SPA_MIN(len, size - offset), l1 = len - l0; -+ spa_memcpy(data, SPA_MEMBER(buffer, offset, void), l0); -+ if (SPA_UNLIKELY(l1 > 0)) -+ spa_memcpy(SPA_MEMBER(data, l0, void), buffer, l1); -+} -+ -+/** -+ * Update the read pointer to \a index. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index new index -+ */ -+static inline void spa_ringbuffer_read_update(struct spa_ringbuffer *rbuf, int32_t index) -+{ -+ __atomic_store_n(&rbuf->readindex, index, __ATOMIC_RELEASE); -+} -+ -+/** -+ * Get the write index and the number of bytes inside the ringbuffer. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index the value of writeindex, should be taken modulo the size of the -+ * ringbuffer memory to get the offset in the ringbuffer memory -+ * \return the fill level of \a rbuf. values < 0 mean -+ * there was an underrun. values > rbuf->size means there -+ * was an overrun. Subtract from the buffer size to get -+ * the number of bytes available for writing. -+ */ -+static inline int32_t spa_ringbuffer_get_write_index(struct spa_ringbuffer *rbuf, uint32_t *index) -+{ -+ *index = __atomic_load_n(&rbuf->writeindex, __ATOMIC_RELAXED); -+ return (int32_t) (*index - __atomic_load_n(&rbuf->readindex, __ATOMIC_ACQUIRE)); -+} -+ -+/** -+ * Write \a len bytes to \a buffer starting \a offset. \a offset must be taken -+ * modulo \a size and len should be smaller than \a size. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param buffer memory to write to -+ * \param size the size of \a buffer -+ * \param offset offset in \a buffer to write to -+ * \param data source memory -+ * \param len number of bytes to write -+ */ -+static inline void -+spa_ringbuffer_write_data(struct spa_ringbuffer *rbuf, -+ void *buffer, uint32_t size, -+ uint32_t offset, const void *data, uint32_t len) -+{ -+ uint32_t l0 = SPA_MIN(len, size - offset), l1 = len - l0; -+ spa_memcpy(SPA_MEMBER(buffer, offset, void), data, l0); -+ if (SPA_UNLIKELY(l1 > 0)) -+ spa_memcpy(buffer, SPA_MEMBER(data, l0, void), l1); -+} -+ -+/** -+ * Update the write pointer to \a index -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index new index -+ */ -+static inline void spa_ringbuffer_write_update(struct spa_ringbuffer *rbuf, int32_t index) -+{ -+ __atomic_store_n(&rbuf->writeindex, index, __ATOMIC_RELEASE); -+} -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_RINGBUFFER_H */ -diff --git a/third_party/pipewire/spa/utils/type-info.h b/third_party/pipewire/spa/utils/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/type-info.h -@@ -0,0 +1,128 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_TYPE_INFO_H -+#define SPA_TYPE_INFO_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef SPA_TYPE_ROOT -+#define SPA_TYPE_ROOT spa_types -+#endif -+ -+static inline bool spa_type_is_a(const char *type, const char *parent) -+{ -+ return type != NULL && parent != NULL && strncmp(type, parent, strlen(parent)) == 0; -+} -+ -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_Direction SPA_TYPE_INFO_ENUM_BASE "Direction" -+#define SPA_TYPE_INFO_DIRECTION_BASE SPA_TYPE_INFO_Direction ":" -+ -+static const struct spa_type_info spa_type_direction[] = { -+ { SPA_DIRECTION_INPUT, SPA_TYPE_Int, SPA_TYPE_INFO_DIRECTION_BASE "Input", NULL }, -+ { SPA_DIRECTION_OUTPUT, SPA_TYPE_Int, SPA_TYPE_INFO_DIRECTION_BASE "Output", NULL }, -+ { 0, 0, NULL, NULL } -+}; -+ -+#include -+#include -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_Choice SPA_TYPE_INFO_ENUM_BASE "Choice" -+#define SPA_TYPE_INFO_CHOICE_BASE SPA_TYPE_INFO_Choice ":" -+ -+static const struct spa_type_info spa_type_choice[] = { -+ { SPA_CHOICE_None, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "None", NULL }, -+ { SPA_CHOICE_Range, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Range", NULL }, -+ { SPA_CHOICE_Step, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Step", NULL }, -+ { SPA_CHOICE_Enum, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Enum", NULL }, -+ { SPA_CHOICE_Flags, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Flags", NULL }, -+ { 0, 0, NULL, NULL } -+}; -+ -+static const struct spa_type_info spa_types[] = { -+ /* Basic types */ -+ { SPA_TYPE_START, SPA_TYPE_START, SPA_TYPE_INFO_BASE, NULL }, -+ { SPA_TYPE_None, SPA_TYPE_None, SPA_TYPE_INFO_BASE "None", NULL }, -+ { SPA_TYPE_Bool, SPA_TYPE_Bool, SPA_TYPE_INFO_BASE "Bool", NULL }, -+ { SPA_TYPE_Id, SPA_TYPE_Int, SPA_TYPE_INFO_BASE "Id", NULL }, -+ { SPA_TYPE_Int, SPA_TYPE_Int, SPA_TYPE_INFO_BASE "Int", NULL }, -+ { SPA_TYPE_Long, SPA_TYPE_Long, SPA_TYPE_INFO_BASE "Long", NULL }, -+ { SPA_TYPE_Float, SPA_TYPE_Float, SPA_TYPE_INFO_BASE "Float", NULL }, -+ { SPA_TYPE_Double, SPA_TYPE_Double, SPA_TYPE_INFO_BASE "Double", NULL }, -+ { SPA_TYPE_String, SPA_TYPE_String, SPA_TYPE_INFO_BASE "String", NULL }, -+ { SPA_TYPE_Bytes, SPA_TYPE_Bytes, SPA_TYPE_INFO_BASE "Bytes", NULL }, -+ { SPA_TYPE_Rectangle, SPA_TYPE_Rectangle, SPA_TYPE_INFO_BASE "Rectangle", NULL }, -+ { SPA_TYPE_Fraction, SPA_TYPE_Fraction, SPA_TYPE_INFO_BASE "Fraction", NULL }, -+ { SPA_TYPE_Bitmap, SPA_TYPE_Bitmap, SPA_TYPE_INFO_BASE "Bitmap", NULL }, -+ { SPA_TYPE_Array, SPA_TYPE_Array, SPA_TYPE_INFO_BASE "Array", NULL }, -+ { SPA_TYPE_Pod, SPA_TYPE_Pod, SPA_TYPE_INFO_Pod, NULL }, -+ { SPA_TYPE_Struct, SPA_TYPE_Pod, SPA_TYPE_INFO_Struct, NULL }, -+ { SPA_TYPE_Object, SPA_TYPE_Pod, SPA_TYPE_INFO_Object, NULL }, -+ { SPA_TYPE_Sequence, SPA_TYPE_Pod, SPA_TYPE_INFO_POD_BASE "Sequence", NULL }, -+ { SPA_TYPE_Pointer, SPA_TYPE_Pointer, SPA_TYPE_INFO_Pointer, NULL }, -+ { SPA_TYPE_Fd, SPA_TYPE_Fd, SPA_TYPE_INFO_BASE "Fd", NULL }, -+ { SPA_TYPE_Choice, SPA_TYPE_Pod, SPA_TYPE_INFO_POD_BASE "Choice", NULL }, -+ -+ { SPA_TYPE_POINTER_START, SPA_TYPE_Pointer, SPA_TYPE_INFO_Pointer, NULL }, -+ { SPA_TYPE_POINTER_Buffer, SPA_TYPE_Pointer, SPA_TYPE_INFO_POINTER_BASE "Buffer", NULL }, -+ { SPA_TYPE_POINTER_Meta, SPA_TYPE_Pointer, SPA_TYPE_INFO_POINTER_BASE "Meta", NULL }, -+ { SPA_TYPE_POINTER_Dict, SPA_TYPE_Pointer, SPA_TYPE_INFO_POINTER_BASE "Dict", NULL }, -+ -+ { SPA_TYPE_EVENT_START, SPA_TYPE_Object, SPA_TYPE_INFO_Event, NULL }, -+ { SPA_TYPE_EVENT_Device, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Device", NULL }, -+ { SPA_TYPE_EVENT_Node, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Node", spa_type_node_event }, -+ -+ { SPA_TYPE_COMMAND_START, SPA_TYPE_Object, SPA_TYPE_INFO_Command, NULL }, -+ { SPA_TYPE_COMMAND_Device, SPA_TYPE_Object, SPA_TYPE_INFO_COMMAND_BASE "Device", NULL }, -+ { SPA_TYPE_COMMAND_Node, SPA_TYPE_Object, SPA_TYPE_INFO_COMMAND_BASE "Node", spa_type_node_command }, -+ -+ { SPA_TYPE_OBJECT_START, SPA_TYPE_Object, SPA_TYPE_INFO_Object, NULL }, -+ { SPA_TYPE_OBJECT_PropInfo, SPA_TYPE_Object, SPA_TYPE_INFO_PropInfo, spa_type_prop_info, }, -+ { SPA_TYPE_OBJECT_Props, SPA_TYPE_Object, SPA_TYPE_INFO_Props, spa_type_props }, -+ { SPA_TYPE_OBJECT_Format, SPA_TYPE_Object, SPA_TYPE_INFO_Format, spa_type_format }, -+ { SPA_TYPE_OBJECT_ParamBuffers, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Buffers, spa_type_param_buffers, }, -+ { SPA_TYPE_OBJECT_ParamMeta, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Meta, spa_type_param_meta }, -+ { SPA_TYPE_OBJECT_ParamIO, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_IO, spa_type_param_io }, -+ { SPA_TYPE_OBJECT_ParamProfile, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Profile, spa_type_param_profile }, -+ { SPA_TYPE_OBJECT_ParamPortConfig, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_PortConfig, spa_type_param_port_config }, -+ { SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Route, spa_type_param_route }, -+ { SPA_TYPE_OBJECT_Profiler, SPA_TYPE_Object, SPA_TYPE_INFO_Profiler, spa_type_profiler }, -+ -+ { 0, 0, NULL, NULL } -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_TYPE_INFO_H */ -diff --git a/third_party/pipewire/spa/utils/type.h b/third_party/pipewire/spa/utils/type.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/type.h -@@ -0,0 +1,138 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_TYPE_H -+#define SPA_TYPE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+enum { -+ /* Basic types */ -+ SPA_TYPE_START = 0x00000, -+ SPA_TYPE_None, -+ SPA_TYPE_Bool, -+ SPA_TYPE_Id, -+ SPA_TYPE_Int, -+ SPA_TYPE_Long, -+ SPA_TYPE_Float, -+ SPA_TYPE_Double, -+ SPA_TYPE_String, -+ SPA_TYPE_Bytes, -+ SPA_TYPE_Rectangle, -+ SPA_TYPE_Fraction, -+ SPA_TYPE_Bitmap, -+ SPA_TYPE_Array, -+ SPA_TYPE_Struct, -+ SPA_TYPE_Object, -+ SPA_TYPE_Sequence, -+ SPA_TYPE_Pointer, -+ SPA_TYPE_Fd, -+ SPA_TYPE_Choice, -+ SPA_TYPE_Pod, -+ SPA_TYPE_LAST, /**< not part of ABI */ -+ -+ /* Pointers */ -+ SPA_TYPE_POINTER_START = 0x10000, -+ SPA_TYPE_POINTER_Buffer, -+ SPA_TYPE_POINTER_Meta, -+ SPA_TYPE_POINTER_Dict, -+ SPA_TYPE_POINTER_LAST, /**< not part of ABI */ -+ -+ /* Events */ -+ SPA_TYPE_EVENT_START = 0x20000, -+ SPA_TYPE_EVENT_Device, -+ SPA_TYPE_EVENT_Node, -+ SPA_TYPE_EVENT_LAST, /**< not part of ABI */ -+ -+ /* Commands */ -+ SPA_TYPE_COMMAND_START = 0x30000, -+ SPA_TYPE_COMMAND_Device, -+ SPA_TYPE_COMMAND_Node, -+ SPA_TYPE_COMMAND_LAST, /**< not part of ABI */ -+ -+ /* Objects */ -+ SPA_TYPE_OBJECT_START = 0x40000, -+ SPA_TYPE_OBJECT_PropInfo, -+ SPA_TYPE_OBJECT_Props, -+ SPA_TYPE_OBJECT_Format, -+ SPA_TYPE_OBJECT_ParamBuffers, -+ SPA_TYPE_OBJECT_ParamMeta, -+ SPA_TYPE_OBJECT_ParamIO, -+ SPA_TYPE_OBJECT_ParamProfile, -+ SPA_TYPE_OBJECT_ParamPortConfig, -+ SPA_TYPE_OBJECT_ParamRoute, -+ SPA_TYPE_OBJECT_Profiler, -+ SPA_TYPE_OBJECT_LAST, /**< not part of ABI */ -+ -+ /* vendor extensions */ -+ SPA_TYPE_VENDOR_PipeWire = 0x02000000, -+ -+ SPA_TYPE_VENDOR_Other = 0x7f000000, -+}; -+ -+#define SPA_TYPE_INFO_BASE "Spa:" -+ -+#define SPA_TYPE_INFO_Flags SPA_TYPE_INFO_BASE "Flags" -+#define SPA_TYPE_INFO_FLAGS_BASE SPA_TYPE_INFO_Flags ":" -+ -+#define SPA_TYPE_INFO_Enum SPA_TYPE_INFO_BASE "Enum" -+#define SPA_TYPE_INFO_ENUM_BASE SPA_TYPE_INFO_Enum ":" -+ -+#define SPA_TYPE_INFO_Pod SPA_TYPE_INFO_BASE "Pod" -+#define SPA_TYPE_INFO_POD_BASE SPA_TYPE_INFO_Pod ":" -+ -+#define SPA_TYPE_INFO_Struct SPA_TYPE_INFO_POD_BASE "Struct" -+#define SPA_TYPE_INFO_STRUCT_BASE SPA_TYPE_INFO_Struct ":" -+ -+#define SPA_TYPE_INFO_Object SPA_TYPE_INFO_POD_BASE "Object" -+#define SPA_TYPE_INFO_OBJECT_BASE SPA_TYPE_INFO_Object ":" -+ -+#define SPA_TYPE_INFO_Pointer SPA_TYPE_INFO_BASE "Pointer" -+#define SPA_TYPE_INFO_POINTER_BASE SPA_TYPE_INFO_Pointer ":" -+ -+#define SPA_TYPE_INFO_Interface SPA_TYPE_INFO_POINTER_BASE "Interface" -+#define SPA_TYPE_INFO_INTERFACE_BASE SPA_TYPE_INFO_Interface ":" -+ -+#define SPA_TYPE_INFO_Event SPA_TYPE_INFO_OBJECT_BASE "Event" -+#define SPA_TYPE_INFO_EVENT_BASE SPA_TYPE_INFO_Event ":" -+ -+#define SPA_TYPE_INFO_Command SPA_TYPE_INFO_OBJECT_BASE "Command" -+#define SPA_TYPE_INFO_COMMAND_BASE SPA_TYPE_INFO_Command ":" -+ -+struct spa_type_info { -+ uint32_t type; -+ uint32_t parent; -+ const char *name; -+ const struct spa_type_info *values; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_TYPE_H */ - diff --git a/pw5.patch b/pw5.patch deleted file mode 100644 index bcb004e..0000000 --- a/pw5.patch +++ /dev/null @@ -1,53 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1605025841 0 -# Node ID e04be7688dfb4fbbe8dee73e366df8bc9a5da580 -# Parent 41d3c1292480de14d05b34aa0cf2d56015994878 -Bug 1675767 [Linux] Use PipeWire on Wayland desktop, r=dminor - -Differential Revision: https://phabricator.services.mozilla.com/D96587 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -@@ -72,37 +72,21 @@ std::unique_ptr Desktop - if (capturer && options.detect_updated_region()) { - capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer))); - } - - return capturer; - } - - #if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) --// Return true if Firefox is actually running with Wayland backend. --static bool IsWaylandDisplayUsed() { -- const auto display = gdk_display_get_default(); -- if (display == nullptr) { -- // We're running in headless mode. -- return false; -- } -- return !GDK_IS_X11_DISPLAY(display); --} -- --// Return true if Firefox is actually running on Wayland enabled session. --// It means some screensharing capabilities may be limited. --static bool IsWaylandSessionUsed() { -+bool DesktopCapturer::IsRunningUnderWayland() { - const char* xdg_session_type = getenv("XDG_SESSION_TYPE"); - if (!xdg_session_type || strncmp(xdg_session_type, "wayland", 7) != 0) - return false; - - if (!(getenv("WAYLAND_DISPLAY"))) - return false; - - return true; - } -- --bool DesktopCapturer::IsRunningUnderWayland() { -- return IsWaylandSessionUsed() ? IsWaylandDisplayUsed() : false; --} - #endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - - } // namespace webrtc - diff --git a/pw6.patch b/pw6.patch deleted file mode 100644 index 90f0879..0000000 --- a/pw6.patch +++ /dev/null @@ -1,163 +0,0 @@ -diff -up firefox-83.0/browser/actors/WebRTCParent.jsm.pw6 firefox-83.0/browser/actors/WebRTCParent.jsm ---- firefox-83.0/browser/actors/WebRTCParent.jsm.pw6 2020-11-12 19:04:30.000000000 +0100 -+++ firefox-83.0/browser/actors/WebRTCParent.jsm 2020-11-25 10:28:32.492865982 +0100 -@@ -45,6 +45,9 @@ XPCOMUtils.defineLazyServiceGetter( - "nsIOSPermissionRequest" - ); - -+const PIPEWIRE_PORTAL_NAME = "####_PIPEWIRE_PORTAL_####"; -+const PIPEWIRE_ID = 0xaffffff; -+ - class WebRTCParent extends JSWindowActorParent { - didDestroy() { - webrtcUI.forgetStreamsFromBrowserContext(this.browsingContext); -@@ -753,6 +756,8 @@ function prompt(aActor, aBrowser, aReque - ); - menupopup.appendChild(doc.createXULElement("menuseparator")); - -+ let isPipeWire = false; -+ - // Build the list of 'devices'. - let monitorIndex = 1; - for (let i = 0; i < devices.length; ++i) { -@@ -774,6 +779,29 @@ function prompt(aActor, aBrowser, aReque - } - } else { - name = device.name; -+ // When we share content by PipeWire add only one item to the device -+ // list. When it's selected PipeWire portal dialog is opened and -+ // user confirms actual window/screen sharing there. -+ // Don't mark it as scary as there's an extra confirmation step by -+ // PipeWire portal dialog. -+ if (name == PIPEWIRE_PORTAL_NAME && device.id == PIPEWIRE_ID) { -+ isPipeWire = true; -+ let name; -+ try { -+ name = stringBundle.getString("getUserMedia.sharePipeWirePortal.label"); -+ } catch (err) { -+ name = "Use operating system settings" -+ } -+ let item = addDeviceToList( -+ menupopup, -+ name, -+ i, -+ type -+ ); -+ item.deviceId = device.id; -+ item.mediaSource = type; -+ break; -+ } - if (type == "application") { - // The application names returned by the platform are of the form: - // \x1e -@@ -888,39 +916,41 @@ function prompt(aActor, aBrowser, aReque - perms.EXPIRE_SESSION - ); - -- video.deviceId = deviceId; -- let constraints = { -- video: { mediaSource: type, deviceId: { exact: deviceId } }, -- }; -- chromeWin.navigator.mediaDevices.getUserMedia(constraints).then( -- stream => { -- if (video.deviceId != deviceId) { -- // The user has selected a different device or closed the panel -- // before getUserMedia finished. -- stream.getTracks().forEach(t => t.stop()); -- return; -- } -- video.srcObject = stream; -- video.stream = stream; -- doc.getElementById("webRTC-preview").hidden = false; -- video.onloadedmetadata = function(e) { -- video.play(); -- }; -- }, -- err => { -- if ( -- err.name == "OverconstrainedError" && -- err.constraint == "deviceId" -- ) { -- // Window has disappeared since enumeration, which can happen. -- // No preview for you. -- return; -+ if (!isPipeWire) { -+ video.deviceId = deviceId; -+ let constraints = { -+ video: { mediaSource: type, deviceId: { exact: deviceId } }, -+ }; -+ chromeWin.navigator.mediaDevices.getUserMedia(constraints).then( -+ stream => { -+ if (video.deviceId != deviceId) { -+ // The user has selected a different device or closed the panel -+ // before getUserMedia finished. -+ stream.getTracks().forEach(t => t.stop()); -+ return; -+ } -+ video.srcObject = stream; -+ video.stream = stream; -+ doc.getElementById("webRTC-preview").hidden = false; -+ video.onloadedmetadata = function(e) { -+ video.play(); -+ }; -+ }, -+ err => { -+ if ( -+ err.name == "OverconstrainedError" && -+ err.constraint == "deviceId" -+ ) { -+ // Window has disappeared since enumeration, which can happen. -+ // No preview for you. -+ return; -+ } -+ Cu.reportError( -+ `error in preview: ${err.message} ${err.constraint}` -+ ); - } -- Cu.reportError( -- `error in preview: ${err.message} ${err.constraint}` -- ); -- } -- ); -+ ); -+ } - }; - menupopup.addEventListener("command", menupopup._commandEventListener); - } -diff -up firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties.pw6 firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties ---- firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties.pw6 2020-11-12 19:04:30.000000000 +0100 -+++ firefox-83.0/browser/locales/en-US/chrome/browser/browser.properties 2020-11-25 09:24:26.378857626 +0100 -@@ -764,6 +764,7 @@ getUserMedia.selectWindowOrScreen.label= - getUserMedia.selectWindowOrScreen.accesskey=W - getUserMedia.pickWindowOrScreen.label = Select Window or Screen - getUserMedia.shareEntireScreen.label = Entire screen -+getUserMedia.sharePipeWirePortal.label = Use operating system settings - # LOCALIZATION NOTE (getUserMedia.shareMonitor.label): - # %S is screen number (digits 1, 2, etc) - # Example: Screen 1, Screen 2,.. -diff -up firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc.pw6 firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc ---- firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc.pw6 2020-11-25 09:24:26.358857788 +0100 -+++ firefox-83.0/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc 2020-11-25 09:24:26.378857626 +0100 -@@ -879,17 +879,17 @@ void BaseCapturerPipeWire::CaptureFrame( - callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); - } - -+#define PIPEWIRE_ID 0xaffffff -+#define PIPEWIRE_NAME "####_PIPEWIRE_PORTAL_####" -+ - bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { -- RTC_DCHECK(sources->size() == 0); -- // List of available screens is already presented by the xdg-desktop-portal. -- // But we have to add an empty source as the code expects it. -- sources->push_back({0}); -+ sources->push_back({PIPEWIRE_ID, 0, PIPEWIRE_NAME}); - return true; - } - - bool BaseCapturerPipeWire::SelectSource(SourceId id) { - // Screen selection is handled by the xdg-desktop-portal. -- return true; -+ return id == PIPEWIRE_ID; - } - - // static diff --git a/sources b/sources index 0a077ef..91c83fd 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ SHA512 (cbindgen-vendor.tar.xz) = 3c925c5523246b7dfbcb4ce563483d5b45315a06dc90f2cf07cddef0c263dd15b410afbbe4d86594de96a308e93be3b27ffec01f5f759a42ecba3cc983b1677f SHA512 (mochitest-python.tar.gz) = 7f357cb8bd93d64be5cb75819a8a813d2f8f217ff25f0df8c3190910744132405d45797b3900775a44b554f5c70cf2682809c9e7a686ca131fddcd81e98028d9 -SHA512 (firefox-84.0.2.source.tar.xz) = 3fd4c9a5ec2409f23507b38c809e71a35aa674779dc5a7a2e3ff82841e0b65ead29d38ac4d5b17f7108479ed7338b3d2b40cbcfa9c51e01696634166d92edf99 -SHA512 (firefox-langpacks-84.0.2-20210106.tar.xz) = 49b6bae80031d70a413a1e5033e7b8d2625ad687bbbbda7ade4e523c549c6a46af5f29de7bf538e0e464ea17734fcd43ba2e015cc190f93af4e3b88d3f50ccde +SHA512 (firefox-85.0.source.tar.xz) = a88472e66baab32d98cb9d13d7dd3c41b47a697ce2a42209612d2342bd6c1c26cd80cdd8905a4cecc72895f155df09762735e8af24bc6156663b7a14e890be4e +SHA512 (firefox-langpacks-85.0-20210120.tar.xz) = ec4b720d74940849f90831de72c5b7bdc004075e4a9b3b966c218b87e4ff9c3c10117a193d947cd971db955f1f3be99d7af706f981b8c0195c16936b1a10881e