h264: introduce GST_VAAPI_PICTURE_{SHORT,LONG}_TERM_REFERENCE flags.

Further get rid of GstVaapiPictureH264-local VAPictureH264.flags for
reference bits, thus simplifying the reference picture marking process
to only track a single set of reference flags. Also introduce a new
long_term_frame_idx member.
This commit is contained in:
Gwenole Beauchesne 2012-10-31 11:45:14 +01:00
parent af22813f59
commit 3c721e1123

View file

@ -80,14 +80,38 @@ typedef struct _GstVaapiSliceH264Class GstVaapiSliceH264Class;
* Extended picture flags: * Extended picture flags:
* *
* @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture * @GST_VAAPI_PICTURE_FLAG_IDR: flag that specifies an IDR picture
* @GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE: flag that specifies
* "used for short-term reference"
* @GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE: flag that specifies
* "used for long-term reference"
* @GST_VAAPI_PICTURE_FLAGS_REFERENCE: mask covering any kind of
* reference picture (short-term reference or long-term reference)
*/ */
enum { enum {
GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0), GST_VAAPI_PICTURE_FLAG_IDR = (GST_VAAPI_PICTURE_FLAG_LAST << 0),
GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE = (
GST_VAAPI_PICTURE_FLAG_REFERENCE),
GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE = (
GST_VAAPI_PICTURE_FLAG_REFERENCE | (GST_VAAPI_PICTURE_FLAG_LAST << 1)),
GST_VAAPI_PICTURE_FLAGS_REFERENCE = (
GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE |
GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE),
}; };
#define GST_VAAPI_PICTURE_IS_IDR(picture) \ #define GST_VAAPI_PICTURE_IS_IDR(picture) \
(GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR)) (GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_IDR))
#define GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture) \
((GST_VAAPI_PICTURE_FLAGS(picture) & \
GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE)
#define GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture) \
((GST_VAAPI_PICTURE_FLAGS(picture) & \
GST_VAAPI_PICTURE_FLAGS_REFERENCE) == \
GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE)
struct _GstVaapiPictureH264 { struct _GstVaapiPictureH264 {
GstVaapiPicture base; GstVaapiPicture base;
VAPictureH264 info; VAPictureH264 info;
@ -95,9 +119,9 @@ struct _GstVaapiPictureH264 {
gint32 poc; gint32 poc;
gint32 frame_num; // Original frame_num from slice_header() gint32 frame_num; // Original frame_num from slice_header()
gint32 frame_num_wrap; // Temporary for ref pic marking: FrameNumWrap gint32 frame_num_wrap; // Temporary for ref pic marking: FrameNumWrap
gint32 long_term_frame_idx; // Temporary for ref pic marking: LongTermFrameIdx
gint32 pic_num; // Temporary for ref pic marking: PicNum gint32 pic_num; // Temporary for ref pic marking: PicNum
gint32 long_term_pic_num; // Temporary for ref pic marking: LongTermPicNum gint32 long_term_pic_num; // Temporary for ref pic marking: LongTermPicNum
guint is_long_term : 1;
guint output_flag : 1; guint output_flag : 1;
guint output_needed : 1; guint output_needed : 1;
}; };
@ -136,7 +160,6 @@ gst_vaapi_picture_h264_init(GstVaapiPictureH264 *picture)
va_pic->BottomFieldOrderCnt = 0; va_pic->BottomFieldOrderCnt = 0;
picture->poc = 0; picture->poc = 0;
picture->is_long_term = FALSE;
picture->output_needed = FALSE; picture->output_needed = FALSE;
} }
@ -1157,7 +1180,7 @@ compare_picture_long_term_frame_idx_inc(const void *a, const void *b)
const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a; const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b; const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
return picA->info.frame_idx - picB->info.frame_idx; return picA->long_term_frame_idx - picB->long_term_frame_idx;
} }
/* 8.2.4.1 - Decoding process for picture numbers */ /* 8.2.4.1 - Decoding process for picture numbers */
@ -1201,12 +1224,12 @@ init_picture_refs_pic_num(
// (8-29, 8-32, 8-33) // (8-29, 8-32, 8-33)
if (GST_VAAPI_PICTURE_IS_FRAME(picture)) if (GST_VAAPI_PICTURE_IS_FRAME(picture))
pic->long_term_pic_num = pic->info.frame_idx; pic->long_term_pic_num = pic->long_term_frame_idx;
else { else {
if (pic->base.structure == picture->base.structure) if (pic->base.structure == picture->base.structure)
pic->long_term_pic_num = 2 * pic->info.frame_idx + 1; pic->long_term_pic_num = 2 * pic->long_term_frame_idx + 1;
else else
pic->long_term_pic_num = 2 * pic->info.frame_idx; pic->long_term_pic_num = 2 * pic->long_term_frame_idx;
} }
} }
} }
@ -1449,10 +1472,7 @@ remove_reference_at(
g_return_val_if_fail(index < num_pictures, FALSE); g_return_val_if_fail(index < num_pictures, FALSE);
picture = pictures[index]; picture = pictures[index];
GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE); GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAGS_REFERENCE);
picture->is_long_term = FALSE;
picture->info.flags &= ~(VA_PICTURE_H264_SHORT_TERM_REFERENCE |
VA_PICTURE_H264_LONG_TERM_REFERENCE);
if (index != --num_pictures) if (index != --num_pictures)
gst_vaapi_picture_replace(&pictures[index], pictures[num_pictures]); gst_vaapi_picture_replace(&pictures[index], pictures[num_pictures]);
@ -1580,8 +1600,9 @@ exec_picture_refs_modification_1(
gint32 PicNumF; gint32 PicNumF;
if (!ref_list[j]) if (!ref_list[j])
continue; continue;
PicNumF = ref_list[j]->is_long_term ? PicNumF =
MaxPicNum : ref_list[j]->pic_num; GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(ref_list[j]) ?
ref_list[j]->pic_num : MaxPicNum;
if (PicNumF != picNum) if (PicNumF != picNum)
ref_list[n++] = ref_list[j]; ref_list[n++] = ref_list[j];
} }
@ -1601,7 +1622,8 @@ exec_picture_refs_modification_1(
gint32 LongTermPicNumF; gint32 LongTermPicNumF;
if (!ref_list[j]) if (!ref_list[j])
continue; continue;
LongTermPicNumF = ref_list[j]->is_long_term ? LongTermPicNumF =
GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(ref_list[j]) ?
ref_list[j]->long_term_pic_num : INT_MAX; ref_list[j]->long_term_pic_num : INT_MAX;
if (LongTermPicNumF != l->value.long_term_pic_num) if (LongTermPicNumF != l->value.long_term_pic_num)
ref_list[n++] = ref_list[j]; ref_list[n++] = ref_list[j];
@ -1699,7 +1721,6 @@ init_picture(
{ {
GstVaapiDecoderH264Private * const priv = decoder->priv; GstVaapiDecoderH264Private * const priv = decoder->priv;
GstVaapiPicture * const base_picture = &picture->base; GstVaapiPicture * const base_picture = &picture->base;
VAPictureH264 *pic;
priv->prev_frame_num = priv->frame_num; priv->prev_frame_num = priv->frame_num;
priv->frame_num = slice_hdr->frame_num; priv->frame_num = slice_hdr->frame_num;
@ -1716,11 +1737,6 @@ init_picture(
clear_references(decoder, priv->long_ref, &priv->long_ref_count ); clear_references(decoder, priv->long_ref, &priv->long_ref_count );
} }
/* Initialize VA picture info */
pic = &picture->info;
pic->picture_id = picture->base.surface_id;
pic->frame_idx = priv->frame_num;
/* Initialize slice type */ /* Initialize slice type */
switch (slice_hdr->type % 5) { switch (slice_hdr->type % 5) {
case GST_H264_P_SLICE: case GST_H264_P_SLICE:
@ -1751,11 +1767,14 @@ init_picture(
if (nalu->ref_idc) { if (nalu->ref_idc) {
GstH264DecRefPicMarking * const dec_ref_pic_marking = GstH264DecRefPicMarking * const dec_ref_pic_marking =
&slice_hdr->dec_ref_pic_marking; &slice_hdr->dec_ref_pic_marking;
GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
if (GST_VAAPI_PICTURE_IS_IDR(picture)) { if (GST_VAAPI_PICTURE_IS_IDR(picture) &&
if (dec_ref_pic_marking->long_term_reference_flag) dec_ref_pic_marking->long_term_reference_flag)
picture->is_long_term = TRUE; GST_VAAPI_PICTURE_FLAG_SET(picture,
} GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
else
GST_VAAPI_PICTURE_FLAG_SET(picture,
GST_VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE);
} }
init_picture_poc(decoder, picture, slice_hdr); init_picture_poc(decoder, picture, slice_hdr);
@ -1861,11 +1880,10 @@ exec_ref_pic_marking_adaptive_mmco_3(
) )
{ {
GstVaapiDecoderH264Private * const priv = decoder->priv; GstVaapiDecoderH264Private * const priv = decoder->priv;
VAPictureH264 *pic;
gint32 i, picNumX; gint32 i, picNumX;
for (i = 0; i < priv->long_ref_count; i++) { for (i = 0; i < priv->long_ref_count; i++) {
if (priv->long_ref[i]->info.frame_idx == ref_pic_marking->long_term_frame_idx) if (priv->long_ref[i]->long_term_frame_idx == ref_pic_marking->long_term_frame_idx)
break; break;
} }
if (i != priv->long_ref_count) if (i != priv->long_ref_count)
@ -1881,12 +1899,9 @@ exec_ref_pic_marking_adaptive_mmco_3(
gst_vaapi_picture_replace(&priv->long_ref[priv->long_ref_count++], picture); gst_vaapi_picture_replace(&priv->long_ref[priv->long_ref_count++], picture);
gst_vaapi_picture_unref(picture); gst_vaapi_picture_unref(picture);
picture->is_long_term = TRUE; picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
pic = &picture->info; GST_VAAPI_PICTURE_FLAG_SET(picture,
pic->frame_idx = ref_pic_marking->long_term_frame_idx; GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
pic->flags &= ~VA_PICTURE_H264_SHORT_TERM_REFERENCE;
pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
} }
/* 8.2.5.4.4. Mark pictures with LongTermFramIdx > max_long_term_frame_idx /* 8.2.5.4.4. Mark pictures with LongTermFramIdx > max_long_term_frame_idx
@ -1904,7 +1919,7 @@ exec_ref_pic_marking_adaptive_mmco_4(
long_term_frame_idx = ref_pic_marking->max_long_term_frame_idx_plus1 - 1; long_term_frame_idx = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
for (i = 0; i < priv->long_ref_count; i++) { for (i = 0; i < priv->long_ref_count; i++) {
if ((gint32)priv->long_ref[i]->info.frame_idx <= long_term_frame_idx) if (priv->long_ref[i]->long_term_frame_idx <= long_term_frame_idx)
continue; continue;
remove_reference_at(decoder, priv->long_ref, &priv->long_ref_count, i); remove_reference_at(decoder, priv->long_ref, &priv->long_ref_count, i);
i--; i--;
@ -1949,8 +1964,9 @@ exec_ref_pic_marking_adaptive_mmco_6(
GstH264RefPicMarking *ref_pic_marking GstH264RefPicMarking *ref_pic_marking
) )
{ {
picture->is_long_term = TRUE; picture->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
picture->info.frame_idx = ref_pic_marking->long_term_frame_idx; GST_VAAPI_PICTURE_FLAG_SET(picture,
GST_VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE);
} }
/* 8.2.5.4. Adaptive memory control decoded reference picture marking process */ /* 8.2.5.4. Adaptive memory control decoded reference picture marking process */
@ -2024,14 +2040,10 @@ exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
} }
} }
if (picture->is_long_term) { if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture))
picture_ptr = &priv->long_ref[priv->long_ref_count++]; picture_ptr = &priv->long_ref[priv->long_ref_count++];
picture->info.flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE; else
}
else {
picture_ptr = &priv->short_ref[priv->short_ref_count++]; picture_ptr = &priv->short_ref[priv->short_ref_count++];
picture->info.flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
}
gst_vaapi_picture_replace(picture_ptr, picture); gst_vaapi_picture_replace(picture_ptr, picture);
return TRUE; return TRUE;
} }
@ -2052,12 +2064,12 @@ vaapi_fill_picture(VAPictureH264 *pic, GstVaapiPictureH264 *picture)
pic->picture_id = picture->base.surface_id; pic->picture_id = picture->base.surface_id;
pic->flags = 0; pic->flags = 0;
if (picture->info.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE) { if (GST_VAAPI_PICTURE_IS_LONG_TERM_REFERENCE(picture)) {
pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE; pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
pic->frame_idx = picture->info.frame_idx; pic->frame_idx = picture->long_term_frame_idx;
} }
else { else {
if (picture->info.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) if (GST_VAAPI_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE; pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
pic->frame_idx = picture->frame_num; pic->frame_idx = picture->frame_num;
} }