eglCreateImageKHR 返回 EGL_BAD_ATTRIBUTE 错误
eglCreateImageKHR returning EGL_BAD_ATTRIBUTE error
我已经通过 FFmpeg 使用 VAAPI 在 Linux 上实现了硬件解码。因为我有一个 OpenGL 应用程序,所以我使用 vaCopySurfaceGLX 将解码的 VAAPI 表面转换为 OpenGL 纹理。这工作正常,除了有一个副本(在 GPU 上)。有人告诉我,我可以使用 EGL 直接将 VAAPI 表面用作 OpenGL 纹理。我看过一些示例(主要是 Kodi 源代码),但我无法创建 EGLImageKHR。函数 eglCreateImageKHR returns 0,当我检查错误时,我得到一个 EGL_BAD_ATTRIBUTE 错误,但我不明白为什么。
下面是我如何转换 VAAPI 表面。
在初始化期间,我这样设置 EGL:
// currentDisplay comes from call to glXGetCurrentDisplay() and is also used when getting the VADisplay like this: vaGetDisplay(currentDisplay)
EGLint major, minor;
_eglDisplay = eglGetDisplay(currentDisplay);
eglInitialize(_eglDisplay, &major, &minor);
eglBindAPI(EGL_OPENGL_API);
然后,为了创建我的 EGL 图像,这就是我所做的:
// _vaapiContext.vaDisplay comes from vaGetDisplay(currentDisplay)
// surface is the VASurfaceID of the surface I want to use in OpenGL
vaDeriveImage(_vaapiContext.vaDisplay, surface, &_vaapiContext.vaImage);
VABufferInfo buf_info;
memset(&buf_info, 0, sizeof(buf_info));
buf_info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
vaAcquireBufferHandle(_vaapiContext.vaDisplay, _vaapiContext.vaImage.buf, &buf_info);
EGLint attribs[] = {
EGL_WIDTH, _vaapiContext.vaImage.width,
EGL_HEIGHT, _vaapiContext.vaImage.height,
EGL_LINUX_DRM_FOURCC_EXT, fourcc_code('R', '8', ' ', ' '),
EGL_DMA_BUF_PLANE0_FD_EXT, buf_info.handle,
EGL_DMA_BUF_PLANE0_OFFSET_EXT, _vaapiContext.vaImage.offsets[0],
EGL_DMA_BUF_PLANE0_PITCH_EXT, _vaapiContext.vaImage.pitches[0],
EGL_NONE
};
EGLImageKHR eglImage = eglCreateImageKHR(_eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, attribs);
查看以下文档中可能导致此错误的原因 https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt,我还尝试添加以下选项,这应该无关紧要,因为我的格式不是平面的
EGL_YUV_COLOR_SPACE_HINT_EXT, EGL_ITU_REC601_EXT,
EGL_SAMPLE_RANGE_HINT_EXT, EGL_YUV_FULL_RANGE_EXT,
EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT, EGL_YUV_CHROMA_SITING_0_EXT,
EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT, EGL_YUV_CHROMA_SITING_0_EXT
我使用的代码与我见过的所有示例都相似,所以我不确定错误是什么。
请注意,我已删除此 post 的所有错误检查。除了eglCreateImageKHR之外,上面的所有调用都成功了。
将egl 日志级别设置为调试后,我能够获得有关该错误的更多信息并查明该错误在egl 源代码中的位置。原来不支持格式fourcc_code('R', '8', ' ', ' '),因为我的mesa版本太旧了。您需要安装 mesa 11.0.0 或更高版本。重新编译 mesa(我是 运行 Ubuntu 15.04)并安装 11.0.0 版本后,我终于得到了一个 EGL 镜像。
我已经通过 FFmpeg 使用 VAAPI 在 Linux 上实现了硬件解码。因为我有一个 OpenGL 应用程序,所以我使用 vaCopySurfaceGLX 将解码的 VAAPI 表面转换为 OpenGL 纹理。这工作正常,除了有一个副本(在 GPU 上)。有人告诉我,我可以使用 EGL 直接将 VAAPI 表面用作 OpenGL 纹理。我看过一些示例(主要是 Kodi 源代码),但我无法创建 EGLImageKHR。函数 eglCreateImageKHR returns 0,当我检查错误时,我得到一个 EGL_BAD_ATTRIBUTE 错误,但我不明白为什么。
下面是我如何转换 VAAPI 表面。
在初始化期间,我这样设置 EGL:
// currentDisplay comes from call to glXGetCurrentDisplay() and is also used when getting the VADisplay like this: vaGetDisplay(currentDisplay)
EGLint major, minor;
_eglDisplay = eglGetDisplay(currentDisplay);
eglInitialize(_eglDisplay, &major, &minor);
eglBindAPI(EGL_OPENGL_API);
然后,为了创建我的 EGL 图像,这就是我所做的:
// _vaapiContext.vaDisplay comes from vaGetDisplay(currentDisplay)
// surface is the VASurfaceID of the surface I want to use in OpenGL
vaDeriveImage(_vaapiContext.vaDisplay, surface, &_vaapiContext.vaImage);
VABufferInfo buf_info;
memset(&buf_info, 0, sizeof(buf_info));
buf_info.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
vaAcquireBufferHandle(_vaapiContext.vaDisplay, _vaapiContext.vaImage.buf, &buf_info);
EGLint attribs[] = {
EGL_WIDTH, _vaapiContext.vaImage.width,
EGL_HEIGHT, _vaapiContext.vaImage.height,
EGL_LINUX_DRM_FOURCC_EXT, fourcc_code('R', '8', ' ', ' '),
EGL_DMA_BUF_PLANE0_FD_EXT, buf_info.handle,
EGL_DMA_BUF_PLANE0_OFFSET_EXT, _vaapiContext.vaImage.offsets[0],
EGL_DMA_BUF_PLANE0_PITCH_EXT, _vaapiContext.vaImage.pitches[0],
EGL_NONE
};
EGLImageKHR eglImage = eglCreateImageKHR(_eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, attribs);
查看以下文档中可能导致此错误的原因 https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt,我还尝试添加以下选项,这应该无关紧要,因为我的格式不是平面的
EGL_YUV_COLOR_SPACE_HINT_EXT, EGL_ITU_REC601_EXT,
EGL_SAMPLE_RANGE_HINT_EXT, EGL_YUV_FULL_RANGE_EXT,
EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT, EGL_YUV_CHROMA_SITING_0_EXT,
EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT, EGL_YUV_CHROMA_SITING_0_EXT
我使用的代码与我见过的所有示例都相似,所以我不确定错误是什么。
请注意,我已删除此 post 的所有错误检查。除了eglCreateImageKHR之外,上面的所有调用都成功了。
将egl 日志级别设置为调试后,我能够获得有关该错误的更多信息并查明该错误在egl 源代码中的位置。原来不支持格式fourcc_code('R', '8', ' ', ' '),因为我的mesa版本太旧了。您需要安装 mesa 11.0.0 或更高版本。重新编译 mesa(我是 运行 Ubuntu 15.04)并安装 11.0.0 版本后,我终于得到了一个 EGL 镜像。