* practice then correct remapping should be added. */
if (ref >= sl->ref_count[0])
ref = 0;
- if (!sl->ref_list[0][ref].f.data[0]) {
++ if (!sl->ref_list[0][ref].data[0]) {
+ av_log(h->avctx, AV_LOG_DEBUG, "Reference not available for error concealing\n");
+ ref = 0;
+ }
+ if ((sl->ref_list[0][ref].reference&3) != 3) {
+ av_log(h->avctx, AV_LOG_DEBUG, "Reference invalid\n");
+ return;
+ }
fill_rectangle(&h->cur_pic.ref_index[0][4 * sl->mb_xy],
2, 2, 2, ref, 1);
fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
int needs_realloc; ///< picture needs to be reallocated (eg due to a frame size change)
int reference;
int recovered; ///< picture at IDR or recovery point + recovery count
+ int invalid_gap;
+ int sei_recovery_frame_cnt;
+
+ int crop;
+ int crop_left;
+ int crop_top;
} H264Picture;
+ typedef struct H264Ref {
+ uint8_t *data[3];
+ int linesize[3];
+
+ int reference;
+ int poc;
+ int pic_id;
+
+ H264Picture *parent;
+ } H264Ref;
+
typedef struct H264SliceContext {
struct H264Context *h264;
GetBitContext gb;
}
}
--static void await_reference_mb_row(const H264Context *const h, H264Picture *ref,
++static void await_reference_mb_row(const H264Context *const h, H264Ref *ref,
int mb_y)
{
int ref_field = ref->reference - 1;
-- int ref_field_picture = ref->field_picture;
++ int ref_field_picture = ref->parent->field_picture;
int ref_height = 16 * h->mb_height >> ref_field_picture;
if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_FRAME))
/* FIXME: It can be safe to access mb stuff
* even if pixels aren't deblocked yet. */
-- ff_thread_await_progress(&ref->tf,
++ ff_thread_await_progress(&ref->parent->tf,
FFMIN(16 * mb_y >> ref_field_picture,
ref_height - 1),
ref_field_picture && ref_field);
}
}
- await_reference_mb_row(h, sl->ref_list[1][0].parent, mb_y);
+ await_reference_mb_row(h, &sl->ref_list[1][0], mb_y);
- l1mv0 = (void*)&sl->ref_list[1][0].motion_val[0][h->mb2b_xy[mb_xy]];
- l1mv1 = (void*)&sl->ref_list[1][0].motion_val[1][h->mb2b_xy[mb_xy]];
- l1ref0 = &sl->ref_list[1][0].ref_index[0][4 * mb_xy];
- l1ref1 = &sl->ref_list[1][0].ref_index[1][4 * mb_xy];
- l1mv0 = &sl->ref_list[1][0].parent->motion_val[0][h->mb2b_xy[mb_xy]];
- l1mv1 = &sl->ref_list[1][0].parent->motion_val[1][h->mb2b_xy[mb_xy]];
++ l1mv0 = (void*)&sl->ref_list[1][0].parent->motion_val[0][h->mb2b_xy[mb_xy]];
++ l1mv1 = (void*)&sl->ref_list[1][0].parent->motion_val[1][h->mb2b_xy[mb_xy]];
+ l1ref0 = &sl->ref_list[1][0].parent->ref_index[0][4 * mb_xy];
+ l1ref1 = &sl->ref_list[1][0].parent->ref_index[1][4 * mb_xy];
if (!b8_stride) {
if (sl->mb_y & 1) {
l1ref0 += 2;
assert(sl->ref_list[1][0].reference & 3);
- await_reference_mb_row(h, sl->ref_list[1][0].parent,
+ await_reference_mb_row(h, &sl->ref_list[1][0],
sl->mb_y + !!IS_INTERLACED(*mb_type));
- if (IS_INTERLACED(sl->ref_list[1][0].mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL
+ if (IS_INTERLACED(sl->ref_list[1][0].parent->mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL
if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL
mb_y = (sl->mb_y & ~1) + sl->col_parity;
mb_xy = sl->mb_x +
}
}
- await_reference_mb_row(h, sl->ref_list[1][0].parent, mb_y);
+ await_reference_mb_row(h, &sl->ref_list[1][0], mb_y);
- l1mv0 = (void*)&sl->ref_list[1][0].motion_val[0][h->mb2b_xy[mb_xy]];
- l1mv1 = (void*)&sl->ref_list[1][0].motion_val[1][h->mb2b_xy[mb_xy]];
- l1ref0 = &sl->ref_list[1][0].ref_index[0][4 * mb_xy];
- l1ref1 = &sl->ref_list[1][0].ref_index[1][4 * mb_xy];
- l1mv0 = &sl->ref_list[1][0].parent->motion_val[0][h->mb2b_xy[mb_xy]];
- l1mv1 = &sl->ref_list[1][0].parent->motion_val[1][h->mb2b_xy[mb_xy]];
++ l1mv0 = (void*)&sl->ref_list[1][0].parent->motion_val[0][h->mb2b_xy[mb_xy]];
++ l1mv1 = (void*)&sl->ref_list[1][0].parent->motion_val[1][h->mb2b_xy[mb_xy]];
+ l1ref0 = &sl->ref_list[1][0].parent->ref_index[0][4 * mb_xy];
+ l1ref1 = &sl->ref_list[1][0].parent->ref_index[1][4 * mb_xy];
if (!b8_stride) {
if (sl->mb_y & 1) {
l1ref0 += 2;
const int mx = sl->mv_cache[list][scan8[n]][0] + src_x_offset * 8;
int my = sl->mv_cache[list][scan8[n]][1] + src_y_offset * 8;
const int luma_xy = (mx & 3) + ((my & 3) << 2);
- ptrdiff_t offset = ((mx >> 2) << pixel_shift) + (my >> 2) * sl->mb_linesize;
+ ptrdiff_t offset = (mx >> 2) * (1 << pixel_shift) + (my >> 2) * sl->mb_linesize;
- uint8_t *src_y = pic->f.data[0] + offset;
+ uint8_t *src_y = pic->data[0] + offset;
uint8_t *src_cb, *src_cr;
int extra_width = 0;
int extra_height = 0;
emu |= (my >> 3) < 0 || (my >> 3) + 8 >= (pic_height >> 1);
}
- src_cb = pic->f.data[1] + ((mx >> 3) * (1 << pixel_shift)) +
- src_cb = pic->data[1] + ((mx >> 3) << pixel_shift) +
++ src_cb = pic->data[1] + ((mx >> 3) * (1 << pixel_shift)) +
(my >> ysh) * sl->mb_uvlinesize;
- src_cr = pic->f.data[2] + ((mx >> 3) * (1 << pixel_shift)) +
- src_cr = pic->data[2] + ((mx >> 3) << pixel_shift) +
++ src_cr = pic->data[2] + ((mx >> 3) * (1 << pixel_shift)) +
(my >> ysh) * sl->mb_uvlinesize;
if (emu) {
if (refn >= 0) {
const int mx = (sl->mv_cache[list][scan8[0]][0] >> 2) + 16 * sl->mb_x + 8;
const int my = (sl->mv_cache[list][scan8[0]][1] >> 2) + 16 * sl->mb_y;
- uint8_t **src = sl->ref_list[list][refn].f.data;
+ uint8_t **src = sl->ref_list[list][refn].data;
- int off = (mx << pixel_shift) +
+ int off = mx * (1<< pixel_shift) +
(my + (sl->mb_x & 3) * 4) * sl->mb_linesize +
(64 << pixel_shift);
h->vdsp.prefetch(src[0] + off, h->linesize, 4);
* past end by one (callers fault) and resync_mb_y != 0
* causes problems for the first MB line, too.
*/
- if (!FIELD_PICTURE(h)) {
- h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
- h264_set_erpic(&sl->er.last_pic,
- sl->ref_count[0] ? sl->ref_list[0][0].parent : NULL);
- h264_set_erpic(&sl->er.next_pic,
- sl->ref_count[1] ? sl->ref_list[1][0].parent : NULL);
+ if (!FIELD_PICTURE(h) && h->current_slice && !h->sps.new) {
+ int use_last_pic = h->last_pic_for_ec.f.buf[0] && !sl->ref_count[0];
+
+ ff_h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
+
+ if (use_last_pic) {
+ ff_h264_set_erpic(&sl->er.last_pic, &h->last_pic_for_ec);
- COPY_PICTURE(&sl->ref_list[0][0], &h->last_pic_for_ec);
++ sl->ref_list[0][0].parent = &h->last_pic_for_ec;
++ memcpy(sl->ref_list[0][0].data, h->last_pic_for_ec.f.data, sizeof(sl->ref_list[0][0].data));
++ memcpy(sl->ref_list[0][0].linesize, h->last_pic_for_ec.f.linesize, sizeof(sl->ref_list[0][0].linesize));
++ sl->ref_list[0][0].reference = h->last_pic_for_ec.reference;
+ } else if (sl->ref_count[0]) {
- ff_h264_set_erpic(&sl->er.last_pic, &sl->ref_list[0][0]);
++ ff_h264_set_erpic(&sl->er.last_pic, sl->ref_list[0][0].parent);
+ } else
+ ff_h264_set_erpic(&sl->er.last_pic, NULL);
+
+ if (sl->ref_count[1])
- ff_h264_set_erpic(&sl->er.next_pic, &sl->ref_list[1][0]);
++ ff_h264_set_erpic(&sl->er.next_pic, sl->ref_list[1][0].parent);
+
+ sl->er.ref_count = sl->ref_count[0];
+
ff_er_frame_end(&sl->er);
- memset(&sl->ref_list[0][0], 0, sizeof(h->last_pic_for_ec));
+ if (use_last_pic)
++ memset(&sl->ref_list[0][0], 0, sizeof(sl->ref_list[0][0]));
}
#endif /* CONFIG_ERROR_RESILIENCE */
len += build_def_list(h->default_ref_list[list] + len,
FF_ARRAY_ELEMS(h->default_ref_list[0]) - len,
h->long_ref, 16, 1, h->picture_structure);
+ av_assert0(len <= 32);
if (len < sl->ref_count[list])
- memset(&h->default_ref_list[list][len], 0, sizeof(H264Picture) * (sl->ref_count[list] - len));
+ memset(&h->default_ref_list[list][len], 0, sizeof(H264Ref) * (sl->ref_count[list] - len));
lens[list] = len;
}
len += build_def_list(h->default_ref_list[0] + len,
FF_ARRAY_ELEMS(h->default_ref_list[0]) - len,
h-> long_ref, 16, 1, h->picture_structure);
+ av_assert0(len <= 32);
if (len < sl->ref_count[0])
- memset(&h->default_ref_list[0][len], 0, sizeof(H264Picture) * (sl->ref_count[0] - len));
+ memset(&h->default_ref_list[0][len], 0, sizeof(H264Ref) * (sl->ref_count[0] - len));
}
#ifdef TRACE
for (i = 0; i < sl->ref_count[0]; i++) {
}
for (list = 0; list < sl->list_count; list++) {
for (index = 0; index < sl->ref_count[list]; index++) {
- if ( !sl->ref_list[list][index].f.buf[0]
- 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)
++ if ( !sl->ref_list[list][index].parent
+ || (!FIELD_PICTURE(h) && (sl->ref_list[list][index].reference&3) != 3)) {
+ int i;
+ av_log(h->avctx, AV_LOG_ERROR, "Missing reference picture, default is %d\n", h->default_ref_list[list][0].poc);
+ for (i = 0; i < FF_ARRAY_ELEMS(h->last_pocs); i++)
+ h->last_pocs[i] = INT_MIN;
- if (h->default_ref_list[list][0].f.buf[0]
++ if (h->default_ref_list[list][0].parent
+ && !(!FIELD_PICTURE(h) && (h->default_ref_list[list][0].reference&3) != 3))
- COPY_PICTURE(&sl->ref_list[list][index], &h->default_ref_list[list][0]);
+ sl->ref_list[list][index] = h->default_ref_list[list][0];
else
return -1;
}
- av_assert0(av_buffer_get_ref_count(sl->ref_list[list][index].f.buf[0]) > 0);
++ av_assert0(av_buffer_get_ref_count(sl->ref_list[list][index].parent->f.buf[0]) > 0);
}
}
void ff_h264_fill_mbaff_ref_list(H264Context *h, H264SliceContext *sl)
{
int list, i, j;
- for (list = 0; list < sl->list_count; list++) { //FIXME try list_count
+ for (list = 0; list < sl->list_count; list++) {
for (i = 0; i < sl->ref_count[list]; i++) {
- H264Picture *frame = &sl->ref_list[list][i];
- H264Picture *field = &sl->ref_list[list][16 + 2 * i];
- COPY_PICTURE(field, frame);
+ H264Ref *frame = &sl->ref_list[list][i];
+ H264Ref *field = &sl->ref_list[list][16 + 2 * i];
+
+ field[0] = *frame;
+
for (j = 0; j < 3; j++)
- field[0].f.linesize[j] <<= 1;
+ field[0].linesize[j] <<= 1;
field[0].reference = PICT_TOP_FIELD;
- field[0].poc = field[0].field_poc[0];
- COPY_PICTURE(field + 1, field);
+ field[0].poc = field[0].parent->field_poc[0];
+
+ field[1] = field[0];
+
for (j = 0; j < 3; j++)
- field[1].f.data[j] += frame->f.linesize[j];
+ field[1].data[j] += frame->parent->f.linesize[j];
field[1].reference = PICT_BOTTOM_FIELD;
- field[1].poc = field[1].field_poc[1];
+ field[1].poc = field[1].parent->field_poc[1];
sl->luma_weight[16 + 2 * i][list][0] = sl->luma_weight[16 + 2 * i + 1][list][0] = sl->luma_weight[i][list][0];
sl->luma_weight[16 + 2 * i][list][1] = sl->luma_weight[16 + 2 * i + 1][list][1] = sl->luma_weight[i][list][1];