41 int type,
char *
data,
size_t bit_len)
45 VABufferID param_buffer, data_buffer;
47 VAEncPackedHeaderParameterBuffer params = {
49 .bit_length = bit_len,
50 .has_emulation_bytes = 1,
58 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
59 VAEncPackedHeaderParameterBufferType,
60 sizeof(params), 1, ¶ms, ¶m_buffer);
61 if (vas != VA_STATUS_SUCCESS) {
63 "for packed header (type %d): %d (%s).\n",
64 type, vas, vaErrorStr(vas));
69 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
70 VAEncPackedHeaderDataBufferType,
71 (bit_len + 7) / 8, 1,
data, &data_buffer);
72 if (vas != VA_STATUS_SUCCESS) {
74 "for packed header (type %d): %d (%s).\n",
75 type, vas, vaErrorStr(vas));
81 "(%zu bits).\n",
type, param_buffer, data_buffer, bit_len);
99 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
101 if (vas != VA_STATUS_SUCCESS) {
103 "(type %d): %d (%s).\n",
type, vas, vaErrorStr(vas));
122 VAEncMiscParameterBuffer
header = {
125 size_t buffer_size =
sizeof(
header) +
len;
132 VAEncMiscParameterBufferType,
154 if (vas != VA_STATUS_SUCCESS) {
156 "%d (%s).\n", vas, vaErrorStr(vas));
177 rounding =
ctx->slice_block_rows -
ctx->nb_slices *
ctx->slice_size;
185 for (
i = 0;
i < rounding;
i++)
188 for (
i = 0;
i < (rounding + 1) / 2;
i++)
190 for (
i = 0;
i < rounding / 2;
i++)
193 }
else if (rounding < 0) {
229 for (
i = 0;
i <
ctx->tile_cols;
i++) {
230 for (j = 0; j <
ctx->tile_rows; j++) {
236 ctx->row_bd[j] *
ctx->slice_block_cols;
240 "width:%2d height:%2d (%d blocks).\n",
index,
ctx->col_bd[
i],
305 if (
ctx->codec->picture_params_size > 0) {
310 ctx->codec->picture_params_size);
319 VAEncSequenceParameterBufferType,
320 ctx->codec_sequence_params,
321 ctx->codec->sequence_params_size);
327 for (
i = 0;
i <
ctx->nb_global_params;
i++) {
329 ctx->global_params_type[
i],
330 ctx->global_params[
i],
331 ctx->global_params_size[
i]);
337 if (
ctx->codec->init_picture_params) {
338 err =
ctx->codec->init_picture_params(avctx, pic);
341 "parameters: %d.\n", err);
345 VAEncPictureParameterBufferType,
347 ctx->codec->picture_params_size);
353 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
354 ctx->codec->write_sequence_header) {
355 bit_len = 8 *
sizeof(
data);
356 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
359 "header: %d.\n", err);
363 ctx->codec->sequence_header_type,
370 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_PICTURE &&
371 ctx->codec->write_picture_header) {
372 bit_len = 8 *
sizeof(
data);
373 err =
ctx->codec->write_picture_header(avctx, pic,
data, &bit_len);
376 "header: %d.\n", err);
380 ctx->codec->picture_header_type,
386 if (
ctx->codec->write_extra_buffer) {
390 err =
ctx->codec->write_extra_buffer(avctx, pic,
i, &
type,
396 "buffer %d: %d.\n",
i, err);
407 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_MISC &&
408 ctx->codec->write_extra_header) {
411 bit_len = 8 *
sizeof(
data);
412 err =
ctx->codec->write_extra_header(avctx, pic,
i, &
type,
418 "header %d: %d.\n",
i, err);
438 if (
ctx->tile_rows &&
ctx->tile_cols)
447 if (
ctx->codec->slice_params_size > 0) {
455 if (
ctx->codec->init_slice_params) {
456 err =
ctx->codec->init_slice_params(avctx, pic, slice);
459 "parameters: %d.\n", err);
464 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SLICE &&
465 ctx->codec->write_slice_header) {
466 bit_len = 8 *
sizeof(
data);
467 err =
ctx->codec->write_slice_header(avctx, pic, slice,
471 "header: %d.\n", err);
475 ctx->codec->slice_header_type,
481 if (
ctx->codec->init_slice_params) {
483 VAEncSliceParameterBufferType,
485 ctx->codec->slice_params_size);
491 #if VA_CHECK_VERSION(1, 0, 0)
494 if (sd &&
ctx->roi_allowed) {
497 VAEncMiscParameterBufferROI param_roi;
502 av_assert0(roi_size && sd->size % roi_size == 0);
503 nb_roi = sd->size / roi_size;
504 if (nb_roi >
ctx->roi_max_regions) {
505 if (!
ctx->roi_warned) {
507 "supported by driver (%d > %d).\n",
508 nb_roi,
ctx->roi_max_regions);
511 nb_roi =
ctx->roi_max_regions;
520 for (
i = 0;
i < nb_roi;
i++) {
528 pic->
roi[
i] = (VAEncROI) {
539 param_roi = (VAEncMiscParameterBufferROI) {
541 .max_delta_qp = INT8_MAX,
542 .min_delta_qp = INT8_MIN,
544 .roi_flags.bits.roi_value_is_qp_delta = 1,
548 VAEncMiscParameterTypeROI,
556 vas = vaBeginPicture(
ctx->hwctx->display,
ctx->va_context,
558 if (vas != VA_STATUS_SUCCESS) {
560 "%d (%s).\n", vas, vaErrorStr(vas));
562 goto fail_with_picture;
565 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
567 if (vas != VA_STATUS_SUCCESS) {
569 "%d (%s).\n", vas, vaErrorStr(vas));
571 goto fail_with_picture;
574 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
575 if (vas != VA_STATUS_SUCCESS) {
577 "%d (%s).\n", vas, vaErrorStr(vas));
581 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
588 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
591 vas = vaDestroyBuffer(
ctx->hwctx->display,
593 if (vas != VA_STATUS_SUCCESS) {
595 "param buffer %#x: %d (%s).\n",
607 vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
630 VACodedBufferSegment *buf_list, *buf;
643 if (vas != VA_STATUS_SUCCESS) {
645 "%d (%s).\n", vas, vaErrorStr(vas));
650 for (buf = buf_list; buf; buf = buf->next)
651 total_size += buf->size;
659 for (buf = buf_list; buf; buf = buf->next) {
661 "(status %08x).\n", buf->size, buf->status);
663 memcpy(ptr, buf->buf, buf->size);
673 if (vas != VA_STATUS_SUCCESS) {
675 "%d (%s).\n", vas, vaErrorStr(vas));
702 "%"PRId64
"/%"PRId64
".\n",
721 if (
ctx->codec->picture_priv_data_size > 0) {
770 int is_ref,
int in_dpb,
int prev)
843 if (current_depth ==
ctx->max_b_depth || start->
next->
next == end) {
844 for (pic = start->
next; pic; pic = pic->
next) {
863 for (pic = start->
next; pic != end; pic = pic->
next)
865 for (pic = start->
next,
i = 1; 2 * i < len; pic = pic->next,
i++);
882 current_depth + 1, &next);
887 current_depth + 1, last);
896 int i, b_counter, closed_gop_end;
901 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
916 "encode next.\n", pic->
b_depth);
925 closed_gop_end =
ctx->closed_gop ||
926 ctx->idr_counter ==
ctx->gop_per_idr;
927 for (pic =
ctx->pic_start; pic; pic = next) {
937 if (b_counter ==
ctx->b_per_p)
941 if (
ctx->gop_counter + b_counter + closed_gop_end >=
ctx->gop_size)
945 if (next && next->force_idr)
951 if (!pic &&
ctx->end_of_stream) {
960 "need more input for reference pictures.\n");
963 if (
ctx->input_order <=
ctx->decode_delay && !
ctx->end_of_stream) {
965 "need more input for timestamps.\n");
973 ctx->idr_counter = 1;
974 ctx->gop_counter = 1;
976 }
else if (
ctx->gop_counter + b_counter >=
ctx->gop_size) {
977 if (
ctx->idr_counter ==
ctx->gop_per_idr) {
981 ctx->idr_counter = 1;
988 ctx->gop_counter = 1;
991 if (
ctx->gop_counter + b_counter + closed_gop_end ==
ctx->gop_size) {
1000 ctx->gop_counter += 1 + b_counter;
1013 --
ctx->next_prev->ref_count[0];
1015 if (b_counter > 0) {
1019 ctx->next_prev = pic;
1021 ++
ctx->next_prev->ref_count[0];
1033 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1039 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1046 for (pic =
ctx->pic_start; pic; pic = next) {
1053 ctx->pic_start = next;
1068 if ((
frame->crop_top ||
frame->crop_bottom ||
1069 frame->crop_left ||
frame->crop_right) && !
ctx->crop_warned) {
1071 "frames ignored due to lack of API support.\n");
1072 ctx->crop_warned = 1;
1075 if (!
ctx->roi_allowed) {
1079 if (sd && !
ctx->roi_warned) {
1081 "frames ignored due to lack of driver support.\n");
1082 ctx->roi_warned = 1;
1121 if (
ctx->input_order == 0)
1122 ctx->first_pts = pic->
pts;
1123 if (
ctx->input_order ==
ctx->decode_delay)
1124 ctx->dts_pts_diff = pic->
pts -
ctx->first_pts;
1125 if (
ctx->output_delay > 0)
1126 ctx->ts_ring[
ctx->input_order % (3 *
ctx->output_delay)] = pic->
pts;
1131 if (
ctx->pic_start) {
1132 ctx->pic_end->next = pic;
1135 ctx->pic_start = pic;
1140 ctx->end_of_stream = 1;
1144 if (
ctx->input_order <
ctx->decode_delay)
1145 ctx->dts_pts_diff =
ctx->pic_end->pts -
ctx->first_pts;
1173 if (!
ctx->pic_start) {
1174 if (
ctx->end_of_stream)
1200 if (
ctx->output_delay == 0) {
1209 (3 *
ctx->output_delay)];
1228 ctx->global_params_type[
ctx->nb_global_params] =
type;
1230 ctx->global_params_size[
ctx->nb_global_params] =
size;
1232 ++
ctx->nb_global_params;
1245 {
"YUV400", VA_RT_FORMAT_YUV400, 8, 1, },
1246 {
"YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 },
1247 {
"YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 },
1248 #if VA_CHECK_VERSION(1, 2, 0)
1249 {
"YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 },
1251 {
"YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1252 {
"YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 },
1253 #if VA_CHECK_VERSION(0, 38, 1)
1254 {
"YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
1259 VAEntrypointEncSlice,
1260 VAEntrypointEncPicture,
1261 #if VA_CHECK_VERSION(0, 39, 2)
1262 VAEntrypointEncSliceLP,
1266 #if VA_CHECK_VERSION(0, 39, 2)
1267 static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
1268 VAEntrypointEncSliceLP,
1276 VAProfile *va_profiles =
NULL;
1277 VAEntrypoint *va_entrypoints =
NULL;
1279 const VAEntrypoint *usable_entrypoints;
1282 VAConfigAttrib rt_format_attr;
1284 const char *profile_string, *entrypoint_string;
1285 int i, j, n, depth, err;
1288 if (
ctx->low_power) {
1289 #if VA_CHECK_VERSION(0, 39, 2)
1290 usable_entrypoints = vaapi_encode_entrypoints_low_power;
1293 "supported with this VAAPI version.\n");
1303 ctx->input_frames->sw_format);
1306 depth =
desc->comp[0].depth;
1307 for (
i = 1;
i <
desc->nb_components;
i++) {
1308 if (
desc->comp[
i].depth != depth) {
1317 n = vaMaxNumProfiles(
ctx->hwctx->display);
1323 vas = vaQueryConfigProfiles(
ctx->hwctx->display, va_profiles, &n);
1324 if (vas != VA_STATUS_SUCCESS) {
1326 vas, vaErrorStr(vas));
1332 for (
i = 0; (
ctx->codec->profiles[
i].av_profile !=
1335 if (depth !=
profile->depth ||
1338 if (
desc->nb_components > 1 &&
1346 #if VA_CHECK_VERSION(1, 0, 0)
1347 profile_string = vaProfileStr(
profile->va_profile);
1349 profile_string =
"(no profile names)";
1352 for (j = 0; j < n; j++) {
1353 if (va_profiles[j] ==
profile->va_profile)
1358 "is not supported by driver.\n", profile_string,
1366 if (!
ctx->profile) {
1375 profile_string,
ctx->va_profile);
1377 n = vaMaxNumEntrypoints(
ctx->hwctx->display);
1379 if (!va_entrypoints) {
1383 vas = vaQueryConfigEntrypoints(
ctx->hwctx->display,
ctx->va_profile,
1384 va_entrypoints, &n);
1385 if (vas != VA_STATUS_SUCCESS) {
1387 "profile %s (%d): %d (%s).\n", profile_string,
1388 ctx->va_profile, vas, vaErrorStr(vas));
1393 for (
i = 0;
i < n;
i++) {
1394 for (j = 0; usable_entrypoints[j]; j++) {
1395 if (va_entrypoints[
i] == usable_entrypoints[j])
1398 if (usable_entrypoints[j])
1403 "for profile %s (%d).\n", profile_string,
ctx->va_profile);
1408 ctx->va_entrypoint = va_entrypoints[
i];
1409 #if VA_CHECK_VERSION(1, 0, 0)
1410 entrypoint_string = vaEntrypointStr(
ctx->va_entrypoint);
1412 entrypoint_string =
"(no entrypoint names)";
1415 entrypoint_string,
ctx->va_entrypoint);
1419 if (rt_format->
depth == depth &&
1427 "found for profile %s (%d) entrypoint %s (%d).\n",
1428 profile_string,
ctx->va_profile,
1429 entrypoint_string,
ctx->va_entrypoint);
1434 rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
1435 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1436 ctx->va_profile,
ctx->va_entrypoint,
1437 &rt_format_attr, 1);
1438 if (vas != VA_STATUS_SUCCESS) {
1440 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1445 if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1447 "supported by driver: assuming surface RT format %s "
1448 "is valid.\n", rt_format->
name);
1449 }
else if (!(rt_format_attr.value & rt_format->
value)) {
1451 "by driver for encoding profile %s (%d) entrypoint %s (%d).\n",
1452 rt_format->
name, profile_string,
ctx->va_profile,
1453 entrypoint_string,
ctx->va_entrypoint);
1458 "format %s (%#x).\n", rt_format->
name, rt_format->
value);
1459 ctx->config_attributes[
ctx->nb_config_attributes++] =
1461 .type = VAConfigAttribRTFormat,
1462 .value = rt_format->
value,
1480 #if VA_CHECK_VERSION(1, 1, 0)
1485 #if VA_CHECK_VERSION(1, 3, 0)
1497 uint32_t supported_va_rc_modes;
1499 int64_t rc_bits_per_second;
1500 int rc_target_percentage;
1503 int64_t hrd_buffer_size;
1504 int64_t hrd_initial_buffer_fullness;
1506 VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1508 char supported_rc_modes_string[64];
1510 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1511 ctx->va_profile,
ctx->va_entrypoint,
1513 if (vas != VA_STATUS_SUCCESS) {
1515 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1518 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1520 "supported rate control modes: assuming CQP only.\n");
1521 supported_va_rc_modes = VA_RC_CQP;
1522 strcpy(supported_rc_modes_string,
"unknown");
1524 char *
str = supported_rc_modes_string;
1525 size_t len =
sizeof(supported_rc_modes_string);
1528 supported_va_rc_modes = rc_attr.value;
1531 if (supported_va_rc_modes &
rc_mode->va_mode) {
1547 supported_rc_modes_string);
1562 #define TRY_RC_MODE(mode, fail) do { \
1563 rc_mode = &vaapi_encode_rc_modes[mode]; \
1564 if (!(rc_mode->va_mode & supported_va_rc_modes)) { \
1566 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1567 "RC mode (supported modes: %s).\n", rc_mode->name, \
1568 supported_rc_modes_string); \
1569 return AVERROR(EINVAL); \
1571 av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1572 "RC mode.\n", rc_mode->name); \
1575 goto rc_mode_found; \
1579 if (
ctx->explicit_rc_mode)
1582 if (
ctx->explicit_qp)
1612 "RC mode compatible with selected options "
1613 "(supported modes: %s).\n", supported_rc_modes_string);
1630 rc_bits_per_second = avctx->
bit_rate;
1636 rc_target_percentage = 100;
1643 }
else if (
rc_mode->maxrate) {
1647 "bitrate (%"PRId64
") must not be greater than "
1648 "maxrate (%"PRId64
").\n", avctx->
bit_rate,
1653 rc_target_percentage = (avctx->
bit_rate * 100) /
1660 rc_bits_per_second = 2 * avctx->
bit_rate;
1661 rc_target_percentage = 50;
1666 "in %s RC mode.\n",
rc_mode->name);
1668 rc_bits_per_second = avctx->
bit_rate;
1669 rc_target_percentage = 100;
1672 rc_bits_per_second = 0;
1673 rc_target_percentage = 100;
1677 if (
ctx->explicit_qp) {
1678 rc_quality =
ctx->explicit_qp;
1682 rc_quality =
ctx->codec->default_quality;
1684 "using default (%d).\n", rc_quality);
1700 "must have initial buffer size (%d) <= "
1701 "buffer size (%"PRId64
").\n",
1707 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1710 rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
1714 "in %s RC mode.\n",
rc_mode->name);
1717 hrd_buffer_size = 0;
1718 hrd_initial_buffer_fullness = 0;
1722 rc_window_size = 1000;
1726 if (rc_bits_per_second > UINT32_MAX ||
1727 hrd_buffer_size > UINT32_MAX ||
1728 hrd_initial_buffer_fullness > UINT32_MAX) {
1730 "greater are not supported by VAAPI.\n");
1735 ctx->rc_quality = rc_quality;
1737 ctx->va_bit_rate = rc_bits_per_second;
1740 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1743 ctx->config_attributes[
ctx->nb_config_attributes++] =
1745 .type = VAConfigAttribRateControl,
1746 .value =
ctx->va_rc_mode,
1753 if (
rc_mode->va_mode != VA_RC_CQP) {
1756 "converging in %d frames with %d%% accuracy.\n",
1757 rc_bits_per_second, rc_window_size,
1758 rc_target_percentage);
1759 }
else if (
rc_mode->bitrate) {
1761 "%"PRId64
" bps over %d ms.\n", rc_target_percentage,
1762 rc_bits_per_second, rc_window_size);
1765 ctx->rc_params = (VAEncMiscParameterRateControl) {
1766 .bits_per_second = rc_bits_per_second,
1767 .target_percentage = rc_target_percentage,
1768 .window_size = rc_window_size,
1770 .min_qp = (avctx->
qmin > 0 ? avctx->
qmin : 0),
1771 .basic_unit_size = 0,
1772 #
if VA_CHECK_VERSION(1, 1, 0)
1773 .ICQ_quality_factor =
av_clip(rc_quality, 1, 51),
1774 .max_qp = (avctx->
qmax > 0 ? avctx->
qmax : 0),
1776 #
if VA_CHECK_VERSION(1, 3, 0)
1777 .quality_factor = rc_quality,
1781 VAEncMiscParameterTypeRateControl,
1783 sizeof(
ctx->rc_params));
1788 "initial fullness %"PRId64
" bits.\n",
1789 hrd_buffer_size, hrd_initial_buffer_fullness);
1791 ctx->hrd_params = (VAEncMiscParameterHRD) {
1792 .initial_buffer_fullness = hrd_initial_buffer_fullness,
1793 .buffer_size = hrd_buffer_size,
1796 VAEncMiscParameterTypeHRD,
1798 sizeof(
ctx->hrd_params));
1809 fr_num, fr_den, (
double)fr_num / fr_den);
1811 ctx->fr_params = (VAEncMiscParameterFrameRate) {
1812 .framerate = (
unsigned int)fr_den << 16 | fr_num,
1814 #if VA_CHECK_VERSION(0, 40, 0)
1816 VAEncMiscParameterTypeFrameRate,
1818 sizeof(
ctx->fr_params));
1828 VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
1829 uint32_t ref_l0, ref_l1;
1831 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1835 if (vas != VA_STATUS_SUCCESS) {
1837 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1841 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1842 ref_l0 = ref_l1 = 0;
1844 ref_l0 = attr.value & 0xffff;
1845 ref_l1 = attr.value >> 16 & 0xffff;
1852 }
else if (ref_l0 < 1) {
1854 "reference frames.\n");
1857 ref_l1 < 1 || avctx->max_b_frames < 1) {
1859 "(supported references: %d / %d).\n", ref_l0, ref_l1);
1861 ctx->p_per_i = INT_MAX;
1865 "(supported references: %d / %d).\n", ref_l0, ref_l1);
1867 ctx->p_per_i = INT_MAX;
1873 ctx->max_b_depth = 1;
1879 ctx->gop_per_idr =
ctx->idr_interval + 1;
1881 ctx->closed_gop = 1;
1882 ctx->gop_per_idr = 1;
1889 uint32_t slice_structure)
1899 if (avctx->
slices >
ctx->slice_block_rows) {
1901 "configured number of slices (%d < %d); using "
1902 "maximum.\n",
ctx->slice_block_rows, avctx->
slices);
1903 req_slices =
ctx->slice_block_rows;
1905 req_slices = avctx->
slices;
1907 if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
1908 slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
1909 ctx->nb_slices = req_slices;
1910 ctx->slice_size =
ctx->slice_block_rows /
ctx->nb_slices;
1911 }
else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
1913 for (k = 1;; k *= 2) {
1914 if (2 * k * (req_slices - 1) + 1 >=
ctx->slice_block_rows)
1917 ctx->nb_slices = (
ctx->slice_block_rows + k - 1) / k;
1918 ctx->slice_size = k;
1919 #if VA_CHECK_VERSION(1, 0, 0)
1920 }
else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
1921 ctx->nb_slices =
ctx->slice_block_rows;
1922 ctx->slice_size = 1;
1926 "slice structure modes (%#x).\n", slice_structure);
1934 uint32_t slice_structure)
1939 if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS ||
1940 (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS &&
1941 ctx->tile_cols == 1))) {
1943 "current tile requirement.\n", slice_structure);
1947 if (
ctx->tile_rows >
ctx->slice_block_rows ||
1948 ctx->tile_cols >
ctx->slice_block_cols) {
1950 "for configured number of tile (%d x %d); ",
1951 ctx->slice_block_rows,
ctx->slice_block_cols,
1952 ctx->tile_rows,
ctx->tile_cols);
1953 ctx->tile_rows =
ctx->tile_rows >
ctx->slice_block_rows ?
1954 ctx->slice_block_rows :
ctx->tile_rows;
1955 ctx->tile_cols =
ctx->tile_cols >
ctx->slice_block_cols ?
1956 ctx->slice_block_cols :
ctx->tile_cols;
1958 ctx->tile_rows,
ctx->tile_cols);
1961 req_tiles =
ctx->tile_rows *
ctx->tile_cols;
1966 if (avctx->
slices != req_tiles)
1968 "mismatches with configured number of tile (%d != %d); "
1969 "using requested tile number for slice.\n",
1970 avctx->
slices, req_tiles);
1972 ctx->nb_slices = req_tiles;
1976 for (
i = 0;
i <
ctx->tile_cols;
i++) {
1977 ctx->col_width[
i] = (
i + 1 ) *
ctx->slice_block_cols /
ctx->tile_cols -
1978 i *
ctx->slice_block_cols /
ctx->tile_cols;
1979 ctx->col_bd[
i + 1] =
ctx->col_bd[
i] +
ctx->col_width[
i];
1982 for (
i = 0;
i <
ctx->tile_rows;
i++) {
1983 ctx->row_height[
i] = (
i + 1 ) *
ctx->slice_block_rows /
ctx->tile_rows -
1984 i *
ctx->slice_block_rows /
ctx->tile_rows;
1985 ctx->row_bd[
i + 1] =
ctx->row_bd[
i] +
ctx->row_height[
i];
1989 ctx->tile_rows,
ctx->tile_cols);
1997 VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
1998 { VAConfigAttribEncSliceStructure },
1999 #if VA_CHECK_VERSION(1, 1, 0)
2000 { VAConfigAttribEncTileSupport },
2004 uint32_t max_slices, slice_structure;
2010 "but this codec does not support controlling slices.\n");
2015 ctx->slice_block_rows = (avctx->
height +
ctx->slice_block_height - 1) /
2016 ctx->slice_block_height;
2017 ctx->slice_block_cols = (avctx->
width +
ctx->slice_block_width - 1) /
2018 ctx->slice_block_width;
2020 if (avctx->
slices <= 1 && !
ctx->tile_rows && !
ctx->tile_cols) {
2022 ctx->slice_size =
ctx->slice_block_rows;
2026 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2030 if (vas != VA_STATUS_SUCCESS) {
2032 "attributes: %d (%s).\n", vas, vaErrorStr(vas));
2035 max_slices = attr[0].value;
2036 slice_structure = attr[1].value;
2037 if (max_slices == VA_ATTRIB_NOT_SUPPORTED ||
2038 slice_structure == VA_ATTRIB_NOT_SUPPORTED) {
2040 "pictures as multiple slices.\n.");
2044 if (
ctx->tile_rows &&
ctx->tile_cols) {
2045 #if VA_CHECK_VERSION(1, 1, 0)
2046 uint32_t tile_support = attr[2].value;
2047 if (tile_support == VA_ATTRIB_NOT_SUPPORTED) {
2049 "pictures as multiple tiles.\n.");
2054 "not supported with this VAAPI version.\n");
2059 if (
ctx->tile_rows &&
ctx->tile_cols)
2068 "%d (from %d) due to driver constraints on slice "
2069 "structure.\n",
ctx->nb_slices, avctx->
slices);
2071 if (
ctx->nb_slices > max_slices) {
2073 "encoding with %d slices (max %"PRIu32
").\n",
2074 ctx->nb_slices, max_slices);
2087 VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
2089 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2093 if (vas != VA_STATUS_SUCCESS) {
2095 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2099 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2100 if (
ctx->desired_packed_headers) {
2102 "packed headers (wanted %#x).\n",
2103 ctx->desired_packed_headers);
2106 "packed headers (none wanted).\n");
2108 ctx->va_packed_headers = 0;
2110 if (
ctx->desired_packed_headers & ~attr.value) {
2112 "wanted packed headers (wanted %#x, found %#x).\n",
2113 ctx->desired_packed_headers, attr.value);
2116 "available (wanted %#x, found %#x).\n",
2117 ctx->desired_packed_headers, attr.value);
2119 ctx->va_packed_headers =
ctx->desired_packed_headers & attr.value;
2122 if (
ctx->va_packed_headers) {
2123 ctx->config_attributes[
ctx->nb_config_attributes++] =
2125 .type = VAConfigAttribEncPackedHeaders,
2126 .value =
ctx->va_packed_headers,
2130 if ( (
ctx->desired_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2131 !(
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2134 "sequence headers, but a global header is requested.\n");
2136 "this may result in a stream which is not usable for some "
2137 "purposes (e.g. not muxable to some containers).\n");
2145 #if VA_CHECK_VERSION(0, 36, 0)
2148 VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
2151 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2155 if (vas != VA_STATUS_SUCCESS) {
2157 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2161 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2164 "supported: will use default quality level.\n");
2169 "valid range is 0-%d, using %d.\n",
2170 attr.value, attr.value);
2174 ctx->quality_params = (VAEncMiscParameterBufferQualityLevel) {
2178 VAEncMiscParameterTypeQualityLevel,
2179 &
ctx->quality_params,
2180 sizeof(
ctx->quality_params));
2184 "not supported with this VAAPI version.\n");
2192 #if VA_CHECK_VERSION(1, 0, 0)
2195 VAConfigAttrib attr = { VAConfigAttribEncROI };
2197 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2201 if (vas != VA_STATUS_SUCCESS) {
2203 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2207 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2208 ctx->roi_allowed = 0;
2210 VAConfigAttribValEncROI roi = {
2211 .value = attr.value,
2214 ctx->roi_max_regions = roi.bits.num_roi_regions;
2215 ctx->roi_allowed =
ctx->roi_max_regions > 0 &&
2216 (
ctx->va_rc_mode == VA_RC_CQP ||
2217 roi.bits.roi_rc_qp_delta_support);
2228 VABufferID buffer_id;
2230 buffer_id = (VABufferID)(uintptr_t)
data;
2232 vaDestroyBuffer(
ctx->hwctx->display, buffer_id);
2242 VABufferID buffer_id;
2250 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
2251 VAEncCodedBufferType,
2252 3 *
ctx->surface_width *
ctx->surface_height +
2253 (1 << 16), 1, 0, &buffer_id);
2254 if (vas != VA_STATUS_SUCCESS) {
2256 "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
2267 vaDestroyBuffer(
ctx->hwctx->display, buffer_id);
2302 if (
ctx->input_frames->sw_format ==
2304 recon_format =
ctx->input_frames->sw_format;
2315 recon_format =
ctx->input_frames->sw_format;
2325 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
2326 ctx->surface_width,
ctx->surface_height,
2337 if (!
ctx->recon_frames_ref) {
2344 ctx->recon_frames->sw_format = recon_format;
2345 ctx->recon_frames->width =
ctx->surface_width;
2346 ctx->recon_frames->height =
ctx->surface_height;
2351 "frame context: %d.\n", err);
2369 ctx->va_config = VA_INVALID_ID;
2370 ctx->va_context = VA_INVALID_ID;
2381 "required to associate the encoding device.\n");
2386 if (!
ctx->input_frames_ref) {
2393 if (!
ctx->device_ref) {
2398 ctx->hwctx =
ctx->device->hwctx;
2430 vas = vaCreateConfig(
ctx->hwctx->display,
2431 ctx->va_profile,
ctx->va_entrypoint,
2432 ctx->config_attributes,
ctx->nb_config_attributes,
2434 if (vas != VA_STATUS_SUCCESS) {
2436 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
2445 recon_hwctx =
ctx->recon_frames->hwctx;
2446 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
2447 ctx->surface_width,
ctx->surface_height,
2452 if (vas != VA_STATUS_SUCCESS) {
2454 "context: %d (%s).\n", vas, vaErrorStr(vas));
2459 ctx->output_buffer_pool =
2462 if (!
ctx->output_buffer_pool) {
2467 if (
ctx->codec->configure) {
2468 err =
ctx->codec->configure(avctx);
2473 ctx->output_delay =
ctx->b_per_p;
2474 ctx->decode_delay =
ctx->max_b_depth;
2476 if (
ctx->codec->sequence_params_size > 0) {
2477 ctx->codec_sequence_params =
2479 if (!
ctx->codec_sequence_params) {
2484 if (
ctx->codec->picture_params_size > 0) {
2485 ctx->codec_picture_params =
2487 if (!
ctx->codec_picture_params) {
2493 if (
ctx->codec->init_sequence_params) {
2494 err =
ctx->codec->init_sequence_params(avctx);
2497 "failed: %d.\n", err);
2502 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
2503 ctx->codec->write_sequence_header &&
2506 size_t bit_len = 8 *
sizeof(
data);
2508 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
2511 "for extradata: %d.\n", err);
2541 for (pic =
ctx->pic_start; pic; pic = next) {
2548 if (
ctx->va_context != VA_INVALID_ID) {
2549 vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
2550 ctx->va_context = VA_INVALID_ID;
2553 if (
ctx->va_config != VA_INVALID_ID) {
2554 vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
2555 ctx->va_config = VA_INVALID_ID;