h264: eliminate default_ref_list

According to the spec, the reference list for a slice should be
constructed by first generating an initial (what we now call "default")
reference list and then optionally applying modifications to it.

Our code has an optimization where the initial reference list is
constructed for the first inter slice and then rebuilt for other slices
if needed. This, however, adds complexity to the code, requires an extra
2.5kB array in the codec context and there is no reason to think that it
has any positive effect on performance. Therefore, simplify the code by
generating the reference list from scratch for each slice.
This commit is contained in:
Anton Khirnov 2015-11-30 17:51:48 +01:00
parent e7078e842d
commit 741b494fa8
3 changed files with 22 additions and 49 deletions

View File

@ -600,7 +600,6 @@ typedef struct H264Context {
*/
int max_pic_num;
H264Ref default_ref_list[2][32]; ///< base reference list for all slices of a coded picture
H264Picture *short_ref[32];
H264Picture *long_ref[32];
H264Picture *delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // FIXME size?
@ -645,7 +644,6 @@ typedef struct H264Context {
enum AVPictureType pict_type;
int last_slice_type;
/** @} */
/**
@ -804,11 +802,6 @@ int ff_h264_get_slice_type(const H264SliceContext *sl);
*/
int ff_h264_alloc_tables(H264Context *h);
/**
* Fill the default_ref_list.
*/
int ff_h264_fill_default_ref_list(H264Context *h, H264SliceContext *sl);
int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl);
void ff_h264_fill_mbaff_ref_list(H264Context *h, H264SliceContext *sl);
void ff_h264_remove_all_refs(H264Context *h);

View File

@ -119,7 +119,7 @@ static int add_sorted(H264Picture **sorted, H264Picture **src, int len, int limi
return out_i;
}
int ff_h264_fill_default_ref_list(H264Context *h, H264SliceContext *sl)
static void h264_initialise_ref_list(H264Context *h, H264SliceContext *sl)
{
int i, len;
@ -138,52 +138,51 @@ int ff_h264_fill_default_ref_list(H264Context *h, H264SliceContext *sl)
len += add_sorted(sorted + len, h->short_ref, h->short_ref_count, cur_poc, 0 ^ list);
assert(len <= 32);
len = build_def_list(h->default_ref_list[list], FF_ARRAY_ELEMS(h->default_ref_list[0]),
len = build_def_list(sl->ref_list[list], FF_ARRAY_ELEMS(sl->ref_list[0]),
sorted, len, 0, h->picture_structure);
len += build_def_list(h->default_ref_list[list] + len,
FF_ARRAY_ELEMS(h->default_ref_list[0]) - len,
len += build_def_list(sl->ref_list[list] + len,
FF_ARRAY_ELEMS(sl->ref_list[0]) - len,
h->long_ref, 16, 1, h->picture_structure);
if (len < sl->ref_count[list])
memset(&h->default_ref_list[list][len], 0, sizeof(H264Ref) * (sl->ref_count[list] - len));
memset(&sl->ref_list[list][len], 0, sizeof(H264Ref) * (sl->ref_count[list] - len));
lens[list] = len;
}
if (lens[0] == lens[1] && lens[1] > 1) {
for (i = 0; i < lens[0] &&
h->default_ref_list[0][i].parent->f->buf[0]->buffer ==
h->default_ref_list[1][i].parent->f->buf[0]->buffer; i++);
sl->ref_list[0][i].parent->f->buf[0]->buffer ==
sl->ref_list[1][i].parent->f->buf[0]->buffer; i++);
if (i == lens[0]) {
FFSWAP(H264Ref, h->default_ref_list[1][0], h->default_ref_list[1][1]);
FFSWAP(H264Ref, sl->ref_list[1][0], sl->ref_list[1][1]);
}
}
} else {
len = build_def_list(h->default_ref_list[0], FF_ARRAY_ELEMS(h->default_ref_list[0]),
len = build_def_list(sl->ref_list[0], FF_ARRAY_ELEMS(sl->ref_list[0]),
h->short_ref, h->short_ref_count, 0, h->picture_structure);
len += build_def_list(h->default_ref_list[0] + len,
FF_ARRAY_ELEMS(h->default_ref_list[0]) - len,
len += build_def_list(sl->ref_list[0] + len,
FF_ARRAY_ELEMS(sl->ref_list[0]) - len,
h-> long_ref, 16, 1, h->picture_structure);
if (len < sl->ref_count[0])
memset(&h->default_ref_list[0][len], 0, sizeof(H264Ref) * (sl->ref_count[0] - len));
memset(&sl->ref_list[0][len], 0, sizeof(H264Ref) * (sl->ref_count[0] - len));
}
#ifdef TRACE
for (i = 0; i < sl->ref_count[0]; i++) {
ff_tlog(h->avctx, "List0: %s fn:%d 0x%p\n",
(h->default_ref_list[0][i].long_ref ? "LT" : "ST"),
h->default_ref_list[0][i].pic_id,
h->default_ref_list[0][i].f->data[0]);
(sl->ref_list[0][i].long_ref ? "LT" : "ST"),
sl->ref_list[0][i].pic_id,
sl->ref_list[0][i].f->data[0]);
}
if (sl->slice_type_nos == AV_PICTURE_TYPE_B) {
for (i = 0; i < sl->ref_count[1]; i++) {
ff_tlog(h->avctx, "List1: %s fn:%d 0x%p\n",
(h->default_ref_list[1][i].long_ref ? "LT" : "ST"),
h->default_ref_list[1][i].pic_id,
h->default_ref_list[1][i].f->data[0]);
(sl->ref_list[1][i].long_ref ? "LT" : "ST"),
sl->ref_list[1][i].pic_id,
sl->ref_list[1][i].f->data[0]);
}
}
#endif
return 0;
}
static void print_short_term(H264Context *h);
@ -219,9 +218,9 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl)
print_short_term(h);
print_long_term(h);
for (list = 0; list < sl->list_count; list++) {
memcpy(sl->ref_list[list], h->default_ref_list[list], sl->ref_count[list] * sizeof(sl->ref_list[0][0]));
h264_initialise_ref_list(h, sl);
for (list = 0; list < sl->list_count; list++) {
if (get_bits1(&sl->gb)) { // ref_pic_list_modification_flag_l[01]
int pred = h->curr_pic_num;
@ -326,10 +325,7 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl)
for (index = 0; index < sl->ref_count[list]; index++) {
if (!sl->ref_list[list][index].parent) {
av_log(h->avctx, AV_LOG_ERROR, "Missing reference picture\n");
if (h->default_ref_list[list][0].parent)
sl->ref_list[list][index] = h->default_ref_list[list][0];
else
return -1;
return -1;
}
}
}

View File

@ -510,18 +510,13 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
h->dequant_coeff_pps = h1->dequant_coeff_pps;
// POC timing
copy_fields(h, h1, poc_lsb, default_ref_list);
// reference lists
copy_fields(h, h1, short_ref, current_slice);
copy_fields(h, h1, poc_lsb, current_slice);
copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1);
copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1);
copy_picture_range(h->delayed_pic, h1->delayed_pic,
MAX_DELAYED_PIC_COUNT + 2, h, h1);
h->last_slice_type = h1->last_slice_type;
if (!h->cur_pic_ptr)
return 0;
@ -1032,7 +1027,6 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
unsigned int pps_id;
int ret;
unsigned int slice_type, tmp, i, j;
int default_ref_list_done = 0;
int last_pic_structure, last_pic_droppable;
int needs_reinit = 0;
int field_pic_flag, bottom_field_flag;
@ -1073,10 +1067,6 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
sl->slice_type_fixed = 0;
slice_type = golomb_to_pict_type[slice_type];
if (slice_type == AV_PICTURE_TYPE_I ||
(h->current_slice != 0 && slice_type == h->last_slice_type)) {
default_ref_list_done = 1;
}
sl->slice_type = slice_type;
sl->slice_type_nos = slice_type & 3;
@ -1491,11 +1481,6 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
ret = ff_set_ref_count(h, sl);
if (ret < 0)
return ret;
else if (ret == 1)
default_ref_list_done = 0;
if (!default_ref_list_done)
ff_h264_fill_default_ref_list(h, sl);
if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
ret = ff_h264_decode_ref_pic_list_reordering(h, sl);
@ -1635,7 +1620,6 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
h->pps.chroma_qp_index_offset[1]) +
6 * (h->sps.bit_depth_luma - 8);
h->last_slice_type = slice_type;
sl->slice_num = ++h->current_slice;
if (sl->slice_num >= MAX_SLICES) {
av_log(h->avctx, AV_LOG_ERROR,