+ // Discard everything which is in the DPB of the previous frame but
+ // not in the DPB of this one.
+ for (i = 0; i < prev->nb_dpb_pics; i++) {
+ for (j = 0; j < pic->nb_dpb_pics; j++) {
+ if (prev->dpb[i] == pic->dpb[j])
+ break;
+ }
+ if (j == pic->nb_dpb_pics) {
+ discard_list[discard] = prev->dpb[i];
+ ++discard;
+ } else {
+ ++keep;
+ }
+ }
+ av_assert0(keep <= priv->dpb_frames);
+
+ if (discard == 0) {
+ sh->adaptive_ref_pic_marking_mode_flag = 0;
+ } else {
+ sh->adaptive_ref_pic_marking_mode_flag = 1;
+ for (i = 0; i < discard; i++) {
+ VAAPIEncodeH264Picture *old = discard_list[i]->priv_data;
+ av_assert0(old->frame_num < hpic->frame_num);
+ sh->mmco[i].memory_management_control_operation = 1;
+ sh->mmco[i].difference_of_pic_nums_minus1 =
+ hpic->frame_num - old->frame_num - 1;
+ }
+ sh->mmco[i].memory_management_control_operation = 0;
+ }
+ }
+
+ // If the intended references are not the first entries of RefPicListN
+ // by default, use ref-pic-list-modification to move them there.
+ if (pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B) {
+ VAAPIEncodePicture *def_l0[MAX_DPB_SIZE], *def_l1[MAX_DPB_SIZE];
+ VAAPIEncodeH264Picture *href;
+ int n;
+
+ vaapi_encode_h264_default_ref_pic_list(avctx, pic,
+ def_l0, def_l1, &n);
+
+ if (pic->type == PICTURE_TYPE_P) {
+ int need_rplm = 0;
+ for (i = 0; i < pic->nb_refs; i++) {
+ av_assert0(pic->refs[i]);
+ if (pic->refs[i] != def_l0[i])
+ need_rplm = 1;
+ }
+
+ sh->ref_pic_list_modification_flag_l0 = need_rplm;
+ if (need_rplm) {
+ int pic_num = hpic->frame_num;
+ for (i = 0; i < pic->nb_refs; i++) {
+ href = pic->refs[i]->priv_data;
+ av_assert0(href->frame_num != pic_num);
+ if (href->frame_num < pic_num) {
+ sh->rplm_l0[i].modification_of_pic_nums_idc = 0;
+ sh->rplm_l0[i].abs_diff_pic_num_minus1 =
+ pic_num - href->frame_num - 1;
+ } else {
+ sh->rplm_l0[i].modification_of_pic_nums_idc = 1;
+ sh->rplm_l0[i].abs_diff_pic_num_minus1 =
+ href->frame_num - pic_num - 1;
+ }
+ pic_num = href->frame_num;
+ }
+ sh->rplm_l0[i].modification_of_pic_nums_idc = 3;
+ }
+
+ } else {
+ int need_rplm_l0 = 0, need_rplm_l1 = 0;
+ int n0 = 0, n1 = 0;
+ for (i = 0; i < pic->nb_refs; i++) {
+ av_assert0(pic->refs[i]);
+ href = pic->refs[i]->priv_data;
+ av_assert0(href->pic_order_cnt != hpic->pic_order_cnt);
+ if (href->pic_order_cnt < hpic->pic_order_cnt) {
+ if (pic->refs[i] != def_l0[n0])
+ need_rplm_l0 = 1;
+ ++n0;
+ } else {
+ if (pic->refs[i] != def_l1[n1])
+ need_rplm_l1 = 1;
+ ++n1;
+ }
+ }
+
+ sh->ref_pic_list_modification_flag_l0 = need_rplm_l0;
+ if (need_rplm_l0) {
+ int pic_num = hpic->frame_num;
+ for (i = j = 0; i < pic->nb_refs; i++) {
+ href = pic->refs[i]->priv_data;
+ if (href->pic_order_cnt > hpic->pic_order_cnt)
+ continue;
+ av_assert0(href->frame_num != pic_num);
+ if (href->frame_num < pic_num) {
+ sh->rplm_l0[j].modification_of_pic_nums_idc = 0;
+ sh->rplm_l0[j].abs_diff_pic_num_minus1 =
+ pic_num - href->frame_num - 1;
+ } else {
+ sh->rplm_l0[j].modification_of_pic_nums_idc = 1;
+ sh->rplm_l0[j].abs_diff_pic_num_minus1 =
+ href->frame_num - pic_num - 1;
+ }
+ pic_num = href->frame_num;
+ ++j;
+ }
+ av_assert0(j == n0);
+ sh->rplm_l0[j].modification_of_pic_nums_idc = 3;
+ }
+
+ sh->ref_pic_list_modification_flag_l1 = need_rplm_l1;
+ if (need_rplm_l1) {
+ int pic_num = hpic->frame_num;
+ for (i = j = 0; i < pic->nb_refs; i++) {
+ href = pic->refs[i]->priv_data;
+ if (href->pic_order_cnt < hpic->pic_order_cnt)
+ continue;
+ av_assert0(href->frame_num != pic_num);
+ if (href->frame_num < pic_num) {
+ sh->rplm_l1[j].modification_of_pic_nums_idc = 0;
+ sh->rplm_l1[j].abs_diff_pic_num_minus1 =
+ pic_num - href->frame_num - 1;
+ } else {
+ sh->rplm_l1[j].modification_of_pic_nums_idc = 1;
+ sh->rplm_l1[j].abs_diff_pic_num_minus1 =
+ href->frame_num - pic_num - 1;
+ }
+ pic_num = href->frame_num;
+ ++j;
+ }
+ av_assert0(j == n1);
+ sh->rplm_l1[j].modification_of_pic_nums_idc = 3;
+ }
+ }
+ }
+
+ vslice->macroblock_address = slice->block_start;
+ vslice->num_macroblocks = slice->block_size;