Bug 1660336 Provide libva wrapper to run Firefox on systems without libva installed, r=jya
authorstransky <stransky@redhat.com>
Wed, 02 Dec 2020 10:30:21 +0000
changeset 559037 708c5d0699366502304bf3b8842adabc9b4cf0c4
parent 559036 f60e1ba03fbfbf41b47b9b1feb738de8a33938dc
child 559038 9d4893cc2f992294be0a7989e9f1c67730143154
push id37997
push userbtara@mozilla.com
push dateWed, 02 Dec 2020 21:42:50 +0000
treeherdermozilla-central@575b67d9c9b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1660336
milestone85.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1660336 Provide libva wrapper to run Firefox on systems without libva installed, r=jya Differential Revision: https://phabricator.services.mozilla.com/D94650
media/ffvpx/moz.build
media/ffvpx/mozva/moz.build
media/ffvpx/mozva/mozva.cpp
--- a/media/ffvpx/moz.build
+++ b/media/ffvpx/moz.build
@@ -6,8 +6,13 @@
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "Audio/Video: Playback")
 
 DIRS += [
     'libavutil',
     'libavcodec'
 ]
+
+if CONFIG['MOZ_WAYLAND']:
+    DIRS += [
+        'mozva',
+    ]
new file mode 100644
--- /dev/null
+++ b/media/ffvpx/mozva/moz.build
@@ -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.cpp',
+]
+
+LOCAL_INCLUDES += ['/media/ffvpx']
+
+Library('mozva')
new file mode 100644
--- /dev/null
+++ b/media/ffvpx/mozva/mozva.cpp
@@ -0,0 +1,477 @@
+/* -*- 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 <va/va.h>
+#pragma GCC visibility pop
+
+#include "mozilla/Types.h"
+#include "mozilla/ScopeExit.h"
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#define GET_FUNC(func, lib)                                   \
+    func##Fn =                                                \
+      (decltype(func##Fn))dlsym(lib, #func)                   \
+
+#define IS_FUNC_LOADED(func)                                  \
+    (func##Fn != nullptr)                                     \
+
+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);
+
+bool LoadVALibrary() {
+  static bool vaLibraryLoaded = []() {
+    static void* sVALib = dlopen("libva.so.2", RTLD_LAZY);
+    if (!sVALib) {
+      return false;
+    }
+    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);
+
+    return (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));
+  }();
+  return vaLibraryLoaded;
+}
+
+#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 nullptr;
+}
+
+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