From: Maarten Lankhorst Date: Tue, 15 Apr 2014 15:35:31 +0000 (+0200) Subject: nouveau/vdec: small fixes to h264 handling X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=49d26a277d8653f63b50f07371bf02b3453e8839;p=mesa.git nouveau/vdec: small fixes to h264 handling nouveau_vp3_inter_sizes requires sliec_count as argument just as the other places that call it from h264 code do. Hopefully fixes something. Fix the status_vp code to allow status == 0 too, when processing hasn't started yet. set h264->second_field correctly. --- diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video.h b/src/gallium/drivers/nouveau/nouveau_vp3_video.h index 88c14ec60ff..5c1af7104fc 100644 --- a/src/gallium/drivers/nouveau/nouveau_vp3_video.h +++ b/src/gallium/drivers/nouveau/nouveau_vp3_video.h @@ -107,6 +107,7 @@ struct nouveau_vp3_decoder { unsigned field_pic_flag : 1; unsigned decoded_top : 1; unsigned decoded_bottom : 1; + unsigned decoded_first : 1; } refs[17]; unsigned fence_seq, fw_sizes, last_frame_num, tmp_stride, ref_stride; diff --git a/src/gallium/drivers/nouveau/nouveau_vp3_video_vp.c b/src/gallium/drivers/nouveau/nouveau_vp3_video_vp.c index 1130d100390..1dcb99c1b52 100644 --- a/src/gallium/drivers/nouveau/nouveau_vp3_video_vp.c +++ b/src/gallium/drivers/nouveau/nouveau_vp3_video_vp.c @@ -169,19 +169,14 @@ struct h264_picparm_vp { // 700..a00 static void nouveau_vp3_handle_references(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *refs[16], unsigned seq, struct nouveau_vp3_video_buffer *target) { - unsigned h264 = u_reduce_video_profile(dec->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC; - unsigned i, idx, empty_spot = dec->base.max_references + 1; + unsigned i, idx, empty_spot = ~0; + for (i = 0; i < dec->base.max_references; ++i) { if (!refs[i]) continue; idx = refs[i]->valid_ref; //debug_printf("ref[%i] %p in slot %i\n", i, refs[i], idx); - assert(target != refs[i] || - (h264 && empty_spot && - (!dec->refs[idx].decoded_bottom || !dec->refs[idx].decoded_top))); - if (target == refs[i]) - empty_spot = 0; if (dec->refs[idx].vidbuf != refs[i]) { debug_printf("%p is not a real ref\n", refs[i]); @@ -192,26 +187,23 @@ nouveau_vp3_handle_references(struct nouveau_vp3_decoder *dec, struct nouveau_vp assert(dec->refs[idx].vidbuf == refs[i]); dec->refs[idx].last_used = seq; } - if (!empty_spot) + + if (dec->refs[target->valid_ref].vidbuf == target) { + dec->refs[target->valid_ref].last_used = seq; return; + } /* Try to find a real empty spot first, there should be one.. */ for (i = 0; i < dec->base.max_references + 1; ++i) { - if (dec->refs[i].last_used < seq) { - if (!dec->refs[i].vidbuf) { - empty_spot = i; - break; - } - if (empty_spot < dec->base.max_references+1 && - dec->refs[empty_spot].last_used < dec->refs[i].last_used) - continue; + if (dec->refs[i].last_used != seq) { empty_spot = i; + break; } } assert(empty_spot < dec->base.max_references+1); dec->refs[empty_spot].last_used = seq; -// debug_printf("Kicked %p to add %p to slot %i\n", dec->refs[empty_spot].vidbuf, target, i); +// debug_printf("Kicked %p to add %p to slot %i\n", dec->refs[empty_spot].vidbuf, target, empty_spot); dec->refs[empty_spot].vidbuf = target; dec->refs[empty_spot].decoded_bottom = dec->refs[empty_spot].decoded_top = 0; target->valid_ref = empty_spot; @@ -335,7 +327,7 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec, h->ofs[0] = h->ofs[2] = 0; h->tmp_stride = dec->tmp_stride >> 8; assert(h->tmp_stride); - nouveau_vp3_inter_sizes(dec, 1, &ring, &h->bucket_size, &h->inter_ring_data_size); + nouveau_vp3_inter_sizes(dec, d->slice_count, &ring, &h->bucket_size, &h->inter_ring_data_size); h->u220 = 0; h->mb_adaptive_frame_field_flag = d->pps->sps->mb_adaptive_frame_field_flag; @@ -345,7 +337,8 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec, h->is_reference = d->is_reference; h->interlace = d->field_pic_flag; h->bottom_field_flag = d->bottom_field_flag; - h->second_field = 0; // TODO: figure out when set.. + h->second_field = 0; // set in nouveau_vp3_fill_picparm_h264_vp_refs + h->log2_max_frame_num_minus4 = d->pps->sps->log2_max_frame_num_minus4; h->chroma_format_idc = 1; @@ -360,7 +353,6 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec, h->u34_3030 = h->u34_3131 = 0; h->field_order_cnt[0] = d->field_order_cnt[0]; h->field_order_cnt[1] = d->field_order_cnt[1]; - memset(h->refs, 0, sizeof(h->refs)); memcpy(h->m4x4, d->pps->ScalingList4x4, sizeof(h->m4x4)); memcpy(h->m8x8, d->pps->ScalingList8x8, sizeof(h->m8x8)); h->u220 = 0; @@ -370,6 +362,7 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec, refs[j] = (struct nouveau_vp3_video_buffer *)d->ref[i]; h->refs[j].fifo_idx = j + 1; h->refs[j].tmp_idx = refs[j]->valid_ref; + assert(dec->refs[refs[j]->valid_ref].vidbuf == refs[j]); h->refs[j].field_order_cnt[0] = d->field_order_cnt_list[i][0]; h->refs[j].field_order_cnt[1] = d->field_order_cnt_list[i][1]; h->refs[j].frame_idx = d->frame_num_list[i]; @@ -411,6 +404,12 @@ nouveau_vp3_fill_picparm_h264_vp_refs(struct nouveau_vp3_decoder *dec, assert(dec->refs[target->valid_ref].vidbuf == target); // debug_printf("Target: %p\n", target); + if (!dec->refs[target->valid_ref].decoded_top && + !dec->refs[target->valid_ref].decoded_bottom) + dec->refs[target->valid_ref].decoded_first = d->bottom_field_flag; + else if (dec->refs[target->valid_ref].decoded_first != d->bottom_field_flag) + h->second_field = 1; + h->tmp_idx = target->valid_ref; dec->refs[target->valid_ref].field_pic_flag = d->field_pic_flag; if (!d->field_pic_flag || d->bottom_field_flag) diff --git a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c index 9b756ea73f5..9cdb40ba025 100644 --- a/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c +++ b/src/gallium/drivers/nouveau/nv50/nv98_video_vp.c @@ -39,7 +39,7 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]); #endif debug_printf("mb_y = %u\n", comm->mb_y[idx]); - if (comm->status_vp[idx] == 1) + if (comm->status_vp[idx] <= 1) return; if ((comm->pvp_stage & 0xff) != 0xff) { @@ -112,7 +112,7 @@ nv98_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, else pic_addr[i] = null_addr; } - if (!is_ref) + if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom)) nv98_decoder_kick_ref(dec, target); nouveau_pushbuf_space(push, 8 + 3 * (codec != PIPE_VIDEO_FORMAT_MPEG12) + diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c index 0d152b9624f..07170a0e4c3 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c @@ -39,7 +39,7 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]); #endif debug_printf("mb_y = %u\n", comm->mb_y[idx]); - if (comm->status_vp[idx] == 1) + if (comm->status_vp[idx] <= 1) return; if ((comm->pvp_stage & 0xff) != 0xff) { @@ -112,7 +112,7 @@ nvc0_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, else pic_addr[i] = null_addr; } - if (!is_ref) + if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom)) nvc0_decoder_kick_ref(dec, target); nouveau_pushbuf_space(push, 8 + 3 * (codec != PIPE_VIDEO_FORMAT_MPEG12) +