From patchwork Tue Apr 28 22:56:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 19349 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id B91A444AF68 for ; Wed, 29 Apr 2020 03:00:34 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 95D9668BCCA; Wed, 29 Apr 2020 03:00:34 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f66.google.com (mail-ej1-f66.google.com [209.85.218.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7363668AF17 for ; Wed, 29 Apr 2020 03:00:28 +0300 (EEST) Received: by mail-ej1-f66.google.com with SMTP id re23so111879ejb.4 for ; Tue, 28 Apr 2020 17:00:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jkqxz-net.20150623.gappssmtp.com; s=20150623; h=to:from:subject:message-id:date:user-agent:mime-version :content-language:content-transfer-encoding; bh=+EKfUAn3RSVggcZNMVNJFPNaK15csOws/Sv7xNT2P+E=; b=fT8L65HZEEWDG7ZUBKHLhrdJ3P2sq1ywgTm0nBGE68m6nD2K9zCnGmMo5KpOgoEIUn zCL9oQPOrGZ7G8UgVqyqq3xWScPDRVYlMSdsf4p1ahlyx2LySNGB6hlqLrz01CUl4r1f y75/ZNXqwZEuv2p4WifxBSF95dNpzU+MQEQLWyeXuBO6lev3c6ckJlJgI+aknsR923e5 /fCbUx6dPVEeKma7j510jazEVYf5lt4aNCP0eYiB1NtF4pM99XcktWHIIzTknbs6qtSf YMe38+9CjSO6S9kQqdvIM9v5lG8G8p9iKMUAhDzWmqUwMy0JZfXbUySKXvAlshJOzt4t U/5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language:content-transfer-encoding; bh=+EKfUAn3RSVggcZNMVNJFPNaK15csOws/Sv7xNT2P+E=; b=RdZC5S8e1DN+1NrfhYZXvms0Q5JPeabIKy3ly8ToVbWrXIW6JtWmk4ukcbY+TGjVz8 V1c0/PUBFgb7Zz3ebgrqOONTeSKiQVAokxLTQMqYlynsZhLbYEtOhQd/KY935ovcu252 IfOvAk+b1+jKoOiTZJ2h8SG/q6g9lTMyd0B78s7V1rMktE8X+8OYp5/RhHVRrRbRy9uV HYTGy2zSrLlVaKMwkXEy9UKnV7qO8I3b5IOljnoFgtvDsIfKV3/UBkOTI4zOj5dbksDF IzJtEw49rjc3/uOl33sRCkn+132nwVF4cui3r3A7JN0j7A5G+oh1xhnXQomJqJY76v1x 0D5g== X-Gm-Message-State: AGi0Pubv0rp8RF3IwHKSOiWiOIdEm0fhUJpgglFtSWVxtMnjAP0z+nUw kmK5KcqNGarmxScdktic2nJcHZ2BoT4= X-Google-Smtp-Source: APiQypJx/GevuGED4jhffn6yr/5RLwnzJkcX3K8exaO19sgDtYu9UqsQF1bl0VW/asL7Eb4scGvKoA== X-Received: by 2002:a5d:574b:: with SMTP id q11mr30221812wrw.324.1588114603954; Tue, 28 Apr 2020 15:56:43 -0700 (PDT) Received: from [192.168.0.3] (cpc91242-cmbg18-2-0-cust650.5-4.cable.virginm.net. [82.8.130.139]) by smtp.gmail.com with ESMTPSA id k6sm5331116wma.19.2020.04.28.15.56.42 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Apr 2020 15:56:43 -0700 (PDT) To: FFmpeg development discussions and patches From: Mark Thompson Message-ID: Date: Tue, 28 Apr 2020 23:56:42 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US Subject: [FFmpeg-devel] [PATCH] ffmpeg: Don't require a known device to pass a frames context to an encoder 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" The previous version here did not handle passing a frames context when ffmpeg itself did not know about the device it came from (for example, because it was created by device derivation inside a filter graph), which would break encoders requiring that input. Fix that by checking for HW frames and device context methods independently, and prefer to use a frames context method if possible. At the same time, revert the encoding additions to the device matching function because the additional complexity was not relevant to decoding. --- fftools/ffmpeg_hw.c | 75 +++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/fftools/ffmpeg_hw.c b/fftools/ffmpeg_hw.c index c5c8aa97ef..fc4a5d31d6 100644 --- a/fftools/ffmpeg_hw.c +++ b/fftools/ffmpeg_hw.c @@ -19,6 +19,7 @@ #include #include "libavutil/avstring.h" +#include "libavutil/pixdesc.h" #include "libavfilter/buffersink.h" #include "ffmpeg.h" @@ -282,10 +283,7 @@ void hw_device_free_all(void) nb_hw_devices = 0; } -static HWDevice *hw_device_match_by_codec(const AVCodec *codec, - enum AVPixelFormat format, - int possible_methods, - int *matched_methods) +static HWDevice *hw_device_match_by_codec(const AVCodec *codec) { const AVCodecHWConfig *config; HWDevice *dev; @@ -294,18 +292,11 @@ static HWDevice *hw_device_match_by_codec(const AVCodec *codec, config = avcodec_get_hw_config(codec, i); if (!config) return NULL; - if (format != AV_PIX_FMT_NONE && - config->pix_fmt != AV_PIX_FMT_NONE && - config->pix_fmt != format) - continue; - if (!(config->methods & possible_methods)) + if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) continue; dev = hw_device_get_by_type(config->device_type); - if (dev) { - if (matched_methods) - *matched_methods = config->methods & possible_methods; + if (dev) return dev; - } } } @@ -351,9 +342,7 @@ int hw_device_setup_for_decode(InputStream *ist) if (!dev) err = hw_device_init_from_type(type, NULL, &dev); } else { - dev = hw_device_match_by_codec(ist->dec, AV_PIX_FMT_NONE, - AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, - NULL); + dev = hw_device_match_by_codec(ist->dec); if (!dev) { // No device for this codec, but not using generic hwaccel // and therefore may well not need one - ignore. @@ -429,37 +418,57 @@ int hw_device_setup_for_decode(InputStream *ist) int hw_device_setup_for_encode(OutputStream *ost) { - HWDevice *dev; - AVBufferRef *frames_ref; - int methods = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX; - int matched_methods; + const AVCodecHWConfig *config; + HWDevice *dev = NULL; + AVBufferRef *frames_ref = NULL; + int i; if (ost->filter) { frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter); if (frames_ref && ((AVHWFramesContext*)frames_ref->data)->format == - ost->enc_ctx->pix_fmt) - methods |= AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX; + ost->enc_ctx->pix_fmt) { + // Matching format, will try to use hw_frames_ctx. + } else { + frames_ref = NULL; + } } - dev = hw_device_match_by_codec(ost->enc, ost->enc_ctx->pix_fmt, - methods, &matched_methods); - if (dev) { - if (matched_methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) { - ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); - if (!ost->enc_ctx->hw_device_ctx) - return AVERROR(ENOMEM); - } - if (matched_methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) { + for (i = 0;; i++) { + config = avcodec_get_hw_config(ost->enc, i); + if (!config) + break; + + if (frames_ref && + config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && + (config->pix_fmt == AV_PIX_FMT_NONE || + config->pix_fmt == ost->enc_ctx->pix_fmt)) { + av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input " + "frames context (format %s) with %s encoder.\n", + av_get_pix_fmt_name(ost->enc_ctx->pix_fmt), + ost->enc->name); ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref); if (!ost->enc_ctx->hw_frames_ctx) return AVERROR(ENOMEM); + return 0; } - return 0; + + if (!dev && + config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) + dev = hw_device_get_by_type(config->device_type); + } + + if (dev) { + av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s " + "(type %s) with %s encoder.\n", dev->name, + av_hwdevice_get_type_name(dev->type), ost->enc->name); + ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); + if (!ost->enc_ctx->hw_device_ctx) + return AVERROR(ENOMEM); } else { // No device required, or no device available. - return 0; } + return 0; } static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)