Jun 19, 2020, 07:47 by haihao.xi...@intel.com: > User should provide the modifier when importing a DMABuf if this DMABuf > has modifier. > > Signed-off-by: Haihao Xiang <haihao.xi...@intel.com> > --- > libavutil/hwcontext_vaapi.c | 137 +++++++++++++++++++++++++++++++++--- > 1 file changed, 126 insertions(+), 11 deletions(-) > > diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c > index a378bcd12a..514bb07a20 100644 > --- a/libavutil/hwcontext_vaapi.c > +++ b/libavutil/hwcontext_vaapi.c > @@ -999,8 +999,9 @@ static void vaapi_unmap_from_drm(AVHWFramesContext > *dst_fc, > vaDestroySurfaces(dst_dev->display, &surface_id, 1); > } > > -static int vaapi_map_from_drm(AVHWFramesContext *dst_fc, AVFrame *dst, > - const AVFrame *src, int flags) > +static VASurfaceID vaapi_get_surface_from_drm_prime(AVHWFramesContext > *dst_fc, > + AVFrame *dst, > + const AVFrame *src) > { > AVHWFramesContext *src_fc = > (AVHWFramesContext*)src->hw_frames_ctx->data; > @@ -1010,7 +1011,7 @@ static int vaapi_map_from_drm(AVHWFramesContext > *dst_fc, AVFrame *dst, > VASurfaceID surface_id; > VAStatus vas; > uint32_t va_fourcc; > - int err, i, j, k; > + int i, j, k; > > unsigned long buffer_handle; > VASurfaceAttribExternalBuffers buffer_desc; > @@ -1030,13 +1031,6 @@ static int vaapi_map_from_drm(AVHWFramesContext > *dst_fc, AVFrame *dst, > }; > > desc = (AVDRMFrameDescriptor*)src->data[0]; > - > - if (desc->nb_objects != 1) { > - av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames " > - "made from a single DRM object.\n"); > - return AVERROR(EINVAL); > - } > - > va_fourcc = 0; > for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { > if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats) > @@ -1092,9 +1086,130 @@ static int vaapi_map_from_drm(AVHWFramesContext > *dst_fc, AVFrame *dst, > src->width, src->height, > &surface_id, 1, > attrs, FF_ARRAY_ELEMS(attrs)); > + > + if (vas != VA_STATUS_SUCCESS) { > + av_log(dst_fc, AV_LOG_DEBUG, "Failed to create surface from > DRM_PRIME " > + "object: %d (%s).\n", vas, vaErrorStr(vas)); > + return VA_INVALID_ID; > + } > + > + return surface_id; > +} > + > +static VASurfaceID vaapi_get_surface_from_drm_prime2(AVHWFramesContext > *dst_fc, > + AVFrame *dst, > + const AVFrame *src) > +{ > + AVHWFramesContext *src_fc = > + (AVHWFramesContext*)src->hw_frames_ctx->data; > + AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; > + const AVDRMFrameDescriptor *desc; > + const VAAPIFormatDescriptor *format_desc; > + VASurfaceID surface_id; > + VAStatus vas; > + uint32_t va_fourcc; > + int i, j; > + > + VADRMPRIMESurfaceDescriptor surface_desc; > + VASurfaceAttrib attrs[2] = { > + { > + .type = VASurfaceAttribMemoryType, > + .flags = VA_SURFACE_ATTRIB_SETTABLE, > + .value.type = VAGenericValueTypeInteger, > + .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, > + }, > + { > + .type = VASurfaceAttribExternalBufferDescriptor, > + .flags = VA_SURFACE_ATTRIB_SETTABLE, > + .value.type = VAGenericValueTypePointer, > + .value.value.p = &surface_desc, > + } > + }; > + > + desc = (AVDRMFrameDescriptor*)src->data[0]; > + va_fourcc = 0; > + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { > + if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats) > + continue; > + for (j = 0; j < desc->nb_layers; j++) { > + if (desc->layers[j].format != > + vaapi_drm_format_map[i].layer_formats[j]) > + break; > + } > + if (j != desc->nb_layers) > + continue; > + va_fourcc = vaapi_drm_format_map[i].va_fourcc; > + break; > + } > + if (!va_fourcc) { > + av_log(dst_fc, AV_LOG_ERROR, "DRM format not supported " > + "by VAAPI.\n"); > + return AVERROR(EINVAL); > + } > + > + av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as " > + "%08x.\n", desc->objects[0].fd, va_fourcc); > + > + format_desc = vaapi_format_from_fourcc(va_fourcc); > + av_assert0(format_desc && !format_desc->chroma_planes_swapped); > + > + surface_desc.fourcc = va_fourcc; > + surface_desc.width = src_fc->width; > + surface_desc.height = src_fc->height; > + surface_desc.num_objects = 1; > + surface_desc.objects[0].fd = desc->objects[0].fd; > + surface_desc.objects[0].size = desc->objects[0].size; > + surface_desc.objects[0].drm_format_modifier = > desc->objects[0].format_modifier; > + surface_desc.num_layers = desc->nb_layers; > + > + for (i = 0; i < desc->nb_layers; i++) { > + surface_desc.layers[i].drm_format = desc->layers[i].format; > + surface_desc.layers[i].num_planes = desc->layers[i].nb_planes; > + > + for (j = 0; j < desc->layers[i].nb_planes; j++) { > + surface_desc.layers[i].object_index[j] = > desc->layers[i].planes[j].object_index; > + surface_desc.layers[i].offset[j] = > desc->layers[i].planes[j].offset; > + surface_desc.layers[i].pitch[j] = > desc->layers[i].planes[j].pitch; > + } > + } > + > + vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, > + src->width, src->height, > + &surface_id, 1, > + attrs, FF_ARRAY_ELEMS(attrs)); > + > if (vas != VA_STATUS_SUCCESS) { > - av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM " > + av_log(dst_fc, AV_LOG_DEBUG, "Failed to create surface from > DRM_PRIME_2" > "object: %d (%s).\n", vas, vaErrorStr(vas)); > + return VA_INVALID_ID; > + } > + > + return surface_id; > +} > + > +static int vaapi_map_from_drm(AVHWFramesContext *dst_fc, AVFrame *dst, > + const AVFrame *src, int flags) > +{ > + const AVDRMFrameDescriptor *desc; > + VASurfaceID surface_id; > + int err; > + > + desc = (AVDRMFrameDescriptor*)src->data[0]; > + > + if (desc->nb_objects != 1) { > + av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames " > + "made from a single DRM object.\n"); > + return AVERROR(EINVAL); > + } > + > + surface_id = vaapi_get_surface_from_drm_prime2(dst_fc, dst, src); > + > + if (surface_id == VA_INVALID_SURFACE) > + surface_id = vaapi_get_surface_from_drm_prime(dst_fc, dst, src); > + > + if (surface_id == VA_INVALID_SURFACE) { > + av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from " > + "DRM_PRIME2 or DRM_PRIME.\n"); > return AVERROR(EIO); > } > av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id); >
I tested this because I need it to import compressed display framebuffers where the second object FD contains the compression parameters, but after patching it, mapping fails with: >[AVHWFramesContext @ 0x5644973a4f00] Failed to read image from surface 0x1: -1 >(unknown libva error). >[dmabuf-capture @ 0x7ffc14d6d9a0] Error encoding: Invalid argument! I've attached a diff of what I used. Does DRM_PRIME_2 on intel still not support compressed framebuffers? Users have been wanting to use kmsgrab but if the compositor picks a compressed modifier, they're out of luck.
diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 514bb07a20..9ced2d2e31 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -1156,10 +1156,12 @@ static VASurfaceID vaapi_get_surface_from_drm_prime2(AVHWFramesContext *dst_fc, surface_desc.fourcc = va_fourcc; surface_desc.width = src_fc->width; surface_desc.height = src_fc->height; - surface_desc.num_objects = 1; - surface_desc.objects[0].fd = desc->objects[0].fd; - surface_desc.objects[0].size = desc->objects[0].size; - surface_desc.objects[0].drm_format_modifier = desc->objects[0].format_modifier; + surface_desc.num_objects = desc->nb_objects; + for (int i = 0; i < surface_desc.num_objects; i++) { + surface_desc.objects[i].fd = desc->objects[i].fd; + surface_desc.objects[i].size = desc->objects[i].size; + surface_desc.objects[i].drm_format_modifier = desc->objects[0].format_modifier; + } surface_desc.num_layers = desc->nb_layers; for (i = 0; i < desc->nb_layers; i++) { @@ -1196,12 +1198,6 @@ static int vaapi_map_from_drm(AVHWFramesContext *dst_fc, AVFrame *dst, desc = (AVDRMFrameDescriptor*)src->data[0]; - if (desc->nb_objects != 1) { - av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames " - "made from a single DRM object.\n"); - return AVERROR(EINVAL); - } - surface_id = vaapi_get_surface_from_drm_prime2(dst_fc, dst, src); if (surface_id == VA_INVALID_SURFACE)
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".