123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/gpu/vaapi/vaapi_image_decoder.h"
- #include <utility>
- #include "base/logging.h"
- #include "media/gpu/macros.h"
- #include "media/gpu/vaapi/va_surface.h"
- #include "media/gpu/vaapi/vaapi_utils.h"
- #include "media/gpu/vaapi/vaapi_wrapper.h"
- #include "ui/gfx/geometry/size.h"
- #include "ui/gfx/linux/native_pixmap_dmabuf.h"
- namespace media {
- void VAContextAndScopedVASurfaceDeleter::operator()(
- ScopedVASurface* scoped_va_surface) const {
- scoped_va_surface->vaapi_wrapper_->DestroyContext();
- delete scoped_va_surface;
- }
- VaapiImageDecoder::VaapiImageDecoder(VAProfile va_profile)
- : va_profile_(va_profile) {}
- VaapiImageDecoder::~VaapiImageDecoder() = default;
- bool VaapiImageDecoder::Initialize(const ReportErrorToUMACB& error_uma_cb) {
- vaapi_wrapper_ =
- VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile_,
- EncryptionScheme::kUnencrypted, error_uma_cb);
- return !!vaapi_wrapper_;
- }
- VaapiImageDecodeStatus VaapiImageDecoder::Decode(
- base::span<const uint8_t> encoded_image) {
- if (!vaapi_wrapper_) {
- VLOGF(1) << "VaapiImageDecoder has not been initialized";
- scoped_va_context_and_surface_.reset();
- return VaapiImageDecodeStatus::kInvalidState;
- }
- const VaapiImageDecodeStatus status =
- AllocateVASurfaceAndSubmitVABuffers(encoded_image);
- if (status != VaapiImageDecodeStatus::kSuccess) {
- scoped_va_context_and_surface_.reset();
- return status;
- }
- if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
- scoped_va_context_and_surface_->id())) {
- VLOGF(1) << "ExecuteAndDestroyPendingBuffers() failed";
- scoped_va_context_and_surface_.reset();
- return VaapiImageDecodeStatus::kExecuteDecodeFailed;
- }
- return VaapiImageDecodeStatus::kSuccess;
- }
- const ScopedVASurface* VaapiImageDecoder::GetScopedVASurface() const {
- return scoped_va_context_and_surface_.get();
- }
- gpu::ImageDecodeAcceleratorSupportedProfile
- VaapiImageDecoder::GetSupportedProfile() const {
- if (!vaapi_wrapper_) {
- DVLOGF(1) << "The VAAPI has not been initialized";
- return gpu::ImageDecodeAcceleratorSupportedProfile();
- }
- gpu::ImageDecodeAcceleratorSupportedProfile profile;
- profile.image_type = GetType();
- DCHECK_NE(gpu::ImageDecodeAcceleratorType::kUnknown, profile.image_type);
- // Note that since |vaapi_wrapper_| was created successfully, we expect the
- // following call to be successful. Hence the DCHECK.
- const bool got_supported_resolutions = VaapiWrapper::GetSupportedResolutions(
- va_profile_, VaapiWrapper::CodecMode::kDecode,
- profile.min_encoded_dimensions, profile.max_encoded_dimensions);
- DCHECK(got_supported_resolutions);
- // TODO(andrescj): Ideally, we would advertise support for all the formats
- // supported by the driver. However, for now, we will only support exposing
- // YUV 4:2:0 surfaces as DmaBufs.
- DCHECK(VaapiWrapper::GetDecodeSupportedInternalFormats(va_profile_).yuv420);
- profile.subsamplings.push_back(gpu::ImageDecodeAcceleratorSubsampling::k420);
- return profile;
- }
- std::unique_ptr<NativePixmapAndSizeInfo>
- VaapiImageDecoder::ExportAsNativePixmapDmaBuf(VaapiImageDecodeStatus* status) {
- DCHECK(status);
- // We need to take ownership of the ScopedVASurface so that the next Decode()
- // doesn't attempt to use the same ScopedVASurface. Otherwise, it could
- // overwrite the result of the current decode before it's used by the caller.
- // This ScopedVASurface will self-clean at the end of this scope, but the
- // underlying buffer should stay alive because of the exported FDs.
- ScopedVAContextAndSurface temp_scoped_va_surface =
- std::move(scoped_va_context_and_surface_);
- if (!temp_scoped_va_surface) {
- DVLOGF(1) << "No decoded image available";
- *status = VaapiImageDecodeStatus::kInvalidState;
- return nullptr;
- }
- DCHECK(temp_scoped_va_surface->IsValid());
- std::unique_ptr<NativePixmapAndSizeInfo> exported_pixmap =
- vaapi_wrapper_->ExportVASurfaceAsNativePixmapDmaBuf(
- *temp_scoped_va_surface);
- if (!exported_pixmap) {
- *status = VaapiImageDecodeStatus::kCannotExportSurface;
- return nullptr;
- }
- DCHECK_EQ(temp_scoped_va_surface->size(),
- exported_pixmap->pixmap->GetBufferSize());
- *status = VaapiImageDecodeStatus::kSuccess;
- return exported_pixmap;
- }
- } // namespace media
|