diff options
Diffstat (limited to 'video/out/hwdec')
-rw-r--r-- | video/out/hwdec/dmabuf_interop.h | 2 | ||||
-rw-r--r-- | video/out/hwdec/dmabuf_interop_gl.c | 176 | ||||
-rw-r--r-- | video/out/hwdec/dmabuf_interop_pl.c | 2 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_aimagereader.c | 12 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_cuda.c | 2 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_drmprime.c | 27 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_vaapi.c | 10 | ||||
-rw-r--r-- | video/out/hwdec/hwdec_vt.c | 2 |
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 |