44 int type,
char *
data,
size_t bit_len)
48 VABufferID param_buffer, data_buffer;
50 VAEncPackedHeaderParameterBuffer params = {
52 .bit_length = bit_len,
53 .has_emulation_bytes = 1,
61 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
62 VAEncPackedHeaderParameterBufferType,
63 sizeof(params), 1, ¶ms, ¶m_buffer);
64 if (vas != VA_STATUS_SUCCESS) {
66 "for packed header (type %d): %d (%s).\n",
67 type, vas, vaErrorStr(vas));
72 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
73 VAEncPackedHeaderDataBufferType,
74 (bit_len + 7) / 8, 1,
data, &data_buffer);
75 if (vas != VA_STATUS_SUCCESS) {
77 "for packed header (type %d): %d (%s).\n",
78 type, vas, vaErrorStr(vas));
84 "(%zu bits).\n",
type, param_buffer, data_buffer, bit_len);
102 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
104 if (vas != VA_STATUS_SUCCESS) {
106 "(type %d): %d (%s).\n",
type, vas, vaErrorStr(vas));
125 VAEncMiscParameterBuffer
header = {
128 size_t buffer_size =
sizeof(
header) +
len;
135 VAEncMiscParameterBufferType,
156 #if VA_CHECK_VERSION(1, 9, 0)
157 if (
ctx->has_sync_buffer_func) {
158 vas = vaSyncBuffer(
ctx->hwctx->display,
160 VA_TIMEOUT_INFINITE);
161 if (vas != VA_STATUS_SUCCESS) {
163 "%d (%s).\n", vas, vaErrorStr(vas));
170 if (vas != VA_STATUS_SUCCESS) {
172 "%d (%s).\n", vas, vaErrorStr(vas));
194 rounding =
ctx->slice_block_rows -
ctx->nb_slices *
ctx->slice_size;
202 for (
i = 0;
i < rounding;
i++)
205 for (
i = 0;
i < (rounding + 1) / 2;
i++)
207 for (
i = 0;
i < rounding / 2;
i++)
210 }
else if (rounding < 0) {
246 for (
i = 0;
i <
ctx->tile_cols;
i++) {
247 for (j = 0; j <
ctx->tile_rows; j++) {
253 ctx->row_bd[j] *
ctx->slice_block_cols;
257 "width:%2d height:%2d (%d blocks).\n",
index,
ctx->col_bd[
i],
335 if (
ctx->codec->picture_params_size > 0) {
340 ctx->codec->picture_params_size);
349 VAEncSequenceParameterBufferType,
350 ctx->codec_sequence_params,
351 ctx->codec->sequence_params_size);
357 for (
i = 0;
i <
ctx->nb_global_params;
i++) {
359 ctx->global_params_type[
i],
360 ctx->global_params[
i],
361 ctx->global_params_size[
i]);
367 if (
ctx->codec->init_picture_params) {
368 err =
ctx->codec->init_picture_params(avctx, pic);
371 "parameters: %d.\n", err);
375 VAEncPictureParameterBufferType,
377 ctx->codec->picture_params_size);
382 #if VA_CHECK_VERSION(1, 5, 0)
383 if (
ctx->max_frame_size) {
385 VAEncMiscParameterTypeMaxFrameSize,
387 sizeof(
ctx->mfs_params));
394 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
395 ctx->codec->write_sequence_header) {
396 bit_len = 8 *
sizeof(
data);
397 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
400 "header: %d.\n", err);
404 ctx->codec->sequence_header_type,
411 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_PICTURE &&
412 ctx->codec->write_picture_header) {
413 bit_len = 8 *
sizeof(
data);
414 err =
ctx->codec->write_picture_header(avctx, pic,
data, &bit_len);
417 "header: %d.\n", err);
421 ctx->codec->picture_header_type,
427 if (
ctx->codec->write_extra_buffer) {
431 err =
ctx->codec->write_extra_buffer(avctx, pic,
i, &
type,
437 "buffer %d: %d.\n",
i, err);
448 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_MISC &&
449 ctx->codec->write_extra_header) {
452 bit_len = 8 *
sizeof(
data);
453 err =
ctx->codec->write_extra_header(avctx, pic,
i, &
type,
459 "header %d: %d.\n",
i, err);
479 if (
ctx->tile_rows &&
ctx->tile_cols)
488 if (
ctx->codec->slice_params_size > 0) {
496 if (
ctx->codec->init_slice_params) {
497 err =
ctx->codec->init_slice_params(avctx, pic, slice);
500 "parameters: %d.\n", err);
505 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SLICE &&
506 ctx->codec->write_slice_header) {
507 bit_len = 8 *
sizeof(
data);
508 err =
ctx->codec->write_slice_header(avctx, pic, slice,
512 "header: %d.\n", err);
516 ctx->codec->slice_header_type,
522 if (
ctx->codec->init_slice_params) {
524 VAEncSliceParameterBufferType,
526 ctx->codec->slice_params_size);
532 #if VA_CHECK_VERSION(1, 0, 0)
535 if (sd &&
ctx->roi_allowed) {
538 VAEncMiscParameterBufferROI param_roi;
543 av_assert0(roi_size && sd->size % roi_size == 0);
544 nb_roi = sd->size / roi_size;
545 if (nb_roi >
ctx->roi_max_regions) {
546 if (!
ctx->roi_warned) {
548 "supported by driver (%d > %d).\n",
549 nb_roi,
ctx->roi_max_regions);
552 nb_roi =
ctx->roi_max_regions;
561 for (
i = 0;
i < nb_roi;
i++) {
569 pic->
roi[
i] = (VAEncROI) {
580 param_roi = (VAEncMiscParameterBufferROI) {
582 .max_delta_qp = INT8_MAX,
583 .min_delta_qp = INT8_MIN,
585 .roi_flags.bits.roi_value_is_qp_delta = 1,
589 VAEncMiscParameterTypeROI,
597 vas = vaBeginPicture(
ctx->hwctx->display,
ctx->va_context,
599 if (vas != VA_STATUS_SUCCESS) {
601 "%d (%s).\n", vas, vaErrorStr(vas));
603 goto fail_with_picture;
606 vas = vaRenderPicture(
ctx->hwctx->display,
ctx->va_context,
608 if (vas != VA_STATUS_SUCCESS) {
610 "%d (%s).\n", vas, vaErrorStr(vas));
612 goto fail_with_picture;
615 vas = vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
616 if (vas != VA_STATUS_SUCCESS) {
618 "%d (%s).\n", vas, vaErrorStr(vas));
622 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
629 if (CONFIG_VAAPI_1 ||
ctx->hwctx->driver_quirks &
632 vas = vaDestroyBuffer(
ctx->hwctx->display,
634 if (vas != VA_STATUS_SUCCESS) {
636 "param buffer %#x: %d (%s).\n",
648 vaEndPicture(
ctx->hwctx->display,
ctx->va_context);
692 if (
ctx->output_delay == 0) {
701 (3 *
ctx->output_delay +
ctx->async_depth)];
710 VACodedBufferSegment *buf_list, *buf;
715 vas = vaMapBuffer(
ctx->hwctx->display, buf_id,
717 if (vas != VA_STATUS_SUCCESS) {
719 "%d (%s).\n", vas, vaErrorStr(vas));
724 for (buf = buf_list; buf; buf = buf->next)
727 vas = vaUnmapBuffer(
ctx->hwctx->display, buf_id);
728 if (vas != VA_STATUS_SUCCESS) {
730 "%d (%s).\n", vas, vaErrorStr(vas));
739 VABufferID buf_id, uint8_t **dst)
742 VACodedBufferSegment *buf_list, *buf;
746 vas = vaMapBuffer(
ctx->hwctx->display, buf_id,
748 if (vas != VA_STATUS_SUCCESS) {
750 "%d (%s).\n", vas, vaErrorStr(vas));
755 for (buf = buf_list; buf; buf = buf->next) {
757 "(status %08x).\n", buf->size, buf->status);
759 memcpy(*dst, buf->buf, buf->size);
763 vas = vaUnmapBuffer(
ctx->hwctx->display, buf_id);
764 if (vas != VA_STATUS_SUCCESS) {
766 "%d (%s).\n", vas, vaErrorStr(vas));
778 VABufferID output_buffer_prev;
783 if (
ctx->coded_buffer_ref) {
784 output_buffer_prev = *
ctx->coded_buffer_ref;
801 if (
ctx->coded_buffer_ref) {
835 if (
ctx->tail_pkt->size) {
845 pkt_ptr =
ctx->tail_pkt;
871 "%"PRId64
"/%"PRId64
".\n",
890 if (
ctx->codec->picture_priv_data_size > 0) {
940 int is_ref,
int in_dpb,
int prev)
1023 if (current_depth ==
ctx->max_b_depth || start->
next->
next == end) {
1024 for (pic = start->
next; pic; pic = pic->
next) {
1043 for (pic = start->
next; pic != end; pic = pic->
next)
1045 for (pic = start->
next,
i = 1; 2 * i < len; pic = pic->next,
i++);
1062 current_depth + 1, &next);
1067 current_depth + 1, last);
1081 for (
i = 0;
i <
ctx->nb_next_prev;
i++) {
1082 --
ctx->next_prev[
i]->ref_count[0];
1085 ctx->next_prev[0] = pic;
1087 ctx->nb_next_prev = 1;
1093 ctx->next_prev[
ctx->nb_next_prev++] = pic;
1096 --
ctx->next_prev[0]->ref_count[0];
1098 ctx->next_prev[
i] =
ctx->next_prev[
i + 1];
1099 ctx->next_prev[
i] = pic;
1109 int i, b_counter, closed_gop_end;
1114 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1136 "encode next.\n", pic->
b_depth);
1145 closed_gop_end =
ctx->closed_gop ||
1146 ctx->idr_counter ==
ctx->gop_per_idr;
1147 for (pic =
ctx->pic_start; pic; pic = next) {
1157 if (b_counter ==
ctx->b_per_p)
1161 if (
ctx->gop_counter + b_counter + closed_gop_end >=
ctx->gop_size)
1165 if (next && next->force_idr)
1171 if (!pic &&
ctx->end_of_stream) {
1182 "need more input for reference pictures.\n");
1185 if (
ctx->input_order <=
ctx->decode_delay && !
ctx->end_of_stream) {
1187 "need more input for timestamps.\n");
1195 ctx->idr_counter = 1;
1196 ctx->gop_counter = 1;
1198 }
else if (
ctx->gop_counter + b_counter >=
ctx->gop_size) {
1199 if (
ctx->idr_counter ==
ctx->gop_per_idr) {
1203 ctx->idr_counter = 1;
1210 ctx->gop_counter = 1;
1213 if (
ctx->gop_counter + b_counter + closed_gop_end ==
ctx->gop_size) {
1222 ctx->gop_counter += 1 + b_counter;
1233 for (
i = 0;
i <
ctx->nb_next_prev;
i++)
1245 if (b_counter > 0) {
1264 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1270 for (pic =
ctx->pic_start; pic; pic = pic->
next) {
1277 for (pic =
ctx->pic_start; pic; pic = next) {
1284 ctx->pic_start = next;
1302 "frames ignored due to lack of API support.\n");
1303 ctx->crop_warned = 1;
1306 if (!
ctx->roi_allowed) {
1310 if (sd && !
ctx->roi_warned) {
1312 "frames ignored due to lack of driver support.\n");
1313 ctx->roi_warned = 1;
1361 if (
ctx->input_order == 0)
1362 ctx->first_pts = pic->
pts;
1363 if (
ctx->input_order ==
ctx->decode_delay)
1364 ctx->dts_pts_diff = pic->
pts -
ctx->first_pts;
1365 if (
ctx->output_delay > 0)
1366 ctx->ts_ring[
ctx->input_order %
1367 (3 *
ctx->output_delay +
ctx->async_depth)] = pic->
pts;
1372 if (
ctx->pic_start) {
1373 ctx->pic_end->next = pic;
1376 ctx->pic_start = pic;
1381 ctx->end_of_stream = 1;
1385 if (
ctx->input_order <
ctx->decode_delay)
1386 ctx->dts_pts_diff =
ctx->pic_end->pts -
ctx->first_pts;
1405 if (
ctx->tail_pkt->size) {
1409 else if (!
tmp->next) {
1427 if (!
ctx->pic_start) {
1428 if (
ctx->end_of_stream)
1434 if (
ctx->has_sync_buffer_func) {
1502 ctx->global_params_type[
ctx->nb_global_params] =
type;
1504 ctx->global_params_size[
ctx->nb_global_params] =
size;
1506 ++
ctx->nb_global_params;
1519 {
"YUV400", VA_RT_FORMAT_YUV400, 8, 1, },
1520 {
"YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 },
1521 {
"YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 },
1522 #if VA_CHECK_VERSION(1, 2, 0)
1523 {
"YUV420_12", VA_RT_FORMAT_YUV420_12, 12, 3, 1, 1 },
1524 {
"YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 },
1525 {
"YUV422_12", VA_RT_FORMAT_YUV422_12, 12, 3, 1, 0 },
1526 {
"YUV444_10", VA_RT_FORMAT_YUV444_10, 10, 3, 0, 0 },
1527 {
"YUV444_12", VA_RT_FORMAT_YUV444_12, 12, 3, 0, 0 },
1529 {
"YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1530 {
"XYUV", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1531 {
"YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 },
1532 #if VA_CHECK_VERSION(0, 38, 1)
1533 {
"YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
1538 VAEntrypointEncSlice,
1539 VAEntrypointEncPicture,
1540 #if VA_CHECK_VERSION(0, 39, 2)
1541 VAEntrypointEncSliceLP,
1545 #if VA_CHECK_VERSION(0, 39, 2)
1546 static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
1547 VAEntrypointEncSliceLP,
1555 VAProfile *va_profiles =
NULL;
1556 VAEntrypoint *va_entrypoints =
NULL;
1558 const VAEntrypoint *usable_entrypoints;
1561 VAConfigAttrib rt_format_attr;
1563 const char *profile_string, *entrypoint_string;
1564 int i, j, n, depth, err;
1567 if (
ctx->low_power) {
1568 #if VA_CHECK_VERSION(0, 39, 2)
1569 usable_entrypoints = vaapi_encode_entrypoints_low_power;
1572 "supported with this VAAPI version.\n");
1582 ctx->input_frames->sw_format);
1585 depth =
desc->comp[0].depth;
1586 for (
i = 1;
i <
desc->nb_components;
i++) {
1587 if (
desc->comp[
i].depth != depth) {
1596 n = vaMaxNumProfiles(
ctx->hwctx->display);
1602 vas = vaQueryConfigProfiles(
ctx->hwctx->display, va_profiles, &n);
1603 if (vas != VA_STATUS_SUCCESS) {
1605 vas, vaErrorStr(vas));
1611 for (
i = 0; (
ctx->codec->profiles[
i].av_profile !=
1614 if (depth !=
profile->depth ||
1617 if (
desc->nb_components > 1 &&
1625 #if VA_CHECK_VERSION(1, 0, 0)
1626 profile_string = vaProfileStr(
profile->va_profile);
1628 profile_string =
"(no profile names)";
1631 for (j = 0; j < n; j++) {
1632 if (va_profiles[j] ==
profile->va_profile)
1637 "is not supported by driver.\n", profile_string,
1645 if (!
ctx->profile) {
1654 profile_string,
ctx->va_profile);
1656 n = vaMaxNumEntrypoints(
ctx->hwctx->display);
1658 if (!va_entrypoints) {
1662 vas = vaQueryConfigEntrypoints(
ctx->hwctx->display,
ctx->va_profile,
1663 va_entrypoints, &n);
1664 if (vas != VA_STATUS_SUCCESS) {
1666 "profile %s (%d): %d (%s).\n", profile_string,
1667 ctx->va_profile, vas, vaErrorStr(vas));
1672 for (
i = 0;
i < n;
i++) {
1673 for (j = 0; usable_entrypoints[j]; j++) {
1674 if (va_entrypoints[
i] == usable_entrypoints[j])
1677 if (usable_entrypoints[j])
1682 "for profile %s (%d).\n", profile_string,
ctx->va_profile);
1687 ctx->va_entrypoint = va_entrypoints[
i];
1688 #if VA_CHECK_VERSION(1, 0, 0)
1689 entrypoint_string = vaEntrypointStr(
ctx->va_entrypoint);
1691 entrypoint_string =
"(no entrypoint names)";
1694 entrypoint_string,
ctx->va_entrypoint);
1698 if (rt_format->
depth == depth &&
1706 "found for profile %s (%d) entrypoint %s (%d).\n",
1707 profile_string,
ctx->va_profile,
1708 entrypoint_string,
ctx->va_entrypoint);
1713 rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
1714 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1715 ctx->va_profile,
ctx->va_entrypoint,
1716 &rt_format_attr, 1);
1717 if (vas != VA_STATUS_SUCCESS) {
1719 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1724 if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1726 "supported by driver: assuming surface RT format %s "
1727 "is valid.\n", rt_format->
name);
1728 }
else if (!(rt_format_attr.value & rt_format->
value)) {
1730 "by driver for encoding profile %s (%d) entrypoint %s (%d).\n",
1731 rt_format->
name, profile_string,
ctx->va_profile,
1732 entrypoint_string,
ctx->va_entrypoint);
1737 "format %s (%#x).\n", rt_format->
name, rt_format->
value);
1738 ctx->config_attributes[
ctx->nb_config_attributes++] =
1740 .type = VAConfigAttribRTFormat,
1741 .value = rt_format->
value,
1759 #if VA_CHECK_VERSION(1, 1, 0)
1764 #if VA_CHECK_VERSION(1, 3, 0)
1776 uint32_t supported_va_rc_modes;
1779 int rc_target_percentage;
1783 int64_t hrd_initial_buffer_fullness;
1785 VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1787 char supported_rc_modes_string[64];
1789 vas = vaGetConfigAttributes(
ctx->hwctx->display,
1790 ctx->va_profile,
ctx->va_entrypoint,
1792 if (vas != VA_STATUS_SUCCESS) {
1794 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1797 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1799 "supported rate control modes: assuming CQP only.\n");
1800 supported_va_rc_modes = VA_RC_CQP;
1801 strcpy(supported_rc_modes_string,
"unknown");
1803 char *str = supported_rc_modes_string;
1804 size_t len =
sizeof(supported_rc_modes_string);
1807 supported_va_rc_modes = rc_attr.value;
1809 #if VA_CHECK_VERSION(0, 39, 2)
1810 if (!(supported_va_rc_modes & VA_RC_MB)) {
1817 "or above, which can support BLBRC.\n");
1823 if (supported_va_rc_modes &
rc_mode->va_mode) {
1839 supported_rc_modes_string);
1854 #define TRY_RC_MODE(mode, fail) do { \
1855 rc_mode = &vaapi_encode_rc_modes[mode]; \
1856 if (!(rc_mode->va_mode & supported_va_rc_modes)) { \
1858 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1859 "RC mode (supported modes: %s).\n", rc_mode->name, \
1860 supported_rc_modes_string); \
1861 return AVERROR(EINVAL); \
1863 av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1864 "RC mode.\n", rc_mode->name); \
1867 goto rc_mode_found; \
1871 if (
ctx->explicit_rc_mode)
1874 if (
ctx->explicit_qp)
1904 "RC mode compatible with selected options "
1905 "(supported modes: %s).\n", supported_rc_modes_string);
1922 rc_bits_per_second = avctx->
bit_rate;
1928 rc_target_percentage = 100;
1935 }
else if (
rc_mode->maxrate) {
1939 "bitrate (%"PRId64
") must not be greater than "
1940 "maxrate (%"PRId64
").\n", avctx->
bit_rate,
1945 rc_target_percentage = (avctx->
bit_rate * 100) /
1952 rc_bits_per_second = 2 * avctx->
bit_rate;
1953 rc_target_percentage = 50;
1958 "in %s RC mode.\n",
rc_mode->name);
1960 rc_bits_per_second = avctx->
bit_rate;
1961 rc_target_percentage = 100;
1964 rc_bits_per_second = 0;
1965 rc_target_percentage = 100;
1969 if (
ctx->explicit_qp) {
1970 rc_quality =
ctx->explicit_qp;
1977 rc_quality =
ctx->codec->default_quality;
1979 "using default (%d).\n", rc_quality);
1995 "must have initial buffer size (%d) <= "
1996 "buffer size (%"PRId64
").\n",
2002 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
2005 rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
2009 "in %s RC mode.\n",
rc_mode->name);
2012 hrd_buffer_size = 0;
2013 hrd_initial_buffer_fullness = 0;
2017 rc_window_size = 1000;
2021 if (rc_bits_per_second > UINT32_MAX ||
2022 hrd_buffer_size > UINT32_MAX ||
2023 hrd_initial_buffer_fullness > UINT32_MAX) {
2025 "greater are not supported by VAAPI.\n");
2030 ctx->rc_quality = rc_quality;
2032 ctx->va_bit_rate = rc_bits_per_second;
2036 if (
ctx->blbrc &&
ctx->va_rc_mode == VA_RC_CQP)
2040 if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2043 ctx->config_attributes[
ctx->nb_config_attributes++] =
2045 .type = VAConfigAttribRateControl,
2046 #if VA_CHECK_VERSION(0, 39, 2)
2047 .value =
ctx->blbrc ?
ctx->va_rc_mode | VA_RC_MB :
ctx->va_rc_mode,
2049 .value =
ctx->va_rc_mode,
2057 if (
rc_mode->va_mode != VA_RC_CQP) {
2060 "converging in %d frames with %d%% accuracy.\n",
2061 rc_bits_per_second, rc_window_size,
2062 rc_target_percentage);
2063 }
else if (
rc_mode->bitrate) {
2065 "%"PRId64
" bps over %d ms.\n", rc_target_percentage,
2066 rc_bits_per_second, rc_window_size);
2069 ctx->rc_params = (VAEncMiscParameterRateControl) {
2070 .bits_per_second = rc_bits_per_second,
2071 .target_percentage = rc_target_percentage,
2072 .window_size = rc_window_size,
2074 .min_qp = (avctx->
qmin > 0 ? avctx->
qmin : 0),
2075 .basic_unit_size = 0,
2076 #
if VA_CHECK_VERSION(1, 1, 0)
2077 .ICQ_quality_factor =
av_clip(rc_quality, 1, 51),
2078 .max_qp = (avctx->
qmax > 0 ? avctx->
qmax : 0),
2080 #
if VA_CHECK_VERSION(1, 3, 0)
2081 .quality_factor = rc_quality,
2083 #if VA_CHECK_VERSION(0, 39, 2)
2084 .rc_flags.bits.mb_rate_control =
ctx->blbrc ? 1 : 2,
2088 VAEncMiscParameterTypeRateControl,
2090 sizeof(
ctx->rc_params));
2095 "initial fullness %"PRId64
" bits.\n",
2096 hrd_buffer_size, hrd_initial_buffer_fullness);
2098 ctx->hrd_params = (VAEncMiscParameterHRD) {
2099 .initial_buffer_fullness = hrd_initial_buffer_fullness,
2100 .buffer_size = hrd_buffer_size,
2103 VAEncMiscParameterTypeHRD,
2105 sizeof(
ctx->hrd_params));
2116 fr_num, fr_den, (
double)fr_num / fr_den);
2118 ctx->fr_params = (VAEncMiscParameterFrameRate) {
2119 .framerate = (
unsigned int)fr_den << 16 | fr_num,
2121 #if VA_CHECK_VERSION(0, 40, 0)
2123 VAEncMiscParameterTypeFrameRate,
2125 sizeof(
ctx->fr_params));
2133 #if VA_CHECK_VERSION(1, 5, 0)
2135 VAConfigAttrib attr = { VAConfigAttribMaxFrameSize };
2138 if (
ctx->va_rc_mode == VA_RC_CQP) {
2139 ctx->max_frame_size = 0;
2145 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2149 if (vas != VA_STATUS_SUCCESS) {
2150 ctx->max_frame_size = 0;
2152 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2156 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2157 ctx->max_frame_size = 0;
2159 "is not supported.\n");
2162 VAConfigAttribValMaxFrameSize attr_mfs;
2163 attr_mfs.value = attr.value;
2165 if (!attr_mfs.bits.max_frame_size && attr_mfs.bits.multiple_pass) {
2166 ctx->max_frame_size = 0;
2168 "max frame size which has not been implemented in FFmpeg.\n");
2172 ctx->mfs_params = (VAEncMiscParameterBufferMaxFrameSize){
2173 .max_frame_size =
ctx->max_frame_size * 8,
2177 ctx->max_frame_size);
2181 "this VAAPI version.\n");
2192 VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
2193 uint32_t ref_l0, ref_l1;
2194 int prediction_pre_only;
2196 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2200 if (vas != VA_STATUS_SUCCESS) {
2202 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2206 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2207 ref_l0 = ref_l1 = 0;
2209 ref_l0 = attr.value & 0xffff;
2210 ref_l1 = attr.value >> 16 & 0xffff;
2214 prediction_pre_only = 0;
2216 #if VA_CHECK_VERSION(1, 9, 0)
2219 attr = (VAConfigAttrib) { VAConfigAttribPredictionDirection };
2220 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2224 if (vas != VA_STATUS_SUCCESS) {
2226 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2228 }
else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2230 "prediction constraints.\n");
2232 if (((ref_l0 > 0 || ref_l1 > 0) && !(attr.value & VA_PREDICTION_DIRECTION_PREVIOUS)) ||
2233 ((ref_l1 == 0) && (attr.value & (VA_PREDICTION_DIRECTION_FUTURE | VA_PREDICTION_DIRECTION_BI_NOT_EMPTY)))) {
2235 "direction attribute.\n");
2239 if (!(attr.value & VA_PREDICTION_DIRECTION_FUTURE)) {
2240 if (ref_l0 > 0 && ref_l1 > 0) {
2241 prediction_pre_only = 1;
2243 "lists for B-frames.\n");
2247 if (attr.value & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) {
2248 if (ref_l0 > 0 && ref_l1 > 0) {
2251 "replacing them with B-frames.\n");
2262 }
else if (ref_l0 < 1) {
2264 "reference frames.\n");
2267 ref_l1 < 1 || avctx->max_b_frames < 1 ||
2268 prediction_pre_only) {
2271 "(supported references: %d / %d).\n",
2275 "(supported references: %d / %d).\n", ref_l0, ref_l1);
2277 ctx->p_per_i = INT_MAX;
2282 "(supported references: %d / %d).\n",
2286 "(supported references: %d / %d).\n", ref_l0, ref_l1);
2288 ctx->p_per_i = INT_MAX;
2294 ctx->max_b_depth = 1;
2300 ctx->gop_per_idr =
ctx->idr_interval + 1;
2302 ctx->closed_gop = 1;
2303 ctx->gop_per_idr = 1;
2310 uint32_t slice_structure)
2320 if (avctx->
slices >
ctx->slice_block_rows) {
2322 "configured number of slices (%d < %d); using "
2323 "maximum.\n",
ctx->slice_block_rows, avctx->
slices);
2324 req_slices =
ctx->slice_block_rows;
2326 req_slices = avctx->
slices;
2328 if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
2329 slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
2330 ctx->nb_slices = req_slices;
2331 ctx->slice_size =
ctx->slice_block_rows /
ctx->nb_slices;
2332 }
else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
2334 for (k = 1;; k *= 2) {
2335 if (2 * k * (req_slices - 1) + 1 >=
ctx->slice_block_rows)
2338 ctx->nb_slices = (
ctx->slice_block_rows + k - 1) / k;
2339 ctx->slice_size = k;
2340 #if VA_CHECK_VERSION(1, 0, 0)
2341 }
else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
2342 ctx->nb_slices =
ctx->slice_block_rows;
2343 ctx->slice_size = 1;
2347 "slice structure modes (%#x).\n", slice_structure);
2355 uint32_t slice_structure)
2360 if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS ||
2361 (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS &&
2362 ctx->tile_cols == 1))) {
2364 "current tile requirement.\n", slice_structure);
2368 if (
ctx->tile_rows >
ctx->slice_block_rows ||
2369 ctx->tile_cols >
ctx->slice_block_cols) {
2371 "for configured number of tile (%d x %d); ",
2372 ctx->slice_block_rows,
ctx->slice_block_cols,
2373 ctx->tile_rows,
ctx->tile_cols);
2374 ctx->tile_rows =
ctx->tile_rows >
ctx->slice_block_rows ?
2375 ctx->slice_block_rows :
ctx->tile_rows;
2376 ctx->tile_cols =
ctx->tile_cols >
ctx->slice_block_cols ?
2377 ctx->slice_block_cols :
ctx->tile_cols;
2379 ctx->tile_rows,
ctx->tile_cols);
2382 req_tiles =
ctx->tile_rows *
ctx->tile_cols;
2387 if (avctx->
slices != req_tiles)
2389 "mismatches with configured number of tile (%d != %d); "
2390 "using requested tile number for slice.\n",
2391 avctx->
slices, req_tiles);
2393 ctx->nb_slices = req_tiles;
2397 for (
i = 0;
i <
ctx->tile_cols;
i++) {
2398 ctx->col_width[
i] = (
i + 1 ) *
ctx->slice_block_cols /
ctx->tile_cols -
2399 i *
ctx->slice_block_cols /
ctx->tile_cols;
2400 ctx->col_bd[
i + 1] =
ctx->col_bd[
i] +
ctx->col_width[
i];
2403 for (
i = 0;
i <
ctx->tile_rows;
i++) {
2404 ctx->row_height[
i] = (
i + 1 ) *
ctx->slice_block_rows /
ctx->tile_rows -
2405 i *
ctx->slice_block_rows /
ctx->tile_rows;
2406 ctx->row_bd[
i + 1] =
ctx->row_bd[
i] +
ctx->row_height[
i];
2410 ctx->tile_rows,
ctx->tile_cols);
2418 VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
2419 { VAConfigAttribEncSliceStructure },
2420 #if VA_CHECK_VERSION(1, 1, 0)
2421 { VAConfigAttribEncTileSupport },
2425 uint32_t max_slices, slice_structure;
2431 "but this codec does not support controlling slices.\n");
2438 ctx->slice_block_rows = (avctx->
height +
ctx->slice_block_height - 1) /
2439 ctx->slice_block_height;
2440 ctx->slice_block_cols = (avctx->
width +
ctx->slice_block_width - 1) /
2441 ctx->slice_block_width;
2443 if (avctx->
slices <= 1 && !
ctx->tile_rows && !
ctx->tile_cols) {
2445 ctx->slice_size =
ctx->slice_block_rows;
2449 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2453 if (vas != VA_STATUS_SUCCESS) {
2455 "attributes: %d (%s).\n", vas, vaErrorStr(vas));
2458 max_slices = attr[0].value;
2459 slice_structure = attr[1].value;
2460 if (max_slices == VA_ATTRIB_NOT_SUPPORTED ||
2461 slice_structure == VA_ATTRIB_NOT_SUPPORTED) {
2463 "pictures as multiple slices.\n.");
2467 if (
ctx->tile_rows &&
ctx->tile_cols) {
2468 #if VA_CHECK_VERSION(1, 1, 0)
2469 uint32_t tile_support = attr[2].value;
2470 if (tile_support == VA_ATTRIB_NOT_SUPPORTED) {
2472 "pictures as multiple tiles.\n.");
2477 "not supported with this VAAPI version.\n");
2482 if (
ctx->tile_rows &&
ctx->tile_cols)
2491 "%d (from %d) due to driver constraints on slice "
2492 "structure.\n",
ctx->nb_slices, avctx->
slices);
2494 if (
ctx->nb_slices > max_slices) {
2496 "encoding with %d slices (max %"PRIu32
").\n",
2497 ctx->nb_slices, max_slices);
2510 VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
2512 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2516 if (vas != VA_STATUS_SUCCESS) {
2518 "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2522 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2523 if (
ctx->desired_packed_headers) {
2525 "packed headers (wanted %#x).\n",
2526 ctx->desired_packed_headers);
2529 "packed headers (none wanted).\n");
2531 ctx->va_packed_headers = 0;
2533 if (
ctx->desired_packed_headers & ~attr.value) {
2535 "wanted packed headers (wanted %#x, found %#x).\n",
2536 ctx->desired_packed_headers, attr.value);
2539 "available (wanted %#x, found %#x).\n",
2540 ctx->desired_packed_headers, attr.value);
2542 ctx->va_packed_headers =
ctx->desired_packed_headers & attr.value;
2545 if (
ctx->va_packed_headers) {
2546 ctx->config_attributes[
ctx->nb_config_attributes++] =
2548 .type = VAConfigAttribEncPackedHeaders,
2549 .value =
ctx->va_packed_headers,
2553 if ( (
ctx->desired_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2554 !(
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2557 "sequence headers, but a global header is requested.\n");
2559 "this may result in a stream which is not usable for some "
2560 "purposes (e.g. not muxable to some containers).\n");
2568 #if VA_CHECK_VERSION(0, 36, 0)
2571 VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
2574 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2578 if (vas != VA_STATUS_SUCCESS) {
2580 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2584 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2587 "supported: will use default quality level.\n");
2592 "valid range is 0-%d, using %d.\n",
2593 attr.value, attr.value);
2597 ctx->quality_params = (VAEncMiscParameterBufferQualityLevel) {
2601 VAEncMiscParameterTypeQualityLevel,
2602 &
ctx->quality_params,
2603 sizeof(
ctx->quality_params));
2607 "not supported with this VAAPI version.\n");
2615 #if VA_CHECK_VERSION(1, 0, 0)
2618 VAConfigAttrib attr = { VAConfigAttribEncROI };
2620 vas = vaGetConfigAttributes(
ctx->hwctx->display,
2624 if (vas != VA_STATUS_SUCCESS) {
2626 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2630 if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2631 ctx->roi_allowed = 0;
2633 VAConfigAttribValEncROI roi = {
2634 .value = attr.value,
2637 ctx->roi_max_regions = roi.bits.num_roi_regions;
2638 ctx->roi_allowed =
ctx->roi_max_regions > 0 &&
2639 (
ctx->va_rc_mode == VA_RC_CQP ||
2640 roi.bits.roi_rc_qp_delta_support);
2651 VABufferID *buffer_id_ref = obj;
2652 VABufferID buffer_id = *buffer_id_ref;
2654 vaDestroyBuffer(
ctx->hwctx->display, buffer_id);
2663 VABufferID *buffer_id = obj;
2670 vas = vaCreateBuffer(
ctx->hwctx->display,
ctx->va_context,
2671 VAEncCodedBufferType,
2672 3 *
ctx->surface_width *
ctx->surface_height +
2673 (1 << 16), 1, 0, buffer_id);
2674 if (vas != VA_STATUS_SUCCESS) {
2676 "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
2713 if (
ctx->input_frames->sw_format ==
2715 recon_format =
ctx->input_frames->sw_format;
2726 recon_format =
ctx->input_frames->sw_format;
2736 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
2737 ctx->surface_width,
ctx->surface_height,
2748 if (!
ctx->recon_frames_ref) {
2755 ctx->recon_frames->sw_format = recon_format;
2756 ctx->recon_frames->width =
ctx->surface_width;
2757 ctx->recon_frames->height =
ctx->surface_height;
2762 "frame context: %d.\n", err);
2780 ctx->va_config = VA_INVALID_ID;
2781 ctx->va_context = VA_INVALID_ID;
2792 "required to associate the encoding device.\n");
2797 if (!
ctx->input_frames_ref) {
2804 if (!
ctx->device_ref) {
2809 ctx->hwctx =
ctx->device->hwctx;
2812 if (!
ctx->tail_pkt) {
2821 if (
ctx->codec->get_encoder_caps) {
2822 err =
ctx->codec->get_encoder_caps(avctx);
2830 ctx->slice_block_width = 16;
2831 ctx->slice_block_height = 16;
2861 if (
ctx->max_frame_size) {
2867 vas = vaCreateConfig(
ctx->hwctx->display,
2868 ctx->va_profile,
ctx->va_entrypoint,
2869 ctx->config_attributes,
ctx->nb_config_attributes,
2871 if (vas != VA_STATUS_SUCCESS) {
2873 "configuration: %d (%s).\n", vas, vaErrorStr(vas));
2882 recon_hwctx =
ctx->recon_frames->hwctx;
2883 vas = vaCreateContext(
ctx->hwctx->display,
ctx->va_config,
2884 ctx->surface_width,
ctx->surface_height,
2889 if (vas != VA_STATUS_SUCCESS) {
2891 "context: %d (%s).\n", vas, vaErrorStr(vas));
2896 ctx->output_buffer_pool =
2900 if (!
ctx->output_buffer_pool) {
2905 if (
ctx->codec->configure) {
2906 err =
ctx->codec->configure(avctx);
2911 ctx->output_delay =
ctx->b_per_p;
2912 ctx->decode_delay =
ctx->max_b_depth;
2914 if (
ctx->codec->sequence_params_size > 0) {
2915 ctx->codec_sequence_params =
2917 if (!
ctx->codec_sequence_params) {
2922 if (
ctx->codec->picture_params_size > 0) {
2923 ctx->codec_picture_params =
2925 if (!
ctx->codec_picture_params) {
2931 if (
ctx->codec->init_sequence_params) {
2932 err =
ctx->codec->init_sequence_params(avctx);
2935 "failed: %d.\n", err);
2940 if (
ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
2941 ctx->codec->write_sequence_header &&
2944 size_t bit_len = 8 *
sizeof(
data);
2946 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
2949 "for extradata: %d.\n", err);
2963 #if VA_CHECK_VERSION(1, 9, 0)
2965 vas = vaSyncBuffer(
ctx->hwctx->display, VA_INVALID_ID, 0);
2966 if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
2967 ctx->has_sync_buffer_func = 1;
2971 if (!
ctx->encode_fifo)
2992 for (pic =
ctx->pic_start; pic; pic = next) {
2999 if (
ctx->va_context != VA_INVALID_ID) {
3001 vaDestroyContext(
ctx->hwctx->display,
ctx->va_context);
3002 ctx->va_context = VA_INVALID_ID;
3005 if (
ctx->va_config != VA_INVALID_ID) {
3007 vaDestroyConfig(
ctx->hwctx->display,
ctx->va_config);
3008 ctx->va_config = VA_INVALID_ID;