diff --git a/.gitignore b/.gitignore index 0b5520a..cba71f3 100644 --- a/.gitignore +++ b/.gitignore @@ -436,3 +436,5 @@ firefox-3.6.4.source.tar.bz2 /firefox-testing.tar.gz /site-packages.tar.gz /mochitest-python.tar.gz +/firefox-84.0.source.tar.xz +/firefox-langpacks-84.0-20201210.tar.xz diff --git a/build-disable-elfhack.patch b/build-disable-elfhack.patch index a80c551..faaf669 100644 --- a/build-disable-elfhack.patch +++ b/build-disable-elfhack.patch @@ -1,12 +1,12 @@ -diff -up firefox-65.0/toolkit/moz.configure.disable-elfhack firefox-65.0/toolkit/moz.configure ---- firefox-65.0/toolkit/moz.configure.disable-elfhack 2019-01-28 14:16:48.530345132 +0100 -+++ firefox-65.0/toolkit/moz.configure 2019-01-28 14:18:03.231029682 +0100 -@@ -1036,7 +1036,7 @@ with only_when('--enable-compile-environ - help='{Enable|Disable} elf hacks') +diff -up firefox-84.0/toolkit/moz.configure.disable-elfhack firefox-84.0/toolkit/moz.configure +--- firefox-84.0/toolkit/moz.configure.disable-elfhack 2020-12-10 12:37:30.727243266 +0100 ++++ firefox-84.0/toolkit/moz.configure 2020-12-10 12:39:42.771967894 +0100 +@@ -1280,7 +1280,7 @@ with only_when("--enable-compile-environ + help="{Enable|Disable} elf hacks", + ) - set_config('USE_ELF_HACK', -- depends_if('--enable-elf-hack')(lambda _: True)) -+ depends_if('--enable-elf-hack')(lambda _: False)) +- set_config("USE_ELF_HACK", depends_if("--enable-elf-hack")(lambda _: True)) ++ set_config("USE_ELF_HACK", depends_if("--enable-elf-hack")(lambda _: False)) @depends(check_build_environment) diff --git a/ffvpx.patch b/ffvpx.patch new file mode 100644 index 0000000..cff0437 --- /dev/null +++ b/ffvpx.patch @@ -0,0 +1,9502 @@ +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +0100 +@@ -124,8 +124,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 +138,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 +148,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 +158,7 @@ void DMABufSurfaceWrapper::ReleaseVAAPID + mSurface->ReleaseSurface(); + } + +-DMABufSurfaceWrapper::~DMABufSurfaceWrapper() { ++DMABufSurfaceWrapper::~DMABufSurfaceWrapper() { + FFMPEG_LOG("DMABufSurfaceWrapper: deleting dmabuf surface UID = %d", + mSurface->GetUID()); + ReleaseVAAPIData(); +@@ -181,7 +181,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 +200,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 +237,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 +711,7 @@ void FFmpegVideoDecoder::Rele + } + } + +-DMABufSurfaceWrapper* ++DMABufSurfaceWrapper* + FFmpegVideoDecoder::GetUnusedDMABufSurfaceWrapper() { + int len = mDMABufSurfaces.Length(); + for (int i = 0; i < len; i++) { +@@ -769,7 +777,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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +0100 +@@ -9,6 +9,7 @@ + #include "mozilla/layers/CompositableClient.h" + #include "mozilla/layers/CompositableForwarder.h" + #include "mozilla/layers/DMABUFTextureClientOGL.h" ++#include "mozilla/layers/TextureForwarder.h" + #include "mozilla/UniquePtr.h" + + using namespace mozilla; +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.731266180 +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 17:03:31.725266007 +0100 ++++ firefox-84.0/media/ffvpx/libavcodec/moz.build 2020-12-10 17:03:31.732266209 +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 17:03:31.732266209 +0100 ++++ firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.c 2020-12-10 17:03:31.732266209 +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 17:03:31.732266209 +0100 ++++ firefox-84.0/media/ffvpx/libavcodec/vaapi_decode.h 2020-12-10 17:03:31.732266209 +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 17:03:31.732266209 +0100 ++++ firefox-84.0/media/ffvpx/libavcodec/vaapi.h 2020-12-10 17:03:31.732266209 +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 17:03:31.732266209 +0100 ++++ firefox-84.0/media/ffvpx/libavcodec/vaapi_vp8.c 2020-12-10 17:03:31.732266209 +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 17:03:31.732266209 +0100 ++++ firefox-84.0/media/ffvpx/libavcodec/vaapi_vp9.c 2020-12-10 17:03:31.732266209 +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 17:03:31.732266209 +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 17:03:31.732266209 +0100 ++++ firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.c 2020-12-10 17:03:31.732266209 +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 17:03:31.733266237 +0100 ++++ firefox-84.0/media/ffvpx/libavutil/hwcontext_vaapi.h 2020-12-10 17:03:31.733266237 +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 17:03:31.733266237 +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 17:03:31.733266237 +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 17:06:25.599272289 +0100 ++++ firefox-84.0/media/ffvpx/mozva/moz.build 2020-12-10 17:07:19.630827998 +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 17:05:06.119983875 +0100 ++++ firefox-84.0/media/ffvpx/mozva/mozva.c 2020-12-10 17:05:06.119983875 +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 17:05:06.119983875 +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 17:05:06.119983875 +0100 ++++ firefox-84.0/media/ffvpx/va/README 2020-12-10 17:05:06.119983875 +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 17:05:06.119983875 +0100 ++++ firefox-84.0/media/ffvpx/va/va_dec_vp8.h 2020-12-10 17:05:06.119983875 +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 17:05:06.121983932 +0100 ++++ firefox-84.0/media/ffvpx/va/va.h 2020-12-10 17:05:06.121983932 +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 17:05:06.121983932 +0100 ++++ firefox-84.0/media/ffvpx/va/va.patch 2020-12-10 17:05:06.121983932 +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 17:05:06.121983932 +0100 ++++ firefox-84.0/media/ffvpx/va/va_version.h 2020-12-10 17:05:06.121983932 +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 17:05:06.121983932 +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 17:05:06.121983932 +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 17:05:06.122983961 +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-mochitest.patch b/firefox-mochitest.patch deleted file mode 100644 index c7539be..0000000 --- a/firefox-mochitest.patch +++ /dev/null @@ -1,9 +0,0 @@ -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 -@@ -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 --git a/firefox-testing.patch b/firefox-testing.patch index 04ef0f3..c973db6 100644 --- a/firefox-testing.patch +++ b/firefox-testing.patch @@ -1,6 +1,6 @@ -diff -up firefox-83.0/docshell/base/crashtests/crashtests.list.test firefox-83.0/docshell/base/crashtests/crashtests.list ---- firefox-83.0/docshell/base/crashtests/crashtests.list.test 2020-11-12 19:04:36.000000000 +0100 -+++ firefox-83.0/docshell/base/crashtests/crashtests.list 2020-11-19 10:30:26.127468382 +0100 +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 @@ -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,8 +9,9 @@ diff -up firefox-83.0/docshell/base/crashtests/crashtests.list.test firefox-83.0 load 1341657.html load 1584467.html load 1614211-1.html ---- firefox-83.0/dom/media/tests/crashtests/crashtests.list.test 2020-11-19 10:42:04.960128784 +0100 -+++ firefox-83.0/dom/media/tests/crashtests/crashtests.list 2020-11-19 10:42:21.508182030 +0100 +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 asserts-if(Android,0-2) load 1453030.html @@ -20,41 +21,32 @@ diff -up firefox-83.0/docshell/base/crashtests/crashtests.list.test firefox-83.0 load 1505957.html load 1509442.html load 1511130.html -diff -up firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.old firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py ---- firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.old 2020-11-19 11:15:59.150990819 +0100 -+++ firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py 2020-11-19 11:17:53.390337862 +0100 -@@ -62,16 +62,9 @@ class TestMarionette(MarionetteTestCase) +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 +@@ -69,15 +69,7 @@ class TestMarionette(MarionetteTestCase) def test_application_update_disabled(self): # Updates of the application should always be disabled by default - with self.marionette.using_context("chrome"): -- update_allowed = self.marionette.execute_script(""" +- update_allowed = self.marionette.execute_script( +- """ - let aus = Cc['@mozilla.org/updates/update-service;1'] - .getService(Ci.nsIApplicationUpdateService); - return aus.canCheckForUpdates; -- """) +- """ +- ) - + update_allowed = False self.assertFalse(update_allowed) -- - class TestContext(MarionetteTestCase): - - def setUp(self): -diff -up firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py.old firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py ---- firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py.old 2020-11-19 11:37:03.591683420 +0100 -+++ firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py 2020-11-19 11:37:18.730715053 +0100 -@@ -9,11 +9,8 @@ from six.moves.collections_abc import Mu - - from .utils import git - --try: -- from ..gitignore import gitignore --except ValueError: -- # relative import beyond toplevel throws *ValueError*! -- from gitignore import gitignore # type: ignore -+# relative import beyond toplevel throws *ValueError*! -+from gitignore import gitignore # type: ignore +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 +@@ -1,4 +1,5 @@ + # This file is the websocketprocess requirements.txt used with python 3. ++pyrsistent - MYPY = False + # needed by txws, and we'd like pip to get it from the local server before setuptools tries pypi + six diff --git a/firefox.spec b/firefox.spec index 071dc6a..eb54712 100644 --- a/firefox.spec +++ b/firefox.spec @@ -5,7 +5,7 @@ %global build_with_asan 0 %global run_firefox_tests 1 %global create_debuginfo 1 -%global system_nss 1 +%global system_nss 0 # There are still build problems on s390x, see # https://koji.fedoraproject.org/koji/taskinfo?taskID=55048351 @@ -120,13 +120,13 @@ Summary: Mozilla Firefox Web browser Name: firefox -Version: 83.0 -Release: 15%{?pre_tag}%{?dist} +Version: 84.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}-20201116.tar.xz +Source1: firefox-langpacks-%{version}%{?pre_version}-20201210.tar.xz %endif Source2: cbindgen-vendor.tar.xz Source10: firefox-mozconfig @@ -179,7 +179,6 @@ Patch224: mozilla-1170092.patch Patch226: rhbz-1354671.patch Patch227: firefox-locale-debug.patch Patch228: disable-openh264-download.patch -Patch229: firefox-mochitest.patch # Upstream patches Patch402: mozilla-1196777.patch @@ -187,11 +186,8 @@ Patch407: mozilla-1667096.patch Patch408: mozilla-1663844.patch Patch415: mozilla-1670333.patch Patch416: mozilla-1673202.patch -Patch417: mozilla-1673313.patch Patch418: mozilla-1556931-s390x-hidden-syms.patch -Patch419: mozilla-1885133.patch Patch420: mozilla-1678680.patch -Patch421: mozilla-1672139.patch # Upstream patches from mozbz#1672944 Patch450: pw1.patch @@ -201,8 +197,9 @@ Patch453: pw4.patch Patch454: pw5.patch Patch455: pw6.patch +Patch500: ffvpx.patch + #VA-API patches -Patch584: firefox-disable-ffvpx-with-vapi.patch Patch585: firefox-vaapi-extra-frames.patch # PGO/LTO patches @@ -401,7 +398,6 @@ This package contains results of tests executed during build. %endif %patch227 -p1 -b .locale-debug %patch228 -p1 -b .disable-openh264-download -%patch229 -p1 -b .firefox-mochitest %patch402 -p1 -b .1196777 %patch407 -p1 -b .1667096 @@ -410,21 +406,19 @@ This package contains results of tests executed during build. %if 0%{?fedora} > 33 || 0%{?eln} %patch416 -p1 -b .1673202 %endif -%patch417 -p1 -b .1673313 %patch418 -p1 -b .1556931-s390x-hidden-syms -%patch419 -p1 -b .1885133 -%patch450 -p1 -b .pw1 -%patch451 -p1 -b .pw2 -%patch452 -p1 -b .pw3 -%patch453 -p1 -b .pw4 -%patch454 -p1 -b .pw5 +#%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 .1672139 + +%patch500 -p1 -b .ffvpx # VA-API fixes -%patch584 -p1 -b .firefox-disable-ffvpx-with-vapi %patch585 -p1 -b .firefox-vaapi-extra-frames # PGO patches diff --git a/mozilla-1516803.patch b/mozilla-1516803.patch index f1f37f4..5053e51 100644 --- a/mozilla-1516803.patch +++ b/mozilla-1516803.patch @@ -1,16 +1,15 @@ -diff --git a/security/sandbox/linux/moz.build b/security/sandbox/linux/moz.build ---- a/security/sandbox/linux/moz.build -+++ b/security/sandbox/linux/moz.build -@@ -99,9 +99,8 @@ +diff -up firefox-84.0/security/sandbox/linux/moz.build.1516803 firefox-84.0/security/sandbox/linux/moz.build +--- firefox-84.0/security/sandbox/linux/moz.build.1516803 2020-12-10 16:17:55.425139545 +0100 ++++ firefox-84.0/security/sandbox/linux/moz.build 2020-12-10 16:29:21.945860841 +0100 +@@ -114,9 +114,8 @@ if CONFIG["CC_TYPE"] in ("clang", "gcc") # gcc lto likes to put the top level asm in syscall.cc in a different partition # from the function using it which breaks the build. Work around that by # forcing there to be only one partition. --for f in CONFIG['OS_CXXFLAGS']: -- if f.startswith('-flto') and CONFIG['CC_TYPE'] != 'clang': -- LDFLAGS += ['--param lto-partitions=1'] +-for f in CONFIG["OS_CXXFLAGS"]: +- if f.startswith("-flto") and CONFIG["CC_TYPE"] != "clang": +- LDFLAGS += ["--param lto-partitions=1"] +if CONFIG['CC_TYPE'] != 'clang': + LDFLAGS += ['--param', 'lto-partitions=1'] - DEFINES['NS_NO_XPCOM'] = True + DEFINES["NS_NO_XPCOM"] = True DisableStlWrapping() - diff --git a/mozilla-1663844.patch b/mozilla-1663844.patch index 3e55e80..6c2392f 100644 --- a/mozilla-1663844.patch +++ b/mozilla-1663844.patch @@ -1,7 +1,19 @@ -diff --git a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp ---- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp -+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp -@@ -86,7 +86,7 @@ bool GMPDecoderModule::SupportsMimeType( +diff -up firefox-84.0/dom/media/gmp/GMPSharedMemManager.h.1663844 firefox-84.0/dom/media/gmp/GMPSharedMemManager.h +--- firefox-84.0/dom/media/gmp/GMPSharedMemManager.h.1663844 2020-12-07 23:32:59.000000000 +0100 ++++ firefox-84.0/dom/media/gmp/GMPSharedMemManager.h 2020-12-10 12:59:39.287832851 +0100 +@@ -27,7 +27,7 @@ class GMPSharedMem { + // returned to the parent pool (which is not included). If more than + // this are needed, we presume the client has either crashed or hung + // (perhaps temporarily). +- static const uint32_t kGMPBufLimit = 20; ++ static const uint32_t kGMPBufLimit = 40; + + GMPSharedMem() { + for (size_t i = 0; i < sizeof(mGmpAllocated) / sizeof(mGmpAllocated[0]); +diff -up firefox-84.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp.1663844 firefox-84.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp +--- firefox-84.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp.1663844 2020-12-10 12:59:39.287832851 +0100 ++++ firefox-84.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp 2020-12-10 14:05:00.833685947 +0100 +@@ -82,7 +82,7 @@ bool GMPDecoderModule::SupportsMimeType( bool GMPDecoderModule::SupportsMimeType( const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { @@ -9,10 +21,10 @@ diff --git a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp b/dom/media/p + return MP4Decoder::IsH264(aMimeType); } - } // namespace mozilla -diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp ---- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp -+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp + /* static */ +diff -up firefox-84.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp.1663844 firefox-84.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp +--- firefox-84.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp.1663844 2020-12-08 00:35:04.000000000 +0100 ++++ firefox-84.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp 2020-12-10 12:59:39.287832851 +0100 @@ -67,6 +67,8 @@ void GMPVideoDecoder::Decoded(GMPVideoi4 RefPtr self = this; if (v) { @@ -22,15 +34,3 @@ diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp b/dom/media/pl } else { mDecodedData.Clear(); mDecodePromise.RejectIfExists( -diff -up firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h.oldd firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h ---- firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h.oldd 2020-10-12 18:19:09.158070701 +0200 -+++ firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h 2020-10-12 18:19:18.398109540 +0200 -@@ -27,7 +27,7 @@ class GMPSharedMem { - // returned to the parent pool (which is not included). If more than - // this are needed, we presume the client has either crashed or hung - // (perhaps temporarily). -- static const uint32_t kGMPBufLimit = 20; -+ static const uint32_t kGMPBufLimit = 40; - - GMPSharedMem() { - for (size_t i = 0; i < sizeof(mGmpAllocated) / sizeof(mGmpAllocated[0]); diff --git a/mozilla-1667096.patch b/mozilla-1667096.patch index 5d98fe2..cbe8aea 100644 --- a/mozilla-1667096.patch +++ b/mozilla-1667096.patch @@ -1,18 +1,6 @@ -changeset: 551978:40c95986d358 -tag: tip -parent: 551976:daadcfadb2f8 -user: stransky -date: Thu Sep 24 15:51:06 2020 +0200 -files: media/ffvpx/libavcodec/codec_list.c media/ffvpx/libavcodec/libfdk-aacdec.c media/ffvpx/libavcodec/moz.build toolkit/moz.configure -description: -Bug 1667096 Add libfdk-aacdec.c to bundled ffvpx and allow build Firefox with system fdk-aac-free library, r?jya - -Differential Revision: https://phabricator.services.mozilla.com/D91278 - - -diff --git a/media/ffvpx/libavcodec/codec_list.c b/media/ffvpx/libavcodec/codec_list.c ---- a/media/ffvpx/libavcodec/codec_list.c -+++ b/media/ffvpx/libavcodec/codec_list.c +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 @@ -11,4 +11,8 @@ static const AVCodec * const codec_list[ #if CONFIG_MP3_DECODER &ff_mp3_decoder, @@ -22,10 +10,9 @@ diff --git a/media/ffvpx/libavcodec/codec_list.c b/media/ffvpx/libavcodec/codec_ +#endif + NULL }; -diff --git a/media/ffvpx/libavcodec/libfdk-aacdec.c b/media/ffvpx/libavcodec/libfdk-aacdec.c -new file mode 100644 ---- /dev/null -+++ b/media/ffvpx/libavcodec/libfdk-aacdec.c +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 @@ -0,0 +1,409 @@ +/* + * AAC decoder wrapper @@ -436,9 +423,9 @@ new file mode 100644 + FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libfdk", +}; -diff --git a/media/ffvpx/libavcodec/moz.build b/media/ffvpx/libavcodec/moz.build ---- a/media/ffvpx/libavcodec/moz.build -+++ b/media/ffvpx/libavcodec/moz.build +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' ] @@ -452,12 +439,12 @@ diff --git a/media/ffvpx/libavcodec/moz.build b/media/ffvpx/libavcodec/moz.build if CONFIG['MOZ_LIBAV_FFT']: SOURCES += [ 'avfft.c', -diff --git a/toolkit/moz.configure b/toolkit/moz.configure ---- a/toolkit/moz.configure -+++ b/toolkit/moz.configure -@@ -1592,6 +1592,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 -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 +@@ -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) +# fdk aac support +option('--with-system-fdk-aac', @@ -470,4 +457,3 @@ diff --git a/toolkit/moz.configure b/toolkit/moz.configure # FFmpeg's ffvpx configuration # ============================================================== - diff --git a/mozilla-1670333.patch b/mozilla-1670333.patch index a7c7f8a..01dfb25 100644 --- a/mozilla-1670333.patch +++ b/mozilla-1670333.patch @@ -1,6 +1,6 @@ -diff -up firefox-82.0/dom/media/mp4/MP4Demuxer.cpp.1670333 firefox-82.0/dom/media/mp4/MP4Demuxer.cpp ---- firefox-82.0/dom/media/mp4/MP4Demuxer.cpp.1670333 2020-10-14 19:20:18.000000000 +0200 -+++ firefox-82.0/dom/media/mp4/MP4Demuxer.cpp 2020-10-19 20:56:38.362039524 +0200 +diff -up firefox-84.0/dom/media/mp4/MP4Demuxer.cpp.1670333 firefox-84.0/dom/media/mp4/MP4Demuxer.cpp +--- firefox-84.0/dom/media/mp4/MP4Demuxer.cpp.1670333 2020-12-07 23:32:59.000000000 +0100 ++++ firefox-84.0/dom/media/mp4/MP4Demuxer.cpp 2020-12-10 14:07:49.095266466 +0100 @@ -31,6 +31,8 @@ mozilla::LogModule* GetDemuxerLog() { re DDMOZ_LOG(gMediaDemuxerLog, mozilla::LogLevel::Debug, "::%s: " arg, \ __func__, ##__VA_ARGS__) @@ -23,10 +23,10 @@ diff -up firefox-82.0/dom/media/mp4/MP4Demuxer.cpp.1670333 firefox-82.0/dom/medi if (sample->mKeyframe != keyframe) { NS_WARNING(nsPrintfCString("Frame incorrectly marked as %skeyframe " "@ pts:%" PRId64 " dur:%" PRId64 -diff -up firefox-82.0/dom/media/platforms/PDMFactory.cpp.1670333 firefox-82.0/dom/media/platforms/PDMFactory.cpp ---- firefox-82.0/dom/media/platforms/PDMFactory.cpp.1670333 2020-10-14 19:20:18.000000000 +0200 -+++ firefox-82.0/dom/media/platforms/PDMFactory.cpp 2020-10-19 20:53:14.631214334 +0200 -@@ -49,6 +49,8 @@ +diff -up firefox-84.0/dom/media/platforms/PDMFactory.cpp.1670333 firefox-84.0/dom/media/platforms/PDMFactory.cpp +--- firefox-84.0/dom/media/platforms/PDMFactory.cpp.1670333 2020-12-10 14:07:49.095266466 +0100 ++++ firefox-84.0/dom/media/platforms/PDMFactory.cpp 2020-12-10 15:29:28.969006031 +0100 +@@ -52,6 +52,8 @@ #include @@ -34,35 +34,42 @@ diff -up firefox-82.0/dom/media/platforms/PDMFactory.cpp.1670333 firefox-82.0/do + namespace mozilla { - extern already_AddRefed CreateBlankDecoderModule(); -@@ -380,7 +382,8 @@ void PDMFactory::CreatePDMs() { + // Set on the main thread, in content processes before any PDMFactory will ever +@@ -522,9 +524,11 @@ void PDMFactory::CreateContentPDMs() { + } + #endif #ifdef MOZ_FFMPEG - if (StaticPrefs::media_ffmpeg_enabled()) { - m = FFmpegRuntimeLinker::CreateDecoderModule(); -- mFFmpegFailedToLoad = !StartupPDM(m); -+ mFFmpegUsed = StartupPDM(m); -+ mFFmpegFailedToLoad = !mFFmpegUsed; - } else { - mFFmpegFailedToLoad = false; +- if (StaticPrefs::media_ffmpeg_enabled() && +- !CreateAndStartupPDM()) { +- mFailureFlags += DecoderDoctorDiagnostics::Flags::FFmpegFailedToLoad; ++ if (StaticPrefs::media_ffmpeg_enabled()) { ++ mFFmpegUsed = CreateAndStartupPDM(); ++ if (!mFFmpegUsed) { ++ mFailureFlags += DecoderDoctorDiagnostics::Flags::FFmpegFailedToLoad; ++ } } -@@ -395,7 +398,8 @@ void PDMFactory::CreatePDMs() { - m = new AgnosticDecoderModule(); - StartupPDM(m); + #endif + #ifdef MOZ_WIDGET_ANDROID +@@ -536,8 +540,9 @@ void PDMFactory::CreateContentPDMs() { + + CreateAndStartupPDM(); -- if (StaticPrefs::media_gmp_decoder_enabled()) { -+ if (StaticPrefs::media_gmp_decoder_enabled() && !mFFmpegUsed) { +- if (StaticPrefs::media_gmp_decoder_enabled() && ++ if (StaticPrefs::media_gmp_decoder_enabled() && !mFFmpegUsed && + !CreateAndStartupPDM()) { + gUseKeyframeFromContainer = true; - m = new GMPDecoderModule(); - mGMPPDMFailedToStartup = !StartupPDM(m); - } else { -diff -up firefox-82.0/dom/media/platforms/PDMFactory.h.1670333 firefox-82.0/dom/media/platforms/PDMFactory.h ---- firefox-82.0/dom/media/platforms/PDMFactory.h.1670333 2020-10-14 19:20:18.000000000 +0200 -+++ firefox-82.0/dom/media/platforms/PDMFactory.h 2020-10-19 20:53:14.631214334 +0200 -@@ -70,6 +70,7 @@ class PDMFactory final { + mFailureFlags += DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup; + } + } +diff -up firefox-84.0/dom/media/platforms/PDMFactory.h.1670333 firefox-84.0/dom/media/platforms/PDMFactory.h +--- firefox-84.0/dom/media/platforms/PDMFactory.h.1670333 2020-12-10 14:07:49.096266493 +0100 ++++ firefox-84.0/dom/media/platforms/PDMFactory.h 2020-12-10 15:27:42.363034881 +0100 +@@ -116,6 +116,8 @@ class PDMFactory final { - bool mWMFFailedToLoad = false; - bool mFFmpegFailedToLoad = false; -+ bool mFFmpegUsed = false; - bool mGMPPDMFailedToStartup = false; + DecoderDoctorDiagnostics::FlagsSet mFailureFlags; ++ bool mFFmpegUsed = false; ++ friend class RemoteVideoDecoderParent; + static void EnsureInit(); + template diff --git a/pgo.patch b/pgo.patch index c4a6bf4..f6b4953 100644 --- a/pgo.patch +++ b/pgo.patch @@ -1,24 +1,7 @@ -diff -up firefox-81.0.1/build/moz.configure/lto-pgo.configure.pgo firefox-81.0.1/build/moz.configure/lto-pgo.configure ---- firefox-81.0.1/build/moz.configure/lto-pgo.configure.pgo 2020-09-30 19:41:10.000000000 +0200 -+++ firefox-81.0.1/build/moz.configure/lto-pgo.configure 2020-10-07 09:16:44.071786956 +0200 -@@ -69,12 +69,14 @@ set_config('PGO_PROFILE_PATH', pgo_profi - @imports(_from='__builtin__', _import='min') - def pgo_flags(compiler, profdata, target_is_windows): - if compiler.type == 'gcc': -+ #profile_use = '-fprofile-use=$(topobjdir)' -+ profile_use = '-fprofile-use' - return namespace( - gen_cflags=['-fprofile-generate'], - gen_ldflags=['-fprofile-generate'], -- use_cflags=['-fprofile-use', '-fprofile-correction', -+ use_cflags=[profile_use, '-fprofile-correction', - '-Wcoverage-mismatch'], -- use_ldflags=['-fprofile-use'], -+ use_ldflags=[profile_use], - ) - - if compiler.type in ('clang-cl', 'clang'): -@@ -192,13 +194,13 @@ def lto(value, c_compiler, ld64_known_go +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 cflags.append("-flto") ldflags.append("-flto") else: @@ -26,17 +9,17 @@ diff -up firefox-81.0.1/build/moz.configure/lto-pgo.configure.pgo firefox-81.0.1 - ldflags.append("-flto=thin") + cflags.append("-flto") + ldflags.append("-flto") - elif c_compiler.type == 'clang-cl': - if len(value) and value[0].lower() == 'full': + elif c_compiler.type == "clang-cl": + if len(value) and value[0].lower() == "full": cflags.append("-flto") else: - cflags.append("-flto=thin") + cflags.append("-flto") # 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"); -@@ -232,7 +234,7 @@ def lto(value, c_compiler, ld64_known_go - if len(value) and value[0].lower() == 'full': + 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") @@ -44,9 +27,9 @@ diff -up firefox-81.0.1/build/moz.configure/lto-pgo.configure.pgo firefox-81.0.1 cflags.append("-flifetime-dse=1") ldflags.append("-flto=%s" % num_cores) -diff -up firefox-81.0.1/build/pgo/profileserver.py.pgo firefox-81.0.1/build/pgo/profileserver.py ---- firefox-81.0.1/build/pgo/profileserver.py.pgo 2020-09-30 19:41:10.000000000 +0200 -+++ firefox-81.0.1/build/pgo/profileserver.py 2020-10-07 09:16:44.071786956 +0200 +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 @@ -11,7 +11,7 @@ import glob import subprocess @@ -56,11 +39,11 @@ diff -up firefox-81.0.1/build/pgo/profileserver.py.pgo firefox-81.0.1/build/pgo/ from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences -@@ -84,9 +84,22 @@ if __name__ == '__main__': - port=PORT, - options='primary,privileged') +@@ -87,9 +87,22 @@ if __name__ == "__main__": + locations = ServerLocations() + locations.add_host(host="127.0.0.1", port=PORT, options="primary,privileged") -- old_profraw_files = glob.glob('*.profraw') +- old_profraw_files = glob.glob("*.profraw") - for f in old_profraw_files: - os.remove(f) + using_gcc = False @@ -82,21 +65,20 @@ diff -up firefox-81.0.1/build/pgo/profileserver.py.pgo firefox-81.0.1/build/pgo/ with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile -@@ -191,6 +204,11 @@ if __name__ == '__main__': +@@ -212,6 +225,10 @@ if __name__ == "__main__": print("Firefox exited successfully, but produced a crashreport") sys.exit(1) -+ + print('Copying profile data....') + os.system('pwd'); + os.system('tar cf profdata.tar.gz `find . -name "*.gcda"`; cd ..; tar xf instrumented/profdata.tar.gz;'); + - llvm_profdata = env.get('LLVM_PROFDATA') + llvm_profdata = env.get("LLVM_PROFDATA") if llvm_profdata: - profraw_files = glob.glob('*.profraw') -diff -up firefox-81.0.1/build/unix/mozconfig.unix.pgo firefox-81.0.1/build/unix/mozconfig.unix ---- firefox-81.0.1/build/unix/mozconfig.unix.pgo 2020-09-30 19:41:10.000000000 +0200 -+++ firefox-81.0.1/build/unix/mozconfig.unix 2020-10-07 09:16:44.071786956 +0200 + 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 @@ -6,6 +6,15 @@ if [ -n "$FORCE_GCC" ]; then CC="$MOZ_FETCHES_DIR/gcc/bin/gcc" CXX="$MOZ_FETCHES_DIR/gcc/bin/g++" @@ -113,32 +95,33 @@ diff -up firefox-81.0.1/build/unix/mozconfig.unix.pgo firefox-81.0.1/build/unix/ # 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-81.0.1/extensions/spellcheck/src/moz.build.pgo firefox-81.0.1/extensions/spellcheck/src/moz.build ---- firefox-81.0.1/extensions/spellcheck/src/moz.build.pgo 2020-09-30 19:41:17.000000000 +0200 -+++ firefox-81.0.1/extensions/spellcheck/src/moz.build 2020-10-07 09:16:44.071786956 +0200 +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 @@ -31,3 +31,5 @@ EXPORTS.mozilla += [ - if CONFIG['CC_TYPE'] in ('clang', 'gcc'): - CXXFLAGS += ['-Wno-error=shadow'] + if CONFIG["CC_TYPE"] in ("clang", "gcc"): + CXXFLAGS += ["-Wno-error=shadow"] + +CXXFLAGS += ['-fno-devirtualize'] -\ No newline at end of file -diff -up firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py.pgo firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py ---- firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py.pgo 2020-09-30 19:41:46.000000000 +0200 -+++ firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py 2020-10-07 09:16:44.071786956 +0200 -@@ -108,7 +108,8 @@ class Build(MachCommandBase): +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') +- 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_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-81.0.1/toolkit/components/terminator/nsTerminator.cpp.pgo firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp ---- firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp.pgo 2020-10-07 09:22:26.698243673 +0200 -+++ firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp 2020-10-07 09:22:43.026312999 +0200 +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() { } #endif diff --git a/print_results b/print_results index c4c60ef..d0bb535 100755 --- a/print_results +++ b/print_results @@ -4,17 +4,7 @@ export TEST_DIR="test_results" echo "Test results" -echo "SW" +echo "Basic compositor" ./print_subtest "test_results" "" -echo "WR" +echo "WebRender" ./print_subtest "test_results" "-wr" -echo "General" - -UNPASS=`grep "cppunittests INFO | Passed:" $TEST_DIR/cppunittest | cut -d ' ' -f 5` -UNFAIL=`grep "cppunittests INFO | Failed:" $TEST_DIR/cppunittest | cut -d ' ' -f 5` -echo "CPP UNIT: PASSED: $UNPASS FAILED: $UNFAIL" - -JSPASS=`grep "TEST-PASS" $TEST_DIR/jsapi | wc -l` -echo "JSAPI: PASSED: $JSPASS" - -echo "JStests: "`tail -n 1 $TEST_DIR/jstests` diff --git a/print_subtest b/print_subtest index 2870188..6657757 100755 --- a/print_subtest +++ b/print_subtest @@ -14,8 +14,8 @@ MARSKIP=`grep --text "Skipped:" $TEST_DIR/marionette$TEST_FLAVOUR | cut -d ' ' - MARFAILED=`grep --text "Unexpected results:" $TEST_DIR/marionette$TEST_FLAVOUR | cut -d ' ' -f 3` echo "Marionette: PASSED: $MARPASS FAILED: $MARSKIP Known issues: $MARFAILED" -XPCPASS=`grep --text "INFO INFO | Passed:" $TEST_DIR/xpcshell$TEST_FLAVOUR | cut -d ' ' -f 7` -XPCFAIL=`grep --text "INFO INFO | Failed:" $TEST_DIR/xpcshell$TEST_FLAVOUR | cut -d ' ' -f 7` +XPCPASS=`grep --text "Expected results:" $TEST_DIR/xpcshell$TEST_FLAVOUR | cut -d ' ' -f 3` +XPCFAIL=`grep --text "Unexpected results:" $TEST_DIR/xpcshell$TEST_FLAVOUR | cut -d ' ' -f 3` echo "XPCShell: PASSED: $XPCPASS FAILED: $XPCFAIL" CRPASS=`grep "REFTEST INFO | Successful:" $TEST_DIR/crashtest$TEST_FLAVOUR | cut -d ' ' -f 5` diff --git a/run-tests b/run-tests index dcfe318..f5f5056 100755 --- a/run-tests +++ b/run-tests @@ -31,11 +31,5 @@ xvfb-run -s "$X_PARAMS" ./mach marionette-test $TEST_PARAMS >& $TEST_DIR/marione xvfb-run -s "$X_PARAMS" ./mach reftest $TEST_PARAMS --run-tests-in-parallel >& $TEST_DIR/reftest$TEST_FLAVOUR ./mach xpcshell-test $TEST_PARAMS 2>&1 | cat - > $TEST_DIR/xpcshell$TEST_FLAVOUR -# Rest -export TEST_DIR="test" -objdir/dist/bin/jsapi-tests >& $TEST_DIR/jsapi -./mach cppunittest >& $TEST_DIR/cppunittest -./mach jstests >& $TEST_DIR/jstests - rm -f objdir/dist/bin/certutil rm -f objdir/dist/bin/pk12util diff --git a/sources b/sources index 32b62ca..049b0ec 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ SHA512 (cbindgen-vendor.tar.xz) = 3c925c5523246b7dfbcb4ce563483d5b45315a06dc90f2cf07cddef0c263dd15b410afbbe4d86594de96a308e93be3b27ffec01f5f759a42ecba3cc983b1677f -SHA512 (firefox-83.0.source.tar.xz) = 4ac49cefed278d1f898907bbedacf81ea4bb4e5784f567d4c0971d9cbc2cf4a2e4472de81a7ded620bc3a516bc972d600b516b7674319cdfc9734c3824a9a2f6 -SHA512 (firefox-langpacks-83.0-20201116.tar.xz) = 0d26660a7f09481e82d8d88ac43917001301d422a94dc48d3913dff92805f100221ca6db15fea05e895221efe5a9d74c07780a671aebc26a69d7a588e1cd423d SHA512 (mochitest-python.tar.gz) = 7f357cb8bd93d64be5cb75819a8a813d2f8f217ff25f0df8c3190910744132405d45797b3900775a44b554f5c70cf2682809c9e7a686ca131fddcd81e98028d9 +SHA512 (firefox-84.0.source.tar.xz) = 16e3219e28d0807f53c9713e7efaea56cea65bb02959680bed13db4bd9331d9651de5c80c70c928a41b3db9d5471d7b38fa2d88f3e8017565ca7ea79ed0527e9 +SHA512 (firefox-langpacks-84.0-20201210.tar.xz) = 3f836e854425ad9911cc02d5e82f88b904ecbd63357caa677a35bd226d475a161bcbb1647bfce17fed3ccb719dd95340cc7b0b6f7478c87d7c0b45c9493218a5