From patchwork Wed Mar 21 23:12:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 8084 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.1.70 with SMTP id c67csp154617jad; Wed, 21 Mar 2018 16:18:37 -0700 (PDT) X-Google-Smtp-Source: AG47ELufefsdYXIvCfLeA2mhYjja1yHzR5/8dzti4ZhvW+YOlBKkYIXMshU+5coig9GlcU+DiZD0 X-Received: by 10.223.150.161 with SMTP id u30mr17268725wrb.151.1521674317362; Wed, 21 Mar 2018 16:18:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521674317; cv=none; d=google.com; s=arc-20160816; b=m9+9VRWXyIRcKQ1BiwoWJ0gp3ICwt4iXxFrlm6eLZ12C6fktjHnflYHyRmM7BfnLU5 VZ2j7kPUPaAntsGFuvJwhz93XzEce3kdu03tPJZsgs4k3iZ7IG7RO4UxSBlZ+yDsaZie v5kZ3zfTirL8neFdkPXAPr0EV8xFmhOeGEd8kmyX5XcOdnwRPsodH0N7TDRtIO2afynT HyCCBnNIWlPxmb6PFHmPCWD0kivNaDOOCTx1qscbact7dDdbQNYQz85+0VmUcoyEsQwZ 4BtazwY1QoXeLbvlTwdP9qPPwQaDegquFsKc+vYRZgj1X592S2JKEjWqsO2BTAPfiobf Y7AA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=fEBdvcRNiIErYLlPMcazRXmuAkL+KpDlCztKb0/nNIs=; b=py4rpBtizN89OLr1nJFh+QzJTb99VSekUVrd+F7tBwgLnnefz6KMGECgOkZKHqtg/Z XH61PynFfkPrtFOVEATPjsuulbZ9Anf+48NHkLPYkkJnDuyg2i8wuOFOjLJfusUCv9zV edJS2HSOvfKGjBYTXhEgdLFK5O7P6HpB47a2DCjN/TKeYt8K6fkBR5CgW3aABshux2M7 MtV3K90RL0uAuahfSrWVKGQabViaAkA5sotRM7tvm3KEWXDj6gx60U6a1kELUvNNDwoW zebg1iwhCHoj77a9RiL+zBfHXmpOAd+fWWfRy7QURazUs4ADIwppHc/7F0C8L8Bd88Eh qGCQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@jkqxz-net.20150623.gappssmtp.com header.s=20150623 header.b=abKPTdyF; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id h63si3511683wmh.118.2018.03.21.16.18.37; Wed, 21 Mar 2018 16:18:37 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@jkqxz-net.20150623.gappssmtp.com header.s=20150623 header.b=abKPTdyF; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 098BB689C30; Thu, 22 Mar 2018 01:18:10 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0CD17689B17 for ; Thu, 22 Mar 2018 01:18:06 +0200 (EET) Received: by mail-wr0-f194.google.com with SMTP id o1so6842570wro.10 for ; Wed, 21 Mar 2018 16:18:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jkqxz-net.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references; bh=ag/HzcK63kB02N6FU0DxmdOcWy7c7XczPEL5t2TtUJU=; b=abKPTdyFUgVOwLGTbZSmC/5Je+j/b/c1CmaUJGc2mU0G0O0OA1N3hUA/QNfyS4VjLX A8cDwkU0XRl3HANdq4RPENNi0aWkurtVK75JM+jZ/k+ZDh1WnPt/Aa8tHMFLbAhbqGXA KZbsBSI5r/ZkCuj8vFo9H2H6GdJ1axCLQVBJkglZaG8fjAZg868HF+GF6VsjIjNlB5uO segzRDqWa3+9cVakqAlFxqCgtd2eYRkHemDoGcohc+hMzeqhFr1xCGS5rdzG0LS5DuT3 23lK/sdQCyF+szfm2gbP5ltPZuGz8pzJJnrtA5yuD4IfPHrCAVyesvT2os1nkhkFW+Af b1jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=ag/HzcK63kB02N6FU0DxmdOcWy7c7XczPEL5t2TtUJU=; b=EJi8gZsKdpzGpVtBnB8EwHL0ubj+WqZBmorFFFv6C9AKnkpXhW1NS9MaL3dv9HOZd5 21790kRvNVYRjXWe/KM64uhlA7PAK0dDlrLRDuue4SoBYmAveH47IAQODy8fVcHTlT44 yPqP871dPDt+/fCeStmw9Sm/3c5LZLJIBMs0SQ3TSdN46zcSBFABOYmG1DjHvIGIJem+ Zfbdz9ZbdCb3zwgzH1vxDYoC/kbiJoa8HKaGILurNs3eY+k4WS2EhgSxhOY+CDBeNNGe 09rwLXSr1DyiLjFL6wAczeaxAqPlWmhsPQ2Pba2AIJN08hCIbbfaTpOMZhJL8oJIG4JX RtTQ== X-Gm-Message-State: AElRT7HzWKUcW10iqeksIarQX9/5wxMziAelO5GLWNgxcfAacEfy3rMD P1YkAS2JZoABbhdZT2q8kZa9Q/Yp X-Received: by 10.223.152.142 with SMTP id w14mr19033033wrb.210.1521673961506; Wed, 21 Mar 2018 16:12:41 -0700 (PDT) Received: from rywe.jkqxz.net (cpc91242-cmbg18-2-0-cust650.5-4.cable.virginm.net. [82.8.130.139]) by smtp.gmail.com with ESMTPSA id 11sm5218741wmd.1.2018.03.21.16.12.40 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Mar 2018 16:12:40 -0700 (PDT) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Wed, 21 Mar 2018 23:12:31 +0000 Message-Id: <20180321231236.3024-2-sw@jkqxz.net> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180321231236.3024-1-sw@jkqxz.net> References: <20180321231236.3024-1-sw@jkqxz.net> Subject: [FFmpeg-devel] [PATCH v2 2/7] hwcontext_vaapi: Add support for legacy DRM mapping X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" The old vaAcquireBufferHandle() API works in fewer cases and provides less information than the current vaExportSurfaceHandle(), but it exists on older versions and is already used by the OpenCL code. --- Now we set the INVALID format modifier so that a user can distinguish between ESH with linear format modifier and ABH with unknown format modifier. It is kernel ABI and therefore fixed, but the constant needs a recent libdrm; get around that by defining it locally if it isn't present. libavutil/hwcontext_vaapi.c | 194 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 12 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 3797005433..998e954c44 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -28,6 +28,9 @@ #if CONFIG_LIBDRM # include # include +# ifndef DRM_FORMAT_MOD_INVALID +# define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) +# endif #endif #include @@ -1071,8 +1074,9 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, return 0; } -static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc, - HWMapDescriptor *hwmap) +#if VA_CHECK_VERSION(1, 1, 0) +static void vaapi_unmap_to_drm_esh(AVHWFramesContext *hwfc, + HWMapDescriptor *hwmap) { AVDRMFrameDescriptor *drm_desc = hwmap->priv; int i; @@ -1083,10 +1087,9 @@ static void vaapi_unmap_to_drm(AVHWFramesContext *dst_fc, av_freep(&drm_desc); } -static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, - const AVFrame *src, int flags) +static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) { -#if VA_CHECK_VERSION(1, 1, 0) AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; VASurfaceID surface_id; VAStatus vas; @@ -1138,7 +1141,7 @@ static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, } err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, - &vaapi_unmap_to_drm, drm_desc); + &vaapi_unmap_to_drm_esh, drm_desc); if (err < 0) goto fail; @@ -1153,15 +1156,182 @@ fail: close(va_desc.objects[i].fd); av_freep(&drm_desc); return err; -#else - // Older versions without vaExportSurfaceHandle() are not supported - - // in theory this is possible with a combination of vaDeriveImage() - // and vaAcquireBufferHandle(), but it doesn't carry enough metadata - // to actually use the result in a generic way. - return AVERROR(ENOSYS); +} #endif + +typedef struct VAAPIDRMImageBufferMapping { + VAImage image; + VABufferInfo buffer_info; + + AVDRMFrameDescriptor drm_desc; +} VAAPIDRMImageBufferMapping; + +static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc, + HWMapDescriptor *hwmap) +{ + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAAPIDRMImageBufferMapping *mapping = hwmap->priv; + VASurfaceID surface_id; + VAStatus vas; + + surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3]; + av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n", + surface_id); + + // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(), + // so we shouldn't close them separately. + + vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer " + "handle of image %#x (derived from surface %#x): " + "%d (%s).\n", mapping->image.buf, surface_id, + vas, vaErrorStr(vas)); + } + + vas = vaDestroyImage(hwctx->display, mapping->image.image_id); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image " + "derived from surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + } + + av_free(mapping); } + +static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VAAPIDRMImageBufferMapping *mapping = NULL; + VASurfaceID surface_id; + VAStatus vas; + int err, i, p; + + surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n", + surface_id); + + mapping = av_mallocz(sizeof(*mapping)); + if (!mapping) + return AVERROR(ENOMEM); + + vas = vaDeriveImage(hwctx->display, surface_id, + &mapping->image); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " + "surface %#x: %d (%s).\n", + surface_id, vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail; + } + + for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { + if (vaapi_drm_format_map[i].va_fourcc == + mapping->image.format.fourcc) + break; + } + if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) { + av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for " + "VAAPI format %#x.\n", mapping->image.format.fourcc); + err = AVERROR(EINVAL); + goto fail_derived; + } + + mapping->buffer_info.mem_type = + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + + mapping->drm_desc.nb_layers = + vaapi_drm_format_map[i].nb_layer_formats; + if (mapping->drm_desc.nb_layers > 1) { + if (mapping->drm_desc.nb_layers != mapping->image.num_planes) { + av_log(hwfc, AV_LOG_ERROR, "Image properties do not match " + "expected format: got %d planes, but expected %d.\n", + mapping->image.num_planes, mapping->drm_desc.nb_layers); + err = AVERROR(EINVAL); + goto fail_derived; + } + + for(p = 0; p < mapping->drm_desc.nb_layers; p++) { + mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) { + .format = vaapi_drm_format_map[i].layer_formats[p], + .nb_planes = 1, + .planes[0] = { + .object_index = 0, + .offset = mapping->image.offsets[p], + .pitch = mapping->image.pitches[p], + }, + }; + } + } else { + mapping->drm_desc.layers[0].format = + vaapi_drm_format_map[i].layer_formats[0]; + mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes; + for (p = 0; p < mapping->image.num_planes; p++) { + mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) { + .object_index = 0, + .offset = mapping->image.offsets[p], + .pitch = mapping->image.pitches[p], + }; + } + } + + vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf, + &mapping->buffer_info); + if (vas != VA_STATUS_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer " + "handle from image %#x (derived from surface %#x): " + "%d (%s).\n", mapping->image.buf, surface_id, + vas, vaErrorStr(vas)); + err = AVERROR(EIO); + goto fail_derived; + } + + av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n", + mapping->buffer_info.handle); + + mapping->drm_desc.nb_objects = 1; + mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) { + .fd = mapping->buffer_info.handle, + .size = mapping->image.data_size, + // There is no way to get the format modifier with this API. + .format_modifier = DRM_FORMAT_MOD_INVALID, + }; + + err = ff_hwframe_map_create(src->hw_frames_ctx, + dst, src, &vaapi_unmap_to_drm_abh, + mapping); + if (err < 0) + goto fail_mapped; + + dst->data[0] = (uint8_t*)&mapping->drm_desc; + dst->width = src->width; + dst->height = src->height; + + return 0; + +fail_mapped: + vaReleaseBufferHandle(hwctx->display, mapping->image.buf); +fail_derived: + vaDestroyImage(hwctx->display, mapping->image.image_id); +fail: + av_freep(&mapping); + return err; +} + +static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ +#if VA_CHECK_VERSION(1, 1, 0) + int err; + err = vaapi_map_to_drm_esh(hwfc, dst, src, flags); + if (err != AVERROR(ENOSYS)) + return err; #endif + return vaapi_map_to_drm_abh(hwfc, dst, src, flags); +} + +#endif /* CONFIG_LIBDRM */ static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)