From patchwork Sun Sep 1 00:02:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lynne X-Patchwork-Id: 51272 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:4027:b0:48e:c0f8:d0de with SMTP id ky39csp1134257vqb; Sat, 31 Aug 2024 17:03:40 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUHixqImQNTUrupQ1u6XfCmao5MbPoRNLL65P9siHwmU4eqJgdlpqXQ2a4ETsJWGoS+tSryrKEaL6fNFife/s9i@gmail.com X-Google-Smtp-Source: AGHT+IGIBTvoLxQCmMvoNIBGclvvL5aTSY62jDVSB+V3urmoSinoYaT2eNPUEonR9wPPWs2ELNNf X-Received: by 2002:a05:6000:4402:b0:374:c429:b066 with SMTP id ffacd0b85a97d-374c429b877mr933008f8f.63.1725149019879; Sat, 31 Aug 2024 17:03:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1725149019; cv=none; d=google.com; s=arc-20240605; b=CXYxVkCyOB9OFYjlu3rwnspYsnQePCUuUtorWC26yfLCVK+cAi/tT6wD6GtAStSGvj OyIZuD0/08PKzhHMluw8lsDYFTL9wKbNLo7ua3MD2eBfIjMrS/DqXiiOM79zhQywJL+a O4Z3hMsGq05ByYVYhXhv6B1b0qktFRbAp18erb4+q06TkFBRdd+SwDziH6KDMoVIo8Lj fhDA1LE2c4ExQarXfkmEVAPG3q8QJF4JOvwm/uFz8ZBjBiBxIpDqR/vtHzd9QS4q2NL1 UEEl3WDIp0vBZetZkVBolTc0oAnTyW16Z/p3WUtkx4UF6GWgw6101J/wdeShpJ6IZkDx SwJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to:from :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to :delivered-to; bh=Aik5ldyaPPQ3Sv6JHA/mtO7RFGSodXJsCQAMf0unoaI=; fh=nenT92/WZoU6unXd3J6UhGUdod4piddKfVtctNBOh6k=; b=KFpiS4tEZocfQIw/4UBWKhFdIhX3nng9kwo2qpX/Co8wZvi/yv+/XihpO2NqXm5/Jh LoZ5QVRu7apTG3d9kL+EjoFQzJeGLkID+gt+nzQ+ClesG9X/tb/mGgTQa3oGgOCqD3mj Gjegexa+kkdxXPEaQ9k6AQfyq/4ubPfMNhguH7Hqr5Bw3F8en190S35dn8oHW5SNHn89 54Apqec+lPgcelX1bpJKsqI31N55zuDBu0r/XzkzEL1uWgGLx0eT36sI+s96an85Jjxe ZUTEwJgCVIdvo5vdjFggSU7ICAgLS4j25Zq5QQYJiba2p8SCQalEcMjfWR+H6t5lKcP+ B1EQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a640c23a62f3a-a8988fb4d1esi500786766b.272.2024.08.31.17.03.39; Sat, 31 Aug 2024 17:03:39 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 634C068DECA; Sun, 1 Sep 2024 03:03:35 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from vidala.lynne.ee (vidala.pars.ee [116.203.72.101]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5BBE668DADC for ; Sun, 1 Sep 2024 03:03:28 +0300 (EEST) To: ffmpeg-devel@ffmpeg.org Date: Sun, 1 Sep 2024 02:02:59 +0200 Message-ID: <20240901000314.379276-1-dev@lynne.ee> X-Mailer: git-send-email 2.45.2.753.g447d99e1c3b MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 02/10] hw_base_encode: move VAAPI SPS/PPS constructors to a shared file X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Lynne via ffmpeg-devel From: Lynne Reply-To: FFmpeg development discussions and patches Cc: Lynne Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 07V9LrCTzhog --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode_h264.c | 265 +++++++++++++++++++++++++++++++ libavcodec/hw_base_encode_h264.h | 53 +++++++ libavcodec/vaapi_encode_h264.c | 262 +++--------------------------- 4 files changed, 341 insertions(+), 241 deletions(-) create mode 100644 libavcodec/hw_base_encode_h264.c create mode 100644 libavcodec/hw_base_encode_h264.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3b4b8681f5..2e53dd723a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -166,7 +166,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o hw_base_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE) += vaapi_encode.o hw_base_encode.o hw_base_encode_h264.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP) += videodsp.o diff --git a/libavcodec/hw_base_encode_h264.c b/libavcodec/hw_base_encode_h264.c new file mode 100644 index 0000000000..5c3957cddb --- /dev/null +++ b/libavcodec/hw_base_encode_h264.c @@ -0,0 +1,265 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hw_base_encode_h264.h" + +#include "h2645data.h" +#include "h264_levels.h" + +#include "libavutil/pixdesc.h" + +int ff_hw_base_encode_init_params_h264(FFHWBaseEncodeContext *base_ctx, + AVCodecContext *avctx, + FFHWBaseEncodeH264 *common, + FFHWBaseEncodeH264Opts *opts) +{ + H264RawSPS *sps = &common->raw_sps; + H264RawPPS *pps = &common->raw_pps; + const AVPixFmtDescriptor *desc; + int bit_depth; + + memset(sps, 0, sizeof(*sps)); + memset(pps, 0, sizeof(*pps)); + + desc = av_pix_fmt_desc_get(base_ctx->input_frames->sw_format); + av_assert0(desc); + if (desc->nb_components == 1 || desc->log2_chroma_w != 1 || desc->log2_chroma_h != 1) { + av_log(avctx, AV_LOG_ERROR, "Chroma format of input pixel format " + "%s is not supported.\n", desc->name); + return AVERROR(EINVAL); + } + bit_depth = desc->comp[0].depth; + + sps->nal_unit_header.nal_ref_idc = 3; + sps->nal_unit_header.nal_unit_type = H264_NAL_SPS; + + sps->profile_idc = avctx->profile & 0xff; + + if (avctx->profile == AV_PROFILE_H264_CONSTRAINED_BASELINE || + avctx->profile == AV_PROFILE_H264_MAIN) + sps->constraint_set1_flag = 1; + + if (avctx->profile == AV_PROFILE_H264_HIGH || avctx->profile == AV_PROFILE_H264_HIGH_10) + sps->constraint_set3_flag = base_ctx->gop_size == 1; + + if (avctx->profile == AV_PROFILE_H264_MAIN || + avctx->profile == AV_PROFILE_H264_HIGH || avctx->profile == AV_PROFILE_H264_HIGH_10) { + sps->constraint_set4_flag = 1; + sps->constraint_set5_flag = base_ctx->b_per_p == 0; + } + + if (base_ctx->gop_size == 1) + common->dpb_frames = 0; + else + common->dpb_frames = 1 + base_ctx->max_b_depth; + + if (avctx->level != AV_LEVEL_UNKNOWN) { + sps->level_idc = avctx->level; + } else { + const H264LevelDescriptor *level; + int framerate; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + framerate = avctx->framerate.num / avctx->framerate.den; + else + framerate = 0; + + level = ff_h264_guess_level(sps->profile_idc, + opts->bit_rate, + framerate, + common->mb_width * 16, + common->mb_height * 16, + common->dpb_frames); + if (level) { + av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); + if (level->constraint_set3_flag) + sps->constraint_set3_flag = 1; + sps->level_idc = level->level_idc; + } else { + av_log(avctx, AV_LOG_WARNING, "Stream will not conform " + "to any level: using level 6.2.\n"); + sps->level_idc = 62; + } + } + + sps->seq_parameter_set_id = 0; + sps->chroma_format_idc = 1; + sps->bit_depth_luma_minus8 = bit_depth - 8; + sps->bit_depth_chroma_minus8 = bit_depth - 8; + + sps->log2_max_frame_num_minus4 = 4; + sps->pic_order_cnt_type = base_ctx->max_b_depth ? 0 : 2; + if (sps->pic_order_cnt_type == 0) { + sps->log2_max_pic_order_cnt_lsb_minus4 = 4; + } + + sps->max_num_ref_frames = common->dpb_frames; + + sps->pic_width_in_mbs_minus1 = common->mb_width - 1; + sps->pic_height_in_map_units_minus1 = common->mb_height - 1; + + sps->frame_mbs_only_flag = 1; + sps->direct_8x8_inference_flag = 1; + + if (avctx->width != 16 * common->mb_width || + avctx->height != 16 * common->mb_height) { + sps->frame_cropping_flag = 1; + + sps->frame_crop_left_offset = 0; + sps->frame_crop_right_offset = + (16 * common->mb_width - avctx->width) / 2; + sps->frame_crop_top_offset = 0; + sps->frame_crop_bottom_offset = + (16 * common->mb_height - avctx->height) / 2; + } else { + sps->frame_cropping_flag = 0; + } + + sps->vui_parameters_present_flag = 1; + + if (avctx->sample_aspect_ratio.num != 0 && + avctx->sample_aspect_ratio.den != 0) { + int num, den, i; + av_reduce(&num, &den, avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den, 65535); + for (i = 0; i < FF_ARRAY_ELEMS(ff_h2645_pixel_aspect); i++) { + if (num == ff_h2645_pixel_aspect[i].num && + den == ff_h2645_pixel_aspect[i].den) { + sps->vui.aspect_ratio_idc = i; + break; + } + } + if (i >= FF_ARRAY_ELEMS(ff_h2645_pixel_aspect)) { + sps->vui.aspect_ratio_idc = 255; + sps->vui.sar_width = num; + sps->vui.sar_height = den; + } + sps->vui.aspect_ratio_info_present_flag = 1; + } + + // Unspecified video format, from table E-2. + sps->vui.video_format = 5; + sps->vui.video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + sps->vui.colour_primaries = avctx->color_primaries; + sps->vui.transfer_characteristics = avctx->color_trc; + sps->vui.matrix_coefficients = avctx->colorspace; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) + sps->vui.colour_description_present_flag = 1; + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + sps->vui.colour_description_present_flag) + sps->vui.video_signal_type_present_flag = 1; + + if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { + sps->vui.chroma_loc_info_present_flag = 1; + sps->vui.chroma_sample_loc_type_top_field = + sps->vui.chroma_sample_loc_type_bottom_field = + avctx->chroma_sample_location - 1; + } + + sps->vui.timing_info_present_flag = 1; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + sps->vui.num_units_in_tick = avctx->framerate.den; + sps->vui.time_scale = 2 * avctx->framerate.num; + sps->vui.fixed_frame_rate_flag = 1; + } else { + sps->vui.num_units_in_tick = avctx->time_base.num; + sps->vui.time_scale = 2 * avctx->time_base.den; + sps->vui.fixed_frame_rate_flag = 0; + } + + if (opts->flags & FF_HW_H264_SEI_TIMING) { + H264RawHRD *hrd = &sps->vui.nal_hrd_parameters; + H264RawSEIBufferingPeriod *bp = &common->sei_buffering_period; + + sps->vui.nal_hrd_parameters_present_flag = 1; + + hrd->cpb_cnt_minus1 = 0; + + // Try to scale these to a sensible range so that the + // golomb encode of the value is not overlong. + hrd->bit_rate_scale = + av_clip_uintp2(av_log2(opts->bit_rate) - 15 - 6, 4); + hrd->bit_rate_value_minus1[0] = + (opts->bit_rate >> hrd->bit_rate_scale + 6) - 1; + + hrd->cpb_size_scale = + av_clip_uintp2(av_log2(opts->hrd_buffer_size) - 15 - 4, 4); + hrd->cpb_size_value_minus1[0] = + (opts->hrd_buffer_size >> hrd->cpb_size_scale + 4) - 1; + + // CBR mode as defined for the HRD cannot be achieved without filler + // data, so this flag cannot be set even with VAAPI CBR modes. + hrd->cbr_flag[0] = 0; + + hrd->initial_cpb_removal_delay_length_minus1 = 23; + hrd->cpb_removal_delay_length_minus1 = 23; + hrd->dpb_output_delay_length_minus1 = 7; + hrd->time_offset_length = 0; + + bp->seq_parameter_set_id = sps->seq_parameter_set_id; + + // This calculation can easily overflow 32 bits. + bp->nal.initial_cpb_removal_delay[0] = 90000 * + (uint64_t)opts->initial_buffer_fullness / + opts->hrd_buffer_size; + bp->nal.initial_cpb_removal_delay_offset[0] = 0; + } else { + sps->vui.nal_hrd_parameters_present_flag = 0; + sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag; + } + + sps->vui.bitstream_restriction_flag = 1; + sps->vui.motion_vectors_over_pic_boundaries_flag = 1; + sps->vui.log2_max_mv_length_horizontal = 15; + sps->vui.log2_max_mv_length_vertical = 15; + sps->vui.max_num_reorder_frames = base_ctx->max_b_depth; + sps->vui.max_dec_frame_buffering = base_ctx->max_b_depth + 1; + + pps->nal_unit_header.nal_ref_idc = 3; + pps->nal_unit_header.nal_unit_type = H264_NAL_PPS; + + pps->pic_parameter_set_id = 0; + pps->seq_parameter_set_id = 0; + + pps->entropy_coding_mode_flag = + !(sps->profile_idc == AV_PROFILE_H264_BASELINE || + sps->profile_idc == AV_PROFILE_H264_EXTENDED || + sps->profile_idc == AV_PROFILE_H264_CAVLC_444); + if (!opts->cabac && pps->entropy_coding_mode_flag) + pps->entropy_coding_mode_flag = 0; + + pps->num_ref_idx_l0_default_active_minus1 = 0; + pps->num_ref_idx_l1_default_active_minus1 = 0; + + pps->pic_init_qp_minus26 = opts->fixed_qp_idr - 26; + + if (sps->profile_idc == AV_PROFILE_H264_BASELINE || + sps->profile_idc == AV_PROFILE_H264_EXTENDED || + sps->profile_idc == AV_PROFILE_H264_MAIN) { + pps->more_rbsp_data = 0; + } else { + pps->more_rbsp_data = 1; + + pps->transform_8x8_mode_flag = 1; + } + + return 0; +} diff --git a/libavcodec/hw_base_encode_h264.h b/libavcodec/hw_base_encode_h264.h new file mode 100644 index 0000000000..d1bae8f36f --- /dev/null +++ b/libavcodec/hw_base_encode_h264.h @@ -0,0 +1,53 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H264_H +#define AVCODEC_HW_BASE_ENCODE_H264_H + +#include "hw_base_encode.h" +#include "cbs_h264.h" + +typedef struct FFHWBaseEncodeH264 { + H264RawSPS raw_sps; + H264RawPPS raw_pps; + H264RawAUD raw_aud; + + H264RawSEIBufferingPeriod sei_buffering_period; + + int dpb_frames; + int mb_width; + int mb_height; +} FFHWBaseEncodeH264; + +typedef struct FFHWBaseEncodeH264Opts { + int flags; +#define FF_HW_H264_SEI_TIMING (1 << 0) + + int64_t bit_rate; + int cabac; + int fixed_qp_idr; + uint64_t hrd_buffer_size; + uint64_t initial_buffer_fullness; +} FFHWBaseEncodeH264Opts; + +int ff_hw_base_encode_init_params_h264(FFHWBaseEncodeContext *base_ctx, + AVCodecContext *avctx, + FFHWBaseEncodeH264 *common, + FFHWBaseEncodeH264Opts *opts); + +#endif /* AVCODEC_HW_BASE_ENCODE_H264_H */ diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 35d3967766..443a569104 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -33,6 +33,7 @@ #include "cbs_h264.h" #include "codec_internal.h" #include "h264.h" +#include "hw_base_encode_h264.h" #include "h264_levels.h" #include "h2645data.h" #include "vaapi_encode.h" @@ -67,6 +68,7 @@ typedef struct VAAPIEncodeH264Picture { typedef struct VAAPIEncodeH264Context { VAAPIEncodeContext common; + FFHWBaseEncodeH264 units; // User options. int qp; @@ -85,15 +87,11 @@ typedef struct VAAPIEncodeH264Context { int fixed_qp_p; int fixed_qp_b; - int dpb_frames; - // Writer structures. CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; H264RawAUD raw_aud; - H264RawSPS raw_sps; - H264RawPPS raw_pps; H264RawSlice raw_slice; H264RawSEIBufferingPeriod sei_buffering_period; @@ -168,11 +166,11 @@ static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx, priv->aud_needed = 0; } - err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_sps); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->units.raw_sps); if (err < 0) goto fail; - err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_pps); + err = vaapi_encode_h264_add_nal(avctx, au, &priv->units.raw_pps); if (err < 0) goto fail; @@ -298,240 +296,24 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) FFHWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH264Context *priv = avctx->priv_data; - H264RawSPS *sps = &priv->raw_sps; - H264RawPPS *pps = &priv->raw_pps; + H264RawSPS *sps = &priv->units.raw_sps; + H264RawPPS *pps = &priv->units.raw_pps; VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params; VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params; - const AVPixFmtDescriptor *desc; - int bit_depth; - - memset(sps, 0, sizeof(*sps)); - memset(pps, 0, sizeof(*pps)); - - desc = av_pix_fmt_desc_get(base_ctx->input_frames->sw_format); - av_assert0(desc); - if (desc->nb_components == 1 || desc->log2_chroma_w != 1 || desc->log2_chroma_h != 1) { - av_log(avctx, AV_LOG_ERROR, "Chroma format of input pixel format " - "%s is not supported.\n", desc->name); - return AVERROR(EINVAL); - } - bit_depth = desc->comp[0].depth; - - sps->nal_unit_header.nal_ref_idc = 3; - sps->nal_unit_header.nal_unit_type = H264_NAL_SPS; - - sps->profile_idc = avctx->profile & 0xff; - - if (avctx->profile == AV_PROFILE_H264_CONSTRAINED_BASELINE || - avctx->profile == AV_PROFILE_H264_MAIN) - sps->constraint_set1_flag = 1; - - if (avctx->profile == AV_PROFILE_H264_HIGH || avctx->profile == AV_PROFILE_H264_HIGH_10) - sps->constraint_set3_flag = base_ctx->gop_size == 1; - - if (avctx->profile == AV_PROFILE_H264_MAIN || - avctx->profile == AV_PROFILE_H264_HIGH || avctx->profile == AV_PROFILE_H264_HIGH_10) { - sps->constraint_set4_flag = 1; - sps->constraint_set5_flag = base_ctx->b_per_p == 0; - } - - if (base_ctx->gop_size == 1) - priv->dpb_frames = 0; - else - priv->dpb_frames = 1 + base_ctx->max_b_depth; - - if (avctx->level != AV_LEVEL_UNKNOWN) { - sps->level_idc = avctx->level; - } else { - const H264LevelDescriptor *level; - int framerate; - - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - framerate = avctx->framerate.num / avctx->framerate.den; - else - framerate = 0; - - level = ff_h264_guess_level(sps->profile_idc, - avctx->bit_rate, - framerate, - priv->mb_width * 16, - priv->mb_height * 16, - priv->dpb_frames); - if (level) { - av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); - if (level->constraint_set3_flag) - sps->constraint_set3_flag = 1; - sps->level_idc = level->level_idc; - } else { - av_log(avctx, AV_LOG_WARNING, "Stream will not conform " - "to any level: using level 6.2.\n"); - sps->level_idc = 62; - } - } - - sps->seq_parameter_set_id = 0; - sps->chroma_format_idc = 1; - sps->bit_depth_luma_minus8 = bit_depth - 8; - sps->bit_depth_chroma_minus8 = bit_depth - 8; - - sps->log2_max_frame_num_minus4 = 4; - sps->pic_order_cnt_type = base_ctx->max_b_depth ? 0 : 2; - if (sps->pic_order_cnt_type == 0) { - sps->log2_max_pic_order_cnt_lsb_minus4 = 4; - } - - sps->max_num_ref_frames = priv->dpb_frames; - - sps->pic_width_in_mbs_minus1 = priv->mb_width - 1; - sps->pic_height_in_map_units_minus1 = priv->mb_height - 1; - - sps->frame_mbs_only_flag = 1; - sps->direct_8x8_inference_flag = 1; - - if (avctx->width != 16 * priv->mb_width || - avctx->height != 16 * priv->mb_height) { - sps->frame_cropping_flag = 1; - - sps->frame_crop_left_offset = 0; - sps->frame_crop_right_offset = - (16 * priv->mb_width - avctx->width) / 2; - sps->frame_crop_top_offset = 0; - sps->frame_crop_bottom_offset = - (16 * priv->mb_height - avctx->height) / 2; - } else { - sps->frame_cropping_flag = 0; - } - - sps->vui_parameters_present_flag = 1; - - if (avctx->sample_aspect_ratio.num != 0 && - avctx->sample_aspect_ratio.den != 0) { - int num, den, i; - av_reduce(&num, &den, avctx->sample_aspect_ratio.num, - avctx->sample_aspect_ratio.den, 65535); - for (i = 0; i < FF_ARRAY_ELEMS(ff_h2645_pixel_aspect); i++) { - if (num == ff_h2645_pixel_aspect[i].num && - den == ff_h2645_pixel_aspect[i].den) { - sps->vui.aspect_ratio_idc = i; - break; - } - } - if (i >= FF_ARRAY_ELEMS(ff_h2645_pixel_aspect)) { - sps->vui.aspect_ratio_idc = 255; - sps->vui.sar_width = num; - sps->vui.sar_height = den; - } - sps->vui.aspect_ratio_info_present_flag = 1; - } - - // Unspecified video format, from table E-2. - sps->vui.video_format = 5; - sps->vui.video_full_range_flag = - avctx->color_range == AVCOL_RANGE_JPEG; - sps->vui.colour_primaries = avctx->color_primaries; - sps->vui.transfer_characteristics = avctx->color_trc; - sps->vui.matrix_coefficients = avctx->colorspace; - if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || - avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - avctx->colorspace != AVCOL_SPC_UNSPECIFIED) - sps->vui.colour_description_present_flag = 1; - if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || - sps->vui.colour_description_present_flag) - sps->vui.video_signal_type_present_flag = 1; - - if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { - sps->vui.chroma_loc_info_present_flag = 1; - sps->vui.chroma_sample_loc_type_top_field = - sps->vui.chroma_sample_loc_type_bottom_field = - avctx->chroma_sample_location - 1; - } - - sps->vui.timing_info_present_flag = 1; - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - sps->vui.num_units_in_tick = avctx->framerate.den; - sps->vui.time_scale = 2 * avctx->framerate.num; - sps->vui.fixed_frame_rate_flag = 1; - } else { - sps->vui.num_units_in_tick = avctx->time_base.num; - sps->vui.time_scale = 2 * avctx->time_base.den; - sps->vui.fixed_frame_rate_flag = 0; - } - - if (priv->sei & SEI_TIMING) { - H264RawHRD *hrd = &sps->vui.nal_hrd_parameters; - H264RawSEIBufferingPeriod *bp = &priv->sei_buffering_period; - - sps->vui.nal_hrd_parameters_present_flag = 1; - - hrd->cpb_cnt_minus1 = 0; - - // Try to scale these to a sensible range so that the - // golomb encode of the value is not overlong. - hrd->bit_rate_scale = - av_clip_uintp2(av_log2(ctx->va_bit_rate) - 15 - 6, 4); - hrd->bit_rate_value_minus1[0] = - (ctx->va_bit_rate >> hrd->bit_rate_scale + 6) - 1; - - hrd->cpb_size_scale = - av_clip_uintp2(av_log2(ctx->hrd_params.buffer_size) - 15 - 4, 4); - hrd->cpb_size_value_minus1[0] = - (ctx->hrd_params.buffer_size >> hrd->cpb_size_scale + 4) - 1; - - // CBR mode as defined for the HRD cannot be achieved without filler - // data, so this flag cannot be set even with VAAPI CBR modes. - hrd->cbr_flag[0] = 0; - hrd->initial_cpb_removal_delay_length_minus1 = 23; - hrd->cpb_removal_delay_length_minus1 = 23; - hrd->dpb_output_delay_length_minus1 = 7; - hrd->time_offset_length = 0; - - bp->seq_parameter_set_id = sps->seq_parameter_set_id; - - // This calculation can easily overflow 32 bits. - bp->nal.initial_cpb_removal_delay[0] = 90000 * - (uint64_t)ctx->hrd_params.initial_buffer_fullness / - ctx->hrd_params.buffer_size; - bp->nal.initial_cpb_removal_delay_offset[0] = 0; - } else { - sps->vui.nal_hrd_parameters_present_flag = 0; - sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag; - } - - sps->vui.bitstream_restriction_flag = 1; - sps->vui.motion_vectors_over_pic_boundaries_flag = 1; - sps->vui.log2_max_mv_length_horizontal = 15; - sps->vui.log2_max_mv_length_vertical = 15; - sps->vui.max_num_reorder_frames = base_ctx->max_b_depth; - sps->vui.max_dec_frame_buffering = base_ctx->max_b_depth + 1; - - pps->nal_unit_header.nal_ref_idc = 3; - pps->nal_unit_header.nal_unit_type = H264_NAL_PPS; - - pps->pic_parameter_set_id = 0; - pps->seq_parameter_set_id = 0; - - pps->entropy_coding_mode_flag = - !(sps->profile_idc == AV_PROFILE_H264_BASELINE || - sps->profile_idc == AV_PROFILE_H264_EXTENDED || - sps->profile_idc == AV_PROFILE_H264_CAVLC_444); - if (!priv->coder && pps->entropy_coding_mode_flag) - pps->entropy_coding_mode_flag = 0; - - pps->num_ref_idx_l0_default_active_minus1 = 0; - pps->num_ref_idx_l1_default_active_minus1 = 0; - - pps->pic_init_qp_minus26 = priv->fixed_qp_idr - 26; - - if (sps->profile_idc == AV_PROFILE_H264_BASELINE || - sps->profile_idc == AV_PROFILE_H264_EXTENDED || - sps->profile_idc == AV_PROFILE_H264_MAIN) { - pps->more_rbsp_data = 0; - } else { - pps->more_rbsp_data = 1; + FFHWBaseEncodeH264Opts unit_opts = { + .flags = (priv->sei & SEI_TIMING) ? FF_HW_H264_SEI_TIMING : 0, + .cabac = priv->coder, + .hrd_buffer_size = ctx->hrd_params.buffer_size, + .fixed_qp_idr = priv->fixed_qp_idr, + .initial_buffer_fullness = ctx->hrd_params.initial_buffer_fullness, + .bit_rate = ctx->va_bit_rate, + }; - pps->transform_8x8_mode_flag = 1; - } + int err = ff_hw_base_encode_init_params_h264(base_ctx, avctx, + &priv->units, &unit_opts); + if (err < 0) + return err; *vseq = (VAEncSequenceParameterBufferH264) { .seq_parameter_set_id = sps->seq_parameter_set_id, @@ -660,7 +442,7 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, } } hpic->pic_order_cnt = pic->display_order - hpic->last_idr_frame; - if (priv->raw_sps.pic_order_cnt_type == 2) { + if (priv->units.raw_sps.pic_order_cnt_type == 2) { hpic->pic_order_cnt *= 2; } @@ -870,8 +652,8 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, VAAPIEncodePicture *vaapi_pic = pic->priv; VAAPIEncodeH264Picture *hpic = pic->codec_priv; FFHWBaseEncodePicture *prev = pic->prev; - H264RawSPS *sps = &priv->raw_sps; - H264RawPPS *pps = &priv->raw_pps; + H264RawSPS *sps = &priv->units.raw_sps; + H264RawPPS *pps = &priv->units.raw_pps; H264RawSliceHeader *sh = &priv->raw_slice.header; VAEncPictureParameterBufferH264 *vpic = vaapi_pic->codec_picture_params; VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params; @@ -923,7 +705,7 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, ++keep; } } - av_assert0(keep <= priv->dpb_frames); + av_assert0(keep <= priv->units.dpb_frames); if (discard == 0) { sh->adaptive_ref_pic_marking_mode_flag = 0;