19 #include "config_components.h"
43 int type,
char *
data,
size_t bit_len)
47 VABufferID param_buffer, data_buffer;
49 VAEncPackedHeaderParameterBuffer params = {
51 .bit_length = bit_len,
52 .has_emulation_bytes = 1,
60 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
61 VAEncPackedHeaderParameterBufferType,
62 sizeof(params), 1, ¶ms, ¶m_buffer);
63 if (vas != VA_STATUS_SUCCESS) {
65 "for packed header (type %d): %d (%s).\n",
66 type, vas, vaErrorStr(vas));
71 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
72 VAEncPackedHeaderDataBufferType,
73 (bit_len + 7) / 8, 1,
data, &data_buffer);
74 if (vas != VA_STATUS_SUCCESS) {
76 "for packed header (type %d): %d (%s).\n",
77 type, vas, vaErrorStr(vas));
83 "(%zu bits).\n",
type, param_buffer, data_buffer, bit_len);
101 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
103 if (vas != VA_STATUS_SUCCESS) {
105 "(type %d): %d (%s).\n",
type, vas, vaErrorStr(vas));
124 VAEncMiscParameterBuffer
header = {
127 size_t buffer_size =
sizeof(
header) +
len;
134 VAEncMiscParameterBufferType,
155 #if VA_CHECK_VERSION(1, 9, 0)
156 if (
ctx->has_sync_buffer_func) {
157 vas = vaSyncBuffer(
ctx->hwctx->display,
159 VA_TIMEOUT_INFINITE);
160 if (vas != VA_STATUS_SUCCESS) {
162 "%d (%s).\n", vas, vaErrorStr(vas));
169 if (vas != VA_STATUS_SUCCESS) {
171 "%d (%s).\n", vas, vaErrorStr(vas));
193 rounding =
ctx->slice_block_rows -
ctx->nb_slices *
ctx->slice_size;
201 for (
i = 0;
i < rounding;
i++)
204 for (
i = 0;
i < (rounding + 1) / 2;
i++)
206 for (
i = 0;
i < rounding / 2;
i++)
209 }
else if (rounding < 0) {
245 for (
i = 0;
i <
ctx->tile_cols;
i++) {
246 for (j = 0; j <
ctx->tile_rows; j++) {
252 ctx->row_bd[j] *
ctx->slice_block_cols;
256 "width:%2d height:%2d (%d blocks).\n",
index,
ctx->col_bd[
i],
321 if (
ctx->codec->picture_params_size > 0) {
326 ctx->codec->picture_params_size);
335 VAEncSequenceParameterBufferType,
336 ctx->codec_sequence_params,
337 ctx->codec->sequence_params_size);
343 for (
i = 0;
i <
ctx->nb_global_params;
i++) {
345 ctx->global_params_type[
i],
346 ctx->global_params[
i],
347 ctx->global_params_size[
i]);
353 if (
ctx->codec->init_picture_params) {
354 err =
ctx->codec->init_picture_params(avctx, pic);
357 "parameters: %d.\n", err);
361 VAEncPictureParameterBufferType,
363 ctx->codec->picture_params_size);
368 #if VA_CHECK_VERSION(1, 5, 0)
369 if (
ctx->max_frame_size) {
371 VAEncMiscParameterTypeMaxFrameSize,
373 sizeof(
ctx->mfs_params));
380 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
381 ctx->codec->write_sequence_header) {
382 bit_len = 8 *
sizeof(
data);
383 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
386 "header: %d.\n", err);
390 ctx->codec->sequence_header_type,
397 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_PICTURE &&
398 ctx->codec->write_picture_header) {
399 bit_len = 8 *
sizeof(
data);
400 err =
ctx->codec->write_picture_header(avctx, pic,
data, &bit_len);
403 "header: %d.\n", err);
407 ctx->codec->picture_header_type,
413 if (
ctx->codec->write_extra_buffer) {
417 err =
ctx->codec->write_extra_buffer(avctx, pic,
i, &
type,
423 "buffer %d: %d.\n",
i, err);
434 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_MISC &&
435 ctx->codec->write_extra_header) {
438 bit_len = 8 *
sizeof(
data);
439 err =
ctx->codec->write_extra_header(avctx, pic,
i, &
type,
445 "header %d: %d.\n",
i, err);
465 if (
ctx->tile_rows &&
ctx->tile_cols)
474 if (
ctx->codec->slice_params_size > 0) {
482 if (
ctx->codec->init_slice_params) {
483 err =
ctx->codec->init_slice_params(avctx, pic, slice);
486 "parameters: %d.\n", err);
491 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SLICE &&
492 ctx->codec->write_slice_header) {
493 bit_len = 8 *
sizeof(
data);
494 err =
ctx->codec->write_slice_header(avctx, pic, slice,
498 "header: %d.\n", err);
502 ctx->codec->slice_header_type,
508 if (
ctx->codec->init_slice_params) {
510 VAEncSliceParameterBufferType,
512 ctx->codec->slice_params_size);
518 #if VA_CHECK_VERSION(1, 0, 0)
521 if (sd &&
ctx->roi_allowed) {
524 VAEncMiscParameterBufferROI param_roi;
529 av_assert0(roi_size && sd->size % roi_size == 0);
530 nb_roi = sd->size / roi_size;
531 if (nb_roi >
ctx->roi_max_regions) {
532 if (!
ctx->roi_warned) {
534 "supported by driver (%d > %d).\n",
535 nb_roi,
ctx->roi_max_regions);
538 nb_roi =
ctx->roi_max_regions;
547 for (
i = 0;
i < nb_roi;
i++) {
555 pic->
roi[
i] = (VAEncROI) {
566 param_roi = (VAEncMiscParameterBufferROI) {
568 .max_delta_qp = INT8_MAX,
569 .min_delta_qp = INT8_MIN,
571 .roi_flags.bits.roi_value_is_qp_delta = 1,
575 VAEncMiscParameterTypeROI,
583 vas = vaBeginPicture(
ctx->hwctx->display,
ctx->va_context,
585 if (vas != VA_STATUS_SUCCESS) {
587 "%d (%s).\n", vas, vaErrorStr(vas));
589 goto fail_with_picture;
592 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
594 if (vas != VA_STATUS_SUCCESS) {
596 "%d (%s).\n", vas, vaErrorStr(vas));
598 goto fail_with_picture;
601 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
602 if (vas != VA_STATUS_SUCCESS) {
604 "%d (%s).\n", vas, vaErrorStr(vas));
608 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
615 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
618 vas = vaDestroyBuffer(
ctx->hwctx->display,
620 if (vas != VA_STATUS_SUCCESS) {
622 "param buffer %#x: %d (%s).\n",
634 vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
657 VACodedBufferSegment *buf_list, *buf;
670 if (vas != VA_STATUS_SUCCESS) {
672 "%d (%s).\n", vas, vaErrorStr(vas));
677 for (buf = buf_list; buf; buf = buf->next)
678 total_size += buf->size;
686 for (buf = buf_list; buf; buf = buf->next) {
688 "(status %08x).\n", buf->size, buf->status);
690 memcpy(ptr, buf->buf, buf->size);
701 if (vas != VA_STATUS_SUCCESS) {
703 "%d (%s).\n", vas, vaErrorStr(vas));
738 "%"PRId64
"/%"PRId64
".\n",
757 if (
ctx->codec->picture_priv_data_size > 0) {
808 int is_ref,
int in_dpb,
int prev)
881 if (current_depth ==
ctx->max_b_depth || start->
next->
next == end) {
882 for (pic = start->
next; pic; pic = pic->
next) {
901 for (pic = start->
next; pic != end; pic = pic->
next)
903 for (pic = start->
next,
i = 1; 2 * i < len; pic = pic->next,
i++);
920 current_depth + 1, &next);
925 current_depth + 1, last);
934 int i, b_counter, closed_gop_end;
939 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
954 "encode next.\n", pic->
b_depth);
963 closed_gop_end =
ctx->closed_gop ||
964 ctx->idr_counter ==
ctx->gop_per_idr;
965 for (pic =
ctx->pic_start; pic; pic = next) {
975 if (b_counter ==
ctx->b_per_p)
979 if (
ctx->gop_counter + b_counter + closed_gop_end >=
ctx->gop_size)
983 if (next && next->force_idr)
989 if (!pic &&
ctx->end_of_stream) {
1000 "need more input for reference pictures.\n");
1003 if (
ctx->input_order <=
ctx->decode_delay && !
ctx->end_of_stream) {
1005 "need more input for timestamps.\n");
1013 ctx->idr_counter = 1;
1014 ctx->gop_counter = 1;
1016 }
else if (
ctx->gop_counter + b_counter >=
ctx->gop_size) {
1017 if (
ctx->idr_counter ==
ctx->gop_per_idr) {
1021 ctx->idr_counter = 1;
1028 ctx->gop_counter = 1;
1031 if (
ctx->gop_counter + b_counter + closed_gop_end ==
ctx->gop_size) {
1040 ctx->gop_counter += 1 + b_counter;
1053 --
ctx->next_prev->ref_count[0];
1055 if (b_counter > 0) {
1059 ctx->next_prev = pic;
1061 ++
ctx->next_prev->ref_count[0];
1073 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1079 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1086 for (pic =
ctx->pic_start; pic; pic = next) {
1093 ctx->pic_start = next;
1108 if ((
frame->crop_top ||
frame->crop_bottom ||
1109 frame->crop_left ||
frame->crop_right) && !
ctx->crop_warned) {
1111 "frames ignored due to lack of API support.\n");
1112 ctx->crop_warned = 1;
1115 if (!
ctx->roi_allowed) {
1119 if (sd && !
ctx->roi_warned) {
1121 "frames ignored due to lack of driver support.\n");
1122 ctx->roi_warned = 1;
1170 if (
ctx->input_order == 0)
1171 ctx->first_pts = pic->
pts;
1172 if (
ctx->input_order ==
ctx->decode_delay)
1173 ctx->dts_pts_diff = pic->
pts -
ctx->first_pts;
1174 if (
ctx->output_delay > 0)
1175 ctx->ts_ring[
ctx->input_order %
1176 (3 *
ctx->output_delay +
ctx->async_depth)] = pic->
pts;
1181 if (
ctx->pic_start) {
1182 ctx->pic_end->next = pic;
1185 ctx->pic_start = pic;
1190 ctx->end_of_stream = 1;
1194 if (
ctx->input_order <
ctx->decode_delay)
1195 ctx->dts_pts_diff =
ctx->pic_end->pts -
ctx->first_pts;
1223 if (!
ctx->pic_start) {
1224 if (
ctx->end_of_stream)
1230 if (
ctx->has_sync_buffer_func) {
1279 if (
ctx->output_delay == 0) {
1288 (3 *
ctx->output_delay +
ctx->async_depth)];
1307 ctx->global_params_type[
ctx->nb_global_params] =
type;
1309 ctx->global_params_size[
ctx->nb_global_params] =
size;
1311 ++
ctx->nb_global_params;
1324 {
"YUV400", VA_RT_FORMAT_YUV400, 8, 1, },
1325 {
"YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 },
1326 {
"YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 },
1327 #if VA_CHECK_VERSION(1, 2, 0)
1328 {
"YUV420_12", VA_RT_FORMAT_YUV420_12, 12, 3, 1, 1 },
1329 {
"YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 },
1330 {
"YUV422_12", VA_RT_FORMAT_YUV422_12, 12, 3, 1, 0 },
1331 {
"YUV444_10", VA_RT_FORMAT_YUV444_10, 10, 3, 0, 0 },
1332 {
"YUV444_12", VA_RT_FORMAT_YUV444_12, 12, 3, 0, 0 },
1334 {
"YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1335 {
"XYUV", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1336 {
"YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 },
1337 #if VA_CHECK_VERSION(0, 38, 1)
1338 {
"YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
1343 VAEntrypointEncSlice,
1344 VAEntrypointEncPicture,
1345 #if VA_CHECK_VERSION(0, 39, 2)
1346 VAEntrypointEncSliceLP,
1350 #if VA_CHECK_VERSION(0, 39, 2)
1351 static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
1352 VAEntrypointEncSliceLP,
1360 VAProfile *va_profiles =
NULL;
1361 VAEntrypoint *va_entrypoints =
NULL;
1363 const VAEntrypoint *usable_entrypoints;
1366 VAConfigAttrib rt_format_attr;
1368 const char *profile_string, *entrypoint_string;
1369 int i, j, n, depth, err;
1372 if (
ctx->low_power) {
1373 #if VA_CHECK_VERSION(0, 39, 2)
1374 usable_entrypoints = vaapi_encode_entrypoints_low_power;
1377 "supported with this VAAPI version.\n");
1387 ctx->input_frames->sw_format);
1390 depth =
desc->comp[0].depth;
1391 for (
i = 1;
i <
desc->nb_components;
i++) {
1392 if (
desc->comp[
i].depth != depth) {
1401 n = vaMaxNumProfiles(
ctx->hwctx->display);
1407 vas = vaQueryConfigProfiles(
ctx->hwctx->display, va_profiles, &n);
1408 if (vas != VA_STATUS_SUCCESS) {
1410 vas, vaErrorStr(vas));
1416 for (
i = 0; (
ctx->codec->profiles[
i].av_profile !=
1419 if (depth !=
profile->depth ||
1422 if (
desc->nb_components > 1 &&
1430 #if VA_CHECK_VERSION(1, 0, 0)
1431 profile_string = vaProfileStr(
profile->va_profile);
1433 profile_string =
"(no profile names)";
1436 for (j = 0; j < n; j++) {
1437 if (va_profiles[j] ==
profile->va_profile)
1442 "is not supported by driver.\n", profile_string,
1450 if (!
ctx->profile) {
1459 profile_string,
ctx->va_profile);
1461 n = vaMaxNumEntrypoints(
ctx->hwctx->display);
1463 if (!va_entrypoints) {
1467 vas = vaQueryConfigEntrypoints(
ctx->hwctx->display,
ctx->va_profile,
1468 va_entrypoints, &n);
1469 if (vas != VA_STATUS_SUCCESS) {
1471 "profile %s (%d): %d (%s).\n", profile_string,
1472 ctx->va_profile, vas, vaErrorStr(vas));
1477 for (
i = 0;
i < n;
i++) {
1478 for (j = 0; usable_entrypoints[j]; j++) {
1479 if (va_entrypoints[
i] == usable_entrypoints[j])
1482 if (usable_entrypoints[j])
1487 "for profile %s (%d).\n", profile_string,
ctx->va_profile);
1492 ctx->va_entrypoint = va_entrypoints[
i];
1493 #if VA_CHECK_VERSION(1, 0, 0)
1494 entrypoint_string = vaEntrypointStr(
ctx->va_entrypoint);
1496 entrypoint_string =
"(no entrypoint names)";
1499 entrypoint_string,
ctx->va_entrypoint);
1503 if (rt_format->
depth == depth &&
1511 "found for profile %s (%d) entrypoint %s (%d).\n",
1512 profile_string,
ctx->va_profile,
1513 entrypoint_string,
ctx->va_entrypoint);
1518 rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
1519 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1520 ctx->va_profile,
ctx->va_entrypoint,
1521 &rt_format_attr, 1);
1522 if (vas != VA_STATUS_SUCCESS) {
1524 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1529 if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1531 "supported by driver: assuming surface RT format %s "
1532 "is valid.\n", rt_format->
name);
1533 }
else if (!(rt_format_attr.value & rt_format->
value)) {
1535 "by driver for encoding profile %s (%d) entrypoint %s (%d).\n",
1536 rt_format->
name, profile_string,
ctx->va_profile,
1537 entrypoint_string,
ctx->va_entrypoint);
1542 "format %s (%#x).\n", rt_format->
name, rt_format->
value);
1543 ctx->config_attributes[
ctx->nb_config_attributes++] =
1545 .type = VAConfigAttribRTFormat,
1546 .value = rt_format->
value,
1564 #if VA_CHECK_VERSION(1, 1, 0)
1569 #if VA_CHECK_VERSION(1, 3, 0)
1581 uint32_t supported_va_rc_modes;
1583 int64_t rc_bits_per_second;
1584 int rc_target_percentage;
1587 int64_t hrd_buffer_size;
1588 int64_t hrd_initial_buffer_fullness;
1590 VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1592 char supported_rc_modes_string[64];
1594 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1595 ctx->va_profile,
ctx->va_entrypoint,
1597 if (vas != VA_STATUS_SUCCESS) {
1599 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1602 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1604 "supported rate control modes: assuming CQP only.\n");
1605 supported_va_rc_modes = VA_RC_CQP;
1606 strcpy(supported_rc_modes_string,
"unknown");
1608 char *
str = supported_rc_modes_string;
1609 size_t len =
sizeof(supported_rc_modes_string);
1612 supported_va_rc_modes = rc_attr.value;
1615 if (supported_va_rc_modes &
rc_mode->va_mode) {
1631 supported_rc_modes_string);
1646 #define TRY_RC_MODE(mode, fail) do { \
1647 rc_mode = &vaapi_encode_rc_modes[mode]; \
1648 if (!(rc_mode->va_mode & supported_va_rc_modes)) { \
1650 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1651 "RC mode (supported modes: %s).\n", rc_mode->name, \
1652 supported_rc_modes_string); \
1653 return AVERROR(EINVAL); \
1655 av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1656 "RC mode.\n", rc_mode->name); \
1659 goto rc_mode_found; \
1663 if (
ctx->explicit_rc_mode)
1666 if (
ctx->explicit_qp)
1696 "RC mode compatible with selected options "
1697 "(supported modes: %s).\n", supported_rc_modes_string);
1714 rc_bits_per_second = avctx->
bit_rate;
1720 rc_target_percentage = 100;
1727 }
else if (
rc_mode->maxrate) {
1731 "bitrate (%"PRId64
") must not be greater than "
1732 "maxrate (%"PRId64
").\n", avctx->
bit_rate,
1737 rc_target_percentage = (avctx->
bit_rate * 100) /
1744 rc_bits_per_second = 2 * avctx->
bit_rate;
1745 rc_target_percentage = 50;
1750 "in %s RC mode.\n",
rc_mode->name);
1752 rc_bits_per_second = avctx->
bit_rate;
1753 rc_target_percentage = 100;
1756 rc_bits_per_second = 0;
1757 rc_target_percentage = 100;
1761 if (
ctx->explicit_qp) {
1762 rc_quality =
ctx->explicit_qp;
1766 rc_quality =
ctx->codec->default_quality;
1768 "using default (%d).\n", rc_quality);
1784 "must have initial buffer size (%d) <= "
1785 "buffer size (%"PRId64
").\n",
1791 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1794 rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
1798 "in %s RC mode.\n",
rc_mode->name);
1801 hrd_buffer_size = 0;
1802 hrd_initial_buffer_fullness = 0;
1806 rc_window_size = 1000;
1810 if (rc_bits_per_second > UINT32_MAX ||
1811 hrd_buffer_size > UINT32_MAX ||
1812 hrd_initial_buffer_fullness > UINT32_MAX) {
1814 "greater are not supported by VAAPI.\n");
1819 ctx->rc_quality = rc_quality;
1821 ctx->va_bit_rate = rc_bits_per_second;
1824 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1827 ctx->config_attributes[
ctx->nb_config_attributes++] =
1829 .type = VAConfigAttribRateControl,
1830 .value =
ctx->va_rc_mode,
1837 if (
rc_mode->va_mode != VA_RC_CQP) {
1840 "converging in %d frames with %d%% accuracy.\n",
1841 rc_bits_per_second, rc_window_size,
1842 rc_target_percentage);
1843 }
else if (
rc_mode->bitrate) {
1845 "%"PRId64
" bps over %d ms.\n", rc_target_percentage,
1846 rc_bits_per_second, rc_window_size);
1849 ctx->rc_params = (VAEncMiscParameterRateControl) {
1850 .bits_per_second = rc_bits_per_second,
1851 .target_percentage = rc_target_percentage,
1852 .window_size = rc_window_size,
1854 .min_qp = (avctx->
qmin > 0 ? avctx->
qmin : 0),
1855 .basic_unit_size = 0,
1856 #
if VA_CHECK_VERSION(1, 1, 0)
1857 .ICQ_quality_factor =
av_clip(rc_quality, 1, 51),
1858 .max_qp = (avctx->
qmax > 0 ? avctx->
qmax : 0),
1860 #
if VA_CHECK_VERSION(1, 3, 0)
1861 .quality_factor = rc_quality,
1865 VAEncMiscParameterTypeRateControl,
1867 sizeof(
ctx->rc_params));
1872 "initial fullness %"PRId64
" bits.\n",
1873 hrd_buffer_size, hrd_initial_buffer_fullness);
1875 ctx->hrd_params = (VAEncMiscParameterHRD) {
1876 .initial_buffer_fullness = hrd_initial_buffer_fullness,
1877 .buffer_size = hrd_buffer_size,
1880 VAEncMiscParameterTypeHRD,
1882 sizeof(
ctx->hrd_params));
1893 fr_num, fr_den, (
double)fr_num / fr_den);
1895 ctx->fr_params = (VAEncMiscParameterFrameRate) {
1896 .framerate = (
unsigned int)fr_den << 16 | fr_num,
1898 #if VA_CHECK_VERSION(0, 40, 0)
1900 VAEncMiscParameterTypeFrameRate,
1902 sizeof(
ctx->fr_params));
1910 #if VA_CHECK_VERSION(1, 5, 0)
1912 VAConfigAttrib attr = { VAConfigAttribMaxFrameSize };
1915 if (
ctx->va_rc_mode == VA_RC_CQP) {
1916 ctx->max_frame_size = 0;
1922 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1926 if (vas != VA_STATUS_SUCCESS) {
1927 ctx->max_frame_size = 0;
1929 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1933 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1934 ctx->max_frame_size = 0;
1936 "is not supported.\n");
1939 VAConfigAttribValMaxFrameSize attr_mfs;
1940 attr_mfs.value = attr.value;
1942 if (!attr_mfs.bits.max_frame_size && attr_mfs.bits.multiple_pass) {
1943 ctx->max_frame_size = 0;
1945 "max frame size which has not been implemented in FFmpeg.\n");
1949 ctx->mfs_params = (VAEncMiscParameterBufferMaxFrameSize){
1950 .max_frame_size =
ctx->max_frame_size * 8,
1954 ctx->max_frame_size);
1958 "this VAAPI version.\n");
1969 VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
1970 uint32_t ref_l0, ref_l1;
1971 int prediction_pre_only;
1973 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1977 if (vas != VA_STATUS_SUCCESS) {
1979 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1983 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1984 ref_l0 = ref_l1 = 0;
1986 ref_l0 = attr.value & 0xffff;
1987 ref_l1 = attr.value >> 16 & 0xffff;
1991 prediction_pre_only = 0;
1993 #if VA_CHECK_VERSION(1, 9, 0)
1996 attr = (VAConfigAttrib) { VAConfigAttribPredictionDirection };
1997 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2001 if (vas != VA_STATUS_SUCCESS) {
2003 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2005 }
else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2007 "prediction constraints.\n");
2009 if (((ref_l0 > 0 || ref_l1 > 0) && !(attr.value & VA_PREDICTION_DIRECTION_PREVIOUS)) ||
2010 ((ref_l1 == 0) && (attr.value & (VA_PREDICTION_DIRECTION_FUTURE | VA_PREDICTION_DIRECTION_BI_NOT_EMPTY)))) {
2012 "direction attribute.\n");
2016 if (!(attr.value & VA_PREDICTION_DIRECTION_FUTURE)) {
2017 if (ref_l0 > 0 && ref_l1 > 0) {
2018 prediction_pre_only = 1;
2020 "lists for B-frames.\n");
2024 if (attr.value & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) {
2025 if (ref_l0 > 0 && ref_l1 > 0) {
2028 "replacing them with B-frames.\n");
2039 }
else if (ref_l0 < 1) {
2041 "reference frames.\n");
2044 ref_l1 < 1 || avctx->max_b_frames < 1 ||
2045 prediction_pre_only) {
2048 "(supported references: %d / %d).\n",
2052 "(supported references: %d / %d).\n", ref_l0, ref_l1);
2054 ctx->p_per_i = INT_MAX;
2059 "(supported references: %d / %d).\n",
2063 "(supported references: %d / %d).\n", ref_l0, ref_l1);
2065 ctx->p_per_i = INT_MAX;
2071 ctx->max_b_depth = 1;
2077 ctx->gop_per_idr =
ctx->idr_interval + 1;
2079 ctx->closed_gop = 1;
2080 ctx->gop_per_idr = 1;
2087 uint32_t slice_structure)
2097 if (avctx->
slices >
ctx->slice_block_rows) {
2099 "configured number of slices (%d < %d); using "
2100 "maximum.\n",
ctx->slice_block_rows, avctx->
slices);
2101 req_slices =
ctx->slice_block_rows;
2103 req_slices = avctx->
slices;
2105 if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
2106 slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
2107 ctx->nb_slices = req_slices;
2108 ctx->slice_size =
ctx->slice_block_rows /
ctx->nb_slices;
2109 }
else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
2111 for (k = 1;; k *= 2) {
2112 if (2 * k * (req_slices - 1) + 1 >=
ctx->slice_block_rows)
2115 ctx->nb_slices = (
ctx->slice_block_rows + k - 1) / k;
2116 ctx->slice_size = k;
2117 #if VA_CHECK_VERSION(1, 0, 0)
2118 }
else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
2119 ctx->nb_slices =
ctx->slice_block_rows;
2120 ctx->slice_size = 1;
2124 "slice structure modes (%#x).\n", slice_structure);
2132 uint32_t slice_structure)
2137 if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS ||
2138 (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS &&
2139 ctx->tile_cols == 1))) {
2141 "current tile requirement.\n", slice_structure);
2145 if (
ctx->tile_rows >
ctx->slice_block_rows ||
2146 ctx->tile_cols >
ctx->slice_block_cols) {
2148 "for configured number of tile (%d x %d); ",
2149 ctx->slice_block_rows,
ctx->slice_block_cols,
2150 ctx->tile_rows,
ctx->tile_cols);
2151 ctx->tile_rows =
ctx->tile_rows >
ctx->slice_block_rows ?
2152 ctx->slice_block_rows :
ctx->tile_rows;
2153 ctx->tile_cols =
ctx->tile_cols >
ctx->slice_block_cols ?
2154 ctx->slice_block_cols :
ctx->tile_cols;
2156 ctx->tile_rows,
ctx->tile_cols);
2159 req_tiles =
ctx->tile_rows *
ctx->tile_cols;
2164 if (avctx->
slices != req_tiles)
2166 "mismatches with configured number of tile (%d != %d); "
2167 "using requested tile number for slice.\n",
2168 avctx->
slices, req_tiles);
2170 ctx->nb_slices = req_tiles;
2174 for (
i = 0;
i <
ctx->tile_cols;
i++) {
2175 ctx->col_width[
i] = (
i + 1 ) *
ctx->slice_block_cols /
ctx->tile_cols -
2176 i *
ctx->slice_block_cols /
ctx->tile_cols;
2177 ctx->col_bd[
i + 1] =
ctx->col_bd[
i] +
ctx->col_width[
i];
2180 for (
i = 0;
i <
ctx->tile_rows;
i++) {
2181 ctx->row_height[
i] = (
i + 1 ) *
ctx->slice_block_rows /
ctx->tile_rows -
2182 i *
ctx->slice_block_rows /
ctx->tile_rows;
2183 ctx->row_bd[
i + 1] =
ctx->row_bd[
i] +
ctx->row_height[
i];
2187 ctx->tile_rows,
ctx->tile_cols);
2195 VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
2196 { VAConfigAttribEncSliceStructure },
2197 #if VA_CHECK_VERSION(1, 1, 0)
2198 { VAConfigAttribEncTileSupport },
2202 uint32_t max_slices, slice_structure;
2208 "but this codec does not support controlling slices.\n");
2215 ctx->slice_block_rows = (avctx->
height +
ctx->slice_block_height - 1) /
2216 ctx->slice_block_height;
2217 ctx->slice_block_cols = (avctx->
width +
ctx->slice_block_width - 1) /
2218 ctx->slice_block_width;
2220 if (avctx->
slices <= 1 && !
ctx->tile_rows && !
ctx->tile_cols) {
2222 ctx->slice_size =
ctx->slice_block_rows;
2226 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2230 if (vas != VA_STATUS_SUCCESS) {
2232 "attributes: %d (%s).\n", vas, vaErrorStr(vas));
2235 max_slices = attr[0].value;
2236 slice_structure = attr[1].value;
2237 if (max_slices == VA_ATTRIB_NOT_SUPPORTED ||
2238 slice_structure == VA_ATTRIB_NOT_SUPPORTED) {
2240 "pictures as multiple slices.\n.");
2244 if (
ctx->tile_rows &&
ctx->tile_cols) {
2245 #if VA_CHECK_VERSION(1, 1, 0)
2246 uint32_t tile_support = attr[2].value;
2247 if (tile_support == VA_ATTRIB_NOT_SUPPORTED) {
2249 "pictures as multiple tiles.\n.");
2254 "not supported with this VAAPI version.\n");
2259 if (
ctx->tile_rows &&
ctx->tile_cols)
2268 "%d (from %d) due to driver constraints on slice "
2269 "structure.\n",
ctx->nb_slices, avctx->
slices);
2271 if (
ctx->nb_slices > max_slices) {
2273 "encoding with %d slices (max %"PRIu32
").\n",
2274 ctx->nb_slices, max_slices);
2287 VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
2289 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2293 if (vas != VA_STATUS_SUCCESS) {
2295 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2299 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2300 if (
ctx->desired_packed_headers) {
2302 "packed headers (wanted %#x).\n",
2303 ctx->desired_packed_headers);
2306 "packed headers (none wanted).\n");
2308 ctx->va_packed_headers = 0;
2310 if (
ctx->desired_packed_headers & ~attr.value) {
2312 "wanted packed headers (wanted %#x, found %#x).\n",
2313 ctx->desired_packed_headers, attr.value);
2316 "available (wanted %#x, found %#x).\n",
2317 ctx->desired_packed_headers, attr.value);
2319 ctx->va_packed_headers =
ctx->desired_packed_headers & attr.value;
2322 if (
ctx->va_packed_headers) {
2323 ctx->config_attributes[
ctx->nb_config_attributes++] =
2325 .type = VAConfigAttribEncPackedHeaders,
2326 .value =
ctx->va_packed_headers,
2330 if ( (
ctx->desired_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2331 !(
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2334 "sequence headers, but a global header is requested.\n");
2336 "this may result in a stream which is not usable for some "
2337 "purposes (e.g. not muxable to some containers).\n");
2345 #if VA_CHECK_VERSION(0, 36, 0)
2348 VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
2351 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2355 if (vas != VA_STATUS_SUCCESS) {
2357 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2361 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2364 "supported: will use default quality level.\n");
2369 "valid range is 0-%d, using %d.\n",
2370 attr.value, attr.value);
2374 ctx->quality_params = (VAEncMiscParameterBufferQualityLevel) {
2378 VAEncMiscParameterTypeQualityLevel,
2379 &
ctx->quality_params,
2380 sizeof(
ctx->quality_params));
2384 "not supported with this VAAPI version.\n");
2392 #if VA_CHECK_VERSION(1, 0, 0)
2395 VAConfigAttrib attr = { VAConfigAttribEncROI };
2397 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2401 if (vas != VA_STATUS_SUCCESS) {
2403 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2407 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2408 ctx->roi_allowed = 0;
2410 VAConfigAttribValEncROI roi = {
2411 .value = attr.value,
2414 ctx->roi_max_regions = roi.bits.num_roi_regions;
2415 ctx->roi_allowed =
ctx->roi_max_regions > 0 &&
2416 (
ctx->va_rc_mode == VA_RC_CQP ||
2417 roi.bits.roi_rc_qp_delta_support);
2428 VABufferID buffer_id;
2430 buffer_id = (VABufferID)(uintptr_t)
data;
2432 vaDestroyBuffer(
ctx->hwctx->display, buffer_id);
2442 VABufferID buffer_id;
2450 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
2451 VAEncCodedBufferType,
2452 3 *
ctx->surface_width *
ctx->surface_height +
2453 (1 << 16), 1, 0, &buffer_id);
2454 if (vas != VA_STATUS_SUCCESS) {
2456 "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
2467 vaDestroyBuffer(
ctx->hwctx->display, buffer_id);
2502 if (
ctx->input_frames->sw_format ==
2504 recon_format =
ctx->input_frames->sw_format;
2515 recon_format =
ctx->input_frames->sw_format;
2525 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
2526 ctx->surface_width,
ctx->surface_height,
2537 if (!
ctx->recon_frames_ref) {
2544 ctx->recon_frames->sw_format = recon_format;
2545 ctx->recon_frames->width =
ctx->surface_width;
2546 ctx->recon_frames->height =
ctx->surface_height;
2551 "frame context: %d.\n", err);
2569 ctx->va_config = VA_INVALID_ID;
2570 ctx->va_context = VA_INVALID_ID;
2581 "required to associate the encoding device.\n");
2586 if (!
ctx->input_frames_ref) {
2593 if (!
ctx->device_ref) {
2598 ctx->hwctx =
ctx->device->hwctx;
2604 if (
ctx->codec->get_encoder_caps) {
2605 err =
ctx->codec->get_encoder_caps(avctx);
2613 ctx->slice_block_width = 16;
2614 ctx->slice_block_height = 16;
2644 if (
ctx->max_frame_size) {
2650 vas = vaCreateConfig(
ctx->hwctx->display,
2651 ctx->va_profile,
ctx->va_entrypoint,
2652 ctx->config_attributes,
ctx->nb_config_attributes,
2654 if (vas != VA_STATUS_SUCCESS) {
2656 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
2665 recon_hwctx =
ctx->recon_frames->hwctx;
2666 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
2667 ctx->surface_width,
ctx->surface_height,
2672 if (vas != VA_STATUS_SUCCESS) {
2674 "context: %d (%s).\n", vas, vaErrorStr(vas));
2679 ctx->output_buffer_pool =
2682 if (!
ctx->output_buffer_pool) {
2687 if (
ctx->codec->configure) {
2688 err =
ctx->codec->configure(avctx);
2693 ctx->output_delay =
ctx->b_per_p;
2694 ctx->decode_delay =
ctx->max_b_depth;
2696 if (
ctx->codec->sequence_params_size > 0) {
2697 ctx->codec_sequence_params =
2699 if (!
ctx->codec_sequence_params) {
2704 if (
ctx->codec->picture_params_size > 0) {
2705 ctx->codec_picture_params =
2707 if (!
ctx->codec_picture_params) {
2713 if (
ctx->codec->init_sequence_params) {
2714 err =
ctx->codec->init_sequence_params(avctx);
2717 "failed: %d.\n", err);
2722 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
2723 ctx->codec->write_sequence_header &&
2726 size_t bit_len = 8 *
sizeof(
data);
2728 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
2731 "for extradata: %d.\n", err);
2745 #if VA_CHECK_VERSION(1, 9, 0)
2747 vas = vaSyncBuffer(
ctx->hwctx->display, VA_INVALID_ID, 0);
2748 if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
2749 ctx->has_sync_buffer_func = 1;
2753 if (!
ctx->encode_fifo)
2774 for (pic =
ctx->pic_start; pic; pic = next) {
2781 if (
ctx->va_context != VA_INVALID_ID) {
2782 vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
2783 ctx->va_context = VA_INVALID_ID;
2786 if (
ctx->va_config != VA_INVALID_ID) {
2787 vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
2788 ctx->va_config = VA_INVALID_ID;