summarylogtreecommitdiffstats
path: root/enable-vaapi.patch
blob: d241aa435372abdf2fd88f6ab656024719f4a0d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
From 53b93dfe87fd10cced5d2a2a63072dfc7a2af6e4 Mon Sep 17 00:00:00 2001
From: Daniel Charles <daniel.charles@intel.com>
Date: Fri, 28 Jul 2017 16:31:47 -0700
Subject: [PATCH] Enable VAVDA, VAVEA and VAJDA on linux with VAAPI only

This patch contains all the changes necessary to use VA-API along with
vaapi-driver to run all media use cases supported with hardware acceleration.

It is intended to remain as experimental accessible from chrome://flags on linux.
It requires libva/intel-vaapi-driver to be installed on the system path where
chrome is executed.  Other drivers could be tested if available. Flags are
kept independent for linux, where this feature has to be enabled before
actually using it.  This should not change how other OSes use the flags
already, the new flags will show at the buttom on the section of unavailable
experiments

The changes cover a range of compiler pre-processor flags to enable the stack.
It moves the presandbox operations to the vaapi_wrapper class as the hook function
is available there. vaInit will open driver on the correct installed folder.

chrome flags consolidtation into only two flags for linux.  Mjpeg and accelerated
video are used.  The other flags are kept for ChromeOS and other OSes.

Developer testing was made on skylake hardware, ChromeOS and Ubuntu.

BUG=NONE
TEST="subjective testing with VAVDA,VAVEA and VAJDA, autotest for encoder"
TEST="and decoder hardware accelerated"
TEST="have libva/intel-vaapi-driver installed and not installed in the system"
TEST="repeat on different hardware families"
R=posciak@chromium.org
R=kcwu@chromium.org

Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Ifbbf5c9e5221a8b5733fc6d4d0cf984a1f103171
Signed-off-by: Daniel Charles <daniel.charles@intel.com>
---

Index: dev/chrome/browser/about_flags.cc
===================================================================
--- dev.orig/chrome/browser/about_flags.cc
+++ dev/chrome/browser/about_flags.cc
@@ -1420,7 +1420,7 @@ const FeatureEntry kFeatureEntries[] = {
         "disable-accelerated-video-decode",
         flag_descriptions::kAcceleratedVideoDecodeName,
         flag_descriptions::kAcceleratedVideoDecodeDescription,
-        kOsMac | kOsWin | kOsCrOS | kOsAndroid,
+        kOsAll,
         SINGLE_DISABLE_VALUE_TYPE(switches::kDisableAcceleratedVideoDecode),
     },
     {
@@ -1867,10 +1867,10 @@ const FeatureEntry kFeatureEntries[] = {
      FEATURE_VALUE_TYPE(service_manager::features::kXRSandbox)},
 #endif  // ENABLE_ISOLATED_XR_SERVICE
 #endif  // ENABLE_VR
-#if defined(OS_CHROMEOS)
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
     {"disable-accelerated-mjpeg-decode",
      flag_descriptions::kAcceleratedMjpegDecodeName,
-     flag_descriptions::kAcceleratedMjpegDecodeDescription, kOsCrOS,
+     flag_descriptions::kAcceleratedMjpegDecodeDescription, kOsCrOS | kOsLinux,
      SINGLE_DISABLE_VALUE_TYPE(switches::kDisableAcceleratedMjpegDecode)},
 #endif  // OS_CHROMEOS
     {"system-keyboard-lock", flag_descriptions::kSystemKeyboardLockName,
Index: dev/chrome/browser/flag_descriptions.cc
===================================================================
--- dev.orig/chrome/browser/flag_descriptions.cc
+++ dev/chrome/browser/flag_descriptions.cc
@@ -2789,9 +2789,7 @@ const char kMacSystemMediaPermissionsInf
 
 #endif
 
-// Chrome OS -------------------------------------------------------------------
-
-#if defined(OS_CHROMEOS)
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
 
 const char kAcceleratedMjpegDecodeName[] =
     "Hardware-accelerated mjpeg decode for captured frame";
@@ -2799,6 +2797,12 @@ const char kAcceleratedMjpegDecodeDescri
     "Enable hardware-accelerated mjpeg decode for captured frame where "
     "available.";
 
+#endif
+
+// Chrome OS -------------------------------------------------------------------
+
+#if defined(OS_CHROMEOS)
+
 const char kAppServiceAshName[] = "App Service Ash";
 const char kAppServiceAshDescription[] =
     "Use the App Service to provide data to the Ash UI, such as the shelf and "
Index: dev/chrome/browser/flag_descriptions.h
===================================================================
--- dev.orig/chrome/browser/flag_descriptions.h
+++ dev/chrome/browser/flag_descriptions.h
@@ -1659,13 +1659,17 @@ extern const char kPermissionPromptPersi
 
 #endif  // defined(OS_MACOSX)
 
-// Chrome OS ------------------------------------------------------------------
-
-#if defined(OS_CHROMEOS)
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
 
 extern const char kAcceleratedMjpegDecodeName[];
 extern const char kAcceleratedMjpegDecodeDescription[];
 
+#endif
+
+// Chrome OS ------------------------------------------------------------------
+
+#if defined(OS_CHROMEOS)
+
 extern const char kAggregatedMlAppRankingName[];
 extern const char kAggregatedMlAppRankingDescription[];
 
Index: dev/content/gpu/BUILD.gn
===================================================================
--- dev.orig/content/gpu/BUILD.gn
+++ dev/content/gpu/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//gpu/vulkan/features.gni")
 import("//media/media_options.gni")
+import("//media/gpu/args.gni")
 import("//ui/ozone/ozone.gni")
 
 # See //content/BUILD.gn for how this works.
@@ -128,4 +129,8 @@ target(link_target_type, "gpu_sources")
       (!is_chromecast || is_cast_desktop_build)) {
     configs += [ "//build/config/linux/dri" ]
   }
+
+  if (is_desktop_linux && use_vaapi) {
+    public_configs = [ "//build/config/linux/libva" ]
+  }
 }
