blob: 98d5e39cccb2a5b358c69d2bb22246f3c6ef6e0d [file] [log] [blame]
// Copyright 2018 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.
#ifndef MEDIA_GPU_VAAPI_VAAPI_UTILS_H_
#define MEDIA_GPU_VAAPI_VAAPI_UTILS_H_
#include <va/va.h>
#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/thread_annotations.h"
#include "ui/gfx/geometry/size.h"
namespace base {
class Lock;
}
namespace media {
class VaapiWrapper;
class Vp8ReferenceFrameVector;
struct VAContextAndScopedVASurfaceDeleter;
struct Vp8FrameHeader;
// Class to map a given VABuffer, identified by |buffer_id|, for its lifetime.
// This class must operate under |lock_| acquired.
class ScopedVABufferMapping {
public:
// |release_callback| will be called if the mapping of the buffer failed.
ScopedVABufferMapping(const base::Lock* lock,
VADisplay va_display,
VABufferID buffer_id,
base::OnceCallback<void(VABufferID)> release_callback =
base::NullCallback());
ScopedVABufferMapping(const ScopedVABufferMapping&) = delete;
ScopedVABufferMapping& operator=(const ScopedVABufferMapping&) = delete;
~ScopedVABufferMapping();
bool IsValid() const { return !!va_buffer_data_; }
void* data() const {
DCHECK(IsValid());
return va_buffer_data_;
}
// Explicit destruction method, to retrieve the success/error result. It is
// safe to call this method several times.
VAStatus Unmap();
private:
const base::Lock* lock_; // Only for AssertAcquired() calls.
const VADisplay va_display_;
const VABufferID buffer_id_;
void* va_buffer_data_ = nullptr;
};
// This class tracks the VABuffer life cycle from vaCreateBuffer() to
// vaDestroyBuffer(). Users of this class are responsible for mapping and
// unmapping the buffer as needed. The destructor acquires |lock|, but the user
// of this class must acquire the lock prior to construction.
class ScopedVABuffer {
public:
// Creates ScopedVABuffer. Returns nullptr if creating the va buffer fails.
static std::unique_ptr<ScopedVABuffer> Create(base::Lock* lock,
VADisplay va_display,
VAContextID va_context_id,
VABufferType va_buffer_type,
size_t size);
static std::unique_ptr<ScopedVABuffer>
CreateForTesting(VABufferID buffer_id, VABufferType buffer_type, size_t size);
ScopedVABuffer(const ScopedVABuffer&) = delete;
ScopedVABuffer& operator=(const ScopedVABuffer&) = delete;
~ScopedVABuffer();
VABufferID id() const { return va_buffer_id_; }
VABufferType type() const { return va_buffer_type_; }
size_t size() const { return size_; }
private:
ScopedVABuffer(base::Lock* lock,
VADisplay va_display,
VABufferID va_buffer_id,
VABufferType va_buffer_type,
size_t size);
base::Lock* const lock_;
const VADisplay va_display_ GUARDED_BY(lock_);
const VABufferID va_buffer_id_;
const VABufferType va_buffer_type_;
const size_t size_;
};
// This class tracks the VAImage life cycle from vaCreateImage() - vaGetImage()
// to vaDestroyImage(). In between creation and destruction, image()->buf will
// try to be be mapped on user space using a ScopedVABufferMapping. All
// resources will be cleaned up appropriately. |lock| is acquired for
// destruction purposes.
class ScopedVAImage {
public:
ScopedVAImage(base::Lock* lock,
VADisplay va_display,
VASurfaceID va_surface_id,
VAImageFormat* format /* Needs to be a pointer for libva */,
const gfx::Size& size);
ScopedVAImage(const ScopedVAImage&) = delete;
ScopedVAImage& operator=(const ScopedVAImage&) = delete;
~ScopedVAImage();
bool IsValid() const { return va_buffer_ && va_buffer_->IsValid(); }
const VAImage* image() const { return image_.get(); }
const ScopedVABufferMapping* va_buffer() const {
DCHECK(IsValid());
return va_buffer_.get();
}
private:
base::Lock* lock_;
const VADisplay va_display_ GUARDED_BY(lock_);
std::unique_ptr<VAImage> image_;
std::unique_ptr<ScopedVABufferMapping> va_buffer_;
};
// A VA-API-specific surface used by video/image codec accelerators to work on.
// As the name suggests, this class is self-cleaning.
class ScopedVASurface {
public:
ScopedVASurface(scoped_refptr<VaapiWrapper> vaapi_wrapper,
VASurfaceID va_surface_id,
const gfx::Size& size,
unsigned int va_rt_format);
ScopedVASurface(const ScopedVASurface&) = delete;
ScopedVASurface& operator=(const ScopedVASurface&) = delete;
~ScopedVASurface();
bool IsValid() const;
VASurfaceID id() const { return va_surface_id_; }
const gfx::Size& size() const { return size_; }
unsigned int format() const { return va_rt_format_; }
private:
friend struct VAContextAndScopedVASurfaceDeleter;
const scoped_refptr<VaapiWrapper> vaapi_wrapper_;
const VASurfaceID va_surface_id_;
const gfx::Size size_;
const unsigned int va_rt_format_;
};
// A combination of a numeric ID |id| and a callback to release it. This class
// makes no assumptions on threading or lifetimes; |release_cb_| must provide
// for this.
// ScopedID allows for object-specific release callbacks, whereas
// unique_ptr::deleter_type (or base::ScopedGeneric) only supports free
// functions (or class-static methods) for freeing.
template <typename T>
class ScopedID {
public:
using ReleaseCB = base::OnceCallback<void(T)>;
ScopedID(T id, ReleaseCB release_cb)
: id_(id), release_cb_(std::move(release_cb)) {
DCHECK(release_cb_);
static_assert(std::is_integral<T>::value, "T must be a numeric type.");
}
~ScopedID() { std::move(release_cb_).Run(id_); }
ScopedID& operator=(const ScopedID&) = delete;
ScopedID(const ScopedID&) = delete;
T id() const { return id_; }
private:
const T id_;
ReleaseCB release_cb_;
};
// Adapts |frame_header| to the Vaapi data types.
void FillVP8DataStructures(const Vp8FrameHeader& frame_header,
const Vp8ReferenceFrameVector& reference_frames,
VAIQMatrixBufferVP8* iq_matrix_buf,
VAProbabilityDataBufferVP8* prob_buf,
VAPictureParameterBufferVP8* pic_param,
VASliceParameterBufferVP8* slice_param);
bool IsValidVABufferType(VABufferType type);
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_UTILS_H_