mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
vaapi_encode_h265: Support more complex reference structures
The reference picture sets are now constructed directly from the DPB information.
This commit is contained in:
parent
25c0ede93b
commit
362992e94b
@ -42,6 +42,16 @@ enum {
|
|||||||
SEI_CONTENT_LIGHT_LEVEL = 0x10,
|
SEI_CONTENT_LIGHT_LEVEL = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct VAAPIEncodeH265Picture {
|
||||||
|
int pic_order_cnt;
|
||||||
|
|
||||||
|
int64_t last_idr_frame;
|
||||||
|
|
||||||
|
int slice_nal_unit;
|
||||||
|
int slice_type;
|
||||||
|
int pic_type;
|
||||||
|
} VAAPIEncodeH265Picture;
|
||||||
|
|
||||||
typedef struct VAAPIEncodeH265Context {
|
typedef struct VAAPIEncodeH265Context {
|
||||||
VAAPIEncodeContext common;
|
VAAPIEncodeContext common;
|
||||||
|
|
||||||
@ -58,14 +68,6 @@ typedef struct VAAPIEncodeH265Context {
|
|||||||
int fixed_qp_p;
|
int fixed_qp_p;
|
||||||
int fixed_qp_b;
|
int fixed_qp_b;
|
||||||
|
|
||||||
// Stream state.
|
|
||||||
int64_t last_idr_frame;
|
|
||||||
int pic_order_cnt;
|
|
||||||
|
|
||||||
int slice_nal_unit;
|
|
||||||
int slice_type;
|
|
||||||
int pic_type;
|
|
||||||
|
|
||||||
// Writer structures.
|
// Writer structures.
|
||||||
H265RawAUD raw_aud;
|
H265RawAUD raw_aud;
|
||||||
H265RawVPS raw_vps;
|
H265RawVPS raw_vps;
|
||||||
@ -361,8 +363,8 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vps->vps_sub_layer_ordering_info_present_flag = 0;
|
vps->vps_sub_layer_ordering_info_present_flag = 0;
|
||||||
vps->vps_max_dec_pic_buffering_minus1[0] = (ctx->b_per_p > 0) + 1;
|
vps->vps_max_dec_pic_buffering_minus1[0] = ctx->max_b_depth + 1;
|
||||||
vps->vps_max_num_reorder_pics[0] = (ctx->b_per_p > 0);
|
vps->vps_max_num_reorder_pics[0] = ctx->max_b_depth;
|
||||||
vps->vps_max_latency_increase_plus1[0] = 0;
|
vps->vps_max_latency_increase_plus1[0] = 0;
|
||||||
|
|
||||||
vps->vps_max_layer_id = 0;
|
vps->vps_max_layer_id = 0;
|
||||||
@ -673,41 +675,54 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
|
|||||||
static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
|
static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
|
||||||
VAAPIEncodePicture *pic)
|
VAAPIEncodePicture *pic)
|
||||||
{
|
{
|
||||||
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||||
VAAPIEncodeH265Context *priv = avctx->priv_data;
|
VAAPIEncodeH265Context *priv = avctx->priv_data;
|
||||||
|
VAAPIEncodeH265Picture *hpic = pic->priv_data;
|
||||||
|
VAAPIEncodePicture *prev = pic->prev;
|
||||||
|
VAAPIEncodeH265Picture *hprev = prev ? prev->priv_data : NULL;
|
||||||
VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params;
|
VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (pic->type == PICTURE_TYPE_IDR) {
|
if (pic->type == PICTURE_TYPE_IDR) {
|
||||||
av_assert0(pic->display_order == pic->encode_order);
|
av_assert0(pic->display_order == pic->encode_order);
|
||||||
|
|
||||||
priv->last_idr_frame = pic->display_order;
|
hpic->last_idr_frame = pic->display_order;
|
||||||
|
|
||||||
priv->slice_nal_unit = HEVC_NAL_IDR_W_RADL;
|
hpic->slice_nal_unit = HEVC_NAL_IDR_W_RADL;
|
||||||
priv->slice_type = HEVC_SLICE_I;
|
hpic->slice_type = HEVC_SLICE_I;
|
||||||
priv->pic_type = 0;
|
hpic->pic_type = 0;
|
||||||
} else {
|
} else {
|
||||||
av_assert0(pic->encode_order > priv->last_idr_frame);
|
av_assert0(prev);
|
||||||
|
hpic->last_idr_frame = hprev->last_idr_frame;
|
||||||
|
|
||||||
if (pic->type == PICTURE_TYPE_I) {
|
if (pic->type == PICTURE_TYPE_I) {
|
||||||
priv->slice_nal_unit = HEVC_NAL_CRA_NUT;
|
hpic->slice_nal_unit = HEVC_NAL_CRA_NUT;
|
||||||
priv->slice_type = HEVC_SLICE_I;
|
hpic->slice_type = HEVC_SLICE_I;
|
||||||
priv->pic_type = 0;
|
hpic->pic_type = 0;
|
||||||
} else if (pic->type == PICTURE_TYPE_P) {
|
} else if (pic->type == PICTURE_TYPE_P) {
|
||||||
av_assert0(pic->refs[0]);
|
av_assert0(pic->refs[0]);
|
||||||
priv->slice_nal_unit = HEVC_NAL_TRAIL_R;
|
hpic->slice_nal_unit = HEVC_NAL_TRAIL_R;
|
||||||
priv->slice_type = HEVC_SLICE_P;
|
hpic->slice_type = HEVC_SLICE_P;
|
||||||
priv->pic_type = 1;
|
hpic->pic_type = 1;
|
||||||
} else {
|
} else {
|
||||||
|
VAAPIEncodePicture *irap_ref;
|
||||||
av_assert0(pic->refs[0] && pic->refs[1]);
|
av_assert0(pic->refs[0] && pic->refs[1]);
|
||||||
if (pic->refs[1]->type == PICTURE_TYPE_I)
|
for (irap_ref = pic; irap_ref; irap_ref = irap_ref->refs[1]) {
|
||||||
priv->slice_nal_unit = HEVC_NAL_RASL_N;
|
if (irap_ref->type == PICTURE_TYPE_I)
|
||||||
else
|
break;
|
||||||
priv->slice_nal_unit = HEVC_NAL_TRAIL_N;
|
}
|
||||||
priv->slice_type = HEVC_SLICE_B;
|
if (pic->b_depth == ctx->max_b_depth) {
|
||||||
priv->pic_type = 2;
|
hpic->slice_nal_unit = irap_ref ? HEVC_NAL_RASL_N
|
||||||
|
: HEVC_NAL_TRAIL_N;
|
||||||
|
} else {
|
||||||
|
hpic->slice_nal_unit = irap_ref ? HEVC_NAL_RASL_R
|
||||||
|
: HEVC_NAL_TRAIL_R;
|
||||||
|
}
|
||||||
|
hpic->slice_type = HEVC_SLICE_B;
|
||||||
|
hpic->pic_type = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
priv->pic_order_cnt = pic->display_order - priv->last_idr_frame;
|
hpic->pic_order_cnt = pic->display_order - hpic->last_idr_frame;
|
||||||
|
|
||||||
if (priv->aud) {
|
if (priv->aud) {
|
||||||
priv->aud_needed = 1;
|
priv->aud_needed = 1;
|
||||||
@ -717,7 +732,7 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
|
|||||||
.nuh_layer_id = 0,
|
.nuh_layer_id = 0,
|
||||||
.nuh_temporal_id_plus1 = 1,
|
.nuh_temporal_id_plus1 = 1,
|
||||||
},
|
},
|
||||||
.pic_type = priv->pic_type,
|
.pic_type = hpic->pic_type,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
priv->aud_needed = 0;
|
priv->aud_needed = 0;
|
||||||
@ -797,17 +812,20 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
|
|||||||
|
|
||||||
vpic->decoded_curr_pic = (VAPictureHEVC) {
|
vpic->decoded_curr_pic = (VAPictureHEVC) {
|
||||||
.picture_id = pic->recon_surface,
|
.picture_id = pic->recon_surface,
|
||||||
.pic_order_cnt = priv->pic_order_cnt,
|
.pic_order_cnt = hpic->pic_order_cnt,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i = 0; i < pic->nb_refs; i++) {
|
for (i = 0; i < pic->nb_refs; i++) {
|
||||||
VAAPIEncodePicture *ref = pic->refs[i];
|
VAAPIEncodePicture *ref = pic->refs[i];
|
||||||
|
VAAPIEncodeH265Picture *href;
|
||||||
|
|
||||||
av_assert0(ref && ref->encode_order < pic->encode_order);
|
av_assert0(ref && ref->encode_order < pic->encode_order);
|
||||||
|
href = ref->priv_data;
|
||||||
|
|
||||||
vpic->reference_frames[i] = (VAPictureHEVC) {
|
vpic->reference_frames[i] = (VAPictureHEVC) {
|
||||||
.picture_id = ref->recon_surface,
|
.picture_id = ref->recon_surface,
|
||||||
.pic_order_cnt = ref->display_order - priv->last_idr_frame,
|
.pic_order_cnt = href->pic_order_cnt,
|
||||||
.flags = (ref->display_order < pic->display_order ?
|
.flags = (ref->display_order < pic->display_order ?
|
||||||
VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) |
|
VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) |
|
||||||
(ref->display_order > pic->display_order ?
|
(ref->display_order > pic->display_order ?
|
||||||
@ -823,7 +841,7 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
|
|||||||
|
|
||||||
vpic->coded_buf = pic->output_buffer;
|
vpic->coded_buf = pic->output_buffer;
|
||||||
|
|
||||||
vpic->nal_unit_type = priv->slice_nal_unit;
|
vpic->nal_unit_type = hpic->slice_nal_unit;
|
||||||
|
|
||||||
switch (pic->type) {
|
switch (pic->type) {
|
||||||
case PICTURE_TYPE_IDR:
|
case PICTURE_TYPE_IDR:
|
||||||
@ -857,8 +875,8 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
|
|||||||
VAAPIEncodePicture *pic,
|
VAAPIEncodePicture *pic,
|
||||||
VAAPIEncodeSlice *slice)
|
VAAPIEncodeSlice *slice)
|
||||||
{
|
{
|
||||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
||||||
VAAPIEncodeH265Context *priv = avctx->priv_data;
|
VAAPIEncodeH265Context *priv = avctx->priv_data;
|
||||||
|
VAAPIEncodeH265Picture *hpic = pic->priv_data;
|
||||||
const H265RawSPS *sps = &priv->raw_sps;
|
const H265RawSPS *sps = &priv->raw_sps;
|
||||||
const H265RawPPS *pps = &priv->raw_pps;
|
const H265RawPPS *pps = &priv->raw_pps;
|
||||||
H265RawSliceHeader *sh = &priv->raw_slice.header;
|
H265RawSliceHeader *sh = &priv->raw_slice.header;
|
||||||
@ -867,7 +885,7 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
sh->nal_unit_header = (H265RawNALUnitHeader) {
|
sh->nal_unit_header = (H265RawNALUnitHeader) {
|
||||||
.nal_unit_type = priv->slice_nal_unit,
|
.nal_unit_type = hpic->slice_nal_unit,
|
||||||
.nuh_layer_id = 0,
|
.nuh_layer_id = 0,
|
||||||
.nuh_temporal_id_plus1 = 1,
|
.nuh_temporal_id_plus1 = 1,
|
||||||
};
|
};
|
||||||
@ -877,64 +895,74 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
|
|||||||
sh->first_slice_segment_in_pic_flag = slice->index == 0;
|
sh->first_slice_segment_in_pic_flag = slice->index == 0;
|
||||||
sh->slice_segment_address = slice->block_start;
|
sh->slice_segment_address = slice->block_start;
|
||||||
|
|
||||||
sh->slice_type = priv->slice_type;
|
sh->slice_type = hpic->slice_type;
|
||||||
|
|
||||||
sh->slice_pic_order_cnt_lsb = priv->pic_order_cnt &
|
sh->slice_pic_order_cnt_lsb = hpic->pic_order_cnt &
|
||||||
(1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1;
|
(1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1;
|
||||||
|
|
||||||
if (pic->type != PICTURE_TYPE_IDR) {
|
if (pic->type != PICTURE_TYPE_IDR) {
|
||||||
H265RawSTRefPicSet *rps;
|
H265RawSTRefPicSet *rps;
|
||||||
VAAPIEncodePicture *st;
|
int rps_poc[MAX_DPB_SIZE];
|
||||||
int used;
|
int rps_used[MAX_DPB_SIZE];
|
||||||
|
int i, j, poc, rps_pics;
|
||||||
|
|
||||||
sh->short_term_ref_pic_set_sps_flag = 0;
|
sh->short_term_ref_pic_set_sps_flag = 0;
|
||||||
|
|
||||||
rps = &sh->short_term_ref_pic_set;
|
rps = &sh->short_term_ref_pic_set;
|
||||||
memset(rps, 0, sizeof(*rps));
|
memset(rps, 0, sizeof(*rps));
|
||||||
|
|
||||||
for (st = ctx->pic_start; st; st = st->next) {
|
rps_pics = 0;
|
||||||
if (st->encode_order >= pic->encode_order) {
|
for (i = 0; i < pic->nb_dpb_pics; i++) {
|
||||||
// Not yet in DPB.
|
VAAPIEncodeH265Picture *strp;
|
||||||
|
if (pic->dpb[i] == pic)
|
||||||
continue;
|
continue;
|
||||||
|
strp = pic->dpb[i]->priv_data;
|
||||||
|
rps_poc[rps_pics] = strp->pic_order_cnt;
|
||||||
|
rps_used[rps_pics] = 0;
|
||||||
|
for (j = 0; j < pic->nb_refs; j++)
|
||||||
|
if (pic->dpb[i] == pic->refs[j])
|
||||||
|
rps_used[rps_pics] = 1;
|
||||||
|
++rps_pics;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < rps_pics; i++) {
|
||||||
|
for (j = i; j > 0; j--) {
|
||||||
|
if (rps_poc[j] > rps_poc[j - 1])
|
||||||
|
break;
|
||||||
|
av_assert0(rps_poc[j] != rps_poc[j - 1]);
|
||||||
|
FFSWAP(int, rps_poc[j], rps_poc[j - 1]);
|
||||||
|
FFSWAP(int, rps_used[j], rps_used[j - 1]);
|
||||||
}
|
}
|
||||||
used = 0;
|
}
|
||||||
for (i = 0; i < pic->nb_refs; i++) {
|
|
||||||
if (pic->refs[i] == st)
|
av_log(avctx, AV_LOG_DEBUG, "RPS for POC %d:",
|
||||||
used = 1;
|
hpic->pic_order_cnt);
|
||||||
}
|
for (i = 0; i < rps_pics; i++) {
|
||||||
if (!used) {
|
av_log(avctx, AV_LOG_DEBUG, " (%d,%d)",
|
||||||
// Usually each picture always uses all of the others in the
|
rps_poc[i], rps_used[i]);
|
||||||
// DPB as references. The one case we have to treat here is
|
}
|
||||||
// a non-IDR IRAP picture, which may need to hold unused
|
av_log(avctx, AV_LOG_DEBUG, "\n");
|
||||||
// references across itself to be used for the decoding of
|
|
||||||
// following RASL pictures. This looks for such an RASL
|
for (i = 0; i < rps_pics; i++) {
|
||||||
// picture, and keeps the reference if there is one.
|
av_assert0(rps_poc[i] != hpic->pic_order_cnt);
|
||||||
VAAPIEncodePicture *rp;
|
if (rps_poc[i] > hpic->pic_order_cnt)
|
||||||
for (rp = ctx->pic_start; rp; rp = rp->next) {
|
break;
|
||||||
if (rp->encode_order < pic->encode_order)
|
}
|
||||||
continue;
|
|
||||||
if (rp->type != PICTURE_TYPE_B)
|
rps->num_negative_pics = i;
|
||||||
continue;
|
poc = hpic->pic_order_cnt;
|
||||||
if (rp->refs[0] == st && rp->refs[1] == pic)
|
for (j = i - 1; j >= 0; j--) {
|
||||||
break;
|
rps->delta_poc_s0_minus1[i - 1 - j] = poc - rps_poc[j] - 1;
|
||||||
}
|
rps->used_by_curr_pic_s0_flag[i - 1 - j] = rps_used[j];
|
||||||
if (!rp)
|
poc = rps_poc[j];
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
// This only works for one instance of each (delta_poc_sN_minus1
|
rps->num_positive_pics = rps_pics - i;
|
||||||
// is relative to the previous frame in the list, not relative to
|
poc = hpic->pic_order_cnt;
|
||||||
// the current frame directly).
|
for (j = i; j < rps_pics; j++) {
|
||||||
if (st->display_order < pic->display_order) {
|
rps->delta_poc_s1_minus1[j - i] = rps_poc[j] - poc - 1;
|
||||||
rps->delta_poc_s0_minus1[rps->num_negative_pics] =
|
rps->used_by_curr_pic_s1_flag[j - i] = rps_used[j];
|
||||||
pic->display_order - st->display_order - 1;
|
poc = rps_poc[j];
|
||||||
rps->used_by_curr_pic_s0_flag[rps->num_negative_pics] = used;
|
|
||||||
++rps->num_negative_pics;
|
|
||||||
} else {
|
|
||||||
rps->delta_poc_s1_minus1[rps->num_positive_pics] =
|
|
||||||
st->display_order - pic->display_order - 1;
|
|
||||||
rps->used_by_curr_pic_s1_flag[rps->num_positive_pics] = used;
|
|
||||||
++rps->num_positive_pics;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sh->num_long_term_sps = 0;
|
sh->num_long_term_sps = 0;
|
||||||
@ -1084,10 +1112,13 @@ static const VAAPIEncodeType vaapi_encode_type_h265 = {
|
|||||||
|
|
||||||
.flags = FLAG_SLICE_CONTROL |
|
.flags = FLAG_SLICE_CONTROL |
|
||||||
FLAG_B_PICTURES |
|
FLAG_B_PICTURES |
|
||||||
|
FLAG_B_PICTURE_REFERENCES |
|
||||||
FLAG_NON_IDR_KEY_PICTURES,
|
FLAG_NON_IDR_KEY_PICTURES,
|
||||||
|
|
||||||
.configure = &vaapi_encode_h265_configure,
|
.configure = &vaapi_encode_h265_configure,
|
||||||
|
|
||||||
|
.picture_priv_data_size = sizeof(VAAPIEncodeH265Picture),
|
||||||
|
|
||||||
.sequence_params_size = sizeof(VAEncSequenceParameterBufferHEVC),
|
.sequence_params_size = sizeof(VAEncSequenceParameterBufferHEVC),
|
||||||
.init_sequence_params = &vaapi_encode_h265_init_sequence_params,
|
.init_sequence_params = &vaapi_encode_h265_init_sequence_params,
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user