Index: dev/gpu/config/software_rendering_list.json
===================================================================
--- dev.orig/gpu/config/software_rendering_list.json
+++ dev/gpu/config/software_rendering_list.json
@@ -369,17 +369,6 @@
       ]
     },
     {
-      "id": 48,
-      "description": "Accelerated video decode is unavailable on Linux",
-      "cr_bugs": [137247],
-      "os": {
-        "type": "linux"
-      },
-      "features": [
-        "accelerated_video_decode"
-      ]
-    },
-    {
       "id": 50,
       "description": "Disable VMware software renderer on older Mesa",
       "cr_bugs": [145531, 332596, 571899, 629434],
Index: dev/media/base/media_switches.cc
===================================================================
--- dev.orig/media/base/media_switches.cc
+++ dev/media/base/media_switches.cc
@@ -528,7 +528,7 @@ bool IsVideoCaptureAcceleratedJpegDecodi
           switches::kUseFakeMjpegDecodeAccelerator)) {
     return true;
   }
-#if defined(OS_CHROMEOS)
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
   return true;
 #endif
   return false;
Index: dev/media/filters/BUILD.gn
===================================================================
--- dev.orig/media/filters/BUILD.gn
+++ dev/media/filters/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/jumbo.gni")
 import("//media/media_options.gni")
 import("//third_party/libaom/options.gni")
+import("//media/gpu/args.gni")
 
 jumbo_source_set("filters") {
   # Do not expand the visibility here without double-checking with OWNERS, this
@@ -196,7 +197,7 @@ jumbo_source_set("filters") {
     deps += [ "//media/base/android" ]
   }
 
-  if (current_cpu != "arm" && is_linux) {
+  if (use_vaapi) {
     sources += [
       "h264_bitstream_buffer.cc",
       "h264_bitstream_buffer.h",
Index: dev/media/gpu/BUILD.gn
===================================================================
--- dev.orig/media/gpu/BUILD.gn
+++ dev/media/gpu/BUILD.gn
@@ -521,6 +521,7 @@ if (use_v4l2_codec || use_vaapi || is_ma
     if (use_ozone) {
       deps += [ "//ui/ozone" ]
     }
+    public_configs = [ "//build/config/linux/libva" ]
   }
 }
 
Index: dev/media/gpu/gpu_video_decode_accelerator_factory.cc
===================================================================
--- dev.orig/media/gpu/gpu_video_decode_accelerator_factory.cc
+++ dev/media/gpu/gpu_video_decode_accelerator_factory.cc
@@ -171,6 +171,8 @@ GpuVideoDecodeAcceleratorFactory::Create
     vda = (this->*create_vda_function)(workarounds, gpu_preferences, media_log);
     if (vda && vda->Initialize(config, client))
       return vda;
+    else
+      LOG(ERROR) << "Initialization of one or more VDAs failed.";
   }
 
   return nullptr;
@@ -229,6 +231,7 @@ GpuVideoDecodeAcceleratorFactory::Create
     const gpu::GpuDriverBugWorkarounds& workarounds,
     const gpu::GpuPreferences& gpu_preferences,
     MediaLog* media_log) const {
+  LOG(WARNING) << "Initializing VAAPI VDA.";
   std::unique_ptr<VideoDecodeAccelerator> decoder;
   decoder.reset(new VaapiVideoDecodeAccelerator(make_context_current_cb_,
                                                 bind_image_cb_));
Index: dev/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
===================================================================
--- dev.orig/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
+++ dev/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -381,6 +381,7 @@ bool GpuVideoDecodeAccelerator::Initiali
     LOG(ERROR) << "Failed creating the VDA factory";
     return false;
   }
+  LOG(WARNING) << "Created the VDA factory";
 
   const gpu::GpuDriverBugWorkarounds& gpu_workarounds =
       stub_->channel()->gpu_channel_manager()->gpu_driver_bug_workarounds();
@@ -394,6 +395,7 @@ bool GpuVideoDecodeAccelerator::Initiali
                << (config.is_encrypted() ? " with encryption" : "");
     return false;
   }
