/* * 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 <string.h> #include <va/va.h>#include <va/va_enc_hevc.h> #include "libavutil/avassert.h"#include "libavutil/common.h"#include "libavutil/pixdesc.h"#include "libavutil/opt.h"#include "libavutil/mastering_display_metadata.h" #include "avcodec.h"#include "cbs.h"#include "cbs_h265.h"#include "h265_profile_level.h"#include "hevc.h"#include "hevc_sei.h"#include "internal.h"#include "put_bits.h"#include "vaapi_encode.h" enum { SEI_MASTERING_DISPLAY = 0x08, SEI_CONTENT_LIGHT_LEVEL = 0x10,}; typedef struct VAAPIEncodeH265Picture { int pic_order_cnt; int64_t last_idr_frame; int slice_nal_unit; int slice_type; int pic_type;} VAAPIEncodeH265Picture; typedef struct VAAPIEncodeH265Context { VAAPIEncodeContext common; // User options. int qp; int aud; int profile; int tier; int level; int sei; // Derived settings. int fixed_qp_idr; int fixed_qp_p; int fixed_qp_b; // Writer structures. H265RawAUD raw_aud; H265RawVPS raw_vps; H265RawSPS raw_sps; H265RawPPS raw_pps; H265RawSlice raw_slice; SEIRawMasteringDisplayColourVolume sei_mastering_display; SEIRawContentLightLevelInfo sei_content_light_level; CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; int aud_needed; int sei_needed;} VAAPIEncodeH265Context; static int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, char *data, size_t *data_len, CodedBitstreamFragment *au){ VAAPIEncodeH265Context *priv = avctx->priv_data; int err; err = ff_cbs_write_fragment_data(priv->cbc, au); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); return err; } if (*data_len < 8 * au->data_size - au->data_bit_padding) { av_log(avctx, AV_LOG_ERROR, "Access unit too large: " "%zu < %zu.\n", *data_len, 8 * au->data_size - au->data_bit_padding); return AVERROR(ENOSPC); } memcpy(data, au->data, au->data_size); *data_len = 8 * au->data_size - au->data_bit_padding; return 0;} static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, CodedBitstreamFragment *au, void *nal_unit){ H265RawNALUnitHeader *header = nal_unit; int err; err = ff_cbs_insert_unit_content(au, -1, header->nal_unit_type, nal_unit, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " "type = %d.\n", header->nal_unit_type); return err; } return 0;} static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len){ VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; int err; if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_aud); if (err < 0) goto fail; priv->aud_needed = 0; } err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_vps); if (err < 0) goto fail; err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_sps); if (err < 0) goto fail; err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_pps); if (err < 0) goto fail; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au);fail: ff_cbs_fragment_reset(au); return err;} static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice, char *data, size_t *data_len){ VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; int err; if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_aud); if (err < 0) goto fail; priv->aud_needed = 0; } err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_slice); if (err < 0) goto fail; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au);fail: ff_cbs_fragment_reset(au); return err;} static int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int index, int *type, char *data, size_t *data_len){ VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; int err; if (priv->sei_needed) { if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); if (err < 0) goto fail; priv->aud_needed = 0; } if (priv->sei_needed & SEI_MASTERING_DISPLAY) { err = ff_cbs_sei_add_message(priv->cbc, au, 1, SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME, &priv->sei_mastering_display, NULL); if (err < 0) goto fail; } if (priv->sei_needed & SEI_CONTENT_LIGHT_LEVEL) { err = ff_cbs_sei_add_message(priv->cbc, au, 1, SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO, &priv->sei_content_light_level, NULL); if (err < 0) goto fail; } priv->sei_needed = 0; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); if (err < 0) goto fail; ff_cbs_fragment_reset(au); *type = VAEncPackedHeaderRawData; return 0; } else { return AVERROR_EOF; } fail: ff_cbs_fragment_reset(au); return err;} static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx){ VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = avctx->priv_data; H265RawVPS *vps = &priv->raw_vps; H265RawSPS *sps = &priv->raw_sps; H265RawPPS *pps = &priv->raw_pps; H265RawProfileTierLevel *ptl = &vps->profile_tier_level; H265RawVUI *vui = &sps->vui; VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; const AVPixFmtDescriptor *desc; int chroma_format, bit_depth; int i; memset(vps, 0, sizeof(*vps)); memset(sps, 0, sizeof(*sps)); memset(pps, 0, sizeof(*pps)); desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format); av_assert0(desc); if (desc->nb_components == 1) { chroma_format = 0; } else { if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) { chroma_format = 1; } else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 0) { chroma_format = 2; } else if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) { chroma_format = 3; } else { 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; // VPS vps->nal_unit_header = (H265RawNALUnitHeader) { .nal_unit_type = HEVC_NAL_VPS, .nuh_layer_id = 0, .nuh_temporal_id_plus1 = 1, }; vps->vps_video_parameter_set_id = 0; vps->vps_base_layer_internal_flag = 1; vps->vps_base_layer_available_flag = 1; vps->vps_max_layers_minus1 = 0; vps->vps_max_sub_layers_minus1 = 0; vps->vps_temporal_id_nesting_flag = 1; ptl->general_profile_space = 0; ptl->general_profile_idc = avctx->profile; ptl->general_tier_flag = priv->tier; if (chroma_format == 1) { ptl->general_profile_compatibility_flag[1] = bit_depth == 8; ptl->general_profile_compatibility_flag[2] = bit_depth <= 10; } ptl->general_profile_compatibility_flag[4] = 1; ptl->general_progressive_source_flag = 1; ptl->general_interlaced_source_flag = 0; ptl->general_non_packed_constraint_flag = 1; ptl->general_frame_only_constraint_flag = 1; ptl->general_max_12bit_constraint_flag = bit_depth <= 12; ptl->general_max_10bit_constraint_flag = bit_depth <= 10; ptl->general_max_8bit_constraint_flag = bit_depth == 8; ptl->general_max_422chroma_constraint_flag = chroma_format <= 2; ptl->general_max_420chroma_constraint_flag = chroma_format <= 1; ptl->general_max_monochrome_constraint_flag = chroma_format == 0; ptl->general_intra_constraint_flag = ctx->gop_size == 1; ptl->general_lower_bit_rate_constraint_flag = 1; if (avctx->level != FF_LEVEL_UNKNOWN) { ptl->general_level_idc = avctx->level; } else { const H265LevelDescriptor *level; level = ff_h265_guess_level(ptl, avctx->bit_rate, ctx->surface_width, ctx->surface_height, ctx->nb_slices, ctx->tile_rows, ctx->tile_cols, (ctx->b_per_p > 0) + 1); if (level) { av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); ptl->general_level_idc = level->level_idc; } else { av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to " "any normal level; using level 8.5.\n"); ptl->general_level_idc = 255; // The tier flag must be set in level 8.5. ptl->general_tier_flag = 1; } } vps->vps_sub_layer_ordering_info_present_flag = 0; vps->vps_max_dec_pic_buffering_minus1[0] = ctx->max_b_depth + 1; vps->vps_max_num_reorder_pics[0] = ctx->max_b_depth; vps->vps_max_latency_increase_plus1[0] = 0; vps->vps_max_layer_id = 0; vps->vps_num_layer_sets_minus1 = 0; vps->layer_id_included_flag[0][0] = 1; vps->vps_timing_info_present_flag = 1; if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { vps->vps_num_units_in_tick = avctx->framerate.den; vps->vps_time_scale = avctx->framerate.num; vps->vps_poc_proportional_to_timing_flag = 1; vps->vps_num_ticks_poc_diff_one_minus1 = 0; } else { vps->vps_num_units_in_tick = avctx->time_base.num; vps->vps_time_scale = avctx->time_base.den; vps->vps_poc_proportional_to_timing_flag = 0; } vps->vps_num_hrd_parameters = 0; // SPS sps->nal_unit_header = (H265RawNALUnitHeader) { .nal_unit_type = HEVC_NAL_SPS, .nuh_layer_id = 0, .nuh_temporal_id_plus1 = 1, }; sps->sps_video_parameter_set_id = vps->vps_video_parameter_set_id; sps->sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1; sps->sps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag; sps->profile_tier_level = vps->profile_tier_level; sps->sps_seq_parameter_set_id = 0; sps->chroma_format_idc = chroma_format; sps->separate_colour_plane_flag = 0; sps->pic_width_in_luma_samples = ctx->surface_width; sps->pic_height_in_luma_samples = ctx->surface_height; if (avctx->width != ctx->surface_width || avctx->height != ctx->surface_height) { sps->conformance_window_flag = 1; sps->conf_win_left_offset = 0; sps->conf_win_right_offset = (ctx->surface_width - avctx->width) >> desc->log2_chroma_w; sps->conf_win_top_offset = 0; sps->conf_win_bottom_offset = (ctx->surface_height - avctx->height) >> desc->log2_chroma_h; } else { sps->conformance_window_flag = 0; } sps->bit_depth_luma_minus8 = bit_depth - 8; sps->bit_depth_chroma_minus8 = bit_depth - 8; sps->log2_max_pic_order_cnt_lsb_minus4 = 8; sps->sps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag; for (i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { sps->sps_max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering_minus1[i]; sps->sps_max_num_reorder_pics[i] = vps->vps_max_num_reorder_pics[i]; sps->sps_max_latency_increase_plus1[i] = vps->vps_max_latency_increase_plus1[i]; } // These have to come from the capabilities of the encoder. We have no // way to query them, so just hardcode parameters which work on the Intel // driver. // CTB size from 8x8 to 32x32. sps->log2_min_luma_coding_block_size_minus3 = 0; sps->log2_diff_max_min_luma_coding_block_size = 2; // Transform size from 4x4 to 32x32. sps->log2_min_luma_transform_block_size_minus2 = 0; sps->log2_diff_max_min_luma_transform_block_size = 3; // Full transform hierarchy allowed (2-5). sps->max_transform_hierarchy_depth_inter = 3; sps->max_transform_hierarchy_depth_intra = 3; // AMP works. sps->amp_enabled_flag = 1; // SAO and temporal MVP do not work. sps->sample_adaptive_offset_enabled_flag = 0; sps->sps_temporal_mvp_enabled_flag = 0; sps->pcm_enabled_flag = 0; // STRPSs should ideally be here rather than defined individually in // each slice, but the structure isn't completely fixed so for now // don't bother. sps->num_short_term_ref_pic_sets = 0; sps->long_term_ref_pics_present_flag = 0; sps->vui_parameters_present_flag = 1; if (avctx->sample_aspect_ratio.num != 0 && avctx->sample_aspect_ratio.den != 0) { static const AVRational sar_idc[] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; 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(sar_idc); i++) { if (num == sar_idc[i].num && den == sar_idc[i].den) { vui->aspect_ratio_idc = i; break; } } if (i >= FF_ARRAY_ELEMS(sar_idc)) { vui->aspect_ratio_idc = 255; vui->sar_width = num; vui->sar_height = den; } vui->aspect_ratio_info_present_flag = 1; } // Unspecified video format, from table E-2. vui->video_format = 5; vui->video_full_range_flag = avctx->color_range == AVCOL_RANGE_JPEG; vui->colour_primaries = avctx->color_primaries; vui->transfer_characteristics = avctx->color_trc; vui->matrix_coefficients = avctx->colorspace; if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || avctx->colorspace != AVCOL_SPC_UNSPECIFIED) vui->colour_description_present_flag = 1; if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || vui->colour_description_present_flag) vui->video_signal_type_present_flag = 1; if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { vui->chroma_loc_info_present_flag = 1; vui->chroma_sample_loc_type_top_field = vui->chroma_sample_loc_type_bottom_field = avctx->chroma_sample_location - 1; } vui->vui_timing_info_present_flag = 1; vui->vui_num_units_in_tick = vps->vps_num_units_in_tick; vui->vui_time_scale = vps->vps_time_scale;Lines 1–500 of 1324. Load more
/* * 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 <string.h> #include <va/va.h> #include <va/va_enc_hevc.h> #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "libavutil/mastering_display_metadata.h" #include "avcodec.h" #include "cbs.h" #include "cbs_h265.h" #include "h265_profile_level.h" #include "hevc.h" #include "hevc_sei.h" #include "internal.h" #include "put_bits.h" #include "vaapi_encode.h" enum { SEI_MASTERING_DISPLAY = 0x08, SEI_CONTENT_LIGHT_LEVEL = 0x10, }; typedef struct VAAPIEncodeH265Picture { int pic_order_cnt; int64_t last_idr_frame; int slice_nal_unit; int slice_type; int pic_type; } VAAPIEncodeH265Picture; typedef struct VAAPIEncodeH265Context { VAAPIEncodeContext common; // User options. int qp; int aud; int profile; int tier; int level; int sei; // Derived settings. int fixed_qp_idr; int fixed_qp_p; int fixed_qp_b; // Writer structures. H265RawAUD raw_aud; H265RawVPS raw_vps; H265RawSPS raw_sps; H265RawPPS raw_pps; H265RawSlice raw_slice; SEIRawMasteringDisplayColourVolume sei_mastering_display; SEIRawContentLightLevelInfo sei_content_light_level; CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; int aud_needed; int sei_needed; } VAAPIEncodeH265Context; static int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, char *data, size_t *data_len, CodedBitstreamFragment *au) { VAAPIEncodeH265Context *priv = avctx->priv_data; int err; err = ff_cbs_write_fragment_data(priv->cbc, au); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); return err; } if (*data_len < 8 * au->data_size - au->data_bit_padding) { av_log(avctx, AV_LOG_ERROR, "Access unit too large: " "%zu < %zu.\n", *data_len, 8 * au->data_size - au->data_bit_padding); return AVERROR(ENOSPC); } memcpy(data, au->data, au->data_size); *data_len = 8 * au->data_size - au->data_bit_padding; return 0; } static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, CodedBitstreamFragment *au, void *nal_unit) { H265RawNALUnitHeader *header = nal_unit; int err; err = ff_cbs_insert_unit_content(au, -1, header->nal_unit_type, nal_unit, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " "type = %d.\n", header->nal_unit_type); return err; } return 0; } static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len) { VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; int err; if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_aud); if (err < 0) goto fail; priv->aud_needed = 0; } err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_vps); if (err < 0) goto fail; err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_sps); if (err < 0) goto fail; err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_pps); if (err < 0) goto fail; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); fail: ff_cbs_fragment_reset(au); return err; } static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice, char *data, size_t *data_len) { VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; int err; if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_aud); if (err < 0) goto fail; priv->aud_needed = 0; } err = vaapi_encode_h265_add_nal(avctx, au, &priv->raw_slice); if (err < 0) goto fail; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); fail: ff_cbs_fragment_reset(au); return err; } static int vaapi_encode_h265_write_extra_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int index, int *type, char *data, size_t *data_len) { VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; int err; if (priv->sei_needed) { if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); if (err < 0) goto fail; priv->aud_needed = 0; } if (priv->sei_needed & SEI_MASTERING_DISPLAY) { err = ff_cbs_sei_add_message(priv->cbc, au, 1, SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME, &priv->sei_mastering_display, NULL); if (err < 0) goto fail; } if (priv->sei_needed & SEI_CONTENT_LIGHT_LEVEL) { err = ff_cbs_sei_add_message(priv->cbc, au, 1, SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO, &priv->sei_content_light_level, NULL); if (err < 0) goto fail; } priv->sei_needed = 0; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); if (err < 0) goto fail; ff_cbs_fragment_reset(au); *type = VAEncPackedHeaderRawData; return 0; } else { return AVERROR_EOF; } fail: ff_cbs_fragment_reset(au); return err; } static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = avctx->priv_data; H265RawVPS *vps = &priv->raw_vps; H265RawSPS *sps = &priv->raw_sps; H265RawPPS *pps = &priv->raw_pps; H265RawProfileTierLevel *ptl = &vps->profile_tier_level; H265RawVUI *vui = &sps->vui; VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; const AVPixFmtDescriptor *desc; int chroma_format, bit_depth; int i; memset(vps, 0, sizeof(*vps)); memset(sps, 0, sizeof(*sps)); memset(pps, 0, sizeof(*pps)); desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format); av_assert0(desc); if (desc->nb_components == 1) { chroma_format = 0; } else { if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) { chroma_format = 1; } else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 0) { chroma_format = 2; } else if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) { chroma_format = 3; } else { 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; // VPS vps->nal_unit_header = (H265RawNALUnitHeader) { .nal_unit_type = HEVC_NAL_VPS, .nuh_layer_id = 0, .nuh_temporal_id_plus1 = 1, }; vps->vps_video_parameter_set_id = 0; vps->vps_base_layer_internal_flag = 1; vps->vps_base_layer_available_flag = 1; vps->vps_max_layers_minus1 = 0; vps->vps_max_sub_layers_minus1 = 0; vps->vps_temporal_id_nesting_flag = 1; ptl->general_profile_space = 0; ptl->general_profile_idc = avctx->profile; ptl->general_tier_flag = priv->tier; if (chroma_format == 1) { ptl->general_profile_compatibility_flag[1] = bit_depth == 8; ptl->general_profile_compatibility_flag[2] = bit_depth <= 10; } ptl->general_profile_compatibility_flag[4] = 1; ptl->general_progressive_source_flag = 1; ptl->general_interlaced_source_flag = 0; ptl->general_non_packed_constraint_flag = 1; ptl->general_frame_only_constraint_flag = 1; ptl->general_max_12bit_constraint_flag = bit_depth <= 12; ptl->general_max_10bit_constraint_flag = bit_depth <= 10; ptl->general_max_8bit_constraint_flag = bit_depth == 8; ptl->general_max_422chroma_constraint_flag = chroma_format <= 2; ptl->general_max_420chroma_constraint_flag = chroma_format <= 1; ptl->general_max_monochrome_constraint_flag = chroma_format == 0; ptl->general_intra_constraint_flag = ctx->gop_size == 1; ptl->general_lower_bit_rate_constraint_flag = 1; if (avctx->level != FF_LEVEL_UNKNOWN) { ptl->general_level_idc = avctx->level; } else { const H265LevelDescriptor *level; level = ff_h265_guess_level(ptl, avctx->bit_rate, ctx->surface_width, ctx->surface_height, ctx->nb_slices, ctx->tile_rows, ctx->tile_cols, (ctx->b_per_p > 0) + 1); if (level) { av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); ptl->general_level_idc = level->level_idc; } else { av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to " "any normal level; using level 8.5.\n"); ptl->general_level_idc = 255; // The tier flag must be set in level 8.5. ptl->general_tier_flag = 1; } } vps->vps_sub_layer_ordering_info_present_flag = 0; vps->vps_max_dec_pic_buffering_minus1[0] = ctx->max_b_depth + 1; vps->vps_max_num_reorder_pics[0] = ctx->max_b_depth; vps->vps_max_latency_increase_plus1[0] = 0; vps->vps_max_layer_id = 0; vps->vps_num_layer_sets_minus1 = 0; vps->layer_id_included_flag[0][0] = 1; vps->vps_timing_info_present_flag = 1; if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { vps->vps_num_units_in_tick = avctx->framerate.den; vps->vps_time_scale = avctx->framerate.num; vps->vps_poc_proportional_to_timing_flag = 1; vps->vps_num_ticks_poc_diff_one_minus1 = 0; } else { vps->vps_num_units_in_tick = avctx->time_base.num; vps->vps_time_scale = avctx->time_base.den; vps->vps_poc_proportional_to_timing_flag = 0; } vps->vps_num_hrd_parameters = 0; // SPS sps->nal_unit_header = (H265RawNALUnitHeader) { .nal_unit_type = HEVC_NAL_SPS, .nuh_layer_id = 0, .nuh_temporal_id_plus1 = 1, }; sps->sps_video_parameter_set_id = vps->vps_video_parameter_set_id; sps->sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1; sps->sps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag; sps->profile_tier_level = vps->profile_tier_level; sps->sps_seq_parameter_set_id = 0; sps->chroma_format_idc = chroma_format; sps->separate_colour_plane_flag = 0; sps->pic_width_in_luma_samples = ctx->surface_width; sps->pic_height_in_luma_samples = ctx->surface_height; if (avctx->width != ctx->surface_width || avctx->height != ctx->surface_height) { sps->conformance_window_flag = 1; sps->conf_win_left_offset = 0; sps->conf_win_right_offset = (ctx->surface_width - avctx->width) >> desc->log2_chroma_w; sps->conf_win_top_offset = 0; sps->conf_win_bottom_offset = (ctx->surface_height - avctx->height) >> desc->log2_chroma_h; } else { sps->conformance_window_flag = 0; } sps->bit_depth_luma_minus8 = bit_depth - 8; sps->bit_depth_chroma_minus8 = bit_depth - 8; sps->log2_max_pic_order_cnt_lsb_minus4 = 8; sps->sps_sub_layer_ordering_info_present_flag = vps->vps_sub_layer_ordering_info_present_flag; for (i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { sps->sps_max_dec_pic_buffering_minus1[i] = vps->vps_max_dec_pic_buffering_minus1[i]; sps->sps_max_num_reorder_pics[i] = vps->vps_max_num_reorder_pics[i]; sps->sps_max_latency_increase_plus1[i] = vps->vps_max_latency_increase_plus1[i]; } // These have to come from the capabilities of the encoder. We have no // way to query them, so just hardcode parameters which work on the Intel // driver. // CTB size from 8x8 to 32x32. sps->log2_min_luma_coding_block_size_minus3 = 0; sps->log2_diff_max_min_luma_coding_block_size = 2; // Transform size from 4x4 to 32x32. sps->log2_min_luma_transform_block_size_minus2 = 0; sps->log2_diff_max_min_luma_transform_block_size = 3; // Full transform hierarchy allowed (2-5). sps->max_transform_hierarchy_depth_inter = 3; sps->max_transform_hierarchy_depth_intra = 3; // AMP works. sps->amp_enabled_flag = 1; // SAO and temporal MVP do not work. sps->sample_adaptive_offset_enabled_flag = 0; sps->sps_temporal_mvp_enabled_flag = 0; sps->pcm_enabled_flag = 0; // STRPSs should ideally be here rather than defined individually in // each slice, but the structure isn't completely fixed so for now // don't bother. sps->num_short_term_ref_pic_sets = 0; sps->long_term_ref_pics_present_flag = 0; sps->vui_parameters_present_flag = 1; if (avctx->sample_aspect_ratio.num != 0 && avctx->sample_aspect_ratio.den != 0) { static const AVRational sar_idc[] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; 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(sar_idc); i++) { if (num == sar_idc[i].num && den == sar_idc[i].den) { vui->aspect_ratio_idc = i; break; } } if (i >= FF_ARRAY_ELEMS(sar_idc)) { vui->aspect_ratio_idc = 255; vui->sar_width = num; vui->sar_height = den; } vui->aspect_ratio_info_present_flag = 1; } // Unspecified video format, from table E-2. vui->video_format = 5; vui->video_full_range_flag = avctx->color_range == AVCOL_RANGE_JPEG; vui->colour_primaries = avctx->color_primaries; vui->transfer_characteristics = avctx->color_trc; vui->matrix_coefficients = avctx->colorspace; if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || avctx->colorspace != AVCOL_SPC_UNSPECIFIED) vui->colour_description_present_flag = 1; if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || vui->colour_description_present_flag) vui->video_signal_type_present_flag = 1; if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { vui->chroma_loc_info_present_flag = 1; vui->chroma_sample_loc_type_top_field = vui->chroma_sample_loc_type_bottom_field = avctx->chroma_sample_location - 1; } vui->vui_timing_info_present_flag = 1; vui->vui_num_units_in_tick = vps->vps_num_units_in_tick; vui->vui_time_scale = vps->vps_time_scale;