Commit 9583705f authored by hshi's avatar hshi Committed by Commit bot

VAAPI Wrapper: refactor management of drm file

Make sure we use the same file in all instances of VaapiWrapper.

Define a refcounted global instance of VADisplayState that is only initialized
(via vaInitialize()) once and destroyed upon release of the last refcount.
This ensures a single drm_intel_bufmgr per fd, and avoids the double-close
problem as seen in bug 464628.

Pipe a PreSandboxInitialization to open the render node before starting sandbox.

After this CL the VEA/VDA unittests need to invoke the PreSandboxInitialization
as well.

BUG=475250
TEST=verify HW video works on link (check histograms) and VDA/VEA unittests

Review URL: https://codereview.chromium.org/1137483002

Cr-Commit-Position: refs/heads/master@{#329410}
parent a26ccdf9
...@@ -62,6 +62,9 @@ namespace content { ...@@ -62,6 +62,9 @@ namespace content {
// and not taken from HW documentation. // and not taken from HW documentation.
const int kMaxEncoderFramerate = 30; const int kMaxEncoderFramerate = 30;
base::LazyInstance<VaapiWrapper::VADisplayState>
VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<VaapiWrapper::LazyProfileInfos> base::LazyInstance<VaapiWrapper::LazyProfileInfos>
VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER;
...@@ -123,10 +126,10 @@ VaapiWrapper::VaapiWrapper() ...@@ -123,10 +126,10 @@ VaapiWrapper::VaapiWrapper()
: va_display_(NULL), : va_display_(NULL),
va_config_id_(VA_INVALID_ID), va_config_id_(VA_INVALID_ID),
va_context_id_(VA_INVALID_ID), va_context_id_(VA_INVALID_ID),
va_initialized_(false),
va_vpp_config_id_(VA_INVALID_ID), va_vpp_config_id_(VA_INVALID_ID),
va_vpp_context_id_(VA_INVALID_ID), va_vpp_context_id_(VA_INVALID_ID),
va_vpp_buffer_id_(VA_INVALID_ID) { va_vpp_buffer_id_(VA_INVALID_ID) {
va_lock_ = va_display_state_.Get().va_lock();
} }
VaapiWrapper::~VaapiWrapper() { VaapiWrapper::~VaapiWrapper() {
...@@ -223,7 +226,7 @@ VaapiWrapper::GetSupportedDecodeProfiles() { ...@@ -223,7 +226,7 @@ VaapiWrapper::GetSupportedDecodeProfiles() {
} }
void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VADisplayAttribute item = {VADisplayAttribRenderMode, VADisplayAttribute item = {VADisplayAttribRenderMode,
1, // At least support '_LOCAL_OVERLAY'. 1, // At least support '_LOCAL_OVERLAY'.
-1, // The maximum possible support 'ALL'. -1, // The maximum possible support 'ALL'.
...@@ -272,7 +275,7 @@ VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { ...@@ -272,7 +275,7 @@ VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) {
VAEntrypoint entrypoint = VAEntrypoint entrypoint =
(mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD);
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
for (const auto& va_profile : va_profiles) { for (const auto& va_profile : va_profiles) {
if (!IsEntrypointSupported_Locked(va_profile, entrypoint)) if (!IsEntrypointSupported_Locked(va_profile, entrypoint))
continue; continue;
...@@ -312,37 +315,26 @@ bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { ...@@ -312,37 +315,26 @@ bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
report_error_to_uma_cb_ = report_error_to_uma_cb; report_error_to_uma_cb_ = report_error_to_uma_cb;
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
#if defined(USE_X11)
va_display_ = vaGetDisplay(gfx::GetXDisplay());
#elif defined(USE_OZONE)
const char* kDriRenderNode0Path = "/dev/dri/renderD128";
drm_file_ = base::File(base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path),
base::File::FLAG_OPEN | base::File::FLAG_READ |
base::File::FLAG_WRITE);
va_display_ = vaGetDisplayDRM(drm_file_.GetPlatformFile());
#endif // USE_X11
if (!vaDisplayIsValid(va_display_)) { VADisplayState* va_display_state = &va_display_state_.Get();
LOG(ERROR) << "Could not get a valid VA display"; if (!va_display_state) {
LOG(ERROR) << "Failed to allocate VA display state";
return false; return false;
} }
VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); VAStatus va_res = VA_STATUS_SUCCESS;
VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); if (!va_display_state->Initialize(&va_res)) {
va_initialized_ = true; VA_LOG_ON_ERROR(va_res, "vaInitialize failed");
DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
if (VAAPIVersionLessThan(0, 34)) {
LOG(ERROR) << "VAAPI version < 0.34 is not supported.";
return false; return false;
} }
va_display_ = va_display_state->va_display();
return true; return true;
} }
bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
// Query the driver for supported profiles. // Query the driver for supported profiles.
int max_profiles = vaMaxNumProfiles(va_display_); int max_profiles = vaMaxNumProfiles(va_display_);
std::vector<VAProfile> supported_profiles( std::vector<VAProfile> supported_profiles(
...@@ -364,7 +356,7 @@ bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { ...@@ -364,7 +356,7 @@ bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile, bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile,
VAEntrypoint entrypoint) { VAEntrypoint entrypoint) {
va_lock_.AssertAcquired(); va_lock_->AssertAcquired();
// Query the driver for supported entrypoints. // Query the driver for supported entrypoints.
int max_entrypoints = vaMaxNumEntrypoints(va_display_); int max_entrypoints = vaMaxNumEntrypoints(va_display_);
std::vector<VAEntrypoint> supported_entrypoints( std::vector<VAEntrypoint> supported_entrypoints(
...@@ -396,7 +388,7 @@ bool VaapiWrapper::AreAttribsSupported_Locked( ...@@ -396,7 +388,7 @@ bool VaapiWrapper::AreAttribsSupported_Locked(
VAProfile va_profile, VAProfile va_profile,
VAEntrypoint entrypoint, VAEntrypoint entrypoint,
const std::vector<VAConfigAttrib>& required_attribs) { const std::vector<VAConfigAttrib>& required_attribs) {
va_lock_.AssertAcquired(); va_lock_->AssertAcquired();
// Query the driver for required attributes. // Query the driver for required attributes.
std::vector<VAConfigAttrib> attribs = required_attribs; std::vector<VAConfigAttrib> attribs = required_attribs;
for (size_t i = 0; i < required_attribs.size(); ++i) for (size_t i = 0; i < required_attribs.size(); ++i)
...@@ -423,7 +415,7 @@ bool VaapiWrapper::GetMaxResolution_Locked( ...@@ -423,7 +415,7 @@ bool VaapiWrapper::GetMaxResolution_Locked(
VAEntrypoint entrypoint, VAEntrypoint entrypoint,
std::vector<VAConfigAttrib>& required_attribs, std::vector<VAConfigAttrib>& required_attribs,
gfx::Size* resolution) { gfx::Size* resolution) {
va_lock_.AssertAcquired(); va_lock_->AssertAcquired();
VAConfigID va_config_id; VAConfigID va_config_id;
VAStatus va_res = vaCreateConfig( VAStatus va_res = vaCreateConfig(
va_display_, va_display_,
...@@ -472,7 +464,7 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { ...@@ -472,7 +464,7 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
VAEntrypoint entrypoint = VAEntrypoint entrypoint =
(mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaCreateConfig(va_display_, VAStatus va_res = vaCreateConfig(va_display_,
va_profile, va_profile,
entrypoint, entrypoint,
...@@ -485,37 +477,28 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { ...@@ -485,37 +477,28 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
} }
void VaapiWrapper::Deinitialize() { void VaapiWrapper::Deinitialize() {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
if (va_config_id_ != VA_INVALID_ID) { if (va_config_id_ != VA_INVALID_ID) {
VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_);
VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed");
} }
// Must check if vaInitialize completed successfully, to work around a bug in VADisplayState* va_display_state = &va_display_state_.Get();
// libva. The bug was fixed upstream: if (va_display_state) {
// http://lists.freedesktop.org/archives/libva/2013-July/001807.html VAStatus va_res = VA_STATUS_SUCCESS;
// TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once va_display_state->Deinitialize(&va_res);
// the fix has rolled out sufficiently.
if (va_initialized_ && va_display_) {
VAStatus va_res = vaTerminate(va_display_);
VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); VA_LOG_ON_ERROR(va_res, "vaTerminate failed");
} }
va_config_id_ = VA_INVALID_ID; va_config_id_ = VA_INVALID_ID;
va_display_ = NULL; va_display_ = NULL;
va_initialized_ = false;
}
bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) {
return (major_version_ < major) ||
(major_version_ == major && minor_version_ < minor);
} }
bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, bool VaapiWrapper::CreateSurfaces(const gfx::Size& size,
size_t num_surfaces, size_t num_surfaces,
std::vector<VASurfaceID>* va_surfaces) { std::vector<VASurfaceID>* va_surfaces) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
DVLOG(2) << "Creating " << num_surfaces << " surfaces"; DVLOG(2) << "Creating " << num_surfaces << " surfaces";
DCHECK(va_surfaces->empty()); DCHECK(va_surfaces->empty());
...@@ -553,7 +536,7 @@ bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, ...@@ -553,7 +536,7 @@ bool VaapiWrapper::CreateSurfaces(const gfx::Size& size,
} }
void VaapiWrapper::DestroySurfaces() { void VaapiWrapper::DestroySurfaces() {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces";
if (va_context_id_ != VA_INVALID_ID) { if (va_context_id_ != VA_INVALID_ID) {
...@@ -575,7 +558,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( ...@@ -575,7 +558,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface(
unsigned int va_format, unsigned int va_format,
const gfx::Size& size, const gfx::Size& size,
const std::vector<VASurfaceAttrib>& va_attribs) { const std::vector<VASurfaceAttrib>& va_attribs) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
std::vector<VASurfaceAttrib> attribs(va_attribs); std::vector<VASurfaceAttrib> attribs(va_attribs);
VASurfaceID va_surface_id; VASurfaceID va_surface_id;
...@@ -598,7 +581,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( ...@@ -598,7 +581,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface(
} }
void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1);
VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed");
...@@ -607,7 +590,7 @@ void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { ...@@ -607,7 +590,7 @@ void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) {
bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
size_t size, size_t size,
void* buffer) { void* buffer) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VABufferID buffer_id; VABufferID buffer_id;
VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_,
...@@ -634,7 +617,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer( ...@@ -634,7 +617,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
VAEncMiscParameterType misc_param_type, VAEncMiscParameterType misc_param_type,
size_t size, size_t size,
void* buffer) { void* buffer) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VABufferID buffer_id; VABufferID buffer_id;
VAStatus va_res = vaCreateBuffer(va_display_, VAStatus va_res = vaCreateBuffer(va_display_,
...@@ -668,7 +651,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer( ...@@ -668,7 +651,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
} }
void VaapiWrapper::DestroyPendingBuffers() { void VaapiWrapper::DestroyPendingBuffers() {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
for (const auto& pending_va_buf : pending_va_bufs_) { for (const auto& pending_va_buf : pending_va_bufs_) {
VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf);
...@@ -685,7 +668,7 @@ void VaapiWrapper::DestroyPendingBuffers() { ...@@ -685,7 +668,7 @@ void VaapiWrapper::DestroyPendingBuffers() {
} }
bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaCreateBuffer(va_display_, VAStatus va_res = vaCreateBuffer(va_display_,
va_context_id_, va_context_id_,
VAEncCodedBufferType, VAEncCodedBufferType,
...@@ -700,7 +683,7 @@ bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { ...@@ -700,7 +683,7 @@ bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) {
} }
void VaapiWrapper::DestroyCodedBuffers() { void VaapiWrapper::DestroyCodedBuffers() {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin(); for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin();
iter != coded_buffers_.end(); iter != coded_buffers_.end();
...@@ -713,7 +696,7 @@ void VaapiWrapper::DestroyCodedBuffers() { ...@@ -713,7 +696,7 @@ void VaapiWrapper::DestroyCodedBuffers() {
} }
bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
...@@ -759,7 +742,7 @@ bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { ...@@ -759,7 +742,7 @@ bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
Pixmap x_pixmap, Pixmap x_pixmap,
gfx::Size dest_size) { gfx::Size dest_size) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
...@@ -779,7 +762,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, ...@@ -779,7 +762,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id, bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id,
VAImage* image, VAImage* image,
void** mem) { void** mem) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
...@@ -807,7 +790,7 @@ bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, ...@@ -807,7 +790,7 @@ bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id,
const gfx::Size& size, const gfx::Size& size,
VAImage* image, VAImage* image,
void** mem) { void** mem) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
...@@ -836,7 +819,7 @@ bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, ...@@ -836,7 +819,7 @@ bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id,
} }
void VaapiWrapper::ReturnVaImage(VAImage* image) { void VaapiWrapper::ReturnVaImage(VAImage* image) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); VAStatus va_res = vaUnmapBuffer(va_display_, image->buf);
VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
...@@ -853,7 +836,7 @@ static void DestroyVAImage(VADisplay va_display, VAImage image) { ...@@ -853,7 +836,7 @@ static void DestroyVAImage(VADisplay va_display, VAImage image) {
bool VaapiWrapper::UploadVideoFrameToSurface( bool VaapiWrapper::UploadVideoFrameToSurface(
const scoped_refptr<media::VideoFrame>& frame, const scoped_refptr<media::VideoFrame>& frame,
VASurfaceID va_surface_id) { VASurfaceID va_surface_id) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAImage image; VAImage image;
VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image);
...@@ -878,7 +861,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface( ...@@ -878,7 +861,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface(
int ret = 0; int ret = 0;
{ {
base::AutoUnlock auto_unlock(va_lock_); base::AutoUnlock auto_unlock(*va_lock_);
ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kYPlane), frame->stride(media::VideoFrame::kYPlane),
frame->data(media::VideoFrame::kUPlane), frame->data(media::VideoFrame::kUPlane),
...@@ -904,7 +887,7 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, ...@@ -904,7 +887,7 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
uint8* target_ptr, uint8* target_ptr,
size_t target_size, size_t target_size,
size_t* coded_data_size) { size_t* coded_data_size) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id); VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
...@@ -916,7 +899,7 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, ...@@ -916,7 +899,7 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
DCHECK(target_ptr); DCHECK(target_ptr);
{ {
base::AutoUnlock auto_unlock(va_lock_); base::AutoUnlock auto_unlock(*va_lock_);
*coded_data_size = 0; *coded_data_size = 0;
while (buffer_segment) { while (buffer_segment) {
...@@ -953,7 +936,7 @@ bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, ...@@ -953,7 +936,7 @@ bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src,
const gfx::Size& src_size, const gfx::Size& src_size,
VASurfaceID va_surface_id_dest, VASurfaceID va_surface_id_dest,
const gfx::Size& dest_size) { const gfx::Size& dest_size) {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
// Initialize the post processing engine if not already done. // Initialize the post processing engine if not already done.
if (va_vpp_buffer_id_ == VA_INVALID_ID) { if (va_vpp_buffer_id_ == VA_INVALID_ID) {
...@@ -1002,7 +985,7 @@ bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, ...@@ -1002,7 +985,7 @@ bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src,
} }
bool VaapiWrapper::InitializeVpp_Locked() { bool VaapiWrapper::InitializeVpp_Locked() {
va_lock_.AssertAcquired(); va_lock_->AssertAcquired();
VA_SUCCESS_OR_RETURN( VA_SUCCESS_OR_RETURN(
vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0, vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0,
...@@ -1025,7 +1008,7 @@ bool VaapiWrapper::InitializeVpp_Locked() { ...@@ -1025,7 +1008,7 @@ bool VaapiWrapper::InitializeVpp_Locked() {
} }
void VaapiWrapper::DeinitializeVpp() { void VaapiWrapper::DeinitializeVpp() {
base::AutoLock auto_lock(va_lock_); base::AutoLock auto_lock(*va_lock_);
if (va_vpp_buffer_id_ != VA_INVALID_ID) { if (va_vpp_buffer_id_ != VA_INVALID_ID) {
vaDestroyBuffer(va_display_, va_vpp_buffer_id_); vaDestroyBuffer(va_display_, va_vpp_buffer_id_);
...@@ -1041,6 +1024,18 @@ void VaapiWrapper::DeinitializeVpp() { ...@@ -1041,6 +1024,18 @@ void VaapiWrapper::DeinitializeVpp() {
} }
} }
// static
void VaapiWrapper::PreSandboxInitialization() {
#if defined(USE_OZONE)
const char* kDriRenderNode0Path = "/dev/dri/renderD128";
base::File drm_file = base::File(
base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path),
base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE);
if (drm_file.IsValid())
va_display_state_.Get().SetDrmFd(drm_file.GetPlatformFile());
#endif
}
// static // static
bool VaapiWrapper::PostSandboxInitialization() { bool VaapiWrapper::PostSandboxInitialization() {
StubPathMap paths; StubPathMap paths;
...@@ -1087,4 +1082,70 @@ bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( ...@@ -1087,4 +1082,70 @@ bool VaapiWrapper::LazyProfileInfos::IsProfileSupported(
return false; return false;
} }
VaapiWrapper::VADisplayState::VADisplayState()
: refcount_(0),
va_display_(nullptr),
major_version_(-1),
minor_version_(-1),
va_initialized_(false) {}
VaapiWrapper::VADisplayState::~VADisplayState() {}
bool VaapiWrapper::VADisplayState::Initialize(VAStatus* status) {
va_lock_.AssertAcquired();
if (refcount_++ == 0) {
#if defined(USE_X11)
va_display_ = vaGetDisplay(gfx::GetXDisplay());
#elif defined(USE_OZONE)
va_display_ = vaGetDisplayDRM(drm_fd_.get());
#endif // USE_X11
if (!vaDisplayIsValid(va_display_)) {
LOG(ERROR) << "Could not get a valid VA display";
return false;
}
*status = vaInitialize(va_display_, &major_version_, &minor_version_);
if (*status != VA_STATUS_SUCCESS)
return false;
va_initialized_ = true;
DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
}
if (VAAPIVersionLessThan(0, 34)) {
LOG(ERROR) << "VAAPI version < 0.34 is not supported.";
return false;
}
return true;
}
void VaapiWrapper::VADisplayState::Deinitialize(VAStatus* status) {
va_lock_.AssertAcquired();
if (--refcount_ > 0)
return;
// Must check if vaInitialize completed successfully, to work around a bug in
// libva. The bug was fixed upstream:
// http://lists.freedesktop.org/archives/libva/2013-July/001807.html
// TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once
// the fix has rolled out sufficiently.
if (va_initialized_ && va_display_) {
*status = vaTerminate(va_display_);
}
va_initialized_ = false;
va_display_ = nullptr;
}
#if defined(USE_OZONE)
void VaapiWrapper::VADisplayState::SetDrmFd(base::PlatformFile fd) {
drm_fd_.reset(HANDLE_EINTR(dup(fd)));
}
#endif // USE_OZONE
bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) {
return (major_version_ < major) ||
(major_version_ == major && minor_version_ < minor);
}
} // namespace content } // namespace content
...@@ -134,9 +134,6 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -134,9 +134,6 @@ class CONTENT_EXPORT VaapiWrapper {
gfx::Size dest_size); gfx::Size dest_size);
#endif // USE_X11 #endif // USE_X11
// Returns true if the VAAPI version is less than the specified version.
bool VAAPIVersionLessThan(int major, int minor);
// Get a VAImage from a VASurface and map it into memory. The size and format // Get a VAImage from a VASurface and map it into memory. The size and format
// are derived from the surface. Use GetVaImage() instead if |format| or // are derived from the surface. Use GetVaImage() instead if |format| or
// |size| are different from surface internal representation. The VAImage // |size| are different from surface internal representation. The VAImage
...@@ -191,6 +188,9 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -191,6 +188,9 @@ class CONTENT_EXPORT VaapiWrapper {
VASurfaceID va_surface_id_dest, VASurfaceID va_surface_id_dest,
const gfx::Size& dest_size); const gfx::Size& dest_size);
// Initialize static data before sandbox is enabled.
static void PreSandboxInitialization();
private: private:
struct ProfileInfo { struct ProfileInfo {
VAProfile va_profile; VAProfile va_profile;
...@@ -209,6 +209,51 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -209,6 +209,51 @@ class CONTENT_EXPORT VaapiWrapper {
std::vector<ProfileInfo> supported_profiles_[kCodecModeMax]; std::vector<ProfileInfo> supported_profiles_[kCodecModeMax];
}; };
class VADisplayState {
public:
VADisplayState();
~VADisplayState();
// |va_lock_| must be held on entry.
bool Initialize(VAStatus* status);
void Deinitialize(VAStatus* status);
base::Lock* va_lock() { return &va_lock_; }
VADisplay va_display() const { return va_display_; }
#if defined(USE_OZONE)
void SetDrmFd(base::PlatformFile fd);
#endif // USE_OZONE
private:
friend class base::LazyInstance<VADisplayState>;
// Returns true if the VAAPI version is less than the specified version.
bool VAAPIVersionLessThan(int major, int minor);
// Protected by |va_lock_|.
int refcount_;
// Libva is not thread safe, so we have to do locking for it ourselves.
// This lock is to be taken for the duration of all VA-API calls and for
// the entire job submission sequence in ExecuteAndDestroyPendingBuffers().
base::Lock va_lock_;
#if defined(USE_OZONE)
// Drm fd used to obtain access to the driver interface by VA.
base::ScopedFD drm_fd_;
#endif // USE_OZONE
// The VADisplay handle.
VADisplay va_display_;
// The VAAPI version.
int major_version_, minor_version_;
// True if vaInitialize has been called successfully.
bool va_initialized_;
};
VaapiWrapper(); VaapiWrapper();
bool Initialize(CodecMode mode, VAProfile va_profile); bool Initialize(CodecMode mode, VAProfile va_profile);
...@@ -269,16 +314,15 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -269,16 +314,15 @@ class CONTENT_EXPORT VaapiWrapper {
static VAProfile ProfileToVAProfile(media::VideoCodecProfile profile, static VAProfile ProfileToVAProfile(media::VideoCodecProfile profile,
CodecMode mode); CodecMode mode);
// Libva is not thread safe, so we have to do locking for it ourselves. // Pointer to VADisplayState's member |va_lock_|. Guaranteed to be valid for
// This lock is to be taken for the duration of all VA-API calls and for // the lifetime of VaapiWrapper.
// the entire job submission sequence in ExecuteAndDestroyPendingBuffers(). base::Lock* va_lock_;
base::Lock va_lock_;
// Allocated ids for VASurfaces. // Allocated ids for VASurfaces.
std::vector<VASurfaceID> va_surface_ids_; std::vector<VASurfaceID> va_surface_ids_;
// The VAAPI version. // Singleton instance of VADisplayState.
int major_version_, minor_version_; static base::LazyInstance<VADisplayState> va_display_state_;
// VA handles. // VA handles.
// All valid after successful Initialize() and until Deinitialize(). // All valid after successful Initialize() and until Deinitialize().
...@@ -287,8 +331,6 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -287,8 +331,6 @@ class CONTENT_EXPORT VaapiWrapper {
// Created for the current set of va_surface_ids_ in CreateSurfaces() and // Created for the current set of va_surface_ids_ in CreateSurfaces() and
// valid until DestroySurfaces(). // valid until DestroySurfaces().
VAContextID va_context_id_; VAContextID va_context_id_;
// True if vaInitialize has been called successfully.
bool va_initialized_;
// Data queued up for HW codec, to be committed on next execution. // Data queued up for HW codec, to be committed on next execution.
std::vector<VABufferID> pending_slice_bufs_; std::vector<VABufferID> pending_slice_bufs_;
...@@ -308,11 +350,6 @@ class CONTENT_EXPORT VaapiWrapper { ...@@ -308,11 +350,6 @@ class CONTENT_EXPORT VaapiWrapper {
VAContextID va_vpp_context_id_; VAContextID va_vpp_context_id_;
VABufferID va_vpp_buffer_id_; VABufferID va_vpp_buffer_id_;
#if defined(USE_OZONE)
// Drm file used to obtain access to the driver interface by VA.
base::File drm_file_;
#endif // USE_OZONE
// Singleton variable to store supported profile information for encode and // Singleton variable to store supported profile information for encode and
// decode. // decode.
static base::LazyInstance<LazyProfileInfos> profile_infos_; static base::LazyInstance<LazyProfileInfos> profile_infos_;
......
...@@ -1638,6 +1638,10 @@ int main(int argc, char **argv) { ...@@ -1638,6 +1638,10 @@ int main(int argc, char **argv) {
ui::OzonePlatform::InitializeForUI(); ui::OzonePlatform::InitializeForUI();
#endif #endif
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
content::VaapiWrapper::PreSandboxInitialization();
#endif
content::g_env = content::g_env =
reinterpret_cast<content::VideoDecodeAcceleratorTestEnvironment*>( reinterpret_cast<content::VideoDecodeAcceleratorTestEnvironment*>(
testing::AddGlobalTestEnvironment( testing::AddGlobalTestEnvironment(
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#endif #endif
#if defined(ARCH_CPU_X86_FAMILY) #if defined(ARCH_CPU_X86_FAMILY)
#include "content/common/gpu/media/vaapi_video_encode_accelerator.h" #include "content/common/gpu/media/vaapi_video_encode_accelerator.h"
#include "content/common/gpu/media/vaapi_wrapper.h"
#endif // defined(ARCH_CPU_X86_FAMILY) #endif // defined(ARCH_CPU_X86_FAMILY)
#else #else
#error The VideoEncodeAcceleratorUnittest is not supported on this platform. #error The VideoEncodeAcceleratorUnittest is not supported on this platform.
...@@ -1431,6 +1432,10 @@ int main(int argc, char** argv) { ...@@ -1431,6 +1432,10 @@ int main(int argc, char** argv) {
LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
} }
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
content::VaapiWrapper::PreSandboxInitialization();
#endif
content::g_env = content::g_env =
reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>(
testing::AddGlobalTestEnvironment( testing::AddGlobalTestEnvironment(
......
...@@ -321,7 +321,6 @@ void GpuProcessPolicy::InitGpuBrokerProcess( ...@@ -321,7 +321,6 @@ void GpuProcessPolicy::InitGpuBrokerProcess(
const std::vector<BrokerFilePermission>& permissions_extra) { const std::vector<BrokerFilePermission>& permissions_extra) {
static const char kDriRcPath[] = "/etc/drirc"; static const char kDriRcPath[] = "/etc/drirc";
static const char kDriCard0Path[] = "/dev/dri/card0"; static const char kDriCard0Path[] = "/dev/dri/card0";
static const char kDriRenderNode0Path[] = "/dev/dri/renderD128";
static const char kDevShm[] = "/dev/shm/"; static const char kDevShm[] = "/dev/shm/";
CHECK(broker_process_ == NULL); CHECK(broker_process_ == NULL);
...@@ -329,7 +328,6 @@ void GpuProcessPolicy::InitGpuBrokerProcess( ...@@ -329,7 +328,6 @@ void GpuProcessPolicy::InitGpuBrokerProcess(
// All GPU process policies need these files brokered out. // All GPU process policies need these files brokered out.
std::vector<BrokerFilePermission> permissions; std::vector<BrokerFilePermission> permissions;
permissions.push_back(BrokerFilePermission::ReadWrite(kDriCard0Path)); permissions.push_back(BrokerFilePermission::ReadWrite(kDriCard0Path));
permissions.push_back(BrokerFilePermission::ReadWrite(kDriRenderNode0Path));
permissions.push_back(BrokerFilePermission::ReadOnly(kDriRcPath)); permissions.push_back(BrokerFilePermission::ReadOnly(kDriRcPath));
if (!IsChromeOS()) { if (!IsChromeOS()) {
permissions.push_back( permissions.push_back(
......
...@@ -62,6 +62,10 @@ ...@@ -62,6 +62,10 @@
#include "content/common/sandbox_mac.h" #include "content/common/sandbox_mac.h"
#endif #endif
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
#include "content/common/gpu/media/vaapi_wrapper.h"
#endif
#if defined(SANITIZER_COVERAGE) #if defined(SANITIZER_COVERAGE)
#include <sanitizer/common_interface_defs.h> #include <sanitizer/common_interface_defs.h>
#include <sanitizer/coverage_interface.h> #include <sanitizer/coverage_interface.h>
...@@ -218,6 +222,10 @@ int GpuMain(const MainFunctionParams& parameters) { ...@@ -218,6 +222,10 @@ int GpuMain(const MainFunctionParams& parameters) {
// commandline switches. // commandline switches.
GetGpuInfoFromCommandLine(gpu_info, command_line); GetGpuInfoFromCommandLine(gpu_info, command_line);
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
VaapiWrapper::PreSandboxInitialization();
#endif
// Warm up resources that don't need access to GPUInfo. // Warm up resources that don't need access to GPUInfo.
if (WarmUpSandbox(command_line)) { if (WarmUpSandbox(command_line)) {
#if defined(OS_LINUX) #if defined(OS_LINUX)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment