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 10#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_ 11#define CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_ 12 13#include <set> 14#include <vector> 15 16#include "base/callback.h" 17#include "base/memory/ref_counted.h" 18#include "base/synchronization/lock.h" 19#include "content/common/content_export.h" 20#include "content/common/gpu/media/va_surface.h" 21#include "media/base/video_decoder_config.h" 22#include "media/base/video_frame.h" 23#include "third_party/libva/va/va_x11.h" 24#include "ui/gfx/size.h" 25 26namespace content { 27 28// This class handles VA-API calls and ensures proper locking of VA-API calls 29// to libva, the userspace shim to the HW codec driver. libva is not 30// thread-safe, so we have to perform locking ourselves. This class is fully 31// synchronous and its methods can be called from any thread and may wait on 32// the va_lock_ while other, concurrent calls run. 33// 34// This class is responsible for managing VAAPI connection, contexts and state. 35// It is also responsible for managing and freeing VABuffers (not VASurfaces), 36// which are used to queue parameters and slice data to the HW codec, 37// as well as underlying memory for VASurfaces themselves. 38class CONTENT_EXPORT VaapiWrapper { 39 public: 40 enum CodecMode { 41 kDecode, 42 kEncode, 43 }; 44 45 // |report_error_to_uma_cb| will be called independently from reporting 46 // errors to clients via method return values. 47 static scoped_ptr<VaapiWrapper> Create( 48 CodecMode mode, 49 media::VideoCodecProfile profile, 50 Display* x_display, 51 const base::Closure& report_error_to_uma_cb); 52 53 // Return the supported encode profiles. 54 static std::vector<media::VideoCodecProfile> GetSupportedEncodeProfiles( 55 Display* x_display, 56 const base::Closure& report_error_to_uma_cb); 57 58 ~VaapiWrapper(); 59 60 // Create |num_surfaces| backing surfaces in driver for VASurfaces, each 61 // of size |size|. Returns true when successful, with the created IDs in 62 // |va_surfaces| to be managed and later wrapped in VASurfaces. 63 // The client must DestroySurfaces() each time before calling this method 64 // again to free the allocated surfaces first, but is not required to do so 65 // at destruction time, as this will be done automatically from 66 // the destructor. 67 bool CreateSurfaces(gfx::Size size, 68 size_t num_surfaces, 69 std::vector<VASurfaceID>* va_surfaces); 70 71 // Free all memory allocated in CreateSurfaces. 72 void DestroySurfaces(); 73 74 // Submit parameters or slice data of |va_buffer_type|, copying them from 75 // |buffer| of size |size|, into HW codec. The data in |buffer| is no 76 // longer needed and can be freed after this method returns. 77 // Data submitted via this method awaits in the HW codec until 78 // ExecuteAndDestroyPendingBuffers() is called to execute or 79 // DestroyPendingBuffers() is used to cancel a pending job. 80 bool SubmitBuffer(VABufferType va_buffer_type, size_t size, void* buffer); 81 82 // Submit a VAEncMiscParameterBuffer of given |misc_param_type|, copying its 83 // data from |buffer| of size |size|, into HW codec. The data in |buffer| is 84 // no longer needed and can be freed after this method returns. 85 // Data submitted via this method awaits in the HW codec until 86 // ExecuteAndDestroyPendingBuffers() is called to execute or 87 // DestroyPendingBuffers() is used to cancel a pending job. 88 bool SubmitVAEncMiscParamBuffer(VAEncMiscParameterType misc_param_type, 89 size_t size, 90 void* buffer); 91 92 // Cancel and destroy all buffers queued to the HW codec via SubmitBuffer(). 93 // Useful when a pending job is to be cancelled (on reset or error). 94 void DestroyPendingBuffers(); 95 96 // Execute job in hardware on target |va_surface_id| and destroy pending 97 // buffers. Return false if Execute() fails. 98 bool ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id); 99 100 // Put data from |va_surface_id| into |x_pixmap| of size |size|, 101 // converting/scaling to it. 102 bool PutSurfaceIntoPixmap(VASurfaceID va_surface_id, 103 Pixmap x_pixmap, 104 gfx::Size dest_size); 105 106 // Returns true if the VAAPI version is less than the specified version. 107 bool VAAPIVersionLessThan(int major, int minor); 108 109 // Get a VAImage from a VASurface and map it into memory. The VAImage should 110 // be released using the ReturnVaImage function. Returns true when successful. 111 // This is intended for testing only. 112 bool GetVaImageForTesting(VASurfaceID va_surface_id, 113 VAImage* image, 114 void** mem); 115 116 // Release the VAImage (and the associated memory mapping) obtained from 117 // GetVaImage(). This is intended for testing only. 118 void ReturnVaImageForTesting(VAImage* image); 119 120 // Upload contents of |frame| into |va_surface_id| for encode. 121 bool UploadVideoFrameToSurface(const scoped_refptr<media::VideoFrame>& frame, 122 VASurfaceID va_surface_id); 123 124 // Create a buffer of |size| bytes to be used as encode output. 125 bool CreateCodedBuffer(size_t size, VABufferID* buffer_id); 126 127 // Download the contents of the buffer with given |buffer_id| into a buffer of 128 // size |target_size|, pointed to by |target_ptr|. The number of bytes 129 // downloaded will be returned in |coded_data_size|. |sync_surface_id| will 130 // be used as a sync point, i.e. it will have to become idle before starting 131 // the download. |sync_surface_id| should be the source surface passed 132 // to the encode job. 133 bool DownloadAndDestroyCodedBuffer(VABufferID buffer_id, 134 VASurfaceID sync_surface_id, 135 uint8* target_ptr, 136 size_t target_size, 137 size_t* coded_data_size); 138 139 // Destroy all previously-allocated (and not yet destroyed) coded buffers. 140 void DestroyCodedBuffers(); 141 142 private: 143 VaapiWrapper(); 144 145 bool Initialize(CodecMode mode, 146 media::VideoCodecProfile profile, 147 Display* x_display, 148 const base::Closure& report_error_to_uma_cb); 149 void Deinitialize(); 150 bool VaInitialize(Display* x_display, 151 const base::Closure& report_error_to_uma_cb); 152 bool GetSupportedVaProfiles(std::vector<VAProfile>* profiles); 153 bool IsEntrypointSupported(VAProfile va_profile, VAEntrypoint entrypoint); 154 bool AreAttribsSupported(VAProfile va_profile, 155 VAEntrypoint entrypoint, 156 const std::vector<VAConfigAttrib>& required_attribs); 157 158 // Execute pending job in hardware and destroy pending buffers. Return false 159 // if vaapi driver refuses to accept parameter or slice buffers submitted 160 // by client, or if execution fails in hardware. 161 bool Execute(VASurfaceID va_surface_id); 162 163 // Attempt to set render mode to "render to texture.". Failure is non-fatal. 164 void TryToSetVADisplayAttributeToLocalGPU(); 165 166 // Lazily initialize static data after sandbox is enabled. Return false on 167 // init failure. 168 static bool PostSandboxInitialization(); 169 170 // Libva is not thread safe, so we have to do locking for it ourselves. 171 // This lock is to be taken for the duration of all VA-API calls and for 172 // the entire job submission sequence in ExecuteAndDestroyPendingBuffers(). 173 base::Lock va_lock_; 174 175 // Allocated ids for VASurfaces. 176 std::vector<VASurfaceID> va_surface_ids_; 177 178 // The VAAPI version. 179 int major_version_, minor_version_; 180 181 // VA handles. 182 // Both valid after successful Initialize() and until Deinitialize(). 183 VADisplay va_display_; 184 VAConfigID va_config_id_; 185 // Created for the current set of va_surface_ids_ in CreateSurfaces() and 186 // valid until DestroySurfaces(). 187 VAContextID va_context_id_; 188 189 // Data queued up for HW codec, to be committed on next execution. 190 std::vector<VABufferID> pending_slice_bufs_; 191 std::vector<VABufferID> pending_va_bufs_; 192 193 // Bitstream buffers for encode. 194 std::set<VABufferID> coded_buffers_; 195 196 // Called to report codec errors to UMA. Errors to clients are reported via 197 // return values from public methods. 198 base::Closure report_error_to_uma_cb_; 199 200 DISALLOW_COPY_AND_ASSIGN(VaapiWrapper); 201}; 202 203} // namespace content 204 205#endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_ 206