summaryrefslogtreecommitdiffstats
path: root/video/out/hwdec
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/hwdec')
-rw-r--r--video/out/hwdec/dmabuf_interop.h2
-rw-r--r--video/out/hwdec/dmabuf_interop_gl.c176
-rw-r--r--video/out/hwdec/dmabuf_interop_pl.c2
-rw-r--r--video/out/hwdec/hwdec_aimagereader.c12
-rw-r--r--video/out/hwdec/hwdec_cuda.c2
-rw-r--r--video/out/hwdec/hwdec_drmprime.c27
-rw-r--r--video/out/hwdec/hwdec_vaapi.c10
-rw-r--r--video/out/hwdec/hwdec_vt.c2
8 files changed, 161 insertions, 72 deletions
diff --git a/video/out/hwdec/dmabuf_interop.h b/video/out/hwdec/dmabuf_interop.h
index e9b3e8e..3bf01a0 100644
--- a/video/out/hwdec/dmabuf_interop.h
+++ b/video/out/hwdec/dmabuf_interop.h
@@ -38,7 +38,7 @@ struct dmabuf_interop {
struct dmabuf_interop_priv {
int num_planes;
struct mp_image layout;
- struct ra_tex *tex[4];
+ struct ra_tex *tex[AV_DRM_MAX_PLANES];
AVDRMFrameDescriptor desc;
bool surface_acquired;
diff --git a/video/out/hwdec/dmabuf_interop_gl.c b/video/out/hwdec/dmabuf_interop_gl.c
index e7fb103..0f6fb89 100644
--- a/video/out/hwdec/dmabuf_interop_gl.c
+++ b/video/out/hwdec/dmabuf_interop_gl.c
@@ -52,39 +52,28 @@ typedef void *EGLImageKHR;
#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
struct vaapi_gl_mapper_priv {
- GLuint gl_textures[4];
- EGLImageKHR images[4];
+ GLuint gl_textures[AV_DRM_MAX_PLANES];
+ EGLImageKHR images[AV_DRM_MAX_PLANES];
+
+ const struct ra_format *planes[AV_DRM_MAX_PLANES];
EGLImageKHR (EGLAPIENTRY *CreateImageKHR)(EGLDisplay, EGLContext,
EGLenum, EGLClientBuffer,
const EGLint *);
EGLBoolean (EGLAPIENTRY *DestroyImageKHR)(EGLDisplay, EGLImageKHR);
void (EGLAPIENTRY *EGLImageTargetTexture2DOES)(GLenum, GLeglImageOES);
+ void (EGLAPIENTRY *EGLImageTargetTexStorageEXT)(GLenum, GLeglImageOES,
+ const GLint *);
};
-static bool vaapi_gl_mapper_init(struct ra_hwdec_mapper *mapper,
- const struct ra_imgfmt_desc *desc)
+static bool gl_create_textures(struct ra_hwdec_mapper *mapper)
{
struct dmabuf_interop_priv *p_mapper = mapper->priv;
- struct vaapi_gl_mapper_priv *p = talloc_ptrtype(NULL, p);
- p_mapper->interop_mapper_priv = p;
-
- *p = (struct vaapi_gl_mapper_priv) {
- // EGL_KHR_image_base
- .CreateImageKHR = (void *)eglGetProcAddress("eglCreateImageKHR"),
- .DestroyImageKHR = (void *)eglGetProcAddress("eglDestroyImageKHR"),
- // GL_OES_EGL_image
- .EGLImageTargetTexture2DOES =
- (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES"),
- };
-
- if (!p->CreateImageKHR || !p->DestroyImageKHR ||
- !p->EGLImageTargetTexture2DOES)
- return false;
+ struct vaapi_gl_mapper_priv *p = p_mapper->interop_mapper_priv;
GL *gl = ra_gl_get(mapper->ra);
- gl->GenTextures(4, p->gl_textures);
- for (int n = 0; n < desc->num_planes; n++) {
+ gl->GenTextures(AV_DRM_MAX_PLANES, p->gl_textures);
+ for (int n = 0; n < p_mapper->num_planes; n++) {
gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -97,7 +86,7 @@ static bool vaapi_gl_mapper_init(struct ra_hwdec_mapper *mapper,
.w = mp_image_plane_w(&p_mapper->layout, n),
.h = mp_image_plane_h(&p_mapper->layout, n),
.d = 1,
- .format = desc->planes[n],
+ .format = p->planes[n],
.render_src = true,
.src_linear = true,
};
@@ -114,44 +103,99 @@ static bool vaapi_gl_mapper_init(struct ra_hwdec_mapper *mapper,
return true;
}
+static void gl_delete_textures(const struct ra_hwdec_mapper *mapper)
+{
+ struct dmabuf_interop_priv *p_mapper = mapper->priv;
+ struct vaapi_gl_mapper_priv *p = p_mapper->interop_mapper_priv;
+
+ GL *gl = ra_gl_get(mapper->ra);
+ gl->DeleteTextures(AV_DRM_MAX_PLANES, p->gl_textures);
+ for (int n = 0; n < AV_DRM_MAX_PLANES; n++) {
+ p->gl_textures[n] = 0;
+ ra_tex_free(mapper->ra, &p_mapper->tex[n]);
+ }
+}
+
+static bool vaapi_gl_mapper_init(struct ra_hwdec_mapper *mapper,
+ const struct ra_imgfmt_desc *desc)
+{
+ struct dmabuf_interop_priv *p_mapper = mapper->priv;
+ struct vaapi_gl_mapper_priv *p = talloc_ptrtype(NULL, p);
+ p_mapper->interop_mapper_priv = p;
+
+ *p = (struct vaapi_gl_mapper_priv) {
+ // EGL_KHR_image_base
+ .CreateImageKHR = (void *)eglGetProcAddress("eglCreateImageKHR"),
+ .DestroyImageKHR = (void *)eglGetProcAddress("eglDestroyImageKHR"),
+ };
+ if (ra_gl_get(mapper->ra)->es) {
+ // GL_OES_EGL_image
+ p->EGLImageTargetTexture2DOES =
+ (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES");
+ } else {
+ // GL_EXT_EGL_image_storage
+ p->EGLImageTargetTexStorageEXT =
+ (void *)eglGetProcAddress("glEGLImageTargetTexStorageEXT");
+ }
+
+ if (!p->CreateImageKHR || !p->DestroyImageKHR ||
+ (!p->EGLImageTargetTexture2DOES && !p->EGLImageTargetTexStorageEXT)) {
+ return false;
+ }
+
+ static_assert(MP_ARRAY_SIZE(desc->planes) == AV_DRM_MAX_PLANES, "");
+ static_assert(MP_ARRAY_SIZE(mapper->tex) == AV_DRM_MAX_PLANES, "");
+
+ // remember format to allow texture recreation
+ for (int n = 0; n < desc->num_planes; n++) {
+ p->planes[n] = desc->planes[n];
+ }
+ if (p->EGLImageTargetTexture2DOES) {
+ // created only once
+ if (!gl_create_textures(mapper))
+ return false;
+ }
+
+ return true;
+}
+
static void vaapi_gl_mapper_uninit(const struct ra_hwdec_mapper *mapper)
{
struct dmabuf_interop_priv *p_mapper = mapper->priv;
struct vaapi_gl_mapper_priv *p = p_mapper->interop_mapper_priv;
if (p) {
- GL *gl = ra_gl_get(mapper->ra);
- gl->DeleteTextures(4, p->gl_textures);
- for (int n = 0; n < 4; n++) {
- p->gl_textures[n] = 0;
- ra_tex_free(mapper->ra, &p_mapper->tex[n]);
- }
+ gl_delete_textures(mapper);
talloc_free(p);
p_mapper->interop_mapper_priv = NULL;
}
}
-#define ADD_ATTRIB(name, value) \
- do { \
- assert(num_attribs + 3 < MP_ARRAY_SIZE(attribs)); \
- attribs[num_attribs++] = (name); \
- attribs[num_attribs++] = (value); \
- attribs[num_attribs] = EGL_NONE; \
+#define ADD_ATTRIB(name, value) \
+ do { \
+ assert(num_attribs + 3 < MP_ARRAY_SIZE(attribs)); \
+ attribs[num_attribs++] = (name); \
+ attribs[num_attribs++] = (value); \
+ attribs[num_attribs] = EGL_NONE; \
} while(0)
-#define ADD_PLANE_ATTRIBS(plane) do { \
- uint64_t drm_format_modifier = p_mapper->desc.objects[p_mapper->desc.layers[i].planes[j].object_index].format_modifier; \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _FD_EXT, \
- p_mapper->desc.objects[p_mapper->desc.layers[i].planes[j].object_index].fd); \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _OFFSET_EXT, \
- p_mapper->desc.layers[i].planes[j].offset); \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _PITCH_EXT, \
- p_mapper->desc.layers[i].planes[j].pitch); \
- if (dmabuf_interop->use_modifiers && drm_format_modifier != DRM_FORMAT_MOD_INVALID) { \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _MODIFIER_LO_EXT, drm_format_modifier & 0xfffffffful); \
- ADD_ATTRIB(EGL_DMA_BUF_PLANE ## plane ## _MODIFIER_HI_EXT, drm_format_modifier >> 32); \
- } \
- } while (0)
+#define ADD_PLANE_ATTRIBS(nplane) \
+ do { \
+ const AVDRMPlaneDescriptor *plane = &p_mapper->desc.layers[i].planes[j]; \
+ const AVDRMObjectDescriptor *object = \
+ &p_mapper->desc.objects[plane->object_index]; \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## nplane ## _FD_EXT, object->fd); \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## nplane ## _OFFSET_EXT, plane->offset); \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## nplane ## _PITCH_EXT, plane->pitch); \
+ uint64_t drm_format_modifier = object->format_modifier; \
+ if (dmabuf_interop->use_modifiers && \
+ drm_format_modifier != DRM_FORMAT_MOD_INVALID) { \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## nplane ## _MODIFIER_LO_EXT, \
+ drm_format_modifier & 0xfffffffful); \
+ ADD_ATTRIB(EGL_DMA_BUF_PLANE ## nplane ## _MODIFIER_HI_EXT, \
+ drm_format_modifier >> 32); \
+ } \
+ } while (0)
static bool vaapi_gl_map(struct ra_hwdec_mapper *mapper,
struct dmabuf_interop *dmabuf_interop,
@@ -162,6 +206,11 @@ static bool vaapi_gl_map(struct ra_hwdec_mapper *mapper,
GL *gl = ra_gl_get(mapper->ra);
+ if (p->EGLImageTargetTexStorageEXT) {
+ if (!gl_create_textures(mapper))
+ return false;
+ }
+
for (int i = 0, n = 0; i < p_mapper->desc.nb_layers; i++) {
/*
* As we must map surfaces as one texture per plane, we can only support
@@ -186,6 +235,7 @@ static bool vaapi_gl_map(struct ra_hwdec_mapper *mapper,
format[2] = DRM_FORMAT_R8;
break;
case DRM_FORMAT_P010:
+ case DRM_FORMAT_P210:
#ifdef DRM_FORMAT_P030 /* Format added in a newer libdrm version than minimum */
case DRM_FORMAT_P030:
#endif
@@ -251,7 +301,11 @@ static bool vaapi_gl_map(struct ra_hwdec_mapper *mapper,
}
gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]);
- p->EGLImageTargetTexture2DOES(GL_TEXTURE_2D, p->images[n]);
+ if (p->EGLImageTargetTexStorageEXT) {
+ p->EGLImageTargetTexStorageEXT(GL_TEXTURE_2D, p->images[n], NULL);
+ } else {
+ p->EGLImageTargetTexture2DOES(GL_TEXTURE_2D, p->images[n]);
+ }
mapper->tex[n] = p_mapper->tex[n];
}
@@ -266,12 +320,18 @@ static void vaapi_gl_unmap(struct ra_hwdec_mapper *mapper)
struct dmabuf_interop_priv *p_mapper = mapper->priv;
struct vaapi_gl_mapper_priv *p = p_mapper->interop_mapper_priv;
- if (p) {
- for (int n = 0; n < 4; n++) {
- if (p->images[n])
- p->DestroyImageKHR(eglGetCurrentDisplay(), p->images[n]);
- p->images[n] = 0;
- }
+ if (!p)
+ return;
+
+ if (p->EGLImageTargetTexStorageEXT) {
+ // textures are immutable, can't reuse
+ gl_delete_textures(mapper);
+ }
+
+ for (int n = 0; n < AV_DRM_MAX_PLANES; n++) {
+ if (p->images[n])
+ p->DestroyImageKHR(eglGetCurrentDisplay(), p->images[n]);
+ p->images[n] = 0;
}
}
@@ -291,16 +351,18 @@ bool dmabuf_interop_gl_init(const struct ra_hwdec *hw,
return false;
GL *gl = ra_gl_get(hw->ra_ctx->ra);
+ const char *imageext = gl->es ? "GL_OES_EGL_image" : "GL_EXT_EGL_image_storage";
if (!gl_check_extension(exts, "EGL_EXT_image_dma_buf_import") ||
!gl_check_extension(exts, "EGL_KHR_image_base") ||
- !gl_check_extension(gl->extensions, "GL_OES_EGL_image") ||
- !(gl->mpgl_caps & MPGL_CAP_TEX_RG))
+ !gl_check_extension(gl->extensions, imageext) ||
+ !(gl->mpgl_caps & MPGL_CAP_TEX_RG)) {
return false;
+ }
dmabuf_interop->use_modifiers =
gl_check_extension(exts, "EGL_EXT_image_dma_buf_import_modifiers");
- MP_VERBOSE(hw, "using EGL dmabuf interop\n");
+ MP_VERBOSE(hw, "Using EGL dmabuf interop via %s\n", imageext);
dmabuf_interop->interop_init = vaapi_gl_mapper_init;
dmabuf_interop->interop_uninit = vaapi_gl_mapper_uninit;
diff --git a/video/out/hwdec/dmabuf_interop_pl.c b/video/out/hwdec/dmabuf_interop_pl.c
index 0a8ec5b..1f036e3 100644
--- a/video/out/hwdec/dmabuf_interop_pl.c
+++ b/video/out/hwdec/dmabuf_interop_pl.c
@@ -110,7 +110,7 @@ static bool vaapi_pl_map(struct ra_hwdec_mapper *mapper,
static void vaapi_pl_unmap(struct ra_hwdec_mapper *mapper)
{
- for (int n = 0; n < 4; n++)
+ for (int n = 0; n < MP_ARRAY_SIZE(mapper->tex); n++)
ra_tex_free(mapper->ra, &mapper->tex[n]);
}
diff --git a/video/out/hwdec/hwdec_aimagereader.c b/video/out/hwdec/hwdec_aimagereader.c
index 0dd5497..1aa92ee 100644
--- a/video/out/hwdec/hwdec_aimagereader.c
+++ b/video/out/hwdec/hwdec_aimagereader.c
@@ -75,7 +75,7 @@ struct priv {
void (EGLAPIENTRY *EGLImageTargetTexture2DOES)(GLenum, GLeglImageOES);
};
-const static struct { const char *symbol; int offset; } lib_functions[] = {
+static const struct { const char *symbol; int offset; } lib_functions[] = {
{ "AImageReader_newWithUsage", offsetof(struct priv_owner, AImageReader_newWithUsage) },
{ "AImageReader_getWindow", offsetof(struct priv_owner, AImageReader_getWindow) },
{ "AImageReader_setImageListener", offsetof(struct priv_owner, AImageReader_setImageListener) },
@@ -138,6 +138,10 @@ static int init(struct ra_hwdec *hw)
if (!gl_check_extension(exts, "EGL_ANDROID_image_native_buffer"))
return -1;
+ JNIEnv *env = MP_JNI_GET_ENV(hw);
+ if (!env)
+ return -1;
+
if (!load_lib_functions(p, hw->log))
return -1;
@@ -167,8 +171,6 @@ static int init(struct ra_hwdec *hw)
}
assert(window);
- JNIEnv *env = MP_JNI_GET_ENV(hw);
- assert(env);
jobject surface = p->ANativeWindow_toSurface(env, window);
p->surface = (*env)->NewGlobalRef(env, surface);
(*env)->DeleteLocalRef(env, surface);
@@ -192,10 +194,10 @@ static int init(struct ra_hwdec *hw)
static void uninit(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
- JNIEnv *env = MP_JNI_GET_ENV(hw);
- assert(env);
if (p->surface) {
+ JNIEnv *env = MP_JNI_GET_ENV(hw);
+ assert(env);
(*env)->DeleteGlobalRef(env, p->surface);
p->surface = NULL;
}
diff --git a/video/out/hwdec/hwdec_cuda.c b/video/out/hwdec/hwdec_cuda.c
index 68ad60d..57e4fb4 100644
--- a/video/out/hwdec/hwdec_cuda.c
+++ b/video/out/hwdec/hwdec_cuda.c
@@ -57,7 +57,7 @@ int check_cu(const struct ra_hwdec *hw, CUresult err, const char *func)
#define CHECK_CU(x) check_cu(hw, (x), #x)
-const static cuda_interop_init interop_inits[] = {
+static const cuda_interop_init interop_inits[] = {
#if HAVE_GL
cuda_gl_init,
#endif
diff --git a/video/out/hwdec/hwdec_drmprime.c b/video/out/hwdec/hwdec_drmprime.c
index f7c6250..bf60405 100644
--- a/video/out/hwdec/hwdec_drmprime.c
+++ b/video/out/hwdec/hwdec_drmprime.c
@@ -23,6 +23,7 @@
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_drm.h>
+#include <libavutil/pixdesc.h>
#include <xf86drm.h>
#include "config.h"
@@ -51,7 +52,7 @@ static void uninit(struct ra_hwdec *hw)
av_buffer_unref(&p->hwctx.av_device_ref);
}
-const static dmabuf_interop_init interop_inits[] = {
+static const dmabuf_interop_init interop_inits[] = {
#if HAVE_DMABUF_INTEROP_GL
dmabuf_interop_gl_init,
#endif
@@ -64,6 +65,18 @@ const static dmabuf_interop_init interop_inits[] = {
NULL
};
+/**
+ * Due to the fact that Raspberry Pi support only exists in forked ffmpegs and
+ * also requires custom pixel formats, we need some way to work with those formats
+ * without introducing any build time dependencies. We do this by looking up the
+ * pixel formats by name. As rpi is an important target platform for this hwdec
+ * we don't really have the luxury of ignoring these forks.
+ */
+static const char *forked_pix_fmt_names[] = {
+ "rpi4_8",
+ "rpi4_10",
+};
+
static int init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
@@ -119,6 +132,18 @@ static int init(struct ra_hwdec *hw)
MP_TARRAY_APPEND(p, p->formats, num_formats, IMGFMT_NV12);
MP_TARRAY_APPEND(p, p->formats, num_formats, IMGFMT_420P);
MP_TARRAY_APPEND(p, p->formats, num_formats, pixfmt2imgfmt(AV_PIX_FMT_NV16));
+ MP_TARRAY_APPEND(p, p->formats, num_formats, IMGFMT_P010);
+#ifdef AV_PIX_FMT_P210
+ MP_TARRAY_APPEND(p, p->formats, num_formats, pixfmt2imgfmt(AV_PIX_FMT_P210));
+#endif
+
+ for (int i = 0; i < MP_ARRAY_SIZE(forked_pix_fmt_names); i++) {
+ enum AVPixelFormat fmt = av_get_pix_fmt(forked_pix_fmt_names[i]);
+ if (fmt != AV_PIX_FMT_NONE) {
+ MP_TARRAY_APPEND(p, p->formats, num_formats, pixfmt2imgfmt(fmt));
+ }
+ }
+
MP_TARRAY_APPEND(p, p->formats, num_formats, 0); // terminate it
p->hwctx.hw_imgfmt = IMGFMT_DRMPRIME;
diff --git a/video/out/hwdec/hwdec_vaapi.c b/video/out/hwdec/hwdec_vaapi.c
index d8a4517..34b6e52 100644
--- a/video/out/hwdec/hwdec_vaapi.c
+++ b/video/out/hwdec/hwdec_vaapi.c
@@ -124,7 +124,7 @@ static void uninit(struct ra_hwdec *hw)
va_destroy(p->ctx);
}
-const static dmabuf_interop_init interop_inits[] = {
+static const dmabuf_interop_init interop_inits[] = {
#if HAVE_DMABUF_INTEROP_GL
dmabuf_interop_gl_init,
#endif
@@ -261,10 +261,10 @@ static int mapper_init(struct ra_hwdec_mapper *mapper)
return 0;
}
-static void close_file_descriptors(VADRMPRIMESurfaceDescriptor desc)
+static void close_file_descriptors(const VADRMPRIMESurfaceDescriptor *desc)
{
- for (int i = 0; i < desc.num_objects; i++)
- close(desc.objects[i].fd);
+ for (int i = 0; i < desc->num_objects; i++)
+ close(desc->objects[i].fd);
}
static int mapper_map(struct ra_hwdec_mapper *mapper)
@@ -285,7 +285,7 @@ static int mapper_map(struct ra_hwdec_mapper *mapper)
if (!CHECK_VA_STATUS_LEVEL(mapper, "vaExportSurfaceHandle()",
p_owner->probing_formats ? MSGL_DEBUG : MSGL_ERR))
{
- close_file_descriptors(desc);
+ close_file_descriptors(&desc);
goto err;
}
vaSyncSurface(display, va_surface_id(mapper->src));
diff --git a/video/out/hwdec/hwdec_vt.c b/video/out/hwdec/hwdec_vt.c
index ab41d02..643ff90 100644
--- a/video/out/hwdec/hwdec_vt.c
+++ b/video/out/hwdec/hwdec_vt.c
@@ -36,7 +36,7 @@ static void uninit(struct ra_hwdec *hw)
av_buffer_unref(&p->hwctx.av_device_ref);
}
-const static vt_interop_init interop_inits[] = {
+static const vt_interop_init interop_inits[] = {
#if HAVE_VIDEOTOOLBOX_GL || HAVE_IOS_GL
vt_gl_init,
#endif