+  LOG(WARNING) << "Created VDA";
 
   // Attempt to set up performing decoding tasks on IO thread, if supported by
   // the VDA.
Index: dev/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
===================================================================
--- dev.orig/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
+++ dev/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -64,6 +64,7 @@ void ReportToUMA(VAVDADecoderFailure fai
                             VAVDA_DECODER_FAILURES_MAX + 1);
 }
 
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
 // Returns true if the CPU is an Intel Gemini Lake or later (including Kaby
 // Lake) Cpu platform id's are referenced from the following file in kernel
 // source arch/x86/include/asm/intel-family.h
@@ -76,6 +77,7 @@ bool IsGeminiLakeOrLater() {
       cpuid.model() >= kGeminiLakeModelId;
   return is_geminilake_or_later;
 }
+#endif
 
 }  // namespace
 
@@ -635,6 +637,10 @@ void VaapiVideoDecodeAccelerator::Assign
   va_surface_format_ = GetVaFormatForVideoCodecProfile(profile_);
   std::vector<VASurfaceID> va_surface_ids;
 
+  // Nvidia doesn't support VAProfileNone, so don't try to create a temporary
+  // copy buffer there. It's not needed anyways for hardware video decoding
+  // to work.
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
   // If we aren't in BufferAllocationMode::kNone, we have to allocate a
   // |vpp_vaapi_wrapper_| for VaapiPicture to DownloadFromSurface() the VA's
   // internal decoded frame.
@@ -648,6 +654,7 @@ void VaapiVideoDecodeAccelerator::Assign
       NotifyError(PLATFORM_FAILURE);
     }
   }
