Commit | Line | Data |
---|---|---|
31fe1f25 MT |
1 | /* |
2 | * This file is part of Libav. | |
3 | * | |
4 | * Libav is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * Libav is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with Libav; if not, write to the Free Software | |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | ||
ac124867 MT |
19 | #include <string.h> |
20 | ||
31fe1f25 MT |
21 | #include <va/va.h> |
22 | #include <va/va_enc_hevc.h> | |
23 | ||
24 | #include "libavutil/avassert.h" | |
ac124867 | 25 | #include "libavutil/common.h" |
31fe1f25 | 26 | #include "libavutil/opt.h" |
31fe1f25 MT |
27 | |
28 | #include "avcodec.h" | |
ac124867 MT |
29 | #include "cbs.h" |
30 | #include "cbs_h265.h" | |
0bfdcce4 | 31 | #include "hevc.h" |
31fe1f25 MT |
32 | #include "internal.h" |
33 | #include "put_bits.h" | |
34 | #include "vaapi_encode.h" | |
31fe1f25 | 35 | |
31fe1f25 | 36 | |
ac124867 | 37 | typedef struct VAAPIEncodeH265Context { |
31fe1f25 MT |
38 | unsigned int ctu_width; |
39 | unsigned int ctu_height; | |
40 | ||
41 | int fixed_qp_idr; | |
42 | int fixed_qp_p; | |
43 | int fixed_qp_b; | |
44 | ||
ac124867 MT |
45 | H265RawVPS vps; |
46 | H265RawSPS sps; | |
47 | H265RawPPS pps; | |
48 | H265RawSlice slice; | |
49 | ||
31fe1f25 | 50 | int64_t last_idr_frame; |
ac124867 | 51 | int pic_order_cnt; |
f70e4627 | 52 | |
ac124867 MT |
53 | int slice_nal_unit; |
54 | int slice_type; | |
55 | ||
56 | CodedBitstreamContext cbc; | |
57 | CodedBitstreamFragment current_access_unit; | |
31fe1f25 MT |
58 | } VAAPIEncodeH265Context; |
59 | ||
92fdea37 MT |
60 | typedef struct VAAPIEncodeH265Options { |
61 | int qp; | |
62 | } VAAPIEncodeH265Options; | |
63 | ||
31fe1f25 | 64 | |
ac124867 MT |
65 | static int vaapi_encode_h265_write_access_unit(AVCodecContext *avctx, |
66 | char *data, size_t *data_len, | |
67 | CodedBitstreamFragment *au) | |
31fe1f25 | 68 | { |
ac124867 MT |
69 | VAAPIEncodeContext *ctx = avctx->priv_data; |
70 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
71 | int err; | |
31fe1f25 | 72 | |
ac124867 MT |
73 | err = ff_cbs_write_fragment_data(&priv->cbc, au); |
74 | if (err < 0) { | |
75 | av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n"); | |
76 | return err; | |
31fe1f25 MT |
77 | } |
78 | ||
ac124867 MT |
79 | if (*data_len < 8 * au->data_size - au->data_bit_padding) { |
80 | av_log(avctx, AV_LOG_ERROR, "Access unit too large: " | |
81 | "%zu < %zu.\n", *data_len, | |
82 | 8 * au->data_size - au->data_bit_padding); | |
83 | return AVERROR(ENOSPC); | |
31fe1f25 MT |
84 | } |
85 | ||
ac124867 MT |
86 | memcpy(data, au->data, au->data_size); |
87 | *data_len = 8 * au->data_size - au->data_bit_padding; | |
31fe1f25 | 88 | |
ac124867 | 89 | return 0; |
31fe1f25 MT |
90 | } |
91 | ||
ac124867 MT |
92 | static int vaapi_encode_h265_add_nal(AVCodecContext *avctx, |
93 | CodedBitstreamFragment *au, | |
94 | void *nal_unit) | |
31fe1f25 | 95 | { |
ac124867 MT |
96 | VAAPIEncodeContext *ctx = avctx->priv_data; |
97 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
98 | H265RawNALUnitHeader *header = nal_unit; | |
99 | int err; | |
31fe1f25 | 100 | |
ac124867 MT |
101 | err = ff_cbs_insert_unit_content(&priv->cbc, au, -1, |
102 | header->nal_unit_type, nal_unit); | |
103 | if (err < 0) { | |
104 | av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " | |
105 | "type = %d.\n", header->nal_unit_type); | |
106 | return err; | |
31fe1f25 MT |
107 | } |
108 | ||
ac124867 | 109 | return 0; |
31fe1f25 MT |
110 | } |
111 | ||
112 | static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx, | |
113 | char *data, size_t *data_len) | |
114 | { | |
ac124867 MT |
115 | VAAPIEncodeContext *ctx = avctx->priv_data; |
116 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
117 | CodedBitstreamFragment *au = &priv->current_access_unit; | |
31fe1f25 | 118 | int err; |
31fe1f25 | 119 | |
ac124867 | 120 | err = vaapi_encode_h265_add_nal(avctx, au, &priv->vps); |
31fe1f25 | 121 | if (err < 0) |
ac124867 | 122 | goto fail; |
31fe1f25 | 123 | |
ac124867 | 124 | err = vaapi_encode_h265_add_nal(avctx, au, &priv->sps); |
31fe1f25 | 125 | if (err < 0) |
ac124867 | 126 | goto fail; |
31fe1f25 | 127 | |
ac124867 | 128 | err = vaapi_encode_h265_add_nal(avctx, au, &priv->pps); |
31fe1f25 | 129 | if (err < 0) |
ac124867 | 130 | goto fail; |
31fe1f25 | 131 | |
ac124867 MT |
132 | err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); |
133 | fail: | |
134 | ff_cbs_fragment_uninit(&priv->cbc, au); | |
135 | return err; | |
31fe1f25 MT |
136 | } |
137 | ||
138 | static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx, | |
139 | VAAPIEncodePicture *pic, | |
140 | VAAPIEncodeSlice *slice, | |
141 | char *data, size_t *data_len) | |
142 | { | |
ac124867 MT |
143 | VAAPIEncodeContext *ctx = avctx->priv_data; |
144 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
145 | CodedBitstreamFragment *au = &priv->current_access_unit; | |
146 | int err; | |
31fe1f25 | 147 | |
ac124867 MT |
148 | err = vaapi_encode_h265_add_nal(avctx, au, &priv->slice); |
149 | if (err < 0) | |
150 | goto fail; | |
31fe1f25 | 151 | |
ac124867 MT |
152 | err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); |
153 | fail: | |
154 | ff_cbs_fragment_uninit(&priv->cbc, au); | |
155 | return err; | |
31fe1f25 MT |
156 | } |
157 | ||
158 | static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) | |
159 | { | |
ac124867 MT |
160 | VAAPIEncodeContext *ctx = avctx->priv_data; |
161 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
162 | H265RawVPS *vps = &priv->vps; | |
163 | H265RawSPS *sps = &priv->sps; | |
164 | H265RawPPS *pps = &priv->pps; | |
165 | H265RawVUI *vui = &sps->vui; | |
166 | VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; | |
167 | VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; | |
31fe1f25 MT |
168 | int i; |
169 | ||
ac124867 MT |
170 | memset(&priv->current_access_unit, 0, |
171 | sizeof(priv->current_access_unit)); | |
f70e4627 | 172 | |
ac124867 MT |
173 | memset(vps, 0, sizeof(*vps)); |
174 | memset(sps, 0, sizeof(*sps)); | |
175 | memset(pps, 0, sizeof(*pps)); | |
31fe1f25 | 176 | |
31fe1f25 | 177 | |
ac124867 | 178 | // VPS |
31fe1f25 | 179 | |
ac124867 MT |
180 | vps->nal_unit_header = (H265RawNALUnitHeader) { |
181 | .nal_unit_type = HEVC_NAL_VPS, | |
182 | .nuh_layer_id = 0, | |
183 | .nuh_temporal_id_plus1 = 1, | |
184 | }; | |
31fe1f25 | 185 | |
ac124867 | 186 | vps->vps_video_parameter_set_id = 0; |
31fe1f25 | 187 | |
ac124867 MT |
188 | vps->vps_base_layer_internal_flag = 1; |
189 | vps->vps_base_layer_available_flag = 1; | |
190 | vps->vps_max_layers_minus1 = 0; | |
191 | vps->vps_max_sub_layers_minus1 = 0; | |
192 | vps->vps_temporal_id_nesting_flag = 1; | |
31fe1f25 | 193 | |
ac124867 MT |
194 | vps->profile_tier_level = (H265RawProfileTierLevel) { |
195 | .general_profile_space = 0, | |
196 | .general_profile_idc = avctx->profile, | |
197 | .general_tier_flag = 0, | |
31fe1f25 | 198 | |
ac124867 MT |
199 | .general_progressive_source_flag = 1, |
200 | .general_interlaced_source_flag = 0, | |
201 | .general_non_packed_constraint_flag = 1, | |
202 | .general_frame_only_constraint_flag = 1, | |
31fe1f25 | 203 | |
ac124867 MT |
204 | .general_level_idc = avctx->level, |
205 | }; | |
206 | vps->profile_tier_level.general_profile_compatibility_flag[avctx->profile & 31] = 1; | |
31fe1f25 | 207 | |
ac124867 MT |
208 | vps->vps_sub_layer_ordering_info_present_flag = 0; |
209 | vps->vps_max_dec_pic_buffering_minus1[0] = (ctx->b_per_p > 0) + 1; | |
210 | vps->vps_max_num_reorder_pics[0] = (ctx->b_per_p > 0); | |
211 | vps->vps_max_latency_increase_plus1[0] = 0; | |
31fe1f25 | 212 | |
ac124867 MT |
213 | vps->vps_max_layer_id = 0; |
214 | vps->vps_num_layer_sets_minus1 = 0; | |
215 | vps->layer_id_included_flag[0][0] = 1; | |
31fe1f25 | 216 | |
ac124867 MT |
217 | vps->vps_timing_info_present_flag = 1; |
218 | if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { | |
219 | vps->vps_num_units_in_tick = avctx->framerate.den; | |
220 | vps->vps_time_scale = avctx->framerate.num; | |
221 | vps->vps_poc_proportional_to_timing_flag = 1; | |
222 | vps->vps_num_ticks_poc_diff_one_minus1 = 0; | |
223 | } else { | |
224 | vps->vps_num_units_in_tick = avctx->time_base.num; | |
225 | vps->vps_time_scale = avctx->time_base.den; | |
226 | vps->vps_poc_proportional_to_timing_flag = 0; | |
227 | } | |
228 | vps->vps_num_hrd_parameters = 0; | |
31fe1f25 | 229 | |
2940e196 | 230 | |
ac124867 | 231 | // SPS |
31fe1f25 | 232 | |
ac124867 MT |
233 | sps->nal_unit_header = (H265RawNALUnitHeader) { |
234 | .nal_unit_type = HEVC_NAL_SPS, | |
235 | .nuh_layer_id = 0, | |
236 | .nuh_temporal_id_plus1 = 1, | |
237 | }; | |
31fe1f25 | 238 | |
ac124867 | 239 | sps->sps_video_parameter_set_id = vps->vps_video_parameter_set_id; |
31fe1f25 | 240 | |
ac124867 MT |
241 | sps->sps_max_sub_layers_minus1 = vps->vps_max_sub_layers_minus1; |
242 | sps->sps_temporal_id_nesting_flag = vps->vps_temporal_id_nesting_flag; | |
31fe1f25 | 243 | |
ac124867 | 244 | sps->profile_tier_level = vps->profile_tier_level; |
31fe1f25 | 245 | |
ac124867 | 246 | sps->sps_seq_parameter_set_id = 0; |
31fe1f25 | 247 | |
ac124867 MT |
248 | sps->chroma_format_idc = 1; // YUV 4:2:0. |
249 | sps->separate_colour_plane_flag = 0; | |
250 | ||
251 | sps->pic_width_in_luma_samples = ctx->surface_width; | |
252 | sps->pic_height_in_luma_samples = ctx->surface_height; | |
253 | ||
254 | if (avctx->width != ctx->surface_width || | |
255 | avctx->height != ctx->surface_height) { | |
256 | sps->conformance_window_flag = 1; | |
257 | sps->conf_win_left_offset = 0; | |
258 | sps->conf_win_right_offset = | |
259 | (ctx->surface_width - avctx->width) / 2; | |
260 | sps->conf_win_top_offset = 0; | |
261 | sps->conf_win_bottom_offset = | |
262 | (ctx->surface_height - avctx->height) / 2; | |
263 | } else { | |
264 | sps->conformance_window_flag = 0; | |
265 | } | |
266 | ||
267 | sps->bit_depth_luma_minus8 = | |
268 | avctx->profile == FF_PROFILE_HEVC_MAIN_10 ? 2 : 0; | |
269 | sps->bit_depth_chroma_minus8 = sps->bit_depth_luma_minus8; | |
270 | ||
271 | sps->log2_max_pic_order_cnt_lsb_minus4 = 8; | |
272 | ||
273 | sps->sps_sub_layer_ordering_info_present_flag = | |
274 | vps->vps_sub_layer_ordering_info_present_flag; | |
275 | for (i = 0; i <= sps->sps_max_sub_layers_minus1; i++) { | |
276 | sps->sps_max_dec_pic_buffering_minus1[i] = | |
277 | vps->vps_max_dec_pic_buffering_minus1[i]; | |
278 | sps->sps_max_num_reorder_pics[i] = | |
279 | vps->vps_max_num_reorder_pics[i]; | |
280 | sps->sps_max_latency_increase_plus1[i] = | |
281 | vps->vps_max_latency_increase_plus1[i]; | |
282 | } | |
283 | ||
284 | // These have to come from the capabilities of the encoder. We have no | |
285 | // way to query them, so just hardcode parameters which work on the Intel | |
286 | // driver. | |
287 | // CTB size from 8x8 to 32x32. | |
288 | sps->log2_min_luma_coding_block_size_minus3 = 0; | |
289 | sps->log2_diff_max_min_luma_coding_block_size = 2; | |
290 | // Transform size from 4x4 to 32x32. | |
291 | sps->log2_min_luma_transform_block_size_minus2 = 0; | |
292 | sps->log2_diff_max_min_luma_transform_block_size = 3; | |
293 | // Full transform hierarchy allowed (2-5). | |
294 | sps->max_transform_hierarchy_depth_inter = 3; | |
295 | sps->max_transform_hierarchy_depth_intra = 3; | |
296 | // AMP works. | |
297 | sps->amp_enabled_flag = 1; | |
298 | // SAO and temporal MVP do not work. | |
299 | sps->sample_adaptive_offset_enabled_flag = 0; | |
300 | sps->sps_temporal_mvp_enabled_flag = 0; | |
301 | ||
302 | sps->pcm_enabled_flag = 0; | |
303 | ||
304 | // STRPSs should ideally be here rather than defined individually in | |
305 | // each slice, but the structure isn't completely fixed so for now | |
306 | // don't bother. | |
307 | sps->num_short_term_ref_pic_sets = 0; | |
308 | sps->long_term_ref_pics_present_flag = 0; | |
309 | ||
310 | sps->vui_parameters_present_flag = 1; | |
311 | ||
312 | if (avctx->sample_aspect_ratio.num != 0 && | |
313 | avctx->sample_aspect_ratio.den != 0) { | |
314 | static const AVRational sar_idc[] = { | |
315 | { 0, 0 }, | |
316 | { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, | |
317 | { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, | |
318 | { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, | |
319 | { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, | |
320 | }; | |
321 | int i; | |
322 | for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) { | |
323 | if (avctx->sample_aspect_ratio.num == sar_idc[i].num && | |
324 | avctx->sample_aspect_ratio.den == sar_idc[i].den) { | |
325 | vui->aspect_ratio_idc = i; | |
326 | break; | |
31fe1f25 MT |
327 | } |
328 | } | |
ac124867 MT |
329 | if (i >= FF_ARRAY_ELEMS(sar_idc)) { |
330 | vui->aspect_ratio_idc = 255; | |
331 | vui->sar_width = avctx->sample_aspect_ratio.num; | |
332 | vui->sar_height = avctx->sample_aspect_ratio.den; | |
333 | } | |
334 | vui->aspect_ratio_info_present_flag = 1; | |
335 | } | |
336 | ||
337 | if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || | |
338 | avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || | |
339 | avctx->color_trc != AVCOL_TRC_UNSPECIFIED || | |
340 | avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { | |
341 | vui->video_signal_type_present_flag = 1; | |
342 | vui->video_format = 5; // Unspecified. | |
343 | vui->video_full_range_flag = | |
344 | avctx->color_range == AVCOL_RANGE_JPEG; | |
345 | ||
346 | if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || | |
347 | avctx->color_trc != AVCOL_TRC_UNSPECIFIED || | |
348 | avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { | |
349 | vui->colour_description_present_flag = 1; | |
350 | vui->colour_primaries = avctx->color_primaries; | |
351 | vui->transfer_characteristics = avctx->color_trc; | |
352 | vui->matrix_coefficients = avctx->colorspace; | |
31fe1f25 | 353 | } |
ac124867 MT |
354 | } else { |
355 | vui->video_format = 5; | |
356 | vui->video_full_range_flag = 0; | |
357 | vui->colour_primaries = avctx->color_primaries; | |
358 | vui->transfer_characteristics = avctx->color_trc; | |
359 | vui->matrix_coefficients = avctx->colorspace; | |
360 | } | |
361 | ||
362 | if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { | |
363 | vui->chroma_loc_info_present_flag = 1; | |
364 | vui->chroma_sample_loc_type_top_field = | |
365 | vui->chroma_sample_loc_type_bottom_field = | |
366 | avctx->chroma_sample_location - 1; | |
31fe1f25 MT |
367 | } |
368 | ||
ac124867 MT |
369 | vui->vui_timing_info_present_flag = 1; |
370 | vui->vui_num_units_in_tick = vps->vps_num_units_in_tick; | |
371 | vui->vui_time_scale = vps->vps_time_scale; | |
372 | vui->vui_poc_proportional_to_timing_flag = vps->vps_poc_proportional_to_timing_flag; | |
373 | vui->vui_num_ticks_poc_diff_one_minus1 = vps->vps_num_ticks_poc_diff_one_minus1; | |
374 | vui->vui_hrd_parameters_present_flag = 0; | |
375 | ||
376 | vui->bitstream_restriction_flag = 1; | |
377 | vui->motion_vectors_over_pic_boundaries_flag = 1; | |
378 | vui->restricted_ref_pic_lists_flag = 1; | |
379 | vui->max_bytes_per_pic_denom = 0; | |
380 | vui->max_bits_per_min_cu_denom = 0; | |
381 | vui->log2_max_mv_length_horizontal = 15; | |
382 | vui->log2_max_mv_length_vertical = 15; | |
383 | ||
384 | ||
385 | // PPS | |
386 | ||
387 | pps->nal_unit_header = (H265RawNALUnitHeader) { | |
388 | .nal_unit_type = HEVC_NAL_PPS, | |
389 | .nuh_layer_id = 0, | |
390 | .nuh_temporal_id_plus1 = 1, | |
391 | }; | |
392 | ||
393 | pps->pps_pic_parameter_set_id = 0; | |
394 | pps->pps_seq_parameter_set_id = sps->sps_seq_parameter_set_id; | |
395 | ||
396 | pps->num_ref_idx_l0_default_active_minus1 = 0; | |
397 | pps->num_ref_idx_l1_default_active_minus1 = 0; | |
398 | ||
399 | pps->init_qp_minus26 = priv->fixed_qp_idr - 26; | |
400 | ||
401 | pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP); | |
402 | pps->diff_cu_qp_delta_depth = 0; | |
403 | ||
404 | pps->pps_loop_filter_across_slices_enabled_flag = 1; | |
405 | ||
406 | ||
407 | // Fill VAAPI parameter buffers. | |
408 | ||
409 | *vseq = (VAEncSequenceParameterBufferHEVC) { | |
410 | .general_profile_idc = vps->profile_tier_level.general_profile_idc, | |
411 | .general_level_idc = vps->profile_tier_level.general_level_idc, | |
412 | .general_tier_flag = vps->profile_tier_level.general_tier_flag, | |
413 | ||
414 | .intra_period = avctx->gop_size, | |
415 | .intra_idr_period = avctx->gop_size, | |
416 | .ip_period = ctx->b_per_p + 1, | |
417 | .bits_per_second = avctx->bit_rate, | |
418 | ||
419 | .pic_width_in_luma_samples = sps->pic_width_in_luma_samples, | |
420 | .pic_height_in_luma_samples = sps->pic_height_in_luma_samples, | |
421 | ||
422 | .seq_fields.bits = { | |
423 | .chroma_format_idc = sps->chroma_format_idc, | |
424 | .separate_colour_plane_flag = sps->separate_colour_plane_flag, | |
425 | .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8, | |
426 | .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8, | |
427 | .scaling_list_enabled_flag = sps->scaling_list_enabled_flag, | |
428 | .strong_intra_smoothing_enabled_flag = | |
429 | sps->strong_intra_smoothing_enabled_flag, | |
430 | .amp_enabled_flag = sps->amp_enabled_flag, | |
431 | .sample_adaptive_offset_enabled_flag = | |
432 | sps->sample_adaptive_offset_enabled_flag, | |
433 | .pcm_enabled_flag = sps->pcm_enabled_flag, | |
434 | .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag, | |
435 | .sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag, | |
436 | }, | |
437 | ||
438 | .log2_min_luma_coding_block_size_minus3 = | |
439 | sps->log2_min_luma_coding_block_size_minus3, | |
440 | .log2_diff_max_min_luma_coding_block_size = | |
441 | sps->log2_diff_max_min_luma_coding_block_size, | |
442 | .log2_min_transform_block_size_minus2 = | |
443 | sps->log2_min_luma_transform_block_size_minus2, | |
444 | .log2_diff_max_min_transform_block_size = | |
445 | sps->log2_diff_max_min_luma_transform_block_size, | |
446 | .max_transform_hierarchy_depth_inter = | |
447 | sps->max_transform_hierarchy_depth_inter, | |
448 | .max_transform_hierarchy_depth_intra = | |
449 | sps->max_transform_hierarchy_depth_intra, | |
450 | ||
451 | .pcm_sample_bit_depth_luma_minus1 = | |
452 | sps->pcm_sample_bit_depth_luma_minus1, | |
453 | .pcm_sample_bit_depth_chroma_minus1 = | |
454 | sps->pcm_sample_bit_depth_chroma_minus1, | |
455 | .log2_min_pcm_luma_coding_block_size_minus3 = | |
456 | sps->log2_min_pcm_luma_coding_block_size_minus3, | |
457 | .log2_max_pcm_luma_coding_block_size_minus3 = | |
458 | sps->log2_min_pcm_luma_coding_block_size_minus3 + | |
459 | sps->log2_diff_max_min_pcm_luma_coding_block_size, | |
460 | ||
461 | .vui_parameters_present_flag = 0, | |
462 | }; | |
463 | ||
464 | *vpic = (VAEncPictureParameterBufferHEVC) { | |
465 | .decoded_curr_pic = { | |
466 | .picture_id = VA_INVALID_ID, | |
467 | .flags = VA_PICTURE_HEVC_INVALID, | |
468 | }, | |
469 | ||
470 | .coded_buf = VA_INVALID_ID, | |
471 | ||
472 | .collocated_ref_pic_index = 0xff, | |
473 | ||
474 | .last_picture = 0, | |
475 | ||
476 | .pic_init_qp = pps->init_qp_minus26 + 26, | |
477 | .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth, | |
478 | .pps_cb_qp_offset = pps->pps_cb_qp_offset, | |
479 | .pps_cr_qp_offset = pps->pps_cr_qp_offset, | |
480 | ||
481 | .num_tile_columns_minus1 = pps->num_tile_columns_minus1, | |
482 | .num_tile_rows_minus1 = pps->num_tile_rows_minus1, | |
483 | ||
484 | .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2, | |
485 | .ctu_max_bitsize_allowed = 0, | |
486 | ||
487 | .num_ref_idx_l0_default_active_minus1 = | |
488 | pps->num_ref_idx_l0_default_active_minus1, | |
489 | .num_ref_idx_l1_default_active_minus1 = | |
490 | pps->num_ref_idx_l1_default_active_minus1, | |
491 | ||
492 | .slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id, | |
493 | ||
494 | .pic_fields.bits = { | |
495 | .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag, | |
496 | .constrained_intra_pred_flag = pps->constrained_intra_pred_flag, | |
497 | .transform_skip_enabled_flag = pps->transform_skip_enabled_flag, | |
498 | .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag, | |
499 | .weighted_pred_flag = pps->weighted_pred_flag, | |
500 | .weighted_bipred_flag = pps->weighted_bipred_flag, | |
501 | .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag, | |
502 | .tiles_enabled_flag = pps->tiles_enabled_flag, | |
503 | .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, | |
504 | .loop_filter_across_tiles_enabled_flag = | |
505 | pps->loop_filter_across_tiles_enabled_flag, | |
506 | .scaling_list_data_present_flag = (sps->sps_scaling_list_data_present_flag | | |
507 | pps->pps_scaling_list_data_present_flag), | |
508 | .screen_content_flag = 0, | |
509 | .enable_gpu_weighted_prediction = 0, | |
510 | .no_output_of_prior_pics_flag = 0, | |
511 | }, | |
512 | }; | |
513 | ||
31fe1f25 MT |
514 | return 0; |
515 | } | |
516 | ||
517 | static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, | |
518 | VAAPIEncodePicture *pic) | |
519 | { | |
520 | VAAPIEncodeContext *ctx = avctx->priv_data; | |
31fe1f25 | 521 | VAAPIEncodeH265Context *priv = ctx->priv_data; |
ac124867 | 522 | VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; |
31fe1f25 MT |
523 | int i; |
524 | ||
525 | if (pic->type == PICTURE_TYPE_IDR) { | |
526 | av_assert0(pic->display_order == pic->encode_order); | |
ac124867 | 527 | |
31fe1f25 | 528 | priv->last_idr_frame = pic->display_order; |
ac124867 MT |
529 | |
530 | priv->slice_nal_unit = HEVC_NAL_IDR_W_RADL; | |
531 | priv->slice_type = HEVC_SLICE_I; | |
31fe1f25 MT |
532 | } else { |
533 | av_assert0(pic->encode_order > priv->last_idr_frame); | |
ac124867 MT |
534 | |
535 | if (pic->type == PICTURE_TYPE_I) { | |
536 | priv->slice_nal_unit = HEVC_NAL_CRA_NUT; | |
537 | priv->slice_type = HEVC_SLICE_I; | |
538 | } else if (pic->type == PICTURE_TYPE_P) { | |
539 | av_assert0(pic->refs[0]); | |
540 | priv->slice_nal_unit = HEVC_NAL_TRAIL_R; | |
541 | priv->slice_type = HEVC_SLICE_P; | |
542 | } else { | |
543 | av_assert0(pic->refs[0] && pic->refs[1]); | |
544 | if (pic->refs[1]->type == PICTURE_TYPE_I) | |
545 | priv->slice_nal_unit = HEVC_NAL_RASL_N; | |
546 | else | |
547 | priv->slice_nal_unit = HEVC_NAL_TRAIL_N; | |
548 | priv->slice_type = HEVC_SLICE_B; | |
549 | } | |
31fe1f25 | 550 | } |
ac124867 | 551 | priv->pic_order_cnt = pic->display_order - priv->last_idr_frame; |
31fe1f25 | 552 | |
ac124867 MT |
553 | vpic->decoded_curr_pic = (VAPictureHEVC) { |
554 | .picture_id = pic->recon_surface, | |
555 | .pic_order_cnt = priv->pic_order_cnt, | |
556 | .flags = 0, | |
557 | }; | |
31fe1f25 MT |
558 | |
559 | for (i = 0; i < pic->nb_refs; i++) { | |
560 | VAAPIEncodePicture *ref = pic->refs[i]; | |
ac124867 MT |
561 | av_assert0(ref && ref->encode_order < pic->encode_order); |
562 | ||
563 | vpic->reference_frames[i] = (VAPictureHEVC) { | |
564 | .picture_id = ref->recon_surface, | |
565 | .pic_order_cnt = ref->display_order - priv->last_idr_frame, | |
566 | .flags = (ref->display_order < pic->display_order ? | |
567 | VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) | | |
568 | (ref->display_order > pic->display_order ? | |
569 | VA_PICTURE_HEVC_RPS_ST_CURR_AFTER : 0), | |
570 | }; | |
31fe1f25 MT |
571 | } |
572 | for (; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) { | |
ac124867 MT |
573 | vpic->reference_frames[i] = (VAPictureHEVC) { |
574 | .picture_id = VA_INVALID_ID, | |
575 | .flags = VA_PICTURE_HEVC_INVALID, | |
576 | }; | |
31fe1f25 MT |
577 | } |
578 | ||
579 | vpic->coded_buf = pic->output_buffer; | |
580 | ||
ac124867 MT |
581 | vpic->nal_unit_type = priv->slice_nal_unit; |
582 | ||
31fe1f25 MT |
583 | switch (pic->type) { |
584 | case PICTURE_TYPE_IDR: | |
ac124867 MT |
585 | vpic->pic_fields.bits.idr_pic_flag = 1; |
586 | vpic->pic_fields.bits.coding_type = 1; | |
31fe1f25 MT |
587 | vpic->pic_fields.bits.reference_pic_flag = 1; |
588 | break; | |
589 | case PICTURE_TYPE_I: | |
ac124867 MT |
590 | vpic->pic_fields.bits.idr_pic_flag = 0; |
591 | vpic->pic_fields.bits.coding_type = 1; | |
31fe1f25 MT |
592 | vpic->pic_fields.bits.reference_pic_flag = 1; |
593 | break; | |
594 | case PICTURE_TYPE_P: | |
ac124867 MT |
595 | vpic->pic_fields.bits.idr_pic_flag = 0; |
596 | vpic->pic_fields.bits.coding_type = 2; | |
31fe1f25 MT |
597 | vpic->pic_fields.bits.reference_pic_flag = 1; |
598 | break; | |
599 | case PICTURE_TYPE_B: | |
ac124867 MT |
600 | vpic->pic_fields.bits.idr_pic_flag = 0; |
601 | vpic->pic_fields.bits.coding_type = 3; | |
31fe1f25 MT |
602 | vpic->pic_fields.bits.reference_pic_flag = 0; |
603 | break; | |
604 | default: | |
605 | av_assert0(0 && "invalid picture type"); | |
606 | } | |
607 | ||
608 | pic->nb_slices = 1; | |
609 | ||
610 | return 0; | |
611 | } | |
612 | ||
613 | static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, | |
614 | VAAPIEncodePicture *pic, | |
615 | VAAPIEncodeSlice *slice) | |
616 | { | |
617 | VAAPIEncodeContext *ctx = avctx->priv_data; | |
ac124867 MT |
618 | VAAPIEncodeH265Context *priv = ctx->priv_data; |
619 | const H265RawSPS *sps = &priv->sps; | |
620 | const H265RawPPS *pps = &priv->pps; | |
621 | H265RawSliceHeader *sh = &priv->slice.header; | |
31fe1f25 MT |
622 | VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params; |
623 | VAEncSliceParameterBufferHEVC *vslice = slice->codec_slice_params; | |
31fe1f25 MT |
624 | int i; |
625 | ||
ac124867 MT |
626 | sh->nal_unit_header = (H265RawNALUnitHeader) { |
627 | .nal_unit_type = priv->slice_nal_unit, | |
628 | .nuh_layer_id = 0, | |
629 | .nuh_temporal_id_plus1 = 1, | |
630 | }; | |
31fe1f25 | 631 | |
ac124867 | 632 | sh->slice_pic_parameter_set_id = pps->pps_pic_parameter_set_id; |
31fe1f25 | 633 | |
ac124867 MT |
634 | // Currently we only support one slice per frame. |
635 | sh->first_slice_segment_in_pic_flag = 1; | |
636 | sh->slice_segment_address = 0; | |
31fe1f25 | 637 | |
ac124867 | 638 | sh->slice_type = priv->slice_type; |
31fe1f25 | 639 | |
ac124867 MT |
640 | sh->slice_pic_order_cnt_lsb = priv->pic_order_cnt & |
641 | (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1; | |
31fe1f25 | 642 | |
ac124867 MT |
643 | if (pic->type != PICTURE_TYPE_IDR) { |
644 | H265RawSTRefPicSet *rps; | |
31fe1f25 MT |
645 | VAAPIEncodePicture *st; |
646 | int used; | |
647 | ||
ac124867 MT |
648 | sh->short_term_ref_pic_set_sps_flag = 0; |
649 | ||
650 | rps = &sh->short_term_ref_pic_set; | |
651 | memset(rps, 0, sizeof(*rps)); | |
31fe1f25 MT |
652 | |
653 | for (st = ctx->pic_start; st; st = st->next) { | |
654 | if (st->encode_order >= pic->encode_order) { | |
655 | // Not yet in DPB. | |
656 | continue; | |
657 | } | |
658 | used = 0; | |
659 | for (i = 0; i < pic->nb_refs; i++) { | |
660 | if (pic->refs[i] == st) | |
661 | used = 1; | |
662 | } | |
663 | if (!used) { | |
ac124867 MT |
664 | // Usually each picture always uses all of the others in the |
665 | // DPB as references. The one case we have to treat here is | |
666 | // a non-IDR IRAP picture, which may need to hold unused | |
667 | // references across itself to be used for the decoding of | |
668 | // following RASL pictures. This looks for such an RASL | |
669 | // picture, and keeps the reference if there is one. | |
670 | VAAPIEncodePicture *rp; | |
671 | for (rp = ctx->pic_start; rp; rp = rp->next) { | |
672 | if (rp->encode_order < pic->encode_order) | |
673 | continue; | |
674 | if (rp->type != PICTURE_TYPE_B) | |
675 | continue; | |
676 | if (rp->refs[0] == st && rp->refs[1] == pic) | |
677 | break; | |
678 | } | |
679 | if (!rp) | |
680 | continue; | |
31fe1f25 MT |
681 | } |
682 | // This only works for one instance of each (delta_poc_sN_minus1 | |
683 | // is relative to the previous frame in the list, not relative to | |
684 | // the current frame directly). | |
685 | if (st->display_order < pic->display_order) { | |
ac124867 | 686 | rps->delta_poc_s0_minus1[rps->num_negative_pics] = |
31fe1f25 | 687 | pic->display_order - st->display_order - 1; |
ac124867 MT |
688 | rps->used_by_curr_pic_s0_flag[rps->num_negative_pics] = used; |
689 | ++rps->num_negative_pics; | |
31fe1f25 | 690 | } else { |
ac124867 | 691 | rps->delta_poc_s1_minus1[rps->num_positive_pics] = |
31fe1f25 | 692 | st->display_order - pic->display_order - 1; |
ac124867 MT |
693 | rps->used_by_curr_pic_s1_flag[rps->num_positive_pics] = used; |
694 | ++rps->num_positive_pics; | |
31fe1f25 MT |
695 | } |
696 | } | |
ac124867 MT |
697 | |
698 | sh->num_long_term_sps = 0; | |
699 | sh->num_long_term_pics = 0; | |
700 | ||
701 | sh->slice_temporal_mvp_enabled_flag = | |
702 | sps->sps_temporal_mvp_enabled_flag; | |
703 | if (sh->slice_temporal_mvp_enabled_flag) { | |
704 | sh->collocated_from_l0_flag = sh->slice_type == HEVC_SLICE_B; | |
705 | sh->collocated_ref_idx = 0; | |
706 | } | |
707 | ||
708 | sh->num_ref_idx_active_override_flag = 0; | |
709 | sh->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; | |
710 | sh->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; | |
31fe1f25 MT |
711 | } |
712 | ||
ac124867 MT |
713 | sh->slice_sao_luma_flag = sh->slice_sao_chroma_flag = |
714 | sps->sample_adaptive_offset_enabled_flag; | |
715 | ||
716 | if (pic->type == PICTURE_TYPE_B) | |
717 | sh->slice_qp_delta = priv->fixed_qp_b - (pps->init_qp_minus26 + 26); | |
718 | else if (pic->type == PICTURE_TYPE_P) | |
719 | sh->slice_qp_delta = priv->fixed_qp_p - (pps->init_qp_minus26 + 26); | |
720 | else | |
721 | sh->slice_qp_delta = priv->fixed_qp_idr - (pps->init_qp_minus26 + 26); | |
722 | ||
723 | ||
724 | *vslice = (VAEncSliceParameterBufferHEVC) { | |
725 | .slice_segment_address = sh->slice_segment_address, | |
726 | .num_ctu_in_slice = priv->ctu_width * priv->ctu_height, | |
727 | ||
728 | .slice_type = sh->slice_type, | |
729 | .slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id, | |
730 | ||
731 | .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1, | |
732 | .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1, | |
733 | .ref_pic_list0[0] = vpic->reference_frames[0], | |
734 | .ref_pic_list1[0] = vpic->reference_frames[1], | |
735 | ||
736 | .luma_log2_weight_denom = sh->luma_log2_weight_denom, | |
737 | .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom, | |
738 | ||
739 | .max_num_merge_cand = 5 - sh->five_minus_max_num_merge_cand, | |
740 | ||
741 | .slice_qp_delta = sh->slice_qp_delta, | |
742 | .slice_cb_qp_offset = sh->slice_cb_qp_offset, | |
743 | .slice_cr_qp_offset = sh->slice_cr_qp_offset, | |
744 | ||
745 | .slice_beta_offset_div2 = sh->slice_beta_offset_div2, | |
746 | .slice_tc_offset_div2 = sh->slice_tc_offset_div2, | |
747 | ||
748 | .slice_fields.bits = { | |
749 | .last_slice_of_pic_flag = 1, | |
750 | .dependent_slice_segment_flag = sh->dependent_slice_segment_flag, | |
751 | .colour_plane_id = sh->colour_plane_id, | |
752 | .slice_temporal_mvp_enabled_flag = | |
753 | sh->slice_temporal_mvp_enabled_flag, | |
754 | .slice_sao_luma_flag = sh->slice_sao_luma_flag, | |
755 | .slice_sao_chroma_flag = sh->slice_sao_chroma_flag, | |
756 | .num_ref_idx_active_override_flag = | |
757 | sh->num_ref_idx_active_override_flag, | |
758 | .mvd_l1_zero_flag = sh->mvd_l1_zero_flag, | |
759 | .cabac_init_flag = sh->cabac_init_flag, | |
760 | .slice_deblocking_filter_disabled_flag = | |
761 | sh->slice_deblocking_filter_disabled_flag, | |
762 | .slice_loop_filter_across_slices_enabled_flag = | |
763 | sh->slice_loop_filter_across_slices_enabled_flag, | |
764 | .collocated_from_l0_flag = sh->collocated_from_l0_flag, | |
765 | }, | |
766 | }; | |
767 | ||
768 | ||
31fe1f25 MT |
769 | return 0; |
770 | } | |
771 | ||
80a5d051 | 772 | static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx) |
f70e4627 MT |
773 | { |
774 | VAAPIEncodeContext *ctx = avctx->priv_data; | |
775 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
80a5d051 | 776 | VAAPIEncodeH265Options *opt = ctx->codec_options; |
ac124867 MT |
777 | int err; |
778 | ||
779 | err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_HEVC, avctx); | |
780 | if (err < 0) | |
781 | return err; | |
80a5d051 MT |
782 | |
783 | priv->ctu_width = FFALIGN(ctx->surface_width, 32) / 32; | |
784 | priv->ctu_height = FFALIGN(ctx->surface_height, 32) / 32; | |
785 | ||
786 | av_log(avctx, AV_LOG_VERBOSE, "Input %ux%u -> Surface %ux%u -> CTU %ux%u.\n", | |
787 | avctx->width, avctx->height, ctx->surface_width, | |
788 | ctx->surface_height, priv->ctu_width, priv->ctu_height); | |
789 | ||
790 | if (ctx->va_rc_mode == VA_RC_CQP) { | |
791 | priv->fixed_qp_p = opt->qp; | |
792 | if (avctx->i_quant_factor > 0.0) | |
793 | priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor + | |
794 | avctx->i_quant_offset) + 0.5); | |
795 | else | |
796 | priv->fixed_qp_idr = priv->fixed_qp_p; | |
797 | if (avctx->b_quant_factor > 0.0) | |
798 | priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor + | |
799 | avctx->b_quant_offset) + 0.5); | |
800 | else | |
801 | priv->fixed_qp_b = priv->fixed_qp_p; | |
802 | ||
803 | av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " | |
804 | "%d / %d / %d for IDR- / P- / B-frames.\n", | |
805 | priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); | |
806 | ||
807 | } else if (ctx->va_rc_mode == VA_RC_CBR) { | |
808 | // These still need to be set for pic_init_qp/slice_qp_delta. | |
809 | priv->fixed_qp_idr = 30; | |
810 | priv->fixed_qp_p = 30; | |
811 | priv->fixed_qp_b = 30; | |
812 | ||
813 | av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n", | |
814 | avctx->bit_rate); | |
815 | ||
816 | } else { | |
817 | av_assert0(0 && "Invalid RC mode."); | |
818 | } | |
f70e4627 | 819 | |
f70e4627 MT |
820 | return 0; |
821 | } | |
822 | ||
80a5d051 MT |
823 | static const VAAPIEncodeType vaapi_encode_type_h265 = { |
824 | .priv_data_size = sizeof(VAAPIEncodeH265Context), | |
f70e4627 | 825 | |
80a5d051 | 826 | .configure = &vaapi_encode_h265_configure, |
f70e4627 | 827 | |
80a5d051 MT |
828 | .sequence_params_size = sizeof(VAEncSequenceParameterBufferHEVC), |
829 | .init_sequence_params = &vaapi_encode_h265_init_sequence_params, | |
f70e4627 | 830 | |
80a5d051 MT |
831 | .picture_params_size = sizeof(VAEncPictureParameterBufferHEVC), |
832 | .init_picture_params = &vaapi_encode_h265_init_picture_params, | |
833 | ||
834 | .slice_params_size = sizeof(VAEncSliceParameterBufferHEVC), | |
835 | .init_slice_params = &vaapi_encode_h265_init_slice_params, | |
836 | ||
837 | .sequence_header_type = VAEncPackedHeaderSequence, | |
838 | .write_sequence_header = &vaapi_encode_h265_write_sequence_header, | |
839 | ||
840 | .slice_header_type = VAEncPackedHeaderHEVC_Slice, | |
841 | .write_slice_header = &vaapi_encode_h265_write_slice_header, | |
842 | }; | |
843 | ||
844 | static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) | |
31fe1f25 | 845 | { |
80a5d051 | 846 | VAAPIEncodeContext *ctx = avctx->priv_data; |
f6b85523 | 847 | |
80a5d051 | 848 | ctx->codec = &vaapi_encode_type_h265; |
31fe1f25 MT |
849 | |
850 | switch (avctx->profile) { | |
851 | case FF_PROFILE_HEVC_MAIN: | |
852 | case FF_PROFILE_UNKNOWN: | |
853 | ctx->va_profile = VAProfileHEVCMain; | |
5a5df90d | 854 | ctx->va_rt_format = VA_RT_FORMAT_YUV420; |
31fe1f25 MT |
855 | break; |
856 | case FF_PROFILE_HEVC_MAIN_10: | |
d08e02d9 | 857 | #ifdef VA_RT_FORMAT_YUV420_10BPP |
5a5df90d MT |
858 | ctx->va_profile = VAProfileHEVCMain10; |
859 | ctx->va_rt_format = VA_RT_FORMAT_YUV420_10BPP; | |
860 | break; | |
d08e02d9 MT |
861 | #else |
862 | av_log(avctx, AV_LOG_ERROR, "10-bit encoding is not " | |
863 | "supported with this VAAPI version.\n"); | |
864 | return AVERROR(ENOSYS); | |
865 | #endif | |
31fe1f25 MT |
866 | default: |
867 | av_log(avctx, AV_LOG_ERROR, "Unknown H.265 profile %d.\n", | |
868 | avctx->profile); | |
869 | return AVERROR(EINVAL); | |
870 | } | |
871 | ctx->va_entrypoint = VAEntrypointEncSlice; | |
872 | ||
80a5d051 | 873 | if (avctx->bit_rate > 0) |
f70e4627 | 874 | ctx->va_rc_mode = VA_RC_CBR; |
80a5d051 | 875 | else |
f70e4627 | 876 | ctx->va_rc_mode = VA_RC_CQP; |
f6b85523 | 877 | |
892bbbcd MT |
878 | ctx->va_packed_headers = |
879 | VA_ENC_PACKED_HEADER_SEQUENCE | // VPS, SPS and PPS. | |
880 | VA_ENC_PACKED_HEADER_SLICE; // Slice headers. | |
31fe1f25 | 881 | |
80a5d051 MT |
882 | ctx->surface_width = FFALIGN(avctx->width, 16); |
883 | ctx->surface_height = FFALIGN(avctx->height, 16); | |
31fe1f25 | 884 | |
80a5d051 | 885 | return ff_vaapi_encode_init(avctx); |
31fe1f25 MT |
886 | } |
887 | ||
ac124867 MT |
888 | static av_cold int vaapi_encode_h265_close(AVCodecContext *avctx) |
889 | { | |
890 | VAAPIEncodeContext *ctx = avctx->priv_data; | |
891 | VAAPIEncodeH265Context *priv = ctx->priv_data; | |
892 | ||
893 | if (priv) | |
894 | ff_cbs_close(&priv->cbc); | |
895 | ||
896 | return ff_vaapi_encode_close(avctx); | |
897 | } | |
898 | ||
92fdea37 MT |
899 | #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \ |
900 | offsetof(VAAPIEncodeH265Options, x)) | |
901 | #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) | |
902 | static const AVOption vaapi_encode_h265_options[] = { | |
41ed7ab4 | 903 | { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)", |
92fdea37 MT |
904 | OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS }, |
905 | { NULL }, | |
906 | }; | |
907 | ||
31fe1f25 MT |
908 | static const AVCodecDefault vaapi_encode_h265_defaults[] = { |
909 | { "profile", "1" }, | |
910 | { "level", "51" }, | |
911 | { "b", "0" }, | |
912 | { "bf", "2" }, | |
913 | { "g", "120" }, | |
31fe1f25 MT |
914 | { "i_qfactor", "1.0" }, |
915 | { "i_qoffset", "0.0" }, | |
916 | { "b_qfactor", "1.2" }, | |
917 | { "b_qoffset", "0.0" }, | |
918 | { NULL }, | |
919 | }; | |
920 | ||
921 | static const AVClass vaapi_encode_h265_class = { | |
922 | .class_name = "h265_vaapi", | |
923 | .item_name = av_default_item_name, | |
92fdea37 | 924 | .option = vaapi_encode_h265_options, |
31fe1f25 MT |
925 | .version = LIBAVUTIL_VERSION_INT, |
926 | }; | |
927 | ||
928 | AVCodec ff_hevc_vaapi_encoder = { | |
929 | .name = "hevc_vaapi", | |
930 | .long_name = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"), | |
931 | .type = AVMEDIA_TYPE_VIDEO, | |
932 | .id = AV_CODEC_ID_HEVC, | |
92fdea37 MT |
933 | .priv_data_size = (sizeof(VAAPIEncodeContext) + |
934 | sizeof(VAAPIEncodeH265Options)), | |
31fe1f25 MT |
935 | .init = &vaapi_encode_h265_init, |
936 | .encode2 = &ff_vaapi_encode2, | |
ac124867 | 937 | .close = &vaapi_encode_h265_close, |
31fe1f25 MT |
938 | .priv_class = &vaapi_encode_h265_class, |
939 | .capabilities = AV_CODEC_CAP_DELAY, | |
940 | .defaults = vaapi_encode_h265_defaults, | |
941 | .pix_fmts = (const enum AVPixelFormat[]) { | |
942 | AV_PIX_FMT_VAAPI, | |
943 | AV_PIX_FMT_NONE, | |
944 | }, | |
945 | }; |