1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <string.h> 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <va/va.h> 22cabdff1aSopenharmony_ci#include <va/va_enc_hevc.h> 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 25cabdff1aSopenharmony_ci#include "libavutil/common.h" 26cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 27cabdff1aSopenharmony_ci#include "libavutil/opt.h" 28cabdff1aSopenharmony_ci#include "libavutil/mastering_display_metadata.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "avcodec.h" 31cabdff1aSopenharmony_ci#include "cbs.h" 32cabdff1aSopenharmony_ci#include "cbs_h265.h" 33cabdff1aSopenharmony_ci#include "codec_internal.h" 34cabdff1aSopenharmony_ci#include "h265_profile_level.h" 35cabdff1aSopenharmony_ci#include "hevc.h" 36cabdff1aSopenharmony_ci#include "hevc_sei.h" 37cabdff1aSopenharmony_ci#include "put_bits.h" 38cabdff1aSopenharmony_ci#include "vaapi_encode.h" 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cienum { 41cabdff1aSopenharmony_ci SEI_MASTERING_DISPLAY = 0x08, 42cabdff1aSopenharmony_ci SEI_CONTENT_LIGHT_LEVEL = 0x10, 43cabdff1aSopenharmony_ci}; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_citypedef struct VAAPIEncodeH265Picture { 46cabdff1aSopenharmony_ci int pic_order_cnt; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci int64_t last_idr_frame; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci int slice_nal_unit; 51cabdff1aSopenharmony_ci int slice_type; 52cabdff1aSopenharmony_ci int pic_type; 53cabdff1aSopenharmony_ci} VAAPIEncodeH265Picture; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_citypedef struct VAAPIEncodeH265Context { 56cabdff1aSopenharmony_ci VAAPIEncodeContext common; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci // Encoder features. 59cabdff1aSopenharmony_ci uint32_t va_features; 60cabdff1aSopenharmony_ci // Block size info. 61cabdff1aSopenharmony_ci uint32_t va_bs; 62cabdff1aSopenharmony_ci uint32_t ctu_size; 63cabdff1aSopenharmony_ci uint32_t min_cb_size; 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci // User options. 66cabdff1aSopenharmony_ci int qp; 67cabdff1aSopenharmony_ci int aud; 68cabdff1aSopenharmony_ci int profile; 69cabdff1aSopenharmony_ci int tier; 70cabdff1aSopenharmony_ci int level; 71cabdff1aSopenharmony_ci int sei; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci // Derived settings. 74cabdff1aSopenharmony_ci int fixed_qp_idr; 75cabdff1aSopenharmony_ci int fixed_qp_p; 76cabdff1aSopenharmony_ci int fixed_qp_b; 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci // Writer structures. 79cabdff1aSopenharmony_ci H265RawAUD raw_aud; 80cabdff1aSopenharmony_ci H265RawVPS raw_vps; 81cabdff1aSopenharmony_ci H265RawSPS raw_sps; 82cabdff1aSopenharmony_ci H265RawPPS raw_pps; 83cabdff1aSopenharmony_ci H265RawSlice raw_slice; 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci SEIRawMasteringDisplayColourVolume sei_mastering_display; 86cabdff1aSopenharmony_ci SEIRawContentLightLevelInfo sei_content_light_level; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci CodedBitstreamContext *cbc; 89cabdff1aSopenharmony_ci CodedBitstreamFragment current_access_unit; 90cabdff1aSopenharmony_ci int aud_needed; 91cabdff1aSopenharmony_ci int sei_needed; 92cabdff1aSopenharmony_ci} VAAPIEncodeH265Context; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_cistatic int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, 96cabdff1aSopenharmony_ci char *data, size_t *data_len, 97cabdff1aSopenharmony_ci CodedBitstreamFragment *au) 98cabdff1aSopenharmony_ci{ 99cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 100cabdff1aSopenharmony_ci int err; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci err = ff_cbs_write_fragment_data(priv->cbc, au); 103cabdff1aSopenharmony_ci if (err < 0) { 104cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); 105cabdff1aSopenharmony_ci return err; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci if (*data_len < 8 * au->data_size - au->data_bit_padding) { 109cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Access unit too large: " 110cabdff1aSopenharmony_ci "%zu < %zu.\n", *data_len, 111cabdff1aSopenharmony_ci 8 * au->data_size - au->data_bit_padding); 112cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci memcpy(data, au->data, au->data_size); 116cabdff1aSopenharmony_ci *data_len = 8 * au->data_size - au->data_bit_padding; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci return 0; 119cabdff1aSopenharmony_ci} 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_cistatic int vaapi_encode_h265_add_nal(AVCodecContext *avctx, 122cabdff1aSopenharmony_ci CodedBitstreamFragment *au, 123cabdff1aSopenharmony_ci void *nal_unit) 124cabdff1aSopenharmony_ci{ 125cabdff1aSopenharmony_ci H265RawNALUnitHeader *header = nal_unit; 126cabdff1aSopenharmony_ci int err; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci err = ff_cbs_insert_unit_content(au, -1, 129cabdff1aSopenharmony_ci header->nal_unit_type, nal_unit, NULL); 130cabdff1aSopenharmony_ci if (err < 0) { 131cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " 132cabdff1aSopenharmony_ci "type = %d.\n", header->nal_unit_type); 133cabdff1aSopenharmony_ci return err; 134cabdff1aSopenharmony_ci } 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci return 0; 137cabdff1aSopenharmony_ci} 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_cistatic int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, 140cabdff1aSopenharmony_ci char *data, size_t *data_len) 141cabdff1aSopenharmony_ci{ 142cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 143cabdff1aSopenharmony_ci CodedBitstreamFragment *au = &priv->current_access_unit; 144cabdff1aSopenharmony_ci int err; 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci if (priv->aud_needed) { 147cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_aud); 148cabdff1aSopenharmony_ci if (err < 0) 149cabdff1aSopenharmony_ci goto fail; 150cabdff1aSopenharmony_ci priv->aud_needed = 0; 151cabdff1aSopenharmony_ci } 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_vps); 154cabdff1aSopenharmony_ci if (err < 0) 155cabdff1aSopenharmony_ci goto fail; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_sps); 158cabdff1aSopenharmony_ci if (err < 0) 159cabdff1aSopenharmony_ci goto fail; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_pps); 162cabdff1aSopenharmony_ci if (err < 0) 163cabdff1aSopenharmony_ci goto fail; 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); 166cabdff1aSopenharmony_cifail: 167cabdff1aSopenharmony_ci ff_cbs_fragment_reset(au); 168cabdff1aSopenharmony_ci return err; 169cabdff1aSopenharmony_ci} 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_cistatic int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, 172cabdff1aSopenharmony_ci VAAPIEncodePicture *pic, 173cabdff1aSopenharmony_ci VAAPIEncodeSlice *slice, 174cabdff1aSopenharmony_ci char *data, size_t *data_len) 175cabdff1aSopenharmony_ci{ 176cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 177cabdff1aSopenharmony_ci CodedBitstreamFragment *au = &priv->current_access_unit; 178cabdff1aSopenharmony_ci int err; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci if (priv->aud_needed) { 181cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_aud); 182cabdff1aSopenharmony_ci if (err < 0) 183cabdff1aSopenharmony_ci goto fail; 184cabdff1aSopenharmony_ci priv->aud_needed = 0; 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_slice); 188cabdff1aSopenharmony_ci if (err < 0) 189cabdff1aSopenharmony_ci goto fail; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); 192cabdff1aSopenharmony_cifail: 193cabdff1aSopenharmony_ci ff_cbs_fragment_reset(au); 194cabdff1aSopenharmony_ci return err; 195cabdff1aSopenharmony_ci} 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_cistatic int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx, 198cabdff1aSopenharmony_ci VAAPIEncodePicture *pic, 199cabdff1aSopenharmony_ci int index, int *type, 200cabdff1aSopenharmony_ci char *data, size_t *data_len) 201cabdff1aSopenharmony_ci{ 202cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 203cabdff1aSopenharmony_ci CodedBitstreamFragment *au = &priv->current_access_unit; 204cabdff1aSopenharmony_ci int err; 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci if (priv->sei_needed) { 207cabdff1aSopenharmony_ci if (priv->aud_needed) { 208cabdff1aSopenharmony_ci err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); 209cabdff1aSopenharmony_ci if (err < 0) 210cabdff1aSopenharmony_ci goto fail; 211cabdff1aSopenharmony_ci priv->aud_needed = 0; 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci if (priv->sei_needed & SEI_MASTERING_DISPLAY) { 215cabdff1aSopenharmony_ci err = ff_cbs_sei_add_message(priv->cbc, au, 1, 216cabdff1aSopenharmony_ci SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME, 217cabdff1aSopenharmony_ci &priv->sei_mastering_display, NULL); 218cabdff1aSopenharmony_ci if (err < 0) 219cabdff1aSopenharmony_ci goto fail; 220cabdff1aSopenharmony_ci } 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci if (priv->sei_needed & SEI_CONTENT_LIGHT_LEVEL) { 223cabdff1aSopenharmony_ci err = ff_cbs_sei_add_message(priv->cbc, au, 1, 224cabdff1aSopenharmony_ci SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO, 225cabdff1aSopenharmony_ci &priv->sei_content_light_level, NULL); 226cabdff1aSopenharmony_ci if (err < 0) 227cabdff1aSopenharmony_ci goto fail; 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci priv->sei_needed = 0; 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); 233cabdff1aSopenharmony_ci if (err < 0) 234cabdff1aSopenharmony_ci goto fail; 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci ff_cbs_fragment_reset(au); 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci *type = VAEncPackedHeaderRawData; 239cabdff1aSopenharmony_ci return 0; 240cabdff1aSopenharmony_ci } else { 241cabdff1aSopenharmony_ci return AVERROR_EOF; 242cabdff1aSopenharmony_ci } 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_cifail: 245cabdff1aSopenharmony_ci ff_cbs_fragment_reset(au); 246cabdff1aSopenharmony_ci return err; 247cabdff1aSopenharmony_ci} 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_cistatic int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) 250cabdff1aSopenharmony_ci{ 251cabdff1aSopenharmony_ci VAAPIEncodeContext *ctx = avctx->priv_data; 252cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 253cabdff1aSopenharmony_ci H265RawVPS *vps = &priv->raw_vps; 254cabdff1aSopenharmony_ci H265RawSPS *sps = &priv->raw_sps; 255cabdff1aSopenharmony_ci H265RawPPS *pps = &priv->raw_pps; 256cabdff1aSopenharmony_ci H265RawProfileTierLevel *ptl = &vps->profile_tier_level; 257cabdff1aSopenharmony_ci H265RawVUI *vui = &sps->vui; 258cabdff1aSopenharmony_ci VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; 259cabdff1aSopenharmony_ci VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; 260cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc; 261cabdff1aSopenharmony_ci int chroma_format, bit_depth; 262cabdff1aSopenharmony_ci int i; 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci memset(vps, 0, sizeof(*vps)); 265cabdff1aSopenharmony_ci memset(sps, 0, sizeof(*sps)); 266cabdff1aSopenharmony_ci memset(pps, 0, sizeof(*pps)); 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format); 270cabdff1aSopenharmony_ci av_assert0(desc); 271cabdff1aSopenharmony_ci if (desc->nb_components == 1) { 272cabdff1aSopenharmony_ci chroma_format = 0; 273cabdff1aSopenharmony_ci } else { 274cabdff1aSopenharmony_ci if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) { 275cabdff1aSopenharmony_ci chroma_format = 1; 276cabdff1aSopenharmony_ci } else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 0) { 277cabdff1aSopenharmony_ci chroma_format = 2; 278cabdff1aSopenharmony_ci } else if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) { 279cabdff1aSopenharmony_ci chroma_format = 3; 280cabdff1aSopenharmony_ci } else { 281cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Chroma format of input pixel format " 282cabdff1aSopenharmony_ci "%s is not supported.\n", desc->name); 283cabdff1aSopenharmony_ci return AVERROR(EINVAL); 284cabdff1aSopenharmony_ci } 285cabdff1aSopenharmony_ci } 286cabdff1aSopenharmony_ci bit_depth = desc->comp[0].depth; 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci // VPS 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci vps->nal_unit_header = (H265RawNALUnitHeader) { 292cabdff1aSopenharmony_ci .nal_unit_type = HEVC_NAL_VPS, 293cabdff1aSopenharmony_ci .nuh_layer_id = 0, 294cabdff1aSopenharmony_ci .nuh_temporal_id_plus1 = 1, 295cabdff1aSopenharmony_ci }; 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci vps->vps_video_parameter_set_id = 0; 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci vps->vps_base_layer_internal_flag = 1; 300cabdff1aSopenharmony_ci vps->vps_base_layer_available_flag = 1; 301cabdff1aSopenharmony_ci vps->vps_max_layers_minus1 = 0; 302cabdff1aSopenharmony_ci vps->vps_max_sub_layers_minus1 = 0; 303cabdff1aSopenharmony_ci vps->vps_temporal_id_nesting_flag = 1; 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci ptl->general_profile_space = 0; 306cabdff1aSopenharmony_ci ptl->general_profile_idc = avctx->profile; 307cabdff1aSopenharmony_ci ptl->general_tier_flag = priv->tier; 308cabdff1aSopenharmony_ci 309cabdff1aSopenharmony_ci ptl->general_profile_compatibility_flag[ptl->general_profile_idc] = 1; 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci if (ptl->general_profile_compatibility_flag[1]) 312cabdff1aSopenharmony_ci ptl->general_profile_compatibility_flag[2] = 1; 313cabdff1aSopenharmony_ci if (ptl->general_profile_compatibility_flag[3]) { 314cabdff1aSopenharmony_ci ptl->general_profile_compatibility_flag[1] = 1; 315cabdff1aSopenharmony_ci ptl->general_profile_compatibility_flag[2] = 1; 316cabdff1aSopenharmony_ci } 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci ptl->general_progressive_source_flag = 1; 319cabdff1aSopenharmony_ci ptl->general_interlaced_source_flag = 0; 320cabdff1aSopenharmony_ci ptl->general_non_packed_constraint_flag = 1; 321cabdff1aSopenharmony_ci ptl->general_frame_only_constraint_flag = 1; 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci ptl->general_max_14bit_constraint_flag = bit_depth <= 14; 324cabdff1aSopenharmony_ci ptl->general_max_12bit_constraint_flag = bit_depth <= 12; 325cabdff1aSopenharmony_ci ptl->general_max_10bit_constraint_flag = bit_depth <= 10; 326cabdff1aSopenharmony_ci ptl->general_max_8bit_constraint_flag = bit_depth == 8; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci ptl->general_max_422chroma_constraint_flag = chroma_format <= 2; 329cabdff1aSopenharmony_ci ptl->general_max_420chroma_constraint_flag = chroma_format <= 1; 330cabdff1aSopenharmony_ci ptl->general_max_monochrome_constraint_flag = chroma_format == 0; 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci ptl->general_intra_constraint_flag = ctx->gop_size == 1; 333cabdff1aSopenharmony_ci ptl->general_one_picture_only_constraint_flag = 0; 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci ptl->general_lower_bit_rate_constraint_flag = 1; 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci if (avctx->level != FF_LEVEL_UNKNOWN) { 338cabdff1aSopenharmony_ci ptl->general_level_idc = avctx->level; 339cabdff1aSopenharmony_ci } else { 340cabdff1aSopenharmony_ci const H265LevelDescriptor *level; 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci level = ff_h265_guess_level(ptl, avctx->bit_rate, 343cabdff1aSopenharmony_ci ctx->surface_width, ctx->surface_height, 344cabdff1aSopenharmony_ci ctx->nb_slices, ctx->tile_rows, ctx->tile_cols, 345cabdff1aSopenharmony_ci (ctx->b_per_p > 0) + 1); 346cabdff1aSopenharmony_ci if (level) { 347cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); 348cabdff1aSopenharmony_ci ptl->general_level_idc = level->level_idc; 349cabdff1aSopenharmony_ci } else { 350cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to " 351cabdff1aSopenharmony_ci "any normal level; using level 8.5.\n"); 352cabdff1aSopenharmony_ci ptl->general_level_idc = 255; 353cabdff1aSopenharmony_ci // The tier flag must be set in level 8.5. 354cabdff1aSopenharmony_ci ptl->general_tier_flag = 1; 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci vps->vps_sub_layer_ordering_info_present_flag = 0; 359cabdff1aSopenharmony_ci vps->vps_max_dec_pic_buffering_minus1[0] = ctx->max_b_depth + 1; 360cabdff1aSopenharmony_ci vps->vps_max_num_reorder_pics[0] = ctx->max_b_depth; 361cabdff1aSopenharmony_ci vps->vps_max_latency_increase_plus1[0] = 0; 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ci vps->vps_max_layer_id = 0; 364cabdff1aSopenharmony_ci vps->vps_num_layer_sets_minus1 = 0; 365cabdff1aSopenharmony_ci vps->layer_id_included_flag[0][0] = 1; 366cabdff1aSopenharmony_ci 367cabdff1aSopenharmony_ci vps->vps_timing_info_present_flag = 1; 368cabdff1aSopenharmony_ci if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { 369cabdff1aSopenharmony_ci vps->vps_num_units_in_tick = avctx->framerate.den; 370cabdff1aSopenharmony_ci vps->vps_time_scale = avctx->framerate.num; 371cabdff1aSopenharmony_ci vps->vps_poc_proportional_to_timing_flag = 1; 372cabdff1aSopenharmony_ci vps->vps_num_ticks_poc_diff_one_minus1 = 0; 373cabdff1aSopenharmony_ci } else { 374cabdff1aSopenharmony_ci vps->vps_num_units_in_tick = avctx->time_base.num; 375cabdff1aSopenharmony_ci vps->vps_time_scale = avctx->time_base.den; 376cabdff1aSopenharmony_ci vps->vps_poc_proportional_to_timing_flag = 0; 377cabdff1aSopenharmony_ci } 378cabdff1aSopenharmony_ci vps->vps_num_hrd_parameters = 0; 379cabdff1aSopenharmony_ci 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_ci // SPS 382cabdff1aSopenharmony_ci 383cabdff1aSopenharmony_ci sps->nal_unit_header = (H265RawNALUnitHeader) { 384cabdff1aSopenharmony_ci .nal_unit_type = HEVC_NAL_SPS, 385cabdff1aSopenharmony_ci .nuh_layer_id = 0, 386cabdff1aSopenharmony_ci .nuh_temporal_id_plus1 = 1, 387cabdff1aSopenharmony_ci }; 388cabdff1aSopenharmony_ci 389cabdff1aSopenharmony_ci sps->sps_video_parameter_set_id = vps->vps_video_parameter_set_id; 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_ci sps->sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1; 392cabdff1aSopenharmony_ci sps->sps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag; 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci sps->profile_tier_level = vps->profile_tier_level; 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci sps->sps_seq_parameter_set_id = 0; 397cabdff1aSopenharmony_ci 398cabdff1aSopenharmony_ci sps->chroma_format_idc = chroma_format; 399cabdff1aSopenharmony_ci sps->separate_colour_plane_flag = 0; 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci sps->pic_width_in_luma_samples = ctx->surface_width; 402cabdff1aSopenharmony_ci sps->pic_height_in_luma_samples = ctx->surface_height; 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci if (avctx->width != ctx->surface_width || 405cabdff1aSopenharmony_ci avctx->height != ctx->surface_height) { 406cabdff1aSopenharmony_ci sps->conformance_window_flag = 1; 407cabdff1aSopenharmony_ci sps->conf_win_left_offset = 0; 408cabdff1aSopenharmony_ci sps->conf_win_right_offset = 409cabdff1aSopenharmony_ci (ctx->surface_width - avctx->width) >> desc->log2_chroma_w; 410cabdff1aSopenharmony_ci sps->conf_win_top_offset = 0; 411cabdff1aSopenharmony_ci sps->conf_win_bottom_offset = 412cabdff1aSopenharmony_ci (ctx->surface_height - avctx->height) >> desc->log2_chroma_h; 413cabdff1aSopenharmony_ci } else { 414cabdff1aSopenharmony_ci sps->conformance_window_flag = 0; 415cabdff1aSopenharmony_ci } 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci sps->bit_depth_luma_minus8 = bit_depth - 8; 418cabdff1aSopenharmony_ci sps->bit_depth_chroma_minus8 = bit_depth - 8; 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci sps->log2_max_pic_order_cnt_lsb_minus4 = 8; 421cabdff1aSopenharmony_ci 422cabdff1aSopenharmony_ci sps->sps_sub_layer_ordering_info_present_flag = 423cabdff1aSopenharmony_ci vps->vps_sub_layer_ordering_info_present_flag; 424cabdff1aSopenharmony_ci for (i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { 425cabdff1aSopenharmony_ci sps->sps_max_dec_pic_buffering_minus1[i] = 426cabdff1aSopenharmony_ci vps->vps_max_dec_pic_buffering_minus1[i]; 427cabdff1aSopenharmony_ci sps->sps_max_num_reorder_pics[i] = 428cabdff1aSopenharmony_ci vps->vps_max_num_reorder_pics[i]; 429cabdff1aSopenharmony_ci sps->sps_max_latency_increase_plus1[i] = 430cabdff1aSopenharmony_ci vps->vps_max_latency_increase_plus1[i]; 431cabdff1aSopenharmony_ci } 432cabdff1aSopenharmony_ci 433cabdff1aSopenharmony_ci // These values come from the capabilities of the first encoder 434cabdff1aSopenharmony_ci // implementation in the i965 driver on Intel Skylake. They may 435cabdff1aSopenharmony_ci // fail badly with other platforms or drivers. 436cabdff1aSopenharmony_ci // CTB size from 8x8 to 32x32. 437cabdff1aSopenharmony_ci sps->log2_min_luma_coding_block_size_minus3 = 0; 438cabdff1aSopenharmony_ci sps->log2_diff_max_min_luma_coding_block_size = 2; 439cabdff1aSopenharmony_ci // Transform size from 4x4 to 32x32. 440cabdff1aSopenharmony_ci sps->log2_min_luma_transform_block_size_minus2 = 0; 441cabdff1aSopenharmony_ci sps->log2_diff_max_min_luma_transform_block_size = 3; 442cabdff1aSopenharmony_ci // Full transform hierarchy allowed (2-5). 443cabdff1aSopenharmony_ci sps->max_transform_hierarchy_depth_inter = 3; 444cabdff1aSopenharmony_ci sps->max_transform_hierarchy_depth_intra = 3; 445cabdff1aSopenharmony_ci // AMP works. 446cabdff1aSopenharmony_ci sps->amp_enabled_flag = 1; 447cabdff1aSopenharmony_ci // SAO and temporal MVP do not work. 448cabdff1aSopenharmony_ci sps->sample_adaptive_offset_enabled_flag = 0; 449cabdff1aSopenharmony_ci sps->sps_temporal_mvp_enabled_flag = 0; 450cabdff1aSopenharmony_ci 451cabdff1aSopenharmony_ci sps->pcm_enabled_flag = 0; 452cabdff1aSopenharmony_ci 453cabdff1aSopenharmony_ci// update sps setting according to queried result 454cabdff1aSopenharmony_ci#if VA_CHECK_VERSION(1, 13, 0) 455cabdff1aSopenharmony_ci if (priv->va_features) { 456cabdff1aSopenharmony_ci VAConfigAttribValEncHEVCFeatures features = { .value = priv->va_features }; 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci // Enable feature if get queried result is VA_FEATURE_SUPPORTED | VA_FEATURE_REQUIRED 459cabdff1aSopenharmony_ci sps->amp_enabled_flag = 460cabdff1aSopenharmony_ci !!features.bits.amp; 461cabdff1aSopenharmony_ci sps->sample_adaptive_offset_enabled_flag = 462cabdff1aSopenharmony_ci !!features.bits.sao; 463cabdff1aSopenharmony_ci sps->sps_temporal_mvp_enabled_flag = 464cabdff1aSopenharmony_ci !!features.bits.temporal_mvp; 465cabdff1aSopenharmony_ci sps->pcm_enabled_flag = 466cabdff1aSopenharmony_ci !!features.bits.pcm; 467cabdff1aSopenharmony_ci } 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci if (priv->va_bs) { 470cabdff1aSopenharmony_ci VAConfigAttribValEncHEVCBlockSizes bs = { .value = priv->va_bs }; 471cabdff1aSopenharmony_ci sps->log2_min_luma_coding_block_size_minus3 = 472cabdff1aSopenharmony_ci ff_ctz(priv->min_cb_size) - 3; 473cabdff1aSopenharmony_ci sps->log2_diff_max_min_luma_coding_block_size = 474cabdff1aSopenharmony_ci ff_ctz(priv->ctu_size) - ff_ctz(priv->min_cb_size); 475cabdff1aSopenharmony_ci 476cabdff1aSopenharmony_ci sps->log2_min_luma_transform_block_size_minus2 = 477cabdff1aSopenharmony_ci bs.bits.log2_min_luma_transform_block_size_minus2; 478cabdff1aSopenharmony_ci sps->log2_diff_max_min_luma_transform_block_size = 479cabdff1aSopenharmony_ci bs.bits.log2_max_luma_transform_block_size_minus2 - 480cabdff1aSopenharmony_ci bs.bits.log2_min_luma_transform_block_size_minus2; 481cabdff1aSopenharmony_ci 482cabdff1aSopenharmony_ci sps->max_transform_hierarchy_depth_inter = 483cabdff1aSopenharmony_ci bs.bits.max_max_transform_hierarchy_depth_inter; 484cabdff1aSopenharmony_ci sps->max_transform_hierarchy_depth_intra = 485cabdff1aSopenharmony_ci bs.bits.max_max_transform_hierarchy_depth_intra; 486cabdff1aSopenharmony_ci } 487cabdff1aSopenharmony_ci#endif 488cabdff1aSopenharmony_ci 489cabdff1aSopenharmony_ci // STRPSs should ideally be here rather than defined individually in 490cabdff1aSopenharmony_ci // each slice, but the structure isn't completely fixed so for now 491cabdff1aSopenharmony_ci // don't bother. 492cabdff1aSopenharmony_ci sps->num_short_term_ref_pic_sets = 0; 493cabdff1aSopenharmony_ci sps->long_term_ref_pics_present_flag = 0; 494cabdff1aSopenharmony_ci 495cabdff1aSopenharmony_ci sps->vui_parameters_present_flag = 1; 496cabdff1aSopenharmony_ci 497cabdff1aSopenharmony_ci if (avctx->sample_aspect_ratio.num != 0 && 498cabdff1aSopenharmony_ci avctx->sample_aspect_ratio.den != 0) { 499cabdff1aSopenharmony_ci static const AVRational sar_idc[] = { 500cabdff1aSopenharmony_ci { 0, 0 }, 501cabdff1aSopenharmony_ci { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, 502cabdff1aSopenharmony_ci { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, 503cabdff1aSopenharmony_ci { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, 504cabdff1aSopenharmony_ci { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, 505cabdff1aSopenharmony_ci }; 506cabdff1aSopenharmony_ci int num, den, i; 507cabdff1aSopenharmony_ci av_reduce(&num, &den, avctx->sample_aspect_ratio.num, 508cabdff1aSopenharmony_ci avctx->sample_aspect_ratio.den, 65535); 509cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) { 510cabdff1aSopenharmony_ci if (num == sar_idc[i].num && 511cabdff1aSopenharmony_ci den == sar_idc[i].den) { 512cabdff1aSopenharmony_ci vui->aspect_ratio_idc = i; 513cabdff1aSopenharmony_ci break; 514cabdff1aSopenharmony_ci } 515cabdff1aSopenharmony_ci } 516cabdff1aSopenharmony_ci if (i >= FF_ARRAY_ELEMS(sar_idc)) { 517cabdff1aSopenharmony_ci vui->aspect_ratio_idc = 255; 518cabdff1aSopenharmony_ci vui->sar_width = num; 519cabdff1aSopenharmony_ci vui->sar_height = den; 520cabdff1aSopenharmony_ci } 521cabdff1aSopenharmony_ci vui->aspect_ratio_info_present_flag = 1; 522cabdff1aSopenharmony_ci } 523cabdff1aSopenharmony_ci 524cabdff1aSopenharmony_ci // Unspecified video format, from table E-2. 525cabdff1aSopenharmony_ci vui->video_format = 5; 526cabdff1aSopenharmony_ci vui->video_full_range_flag = 527cabdff1aSopenharmony_ci avctx->color_range == AVCOL_RANGE_JPEG; 528cabdff1aSopenharmony_ci vui->colour_primaries = avctx->color_primaries; 529cabdff1aSopenharmony_ci vui->transfer_characteristics = avctx->color_trc; 530cabdff1aSopenharmony_ci vui->matrix_coefficients = avctx->colorspace; 531cabdff1aSopenharmony_ci if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || 532cabdff1aSopenharmony_ci avctx->color_trc != AVCOL_TRC_UNSPECIFIED || 533cabdff1aSopenharmony_ci avctx->colorspace != AVCOL_SPC_UNSPECIFIED) 534cabdff1aSopenharmony_ci vui->colour_description_present_flag = 1; 535cabdff1aSopenharmony_ci if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || 536cabdff1aSopenharmony_ci vui->colour_description_present_flag) 537cabdff1aSopenharmony_ci vui->video_signal_type_present_flag = 1; 538cabdff1aSopenharmony_ci 539cabdff1aSopenharmony_ci if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { 540cabdff1aSopenharmony_ci vui->chroma_loc_info_present_flag = 1; 541cabdff1aSopenharmony_ci vui->chroma_sample_loc_type_top_field = 542cabdff1aSopenharmony_ci vui->chroma_sample_loc_type_bottom_field = 543cabdff1aSopenharmony_ci avctx->chroma_sample_location - 1; 544cabdff1aSopenharmony_ci } 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci vui->vui_timing_info_present_flag = 1; 547cabdff1aSopenharmony_ci vui->vui_num_units_in_tick = vps->vps_num_units_in_tick; 548cabdff1aSopenharmony_ci vui->vui_time_scale = vps->vps_time_scale; 549cabdff1aSopenharmony_ci vui->vui_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag; 550cabdff1aSopenharmony_ci vui->vui_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1; 551cabdff1aSopenharmony_ci vui->vui_hrd_parameters_present_flag = 0; 552cabdff1aSopenharmony_ci 553cabdff1aSopenharmony_ci vui->bitstream_restriction_flag = 1; 554cabdff1aSopenharmony_ci vui->motion_vectors_over_pic_boundaries_flag = 1; 555cabdff1aSopenharmony_ci vui->restricted_ref_pic_lists_flag = 1; 556cabdff1aSopenharmony_ci vui->max_bytes_per_pic_denom = 0; 557cabdff1aSopenharmony_ci vui->max_bits_per_min_cu_denom = 0; 558cabdff1aSopenharmony_ci vui->log2_max_mv_length_horizontal = 15; 559cabdff1aSopenharmony_ci vui->log2_max_mv_length_vertical = 15; 560cabdff1aSopenharmony_ci 561cabdff1aSopenharmony_ci 562cabdff1aSopenharmony_ci // PPS 563cabdff1aSopenharmony_ci 564cabdff1aSopenharmony_ci pps->nal_unit_header = (H265RawNALUnitHeader) { 565cabdff1aSopenharmony_ci .nal_unit_type = HEVC_NAL_PPS, 566cabdff1aSopenharmony_ci .nuh_layer_id = 0, 567cabdff1aSopenharmony_ci .nuh_temporal_id_plus1 = 1, 568cabdff1aSopenharmony_ci }; 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_ci pps->pps_pic_parameter_set_id = 0; 571cabdff1aSopenharmony_ci pps->pps_seq_parameter_set_id = sps->sps_seq_parameter_set_id; 572cabdff1aSopenharmony_ci 573cabdff1aSopenharmony_ci pps->num_ref_idx_l0_default_active_minus1 = 0; 574cabdff1aSopenharmony_ci pps->num_ref_idx_l1_default_active_minus1 = 0; 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_ci pps->init_qp_minus26 = priv->fixed_qp_idr - 26; 577cabdff1aSopenharmony_ci 578cabdff1aSopenharmony_ci pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP); 579cabdff1aSopenharmony_ci pps->diff_cu_qp_delta_depth = 0; 580cabdff1aSopenharmony_ci 581cabdff1aSopenharmony_ci// update pps setting according to queried result 582cabdff1aSopenharmony_ci#if VA_CHECK_VERSION(1, 13, 0) 583cabdff1aSopenharmony_ci if (priv->va_features) { 584cabdff1aSopenharmony_ci VAConfigAttribValEncHEVCFeatures features = { .value = priv->va_features }; 585cabdff1aSopenharmony_ci if (ctx->va_rc_mode != VA_RC_CQP) 586cabdff1aSopenharmony_ci pps->cu_qp_delta_enabled_flag = 587cabdff1aSopenharmony_ci !!features.bits.cu_qp_delta; 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_ci pps->transform_skip_enabled_flag = 590cabdff1aSopenharmony_ci !!features.bits.transform_skip; 591cabdff1aSopenharmony_ci // set diff_cu_qp_delta_depth as its max value if cu_qp_delta enabled. Otherwise 592cabdff1aSopenharmony_ci // 0 will make cu_qp_delta invalid. 593cabdff1aSopenharmony_ci if (pps->cu_qp_delta_enabled_flag) 594cabdff1aSopenharmony_ci pps->diff_cu_qp_delta_depth = sps->log2_diff_max_min_luma_coding_block_size; 595cabdff1aSopenharmony_ci } 596cabdff1aSopenharmony_ci#endif 597cabdff1aSopenharmony_ci 598cabdff1aSopenharmony_ci if (ctx->tile_rows && ctx->tile_cols) { 599cabdff1aSopenharmony_ci int uniform_spacing; 600cabdff1aSopenharmony_ci 601cabdff1aSopenharmony_ci pps->tiles_enabled_flag = 1; 602cabdff1aSopenharmony_ci pps->num_tile_columns_minus1 = ctx->tile_cols - 1; 603cabdff1aSopenharmony_ci pps->num_tile_rows_minus1 = ctx->tile_rows - 1; 604cabdff1aSopenharmony_ci 605cabdff1aSopenharmony_ci // Test whether the spacing provided matches the H.265 uniform 606cabdff1aSopenharmony_ci // spacing, and set the flag if it does. 607cabdff1aSopenharmony_ci uniform_spacing = 1; 608cabdff1aSopenharmony_ci for (i = 0; i <= pps->num_tile_columns_minus1 && 609cabdff1aSopenharmony_ci uniform_spacing; i++) { 610cabdff1aSopenharmony_ci if (ctx->col_width[i] != 611cabdff1aSopenharmony_ci (i + 1) * ctx->slice_block_cols / ctx->tile_cols - 612cabdff1aSopenharmony_ci i * ctx->slice_block_cols / ctx->tile_cols) 613cabdff1aSopenharmony_ci uniform_spacing = 0; 614cabdff1aSopenharmony_ci } 615cabdff1aSopenharmony_ci for (i = 0; i <= pps->num_tile_rows_minus1 && 616cabdff1aSopenharmony_ci uniform_spacing; i++) { 617cabdff1aSopenharmony_ci if (ctx->row_height[i] != 618cabdff1aSopenharmony_ci (i + 1) * ctx->slice_block_rows / ctx->tile_rows - 619cabdff1aSopenharmony_ci i * ctx->slice_block_rows / ctx->tile_rows) 620cabdff1aSopenharmony_ci uniform_spacing = 0; 621cabdff1aSopenharmony_ci } 622cabdff1aSopenharmony_ci pps->uniform_spacing_flag = uniform_spacing; 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci for (i = 0; i <= pps->num_tile_columns_minus1; i++) 625cabdff1aSopenharmony_ci pps->column_width_minus1[i] = ctx->col_width[i] - 1; 626cabdff1aSopenharmony_ci for (i = 0; i <= pps->num_tile_rows_minus1; i++) 627cabdff1aSopenharmony_ci pps->row_height_minus1[i] = ctx->row_height[i] - 1; 628cabdff1aSopenharmony_ci 629cabdff1aSopenharmony_ci pps->loop_filter_across_tiles_enabled_flag = 1; 630cabdff1aSopenharmony_ci } 631cabdff1aSopenharmony_ci 632cabdff1aSopenharmony_ci pps->pps_loop_filter_across_slices_enabled_flag = 1; 633cabdff1aSopenharmony_ci 634cabdff1aSopenharmony_ci // Fill VAAPI parameter buffers. 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_ci *vseq = (VAEncSequenceParameterBufferHEVC) { 637cabdff1aSopenharmony_ci .general_profile_idc = vps->profile_tier_level.general_profile_idc, 638cabdff1aSopenharmony_ci .general_level_idc = vps->profile_tier_level.general_level_idc, 639cabdff1aSopenharmony_ci .general_tier_flag = vps->profile_tier_level.general_tier_flag, 640cabdff1aSopenharmony_ci 641cabdff1aSopenharmony_ci .intra_period = ctx->gop_size, 642cabdff1aSopenharmony_ci .intra_idr_period = ctx->gop_size, 643cabdff1aSopenharmony_ci .ip_period = ctx->b_per_p + 1, 644cabdff1aSopenharmony_ci .bits_per_second = ctx->va_bit_rate, 645cabdff1aSopenharmony_ci 646cabdff1aSopenharmony_ci .pic_width_in_luma_samples = sps->pic_width_in_luma_samples, 647cabdff1aSopenharmony_ci .pic_height_in_luma_samples = sps->pic_height_in_luma_samples, 648cabdff1aSopenharmony_ci 649cabdff1aSopenharmony_ci .seq_fields.bits = { 650cabdff1aSopenharmony_ci .chroma_format_idc = sps->chroma_format_idc, 651cabdff1aSopenharmony_ci .separate_colour_plane_flag = sps->separate_colour_plane_flag, 652cabdff1aSopenharmony_ci .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8, 653cabdff1aSopenharmony_ci .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8, 654cabdff1aSopenharmony_ci .scaling_list_enabled_flag = sps->scaling_list_enabled_flag, 655cabdff1aSopenharmony_ci .strong_intra_smoothing_enabled_flag = 656cabdff1aSopenharmony_ci sps->strong_intra_smoothing_enabled_flag, 657cabdff1aSopenharmony_ci .amp_enabled_flag = sps->amp_enabled_flag, 658cabdff1aSopenharmony_ci .sample_adaptive_offset_enabled_flag = 659cabdff1aSopenharmony_ci sps->sample_adaptive_offset_enabled_flag, 660cabdff1aSopenharmony_ci .pcm_enabled_flag = sps->pcm_enabled_flag, 661cabdff1aSopenharmony_ci .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag, 662cabdff1aSopenharmony_ci .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, 663cabdff1aSopenharmony_ci }, 664cabdff1aSopenharmony_ci 665cabdff1aSopenharmony_ci .log2_min_luma_coding_block_size_minus3 = 666cabdff1aSopenharmony_ci sps->log2_min_luma_coding_block_size_minus3, 667cabdff1aSopenharmony_ci .log2_diff_max_min_luma_coding_block_size = 668cabdff1aSopenharmony_ci sps->log2_diff_max_min_luma_coding_block_size, 669cabdff1aSopenharmony_ci .log2_min_transform_block_size_minus2 = 670cabdff1aSopenharmony_ci sps->log2_min_luma_transform_block_size_minus2, 671cabdff1aSopenharmony_ci .log2_diff_max_min_transform_block_size = 672cabdff1aSopenharmony_ci sps->log2_diff_max_min_luma_transform_block_size, 673cabdff1aSopenharmony_ci .max_transform_hierarchy_depth_inter = 674cabdff1aSopenharmony_ci sps->max_transform_hierarchy_depth_inter, 675cabdff1aSopenharmony_ci .max_transform_hierarchy_depth_intra = 676cabdff1aSopenharmony_ci sps->max_transform_hierarchy_depth_intra, 677cabdff1aSopenharmony_ci 678cabdff1aSopenharmony_ci .pcm_sample_bit_depth_luma_minus1 = 679cabdff1aSopenharmony_ci sps->pcm_sample_bit_depth_luma_minus1, 680cabdff1aSopenharmony_ci .pcm_sample_bit_depth_chroma_minus1 = 681cabdff1aSopenharmony_ci sps->pcm_sample_bit_depth_chroma_minus1, 682cabdff1aSopenharmony_ci .log2_min_pcm_luma_coding_block_size_minus3 = 683cabdff1aSopenharmony_ci sps->log2_min_pcm_luma_coding_block_size_minus3, 684cabdff1aSopenharmony_ci .log2_max_pcm_luma_coding_block_size_minus3 = 685cabdff1aSopenharmony_ci sps->log2_min_pcm_luma_coding_block_size_minus3 + 686cabdff1aSopenharmony_ci sps->log2_diff_max_min_pcm_luma_coding_block_size, 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci .vui_parameters_present_flag = 0, 689cabdff1aSopenharmony_ci }; 690cabdff1aSopenharmony_ci 691cabdff1aSopenharmony_ci *vpic = (VAEncPictureParameterBufferHEVC) { 692cabdff1aSopenharmony_ci .decoded_curr_pic = { 693cabdff1aSopenharmony_ci .picture_id = VA_INVALID_ID, 694cabdff1aSopenharmony_ci .flags = VA_PICTURE_HEVC_INVALID, 695cabdff1aSopenharmony_ci }, 696cabdff1aSopenharmony_ci 697cabdff1aSopenharmony_ci .coded_buf = VA_INVALID_ID, 698cabdff1aSopenharmony_ci 699cabdff1aSopenharmony_ci .collocated_ref_pic_index = sps->sps_temporal_mvp_enabled_flag ? 700cabdff1aSopenharmony_ci 0 : 0xff, 701cabdff1aSopenharmony_ci .last_picture = 0, 702cabdff1aSopenharmony_ci 703cabdff1aSopenharmony_ci .pic_init_qp = pps->init_qp_minus26 + 26, 704cabdff1aSopenharmony_ci .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, 705cabdff1aSopenharmony_ci .pps_cb_qp_offset = pps->pps_cb_qp_offset, 706cabdff1aSopenharmony_ci .pps_cr_qp_offset = pps->pps_cr_qp_offset, 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_ci .num_tile_columns_minus1 = pps->num_tile_columns_minus1, 709cabdff1aSopenharmony_ci .num_tile_rows_minus1 = pps->num_tile_rows_minus1, 710cabdff1aSopenharmony_ci 711cabdff1aSopenharmony_ci .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2, 712cabdff1aSopenharmony_ci .ctu_max_bitsize_allowed = 0, 713cabdff1aSopenharmony_ci 714cabdff1aSopenharmony_ci .num_ref_idx_l0_default_active_minus1 = 715cabdff1aSopenharmony_ci pps->num_ref_idx_l0_default_active_minus1, 716cabdff1aSopenharmony_ci .num_ref_idx_l1_default_active_minus1 = 717cabdff1aSopenharmony_ci pps->num_ref_idx_l1_default_active_minus1, 718cabdff1aSopenharmony_ci 719cabdff1aSopenharmony_ci .slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id, 720cabdff1aSopenharmony_ci 721cabdff1aSopenharmony_ci .pic_fields.bits = { 722cabdff1aSopenharmony_ci .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag, 723cabdff1aSopenharmony_ci .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, 724cabdff1aSopenharmony_ci .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, 725cabdff1aSopenharmony_ci .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, 726cabdff1aSopenharmony_ci .weighted_pred_flag = pps->weighted_pred_flag, 727cabdff1aSopenharmony_ci .weighted_bipred_flag = pps->weighted_bipred_flag, 728cabdff1aSopenharmony_ci .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag, 729cabdff1aSopenharmony_ci .tiles_enabled_flag = pps->tiles_enabled_flag, 730cabdff1aSopenharmony_ci .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, 731cabdff1aSopenharmony_ci .loop_filter_across_tiles_enabled_flag = 732cabdff1aSopenharmony_ci pps->loop_filter_across_tiles_enabled_flag, 733cabdff1aSopenharmony_ci .pps_loop_filter_across_slices_enabled_flag = 734cabdff1aSopenharmony_ci pps->pps_loop_filter_across_slices_enabled_flag, 735cabdff1aSopenharmony_ci .scaling_list_data_present_flag = (sps->sps_scaling_list_data_present_flag | 736cabdff1aSopenharmony_ci pps->pps_scaling_list_data_present_flag), 737cabdff1aSopenharmony_ci .screen_content_flag = 0, 738cabdff1aSopenharmony_ci .enable_gpu_weighted_prediction = 0, 739cabdff1aSopenharmony_ci .no_output_of_prior_pics_flag = 0, 740cabdff1aSopenharmony_ci }, 741cabdff1aSopenharmony_ci }; 742cabdff1aSopenharmony_ci 743cabdff1aSopenharmony_ci if (pps->tiles_enabled_flag) { 744cabdff1aSopenharmony_ci for (i = 0; i <= vpic->num_tile_rows_minus1; i++) 745cabdff1aSopenharmony_ci vpic->row_height_minus1[i] = pps->row_height_minus1[i]; 746cabdff1aSopenharmony_ci for (i = 0; i <= vpic->num_tile_columns_minus1; i++) 747cabdff1aSopenharmony_ci vpic->column_width_minus1[i] = pps->column_width_minus1[i]; 748cabdff1aSopenharmony_ci } 749cabdff1aSopenharmony_ci 750cabdff1aSopenharmony_ci return 0; 751cabdff1aSopenharmony_ci} 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_cistatic int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, 754cabdff1aSopenharmony_ci VAAPIEncodePicture *pic) 755cabdff1aSopenharmony_ci{ 756cabdff1aSopenharmony_ci VAAPIEncodeContext *ctx = avctx->priv_data; 757cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 758cabdff1aSopenharmony_ci VAAPIEncodeH265Picture *hpic = pic->priv_data; 759cabdff1aSopenharmony_ci VAAPIEncodePicture *prev = pic->prev; 760cabdff1aSopenharmony_ci VAAPIEncodeH265Picture *hprev = prev ? prev->priv_data : NULL; 761cabdff1aSopenharmony_ci VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; 762cabdff1aSopenharmony_ci int i; 763cabdff1aSopenharmony_ci 764cabdff1aSopenharmony_ci if (pic->type == PICTURE_TYPE_IDR) { 765cabdff1aSopenharmony_ci av_assert0(pic->display_order == pic->encode_order); 766cabdff1aSopenharmony_ci 767cabdff1aSopenharmony_ci hpic->last_idr_frame = pic->display_order; 768cabdff1aSopenharmony_ci 769cabdff1aSopenharmony_ci hpic->slice_nal_unit = HEVC_NAL_IDR_W_RADL; 770cabdff1aSopenharmony_ci hpic->slice_type = HEVC_SLICE_I; 771cabdff1aSopenharmony_ci hpic->pic_type = 0; 772cabdff1aSopenharmony_ci } else { 773cabdff1aSopenharmony_ci av_assert0(prev); 774cabdff1aSopenharmony_ci hpic->last_idr_frame = hprev->last_idr_frame; 775cabdff1aSopenharmony_ci 776cabdff1aSopenharmony_ci if (pic->type == PICTURE_TYPE_I) { 777cabdff1aSopenharmony_ci hpic->slice_nal_unit = HEVC_NAL_CRA_NUT; 778cabdff1aSopenharmony_ci hpic->slice_type = HEVC_SLICE_I; 779cabdff1aSopenharmony_ci hpic->pic_type = 0; 780cabdff1aSopenharmony_ci } else if (pic->type == PICTURE_TYPE_P) { 781cabdff1aSopenharmony_ci av_assert0(pic->refs[0]); 782cabdff1aSopenharmony_ci hpic->slice_nal_unit = HEVC_NAL_TRAIL_R; 783cabdff1aSopenharmony_ci hpic->slice_type = HEVC_SLICE_P; 784cabdff1aSopenharmony_ci hpic->pic_type = 1; 785cabdff1aSopenharmony_ci } else { 786cabdff1aSopenharmony_ci VAAPIEncodePicture *irap_ref; 787cabdff1aSopenharmony_ci av_assert0(pic->refs[0] && pic->refs[1]); 788cabdff1aSopenharmony_ci for (irap_ref = pic; irap_ref; irap_ref = irap_ref->refs[1]) { 789cabdff1aSopenharmony_ci if (irap_ref->type == PICTURE_TYPE_I) 790cabdff1aSopenharmony_ci break; 791cabdff1aSopenharmony_ci } 792cabdff1aSopenharmony_ci if (pic->b_depth == ctx->max_b_depth) { 793cabdff1aSopenharmony_ci hpic->slice_nal_unit = irap_ref ? HEVC_NAL_RASL_N 794cabdff1aSopenharmony_ci : HEVC_NAL_TRAIL_N; 795cabdff1aSopenharmony_ci } else { 796cabdff1aSopenharmony_ci hpic->slice_nal_unit = irap_ref ? HEVC_NAL_RASL_R 797cabdff1aSopenharmony_ci : HEVC_NAL_TRAIL_R; 798cabdff1aSopenharmony_ci } 799cabdff1aSopenharmony_ci hpic->slice_type = HEVC_SLICE_B; 800cabdff1aSopenharmony_ci hpic->pic_type = 2; 801cabdff1aSopenharmony_ci } 802cabdff1aSopenharmony_ci } 803cabdff1aSopenharmony_ci hpic->pic_order_cnt = pic->display_order - hpic->last_idr_frame; 804cabdff1aSopenharmony_ci 805cabdff1aSopenharmony_ci if (priv->aud) { 806cabdff1aSopenharmony_ci priv->aud_needed = 1; 807cabdff1aSopenharmony_ci priv->raw_aud = (H265RawAUD) { 808cabdff1aSopenharmony_ci .nal_unit_header = { 809cabdff1aSopenharmony_ci .nal_unit_type = HEVC_NAL_AUD, 810cabdff1aSopenharmony_ci .nuh_layer_id = 0, 811cabdff1aSopenharmony_ci .nuh_temporal_id_plus1 = 1, 812cabdff1aSopenharmony_ci }, 813cabdff1aSopenharmony_ci .pic_type = hpic->pic_type, 814cabdff1aSopenharmony_ci }; 815cabdff1aSopenharmony_ci } else { 816cabdff1aSopenharmony_ci priv->aud_needed = 0; 817cabdff1aSopenharmony_ci } 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci priv->sei_needed = 0; 820cabdff1aSopenharmony_ci 821cabdff1aSopenharmony_ci // Only look for the metadata on I/IDR frame on the output. We 822cabdff1aSopenharmony_ci // may force an IDR frame on the output where the medadata gets 823cabdff1aSopenharmony_ci // changed on the input frame. 824cabdff1aSopenharmony_ci if ((priv->sei & SEI_MASTERING_DISPLAY) && 825cabdff1aSopenharmony_ci (pic->type == PICTURE_TYPE_I || pic->type == PICTURE_TYPE_IDR)) { 826cabdff1aSopenharmony_ci AVFrameSideData *sd = 827cabdff1aSopenharmony_ci av_frame_get_side_data(pic->input_image, 828cabdff1aSopenharmony_ci AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); 829cabdff1aSopenharmony_ci 830cabdff1aSopenharmony_ci if (sd) { 831cabdff1aSopenharmony_ci AVMasteringDisplayMetadata *mdm = 832cabdff1aSopenharmony_ci (AVMasteringDisplayMetadata *)sd->data; 833cabdff1aSopenharmony_ci 834cabdff1aSopenharmony_ci // SEI is needed when both the primaries and luminance are set 835cabdff1aSopenharmony_ci if (mdm->has_primaries && mdm->has_luminance) { 836cabdff1aSopenharmony_ci SEIRawMasteringDisplayColourVolume *mdcv = 837cabdff1aSopenharmony_ci &priv->sei_mastering_display; 838cabdff1aSopenharmony_ci const int mapping[3] = {1, 2, 0}; 839cabdff1aSopenharmony_ci const int chroma_den = 50000; 840cabdff1aSopenharmony_ci const int luma_den = 10000; 841cabdff1aSopenharmony_ci 842cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 843cabdff1aSopenharmony_ci const int j = mapping[i]; 844cabdff1aSopenharmony_ci mdcv->display_primaries_x[i] = 845cabdff1aSopenharmony_ci FFMIN(lrint(chroma_den * 846cabdff1aSopenharmony_ci av_q2d(mdm->display_primaries[j][0])), 847cabdff1aSopenharmony_ci chroma_den); 848cabdff1aSopenharmony_ci mdcv->display_primaries_y[i] = 849cabdff1aSopenharmony_ci FFMIN(lrint(chroma_den * 850cabdff1aSopenharmony_ci av_q2d(mdm->display_primaries[j][1])), 851cabdff1aSopenharmony_ci chroma_den); 852cabdff1aSopenharmony_ci } 853cabdff1aSopenharmony_ci 854cabdff1aSopenharmony_ci mdcv->white_point_x = 855cabdff1aSopenharmony_ci FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])), 856cabdff1aSopenharmony_ci chroma_den); 857cabdff1aSopenharmony_ci mdcv->white_point_y = 858cabdff1aSopenharmony_ci FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])), 859cabdff1aSopenharmony_ci chroma_den); 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_ci mdcv->max_display_mastering_luminance = 862cabdff1aSopenharmony_ci lrint(luma_den * av_q2d(mdm->max_luminance)); 863cabdff1aSopenharmony_ci mdcv->min_display_mastering_luminance = 864cabdff1aSopenharmony_ci FFMIN(lrint(luma_den * av_q2d(mdm->min_luminance)), 865cabdff1aSopenharmony_ci mdcv->max_display_mastering_luminance); 866cabdff1aSopenharmony_ci 867cabdff1aSopenharmony_ci priv->sei_needed |= SEI_MASTERING_DISPLAY; 868cabdff1aSopenharmony_ci } 869cabdff1aSopenharmony_ci } 870cabdff1aSopenharmony_ci } 871cabdff1aSopenharmony_ci 872cabdff1aSopenharmony_ci if ((priv->sei & SEI_CONTENT_LIGHT_LEVEL) && 873cabdff1aSopenharmony_ci (pic->type == PICTURE_TYPE_I || pic->type == PICTURE_TYPE_IDR)) { 874cabdff1aSopenharmony_ci AVFrameSideData *sd = 875cabdff1aSopenharmony_ci av_frame_get_side_data(pic->input_image, 876cabdff1aSopenharmony_ci AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); 877cabdff1aSopenharmony_ci 878cabdff1aSopenharmony_ci if (sd) { 879cabdff1aSopenharmony_ci AVContentLightMetadata *clm = 880cabdff1aSopenharmony_ci (AVContentLightMetadata *)sd->data; 881cabdff1aSopenharmony_ci SEIRawContentLightLevelInfo *clli = 882cabdff1aSopenharmony_ci &priv->sei_content_light_level; 883cabdff1aSopenharmony_ci 884cabdff1aSopenharmony_ci clli->max_content_light_level = FFMIN(clm->MaxCLL, 65535); 885cabdff1aSopenharmony_ci clli->max_pic_average_light_level = FFMIN(clm->MaxFALL, 65535); 886cabdff1aSopenharmony_ci 887cabdff1aSopenharmony_ci priv->sei_needed |= SEI_CONTENT_LIGHT_LEVEL; 888cabdff1aSopenharmony_ci } 889cabdff1aSopenharmony_ci } 890cabdff1aSopenharmony_ci 891cabdff1aSopenharmony_ci vpic->decoded_curr_pic = (VAPictureHEVC) { 892cabdff1aSopenharmony_ci .picture_id = pic->recon_surface, 893cabdff1aSopenharmony_ci .pic_order_cnt = hpic->pic_order_cnt, 894cabdff1aSopenharmony_ci .flags = 0, 895cabdff1aSopenharmony_ci }; 896cabdff1aSopenharmony_ci 897cabdff1aSopenharmony_ci for (i = 0; i < pic->nb_refs; i++) { 898cabdff1aSopenharmony_ci VAAPIEncodePicture *ref = pic->refs[i]; 899cabdff1aSopenharmony_ci VAAPIEncodeH265Picture *href; 900cabdff1aSopenharmony_ci 901cabdff1aSopenharmony_ci av_assert0(ref && ref->encode_order < pic->encode_order); 902cabdff1aSopenharmony_ci href = ref->priv_data; 903cabdff1aSopenharmony_ci 904cabdff1aSopenharmony_ci vpic->reference_frames[i] = (VAPictureHEVC) { 905cabdff1aSopenharmony_ci .picture_id = ref->recon_surface, 906cabdff1aSopenharmony_ci .pic_order_cnt = href->pic_order_cnt, 907cabdff1aSopenharmony_ci .flags = (ref->display_order < pic->display_order ? 908cabdff1aSopenharmony_ci VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | 909cabdff1aSopenharmony_ci (ref->display_order > pic->display_order ? 910cabdff1aSopenharmony_ci VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0), 911cabdff1aSopenharmony_ci }; 912cabdff1aSopenharmony_ci } 913cabdff1aSopenharmony_ci for (; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { 914cabdff1aSopenharmony_ci vpic->reference_frames[i] = (VAPictureHEVC) { 915cabdff1aSopenharmony_ci .picture_id = VA_INVALID_ID, 916cabdff1aSopenharmony_ci .flags = VA_PICTURE_HEVC_INVALID, 917cabdff1aSopenharmony_ci }; 918cabdff1aSopenharmony_ci } 919cabdff1aSopenharmony_ci 920cabdff1aSopenharmony_ci vpic->coded_buf = pic->output_buffer; 921cabdff1aSopenharmony_ci 922cabdff1aSopenharmony_ci vpic->nal_unit_type = hpic->slice_nal_unit; 923cabdff1aSopenharmony_ci 924cabdff1aSopenharmony_ci switch (pic->type) { 925cabdff1aSopenharmony_ci case PICTURE_TYPE_IDR: 926cabdff1aSopenharmony_ci vpic->pic_fields.bits.idr_pic_flag = 1; 927cabdff1aSopenharmony_ci vpic->pic_fields.bits.coding_type = 1; 928cabdff1aSopenharmony_ci vpic->pic_fields.bits.reference_pic_flag = 1; 929cabdff1aSopenharmony_ci break; 930cabdff1aSopenharmony_ci case PICTURE_TYPE_I: 931cabdff1aSopenharmony_ci vpic->pic_fields.bits.idr_pic_flag = 0; 932cabdff1aSopenharmony_ci vpic->pic_fields.bits.coding_type = 1; 933cabdff1aSopenharmony_ci vpic->pic_fields.bits.reference_pic_flag = 1; 934cabdff1aSopenharmony_ci break; 935cabdff1aSopenharmony_ci case PICTURE_TYPE_P: 936cabdff1aSopenharmony_ci vpic->pic_fields.bits.idr_pic_flag = 0; 937cabdff1aSopenharmony_ci vpic->pic_fields.bits.coding_type = 2; 938cabdff1aSopenharmony_ci vpic->pic_fields.bits.reference_pic_flag = 1; 939cabdff1aSopenharmony_ci break; 940cabdff1aSopenharmony_ci case PICTURE_TYPE_B: 941cabdff1aSopenharmony_ci vpic->pic_fields.bits.idr_pic_flag = 0; 942cabdff1aSopenharmony_ci vpic->pic_fields.bits.coding_type = 3; 943cabdff1aSopenharmony_ci vpic->pic_fields.bits.reference_pic_flag = 0; 944cabdff1aSopenharmony_ci break; 945cabdff1aSopenharmony_ci default: 946cabdff1aSopenharmony_ci av_assert0(0 && "invalid picture type"); 947cabdff1aSopenharmony_ci } 948cabdff1aSopenharmony_ci 949cabdff1aSopenharmony_ci return 0; 950cabdff1aSopenharmony_ci} 951cabdff1aSopenharmony_ci 952cabdff1aSopenharmony_cistatic int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, 953cabdff1aSopenharmony_ci VAAPIEncodePicture *pic, 954cabdff1aSopenharmony_ci VAAPIEncodeSlice *slice) 955cabdff1aSopenharmony_ci{ 956cabdff1aSopenharmony_ci VAAPIEncodeContext *ctx = avctx->priv_data; 957cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 958cabdff1aSopenharmony_ci VAAPIEncodeH265Picture *hpic = pic->priv_data; 959cabdff1aSopenharmony_ci const H265RawSPS *sps = &priv->raw_sps; 960cabdff1aSopenharmony_ci const H265RawPPS *pps = &priv->raw_pps; 961cabdff1aSopenharmony_ci H265RawSliceHeader *sh = &priv->raw_slice.header; 962cabdff1aSopenharmony_ci VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; 963cabdff1aSopenharmony_ci VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; 964cabdff1aSopenharmony_ci int i; 965cabdff1aSopenharmony_ci 966cabdff1aSopenharmony_ci sh->nal_unit_header = (H265RawNALUnitHeader) { 967cabdff1aSopenharmony_ci .nal_unit_type = hpic->slice_nal_unit, 968cabdff1aSopenharmony_ci .nuh_layer_id = 0, 969cabdff1aSopenharmony_ci .nuh_temporal_id_plus1 = 1, 970cabdff1aSopenharmony_ci }; 971cabdff1aSopenharmony_ci 972cabdff1aSopenharmony_ci sh->slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id; 973cabdff1aSopenharmony_ci 974cabdff1aSopenharmony_ci sh->first_slice_segment_in_pic_flag = slice->index == 0; 975cabdff1aSopenharmony_ci sh->slice_segment_address = slice->block_start; 976cabdff1aSopenharmony_ci 977cabdff1aSopenharmony_ci sh->slice_type = hpic->slice_type; 978cabdff1aSopenharmony_ci 979cabdff1aSopenharmony_ci if (sh->slice_type == HEVC_SLICE_P && ctx->p_to_gpb) 980cabdff1aSopenharmony_ci sh->slice_type = HEVC_SLICE_B; 981cabdff1aSopenharmony_ci 982cabdff1aSopenharmony_ci sh->slice_pic_order_cnt_lsb = hpic->pic_order_cnt & 983cabdff1aSopenharmony_ci (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1; 984cabdff1aSopenharmony_ci 985cabdff1aSopenharmony_ci if (pic->type != PICTURE_TYPE_IDR) { 986cabdff1aSopenharmony_ci H265RawSTRefPicSet *rps; 987cabdff1aSopenharmony_ci const VAAPIEncodeH265Picture *strp; 988cabdff1aSopenharmony_ci int rps_poc[MAX_DPB_SIZE]; 989cabdff1aSopenharmony_ci int rps_used[MAX_DPB_SIZE]; 990cabdff1aSopenharmony_ci int i, j, poc, rps_pics; 991cabdff1aSopenharmony_ci 992cabdff1aSopenharmony_ci sh->short_term_ref_pic_set_sps_flag = 0; 993cabdff1aSopenharmony_ci 994cabdff1aSopenharmony_ci rps = &sh->short_term_ref_pic_set; 995cabdff1aSopenharmony_ci memset(rps, 0, sizeof(*rps)); 996cabdff1aSopenharmony_ci 997cabdff1aSopenharmony_ci rps_pics = 0; 998cabdff1aSopenharmony_ci for (i = 0; i < pic->nb_refs; i++) { 999cabdff1aSopenharmony_ci strp = pic->refs[i]->priv_data; 1000cabdff1aSopenharmony_ci rps_poc[rps_pics] = strp->pic_order_cnt; 1001cabdff1aSopenharmony_ci rps_used[rps_pics] = 1; 1002cabdff1aSopenharmony_ci ++rps_pics; 1003cabdff1aSopenharmony_ci } 1004cabdff1aSopenharmony_ci for (i = 0; i < pic->nb_dpb_pics; i++) { 1005cabdff1aSopenharmony_ci if (pic->dpb[i] == pic) 1006cabdff1aSopenharmony_ci continue; 1007cabdff1aSopenharmony_ci for (j = 0; j < pic->nb_refs; j++) { 1008cabdff1aSopenharmony_ci if (pic->dpb[i] == pic->refs[j]) 1009cabdff1aSopenharmony_ci break; 1010cabdff1aSopenharmony_ci } 1011cabdff1aSopenharmony_ci if (j < pic->nb_refs) 1012cabdff1aSopenharmony_ci continue; 1013cabdff1aSopenharmony_ci strp = pic->dpb[i]->priv_data; 1014cabdff1aSopenharmony_ci rps_poc[rps_pics] = strp->pic_order_cnt; 1015cabdff1aSopenharmony_ci rps_used[rps_pics] = 0; 1016cabdff1aSopenharmony_ci ++rps_pics; 1017cabdff1aSopenharmony_ci } 1018cabdff1aSopenharmony_ci 1019cabdff1aSopenharmony_ci for (i = 1; i < rps_pics; i++) { 1020cabdff1aSopenharmony_ci for (j = i; j > 0; j--) { 1021cabdff1aSopenharmony_ci if (rps_poc[j] > rps_poc[j - 1]) 1022cabdff1aSopenharmony_ci break; 1023cabdff1aSopenharmony_ci av_assert0(rps_poc[j] != rps_poc[j - 1]); 1024cabdff1aSopenharmony_ci FFSWAP(int, rps_poc[j], rps_poc[j - 1]); 1025cabdff1aSopenharmony_ci FFSWAP(int, rps_used[j], rps_used[j - 1]); 1026cabdff1aSopenharmony_ci } 1027cabdff1aSopenharmony_ci } 1028cabdff1aSopenharmony_ci 1029cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "RPS for POC %d:", 1030cabdff1aSopenharmony_ci hpic->pic_order_cnt); 1031cabdff1aSopenharmony_ci for (i = 0; i < rps_pics; i++) { 1032cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, " (%d,%d)", 1033cabdff1aSopenharmony_ci rps_poc[i], rps_used[i]); 1034cabdff1aSopenharmony_ci } 1035cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "\n"); 1036cabdff1aSopenharmony_ci 1037cabdff1aSopenharmony_ci for (i = 0; i < rps_pics; i++) { 1038cabdff1aSopenharmony_ci av_assert0(rps_poc[i] != hpic->pic_order_cnt); 1039cabdff1aSopenharmony_ci if (rps_poc[i] > hpic->pic_order_cnt) 1040cabdff1aSopenharmony_ci break; 1041cabdff1aSopenharmony_ci } 1042cabdff1aSopenharmony_ci 1043cabdff1aSopenharmony_ci rps->num_negative_pics = i; 1044cabdff1aSopenharmony_ci poc = hpic->pic_order_cnt; 1045cabdff1aSopenharmony_ci for (j = i - 1; j >= 0; j--) { 1046cabdff1aSopenharmony_ci rps->delta_poc_s0_minus1[i - 1 - j] = poc - rps_poc[j] - 1; 1047cabdff1aSopenharmony_ci rps->used_by_curr_pic_s0_flag[i - 1 - j] = rps_used[j]; 1048cabdff1aSopenharmony_ci poc = rps_poc[j]; 1049cabdff1aSopenharmony_ci } 1050cabdff1aSopenharmony_ci 1051cabdff1aSopenharmony_ci rps->num_positive_pics = rps_pics - i; 1052cabdff1aSopenharmony_ci poc = hpic->pic_order_cnt; 1053cabdff1aSopenharmony_ci for (j = i; j < rps_pics; j++) { 1054cabdff1aSopenharmony_ci rps->delta_poc_s1_minus1[j - i] = rps_poc[j] - poc - 1; 1055cabdff1aSopenharmony_ci rps->used_by_curr_pic_s1_flag[j - i] = rps_used[j]; 1056cabdff1aSopenharmony_ci poc = rps_poc[j]; 1057cabdff1aSopenharmony_ci } 1058cabdff1aSopenharmony_ci 1059cabdff1aSopenharmony_ci sh->num_long_term_sps = 0; 1060cabdff1aSopenharmony_ci sh->num_long_term_pics = 0; 1061cabdff1aSopenharmony_ci 1062cabdff1aSopenharmony_ci // when this flag is not present, it is inerred to 1. 1063cabdff1aSopenharmony_ci sh->collocated_from_l0_flag = 1; 1064cabdff1aSopenharmony_ci sh->slice_temporal_mvp_enabled_flag = 1065cabdff1aSopenharmony_ci sps->sps_temporal_mvp_enabled_flag; 1066cabdff1aSopenharmony_ci if (sh->slice_temporal_mvp_enabled_flag) { 1067cabdff1aSopenharmony_ci if (sh->slice_type == HEVC_SLICE_B) 1068cabdff1aSopenharmony_ci sh->collocated_from_l0_flag = 1; 1069cabdff1aSopenharmony_ci sh->collocated_ref_idx = 0; 1070cabdff1aSopenharmony_ci } 1071cabdff1aSopenharmony_ci 1072cabdff1aSopenharmony_ci sh->num_ref_idx_active_override_flag = 0; 1073cabdff1aSopenharmony_ci sh->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; 1074cabdff1aSopenharmony_ci sh->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; 1075cabdff1aSopenharmony_ci } 1076cabdff1aSopenharmony_ci 1077cabdff1aSopenharmony_ci sh->slice_sao_luma_flag = sh->slice_sao_chroma_flag = 1078cabdff1aSopenharmony_ci sps->sample_adaptive_offset_enabled_flag; 1079cabdff1aSopenharmony_ci 1080cabdff1aSopenharmony_ci if (pic->type == PICTURE_TYPE_B) 1081cabdff1aSopenharmony_ci sh->slice_qp_delta = priv->fixed_qp_b - (pps->init_qp_minus26 + 26); 1082cabdff1aSopenharmony_ci else if (pic->type == PICTURE_TYPE_P) 1083cabdff1aSopenharmony_ci sh->slice_qp_delta = priv->fixed_qp_p - (pps->init_qp_minus26 + 26); 1084cabdff1aSopenharmony_ci else 1085cabdff1aSopenharmony_ci sh->slice_qp_delta = priv->fixed_qp_idr - (pps->init_qp_minus26 + 26); 1086cabdff1aSopenharmony_ci 1087cabdff1aSopenharmony_ci 1088cabdff1aSopenharmony_ci *vslice = (VAEncSliceParameterBufferHEVC) { 1089cabdff1aSopenharmony_ci .slice_segment_address = sh->slice_segment_address, 1090cabdff1aSopenharmony_ci .num_ctu_in_slice = slice->block_size, 1091cabdff1aSopenharmony_ci 1092cabdff1aSopenharmony_ci .slice_type = sh->slice_type, 1093cabdff1aSopenharmony_ci .slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id, 1094cabdff1aSopenharmony_ci 1095cabdff1aSopenharmony_ci .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1, 1096cabdff1aSopenharmony_ci .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1, 1097cabdff1aSopenharmony_ci 1098cabdff1aSopenharmony_ci .luma_log2_weight_denom = sh->luma_log2_weight_denom, 1099cabdff1aSopenharmony_ci .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom, 1100cabdff1aSopenharmony_ci 1101cabdff1aSopenharmony_ci .max_num_merge_cand = 5 - sh->five_minus_max_num_merge_cand, 1102cabdff1aSopenharmony_ci 1103cabdff1aSopenharmony_ci .slice_qp_delta = sh->slice_qp_delta, 1104cabdff1aSopenharmony_ci .slice_cb_qp_offset = sh->slice_cb_qp_offset, 1105cabdff1aSopenharmony_ci .slice_cr_qp_offset = sh->slice_cr_qp_offset, 1106cabdff1aSopenharmony_ci 1107cabdff1aSopenharmony_ci .slice_beta_offset_div2 = sh->slice_beta_offset_div2, 1108cabdff1aSopenharmony_ci .slice_tc_offset_div2 = sh->slice_tc_offset_div2, 1109cabdff1aSopenharmony_ci 1110cabdff1aSopenharmony_ci .slice_fields.bits = { 1111cabdff1aSopenharmony_ci .last_slice_of_pic_flag = slice->index == pic->nb_slices - 1, 1112cabdff1aSopenharmony_ci .dependent_slice_segment_flag = sh->dependent_slice_segment_flag, 1113cabdff1aSopenharmony_ci .colour_plane_id = sh->colour_plane_id, 1114cabdff1aSopenharmony_ci .slice_temporal_mvp_enabled_flag = 1115cabdff1aSopenharmony_ci sh->slice_temporal_mvp_enabled_flag, 1116cabdff1aSopenharmony_ci .slice_sao_luma_flag = sh->slice_sao_luma_flag, 1117cabdff1aSopenharmony_ci .slice_sao_chroma_flag = sh->slice_sao_chroma_flag, 1118cabdff1aSopenharmony_ci .num_ref_idx_active_override_flag = 1119cabdff1aSopenharmony_ci sh->num_ref_idx_active_override_flag, 1120cabdff1aSopenharmony_ci .mvd_l1_zero_flag = sh->mvd_l1_zero_flag, 1121cabdff1aSopenharmony_ci .cabac_init_flag = sh->cabac_init_flag, 1122cabdff1aSopenharmony_ci .slice_deblocking_filter_disabled_flag = 1123cabdff1aSopenharmony_ci sh->slice_deblocking_filter_disabled_flag, 1124cabdff1aSopenharmony_ci .slice_loop_filter_across_slices_enabled_flag = 1125cabdff1aSopenharmony_ci sh->slice_loop_filter_across_slices_enabled_flag, 1126cabdff1aSopenharmony_ci .collocated_from_l0_flag = sh->collocated_from_l0_flag, 1127cabdff1aSopenharmony_ci }, 1128cabdff1aSopenharmony_ci }; 1129cabdff1aSopenharmony_ci 1130cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { 1131cabdff1aSopenharmony_ci vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID; 1132cabdff1aSopenharmony_ci vslice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; 1133cabdff1aSopenharmony_ci vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID; 1134cabdff1aSopenharmony_ci vslice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; 1135cabdff1aSopenharmony_ci } 1136cabdff1aSopenharmony_ci 1137cabdff1aSopenharmony_ci av_assert0(pic->nb_refs <= 2); 1138cabdff1aSopenharmony_ci if (pic->nb_refs >= 1) { 1139cabdff1aSopenharmony_ci // Backward reference for P- or B-frame. 1140cabdff1aSopenharmony_ci av_assert0(pic->type == PICTURE_TYPE_P || 1141cabdff1aSopenharmony_ci pic->type == PICTURE_TYPE_B); 1142cabdff1aSopenharmony_ci vslice->ref_pic_list0[0] = vpic->reference_frames[0]; 1143cabdff1aSopenharmony_ci if (ctx->p_to_gpb && pic->type == PICTURE_TYPE_P) 1144cabdff1aSopenharmony_ci // Reference for GPB B-frame, L0 == L1 1145cabdff1aSopenharmony_ci vslice->ref_pic_list1[0] = vpic->reference_frames[0]; 1146cabdff1aSopenharmony_ci } 1147cabdff1aSopenharmony_ci if (pic->nb_refs >= 2) { 1148cabdff1aSopenharmony_ci // Forward reference for B-frame. 1149cabdff1aSopenharmony_ci av_assert0(pic->type == PICTURE_TYPE_B); 1150cabdff1aSopenharmony_ci vslice->ref_pic_list1[0] = vpic->reference_frames[1]; 1151cabdff1aSopenharmony_ci } 1152cabdff1aSopenharmony_ci 1153cabdff1aSopenharmony_ci if (pic->type == PICTURE_TYPE_P && ctx->p_to_gpb) { 1154cabdff1aSopenharmony_ci vslice->slice_type = HEVC_SLICE_B; 1155cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { 1156cabdff1aSopenharmony_ci vslice->ref_pic_list1[i].picture_id = vslice->ref_pic_list0[i].picture_id; 1157cabdff1aSopenharmony_ci vslice->ref_pic_list1[i].flags = vslice->ref_pic_list0[i].flags; 1158cabdff1aSopenharmony_ci } 1159cabdff1aSopenharmony_ci } 1160cabdff1aSopenharmony_ci 1161cabdff1aSopenharmony_ci return 0; 1162cabdff1aSopenharmony_ci} 1163cabdff1aSopenharmony_ci 1164cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h265_get_encoder_caps(AVCodecContext *avctx) 1165cabdff1aSopenharmony_ci{ 1166cabdff1aSopenharmony_ci VAAPIEncodeContext *ctx = avctx->priv_data; 1167cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 1168cabdff1aSopenharmony_ci 1169cabdff1aSopenharmony_ci#if VA_CHECK_VERSION(1, 13, 0) 1170cabdff1aSopenharmony_ci { 1171cabdff1aSopenharmony_ci VAConfigAttribValEncHEVCBlockSizes block_size; 1172cabdff1aSopenharmony_ci VAConfigAttrib attr; 1173cabdff1aSopenharmony_ci VAStatus vas; 1174cabdff1aSopenharmony_ci 1175cabdff1aSopenharmony_ci attr.type = VAConfigAttribEncHEVCFeatures; 1176cabdff1aSopenharmony_ci vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, 1177cabdff1aSopenharmony_ci ctx->va_entrypoint, &attr, 1); 1178cabdff1aSopenharmony_ci if (vas != VA_STATUS_SUCCESS) { 1179cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to query encoder " 1180cabdff1aSopenharmony_ci "features, using guessed defaults.\n"); 1181cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 1182cabdff1aSopenharmony_ci } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { 1183cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Driver does not advertise " 1184cabdff1aSopenharmony_ci "encoder features, using guessed defaults.\n"); 1185cabdff1aSopenharmony_ci } else { 1186cabdff1aSopenharmony_ci priv->va_features = attr.value; 1187cabdff1aSopenharmony_ci } 1188cabdff1aSopenharmony_ci 1189cabdff1aSopenharmony_ci attr.type = VAConfigAttribEncHEVCBlockSizes; 1190cabdff1aSopenharmony_ci vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, 1191cabdff1aSopenharmony_ci ctx->va_entrypoint, &attr, 1); 1192cabdff1aSopenharmony_ci if (vas != VA_STATUS_SUCCESS) { 1193cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to query encoder " 1194cabdff1aSopenharmony_ci "block size, using guessed defaults.\n"); 1195cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 1196cabdff1aSopenharmony_ci } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { 1197cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Driver does not advertise " 1198cabdff1aSopenharmony_ci "encoder block size, using guessed defaults.\n"); 1199cabdff1aSopenharmony_ci } else { 1200cabdff1aSopenharmony_ci priv->va_bs = block_size.value = attr.value; 1201cabdff1aSopenharmony_ci 1202cabdff1aSopenharmony_ci priv->ctu_size = 1203cabdff1aSopenharmony_ci 1 << block_size.bits.log2_max_coding_tree_block_size_minus3 + 3; 1204cabdff1aSopenharmony_ci priv->min_cb_size = 1205cabdff1aSopenharmony_ci 1 << block_size.bits.log2_min_luma_coding_block_size_minus3 + 3; 1206cabdff1aSopenharmony_ci } 1207cabdff1aSopenharmony_ci } 1208cabdff1aSopenharmony_ci#endif 1209cabdff1aSopenharmony_ci 1210cabdff1aSopenharmony_ci if (!priv->ctu_size) { 1211cabdff1aSopenharmony_ci priv->ctu_size = 32; 1212cabdff1aSopenharmony_ci priv->min_cb_size = 16; 1213cabdff1aSopenharmony_ci } 1214cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Using CTU size %dx%d, " 1215cabdff1aSopenharmony_ci "min CB size %dx%d.\n", priv->ctu_size, priv->ctu_size, 1216cabdff1aSopenharmony_ci priv->min_cb_size, priv->min_cb_size); 1217cabdff1aSopenharmony_ci 1218cabdff1aSopenharmony_ci ctx->surface_width = FFALIGN(avctx->width, priv->min_cb_size); 1219cabdff1aSopenharmony_ci ctx->surface_height = FFALIGN(avctx->height, priv->min_cb_size); 1220cabdff1aSopenharmony_ci 1221cabdff1aSopenharmony_ci ctx->slice_block_width = ctx->slice_block_height = priv->ctu_size; 1222cabdff1aSopenharmony_ci 1223cabdff1aSopenharmony_ci return 0; 1224cabdff1aSopenharmony_ci} 1225cabdff1aSopenharmony_ci 1226cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) 1227cabdff1aSopenharmony_ci{ 1228cabdff1aSopenharmony_ci VAAPIEncodeContext *ctx = avctx->priv_data; 1229cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 1230cabdff1aSopenharmony_ci int err; 1231cabdff1aSopenharmony_ci 1232cabdff1aSopenharmony_ci err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_HEVC, avctx); 1233cabdff1aSopenharmony_ci if (err < 0) 1234cabdff1aSopenharmony_ci return err; 1235cabdff1aSopenharmony_ci 1236cabdff1aSopenharmony_ci if (ctx->va_rc_mode == VA_RC_CQP) { 1237cabdff1aSopenharmony_ci // Note that VAAPI only supports positive QP values - the range is 1238cabdff1aSopenharmony_ci // therefore always bounded below by 1, even in 10-bit mode where 1239cabdff1aSopenharmony_ci // it should go down to -12. 1240cabdff1aSopenharmony_ci 1241cabdff1aSopenharmony_ci priv->fixed_qp_p = av_clip(ctx->rc_quality, 1, 51); 1242cabdff1aSopenharmony_ci if (avctx->i_quant_factor > 0.0) 1243cabdff1aSopenharmony_ci priv->fixed_qp_idr = 1244cabdff1aSopenharmony_ci av_clip((avctx->i_quant_factor * priv->fixed_qp_p + 1245cabdff1aSopenharmony_ci avctx->i_quant_offset) + 0.5, 1, 51); 1246cabdff1aSopenharmony_ci else 1247cabdff1aSopenharmony_ci priv->fixed_qp_idr = priv->fixed_qp_p; 1248cabdff1aSopenharmony_ci if (avctx->b_quant_factor > 0.0) 1249cabdff1aSopenharmony_ci priv->fixed_qp_b = 1250cabdff1aSopenharmony_ci av_clip((avctx->b_quant_factor * priv->fixed_qp_p + 1251cabdff1aSopenharmony_ci avctx->b_quant_offset) + 0.5, 1, 51); 1252cabdff1aSopenharmony_ci else 1253cabdff1aSopenharmony_ci priv->fixed_qp_b = priv->fixed_qp_p; 1254cabdff1aSopenharmony_ci 1255cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " 1256cabdff1aSopenharmony_ci "%d / %d / %d for IDR- / P- / B-frames.\n", 1257cabdff1aSopenharmony_ci priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); 1258cabdff1aSopenharmony_ci 1259cabdff1aSopenharmony_ci } else { 1260cabdff1aSopenharmony_ci // These still need to be set for init_qp/slice_qp_delta. 1261cabdff1aSopenharmony_ci priv->fixed_qp_idr = 30; 1262cabdff1aSopenharmony_ci priv->fixed_qp_p = 30; 1263cabdff1aSopenharmony_ci priv->fixed_qp_b = 30; 1264cabdff1aSopenharmony_ci } 1265cabdff1aSopenharmony_ci 1266cabdff1aSopenharmony_ci ctx->roi_quant_range = 51 + 6 * (ctx->profile->depth - 8); 1267cabdff1aSopenharmony_ci 1268cabdff1aSopenharmony_ci return 0; 1269cabdff1aSopenharmony_ci} 1270cabdff1aSopenharmony_ci 1271cabdff1aSopenharmony_cistatic const VAAPIEncodeProfile vaapi_encode_h265_profiles[] = { 1272cabdff1aSopenharmony_ci { FF_PROFILE_HEVC_MAIN, 8, 3, 1, 1, VAProfileHEVCMain }, 1273cabdff1aSopenharmony_ci { FF_PROFILE_HEVC_REXT, 8, 3, 1, 1, VAProfileHEVCMain }, 1274cabdff1aSopenharmony_ci#if VA_CHECK_VERSION(0, 37, 0) 1275cabdff1aSopenharmony_ci { FF_PROFILE_HEVC_MAIN_10, 10, 3, 1, 1, VAProfileHEVCMain10 }, 1276cabdff1aSopenharmony_ci { FF_PROFILE_HEVC_REXT, 10, 3, 1, 1, VAProfileHEVCMain10 }, 1277cabdff1aSopenharmony_ci#endif 1278cabdff1aSopenharmony_ci#if VA_CHECK_VERSION(1, 2, 0) 1279cabdff1aSopenharmony_ci { FF_PROFILE_HEVC_REXT, 8, 3, 1, 0, VAProfileHEVCMain422_10 }, 1280cabdff1aSopenharmony_ci { FF_PROFILE_HEVC_REXT, 10, 3, 1, 0, VAProfileHEVCMain422_10 }, 1281cabdff1aSopenharmony_ci#endif 1282cabdff1aSopenharmony_ci { FF_PROFILE_UNKNOWN } 1283cabdff1aSopenharmony_ci}; 1284cabdff1aSopenharmony_ci 1285cabdff1aSopenharmony_cistatic const VAAPIEncodeType vaapi_encode_type_h265 = { 1286cabdff1aSopenharmony_ci .profiles = vaapi_encode_h265_profiles, 1287cabdff1aSopenharmony_ci 1288cabdff1aSopenharmony_ci .flags = FLAG_SLICE_CONTROL | 1289cabdff1aSopenharmony_ci FLAG_B_PICTURES | 1290cabdff1aSopenharmony_ci FLAG_B_PICTURE_REFERENCES | 1291cabdff1aSopenharmony_ci FLAG_NON_IDR_KEY_PICTURES, 1292cabdff1aSopenharmony_ci 1293cabdff1aSopenharmony_ci .default_quality = 25, 1294cabdff1aSopenharmony_ci 1295cabdff1aSopenharmony_ci .get_encoder_caps = &vaapi_encode_h265_get_encoder_caps, 1296cabdff1aSopenharmony_ci .configure = &vaapi_encode_h265_configure, 1297cabdff1aSopenharmony_ci 1298cabdff1aSopenharmony_ci .picture_priv_data_size = sizeof(VAAPIEncodeH265Picture), 1299cabdff1aSopenharmony_ci 1300cabdff1aSopenharmony_ci .sequence_params_size = sizeof(VAEncSequenceParameterBufferHEVC), 1301cabdff1aSopenharmony_ci .init_sequence_params = &vaapi_encode_h265_init_sequence_params, 1302cabdff1aSopenharmony_ci 1303cabdff1aSopenharmony_ci .picture_params_size = sizeof(VAEncPictureParameterBufferHEVC), 1304cabdff1aSopenharmony_ci .init_picture_params = &vaapi_encode_h265_init_picture_params, 1305cabdff1aSopenharmony_ci 1306cabdff1aSopenharmony_ci .slice_params_size = sizeof(VAEncSliceParameterBufferHEVC), 1307cabdff1aSopenharmony_ci .init_slice_params = &vaapi_encode_h265_init_slice_params, 1308cabdff1aSopenharmony_ci 1309cabdff1aSopenharmony_ci .sequence_header_type = VAEncPackedHeaderSequence, 1310cabdff1aSopenharmony_ci .write_sequence_header = &vaapi_encode_h265_write_sequence_header, 1311cabdff1aSopenharmony_ci 1312cabdff1aSopenharmony_ci .slice_header_type = VAEncPackedHeaderHEVC_Slice, 1313cabdff1aSopenharmony_ci .write_slice_header = &vaapi_encode_h265_write_slice_header, 1314cabdff1aSopenharmony_ci 1315cabdff1aSopenharmony_ci .write_extra_header = &vaapi_encode_h265_write_extra_header, 1316cabdff1aSopenharmony_ci}; 1317cabdff1aSopenharmony_ci 1318cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) 1319cabdff1aSopenharmony_ci{ 1320cabdff1aSopenharmony_ci VAAPIEncodeContext *ctx = avctx->priv_data; 1321cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 1322cabdff1aSopenharmony_ci 1323cabdff1aSopenharmony_ci ctx->codec = &vaapi_encode_type_h265; 1324cabdff1aSopenharmony_ci 1325cabdff1aSopenharmony_ci if (avctx->profile == FF_PROFILE_UNKNOWN) 1326cabdff1aSopenharmony_ci avctx->profile = priv->profile; 1327cabdff1aSopenharmony_ci if (avctx->level == FF_LEVEL_UNKNOWN) 1328cabdff1aSopenharmony_ci avctx->level = priv->level; 1329cabdff1aSopenharmony_ci 1330cabdff1aSopenharmony_ci if (avctx->level != FF_LEVEL_UNKNOWN && avctx->level & ~0xff) { 1331cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid level %d: must fit " 1332cabdff1aSopenharmony_ci "in 8-bit unsigned integer.\n", avctx->level); 1333cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1334cabdff1aSopenharmony_ci } 1335cabdff1aSopenharmony_ci 1336cabdff1aSopenharmony_ci ctx->desired_packed_headers = 1337cabdff1aSopenharmony_ci VA_ENC_PACKED_HEADER_SEQUENCE | // VPS, SPS and PPS. 1338cabdff1aSopenharmony_ci VA_ENC_PACKED_HEADER_SLICE | // Slice headers. 1339cabdff1aSopenharmony_ci VA_ENC_PACKED_HEADER_MISC; // SEI 1340cabdff1aSopenharmony_ci 1341cabdff1aSopenharmony_ci if (priv->qp > 0) 1342cabdff1aSopenharmony_ci ctx->explicit_qp = priv->qp; 1343cabdff1aSopenharmony_ci 1344cabdff1aSopenharmony_ci return ff_vaapi_encode_init(avctx); 1345cabdff1aSopenharmony_ci} 1346cabdff1aSopenharmony_ci 1347cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) 1348cabdff1aSopenharmony_ci{ 1349cabdff1aSopenharmony_ci VAAPIEncodeH265Context *priv = avctx->priv_data; 1350cabdff1aSopenharmony_ci 1351cabdff1aSopenharmony_ci ff_cbs_fragment_free(&priv->current_access_unit); 1352cabdff1aSopenharmony_ci ff_cbs_close(&priv->cbc); 1353cabdff1aSopenharmony_ci 1354cabdff1aSopenharmony_ci return ff_vaapi_encode_close(avctx); 1355cabdff1aSopenharmony_ci} 1356cabdff1aSopenharmony_ci 1357cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(VAAPIEncodeH265Context, x) 1358cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) 1359cabdff1aSopenharmony_cistatic const AVOption vaapi_encode_h265_options[] = { 1360cabdff1aSopenharmony_ci VAAPI_ENCODE_COMMON_OPTIONS, 1361cabdff1aSopenharmony_ci VAAPI_ENCODE_RC_OPTIONS, 1362cabdff1aSopenharmony_ci 1363cabdff1aSopenharmony_ci { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)", 1364cabdff1aSopenharmony_ci OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, FLAGS }, 1365cabdff1aSopenharmony_ci 1366cabdff1aSopenharmony_ci { "aud", "Include AUD", 1367cabdff1aSopenharmony_ci OFFSET(aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, 1368cabdff1aSopenharmony_ci 1369cabdff1aSopenharmony_ci { "profile", "Set profile (general_profile_idc)", 1370cabdff1aSopenharmony_ci OFFSET(profile), AV_OPT_TYPE_INT, 1371cabdff1aSopenharmony_ci { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xff, FLAGS, "profile" }, 1372cabdff1aSopenharmony_ci 1373cabdff1aSopenharmony_ci#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ 1374cabdff1aSopenharmony_ci { .i64 = value }, 0, 0, FLAGS, "profile" 1375cabdff1aSopenharmony_ci { PROFILE("main", FF_PROFILE_HEVC_MAIN) }, 1376cabdff1aSopenharmony_ci { PROFILE("main10", FF_PROFILE_HEVC_MAIN_10) }, 1377cabdff1aSopenharmony_ci { PROFILE("rext", FF_PROFILE_HEVC_REXT) }, 1378cabdff1aSopenharmony_ci#undef PROFILE 1379cabdff1aSopenharmony_ci 1380cabdff1aSopenharmony_ci { "tier", "Set tier (general_tier_flag)", 1381cabdff1aSopenharmony_ci OFFSET(tier), AV_OPT_TYPE_INT, 1382cabdff1aSopenharmony_ci { .i64 = 0 }, 0, 1, FLAGS, "tier" }, 1383cabdff1aSopenharmony_ci { "main", NULL, 0, AV_OPT_TYPE_CONST, 1384cabdff1aSopenharmony_ci { .i64 = 0 }, 0, 0, FLAGS, "tier" }, 1385cabdff1aSopenharmony_ci { "high", NULL, 0, AV_OPT_TYPE_CONST, 1386cabdff1aSopenharmony_ci { .i64 = 1 }, 0, 0, FLAGS, "tier" }, 1387cabdff1aSopenharmony_ci 1388cabdff1aSopenharmony_ci { "level", "Set level (general_level_idc)", 1389cabdff1aSopenharmony_ci OFFSET(level), AV_OPT_TYPE_INT, 1390cabdff1aSopenharmony_ci { .i64 = FF_LEVEL_UNKNOWN }, FF_LEVEL_UNKNOWN, 0xff, FLAGS, "level" }, 1391cabdff1aSopenharmony_ci 1392cabdff1aSopenharmony_ci#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ 1393cabdff1aSopenharmony_ci { .i64 = value }, 0, 0, FLAGS, "level" 1394cabdff1aSopenharmony_ci { LEVEL("1", 30) }, 1395cabdff1aSopenharmony_ci { LEVEL("2", 60) }, 1396cabdff1aSopenharmony_ci { LEVEL("2.1", 63) }, 1397cabdff1aSopenharmony_ci { LEVEL("3", 90) }, 1398cabdff1aSopenharmony_ci { LEVEL("3.1", 93) }, 1399cabdff1aSopenharmony_ci { LEVEL("4", 120) }, 1400cabdff1aSopenharmony_ci { LEVEL("4.1", 123) }, 1401cabdff1aSopenharmony_ci { LEVEL("5", 150) }, 1402cabdff1aSopenharmony_ci { LEVEL("5.1", 153) }, 1403cabdff1aSopenharmony_ci { LEVEL("5.2", 156) }, 1404cabdff1aSopenharmony_ci { LEVEL("6", 180) }, 1405cabdff1aSopenharmony_ci { LEVEL("6.1", 183) }, 1406cabdff1aSopenharmony_ci { LEVEL("6.2", 186) }, 1407cabdff1aSopenharmony_ci#undef LEVEL 1408cabdff1aSopenharmony_ci 1409cabdff1aSopenharmony_ci { "sei", "Set SEI to include", 1410cabdff1aSopenharmony_ci OFFSET(sei), AV_OPT_TYPE_FLAGS, 1411cabdff1aSopenharmony_ci { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, 1412cabdff1aSopenharmony_ci 0, INT_MAX, FLAGS, "sei" }, 1413cabdff1aSopenharmony_ci { "hdr", 1414cabdff1aSopenharmony_ci "Include HDR metadata for mastering display colour volume " 1415cabdff1aSopenharmony_ci "and content light level information", 1416cabdff1aSopenharmony_ci 0, AV_OPT_TYPE_CONST, 1417cabdff1aSopenharmony_ci { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, 1418cabdff1aSopenharmony_ci INT_MIN, INT_MAX, FLAGS, "sei" }, 1419cabdff1aSopenharmony_ci 1420cabdff1aSopenharmony_ci { "tiles", "Tile columns x rows", 1421cabdff1aSopenharmony_ci OFFSET(common.tile_cols), AV_OPT_TYPE_IMAGE_SIZE, 1422cabdff1aSopenharmony_ci { .str = NULL }, 0, 0, FLAGS }, 1423cabdff1aSopenharmony_ci 1424cabdff1aSopenharmony_ci { NULL }, 1425cabdff1aSopenharmony_ci}; 1426cabdff1aSopenharmony_ci 1427cabdff1aSopenharmony_cistatic const FFCodecDefault vaapi_encode_h265_defaults[] = { 1428cabdff1aSopenharmony_ci { "b", "0" }, 1429cabdff1aSopenharmony_ci { "bf", "2" }, 1430cabdff1aSopenharmony_ci { "g", "120" }, 1431cabdff1aSopenharmony_ci { "i_qfactor", "1" }, 1432cabdff1aSopenharmony_ci { "i_qoffset", "0" }, 1433cabdff1aSopenharmony_ci { "b_qfactor", "6/5" }, 1434cabdff1aSopenharmony_ci { "b_qoffset", "0" }, 1435cabdff1aSopenharmony_ci { "qmin", "-1" }, 1436cabdff1aSopenharmony_ci { "qmax", "-1" }, 1437cabdff1aSopenharmony_ci { NULL }, 1438cabdff1aSopenharmony_ci}; 1439cabdff1aSopenharmony_ci 1440cabdff1aSopenharmony_cistatic const AVClass vaapi_encode_h265_class = { 1441cabdff1aSopenharmony_ci .class_name = "h265_vaapi", 1442cabdff1aSopenharmony_ci .item_name = av_default_item_name, 1443cabdff1aSopenharmony_ci .option = vaapi_encode_h265_options, 1444cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 1445cabdff1aSopenharmony_ci}; 1446cabdff1aSopenharmony_ci 1447cabdff1aSopenharmony_ciconst FFCodec ff_hevc_vaapi_encoder = { 1448cabdff1aSopenharmony_ci .p.name = "hevc_vaapi", 1449cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"), 1450cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 1451cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_HEVC, 1452cabdff1aSopenharmony_ci .priv_data_size = sizeof(VAAPIEncodeH265Context), 1453cabdff1aSopenharmony_ci .init = &vaapi_encode_h265_init, 1454cabdff1aSopenharmony_ci FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), 1455cabdff1aSopenharmony_ci .close = &vaapi_encode_h265_close, 1456cabdff1aSopenharmony_ci .p.priv_class = &vaapi_encode_h265_class, 1457cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | 1458cabdff1aSopenharmony_ci AV_CODEC_CAP_DR1, 1459cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, 1460cabdff1aSopenharmony_ci .defaults = vaapi_encode_h265_defaults, 1461cabdff1aSopenharmony_ci .p.pix_fmts = (const enum AVPixelFormat[]) { 1462cabdff1aSopenharmony_ci AV_PIX_FMT_VAAPI, 1463cabdff1aSopenharmony_ci AV_PIX_FMT_NONE, 1464cabdff1aSopenharmony_ci }, 1465cabdff1aSopenharmony_ci .hw_configs = ff_vaapi_encode_hw_configs, 1466cabdff1aSopenharmony_ci .p.wrapper_name = "vaapi", 1467cabdff1aSopenharmony_ci}; 1468