+#endif
 
   for (size_t i = 0; i < buffers.size(); ++i) {
     DCHECK(requested_pic_size_ == buffers[i].size());
@@ -656,9 +663,13 @@ void VaapiVideoDecodeAccelerator::Assign
     PictureBuffer buffer = buffers[i];
     buffer.set_size(requested_pic_size_);
     std::unique_ptr<VaapiPicture> picture = vaapi_picture_factory_->Create(
+#if defined(OS_LINUX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+            vaapi_wrapper_,
+#else
         (buffer_allocation_mode_ == BufferAllocationMode::kNone)
             ? vaapi_wrapper_
             : vpp_vaapi_wrapper_,
+#endif
         make_context_current_cb_, bind_image_cb_, buffer);
     RETURN_AND_NOTIFY_ON_FAILURE(picture, "Failed creating a VaapiPicture",
                                  PLATFORM_FAILURE, );
@@ -1077,6 +1088,9 @@ VaapiVideoDecodeAccelerator::GetSupporte
 
 VaapiVideoDecodeAccelerator::BufferAllocationMode
 VaapiVideoDecodeAccelerator::DecideBufferAllocationMode() {
+#if defined(OS_LINUX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+  return BufferAllocationMode::kNormal;
+#else
   // TODO(crbug.com/912295): Enable a better BufferAllocationMode for IMPORT
   // |output_mode_| as well.
   if (output_mode_ == VideoDecodeAccelerator::Config::OutputMode::IMPORT)
@@ -1109,6 +1123,7 @@ VaapiVideoDecodeAccelerator::DecideBuffe
     return BufferAllocationMode::kReduced;
 
   return BufferAllocationMode::kSuperReduced;
+#endif
 }
 
 bool VaapiVideoDecodeAccelerator::IsBufferAllocationModeReducedOrSuperReduced()
Index: dev/media/gpu/vaapi/vaapi_wrapper.cc
===================================================================
--- dev.orig/media/gpu/vaapi/vaapi_wrapper.cc
+++ dev/media/gpu/vaapi/vaapi_wrapper.cc
@@ -250,6 +250,11 @@ void VADisplayState::PreSandboxInitializ
       base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
   if (drm_file.IsValid())
     VADisplayState::Get()->SetDrmFd(drm_file.GetPlatformFile());
+
+  const char kNvidiaPath[] = "/dev/dri/nvidiactl";
+  base::File nvidia_file = base::File(
+      base::FilePath::FromUTF8Unsafe(kNvidiaPath),
+      base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
 }
 
 VADisplayState::VADisplayState()
@@ -277,10 +282,6 @@ bool VADisplayState::Initialize() {
 }
 
 bool VADisplayState::InitializeOnce() {
-  static_assert(
-      VA_MAJOR_VERSION >= 2 || (VA_MAJOR_VERSION == 1 && VA_MINOR_VERSION >= 1),
-      "Requires VA-API >= 1.1.0");
-
   switch (gl::GetGLImplementation()) {
     case gl::kGLImplementationEGLGLES2:
       va_display_ = vaGetDisplayDRM(drm_fd_.get());
@@ -287,10 +289,10 @@ bool VADisplayState::InitializeOnce() {
     case gl::kGLImplementationDesktopGL:
 #if defined(USE_X11)
       va_display_ = vaGetDisplay(gfx::GetXDisplay());
-#else
-      LOG(WARNING) << "VAAPI video acceleration not available without "
-                      "DesktopGL (GLX).";
+      if (vaDisplayIsValid(va_display_))
+        break;
 #endif  // USE_X11
+      va_display_ = vaGetDisplayDRM(drm_fd_.get());
       break;
     // Cannot infer platform from GL, try all available displays
     case gl::kGLImplementationNone:
@@ -323,8 +325,19 @@ bool VADisplayState::InitializeOnce() {
   int major_version, minor_version;
   VAStatus va_res = vaInitialize(va_display_, &major_version, &minor_version);
   if (va_res != VA_STATUS_SUCCESS) {
-    LOG(ERROR) << "vaInitialize failed: " << vaErrorStr(va_res);
-    return false;
+    LOG(ERROR) << "vaInitialize failed (ignore if using Wayland desktop environment): " << vaErrorStr(va_res);
+    va_display_ = vaGetDisplayDRM(drm_fd_.get());
+    if (!vaDisplayIsValid(va_display_)) {
+      LOG(ERROR) << "Could not get a valid DRM VA display";
+      return false;
+    }
+    va_res = vaInitialize(va_display_, &major_version, &minor_version);
+    if (va_res != VA_STATUS_SUCCESS) {
+      LOG(ERROR) << "vaInitialize failed using DRM: " << vaErrorStr(va_res);
+      return false;
+    } else {
+      LOG(WARNING) << "vaInitialize succeeded for DRM";
+    }
   }
 
   va_initialized_ = true;
@@ -332,7 +345,7 @@ bool VADisplayState::InitializeOnce() {
   va_vendor_string_ = vaQueryVendorString(va_display_);
   DLOG_IF(WARNING, va_vendor_string_.empty())
       << "Vendor string empty or error reading.";
-  DVLOG(1) << "VAAPI version: " << major_version << "." << minor_version << " "
+  VLOG(1) << "VAAPI version: " << major_version << "." << minor_version << " "
            << va_vendor_string_;
 
   // The VAAPI version is determined from what is loaded on the system by
@@ -665,7 +678,7 @@ bool VASupportedProfiles::AreAttribsSupp
     if (attribs[i].type != required_attribs[i].type ||
         (attribs[i].value & required_attribs[i].value) !=
             required_attribs[i].value) {
-      DVLOG(1) << "Unsupported value " << required_attribs[i].value
+      VLOG(1) << "Unsupported value " << required_attribs[i].value
                << " for attribute type " << required_attribs[i].type;
       return false;
     }