From patchwork Tue Mar 21 22:43:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 3049 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.50.79 with SMTP id y76csp47411vsy; Tue, 21 Mar 2017 15:44:21 -0700 (PDT) X-Received: by 10.28.165.147 with SMTP id o141mr4851970wme.67.1490136261757; Tue, 21 Mar 2017 15:44:21 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id i23si29849784wrc.50.2017.03.21.15.44.21; Tue, 21 Mar 2017 15:44:21 -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; 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 CFA35688345; Wed, 22 Mar 2017 00:43:53 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f49.google.com (mail-wm0-f49.google.com [74.125.82.49]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 83741688326 for ; Wed, 22 Mar 2017 00:43:46 +0200 (EET) Received: by mail-wm0-f49.google.com with SMTP id n11so23109793wma.0 for ; Tue, 21 Mar 2017 15:44:05 -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=OjivClxb+Ao9p6Etqg6c5A6//Nq3fy7+vIGpn9YnurY=; b=ZaoTAafBk3v1csbi8P82uD6Noe8/23IhyXs8+w3sYhMqmkC91Dxme+o9yH42pYk18d gYE2FQdLMIkJXpEruucWhZ6Mk/rQ2SEMWhW2LKq45iJ/jTKNeJ5/YxGhbTfI5b/JNG3F 4WjOynyy06c45dGAaXvdGGDbti9LRSrAtmgzso/FxrzdSs4cDA+bGXkQ6rTC5zCp592J CiAbmAEbxWu+q2YJTBgEgK5n/PUUNYy29njOGq2iynvwgu/rgsGDTLAOJkonWGi+uuQf 2ZOaNNNCH7L/siLSxPPZIv36uinl0n2AsltIHQO0oThs+1oSXOse6ZPEPh+Az/2jlEMH D3Ew== 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=OjivClxb+Ao9p6Etqg6c5A6//Nq3fy7+vIGpn9YnurY=; b=ZUSIJBEiiUZTCzFIQeYaaqFqEhGj72Z5CQ1L7UJayY6Wo+tfdUJ3kSa2ZCWLZYxlMK 7ts72M0PDU0DNyimDxE6fmVdcqiJKZ/ZuYTz/jdvqVPGlSg5i9f+2P5bD0Y/CNnSR5HC x/hJMJdSxkp/iy+NldqMT5hWtESogi8JTkFm5e7wBt+5cmpb2DvE4TPZIwgnwCFu1sM4 xahnINeYpvKaLky4hoOpI6hsUNiAOpo9oeYBDWuzFWfmg3xSUO/js8E6pcvpTb23dVpx lTT2+/AM2p/aVFzOitAqcW55ksZS/lctcb1iCoFpUjJr5HFUyXk8sqwcMstPmDz/2XLU cX/Q== X-Gm-Message-State: AFeK/H17yncjv+Sb5/kkomECzEGd6GLBYoOuEO5LPdSSxcD4Gn35crHRYwHqGo+5bti0/g== X-Received: by 10.28.157.150 with SMTP id g144mr4992607wme.89.1490136244335; Tue, 21 Mar 2017 15:44:04 -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 c35sm26585493wra.1.2017.03.21.15.44.03 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Mar 2017 15:44:03 -0700 (PDT) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Tue, 21 Mar 2017 22:43:56 +0000 Message-Id: <20170321224358.21315-2-sw@jkqxz.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170321224358.21315-1-sw@jkqxz.net> References: <20170321224358.21315-1-sw@jkqxz.net> Subject: [FFmpeg-devel] [PATCH 2/4] vaapi: Implement device-only setup 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" In this case, the user only supplies a device and the frame context is allocated internally by lavc. (cherry picked from commit 5dd9a4b88b287bf8c93520afda7becb1ad0d1894) --- This doesn't work with ffmpeg.c yet (still uses hw_frames_ctx), but is accessible to lavc users. See for the intended structure in ffmpeg.c (not yet merging because of further patches pending). libavcodec/vaapi_decode.c | 129 +++++++++++++++++++++++++++++++++++++++------- libavcodec/vaapi_decode.h | 3 ++ libavcodec/version.h | 2 +- 3 files changed, 115 insertions(+), 19 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index da9e4aedde..b63fb94fc1 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -18,6 +18,7 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/pixdesc.h" #include "avcodec.h" #include "internal.h" @@ -283,6 +284,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) const AVCodecDescriptor *codec_desc; VAProfile profile, *profile_list = NULL; int profile_count, exact_match, alt_profile; + const AVPixFmtDescriptor *sw_desc, *desc; // Allowing a profile mismatch can be useful because streams may // over-declare their required capabilities - in particular, many @@ -375,7 +377,9 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) goto fail; } - hwconfig = av_hwdevice_hwconfig_alloc(ctx->frames->device_ref); + hwconfig = av_hwdevice_hwconfig_alloc(avctx->hw_device_ctx ? + avctx->hw_device_ctx : + ctx->frames->device_ref); if (!hwconfig) { err = AVERROR(ENOMEM); goto fail; @@ -383,24 +387,77 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) hwconfig->config_id = ctx->va_config; constraints = - av_hwdevice_get_hwframe_constraints(ctx->frames->device_ref, + av_hwdevice_get_hwframe_constraints(avctx->hw_device_ctx ? + avctx->hw_device_ctx : + ctx->frames->device_ref, hwconfig); if (!constraints) { - // Ignore. - } else { - if (avctx->coded_width < constraints->min_width || - avctx->coded_height < constraints->min_height || - avctx->coded_width > constraints->max_width || - avctx->coded_height > constraints->max_height) { - av_log(avctx, AV_LOG_ERROR, "Hardware does not support image " - "size %dx%d (constraints: width %d-%d height %d-%d).\n", - avctx->coded_width, avctx->coded_height, - constraints->min_width, constraints->max_width, - constraints->min_height, constraints->max_height); - err = AVERROR(EINVAL); - goto fail; + err = AVERROR(ENOMEM); + goto fail; + } + + if (avctx->coded_width < constraints->min_width || + avctx->coded_height < constraints->min_height || + avctx->coded_width > constraints->max_width || + avctx->coded_height > constraints->max_height) { + av_log(avctx, AV_LOG_ERROR, "Hardware does not support image " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + avctx->coded_width, avctx->coded_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); + err = AVERROR(EINVAL); + goto fail; + } + if (!constraints->valid_sw_formats || + constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any " + "usable surface formats.\n"); + err = AVERROR(EINVAL); + goto fail; + } + + // Find the first format in the list which matches the expected + // bit depth and subsampling. If none are found (this can happen + // when 10-bit streams are decoded to 8-bit surfaces, for example) + // then just take the first format on the list. + ctx->surface_format = constraints->valid_sw_formats[0]; + sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { + desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]); + if (desc->nb_components != sw_desc->nb_components || + desc->log2_chroma_w != sw_desc->log2_chroma_w || + desc->log2_chroma_h != sw_desc->log2_chroma_h) + continue; + for (j = 0; j < desc->nb_components; j++) { + if (desc->comp[j].depth != sw_desc->comp[j].depth) + break; } + if (j < desc->nb_components) + continue; + ctx->surface_format = constraints->valid_sw_formats[i]; + break; + } + + // Start with at least four surfaces. + ctx->surface_count = 4; + // Add per-codec number of surfaces used for storing reference frames. + switch (avctx->codec_id) { + case AV_CODEC_ID_H264: + case AV_CODEC_ID_HEVC: + ctx->surface_count += 16; + break; + case AV_CODEC_ID_VP9: + ctx->surface_count += 8; + break; + case AV_CODEC_ID_VP8: + ctx->surface_count += 3; + break; + default: + ctx->surface_count += 2; } + // Add an additional surface per thread is frame threading is enabled. + if (avctx->active_thread_type & FF_THREAD_FRAME) + ctx->surface_count += avctx->thread_count; av_hwframe_constraints_free(&constraints); av_freep(&hwconfig); @@ -463,13 +520,24 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; ctx->hwfc = ctx->frames->hwctx; - ctx->device = ctx->frames->device_ctx; ctx->hwctx = ctx->device->hwctx; + } else if (avctx->hw_device_ctx) { + ctx->device = (AVHWDeviceContext*)avctx->hw_device_ctx->data; + ctx->hwctx = ctx->device->hwctx; + + if (ctx->device->type != AV_HWDEVICE_TYPE_VAAPI) { + av_log(avctx, AV_LOG_ERROR, "Device supplied for VAAPI " + "decoding must be a VAAPI device (not %d).\n", + ctx->device->type); + err = AVERROR(EINVAL); + goto fail; + } + } else { - av_log(avctx, AV_LOG_ERROR, "A hardware frames context is " - "required for VAAPI decoding.\n"); + av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context " + "is required for VAAPI decoding.\n"); err = AVERROR(EINVAL); goto fail; } @@ -488,6 +556,31 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) if (err) goto fail; + if (!avctx->hw_frames_ctx) { + avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); + if (!avctx->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto fail; + } + ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + + ctx->frames->format = AV_PIX_FMT_VAAPI; + ctx->frames->width = avctx->coded_width; + ctx->frames->height = avctx->coded_height; + + ctx->frames->sw_format = ctx->surface_format; + ctx->frames->initial_pool_size = ctx->surface_count; + + err = av_hwframe_ctx_init(avctx->hw_frames_ctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise internal " + "frames context: %d.\n", err); + goto fail; + } + + ctx->hwfc = ctx->frames->hwctx; + } + vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, avctx->coded_width, avctx->coded_height, VA_PROGRESSIVE, diff --git a/libavcodec/vaapi_decode.h b/libavcodec/vaapi_decode.h index 5ac3069ef3..4fe414c504 100644 --- a/libavcodec/vaapi_decode.h +++ b/libavcodec/vaapi_decode.h @@ -69,6 +69,9 @@ typedef struct VAAPIDecodeContext { AVHWFramesContext *frames; AVVAAPIFramesContext *hwfc; + + enum AVPixelFormat surface_format; + int surface_count; } VAAPIDecodeContext; diff --git a/libavcodec/version.h b/libavcodec/version.h index ec8651f086..8d9dda7675 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 57 #define LIBAVCODEC_VERSION_MINOR 83 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MICRO 102 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \