资讯详情

libdrm的与VAAPI的surface转换的若干问题

📅 2026/11/1 1:15:11 | 华诺云谱 👁 阅读
libdrm的与VAAPI的surface转换的若干问题
主要内容本章主要讲解libdrm相关使用内容主要是libdrm的与VAAPI的交互使用方法libva流程主要是使用libva的API将surface转换为drm可以接受的drm的framebuffer ID。分为旧版本和新版本。libva旧版本123surface的导出vaDeriveImage将surface转化为VAImagevaAcquireBufferHandle将surface导出为handle,并lockvaReleaseBufferHandle释放handle对象,并unlockvaDeriveImage使用vaDeriveImage 将surface导入成image.获取image的所有信息,主要是VABufferID对象为vaAcquireBufferHandle提供参数。VAStatus vaDeriveImage ( VADisplay dpy, VASurfaceID surface, VAImage *image /* out */VAImage结构体如下typedef struct _VAImage { VAImageID image_id; /* uniquely identify this image */ VAImageFormat format; VABufferID buf; /* image data buffer */ /* * Image data will be stored in a buffer of type VAImageBufferType to facilitate * data store on the server side for optimal performance. The buffer will be * created by the CreateImage function, and proper storage allocated based on the image * size and format. This buffer is managed by the library implementation, and * accessed by the client through the buffer Map/Unmap functions. */ uint16_t width; uint16_t height; uint32_t data_size; uint32_t num_planes; /* can not be greater than 3 */ /* * An array indicating the scanline pitch in bytes for each plane. * Each plane may have a different pitch. Maximum 3 planes for planar formats */ uint32_t pitches[3]; /* * An array indicating the byte offset from the beginning of the image data * to the start of each plane. */ uint32_t offsets[3]; /* The following fields are only needed for paletted formats */ int32_t num_palette_entries; /* set to zero for non-palette images */ /* * Each component is one byte and entry_bytes indicates the number of components in * each entry (eg. 3 for YUV palette entries). set to zero for non-palette images */ int32_t entry_bytes; /* * An array of ascii characters describing the order of the components within the bytes. * Only entry_bytes characters of the string are used. */ int8_t component_order[4]; /** \brief Reserved bytes for future use, must be zero */ uint32_t va_reserved[VA_PADDING_LOW]; } VAImage;vaAcquireBufferHandlevaAcquireBufferHandle可以获取对应buffer ID的相关信息。可以共给EGL OpenCL (OCL)DRM等使用信息主要是handle句柄以及mem_typemem_size信息。VAStatus vaAcquireBufferHandle(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info);VABufferInfo 结构体作为输入和输出在DRM情况下type为VAImageBufferTypemem_type为VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM。输出为handle和mem_size。VABufferInfo 结构体如下typedef struct { /** \brief Buffer handle */ uintptr_t handle; /** \brief Buffer type (See \ref VABufferType). */ uint32_t type; /** * \brief Buffer memory type (See \ref VASurfaceAttribMemoryType). * * On input to vaAcquireBufferHandle(), this field can serve as a hint * to specify the set of memory types the caller is interested in. * On successful return from vaAcquireBufferHandle(), the field is * updated with the best matching memory type. */ uint32_t mem_type; /** \brief Size of the underlying buffer. */ size_t mem_size; /** \brief Reserved bytes for future use, must be zero */ uint32_t va_reserved[VA_PADDING_LOW]; } VABufferInfo;libva新版本新版本libva-2.1,版本号为1.1.0的导出方法主要依赖vaExportSurfaceHandle函数和VADRMPRIMESurfaceDescriptor结构体1surface的导出vaExportSurfaceHandle将surface进行export成VADRMPRIMESurfaceDescriptor结构体对象VAStatus vaExportSurfaceHandle(VADisplay dpy, VASurfaceID surface_id, uint32_t mem_type, uint32_t flags, void *descriptor)VADRMPRIMESurfaceDescriptor结构体如下typedef struct _VADRMPRIMESurfaceDescriptor { /** Pixel format fourcc of the whole surface (VA_FOURCC_*). */ uint32_t fourcc; /** Width of the surface in pixels. */ uint32_t width; /** Height of the surface in pixels. */ uint32_t height; /** Number of distinct DRM objects making up the surface. */ uint32_t num_objects; /** Description of each object. */ struct { /** DRM PRIME file descriptor for this object. */ int fd; /** Total size of this object (may include regions which are * not part of the surface). */ uint32_t size; /** Format modifier applied to this object. */ uint64_t drm_format_modifier; } objects[4]; /** Number of layers making up the surface. */ uint32_t num_layers; /** Description of each layer in the surface. */ struct { /** DRM format fourcc of this layer (DRM_FOURCC_*). */ uint32_t drm_format; /** Number of planes in this layer. */ uint32_t num_planes; /** Index in the objects array of the object containing each * plane. */ uint32_t object_index[4]; /** Offset within the object of each plane. */ uint32_t offset[4]; /** Pitch of each plane. */ uint32_t pitch[4]; } layers[4]; } VADRMPRIMESurfaceDescriptor;在调用vaExportSurfaceHandle后驱动会填充VADRMPRIMESurfaceDescriptor结构体相关的handleformat信息都会存在。drm流程在drm的API中surface ID对应的就是handledrm的API会使用handle进行操作。主要函数是drmModeAddFB2drmModeAddFB和drmModeAddFB2WithModifiers。将外部的buffer描述作为创建新的frame buffer的参数然后创建一个新的FBbuf_id 作为新的FB的对象作为新版本存在由于旧版本的局限性所以产生可新版本API可以最多支持四个图像平面buffer的参数输入。 drm_public int drmModeAddFB2(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4], const uint32_t pitches[4], const uint32_t offsets[4], uint32_t *buf_id, uint32_t flags) drmModeAddFB2WithModifiers是drmModeAddFB2调用的函数但是modifier为NULL。 drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4], const uint32_t pitches[4], const uint32_t offsets[4], const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags) drmModeAddFB将外部的buffer描述作为创建新的frame buffer的参数然后创建一个新的FBbuf_id 作为新的FB的对象作为旧版本存在,但是只能描述一个平面图像的情况无法描述多个平面情况但是现代显示硬件通常存在多个硬件平面作为混合使用。所以具有局限性。 drm_public int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id)经常使用的就是drmModeAddFB2将va中的信息导出并创建一个framebuffer ID对应于va的surface实例导出NV12格式surface前提在intel上当创建一个NV12格式的surface时使用va新版本vaExportSurfaceHandle导出时参数dpyva的VADisplay对象surface_id:需要导出的suface的ID值mem_type内存类型为VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2intel上只支持这种。flags:导出为分量为单平面(理论上支持NV12,RGBX系列等可以具有多平面分量的图像格式实际上需要驱动支持)VA_EXPORT_SURFACE_READ_WRITE|VA_EXPORT_SURFACE_SEPARATE_LAYERS或者导出为合成平面(理论上支持YUY2,YVYU,UYVY,RGBX系列,等可以具有合成平面分量的图像格式实际上需要驱动支持)VA_EXPORT_SURFACE_READ_WRITE|VA_EXPORT_SURFACE_COMPOSED_LAYERS导出的结构体参数可能如下合成平面导出时如下:desc{ fourcc0x3231564E,width1920,height1080,num_objects1, num_objects[4]{ {fd0x5,size5570560,drm_format_modifier(156|2)} {0} {0} {0} } num_layers1, layers[4]{ {drm_format0x3231564E,num_planes1,object_index[4]{0},offset[4]{0},pitch[4]{1920,0,0,0}} {0} {0} {0} } }多平面导出时如下:desc{ fourcc0x3231564E,width1920,height1080,num_objects1, num_objects[4]{ {fd0x5,size5570560,drm_format_modifier(156|2)} {0} {0} {0} } num_layers2, layers[4]{ {drm_format0x3231564E,num_planes1,object_index[4]{0},offset[4]{0},pitch[4]{1920,0,0,0}} {drm_format0x3231564E,num_planes1,object_index[4]{0},offset[4]{2073600,0,0,0},pitch[4]{1920,0,0,0}} {0} {0} } }导出YUY2格式surface前提在intel上当创建一个YUY2格式的surface时使用va新版本vaExportSurfaceHandle导出时,对于YUY2格式的图像只能使用合成平面导出参数dpyva的VADisplay对象surface_id:需要导出的suface的ID值mem_type内存类型为VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2intel上只支持这种。flags:导出为合成平面(理论上支持YUY2,YVYU,UYVY,RGBX系列,等可以具有合成平面分量的图像格式实际上需要驱动支持)VA_EXPORT_SURFACE_READ_WRITE|VA_EXPORT_SURFACE_COMPOSED_LAYERS导出的结构体参数可能如下合成平面导出时结构体如下:desc{ fourcc0x32595559,width1920,height1080,num_objects1, num_objects[4]{ {fd0x5,size4177920,drm_format_modifier(156|2)} {0} {0} {0} } num_layers1, layers[4]{ {drm_format0x56595559,num_planes1,object_index[4]{0},offset[4]{0},pitch[4]{3840,0,0,0}} {0} {0} {0} } }
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