1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-26 10:14:33 +00:00
mpv/video/hwdec.h
Philip Langdale 25fa1b0b45 hwdec/drmprime: add drmprime hwdec-interop
In the confusing landscape of hardware video decoding APIs, we have had
a long standing support gap for the v4l2 based APIs implemented for the
various SoCs from Rockship, Amlogic, Allwinner, etc. While VAAPI is the
defacto default for desktop GPUs, the developers who work on these SoCs
(who are not the vendors!) have preferred to implement kernel APIs
rather than maintain a userspace driver as VAAPI would require.

While there are two v4l2 APIs (m2m and requests), and multiple forks of
ffmpeg where support for those APIs languishes without reaching
upstream, we can at least say that these APIs export frames as DRMPrime
dmabufs, and that they use the ffmpeg drm hwcontext.

With those two constants, it is possible for us to write a
hwdec-interop without worrying about the mess underneath - for the most
part.

Accordingly, this change implements a hwdec-interop for any decoder
that produces frames as DRMPrime dmabufs. The bulk of the heavy
lifting is done by the dmabuf interop code we already had from
supporting vaapi, and which I refactored for reusability in a previous
set of changes.

When we combine that with the fact that we can't probe for supported
formats, the new code in this change is pretty simple.

This change also includes the hwcontext_fns that are required for us to
be able to configure the hwcontext used by `hwdec=drm-copy`. This is
technically unrelated, but it seemed a good time to fill this gap.

From a testing perspective, I have directly tested on a RockPRO64,
while others have tested with different flavours of Rockchip and on
Amlogic, providing m2m coverage.

I have some other SoCs that I need to spin up to test with, but I don't
expect big surprises, and when we inevitably need to account for new
special cases down the line, we can do so - we won't be able to support
every possible configuration blindly.
2022-08-09 10:19:18 -07:00

108 lines
4.3 KiB
C

#ifndef MP_HWDEC_H_
#define MP_HWDEC_H_
#include <libavutil/buffer.h>
#include "options/m_option.h"
struct mp_image_pool;
struct mp_hwdec_ctx {
const char *driver_name; // NULL if unknown/not loaded
// libavutil-wrapped context, if available.
struct AVBufferRef *av_device_ref; // AVHWDeviceContext*
// List of IMGFMT_s, terminated with 0. NULL if N/A.
const int *supported_formats;
// HW format for which above hw_subfmts are valid.
int hw_imgfmt;
};
// Used to communicate hardware decoder device handles from VO to video decoder.
struct mp_hwdec_devices;
struct mp_hwdec_devices *hwdec_devices_create(void);
void hwdec_devices_destroy(struct mp_hwdec_devices *devs);
// Return the device context for the given API type. Returns NULL if none
// available. Logically, the returned pointer remains valid until VO
// uninitialization is started (all users of it must be uninitialized before).
// hwdec_devices_request() may be used before this to lazily load devices.
// Contains a wrapped AVHWDeviceContext.
// Beware that this creates a _new_ reference.
struct AVBufferRef *hwdec_devices_get_lavc(struct mp_hwdec_devices *devs,
int av_hwdevice_type);
struct mp_hwdec_ctx *hwdec_devices_get_by_lavc(struct mp_hwdec_devices *devs,
int av_hwdevice_type);
// For code which still strictly assumes there is 1 (or none) device.
struct mp_hwdec_ctx *hwdec_devices_get_first(struct mp_hwdec_devices *devs);
// Return the n-th device. NULL if none.
struct mp_hwdec_ctx *hwdec_devices_get_n(struct mp_hwdec_devices *devs, int n);
// Add this to the list of internal devices. Adding the same pointer twice must
// be avoided.
void hwdec_devices_add(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx);
// Remove this from the list of internal devices. Idempotent/ignores entries
// not added yet. This is not thread-safe.
void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx);
struct hwdec_imgfmt_request {
int imgfmt;
bool probing;
};
// Can be used to enable lazy loading of an API with hwdec_devices_request().
// If used at all, this must be set/unset during initialization/uninitialization,
// as concurrent use with hwdec_devices_request() is a race condition.
void hwdec_devices_set_loader(struct mp_hwdec_devices *devs,
void (*load_api)(void *ctx, struct hwdec_imgfmt_request *params),
void *load_api_ctx);
// Cause VO to lazily load all devices for a specified img format, and will
// block until this is done (even if not available). Pass IMGFMT_NONE to load
// all available devices.
void hwdec_devices_request_for_img_fmt(struct mp_hwdec_devices *devs,
struct hwdec_imgfmt_request *params);
// Return "," concatenated list (for introspection/debugging). Use talloc_free().
char *hwdec_devices_get_names(struct mp_hwdec_devices *devs);
struct mp_image;
struct mpv_global;
struct hwcontext_create_dev_params {
bool probing; // if true, don't log errors if unavailable
};
// Per AV_HWDEVICE_TYPE_* functions, queryable via hwdec_get_hwcontext_fns().
// All entries are strictly optional.
struct hwcontext_fns {
int av_hwdevice_type;
// Fill in special format-specific requirements.
void (*refine_hwframes)(struct AVBufferRef *hw_frames_ctx);
// Returns a AVHWDeviceContext*. Used for copy hwdecs.
struct AVBufferRef *(*create_dev)(struct mpv_global *global,
struct mp_log *log,
struct hwcontext_create_dev_params *params);
// Return whether this is using some sort of sub-optimal emulation layer.
bool (*is_emulated)(struct AVBufferRef *hw_device_ctx);
};
// The parameter is of type enum AVHWDeviceType (as in int to avoid extensive
// recursive includes). May return NULL for unknown device types.
const struct hwcontext_fns *hwdec_get_hwcontext_fns(int av_hwdevice_type);
extern const struct hwcontext_fns hwcontext_fns_cuda;
extern const struct hwcontext_fns hwcontext_fns_d3d11;
extern const struct hwcontext_fns hwcontext_fns_drmprime;
extern const struct hwcontext_fns hwcontext_fns_dxva2;
extern const struct hwcontext_fns hwcontext_fns_vaapi;
extern const struct hwcontext_fns hwcontext_fns_vdpau;
#endif