2016-05-09 17:42:03 +00:00
|
|
|
#include <pthread.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
video: add mp_image_params.hw_flags and add an example
It seems this will be useful for Rokchip DRM hwcontext integration.
DRM hwcontexts have additional internal structure which can be different
depending on the decoder, and which is not part of the generic hwcontext
API. Rockchip has 1 layer, which EGL interop happens to translate to a
RGB texture, while VAAPI (mapped as DRM hwcontext) will use multiple
layers. Both will use sw_format=nv12, and thus are indistinguishable on
the mp_image_params level. But this is needed to initialize the EGL
mapping and the vo_gpu video renderer correctly.
We hope that the layer count is enough to tell whether EGL will
translate the data to a RGB texture (vs. 2 texture resembling raw nv12
data). For that we introduce MP_IMAGE_HW_FLAG_OPAQUE.
This commit adds the flag, infrastructure to set it, and an "example"
for D3D11.
The D3D11 addition is quite useless at this point. But later we want to
get rid of d3d11_update_image_attribs() anyway, while we still need a
way to force d3d11vpp filter insertion, so maybe it has some
justification (who knows). In any case it makes testing this easier.
Obviously it also adds some basic support for triggering the opaque
format for decoding, which will use a driver-specific format, but which
is not supported in shaders. The opaque flag is not used to determine
whether d3d11vpp needs to be inserted, though.
2017-10-16 12:44:59 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2016-05-09 17:42:03 +00:00
|
|
|
#include "hwdec.h"
|
|
|
|
|
|
|
|
struct mp_hwdec_devices {
|
|
|
|
pthread_mutex_t lock;
|
|
|
|
|
|
|
|
struct mp_hwdec_ctx *hwctx;
|
|
|
|
|
|
|
|
void (*load_api)(void *ctx, enum hwdec_type type);
|
|
|
|
void *load_api_ctx;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mp_hwdec_devices *hwdec_devices_create(void)
|
|
|
|
{
|
|
|
|
struct mp_hwdec_devices *devs = talloc_zero(NULL, struct mp_hwdec_devices);
|
|
|
|
pthread_mutex_init(&devs->lock, NULL);
|
|
|
|
return devs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwdec_devices_destroy(struct mp_hwdec_devices *devs)
|
|
|
|
{
|
|
|
|
if (!devs)
|
|
|
|
return;
|
|
|
|
assert(!devs->hwctx); // must have been hwdec_devices_remove()ed
|
|
|
|
assert(!devs->load_api); // must have been unset
|
|
|
|
pthread_mutex_destroy(&devs->lock);
|
|
|
|
talloc_free(devs);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mp_hwdec_ctx *hwdec_devices_get(struct mp_hwdec_devices *devs,
|
|
|
|
enum hwdec_type type)
|
|
|
|
{
|
|
|
|
struct mp_hwdec_ctx *res = NULL;
|
|
|
|
pthread_mutex_lock(&devs->lock);
|
|
|
|
if (devs->hwctx && devs->hwctx->type == type)
|
|
|
|
res = devs->hwctx;
|
|
|
|
pthread_mutex_unlock(&devs->lock);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mp_hwdec_ctx *hwdec_devices_get_first(struct mp_hwdec_devices *devs)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&devs->lock);
|
|
|
|
struct mp_hwdec_ctx *res = devs->hwctx;
|
|
|
|
pthread_mutex_unlock(&devs->lock);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwdec_devices_add(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&devs->lock);
|
|
|
|
// We support only 1 device; ignore the rest.
|
|
|
|
if (!devs->hwctx)
|
|
|
|
devs->hwctx = ctx;
|
|
|
|
pthread_mutex_unlock(&devs->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&devs->lock);
|
|
|
|
if (devs->hwctx == ctx)
|
|
|
|
devs->hwctx = NULL;
|
|
|
|
pthread_mutex_unlock(&devs->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwdec_devices_set_loader(struct mp_hwdec_devices *devs,
|
|
|
|
void (*load_api)(void *ctx, enum hwdec_type type), void *load_api_ctx)
|
|
|
|
{
|
|
|
|
devs->load_api = load_api;
|
|
|
|
devs->load_api_ctx = load_api_ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwdec_devices_request(struct mp_hwdec_devices *devs, enum hwdec_type type)
|
|
|
|
{
|
|
|
|
if (devs->load_api && !hwdec_devices_get_first(devs))
|
|
|
|
devs->load_api(devs->load_api_ctx, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *hwdec_devices_load(struct mp_hwdec_devices *devs, enum hwdec_type type)
|
|
|
|
{
|
|
|
|
if (!devs)
|
|
|
|
return NULL;
|
|
|
|
hwdec_devices_request(devs, type);
|
|
|
|
struct mp_hwdec_ctx *hwctx = hwdec_devices_get(devs, type);
|
|
|
|
return hwctx ? hwctx->ctx : NULL;
|
|
|
|
}
|
video: add mp_image_params.hw_flags and add an example
It seems this will be useful for Rokchip DRM hwcontext integration.
DRM hwcontexts have additional internal structure which can be different
depending on the decoder, and which is not part of the generic hwcontext
API. Rockchip has 1 layer, which EGL interop happens to translate to a
RGB texture, while VAAPI (mapped as DRM hwcontext) will use multiple
layers. Both will use sw_format=nv12, and thus are indistinguishable on
the mp_image_params level. But this is needed to initialize the EGL
mapping and the vo_gpu video renderer correctly.
We hope that the layer count is enough to tell whether EGL will
translate the data to a RGB texture (vs. 2 texture resembling raw nv12
data). For that we introduce MP_IMAGE_HW_FLAG_OPAQUE.
This commit adds the flag, infrastructure to set it, and an "example"
for D3D11.
The D3D11 addition is quite useless at this point. But later we want to
get rid of d3d11_update_image_attribs() anyway, while we still need a
way to force d3d11vpp filter insertion, so maybe it has some
justification (who knows). In any case it makes testing this easier.
Obviously it also adds some basic support for triggering the opaque
format for decoding, which will use a driver-specific format, but which
is not supported in shaders. The opaque flag is not used to determine
whether d3d11vpp needs to be inserted, though.
2017-10-16 12:44:59 +00:00
|
|
|
|
|
|
|
#if HAVE_D3D_HWACCEL
|
|
|
|
extern const struct hwcontext_fns hwcontext_fns_d3d11;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static const struct hwcontext_fns *const hwcontext_fns[] = {
|
|
|
|
#if HAVE_D3D_HWACCEL
|
|
|
|
&hwcontext_fns_d3d11,
|
|
|
|
#endif
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct hwcontext_fns *hwdec_get_hwcontext_fns(int av_hwdevice_type)
|
|
|
|
{
|
|
|
|
for (int n = 0; hwcontext_fns[n]; n++) {
|
|
|
|
if (hwcontext_fns[n]->av_hwdevice_type == av_hwdevice_type)
|
|
|
|
return hwcontext_fns[n];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|