Index: content/common/gpu/media/vaapi_wrapper.cc |
diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc |
index 219e370e5bdc29475be4555ccc20660528d03500..6be12d237f64f10f71f9af496379041ac198d563 100644 |
--- a/content/common/gpu/media/vaapi_wrapper.cc |
+++ b/content/common/gpu/media/vaapi_wrapper.cc |
@@ -62,6 +62,11 @@ namespace content { |
// and not taken from HW documentation. |
const int kMaxEncoderFramerate = 30; |
+#if defined(USE_OZONE) |
+base::LazyInstance<VaapiWrapper::VADisplayState> |
+ VaapiWrapper::g_va_display_state_ = LAZY_INSTANCE_INITIALIZER; |
+#endif |
+ |
base::LazyInstance<VaapiWrapper::LazyProfileInfos> |
VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; |
@@ -123,10 +128,15 @@ VaapiWrapper::VaapiWrapper() |
: va_display_(NULL), |
va_config_id_(VA_INVALID_ID), |
va_context_id_(VA_INVALID_ID), |
- va_initialized_(false), |
va_vpp_config_id_(VA_INVALID_ID), |
va_vpp_context_id_(VA_INVALID_ID), |
va_vpp_buffer_id_(VA_INVALID_ID) { |
+#if defined(USE_X11) |
+ va_display_state_.reset(new VADisplayState()); |
+ va_lock_ = va_display_state_->va_lock(); |
+#elif defined(USE_OZONE) |
+ va_lock_ = g_va_display_state_.Get().va_lock(); |
+#endif // USE_X11 |
} |
VaapiWrapper::~VaapiWrapper() { |
@@ -223,7 +233,7 @@ VaapiWrapper::GetSupportedDecodeProfiles() { |
} |
void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
VADisplayAttribute item = {VADisplayAttribRenderMode, |
1, // At least support '_LOCAL_OVERLAY'. |
-1, // The maximum possible support 'ALL'. |
@@ -272,7 +282,7 @@ VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { |
VAEntrypoint entrypoint = |
(mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
for (const auto& va_profile : va_profiles) { |
if (!IsEntrypointSupported_Locked(va_profile, entrypoint)) |
continue; |
@@ -312,37 +322,33 @@ bool VaapiWrapper::VaInitialize(const base::Closure& 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_); |
+ |
+ VADisplayState* va_display_state = nullptr; |
#if defined(USE_X11) |
- va_display_ = vaGetDisplay(gfx::GetXDisplay()); |
+ va_display_state = va_display_state_.get(); |
#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()); |
+ va_display_state = &g_va_display_state_.Get(); |
#endif // USE_X11 |
- if (!vaDisplayIsValid(va_display_)) { |
- LOG(ERROR) << "Could not get a valid VA display"; |
+ if (!va_display_state) { |
+ LOG(ERROR) << "Failed to allocate VA display state"; |
return false; |
} |
- VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
- VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", 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."; |
+ VAStatus va_res = VA_STATUS_SUCCESS; |
+ if (!va_display_state->Initialize(&va_res)) { |
+ VA_LOG_ON_ERROR(va_res, "vaInitialize failed"); |
return false; |
} |
+ |
+ va_display_ = va_display_state->GetVADisplay(); |
return true; |
} |
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. |
int max_profiles = vaMaxNumProfiles(va_display_); |
std::vector<VAProfile> supported_profiles( |
@@ -364,7 +370,7 @@ bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { |
bool VaapiWrapper::IsEntrypointSupported_Locked(VAProfile va_profile, |
VAEntrypoint entrypoint) { |
- va_lock_.AssertAcquired(); |
+ va_lock_->AssertAcquired(); |
// Query the driver for supported entrypoints. |
int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
std::vector<VAEntrypoint> supported_entrypoints( |
@@ -396,7 +402,7 @@ bool VaapiWrapper::AreAttribsSupported_Locked( |
VAProfile va_profile, |
VAEntrypoint entrypoint, |
const std::vector<VAConfigAttrib>& required_attribs) { |
- va_lock_.AssertAcquired(); |
+ va_lock_->AssertAcquired(); |
// Query the driver for required attributes. |
std::vector<VAConfigAttrib> attribs = required_attribs; |
for (size_t i = 0; i < required_attribs.size(); ++i) |
@@ -423,7 +429,7 @@ bool VaapiWrapper::GetMaxResolution_Locked( |
VAEntrypoint entrypoint, |
std::vector<VAConfigAttrib>& required_attribs, |
gfx::Size* resolution) { |
- va_lock_.AssertAcquired(); |
+ va_lock_->AssertAcquired(); |
VAConfigID va_config_id; |
VAStatus va_res = vaCreateConfig( |
va_display_, |
@@ -472,7 +478,7 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { |
VAEntrypoint entrypoint = |
(mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); |
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_, |
va_profile, |
entrypoint, |
@@ -485,37 +491,35 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { |
} |
void VaapiWrapper::Deinitialize() { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
if (va_config_id_ != VA_INVALID_ID) { |
VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); |
VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); |
} |
- // 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_) { |
- VAStatus va_res = vaTerminate(va_display_); |
+ VADisplayState* va_display_state = nullptr; |
+ |
+#if defined(USE_X11) |
+ va_display_state = va_display_state_.get(); |
+#elif defined(USE_OZONE) |
+ va_display_state = &g_va_display_state_.Get(); |
+#endif // USE_X11 |
+ |
+ if (va_display_state) { |
+ VAStatus va_res = VA_STATUS_SUCCESS; |
+ va_display_state->Deinitialize(&va_res); |
VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); |
} |
va_config_id_ = VA_INVALID_ID; |
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, |
size_t num_surfaces, |
std::vector<VASurfaceID>* va_surfaces) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
DCHECK(va_surfaces->empty()); |
@@ -553,7 +557,7 @@ bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
} |
void VaapiWrapper::DestroySurfaces() { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; |
if (va_context_id_ != VA_INVALID_ID) { |
@@ -575,7 +579,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( |
unsigned int va_format, |
const gfx::Size& size, |
const std::vector<VASurfaceAttrib>& va_attribs) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
std::vector<VASurfaceAttrib> attribs(va_attribs); |
VASurfaceID va_surface_id; |
@@ -598,7 +602,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( |
} |
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); |
VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); |
@@ -607,7 +611,7 @@ void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { |
bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
size_t size, |
void* buffer) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
VABufferID buffer_id; |
VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, |
@@ -634,7 +638,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer( |
VAEncMiscParameterType misc_param_type, |
size_t size, |
void* buffer) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
VABufferID buffer_id; |
VAStatus va_res = vaCreateBuffer(va_display_, |
@@ -668,7 +672,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer( |
} |
void VaapiWrapper::DestroyPendingBuffers() { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
for (const auto& pending_va_buf : pending_va_bufs_) { |
VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); |
@@ -685,7 +689,7 @@ void VaapiWrapper::DestroyPendingBuffers() { |
} |
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_, |
va_context_id_, |
VAEncCodedBufferType, |
@@ -700,7 +704,7 @@ bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { |
} |
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(); |
iter != coded_buffers_.end(); |
@@ -713,7 +717,7 @@ void VaapiWrapper::DestroyCodedBuffers() { |
} |
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 slice bufs to commit: " << pending_slice_bufs_.size(); |
@@ -759,7 +763,7 @@ bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, |
Pixmap x_pixmap, |
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); |
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
@@ -779,7 +783,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, |
bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id, |
VAImage* image, |
void** mem) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
@@ -807,7 +811,7 @@ bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, |
const gfx::Size& size, |
VAImage* image, |
void** mem) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
@@ -836,7 +840,7 @@ bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, |
} |
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); |
VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
@@ -853,7 +857,7 @@ static void DestroyVAImage(VADisplay va_display, VAImage image) { |
bool VaapiWrapper::UploadVideoFrameToSurface( |
const scoped_refptr<media::VideoFrame>& frame, |
VASurfaceID va_surface_id) { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
VAImage image; |
VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); |
@@ -878,7 +882,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface( |
int ret = 0; |
{ |
- base::AutoUnlock auto_unlock(va_lock_); |
+ base::AutoUnlock auto_unlock(*va_lock_); |
ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), |
frame->stride(media::VideoFrame::kYPlane), |
frame->data(media::VideoFrame::kUPlane), |
@@ -904,7 +908,7 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, |
uint8* target_ptr, |
size_t target_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); |
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
@@ -916,7 +920,7 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, |
DCHECK(target_ptr); |
{ |
- base::AutoUnlock auto_unlock(va_lock_); |
+ base::AutoUnlock auto_unlock(*va_lock_); |
*coded_data_size = 0; |
while (buffer_segment) { |
@@ -953,7 +957,7 @@ bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, |
const gfx::Size& src_size, |
VASurfaceID va_surface_id_dest, |
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. |
if (va_vpp_buffer_id_ == VA_INVALID_ID) { |
@@ -1002,7 +1006,7 @@ bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, |
} |
bool VaapiWrapper::InitializeVpp_Locked() { |
- va_lock_.AssertAcquired(); |
+ va_lock_->AssertAcquired(); |
VA_SUCCESS_OR_RETURN( |
vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0, |
@@ -1025,7 +1029,7 @@ bool VaapiWrapper::InitializeVpp_Locked() { |
} |
void VaapiWrapper::DeinitializeVpp() { |
- base::AutoLock auto_lock(va_lock_); |
+ base::AutoLock auto_lock(*va_lock_); |
if (va_vpp_buffer_id_ != VA_INVALID_ID) { |
vaDestroyBuffer(va_display_, va_vpp_buffer_id_); |
@@ -1042,6 +1046,17 @@ 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); |
+ g_va_display_state_.Get().SetDrmFd(drm_file.GetPlatformFile()); |
+#endif |
+} |
+ |
+// static |
bool VaapiWrapper::PostSandboxInitialization() { |
StubPathMap paths; |
@@ -1087,4 +1102,67 @@ bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( |
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) { |
+ 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) { |
+ 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; |
+} |
+ |
+#if defined(USE_OZONE) |
+void VaapiWrapper::VADisplayState::SetDrmFd(base::PlatformFile fd) { |
+ drm_fd_.reset(dup(fd)); |
piman
2015/05/11 21:54:07
nit: dup needs to be wrapped into a HANDLE_EINTR m
hshi1
2015/05/11 22:26:40
Done.
|
+} |
+#endif // USE_OZONE |
+ |
+bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { |
+ return (major_version_ < major) || |
+ (major_version_ == major && minor_version_ < minor); |
+} |
+ |
} // namespace content |