vaapi_wrapper.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. //
  5. // This file contains an implementation of VaapiWrapper, used by
  6. // VaapiVideoDecodeAccelerator and VaapiH264Decoder for decode,
  7. // and VaapiVideoEncodeAccelerator for encode, to interface
  8. // with libva (VA-API library for hardware video codec).
  9. #ifndef MEDIA_GPU_VAAPI_VAAPI_WRAPPER_H_
  10. #define MEDIA_GPU_VAAPI_VAAPI_WRAPPER_H_
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <va/va.h>
  14. #include <map>
  15. #include <memory>
  16. #include <set>
  17. #include <vector>
  18. #include "base/files/file.h"
  19. #include "base/gtest_prod_util.h"
  20. #include "base/memory/raw_ptr.h"
  21. #include "base/memory/ref_counted.h"
  22. #include "base/memory/scoped_refptr.h"
  23. #include "base/synchronization/lock.h"
  24. #include "base/thread_annotations.h"
  25. #include "build/chromeos_buildflags.h"
  26. #include "media/gpu/chromeos/fourcc.h"
  27. #include "media/gpu/media_gpu_export.h"
  28. #include "media/gpu/vaapi/va_surface.h"
  29. #include "media/gpu/vaapi/vaapi_utils.h"
  30. #include "media/video/video_decode_accelerator.h"
  31. #include "media/video/video_encode_accelerator.h"
  32. #include "third_party/abseil-cpp/absl/types/optional.h"
  33. #include "ui/gfx/geometry/size.h"
  34. #if BUILDFLAG(USE_VAAPI_X11)
  35. #include "ui/gfx/x/xproto.h" // nogncheck
  36. #endif // BUILDFLAG(USE_VAAPI_X11)
  37. namespace gfx {
  38. enum class BufferFormat;
  39. class NativePixmap;
  40. class NativePixmapDmaBuf;
  41. class Rect;
  42. }
  43. #define MAYBE_ASSERT_ACQUIRED(lock) \
  44. if (lock) \
  45. lock->AssertAcquired()
  46. namespace media {
  47. constexpr unsigned int kInvalidVaRtFormat = 0u;
  48. class VideoFrame;
  49. // Enum, function and callback type to allow VaapiWrapper to log errors in VA
  50. // function calls executed on behalf of its owner. |histogram_name| is prebound
  51. // to allow for disinguishing such owners.
  52. enum class VaapiFunctions;
  53. void ReportVaapiErrorToUMA(const std::string& histogram_name,
  54. VaapiFunctions value);
  55. using ReportErrorToUMACB = base::RepeatingCallback<void(VaapiFunctions)>;
  56. // This struct holds a NativePixmapDmaBuf, usually the result of exporting a VA
  57. // surface, and some associated size information needed to tell clients about
  58. // the underlying buffer.
  59. struct NativePixmapAndSizeInfo {
  60. NativePixmapAndSizeInfo();
  61. ~NativePixmapAndSizeInfo();
  62. // The VA-API internal buffer dimensions, which may be different than the
  63. // dimensions requested at the time of creation of the surface (but always
  64. // larger than or equal to those). This can be used for validation in, e.g.,
  65. // testing.
  66. gfx::Size va_surface_resolution;
  67. // The size of the underlying Buffer Object. A use case for this is when an
  68. // image decode is requested and the caller needs to know the size of the
  69. // allocated buffer for caching purposes.
  70. size_t byte_size = 0u;
  71. // Contains the information needed to use the surface in a graphics API,
  72. // including the visible size (|pixmap|->GetBufferSize()) which should be no
  73. // larger than |va_surface_resolution|.
  74. scoped_refptr<gfx::NativePixmapDmaBuf> pixmap;
  75. };
  76. enum class VAImplementation {
  77. kMesaGallium,
  78. kIntelI965,
  79. kIntelIHD,
  80. kOther,
  81. kInvalid,
  82. };
  83. // This class handles VA-API calls and ensures proper locking of VA-API calls
  84. // to libva, the userspace shim to the HW codec driver. The thread safety of
  85. // libva depends on the backend. If the backend is not thread-safe, we need to
  86. // maintain a global lock that guards all libva calls. This class is fully
  87. // synchronous and its constructor, all of its methods, and its destructor must
  88. // be called on the same sequence. These methods may wait on the |va_lock_|
  89. // which guards libva calls across all VaapiWrapper instances and other libva
  90. // call sites. If the backend is known to be thread safe and
  91. // |enforce_sequence_affinity_| is true when the |kGlobalVaapiLock| flag is
  92. // disabled, |va_lock_| will be null and won't guard any libva calls.
  93. //
  94. // This class is responsible for managing VAAPI connection, contexts and state.
  95. // It is also responsible for managing and freeing VABuffers (not VASurfaces),
  96. // which are used to queue parameters and slice data to the HW codec,
  97. // as well as underlying memory for VASurfaces themselves.
  98. //
  99. // Historical note: the sequence affinity characteristic was introduced as a
  100. // pre-requisite to remove the global *|va_lock_|. However, the legacy
  101. // VaapiVideoDecodeAccelerator is known to use its VaapiWrapper from multiple
  102. // threads. Therefore, to avoid doing a large refactoring of a legacy class, we
  103. // allow it to call VaapiWrapper::Create() or
  104. // VaapiWrapper::CreateForVideoCodec() with |enforce_sequence_affinity| == false
  105. // so that sequence affinity is not enforced. This also indicates that the
  106. // global lock will still be in effect for the VaapiVideoDecodeAccelerator.
  107. class MEDIA_GPU_EXPORT VaapiWrapper
  108. : public base::RefCountedThreadSafe<VaapiWrapper> {
  109. public:
  110. enum CodecMode {
  111. kDecode,
  112. #if BUILDFLAG(IS_CHROMEOS_ASH)
  113. // NOTE: A kDecodeProtected VaapiWrapper is created using the actual video
  114. // profile and an extra VAProfileProtected, each with some special added
  115. // VAConfigAttribs. Then when CreateProtectedSession() is called, it will
  116. // then create a protected session using protected profile & entrypoint
  117. // which gets attached to the decoding context (or attached when the
  118. // decoding context is created or re-created). This then enables
  119. // decrypt + decode support in the driver and encrypted frame data can then
  120. // be submitted.
  121. kDecodeProtected, // Decrypt + decode to protected surface.
  122. #endif
  123. kEncodeConstantBitrate, // Encode with Constant Bitrate algorithm.
  124. kEncodeConstantQuantizationParameter, // Encode with Constant Quantization
  125. // Parameter algorithm.
  126. kEncodeVariableBitrate, // Encode with variable bitrate algorithm.
  127. kVideoProcess,
  128. kCodecModeMax,
  129. };
  130. // This is enum associated with VASurfaceAttribUsageHint.
  131. enum class SurfaceUsageHint : int32_t {
  132. kGeneric = VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC,
  133. kVideoDecoder = VA_SURFACE_ATTRIB_USAGE_HINT_DECODER,
  134. kVideoEncoder = VA_SURFACE_ATTRIB_USAGE_HINT_ENCODER,
  135. kVideoProcessWrite = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE,
  136. };
  137. using InternalFormats = struct {
  138. bool yuv420 : 1;
  139. bool yuv420_10 : 1;
  140. bool yuv422 : 1;
  141. bool yuv444 : 1;
  142. };
  143. // Returns the type of the underlying VA-API implementation.
  144. static VAImplementation GetImplementationType();
  145. // Return an instance of VaapiWrapper initialized for |va_profile| and
  146. // |mode|. |report_error_to_uma_cb| will be called independently from
  147. // reporting errors to clients via method return values.
  148. static scoped_refptr<VaapiWrapper> Create(
  149. CodecMode mode,
  150. VAProfile va_profile,
  151. EncryptionScheme encryption_scheme,
  152. const ReportErrorToUMACB& report_error_to_uma_cb,
  153. bool enforce_sequence_affinity = true);
  154. // Create VaapiWrapper for VideoCodecProfile. It maps VideoCodecProfile
  155. // |profile| to VAProfile.
  156. // |report_error_to_uma_cb| will be called independently from reporting
  157. // errors to clients via method return values.
  158. static scoped_refptr<VaapiWrapper> CreateForVideoCodec(
  159. CodecMode mode,
  160. VideoCodecProfile profile,
  161. EncryptionScheme encryption_scheme,
  162. const ReportErrorToUMACB& report_error_to_uma_cb,
  163. bool enforce_sequence_affinity = true);
  164. VaapiWrapper(const VaapiWrapper&) = delete;
  165. VaapiWrapper& operator=(const VaapiWrapper&) = delete;
  166. // Returns the supported SVC scalability modes for specified profile.
  167. static std::vector<SVCScalabilityMode> GetSupportedScalabilityModes(
  168. VideoCodecProfile media_profile,
  169. VAProfile va_profile);
  170. // Return the supported video encode profiles.
  171. static VideoEncodeAccelerator::SupportedProfiles GetSupportedEncodeProfiles();
  172. // Return the supported video decode profiles.
  173. static VideoDecodeAccelerator::SupportedProfiles GetSupportedDecodeProfiles();
  174. // Return true when decoding using |va_profile| is supported.
  175. static bool IsDecodeSupported(VAProfile va_profile);
  176. // Returns the supported internal formats for decoding using |va_profile|. If
  177. // decoding is not supported for that profile, returns InternalFormats{}.
  178. static InternalFormats GetDecodeSupportedInternalFormats(
  179. VAProfile va_profile);
  180. // Returns true if |rt_format| is supported for decoding using |va_profile|.
  181. // Returns false if |rt_format| or |va_profile| is not supported for decoding.
  182. static bool IsDecodingSupportedForInternalFormat(VAProfile va_profile,
  183. unsigned int rt_format);
  184. // Gets the minimum and maximum surface sizes allowed for |va_profile| in
  185. // |codec_mode|. Returns true if both sizes can be obtained, false otherwise.
  186. // Each dimension in |min_size| will be at least 1 (as long as this method
  187. // returns true). Additionally, because of the initialization in
  188. // VASupportedProfiles::FillProfileInfo_Locked(), the |max_size| is guaranteed
  189. // to not be empty (as long as this method returns true).
  190. static bool GetSupportedResolutions(VAProfile va_profile,
  191. CodecMode codec_mode,
  192. gfx::Size& min_size,
  193. gfx::Size& max_size);
  194. // Obtains a suitable FOURCC that can be used in vaCreateImage() +
  195. // vaGetImage(). |rt_format| corresponds to the JPEG's subsampling format.
  196. // |preferred_fourcc| is the FOURCC of the format preferred by the caller. If
  197. // it is determined that the VAAPI driver can do the conversion from the
  198. // internal format (|rt_format|), *|suitable_fourcc| is set to
  199. // |preferred_fourcc|. Otherwise, it is set to a supported format. Returns
  200. // true if a suitable FOURCC could be determined, false otherwise (e.g., if
  201. // the |rt_format| is unsupported by the driver). If |preferred_fourcc| is not
  202. // a supported image format, *|suitable_fourcc| is set to VA_FOURCC_I420.
  203. static bool GetJpegDecodeSuitableImageFourCC(unsigned int rt_format,
  204. uint32_t preferred_fourcc,
  205. uint32_t* suitable_fourcc);
  206. // Checks the surface size is allowed for VPP. Returns true if the size is
  207. // supported, false otherwise.
  208. static bool IsVppResolutionAllowed(const gfx::Size& size);
  209. // Returns true if the VPP supports converting from/to |fourcc|.
  210. static bool IsVppFormatSupported(uint32_t fourcc);
  211. // Returns the pixel formats supported by the VPP.
  212. static std::vector<Fourcc> GetVppSupportedFormats();
  213. // Returns true if VPP supports the format conversion from a JPEG decoded
  214. // internal surface to a FOURCC. |rt_format| corresponds to the JPEG's
  215. // subsampling format. |fourcc| is the output surface's FOURCC.
  216. static bool IsVppSupportedForJpegDecodedSurfaceToFourCC(
  217. unsigned int rt_format,
  218. uint32_t fourcc);
  219. // Return true when JPEG encode is supported.
  220. static bool IsJpegEncodeSupported();
  221. // Return true when the specified image format is supported.
  222. static bool IsImageFormatSupported(const VAImageFormat& format);
  223. // Returns the list of VAImageFormats supported by the driver.
  224. static const std::vector<VAImageFormat>& GetSupportedImageFormatsForTesting();
  225. // Returns the list of supported profiles and entrypoints for a given |mode|.
  226. static std::map<VAProfile, std::vector<VAEntrypoint>>
  227. GetSupportedConfigurationsForCodecModeForTesting(CodecMode mode);
  228. static VAEntrypoint GetDefaultVaEntryPoint(CodecMode mode, VAProfile profile);
  229. static uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt);
  230. // Creates |num_surfaces| VASurfaceIDs of |va_format|, |size| and
  231. // |surface_usage_hints| and, if successful, creates a |va_context_id_| of the
  232. // same size. |surface_usage_hints| may affect an alignment and tiling of the
  233. // created surface. Returns true if successful, with the created IDs in
  234. // |va_surfaces|. The client is responsible for destroying |va_surfaces| via
  235. // DestroyContextAndSurfaces() to free the allocated surfaces.
  236. [[nodiscard]] virtual bool CreateContextAndSurfaces(
  237. unsigned int va_format,
  238. const gfx::Size& size,
  239. const std::vector<SurfaceUsageHint>& surface_usage_hints,
  240. size_t num_surfaces,
  241. std::vector<VASurfaceID>* va_surfaces);
  242. // Creates |num_surfaces| ScopedVASurfaces of |va_format| and |size| and, if
  243. // successful, creates a |va_context_id_| of the same size. Returns an empty
  244. // vector if creation failed. If |visible_size| is supplied, the returned
  245. // ScopedVASurface's size is set to it. Otherwise, it's set to |size| (refer
  246. // to CreateScopedVASurfaces() for details).
  247. virtual std::vector<std::unique_ptr<ScopedVASurface>>
  248. CreateContextAndScopedVASurfaces(
  249. unsigned int va_format,
  250. const gfx::Size& size,
  251. const std::vector<SurfaceUsageHint>& usage_hints,
  252. size_t num_surfaces,
  253. const absl::optional<gfx::Size>& visible_size);
  254. // Attempts to create a protected session that will be attached to the
  255. // decoding context to enable encrypted video decoding. If it cannot be
  256. // attached now, it will be attached when the decoding context is created or
  257. // re-created. |encryption| should be the encryption scheme from the
  258. // DecryptConfig. |hw_config| should have been obtained from the OEMCrypto
  259. // implementation via the CdmFactoryDaemonProxy. |hw_identifier_out| is an
  260. // output parameter which will return session specific information which can
  261. // be passed through the ChromeOsCdmContext to retrieve encrypted key
  262. // information. Returns true on success and false otherwise.
  263. bool CreateProtectedSession(media::EncryptionScheme encryption,
  264. const std::vector<uint8_t>& hw_config,
  265. std::vector<uint8_t>* hw_identifier_out);
  266. // Returns true if and only if we have created a protected session and
  267. // querying libva indicates that our protected session is no longer alive,
  268. // otherwise this will return false.
  269. bool IsProtectedSessionDead();
  270. #if BUILDFLAG(IS_CHROMEOS_ASH)
  271. // Returns true if and only if |va_protected_session_id| is not VA_INVALID_ID
  272. // and querying libva indicates that the protected session identified by
  273. // |va_protected_session_id| is no longer alive.
  274. bool IsProtectedSessionDead(VAProtectedSessionID va_protected_session_id);
  275. // Returns the ID of the current protected session or VA_INVALID_ID if there's
  276. // none. This must be called on the same sequence as other methods that use
  277. // the protected session ID internally.
  278. //
  279. // TODO(b/183515581): update this documentation once we force the VaapiWrapper
  280. // to be used on a single sequence.
  281. VAProtectedSessionID GetProtectedSessionID() const;
  282. #endif
  283. // If we have a protected session, destroys it immediately. This should be
  284. // used as part of recovering dead protected sessions.
  285. void DestroyProtectedSession();
  286. // Releases the |va_surfaces| and destroys |va_context_id_|.
  287. void DestroyContextAndSurfaces(std::vector<VASurfaceID> va_surfaces);
  288. // Creates a VAContextID of |size| (unless it's a Vpp context in which case
  289. // |size| is ignored and 0x0 is used instead). The client is responsible for
  290. // releasing said context via DestroyContext() or DestroyContextAndSurfaces(),
  291. // or it will be released on dtor. If a valid |va_protected_session_id_|
  292. // exists, it will be attached to the newly created |va_context_id_| as well.
  293. [[nodiscard]] virtual bool CreateContext(const gfx::Size& size);
  294. // Destroys the context identified by |va_context_id_|.
  295. virtual void DestroyContext();
  296. // Requests |num_surfaces| ScopedVASurfaces of size |size|, |va_rt_format| and
  297. // optionally |va_fourcc|. Returns self-cleaning ScopedVASurfaces or empty
  298. // vector if creation failed. If |visible_size| is supplied, the returned
  299. // ScopedVASurfaces' size are set to it: for example, we may want to request a
  300. // 16x16 surface to decode a 13x12 JPEG: we may want to keep track of the
  301. // visible size 13x12 inside the ScopedVASurface to inform the surface's users
  302. // that that's the only region with meaningful content. If |visible_size| is
  303. // not supplied, we store |size| in the returned ScopedVASurfaces.
  304. virtual std::vector<std::unique_ptr<ScopedVASurface>> CreateScopedVASurfaces(
  305. unsigned int va_rt_format,
  306. const gfx::Size& size,
  307. const std::vector<SurfaceUsageHint>& usage_hints,
  308. size_t num_surfaces,
  309. const absl::optional<gfx::Size>& visible_size,
  310. const absl::optional<uint32_t>& va_fourcc);
  311. // Creates a self-releasing VASurface from |pixmap|. The created VASurface
  312. // shares the ownership of the underlying buffer represented by |pixmap|. The
  313. // ownership of the surface is transferred to the caller. A caller can destroy
  314. // |pixmap| after this method returns and the underlying buffer will be kept
  315. // alive by the VASurface. |protected_content| should only be true if the
  316. // format needs VA_RT_FORMAT_PROTECTED (currently only true for AMD).
  317. virtual scoped_refptr<VASurface> CreateVASurfaceForPixmap(
  318. scoped_refptr<gfx::NativePixmap> pixmap,
  319. bool protected_content = false);
  320. // Creates a self-releasing VASurface from |buffers|. The ownership of the
  321. // surface is transferred to the caller. |buffers| should be a pointer array
  322. // of size 1, with |buffer_size| corresponding to its size. |size| should be
  323. // the desired surface dimensions (which does not need to map to |buffer_size|
  324. // in any relevant way). |buffers| should be kept alive when using the
  325. // VASurface and for accessing the data after the operation is complete.
  326. scoped_refptr<VASurface> CreateVASurfaceForUserPtr(const gfx::Size& size,
  327. uintptr_t* buffers,
  328. size_t buffer_size);
  329. // Creates a self-releasing VASurface with specified usage hints. The
  330. // ownership of the surface is transferred to the caller. |size| should be
  331. // the desired surface dimensions.
  332. scoped_refptr<VASurface> CreateVASurfaceWithUsageHints(
  333. unsigned int va_rt_format,
  334. const gfx::Size& size,
  335. const std::vector<SurfaceUsageHint>& usage_hints);
  336. // Implementations of the pixmap exporter for both types of VASurface.
  337. // See ExportVASurfaceAsNativePixmapDmaBufUnwrapped() for further
  338. // documentation.
  339. std::unique_ptr<NativePixmapAndSizeInfo> ExportVASurfaceAsNativePixmapDmaBuf(
  340. const VASurface& va_surface);
  341. std::unique_ptr<NativePixmapAndSizeInfo> ExportVASurfaceAsNativePixmapDmaBuf(
  342. const ScopedVASurface& scoped_va_surface);
  343. // Synchronize the VASurface explicitly. This is useful when sharing a surface
  344. // between contexts.
  345. [[nodiscard]] bool SyncSurface(VASurfaceID va_surface_id);
  346. // Calls SubmitBuffer_Locked() to request libva to allocate a new VABufferID
  347. // of |va_buffer_type| and |size|, and to map-and-copy the |data| into it. The
  348. // allocated VABufferIDs stay alive until DestroyPendingBuffers_Locked(). Note
  349. // that this method does not submit the buffers for execution, they are simply
  350. // stored until ExecuteAndDestroyPendingBuffers()/Execute_Locked(). The
  351. // ownership of |data| stays with the caller. On failure, all pending buffers
  352. // are destroyed.
  353. [[nodiscard]] bool SubmitBuffer(VABufferType va_buffer_type,
  354. size_t size,
  355. const void* data);
  356. // Convenient templatized version of SubmitBuffer() where |size| is deduced to
  357. // be the size of the type of |*data|.
  358. template <typename T>
  359. [[nodiscard]] bool SubmitBuffer(VABufferType va_buffer_type, const T* data) {
  360. CHECK(!enforce_sequence_affinity_ ||
  361. sequence_checker_.CalledOnValidSequence());
  362. return SubmitBuffer(va_buffer_type, sizeof(T), data);
  363. }
  364. // Batch-version of SubmitBuffer(), where the lock for accessing libva is
  365. // acquired only once.
  366. struct VABufferDescriptor {
  367. VABufferType type;
  368. size_t size;
  369. const void* data;
  370. };
  371. [[nodiscard]] bool SubmitBuffers(
  372. const std::vector<VABufferDescriptor>& va_buffers);
  373. // Destroys all |pending_va_buffers_| sent via SubmitBuffer*(). Useful when a
  374. // pending job is to be cancelled (on reset or error).
  375. void DestroyPendingBuffers();
  376. // Executes job in hardware on target |va_surface_id| and destroys pending
  377. // buffers. Returns false if Execute() fails.
  378. [[nodiscard]] virtual bool ExecuteAndDestroyPendingBuffers(
  379. VASurfaceID va_surface_id);
  380. // Maps each |va_buffers| ID and copies the data described by the associated
  381. // VABufferDescriptor into it; then calls Execute_Locked() on |va_surface_id|.
  382. [[nodiscard]] bool MapAndCopyAndExecute(
  383. VASurfaceID va_surface_id,
  384. const std::vector<std::pair<VABufferID, VABufferDescriptor>>& va_buffers);
  385. #if BUILDFLAG(USE_VAAPI_X11)
  386. // Put data from |va_surface_id| into |x_pixmap| of size
  387. // |dest_size|, converting/scaling to it.
  388. [[nodiscard]] bool PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
  389. x11::Pixmap x_pixmap,
  390. gfx::Size dest_size);
  391. #endif // BUILDFLAG(USE_VAAPI_X11)
  392. // Creates a ScopedVAImage from a VASurface |va_surface_id| and map it into
  393. // memory with the given |format| and |size|. If |format| is not equal to the
  394. // internal format, the underlying implementation will do format conversion if
  395. // supported. |size| should be smaller than or equal to the surface. If |size|
  396. // is smaller, the image will be cropped.
  397. std::unique_ptr<ScopedVAImage> CreateVaImage(VASurfaceID va_surface_id,
  398. VAImageFormat* format,
  399. const gfx::Size& size);
  400. // Uploads contents of |frame| into |va_surface_id| for encode.
  401. [[nodiscard]] virtual bool UploadVideoFrameToSurface(
  402. const VideoFrame& frame,
  403. VASurfaceID va_surface_id,
  404. const gfx::Size& va_surface_size);
  405. // Creates a buffer of |size| bytes to be used as encode output.
  406. virtual std::unique_ptr<ScopedVABuffer> CreateVABuffer(VABufferType type,
  407. size_t size);
  408. // Gets the encoded frame linear size of the buffer with given |buffer_id|.
  409. // |sync_surface_id| will be used as a sync point, i.e. it will have to become
  410. // idle before starting the acquirement. |sync_surface_id| should be the
  411. // source surface passed to the encode job. Returns 0 if it fails for any
  412. // reason.
  413. [[nodiscard]] virtual uint64_t GetEncodedChunkSize(
  414. VABufferID buffer_id,
  415. VASurfaceID sync_surface_id);
  416. // Downloads the contents of the buffer with given |buffer_id| into a buffer
  417. // of size |target_size|, pointed to by |target_ptr|. The number of bytes
  418. // downloaded will be returned in |coded_data_size|. |sync_surface_id| will
  419. // be used as a sync point, i.e. it will have to become idle before starting
  420. // the download. |sync_surface_id| should be the source surface passed
  421. // to the encode job. |sync_surface_id| will be nullopt when it has already
  422. // been synced in GetEncodedChunkSize(). In the case vaSyncSurface()
  423. // is not executed. Returns false if it fails for any reason. For example, the
  424. // linear size of the resulted encoded frame is larger than |target_size|.
  425. [[nodiscard]] virtual bool DownloadFromVABuffer(
  426. VABufferID buffer_id,
  427. absl::optional<VASurfaceID> sync_surface_id,
  428. uint8_t* target_ptr,
  429. size_t target_size,
  430. size_t* coded_data_size);
  431. // Get the max number of reference frames for encoding supported by the
  432. // driver.
  433. // For H.264 encoding, the value represents the maximum number of reference
  434. // frames for both the reference picture list 0 (bottom 16 bits) and the
  435. // reference picture list 1 (top 16 bits).
  436. [[nodiscard]] virtual bool GetVAEncMaxNumOfRefFrames(
  437. VideoCodecProfile profile,
  438. size_t* max_ref_frames);
  439. // Gets packed headers are supported for encoding. This is called for
  440. // H264 encoding. |packed_sps|, |packed_pps| and |packed_slice| stands for
  441. // whether packed slice parameter set, packed picture parameter set and packed
  442. // slice header is supported, respectively.
  443. [[nodiscard]] virtual bool GetSupportedPackedHeaders(
  444. VideoCodecProfile profile,
  445. bool& packed_sps,
  446. bool& packed_pps,
  447. bool& packed_slice);
  448. // Checks if the driver supports frame rotation.
  449. bool IsRotationSupported();
  450. // Blits a VASurface |va_surface_src| into another VASurface
  451. // |va_surface_dest| applying pixel format conversion, rotation, cropping
  452. // and scaling if needed. |src_rect| and |dest_rect| are optional. They can
  453. // be used to specify the area used in the blit. If |va_protected_session_id|
  454. // is provided and is not VA_INVALID_ID, the corresponding protected session
  455. // is attached to the VPP context prior to submitting the VPP buffers and
  456. // detached after submitting those buffers.
  457. [[nodiscard]] virtual bool BlitSurface(
  458. const VASurface& va_surface_src,
  459. const VASurface& va_surface_dest,
  460. absl::optional<gfx::Rect> src_rect = absl::nullopt,
  461. absl::optional<gfx::Rect> dest_rect = absl::nullopt,
  462. VideoRotation rotation = VIDEO_ROTATION_0
  463. #if BUILDFLAG(IS_CHROMEOS_ASH)
  464. ,
  465. VAProtectedSessionID va_protected_session_id = VA_INVALID_ID
  466. #endif
  467. );
  468. // Initialize static data before sandbox is enabled.
  469. static void PreSandboxInitialization();
  470. // vaDestroySurfaces() a vector or a single VASurfaceID.
  471. virtual void DestroySurfaces(std::vector<VASurfaceID> va_surfaces);
  472. virtual void DestroySurface(VASurfaceID va_surface_id);
  473. protected:
  474. explicit VaapiWrapper(CodecMode mode, bool enforce_sequence_affinity = true);
  475. virtual ~VaapiWrapper();
  476. private:
  477. friend class base::RefCountedThreadSafe<VaapiWrapper>;
  478. friend class VaapiWrapperTest;
  479. friend class VaapiVideoEncodeAcceleratorTest;
  480. FRIEND_TEST_ALL_PREFIXES(VaapiTest, LowQualityEncodingSetting);
  481. FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, ScopedVAImage);
  482. FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVAImage);
  483. FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVABufferMapping);
  484. FRIEND_TEST_ALL_PREFIXES(VaapiMinigbmTest, AllocateAndCompareWithMinigbm);
  485. [[nodiscard]] bool Initialize(VAProfile va_profile,
  486. EncryptionScheme encryption_scheme);
  487. void Deinitialize();
  488. [[nodiscard]] bool VaInitialize(
  489. const ReportErrorToUMACB& report_error_to_uma_cb);
  490. // Tries to allocate |num_surfaces| VASurfaceIDs of |size| and |va_format|.
  491. // Fills |va_surfaces| and returns true if successful, or returns false.
  492. [[nodiscard]] bool CreateSurfaces(
  493. unsigned int va_format,
  494. const gfx::Size& size,
  495. const std::vector<SurfaceUsageHint>& usage_hints,
  496. size_t num_surfaces,
  497. std::vector<VASurfaceID>* va_surfaces);
  498. // Syncs and exports |va_surface_id| as a gfx::NativePixmapDmaBuf. Currently,
  499. // the only VAAPI surface pixel formats supported are VA_FOURCC_IMC3 and
  500. // VA_FOURCC_NV12.
  501. //
  502. // Notes:
  503. //
  504. // - For VA_FOURCC_IMC3, the format of the returned NativePixmapDmaBuf is
  505. // gfx::BufferFormat::YVU_420 because we don't have a YUV_420 format. The
  506. // planes are flipped accordingly, i.e.,
  507. // gfx::NativePixmapDmaBuf::GetDmaBufOffset(1) refers to the V plane.
  508. // TODO(andrescj): revisit once crrev.com/c/1573718 lands.
  509. //
  510. // - For VA_FOURCC_NV12, the format of the returned NativePixmapDmaBuf is
  511. // gfx::BufferFormat::YUV_420_BIPLANAR.
  512. //
  513. // Returns nullptr on failure, or if the exported surface can't contain
  514. // |va_surface_size|.
  515. std::unique_ptr<NativePixmapAndSizeInfo>
  516. ExportVASurfaceAsNativePixmapDmaBufUnwrapped(
  517. VASurfaceID va_surface_id,
  518. const gfx::Size& va_surface_size);
  519. // Carries out the vaBeginPicture()-vaRenderPicture()-vaEndPicture() on target
  520. // |va_surface_id|. Returns false if any of these calls fails.
  521. [[nodiscard]] bool Execute_Locked(VASurfaceID va_surface_id,
  522. const std::vector<VABufferID>& va_buffers)
  523. EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
  524. virtual void DestroyPendingBuffers_Locked()
  525. EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
  526. // Requests libva to allocate a new VABufferID of type |va_buffer.type|, then
  527. // maps-and-copies |va_buffer.size| contents of |va_buffer.data| to it. If a
  528. // failure occurs, calls DestroyPendingBuffers_Locked() and returns false.
  529. [[nodiscard]] virtual bool SubmitBuffer_Locked(
  530. const VABufferDescriptor& va_buffer) EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
  531. // Maps |va_buffer_id| and, if successful, copies the contents of |va_buffer|
  532. // into it.
  533. [[nodiscard]] bool MapAndCopy_Locked(VABufferID va_buffer_id,
  534. const VABufferDescriptor& va_buffer)
  535. EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
  536. // Queries whether |va_profile_| and |va_entrypoint_| support encoding quality
  537. // setting and, if available, configures it to its maximum value, for lower
  538. // consumption and maximum speed.
  539. void MaybeSetLowQualityEncoding_Locked() EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
  540. // If a protected session is active, attaches it to the decoding context.
  541. [[nodiscard]] bool MaybeAttachProtectedSession_Locked()
  542. EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
  543. const CodecMode mode_;
  544. const bool enforce_sequence_affinity_;
  545. base::SequenceCheckerImpl sequence_checker_;
  546. // If using global VA lock, this is a pointer to VADisplayState's member
  547. // |va_lock_|. Guaranteed to be valid for the lifetime of VaapiWrapper.
  548. raw_ptr<base::Lock> va_lock_;
  549. // VA handles.
  550. // All valid after successful Initialize() and until Deinitialize().
  551. VADisplay va_display_ GUARDED_BY(va_lock_);
  552. VAConfigID va_config_id_{VA_INVALID_ID};
  553. // Created in CreateContext() or CreateContextAndSurfaces() and valid until
  554. // DestroyContext() or DestroyContextAndSurfaces().
  555. VAContextID va_context_id_{VA_INVALID_ID};
  556. // Profile and entrypoint configured for the corresponding |va_context_id_|.
  557. VAProfile va_profile_;
  558. VAEntrypoint va_entrypoint_;
  559. // Data queued up for HW codec, to be committed on next execution.
  560. // TODO(b/166646505): let callers manage the lifetime of these buffers.
  561. std::vector<VABufferID> pending_va_buffers_;
  562. // VA buffer to be used for kVideoProcess. Allocated the first time around,
  563. // and reused afterwards.
  564. std::unique_ptr<ScopedVABuffer> va_buffer_for_vpp_;
  565. #if BUILDFLAG(IS_CHROMEOS_ASH)
  566. // For protected decode mode.
  567. VAConfigID va_protected_config_id_{VA_INVALID_ID};
  568. VAProtectedSessionID va_protected_session_id_{VA_INVALID_ID};
  569. #endif
  570. // Called to report codec errors to UMA. Errors to clients are reported via
  571. // return values from public methods.
  572. ReportErrorToUMACB report_error_to_uma_cb_;
  573. };
  574. } // namespace media
  575. #endif // MEDIA_GPU_VAAPI_VAAPI_WRAPPER_H_