summaryrefslogtreecommitdiff
path: root/libavcodec/vaapi_encode_h264.c
diff options
context:
space:
mode:
authorMark Thompson <sw@jkqxz.net>2018-08-23 00:44:34 +0100
committerMark Thompson <sw@jkqxz.net>2018-08-27 16:21:37 +0100
commit2fd962efbaf40cbc9d7d5e62f20033a82299497a (patch)
tree425c202f5ff8fa6ff21314423a8ed8be56e4b3d2 /libavcodec/vaapi_encode_h264.c
parent45499e557c808f43175524a98901efeca715813e (diff)
downloadffmpeg-2fd962efbaf40cbc9d7d5e62f20033a82299497a.tar.gz
vaapi_encode_h264: Move options and common structures into context
This will make it easier to support options in common between different encoders. It also cleans up some of the field naming.
Diffstat (limited to 'libavcodec/vaapi_encode_h264.c')
-rw-r--r--libavcodec/vaapi_encode_h264.c226
1 files changed, 114 insertions, 112 deletions
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index 905c50760e..9be05b20a5 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -47,6 +47,19 @@ static const uint8_t vaapi_encode_h264_sei_identifier_uuid[16] = {
};
typedef struct VAAPIEncodeH264Context {
+ VAAPIEncodeContext common;
+
+ // User options.
+ int qp;
+ int quality;
+ int low_power;
+ int coder;
+ int aud;
+ int sei;
+ int profile;
+ int level;
+
+ // Derived settings.
int mb_width;
int mb_height;
@@ -54,18 +67,7 @@ typedef struct VAAPIEncodeH264Context {
int fixed_qp_p;
int fixed_qp_b;
- H264RawAUD aud;
- H264RawSPS sps;
- H264RawPPS pps;
- H264RawSEI sei;
- H264RawSlice slice;
-
- H264RawSEIBufferingPeriod buffering_period;
- H264RawSEIPicTiming pic_timing;
- H264RawSEIRecoveryPoint recovery_point;
- H264RawSEIUserDataUnregistered identifier;
- char *identifier_string;
-
+ // Stream state.
int frame_num;
int pic_order_cnt;
int next_frame_num;
@@ -78,32 +80,33 @@ typedef struct VAAPIEncodeH264Context {
int cpb_delay;
int dpb_delay;
+ // Writer structures.
CodedBitstreamContext *cbc;
CodedBitstreamFragment current_access_unit;
+
+ H264RawAUD raw_aud;
+ H264RawSPS raw_sps;
+ H264RawPPS raw_pps;
+ H264RawSEI raw_sei;
+ H264RawSlice raw_slice;
+
+ H264RawSEIBufferingPeriod sei_buffering_period;
+ H264RawSEIPicTiming sei_pic_timing;
+ H264RawSEIRecoveryPoint sei_recovery_point;
+ H264RawSEIUserDataUnregistered sei_identifier;
+ char *sei_identifier_string;
+
int aud_needed;
int sei_needed;
int sei_cbr_workaround_needed;
} VAAPIEncodeH264Context;
-typedef struct VAAPIEncodeH264Options {
- int qp;
- int quality;
- int low_power;
- // Entropy encoder type.
- int coder;
- int aud;
- int sei;
- int profile;
- int level;
-} VAAPIEncodeH264Options;
-
static int vaapi_encode_h264_write_access_unit(AVCodecContext *avctx,
char *data, size_t *data_len,
CodedBitstreamFragment *au)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
int err;
err = ff_cbs_write_fragment_data(priv->cbc, au);
@@ -129,8 +132,7 @@ static int vaapi_encode_h264_add_nal(AVCodecContext *avctx,
CodedBitstreamFragment *au,
void *nal_unit)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
H264RawNALUnitHeader *header = nal_unit;
int err;
@@ -148,23 +150,22 @@ static int vaapi_encode_h264_add_nal(AVCodecContext *avctx,
static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx,
char *data, size_t *data_len)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
CodedBitstreamFragment *au = &priv->current_access_unit;
int err;
if (priv->aud_needed) {
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud);
+ err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud);
if (err < 0)
goto fail;
priv->aud_needed = 0;
}
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->sps);
+ err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_sps);
if (err < 0)
goto fail;
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->pps);
+ err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_pps);
if (err < 0)
goto fail;
@@ -179,19 +180,18 @@ static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx,
VAAPIEncodeSlice *slice,
char *data, size_t *data_len)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
CodedBitstreamFragment *au = &priv->current_access_unit;
int err;
if (priv->aud_needed) {
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud);
+ err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud);
if (err < 0)
goto fail;
priv->aud_needed = 0;
}
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->slice);
+ err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_slice);
if (err < 0)
goto fail;
@@ -206,48 +206,53 @@ static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx,
int index, int *type,
char *data, size_t *data_len)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
CodedBitstreamFragment *au = &priv->current_access_unit;
int err, i;
if (priv->sei_needed) {
+ H264RawSEI *sei = &priv->raw_sei;
+
if (priv->aud_needed) {
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud);
+ err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud);
if (err < 0)
goto fail;
priv->aud_needed = 0;
}
- memset(&priv->sei, 0, sizeof(priv->sei));
- priv->sei.nal_unit_header.nal_unit_type = H264_NAL_SEI;
+ *sei = (H264RawSEI) {
+ .nal_unit_header = {
+ .nal_unit_type = H264_NAL_SEI,
+ },
+ };
i = 0;
+
if (priv->sei_needed & SEI_IDENTIFIER) {
- priv->sei.payload[i].payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED;
- priv->sei.payload[i].payload.user_data_unregistered = priv->identifier;
+ sei->payload[i].payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED;
+ sei->payload[i].payload.user_data_unregistered = priv->sei_identifier;
++i;
}
if (priv->sei_needed & SEI_TIMING) {
if (pic->type == PICTURE_TYPE_IDR) {
- priv->sei.payload[i].payload_type = H264_SEI_TYPE_BUFFERING_PERIOD;
- priv->sei.payload[i].payload.buffering_period = priv->buffering_period;
+ sei->payload[i].payload_type = H264_SEI_TYPE_BUFFERING_PERIOD;
+ sei->payload[i].payload.buffering_period = priv->sei_buffering_period;
++i;
}
- priv->sei.payload[i].payload_type = H264_SEI_TYPE_PIC_TIMING;
- priv->sei.payload[i].payload.pic_timing = priv->pic_timing;
+ sei->payload[i].payload_type = H264_SEI_TYPE_PIC_TIMING;
+ sei->payload[i].payload.pic_timing = priv->sei_pic_timing;
++i;
}
if (priv->sei_needed & SEI_RECOVERY_POINT) {
- priv->sei.payload[i].payload_type = H264_SEI_TYPE_RECOVERY_POINT;
- priv->sei.payload[i].payload.recovery_point = priv->recovery_point;
+ sei->payload[i].payload_type = H264_SEI_TYPE_RECOVERY_POINT;
+ sei->payload[i].payload.recovery_point = priv->sei_recovery_point;
++i;
}
- priv->sei.payload_count = i;
- av_assert0(priv->sei.payload_count > 0);
+ sei->payload_count = i;
+ av_assert0(sei->payload_count > 0);
- err = vaapi_encode_h264_add_nal(avctx, au, &priv->sei);
+ err = vaapi_encode_h264_add_nal(avctx, au, sei);
if (err < 0)
goto fail;
priv->sei_needed = 0;
@@ -285,10 +290,9 @@ fail:
static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
- VAAPIEncodeH264Options *opt = ctx->codec_options;
- H264RawSPS *sps = &priv->sps;
- H264RawPPS *pps = &priv->pps;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
+ H264RawSPS *sps = &priv->raw_sps;
+ H264RawPPS *pps = &priv->raw_pps;
VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params;
@@ -411,8 +415,9 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
sps->vui.fixed_frame_rate_flag = 0;
}
- if (opt->sei & SEI_TIMING) {
+ if (priv->sei & SEI_TIMING) {
H264RawHRD *hrd = &sps->vui.nal_hrd_parameters;
+ H264RawSEIBufferingPeriod *bp = &priv->sei_buffering_period;
sps->vui.nal_hrd_parameters_present_flag = 1;
@@ -439,13 +444,13 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
hrd->dpb_output_delay_length_minus1 = 7;
hrd->time_offset_length = 0;
- priv->buffering_period.seq_parameter_set_id = sps->seq_parameter_set_id;
+ bp->seq_parameter_set_id = sps->seq_parameter_set_id;
// This calculation can easily overflow 32 bits.
- priv->buffering_period.nal.initial_cpb_removal_delay[0] = 90000 *
+ bp->nal.initial_cpb_removal_delay[0] = 90000 *
(uint64_t)ctx->hrd_params.hrd.initial_buffer_fullness /
ctx->hrd_params.hrd.buffer_size;
- priv->buffering_period.nal.initial_cpb_removal_delay_offset[0] = 0;
+ bp->nal.initial_cpb_removal_delay_offset[0] = 0;
} else {
sps->vui.nal_hrd_parameters_present_flag = 0;
sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag;
@@ -468,7 +473,7 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
!(sps->profile_idc == FF_PROFILE_H264_BASELINE ||
sps->profile_idc == FF_PROFILE_H264_EXTENDED ||
sps->profile_idc == FF_PROFILE_H264_CAVLC_444);
- if (!opt->coder && pps->entropy_coding_mode_flag)
+ if (!priv->coder && pps->entropy_coding_mode_flag)
pps->entropy_coding_mode_flag = 0;
pps->num_ref_idx_l0_default_active_minus1 = 0;
@@ -576,9 +581,8 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
VAAPIEncodePicture *pic)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
- VAAPIEncodeH264Options *opt = ctx->codec_options;
- H264RawSPS *sps = &priv->sps;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
+ H264RawSPS *sps = &priv->raw_sps;
VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
int i;
@@ -619,36 +623,42 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
priv->pic_order_cnt = pic->display_order - priv->last_idr_frame;
priv->dpb_delay = pic->display_order - pic->encode_order + 1;
- if (opt->aud) {
+ if (priv->aud) {
priv->aud_needed = 1;
- priv->aud.nal_unit_header.nal_unit_type = H264_NAL_AUD;
- priv->aud.primary_pic_type = priv->primary_pic_type;
+ priv->raw_aud = (H264RawAUD) {
+ .nal_unit_header = {
+ .nal_unit_type = H264_NAL_AUD,
+ },
+ .primary_pic_type = priv->primary_pic_type,
+ };
} else {
priv->aud_needed = 0;
}
priv->sei_needed = 0;
- if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0)
+ if (priv->sei & SEI_IDENTIFIER && pic->encode_order == 0)
priv->sei_needed |= SEI_IDENTIFIER;
#if !CONFIG_VAAPI_1
if (ctx->va_rc_mode == VA_RC_CBR)
priv->sei_cbr_workaround_needed = 1;
#endif
- if (opt->sei & SEI_TIMING) {
- memset(&priv->pic_timing, 0, sizeof(priv->pic_timing));
-
- priv->pic_timing.cpb_removal_delay = 2 * priv->cpb_delay;
- priv->pic_timing.dpb_output_delay = 2 * priv->dpb_delay;
+ if (priv->sei & SEI_TIMING) {
+ priv->sei_pic_timing = (H264RawSEIPicTiming) {
+ .cpb_removal_delay = 2 * priv->cpb_delay,
+ .dpb_output_delay = 2 * priv->dpb_delay,
+ };
priv->sei_needed |= SEI_TIMING;
}
- if (opt->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) {
- priv->recovery_point.recovery_frame_cnt = 0;
- priv->recovery_point.exact_match_flag = 1;
- priv->recovery_point.broken_link_flag = ctx->b_per_p > 0;
+ if (priv->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) {
+ priv->sei_recovery_point = (H264RawSEIRecoveryPoint) {
+ .recovery_frame_cnt = 0,
+ .exact_match_flag = 1,
+ .broken_link_flag = ctx->b_per_p > 0,
+ };
priv->sei_needed |= SEI_RECOVERY_POINT;
}
@@ -699,11 +709,10 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
VAAPIEncodePicture *pic,
VAAPIEncodeSlice *slice)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
- H264RawSPS *sps = &priv->sps;
- H264RawPPS *pps = &priv->pps;
- H264RawSliceHeader *sh = &priv->slice.header;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
+ H264RawSPS *sps = &priv->raw_sps;
+ H264RawPPS *pps = &priv->raw_pps;
+ H264RawSliceHeader *sh = &priv->raw_slice.header;
VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
int i;
@@ -779,8 +788,7 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
- VAAPIEncodeH264Options *opt = ctx->codec_options;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
int err;
err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_H264, avctx);
@@ -791,7 +799,7 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
priv->mb_height = FFALIGN(avctx->height, 16) / 16;
if (ctx->va_rc_mode == VA_RC_CQP) {
- priv->fixed_qp_p = opt->qp;
+ priv->fixed_qp_p = priv->qp;
if (avctx->i_quant_factor > 0.0)
priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
avctx->i_quant_offset) + 0.5);
@@ -803,7 +811,7 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
else
priv->fixed_qp_b = priv->fixed_qp_p;
- opt->sei &= ~SEI_TIMING;
+ priv->sei &= ~SEI_TIMING;
av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
"%d / %d / %d for IDR- / P- / B-frames.\n",
@@ -825,17 +833,17 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
}
if (avctx->compression_level == FF_COMPRESSION_DEFAULT)
- avctx->compression_level = opt->quality;
+ avctx->compression_level = priv->quality;
- if (opt->sei & SEI_IDENTIFIER) {
+ if (priv->sei & SEI_IDENTIFIER) {
const char *lavc = LIBAVCODEC_IDENT;
const char *vaapi = VA_VERSION_S;
const char *driver;
int len;
- memcpy(priv->identifier.uuid_iso_iec_11578,
+ memcpy(priv->sei_identifier.uuid_iso_iec_11578,
vaapi_encode_h264_sei_identifier_uuid,
- sizeof(priv->identifier.uuid_iso_iec_11578));
+ sizeof(priv->sei_identifier.uuid_iso_iec_11578));
driver = vaQueryVendorString(ctx->hwctx->display);
if (!driver)
@@ -843,15 +851,15 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
len = snprintf(NULL, 0, "%s / VAAPI %s / %s", lavc, vaapi, driver);
if (len >= 0) {
- priv->identifier_string = av_malloc(len + 1);
- if (!priv->identifier_string)
+ priv->sei_identifier_string = av_malloc(len + 1);
+ if (!priv->sei_identifier_string)
return AVERROR(ENOMEM);
- snprintf(priv->identifier_string, len + 1,
+ snprintf(priv->sei_identifier_string, len + 1,
"%s / VAAPI %s / %s", lavc, vaapi, driver);
- priv->identifier.data = priv->identifier_string;
- priv->identifier.data_length = len + 1;
+ priv->sei_identifier.data = priv->sei_identifier_string;
+ priv->sei_identifier.data_length = len + 1;
}
}
@@ -883,16 +891,15 @@ static const VAAPIEncodeType vaapi_encode_type_h264 = {
static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Options *opt =
- (VAAPIEncodeH264Options*)ctx->codec_options_data;
+ VAAPIEncodeContext *ctx = avctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
ctx->codec = &vaapi_encode_type_h264;
if (avctx->profile == FF_PROFILE_UNKNOWN)
- avctx->profile = opt->profile;
+ avctx->profile = priv->profile;
if (avctx->level == FF_LEVEL_UNKNOWN)
- avctx->level = opt->level;
+ avctx->level = priv->level;
switch (avctx->profile) {
case FF_PROFILE_H264_BASELINE:
@@ -937,7 +944,7 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
avctx->profile);
return AVERROR(EINVAL);
}
- if (opt->low_power) {
+ if (priv->low_power) {
#if VA_CHECK_VERSION(0, 39, 2)
ctx->va_entrypoint = VAEntrypointEncSliceLP;
#else
@@ -973,19 +980,15 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
static av_cold int vaapi_encode_h264_close(AVCodecContext *avctx)
{
- VAAPIEncodeContext *ctx = avctx->priv_data;
- VAAPIEncodeH264Context *priv = ctx->priv_data;
+ VAAPIEncodeH264Context *priv = avctx->priv_data;
- if (priv) {
- ff_cbs_close(&priv->cbc);
- av_freep(&priv->identifier_string);
- }
+ ff_cbs_close(&priv->cbc);
+ av_freep(&priv->sei_identifier_string);
return ff_vaapi_encode_close(avctx);
}
-#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
- offsetof(VAAPIEncodeH264Options, x))
+#define OFFSET(x) offsetof(VAAPIEncodeH264Context, x)
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
static const AVOption vaapi_encode_h264_options[] = {
{ "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
@@ -1084,8 +1087,7 @@ AVCodec ff_h264_vaapi_encoder = {
.long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_H264,
- .priv_data_size = (sizeof(VAAPIEncodeContext) +
- sizeof(VAAPIEncodeH264Options)),
+ .priv_data_size = sizeof(VAAPIEncodeH264Context),
.init = &vaapi_encode_h264_init,
.encode2 = &ff_vaapi_encode2,
.close = &vaapi_encode_h264_close,