diff options
Diffstat (limited to 'chromium/media/gpu/vaapi/vaapi_wrapper.cc')
-rw-r--r-- | chromium/media/gpu/vaapi/vaapi_wrapper.cc | 409 |
1 files changed, 265 insertions, 144 deletions
diff --git a/chromium/media/gpu/vaapi/vaapi_wrapper.cc b/chromium/media/gpu/vaapi/vaapi_wrapper.cc index cdbd4fb2c73..dc1b731ea25 100644 --- a/chromium/media/gpu/vaapi/vaapi_wrapper.cc +++ b/chromium/media/gpu/vaapi/vaapi_wrapper.cc @@ -5,6 +5,7 @@ #include "media/gpu/vaapi/vaapi_wrapper.h" #include <dlfcn.h> +#include <drm_fourcc.h> #include <string.h> #include <sys/types.h> #include <unistd.h> @@ -42,6 +43,7 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "media/base/media_switches.h" +#include "media/base/video_codecs.h" #include "media/base/video_frame.h" #include "media/base/video_types.h" #include "media/gpu/macros.h" @@ -53,6 +55,7 @@ #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/linux/drm_util_linux.h" #include "ui/gfx/linux/native_pixmap_dmabuf.h" #include "ui/gfx/native_pixmap.h" #include "ui/gfx/native_pixmap_handle.h" @@ -258,6 +261,152 @@ bool UseGlobalVaapiLock(media::VAImplementation implementation_type) { base::FeatureList::IsEnabled(media::kGlobalVaapiLock); } +bool FillVADRMPRIMESurfaceDescriptor(const gfx::NativePixmap& pixmap, + VADRMPRIMESurfaceDescriptor& descriptor) { + memset(&descriptor, 0, sizeof(VADRMPRIMESurfaceDescriptor)); + + const gfx::BufferFormat buffer_format = pixmap.GetBufferFormat(); + const uint32_t va_fourcc = BufferFormatToVAFourCC(buffer_format); + DCHECK(va_fourcc); + + const gfx::Size size = pixmap.GetBufferSize(); + const size_t num_planes = pixmap.GetNumberOfPlanes(); + const int drm_fourcc = ui::GetFourCCFormatFromBufferFormat(buffer_format); + if (drm_fourcc == DRM_FORMAT_INVALID) { + LOG(ERROR) << "Failed to get the DRM format from the buffer format"; + return false; + } + if (num_planes > std::size(descriptor.objects)) { + LOG(ERROR) << "Too many planes in the NativePixmap; got " << num_planes + << " but the maximum number is " + << std::size(descriptor.objects); + return false; + } + static_assert(std::size(VADRMPRIMESurfaceDescriptor{}.layers) == + std::size(VADRMPRIMESurfaceDescriptor{}.objects)); + static_assert( + std::size(VADRMPRIMESurfaceDescriptor{}.layers[0].object_index) == + std::size(VADRMPRIMESurfaceDescriptor{}.objects)); + static_assert(std::size(VADRMPRIMESurfaceDescriptor{}.layers[0].offset) == + std::size(VADRMPRIMESurfaceDescriptor{}.objects)); + static_assert(std::size(VADRMPRIMESurfaceDescriptor{}.layers[0].pitch) == + std::size(VADRMPRIMESurfaceDescriptor{}.objects)); + + descriptor.fourcc = va_fourcc; + descriptor.width = base::checked_cast<uint32_t>(size.width()); + descriptor.height = base::checked_cast<uint32_t>(size.height()); + + // We can pass the planes as separate layers or all in one layer. The choice + // of doing the latter was arbitrary. + descriptor.num_layers = 1u; + descriptor.layers[0].drm_format = base::checked_cast<uint32_t>(drm_fourcc); + descriptor.layers[0].num_planes = base::checked_cast<uint32_t>(num_planes); + + descriptor.num_objects = base::checked_cast<uint32_t>(num_planes); + for (size_t i = 0u; i < num_planes; i++) { + const int dma_buf_fd = pixmap.GetDmaBufFd(i); + if (dma_buf_fd < 0) { + LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; + return false; + } + const off_t data_size = lseek(dma_buf_fd, /*offset=*/0, SEEK_END); + if (data_size == static_cast<off_t>(-1)) { + PLOG(ERROR) << "Failed to get the size of the dma-buf"; + return false; + } + if (lseek(dma_buf_fd, /*offset=*/0, SEEK_SET) == static_cast<off_t>(-1)) { + PLOG(ERROR) << "Failed to reset the file offset of the dma-buf"; + return false; + } + + descriptor.objects[i].fd = dma_buf_fd; + descriptor.objects[i].size = base::checked_cast<uint32_t>(data_size); + descriptor.objects[i].drm_format_modifier = + pixmap.GetBufferFormatModifier(); + + descriptor.layers[0].object_index[i] = base::checked_cast<uint32_t>(i); + if (!base::IsValueInRangeForNumericType<uint32_t>( + pixmap.GetDmaBufOffset(i))) { + LOG(ERROR) << "The offset for plane " << i << " is out-of-range"; + return false; + } + descriptor.layers[0].offset[i] = + base::checked_cast<uint32_t>(pixmap.GetDmaBufOffset(i)); + descriptor.layers[0].pitch[i] = pixmap.GetDmaBufPitch(i); + } + + return true; +} + +struct VASurfaceAttribExternalBuffersAndFD { + VASurfaceAttribExternalBuffers va_attrib_extbuf; + uintptr_t fd; +}; + +bool FillVASurfaceAttribExternalBuffers( + const gfx::NativePixmap& pixmap, + VASurfaceAttribExternalBuffersAndFD& va_attrib_extbuf_and_fd) { + VASurfaceAttribExternalBuffers& va_attrib_extbuf = + va_attrib_extbuf_and_fd.va_attrib_extbuf; + memset(&va_attrib_extbuf_and_fd, 0, + sizeof(VASurfaceAttribExternalBuffersAndFD)); + + const uint32_t va_fourcc = BufferFormatToVAFourCC(pixmap.GetBufferFormat()); + DCHECK(va_fourcc); + + const gfx::Size size = pixmap.GetBufferSize(); + const size_t num_planes = pixmap.GetNumberOfPlanes(); + + va_attrib_extbuf.pixel_format = va_fourcc; + va_attrib_extbuf.width = base::checked_cast<uint32_t>(size.width()); + va_attrib_extbuf.height = base::checked_cast<uint32_t>(size.height()); + + static_assert(std::size(VASurfaceAttribExternalBuffers{}.pitches) == + std::size(VASurfaceAttribExternalBuffers{}.offsets)); + if (num_planes > std::size(va_attrib_extbuf.pitches)) { + LOG(ERROR) << "Too many planes in the NativePixmap; got " << num_planes + << " but the maximum number is " + << std::size(va_attrib_extbuf.pitches); + return false; + } + for (size_t i = 0; i < num_planes; ++i) { + va_attrib_extbuf.pitches[i] = pixmap.GetDmaBufPitch(i); + va_attrib_extbuf.offsets[i] = + base::checked_cast<uint32_t>(pixmap.GetDmaBufOffset(i)); + DVLOG(4) << "plane " << i << ": pitch: " << va_attrib_extbuf.pitches[i] + << " offset: " << va_attrib_extbuf.offsets[i]; + } + va_attrib_extbuf.num_planes = base::checked_cast<uint32_t>(num_planes); + + const int dma_buf_fd = pixmap.GetDmaBufFd(0); + if (dma_buf_fd < 0) { + LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; + return false; + } + const off_t data_size = lseek(dma_buf_fd, /*offset=*/0, SEEK_END); + if (data_size == static_cast<off_t>(-1)) { + PLOG(ERROR) << "Failed to get the size of the dma-buf"; + return false; + } + if (lseek(dma_buf_fd, /*offset=*/0, SEEK_SET) == static_cast<off_t>(-1)) { + PLOG(ERROR) << "Failed to reset the file offset of the dma-buf"; + return false; + } + // If the data size doesn't fit in a uint32_t, we probably have bigger + // problems. + va_attrib_extbuf.data_size = base::checked_cast<uint32_t>(data_size); + + // We only have to pass the first file descriptor to a driver. A VA-API driver + // shall create a VASurface from the single fd correctly. + va_attrib_extbuf_and_fd.fd = base::checked_cast<uintptr_t>(dma_buf_fd); + va_attrib_extbuf.buffers = &va_attrib_extbuf_and_fd.fd; + va_attrib_extbuf.num_buffers = 1u; + + DCHECK_EQ(va_attrib_extbuf.flags, 0u); + DCHECK_EQ(va_attrib_extbuf.private_data, nullptr); + return true; +} + } // namespace namespace media { @@ -448,6 +597,7 @@ const ProfileCodecMap& GetProfileCodecMap() { // {AV1PROFILE_PROFILE_HIGH, VAProfileAV1Profile1}, #if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER) {HEVCPROFILE_MAIN, VAProfileHEVCMain}, + {HEVCPROFILE_MAIN_STILL_PICTURE, VAProfileHEVCMain}, {HEVCPROFILE_MAIN10, VAProfileHEVCMain10}, #endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER) }); @@ -963,6 +1113,10 @@ class VASupportedProfiles { // Determines if |mode| supports |va_profile| (and |va_entrypoint| if defined // and valid). If so, returns a const pointer to its ProfileInfo, otherwise // returns nullptr. + // TODO(hiroh): If VAEntrypoint is kVAEntrypointInvalid, the default entry + // point acquired by GetDefaultVaEntryPoint() is used. If the default entry + // point is not supported, the earlier supported entrypoint in + // |kAllowedEntryPopints| is used. const ProfileInfo* IsProfileSupported( VaapiWrapper::CodecMode mode, VAProfile va_profile, @@ -1433,6 +1587,24 @@ bool IsLowPowerEncSupported(VAProfile va_profile) { return false; } +bool IsVBREncodingSupported(VAProfile va_profile) { + if (!base::FeatureList::IsEnabled(kChromeOSHWVBREncoding)) + return false; + + auto mode = VaapiWrapper::CodecMode::kCodecModeMax; + switch (va_profile) { + case VAProfileH264ConstrainedBaseline: + case VAProfileH264Main: + case VAProfileH264High: + mode = VaapiWrapper::CodecMode::kEncodeVariableBitrate; + break; + default: + return false; + } + + return VASupportedProfiles::Get().IsProfileSupported(mode, va_profile); +} + } // namespace NativePixmapAndSizeInfo::NativePixmapAndSizeInfo() = default; @@ -1550,8 +1722,13 @@ VaapiWrapper::GetSupportedEncodeProfiles() { constexpr int kMaxEncoderFramerate = 30; profile.max_framerate_numerator = kMaxEncoderFramerate; profile.max_framerate_denominator = 1; - // TODO(b/193680666): remove hard-coding when VBR is supported profile.rate_control_modes = media::VideoEncodeAccelerator::kConstantMode; + // This code assumes that the resolutions are the same between CBR and VBR. + // This is checked in a test in vaapi_unittest.cc: VbrAndCbrResolutionsMatch + if (IsVBREncodingSupported(va_profile)) { + profile.rate_control_modes |= + media::VideoEncodeAccelerator::kVariableMode; + } profile.scalability_modes = GetSupportedScalabilityModes(media_profile, va_profile); profiles.push_back(profile); @@ -1616,26 +1793,18 @@ bool VaapiWrapper::IsDecodingSupportedForInternalFormat( } // static -bool VaapiWrapper::GetDecodeMinResolution(VAProfile va_profile, - gfx::Size* min_size) { +bool VaapiWrapper::GetSupportedResolutions(VAProfile va_profile, + CodecMode codec_mode, + gfx::Size& min_size, + gfx::Size& max_size) { const VASupportedProfiles::ProfileInfo* profile_info = - VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile); - if (!profile_info) + VASupportedProfiles::Get().IsProfileSupported(codec_mode, va_profile); + if (!profile_info || profile_info->max_resolution.IsEmpty()) return false; - *min_size = gfx::Size(std::max(1, profile_info->min_resolution.width()), - std::max(1, profile_info->min_resolution.height())); - return true; -} -// static -bool VaapiWrapper::GetDecodeMaxResolution(VAProfile va_profile, - gfx::Size* max_size) { - const VASupportedProfiles::ProfileInfo* profile_info = - VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile); - if (!profile_info) - return false; - - *max_size = profile_info->max_resolution; + min_size = gfx::Size(std::max(1, profile_info->min_resolution.width()), + std::max(1, profile_info->min_resolution.height())); + max_size = profile_info->max_resolution; return true; } @@ -1921,7 +2090,7 @@ bool VaapiWrapper::CreateProtectedSession( const VAProfile va_profile = VAProfileProtected; const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode_, va_profile); { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); std::vector<VAConfigAttrib> required_attribs; if (!GetRequiredAttribs(va_lock_, va_display_, mode_, va_profile, entrypoint, &required_attribs)) { @@ -1958,7 +2127,7 @@ bool VaapiWrapper::CreateProtectedSession( std::unique_ptr<ScopedVABuffer> hw_update = CreateVABuffer( VAProtectedSessionExecuteBufferType, sizeof(hw_update_buf)); { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); constexpr size_t kHwIdentifierMaxSize = 64; memset(&hw_update_buf, 0, sizeof(hw_update_buf)); hw_update_buf.function_id = VA_TEE_EXEC_TEE_FUNCID_HW_UPDATE; @@ -2032,7 +2201,7 @@ bool VaapiWrapper::IsProtectedSessionDead( tee_exec_buf.output.data_size = sizeof(alive); tee_exec_buf.output.data = &alive; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VABufferID buf_id; VAStatus va_res = vaCreateBuffer( va_display_, va_protected_session_id, VAProtectedSessionExecuteBufferType, @@ -2065,7 +2234,7 @@ void VaapiWrapper::DestroyProtectedSession() { #if BUILDFLAG(IS_CHROMEOS_ASH) if (va_protected_session_id_ == VA_INVALID_ID) return; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaDestroyProtectedSession(va_display_, va_protected_session_id_); VA_LOG_ON_ERROR(va_res, VaapiFunctions::kVADestroyProtectedSession); @@ -2088,7 +2257,7 @@ bool VaapiWrapper::CreateContext(const gfx::Size& size) { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); DVLOG(2) << "Creating context"; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); // vaCreateContext() doesn't really need an array of VASurfaceIDs (see // https://lists.01.org/pipermail/intel-vaapi-media/2017-July/000052.html and @@ -2147,65 +2316,34 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap( CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); const gfx::BufferFormat buffer_format = pixmap->GetBufferFormat(); - - const uint32_t va_fourcc = BufferFormatToVAFourCC(buffer_format); - if (!va_fourcc) { + if (!BufferFormatToVAFourCC(buffer_format)) { LOG(ERROR) << "Failed to get the VA fourcc from the buffer format"; return nullptr; } - const size_t num_planes = pixmap->GetNumberOfPlanes(); - - // Create a VASurface for a NativePixmap by importing the underlying dmabufs. - const gfx::Size size = pixmap->GetBufferSize(); - VASurfaceAttribExternalBuffers va_attrib_extbuf{}; - va_attrib_extbuf.pixel_format = va_fourcc; - va_attrib_extbuf.width = base::checked_cast<uint32_t>(size.width()); - va_attrib_extbuf.height = base::checked_cast<uint32_t>(size.height()); - - static_assert(std::size(va_attrib_extbuf.pitches) == - std::size(va_attrib_extbuf.offsets)); - if (num_planes > std::size(va_attrib_extbuf.pitches)) { - LOG(ERROR) << "Too many planes in the NativePixmap; got " << num_planes - << " but the maximum number is " - << std::size(va_attrib_extbuf.pitches); - return nullptr; - } - for (size_t i = 0; i < num_planes; ++i) { - va_attrib_extbuf.pitches[i] = pixmap->GetDmaBufPitch(i); - va_attrib_extbuf.offsets[i] = - base::checked_cast<uint32_t>(pixmap->GetDmaBufOffset(i)); - DVLOG(4) << "plane " << i << ": pitch: " << va_attrib_extbuf.pitches[i] - << " offset: " << va_attrib_extbuf.offsets[i]; - } - va_attrib_extbuf.num_planes = base::checked_cast<uint32_t>(num_planes); + // TODO(b/233894465): use the DRM_PRIME_2 API with the Mesa Gallium driver + // when AMD supports it. + // TODO(b/233924862): use the DRM_PRIME_2 API with protected content. + // TODO(b/233929647): use the DRM_PRIME_2 API with the i965 driver. + // TODO(b/236746283): remove the kNoModifier check once the modifier is + // plumbed for JPEG decoding and encoding. + const bool use_drm_prime_2 = + GetImplementationType() == VAImplementation::kIntelIHD && + !protected_content && + pixmap->GetBufferFormatModifier() != gfx::NativePixmapHandle::kNoModifier; + + union { + VADRMPRIMESurfaceDescriptor descriptor; + VASurfaceAttribExternalBuffersAndFD va_attrib_extbuf_and_fd; + }; - const int dma_buf_fd = pixmap->GetDmaBufFd(0); - if (dma_buf_fd < 0) { - LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; - return nullptr; - } - const off_t data_size = lseek(dma_buf_fd, /*offset=*/0, SEEK_END); - if (data_size == static_cast<off_t>(-1)) { - PLOG(ERROR) << "Failed to get the size of the dma-buf"; - return nullptr; - } - if (lseek(dma_buf_fd, /*offset=*/0, SEEK_SET) == static_cast<off_t>(-1)) { - PLOG(ERROR) << "Failed to reset the file offset of the dma-buf"; - return nullptr; + if (use_drm_prime_2) { + if (!FillVADRMPRIMESurfaceDescriptor(*pixmap, descriptor)) + return nullptr; + } else { + if (!FillVASurfaceAttribExternalBuffers(*pixmap, va_attrib_extbuf_and_fd)) + return nullptr; } - // If the data size doesn't fit in a uint32_t, we probably have bigger - // problems. - va_attrib_extbuf.data_size = base::checked_cast<uint32_t>(data_size); - - // We only have to pass the first file descriptor to a driver. A VA-API driver - // shall create a VASurface from the single fd correctly. - uintptr_t fd = base::checked_cast<uintptr_t>(dma_buf_fd); - va_attrib_extbuf.buffers = &fd; - va_attrib_extbuf.num_buffers = 1u; - - DCHECK_EQ(va_attrib_extbuf.flags, 0u); - DCHECK_EQ(va_attrib_extbuf.private_data, nullptr); unsigned int va_format = base::strict_cast<unsigned int>(BufferFormatToVARTFormat(buffer_format)); @@ -2215,10 +2353,12 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap( } if (protected_content) { - if (GetImplementationType() == VAImplementation::kMesaGallium) + if (GetImplementationType() == VAImplementation::kMesaGallium) { va_format |= VA_RT_FORMAT_PROTECTED; - else - va_attrib_extbuf.flags = VA_SURFACE_EXTBUF_DESC_PROTECTED; + } else { + va_attrib_extbuf_and_fd.va_attrib_extbuf.flags = + VA_SURFACE_EXTBUF_DESC_PROTECTED; + } } std::vector<VASurfaceAttrib> va_attribs(2); @@ -2226,16 +2366,21 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap( va_attribs[0].type = VASurfaceAttribMemoryType; va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; va_attribs[0].value.type = VAGenericValueTypeInteger; - va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + va_attribs[0].value.value.i = use_drm_prime_2 + ? VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 + : VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; va_attribs[1].value.type = VAGenericValueTypePointer; - va_attribs[1].value.value.p = &va_attrib_extbuf; + va_attribs[1].value.value.p = use_drm_prime_2 + ? static_cast<void*>(&descriptor) + : &va_attrib_extbuf_and_fd.va_attrib_extbuf; + const gfx::Size size = pixmap->GetBufferSize(); VASurfaceID va_surface_id = VA_INVALID_ID; { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaCreateSurfaces( va_display_, va_format, base::checked_cast<unsigned int>(size.width()), base::checked_cast<unsigned int>(size.height()), &va_surface_id, 1, @@ -2285,7 +2430,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForUserPtr( VASurfaceID va_surface_id = VA_INVALID_ID; const unsigned int va_format = VA_RT_FORMAT_RGBP; { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaCreateSurfaces( va_display_, va_format, base::checked_cast<unsigned int>(size.width()), base::checked_cast<unsigned int>(size.height()), &va_surface_id, 1, @@ -2321,7 +2466,7 @@ VaapiWrapper::ExportVASurfaceAsNativePixmapDmaBufUnwrapped( DCHECK(!va_surface_size.IsEmpty()); VADRMPRIMESurfaceDescriptor descriptor; { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, nullptr); va_res = vaExportSurfaceHandle( @@ -2442,7 +2587,7 @@ bool VaapiWrapper::SyncSurface(VASurfaceID va_surface_id) { sequence_checker_.CalledOnValidSequence()); DCHECK_NE(va_surface_id, VA_INVALID_ID); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, false); @@ -2455,7 +2600,7 @@ bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); TRACE_EVENT0("media,gpu", "VaapiWrapper::SubmitBuffer"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); return SubmitBuffer_Locked({va_buffer_type, size, data}); } @@ -2464,7 +2609,7 @@ bool VaapiWrapper::SubmitBuffers( CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); TRACE_EVENT0("media,gpu", "VaapiWrapper::SubmitBuffers"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); for (const VABufferDescriptor& va_buffer : va_buffers) { if (!SubmitBuffer_Locked(va_buffer)) return false; @@ -2476,7 +2621,7 @@ void VaapiWrapper::DestroyPendingBuffers() { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); TRACE_EVENT0("media,gpu", "VaapiWrapper::DestroyPendingBuffers"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); DestroyPendingBuffers_Locked(); } @@ -2495,7 +2640,7 @@ void VaapiWrapper::DestroyPendingBuffers_Locked() { bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); bool result = Execute_Locked(va_surface_id, pending_va_buffers_); DestroyPendingBuffers_Locked(); return result; @@ -2509,7 +2654,7 @@ bool VaapiWrapper::MapAndCopyAndExecute( DCHECK_NE(va_surface_id, VA_INVALID_SURFACE); TRACE_EVENT0("media,gpu", "VaapiWrapper::MapAndCopyAndExecute"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); std::vector<VABufferID> va_buffer_ids; for (const auto& va_buffer : va_buffers) { @@ -2532,7 +2677,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, gfx::Size dest_size) { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, false); @@ -2555,7 +2700,7 @@ std::unique_ptr<ScopedVAImage> VaapiWrapper::CreateVaImage( sequence_checker_.CalledOnValidSequence()); std::unique_ptr<ScopedVAImage> scoped_image; { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, nullptr); @@ -2572,7 +2717,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface(const VideoFrame& frame, CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); TRACE_EVENT0("media,gpu", "VaapiWrapper::UploadVideoFrameToSurface"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); TRACE_EVENT0("media,gpu", "VaapiWrapper::UploadVideoFrameToSurfaceLocked"); if (frame.visible_rect().origin() != gfx::Point(0, 0)) { @@ -2634,42 +2779,18 @@ bool VaapiWrapper::UploadVideoFrameToSurface(const VideoFrame& frame, std::unique_ptr<base::AutoUnlock> auto_unlock; if (va_lock_) auto_unlock = std::make_unique<base::AutoUnlock>(*va_lock_); - switch (frame.format()) { - case PIXEL_FORMAT_I420: - ret = libyuv::I420ToNV12( - frame.data(VideoFrame::kYPlane), frame.stride(VideoFrame::kYPlane), - frame.data(VideoFrame::kUPlane), frame.stride(VideoFrame::kUPlane), - frame.data(VideoFrame::kVPlane), frame.stride(VideoFrame::kVPlane), - image_ptr + image.offsets[0], image.pitches[0], - image_ptr + image.offsets[1], image.pitches[1], - visible_size.width(), visible_size.height()); - break; - case PIXEL_FORMAT_NV12: { - int uv_width = visible_size.width(); - if (visible_size.width() % 2 != 0 && - !base::CheckAdd<int>(visible_size.width(), 1) - .AssignIfValid(&uv_width)) { - return false; - } - - int uv_height = 0; - if (!(base::CheckAdd<int>(visible_size.height(), 1) / 2) - .AssignIfValid(&uv_height)) { - return false; - } - - libyuv::CopyPlane(frame.data(VideoFrame::kYPlane), - frame.stride(VideoFrame::kYPlane), - image_ptr + image.offsets[0], image.pitches[0], - visible_size.width(), visible_size.height()); - libyuv::CopyPlane(frame.data(VideoFrame::kUVPlane), - frame.stride(VideoFrame::kUVPlane), - image_ptr + image.offsets[1], image.pitches[1], - uv_width, uv_height); - } break; - default: - LOG(ERROR) << "Unsupported pixel format: " << frame.format(); - return false; + if (frame.format() == PIXEL_FORMAT_I420) { + ret = libyuv::I420ToNV12( + frame.data(VideoFrame::kYPlane), frame.stride(VideoFrame::kYPlane), + frame.data(VideoFrame::kUPlane), frame.stride(VideoFrame::kUPlane), + frame.data(VideoFrame::kVPlane), frame.stride(VideoFrame::kVPlane), + image_ptr + image.offsets[0], image.pitches[0], + image_ptr + image.offsets[1], image.pitches[1], visible_size.width(), + visible_size.height()); + } else { + LOG(ERROR) << "Unsupported pixel format: " + << VideoPixelFormatToString(frame.format()); + return false; } } if (needs_va_put_image) { @@ -2686,7 +2807,7 @@ std::unique_ptr<ScopedVABuffer> VaapiWrapper::CreateVABuffer(VABufferType type, CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); TRACE_EVENT0("media,gpu", "VaapiWrapper::CreateVABuffer"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); TRACE_EVENT2("media,gpu", "VaapiWrapper::CreateVABufferLocked", "type", type, "size", size); #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -2707,7 +2828,7 @@ uint64_t VaapiWrapper::GetEncodedChunkSize(VABufferID buffer_id, CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); TRACE_EVENT0("media,gpu", "VaapiWrapper::GetEncodedChunkSize"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); TRACE_EVENT0("media,gpu", "VaapiWrapper::GetEncodedChunkSizeLocked"); // vaSyncSurface() is not necessary on Intel platforms as long as there is a @@ -2745,7 +2866,7 @@ bool VaapiWrapper::DownloadFromVABuffer( sequence_checker_.CalledOnValidSequence()); DCHECK(target_ptr); TRACE_EVENT0("media,gpu", "VaapiWrapper::DownloadFromVABuffer"); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); TRACE_EVENT0("media,gpu", "VaapiWrapper::DownloadFromVABufferLocked"); // vaSyncSurface() is not necessary on Intel platforms as long as there is a @@ -2803,7 +2924,7 @@ bool VaapiWrapper::GetVAEncMaxNumOfRefFrames(VideoCodecProfile profile, VAConfigAttrib attrib; attrib.type = VAConfigAttribEncMaxRefFrames; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAStatus va_res = vaGetConfigAttributes(va_display_, va_profile, va_entrypoint_, &attrib, 1); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVAGetConfigAttributes, false); @@ -2822,7 +2943,7 @@ bool VaapiWrapper::GetSupportedPackedHeaders(VideoCodecProfile profile, ProfileToVAProfile(profile, CodecMode::kEncodeConstantBitrate); VAConfigAttrib attrib{}; attrib.type = VAConfigAttribEncPackedHeaders; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); const VAStatus va_res = vaGetConfigAttributes(va_display_, va_profile, va_entrypoint_, &attrib, 1); VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVAGetConfigAttributes, false); @@ -2836,7 +2957,7 @@ bool VaapiWrapper::GetSupportedPackedHeaders(VideoCodecProfile profile, bool VaapiWrapper::IsRotationSupported() { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); VAProcPipelineCaps pipeline_caps; memset(&pipeline_caps, 0, sizeof(pipeline_caps)); VAStatus va_res = vaQueryVideoProcPipelineCaps(va_display_, va_context_id_, @@ -2864,7 +2985,7 @@ bool VaapiWrapper::BlitSurface(const VASurface& va_surface_src, CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); DCHECK_EQ(mode_, kVideoProcess); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); // Create a buffer for VPP if it has not been created. if (!va_buffer_for_vpp_) { @@ -3045,7 +3166,7 @@ bool VaapiWrapper::Initialize(VAProfile va_profile, const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode_, va_profile); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); std::vector<VAConfigAttrib> required_attribs; if (!GetRequiredAttribs(va_lock_, va_display_, mode_, va_profile, entrypoint, &required_attribs)) { @@ -3081,7 +3202,7 @@ void VaapiWrapper::Deinitialize() { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); #if BUILDFLAG(IS_CHROMEOS_ASH) if (va_protected_session_id_ != VA_INVALID_ID) { VAStatus va_res = @@ -3122,7 +3243,7 @@ bool VaapiWrapper::VaInitialize( } { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); va_display_ = VADisplayState::Get()->va_display(); DCHECK(va_display_) << "VADisplayState hasn't been properly Initialize()d"; } @@ -3132,7 +3253,7 @@ bool VaapiWrapper::VaInitialize( void VaapiWrapper::DestroyContext() { CHECK(!enforce_sequence_affinity_ || sequence_checker_.CalledOnValidSequence()); - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); DVLOG(2) << "Destroying context"; if (va_context_id_ != VA_INVALID_ID) { @@ -3180,7 +3301,7 @@ bool VaapiWrapper::CreateSurfaces( VAStatus va_res; { - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); va_res = vaCreateSurfaces( va_display_, va_format, base::checked_cast<unsigned int>(size.width()), base::checked_cast<unsigned int>(size.height()), va_surfaces->data(), @@ -3227,7 +3348,7 @@ VaapiWrapper::CreateScopedVASurfaces( attribs[1].value.type = VAGenericValueTypeInteger; attribs[1].value.value.i = base::checked_cast<int32_t>(*va_fourcc); } - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); std::vector<VASurfaceID> va_surface_ids(num_surfaces, VA_INVALID_ID); const VAStatus va_res = vaCreateSurfaces( va_display_, va_rt_format, base::checked_cast<unsigned int>(size.width()), @@ -3263,7 +3384,7 @@ void VaapiWrapper::DestroySurfaces(std::vector<VASurfaceID> va_surfaces) { if (va_surfaces.empty()) return; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); const VAStatus va_res = vaDestroySurfaces(va_display_, va_surfaces.data(), va_surfaces.size()); VA_LOG_ON_ERROR(va_res, VaapiFunctions::kVADestroySurfaces); @@ -3275,7 +3396,7 @@ void VaapiWrapper::DestroySurface(VASurfaceID va_surface_id) { if (va_surface_id == VA_INVALID_SURFACE) return; DVLOG(3) << __func__ << " " << va_surface_id; - base::AutoLockMaybe auto_lock(va_lock_); + base::AutoLockMaybe auto_lock(va_lock_.get()); const VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); VA_LOG_ON_ERROR(va_res, VaapiFunctions::kVADestroySurfaces); } |