mirror of
https://github.com/librempeg/librempeg
synced 2024-11-23 11:39:47 +00:00
vaapi_encode: Add ROI support
This commit is contained in:
parent
62e6b634a8
commit
3387147860
@ -166,6 +166,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
||||
int err, i;
|
||||
char data[MAX_PARAM_BUFFER_SIZE];
|
||||
size_t bit_len;
|
||||
av_unused AVFrameSideData *sd;
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
|
||||
"as type %s.\n", pic->display_order, pic->encode_order,
|
||||
@ -435,6 +436,71 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
||||
}
|
||||
}
|
||||
|
||||
#if VA_CHECK_VERSION(1, 0, 0)
|
||||
sd = av_frame_get_side_data(pic->input_image,
|
||||
AV_FRAME_DATA_REGIONS_OF_INTEREST);
|
||||
if (sd && ctx->roi_allowed) {
|
||||
const AVRegionOfInterest *roi;
|
||||
uint32_t roi_size;
|
||||
VAEncMiscParameterBufferROI param_roi;
|
||||
int nb_roi, i, v;
|
||||
|
||||
roi = (const AVRegionOfInterest*)sd->data;
|
||||
roi_size = roi->self_size;
|
||||
av_assert0(roi_size && sd->size % roi_size == 0);
|
||||
nb_roi = sd->size / roi_size;
|
||||
if (nb_roi > ctx->roi_max_regions) {
|
||||
if (!ctx->roi_warned) {
|
||||
av_log(avctx, AV_LOG_WARNING, "More ROIs set than "
|
||||
"supported by driver (%d > %d).\n",
|
||||
nb_roi, ctx->roi_max_regions);
|
||||
ctx->roi_warned = 1;
|
||||
}
|
||||
nb_roi = ctx->roi_max_regions;
|
||||
}
|
||||
|
||||
pic->roi = av_mallocz_array(nb_roi, sizeof(*pic->roi));
|
||||
if (!pic->roi) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
// For overlapping regions, the first in the array takes priority.
|
||||
for (i = 0; i < nb_roi; i++) {
|
||||
roi = (const AVRegionOfInterest*)(sd->data + roi_size * i);
|
||||
|
||||
av_assert0(roi->qoffset.den != 0);
|
||||
v = roi->qoffset.num * ctx->roi_quant_range / roi->qoffset.den;
|
||||
av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n",
|
||||
roi->top, roi->left, roi->bottom, roi->right, v);
|
||||
|
||||
pic->roi[i] = (VAEncROI) {
|
||||
.roi_rectangle = {
|
||||
.x = roi->left,
|
||||
.y = roi->top,
|
||||
.width = roi->right - roi->left,
|
||||
.height = roi->bottom - roi->top,
|
||||
},
|
||||
.roi_value = av_clip_c(v, INT8_MIN, INT8_MAX),
|
||||
};
|
||||
}
|
||||
|
||||
param_roi = (VAEncMiscParameterBufferROI) {
|
||||
.num_roi = nb_roi,
|
||||
.max_delta_qp = INT8_MAX,
|
||||
.min_delta_qp = INT8_MIN,
|
||||
.roi = pic->roi,
|
||||
.roi_flags.bits.roi_value_is_qp_delta = 1,
|
||||
};
|
||||
|
||||
err = vaapi_encode_make_misc_param_buffer(avctx, pic,
|
||||
VAEncMiscParameterTypeROI,
|
||||
¶m_roi,
|
||||
sizeof(param_roi));
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
|
||||
pic->input_surface);
|
||||
if (vas != VA_STATUS_SUCCESS) {
|
||||
@ -500,6 +566,7 @@ fail_at_end:
|
||||
av_freep(&pic->codec_picture_params);
|
||||
av_freep(&pic->param_buffers);
|
||||
av_freep(&pic->slices);
|
||||
av_freep(&pic->roi);
|
||||
av_frame_free(&pic->recon_image);
|
||||
av_buffer_unref(&pic->output_buffer_ref);
|
||||
pic->output_buffer = VA_INVALID_ID;
|
||||
@ -634,6 +701,7 @@ static int vaapi_encode_free(AVCodecContext *avctx,
|
||||
|
||||
av_freep(&pic->priv_data);
|
||||
av_freep(&pic->codec_picture_params);
|
||||
av_freep(&pic->roi);
|
||||
|
||||
av_free(pic);
|
||||
|
||||
@ -948,6 +1016,17 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx,
|
||||
ctx->crop_warned = 1;
|
||||
}
|
||||
|
||||
if (!ctx->roi_allowed) {
|
||||
AVFrameSideData *sd =
|
||||
av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST);
|
||||
|
||||
if (sd && !ctx->roi_warned) {
|
||||
av_log(avctx, AV_LOG_WARNING, "ROI side data on input "
|
||||
"frames ignored due to lack of driver support.\n");
|
||||
ctx->roi_warned = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1942,6 +2021,39 @@ static av_cold int vaapi_encode_init_quality(AVCodecContext *avctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int vaapi_encode_init_roi(AVCodecContext *avctx)
|
||||
{
|
||||
#if VA_CHECK_VERSION(1, 0, 0)
|
||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||
VAStatus vas;
|
||||
VAConfigAttrib attr = { VAConfigAttribEncROI };
|
||||
|
||||
vas = vaGetConfigAttributes(ctx->hwctx->display,
|
||||
ctx->va_profile,
|
||||
ctx->va_entrypoint,
|
||||
&attr, 1);
|
||||
if (vas != VA_STATUS_SUCCESS) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to query ROI "
|
||||
"config attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
|
||||
if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
|
||||
ctx->roi_allowed = 0;
|
||||
} else {
|
||||
VAConfigAttribValEncROI roi = {
|
||||
.value = attr.value,
|
||||
};
|
||||
|
||||
ctx->roi_max_regions = roi.bits.num_roi_regions;
|
||||
ctx->roi_allowed = ctx->roi_max_regions > 0 &&
|
||||
(ctx->va_rc_mode == VA_RC_CQP ||
|
||||
roi.bits.roi_rc_qp_delta_support);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vaapi_encode_free_output_buffer(void *opaque,
|
||||
uint8_t *data)
|
||||
{
|
||||
@ -2132,6 +2244,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
err = vaapi_encode_init_roi(avctx);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
if (avctx->compression_level >= 0) {
|
||||
err = vaapi_encode_init_quality(avctx);
|
||||
if (err < 0)
|
||||
|
@ -69,6 +69,13 @@ typedef struct VAAPIEncodePicture {
|
||||
int64_t pts;
|
||||
int force_idr;
|
||||
|
||||
#if VA_CHECK_VERSION(1, 0, 0)
|
||||
// ROI regions.
|
||||
VAEncROI *roi;
|
||||
#else
|
||||
void *roi;
|
||||
#endif
|
||||
|
||||
int type;
|
||||
int b_depth;
|
||||
int encode_issued;
|
||||
@ -304,9 +311,20 @@ typedef struct VAAPIEncodeContext {
|
||||
int gop_counter;
|
||||
int end_of_stream;
|
||||
|
||||
// Whether the driver supports ROI at all.
|
||||
int roi_allowed;
|
||||
// Maximum number of regions supported by the driver.
|
||||
int roi_max_regions;
|
||||
// Quantisation range for offset calculations. Set by codec-specific
|
||||
// code, as it may change based on parameters.
|
||||
int roi_quant_range;
|
||||
|
||||
// The encoder does not support cropping information, so warn about
|
||||
// it the first time we encounter any nonzero crop fields.
|
||||
int crop_warned;
|
||||
// If the driver does not support ROI then warn the first time we
|
||||
// encounter a frame with ROI side data.
|
||||
int roi_warned;
|
||||
} VAAPIEncodeContext;
|
||||
|
||||
enum {
|
||||
|
@ -1130,6 +1130,8 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
|
||||
}
|
||||
}
|
||||
|
||||
ctx->roi_quant_range = 51 + 6 * (ctx->profile->depth - 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1102,6 +1102,8 @@ static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx)
|
||||
priv->fixed_qp_b = 30;
|
||||
}
|
||||
|
||||
ctx->roi_quant_range = 51 + 6 * (ctx->profile->depth - 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -552,6 +552,8 @@ static av_cold int vaapi_encode_mpeg2_configure(AVCodecContext *avctx)
|
||||
ctx->nb_slices = ctx->slice_block_rows;
|
||||
ctx->slice_size = 1;
|
||||
|
||||
ctx->roi_quant_range = 31;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -173,6 +173,8 @@ static av_cold int vaapi_encode_vp8_configure(AVCodecContext *avctx)
|
||||
else
|
||||
priv->q_index_i = priv->q_index_p;
|
||||
|
||||
ctx->roi_quant_range = VP8_MAX_QUANT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -202,6 +202,8 @@ static av_cold int vaapi_encode_vp9_configure(AVCodecContext *avctx)
|
||||
priv->q_idx_idr = priv->q_idx_p = priv->q_idx_b = 100;
|
||||
}
|
||||
|
||||
ctx->roi_quant_range = VP9_MAX_QUANT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user