From patchwork Tue Dec 20 15:20:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitrii Ovchinnikov X-Patchwork-Id: 39733 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bc95:b0:ad:ade2:bfd2 with SMTP id fx21csp5048895pzb; Tue, 20 Dec 2022 07:20:58 -0800 (PST) X-Google-Smtp-Source: AMrXdXvUgtTm9+cRjyo+XFxr9yHISixJ+PU+QDe9PQYOEwao4Vve8yPDQGDjfOFrYdIpkiFrMaGg X-Received: by 2002:a17:907:9711:b0:7e7:4dd7:bc0c with SMTP id jg17-20020a170907971100b007e74dd7bc0cmr13566007ejc.66.1671549658266; Tue, 20 Dec 2022 07:20:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671549658; cv=none; d=google.com; s=arc-20160816; b=uXgkktzMSMtboQ5mVk0eggQfhcd+Abe8TN851x8BmOazod+b3zO3sV404pmKf3IDJs 304RyNeR3oHzxPqyL4bLBKIiD0Qck7gw4UnW/BUIaoA4dNGfGcQQ6KHpfJk7mcariySb UxPElspim5RbE/wsoK5lsDQlmNnSCh0fXaT6klL2xHq9EW/UYSFd0U9986cgsJpXDYQt iK8HrJbyypysmQIQ+471xDU/4LLQwAY1/bHcm4ZmJK2Kgnjfe3uWsBbJTnTENpXZqiV5 KO8x4Ol4/b/JWYnSvxChGuA4c1sGlvNTwN9icih8mrHJRzG4IRoAW49gm2mXuB66gQmG mD5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=LPKbafYRC52HeZeGilQTGp2oWSHzgHXbx486ARjYiqA=; b=fhj541VwQ9Skd3IdpdgIHzrK0MKvql73QasF0yStfW58Dwk84UBsCaSeCIBDbGLBSC D3lwZJaTA6j9M7z9qTMA+hunJzkDI6zl14nRdFqvTV9e+AVNwAzJkph17Npaid6WPVek 2wrEQtBdLsdXP187CCCe7wK3F4FatQfGT2qPkqx8kQWQa0cEBFibUvqEjrCal2/jRK3g XiHAalcLapDmZdEs0DDDjwFhCsSumW55KeIia2SNTviDwTTtw2fxUuMQR5guy9L3CneH SFyugqKAC/e1yRxdi4JSZmheLjCwekHgMkQYw5la4h8CqyqHVic1a5HdpZJMKHy3RKRl AKTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=AR3fNIAM; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id jl3-20020a17090775c300b007c4efab5f0asi9393224ejc.920.2022.12.20.07.20.57; Tue, 20 Dec 2022 07:20:58 -0800 (PST) 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=@gmail.com header.s=20210112 header.b=AR3fNIAM; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 92A506804F9; Tue, 20 Dec 2022 17:20:53 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f50.google.com (mail-ej1-f50.google.com [209.85.218.50]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D4C076804F9 for ; Tue, 20 Dec 2022 17:20:46 +0200 (EET) Received: by mail-ej1-f50.google.com with SMTP id m18so29978916eji.5 for ; Tue, 20 Dec 2022 07:20:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=ECfJaQMFnoQISC2Szva54d64HFIaKUi/jVblXRjlqTY=; b=AR3fNIAMp5xDIRF6i7hc2Cnjtjqek6GI5DnFu0IhC+X6WUCqeB13cVYa7W6q/Ez7Ep 3abcg7QTCCBpiNaGjVsmgxm9YF+Yoa9/t6I+UjsCzrrsnLvXUjO+IsvGQwZRjPRJqKeO sILE6olmhKxiMd1miqWPjWEaxKVACt6hJVp9U0uM6GXhZZt0UXWeqmEwnri5xZaVyxth As2vCcMKzLQNs7SqvZDFCq331po5UoyIenxEgwmYzjpoaQ+vkrYN78mqvYgWFB8XW23e g+5D3mrkUj/zd6xk+7zWYDRp7ylnfNwqnFFWSuGLprkyXPeVkdCqQsfts7t5Bn+WsUVQ PI3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ECfJaQMFnoQISC2Szva54d64HFIaKUi/jVblXRjlqTY=; b=ClbPPWixwVoxud/68pf70ci3x4nZoK16qSYjwfhQHJUZUWJ/NHzOA1DOymFDEBqHJN mS4q20/0RRJwnhV1Q5wLRQDCnIahgI91Nkft7jH7NIDN7n1LzLQ1wAk3XmlVVgsx2bT3 1Tqc4NLUThwb1T1dNXPUhRAGt7wBO4RJNqNqaVjKu2k17fYEyUMaLb7a6DCxDTIT+jfr p6FbPwzJm9abg6ZGqMy6Yv7DHZcQO4aEjbhkbYiPcPnCSmxImPTyx8J6kQreYeocXMU3 mI3nirfM3YAHmBhRqLC0YHv30NvyAETamp+qw1NiL7/4C7HqIgnrKHPwE3slHlftZfls 5z4A== X-Gm-Message-State: ANoB5pnZaFQS4CpulXjApLsDoXTIj9LWWj1zhefpepCLOFCORFvrE/f8 6i0P2KYUcrIFTPHZbES+p8FzModJrL0= X-Received: by 2002:a17:906:2a55:b0:7a2:7226:6c2d with SMTP id k21-20020a1709062a5500b007a272266c2dmr37026734eje.22.1671549645813; Tue, 20 Dec 2022 07:20:45 -0800 (PST) Received: from dovchinn.amd.com (109-93-70-158.dynamic.isp.telekom.rs. [109.93.70.158]) by smtp.gmail.com with ESMTPSA id u2-20020a1709061da200b007c081cf2d25sm5637437ejh.204.2022.12.20.07.20.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Dec 2022 07:20:45 -0800 (PST) From: Dmitrii Ovchinnikov X-Google-Original-From: Dmitrii Ovchinnikov To: ffmpeg-devel@ffmpeg.org Date: Tue, 20 Dec 2022 16:20:37 +0100 Message-Id: <20221220152038.1795-1-Dmitriy.Ovchinnikov@amd.com> X-Mailer: git-send-email 2.38.1.windows.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2] amfenc: Update the min version to 1.4.28.0 for AMF SDK. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Dmitrii Ovchinnikov Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: b7rqznvODeqX From: Dmitrii Ovchinnikov --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 2180ebb4f1..8a20d67612 100755 --- a/configure +++ b/configure @@ -7034,7 +7034,7 @@ fi enabled amf && check_cpp_condition amf "AMF/core/Version.h" \ - "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400090000" + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x00010004001c0000" # Funny iconv installations are not unusual, so check it after all flags have been set if enabled libc_iconv; then From patchwork Tue Dec 20 15:20:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitrii Ovchinnikov X-Patchwork-Id: 39734 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bc95:b0:ad:ade2:bfd2 with SMTP id fx21csp5049018pzb; Tue, 20 Dec 2022 07:21:10 -0800 (PST) X-Google-Smtp-Source: AMrXdXsNOg7drVXkAu5yvZtrWEo839d3NImLVtKnfTjTRtrwPxORx9ZpNjPRzwMzq2JEH920rI0z X-Received: by 2002:a17:907:d604:b0:836:e6f7:8138 with SMTP id wd4-20020a170907d60400b00836e6f78138mr2885903ejc.13.1671549670623; Tue, 20 Dec 2022 07:21:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671549670; cv=none; d=google.com; s=arc-20160816; b=uSAu1NZRk40WZdqYFR0eYWQSqwqC4Juv5an+HAV28PhOTmZ0BJr5MoPu9TDrmiUWiQ MQH9dU0ihaIfDTjM6MnYliFeLCLziGNoKyYNyAkmVdYxrwQ6GQUDkWALEp0v6RqAKsxl /+RPnexeaHFVoB14xGE1OcVomsMdzjWocvbx3A/sW0gZWkmHVSBIo5H0p2UruQWnBG0M hWvzjClCy3+0t4D0eWypCdRDoI30S2RkNHxhGR9/IU1JeXjARJm54IBziGfsITtQmLC0 mQdCX4tTTb29hEUkaYlzV/oG3suEmCxdWSwzjRQpoRIuY9UIHFHhSRZVhIDk5uLhX1Qg UsIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=Tby7pCcE89qh8ktW+czOQwiwjqa7VGc7amzS1vFD3p8=; b=AeBF1mkn0DoVBPhCNdV06lHSokNZ3CKWNw80l/Qm5V9Nh0yEg9p6bNBO5kIoZIBiMC ienq820C/6EdZVrxVNn+KHXQagyGsw4C8EddlCePMT7UvdRlOSdf0F3xPmpFCtxI6HUw hvOO0Whzw8MgC08BRLjUwdMdRhW3yAJuvaqEhXzIBNXnpIMEupVw2dl0el/Sp00cTCVa eKwzG82ut4dsDH8S7VETXgXvRTaK78ck/401I621ea9yZq76ilwchv864Qm8ex2/FfTh c68Jv6ASrQ9A5gBhOtzMLq3jSOfHzEMY/s3BmIN4Oyz4R2+W06c8ptGiwqTueGyYp0St s9mA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=dPytXqY7; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id gs39-20020a1709072d2700b007c0fa2e0f9fsi316867ejc.133.2022.12.20.07.21.08; Tue, 20 Dec 2022 07:21:10 -0800 (PST) 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=@gmail.com header.s=20210112 header.b=dPytXqY7; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CF2BB68BA5C; Tue, 20 Dec 2022 17:20:54 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E6029680CE8 for ; Tue, 20 Dec 2022 17:20:47 +0200 (EET) Received: by mail-ed1-f44.google.com with SMTP id d20so18022109edn.0 for ; Tue, 20 Dec 2022 07:20:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=heA0OrX3xoc88eP22/jPHNeRVLmDxr0g6rKalkhjLTw=; b=dPytXqY7l1wVsUHeX/ILXMumdJcXKDr4Km+a0Ijubiy/bQ2roLiB2gOskzgxQ0AF58 lW+7C+wyn9LcvkAl0z35nJU3RzG0Hb8UfH+zA73xd8599F36EvCUSaYaMQXfYwcyQVnC bLrcuH2s9A1Ro9sdWGFoZVWFnCtbcuOsNvKxNbbQn5w60h/4vPEsCUutpWSVdk+lDJRk 3Xo+hqng+JMDFR6kRaRa8X+NGf8u8yxHlhVDAZIimSqzYIpt23i5wjbp/XOc5XCYdWcB +hW1luYvpjJmx/UsnDbDF1Q2U+uITBT93mUkTzZu5nm5SISGLffy98t5+6BXSJDGrxlm zAFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=heA0OrX3xoc88eP22/jPHNeRVLmDxr0g6rKalkhjLTw=; b=0+HzoWcMU3q6QLrUdTJ708jrd4KCR+baIMy51IBk/KUC4W27sc+QtZPA4TShQxTRFu ITPTrLYO3IUcnGw0LW7yvNNvCUbUWR98TZwR5zhMaptATwCJNorBsuXXWUZXd2IFUAQc Oca2+qbicwJxpZBEYhj1JLe+rQs+qoDA0JtvzCnptme3xNSh85rJlGWULenbObFQ4gtO llBRsr/8VGNOzhub/LClPRtszL1xjb+MbmAXGjj4pnlPNdQ0bG7O8SkYCaLLYmYQEoqs zZttKA7TnhDJJ04jS5oPQhhyq8Vsws1KLAA1fbFRFl1Ss1zS7E1SIjT+ZZpKGQzfe4Xf +/Tw== X-Gm-Message-State: ANoB5pncy5dgqcW/01xRS0YxboKS5DuP9VsTO/AfBHQxomeBeX04G4nY A0K8u2UGBME2aR/eFNukRRkYiOZRYLA= X-Received: by 2002:aa7:cb54:0:b0:46a:96b3:22bf with SMTP id w20-20020aa7cb54000000b0046a96b322bfmr41920684edt.17.1671549646690; Tue, 20 Dec 2022 07:20:46 -0800 (PST) Received: from dovchinn.amd.com (109-93-70-158.dynamic.isp.telekom.rs. [109.93.70.158]) by smtp.gmail.com with ESMTPSA id u2-20020a1709061da200b007c081cf2d25sm5637437ejh.204.2022.12.20.07.20.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Dec 2022 07:20:46 -0800 (PST) From: Dmitrii Ovchinnikov X-Google-Original-From: Dmitrii Ovchinnikov To: ffmpeg-devel@ffmpeg.org Date: Tue, 20 Dec 2022 16:20:38 +0100 Message-Id: <20221220152038.1795-2-Dmitriy.Ovchinnikov@amd.com> X-Mailer: git-send-email 2.38.1.windows.1 In-Reply-To: <20221220152038.1795-1-Dmitriy.Ovchinnikov@amd.com> References: <20221220152038.1795-1-Dmitriy.Ovchinnikov@amd.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/2] libavcodec/amfenc: add AV1 encoding support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Dmitrii Ovchinnikov Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 9WlPBBKVfRyg From: Dmitrii Ovchinnikov --- configure | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/amfenc.c | 9 + libavcodec/amfenc.h | 6 + libavcodec/amfenc_av1.c | 361 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 379 insertions(+) create mode 100644 libavcodec/amfenc_av1.c diff --git a/configure b/configure index 8a20d67612..56c959012e 100755 --- a/configure +++ b/configure @@ -3255,6 +3255,7 @@ wmv3_crystalhd_decoder_select="crystalhd" av1_qsv_decoder_select="qsvdec" av1_qsv_encoder_select="qsvenc" av1_qsv_encoder_deps="libvpl" +av1_amf_encoder_deps="amf" # parsers aac_parser_select="adts_header mpeg4audio" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 98841ed07c..25686c2991 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -163,6 +163,7 @@ OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o +OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP) += videodsp.o OBJS-$(CONFIG_VP3DSP) += vp3dsp.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d5a6c427e1..d7d83be293 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -831,6 +831,7 @@ extern const FFCodec ff_av1_cuvid_decoder; extern const FFCodec ff_av1_nvenc_encoder; extern const FFCodec ff_av1_qsv_decoder; extern const FFCodec ff_av1_qsv_encoder; +extern const FFCodec ff_av1_amf_encoder; extern const FFCodec ff_libopenh264_encoder; extern const FFCodec ff_libopenh264_decoder; extern const FFCodec ff_h264_amf_encoder; diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index a033e1220e..c487fc48aa 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -349,6 +349,9 @@ static int amf_init_encoder(AVCodecContext *avctx) case AV_CODEC_ID_HEVC: codec_id = AMFVideoEncoder_HEVC; break; + case AV_CODEC_ID_AV1 : + codec_id = AMFVideoEncoder_AV1; + break; default: break; } @@ -460,6 +463,11 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff pkt->flags = AV_PKT_FLAG_KEY; } break; + case AV_CODEC_ID_AV1: + buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE, &var); + if (var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY) { + pkt->flags = AV_PKT_FLAG_KEY; + } default: break; } @@ -681,6 +689,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) case AV_CODEC_ID_HEVC: AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); break; + //case AV_CODEC_ID_AV1 not supported default: break; } diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 1ab98d2f78..66e0680719 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -23,6 +23,7 @@ #include #include +#include #include "libavutil/fifo.h" @@ -116,6 +117,11 @@ typedef struct AmfContext { int min_qp_p; int max_qp_p; int tier; + + // AV1 - specific options + + enum AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM align; + } AmfContext; extern const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]; diff --git a/libavcodec/amfenc_av1.c b/libavcodec/amfenc_av1.c new file mode 100644 index 0000000000..6065ce43d9 --- /dev/null +++ b/libavcodec/amfenc_av1.c @@ -0,0 +1,361 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "amfenc.h" +#include "codec_internal.h" +#include "internal.h" + +#define OFFSET(x) offsetof(AmfContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING }, AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING, AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY, VE, "usage" }, + { "transcoding", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING }, 0, 0, VE, "usage" }, + { "lowlatency", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" }, + + { "profile", "Set the profile (default main)", OFFSET(profile), AV_OPT_TYPE_INT,{.i64 = AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN }, AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN, AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST,{.i64 = AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN }, 0, 0, VE, "profile" }, + + { "level", "Set the encoding level (default auto)", OFFSET(level), AV_OPT_TYPE_INT,{.i64 = 0 }, 0, AMF_VIDEO_ENCODER_AV1_LEVEL_7_3, VE, "level" }, + { "auto", "", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, VE, "level" }, + { "2.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_0 }, 0, 0, VE, "level" }, + { "2.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_1 }, 0, 0, VE, "level" }, + { "2.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_2 }, 0, 0, VE, "level" }, + { "2.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_2_3 }, 0, 0, VE, "level" }, + { "3.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_0 }, 0, 0, VE, "level" }, + { "3.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_1 }, 0, 0, VE, "level" }, + { "3.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_2 }, 0, 0, VE, "level" }, + { "3.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_3_3 }, 0, 0, VE, "level" }, + { "4.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_0 }, 0, 0, VE, "level" }, + { "4.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_1 }, 0, 0, VE, "level" }, + { "4.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_2 }, 0, 0, VE, "level" }, + { "4.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_4_3 }, 0, 0, VE, "level" }, + { "5.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_0 }, 0, 0, VE, "level" }, + { "5.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_1 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_2 }, 0, 0, VE, "level" }, + { "5.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_5_3 }, 0, 0, VE, "level" }, + { "6.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_0 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_1 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_2 }, 0, 0, VE, "level" }, + { "6.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_6_3 }, 0, 0, VE, "level" }, + { "7.0", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_0 }, 0, 0, VE, "level" }, + { "7.1", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_1 }, 0, 0, VE, "level" }, + { "7.2", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_2 }, 0, 0, VE, "level" }, + { "7.3", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_LEVEL_7_3 }, 0, 0, VE, "level" }, + + { "quality", "Set the encoding quality", OFFSET(quality), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED, VE, "quality" }, + { "balanced", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" }, + { "speed", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" }, + { "quality", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, + { "high_quality", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY }, 0, 0, VE, "quality" }, + + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR, VE, "rc" }, + { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, + { "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" }, + { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, + + { "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED, VE, "hdrmode" }, + { "none", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" }, + { "gop", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, + { "frame", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED }, 0, 0, VE, "hdrmode" }, + + { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE}, + + // min_qp_i -> min_qp_intra, min_qp_p -> min_qp_inter + { "min_qp_i", "min quantization parameter for I-frame", OFFSET(min_qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "max_qp_i", "max quantization parameter for I-frame", OFFSET(max_qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "min_qp_p", "min quantization parameter for P-frame", OFFSET(min_qp_p), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "max_qp_p", "max quantization parameter for P-frame", OFFSET(max_qp_p), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "qp_p", "quantization parameter for P-frame", OFFSET(qp_p), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "qp_i", "quantization parameter for I-frame", OFFSET(qp_i), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 255, VE }, + { "skip_frame", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_BOOL,{.i64 = 0 }, 0, 1, VE }, + + { "align", "alignment mode", OFFSET(align), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS }, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS, VE, "align" }, + { "64x16", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY }, 0, 0, VE, "align" }, + { "1080p", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082 }, 0, 0, VE, "align" }, + { "none", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS }, 0, 0, VE, "align" }, + + { NULL } + +}; + +static av_cold int amf_encode_init_av1(AVCodecContext* avctx) +{ + int ret = 0; + AMF_RESULT res = AMF_OK; + AmfContext* ctx = avctx->priv_data; + AMFVariantStruct var = { 0 }; + amf_int64 profile = 0; + amf_int64 profile_level = 0; + AMFBuffer* buffer; + AMFGuid guid; + AMFRate framerate; + AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); + + + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); + } + else { + framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame); + } + + if ((ret = ff_amf_encode_init(avctx)) < 0) + return ret; + + // init static parameters + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_USAGE, ctx->usage); + + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FRAMERATE, framerate); + + switch (avctx->profile) { + case FF_PROFILE_AV1_MAIN: + profile = AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN; + break; + default: + break; + } + if (profile == 0) { + profile = ctx->profile; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PROFILE, profile); + + profile_level = avctx->level; + if (profile_level == FF_LEVEL_UNKNOWN) { + profile_level = ctx->level; + } + if (profile_level != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_LEVEL, profile_level); + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET, ctx->quality); + + // Maximum Reference Frames + if (avctx->refs != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_NUM_REFRAMES, avctx->refs); + } + + // Picture control properties + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_GOP_SIZE, avctx->gop_size); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE, ctx->header_insertion_mode); + + // Rate control + // autodetect rate control method + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN) { + if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || + ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || + ctx->qp_i != -1 || ctx->qp_p != -1) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); + } + else if (avctx->rc_max_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); + } + else { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + } + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD, ctx->rate_control_mode); + if (avctx->rc_buffer_size) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_VBV_BUFFER_SIZE, avctx->rc_buffer_size); + + if (avctx->rc_initial_buffer_occupancy != 0) { + int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size; + if (amf_buffer_fullness > 64) + amf_buffer_fullness = 64; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); + } + } + + // Pre-Pass, Pre-Analysis, Two-Pass + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, ctx->preanalysis); + + // init dynamic rate control params + if (ctx->max_au_size) + ctx->enforce_hrd = 1; + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ENFORCE_HRD, ctx->enforce_hrd); + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FILLER_DATA, ctx->filler_data); + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_TARGET_BITRATE, avctx->bit_rate); + + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE, avctx->bit_rate); + } + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE, avctx->rc_max_rate); + } + else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { + av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); + } + if (avctx->bit_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR; + av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); + } + + switch (ctx->align) + { + case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY: + if (avctx->width / 64 * 64 != avctx->width || avctx->height / 16 * 16 != avctx->height) + { + res = AMF_NOT_SUPPORTED; + av_log(ctx, AV_LOG_ERROR, "Resolution incorrect for alignment mode\n"); + return AVERROR_EXIT; + } + break; + case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082: + if ((avctx->width / 64 * 64 == avctx->width && avctx->height / 16 * 16 == avctx->height) || (avctx->width == 1920 && avctx->height == 1080)) + { + res = AMF_OK; + } + else + { + res = AMF_NOT_SUPPORTED; + av_log(ctx, AV_LOG_ERROR, "Resolution incorrect for alignment mode\n"); + return AVERROR_EXIT; + } + break; + case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS: + res = AMF_OK; + break; + default: + res = AMF_NOT_SUPPORTED; + av_log(ctx, AV_LOG_ERROR, "Invalid alignment mode\n"); + return AVERROR_EXIT; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE, ctx->align); + + + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); + + // init dynamic picture control params + if (ctx->min_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA, ctx->min_qp_i); + } + else if (avctx->qmin != -1) { + int qval = avctx->qmin > 255 ? 255 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA, qval); + } + if (ctx->max_qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA, ctx->max_qp_i); + } + else if (avctx->qmax != -1) { + int qval = avctx->qmax > 255 ? 255 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA, qval); + } + if (ctx->min_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER, ctx->min_qp_p); + } + else if (avctx->qmin != -1) { + int qval = avctx->qmin > 255 ? 255 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER, qval); + } + if (ctx->max_qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER, ctx->max_qp_p); + } + else if (avctx->qmax != -1) { + int qval = avctx->qmax > 255 ? 255 : avctx->qmax; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER, qval); + } + + if (ctx->qp_p != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER, ctx->qp_p); + } + if (ctx->qp_i != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA, ctx->qp_i); + } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME, ctx->skip_frame); + + + // fill extradata + res = AMFVariantInit(&var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); + + res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_EXTRA_DATA, &var); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res); + AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n"); + + guid = IID_AMFBuffer(); + + res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface + if (res != AMF_OK) { + var.pInterface->pVtbl->Release(var.pInterface); + } + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); + + avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + return AVERROR(ENOMEM); + } + memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size); + + buffer->pVtbl->Release(buffer); + var.pInterface->pVtbl->Release(var.pInterface); + + return 0; +} + +static const FFCodecDefault defaults[] = { + { "refs", "-1" }, + { "aspect", "0" }, + { "b", "2M" }, + { "g", "250" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { NULL }, +}; + +static const AVClass av1_amf_class = { + .class_name = "av1_amf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_av1_amf_encoder = { + .p.name = "av1_amf", + CODEC_LONG_NAME("AMD AMF AV1 encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, + .init = amf_encode_init_av1, + FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), + .close = ff_amf_encode_close, + .priv_data_size = sizeof(AmfContext), + .p.priv_class = &av1_amf_class, + .defaults = defaults, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .p.pix_fmts = ff_amf_pix_fmts, + .p.wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, +}; \ No newline at end of file