1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Intel MediaSDK QSV encoder utility functions
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * copyright (c) 2013 Yukinori Yamazoe
5cabdff1aSopenharmony_ci * copyright (c) 2015 Anton Khirnov
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * This file is part of FFmpeg.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17cabdff1aSopenharmony_ci * Lesser General Public License for more details.
18cabdff1aSopenharmony_ci *
19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22cabdff1aSopenharmony_ci */
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "config_components.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include <string.h>
27cabdff1aSopenharmony_ci#include <sys/types.h>
28cabdff1aSopenharmony_ci#include <mfx/mfxvideo.h>
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci#include "libavutil/common.h"
31cabdff1aSopenharmony_ci#include "libavutil/hwcontext.h"
32cabdff1aSopenharmony_ci#include "libavutil/hwcontext_qsv.h"
33cabdff1aSopenharmony_ci#include "libavutil/mem.h"
34cabdff1aSopenharmony_ci#include "libavutil/log.h"
35cabdff1aSopenharmony_ci#include "libavutil/time.h"
36cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
37cabdff1aSopenharmony_ci#include "libavcodec/bytestream.h"
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ci#include "avcodec.h"
40cabdff1aSopenharmony_ci#include "internal.h"
41cabdff1aSopenharmony_ci#include "packet_internal.h"
42cabdff1aSopenharmony_ci#include "qsv.h"
43cabdff1aSopenharmony_ci#include "qsv_internal.h"
44cabdff1aSopenharmony_ci#include "qsvenc.h"
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_cistruct profile_names {
47cabdff1aSopenharmony_ci    mfxU16 profile;
48cabdff1aSopenharmony_ci    const char *name;
49cabdff1aSopenharmony_ci};
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_cistatic const struct profile_names avc_profiles[] = {
52cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_BASELINE,                 "avc baseline"              },
53cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_MAIN,                     "avc main"                  },
54cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_EXTENDED,                 "avc extended"              },
55cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_HIGH,                     "avc high"                  },
56cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_HIGH_422,                 "avc high 422"              },
57cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_CONSTRAINED_BASELINE,     "avc constrained baseline"  },
58cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_CONSTRAINED_HIGH,         "avc constrained high"      },
59cabdff1aSopenharmony_ci    { MFX_PROFILE_AVC_PROGRESSIVE_HIGH,         "avc progressive high"      },
60cabdff1aSopenharmony_ci};
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_cistatic const struct profile_names mpeg2_profiles[] = {
63cabdff1aSopenharmony_ci    { MFX_PROFILE_MPEG2_SIMPLE,                 "mpeg2 simple"                },
64cabdff1aSopenharmony_ci    { MFX_PROFILE_MPEG2_MAIN,                   "mpeg2 main"                  },
65cabdff1aSopenharmony_ci    { MFX_PROFILE_MPEG2_HIGH,                   "mpeg2 high"                  },
66cabdff1aSopenharmony_ci};
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_cistatic const struct profile_names hevc_profiles[] = {
69cabdff1aSopenharmony_ci    { MFX_PROFILE_HEVC_MAIN,                    "hevc main"                  },
70cabdff1aSopenharmony_ci    { MFX_PROFILE_HEVC_MAIN10,                  "hevc main10"                },
71cabdff1aSopenharmony_ci    { MFX_PROFILE_HEVC_MAINSP,                  "hevc mainsp"                },
72cabdff1aSopenharmony_ci    { MFX_PROFILE_HEVC_REXT,                    "hevc rext"                  },
73cabdff1aSopenharmony_ci#if QSV_VERSION_ATLEAST(1, 32)
74cabdff1aSopenharmony_ci    { MFX_PROFILE_HEVC_SCC,                     "hevc scc"                   },
75cabdff1aSopenharmony_ci#endif
76cabdff1aSopenharmony_ci};
77cabdff1aSopenharmony_ci
78cabdff1aSopenharmony_cistatic const struct profile_names vp9_profiles[] = {
79cabdff1aSopenharmony_ci    { MFX_PROFILE_VP9_0,                        "vp9 0"                     },
80cabdff1aSopenharmony_ci    { MFX_PROFILE_VP9_1,                        "vp9 1"                     },
81cabdff1aSopenharmony_ci    { MFX_PROFILE_VP9_2,                        "vp9 2"                     },
82cabdff1aSopenharmony_ci    { MFX_PROFILE_VP9_3,                        "vp9 3"                     },
83cabdff1aSopenharmony_ci};
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_citypedef struct QSVPacket {
86cabdff1aSopenharmony_ci    AVPacket        pkt;
87cabdff1aSopenharmony_ci    mfxSyncPoint   *sync;
88cabdff1aSopenharmony_ci    mfxBitstream   *bs;
89cabdff1aSopenharmony_ci} QSVPacket;
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_cistatic const char *print_profile(enum AVCodecID codec_id, mfxU16 profile)
92cabdff1aSopenharmony_ci{
93cabdff1aSopenharmony_ci    const struct profile_names *profiles;
94cabdff1aSopenharmony_ci    int i, num_profiles;
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci    switch (codec_id) {
97cabdff1aSopenharmony_ci    case AV_CODEC_ID_H264:
98cabdff1aSopenharmony_ci        profiles = avc_profiles;
99cabdff1aSopenharmony_ci        num_profiles = FF_ARRAY_ELEMS(avc_profiles);
100cabdff1aSopenharmony_ci        break;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    case AV_CODEC_ID_MPEG2VIDEO:
103cabdff1aSopenharmony_ci        profiles = mpeg2_profiles;
104cabdff1aSopenharmony_ci        num_profiles = FF_ARRAY_ELEMS(mpeg2_profiles);
105cabdff1aSopenharmony_ci        break;
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci    case AV_CODEC_ID_HEVC:
108cabdff1aSopenharmony_ci        profiles = hevc_profiles;
109cabdff1aSopenharmony_ci        num_profiles = FF_ARRAY_ELEMS(hevc_profiles);
110cabdff1aSopenharmony_ci        break;
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci    case AV_CODEC_ID_VP9:
113cabdff1aSopenharmony_ci        profiles = vp9_profiles;
114cabdff1aSopenharmony_ci        num_profiles = FF_ARRAY_ELEMS(vp9_profiles);
115cabdff1aSopenharmony_ci        break;
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci    default:
118cabdff1aSopenharmony_ci        return "unknown";
119cabdff1aSopenharmony_ci    }
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    for (i = 0; i < num_profiles; i++)
122cabdff1aSopenharmony_ci        if (profile == profiles[i].profile)
123cabdff1aSopenharmony_ci            return profiles[i].name;
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    return "unknown";
126cabdff1aSopenharmony_ci}
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_cistatic const struct {
129cabdff1aSopenharmony_ci    mfxU16      rc_mode;
130cabdff1aSopenharmony_ci    const char *name;
131cabdff1aSopenharmony_ci} rc_names[] = {
132cabdff1aSopenharmony_ci    { MFX_RATECONTROL_CBR,     "CBR" },
133cabdff1aSopenharmony_ci    { MFX_RATECONTROL_VBR,     "VBR" },
134cabdff1aSopenharmony_ci    { MFX_RATECONTROL_CQP,     "CQP" },
135cabdff1aSopenharmony_ci#if QSV_HAVE_AVBR
136cabdff1aSopenharmony_ci    { MFX_RATECONTROL_AVBR,    "AVBR" },
137cabdff1aSopenharmony_ci#endif
138cabdff1aSopenharmony_ci    { MFX_RATECONTROL_LA,      "LA" },
139cabdff1aSopenharmony_ci    { MFX_RATECONTROL_ICQ,     "ICQ" },
140cabdff1aSopenharmony_ci    { MFX_RATECONTROL_LA_ICQ,  "LA_ICQ" },
141cabdff1aSopenharmony_ci#if QSV_HAVE_VCM
142cabdff1aSopenharmony_ci    { MFX_RATECONTROL_VCM,     "VCM" },
143cabdff1aSopenharmony_ci#endif
144cabdff1aSopenharmony_ci    { MFX_RATECONTROL_LA_EXT,  "LA_EXT" },
145cabdff1aSopenharmony_ci    { MFX_RATECONTROL_LA_HRD,  "LA_HRD" },
146cabdff1aSopenharmony_ci    { MFX_RATECONTROL_QVBR,    "QVBR" },
147cabdff1aSopenharmony_ci};
148cabdff1aSopenharmony_ci
149cabdff1aSopenharmony_ci#define UPDATE_PARAM(a, b)  \
150cabdff1aSopenharmony_cido {                        \
151cabdff1aSopenharmony_ci    if ((a) != (b)) {       \
152cabdff1aSopenharmony_ci        a = b;              \
153cabdff1aSopenharmony_ci        updated = 1;        \
154cabdff1aSopenharmony_ci    }                       \
155cabdff1aSopenharmony_ci} while (0)                 \
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_cistatic const char *print_ratecontrol(mfxU16 rc_mode)
158cabdff1aSopenharmony_ci{
159cabdff1aSopenharmony_ci    int i;
160cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(rc_names); i++)
161cabdff1aSopenharmony_ci        if (rc_mode == rc_names[i].rc_mode)
162cabdff1aSopenharmony_ci            return rc_names[i].name;
163cabdff1aSopenharmony_ci    return "unknown";
164cabdff1aSopenharmony_ci}
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_cistatic const char *print_threestate(mfxU16 val)
167cabdff1aSopenharmony_ci{
168cabdff1aSopenharmony_ci    if (val == MFX_CODINGOPTION_ON)
169cabdff1aSopenharmony_ci        return "ON";
170cabdff1aSopenharmony_ci    else if (val == MFX_CODINGOPTION_OFF)
171cabdff1aSopenharmony_ci        return "OFF";
172cabdff1aSopenharmony_ci    return "unknown";
173cabdff1aSopenharmony_ci}
174cabdff1aSopenharmony_ci
175cabdff1aSopenharmony_cistatic void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
176cabdff1aSopenharmony_ci                             mfxExtBuffer **coding_opts)
177cabdff1aSopenharmony_ci{
178cabdff1aSopenharmony_ci    mfxInfoMFX *info = &q->param.mfx;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci    // co is always at index 1
181cabdff1aSopenharmony_ci    mfxExtCodingOption   *co = (mfxExtCodingOption*)coding_opts[1];
182cabdff1aSopenharmony_ci    mfxExtCodingOption2 *co2 = NULL;
183cabdff1aSopenharmony_ci    mfxExtCodingOption3 *co3 = NULL;
184cabdff1aSopenharmony_ci    mfxExtHEVCTiles *exthevctiles = NULL;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci    if (q->co2_idx > 0)
187cabdff1aSopenharmony_ci        co2 = (mfxExtCodingOption2*)coding_opts[q->co2_idx];
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    if (q->co3_idx > 0)
190cabdff1aSopenharmony_ci        co3 = (mfxExtCodingOption3*)coding_opts[q->co3_idx];
191cabdff1aSopenharmony_ci
192cabdff1aSopenharmony_ci    if (q->exthevctiles_idx > 0)
193cabdff1aSopenharmony_ci        exthevctiles = (mfxExtHEVCTiles *)coding_opts[q->exthevctiles_idx];
194cabdff1aSopenharmony_ci
195cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
196cabdff1aSopenharmony_ci           print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel);
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ",
199cabdff1aSopenharmony_ci           info->GopPicSize, info->GopRefDist);
200cabdff1aSopenharmony_ci    if (info->GopOptFlag & MFX_GOP_CLOSED)
201cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "closed ");
202cabdff1aSopenharmony_ci    if (info->GopOptFlag & MFX_GOP_STRICT)
203cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "strict ");
204cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "; IdrInterval: %"PRIu16"\n", info->IdrInterval);
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n",
207cabdff1aSopenharmony_ci           info->TargetUsage, print_ratecontrol(info->RateControlMethod));
208cabdff1aSopenharmony_ci
209cabdff1aSopenharmony_ci    if (info->RateControlMethod == MFX_RATECONTROL_CBR ||
210cabdff1aSopenharmony_ci        info->RateControlMethod == MFX_RATECONTROL_VBR
211cabdff1aSopenharmony_ci#if QSV_HAVE_VCM
212cabdff1aSopenharmony_ci        || info->RateControlMethod == MFX_RATECONTROL_VCM
213cabdff1aSopenharmony_ci#endif
214cabdff1aSopenharmony_ci        ) {
215cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
216cabdff1aSopenharmony_ci               "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n",
217cabdff1aSopenharmony_ci               info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier);
218cabdff1aSopenharmony_ci    } else if (info->RateControlMethod == MFX_RATECONTROL_CQP) {
219cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n",
220cabdff1aSopenharmony_ci               info->QPI, info->QPP, info->QPB);
221cabdff1aSopenharmony_ci    }
222cabdff1aSopenharmony_ci#if QSV_HAVE_AVBR
223cabdff1aSopenharmony_ci    else if (info->RateControlMethod == MFX_RATECONTROL_AVBR) {
224cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
225cabdff1aSopenharmony_ci               "TargetKbps: %"PRIu16"; Accuracy: %"PRIu16"; Convergence: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n",
226cabdff1aSopenharmony_ci               info->TargetKbps, info->Accuracy, info->Convergence, info->BRCParamMultiplier);
227cabdff1aSopenharmony_ci    }
228cabdff1aSopenharmony_ci#endif
229cabdff1aSopenharmony_ci    else if (info->RateControlMethod == MFX_RATECONTROL_LA
230cabdff1aSopenharmony_ci             || info->RateControlMethod == MFX_RATECONTROL_LA_HRD
231cabdff1aSopenharmony_ci             ) {
232cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
233cabdff1aSopenharmony_ci               "TargetKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n",
234cabdff1aSopenharmony_ci               info->TargetKbps, info->BRCParamMultiplier);
235cabdff1aSopenharmony_ci    } else if (info->RateControlMethod == MFX_RATECONTROL_ICQ ||
236cabdff1aSopenharmony_ci               info->RateControlMethod == MFX_RATECONTROL_LA_ICQ)
237cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality);
238cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "NumSlice: %"PRIu16"; NumRefFrame: %"PRIu16"\n",
239cabdff1aSopenharmony_ci           info->NumSlice, info->NumRefFrame);
240cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
241cabdff1aSopenharmony_ci           print_threestate(co->RateDistortionOpt));
242cabdff1aSopenharmony_ci
243cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "RecoveryPointSEI: %s\n", print_threestate(co->RecoveryPointSEI));
244cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower));
245cabdff1aSopenharmony_ci
246cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_H264) {
247cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "Entropy coding: %s; MaxDecFrameBuffering: %"PRIu16"\n",
248cabdff1aSopenharmony_ci               co->CAVLC == MFX_CODINGOPTION_ON ? "CAVLC" : "CABAC", co->MaxDecFrameBuffering);
249cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
250cabdff1aSopenharmony_ci               "NalHrdConformance: %s; SingleSeiNalUnit: %s; VuiVclHrdParameters: %s VuiNalHrdParameters: %s\n",
251cabdff1aSopenharmony_ci               print_threestate(co->NalHrdConformance), print_threestate(co->SingleSeiNalUnit),
252cabdff1aSopenharmony_ci               print_threestate(co->VuiVclHrdParameters), print_threestate(co->VuiNalHrdParameters));
253cabdff1aSopenharmony_ci    } else if ((avctx->codec_id == AV_CODEC_ID_HEVC) && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 28)) {
254cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
255cabdff1aSopenharmony_ci               "NalHrdConformance: %s; VuiNalHrdParameters: %s\n",
256cabdff1aSopenharmony_ci               print_threestate(co->NalHrdConformance), print_threestate(co->VuiNalHrdParameters));
257cabdff1aSopenharmony_ci    }
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n",
260cabdff1aSopenharmony_ci           info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN);
261cabdff1aSopenharmony_ci
262cabdff1aSopenharmony_ci    if (co2) {
263cabdff1aSopenharmony_ci        if ((info->RateControlMethod == MFX_RATECONTROL_VBR && q->extbrc && q->look_ahead_depth > 0) ||
264cabdff1aSopenharmony_ci            (info->RateControlMethod == MFX_RATECONTROL_LA) ||
265cabdff1aSopenharmony_ci            (info->RateControlMethod == MFX_RATECONTROL_LA_HRD) ||
266cabdff1aSopenharmony_ci            (info->RateControlMethod == MFX_RATECONTROL_LA_ICQ))
267cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_VERBOSE, "LookAheadDepth: %"PRIu16"\n", co2->LookAheadDepth);
268cabdff1aSopenharmony_ci
269cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
270cabdff1aSopenharmony_ci               co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta);
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize);
273cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "MaxSliceSize: %d; ", co2->MaxSliceSize);
274cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "\n");
275cabdff1aSopenharmony_ci
276cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
277cabdff1aSopenharmony_ci               "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n",
278cabdff1aSopenharmony_ci               print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC),
279cabdff1aSopenharmony_ci               print_threestate(co2->ExtBRC));
280cabdff1aSopenharmony_ci
281cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "Trellis: ");
282cabdff1aSopenharmony_ci        if (co2->Trellis & MFX_TRELLIS_OFF) {
283cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_VERBOSE, "off");
284cabdff1aSopenharmony_ci        } else if (!co2->Trellis) {
285cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_VERBOSE, "auto");
286cabdff1aSopenharmony_ci        } else {
287cabdff1aSopenharmony_ci            if (co2->Trellis & MFX_TRELLIS_I) av_log(avctx, AV_LOG_VERBOSE, "I");
288cabdff1aSopenharmony_ci            if (co2->Trellis & MFX_TRELLIS_P) av_log(avctx, AV_LOG_VERBOSE, "P");
289cabdff1aSopenharmony_ci            if (co2->Trellis & MFX_TRELLIS_B) av_log(avctx, AV_LOG_VERBOSE, "B");
290cabdff1aSopenharmony_ci        }
291cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "\n");
292cabdff1aSopenharmony_ci
293cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
294cabdff1aSopenharmony_ci               "RepeatPPS: %s; NumMbPerSlice: %"PRIu16"; LookAheadDS: ",
295cabdff1aSopenharmony_ci               print_threestate(co2->RepeatPPS), co2->NumMbPerSlice);
296cabdff1aSopenharmony_ci        switch (co2->LookAheadDS) {
297cabdff1aSopenharmony_ci        case MFX_LOOKAHEAD_DS_OFF: av_log(avctx, AV_LOG_VERBOSE, "off");     break;
298cabdff1aSopenharmony_ci        case MFX_LOOKAHEAD_DS_2x:  av_log(avctx, AV_LOG_VERBOSE, "2x");      break;
299cabdff1aSopenharmony_ci        case MFX_LOOKAHEAD_DS_4x:  av_log(avctx, AV_LOG_VERBOSE, "4x");      break;
300cabdff1aSopenharmony_ci        default:                   av_log(avctx, AV_LOG_VERBOSE, "unknown"); break;
301cabdff1aSopenharmony_ci        }
302cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "\n");
303cabdff1aSopenharmony_ci
304cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "AdaptiveI: %s; AdaptiveB: %s; BRefType: ",
305cabdff1aSopenharmony_ci               print_threestate(co2->AdaptiveI), print_threestate(co2->AdaptiveB));
306cabdff1aSopenharmony_ci        switch (co2->BRefType) {
307cabdff1aSopenharmony_ci        case MFX_B_REF_OFF:     av_log(avctx, AV_LOG_VERBOSE, "off");       break;
308cabdff1aSopenharmony_ci        case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid");   break;
309cabdff1aSopenharmony_ci        default:                av_log(avctx, AV_LOG_VERBOSE, "auto");      break;
310cabdff1aSopenharmony_ci        }
311cabdff1aSopenharmony_ci
312cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
313cabdff1aSopenharmony_ci               "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n",
314cabdff1aSopenharmony_ci               co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB);
315cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "DisableDeblockingIdc: %"PRIu32" \n", co2->DisableDeblockingIdc);
316cabdff1aSopenharmony_ci    }
317cabdff1aSopenharmony_ci
318cabdff1aSopenharmony_ci    if (co3) {
319cabdff1aSopenharmony_ci        if (info->RateControlMethod == MFX_RATECONTROL_QVBR)
320cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n", co3->QVBRQuality);
321cabdff1aSopenharmony_ci
322cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "PRefType: ");
323cabdff1aSopenharmony_ci        switch (co3->PRefType) {
324cabdff1aSopenharmony_ci        case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default");   break;
325cabdff1aSopenharmony_ci        case MFX_P_REF_SIMPLE:  av_log(avctx, AV_LOG_VERBOSE, "simple");    break;
326cabdff1aSopenharmony_ci        case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid");   break;
327cabdff1aSopenharmony_ci        default:                av_log(avctx, AV_LOG_VERBOSE, "unknown");   break;
328cabdff1aSopenharmony_ci        }
329cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "\n");
330cabdff1aSopenharmony_ci
331cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_HEVC)
332cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_VERBOSE,"GPB: %s\n", print_threestate(co3->GPB));
333cabdff1aSopenharmony_ci
334cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "TransformSkip: %s \n", print_threestate(co3->TransformSkip));
335cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "IntRefCycleDist: %"PRId16"\n", co3->IntRefCycleDist);
336cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "LowDelayBRC: %s\n", print_threestate(co3->LowDelayBRC));
337cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSizeI: %d; ", co3->MaxFrameSizeI);
338cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSizeP: %d\n", co3->MaxFrameSizeP);
339cabdff1aSopenharmony_ci    }
340cabdff1aSopenharmony_ci
341cabdff1aSopenharmony_ci    if (exthevctiles) {
342cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n",
343cabdff1aSopenharmony_ci               exthevctiles->NumTileColumns, exthevctiles->NumTileRows);
344cabdff1aSopenharmony_ci    }
345cabdff1aSopenharmony_ci}
346cabdff1aSopenharmony_ci
347cabdff1aSopenharmony_cistatic void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q,
348cabdff1aSopenharmony_ci                                 mfxExtBuffer **coding_opts)
349cabdff1aSopenharmony_ci{
350cabdff1aSopenharmony_ci    mfxInfoMFX *info = &q->param.mfx;
351cabdff1aSopenharmony_ci    mfxExtVP9Param *vp9_param = NULL;
352cabdff1aSopenharmony_ci    mfxExtCodingOption2 *co2 = NULL;
353cabdff1aSopenharmony_ci
354cabdff1aSopenharmony_ci    if (q->vp9_idx >= 0)
355cabdff1aSopenharmony_ci        vp9_param = (mfxExtVP9Param *)coding_opts[q->vp9_idx];
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    if (q->co2_idx >= 0)
358cabdff1aSopenharmony_ci        co2 = (mfxExtCodingOption2*)coding_opts[q->co2_idx];
359cabdff1aSopenharmony_ci
360cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "profile: %s \n",
361cabdff1aSopenharmony_ci           print_profile(avctx->codec_id, info->CodecProfile));
362cabdff1aSopenharmony_ci
363cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ",
364cabdff1aSopenharmony_ci           info->GopPicSize, info->GopRefDist);
365cabdff1aSopenharmony_ci    if (info->GopOptFlag & MFX_GOP_CLOSED)
366cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "closed ");
367cabdff1aSopenharmony_ci    if (info->GopOptFlag & MFX_GOP_STRICT)
368cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "strict ");
369cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "; IdrInterval: %"PRIu16"\n", info->IdrInterval);
370cabdff1aSopenharmony_ci
371cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n",
372cabdff1aSopenharmony_ci           info->TargetUsage, print_ratecontrol(info->RateControlMethod));
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ci    if (info->RateControlMethod == MFX_RATECONTROL_CBR ||
375cabdff1aSopenharmony_ci        info->RateControlMethod == MFX_RATECONTROL_VBR) {
376cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
377cabdff1aSopenharmony_ci               "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n",
378cabdff1aSopenharmony_ci               info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier);
379cabdff1aSopenharmony_ci    } else if (info->RateControlMethod == MFX_RATECONTROL_CQP) {
380cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n",
381cabdff1aSopenharmony_ci               info->QPI, info->QPP, info->QPB);
382cabdff1aSopenharmony_ci    }
383cabdff1aSopenharmony_ci    else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) {
384cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality);
385cabdff1aSopenharmony_ci    }
386cabdff1aSopenharmony_ci    else {
387cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "Unsupported ratecontrol method: %d \n", info->RateControlMethod);
388cabdff1aSopenharmony_ci    }
389cabdff1aSopenharmony_ci
390cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "NumRefFrame: %"PRIu16"\n", info->NumRefFrame);
391cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n",
392cabdff1aSopenharmony_ci           info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN);
393cabdff1aSopenharmony_ci
394cabdff1aSopenharmony_ci    if (co2) {
395cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
396cabdff1aSopenharmony_ci               "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n",
397cabdff1aSopenharmony_ci               co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta);
398cabdff1aSopenharmony_ci
399cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize);
400cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "\n");
401cabdff1aSopenharmony_ci
402cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
403cabdff1aSopenharmony_ci               "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n",
404cabdff1aSopenharmony_ci               print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC),
405cabdff1aSopenharmony_ci               print_threestate(co2->ExtBRC));
406cabdff1aSopenharmony_ci
407cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower));
408cabdff1aSopenharmony_ci
409cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE,
410cabdff1aSopenharmony_ci               "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n",
411cabdff1aSopenharmony_ci               co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB);
412cabdff1aSopenharmony_ci    }
413cabdff1aSopenharmony_ci
414cabdff1aSopenharmony_ci    if (vp9_param) {
415cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_VERBOSE, "WriteIVFHeaders: %s \n",
416cabdff1aSopenharmony_ci               print_threestate(vp9_param->WriteIVFHeaders));
417cabdff1aSopenharmony_ci    }
418cabdff1aSopenharmony_ci}
419cabdff1aSopenharmony_ci
420cabdff1aSopenharmony_cistatic void dump_video_mjpeg_param(AVCodecContext *avctx, QSVEncContext *q)
421cabdff1aSopenharmony_ci{
422cabdff1aSopenharmony_ci    mfxInfoMFX *info = &q->param.mfx;
423cabdff1aSopenharmony_ci
424cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "Interleaved: %"PRIu16" \n", info->Interleaved);
425cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "Quality: %"PRIu16" \n", info->Quality);
426cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "RestartInterval: %"PRIu16" \n", info->RestartInterval);
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n",
429cabdff1aSopenharmony_ci           info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN);
430cabdff1aSopenharmony_ci}
431cabdff1aSopenharmony_ci
432cabdff1aSopenharmony_cistatic int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q)
433cabdff1aSopenharmony_ci{
434cabdff1aSopenharmony_ci    const char *rc_desc;
435cabdff1aSopenharmony_ci    mfxU16      rc_mode;
436cabdff1aSopenharmony_ci
437cabdff1aSopenharmony_ci    int want_la     = q->look_ahead;
438cabdff1aSopenharmony_ci    int want_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE);
439cabdff1aSopenharmony_ci    int want_vcm    = q->vcm;
440cabdff1aSopenharmony_ci
441cabdff1aSopenharmony_ci    if (want_vcm && !QSV_HAVE_VCM) {
442cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR,
443cabdff1aSopenharmony_ci               "VCM ratecontrol mode requested, but is not supported by this SDK version\n");
444cabdff1aSopenharmony_ci        return AVERROR(ENOSYS);
445cabdff1aSopenharmony_ci    }
446cabdff1aSopenharmony_ci
447cabdff1aSopenharmony_ci    if (want_la + want_qscale + want_vcm > 1) {
448cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR,
449cabdff1aSopenharmony_ci               "More than one of: { constant qscale, lookahead, VCM } requested, "
450cabdff1aSopenharmony_ci               "only one of them can be used at a time.\n");
451cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
452cabdff1aSopenharmony_ci    }
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_ci    if (want_qscale) {
455cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_CQP;
456cabdff1aSopenharmony_ci        rc_desc = "constant quantization parameter (CQP)";
457cabdff1aSopenharmony_ci    }
458cabdff1aSopenharmony_ci#if QSV_HAVE_VCM
459cabdff1aSopenharmony_ci    else if (want_vcm) {
460cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_VCM;
461cabdff1aSopenharmony_ci        rc_desc = "video conferencing mode (VCM)";
462cabdff1aSopenharmony_ci    }
463cabdff1aSopenharmony_ci#endif
464cabdff1aSopenharmony_ci    else if (want_la) {
465cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_LA;
466cabdff1aSopenharmony_ci        rc_desc = "VBR with lookahead (LA)";
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci        if (avctx->global_quality > 0) {
469cabdff1aSopenharmony_ci            rc_mode = MFX_RATECONTROL_LA_ICQ;
470cabdff1aSopenharmony_ci            rc_desc = "intelligent constant quality with lookahead (LA_ICQ)";
471cabdff1aSopenharmony_ci        }
472cabdff1aSopenharmony_ci    }
473cabdff1aSopenharmony_ci    else if (avctx->global_quality > 0 && !avctx->rc_max_rate) {
474cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_ICQ;
475cabdff1aSopenharmony_ci        rc_desc = "intelligent constant quality (ICQ)";
476cabdff1aSopenharmony_ci    }
477cabdff1aSopenharmony_ci    else if (avctx->rc_max_rate == avctx->bit_rate) {
478cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_CBR;
479cabdff1aSopenharmony_ci        rc_desc = "constant bitrate (CBR)";
480cabdff1aSopenharmony_ci    }
481cabdff1aSopenharmony_ci#if QSV_HAVE_AVBR
482cabdff1aSopenharmony_ci    else if (!avctx->rc_max_rate) {
483cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_AVBR;
484cabdff1aSopenharmony_ci        rc_desc = "average variable bitrate (AVBR)";
485cabdff1aSopenharmony_ci    }
486cabdff1aSopenharmony_ci#endif
487cabdff1aSopenharmony_ci    else if (avctx->global_quality > 0) {
488cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_QVBR;
489cabdff1aSopenharmony_ci        rc_desc = "constant quality with VBR algorithm (QVBR)";
490cabdff1aSopenharmony_ci    }
491cabdff1aSopenharmony_ci    else {
492cabdff1aSopenharmony_ci        rc_mode = MFX_RATECONTROL_VBR;
493cabdff1aSopenharmony_ci        rc_desc = "variable bitrate (VBR)";
494cabdff1aSopenharmony_ci    }
495cabdff1aSopenharmony_ci
496cabdff1aSopenharmony_ci    q->param.mfx.RateControlMethod = rc_mode;
497cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_VERBOSE, "Using the %s ratecontrol method\n", rc_desc);
498cabdff1aSopenharmony_ci
499cabdff1aSopenharmony_ci    return 0;
500cabdff1aSopenharmony_ci}
501cabdff1aSopenharmony_ci
502cabdff1aSopenharmony_cistatic int check_enc_param(AVCodecContext *avctx, QSVEncContext *q)
503cabdff1aSopenharmony_ci{
504cabdff1aSopenharmony_ci    mfxVideoParam param_out = { .mfx.CodecId = q->param.mfx.CodecId };
505cabdff1aSopenharmony_ci    mfxStatus ret;
506cabdff1aSopenharmony_ci
507cabdff1aSopenharmony_ci#define UNMATCH(x) (param_out.mfx.x != q->param.mfx.x)
508cabdff1aSopenharmony_ci
509cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_Query(q->session, &q->param, &param_out);
510cabdff1aSopenharmony_ci
511cabdff1aSopenharmony_ci    if (ret < 0) {
512cabdff1aSopenharmony_ci        if (UNMATCH(CodecId))
513cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Current codec type is unsupported\n");
514cabdff1aSopenharmony_ci        if (UNMATCH(CodecProfile))
515cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Current profile is unsupported\n");
516cabdff1aSopenharmony_ci        if (UNMATCH(RateControlMethod))
517cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Selected ratecontrol mode is unsupported\n");
518cabdff1aSopenharmony_ci        if (UNMATCH(LowPower))
519cabdff1aSopenharmony_ci              av_log(avctx, AV_LOG_ERROR, "Low power mode is unsupported\n");
520cabdff1aSopenharmony_ci        if (UNMATCH(FrameInfo.FrameRateExtN) || UNMATCH(FrameInfo.FrameRateExtD))
521cabdff1aSopenharmony_ci              av_log(avctx, AV_LOG_ERROR, "Current frame rate is unsupported\n");
522cabdff1aSopenharmony_ci        if (UNMATCH(FrameInfo.PicStruct))
523cabdff1aSopenharmony_ci              av_log(avctx, AV_LOG_ERROR, "Current picture structure is unsupported\n");
524cabdff1aSopenharmony_ci        if (UNMATCH(FrameInfo.Width) || UNMATCH(FrameInfo.Height))
525cabdff1aSopenharmony_ci              av_log(avctx, AV_LOG_ERROR, "Current resolution is unsupported\n");
526cabdff1aSopenharmony_ci        if (UNMATCH(FrameInfo.FourCC))
527cabdff1aSopenharmony_ci              av_log(avctx, AV_LOG_ERROR, "Current pixel format is unsupported\n");
528cabdff1aSopenharmony_ci        return 0;
529cabdff1aSopenharmony_ci    }
530cabdff1aSopenharmony_ci    return 1;
531cabdff1aSopenharmony_ci}
532cabdff1aSopenharmony_ci
533cabdff1aSopenharmony_cistatic int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q)
534cabdff1aSopenharmony_ci{
535cabdff1aSopenharmony_ci    enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ?
536cabdff1aSopenharmony_ci                                   avctx->sw_pix_fmt : avctx->pix_fmt;
537cabdff1aSopenharmony_ci    const AVPixFmtDescriptor *desc;
538cabdff1aSopenharmony_ci    int ret;
539cabdff1aSopenharmony_ci
540cabdff1aSopenharmony_ci    ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
541cabdff1aSopenharmony_ci    if (ret < 0)
542cabdff1aSopenharmony_ci        return AVERROR_BUG;
543cabdff1aSopenharmony_ci    q->param.mfx.CodecId = ret;
544cabdff1aSopenharmony_ci
545cabdff1aSopenharmony_ci    if (avctx->level > 0)
546cabdff1aSopenharmony_ci        q->param.mfx.CodecLevel = avctx->level;
547cabdff1aSopenharmony_ci    q->param.mfx.CodecProfile       = q->profile;
548cabdff1aSopenharmony_ci
549cabdff1aSopenharmony_ci    desc = av_pix_fmt_desc_get(sw_format);
550cabdff1aSopenharmony_ci    if (!desc)
551cabdff1aSopenharmony_ci        return AVERROR_BUG;
552cabdff1aSopenharmony_ci
553cabdff1aSopenharmony_ci    ret = ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC);
554cabdff1aSopenharmony_ci    if (ret < 0)
555cabdff1aSopenharmony_ci        return AVERROR_BUG;
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropX          = 0;
558cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropY          = 0;
559cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropW          = avctx->width;
560cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropH          = avctx->height;
561cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.AspectRatioW   = avctx->sample_aspect_ratio.num;
562cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.AspectRatioH   = avctx->sample_aspect_ratio.den;
563cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.ChromaFormat   = MFX_CHROMAFORMAT_YUV420 +
564cabdff1aSopenharmony_ci                                            !desc->log2_chroma_w + !desc->log2_chroma_h;
565cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.BitDepthLuma   = desc->comp[0].depth;
566cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth;
567cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Shift          = desc->comp[0].depth > 8;
568cabdff1aSopenharmony_ci
569cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Width  = FFALIGN(avctx->width, 16);
570cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 16);
571cabdff1aSopenharmony_ci
572cabdff1aSopenharmony_ci    if (avctx->hw_frames_ctx) {
573cabdff1aSopenharmony_ci        AVHWFramesContext *frames_ctx    = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
574cabdff1aSopenharmony_ci        AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
575cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.Width  = frames_hwctx->surfaces[0].Info.Width;
576cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height;
577cabdff1aSopenharmony_ci    }
578cabdff1aSopenharmony_ci
579cabdff1aSopenharmony_ci    if (avctx->framerate.den > 0 && avctx->framerate.num > 0) {
580cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num;
581cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den;
582cabdff1aSopenharmony_ci    } else {
583cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtN  = avctx->time_base.den;
584cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtD  = avctx->time_base.num;
585cabdff1aSopenharmony_ci    }
586cabdff1aSopenharmony_ci
587cabdff1aSopenharmony_ci    q->param.mfx.Interleaved          = 1;
588cabdff1aSopenharmony_ci    q->param.mfx.Quality              = av_clip(avctx->global_quality, 1, 100);
589cabdff1aSopenharmony_ci    q->param.mfx.RestartInterval      = 0;
590cabdff1aSopenharmony_ci
591cabdff1aSopenharmony_ci    q->width_align = 16;
592cabdff1aSopenharmony_ci    q->height_align = 16;
593cabdff1aSopenharmony_ci
594cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align);
595cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align);
596cabdff1aSopenharmony_ci
597cabdff1aSopenharmony_ci    return 0;
598cabdff1aSopenharmony_ci}
599cabdff1aSopenharmony_ci
600cabdff1aSopenharmony_cistatic int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
601cabdff1aSopenharmony_ci{
602cabdff1aSopenharmony_ci    enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ?
603cabdff1aSopenharmony_ci                                   avctx->sw_pix_fmt : avctx->pix_fmt;
604cabdff1aSopenharmony_ci    const AVPixFmtDescriptor *desc;
605cabdff1aSopenharmony_ci    float quant;
606cabdff1aSopenharmony_ci    int target_bitrate_kbps, max_bitrate_kbps, brc_param_multiplier;
607cabdff1aSopenharmony_ci    int buffer_size_in_kilobytes, initial_delay_in_kilobytes;
608cabdff1aSopenharmony_ci    int ret;
609cabdff1aSopenharmony_ci
610cabdff1aSopenharmony_ci    ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
611cabdff1aSopenharmony_ci    if (ret < 0)
612cabdff1aSopenharmony_ci        return AVERROR_BUG;
613cabdff1aSopenharmony_ci    q->param.mfx.CodecId = ret;
614cabdff1aSopenharmony_ci
615cabdff1aSopenharmony_ci    if (avctx->level > 0)
616cabdff1aSopenharmony_ci        q->param.mfx.CodecLevel = avctx->level;
617cabdff1aSopenharmony_ci
618cabdff1aSopenharmony_ci    if (avctx->compression_level == FF_COMPRESSION_DEFAULT) {
619cabdff1aSopenharmony_ci        avctx->compression_level = q->preset;
620cabdff1aSopenharmony_ci    } else if (avctx->compression_level >= 0) {
621cabdff1aSopenharmony_ci        if (avctx->compression_level > MFX_TARGETUSAGE_BEST_SPEED) {
622cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Invalid compression level: "
623cabdff1aSopenharmony_ci                    "valid range is 0-%d, using %d instead\n",
624cabdff1aSopenharmony_ci                    MFX_TARGETUSAGE_BEST_SPEED, MFX_TARGETUSAGE_BEST_SPEED);
625cabdff1aSopenharmony_ci            avctx->compression_level = MFX_TARGETUSAGE_BEST_SPEED;
626cabdff1aSopenharmony_ci        }
627cabdff1aSopenharmony_ci    }
628cabdff1aSopenharmony_ci
629cabdff1aSopenharmony_ci    if (q->low_power == 1) {
630cabdff1aSopenharmony_ci        q->param.mfx.LowPower = MFX_CODINGOPTION_ON;
631cabdff1aSopenharmony_ci    } else if (q->low_power == -1)
632cabdff1aSopenharmony_ci        q->param.mfx.LowPower = MFX_CODINGOPTION_UNKNOWN;
633cabdff1aSopenharmony_ci    else
634cabdff1aSopenharmony_ci        q->param.mfx.LowPower = MFX_CODINGOPTION_OFF;
635cabdff1aSopenharmony_ci
636cabdff1aSopenharmony_ci    q->param.mfx.CodecProfile       = q->profile;
637cabdff1aSopenharmony_ci    q->param.mfx.TargetUsage        = avctx->compression_level;
638cabdff1aSopenharmony_ci    q->param.mfx.GopPicSize         = FFMAX(0, avctx->gop_size);
639cabdff1aSopenharmony_ci    q->param.mfx.GopRefDist         = FFMAX(-1, avctx->max_b_frames) + 1;
640cabdff1aSopenharmony_ci    q->param.mfx.GopOptFlag         = avctx->flags & AV_CODEC_FLAG_CLOSED_GOP ?
641cabdff1aSopenharmony_ci                                      MFX_GOP_CLOSED : MFX_GOP_STRICT;
642cabdff1aSopenharmony_ci    q->param.mfx.IdrInterval        = q->idr_interval;
643cabdff1aSopenharmony_ci    q->param.mfx.NumSlice           = avctx->slices;
644cabdff1aSopenharmony_ci    q->param.mfx.NumRefFrame        = FFMAX(0, avctx->refs);
645cabdff1aSopenharmony_ci    q->param.mfx.EncodedOrder       = 0;
646cabdff1aSopenharmony_ci    q->param.mfx.BufferSizeInKB     = 0;
647cabdff1aSopenharmony_ci
648cabdff1aSopenharmony_ci    desc = av_pix_fmt_desc_get(sw_format);
649cabdff1aSopenharmony_ci    if (!desc)
650cabdff1aSopenharmony_ci        return AVERROR_BUG;
651cabdff1aSopenharmony_ci
652cabdff1aSopenharmony_ci    ret = ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC);
653cabdff1aSopenharmony_ci    if (ret < 0)
654cabdff1aSopenharmony_ci        return AVERROR_BUG;
655cabdff1aSopenharmony_ci
656cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropX          = 0;
657cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropY          = 0;
658cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropW          = avctx->width;
659cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.CropH          = avctx->height;
660cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.AspectRatioW   = avctx->sample_aspect_ratio.num;
661cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.AspectRatioH   = avctx->sample_aspect_ratio.den;
662cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.ChromaFormat   = MFX_CHROMAFORMAT_YUV420 +
663cabdff1aSopenharmony_ci                                            !desc->log2_chroma_w + !desc->log2_chroma_h;
664cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.BitDepthLuma   = desc->comp[0].depth;
665cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth;
666cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Shift          = desc->comp[0].depth > 8;
667cabdff1aSopenharmony_ci
668cabdff1aSopenharmony_ci    // If the minor version is greater than or equal to 19,
669cabdff1aSopenharmony_ci    // then can use the same alignment settings as H.264 for HEVC
670cabdff1aSopenharmony_ci    q->width_align = (avctx->codec_id != AV_CODEC_ID_HEVC ||
671cabdff1aSopenharmony_ci                      QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 19)) ? 16 : 32;
672cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align);
673cabdff1aSopenharmony_ci
674cabdff1aSopenharmony_ci    if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
675cabdff1aSopenharmony_ci        // it is important that PicStruct be setup correctly from the
676cabdff1aSopenharmony_ci        // start--otherwise, encoding doesn't work and results in a bunch
677cabdff1aSopenharmony_ci        // of incompatible video parameter errors
678cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
679cabdff1aSopenharmony_ci        // height alignment always must be 32 for interlaced video
680cabdff1aSopenharmony_ci        q->height_align = 32;
681cabdff1aSopenharmony_ci    } else {
682cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
683cabdff1aSopenharmony_ci        // for progressive video, the height should be aligned to 16 for
684cabdff1aSopenharmony_ci        // H.264.  For HEVC, depending on the version of MFX, it should be
685cabdff1aSopenharmony_ci        // either 32 or 16.  The lower number is better if possible.
686cabdff1aSopenharmony_ci        q->height_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16;
687cabdff1aSopenharmony_ci    }
688cabdff1aSopenharmony_ci    q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align);
689cabdff1aSopenharmony_ci
690cabdff1aSopenharmony_ci    if (avctx->hw_frames_ctx) {
691cabdff1aSopenharmony_ci        AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
692cabdff1aSopenharmony_ci        AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
693cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.Width  = frames_hwctx->surfaces[0].Info.Width;
694cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height;
695cabdff1aSopenharmony_ci    }
696cabdff1aSopenharmony_ci
697cabdff1aSopenharmony_ci    if (avctx->framerate.den > 0 && avctx->framerate.num > 0) {
698cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num;
699cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den;
700cabdff1aSopenharmony_ci    } else {
701cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtN  = avctx->time_base.den;
702cabdff1aSopenharmony_ci        q->param.mfx.FrameInfo.FrameRateExtD  = avctx->time_base.num;
703cabdff1aSopenharmony_ci    }
704cabdff1aSopenharmony_ci
705cabdff1aSopenharmony_ci    ret = select_rc_mode(avctx, q);
706cabdff1aSopenharmony_ci    if (ret < 0)
707cabdff1aSopenharmony_ci        return ret;
708cabdff1aSopenharmony_ci
709cabdff1aSopenharmony_ci    //libmfx BRC parameters are 16 bits thus maybe overflow, then BRCParamMultiplier is needed
710cabdff1aSopenharmony_ci    buffer_size_in_kilobytes   = avctx->rc_buffer_size / 8000;
711cabdff1aSopenharmony_ci    initial_delay_in_kilobytes = avctx->rc_initial_buffer_occupancy / 8000;
712cabdff1aSopenharmony_ci    target_bitrate_kbps        = avctx->bit_rate / 1000;
713cabdff1aSopenharmony_ci    max_bitrate_kbps           = avctx->rc_max_rate / 1000;
714cabdff1aSopenharmony_ci    brc_param_multiplier       = (FFMAX(FFMAX3(target_bitrate_kbps, max_bitrate_kbps, buffer_size_in_kilobytes),
715cabdff1aSopenharmony_ci                                  initial_delay_in_kilobytes) + 0x10000) / 0x10000;
716cabdff1aSopenharmony_ci
717cabdff1aSopenharmony_ci    switch (q->param.mfx.RateControlMethod) {
718cabdff1aSopenharmony_ci    case MFX_RATECONTROL_CBR:
719cabdff1aSopenharmony_ci    case MFX_RATECONTROL_VBR:
720cabdff1aSopenharmony_ci        if (q->extbrc) {
721cabdff1aSopenharmony_ci            q->extco2.LookAheadDepth = q->look_ahead_depth;
722cabdff1aSopenharmony_ci        }
723cabdff1aSopenharmony_ci#if QSV_HAVE_VCM
724cabdff1aSopenharmony_ci    case MFX_RATECONTROL_VCM:
725cabdff1aSopenharmony_ci#endif
726cabdff1aSopenharmony_ci    case MFX_RATECONTROL_QVBR:
727cabdff1aSopenharmony_ci        q->param.mfx.BufferSizeInKB   = buffer_size_in_kilobytes / brc_param_multiplier;
728cabdff1aSopenharmony_ci        q->param.mfx.InitialDelayInKB = initial_delay_in_kilobytes / brc_param_multiplier;
729cabdff1aSopenharmony_ci        q->param.mfx.TargetKbps       = target_bitrate_kbps / brc_param_multiplier;
730cabdff1aSopenharmony_ci        q->param.mfx.MaxKbps          = max_bitrate_kbps / brc_param_multiplier;
731cabdff1aSopenharmony_ci        q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
732cabdff1aSopenharmony_ci        if (q->param.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
733cabdff1aSopenharmony_ci            q->extco3.QVBRQuality = av_clip(avctx->global_quality, 0, 51);
734cabdff1aSopenharmony_ci        break;
735cabdff1aSopenharmony_ci    case MFX_RATECONTROL_CQP:
736cabdff1aSopenharmony_ci        quant = avctx->global_quality / FF_QP2LAMBDA;
737cabdff1aSopenharmony_ci
738cabdff1aSopenharmony_ci        q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
739cabdff1aSopenharmony_ci        q->param.mfx.QPP = av_clip(quant, 0, 51);
740cabdff1aSopenharmony_ci        q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);
741cabdff1aSopenharmony_ci
742cabdff1aSopenharmony_ci        break;
743cabdff1aSopenharmony_ci#if QSV_HAVE_AVBR
744cabdff1aSopenharmony_ci    case MFX_RATECONTROL_AVBR:
745cabdff1aSopenharmony_ci        q->param.mfx.TargetKbps  = target_bitrate_kbps / brc_param_multiplier;
746cabdff1aSopenharmony_ci        q->param.mfx.Convergence = q->avbr_convergence;
747cabdff1aSopenharmony_ci        q->param.mfx.Accuracy    = q->avbr_accuracy;
748cabdff1aSopenharmony_ci        q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
749cabdff1aSopenharmony_ci        break;
750cabdff1aSopenharmony_ci#endif
751cabdff1aSopenharmony_ci    case MFX_RATECONTROL_LA:
752cabdff1aSopenharmony_ci        q->param.mfx.TargetKbps  = target_bitrate_kbps / brc_param_multiplier;
753cabdff1aSopenharmony_ci        q->extco2.LookAheadDepth = q->look_ahead_depth;
754cabdff1aSopenharmony_ci        q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
755cabdff1aSopenharmony_ci        break;
756cabdff1aSopenharmony_ci    case MFX_RATECONTROL_LA_ICQ:
757cabdff1aSopenharmony_ci        q->extco2.LookAheadDepth = q->look_ahead_depth;
758cabdff1aSopenharmony_ci    case MFX_RATECONTROL_ICQ:
759cabdff1aSopenharmony_ci        q->param.mfx.ICQQuality  = av_clip(avctx->global_quality, 1, 51);
760cabdff1aSopenharmony_ci        break;
761cabdff1aSopenharmony_ci    }
762cabdff1aSopenharmony_ci
763cabdff1aSopenharmony_ci    // The HEVC encoder plugin currently fails with some old libmfx version if coding options
764cabdff1aSopenharmony_ci    // are provided. Can't find the extract libmfx version which fixed it, just enable it from
765cabdff1aSopenharmony_ci    // V1.28 in order to keep compatibility security.
766cabdff1aSopenharmony_ci    if (((avctx->codec_id != AV_CODEC_ID_HEVC) || QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 28))
767cabdff1aSopenharmony_ci        && (avctx->codec_id != AV_CODEC_ID_VP9)) {
768cabdff1aSopenharmony_ci        q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
769cabdff1aSopenharmony_ci        q->extco.Header.BufferSz      = sizeof(q->extco);
770cabdff1aSopenharmony_ci
771cabdff1aSopenharmony_ci        q->extco.PicTimingSEI         = q->pic_timing_sei ?
772cabdff1aSopenharmony_ci                                        MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
773cabdff1aSopenharmony_ci
774cabdff1aSopenharmony_ci        if (q->rdo >= 0)
775cabdff1aSopenharmony_ci            q->extco.RateDistortionOpt = q->rdo > 0 ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
776cabdff1aSopenharmony_ci
777cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_H264) {
778cabdff1aSopenharmony_ci            q->extco.CAVLC = q->cavlc ? MFX_CODINGOPTION_ON
779cabdff1aSopenharmony_ci                                      : MFX_CODINGOPTION_UNKNOWN;
780cabdff1aSopenharmony_ci
781cabdff1aSopenharmony_ci            if (avctx->strict_std_compliance != FF_COMPLIANCE_NORMAL)
782cabdff1aSopenharmony_ci                q->extco.NalHrdConformance = avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL ?
783cabdff1aSopenharmony_ci                                             MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
784cabdff1aSopenharmony_ci
785cabdff1aSopenharmony_ci            if (q->single_sei_nal_unit >= 0)
786cabdff1aSopenharmony_ci                q->extco.SingleSeiNalUnit = q->single_sei_nal_unit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
787cabdff1aSopenharmony_ci            if (q->recovery_point_sei >= 0)
788cabdff1aSopenharmony_ci                q->extco.RecoveryPointSEI = q->recovery_point_sei ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
789cabdff1aSopenharmony_ci            q->extco.MaxDecFrameBuffering = q->max_dec_frame_buffering;
790cabdff1aSopenharmony_ci            q->extco.AUDelimiter          = q->aud ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
791cabdff1aSopenharmony_ci        } else if (avctx->codec_id == AV_CODEC_ID_HEVC) {
792cabdff1aSopenharmony_ci            if (avctx->strict_std_compliance != FF_COMPLIANCE_NORMAL)
793cabdff1aSopenharmony_ci                q->extco.NalHrdConformance = avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL ?
794cabdff1aSopenharmony_ci                                             MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
795cabdff1aSopenharmony_ci
796cabdff1aSopenharmony_ci            if (q->recovery_point_sei >= 0)
797cabdff1aSopenharmony_ci                q->extco.RecoveryPointSEI = q->recovery_point_sei ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
798cabdff1aSopenharmony_ci
799cabdff1aSopenharmony_ci            q->extco.AUDelimiter          = q->aud ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
800cabdff1aSopenharmony_ci        }
801cabdff1aSopenharmony_ci
802cabdff1aSopenharmony_ci        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco;
803cabdff1aSopenharmony_ci
804cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_H264) {
805cabdff1aSopenharmony_ci            if (q->bitrate_limit >= 0)
806cabdff1aSopenharmony_ci                q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
807cabdff1aSopenharmony_ci
808cabdff1aSopenharmony_ci            if (avctx->trellis >= 0)
809cabdff1aSopenharmony_ci                q->extco2.Trellis = (avctx->trellis == 0) ? MFX_TRELLIS_OFF : (MFX_TRELLIS_I | MFX_TRELLIS_P | MFX_TRELLIS_B);
810cabdff1aSopenharmony_ci            else
811cabdff1aSopenharmony_ci                q->extco2.Trellis = MFX_TRELLIS_UNKNOWN;
812cabdff1aSopenharmony_ci
813cabdff1aSopenharmony_ci            q->extco2.LookAheadDS = q->look_ahead_downsampling;
814cabdff1aSopenharmony_ci            q->extco2.RepeatPPS   = q->repeat_pps ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
815cabdff1aSopenharmony_ci
816cabdff1aSopenharmony_ci            if (q->adaptive_i >= 0)
817cabdff1aSopenharmony_ci                q->extco2.AdaptiveI = q->adaptive_i ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
818cabdff1aSopenharmony_ci            if (q->adaptive_b >= 0)
819cabdff1aSopenharmony_ci                q->extco2.AdaptiveB = q->adaptive_b ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
820cabdff1aSopenharmony_ci        }
821cabdff1aSopenharmony_ci
822cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) {
823cabdff1aSopenharmony_ci            if (q->extbrc >= 0)
824cabdff1aSopenharmony_ci                q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
825cabdff1aSopenharmony_ci            if (q->max_frame_size >= 0)
826cabdff1aSopenharmony_ci                q->extco2.MaxFrameSize = q->max_frame_size;
827cabdff1aSopenharmony_ci            if (q->int_ref_type >= 0)
828cabdff1aSopenharmony_ci                q->extco2.IntRefType = q->int_ref_type;
829cabdff1aSopenharmony_ci            if (q->int_ref_cycle_size >= 0)
830cabdff1aSopenharmony_ci                q->extco2.IntRefCycleSize = q->int_ref_cycle_size;
831cabdff1aSopenharmony_ci            if (q->int_ref_qp_delta != INT16_MIN)
832cabdff1aSopenharmony_ci                q->extco2.IntRefQPDelta = q->int_ref_qp_delta;
833cabdff1aSopenharmony_ci            if (q->max_slice_size >= 0)
834cabdff1aSopenharmony_ci                q->extco2.MaxSliceSize = q->max_slice_size;
835cabdff1aSopenharmony_ci            q->extco2.DisableDeblockingIdc = q->dblk_idc;
836cabdff1aSopenharmony_ci
837cabdff1aSopenharmony_ci            if (q->b_strategy >= 0)
838cabdff1aSopenharmony_ci                q->extco2.BRefType = q->b_strategy ? MFX_B_REF_PYRAMID : MFX_B_REF_OFF;
839cabdff1aSopenharmony_ci            if ((avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) ||
840cabdff1aSopenharmony_ci                (q->max_qp_i >= 0 && q->min_qp_i >= 0 && q->min_qp_i > q->max_qp_i) ||
841cabdff1aSopenharmony_ci                (q->max_qp_p >= 0 && q->min_qp_p >= 0 && q->min_qp_p > q->max_qp_p) ||
842cabdff1aSopenharmony_ci                (q->max_qp_b >= 0 && q->min_qp_b >= 0 && q->min_qp_b > q->max_qp_b)) {
843cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR,
844cabdff1aSopenharmony_ci                       "qmin and or qmax are set but invalid,"
845cabdff1aSopenharmony_ci                       " please make sure min <= max\n");
846cabdff1aSopenharmony_ci                return AVERROR(EINVAL);
847cabdff1aSopenharmony_ci            }
848cabdff1aSopenharmony_ci            if (avctx->qmin >= 0) {
849cabdff1aSopenharmony_ci                q->extco2.MinQPI = avctx->qmin > 51 ? 51 : avctx->qmin;
850cabdff1aSopenharmony_ci                q->extco2.MinQPP = q->extco2.MinQPB = q->extco2.MinQPI;
851cabdff1aSopenharmony_ci            }
852cabdff1aSopenharmony_ci            if (avctx->qmax >= 0) {
853cabdff1aSopenharmony_ci                q->extco2.MaxQPI = avctx->qmax > 51 ? 51 : avctx->qmax;
854cabdff1aSopenharmony_ci                q->extco2.MaxQPP = q->extco2.MaxQPB = q->extco2.MaxQPI;
855cabdff1aSopenharmony_ci            }
856cabdff1aSopenharmony_ci            if (q->min_qp_i >= 0)
857cabdff1aSopenharmony_ci                q->extco2.MinQPI = q->min_qp_i > 51 ? 51 : q->min_qp_i;
858cabdff1aSopenharmony_ci            if (q->max_qp_i >= 0)
859cabdff1aSopenharmony_ci                q->extco2.MaxQPI = q->max_qp_i > 51 ? 51 : q->max_qp_i;
860cabdff1aSopenharmony_ci            if (q->min_qp_p >= 0)
861cabdff1aSopenharmony_ci                q->extco2.MinQPP = q->min_qp_p > 51 ? 51 : q->min_qp_p;
862cabdff1aSopenharmony_ci            if (q->max_qp_p >= 0)
863cabdff1aSopenharmony_ci                q->extco2.MaxQPP = q->max_qp_p > 51 ? 51 : q->max_qp_p;
864cabdff1aSopenharmony_ci            if (q->min_qp_b >= 0)
865cabdff1aSopenharmony_ci                q->extco2.MinQPB = q->min_qp_b > 51 ? 51 : q->min_qp_b;
866cabdff1aSopenharmony_ci            if (q->max_qp_b >= 0)
867cabdff1aSopenharmony_ci                q->extco2.MaxQPB = q->max_qp_b > 51 ? 51 : q->max_qp_b;
868cabdff1aSopenharmony_ci            if (q->mbbrc >= 0)
869cabdff1aSopenharmony_ci                q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
870cabdff1aSopenharmony_ci
871cabdff1aSopenharmony_ci            q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
872cabdff1aSopenharmony_ci            q->extco2.Header.BufferSz = sizeof(q->extco2);
873cabdff1aSopenharmony_ci
874cabdff1aSopenharmony_ci            q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2;
875cabdff1aSopenharmony_ci        }
876cabdff1aSopenharmony_ci
877cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_H264) {
878cabdff1aSopenharmony_ci#if QSV_HAVE_MF
879cabdff1aSopenharmony_ci            if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 25)) {
880cabdff1aSopenharmony_ci                q->extmfp.Header.BufferId     = MFX_EXTBUFF_MULTI_FRAME_PARAM;
881cabdff1aSopenharmony_ci                q->extmfp.Header.BufferSz     = sizeof(q->extmfp);
882cabdff1aSopenharmony_ci
883cabdff1aSopenharmony_ci                q->extmfp.MFMode = q->mfmode;
884cabdff1aSopenharmony_ci                av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n", q->extmfp.MFMode);
885cabdff1aSopenharmony_ci                q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extmfp;
886cabdff1aSopenharmony_ci            }
887cabdff1aSopenharmony_ci#endif
888cabdff1aSopenharmony_ci        }
889cabdff1aSopenharmony_ci        q->extco3.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION3;
890cabdff1aSopenharmony_ci        q->extco3.Header.BufferSz      = sizeof(q->extco3);
891cabdff1aSopenharmony_ci
892cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_HEVC ||
893cabdff1aSopenharmony_ci            avctx->codec_id == AV_CODEC_ID_H264) {
894cabdff1aSopenharmony_ci            switch (q->p_strategy) {
895cabdff1aSopenharmony_ci            case 0:
896cabdff1aSopenharmony_ci                q->extco3.PRefType = MFX_P_REF_DEFAULT;
897cabdff1aSopenharmony_ci                break;
898cabdff1aSopenharmony_ci            case 1:
899cabdff1aSopenharmony_ci                q->extco3.PRefType = MFX_P_REF_SIMPLE;
900cabdff1aSopenharmony_ci                break;
901cabdff1aSopenharmony_ci            case 2:
902cabdff1aSopenharmony_ci                q->extco3.PRefType = MFX_P_REF_PYRAMID;
903cabdff1aSopenharmony_ci                break;
904cabdff1aSopenharmony_ci            default:
905cabdff1aSopenharmony_ci                q->extco3.PRefType = MFX_P_REF_DEFAULT;
906cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_WARNING,
907cabdff1aSopenharmony_ci                       "invalid p_strategy, set to default\n");
908cabdff1aSopenharmony_ci                break;
909cabdff1aSopenharmony_ci            }
910cabdff1aSopenharmony_ci            if (q->extco3.PRefType == MFX_P_REF_PYRAMID &&
911cabdff1aSopenharmony_ci                avctx->max_b_frames != 0) {
912cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_WARNING,
913cabdff1aSopenharmony_ci                       "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n");
914cabdff1aSopenharmony_ci            }
915cabdff1aSopenharmony_ci            if (q->int_ref_cycle_dist >= 0)
916cabdff1aSopenharmony_ci                q->extco3.IntRefCycleDist = q->int_ref_cycle_dist;
917cabdff1aSopenharmony_ci            if (q->low_delay_brc >= 0)
918cabdff1aSopenharmony_ci                q->extco3.LowDelayBRC = q->low_delay_brc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
919cabdff1aSopenharmony_ci            if (q->max_frame_size_i >= 0)
920cabdff1aSopenharmony_ci                q->extco3.MaxFrameSizeI = q->max_frame_size_i;
921cabdff1aSopenharmony_ci            if (q->max_frame_size_p >= 0)
922cabdff1aSopenharmony_ci                q->extco3.MaxFrameSizeP = q->max_frame_size_p;
923cabdff1aSopenharmony_ci        }
924cabdff1aSopenharmony_ci
925cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_HEVC) {
926cabdff1aSopenharmony_ci            if (q->transform_skip >= 0)
927cabdff1aSopenharmony_ci                q->extco3.TransformSkip = q->transform_skip ? MFX_CODINGOPTION_ON :
928cabdff1aSopenharmony_ci                                                              MFX_CODINGOPTION_OFF;
929cabdff1aSopenharmony_ci            else
930cabdff1aSopenharmony_ci                q->extco3.TransformSkip = MFX_CODINGOPTION_UNKNOWN;
931cabdff1aSopenharmony_ci            q->extco3.GPB              = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
932cabdff1aSopenharmony_ci        }
933cabdff1aSopenharmony_ci        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco3;
934cabdff1aSopenharmony_ci    }
935cabdff1aSopenharmony_ci
936cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_VP9) {
937cabdff1aSopenharmony_ci        q->extvp9param.Header.BufferId = MFX_EXTBUFF_VP9_PARAM;
938cabdff1aSopenharmony_ci        q->extvp9param.Header.BufferSz = sizeof(q->extvp9param);
939cabdff1aSopenharmony_ci        q->extvp9param.WriteIVFHeaders = MFX_CODINGOPTION_OFF;
940cabdff1aSopenharmony_ci#if QSV_HAVE_EXT_VP9_TILES
941cabdff1aSopenharmony_ci        q->extvp9param.NumTileColumns  = q->tile_cols;
942cabdff1aSopenharmony_ci        q->extvp9param.NumTileRows     = q->tile_rows;
943cabdff1aSopenharmony_ci#endif
944cabdff1aSopenharmony_ci        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extvp9param;
945cabdff1aSopenharmony_ci    }
946cabdff1aSopenharmony_ci
947cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_HEVC) {
948cabdff1aSopenharmony_ci        q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES;
949cabdff1aSopenharmony_ci        q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles);
950cabdff1aSopenharmony_ci        q->exthevctiles.NumTileColumns  = q->tile_cols;
951cabdff1aSopenharmony_ci        q->exthevctiles.NumTileRows     = q->tile_rows;
952cabdff1aSopenharmony_ci        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles;
953cabdff1aSopenharmony_ci    }
954cabdff1aSopenharmony_ci
955cabdff1aSopenharmony_ci    q->extvsi.VideoFullRange = (avctx->color_range == AVCOL_RANGE_JPEG);
956cabdff1aSopenharmony_ci    q->extvsi.ColourDescriptionPresent = 0;
957cabdff1aSopenharmony_ci
958cabdff1aSopenharmony_ci    if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
959cabdff1aSopenharmony_ci        avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
960cabdff1aSopenharmony_ci        avctx->colorspace != AVCOL_SPC_UNSPECIFIED) {
961cabdff1aSopenharmony_ci        q->extvsi.ColourDescriptionPresent = 1;
962cabdff1aSopenharmony_ci        q->extvsi.ColourPrimaries = avctx->color_primaries;
963cabdff1aSopenharmony_ci        q->extvsi.TransferCharacteristics = avctx->color_trc;
964cabdff1aSopenharmony_ci        q->extvsi.MatrixCoefficients = avctx->colorspace;
965cabdff1aSopenharmony_ci    }
966cabdff1aSopenharmony_ci
967cabdff1aSopenharmony_ci    if (q->extvsi.VideoFullRange || q->extvsi.ColourDescriptionPresent) {
968cabdff1aSopenharmony_ci        q->extvsi.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO;
969cabdff1aSopenharmony_ci        q->extvsi.Header.BufferSz = sizeof(q->extvsi);
970cabdff1aSopenharmony_ci        q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extvsi;
971cabdff1aSopenharmony_ci    }
972cabdff1aSopenharmony_ci
973cabdff1aSopenharmony_ci    if (!check_enc_param(avctx,q)) {
974cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR,
975cabdff1aSopenharmony_ci               "some encoding parameters are not supported by the QSV "
976cabdff1aSopenharmony_ci               "runtime. Please double check the input parameters.\n");
977cabdff1aSopenharmony_ci        return AVERROR(ENOSYS);
978cabdff1aSopenharmony_ci    }
979cabdff1aSopenharmony_ci
980cabdff1aSopenharmony_ci    return 0;
981cabdff1aSopenharmony_ci}
982cabdff1aSopenharmony_ci
983cabdff1aSopenharmony_cistatic int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q)
984cabdff1aSopenharmony_ci{
985cabdff1aSopenharmony_ci    int ret = 0;
986cabdff1aSopenharmony_ci
987cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
988cabdff1aSopenharmony_ci    if (ret < 0)
989cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
990cabdff1aSopenharmony_ci                                  "Error calling GetVideoParam");
991cabdff1aSopenharmony_ci
992cabdff1aSopenharmony_ci    q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000;
993cabdff1aSopenharmony_ci
994cabdff1aSopenharmony_ci    // for qsv mjpeg the return value maybe 0 so alloc the buffer
995cabdff1aSopenharmony_ci    if (q->packet_size == 0)
996cabdff1aSopenharmony_ci        q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4;
997cabdff1aSopenharmony_ci
998cabdff1aSopenharmony_ci    dump_video_mjpeg_param(avctx, q);
999cabdff1aSopenharmony_ci
1000cabdff1aSopenharmony_ci    return 0;
1001cabdff1aSopenharmony_ci}
1002cabdff1aSopenharmony_ci
1003cabdff1aSopenharmony_cistatic int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q)
1004cabdff1aSopenharmony_ci{
1005cabdff1aSopenharmony_ci    int ret = 0;
1006cabdff1aSopenharmony_ci    mfxExtVP9Param vp9_extend_buf = {
1007cabdff1aSopenharmony_ci         .Header.BufferId = MFX_EXTBUFF_VP9_PARAM,
1008cabdff1aSopenharmony_ci         .Header.BufferSz = sizeof(vp9_extend_buf),
1009cabdff1aSopenharmony_ci    };
1010cabdff1aSopenharmony_ci
1011cabdff1aSopenharmony_ci    mfxExtCodingOption2 co2 = {
1012cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2,
1013cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(co2),
1014cabdff1aSopenharmony_ci    };
1015cabdff1aSopenharmony_ci
1016cabdff1aSopenharmony_ci    mfxExtCodingOption3 co3 = {
1017cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3,
1018cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(co3),
1019cabdff1aSopenharmony_ci    };
1020cabdff1aSopenharmony_ci
1021cabdff1aSopenharmony_ci    mfxExtBuffer *ext_buffers[3];
1022cabdff1aSopenharmony_ci    int ext_buf_num = 0;
1023cabdff1aSopenharmony_ci
1024cabdff1aSopenharmony_ci    q->co2_idx = q->co3_idx = q->vp9_idx = -1;
1025cabdff1aSopenharmony_ci
1026cabdff1aSopenharmony_ci    // It is possible the runtime doesn't support the given ext buffer
1027cabdff1aSopenharmony_ci    if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 6)) {
1028cabdff1aSopenharmony_ci        q->co2_idx = ext_buf_num;
1029cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co2;
1030cabdff1aSopenharmony_ci    }
1031cabdff1aSopenharmony_ci
1032cabdff1aSopenharmony_ci    if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 11)) {
1033cabdff1aSopenharmony_ci        q->co3_idx = ext_buf_num;
1034cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co3;
1035cabdff1aSopenharmony_ci    }
1036cabdff1aSopenharmony_ci
1037cabdff1aSopenharmony_ci    if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 26)) {
1038cabdff1aSopenharmony_ci        q->vp9_idx = ext_buf_num;
1039cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&vp9_extend_buf;
1040cabdff1aSopenharmony_ci    }
1041cabdff1aSopenharmony_ci
1042cabdff1aSopenharmony_ci    q->param.ExtParam    = ext_buffers;
1043cabdff1aSopenharmony_ci    q->param.NumExtParam = ext_buf_num;
1044cabdff1aSopenharmony_ci
1045cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
1046cabdff1aSopenharmony_ci    if (ret < 0)
1047cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
1048cabdff1aSopenharmony_ci                                  "Error calling GetVideoParam");
1049cabdff1aSopenharmony_ci
1050cabdff1aSopenharmony_ci    q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000;
1051cabdff1aSopenharmony_ci
1052cabdff1aSopenharmony_ci    dump_video_vp9_param(avctx, q, ext_buffers);
1053cabdff1aSopenharmony_ci
1054cabdff1aSopenharmony_ci    return 0;
1055cabdff1aSopenharmony_ci}
1056cabdff1aSopenharmony_ci
1057cabdff1aSopenharmony_cistatic int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
1058cabdff1aSopenharmony_ci{
1059cabdff1aSopenharmony_ci    AVCPBProperties *cpb_props;
1060cabdff1aSopenharmony_ci
1061cabdff1aSopenharmony_ci    uint8_t sps_buf[128];
1062cabdff1aSopenharmony_ci    uint8_t pps_buf[128];
1063cabdff1aSopenharmony_ci
1064cabdff1aSopenharmony_ci    mfxExtCodingOptionSPSPPS extradata = {
1065cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
1066cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(extradata),
1067cabdff1aSopenharmony_ci        .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
1068cabdff1aSopenharmony_ci        .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
1069cabdff1aSopenharmony_ci    };
1070cabdff1aSopenharmony_ci
1071cabdff1aSopenharmony_ci    mfxExtCodingOption co = {
1072cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION,
1073cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(co),
1074cabdff1aSopenharmony_ci    };
1075cabdff1aSopenharmony_ci    mfxExtCodingOption2 co2 = {
1076cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2,
1077cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(co2),
1078cabdff1aSopenharmony_ci    };
1079cabdff1aSopenharmony_ci    mfxExtCodingOption3 co3 = {
1080cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3,
1081cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(co3),
1082cabdff1aSopenharmony_ci    };
1083cabdff1aSopenharmony_ci
1084cabdff1aSopenharmony_ci    uint8_t vps_buf[128];
1085cabdff1aSopenharmony_ci    mfxExtCodingOptionVPS extradata_vps = {
1086cabdff1aSopenharmony_ci        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_VPS,
1087cabdff1aSopenharmony_ci        .Header.BufferSz = sizeof(extradata_vps),
1088cabdff1aSopenharmony_ci        .VPSBuffer       = vps_buf,
1089cabdff1aSopenharmony_ci        .VPSBufSize      = sizeof(vps_buf),
1090cabdff1aSopenharmony_ci    };
1091cabdff1aSopenharmony_ci
1092cabdff1aSopenharmony_ci    mfxExtHEVCTiles hevc_tile_buf = {
1093cabdff1aSopenharmony_ci         .Header.BufferId = MFX_EXTBUFF_HEVC_TILES,
1094cabdff1aSopenharmony_ci         .Header.BufferSz = sizeof(hevc_tile_buf),
1095cabdff1aSopenharmony_ci    };
1096cabdff1aSopenharmony_ci
1097cabdff1aSopenharmony_ci    mfxExtBuffer *ext_buffers[6];
1098cabdff1aSopenharmony_ci
1099cabdff1aSopenharmony_ci    int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
1100cabdff1aSopenharmony_ci    int ret, ext_buf_num = 0, extradata_offset = 0;
1101cabdff1aSopenharmony_ci
1102cabdff1aSopenharmony_ci    q->co2_idx = q->co3_idx = q->exthevctiles_idx = -1;
1103cabdff1aSopenharmony_ci    ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata;
1104cabdff1aSopenharmony_ci    ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co;
1105cabdff1aSopenharmony_ci
1106cabdff1aSopenharmony_ci    // It is possible the runtime doesn't support the given ext buffer
1107cabdff1aSopenharmony_ci    if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 6)) {
1108cabdff1aSopenharmony_ci        q->co2_idx = ext_buf_num;
1109cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co2;
1110cabdff1aSopenharmony_ci    }
1111cabdff1aSopenharmony_ci
1112cabdff1aSopenharmony_ci    if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 11)) {
1113cabdff1aSopenharmony_ci        q->co3_idx = ext_buf_num;
1114cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co3;
1115cabdff1aSopenharmony_ci    }
1116cabdff1aSopenharmony_ci
1117cabdff1aSopenharmony_ci    q->hevc_vps = ((avctx->codec_id == AV_CODEC_ID_HEVC) && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 17));
1118cabdff1aSopenharmony_ci    if (q->hevc_vps)
1119cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps;
1120cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_HEVC && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 13)) {
1121cabdff1aSopenharmony_ci        q->exthevctiles_idx = ext_buf_num;
1122cabdff1aSopenharmony_ci        ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf;
1123cabdff1aSopenharmony_ci    }
1124cabdff1aSopenharmony_ci
1125cabdff1aSopenharmony_ci    q->param.ExtParam    = ext_buffers;
1126cabdff1aSopenharmony_ci    q->param.NumExtParam = ext_buf_num;
1127cabdff1aSopenharmony_ci
1128cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
1129cabdff1aSopenharmony_ci    if (ret < 0)
1130cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
1131cabdff1aSopenharmony_ci                                  "Error calling GetVideoParam");
1132cabdff1aSopenharmony_ci
1133cabdff1aSopenharmony_ci    q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000;
1134cabdff1aSopenharmony_ci
1135cabdff1aSopenharmony_ci    if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)
1136cabdff1aSopenharmony_ci        || (q->hevc_vps && !extradata_vps.VPSBufSize)
1137cabdff1aSopenharmony_ci    ) {
1138cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
1139cabdff1aSopenharmony_ci        return AVERROR_UNKNOWN;
1140cabdff1aSopenharmony_ci    }
1141cabdff1aSopenharmony_ci
1142cabdff1aSopenharmony_ci    avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize;
1143cabdff1aSopenharmony_ci    avctx->extradata_size += q->hevc_vps * extradata_vps.VPSBufSize;
1144cabdff1aSopenharmony_ci
1145cabdff1aSopenharmony_ci    avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
1146cabdff1aSopenharmony_ci    if (!avctx->extradata)
1147cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1148cabdff1aSopenharmony_ci
1149cabdff1aSopenharmony_ci    if (q->hevc_vps) {
1150cabdff1aSopenharmony_ci        memcpy(avctx->extradata, vps_buf, extradata_vps.VPSBufSize);
1151cabdff1aSopenharmony_ci        extradata_offset += extradata_vps.VPSBufSize;
1152cabdff1aSopenharmony_ci    }
1153cabdff1aSopenharmony_ci
1154cabdff1aSopenharmony_ci    memcpy(avctx->extradata + extradata_offset, sps_buf, extradata.SPSBufSize);
1155cabdff1aSopenharmony_ci    extradata_offset += extradata.SPSBufSize;
1156cabdff1aSopenharmony_ci    if (need_pps) {
1157cabdff1aSopenharmony_ci        memcpy(avctx->extradata + extradata_offset, pps_buf, extradata.PPSBufSize);
1158cabdff1aSopenharmony_ci        extradata_offset += extradata.PPSBufSize;
1159cabdff1aSopenharmony_ci    }
1160cabdff1aSopenharmony_ci    memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1161cabdff1aSopenharmony_ci
1162cabdff1aSopenharmony_ci    cpb_props = ff_add_cpb_side_data(avctx);
1163cabdff1aSopenharmony_ci    if (!cpb_props)
1164cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1165cabdff1aSopenharmony_ci    cpb_props->max_bitrate = avctx->rc_max_rate;
1166cabdff1aSopenharmony_ci    cpb_props->min_bitrate = avctx->rc_min_rate;
1167cabdff1aSopenharmony_ci    cpb_props->avg_bitrate = avctx->bit_rate;
1168cabdff1aSopenharmony_ci    cpb_props->buffer_size = avctx->rc_buffer_size;
1169cabdff1aSopenharmony_ci
1170cabdff1aSopenharmony_ci    dump_video_param(avctx, q, ext_buffers);
1171cabdff1aSopenharmony_ci
1172cabdff1aSopenharmony_ci    return 0;
1173cabdff1aSopenharmony_ci}
1174cabdff1aSopenharmony_ci
1175cabdff1aSopenharmony_cistatic int qsv_init_opaque_alloc(AVCodecContext *avctx, QSVEncContext *q)
1176cabdff1aSopenharmony_ci{
1177cabdff1aSopenharmony_ci    AVQSVContext *qsv = avctx->hwaccel_context;
1178cabdff1aSopenharmony_ci    mfxFrameSurface1 *surfaces;
1179cabdff1aSopenharmony_ci    int nb_surfaces, i;
1180cabdff1aSopenharmony_ci
1181cabdff1aSopenharmony_ci    nb_surfaces = qsv->nb_opaque_surfaces + q->req.NumFrameSuggested;
1182cabdff1aSopenharmony_ci
1183cabdff1aSopenharmony_ci    q->opaque_alloc_buf = av_buffer_allocz(sizeof(*surfaces) * nb_surfaces);
1184cabdff1aSopenharmony_ci    if (!q->opaque_alloc_buf)
1185cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1186cabdff1aSopenharmony_ci
1187cabdff1aSopenharmony_ci    q->opaque_surfaces = av_malloc_array(nb_surfaces, sizeof(*q->opaque_surfaces));
1188cabdff1aSopenharmony_ci    if (!q->opaque_surfaces)
1189cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1190cabdff1aSopenharmony_ci
1191cabdff1aSopenharmony_ci    surfaces = (mfxFrameSurface1*)q->opaque_alloc_buf->data;
1192cabdff1aSopenharmony_ci    for (i = 0; i < nb_surfaces; i++) {
1193cabdff1aSopenharmony_ci        surfaces[i].Info      = q->req.Info;
1194cabdff1aSopenharmony_ci        q->opaque_surfaces[i] = surfaces + i;
1195cabdff1aSopenharmony_ci    }
1196cabdff1aSopenharmony_ci
1197cabdff1aSopenharmony_ci    q->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
1198cabdff1aSopenharmony_ci    q->opaque_alloc.Header.BufferSz = sizeof(q->opaque_alloc);
1199cabdff1aSopenharmony_ci    q->opaque_alloc.In.Surfaces     = q->opaque_surfaces;
1200cabdff1aSopenharmony_ci    q->opaque_alloc.In.NumSurface   = nb_surfaces;
1201cabdff1aSopenharmony_ci    q->opaque_alloc.In.Type         = q->req.Type;
1202cabdff1aSopenharmony_ci
1203cabdff1aSopenharmony_ci    q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->opaque_alloc;
1204cabdff1aSopenharmony_ci
1205cabdff1aSopenharmony_ci    qsv->nb_opaque_surfaces = nb_surfaces;
1206cabdff1aSopenharmony_ci    qsv->opaque_surfaces    = q->opaque_alloc_buf;
1207cabdff1aSopenharmony_ci    qsv->opaque_alloc_type  = q->req.Type;
1208cabdff1aSopenharmony_ci
1209cabdff1aSopenharmony_ci    return 0;
1210cabdff1aSopenharmony_ci}
1211cabdff1aSopenharmony_ci
1212cabdff1aSopenharmony_cistatic int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
1213cabdff1aSopenharmony_ci{
1214cabdff1aSopenharmony_ci    int ret;
1215cabdff1aSopenharmony_ci
1216cabdff1aSopenharmony_ci    if (avctx->hwaccel_context) {
1217cabdff1aSopenharmony_ci        AVQSVContext *qsv = avctx->hwaccel_context;
1218cabdff1aSopenharmony_ci        q->session = qsv->session;
1219cabdff1aSopenharmony_ci    } else if (avctx->hw_frames_ctx) {
1220cabdff1aSopenharmony_ci        q->frames_ctx.hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
1221cabdff1aSopenharmony_ci        if (!q->frames_ctx.hw_frames_ctx)
1222cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1223cabdff1aSopenharmony_ci
1224cabdff1aSopenharmony_ci        ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
1225cabdff1aSopenharmony_ci                                         &q->frames_ctx, q->load_plugins,
1226cabdff1aSopenharmony_ci                                         q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY,
1227cabdff1aSopenharmony_ci                                         MFX_GPUCOPY_OFF);
1228cabdff1aSopenharmony_ci        if (ret < 0) {
1229cabdff1aSopenharmony_ci            av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
1230cabdff1aSopenharmony_ci            return ret;
1231cabdff1aSopenharmony_ci        }
1232cabdff1aSopenharmony_ci
1233cabdff1aSopenharmony_ci        q->session = q->internal_qs.session;
1234cabdff1aSopenharmony_ci    } else if (avctx->hw_device_ctx) {
1235cabdff1aSopenharmony_ci        ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
1236cabdff1aSopenharmony_ci                                         avctx->hw_device_ctx, q->load_plugins,
1237cabdff1aSopenharmony_ci                                         MFX_GPUCOPY_OFF);
1238cabdff1aSopenharmony_ci        if (ret < 0)
1239cabdff1aSopenharmony_ci            return ret;
1240cabdff1aSopenharmony_ci
1241cabdff1aSopenharmony_ci        q->session = q->internal_qs.session;
1242cabdff1aSopenharmony_ci    } else {
1243cabdff1aSopenharmony_ci        ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
1244cabdff1aSopenharmony_ci                                           q->load_plugins, MFX_GPUCOPY_OFF);
1245cabdff1aSopenharmony_ci        if (ret < 0)
1246cabdff1aSopenharmony_ci            return ret;
1247cabdff1aSopenharmony_ci
1248cabdff1aSopenharmony_ci        q->session = q->internal_qs.session;
1249cabdff1aSopenharmony_ci    }
1250cabdff1aSopenharmony_ci
1251cabdff1aSopenharmony_ci    return 0;
1252cabdff1aSopenharmony_ci}
1253cabdff1aSopenharmony_ci
1254cabdff1aSopenharmony_ciint ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
1255cabdff1aSopenharmony_ci{
1256cabdff1aSopenharmony_ci    int iopattern = 0;
1257cabdff1aSopenharmony_ci    int opaque_alloc = 0;
1258cabdff1aSopenharmony_ci    int ret;
1259cabdff1aSopenharmony_ci
1260cabdff1aSopenharmony_ci    q->param.AsyncDepth = q->async_depth;
1261cabdff1aSopenharmony_ci
1262cabdff1aSopenharmony_ci    q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVPacket), 0);
1263cabdff1aSopenharmony_ci    if (!q->async_fifo)
1264cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1265cabdff1aSopenharmony_ci
1266cabdff1aSopenharmony_ci    if (avctx->hwaccel_context) {
1267cabdff1aSopenharmony_ci        AVQSVContext *qsv = avctx->hwaccel_context;
1268cabdff1aSopenharmony_ci
1269cabdff1aSopenharmony_ci        iopattern    = qsv->iopattern;
1270cabdff1aSopenharmony_ci        opaque_alloc = qsv->opaque_alloc;
1271cabdff1aSopenharmony_ci    }
1272cabdff1aSopenharmony_ci
1273cabdff1aSopenharmony_ci    if (avctx->hw_frames_ctx) {
1274cabdff1aSopenharmony_ci        AVHWFramesContext    *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1275cabdff1aSopenharmony_ci        AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
1276cabdff1aSopenharmony_ci
1277cabdff1aSopenharmony_ci        if (!iopattern) {
1278cabdff1aSopenharmony_ci            if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
1279cabdff1aSopenharmony_ci                iopattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY;
1280cabdff1aSopenharmony_ci            else if (frames_hwctx->frame_type &
1281cabdff1aSopenharmony_ci                     (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
1282cabdff1aSopenharmony_ci                iopattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
1283cabdff1aSopenharmony_ci        }
1284cabdff1aSopenharmony_ci    }
1285cabdff1aSopenharmony_ci
1286cabdff1aSopenharmony_ci    if (!iopattern)
1287cabdff1aSopenharmony_ci        iopattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
1288cabdff1aSopenharmony_ci    q->param.IOPattern = iopattern;
1289cabdff1aSopenharmony_ci    ff_qsv_print_iopattern(avctx, iopattern, "Encoder");
1290cabdff1aSopenharmony_ci
1291cabdff1aSopenharmony_ci    ret = qsvenc_init_session(avctx, q);
1292cabdff1aSopenharmony_ci    if (ret < 0)
1293cabdff1aSopenharmony_ci        return ret;
1294cabdff1aSopenharmony_ci
1295cabdff1aSopenharmony_ci    ret = MFXQueryVersion(q->session,&q->ver);
1296cabdff1aSopenharmony_ci    if (ret < 0) {
1297cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
1298cabdff1aSopenharmony_ci                                  "Error querying mfx version");
1299cabdff1aSopenharmony_ci    }
1300cabdff1aSopenharmony_ci
1301cabdff1aSopenharmony_ci    // in the mfxInfoMFX struct, JPEG is different from other codecs
1302cabdff1aSopenharmony_ci    switch (avctx->codec_id) {
1303cabdff1aSopenharmony_ci    case AV_CODEC_ID_MJPEG:
1304cabdff1aSopenharmony_ci        ret = init_video_param_jpeg(avctx, q);
1305cabdff1aSopenharmony_ci        break;
1306cabdff1aSopenharmony_ci    default:
1307cabdff1aSopenharmony_ci        ret = init_video_param(avctx, q);
1308cabdff1aSopenharmony_ci        break;
1309cabdff1aSopenharmony_ci    }
1310cabdff1aSopenharmony_ci    if (ret < 0)
1311cabdff1aSopenharmony_ci        return ret;
1312cabdff1aSopenharmony_ci
1313cabdff1aSopenharmony_ci    if (avctx->hwaccel_context) {
1314cabdff1aSopenharmony_ci        AVQSVContext *qsv = avctx->hwaccel_context;
1315cabdff1aSopenharmony_ci        int i, j;
1316cabdff1aSopenharmony_ci
1317cabdff1aSopenharmony_ci        q->extparam = av_calloc(qsv->nb_ext_buffers + q->nb_extparam_internal,
1318cabdff1aSopenharmony_ci                                sizeof(*q->extparam));
1319cabdff1aSopenharmony_ci        if (!q->extparam)
1320cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1321cabdff1aSopenharmony_ci
1322cabdff1aSopenharmony_ci        q->param.ExtParam = q->extparam;
1323cabdff1aSopenharmony_ci        for (i = 0; i < qsv->nb_ext_buffers; i++)
1324cabdff1aSopenharmony_ci            q->param.ExtParam[i] = qsv->ext_buffers[i];
1325cabdff1aSopenharmony_ci        q->param.NumExtParam = qsv->nb_ext_buffers;
1326cabdff1aSopenharmony_ci
1327cabdff1aSopenharmony_ci        for (i = 0; i < q->nb_extparam_internal; i++) {
1328cabdff1aSopenharmony_ci            for (j = 0; j < qsv->nb_ext_buffers; j++) {
1329cabdff1aSopenharmony_ci                if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId)
1330cabdff1aSopenharmony_ci                    break;
1331cabdff1aSopenharmony_ci            }
1332cabdff1aSopenharmony_ci            if (j < qsv->nb_ext_buffers)
1333cabdff1aSopenharmony_ci                continue;
1334cabdff1aSopenharmony_ci
1335cabdff1aSopenharmony_ci            q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i];
1336cabdff1aSopenharmony_ci        }
1337cabdff1aSopenharmony_ci    } else {
1338cabdff1aSopenharmony_ci        q->param.ExtParam    = q->extparam_internal;
1339cabdff1aSopenharmony_ci        q->param.NumExtParam = q->nb_extparam_internal;
1340cabdff1aSopenharmony_ci    }
1341cabdff1aSopenharmony_ci
1342cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_Query(q->session, &q->param, &q->param);
1343cabdff1aSopenharmony_ci    if (ret == MFX_WRN_PARTIAL_ACCELERATION) {
1344cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
1345cabdff1aSopenharmony_ci    } else if (ret < 0) {
1346cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
1347cabdff1aSopenharmony_ci                                  "Error querying encoder params");
1348cabdff1aSopenharmony_ci    }
1349cabdff1aSopenharmony_ci
1350cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
1351cabdff1aSopenharmony_ci    if (ret < 0)
1352cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
1353cabdff1aSopenharmony_ci                                  "Error querying (IOSurf) the encoding parameters");
1354cabdff1aSopenharmony_ci
1355cabdff1aSopenharmony_ci    if (opaque_alloc) {
1356cabdff1aSopenharmony_ci        ret = qsv_init_opaque_alloc(avctx, q);
1357cabdff1aSopenharmony_ci        if (ret < 0)
1358cabdff1aSopenharmony_ci            return ret;
1359cabdff1aSopenharmony_ci    }
1360cabdff1aSopenharmony_ci
1361cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_Init(q->session, &q->param);
1362cabdff1aSopenharmony_ci    if (ret < 0)
1363cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret,
1364cabdff1aSopenharmony_ci                                  "Error initializing the encoder");
1365cabdff1aSopenharmony_ci    else if (ret > 0)
1366cabdff1aSopenharmony_ci        ff_qsv_print_warning(avctx, ret,
1367cabdff1aSopenharmony_ci                             "Warning in encoder initialization");
1368cabdff1aSopenharmony_ci
1369cabdff1aSopenharmony_ci    switch (avctx->codec_id) {
1370cabdff1aSopenharmony_ci    case AV_CODEC_ID_MJPEG:
1371cabdff1aSopenharmony_ci        ret = qsv_retrieve_enc_jpeg_params(avctx, q);
1372cabdff1aSopenharmony_ci        break;
1373cabdff1aSopenharmony_ci    case AV_CODEC_ID_VP9:
1374cabdff1aSopenharmony_ci        ret = qsv_retrieve_enc_vp9_params(avctx, q);
1375cabdff1aSopenharmony_ci        break;
1376cabdff1aSopenharmony_ci    default:
1377cabdff1aSopenharmony_ci        ret = qsv_retrieve_enc_params(avctx, q);
1378cabdff1aSopenharmony_ci        break;
1379cabdff1aSopenharmony_ci    }
1380cabdff1aSopenharmony_ci    if (ret < 0) {
1381cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
1382cabdff1aSopenharmony_ci        return ret;
1383cabdff1aSopenharmony_ci    }
1384cabdff1aSopenharmony_ci
1385cabdff1aSopenharmony_ci    q->avctx = avctx;
1386cabdff1aSopenharmony_ci
1387cabdff1aSopenharmony_ci    return 0;
1388cabdff1aSopenharmony_ci}
1389cabdff1aSopenharmony_ci
1390cabdff1aSopenharmony_cistatic void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl)
1391cabdff1aSopenharmony_ci{
1392cabdff1aSopenharmony_ci    if (enc_ctrl) {
1393cabdff1aSopenharmony_ci        int i;
1394cabdff1aSopenharmony_ci        for (i = 0; i < enc_ctrl->NumPayload && i < QSV_MAX_ENC_PAYLOAD; i++) {
1395cabdff1aSopenharmony_ci            av_freep(&enc_ctrl->Payload[i]);
1396cabdff1aSopenharmony_ci        }
1397cabdff1aSopenharmony_ci        enc_ctrl->NumPayload = 0;
1398cabdff1aSopenharmony_ci    }
1399cabdff1aSopenharmony_ci}
1400cabdff1aSopenharmony_ci
1401cabdff1aSopenharmony_cistatic void free_encoder_ctrl_extparam(mfxEncodeCtrl* enc_ctrl)
1402cabdff1aSopenharmony_ci{
1403cabdff1aSopenharmony_ci    if (enc_ctrl) {
1404cabdff1aSopenharmony_ci        int i;
1405cabdff1aSopenharmony_ci        for (i = 0; i < enc_ctrl->NumExtParam && i < QSV_MAX_ENC_EXTPARAM; i++) {
1406cabdff1aSopenharmony_ci            if (enc_ctrl->ExtParam[i])
1407cabdff1aSopenharmony_ci                av_freep(&(enc_ctrl->ExtParam[i]));
1408cabdff1aSopenharmony_ci        }
1409cabdff1aSopenharmony_ci        enc_ctrl->NumExtParam = 0;
1410cabdff1aSopenharmony_ci    }
1411cabdff1aSopenharmony_ci}
1412cabdff1aSopenharmony_ci
1413cabdff1aSopenharmony_cistatic void clear_unused_frames(QSVEncContext *q)
1414cabdff1aSopenharmony_ci{
1415cabdff1aSopenharmony_ci    QSVFrame *cur = q->work_frames;
1416cabdff1aSopenharmony_ci    while (cur) {
1417cabdff1aSopenharmony_ci        if (cur->used && !cur->surface.Data.Locked) {
1418cabdff1aSopenharmony_ci            free_encoder_ctrl_payloads(&cur->enc_ctrl);
1419cabdff1aSopenharmony_ci            free_encoder_ctrl_extparam(&cur->enc_ctrl);
1420cabdff1aSopenharmony_ci            //do not reuse enc_ctrl from previous frame
1421cabdff1aSopenharmony_ci            memset(&cur->enc_ctrl, 0, sizeof(cur->enc_ctrl));
1422cabdff1aSopenharmony_ci            cur->enc_ctrl.Payload = cur->payloads;
1423cabdff1aSopenharmony_ci            cur->enc_ctrl.ExtParam = cur->extparam;
1424cabdff1aSopenharmony_ci            if (cur->frame->format == AV_PIX_FMT_QSV) {
1425cabdff1aSopenharmony_ci                av_frame_unref(cur->frame);
1426cabdff1aSopenharmony_ci            }
1427cabdff1aSopenharmony_ci            cur->used = 0;
1428cabdff1aSopenharmony_ci        }
1429cabdff1aSopenharmony_ci        cur = cur->next;
1430cabdff1aSopenharmony_ci    }
1431cabdff1aSopenharmony_ci}
1432cabdff1aSopenharmony_ci
1433cabdff1aSopenharmony_cistatic int get_free_frame(QSVEncContext *q, QSVFrame **f)
1434cabdff1aSopenharmony_ci{
1435cabdff1aSopenharmony_ci    QSVFrame *frame, **last;
1436cabdff1aSopenharmony_ci
1437cabdff1aSopenharmony_ci    clear_unused_frames(q);
1438cabdff1aSopenharmony_ci
1439cabdff1aSopenharmony_ci    frame = q->work_frames;
1440cabdff1aSopenharmony_ci    last  = &q->work_frames;
1441cabdff1aSopenharmony_ci    while (frame) {
1442cabdff1aSopenharmony_ci        if (!frame->used) {
1443cabdff1aSopenharmony_ci            *f = frame;
1444cabdff1aSopenharmony_ci            frame->used = 1;
1445cabdff1aSopenharmony_ci            return 0;
1446cabdff1aSopenharmony_ci        }
1447cabdff1aSopenharmony_ci
1448cabdff1aSopenharmony_ci        last  = &frame->next;
1449cabdff1aSopenharmony_ci        frame = frame->next;
1450cabdff1aSopenharmony_ci    }
1451cabdff1aSopenharmony_ci
1452cabdff1aSopenharmony_ci    frame = av_mallocz(sizeof(*frame));
1453cabdff1aSopenharmony_ci    if (!frame)
1454cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1455cabdff1aSopenharmony_ci    frame->frame = av_frame_alloc();
1456cabdff1aSopenharmony_ci    if (!frame->frame) {
1457cabdff1aSopenharmony_ci        av_freep(&frame);
1458cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1459cabdff1aSopenharmony_ci    }
1460cabdff1aSopenharmony_ci    frame->enc_ctrl.Payload = frame->payloads;
1461cabdff1aSopenharmony_ci    frame->enc_ctrl.ExtParam = frame->extparam;
1462cabdff1aSopenharmony_ci    *last = frame;
1463cabdff1aSopenharmony_ci
1464cabdff1aSopenharmony_ci    *f = frame;
1465cabdff1aSopenharmony_ci    frame->used = 1;
1466cabdff1aSopenharmony_ci
1467cabdff1aSopenharmony_ci    return 0;
1468cabdff1aSopenharmony_ci}
1469cabdff1aSopenharmony_ci
1470cabdff1aSopenharmony_cistatic int submit_frame(QSVEncContext *q, const AVFrame *frame,
1471cabdff1aSopenharmony_ci                        QSVFrame **new_frame)
1472cabdff1aSopenharmony_ci{
1473cabdff1aSopenharmony_ci    QSVFrame *qf;
1474cabdff1aSopenharmony_ci    int ret;
1475cabdff1aSopenharmony_ci
1476cabdff1aSopenharmony_ci    ret = get_free_frame(q, &qf);
1477cabdff1aSopenharmony_ci    if (ret < 0)
1478cabdff1aSopenharmony_ci        return ret;
1479cabdff1aSopenharmony_ci
1480cabdff1aSopenharmony_ci    if (frame->format == AV_PIX_FMT_QSV) {
1481cabdff1aSopenharmony_ci        ret = av_frame_ref(qf->frame, frame);
1482cabdff1aSopenharmony_ci        if (ret < 0)
1483cabdff1aSopenharmony_ci            return ret;
1484cabdff1aSopenharmony_ci
1485cabdff1aSopenharmony_ci        qf->surface = *(mfxFrameSurface1*)qf->frame->data[3];
1486cabdff1aSopenharmony_ci
1487cabdff1aSopenharmony_ci        if (q->frames_ctx.mids) {
1488cabdff1aSopenharmony_ci            ret = ff_qsv_find_surface_idx(&q->frames_ctx, qf);
1489cabdff1aSopenharmony_ci            if (ret < 0)
1490cabdff1aSopenharmony_ci                return ret;
1491cabdff1aSopenharmony_ci
1492cabdff1aSopenharmony_ci            qf->surface.Data.MemId = &q->frames_ctx.mids[ret];
1493cabdff1aSopenharmony_ci        }
1494cabdff1aSopenharmony_ci    } else {
1495cabdff1aSopenharmony_ci        /* make a copy if the input is not padded as libmfx requires */
1496cabdff1aSopenharmony_ci        /* and to make allocation continious for data[0]/data[1] */
1497cabdff1aSopenharmony_ci         if ((frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) ||
1498cabdff1aSopenharmony_ci            (frame->data[1] - frame->data[0] != frame->linesize[0] * FFALIGN(qf->frame->height, q->height_align))) {
1499cabdff1aSopenharmony_ci            qf->frame->height = FFALIGN(frame->height, q->height_align);
1500cabdff1aSopenharmony_ci            qf->frame->width  = FFALIGN(frame->width, q->width_align);
1501cabdff1aSopenharmony_ci
1502cabdff1aSopenharmony_ci            qf->frame->format = frame->format;
1503cabdff1aSopenharmony_ci
1504cabdff1aSopenharmony_ci            if (!qf->frame->data[0]) {
1505cabdff1aSopenharmony_ci                ret = av_frame_get_buffer(qf->frame, q->width_align);
1506cabdff1aSopenharmony_ci                if (ret < 0)
1507cabdff1aSopenharmony_ci                    return ret;
1508cabdff1aSopenharmony_ci            }
1509cabdff1aSopenharmony_ci
1510cabdff1aSopenharmony_ci            qf->frame->height = frame->height;
1511cabdff1aSopenharmony_ci            qf->frame->width  = frame->width;
1512cabdff1aSopenharmony_ci
1513cabdff1aSopenharmony_ci            ret = av_frame_copy(qf->frame, frame);
1514cabdff1aSopenharmony_ci            if (ret < 0) {
1515cabdff1aSopenharmony_ci                av_frame_unref(qf->frame);
1516cabdff1aSopenharmony_ci                return ret;
1517cabdff1aSopenharmony_ci            }
1518cabdff1aSopenharmony_ci        } else {
1519cabdff1aSopenharmony_ci            av_frame_unref(qf->frame);
1520cabdff1aSopenharmony_ci            ret = av_frame_ref(qf->frame, frame);
1521cabdff1aSopenharmony_ci            if (ret < 0)
1522cabdff1aSopenharmony_ci                return ret;
1523cabdff1aSopenharmony_ci        }
1524cabdff1aSopenharmony_ci
1525cabdff1aSopenharmony_ci        qf->surface.Info = q->param.mfx.FrameInfo;
1526cabdff1aSopenharmony_ci
1527cabdff1aSopenharmony_ci        qf->surface.Info.PicStruct =
1528cabdff1aSopenharmony_ci            !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
1529cabdff1aSopenharmony_ci            frame->top_field_first   ? MFX_PICSTRUCT_FIELD_TFF :
1530cabdff1aSopenharmony_ci                                       MFX_PICSTRUCT_FIELD_BFF;
1531cabdff1aSopenharmony_ci        if (frame->repeat_pict == 1)
1532cabdff1aSopenharmony_ci            qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
1533cabdff1aSopenharmony_ci        else if (frame->repeat_pict == 2)
1534cabdff1aSopenharmony_ci            qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
1535cabdff1aSopenharmony_ci        else if (frame->repeat_pict == 4)
1536cabdff1aSopenharmony_ci            qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
1537cabdff1aSopenharmony_ci
1538cabdff1aSopenharmony_ci        ret = ff_qsv_map_frame_to_surface(qf->frame, &qf->surface);
1539cabdff1aSopenharmony_ci        if (ret < 0) {
1540cabdff1aSopenharmony_ci            av_log(q->avctx, AV_LOG_ERROR, "map frame to surface failed.\n");
1541cabdff1aSopenharmony_ci            return ret;
1542cabdff1aSopenharmony_ci        }
1543cabdff1aSopenharmony_ci    }
1544cabdff1aSopenharmony_ci    qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
1545cabdff1aSopenharmony_ci
1546cabdff1aSopenharmony_ci    *new_frame = qf;
1547cabdff1aSopenharmony_ci
1548cabdff1aSopenharmony_ci    return 0;
1549cabdff1aSopenharmony_ci}
1550cabdff1aSopenharmony_ci
1551cabdff1aSopenharmony_cistatic void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
1552cabdff1aSopenharmony_ci{
1553cabdff1aSopenharmony_ci    if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
1554cabdff1aSopenharmony_ci        if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
1555cabdff1aSopenharmony_ci            q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
1556cabdff1aSopenharmony_ci            q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
1557cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING,
1558cabdff1aSopenharmony_ci                   "Interlaced coding is supported"
1559cabdff1aSopenharmony_ci                   " at Main/High Profile Level 2.2-4.0\n");
1560cabdff1aSopenharmony_ci    }
1561cabdff1aSopenharmony_ci}
1562cabdff1aSopenharmony_ci
1563cabdff1aSopenharmony_cistatic int set_roi_encode_ctrl(AVCodecContext *avctx, const AVFrame *frame,
1564cabdff1aSopenharmony_ci                               mfxEncodeCtrl *enc_ctrl)
1565cabdff1aSopenharmony_ci{
1566cabdff1aSopenharmony_ci    AVFrameSideData *sd = NULL;
1567cabdff1aSopenharmony_ci    int mb_size;
1568cabdff1aSopenharmony_ci
1569cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_H264)
1570cabdff1aSopenharmony_ci        mb_size = 16;
1571cabdff1aSopenharmony_ci    else if (avctx->codec_id == AV_CODEC_ID_H265)
1572cabdff1aSopenharmony_ci        mb_size = 32;
1573cabdff1aSopenharmony_ci    else
1574cabdff1aSopenharmony_ci        return 0;
1575cabdff1aSopenharmony_ci
1576cabdff1aSopenharmony_ci    if (frame)
1577cabdff1aSopenharmony_ci        sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST);
1578cabdff1aSopenharmony_ci
1579cabdff1aSopenharmony_ci    if (sd) {
1580cabdff1aSopenharmony_ci        mfxExtEncoderROI *enc_roi = NULL;
1581cabdff1aSopenharmony_ci        AVRegionOfInterest *roi;
1582cabdff1aSopenharmony_ci        uint32_t roi_size;
1583cabdff1aSopenharmony_ci        int nb_roi, i;
1584cabdff1aSopenharmony_ci
1585cabdff1aSopenharmony_ci        roi = (AVRegionOfInterest *)sd->data;
1586cabdff1aSopenharmony_ci        roi_size = roi->self_size;
1587cabdff1aSopenharmony_ci        if (!roi_size || sd->size % roi_size) {
1588cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Invalid ROI Data.\n");
1589cabdff1aSopenharmony_ci            return AVERROR(EINVAL);
1590cabdff1aSopenharmony_ci        }
1591cabdff1aSopenharmony_ci        nb_roi = sd->size / roi_size;
1592cabdff1aSopenharmony_ci        if (nb_roi > QSV_MAX_ROI_NUM) {
1593cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "More ROIs set than "
1594cabdff1aSopenharmony_ci                    "supported by driver (%d > %d).\n",
1595cabdff1aSopenharmony_ci                    nb_roi, QSV_MAX_ROI_NUM);
1596cabdff1aSopenharmony_ci            nb_roi = QSV_MAX_ROI_NUM;
1597cabdff1aSopenharmony_ci        }
1598cabdff1aSopenharmony_ci
1599cabdff1aSopenharmony_ci        enc_roi = av_mallocz(sizeof(*enc_roi));
1600cabdff1aSopenharmony_ci        if (!enc_roi)
1601cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1602cabdff1aSopenharmony_ci        enc_roi->Header.BufferId = MFX_EXTBUFF_ENCODER_ROI;
1603cabdff1aSopenharmony_ci        enc_roi->Header.BufferSz = sizeof(*enc_roi);
1604cabdff1aSopenharmony_ci        enc_roi->NumROI  = nb_roi;
1605cabdff1aSopenharmony_ci        enc_roi->ROIMode = MFX_ROI_MODE_QP_DELTA;
1606cabdff1aSopenharmony_ci        for (i = 0; i < nb_roi; i++) {
1607cabdff1aSopenharmony_ci            roi = (AVRegionOfInterest *)(sd->data + roi_size * i);
1608cabdff1aSopenharmony_ci            enc_roi->ROI[i].Top    = FFALIGN(roi->top, mb_size);
1609cabdff1aSopenharmony_ci            enc_roi->ROI[i].Bottom = FFALIGN(roi->bottom, mb_size);
1610cabdff1aSopenharmony_ci            enc_roi->ROI[i].Left   = FFALIGN(roi->left, mb_size);
1611cabdff1aSopenharmony_ci            enc_roi->ROI[i].Right  = FFALIGN(roi->right, mb_size);
1612cabdff1aSopenharmony_ci            enc_roi->ROI[i].DeltaQP =
1613cabdff1aSopenharmony_ci                roi->qoffset.num * 51 / roi->qoffset.den;
1614cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n",
1615cabdff1aSopenharmony_ci                   roi->top, roi->left, roi->bottom, roi->right,
1616cabdff1aSopenharmony_ci                   enc_roi->ROI[i].DeltaQP);
1617cabdff1aSopenharmony_ci        }
1618cabdff1aSopenharmony_ci        enc_ctrl->ExtParam[enc_ctrl->NumExtParam] = (mfxExtBuffer *)enc_roi;
1619cabdff1aSopenharmony_ci        enc_ctrl->NumExtParam++;
1620cabdff1aSopenharmony_ci    }
1621cabdff1aSopenharmony_ci    return 0;
1622cabdff1aSopenharmony_ci}
1623cabdff1aSopenharmony_ci
1624cabdff1aSopenharmony_cistatic int update_qp(AVCodecContext *avctx, QSVEncContext *q,
1625cabdff1aSopenharmony_ci                     const AVFrame *frame)
1626cabdff1aSopenharmony_ci{
1627cabdff1aSopenharmony_ci    int updated = 0, qp = 0, new_qp;
1628cabdff1aSopenharmony_ci    char *tail;
1629cabdff1aSopenharmony_ci    AVDictionaryEntry *entry = NULL;
1630cabdff1aSopenharmony_ci
1631cabdff1aSopenharmony_ci    if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC)
1632cabdff1aSopenharmony_ci        return 0;
1633cabdff1aSopenharmony_ci
1634cabdff1aSopenharmony_ci    entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0);
1635cabdff1aSopenharmony_ci    if (entry && q->param.mfx.RateControlMethod == MFX_RATECONTROL_CQP) {
1636cabdff1aSopenharmony_ci        qp = strtol(entry->value, &tail, 10);
1637cabdff1aSopenharmony_ci        if (*tail) {
1638cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Invalid qsv_config_qp string. Ignore this metadata\n");
1639cabdff1aSopenharmony_ci            return 0;
1640cabdff1aSopenharmony_ci        }
1641cabdff1aSopenharmony_ci        if (qp < 0 || qp > 51) {
1642cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Invalid qp, clip to 0 ~ 51\n");
1643cabdff1aSopenharmony_ci            qp = av_clip(qp, 0, 51);
1644cabdff1aSopenharmony_ci        }
1645cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Configure qp: %d\n",qp);
1646cabdff1aSopenharmony_ci        UPDATE_PARAM(q->param.mfx.QPP, qp);
1647cabdff1aSopenharmony_ci        new_qp = av_clip(qp * fabs(avctx->i_quant_factor) +
1648cabdff1aSopenharmony_ci                            avctx->i_quant_offset, 0, 51);
1649cabdff1aSopenharmony_ci        UPDATE_PARAM(q->param.mfx.QPI, new_qp);
1650cabdff1aSopenharmony_ci        new_qp = av_clip(qp * fabs(avctx->b_quant_factor) +
1651cabdff1aSopenharmony_ci                            avctx->b_quant_offset, 0, 51);
1652cabdff1aSopenharmony_ci        UPDATE_PARAM(q->param.mfx.QPB, new_qp);
1653cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG,
1654cabdff1aSopenharmony_ci                "using fixed qp = %d/%d/%d for idr/p/b frames\n",
1655cabdff1aSopenharmony_ci                q->param.mfx.QPI, q->param.mfx.QPP, q->param.mfx.QPB);
1656cabdff1aSopenharmony_ci    }
1657cabdff1aSopenharmony_ci    return updated;
1658cabdff1aSopenharmony_ci}
1659cabdff1aSopenharmony_ci
1660cabdff1aSopenharmony_cistatic int update_parameters(AVCodecContext *avctx, QSVEncContext *q,
1661cabdff1aSopenharmony_ci                             const AVFrame *frame)
1662cabdff1aSopenharmony_ci{
1663cabdff1aSopenharmony_ci    int needReset = 0, ret = 0;
1664cabdff1aSopenharmony_ci
1665cabdff1aSopenharmony_ci    if (!frame)
1666cabdff1aSopenharmony_ci        return 0;
1667cabdff1aSopenharmony_ci
1668cabdff1aSopenharmony_ci    needReset = update_qp(avctx, q, frame);
1669cabdff1aSopenharmony_ci    if (!needReset)
1670cabdff1aSopenharmony_ci        return 0;
1671cabdff1aSopenharmony_ci
1672cabdff1aSopenharmony_ci    if (avctx->hwaccel_context) {
1673cabdff1aSopenharmony_ci        AVQSVContext *qsv = avctx->hwaccel_context;
1674cabdff1aSopenharmony_ci        int i, j;
1675cabdff1aSopenharmony_ci        q->param.ExtParam = q->extparam;
1676cabdff1aSopenharmony_ci        for (i = 0; i < qsv->nb_ext_buffers; i++)
1677cabdff1aSopenharmony_ci            q->param.ExtParam[i] = qsv->ext_buffers[i];
1678cabdff1aSopenharmony_ci        q->param.NumExtParam = qsv->nb_ext_buffers;
1679cabdff1aSopenharmony_ci
1680cabdff1aSopenharmony_ci        for (i = 0; i < q->nb_extparam_internal; i++) {
1681cabdff1aSopenharmony_ci            for (j = 0; j < qsv->nb_ext_buffers; j++) {
1682cabdff1aSopenharmony_ci                if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId)
1683cabdff1aSopenharmony_ci                    break;
1684cabdff1aSopenharmony_ci            }
1685cabdff1aSopenharmony_ci            if (j < qsv->nb_ext_buffers)
1686cabdff1aSopenharmony_ci                continue;
1687cabdff1aSopenharmony_ci            q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i];
1688cabdff1aSopenharmony_ci        }
1689cabdff1aSopenharmony_ci    } else {
1690cabdff1aSopenharmony_ci        q->param.ExtParam    = q->extparam_internal;
1691cabdff1aSopenharmony_ci        q->param.NumExtParam = q->nb_extparam_internal;
1692cabdff1aSopenharmony_ci    }
1693cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n");
1694cabdff1aSopenharmony_ci    ret = MFXVideoENCODE_Reset(q->session, &q->param);
1695cabdff1aSopenharmony_ci    if (ret < 0)
1696cabdff1aSopenharmony_ci        return ff_qsv_print_error(avctx, ret, "Error during resetting");
1697cabdff1aSopenharmony_ci
1698cabdff1aSopenharmony_ci    return 0;
1699cabdff1aSopenharmony_ci}
1700cabdff1aSopenharmony_ci
1701cabdff1aSopenharmony_cistatic int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
1702cabdff1aSopenharmony_ci                        const AVFrame *frame)
1703cabdff1aSopenharmony_ci{
1704cabdff1aSopenharmony_ci    QSVPacket pkt = { { 0 } };
1705cabdff1aSopenharmony_ci    mfxExtAVCEncodedFrameInfo *enc_info = NULL;
1706cabdff1aSopenharmony_ci    mfxExtBuffer **enc_buf = NULL;
1707cabdff1aSopenharmony_ci
1708cabdff1aSopenharmony_ci    mfxFrameSurface1 *surf = NULL;
1709cabdff1aSopenharmony_ci    QSVFrame *qsv_frame = NULL;
1710cabdff1aSopenharmony_ci    mfxEncodeCtrl* enc_ctrl = NULL;
1711cabdff1aSopenharmony_ci    int ret;
1712cabdff1aSopenharmony_ci
1713cabdff1aSopenharmony_ci    if (frame) {
1714cabdff1aSopenharmony_ci        ret = submit_frame(q, frame, &qsv_frame);
1715cabdff1aSopenharmony_ci        if (ret < 0) {
1716cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
1717cabdff1aSopenharmony_ci            return ret;
1718cabdff1aSopenharmony_ci        }
1719cabdff1aSopenharmony_ci    }
1720cabdff1aSopenharmony_ci    if (qsv_frame) {
1721cabdff1aSopenharmony_ci        surf = &qsv_frame->surface;
1722cabdff1aSopenharmony_ci        enc_ctrl = &qsv_frame->enc_ctrl;
1723cabdff1aSopenharmony_ci
1724cabdff1aSopenharmony_ci        if (frame->pict_type == AV_PICTURE_TYPE_I) {
1725cabdff1aSopenharmony_ci            enc_ctrl->FrameType = MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF;
1726cabdff1aSopenharmony_ci            if (q->forced_idr)
1727cabdff1aSopenharmony_ci                enc_ctrl->FrameType |= MFX_FRAMETYPE_IDR;
1728cabdff1aSopenharmony_ci        }
1729cabdff1aSopenharmony_ci    }
1730cabdff1aSopenharmony_ci
1731cabdff1aSopenharmony_ci    ret = av_new_packet(&pkt.pkt, q->packet_size);
1732cabdff1aSopenharmony_ci    if (ret < 0) {
1733cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n");
1734cabdff1aSopenharmony_ci        return ret;
1735cabdff1aSopenharmony_ci    }
1736cabdff1aSopenharmony_ci
1737cabdff1aSopenharmony_ci    pkt.bs = av_mallocz(sizeof(*pkt.bs));
1738cabdff1aSopenharmony_ci    if (!pkt.bs)
1739cabdff1aSopenharmony_ci        goto nomem;
1740cabdff1aSopenharmony_ci    pkt.bs->Data      = pkt.pkt.data;
1741cabdff1aSopenharmony_ci    pkt.bs->MaxLength = pkt.pkt.size;
1742cabdff1aSopenharmony_ci
1743cabdff1aSopenharmony_ci    if (avctx->codec_id == AV_CODEC_ID_H264) {
1744cabdff1aSopenharmony_ci        enc_info = av_mallocz(sizeof(*enc_info));
1745cabdff1aSopenharmony_ci        if (!enc_info)
1746cabdff1aSopenharmony_ci            goto nomem;
1747cabdff1aSopenharmony_ci
1748cabdff1aSopenharmony_ci        enc_info->Header.BufferId = MFX_EXTBUFF_ENCODED_FRAME_INFO;
1749cabdff1aSopenharmony_ci        enc_info->Header.BufferSz = sizeof (*enc_info);
1750cabdff1aSopenharmony_ci        pkt.bs->NumExtParam = 1;
1751cabdff1aSopenharmony_ci        enc_buf = av_mallocz(sizeof(mfxExtBuffer *));
1752cabdff1aSopenharmony_ci        if (!enc_buf)
1753cabdff1aSopenharmony_ci            goto nomem;
1754cabdff1aSopenharmony_ci        enc_buf[0] = (mfxExtBuffer *)enc_info;
1755cabdff1aSopenharmony_ci
1756cabdff1aSopenharmony_ci        pkt.bs->ExtParam = enc_buf;
1757cabdff1aSopenharmony_ci    }
1758cabdff1aSopenharmony_ci
1759cabdff1aSopenharmony_ci    if (q->set_encode_ctrl_cb) {
1760cabdff1aSopenharmony_ci        q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl);
1761cabdff1aSopenharmony_ci    }
1762cabdff1aSopenharmony_ci
1763cabdff1aSopenharmony_ci    if ((avctx->codec_id == AV_CODEC_ID_H264 ||
1764cabdff1aSopenharmony_ci         avctx->codec_id == AV_CODEC_ID_H265) &&
1765cabdff1aSopenharmony_ci         enc_ctrl && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 8)) {
1766cabdff1aSopenharmony_ci        ret = set_roi_encode_ctrl(avctx, frame, enc_ctrl);
1767cabdff1aSopenharmony_ci        if (ret < 0)
1768cabdff1aSopenharmony_ci            goto free;
1769cabdff1aSopenharmony_ci    }
1770cabdff1aSopenharmony_ci
1771cabdff1aSopenharmony_ci    pkt.sync = av_mallocz(sizeof(*pkt.sync));
1772cabdff1aSopenharmony_ci    if (!pkt.sync)
1773cabdff1aSopenharmony_ci        goto nomem;
1774cabdff1aSopenharmony_ci
1775cabdff1aSopenharmony_ci    do {
1776cabdff1aSopenharmony_ci        ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, pkt.bs, pkt.sync);
1777cabdff1aSopenharmony_ci        if (ret == MFX_WRN_DEVICE_BUSY)
1778cabdff1aSopenharmony_ci            av_usleep(500);
1779cabdff1aSopenharmony_ci    } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_WRN_IN_EXECUTION);
1780cabdff1aSopenharmony_ci
1781cabdff1aSopenharmony_ci    if (ret > 0)
1782cabdff1aSopenharmony_ci        ff_qsv_print_warning(avctx, ret, "Warning during encoding");
1783cabdff1aSopenharmony_ci
1784cabdff1aSopenharmony_ci    if (ret < 0) {
1785cabdff1aSopenharmony_ci        ret = (ret == MFX_ERR_MORE_DATA) ?
1786cabdff1aSopenharmony_ci               0 : ff_qsv_print_error(avctx, ret, "Error during encoding");
1787cabdff1aSopenharmony_ci        goto free;
1788cabdff1aSopenharmony_ci    }
1789cabdff1aSopenharmony_ci
1790cabdff1aSopenharmony_ci    if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame && frame->interlaced_frame)
1791cabdff1aSopenharmony_ci        print_interlace_msg(avctx, q);
1792cabdff1aSopenharmony_ci
1793cabdff1aSopenharmony_ci    ret = 0;
1794cabdff1aSopenharmony_ci
1795cabdff1aSopenharmony_ci    if (*pkt.sync) {
1796cabdff1aSopenharmony_ci        av_fifo_write(q->async_fifo, &pkt, 1);
1797cabdff1aSopenharmony_ci    } else {
1798cabdff1aSopenharmony_cifree:
1799cabdff1aSopenharmony_ci        av_freep(&pkt.sync);
1800cabdff1aSopenharmony_ci        av_packet_unref(&pkt.pkt);
1801cabdff1aSopenharmony_ci        av_freep(&pkt.bs);
1802cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_H264) {
1803cabdff1aSopenharmony_ci            av_freep(&enc_info);
1804cabdff1aSopenharmony_ci            av_freep(&enc_buf);
1805cabdff1aSopenharmony_ci        }
1806cabdff1aSopenharmony_ci    }
1807cabdff1aSopenharmony_ci
1808cabdff1aSopenharmony_ci    return ret;
1809cabdff1aSopenharmony_cinomem:
1810cabdff1aSopenharmony_ci    ret = AVERROR(ENOMEM);
1811cabdff1aSopenharmony_ci    goto free;
1812cabdff1aSopenharmony_ci}
1813cabdff1aSopenharmony_ci
1814cabdff1aSopenharmony_ciint ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
1815cabdff1aSopenharmony_ci                  AVPacket *pkt, const AVFrame *frame, int *got_packet)
1816cabdff1aSopenharmony_ci{
1817cabdff1aSopenharmony_ci    int ret;
1818cabdff1aSopenharmony_ci
1819cabdff1aSopenharmony_ci    ret = update_parameters(avctx, q, frame);
1820cabdff1aSopenharmony_ci    if (ret < 0)
1821cabdff1aSopenharmony_ci        return ret;
1822cabdff1aSopenharmony_ci
1823cabdff1aSopenharmony_ci    ret = encode_frame(avctx, q, frame);
1824cabdff1aSopenharmony_ci    if (ret < 0)
1825cabdff1aSopenharmony_ci        return ret;
1826cabdff1aSopenharmony_ci
1827cabdff1aSopenharmony_ci    if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) ||
1828cabdff1aSopenharmony_ci        (!frame && av_fifo_can_read(q->async_fifo))) {
1829cabdff1aSopenharmony_ci        QSVPacket qpkt;
1830cabdff1aSopenharmony_ci        mfxExtAVCEncodedFrameInfo *enc_info;
1831cabdff1aSopenharmony_ci        mfxExtBuffer **enc_buf;
1832cabdff1aSopenharmony_ci        enum AVPictureType pict_type;
1833cabdff1aSopenharmony_ci
1834cabdff1aSopenharmony_ci        av_fifo_read(q->async_fifo, &qpkt, 1);
1835cabdff1aSopenharmony_ci
1836cabdff1aSopenharmony_ci        do {
1837cabdff1aSopenharmony_ci            ret = MFXVideoCORE_SyncOperation(q->session, *qpkt.sync, 1000);
1838cabdff1aSopenharmony_ci        } while (ret == MFX_WRN_IN_EXECUTION);
1839cabdff1aSopenharmony_ci
1840cabdff1aSopenharmony_ci        qpkt.pkt.dts  = av_rescale_q(qpkt.bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
1841cabdff1aSopenharmony_ci        qpkt.pkt.pts  = av_rescale_q(qpkt.bs->TimeStamp,       (AVRational){1, 90000}, avctx->time_base);
1842cabdff1aSopenharmony_ci        qpkt.pkt.size = qpkt.bs->DataLength;
1843cabdff1aSopenharmony_ci
1844cabdff1aSopenharmony_ci        if (qpkt.bs->FrameType & MFX_FRAMETYPE_IDR || qpkt.bs->FrameType & MFX_FRAMETYPE_xIDR) {
1845cabdff1aSopenharmony_ci            qpkt.pkt.flags |= AV_PKT_FLAG_KEY;
1846cabdff1aSopenharmony_ci            pict_type = AV_PICTURE_TYPE_I;
1847cabdff1aSopenharmony_ci        } else if (qpkt.bs->FrameType & MFX_FRAMETYPE_I || qpkt.bs->FrameType & MFX_FRAMETYPE_xI)
1848cabdff1aSopenharmony_ci            pict_type = AV_PICTURE_TYPE_I;
1849cabdff1aSopenharmony_ci        else if (qpkt.bs->FrameType & MFX_FRAMETYPE_P || qpkt.bs->FrameType & MFX_FRAMETYPE_xP)
1850cabdff1aSopenharmony_ci            pict_type = AV_PICTURE_TYPE_P;
1851cabdff1aSopenharmony_ci        else if (qpkt.bs->FrameType & MFX_FRAMETYPE_B || qpkt.bs->FrameType & MFX_FRAMETYPE_xB)
1852cabdff1aSopenharmony_ci            pict_type = AV_PICTURE_TYPE_B;
1853cabdff1aSopenharmony_ci        else if (qpkt.bs->FrameType == MFX_FRAMETYPE_UNKNOWN) {
1854cabdff1aSopenharmony_ci            pict_type = AV_PICTURE_TYPE_NONE;
1855cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Unknown FrameType, set pict_type to AV_PICTURE_TYPE_NONE.\n");
1856cabdff1aSopenharmony_ci        } else {
1857cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Invalid FrameType:%d.\n", qpkt.bs->FrameType);
1858cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1859cabdff1aSopenharmony_ci        }
1860cabdff1aSopenharmony_ci
1861cabdff1aSopenharmony_ci        if (avctx->codec_id == AV_CODEC_ID_H264) {
1862cabdff1aSopenharmony_ci            enc_buf = qpkt.bs->ExtParam;
1863cabdff1aSopenharmony_ci            enc_info = (mfxExtAVCEncodedFrameInfo *)(*enc_buf);
1864cabdff1aSopenharmony_ci            ff_side_data_set_encoder_stats(&qpkt.pkt,
1865cabdff1aSopenharmony_ci                enc_info->QP * FF_QP2LAMBDA, NULL, 0, pict_type);
1866cabdff1aSopenharmony_ci            av_freep(&enc_info);
1867cabdff1aSopenharmony_ci            av_freep(&enc_buf);
1868cabdff1aSopenharmony_ci        }
1869cabdff1aSopenharmony_ci        av_freep(&qpkt.bs);
1870cabdff1aSopenharmony_ci        av_freep(&qpkt.sync);
1871cabdff1aSopenharmony_ci
1872cabdff1aSopenharmony_ci        av_packet_move_ref(pkt, &qpkt.pkt);
1873cabdff1aSopenharmony_ci
1874cabdff1aSopenharmony_ci        *got_packet = 1;
1875cabdff1aSopenharmony_ci    }
1876cabdff1aSopenharmony_ci
1877cabdff1aSopenharmony_ci    return 0;
1878cabdff1aSopenharmony_ci}
1879cabdff1aSopenharmony_ci
1880cabdff1aSopenharmony_ciint ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
1881cabdff1aSopenharmony_ci{
1882cabdff1aSopenharmony_ci    QSVFrame *cur;
1883cabdff1aSopenharmony_ci
1884cabdff1aSopenharmony_ci    if (q->session)
1885cabdff1aSopenharmony_ci        MFXVideoENCODE_Close(q->session);
1886cabdff1aSopenharmony_ci
1887cabdff1aSopenharmony_ci    q->session          = NULL;
1888cabdff1aSopenharmony_ci    ff_qsv_close_internal_session(&q->internal_qs);
1889cabdff1aSopenharmony_ci
1890cabdff1aSopenharmony_ci    av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
1891cabdff1aSopenharmony_ci    av_buffer_unref(&q->frames_ctx.mids_buf);
1892cabdff1aSopenharmony_ci
1893cabdff1aSopenharmony_ci    cur = q->work_frames;
1894cabdff1aSopenharmony_ci    while (cur) {
1895cabdff1aSopenharmony_ci        q->work_frames = cur->next;
1896cabdff1aSopenharmony_ci        av_frame_free(&cur->frame);
1897cabdff1aSopenharmony_ci        free_encoder_ctrl_extparam(&cur->enc_ctrl);
1898cabdff1aSopenharmony_ci        free_encoder_ctrl_payloads(&cur->enc_ctrl);
1899cabdff1aSopenharmony_ci        av_freep(&cur);
1900cabdff1aSopenharmony_ci        cur = q->work_frames;
1901cabdff1aSopenharmony_ci    }
1902cabdff1aSopenharmony_ci
1903cabdff1aSopenharmony_ci    if (q->async_fifo) {
1904cabdff1aSopenharmony_ci        QSVPacket pkt;
1905cabdff1aSopenharmony_ci        while (av_fifo_read(q->async_fifo, &pkt, 1) >= 0) {
1906cabdff1aSopenharmony_ci            if (avctx->codec_id == AV_CODEC_ID_H264) {
1907cabdff1aSopenharmony_ci                mfxExtBuffer **enc_buf = pkt.bs->ExtParam;
1908cabdff1aSopenharmony_ci                mfxExtAVCEncodedFrameInfo *enc_info = (mfxExtAVCEncodedFrameInfo *)(*enc_buf);
1909cabdff1aSopenharmony_ci                av_freep(&enc_info);
1910cabdff1aSopenharmony_ci                av_freep(&enc_buf);
1911cabdff1aSopenharmony_ci            }
1912cabdff1aSopenharmony_ci            av_freep(&pkt.sync);
1913cabdff1aSopenharmony_ci            av_freep(&pkt.bs);
1914cabdff1aSopenharmony_ci            av_packet_unref(&pkt.pkt);
1915cabdff1aSopenharmony_ci        }
1916cabdff1aSopenharmony_ci        av_fifo_freep2(&q->async_fifo);
1917cabdff1aSopenharmony_ci    }
1918cabdff1aSopenharmony_ci
1919cabdff1aSopenharmony_ci    av_freep(&q->opaque_surfaces);
1920cabdff1aSopenharmony_ci    av_buffer_unref(&q->opaque_alloc_buf);
1921cabdff1aSopenharmony_ci
1922cabdff1aSopenharmony_ci    av_freep(&q->extparam);
1923cabdff1aSopenharmony_ci
1924cabdff1aSopenharmony_ci    return 0;
1925cabdff1aSopenharmony_ci}
1926cabdff1aSopenharmony_ci
1927cabdff1aSopenharmony_ciconst AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[] = {
1928cabdff1aSopenharmony_ci    HW_CONFIG_ENCODER_FRAMES(QSV,  QSV),
1929cabdff1aSopenharmony_ci    HW_CONFIG_ENCODER_DEVICE(NV12, QSV),
1930cabdff1aSopenharmony_ci    HW_CONFIG_ENCODER_DEVICE(P010, QSV),
1931cabdff1aSopenharmony_ci    NULL,
1932cabdff1aSopenharmony_ci};
1933