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, ¶m_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